overhaul of interpreter, update ships to match; "make test" works now
[fleet.git] / ships / Counter.ship
1 ship: Counter
2
3 == Ports ===========================================================
4 data  in:   in1
5 data  in:   in2
6 data  in:   inOp
7   constant REPEAT_C1_V1: 0
8   constant REPEAT_C1_V2: 1
9   constant REPEAT_C2_V1: 2
10   constant REPEAT_C2_V2: 3
11   constant PASS_C1_V1:   4
12   constant PASS_C1_V2:   5
13   constant PASS_C2_V1:   6
14   constant PASS_C2_V2:   7
15   constant DROP_C1_V1:   8
16   constant DROP_C1_V2:   9
17   constant DROP_C2_V1:   10
18   constant DROP_C2_V2:   11
19   constant COUNT:        12
20 data  out:  out
21
22 == Fleeterpreter ====================================================
23
24 boolean full = false;
25 boolean op_count = false;
26 boolean op_repeat = false;
27 boolean op_pass = false;
28 boolean op_drop = false;
29 boolean op_c1 = false;
30 boolean op_c2 = false;
31 boolean op_v1 = false;
32 boolean op_v2 = false;
33 long temp = 0;
34
35 public void reset() {
36   super.reset();
37   full = false;
38   temp = 0;
39 }
40 public void service() {
41
42   if (full) {
43     if (temp < 0) {
44       temp = 0;
45       full = false;
46       box_inOp.removeDataForShip();
47       if (op_count) box_in2.removeDataForShip();
48       else if (op_repeat && op_v1) box_in1.removeDataForShip();
49       else if (op_repeat && op_v2) box_in2.removeDataForShip();
50
51     } else if (box_out.readyForDataFromShip()) {
52       if (op_count) {
53         box_out.addDataFromShip(temp);
54         temp = temp - box_in2.peekDataForShip();
55       } else if (op_v1 && box_in1.dataReadyForShip()) {
56         if (op_drop) { box_in1.removeDataForShip(); temp--; }
57         else         { box_out.addDataFromShip(op_pass ? box_in1.removeDataForShip() : box_in1.peekDataForShip()); temp--; }
58       } else if (op_v2 && box_in2.dataReadyForShip()) {
59         if (op_drop) { box_in2.removeDataForShip(); temp--; }
60         else         { box_out.addDataFromShip(op_pass ? box_in2.removeDataForShip() : box_in2.peekDataForShip()); temp--; }
61       }
62       
63     }
64
65   } else if (box_inOp.dataReadyForShip()) {
66     long op   = box_inOp.peekDataForShip();
67     op_count  = (op & 15)==12;
68     op_repeat = ((op>>2) & 3)==0;
69     op_pass   = ((op>>2) & 3)==1;
70     op_drop   = ((op>>2) & 3)==2;
71     op_c1     = (op_repeat || op_pass || op_drop) && !(((op>>1)&1)!=0);
72     op_c2     = (op_repeat || op_pass || op_drop) &&  (((op>>1)&1)!=0);
73     op_v1     = (op_repeat || op_pass || op_drop) && !(((op>>0)&1)!=0);
74     op_v2     = (op_repeat || op_pass || op_drop) &&  (((op>>0)&1)!=0);
75
76     if (op_count && (!box_in1.dataReadyForShip() || !box_in2.dataReadyForShip())) return;
77     if (op_c1    &&  !box_in1.dataReadyForShip()) return;
78     if (op_c2    &&  !box_in2.dataReadyForShip()) return;
79     
80     full = true;
81
82     if (op_count) temp = box_in1.removeDataForShip() - box_in2.peekDataForShip();
83     if (op_c1)    temp = box_in1.removeDataForShip()-1;
84     if (op_c2)    temp = box_in2.removeDataForShip()-1;
85   }
86 }
87
88 == FleetSim ==============================================================
89
90 == FPGA ==============================================================
91
92   wire [3:0]              inOp_d_trunc;
93   assign                  inOp_d_trunc = inOp_d[3:0];
94
95   reg [`WORDWIDTH-1:0] temp;
96   initial temp   = {`WORDWIDTH{1'b1}};
97   reg     out_draining;
98   reg     full;
99   initial full = 0;
100   wire    op_count;  assign op_count  = inOp_d_trunc==12;
101   wire    op_repeat; assign op_repeat = inOp_d[3:2]==0;
102   wire    op_pass;   assign op_pass   = inOp_d[3:2]==1;
103   wire    op_drop;   assign op_drop   = inOp_d[3:2]==2;
104   wire    op_c1;     assign op_c1     = (op_repeat || op_pass || op_drop) && !inOp_d[1];
105   wire    op_c2;     assign op_c2     = (op_repeat || op_pass || op_drop) &&  inOp_d[1];
106   wire    op_v1;     assign op_v1     = (op_repeat || op_pass || op_drop) && !inOp_d[0];
107   wire    op_v2;     assign op_v2     = (op_repeat || op_pass || op_drop) &&  inOp_d[0];
108   assign  out_d_ = op_v1 ? in1_d : op_v2 ? in2_d : temp;
109
110   // FIXME: REPEAT with a count of zero will not work properly
111
112   always @(posedge clk) begin
113     if (!rst) begin
114       `reset
115       full <= 0;
116       out_draining <= 0;
117     end else begin
118       `flush
119       `cleanup
120       if (`inOp_empty)         full   <= 0;
121       if (out_draining && `out_empty) begin
122         if (op_count) temp   <= temp - in2_d;
123         else          temp   <= temp - 1;
124         if (op_pass && op_v1) `drain_in1
125         if (op_pass && op_v2) `drain_in2
126         out_draining <= 0;
127       end else if (`inOp_full) begin
128         if (!full) begin
129           if (op_count && `in1_full && `in2_full) begin
130             temp  <= in1_d[`WORDWIDTH-1:0] - in2_d[`WORDWIDTH-1:0];
131             `drain_in1
132             full  <= 1;
133           end else if (op_c1 && `in1_full) begin
134             temp  <= in1_d[`WORDWIDTH-1:0]-1;
135             `drain_in1
136             full  <= 1;
137           end else if (op_c2 && `in2_full) begin
138             temp  <= in2_d[`WORDWIDTH-1:0]-1;
139             `drain_in2
140             full  <= 1;
141           end
142         end else if (temp[`WORDWIDTH-1]) begin
143           full <= 0;
144           `drain_inOp
145           if (op_count) begin
146             `drain_in2
147           end else if (op_repeat && op_v1) begin
148             `drain_in1
149           end else if (op_repeat && op_v2) begin
150             `drain_in2
151           end
152         end else if (`out_empty) begin
153           if (op_count) begin
154             `fill_out
155             out_draining <= 1;
156           end else if (op_v1 && `in1_full) begin
157             if (op_drop)    begin `drain_in1 temp <= temp-1; end
158             else            begin `fill_out out_draining <= 1; end
159           end else if (op_v2 && `in2_full) begin
160             if (op_drop)    begin `drain_in2 temp <= temp-1; end
161             else            begin `fill_out out_draining <= 1; end
162           end
163         end
164       end
165     end
166   end
167
168 == Test =================================================================
169
170 #ship counter : Counter
171 #ship debug   : Debug
172
173 #expect 6
174 #expect 3
175 #expect 0
176 #expect 2
177 #expect 1
178 #expect 0
179 #expect 2
180 #expect 2
181 #expect 2
182 #expect 2
183 #expect 9
184 #expect 9
185 #expect 9
186
187 debug.in:
188   set ilc=*;
189   recv, deliver;
190
191 counter.in1:
192   set word=9;
193   deliver;
194   set word=3;
195   deliver;
196   set word=4;
197   deliver;
198   set word=3;
199   deliver;
200
201 counter.in2:
202   set word=3;
203   deliver;
204   set word=1;
205   deliver;
206   set word=2;
207   deliver;
208   set word=9;
209   deliver;
210
211 counter.inOp:
212   set word=12;
213   deliver;
214   deliver;
215   set word=1;
216   deliver;
217   deliver;
218
219 counter.out:
220   set ilc=*;
221   collect, send to debug.in;
222
223
224 == Contributors =========================================================
225 Adam Megacz <megacz@cs.berkeley.edu>