Marina/MarinaTest.java: a few hacks to get the silicon working
[fleet.git] / ships / Counter.ship
index dbdb4a5..37aa452 100644 (file)
@@ -20,17 +20,96 @@ data  in:   inOp
 data  out:  out
 
 == Fleeterpreter ====================================================
-public void service() { }
+
+boolean full = false;
+boolean op_count = false;
+boolean op_repeat = false;
+boolean op_pass = false;
+boolean op_drop = false;
+boolean op_c1 = false;
+boolean op_c2 = false;
+boolean op_v1 = false;
+boolean op_v2 = false;
+long temp = 0;
+boolean out_draining;
+
+public void reset() {
+  super.reset();
+  full = false;
+  temp = 0;
+  out_draining = false;
+}
+public void service() {
+
+  if (!box_inOp.dataReadyForShip()) full = false;
+
+  if (out_draining && box_out.readyForDataFromShip()) {
+    if (op_count) temp = temp - box_in2.peekDataForShip();
+    else          temp--;
+    if (op_pass && op_v1) box_in1.removeDataForShip();
+    if (op_pass && op_v2) box_in2.removeDataForShip();
+    out_draining = false;
+
+  } else if (box_inOp.dataReadyForShip()) {
+    long op   = box_inOp.peekDataForShip();
+    op_count  = (op & 15)==12;
+    op_repeat = ((op>>2) & 3)==0;
+    op_pass   = ((op>>2) & 3)==1;
+    op_drop   = ((op>>2) & 3)==2;
+    op_c1     = (op_repeat || op_pass || op_drop) && !(((op>>1)&1)!=0);
+    op_c2     = (op_repeat || op_pass || op_drop) &&  (((op>>1)&1)!=0);
+    op_v1     = (op_repeat || op_pass || op_drop) && !(((op>>0)&1)!=0);
+    op_v2     = (op_repeat || op_pass || op_drop) &&  (((op>>0)&1)!=0);
+    if (!full) {
+      if (op_count && box_in1.dataReadyForShip() && box_in2.dataReadyForShip()) {
+        temp = box_in1.peekDataForShip() - box_in2.peekDataForShip();
+        box_in1.removeDataForShip();
+        full = true;
+      } else if (op_c1 && box_in1.dataReadyForShip()) {
+        temp = box_in1.peekDataForShip() - 1;
+        box_in1.removeDataForShip();
+        full = true;
+      } else if (op_c2 && box_in2.dataReadyForShip()) {
+        temp = box_in2.peekDataForShip() - 1;
+        box_in2.removeDataForShip();
+        full = true;
+      }
+    } else if (temp < 0) {
+      full = false;
+      box_inOp.removeDataForShip();
+      if (op_count) box_in2.removeDataForShip();
+      else if (op_repeat && op_v1) box_in1.removeDataForShip();
+      else if (op_repeat && op_v2) box_in2.removeDataForShip();
+
+    } else if (box_out.readyForDataFromShip()) {
+      if (op_count) {
+        out_draining = true;
+        box_out.addDataFromShip(temp, (temp - box_in2.peekDataForShip()) < 0);
+      } else if (op_v1 && box_in1.dataReadyForShip()) {
+        if (op_drop) { box_in1.removeDataForShip(); temp--; }
+        else         { box_out.addDataFromShip(box_in1.peekDataForShip(), temp<=0); out_draining = true; }
+      } else if (op_v2 && box_in2.dataReadyForShip()) {
+        if (op_drop) { box_in2.removeDataForShip(); temp--; }
+        else         { box_out.addDataFromShip(box_in2.peekDataForShip(), temp<=0); out_draining = true; }
+      }
+    }
+  }
+}
 
 == FleetSim ==============================================================
 
 == FPGA ==============================================================
 
