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