rename Alu2->Alu
[fleet.git] / ships / Alu.ship
diff --git a/ships/Alu.ship b/ships/Alu.ship
new file mode 100644 (file)
index 0000000..9cc5e77
--- /dev/null
@@ -0,0 +1,224 @@
+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>