-  reg [`DATAWIDTH-1:0] temp;
-  initial temp   = {`DATAWIDTH{1'b1}};
+  wire [3:0]              inOp_d_trunc;
+  assign                  inOp_d_trunc = inOp_d[3:0];
+
+  reg [`WORDWIDTH-1:0] temp;
+  initial temp   = {`WORDWIDTH{1'b1}};
+  reg     out_draining;
   reg     full;
   initial full = 0;
-  wire    op_count;  assign op_count  = inOp_d==12;
+  reg c_flag;
+  wire    op_count;  assign op_count  = inOp_d_trunc==12;
   wire    op_repeat; assign op_repeat = inOp_d[3:2]==0;
   wire    op_pass;   assign op_pass   = inOp_d[3:2]==1;
   wire    op_drop;   assign op_drop   = inOp_d[3:2]==2;
@@ -38,39 +117,47 @@ public void service() { }
   wire    op_c2;     assign op_c2     = (op_repeat || op_pass || op_drop) &&  inOp_d[1];
   wire    op_v1;     assign op_v1     = (op_repeat || op_pass || op_drop) && !inOp_d[0];
   wire    op_v2;     assign op_v2     = (op_repeat || op_pass || op_drop) &&  inOp_d[0];
-  assign  out_d_ = op_v1 ? in1_d : op_v2 ? in2_d : temp;
+
+  wire [`WORDWIDTH-1:0] pre_out;
+  assign  pre_out = op_v1 ? in1_d : op_v2 ? in2_d : temp;
+  assign  out_d_  = { c_flag, pre_out };
 
   // FIXME: REPEAT with a count of zero will not work properly
 
+  wire [`WORDWIDTH-1:0] temp_minus_in2;
+  assign temp_minus_in2 = (temp - in2_d);
+
   always @(posedge clk) begin
-    if (!rst) begin
+    if (rst) begin
       `reset
       full <= 0;
+      out_draining <= 0;
+      c_flag <= 0;
     end else begin
-      `flush
       `cleanup
       if (`inOp_empty)         full   <= 0;
-      if (`out_draining) begin
-        if (op_count) temp   <= temp - in2_d;
+      if (out_draining && `out_empty) begin
+        if (op_count) temp   <= temp_minus_in2;
         else          temp   <= temp - 1;
         if (op_pass && op_v1) `drain_in1
         if (op_pass && op_v2) `drain_in2
+        out_draining <= 0;
       end else if (`inOp_full) begin
         if (!full) begin
           if (op_count && `in1_full && `in2_full) begin
-            temp  <= in1_d[`DATAWIDTH-1:0] - in2_d[`DATAWIDTH-1:0];
+            temp  <= in1_d[`WORDWIDTH-1:0] - in2_d[`WORDWIDTH-1:0];
             `drain_in1
             full  <= 1;
           end else if (op_c1 && `in1_full) begin
-            temp  <= in1_d[`DATAWIDTH-1:0]-1;
+            temp  <= in1_d[`WORDWIDTH-1:0]-1;
             `drain_in1
             full  <= 1;
           end else if (op_c2 && `in2_full) begin
-            temp  <= in2_d[`DATAWIDTH-1:0]-1;
+            temp  <= in2_d[`WORDWIDTH-1:0]-1;
             `drain_in2
             full  <= 1;
           end
-        end else if (temp[`DATAWIDTH-1]) begin
+        end else if (temp[`WORDWIDTH-1]) begin
           full <= 0;
           `drain_inOp
           if (op_count) begin
@@ -83,12 +170,16 @@ public void service() { }
         end else if (`out_empty) begin
           if (op_count) begin
             `fill_out
+            out_draining <= 1;
+            c_flag <= temp_minus_in2[`WORDWIDTH-1];
           end else if (op_v1 && `in1_full) begin
             if (op_drop)    begin `drain_in1 temp <= temp-1; end
-            else            `fill_out
+            else            begin `fill_out out_draining <= 1; end
+            c_flag <= (temp==0);
           end else if (op_v2 && `in2_full) begin
             if (op_drop)    begin `drain_in2 temp <= temp-1; end
-            else            `fill_out
+            else            begin `fill_out out_draining <= 1; end
+            c_flag <= (temp==0);
           end
         end
       end
@@ -103,16 +194,20 @@ public void service() { }
 #expect 6
 #expect 3
 #expect 0
+#expect -1
 #expect 2
 #expect 1
 #expect 0
+#expect -1
 #expect 2
 #expect 2
 #expect 2
 #expect 2
+#expect -1
 #expect 9
 #expect 9
 #expect 9
+#expect -1
 
 debug.in:
   set ilc=*;
@@ -147,8 +242,12 @@ counter.inOp:
   deliver;
 
 counter.out:
-  set ilc=*;
+  head;
   collect, send to debug.in;
+  set flags a=c, b=b;
+  set word=-1;
+  [a] send to debug.in;
+  tail;
 
 
 == Contributors =========================================================