1 \e[33mcommit f02c6f4bbf463472d3d68e52bd5ededd3c937f58
\e[m
\e[33m (
\e[m
\e[1;36mHEAD ->
\e[m
\e[1;32mmaster
\e[m
\e[33m,
\e[m
\e[1;31morigin/master
\e[m
\e[33m,
\e[m
\e[1;31morigin/HEAD
\e[m
\e[33m)
\e[m
2 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 Date: Fri Mar 15 12:37:14 2019 +0000
5 add parallel InputGroup unit test
7 \e[33mcommit b13c8a7a5368a53bedc71e5b8969c721103144c4
\e[m
8 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
9 Date: Fri Mar 15 10:59:44 2019 +0000
11 rename BufPipe example to ExampleBufPipe
13 \e[33mcommit a36447fcd4d4f049b7127e1fc02dc1390d05fa75
\e[m
14 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
15 Date: Fri Mar 15 09:59:07 2019 +0000
17 instantiate 2 FPGetOp instances and use them. a little awkwardly.
19 \e[33mcommit 092d2d78fa19a5c73863cb89c5d680cbd2afe027
\e[m
20 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
21 Date: Fri Mar 15 09:33:44 2019 +0000
25 \e[33mcommit 8989cd3452869d43a8a3655acffd3eb3288f5d9a
\e[m
26 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
27 Date: Fri Mar 15 09:22:58 2019 +0000
29 remove unnecessary code
31 \e[33mcommit b90c533476affe63a34292bfe54dde62a105bed8
\e[m
32 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
33 Date: Fri Mar 15 08:47:21 2019 +0000
35 add extra comment block explaining pipe stage example
37 \e[33mcommit 28a8ede4a797a76e83410fb42a9aaa02b44fb2ef
\e[m
38 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
39 Date: Fri Mar 15 08:37:18 2019 +0000
41 inverted busy signal and named it "ready"
43 \e[33mcommit 0ebc09c0a7b74e4807ccdb60ca0a10cbb605666a
\e[m
44 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
45 Date: Fri Mar 15 08:29:56 2019 +0000
49 \e[33mcommit 0bfbc8ff919f0cd9c7f01b4c711b1b91a53ad480
\e[m
50 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
51 Date: Fri Mar 15 08:28:18 2019 +0000
53 create classes for STB/BUSY, split in from out
55 \e[33mcommit ca218a65dc9af73965a5c4f105a780ed04b588e0
\e[m
56 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
57 Date: Fri Mar 15 00:31:30 2019 +0000
59 add use of FPState, not being used yet
61 \e[33mcommit ce7a1d5c48e987cbfb40236f13b17ffcea55b585
\e[m
62 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
63 Date: Thu Mar 14 13:32:06 2019 +0000
65 split pipeline test into 2 functions, one send, one receive
67 \e[33mcommit 481d00c37b31e7908e624235e6e9c93b12baeebb
\e[m
68 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
69 Date: Thu Mar 14 06:33:10 2019 +0000
71 got fpdiv up and running again
73 \e[33mcommit 286fdefc4bbe8c7b4bb34ae33b513e8bb81b3d7e
\e[m
74 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
75 Date: Thu Mar 14 05:41:02 2019 +0000
77 forgot to add submodules
79 \e[33mcommit 43c53078d577aa33d28ba0eb2af782b7d348a517
\e[m
80 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
81 Date: Thu Mar 14 05:09:36 2019 +0000
83 got rounding working again for fmul
85 \e[33mcommit 892d640f8224e6a52907c6899ab6ab671f5f53af
\e[m
86 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
87 Date: Thu Mar 14 04:42:53 2019 +0000
89 remove extra arg from old roundz function
91 \e[33mcommit ccd4d65a7bd2985edb5547daf7df623cda5ab9da
\e[m
92 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
93 Date: Thu Mar 14 04:33:01 2019 +0000
95 make a bit of a mess of the unit tests, getting mul up and running again
96 taking a copy (sigh) of the old version of check_case and get_case
98 \e[33mcommit 9b9732e1c96d085bc9c7b696e7c86dd0c4a4ae49
\e[m
99 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
100 Date: Thu Mar 14 04:17:28 2019 +0000
102 get roundz working again, needed for mul stage
104 \e[33mcommit 38452d7fb64752a897b26e1da96a27d3a5979a76
\e[m
105 Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
106 Date: Thu Mar 14 04:16:28 2019 +0000
108 add new FPNormaliseSingleMod, not tested
109 \e[1mdiff --git a/src/add/example_buf_pipe.py b/src/add/example_buf_pipe.py
\e[m
110 \e[1mindex 6678a67..00eecc3 100644
\e[m
111 \e[1m--- a/src/add/example_buf_pipe.py
\e[m
112 \e[1m+++ b/src/add/example_buf_pipe.py
\e[m
113 \e[36m@@ -12,12 +12,12 @@
\e[m
114 where data will flow on *every* clock when the conditions are right.
\e[m
116 input acceptance conditions are when:
\e[m
117 \e[31m- * incoming previous-stage strobe (i_p_stb) is HIGH
\e[m
118 \e[31m- * outgoing previous-stage busy (o_p_busy) is LOW
\e[m
119 \e[32m+
\e[m
\e[32m * incoming previous-stage strobe (i.p_valid) is HIGH
\e[m
120 \e[32m+
\e[m
\e[32m * outgoing previous-stage ready (o.p_ready) is LOW
\e[m
122 output transmission conditions are when:
\e[m
123 \e[31m- * outgoing next-stage strobe (o_n_stb) is HIGH
\e[m
124 \e[31m- * outgoing next-stage busy (i_n_busy) is LOW
\e[m
125 \e[32m+
\e[m
\e[32m * outgoing next-stage strobe (o.n_valid) is HIGH
\e[m
126 \e[32m+
\e[m
\e[32m * outgoing next-stage ready (i.n_ready) is LOW
\e[m
128 the tricky bit is when the input has valid data and the output is not
\e[m
129 ready to accept it. if it wasn't for the clock synchronisation, it
\e[m
130 \e[36m@@ -33,7 +33,7 @@
\e[m
131 we now effectively have *two* possible pieces of data to "choose" from:
\e[m
132 the buffered data, and the incoming data. the decision as to which
\e[m
133 to process and output is based on whether we are in "stall" or not.
\e[m
134 \e[31m- i.e. when the next stage is no longer busy, the output comes from
\e[m
135 \e[32m+
\e[m
\e[32m i.e. when the next stage is no longer ready, the output comes from
\e[m
136 the buffer if a stall had previously occurred, otherwise it comes
\e[m
137 direct from processing the input.
\e[m
139 \e[36m@@ -69,7 +69,17 @@
\e[m
\e[mclass ExampleStage:
\e[m
141 def __init__(self):
\e[m
142 """ i_data can be a DIFFERENT type from everything else
\e[m
143 \e[31m- o_data, r_data and result must be of the same type
\e[m
144 \e[32m+
\e[m
\e[32m o_data, r_data and result are best of the same type.
\e[m
145 \e[32m+
\e[m
\e[32m however this is not strictly necessary. an intermediate
\e[m
146 \e[32m+
\e[m
\e[32m transformation process could hypothetically be applied, however
\e[m
147 \e[32m+
\e[m
\e[32m it is result and r_data that definitively need to be of the same
\e[m
148 \e[32m+
\e[m
\e[32m (intermediary) type, as it is both result and r_data that
\e[m
149 \e[32m+
\e[m
\e[32m are transferred into o_data:
\e[m
151 \e[32m+
\e[m
\e[32m i_data -> process() -> result --> o_data
\e[m
152 \e[32m+
\e[m
\e[32m | ^
\e[m
153 \e[32m+
\e[m
\e[32m | |
\e[m
154 \e[32m+
\e[m
\e[32m +-> r_data -+
\e[m
156 self.i_data = Signal(16)
\e[m
157 self.r_data = Signal(16)
\e[m
158 \e[36m@@ -83,7 +93,9 @@
\e[m
\e[mclass ExampleStage:
\e[m
159 return self.result.eq(self.i_data + 1)
\e[m
161 def update_buffer(self):
\e[m
162 \e[31m- """ copies the result into the intermediate register r_data
\e[m
163 \e[32m+
\e[m
\e[32m """ copies the result into the intermediate register r_data,
\e[m
164 \e[32m+
\e[m
\e[32m which will need to be outputted on a subsequent cycle
\e[m
165 \e[32m+
\e[m
\e[32m prior to allowing "normal" operation.
\e[m
167 return self.r_data.eq(self.result)
\e[m
169 \e[36m@@ -100,88 +112,98 @@
\e[m
\e[mclass ExampleStage:
\e[m
171 return [self.i_data, self.o_data]
\e[m
173 \e[32m+
\e[m
\e[32mclass IOAckIn:
\e[m
175 \e[32m+
\e[m
\e[32m def __init__(self):
\e[m
176 \e[32m+
\e[m
\e[32m self.p_valid = Signal() # >>in - comes in from PREVIOUS stage
\e[m
177 \e[32m+
\e[m
\e[32m self.n_ready = Signal() # in<< - comes in from the NEXT stage
\e[m
180 \e[32m+
\e[m
\e[32mclass IOAckOut:
\e[m
182 \e[32m+
\e[m
\e[32m def __init__(self):
\e[m
183 \e[32m+
\e[m
\e[32m self.n_valid = Signal() # out>> - goes out to the NEXT stage
\e[m
184 \e[32m+
\e[m
\e[32m self.p_ready = Signal() # <<out - goes out to the PREVIOUS stage
\e[m
187 class BufferedPipeline:
\e[m
188 """ buffered pipeline stage
\e[m
190 \e[31m- stage-1 i_p_stb >>in stage o_n_stb out>> stage+1
\e[m
191 \e[31m- stage-1 o_p_busy <<out stage i_n_busy <<in stage+1
\e[m
192 \e[31m- stage-1 i_data >>in stage o_data out>> stage+1
\e[m
193 \e[32m+
\e[m
\e[32m stage-1 i.p_valid >>in stage o.n_valid out>> stage+1
\e[m
194 \e[32m+
\e[m
\e[32m stage-1 o.p_ready <<out stage i.n_ready <<in stage+1
\e[m
195 \e[32m+
\e[m
\e[32m stage-1 i_data >>in stage o_data out>> stage+1
\e[m
197 +-------> process
\e[m
201 def __init__(self):
\e[m
202 \e[31m- # input: strobe comes in from previous stage, busy comes in from next
\e[m
203 \e[31m- #self.i_p_rst = Signal() # >>in - comes in from PREVIOUS stage
\e[m
204 \e[31m- self.i_p_stb = Signal() # >>in - comes in from PREVIOUS stage
\e[m
205 \e[31m- self.i_n_busy = Signal() # in<< - comes in from the NEXT stage
\e[m
206 \e[32m+
\e[m
\e[32m # input: strobe comes in from previous stage, ready comes in from next
\e[m
207 \e[32m+
\e[m
\e[32m self.i = IOAckIn()
\e[m
208 \e[32m+
\e[m
\e[32m #self.i.p_valid = Signal() # >>in - comes in from PREVIOUS stage
\e[m
209 \e[32m+
\e[m
\e[32m #self.i.n_ready = Signal() # in<< - comes in from the NEXT stage
\e[m
211 \e[31m- # output: strobe goes out to next stage, busy comes in from previous
\e[m
212 \e[31m- self.o_n_stb = Signal() # out>> - goes out to the NEXT stage
\e[m
213 \e[31m- self.o_p_busy = Signal() # <<out - goes out to the PREVIOUS stage
\e[m
214 \e[32m+
\e[m
\e[32m # output: strobe goes out to next stage, ready comes in from previous
\e[m
215 \e[32m+
\e[m
\e[32m self.o = IOAckOut()
\e[m
216 \e[32m+
\e[m
\e[32m #self.o.n_valid = Signal() # out>> - goes out to the NEXT stage
\e[m
217 \e[32m+
\e[m
\e[32m #self.o.p_ready = Signal() # <<out - goes out to the PREVIOUS stage
\e[m
219 def elaborate(self, platform):
\e[m
222 # establish some combinatorial temporaries
\e[m
223 \e[31m- o_p_busyn = Signal(reset_less=True)
\e[m
224 \e[31m- o_n_stbn = Signal(reset_less=True)
\e[m
225 \e[31m- i_n_busyn = Signal(reset_less=True)
\e[m
226 \e[31m- i_p_stb_o_p_busyn = Signal(reset_less=True)
\e[m
227 \e[31m- m.d.comb += [i_n_busyn.eq(~self.i_n_busy),
\e[m
228 \e[31m- o_n_stbn.eq(~self.o_n_stb),
\e[m
229 \e[31m- o_p_busyn.eq(~self.o_p_busy),
\e[m
230 \e[31m- i_p_stb_o_p_busyn.eq(self.i_p_stb & o_p_busyn),
\e[m
231 \e[32m+
\e[m
\e[32m o_n_validn = Signal(reset_less=True)
\e[m
232 \e[32m+
\e[m
\e[32m i_p_valid_o_p_ready = Signal(reset_less=True)
\e[m
233 \e[32m+
\e[m
\e[32m m.d.comb += [o_n_validn.eq(~self.o.n_valid),
\e[m
234 \e[32m+
\e[m
\e[32m i_p_valid_o_p_ready.eq(self.i.p_valid & self.o.p_ready),
\e[m
237 # store result of processing in combinatorial temporary
\e[m
238 \e[31m- with m.If(self.i_p_stb): # input is valid: process it
\e[m
239 \e[32m+
\e[m
\e[32m with m.If(self.i.p_valid): # input is valid: process it
\e[m
240 m.d.comb += self.stage.process()
\e[m
241 # if not in stall condition, update the temporary register
\e[m
242 \e[31m- with m.If(o_p_busyn): # not stalled
\e[m
243 \e[32m+
\e[m
\e[32m with m.If(self.o.p_ready): # not stalled
\e[m
244 m.d.sync += self.stage.update_buffer()
\e[m
246 \e[31m- #with m.If(self.i_p_rst): # reset
\e[m
247 \e[31m- # m.d.sync += self.o_n_stb.eq(0)
\e[m
248 \e[31m- # m.d.sync += self.o_p_busy.eq(0)
\e[m
249 \e[31m- with m.If(i_n_busyn): # next stage is not busy
\e[m
250 \e[31m- with m.If(o_p_busyn): # not stalled
\e[m
251 \e[32m+
\e[m
\e[32m #with m.If(self.i.p_rst): # reset
\e[m
252 \e[32m+
\e[m
\e[32m # m.d.sync += self.o.n_valid.eq(0)
\e[m
253 \e[32m+
\e[m
\e[32m # m.d.sync += self.o.p_ready.eq(0)
\e[m
254 \e[32m+
\e[m
\e[32m with m.If(self.i.n_ready): # next stage is ready
\e[m
255 \e[32m+
\e[m
\e[32m with m.If(self.o.p_ready): # not stalled
\e[m
256 # nothing in buffer: send (processed) input direct to output
\e[m
257 \e[31m- m.d.sync += [self.o_n_stb.eq(self.i_p_stb),
\e[m
258 \e[32m+
\e[m
\e[32m m.d.sync += [self.o.n_valid.eq(self.i.p_valid),
\e[m
259 self.stage.update_output(),
\e[m
261 \e[31m- with m.Else(): # o_p_busy is true, and something is in our buffer.
\e[m
262 \e[32m+
\e[m
\e[32m with m.Else(): # o.p_ready is false, and something is in buffer.
\e[m
263 # Flush the [already processed] buffer to the output port.
\e[m
264 \e[31m- m.d.sync += [self.o_n_stb.eq(1),
\e[m
265 \e[32m+
\e[m
\e[32m m.d.sync += [self.o.n_valid.eq(1),
\e[m
266 self.stage.flush_buffer(),
\e[m
267 # clear stall condition, declare register empty.
\e[m
268 \e[31m- self.o_p_busy.eq(0),
\e[m
269 \e[32m+
\e[m
\e[32m self.o.p_ready.eq(1),
\e[m
271 \e[31m- # ignore input, since o_p_busy is also true.
\e[m
272 \e[32m+
\e[m
\e[32m # ignore input, since o.p_ready is also false.
\e[m
274 \e[31m- # (i_n_busy) is true here: next stage is busy
\e[m
275 \e[31m- with m.Elif(o_n_stbn): # next stage being told "not busy"
\e[m
276 \e[31m- m.d.sync += [self.o_n_stb.eq(self.i_p_stb),
\e[m
277 \e[31m- self.o_p_busy.eq(0), # Keep the buffer empty
\e[m
278 \e[32m+
\e[m
\e[32m # (i.n_ready) is false here: next stage is ready
\e[m
279 \e[32m+
\e[m
\e[32m with m.Elif(o_n_validn): # next stage being told "ready"
\e[m
280 \e[32m+
\e[m
\e[32m m.d.sync += [self.o.n_valid.eq(self.i.p_valid),
\e[m
281 \e[32m+
\e[m
\e[32m self.o.p_ready.eq(1), # Keep the buffer empty
\e[m
282 # set the output data (from comb result)
\e[m
283 self.stage.update_output(),
\e[m
285 \e[31m- # (i_n_busy) and (o_n_stb) both true:
\e[m
286 \e[31m- with m.Elif(i_p_stb_o_p_busyn):
\e[m
287 \e[31m- # If next stage *is* busy, and not stalled yet, accept input
\e[m
288 \e[31m- m.d.sync += self.o_p_busy.eq(self.i_p_stb & self.o_n_stb)
\e[m
289 \e[32m+
\e[m
\e[32m # (i.n_ready) false and (o.n_valid) true:
\e[m
290 \e[32m+
\e[m
\e[32m with m.Elif(i_p_valid_o_p_ready):
\e[m
291 \e[32m+
\e[m
\e[32m # If next stage *is* ready, and not stalled yet, accept input
\e[m
292 \e[32m+
\e[m
\e[32m m.d.sync += self.o.p_ready.eq(~(self.i.p_valid & self.o.n_valid))
\e[m
297 \e[31m- return [self.i_p_stb, self.i_n_busy,
\e[m
298 \e[31m- self.o_n_stb, self.o_p_busy,
\e[m
299 \e[32m+
\e[m
\e[32m return [self.i.p_valid, self.i.n_ready,
\e[m
300 \e[32m+
\e[m
\e[32m self.o.n_valid, self.o.p_ready,
\e[m
304 \e[31m-class BufPipe(BufferedPipeline):
\e[m
305 \e[32m+
\e[m
\e[32mclass ExampleBufPipe(BufferedPipeline):
\e[m
307 def __init__(self):
\e[m
308 BufferedPipeline.__init__(self)
\e[m
309 \e[1mdiff --git a/src/add/fmul.py b/src/add/fmul.py
\e[m
310 \e[1mindex 130d49e..5b6da94 100644
\e[m
311 \e[1m--- a/src/add/fmul.py
\e[m
312 \e[1m+++ b/src/add/fmul.py
\e[m
313 \e[36m@@ -2,7 +2,8 @@
\e[m
\e[mfrom nmigen import Module, Signal, Cat, Mux, Array, Const
\e[m
314 from nmigen.cli import main, verilog
\e[m
316 from fpbase import FPNumIn, FPNumOut, FPOp, Overflow, FPBase
\e[m
317 \e[31m-from nmigen_add_experiment import FPState
\e[m
318 \e[32m+
\e[m
\e[32m+from nmigen_add_experiment import FPState, FPGetOp
\e[m
321 class FPMUL(FPBase):
\e[m
323 \e[1mdiff --git a/src/add/nmigen_div_experiment.py b/src/add/nmigen_div_experiment.py
\e[m
324 \e[1mindex ff4c966..e074c5c 100644
\e[m
325 \e[1m--- a/src/add/nmigen_div_experiment.py
\e[m
326 \e[1m+++ b/src/add/nmigen_div_experiment.py
\e[m
327 \e[36m@@ -6,6 +6,7 @@
\e[m
\e[mfrom nmigen import Module, Signal, Const, Cat
\e[m
328 from nmigen.cli import main, verilog
\e[m
330 from fpbase import FPNumIn, FPNumOut, FPOp, Overflow, FPBase
\e[m
331 \e[32m+
\e[m
\e[32mfrom nmigen_add_experiment import FPState, FPGetOp
\e[m
334 def __init__(self, width):
\e[m
335 \e[36m@@ -36,6 +37,12 @@
\e[m
\e[mclass FPDIV(FPBase):
\e[m
336 self.in_b = FPOp(width)
\e[m
337 self.out_z = FPOp(width)
\e[m
339 \e[32m+
\e[m
\e[32m self.states = []
\e[m
341 \e[32m+
\e[m
\e[32m def add_state(self, state):
\e[m
342 \e[32m+
\e[m
\e[32m self.states.append(state)
\e[m
343 \e[32m+
\e[m
\e[32m return state
\e[m
345 def get_fragment(self, platform=None):
\e[m
346 """ creates the HDL code-fragment for FPDiv
\e[m
348 \e[36m@@ -59,14 +66,26 @@
\e[m
\e[mclass FPDIV(FPBase):
\e[m
352 \e[32m+
\e[m
\e[32m geta = FPGetOp("get_a", "get_b", self.in_a, self.width)
\e[m
353 \e[32m+
\e[m
\e[32m geta.setup(m, self.in_a)
\e[m
355 with m.State("get_a"):
\e[m
356 \e[31m- self.get_op(m, self.in_a, a, "get_b")
\e[m
357 \e[32m+
\e[m
\e[32m geta.action(m)
\e[m
358 \e[32m+
\e[m
\e[32m with m.If(geta.out_decode):
\e[m
359 \e[32m+
\e[m
\e[32m m.d.sync += a.decode(self.in_a.v)
\e[m
360 \e[32m+
\e[m
\e[32m #self.get_op(m, self.in_a, a, "get_b")
\e[m
365 \e[32m+
\e[m
\e[32m getb = FPGetOp("get_b", "special_cases", self.in_b, self.width)
\e[m
366 \e[32m+
\e[m
\e[32m getb.setup(m, self.in_b)
\e[m
368 with m.State("get_b"):
\e[m
369 \e[31m- self.get_op(m, self.in_b, b, "special_cases")
\e[m
370 \e[32m+
\e[m
\e[32m getb.action(m)
\e[m
371 \e[32m+
\e[m
\e[32m with m.If(getb.out_decode):
\e[m
372 \e[32m+
\e[m
\e[32m m.d.sync += b.decode(self.in_b.v)
\e[m
373 \e[32m+
\e[m
\e[32m #self.get_op(m, self.in_b, b, "special_cases")
\e[m
376 # special cases: NaNs, infs, zeros, denormalised
\e[m
377 \e[1mdiff --git a/src/add/test_buf_pipe.py b/src/add/test_buf_pipe.py
\e[m
378 \e[1mindex 8590cca..fa23eac 100644
\e[m
379 \e[1m--- a/src/add/test_buf_pipe.py
\e[m
380 \e[1m+++ b/src/add/test_buf_pipe.py
\e[m
381 \e[36m@@ -1,86 +1,90 @@
\e[m
382 from nmigen import Module, Signal
\e[m
383 from nmigen.compat.sim import run_simulation
\e[m
384 \e[31m-from example_buf_pipe import BufPipe
\e[m
385 \e[32m+
\e[m
\e[32mfrom example_buf_pipe import ExampleBufPipe
\e[m
386 from random import randint
\e[m
389 \e[31m-def check_o_n_stb(dut, val):
\e[m
390 \e[31m- o_n_stb = yield dut.o_n_stb
\e[m
391 \e[31m- assert o_n_stb == val
\e[m
392 \e[32m+
\e[m
\e[32mdef check_o_n_valid(dut, val):
\e[m
393 \e[32m+
\e[m
\e[32m o_n_valid = yield dut.o.n_valid
\e[m
394 \e[32m+
\e[m
\e[32m assert o_n_valid == val
\e[m
396 \e[32m+
\e[m
\e[32mdef check_o_n_valid2(dut, val):
\e[m
397 \e[32m+
\e[m
\e[32m o_n_valid = yield dut.o_n_valid
\e[m
398 \e[32m+
\e[m
\e[32m assert o_n_valid == val
\e[m
401 def testbench(dut):
\e[m
402 #yield dut.i_p_rst.eq(1)
\e[m
403 \e[31m- yield dut.i_n_busy.eq(1)
\e[m
404 \e[31m- yield dut.o_p_busy.eq(1)
\e[m
405 \e[32m+
\e[m
\e[32m yield dut.i.n_ready.eq(0)
\e[m
406 \e[32m+
\e[m
\e[32m yield dut.o.p_ready.eq(0)
\e[m
409 #yield dut.i_p_rst.eq(0)
\e[m
410 \e[31m- yield dut.i_n_busy.eq(0)
\e[m
411 \e[32m+
\e[m
\e[32m yield dut.i.n_ready.eq(1)
\e[m
412 yield dut.stage.i_data.eq(5)
\e[m
413 \e[31m- yield dut.i_p_stb.eq(1)
\e[m
414 \e[32m+
\e[m
\e[32m yield dut.i.p_valid.eq(1)
\e[m
417 yield dut.stage.i_data.eq(7)
\e[m
418 \e[31m- yield from check_o_n_stb(dut, 0) # effects of i_p_stb delayed
\e[m
419 \e[32m+
\e[m
\e[32m yield from check_o_n_valid(dut, 0) # effects of i_p_valid delayed
\e[m
421 \e[31m- yield from check_o_n_stb(dut, 1) # ok *now* i_p_stb effect is felt
\e[m
422 \e[32m+
\e[m
\e[32m yield from check_o_n_valid(dut, 1) # ok *now* i_p_valid effect is felt
\e[m
424 yield dut.stage.i_data.eq(2)
\e[m
426 \e[31m- yield dut.i_n_busy.eq(1) # begin going into "stall" (next stage says busy)
\e[m
427 \e[32m+
\e[m
\e[32m yield dut.i.n_ready.eq(0) # begin going into "stall" (next stage says ready)
\e[m
428 yield dut.stage.i_data.eq(9)
\e[m
430 \e[31m- yield dut.i_p_stb.eq(0)
\e[m
431 \e[32m+
\e[m
\e[32m yield dut.i.p_valid.eq(0)
\e[m
432 yield dut.stage.i_data.eq(12)
\e[m
434 yield dut.stage.i_data.eq(32)
\e[m
435 \e[31m- yield dut.i_n_busy.eq(0)
\e[m
436 \e[32m+
\e[m
\e[32m yield dut.i.n_ready.eq(1)
\e[m
438 \e[31m- yield from check_o_n_stb(dut, 1) # buffer still needs to output
\e[m
439 \e[32m+
\e[m
\e[32m yield from check_o_n_valid(dut, 1) # buffer still needs to output
\e[m
441 \e[31m- yield from check_o_n_stb(dut, 1) # buffer still needs to output
\e[m
442 \e[32m+
\e[m
\e[32m yield from check_o_n_valid(dut, 1) # buffer still needs to output
\e[m
444 \e[31m- yield from check_o_n_stb(dut, 0) # buffer outputted, *now* we're done.
\e[m
445 \e[32m+
\e[m
\e[32m yield from check_o_n_valid(dut, 0) # buffer outputted, *now* we're done.
\e[m
449 def testbench2(dut):
\e[m
450 \e[31m- #yield dut.i_p_rst.eq(1)
\e[m
451 \e[31m- yield dut.i_n_busy.eq(1)
\e[m
452 \e[31m- #yield dut.o_p_busy.eq(1)
\e[m
453 \e[32m+
\e[m
\e[32m #yield dut.i.p_rst.eq(1)
\e[m
454 \e[32m+
\e[m
\e[32m yield dut.i_n_ready.eq(0)
\e[m
455 \e[32m+
\e[m
\e[32m #yield dut.o.p_ready.eq(0)
\e[m
458 \e[31m- #yield dut.i_p_rst.eq(0)
\e[m
459 \e[31m- yield dut.i_n_busy.eq(0)
\e[m
460 \e[32m+
\e[m
\e[32m #yield dut.i.p_rst.eq(0)
\e[m
461 \e[32m+
\e[m
\e[32m yield dut.i_n_ready.eq(1)
\e[m
462 yield dut.i_data.eq(5)
\e[m
463 \e[31m- yield dut.i_p_stb.eq(1)
\e[m
464 \e[32m+
\e[m
\e[32m yield dut.i_p_valid.eq(1)
\e[m
467 yield dut.i_data.eq(7)
\e[m
468 \e[31m- yield from check_o_n_stb(dut, 0) # effects of i_p_stb delayed 2 clocks
\e[m
469 \e[32m+
\e[m
\e[32m yield from check_o_n_valid2(dut, 0) # effects of i_p_valid delayed 2 clocks
\e[m
471 \e[31m- yield from check_o_n_stb(dut, 0) # effects of i_p_stb delayed 2 clocks
\e[m
472 \e[32m+
\e[m
\e[32m yield from check_o_n_valid2(dut, 0) # effects of i_p_valid delayed 2 clocks
\e[m
474 yield dut.i_data.eq(2)
\e[m
476 \e[31m- yield from check_o_n_stb(dut, 1) # ok *now* i_p_stb effect is felt
\e[m
477 \e[31m- yield dut.i_n_busy.eq(1) # begin going into "stall" (next stage says busy)
\e[m
478 \e[32m+
\e[m
\e[32m yield from check_o_n_valid2(dut, 1) # ok *now* i_p_valid effect is felt
\e[m
479 \e[32m+
\e[m
\e[32m yield dut.i_n_ready.eq(0) # begin going into "stall" (next stage says ready)
\e[m
480 yield dut.i_data.eq(9)
\e[m
482 \e[31m- yield dut.i_p_stb.eq(0)
\e[m
483 \e[32m+
\e[m
\e[32m yield dut.i_p_valid.eq(0)
\e[m
484 yield dut.i_data.eq(12)
\e[m
486 yield dut.i_data.eq(32)
\e[m
487 \e[31m- yield dut.i_n_busy.eq(0)
\e[m
488 \e[32m+
\e[m
\e[32m yield dut.i_n_ready.eq(1)
\e[m
490 \e[31m- yield from check_o_n_stb(dut, 1) # buffer still needs to output
\e[m
491 \e[32m+
\e[m
\e[32m yield from check_o_n_valid2(dut, 1) # buffer still needs to output
\e[m
493 \e[31m- yield from check_o_n_stb(dut, 1) # buffer still needs to output
\e[m
494 \e[32m+
\e[m
\e[32m yield from check_o_n_valid2(dut, 1) # buffer still needs to output
\e[m
496 \e[31m- yield from check_o_n_stb(dut, 1) # buffer still needs to output
\e[m
497 \e[32m+
\e[m
\e[32m yield from check_o_n_valid2(dut, 1) # buffer still needs to output
\e[m
499 \e[31m- yield from check_o_n_stb(dut, 0) # buffer outputted, *now* we're done.
\e[m
500 \e[32m+
\e[m
\e[32m yield from check_o_n_valid2(dut, 0) # buffer outputted, *now* we're done.
\e[m
504 \e[36m@@ -104,28 +108,28 @@
\e[m
\e[mclass Test3:
\e[m
507 send = randint(0, send_range) != 0
\e[m
508 \e[31m- o_p_busy = yield self.dut.o_p_busy
\e[m
509 \e[31m- if o_p_busy:
\e[m
510 \e[32m+
\e[m
\e[32m o_p_ready = yield self.dut.o.p_ready
\e[m
511 \e[32m+
\e[m
\e[32m if not o_p_ready:
\e[m
514 if send and self.i != len(self.data):
\e[m
515 \e[31m- yield self.dut.i_p_stb.eq(1)
\e[m
516 \e[32m+
\e[m
\e[32m yield self.dut.i.p_valid.eq(1)
\e[m
517 yield self.dut.stage.i_data.eq(self.data[self.i])
\e[m
520 \e[31m- yield self.dut.i_p_stb.eq(0)
\e[m
521 \e[32m+
\e[m
\e[32m yield self.dut.i.p_valid.eq(0)
\e[m
525 while self.o != len(self.data):
\e[m
526 stall_range = randint(0, 3)
\e[m
527 for j in range(randint(1,10)):
\e[m
528 \e[31m- stall = randint(0, stall_range) == 0
\e[m
529 \e[31m- yield self.dut.i_n_busy.eq(stall)
\e[m
530 \e[32m+
\e[m
\e[32m stall = randint(0, stall_range) != 0
\e[m
531 \e[32m+
\e[m
\e[32m yield self.dut.i.n_ready.eq(stall)
\e[m
533 \e[31m- o_n_stb = yield self.dut.o_n_stb
\e[m
534 \e[31m- i_n_busy = yield self.dut.i_n_busy
\e[m
535 \e[31m- if not o_n_stb or i_n_busy:
\e[m
536 \e[32m+
\e[m
\e[32m o_n_valid = yield self.dut.o.n_valid
\e[m
537 \e[32m+
\e[m
\e[32m i_n_ready = yield self.dut.i.n_ready
\e[m
538 \e[32m+
\e[m
\e[32m if not o_n_valid or not i_n_ready:
\e[m
540 o_data = yield self.dut.stage.o_data
\e[m
541 assert o_data == self.data[self.o] + 1, \
\e[m
542 \e[36m@@ -144,21 +148,21 @@
\e[m
\e[mdef testbench4(dut):
\e[m
546 \e[31m- stall = randint(0, 3) == 0
\e[m
547 \e[32m+
\e[m
\e[32m stall = randint(0, 3) != 0
\e[m
548 send = randint(0, 5) != 0
\e[m
549 \e[31m- yield dut.i_n_busy.eq(stall)
\e[m
550 \e[31m- o_p_busy = yield dut.o_p_busy
\e[m
551 \e[31m- if not o_p_busy:
\e[m
552 \e[32m+
\e[m
\e[32m yield dut.i_n_ready.eq(stall)
\e[m
553 \e[32m+
\e[m
\e[32m o_p_ready = yield dut.o_p_ready
\e[m
554 \e[32m+
\e[m
\e[32m if o_p_ready:
\e[m
555 if send and i != len(data):
\e[m
556 \e[31m- yield dut.i_p_stb.eq(1)
\e[m
557 \e[32m+
\e[m
\e[32m yield dut.i_p_valid.eq(1)
\e[m
558 yield dut.i_data.eq(data[i])
\e[m
561 \e[31m- yield dut.i_p_stb.eq(0)
\e[m
562 \e[32m+
\e[m
\e[32m yield dut.i_p_valid.eq(0)
\e[m
564 \e[31m- o_n_stb = yield dut.o_n_stb
\e[m
565 \e[31m- i_n_busy = yield dut.i_n_busy
\e[m
566 \e[31m- if o_n_stb and not i_n_busy:
\e[m
567 \e[32m+
\e[m
\e[32m o_n_valid = yield dut.o_n_valid
\e[m
568 \e[32m+
\e[m
\e[32m i_n_ready = yield dut.i_n_ready
\e[m
569 \e[32m+
\e[m
\e[32m if o_n_valid and i_n_ready:
\e[m
570 o_data = yield dut.o_data
\e[m
571 assert o_data == data[o] + 2, "%d-%d data %x not match %x\n" \
\e[m
572 % (i, o, o_data, data[o])
\e[m
573 \e[36m@@ -167,26 +171,26 @@
\e[m
\e[mdef testbench4(dut):
\e[m
577 \e[31m-class BufPipe2:
\e[m
578 \e[32m+
\e[m
\e[32mclass ExampleBufPipe2:
\e[m
580 connect these: ------|---------------|
\e[m
582 \e[31m- i_p_stb >>in pipe1 o_n_stb out>> i_p_stb >>in pipe2
\e[m
583 \e[31m- o_p_busy <<out pipe1 i_n_busy <<in o_p_busy <<out pipe2
\e[m
584 \e[32m+
\e[m
\e[32m i_p_valid >>in pipe1 o_n_valid out>> i_p_valid >>in pipe2
\e[m
585 \e[32m+
\e[m
\e[32m o_p_ready <<out pipe1 i_n_ready <<in o_p_ready <<out pipe2
\e[m
586 stage.i_data >>in pipe1 o_data out>> stage.i_data >>in pipe2
\e[m
588 def __init__(self):
\e[m
589 \e[31m- self.pipe1 = BufPipe()
\e[m
590 \e[31m- self.pipe2 = BufPipe()
\e[m
591 \e[32m+
\e[m
\e[32m self.pipe1 = ExampleBufPipe()
\e[m
592 \e[32m+
\e[m
\e[32m self.pipe2 = ExampleBufPipe()
\e[m
595 \e[31m- self.i_p_stb = Signal() # >>in - comes in from PREVIOUS stage
\e[m
596 \e[31m- self.i_n_busy = Signal() # in<< - comes in from the NEXT stage
\e[m
597 \e[32m+
\e[m
\e[32m self.i_p_valid = Signal() # >>in - comes in from PREVIOUS stage
\e[m
598 \e[32m+
\e[m
\e[32m self.i_n_ready = Signal() # in<< - comes in from the NEXT stage
\e[m
599 self.i_data = Signal(32) # >>in - comes in from the PREVIOUS stage
\e[m
602 \e[31m- self.o_n_stb = Signal() # out>> - goes out to the NEXT stage
\e[m
603 \e[31m- self.o_p_busy = Signal() # <<out - goes out to the PREVIOUS stage
\e[m
604 \e[32m+
\e[m
\e[32m self.o_n_valid = Signal() # out>> - goes out to the NEXT stage
\e[m
605 \e[32m+
\e[m
\e[32m self.o_p_ready = Signal() # <<out - goes out to the PREVIOUS stage
\e[m
606 self.o_data = Signal(32) # out>> - goes out to the NEXT stage
\e[m
608 def elaborate(self, platform):
\e[m
609 \e[36m@@ -194,37 +198,37 @@
\e[m
\e[mclass BufPipe2:
\e[m
610 m.submodules.pipe1 = self.pipe1
\e[m
611 m.submodules.pipe2 = self.pipe2
\e[m
613 \e[31m- # connect inter-pipe input/output stb/busy/data
\e[m
614 \e[31m- m.d.comb += self.pipe2.i_p_stb.eq(self.pipe1.o_n_stb)
\e[m
615 \e[31m- m.d.comb += self.pipe1.i_n_busy.eq(self.pipe2.o_p_busy)
\e[m
616 \e[32m+
\e[m
\e[32m # connect inter-pipe input/output valid/ready/data
\e[m
617 \e[32m+
\e[m
\e[32m m.d.comb += self.pipe2.i.p_valid.eq(self.pipe1.o.n_valid)
\e[m
618 \e[32m+
\e[m
\e[32m m.d.comb += self.pipe1.i.n_ready.eq(self.pipe2.o.p_ready)
\e[m
619 m.d.comb += self.pipe2.stage.i_data.eq(self.pipe1.stage.o_data)
\e[m
621 # inputs/outputs to the module: pipe1 connections here (LHS)
\e[m
622 \e[31m- m.d.comb += self.pipe1.i_p_stb.eq(self.i_p_stb)
\e[m
623 \e[31m- m.d.comb += self.o_p_busy.eq(self.pipe1.o_p_busy)
\e[m
624 \e[32m+
\e[m
\e[32m m.d.comb += self.pipe1.i.p_valid.eq(self.i_p_valid)
\e[m
625 \e[32m+
\e[m
\e[32m m.d.comb += self.o_p_ready.eq(self.pipe1.o.p_ready)
\e[m
626 m.d.comb += self.pipe1.stage.i_data.eq(self.i_data)
\e[m
628 # now pipe2 connections (RHS)
\e[m
629 \e[31m- m.d.comb += self.o_n_stb.eq(self.pipe2.o_n_stb)
\e[m
630 \e[31m- m.d.comb += self.pipe2.i_n_busy.eq(self.i_n_busy)
\e[m
631 \e[32m+
\e[m
\e[32m m.d.comb += self.o_n_valid.eq(self.pipe2.o.n_valid)
\e[m
632 \e[32m+
\e[m
\e[32m m.d.comb += self.pipe2.i.n_ready.eq(self.i_n_ready)
\e[m
633 m.d.comb += self.o_data.eq(self.pipe2.stage.o_data)
\e[m
637 if __name__ == '__main__':
\e[m
639 \e[31m- dut = BufPipe()
\e[m
640 \e[32m+
\e[m
\e[32m dut = ExampleBufPipe()
\e[m
641 run_simulation(dut, testbench(dut), vcd_name="test_bufpipe.vcd")
\e[m
644 \e[31m- dut = BufPipe2()
\e[m
645 \e[32m+
\e[m
\e[32m dut = ExampleBufPipe2()
\e[m
646 run_simulation(dut, testbench2(dut), vcd_name="test_bufpipe2.vcd")
\e[m
649 \e[31m- dut = BufPipe()
\e[m
650 \e[32m+
\e[m
\e[32m dut = ExampleBufPipe()
\e[m
651 test = Test3(dut)
\e[m
652 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe3.vcd")
\e[m
655 \e[31m- dut = BufPipe2()
\e[m
656 \e[32m+
\e[m
\e[32m dut = ExampleBufPipe2()
\e[m
657 run_simulation(dut, testbench4(dut), vcd_name="test_bufpipe4.vcd")
\e[m
658 \e[1mdiff --git a/src/add/test_inputgroup.py b/src/add/test_inputgroup.py
\e[m
659 \e[1mindex ca8523d..bb68861 100644
\e[m
660 \e[1m--- a/src/add/test_inputgroup.py
\e[m
661 \e[1m+++ b/src/add/test_inputgroup.py
\e[m
662 \e[36m@@ -99,9 +99,81 @@
\e[m
\e[mdef testbench(dut):
\e[m
663 assert out_mid == 3, "out mid %d" % out_mid
\e[m
666 \e[32m+
\e[m
\e[32mclass InputTest:
\e[m
667 \e[32m+
\e[m
\e[32m def __init__(self, dut):
\e[m
668 \e[32m+
\e[m
\e[32m self.dut = dut
\e[m
669 \e[32m+
\e[m
\e[32m self.di = {}
\e[m
670 \e[32m+
\e[m
\e[32m self.do = {}
\e[m
671 \e[32m+
\e[m
\e[32m self.tlen = 10
\e[m
672 \e[32m+
\e[m
\e[32m for mid in range(dut.num_rows):
\e[m
673 \e[32m+
\e[m
\e[32m self.di[mid] = {}
\e[m
674 \e[32m+
\e[m
\e[32m self.do[mid] = {}
\e[m
675 \e[32m+
\e[m
\e[32m for i in range(self.tlen):
\e[m
676 \e[32m+
\e[m
\e[32m self.di[mid][i] = randint(0, 100)
\e[m
677 \e[32m+
\e[m
\e[32m self.do[mid][i] = self.di[mid][i]
\e[m
679 \e[32m+
\e[m
\e[32m def send(self, mid):
\e[m
680 \e[32m+
\e[m
\e[32m for i in range(self.tlen):
\e[m
681 \e[32m+
\e[m
\e[32m op2 = self.di[mid][i]
\e[m
682 \e[32m+
\e[m
\e[32m rs = dut.rs[mid]
\e[m
683 \e[32m+
\e[m
\e[32m ack = yield rs.ack
\e[m
684 \e[32m+
\e[m
\e[32m while not ack:
\e[m
685 \e[32m+
\e[m
\e[32m yield
\e[m
686 \e[32m+
\e[m
\e[32m ack = yield rs.ack
\e[m
687 \e[32m+
\e[m
\e[32m yield rs.in_op[0].eq(i)
\e[m
688 \e[32m+
\e[m
\e[32m yield rs.in_op[1].eq(op2)
\e[m
689 \e[32m+
\e[m
\e[32m yield rs.stb.eq(0b11) # strobe indicate 1st op ready
\e[m
690 \e[32m+
\e[m
\e[32m ack = yield rs.ack
\e[m
691 \e[32m+
\e[m
\e[32m while ack:
\e[m
692 \e[32m+
\e[m
\e[32m yield
\e[m
693 \e[32m+
\e[m
\e[32m ack = yield rs.ack
\e[m
694 \e[32m+
\e[m
\e[32m yield rs.stb.eq(0)
\e[m
696 \e[32m+
\e[m
\e[32m # wait random period of time before queueing another value
\e[m
697 \e[32m+
\e[m
\e[32m for i in range(randint(0, 12)):
\e[m
698 \e[32m+
\e[m
\e[32m yield
\e[m
700 \e[32m+
\e[m
\e[32m def recv(self):
\e[m
701 \e[32m+
\e[m
\e[32m while True:
\e[m
702 \e[32m+
\e[m
\e[32m stb = yield dut.out_op.stb
\e[m
703 \e[32m+
\e[m
\e[32m yield dut.out_op.ack.eq(0)
\e[m
704 \e[32m+
\e[m
\e[32m while not stb:
\e[m
705 \e[32m+
\e[m
\e[32m yield
\e[m
706 \e[32m+
\e[m
\e[32m stb = yield dut.out_op.stb
\e[m
708 \e[32m+
\e[m
\e[32m yield dut.out_op.ack.eq(1)
\e[m
709 \e[32m+
\e[m
\e[32m stb = yield dut.out_op.stb
\e[m
710 \e[32m+
\e[m
\e[32m while stb:
\e[m
711 \e[32m+
\e[m
\e[32m yield
\e[m
712 \e[32m+
\e[m
\e[32m stb = yield dut.out_op.stb
\e[m
713 \e[32m+
\e[m
\e[32m mid = yield dut.mid
\e[m
714 \e[32m+
\e[m
\e[32m out_i = yield dut.out_op.v[0]
\e[m
715 \e[32m+
\e[m
\e[32m out_v = yield dut.out_op.v[1]
\e[m
717 \e[32m+
\e[m
\e[32m # see if this output has occurred already, delete it if it has
\e[m
718 \e[32m+
\e[m
\e[32m assert out_i in self.do[mid]
\e[m
719 \e[32m+
\e[m
\e[32m assert self.do[mid][out_i] == out_v
\e[m
720 \e[32m+
\e[m
\e[32m del self.do[mid][out_i]
\e[m
722 \e[32m+
\e[m
\e[32m # check if there's any more outputs
\e[m
723 \e[32m+
\e[m
\e[32m zerolen = True
\e[m
724 \e[32m+
\e[m
\e[32m for (k, v) in self.do.items():
\e[m
725 \e[32m+
\e[m
\e[32m if v:
\e[m
726 \e[32m+
\e[m
\e[32m zerolen = False
\e[m
727 \e[32m+
\e[m
\e[32m if zerolen:
\e[m
728 \e[32m+
\e[m
\e[32m break
\e[m
730 if __name__ == '__main__':
\e[m
731 dut = InputGroup(width=32)
\e[m
732 vl = rtlil.convert(dut, ports=dut.ports())
\e[m
733 with open("test_inputgroup.il", "w") as f:
\e[m
735 run_simulation(dut, testbench(dut), vcd_name="test_inputgroup.vcd")
\e[m
737 \e[32m+
\e[m
\e[32m dut = InputGroup(width=16)
\e[m
738 \e[32m+
\e[m
\e[32m test = InputTest(dut)
\e[m
739 \e[32m+
\e[m
\e[32m run_simulation(dut, [test.send(3), test.send(2),
\e[m
740 \e[32m+
\e[m
\e[32m test.send(1), test.send(0),
\e[m
741 \e[32m+
\e[m
\e[32m test.recv()],
\e[m
742 \e[32m+
\e[m
\e[32m vcd_name="test_inputgroup_parallel.vcd")
\e[m