reorder Alu3 instructions to deal with two-instruction literals
[fleet.git] / ships / Choice.ship
index 20dfc4a..eb56a40 100644 (file)
@@ -3,21 +3,18 @@ ship: Choice
 == Ports ===========================================================
 data  in:   in1
 data  in:   in2
-
 data  in:   in.swapIfZero
 data  in:   in.swapIfNonZero
 data  in:   in.swapIfNegative
 data  in:   in.swapIfPositive
 data  in:   in.swapIfNonNegative
 data  in:   in.swapIfNonPositive
-
 data  in:   in.muxIfZero
 data  in:   in.muxIfNonZero
 data  in:   in.muxIfNegative
 data  in:   in.muxIfPositive
 data  in:   in.muxIfNonNegative
 data  in:   in.muxIfNonPositive
-
 data  in:   in.deMuxIfZero
 data  in:   in.deMuxIfNonZero
 data  in:   in.deMuxIfNegative
@@ -32,38 +29,43 @@ data  out:  out2
 
 == TeX ==============================================================
 
-With judicious programming of its BenkoBoxes, this ship can be used to
-implement nearly all forms of selection and branching.
-
-When data is available at the in port, it is examined.  Which
-destination the datum has arrived on determines the *condition* the
-datum should be tested for and the *action* which should be taken if
-the condition holds true.
-
-The latter portion of the name of the destination (IfZero,
-If(Non)Positive, If(Non)Negative) determines the condition which the
-datum on the in port is tested for.  The former portion (mux, demux,
-swap) determines the *action* to be taken if the condition tests true.
-
-  action   condition    effect
-  ------   ---------    -------------------------------
-  swap     false        in1->out1   in2->out2
-  swap     true         in2->out1   in1->out2
-  mux      false        in1->out1
-  mux      true         in2->out1
-  demux    false        in1->out1
-  demux    true         in1->out2
-
-In each case, the ship will wait for a datum to be available on all
-input ports (and only those ports) mentioned in the appropriate row of
-the "effect" column above, and will output them on the corresponding
-output ports.
+This ship needs to be updated to use opcode ports \cite{am25}.  For a
+general idea of what this ship is supposed to do, see \cite{am17}.
+
+%With judicious programming of its pumps, this ship can be used to
+%implement nearly all forms of selection and branching.
+%
+%When data is available at the in port, it is examined.  Which
+%destination the datum has arrived on determines the *condition* the
+%datum should be tested for and the *action* which should be taken if
+%the condition holds true.
+%
+%The latter portion of the name of the destination (IfZero,
+%If(Non)Positive, If(Non)Negative) determines the condition which the
+%datum on the in port is tested for.  The former portion (mux, demux,
+%swap) determines the *action* to be taken if the condition tests true.
+%
+%\begin{verbatim}
+%  action   condition    effect
+%  ------   ---------    -------------------------------
+%  swap     false        in1->out1   in2->out2
+%  swap     true         in2->out1   in1->out2
+%  mux      false        in1->out1
+%  mux      true         in2->out1
+%  demux    false        in1->out1
+%  demux    true         in1->out2
+%\end{verbatim}
+%
+%In each case, the ship will wait for a datum to be available on all
+%input ports (and only those ports) mentioned in the appropriate row of
+%the "effect" column above, and will output them on the corresponding
+%output ports.
 
 
 == Fleeterpreter ====================================================
 private Packet selector;
 public void service() {
-  if (!box_out1.readyForItemFromShip() || !box_out2.readyForItemFromShip()) return;
+  if (!box_out1.readyForDataFromShip() || !box_out2.readyForDataFromShip()) return;
   if (selector == null && !box_in.dataReadyForShip()) return;
   if (selector == null) selector = box_in.removePacketForShip();
   String port = selector.destination.getDestinationName();
@@ -72,7 +74,7 @@ public void service() {
   if (port.startsWith("mux")   && (!box_in1.dataReadyForShip() || !box_in2.dataReadyForShip())) return;
   if (port.startsWith("deMux") && (!box_in1.dataReadyForShip())) return;
 
-  long val = box_in.removeDataForShip();
+  long val = selector.value;
   boolean condition = false;
   if (port.endsWith("IfZero"))        condition = val==0;
   if (port.endsWith("IfNonZero"))     condition = val!=0;
@@ -84,14 +86,18 @@ public void service() {
     if (condition) {
       box_out1.addDataFromShip(box_in2.removeDataForShip());
       box_out2.addDataFromShip(box_in1.removeDataForShip());
+      selector = null;
     } else {
       box_out1.addDataFromShip(box_in1.removeDataForShip());
       box_out2.addDataFromShip(box_in2.removeDataForShip());
+      selector = null;
     }
   } else if (port.startsWith("mux")) {
     box_out1.addDataFromShip(condition ? box_in2.removeDataForShip() : box_in1.removeDataForShip());
+    selector = null;
   } else if (port.startsWith("deMux")) {
     (condition ? box_out2 : box_out1).addDataFromShip(box_in1.removeDataForShip());
+    selector = null;
   }
 }
 
@@ -99,41 +105,113 @@ public void service() {
 
 == FPGA ==============================================================
 
-  // FIXME
-  reg                    have_a;
-  reg [(`DATAWIDTH-1):0] reg_a;
-  reg                    have_b;
-  reg [(`DATAWIDTH-1):0] reg_b;
-  reg                    have_op;
-  reg [(`DATAWIDTH-1):0] reg_op;
+  reg                       have_in1;
+  reg [(`DATAWIDTH-1):0]    reg_in1;
+  reg                       have_in2;
+  reg [(`DATAWIDTH-1):0]    reg_in2;
+  reg                       have_in;
+  reg [(`PACKET_WIDTH-1):0] reg_in;
+  reg                       have_out1;
+  reg                       have_out2;
+  reg fire;
+
+  reg zero;
+  reg pos;
+  reg neg;
 
   always @(posedge clk) begin
-    if (!have_a) begin
-      `onread(in1_r, in1_a) have_a = 1; reg_a = in1_d; end
+
+    if (!have_in1) begin
+      `onread(in1_r, in1_a) have_in1 <= 1; reg_in1 <= in1_d; end
+      end
+    if (!have_in2) begin
+      `onread(in2_r, in2_a) have_in2 <= 1; reg_in2 <= in2_d; end
       end
-    if (!have_b) begin
-      `onread(in2_r, in2_a) have_b = 1; reg_b = in2_d; end
+    if (!have_in) begin
+      `onread(in_r,  in_a)  have_in  <= 1;  reg_in <= in_d;  end
+      end
+
+    if (have_out1) begin
+      `onwrite(out1_r, out1_a) have_out1 <= 0; end
       end
-    if (!have_op) begin
-      `onread(inOp_r, inOp_a) have_op = 1; reg_op = inOp_d; end
+
+    if (have_out2) begin
+      `onwrite(out2_r, out2_a) have_out2 <= 0; end
       end
-  
-    if (have_a && have_b && have_op) begin
-      case (reg_op)
-        0: out_d = reg_a + reg_b;
-        1: out_d = reg_a - reg_b;
-        default: out_d = 0;
-      endcase        
-      `onwrite(out_r, out_a)
-        have_a  = 0;
-        have_b  = 0;
-        have_op = 0;
+
+    if (have_in && !have_out1 && !have_out2) begin
+      zero = reg_in[`DATAWIDTH-1:0] == 0;
+      neg = reg_in[`DATAWIDTH-1];
+      pos = !zero && !neg;
+      case (reg_in[`PACKET_WIDTH-1:`DATAWIDTH])
+        00: fire = zero;
+        06: fire = zero;
+        12: fire = zero;
+        01: fire = !zero;
+        07: fire = !zero;
+        13: fire = !zero;
+        02: fire = neg;
+        08: fire = neg;
+        14: fire = neg;
+        03: fire = pos;
+        09: fire = pos;
+        15: fire = pos;
+        04: fire = !neg;
+        16: fire = !neg;
+        10: fire = !neg;
+        05: fire = !pos;
+        11: fire = !pos;
+        17: fire = !pos;
+      endcase
+
+      if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 5) begin
+            if (have_in1 && have_in2 && !have_out1 && !have_out2) begin
+              have_out1 <= 1;
+              have_out2 <= 1;
+              have_in1  <= 0;
+              have_in2  <= 0;
+              have_in   <= 0;
+              out1_d    <= fire ? reg_in2 : reg_in1;
+              out2_d    <= fire ? reg_in1 : reg_in2;
+            end
+      end else if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 11) begin
+            if (fire && have_in2) begin
+              have_out1 <= 1;
+              have_in2  <= 0;
+              out1_d    <= in2_d;
+              have_in   <= 0;
+            end else if (!fire && have_in1) begin
+              have_out1 <= 1;
+              have_in1  <= 0;
+              out1_d    <= in1_d;
+              have_in   <= 0;
+            end
+      end else begin
+            if (have_in1) begin
+              if (fire) begin
+                have_out2 <= 1;
+                out2_d    <= in1_d;
+                have_in1  <= 0;
+                have_in   <= 0;
+              end else begin
+                have_out1 <= 1;
+                out1_d    <= in1_d;
+                have_in1  <= 0;
+                have_in   <= 0;
+              end
+            end
       end
-    end
+
+   end
+
   end
 
 
 
+== Test ==============================================================================
+#skip
+#ship debug : Debug
+#expect 0
 
 == Contributors =========================================================
 Adam Megacz <megacz@cs.berkeley.edu>