get rid of ChainControls
[fleet.git] / ships / Alu.ship
index 6157fc1..67effe4 100644 (file)
@@ -14,6 +14,9 @@ data  in:   inOp
   constant DROP1: 7
   constant DROP2: 8
   constant MAXMERGE: 9
+  constant AND: 10
+  constant OR: 11
+  constant XOR: 12
 
 data  out:  out
 
@@ -88,31 +91,58 @@ public void service() {
               b = box_in2.removeDataForShip();
               box_out.addDataFromShip(a-b); // SUB
               break;
+
+          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)); // MAX
-              box_out.flag_c = !(a>b);
-              if (a<b) box_in1.removeDataForShip(); else box_in2.removeDataForShip();
+              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)); // MIN
-              box_out.flag_c = a>b;
-              if (a>b) box_in1.removeDataForShip(); else box_in2.removeDataForShip();
+              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); // CMP
-              box_out.flag_c = a==b;
+              box_out.addDataFromShip(0, a==b); // CMP
               break;
-          default:
+/*
+          case 7:
+              box_in1.removeDataForShip();      // DROP1
+              break;
+          case 8:
+              box_in2.removeDataForShip();      // DROP2
+              break;
+*/
+          case 10:
               a = box_in1.removeDataForShip();
               b = box_in2.removeDataForShip();
-              box_out.addDataFromShip(0);
+              box_out.addDataFromShip(a & b); // CMP
               break;
+          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);
       }
   }
 }
@@ -121,71 +151,91 @@ public void service() {
 
 == 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;
+  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[`DATAWIDTH:1];
-  assign greater       = !res[`DATAWIDTH-1];
-  assign both_negative = in1_d[`DATAWIDTH-1] && in2_d[`DATAWIDTH-1];
+  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[`DATAWIDTH];
-
-  assign out_d_[`DATAWIDTH] =
-          (inOp_d==0) ? 1'b0 :
-          (inOp_d==1) ? 1'b0 :
-          (inOp_d==2) ? cout :
-          (inOp_d==3) ? cout :
-          (inOp_d==4) ? ~greater :
-          (inOp_d==5) ?  greater :
-          (inOp_d==6) ?  eq :
-          (inOp_d==9) ? ~greater :
+  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  } :
-          (inOp_d==9) ? (both_negative ? in1_d : (greater ? in1_d : in2_d)) :
+  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
-      `flush
       `cleanup
-      if (`out_draining) begin
+      if (out_draining && `out_empty) begin
         `drain_inOp
-        if      (inOp_d==0) `drain_in1
-        else if (inOp_d==1) `drain_in2
-        else if (inOp_d==9 &&  both_negative) begin `drain_in1 `drain_in2 end
-        else if (inOp_d==4 &&  greater) `drain_in1
-        else if (inOp_d==5 &&  greater) `drain_in2
-        else if (inOp_d==9 &&  greater) `drain_in1
-        else if (inOp_d==4 && !greater) `drain_in2
-        else if (inOp_d==5 && !greater) `drain_in1
-        else if (inOp_d==9 && !greater) `drain_in2
+        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_empty && `in1_full && `in2_full && `inOp_full) begin
-        `fill_out
+      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