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