constant MAX: 4
constant MIN: 5
constant CMP: 6
+ constant DROP1: 7
+ constant DROP2: 8
+ constant MAXMERGE: 9
+ constant AND: 10
+ constant OR: 11
+ constant XOR: 12
data out: out
\subsection*{C-Flag}
\begin{verbatim}
-IN1 - undefined
-IN2 - undefined
-ADD - carry-out
-SUB - undefined
-MAX - 0 if in1>in2, else 1
-MIN - 1 if in1>in2, else 0
-CMP - 0 if in1!=in2, else 1
+IN1 - undefined; drain in1 only
+IN2 - undefined; drain in2 only
+ADD - carry-out
+SUB - undefined
+MAX - if in1>in2 cflag=0 and drain in1, else cflag=1 and drain in2
+MIN - if in1>in2 cflag=1 and drain in2, else cflag=0 and drain in1
+CMP - if in1==in2 cflag=1, else cflag=0
+DROP1 - consume in1, produce no output
+DROP2 - consume in2, produce no output
+MAXMERGE - if (in1<0 && in2<0) consume both, emit either, cflag=undef else act as MAX
\end{verbatim}
\subsection*{To Do}
== Fleeterpreter ====================================================
public void service() {
- if (box_in1.dataReadyForShip() &&
+ if (box_inOp.dataReadyForShip() &&
+ box_in1.dataReadyForShip() &&
box_in2.dataReadyForShip() &&
- box_inOp.dataReadyForShip() &&
box_out.readyForDataFromShip()) {
- long a = box_in1.removeDataForShip();
- long b = box_in2.removeDataForShip();
+ long a;
+ long b;
long op = box_inOp.removeDataForShip();
switch((int)op) {
- case 0: box_out.addDataFromShip(a); // IN1
+ case 0:
+ a = box_in1.removeDataForShip();
+ box_out.addDataFromShip(a); // IN1
break;
- case 1: box_out.addDataFromShip(b); // IN2
+ case 1:
+ b = box_in2.removeDataForShip();
+ box_out.addDataFromShip(b); // IN2
break;
- case 2: box_out.addDataFromShip(a+b); // ADD
+ case 2:
+ a = box_in1.removeDataForShip();
+ b = box_in2.removeDataForShip();
+ box_out.addDataFromShip(a+b); // ADD
break;
- case 3: box_out.addDataFromShip(a-b); // SUB
+ case 3:
+ a = box_in1.removeDataForShip();
+ b = box_in2.removeDataForShip();
+ box_out.addDataFromShip(a-b); // SUB
break;
- case 4: box_out.addDataFromShip(Math.max(a,b)); // MAX
- box_out.flag_c = !(a>b);
+
+ case 9: // MAXMERGE
+ if (box_in1.peekDataForShip()<0 && box_in2.peekDataForShip()<0) {
+ a = box_in1.removeDataForShip();
+ b = box_in2.removeDataForShip();
+ box_out.addDataFromShip(a, false);
+ break;
+ }
+ // fall through to MAX
+ case 4:
+ a = box_in1.peekDataForShip();
+ b = box_in2.peekDataForShip();
+ box_out.addDataFromShip(Math.max(a,b), !(a>b)); // MAX
+ if (a>b) box_in1.removeDataForShip(); else box_in2.removeDataForShip();
+ break;
+
+ case 5:
+ a = box_in1.peekDataForShip();
+ b = box_in2.peekDataForShip();
+ box_out.addDataFromShip(Math.min(a,b), a>b); // MIN
+ if (a<b) box_in1.removeDataForShip(); else box_in2.removeDataForShip();
+ break;
+ case 6:
+ a = box_in1.removeDataForShip();
+ b = box_in2.removeDataForShip();
+ box_out.addDataFromShip(0, a==b); // CMP
+ break;
+/*
+ case 7:
+ box_in1.removeDataForShip(); // DROP1
+ break;
+ case 8:
+ box_in2.removeDataForShip(); // DROP2
break;
- case 5: box_out.addDataFromShip(Math.min(a,b)); // MIN
- box_out.flag_c = a>b;
+*/
+ case 10:
+ a = box_in1.removeDataForShip();
+ b = box_in2.removeDataForShip();
+ box_out.addDataFromShip(a & b); // CMP
break;
- default: box_out.addDataFromShip(0);
+ case 11:
+ a = box_in1.removeDataForShip();
+ b = box_in2.removeDataForShip();
+ box_out.addDataFromShip(a | b); // CMP
break;
+ case 12:
+ a = box_in1.removeDataForShip();
+ b = box_in2.removeDataForShip();
+ box_out.addDataFromShip(a ^ b); // CMP
+ break;
+ default:
+ throw new RuntimeException("invalid opcode: " + op);
}
}
}
== FPGA ==============================================================
- wire [`DATAWIDTH:0] sum;
+ wire [`WORDWIDTH:0] sum;
wire cin;
- wire [(`DATAWIDTH-1):0] in2_inverted;
+ wire [(`WORDWIDTH-1):0] in2_inverted;
- wire [(`DATAWIDTH-1):0] res;
+ wire [(`WORDWIDTH-1):0] res;
wire isplus;
wire eq;
wire cout;
- assign isplus = inOp_d[2:0]==2;
- assign cin = isplus ? 0 : 1;
- assign in2_inverted = isplus ? in2_d : ~in2_d;
- assign sum = {in1_d,cin} + {in2_inverted,cin};
- assign res = sum[`DATAWIDTH:1];
- assign greater = !res[`DATAWIDTH-1];
- assign eq = in1_d == in2_d;
- assign cout = sum[`DATAWIDTH];
-
- assign out_d_[`DATAWIDTH] =
- (inOp_d==0) ? 1'b0 :
- (inOp_d==1) ? 1'b0 :
- (inOp_d==2) ? cout :
- (inOp_d==3) ? 1'b0 :
- (inOp_d==4) ? ~greater :
- (inOp_d==5) ? greater :
- (inOp_d==6) ? eq :
+ wire [4:0] inOp_d_trunc;
+ assign inOp_d_trunc = inOp_d[4:0];
+
+ assign isplus = inOp_d_trunc[4:0]==2;
+ assign cin = isplus ? 0 : 1;
+ assign in2_inverted = isplus ? in2_d : ~in2_d;
+ assign sum = {in1_d,cin} + {in2_inverted,cin};
+ assign res = sum[`WORDWIDTH:1];
+ assign greater = !res[`WORDWIDTH-1];
+ assign both_negative = in1_d[`WORDWIDTH-1] && in2_d[`WORDWIDTH-1];
+ assign eq = in1_d == in2_d;
+ assign cout = sum[`WORDWIDTH];
+
+ reg out_draining;
+
+ assign out_d_[`WORDWIDTH] =
+ (inOp_d_trunc==0) ? 1'b0 :
+ (inOp_d_trunc==1) ? 1'b0 :
+ (inOp_d_trunc==2) ? cout :
+ (inOp_d_trunc==3) ? cout :
+ (inOp_d_trunc==4) ? ~greater :
+ (inOp_d_trunc==5) ? greater :
+ (inOp_d_trunc==6) ? eq :
+ (inOp_d_trunc==9) ? ~greater :
0;
- assign out_d_[(`DATAWIDTH-1):0] =
- (inOp_d==0) ? (in1_d) :
- (inOp_d==1) ? (in2_d) :
- (inOp_d==2) ? (res) :
- (inOp_d==3) ? (res) :
- (inOp_d==4) ? (greater ? in1_d : in2_d) :
- (inOp_d==5) ? (greater ? in2_d : in1_d) :
- (inOp_d==6) ? {{ (`DATAWIDTH-1) {1'b0 }}, eq } :
+ assign out_d_[(`WORDWIDTH-1):0] =
+ (inOp_d_trunc==0) ? (in1_d) :
+ (inOp_d_trunc==1) ? (in2_d) :
+ (inOp_d_trunc==2) ? (res) :
+ (inOp_d_trunc==3) ? (res) :
+ (inOp_d_trunc==4) ? (greater ? in1_d : in2_d) :
+ (inOp_d_trunc==5) ? (greater ? in2_d : in1_d) :
+ (inOp_d_trunc==6) ? {{ (`WORDWIDTH-1) {1'b0 }}, eq } :
+ (inOp_d_trunc==9) ? (both_negative ? in1_d : (greater ? in1_d : in2_d)) :
+ (inOp_d_trunc==10) ? (in1_d & in2_d) :
+ (inOp_d_trunc==11) ? (in1_d | in2_d) :
+ (inOp_d_trunc==12) ? (in1_d ^ in2_d) :
0;
+ wire firing_condition;
+ assign firing_condition =
+ (inOp_d_trunc==0) ? `in1_full :
+ (inOp_d_trunc==1) ? `in2_full :
+ (inOp_d_trunc==7) ? `in1_full :
+ (inOp_d_trunc==8) ? `in2_full :
+ ((`in1_full) && (`in2_full));
+
always @(posedge clk) begin
- if (!rst) begin
+ if (rst) begin
`reset
+ out_draining <= 0;
end else begin
- if (!in1_r && in1_a) in1_a <= 0;
- if (!in2_r && in2_a) in2_a <= 0;
- if (!inOp_r && inOp_a) inOp_a <= 0;
- if (out_r && out_a) begin
- out_r <= 0;
- in1_a <= 1;
- in2_a <= 1;
- inOp_a <= 1;
+ `cleanup
+ if (out_draining && `out_empty) begin
+ `drain_inOp
+ out_draining <= 0;
+ if (inOp_d_trunc==0) `drain_in1
+ else if (inOp_d_trunc==1) `drain_in2
+ else if (inOp_d_trunc==7) `drain_in1
+ else if (inOp_d_trunc==8) `drain_in2
+ else if (inOp_d_trunc==9 && both_negative) begin `drain_in1 `drain_in2 end
+ else if (inOp_d_trunc==4 && greater) `drain_in1
+ else if (inOp_d_trunc==5 && greater) `drain_in2
+ else if (inOp_d_trunc==9 && greater) `drain_in1
+ else if (inOp_d_trunc==4 && !greater) `drain_in2
+ else if (inOp_d_trunc==5 && !greater) `drain_in1
+ else if (inOp_d_trunc==9 && !greater) `drain_in2
+ else begin
+ `drain_in1
+ `drain_in2
+ end
end
- if (!out_r && !out_a && in1_r && !in1_a && in2_r && !in2_a && inOp_r && !inOp_a) begin
- out_r <= 1;
+ if (!out_draining && `out_empty && firing_condition && `inOp_full) begin
+ if (inOp_d_trunc!=7 && inOp_d_trunc!=8) `fill_out
+ out_draining <= 1;
end
end
end
#expect 9
#expect 0
#expect 0
-#expect 0
-#expect 1
#expect 1
debug.in: set ilc=*; recv, deliver;
alu.in1:
set word= 9;
- set ilc=7;
+ set ilc=5;
deliver;
set word= 9;
deliver;
alu.in2:
set word= 8;
- set ilc=7;
+ set ilc=5;
deliver;
set word= 9;
deliver;
set word= Alu.inOp[SUB]; deliver;
set word= Alu.inOp[IN1]; deliver;
set word= Alu.inOp[IN2]; deliver;
-
-alu.inOp:
set word= Alu.inOp[MIN]; deliver;
set word= Alu.inOp[MAX]; deliver;
set word= Alu.inOp[CMP]; deliver;
[!a] set word= 0;
send to debug.in;
- collect, send to debug.in; // CMP
+ collect; // CMP
set flags a=c, b=b;
[a] set word= 1;
[!a] set word= 0;
send to debug.in;
- collect, send to debug.in; // CMP
+ collect; // CMP
set flags a=c, b=b;
[a] set word= 1;
[!a] set word= 0;