1 """ Unit tests for Buffered and Unbuffered pipelines
3 contains useful worked examples of how to use the Pipeline API,
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
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
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 from singlepipe
import SimpleHandshake
30 from random
import randint
, seed
35 def check_o_n_valid(dut
, val
):
36 o_n_valid
= yield dut
.n
.o_valid
37 assert o_n_valid
== val
39 def check_o_n_valid2(dut
, val
):
40 o_n_valid
= yield dut
.n
.o_valid
41 assert o_n_valid
== val
45 #yield dut.i_p_rst.eq(1)
46 yield dut
.n
.i_ready
.eq(0)
47 yield dut
.p
.o_ready
.eq(0)
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)
56 yield dut
.p
.i_data
.eq(7)
57 yield from check_o_n_valid(dut
, 0) # effects of i_p_valid delayed
59 yield from check_o_n_valid(dut
, 1) # ok *now* i_p_valid effect is felt
61 yield dut
.p
.i_data
.eq(2)
63 yield dut
.n
.i_ready
.eq(0) # begin going into "stall" (next stage says ready)
64 yield dut
.p
.i_data
.eq(9)
66 yield dut
.p
.i_valid
.eq(0)
67 yield dut
.p
.i_data
.eq(12)
69 yield dut
.p
.i_data
.eq(32)
70 yield dut
.n
.i_ready
.eq(1)
72 yield from check_o_n_valid(dut
, 1) # buffer still needs to output
74 yield from check_o_n_valid(dut
, 1) # buffer still needs to output
76 yield from check_o_n_valid(dut
, 0) # buffer outputted, *now* we're done.
81 #yield dut.p.i_rst.eq(1)
82 yield dut
.n
.i_ready
.eq(0)
83 #yield dut.p.o_ready.eq(0)
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)
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
95 yield from check_o_n_valid2(dut
, 0) # effects of i_p_valid delayed 2 clocks
97 yield dut
.p
.i_data
.eq(2)
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)
103 yield dut
.p
.i_valid
.eq(0)
104 yield dut
.p
.i_data
.eq(12)
106 yield dut
.p
.i_data
.eq(32)
107 yield dut
.n
.i_ready
.eq(1)
109 yield from check_o_n_valid2(dut
, 1) # buffer still needs to output
111 yield from check_o_n_valid2(dut
, 1) # buffer still needs to output
113 yield from check_o_n_valid2(dut
, 1) # buffer still needs to output
115 yield from check_o_n_valid2(dut
, 0) # buffer outputted, *now* we're done.
122 def __init__(self
, dut
, resultfn
):
124 self
.resultfn
= resultfn
126 for i
in range(num_tests
):
127 #data.append(randint(0, 1<<16-1))
128 self
.data
.append(i
+1)
133 while self
.o
!= len(self
.data
):
134 send_range
= randint(0, 3)
135 for j
in range(randint(1,10)):
139 send
= randint(0, send_range
) != 0
140 o_p_ready
= yield self
.dut
.p
.o_ready
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
])
149 yield self
.dut
.p
.i_valid
.eq(0)
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
)
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
:
163 o_data
= yield self
.dut
.n
.o_data
164 self
.resultfn(o_data
, self
.data
[self
.o
], self
.i
, self
.o
)
166 if self
.o
== len(self
.data
):
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
)
174 def data_placeholder():
176 for i
in range(num_tests
):
178 d
.src1
= randint(0, 1<<16-1)
179 d
.src2
= randint(0, 1<<16-1)
185 for i
in range(num_tests
):
186 data
.append({'src1': randint(0, 1<<16-1),
187 'src2': randint(0, 1<<16-1)})
192 def __init__(self
, dut
, resultfn
, data
=None, stage_ctl
=False):
194 self
.resultfn
= resultfn
195 self
.stage_ctl
= stage_ctl
200 for i
in range(num_tests
):
201 self
.data
.append((randint(0, 1<<16-1), randint(0, 1<<16-1)))
206 while self
.o
!= len(self
.data
):
207 send_range
= randint(0, 3)
208 for j
in range(randint(1,10)):
212 send
= randint(0, send_range
) != 0
214 o_p_ready
= yield self
.dut
.p
.o_ready
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
]):
224 yield self
.dut
.p
.i_valid
.eq(0)
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
233 yield self
.dut
.n
.i_ready
.eq(ready
)
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
:
239 if isinstance(self
.dut
.n
.o_data
, Record
):
241 dod
= self
.dut
.n
.o_data
242 for k
, v
in dod
.fields
.items():
245 o_data
= yield self
.dut
.n
.o_data
246 self
.resultfn(o_data
, self
.data
[self
.o
], self
.i
, self
.o
)
248 if self
.o
== len(self
.data
):
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
))
259 for i
in range(num_tests
):
260 #data.append(randint(0, 1<<16-1))
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
270 if send
and i
!= len(data
):
271 yield dut
.p
.i_valid
.eq(1)
272 yield dut
.p
.i_data
.eq(data
[i
])
275 yield dut
.p
.i_valid
.eq(0)
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
])
287 ######################################################################
289 ######################################################################
291 class ExampleBufPipe2(ControlBase
):
292 """ Example of how to do chained pipeline stages.
295 def elaborate(self
, platform
):
298 pipe1
= ExampleBufPipe()
299 pipe2
= ExampleBufPipe()
301 m
.submodules
.pipe1
= pipe1
302 m
.submodules
.pipe2
= pipe2
304 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
309 ######################################################################
311 ######################################################################
313 class ExampleBufPipeChain2(BufferedPipeline
):
314 """ connects two stages together as a *single* combinatorial stage.
317 stage1
= ExampleStageCls()
318 stage2
= ExampleStageCls()
319 combined
= StageChain([stage1
, stage2
])
320 BufferedPipeline
.__init
__(self
, combined
)
325 for i
in range(num_tests
):
326 data
.append(randint(0, 1<<16-2))
330 def test9_resultfn(o_data
, expected
, i
, o
):
332 assert o_data
== res
, \
333 "%d-%d received data %x not match expected %x\n" \
334 % (i
, o
, o_data
, res
)
337 ######################################################################
339 ######################################################################
342 def __init__(self
, width
, signed
):
344 self
.src1
= Signal((width
, signed
), name
="src1")
345 self
.src2
= Signal((width
, signed
), name
="src2")
346 self
.output
= Signal(width
, name
="out")
348 def elaborate(self
, platform
):
349 self
.m
.d
.comb
+= self
.output
.eq(Mux(self
.src1
< self
.src2
, 1, 0))
353 class LTStage(StageCls
):
354 """ module-based stage example
357 self
.slt
= SetLessThan(16, True)
360 return (Signal(16, name
="sig1"), Signal(16, "sig2"))
363 return Signal(16, "out")
365 def setup(self
, m
, i
):
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
)
372 def process(self
, i
):
376 class LTStageDerived(SetLessThan
, StageCls
):
377 """ special version of a nmigen module where the module is also a stage
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
385 SetLessThan
.__init
__(self
, 16, True)
388 return (Signal(16), Signal(16))
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])
398 def process(self
, i
):
402 class ExampleLTPipeline(UnbufferedPipeline
):
403 """ an example of how to use the unbuffered pipeline.
408 UnbufferedPipeline
.__init
__(self
, stage
)
411 class ExampleLTBufferedPipeDerived(BufferedPipeline
):
412 """ an example of how to use the buffered pipeline.
416 stage
= LTStageDerived()
417 BufferedPipeline
.__init
__(self
, stage
)
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
))
427 ######################################################################
429 ######################################################################
431 class ExampleAddRecordStage(StageCls
):
432 """ example use of a Record
435 record_spec
= [('src1', 16), ('src2', 16)]
437 """ returns a Record using the specification
439 return Record(self
.record_spec
)
442 return Record(self
.record_spec
)
444 def process(self
, i
):
445 """ process the input data, returning a dictionary with key names
446 that exactly match the Record's attributes.
448 return {'src1': i
.src1
+ 1,
451 ######################################################################
453 ######################################################################
455 class ExampleAddRecordPlaceHolderStage(StageCls
):
456 """ example use of a Record, with a placeholder as the processing result
459 record_spec
= [('src1', 16), ('src2', 16)]
461 """ returns a Record using the specification
463 return Record(self
.record_spec
)
466 return Record(self
.record_spec
)
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.
478 class PlaceHolder
: pass
481 class ExampleAddRecordPipe(UnbufferedPipeline
):
482 """ an example of how to use the combinatorial pipeline.
486 stage
= ExampleAddRecordStage()
487 UnbufferedPipeline
.__init
__(self
, stage
)
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
))
497 class ExampleAddRecordPlaceHolderPipe(UnbufferedPipeline
):
498 """ an example of how to use the combinatorial pipeline.
502 stage
= ExampleAddRecordPlaceHolderStage()
503 UnbufferedPipeline
.__init
__(self
, stage
)
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
))
514 ######################################################################
516 ######################################################################
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
525 self
.op1
= Signal(16)
526 self
.op2
= Signal(16)
529 return [self
.op1
.eq(i
.op1
), self
.op2
.eq(i
.op2
)]
532 class ExampleAddClassStage(StageCls
):
533 """ an example of how to use the buffered pipeline, as a class instance
537 """ returns an instance of an Example2OpClass.
539 return Example2OpClass()
542 """ returns an output signal which will happen to contain the sum
547 def process(self
, i
):
548 """ process the input data (sums the values in the tuple) and returns it
553 class ExampleBufPipeAddClass(BufferedPipeline
):
554 """ an example of how to use the buffered pipeline, using a class instance
558 addstage
= ExampleAddClassStage()
559 BufferedPipeline
.__init
__(self
, addstage
)
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
568 def __init__(self
, op1
, op2
):
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
))
581 for i
in range(num_tests
):
582 data
.append(TestInputAdd(randint(0, 1<<16-1), randint(0, 1<<16-1)))
586 ######################################################################
588 ######################################################################
590 class ExampleStageDelayCls(StageCls
):
591 """ an example of how to use the buffered pipeline, in a static class
595 def __init__(self
, valid_trigger
=2):
596 self
.count
= Signal(2)
597 self
.valid_trigger
= valid_trigger
600 return Signal(16, name
="example_input_signal")
603 return Signal(16, name
="example_output_signal")
607 return (self
.count
== 1)# | (self.count == 3)
610 def d_valid(self
, i_ready
):
611 return self
.count
== self
.valid_trigger
614 def process(self
, i
):
615 """ process the input data and returns it (adds 1)
619 def elaborate(self
, platform
):
621 m
.d
.sync
+= self
.count
.eq(self
.count
+ 1)
625 class ExampleBufDelayedPipe(BufferedPipeline
):
628 stage
= ExampleStageDelayCls(valid_trigger
=2)
629 BufferedPipeline
.__init
__(self
, stage
, stage_ctl
=True)
631 def elaborate(self
, platform
):
632 m
= BufferedPipeline
.elaborate(self
, platform
)
633 m
.submodules
.stage
= self
.stage
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]))
646 def test12_resultfn(o_data
, expected
, i
, o
):
648 assert o_data
== res
, \
649 "%d-%d data %x not match %x\n" \
650 % (i
, o
, o_data
, res
)
653 ######################################################################
655 ######################################################################
657 class ExampleUnBufDelayedPipe(BufferedPipeline
):
660 stage
= ExampleStageDelayCls(valid_trigger
=3)
661 BufferedPipeline
.__init
__(self
, stage
, stage_ctl
=True)
663 def elaborate(self
, platform
):
664 m
= BufferedPipeline
.elaborate(self
, platform
)
665 m
.submodules
.stage
= self
.stage
668 ######################################################################
670 ######################################################################
672 class ExampleBufModeAdd1Pipe(SimpleHandshake
):
675 stage
= ExampleStageCls()
676 SimpleHandshake
.__init
__(self
, stage
)
679 ######################################################################
681 ######################################################################
683 class ExampleBufModeUnBufPipe(ControlBase
):
685 def elaborate(self
, platform
):
686 m
= ControlBase
._elaborate
(self
, platform
)
688 pipe1
= ExampleBufModeAdd1Pipe()
689 pipe2
= ExampleBufAdd1Pipe()
691 m
.submodules
.pipe1
= pipe1
692 m
.submodules
.pipe2
= pipe2
694 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
698 ######################################################################
700 ######################################################################
702 class ExampleUnBufAdd1Pipe2(UnbufferedPipeline2
):
705 stage
= ExampleStageCls()
706 UnbufferedPipeline2
.__init__(self
, stage
)
709 ######################################################################
711 ######################################################################
713 class ExampleBufPipe3(ControlBase
):
714 """ Example of how to do delayed pipeline, where the stage signals
718 def elaborate(self
, platform
):
719 m
= ControlBase
._elaborate
(self
, platform
)
721 pipe1
= ExampleBufDelayedPipe()
722 pipe2
= ExampleBufPipe()
724 m
.submodules
.pipe1
= pipe1
725 m
.submodules
.pipe2
= pipe2
727 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
731 ######################################################################
732 # Test 999 - XXX FAILS
733 # http://bugs.libre-riscv.org/show_bug.cgi?id=57
734 ######################################################################
736 class ExampleBufAdd1Pipe(BufferedPipeline
):
739 stage
= ExampleStageCls()
740 BufferedPipeline
.__init
__(self
, stage
)
743 class ExampleUnBufAdd1Pipe(UnbufferedPipeline
):
746 stage
= ExampleStageCls()
747 UnbufferedPipeline
.__init
__(self
, stage
)
750 class ExampleBufUnBufPipe(ControlBase
):
752 def elaborate(self
, platform
):
753 m
= ControlBase
._elaborate
(self
, platform
)
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()
763 m
.submodules
.pipe1
= pipe1
764 m
.submodules
.pipe2
= pipe2
766 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
771 ######################################################################
773 ######################################################################
777 if __name__
== '__main__':
779 dut
= ExampleBufPipe()
780 run_simulation(dut
, testbench(dut
), vcd_name
="test_bufpipe.vcd")
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
:
794 dut
= ExampleBufPipe()
795 test
= Test3(dut
, test3_resultfn
)
796 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe3.vcd")
799 dut
= ExamplePipeline()
800 test
= Test3(dut
, test3_resultfn
)
801 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_combpipe3.vcd")
804 dut
= ExampleBufPipe2()
805 run_simulation(dut
, testbench4(dut
), vcd_name
="test_bufpipe4.vcd")
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")
813 dut
= ExampleLTPipeline()
814 test
= Test5(dut
, test6_resultfn
)
815 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_ltcomb6.vcd")
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
:
825 dut
= ExampleAddRecordPipe()
827 test
= Test5(dut
, test7_resultfn
, data
=data
)
828 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord.vcd")
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
:
839 dut
= ExampleBufPipeAddClass()
841 test
= Test5(dut
, test8_resultfn
, data
=data
)
842 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe8.vcd")
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
:
854 test
= Test5(dut
, test9_resultfn
, data
=data
)
855 run_simulation(dut
, [test
.send
, test
.rcv
],
856 vcd_name
="test_bufpipechain2.vcd")
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
:
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")
874 dut
= ExampleBufDelayedPipe()
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
:
886 dut
= ExampleUnBufDelayedPipe()
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
:
898 dut
= ExampleBufModeAdd1Pipe()
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
:
910 dut
= ExampleBufModeUnBufPipe()
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
:
922 dut
= ExampleUnBufAdd1Pipe2()
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
:
933 print ("test 998 (fails, bug)")
934 dut
= ExampleBufPipe3()
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
:
945 print ("test 999 (expected to fail, which is a bug)")
946 dut
= ExampleBufUnBufPipe()
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
: