ship: Counter == Ports =========================================================== data in: in1 data in: in2 data in: inOp constant REPEAT_C1_V1: 0 constant REPEAT_C1_V2: 1 constant REPEAT_C2_V1: 2 constant REPEAT_C2_V2: 3 constant PASS_C1_V1: 4 constant PASS_C1_V2: 5 constant PASS_C2_V1: 6 constant PASS_C2_V2: 7 constant DROP_C1_V1: 8 constant DROP_C1_V2: 9 constant DROP_C2_V1: 10 constant DROP_C2_V2: 11 constant COUNT: 12 data out: out == Fleeterpreter ==================================================== 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 ============================================================== 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; 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; wire op_c1; assign op_c1 = (op_repeat || op_pass || op_drop) && !inOp_d[1]; 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]; 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 `reset full <= 0; out_draining <= 0; c_flag <= 0; end else begin `cleanup if (`inOp_empty) full <= 0; 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[`WORDWIDTH-1:0] - in2_d[`WORDWIDTH-1:0]; `drain_in1 full <= 1; end else if (op_c1 && `in1_full) begin temp <= in1_d[`WORDWIDTH-1:0]-1; `drain_in1 full <= 1; end else if (op_c2 && `in2_full) begin temp <= in2_d[`WORDWIDTH-1:0]-1; `drain_in2 full <= 1; end end else if (temp[`WORDWIDTH-1]) begin full <= 0; `drain_inOp if (op_count) begin `drain_in2 end else if (op_repeat && op_v1) begin `drain_in1 end else if (op_repeat && op_v2) begin `drain_in2 end 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 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 begin `fill_out out_draining <= 1; end c_flag <= (temp==0); end end end end end == Test ================================================================= #ship counter : Counter #ship debug : Debug #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=*; recv, deliver; counter.in1: set word=9; deliver; set word=3; deliver; set word=4; deliver; set word=3; deliver; counter.in2: set word=3; deliver; set word=1; deliver; set word=2; deliver; set word=9; deliver; counter.inOp: set word=12; deliver; deliver; set word=1; deliver; deliver; counter.out: head; collect, send to debug.in; set flags a=c, b=b; set word=-1; [a] send to debug.in; tail; == Contributors ========================================================= Adam Megacz