794fd9d523ec7c54eb00be52d9a6a3d9c1da9ebd
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
, BufferedHandshake
26 from example_buf_pipe
import StageChain
, ControlBase
, StageCls
27 from singlepipe
import UnbufferedPipeline2
28 from singlepipe
import SimpleHandshake
29 from singlepipe
import PassThroughHandshake
30 from singlepipe
import PassThroughStage
31 from singlepipe
import FIFOControl
32 from singlepipe
import RecordObject
34 from random
import randint
, seed
39 def check_o_n_valid(dut
, val
):
40 o_n_valid
= yield dut
.n
.o_valid
41 assert o_n_valid
== val
43 def check_o_n_valid2(dut
, val
):
44 o_n_valid
= yield dut
.n
.o_valid
45 assert o_n_valid
== val
49 #yield dut.i_p_rst.eq(1)
50 yield dut
.n
.i_ready
.eq(0)
51 #yield dut.p.o_ready.eq(0)
54 #yield dut.i_p_rst.eq(0)
55 yield dut
.n
.i_ready
.eq(1)
56 yield dut
.p
.i_data
.eq(5)
57 yield dut
.p
.i_valid
.eq(1)
60 yield dut
.p
.i_data
.eq(7)
61 yield from check_o_n_valid(dut
, 0) # effects of i_p_valid delayed
63 yield from check_o_n_valid(dut
, 1) # ok *now* i_p_valid effect is felt
65 yield dut
.p
.i_data
.eq(2)
67 yield dut
.n
.i_ready
.eq(0) # begin going into "stall" (next stage says ready)
68 yield dut
.p
.i_data
.eq(9)
70 yield dut
.p
.i_valid
.eq(0)
71 yield dut
.p
.i_data
.eq(12)
73 yield dut
.p
.i_data
.eq(32)
74 yield dut
.n
.i_ready
.eq(1)
76 yield from check_o_n_valid(dut
, 1) # buffer still needs to output
78 yield from check_o_n_valid(dut
, 1) # buffer still needs to output
80 yield from check_o_n_valid(dut
, 0) # buffer outputted, *now* we're done.
85 #yield dut.p.i_rst.eq(1)
86 yield dut
.n
.i_ready
.eq(0)
87 #yield dut.p.o_ready.eq(0)
90 #yield dut.p.i_rst.eq(0)
91 yield dut
.n
.i_ready
.eq(1)
92 yield dut
.p
.i_data
.eq(5)
93 yield dut
.p
.i_valid
.eq(1)
96 yield dut
.p
.i_data
.eq(7)
97 yield from check_o_n_valid2(dut
, 0) # effects of i_p_valid delayed 2 clocks
99 yield from check_o_n_valid2(dut
, 0) # effects of i_p_valid delayed 2 clocks
101 yield dut
.p
.i_data
.eq(2)
103 yield from check_o_n_valid2(dut
, 1) # ok *now* i_p_valid effect is felt
104 yield dut
.n
.i_ready
.eq(0) # begin going into "stall" (next stage says ready)
105 yield dut
.p
.i_data
.eq(9)
107 yield dut
.p
.i_valid
.eq(0)
108 yield dut
.p
.i_data
.eq(12)
110 yield dut
.p
.i_data
.eq(32)
111 yield dut
.n
.i_ready
.eq(1)
113 yield from check_o_n_valid2(dut
, 1) # buffer still needs to output
115 yield from check_o_n_valid2(dut
, 1) # buffer still needs to output
117 yield from check_o_n_valid2(dut
, 1) # buffer still needs to output
119 yield from check_o_n_valid2(dut
, 0) # buffer outputted, *now* we're done.
126 def __init__(self
, dut
, resultfn
):
128 self
.resultfn
= resultfn
130 for i
in range(num_tests
):
131 #data.append(randint(0, 1<<16-1))
132 self
.data
.append(i
+1)
137 while self
.o
!= len(self
.data
):
138 send_range
= randint(0, 3)
139 for j
in range(randint(1,10)):
143 send
= randint(0, send_range
) != 0
144 o_p_ready
= yield self
.dut
.p
.o_ready
148 if send
and self
.i
!= len(self
.data
):
149 yield self
.dut
.p
.i_valid
.eq(1)
150 yield self
.dut
.p
.i_data
.eq(self
.data
[self
.i
])
153 yield self
.dut
.p
.i_valid
.eq(0)
157 while self
.o
!= len(self
.data
):
158 stall_range
= randint(0, 3)
159 for j
in range(randint(1,10)):
160 stall
= randint(0, stall_range
) != 0
161 yield self
.dut
.n
.i_ready
.eq(stall
)
163 o_n_valid
= yield self
.dut
.n
.o_valid
164 i_n_ready
= yield self
.dut
.n
.i_ready_test
165 if not o_n_valid
or not i_n_ready
:
167 o_data
= yield self
.dut
.n
.o_data
168 self
.resultfn(o_data
, self
.data
[self
.o
], self
.i
, self
.o
)
170 if self
.o
== len(self
.data
):
173 def resultfn_3(o_data
, expected
, i
, o
):
174 assert o_data
== expected
+ 1, \
175 "%d-%d data %x not match %x\n" \
176 % (i
, o
, o_data
, expected
)
178 def data_placeholder():
180 for i
in range(num_tests
):
182 d
.src1
= randint(0, 1<<16-1)
183 d
.src2
= randint(0, 1<<16-1)
189 for i
in range(num_tests
):
190 data
.append({'src1': randint(0, 1<<16-1),
191 'src2': randint(0, 1<<16-1)})
196 def __init__(self
, dut
, resultfn
, data
=None, stage_ctl
=False):
198 self
.resultfn
= resultfn
199 self
.stage_ctl
= stage_ctl
204 for i
in range(num_tests
):
205 self
.data
.append((randint(0, 1<<16-1), randint(0, 1<<16-1)))
210 while self
.o
!= len(self
.data
):
211 send_range
= randint(0, 3)
212 for j
in range(randint(1,10)):
216 send
= randint(0, send_range
) != 0
218 o_p_ready
= yield self
.dut
.p
.o_ready
222 if send
and self
.i
!= len(self
.data
):
223 yield self
.dut
.p
.i_valid
.eq(1)
224 for v
in self
.dut
.set_input(self
.data
[self
.i
]):
228 yield self
.dut
.p
.i_valid
.eq(0)
232 while self
.o
!= len(self
.data
):
233 stall_range
= randint(0, 3)
234 for j
in range(randint(1,10)):
235 ready
= randint(0, stall_range
) != 0
237 yield self
.dut
.n
.i_ready
.eq(ready
)
239 o_n_valid
= yield self
.dut
.n
.o_valid
240 i_n_ready
= yield self
.dut
.n
.i_ready_test
241 if not o_n_valid
or not i_n_ready
:
243 if isinstance(self
.dut
.n
.o_data
, Record
):
245 dod
= self
.dut
.n
.o_data
246 for k
, v
in dod
.fields
.items():
249 o_data
= yield self
.dut
.n
.o_data
250 self
.resultfn(o_data
, self
.data
[self
.o
], self
.i
, self
.o
)
252 if self
.o
== len(self
.data
):
255 def resultfn_5(o_data
, expected
, i
, o
):
256 res
= expected
[0] + expected
[1]
257 assert o_data
== res
, \
258 "%d-%d data %x not match %s\n" \
259 % (i
, o
, o_data
, repr(expected
))
263 for i
in range(num_tests
):
264 #data.append(randint(0, 1<<16-1))
269 stall
= randint(0, 3) != 0
270 send
= randint(0, 5) != 0
271 yield dut
.n
.i_ready
.eq(stall
)
272 o_p_ready
= yield dut
.p
.o_ready
274 if send
and i
!= len(data
):
275 yield dut
.p
.i_valid
.eq(1)
276 yield dut
.p
.i_data
.eq(data
[i
])
279 yield dut
.p
.i_valid
.eq(0)
281 o_n_valid
= yield dut
.n
.o_valid
282 i_n_ready
= yield dut
.n
.i_ready_test
283 if o_n_valid
and i_n_ready
:
284 o_data
= yield dut
.n
.o_data
285 assert o_data
== data
[o
] + 2, "%d-%d data %x not match %x\n" \
286 % (i
, o
, o_data
, data
[o
])
291 ######################################################################
293 ######################################################################
295 class ExampleBufPipe2(ControlBase
):
296 """ Example of how to do chained pipeline stages.
299 def elaborate(self
, platform
):
302 pipe1
= ExampleBufPipe()
303 pipe2
= ExampleBufPipe()
305 m
.submodules
.pipe1
= pipe1
306 m
.submodules
.pipe2
= pipe2
308 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
313 ######################################################################
315 ######################################################################
317 class ExampleBufPipeChain2(BufferedHandshake
):
318 """ connects two stages together as a *single* combinatorial stage.
321 stage1
= ExampleStageCls()
322 stage2
= ExampleStageCls()
323 combined
= StageChain([stage1
, stage2
])
324 BufferedHandshake
.__init
__(self
, combined
)
329 for i
in range(num_tests
):
330 data
.append(randint(0, 1<<16-2))
334 def resultfn_9(o_data
, expected
, i
, o
):
336 assert o_data
== res
, \
337 "%d-%d received data %x not match expected %x\n" \
338 % (i
, o
, o_data
, res
)
341 ######################################################################
343 ######################################################################
346 def __init__(self
, width
, signed
):
348 self
.src1
= Signal((width
, signed
), name
="src1")
349 self
.src2
= Signal((width
, signed
), name
="src2")
350 self
.output
= Signal(width
, name
="out")
352 def elaborate(self
, platform
):
353 self
.m
.d
.comb
+= self
.output
.eq(Mux(self
.src1
< self
.src2
, 1, 0))
357 class LTStage(StageCls
):
358 """ module-based stage example
361 self
.slt
= SetLessThan(16, True)
364 return (Signal(16, name
="sig1"), Signal(16, "sig2"))
367 return Signal(16, "out")
369 def setup(self
, m
, i
):
371 m
.submodules
.slt
= self
.slt
372 m
.d
.comb
+= self
.slt
.src1
.eq(i
[0])
373 m
.d
.comb
+= self
.slt
.src2
.eq(i
[1])
374 m
.d
.comb
+= self
.o
.eq(self
.slt
.output
)
376 def process(self
, i
):
380 class LTStageDerived(SetLessThan
, StageCls
):
381 """ special version of a nmigen module where the module is also a stage
383 shows that you don't actually need to combinatorially connect
384 to the outputs, or add the module as a submodule: just return
385 the module output parameter(s) from the Stage.process() function
389 SetLessThan
.__init
__(self
, 16, True)
392 return (Signal(16), Signal(16))
397 def setup(self
, m
, i
):
398 m
.submodules
.slt
= self
399 m
.d
.comb
+= self
.src1
.eq(i
[0])
400 m
.d
.comb
+= self
.src2
.eq(i
[1])
402 def process(self
, i
):
406 class ExampleLTPipeline(UnbufferedPipeline
):
407 """ an example of how to use the unbuffered pipeline.
412 UnbufferedPipeline
.__init
__(self
, stage
)
415 class ExampleLTBufferedPipeDerived(BufferedHandshake
):
416 """ an example of how to use the buffered pipeline.
420 stage
= LTStageDerived()
421 BufferedHandshake
.__init
__(self
, stage
)
424 def resultfn_6(o_data
, expected
, i
, o
):
425 res
= 1 if expected
[0] < expected
[1] else 0
426 assert o_data
== res
, \
427 "%d-%d data %x not match %s\n" \
428 % (i
, o
, o_data
, repr(expected
))
431 ######################################################################
433 ######################################################################
435 class ExampleAddRecordStage(StageCls
):
436 """ example use of a Record
439 record_spec
= [('src1', 16), ('src2', 16)]
441 """ returns a Record using the specification
443 return Record(self
.record_spec
)
446 return Record(self
.record_spec
)
448 def process(self
, i
):
449 """ process the input data, returning a dictionary with key names
450 that exactly match the Record's attributes.
452 return {'src1': i
.src1
+ 1,
455 ######################################################################
457 ######################################################################
459 class ExampleAddRecordPlaceHolderStage(StageCls
):
460 """ example use of a Record, with a placeholder as the processing result
463 record_spec
= [('src1', 16), ('src2', 16)]
465 """ returns a Record using the specification
467 return Record(self
.record_spec
)
470 return Record(self
.record_spec
)
472 def process(self
, i
):
473 """ process the input data, returning a PlaceHolder class instance
474 with attributes that exactly match those of the Record.
482 class PlaceHolder
: pass
485 class ExampleAddRecordPipe(UnbufferedPipeline
):
486 """ an example of how to use the combinatorial pipeline.
490 stage
= ExampleAddRecordStage()
491 UnbufferedPipeline
.__init
__(self
, stage
)
494 def resultfn_7(o_data
, expected
, i
, o
):
495 res
= (expected
['src1'] + 1, expected
['src2'] + 1)
496 assert o_data
['src1'] == res
[0] and o_data
['src2'] == res
[1], \
497 "%d-%d data %s not match %s\n" \
498 % (i
, o
, repr(o_data
), repr(expected
))
501 class ExampleAddRecordPlaceHolderPipe(UnbufferedPipeline
):
502 """ an example of how to use the combinatorial pipeline.
506 stage
= ExampleAddRecordPlaceHolderStage()
507 UnbufferedPipeline
.__init
__(self
, stage
)
510 def resultfn_test11(o_data
, expected
, i
, o
):
511 res1
= expected
.src1
+ 1
512 res2
= expected
.src2
+ 1
513 assert o_data
['src1'] == res1
and o_data
['src2'] == res2
, \
514 "%d-%d data %s not match %s\n" \
515 % (i
, o
, repr(o_data
), repr(expected
))
518 ######################################################################
520 ######################################################################
523 class Example2OpClass
:
524 """ an example of a class used to store 2 operands.
525 requires an eq function, to conform with the pipeline stage API
529 self
.op1
= Signal(16)
530 self
.op2
= Signal(16)
533 return [self
.op1
.eq(i
.op1
), self
.op2
.eq(i
.op2
)]
536 class ExampleAddClassStage(StageCls
):
537 """ an example of how to use the buffered pipeline, as a class instance
541 """ returns an instance of an Example2OpClass.
543 return Example2OpClass()
546 """ returns an output signal which will happen to contain the sum
551 def process(self
, i
):
552 """ process the input data (sums the values in the tuple) and returns it
557 class ExampleBufPipeAddClass(BufferedHandshake
):
558 """ an example of how to use the buffered pipeline, using a class instance
562 addstage
= ExampleAddClassStage()
563 BufferedHandshake
.__init
__(self
, addstage
)
567 """ the eq function, called by set_input, needs an incoming object
568 that conforms to the Example2OpClass.eq function requirements
569 easiest way to do that is to create a class that has the exact
570 same member layout (self.op1, self.op2) as Example2OpClass
572 def __init__(self
, op1
, op2
):
577 def resultfn_8(o_data
, expected
, i
, o
):
578 res
= expected
.op1
+ expected
.op2
# these are a TestInputAdd instance
579 assert o_data
== res
, \
580 "%d-%d data %s res %x not match %s\n" \
581 % (i
, o
, repr(o_data
), res
, repr(expected
))
585 for i
in range(num_tests
):
586 data
.append(TestInputAdd(randint(0, 1<<16-1), randint(0, 1<<16-1)))
590 ######################################################################
592 ######################################################################
594 class ExampleStageDelayCls(StageCls
):
595 """ an example of how to use the buffered pipeline, in a static class
599 def __init__(self
, valid_trigger
=2):
600 self
.count
= Signal(2)
601 self
.valid_trigger
= valid_trigger
604 return Signal(16, name
="example_input_signal")
607 return Signal(16, name
="example_output_signal")
611 """ data is ready to be accepted when this is true
613 return (self
.count
== 1)# | (self.count == 3)
616 def d_valid(self
, i_ready
):
617 """ data is valid at output when this is true
619 return self
.count
== self
.valid_trigger
622 def process(self
, i
):
625 def postprocess(self
, i
):
626 """ process the input data and returns it (adds 1)
630 def elaborate(self
, platform
):
632 m
.d
.sync
+= self
.count
.eq(self
.count
+ 1)
636 class ExampleBufDelayedPipe(BufferedHandshake
):
639 stage
= ExampleStageDelayCls(valid_trigger
=2)
640 BufferedHandshake
.__init
__(self
, stage
, stage_ctl
=True)
642 def elaborate(self
, platform
):
643 m
= BufferedHandshake
.elaborate(self
, platform
)
644 m
.submodules
.stage
= self
.stage
650 for i
in range(num_tests
):
651 data
.append(1<<((i
*3)%15))
652 #data.append(randint(0, 1<<16-2))
653 #print (hex(data[-1]))
657 def resultfn_12(o_data
, expected
, i
, o
):
659 assert o_data
== res
, \
660 "%d-%d data %x not match %x\n" \
661 % (i
, o
, o_data
, res
)
664 ######################################################################
666 ######################################################################
668 class ExampleUnBufDelayedPipe(BufferedHandshake
):
671 stage
= ExampleStageDelayCls(valid_trigger
=3)
672 BufferedHandshake
.__init
__(self
, stage
, stage_ctl
=True)
674 def elaborate(self
, platform
):
675 m
= BufferedHandshake
.elaborate(self
, platform
)
676 m
.submodules
.stage
= self
.stage
679 ######################################################################
681 ######################################################################
683 class ExampleBufModeAdd1Pipe(SimpleHandshake
):
686 stage
= ExampleStageCls()
687 SimpleHandshake
.__init
__(self
, stage
)
690 ######################################################################
692 ######################################################################
694 class ExampleBufModeUnBufPipe(ControlBase
):
696 def elaborate(self
, platform
):
697 m
= ControlBase
._elaborate
(self
, platform
)
699 pipe1
= ExampleBufModeAdd1Pipe()
700 pipe2
= ExampleBufAdd1Pipe()
702 m
.submodules
.pipe1
= pipe1
703 m
.submodules
.pipe2
= pipe2
705 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
709 ######################################################################
711 ######################################################################
713 class ExampleUnBufAdd1Pipe2(UnbufferedPipeline2
):
716 stage
= ExampleStageCls()
717 UnbufferedPipeline2
.__init__(self
, stage
)
720 ######################################################################
722 ######################################################################
724 class PassThroughTest(PassThroughHandshake
):
727 return Signal(16, "out")
730 stage
= PassThroughStage(self
.iospecfn
)
731 PassThroughHandshake
.__init
__(self
, stage
)
733 def resultfn_identical(o_data
, expected
, i
, o
):
735 assert o_data
== res
, \
736 "%d-%d data %x not match %x\n" \
737 % (i
, o
, o_data
, res
)
740 ######################################################################
742 ######################################################################
744 class ExamplePassAdd1Pipe(PassThroughHandshake
):
747 stage
= ExampleStageCls()
748 PassThroughHandshake
.__init
__(self
, stage
)
751 class ExampleBufPassThruPipe(ControlBase
):
753 def elaborate(self
, platform
):
754 m
= ControlBase
._elaborate
(self
, platform
)
756 # XXX currently fails: any other permutation works fine.
757 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
758 # also fails using UnbufferedPipeline as well
759 pipe1
= ExampleBufModeAdd1Pipe()
760 pipe2
= ExamplePassAdd1Pipe()
762 m
.submodules
.pipe1
= pipe1
763 m
.submodules
.pipe2
= pipe2
765 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
770 ######################################################################
772 ######################################################################
775 return Signal(16, name
="d_in")
777 class FIFOTest16(FIFOControl
):
780 stage
= PassThroughStage(iospecfn
)
781 FIFOControl
.__init
__(self
, 2, stage
)
784 ######################################################################
786 ######################################################################
788 class ExampleFIFOPassThruPipe1(ControlBase
):
790 def elaborate(self
, platform
):
791 m
= ControlBase
._elaborate
(self
, platform
)
794 pipe2
= ExamplePassAdd1Pipe()
796 m
.submodules
.pipe1
= pipe1
797 m
.submodules
.pipe2
= pipe2
799 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
804 ######################################################################
806 ######################################################################
808 class Example2OpRecord(RecordObject
):
810 RecordObject
.__init
__(self
)
811 self
.op1
= Signal(16)
812 self
.op2
= Signal(16)
815 class ExampleAddRecordObjectStage(StageCls
):
818 """ returns an instance of an Example2OpRecord.
820 return Example2OpRecord()
823 """ returns an output signal which will happen to contain the sum
828 def process(self
, i
):
829 """ process the input data (sums the values in the tuple) and returns it
834 class ExampleRecordHandshakeAddClass(SimpleHandshake
):
837 addstage
= ExampleAddRecordObjectStage()
838 SimpleHandshake
.__init
__(self
, stage
=addstage
)
841 ######################################################################
843 ######################################################################
845 def iospecfnrecord():
846 return Example2OpRecord()
848 class FIFOTestRecordControl(FIFOControl
):
851 stage
= PassThroughStage(iospecfnrecord
)
852 FIFOControl
.__init
__(self
, 2, stage
)
855 class ExampleFIFORecordObjectPipe(ControlBase
):
857 def elaborate(self
, platform
):
858 m
= ControlBase
._elaborate
(self
, platform
)
860 pipe1
= FIFOTestRecordControl()
861 pipe2
= ExampleRecordHandshakeAddClass()
863 m
.submodules
.pipe1
= pipe1
864 m
.submodules
.pipe2
= pipe2
866 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
871 ######################################################################
873 ######################################################################
875 class FIFOTestRecordAddStageControl(FIFOControl
):
878 stage
= ExampleAddRecordObjectStage()
879 FIFOControl
.__init
__(self
, 2, stage
)
883 ######################################################################
885 ######################################################################
887 class FIFOTestAdd16(FIFOControl
):
890 stage
= ExampleStageCls()
891 FIFOControl
.__init
__(self
, 2, stage
)
894 class ExampleFIFOAdd2Pipe(ControlBase
):
896 def elaborate(self
, platform
):
897 m
= ControlBase
._elaborate
(self
, platform
)
899 pipe1
= FIFOTestAdd16()
900 pipe2
= FIFOTestAdd16()
902 m
.submodules
.pipe1
= pipe1
903 m
.submodules
.pipe2
= pipe2
905 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
910 ######################################################################
912 ######################################################################
915 return (Signal(16, name
="src1"), Signal(16, name
="src2"))
917 class FIFOTest2x16(FIFOControl
):
920 stage
= PassThroughStage(iospecfn2
)
921 FIFOControl
.__init
__(self
, 2, stage
)
924 ######################################################################
926 ######################################################################
928 class ExampleBufPassThruPipe2(ControlBase
):
930 def elaborate(self
, platform
):
931 m
= ControlBase
._elaborate
(self
, platform
)
933 # XXX currently fails: any other permutation works fine.
934 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
935 # also fails using UnbufferedPipeline as well
936 #pipe1 = ExampleUnBufAdd1Pipe()
937 #pipe2 = ExampleBufAdd1Pipe()
938 pipe1
= ExampleBufAdd1Pipe()
939 pipe2
= ExamplePassAdd1Pipe()
941 m
.submodules
.pipe1
= pipe1
942 m
.submodules
.pipe2
= pipe2
944 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
949 ######################################################################
951 ######################################################################
953 class ExampleBufPipe3(ControlBase
):
954 """ Example of how to do delayed pipeline, where the stage signals
958 def elaborate(self
, platform
):
959 m
= ControlBase
._elaborate
(self
, platform
)
961 pipe1
= ExampleBufDelayedPipe()
962 pipe2
= ExampleBufPipe()
964 m
.submodules
.pipe1
= pipe1
965 m
.submodules
.pipe2
= pipe2
967 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
971 ######################################################################
972 # Test 999 - XXX FAILS
973 # http://bugs.libre-riscv.org/show_bug.cgi?id=57
974 ######################################################################
976 class ExampleBufAdd1Pipe(BufferedHandshake
):
979 stage
= ExampleStageCls()
980 BufferedHandshake
.__init
__(self
, stage
)
983 class ExampleUnBufAdd1Pipe(UnbufferedPipeline
):
986 stage
= ExampleStageCls()
987 UnbufferedPipeline
.__init
__(self
, stage
)
990 class ExampleBufUnBufPipe(ControlBase
):
992 def elaborate(self
, platform
):
993 m
= ControlBase
._elaborate
(self
, platform
)
995 # XXX currently fails: any other permutation works fine.
996 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
997 # also fails using UnbufferedPipeline as well
998 #pipe1 = ExampleUnBufAdd1Pipe()
999 #pipe2 = ExampleBufAdd1Pipe()
1000 pipe1
= ExampleBufAdd1Pipe()
1001 pipe2
= ExampleUnBufAdd1Pipe()
1003 m
.submodules
.pipe1
= pipe1
1004 m
.submodules
.pipe2
= pipe2
1006 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
1011 ######################################################################
1013 ######################################################################
1017 if __name__
== '__main__':
1019 dut
= ExampleBufPipe()
1020 run_simulation(dut
, tbench(dut
), vcd_name
="test_bufpipe.vcd")
1023 dut
= ExampleBufPipe2()
1024 run_simulation(dut
, tbench2(dut
), vcd_name
="test_bufpipe2.vcd")
1025 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1026 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1027 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1028 vl
= rtlil
.convert(dut
, ports
=ports
)
1029 with
open("test_bufpipe2.il", "w") as f
:
1034 dut
= ExampleBufPipe()
1035 test
= Test3(dut
, resultfn_3
)
1036 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe3.vcd")
1039 dut
= ExamplePipeline()
1040 test
= Test3(dut
, resultfn_3
)
1041 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_combpipe3.vcd")
1044 dut
= ExampleBufPipe2()
1045 run_simulation(dut
, tbench4(dut
), vcd_name
="test_bufpipe4.vcd")
1048 dut
= ExampleBufPipeAdd()
1049 test
= Test5(dut
, resultfn_5
, stage_ctl
=True)
1050 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe5.vcd")
1053 dut
= ExampleLTPipeline()
1054 test
= Test5(dut
, resultfn_6
)
1055 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_ltcomb6.vcd")
1057 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1058 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1059 list(dut
.p
.i_data
) + [dut
.n
.o_data
]
1060 vl
= rtlil
.convert(dut
, ports
=ports
)
1061 with
open("test_ltcomb_pipe.il", "w") as f
:
1065 dut
= ExampleAddRecordPipe()
1067 test
= Test5(dut
, resultfn_7
, data
=data
)
1068 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord.vcd")
1070 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1071 dut
.n
.o_valid
, dut
.p
.o_ready
,
1072 dut
.p
.i_data
.src1
, dut
.p
.i_data
.src2
,
1073 dut
.n
.o_data
.src1
, dut
.n
.o_data
.src2
]
1074 vl
= rtlil
.convert(dut
, ports
=ports
)
1075 with
open("test_recordcomb_pipe.il", "w") as f
:
1079 dut
= ExampleBufPipeAddClass()
1081 test
= Test5(dut
, resultfn_8
, data
=data
)
1082 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe8.vcd")
1085 dut
= ExampleBufPipeChain2()
1086 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1087 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1088 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1089 vl
= rtlil
.convert(dut
, ports
=ports
)
1090 with
open("test_bufpipechain2.il", "w") as f
:
1093 data
= data_chain2()
1094 test
= Test5(dut
, resultfn_9
, data
=data
)
1095 run_simulation(dut
, [test
.send
, test
.rcv
],
1096 vcd_name
="test_bufpipechain2.vcd")
1099 dut
= ExampleLTBufferedPipeDerived()
1100 test
= Test5(dut
, resultfn_6
)
1101 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_ltbufpipe10.vcd")
1102 vl
= rtlil
.convert(dut
, ports
=ports
)
1103 with
open("test_ltbufpipe10.il", "w") as f
:
1107 dut
= ExampleAddRecordPlaceHolderPipe()
1108 data
=data_placeholder()
1109 test
= Test5(dut
, resultfn_test11
, data
=data
)
1110 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord.vcd")
1114 dut
= ExampleBufDelayedPipe()
1115 data
= data_chain1()
1116 test
= Test5(dut
, resultfn_12
, data
=data
)
1117 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe12.vcd")
1118 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1119 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1120 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1121 vl
= rtlil
.convert(dut
, ports
=ports
)
1122 with
open("test_bufpipe12.il", "w") as f
:
1126 dut
= ExampleUnBufDelayedPipe()
1127 data
= data_chain1()
1128 test
= Test5(dut
, resultfn_12
, data
=data
)
1129 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_unbufpipe13.vcd")
1130 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1131 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1132 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1133 vl
= rtlil
.convert(dut
, ports
=ports
)
1134 with
open("test_unbufpipe13.il", "w") as f
:
1138 dut
= ExampleBufModeAdd1Pipe()
1139 data
= data_chain1()
1140 test
= Test5(dut
, resultfn_12
, data
=data
)
1141 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufunbuf15.vcd")
1142 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1143 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1144 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1145 vl
= rtlil
.convert(dut
, ports
=ports
)
1146 with
open("test_bufunbuf15.il", "w") as f
:
1150 dut
= ExampleBufModeUnBufPipe()
1151 data
= data_chain1()
1152 test
= Test5(dut
, resultfn_9
, data
=data
)
1153 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufunbuf16.vcd")
1154 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1155 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1156 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1157 vl
= rtlil
.convert(dut
, ports
=ports
)
1158 with
open("test_bufunbuf16.il", "w") as f
:
1162 dut
= ExampleUnBufAdd1Pipe2()
1163 data
= data_chain1()
1164 test
= Test5(dut
, resultfn_12
, data
=data
)
1165 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_unbufpipe17.vcd")
1166 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1167 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1168 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1169 vl
= rtlil
.convert(dut
, ports
=ports
)
1170 with
open("test_unbufpipe17.il", "w") as f
:
1174 dut
= PassThroughTest()
1175 data
= data_chain1()
1176 test
= Test5(dut
, resultfn_identical
, data
=data
)
1177 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_passthru18.vcd")
1178 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1179 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1180 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1181 vl
= rtlil
.convert(dut
, ports
=ports
)
1182 with
open("test_passthru18.il", "w") as f
:
1186 dut
= ExampleBufPassThruPipe()
1187 data
= data_chain1()
1188 test
= Test5(dut
, resultfn_9
, data
=data
)
1189 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpass19.vcd")
1190 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1191 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1192 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1193 vl
= rtlil
.convert(dut
, ports
=ports
)
1194 with
open("test_bufpass19.il", "w") as f
:
1199 data
= data_chain1()
1200 test
= Test5(dut
, resultfn_identical
, data
=data
)
1201 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_fifo20.vcd")
1202 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1203 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1204 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1205 vl
= rtlil
.convert(dut
, ports
=ports
)
1206 with
open("test_fifo20.il", "w") as f
:
1210 dut
= ExampleFIFOPassThruPipe1()
1211 data
= data_chain1()
1212 test
= Test5(dut
, resultfn_12
, data
=data
)
1213 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_fifopass21.vcd")
1214 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1215 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1216 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1217 vl
= rtlil
.convert(dut
, ports
=ports
)
1218 with
open("test_fifopass21.il", "w") as f
:
1222 dut
= ExampleRecordHandshakeAddClass()
1224 test
= Test5(dut
, resultfn_8
, data
=data
)
1225 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord22.vcd")
1226 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1227 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1228 [dut
.p
.i_data
.op1
, dut
.p
.i_data
.op2
] + \
1230 vl
= rtlil
.convert(dut
, ports
=ports
)
1231 with
open("test_addrecord22.il", "w") as f
:
1235 dut
= ExampleFIFORecordObjectPipe()
1237 test
= Test5(dut
, resultfn_8
, data
=data
)
1238 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord23.vcd")
1239 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1240 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1241 [dut
.p
.i_data
.op1
, dut
.p
.i_data
.op2
] + \
1243 vl
= rtlil
.convert(dut
, ports
=ports
)
1244 with
open("test_addrecord23.il", "w") as f
:
1248 dut
= FIFOTestRecordAddStageControl()
1250 test
= Test5(dut
, resultfn_8
, data
=data
)
1251 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1252 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1253 [dut
.p
.i_data
.op1
, dut
.p
.i_data
.op2
] + \
1255 vl
= rtlil
.convert(dut
, ports
=ports
)
1256 with
open("test_addrecord24.il", "w") as f
:
1258 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord24.vcd")
1261 dut
= ExampleFIFOAdd2Pipe()
1262 data
= data_chain1()
1263 test
= Test5(dut
, resultfn_9
, data
=data
)
1264 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_add2pipe25.vcd")
1265 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1266 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1267 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1268 vl
= rtlil
.convert(dut
, ports
=ports
)
1269 with
open("test_add2pipe25.il", "w") as f
:
1273 dut
= ExampleBufPassThruPipe2()
1274 data
= data_chain1()
1275 test
= Test5(dut
, resultfn_9
, data
=data
)
1276 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpass997.vcd")
1277 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1278 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1279 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1280 vl
= rtlil
.convert(dut
, ports
=ports
)
1281 with
open("test_bufpass997.il", "w") as f
:
1284 print ("test 998 (fails, bug)")
1285 dut
= ExampleBufPipe3()
1286 data
= data_chain1()
1287 test
= Test5(dut
, resultfn_9
, data
=data
)
1288 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe14.vcd")
1289 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1290 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1291 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1292 vl
= rtlil
.convert(dut
, ports
=ports
)
1293 with
open("test_bufpipe14.il", "w") as f
:
1296 print ("test 999 (expected to fail, which is a bug)")
1297 dut
= ExampleBufUnBufPipe()
1298 data
= data_chain1()
1299 test
= Test5(dut
, resultfn_9
, data
=data
)
1300 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufunbuf999.vcd")
1301 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1302 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1303 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1304 vl
= rtlil
.convert(dut
, ports
=ports
)
1305 with
open("test_bufunbuf999.il", "w") as f
: