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