--- /dev/null
+ship: Alu
+
+== Ports ===========================================================
+data in: in1
+data in: in2
+data in: inOp
+ constant IN1: 0
+ constant IN2: 1
+ constant ADD: 2
+ constant SUB: 3
+ constant MAX: 4
+ constant MIN: 5
+ constant CMP: 6
+
+data out: out
+
+
+== TeX ==============================================================
+
+{\tt Alu} is a ``two-input'' arithmetic logic unit. It includes
+logic for performing arithmetic operations on a pair of arguments.
+Currently this includes
+addition ({\sc add}),
+subtraction ({\sc sub}),
+maximum ({\sc max}), and
+minimum ({\sc min}).
+
+\subsection*{Semantics}
+
+When a value is present at each of {\tt in1}, {\tt in2} and {\tt
+inOp}, these three values are consumed. Based on the value consumed
+at {\tt inOp}, the requested operation is performed on the values
+consumed from {\tt in1} and {\tt in2}. The result of this operation
+is then made available at {\tt 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
+\end{verbatim}
+
+\subsection*{To Do}
+
+The {\it link bit} and other features of \cite{ies31} are not yet
+implemented.
+
+The carry-in, carry-out, zero-test, negative-test, and overflow-test
+flags typically present in a conventional processor ALU are also not
+yet implemented.
+
+== Fleeterpreter ====================================================
+public void service() {
+ if (box_in1.dataReadyForShip() &&
+ box_in2.dataReadyForShip() &&
+ box_inOp.dataReadyForShip() &&
+ box_out.readyForDataFromShip()) {
+ long a = box_in1.removeDataForShip();
+ long b = box_in2.removeDataForShip();
+ long op = box_inOp.removeDataForShip();
+ switch((int)op) {
+ case 0: box_out.addDataFromShip(a); // IN1
+ break;
+ case 1: box_out.addDataFromShip(b); // IN2
+ break;
+ case 2: box_out.addDataFromShip(a+b); // ADD
+ break;
+ case 3: box_out.addDataFromShip(a-b); // SUB
+ break;
+ case 4: box_out.addDataFromShip(Math.max(a,b)); // MAX
+ box_out.flag_c = !(a>b);
+ break;
+ case 5: box_out.addDataFromShip(Math.min(a,b)); // MIN
+ box_out.flag_c = a>b;
+ break;
+ default: box_out.addDataFromShip(0);
+ break;
+ }
+ }
+}
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+ wire [`DATAWIDTH:0] sum;
+ wire cin;
+ wire [(`DATAWIDTH-1):0] in2_inverted;
+
+ wire [(`DATAWIDTH-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 :
+ 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 } :
+ 0;
+
+ always @(posedge clk) begin
+ if (!rst) begin
+ `reset
+ 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;
+ end
+ if (!out_r && !out_a && in1_r && !in1_a && in2_r && !in2_a && inOp_r && !inOp_a) begin
+ out_r <= 1;
+ end
+ end
+ end
+
+== Test ==============================================================================
+
+// FIXME: need test for ADD carry-out c-flag
+
+#ship debug : Debug
+#ship alu : Alu
+
+#expect 17
+#expect 1
+#expect 9
+#expect 8
+#expect 8
+#expect 1
+#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;
+ deliver;
+ set word= 9;
+ deliver;
+
+alu.in2:
+ set word= 8;
+ set ilc=7;
+ deliver;
+ set word= 9;
+ deliver;
+
+alu.out:
+ set ilc=4;
+ collect, send to debug.in;
+alu.inOp:
+ set word= Alu.inOp[ADD]; 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;
+ set word= Alu.inOp[CMP]; deliver;
+
+alu.out:
+ collect, send to debug.in; // MIN
+ set flags a=c, b=b;
+ [a] set word= 1;
+ [!a] set word= 0;
+ send to debug.in;
+
+ collect, send to debug.in; // MAX
+ set flags a=c, b=b;
+ [a] set word= 1;
+ [!a] set word= 0;
+ send to debug.in;
+
+ collect, send to debug.in; // 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
+ set flags a=c, b=b;
+ [a] set word= 1;
+ [!a] set word= 0;
+ send to debug.in;
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>