add more unit tests of PassThroughHandshake
[ieee754fpu.git] / src / add / test_buf_pipe.py
1 """ Unit tests for Buffered and Unbuffered pipelines
2
3 contains useful worked examples of how to use the Pipeline API,
4 including:
5
6 * Combinatorial Stage "Chaining"
7 * class-based data stages
8 * nmigen module-based data stages
9 * special nmigen module-based data stage, where the stage *is* the module
10 * Record-based data stages
11 * static-class data stages
12 * multi-stage pipelines (and how to connect them)
13 * how to *use* the pipelines (see Test5) - how to get data in and out
14
15 """
16
17 from nmigen import Module, Signal, Mux, Const
18 from nmigen.hdl.rec import Record
19 from nmigen.compat.sim import run_simulation
20 from nmigen.cli import verilog, rtlil
21
22 from example_buf_pipe import ExampleBufPipe, ExampleBufPipeAdd
23 from example_buf_pipe import ExamplePipeline, UnbufferedPipeline
24 from example_buf_pipe import ExampleStageCls
25 from example_buf_pipe import PrevControl, NextControl, BufferedHandshake
26 from example_buf_pipe import StageChain, ControlBase, StageCls
27 from singlepipe import UnbufferedPipeline2
28 from singlepipe import SimpleHandshake
29 from singlepipe import PassThroughHandshake
30 from singlepipe import PassThroughStage
31
32 from random import randint, seed
33
34 #seed(4)
35
36
37 def check_o_n_valid(dut, val):
38 o_n_valid = yield dut.n.o_valid
39 assert o_n_valid == val
40
41 def check_o_n_valid2(dut, val):
42 o_n_valid = yield dut.n.o_valid
43 assert o_n_valid == val
44
45
46 def testbench(dut):
47 #yield dut.i_p_rst.eq(1)
48 yield dut.n.i_ready.eq(0)
49 yield dut.p.o_ready.eq(0)
50 yield
51 yield
52 #yield dut.i_p_rst.eq(0)
53 yield dut.n.i_ready.eq(1)
54 yield dut.p.i_data.eq(5)
55 yield dut.p.i_valid.eq(1)
56 yield
57
58 yield dut.p.i_data.eq(7)
59 yield from check_o_n_valid(dut, 0) # effects of i_p_valid delayed
60 yield
61 yield from check_o_n_valid(dut, 1) # ok *now* i_p_valid effect is felt
62
63 yield dut.p.i_data.eq(2)
64 yield
65 yield dut.n.i_ready.eq(0) # begin going into "stall" (next stage says ready)
66 yield dut.p.i_data.eq(9)
67 yield
68 yield dut.p.i_valid.eq(0)
69 yield dut.p.i_data.eq(12)
70 yield
71 yield dut.p.i_data.eq(32)
72 yield dut.n.i_ready.eq(1)
73 yield
74 yield from check_o_n_valid(dut, 1) # buffer still needs to output
75 yield
76 yield from check_o_n_valid(dut, 1) # buffer still needs to output
77 yield
78 yield from check_o_n_valid(dut, 0) # buffer outputted, *now* we're done.
79 yield
80
81
82 def testbench2(dut):
83 #yield dut.p.i_rst.eq(1)
84 yield dut.n.i_ready.eq(0)
85 #yield dut.p.o_ready.eq(0)
86 yield
87 yield
88 #yield dut.p.i_rst.eq(0)
89 yield dut.n.i_ready.eq(1)
90 yield dut.p.i_data.eq(5)
91 yield dut.p.i_valid.eq(1)
92 yield
93
94 yield dut.p.i_data.eq(7)
95 yield from check_o_n_valid2(dut, 0) # effects of i_p_valid delayed 2 clocks
96 yield
97 yield from check_o_n_valid2(dut, 0) # effects of i_p_valid delayed 2 clocks
98
99 yield dut.p.i_data.eq(2)
100 yield
101 yield from check_o_n_valid2(dut, 1) # ok *now* i_p_valid effect is felt
102 yield dut.n.i_ready.eq(0) # begin going into "stall" (next stage says ready)
103 yield dut.p.i_data.eq(9)
104 yield
105 yield dut.p.i_valid.eq(0)
106 yield dut.p.i_data.eq(12)
107 yield
108 yield dut.p.i_data.eq(32)
109 yield dut.n.i_ready.eq(1)
110 yield
111 yield from check_o_n_valid2(dut, 1) # buffer still needs to output
112 yield
113 yield from check_o_n_valid2(dut, 1) # buffer still needs to output
114 yield
115 yield from check_o_n_valid2(dut, 1) # buffer still needs to output
116 yield
117 yield from check_o_n_valid2(dut, 0) # buffer outputted, *now* we're done.
118 yield
119 yield
120 yield
121
122
123 class Test3:
124 def __init__(self, dut, resultfn):
125 self.dut = dut
126 self.resultfn = resultfn
127 self.data = []
128 for i in range(num_tests):
129 #data.append(randint(0, 1<<16-1))
130 self.data.append(i+1)
131 self.i = 0
132 self.o = 0
133
134 def send(self):
135 while self.o != len(self.data):
136 send_range = randint(0, 3)
137 for j in range(randint(1,10)):
138 if send_range == 0:
139 send = True
140 else:
141 send = randint(0, send_range) != 0
142 o_p_ready = yield self.dut.p.o_ready
143 if not o_p_ready:
144 yield
145 continue
146 if send and self.i != len(self.data):
147 yield self.dut.p.i_valid.eq(1)
148 yield self.dut.p.i_data.eq(self.data[self.i])
149 self.i += 1
150 else:
151 yield self.dut.p.i_valid.eq(0)
152 yield
153
154 def rcv(self):
155 while self.o != len(self.data):
156 stall_range = randint(0, 3)
157 for j in range(randint(1,10)):
158 stall = randint(0, stall_range) != 0
159 yield self.dut.n.i_ready.eq(stall)
160 yield
161 o_n_valid = yield self.dut.n.o_valid
162 i_n_ready = yield self.dut.n.i_ready_test
163 if not o_n_valid or not i_n_ready:
164 continue
165 o_data = yield self.dut.n.o_data
166 self.resultfn(o_data, self.data[self.o], self.i, self.o)
167 self.o += 1
168 if self.o == len(self.data):
169 break
170
171 def test3_resultfn(o_data, expected, i, o):
172 assert o_data == expected + 1, \
173 "%d-%d data %x not match %x\n" \
174 % (i, o, o_data, expected)
175
176 def data_placeholder():
177 data = []
178 for i in range(num_tests):
179 d = PlaceHolder()
180 d.src1 = randint(0, 1<<16-1)
181 d.src2 = randint(0, 1<<16-1)
182 data.append(d)
183 return data
184
185 def data_dict():
186 data = []
187 for i in range(num_tests):
188 data.append({'src1': randint(0, 1<<16-1),
189 'src2': randint(0, 1<<16-1)})
190 return data
191
192
193 class Test5:
194 def __init__(self, dut, resultfn, data=None, stage_ctl=False):
195 self.dut = dut
196 self.resultfn = resultfn
197 self.stage_ctl = stage_ctl
198 if data:
199 self.data = data
200 else:
201 self.data = []
202 for i in range(num_tests):
203 self.data.append((randint(0, 1<<16-1), randint(0, 1<<16-1)))
204 self.i = 0
205 self.o = 0
206
207 def send(self):
208 while self.o != len(self.data):
209 send_range = randint(0, 3)
210 for j in range(randint(1,10)):
211 if send_range == 0:
212 send = True
213 else:
214 send = randint(0, send_range) != 0
215 #send = True
216 o_p_ready = yield self.dut.p.o_ready
217 if not o_p_ready:
218 yield
219 continue
220 if send and self.i != len(self.data):
221 yield self.dut.p.i_valid.eq(1)
222 for v in self.dut.set_input(self.data[self.i]):
223 yield v
224 self.i += 1
225 else:
226 yield self.dut.p.i_valid.eq(0)
227 yield
228
229 def rcv(self):
230 while self.o != len(self.data):
231 stall_range = randint(0, 3)
232 for j in range(randint(1,10)):
233 ready = randint(0, stall_range) != 0
234 #ready = True
235 yield self.dut.n.i_ready.eq(ready)
236 yield
237 o_n_valid = yield self.dut.n.o_valid
238 i_n_ready = yield self.dut.n.i_ready_test
239 if not o_n_valid or not i_n_ready:
240 continue
241 if isinstance(self.dut.n.o_data, Record):
242 o_data = {}
243 dod = self.dut.n.o_data
244 for k, v in dod.fields.items():
245 o_data[k] = yield v
246 else:
247 o_data = yield self.dut.n.o_data
248 self.resultfn(o_data, self.data[self.o], self.i, self.o)
249 self.o += 1
250 if self.o == len(self.data):
251 break
252
253 def test5_resultfn(o_data, expected, i, o):
254 res = expected[0] + expected[1]
255 assert o_data == res, \
256 "%d-%d data %x not match %s\n" \
257 % (i, o, o_data, repr(expected))
258
259 def testbench4(dut):
260 data = []
261 for i in range(num_tests):
262 #data.append(randint(0, 1<<16-1))
263 data.append(i+1)
264 i = 0
265 o = 0
266 while True:
267 stall = randint(0, 3) != 0
268 send = randint(0, 5) != 0
269 yield dut.n.i_ready.eq(stall)
270 o_p_ready = yield dut.p.o_ready
271 if o_p_ready:
272 if send and i != len(data):
273 yield dut.p.i_valid.eq(1)
274 yield dut.p.i_data.eq(data[i])
275 i += 1
276 else:
277 yield dut.p.i_valid.eq(0)
278 yield
279 o_n_valid = yield dut.n.o_valid
280 i_n_ready = yield dut.n.i_ready_test
281 if o_n_valid and i_n_ready:
282 o_data = yield dut.n.o_data
283 assert o_data == data[o] + 2, "%d-%d data %x not match %x\n" \
284 % (i, o, o_data, data[o])
285 o += 1
286 if o == len(data):
287 break
288
289 ######################################################################
290 # Test 2 and 4
291 ######################################################################
292
293 class ExampleBufPipe2(ControlBase):
294 """ Example of how to do chained pipeline stages.
295 """
296
297 def elaborate(self, platform):
298 m = Module()
299
300 pipe1 = ExampleBufPipe()
301 pipe2 = ExampleBufPipe()
302
303 m.submodules.pipe1 = pipe1
304 m.submodules.pipe2 = pipe2
305
306 m.d.comb += self.connect([pipe1, pipe2])
307
308 return m
309
310
311 ######################################################################
312 # Test 9
313 ######################################################################
314
315 class ExampleBufPipeChain2(BufferedHandshake):
316 """ connects two stages together as a *single* combinatorial stage.
317 """
318 def __init__(self):
319 stage1 = ExampleStageCls()
320 stage2 = ExampleStageCls()
321 combined = StageChain([stage1, stage2])
322 BufferedHandshake.__init__(self, combined)
323
324
325 def data_chain2():
326 data = []
327 for i in range(num_tests):
328 data.append(randint(0, 1<<16-2))
329 return data
330
331
332 def test9_resultfn(o_data, expected, i, o):
333 res = expected + 2
334 assert o_data == res, \
335 "%d-%d received data %x not match expected %x\n" \
336 % (i, o, o_data, res)
337
338
339 ######################################################################
340 # Test 6 and 10
341 ######################################################################
342
343 class SetLessThan:
344 def __init__(self, width, signed):
345 self.m = Module()
346 self.src1 = Signal((width, signed), name="src1")
347 self.src2 = Signal((width, signed), name="src2")
348 self.output = Signal(width, name="out")
349
350 def elaborate(self, platform):
351 self.m.d.comb += self.output.eq(Mux(self.src1 < self.src2, 1, 0))
352 return self.m
353
354
355 class LTStage(StageCls):
356 """ module-based stage example
357 """
358 def __init__(self):
359 self.slt = SetLessThan(16, True)
360
361 def ispec(self):
362 return (Signal(16, name="sig1"), Signal(16, "sig2"))
363
364 def ospec(self):
365 return Signal(16, "out")
366
367 def setup(self, m, i):
368 self.o = Signal(16)
369 m.submodules.slt = self.slt
370 m.d.comb += self.slt.src1.eq(i[0])
371 m.d.comb += self.slt.src2.eq(i[1])
372 m.d.comb += self.o.eq(self.slt.output)
373
374 def process(self, i):
375 return self.o
376
377
378 class LTStageDerived(SetLessThan, StageCls):
379 """ special version of a nmigen module where the module is also a stage
380
381 shows that you don't actually need to combinatorially connect
382 to the outputs, or add the module as a submodule: just return
383 the module output parameter(s) from the Stage.process() function
384 """
385
386 def __init__(self):
387 SetLessThan.__init__(self, 16, True)
388
389 def ispec(self):
390 return (Signal(16), Signal(16))
391
392 def ospec(self):
393 return Signal(16)
394
395 def setup(self, m, i):
396 m.submodules.slt = self
397 m.d.comb += self.src1.eq(i[0])
398 m.d.comb += self.src2.eq(i[1])
399
400 def process(self, i):
401 return self.output
402
403
404 class ExampleLTPipeline(UnbufferedPipeline):
405 """ an example of how to use the unbuffered pipeline.
406 """
407
408 def __init__(self):
409 stage = LTStage()
410 UnbufferedPipeline.__init__(self, stage)
411
412
413 class ExampleLTBufferedPipeDerived(BufferedHandshake):
414 """ an example of how to use the buffered pipeline.
415 """
416
417 def __init__(self):
418 stage = LTStageDerived()
419 BufferedHandshake.__init__(self, stage)
420
421
422 def test6_resultfn(o_data, expected, i, o):
423 res = 1 if expected[0] < expected[1] else 0
424 assert o_data == res, \
425 "%d-%d data %x not match %s\n" \
426 % (i, o, o_data, repr(expected))
427
428
429 ######################################################################
430 # Test 7
431 ######################################################################
432
433 class ExampleAddRecordStage(StageCls):
434 """ example use of a Record
435 """
436
437 record_spec = [('src1', 16), ('src2', 16)]
438 def ispec(self):
439 """ returns a Record using the specification
440 """
441 return Record(self.record_spec)
442
443 def ospec(self):
444 return Record(self.record_spec)
445
446 def process(self, i):
447 """ process the input data, returning a dictionary with key names
448 that exactly match the Record's attributes.
449 """
450 return {'src1': i.src1 + 1,
451 'src2': i.src2 + 1}
452
453 ######################################################################
454 # Test 11
455 ######################################################################
456
457 class ExampleAddRecordPlaceHolderStage(StageCls):
458 """ example use of a Record, with a placeholder as the processing result
459 """
460
461 record_spec = [('src1', 16), ('src2', 16)]
462 def ispec(self):
463 """ returns a Record using the specification
464 """
465 return Record(self.record_spec)
466
467 def ospec(self):
468 return Record(self.record_spec)
469
470 def process(self, i):
471 """ process the input data, returning a PlaceHolder class instance
472 with attributes that exactly match those of the Record.
473 """
474 o = PlaceHolder()
475 o.src1 = i.src1 + 1
476 o.src2 = i.src2 + 1
477 return o
478
479
480 class PlaceHolder: pass
481
482
483 class ExampleAddRecordPipe(UnbufferedPipeline):
484 """ an example of how to use the combinatorial pipeline.
485 """
486
487 def __init__(self):
488 stage = ExampleAddRecordStage()
489 UnbufferedPipeline.__init__(self, stage)
490
491
492 def test7_resultfn(o_data, expected, i, o):
493 res = (expected['src1'] + 1, expected['src2'] + 1)
494 assert o_data['src1'] == res[0] and o_data['src2'] == res[1], \
495 "%d-%d data %s not match %s\n" \
496 % (i, o, repr(o_data), repr(expected))
497
498
499 class ExampleAddRecordPlaceHolderPipe(UnbufferedPipeline):
500 """ an example of how to use the combinatorial pipeline.
501 """
502
503 def __init__(self):
504 stage = ExampleAddRecordPlaceHolderStage()
505 UnbufferedPipeline.__init__(self, stage)
506
507
508 def test11_resultfn(o_data, expected, i, o):
509 res1 = expected.src1 + 1
510 res2 = expected.src2 + 1
511 assert o_data['src1'] == res1 and o_data['src2'] == res2, \
512 "%d-%d data %s not match %s\n" \
513 % (i, o, repr(o_data), repr(expected))
514
515
516 ######################################################################
517 # Test 8
518 ######################################################################
519
520
521 class Example2OpClass:
522 """ an example of a class used to store 2 operands.
523 requires an eq function, to conform with the pipeline stage API
524 """
525
526 def __init__(self):
527 self.op1 = Signal(16)
528 self.op2 = Signal(16)
529
530 def eq(self, i):
531 return [self.op1.eq(i.op1), self.op2.eq(i.op2)]
532
533
534 class ExampleAddClassStage(StageCls):
535 """ an example of how to use the buffered pipeline, as a class instance
536 """
537
538 def ispec(self):
539 """ returns an instance of an Example2OpClass.
540 """
541 return Example2OpClass()
542
543 def ospec(self):
544 """ returns an output signal which will happen to contain the sum
545 of the two inputs
546 """
547 return Signal(16)
548
549 def process(self, i):
550 """ process the input data (sums the values in the tuple) and returns it
551 """
552 return i.op1 + i.op2
553
554
555 class ExampleBufPipeAddClass(BufferedHandshake):
556 """ an example of how to use the buffered pipeline, using a class instance
557 """
558
559 def __init__(self):
560 addstage = ExampleAddClassStage()
561 BufferedHandshake.__init__(self, addstage)
562
563
564 class TestInputAdd:
565 """ the eq function, called by set_input, needs an incoming object
566 that conforms to the Example2OpClass.eq function requirements
567 easiest way to do that is to create a class that has the exact
568 same member layout (self.op1, self.op2) as Example2OpClass
569 """
570 def __init__(self, op1, op2):
571 self.op1 = op1
572 self.op2 = op2
573
574
575 def test8_resultfn(o_data, expected, i, o):
576 res = expected.op1 + expected.op2 # these are a TestInputAdd instance
577 assert o_data == res, \
578 "%d-%d data %x not match %s\n" \
579 % (i, o, o_data, repr(expected))
580
581 def data_2op():
582 data = []
583 for i in range(num_tests):
584 data.append(TestInputAdd(randint(0, 1<<16-1), randint(0, 1<<16-1)))
585 return data
586
587
588 ######################################################################
589 # Test 12
590 ######################################################################
591
592 class ExampleStageDelayCls(StageCls):
593 """ an example of how to use the buffered pipeline, in a static class
594 fashion
595 """
596
597 def __init__(self, valid_trigger=2):
598 self.count = Signal(2)
599 self.valid_trigger = valid_trigger
600
601 def ispec(self):
602 return Signal(16, name="example_input_signal")
603
604 def ospec(self):
605 return Signal(16, name="example_output_signal")
606
607 @property
608 def d_ready(self):
609 return (self.count == 1)# | (self.count == 3)
610 return Const(1)
611
612 def d_valid(self, i_ready):
613 return self.count == self.valid_trigger
614 return Const(1)
615
616 def process(self, i):
617 """ process the input data and returns it (adds 1)
618 """
619 return i + 1
620
621 def elaborate(self, platform):
622 m = Module()
623 m.d.sync += self.count.eq(self.count + 1)
624 return m
625
626
627 class ExampleBufDelayedPipe(BufferedHandshake):
628
629 def __init__(self):
630 stage = ExampleStageDelayCls(valid_trigger=2)
631 BufferedHandshake.__init__(self, stage, stage_ctl=True)
632
633 def elaborate(self, platform):
634 m = BufferedHandshake.elaborate(self, platform)
635 m.submodules.stage = self.stage
636 return m
637
638
639 def data_chain1():
640 data = []
641 for i in range(num_tests):
642 data.append(1<<((i*3)%15))
643 #data.append(randint(0, 1<<16-2))
644 #print (hex(data[-1]))
645 return data
646
647
648 def test12_resultfn(o_data, expected, i, o):
649 res = expected + 1
650 assert o_data == res, \
651 "%d-%d data %x not match %x\n" \
652 % (i, o, o_data, res)
653
654
655 ######################################################################
656 # Test 13
657 ######################################################################
658
659 class ExampleUnBufDelayedPipe(BufferedHandshake):
660
661 def __init__(self):
662 stage = ExampleStageDelayCls(valid_trigger=3)
663 BufferedHandshake.__init__(self, stage, stage_ctl=True)
664
665 def elaborate(self, platform):
666 m = BufferedHandshake.elaborate(self, platform)
667 m.submodules.stage = self.stage
668 return m
669
670 ######################################################################
671 # Test 15
672 ######################################################################
673
674 class ExampleBufModeAdd1Pipe(SimpleHandshake):
675
676 def __init__(self):
677 stage = ExampleStageCls()
678 SimpleHandshake.__init__(self, stage)
679
680
681 ######################################################################
682 # Test 16
683 ######################################################################
684
685 class ExampleBufModeUnBufPipe(ControlBase):
686
687 def elaborate(self, platform):
688 m = ControlBase._elaborate(self, platform)
689
690 pipe1 = ExampleBufModeAdd1Pipe()
691 pipe2 = ExampleBufAdd1Pipe()
692
693 m.submodules.pipe1 = pipe1
694 m.submodules.pipe2 = pipe2
695
696 m.d.comb += self.connect([pipe1, pipe2])
697
698 return m
699
700 ######################################################################
701 # Test 17
702 ######################################################################
703
704 class ExampleUnBufAdd1Pipe2(UnbufferedPipeline2):
705
706 def __init__(self):
707 stage = ExampleStageCls()
708 UnbufferedPipeline2.__init__(self, stage)
709
710
711 ######################################################################
712 # Test 18
713 ######################################################################
714
715 class PassThroughTest(PassThroughHandshake):
716
717 def iospecfn(self):
718 return Signal(16, "out")
719
720 def __init__(self):
721 stage = PassThroughStage(self.iospecfn)
722 PassThroughHandshake.__init__(self, stage)
723
724 def test_identical_resultfn(o_data, expected, i, o):
725 res = expected
726 assert o_data == res, \
727 "%d-%d data %x not match %x\n" \
728 % (i, o, o_data, res)
729
730
731 ######################################################################
732 # Test 19
733 ######################################################################
734
735 class ExamplePassAdd1Pipe(PassThroughHandshake):
736
737 def __init__(self):
738 stage = ExampleStageCls()
739 PassThroughHandshake.__init__(self, stage)
740
741
742 class ExampleBufPassThruPipe(ControlBase):
743
744 def elaborate(self, platform):
745 m = ControlBase._elaborate(self, platform)
746
747 # XXX currently fails: any other permutation works fine.
748 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
749 # also fails using UnbufferedPipeline as well
750 pipe1 = ExampleBufModeAdd1Pipe()
751 pipe2 = ExamplePassAdd1Pipe()
752
753 m.submodules.pipe1 = pipe1
754 m.submodules.pipe2 = pipe2
755
756 m.d.comb += self.connect([pipe1, pipe2])
757
758 return m
759
760
761 ######################################################################
762 # Test 997
763 ######################################################################
764
765 class ExampleBufPassThruPipe2(ControlBase):
766
767 def elaborate(self, platform):
768 m = ControlBase._elaborate(self, platform)
769
770 # XXX currently fails: any other permutation works fine.
771 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
772 # also fails using UnbufferedPipeline as well
773 #pipe1 = ExampleUnBufAdd1Pipe()
774 #pipe2 = ExampleBufAdd1Pipe()
775 pipe1 = ExampleBufAdd1Pipe()
776 pipe2 = ExamplePassAdd1Pipe()
777
778 m.submodules.pipe1 = pipe1
779 m.submodules.pipe2 = pipe2
780
781 m.d.comb += self.connect([pipe1, pipe2])
782
783 return m
784
785
786 ######################################################################
787 # Test 998
788 ######################################################################
789
790 class ExampleBufPipe3(ControlBase):
791 """ Example of how to do delayed pipeline, where the stage signals
792 whether it is ready.
793 """
794
795 def elaborate(self, platform):
796 m = ControlBase._elaborate(self, platform)
797
798 pipe1 = ExampleBufDelayedPipe()
799 pipe2 = ExampleBufPipe()
800
801 m.submodules.pipe1 = pipe1
802 m.submodules.pipe2 = pipe2
803
804 m.d.comb += self.connect([pipe1, pipe2])
805
806 return m
807
808 ######################################################################
809 # Test 999 - XXX FAILS
810 # http://bugs.libre-riscv.org/show_bug.cgi?id=57
811 ######################################################################
812
813 class ExampleBufAdd1Pipe(BufferedHandshake):
814
815 def __init__(self):
816 stage = ExampleStageCls()
817 BufferedHandshake.__init__(self, stage)
818
819
820 class ExampleUnBufAdd1Pipe(UnbufferedPipeline):
821
822 def __init__(self):
823 stage = ExampleStageCls()
824 UnbufferedPipeline.__init__(self, stage)
825
826
827 class ExampleBufUnBufPipe(ControlBase):
828
829 def elaborate(self, platform):
830 m = ControlBase._elaborate(self, platform)
831
832 # XXX currently fails: any other permutation works fine.
833 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
834 # also fails using UnbufferedPipeline as well
835 #pipe1 = ExampleUnBufAdd1Pipe()
836 #pipe2 = ExampleBufAdd1Pipe()
837 pipe1 = ExampleBufAdd1Pipe()
838 pipe2 = ExampleUnBufAdd1Pipe()
839
840 m.submodules.pipe1 = pipe1
841 m.submodules.pipe2 = pipe2
842
843 m.d.comb += self.connect([pipe1, pipe2])
844
845 return m
846
847
848 ######################################################################
849 # Unit Tests
850 ######################################################################
851
852 num_tests = 100
853
854 if __name__ == '__main__':
855 print ("test 1")
856 dut = ExampleBufPipe()
857 run_simulation(dut, testbench(dut), vcd_name="test_bufpipe.vcd")
858
859 print ("test 2")
860 dut = ExampleBufPipe2()
861 run_simulation(dut, testbench2(dut), vcd_name="test_bufpipe2.vcd")
862 ports = [dut.p.i_valid, dut.n.i_ready,
863 dut.n.o_valid, dut.p.o_ready] + \
864 [dut.p.i_data] + [dut.n.o_data]
865 vl = rtlil.convert(dut, ports=ports)
866 with open("test_bufpipe2.il", "w") as f:
867 f.write(vl)
868
869
870 print ("test 3")
871 dut = ExampleBufPipe()
872 test = Test3(dut, test3_resultfn)
873 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe3.vcd")
874
875 print ("test 3.5")
876 dut = ExamplePipeline()
877 test = Test3(dut, test3_resultfn)
878 run_simulation(dut, [test.send, test.rcv], vcd_name="test_combpipe3.vcd")
879
880 print ("test 4")
881 dut = ExampleBufPipe2()
882 run_simulation(dut, testbench4(dut), vcd_name="test_bufpipe4.vcd")
883
884 print ("test 5")
885 dut = ExampleBufPipeAdd()
886 test = Test5(dut, test5_resultfn, stage_ctl=True)
887 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe5.vcd")
888
889 print ("test 6")
890 dut = ExampleLTPipeline()
891 test = Test5(dut, test6_resultfn)
892 run_simulation(dut, [test.send, test.rcv], vcd_name="test_ltcomb6.vcd")
893
894 ports = [dut.p.i_valid, dut.n.i_ready,
895 dut.n.o_valid, dut.p.o_ready] + \
896 list(dut.p.i_data) + [dut.n.o_data]
897 vl = rtlil.convert(dut, ports=ports)
898 with open("test_ltcomb_pipe.il", "w") as f:
899 f.write(vl)
900
901 print ("test 7")
902 dut = ExampleAddRecordPipe()
903 data=data_dict()
904 test = Test5(dut, test7_resultfn, data=data)
905 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord.vcd")
906
907 ports = [dut.p.i_valid, dut.n.i_ready,
908 dut.n.o_valid, dut.p.o_ready,
909 dut.p.i_data.src1, dut.p.i_data.src2,
910 dut.n.o_data.src1, dut.n.o_data.src2]
911 vl = rtlil.convert(dut, ports=ports)
912 with open("test_recordcomb_pipe.il", "w") as f:
913 f.write(vl)
914
915 print ("test 8")
916 dut = ExampleBufPipeAddClass()
917 data=data_2op()
918 test = Test5(dut, test8_resultfn, data=data)
919 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe8.vcd")
920
921 print ("test 9")
922 dut = ExampleBufPipeChain2()
923 ports = [dut.p.i_valid, dut.n.i_ready,
924 dut.n.o_valid, dut.p.o_ready] + \
925 [dut.p.i_data] + [dut.n.o_data]
926 vl = rtlil.convert(dut, ports=ports)
927 with open("test_bufpipechain2.il", "w") as f:
928 f.write(vl)
929
930 data = data_chain2()
931 test = Test5(dut, test9_resultfn, data=data)
932 run_simulation(dut, [test.send, test.rcv],
933 vcd_name="test_bufpipechain2.vcd")
934
935 print ("test 10")
936 dut = ExampleLTBufferedPipeDerived()
937 test = Test5(dut, test6_resultfn)
938 run_simulation(dut, [test.send, test.rcv], vcd_name="test_ltbufpipe10.vcd")
939 vl = rtlil.convert(dut, ports=ports)
940 with open("test_ltbufpipe10.il", "w") as f:
941 f.write(vl)
942
943 print ("test 11")
944 dut = ExampleAddRecordPlaceHolderPipe()
945 data=data_placeholder()
946 test = Test5(dut, test11_resultfn, data=data)
947 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord.vcd")
948
949
950 print ("test 12")
951 dut = ExampleBufDelayedPipe()
952 data = data_chain1()
953 test = Test5(dut, test12_resultfn, data=data)
954 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe12.vcd")
955 ports = [dut.p.i_valid, dut.n.i_ready,
956 dut.n.o_valid, dut.p.o_ready] + \
957 [dut.p.i_data] + [dut.n.o_data]
958 vl = rtlil.convert(dut, ports=ports)
959 with open("test_bufpipe12.il", "w") as f:
960 f.write(vl)
961
962 print ("test 13")
963 dut = ExampleUnBufDelayedPipe()
964 data = data_chain1()
965 test = Test5(dut, test12_resultfn, data=data)
966 run_simulation(dut, [test.send, test.rcv], vcd_name="test_unbufpipe13.vcd")
967 ports = [dut.p.i_valid, dut.n.i_ready,
968 dut.n.o_valid, dut.p.o_ready] + \
969 [dut.p.i_data] + [dut.n.o_data]
970 vl = rtlil.convert(dut, ports=ports)
971 with open("test_unbufpipe13.il", "w") as f:
972 f.write(vl)
973
974 print ("test 15")
975 dut = ExampleBufModeAdd1Pipe()
976 data = data_chain1()
977 test = Test5(dut, test12_resultfn, data=data)
978 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufunbuf15.vcd")
979 ports = [dut.p.i_valid, dut.n.i_ready,
980 dut.n.o_valid, dut.p.o_ready] + \
981 [dut.p.i_data] + [dut.n.o_data]
982 vl = rtlil.convert(dut, ports=ports)
983 with open("test_bufunbuf15.il", "w") as f:
984 f.write(vl)
985
986 print ("test 16")
987 dut = ExampleBufModeUnBufPipe()
988 data = data_chain1()
989 test = Test5(dut, test9_resultfn, data=data)
990 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufunbuf16.vcd")
991 ports = [dut.p.i_valid, dut.n.i_ready,
992 dut.n.o_valid, dut.p.o_ready] + \
993 [dut.p.i_data] + [dut.n.o_data]
994 vl = rtlil.convert(dut, ports=ports)
995 with open("test_bufunbuf16.il", "w") as f:
996 f.write(vl)
997
998 print ("test 17")
999 dut = ExampleUnBufAdd1Pipe2()
1000 data = data_chain1()
1001 test = Test5(dut, test12_resultfn, data=data)
1002 run_simulation(dut, [test.send, test.rcv], vcd_name="test_unbufpipe17.vcd")
1003 ports = [dut.p.i_valid, dut.n.i_ready,
1004 dut.n.o_valid, dut.p.o_ready] + \
1005 [dut.p.i_data] + [dut.n.o_data]
1006 vl = rtlil.convert(dut, ports=ports)
1007 with open("test_unbufpipe17.il", "w") as f:
1008 f.write(vl)
1009
1010 print ("test 18")
1011 dut = PassThroughTest()
1012 data = data_chain1()
1013 test = Test5(dut, test_identical_resultfn, data=data)
1014 run_simulation(dut, [test.send, test.rcv], vcd_name="test_passthru18.vcd")
1015 ports = [dut.p.i_valid, dut.n.i_ready,
1016 dut.n.o_valid, dut.p.o_ready] + \
1017 [dut.p.i_data] + [dut.n.o_data]
1018 vl = rtlil.convert(dut, ports=ports)
1019 with open("test_passthru18.il", "w") as f:
1020 f.write(vl)
1021
1022 print ("test 19")
1023 dut = ExampleBufPassThruPipe()
1024 data = data_chain1()
1025 test = Test5(dut, test9_resultfn, data=data)
1026 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpass19.vcd")
1027 ports = [dut.p.i_valid, dut.n.i_ready,
1028 dut.n.o_valid, dut.p.o_ready] + \
1029 [dut.p.i_data] + [dut.n.o_data]
1030 vl = rtlil.convert(dut, ports=ports)
1031 with open("test_bufpass19.il", "w") as f:
1032 f.write(vl)
1033
1034 print ("test 997")
1035 dut = ExampleBufPassThruPipe2()
1036 data = data_chain1()
1037 test = Test5(dut, test9_resultfn, data=data)
1038 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpass997.vcd")
1039 ports = [dut.p.i_valid, dut.n.i_ready,
1040 dut.n.o_valid, dut.p.o_ready] + \
1041 [dut.p.i_data] + [dut.n.o_data]
1042 vl = rtlil.convert(dut, ports=ports)
1043 with open("test_bufpass997.il", "w") as f:
1044 f.write(vl)
1045
1046 print ("test 998 (fails, bug)")
1047 dut = ExampleBufPipe3()
1048 data = data_chain1()
1049 test = Test5(dut, test9_resultfn, data=data)
1050 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe14.vcd")
1051 ports = [dut.p.i_valid, dut.n.i_ready,
1052 dut.n.o_valid, dut.p.o_ready] + \
1053 [dut.p.i_data] + [dut.n.o_data]
1054 vl = rtlil.convert(dut, ports=ports)
1055 with open("test_bufpipe14.il", "w") as f:
1056 f.write(vl)
1057
1058 print ("test 999 (expected to fail, which is a bug)")
1059 dut = ExampleBufUnBufPipe()
1060 data = data_chain1()
1061 test = Test5(dut, test9_resultfn, data=data)
1062 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufunbuf999.vcd")
1063 ports = [dut.p.i_valid, dut.n.i_ready,
1064 dut.n.o_valid, dut.p.o_ready] + \
1065 [dut.p.i_data] + [dut.n.o_data]
1066 vl = rtlil.convert(dut, ports=ports)
1067 with open("test_bufunbuf999.il", "w") as f:
1068 f.write(vl)
1069