b04a96a5378ea37edb46c91c487507e19862cad3
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 return (self
.count
== 1)# | (self.count == 3)
614 def d_valid(self
, i_ready
):
615 return self
.count
== self
.valid_trigger
618 def process(self
, i
):
619 """ process the input data and returns it (adds 1)
623 def elaborate(self
, platform
):
625 m
.d
.sync
+= self
.count
.eq(self
.count
+ 1)
629 class ExampleBufDelayedPipe(BufferedHandshake
):
632 stage
= ExampleStageDelayCls(valid_trigger
=2)
633 BufferedHandshake
.__init
__(self
, stage
, stage_ctl
=True)
635 def elaborate(self
, platform
):
636 m
= BufferedHandshake
.elaborate(self
, platform
)
637 m
.submodules
.stage
= self
.stage
643 for i
in range(num_tests
):
644 data
.append(1<<((i
*3)%15))
645 #data.append(randint(0, 1<<16-2))
646 #print (hex(data[-1]))
650 def resultfn_12(o_data
, expected
, i
, o
):
652 assert o_data
== res
, \
653 "%d-%d data %x not match %x\n" \
654 % (i
, o
, o_data
, res
)
657 ######################################################################
659 ######################################################################
661 class ExampleUnBufDelayedPipe(BufferedHandshake
):
664 stage
= ExampleStageDelayCls(valid_trigger
=3)
665 BufferedHandshake
.__init
__(self
, stage
, stage_ctl
=True)
667 def elaborate(self
, platform
):
668 m
= BufferedHandshake
.elaborate(self
, platform
)
669 m
.submodules
.stage
= self
.stage
672 ######################################################################
674 ######################################################################
676 class ExampleBufModeAdd1Pipe(SimpleHandshake
):
679 stage
= ExampleStageCls()
680 SimpleHandshake
.__init
__(self
, stage
)
683 ######################################################################
685 ######################################################################
687 class ExampleBufModeUnBufPipe(ControlBase
):
689 def elaborate(self
, platform
):
690 m
= ControlBase
._elaborate
(self
, platform
)
692 pipe1
= ExampleBufModeAdd1Pipe()
693 pipe2
= ExampleBufAdd1Pipe()
695 m
.submodules
.pipe1
= pipe1
696 m
.submodules
.pipe2
= pipe2
698 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
702 ######################################################################
704 ######################################################################
706 class ExampleUnBufAdd1Pipe2(UnbufferedPipeline2
):
709 stage
= ExampleStageCls()
710 UnbufferedPipeline2
.__init__(self
, stage
)
713 ######################################################################
715 ######################################################################
717 class PassThroughTest(PassThroughHandshake
):
720 return Signal(16, "out")
723 stage
= PassThroughStage(self
.iospecfn
)
724 PassThroughHandshake
.__init
__(self
, stage
)
726 def resultfn_identical(o_data
, expected
, i
, o
):
728 assert o_data
== res
, \
729 "%d-%d data %x not match %x\n" \
730 % (i
, o
, o_data
, res
)
733 ######################################################################
735 ######################################################################
737 class ExamplePassAdd1Pipe(PassThroughHandshake
):
740 stage
= ExampleStageCls()
741 PassThroughHandshake
.__init
__(self
, stage
)
744 class ExampleBufPassThruPipe(ControlBase
):
746 def elaborate(self
, platform
):
747 m
= ControlBase
._elaborate
(self
, platform
)
749 # XXX currently fails: any other permutation works fine.
750 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
751 # also fails using UnbufferedPipeline as well
752 pipe1
= ExampleBufModeAdd1Pipe()
753 pipe2
= ExamplePassAdd1Pipe()
755 m
.submodules
.pipe1
= pipe1
756 m
.submodules
.pipe2
= pipe2
758 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
763 ######################################################################
765 ######################################################################
768 return Signal(16, name
="d_in")
770 class FIFOTest16(FIFOControl
):
773 stage
= PassThroughStage(iospecfn
)
774 FIFOControl
.__init
__(self
, 2, stage
)
777 ######################################################################
779 ######################################################################
781 class ExampleFIFOPassThruPipe1(ControlBase
):
783 def elaborate(self
, platform
):
784 m
= ControlBase
._elaborate
(self
, platform
)
787 pipe2
= ExamplePassAdd1Pipe()
789 m
.submodules
.pipe1
= pipe1
790 m
.submodules
.pipe2
= pipe2
792 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
797 ######################################################################
799 ######################################################################
801 class Example2OpRecord(RecordObject
):
803 RecordObject
.__init
__(self
)
804 self
.op1
= Signal(16)
805 self
.op2
= Signal(16)
808 class ExampleAddRecordObjectStage(StageCls
):
811 """ returns an instance of an Example2OpRecord.
813 return Example2OpRecord()
816 """ returns an output signal which will happen to contain the sum
821 def process(self
, i
):
822 """ process the input data (sums the values in the tuple) and returns it
827 class ExampleRecordHandshakeAddClass(SimpleHandshake
):
830 addstage
= ExampleAddRecordObjectStage()
831 SimpleHandshake
.__init
__(self
, stage
=addstage
)
834 ######################################################################
836 ######################################################################
838 def iospecfnrecord():
839 return Example2OpRecord()
841 class FIFOTestRecordControl(FIFOControl
):
844 stage
= PassThroughStage(iospecfnrecord
)
845 FIFOControl
.__init
__(self
, 2, stage
)
848 class ExampleFIFORecordObjectPipe(ControlBase
):
850 def elaborate(self
, platform
):
851 m
= ControlBase
._elaborate
(self
, platform
)
853 pipe1
= FIFOTestRecordControl()
854 pipe2
= ExampleRecordHandshakeAddClass()
856 m
.submodules
.pipe1
= pipe1
857 m
.submodules
.pipe2
= pipe2
859 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
864 ######################################################################
866 ######################################################################
868 class FIFOTestRecordAddStageControl(FIFOControl
):
871 stage
= ExampleAddRecordObjectStage()
872 FIFOControl
.__init
__(self
, 2, stage
)
876 ######################################################################
878 ######################################################################
880 class FIFOTestAdd16(FIFOControl
):
883 stage
= ExampleStageCls()
884 FIFOControl
.__init
__(self
, 2, stage
)
887 class ExampleFIFOAdd2Pipe(ControlBase
):
889 def elaborate(self
, platform
):
890 m
= ControlBase
._elaborate
(self
, platform
)
892 pipe1
= FIFOTestAdd16()
893 pipe2
= FIFOTestAdd16()
895 m
.submodules
.pipe1
= pipe1
896 m
.submodules
.pipe2
= pipe2
898 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
903 ######################################################################
905 ######################################################################
908 return (Signal(16, name
="src1"), Signal(16, name
="src2"))
910 class FIFOTest2x16(FIFOControl
):
913 stage
= PassThroughStage(iospecfn2
)
914 FIFOControl
.__init
__(self
, 2, stage
)
917 ######################################################################
919 ######################################################################
921 class ExampleBufPassThruPipe2(ControlBase
):
923 def elaborate(self
, platform
):
924 m
= ControlBase
._elaborate
(self
, platform
)
926 # XXX currently fails: any other permutation works fine.
927 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
928 # also fails using UnbufferedPipeline as well
929 #pipe1 = ExampleUnBufAdd1Pipe()
930 #pipe2 = ExampleBufAdd1Pipe()
931 pipe1
= ExampleBufAdd1Pipe()
932 pipe2
= ExamplePassAdd1Pipe()
934 m
.submodules
.pipe1
= pipe1
935 m
.submodules
.pipe2
= pipe2
937 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
942 ######################################################################
944 ######################################################################
946 class ExampleBufPipe3(ControlBase
):
947 """ Example of how to do delayed pipeline, where the stage signals
951 def elaborate(self
, platform
):
952 m
= ControlBase
._elaborate
(self
, platform
)
954 pipe1
= ExampleBufDelayedPipe()
955 pipe2
= ExampleBufPipe()
957 m
.submodules
.pipe1
= pipe1
958 m
.submodules
.pipe2
= pipe2
960 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
964 ######################################################################
965 # Test 999 - XXX FAILS
966 # http://bugs.libre-riscv.org/show_bug.cgi?id=57
967 ######################################################################
969 class ExampleBufAdd1Pipe(BufferedHandshake
):
972 stage
= ExampleStageCls()
973 BufferedHandshake
.__init
__(self
, stage
)
976 class ExampleUnBufAdd1Pipe(UnbufferedPipeline
):
979 stage
= ExampleStageCls()
980 UnbufferedPipeline
.__init
__(self
, stage
)
983 class ExampleBufUnBufPipe(ControlBase
):
985 def elaborate(self
, platform
):
986 m
= ControlBase
._elaborate
(self
, platform
)
988 # XXX currently fails: any other permutation works fine.
989 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
990 # also fails using UnbufferedPipeline as well
991 #pipe1 = ExampleUnBufAdd1Pipe()
992 #pipe2 = ExampleBufAdd1Pipe()
993 pipe1
= ExampleBufAdd1Pipe()
994 pipe2
= ExampleUnBufAdd1Pipe()
996 m
.submodules
.pipe1
= pipe1
997 m
.submodules
.pipe2
= pipe2
999 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
1004 ######################################################################
1006 ######################################################################
1010 if __name__
== '__main__':
1012 dut
= ExampleBufPipe()
1013 run_simulation(dut
, tbench(dut
), vcd_name
="test_bufpipe.vcd")
1016 dut
= ExampleBufPipe2()
1017 run_simulation(dut
, tbench2(dut
), vcd_name
="test_bufpipe2.vcd")
1018 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1019 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1020 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1021 vl
= rtlil
.convert(dut
, ports
=ports
)
1022 with
open("test_bufpipe2.il", "w") as f
:
1027 dut
= ExampleBufPipe()
1028 test
= Test3(dut
, resultfn_3
)
1029 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe3.vcd")
1032 dut
= ExamplePipeline()
1033 test
= Test3(dut
, resultfn_3
)
1034 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_combpipe3.vcd")
1037 dut
= ExampleBufPipe2()
1038 run_simulation(dut
, tbench4(dut
), vcd_name
="test_bufpipe4.vcd")
1041 dut
= ExampleBufPipeAdd()
1042 test
= Test5(dut
, resultfn_5
, stage_ctl
=True)
1043 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe5.vcd")
1046 dut
= ExampleLTPipeline()
1047 test
= Test5(dut
, resultfn_6
)
1048 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_ltcomb6.vcd")
1050 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1051 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1052 list(dut
.p
.i_data
) + [dut
.n
.o_data
]
1053 vl
= rtlil
.convert(dut
, ports
=ports
)
1054 with
open("test_ltcomb_pipe.il", "w") as f
:
1058 dut
= ExampleAddRecordPipe()
1060 test
= Test5(dut
, resultfn_7
, data
=data
)
1061 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord.vcd")
1063 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1064 dut
.n
.o_valid
, dut
.p
.o_ready
,
1065 dut
.p
.i_data
.src1
, dut
.p
.i_data
.src2
,
1066 dut
.n
.o_data
.src1
, dut
.n
.o_data
.src2
]
1067 vl
= rtlil
.convert(dut
, ports
=ports
)
1068 with
open("test_recordcomb_pipe.il", "w") as f
:
1072 dut
= ExampleBufPipeAddClass()
1074 test
= Test5(dut
, resultfn_8
, data
=data
)
1075 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe8.vcd")
1078 dut
= ExampleBufPipeChain2()
1079 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1080 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1081 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1082 vl
= rtlil
.convert(dut
, ports
=ports
)
1083 with
open("test_bufpipechain2.il", "w") as f
:
1086 data
= data_chain2()
1087 test
= Test5(dut
, resultfn_9
, data
=data
)
1088 run_simulation(dut
, [test
.send
, test
.rcv
],
1089 vcd_name
="test_bufpipechain2.vcd")
1092 dut
= ExampleLTBufferedPipeDerived()
1093 test
= Test5(dut
, resultfn_6
)
1094 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_ltbufpipe10.vcd")
1095 vl
= rtlil
.convert(dut
, ports
=ports
)
1096 with
open("test_ltbufpipe10.il", "w") as f
:
1100 dut
= ExampleAddRecordPlaceHolderPipe()
1101 data
=data_placeholder()
1102 test
= Test5(dut
, resultfn_test11
, data
=data
)
1103 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord.vcd")
1107 dut
= ExampleBufDelayedPipe()
1108 data
= data_chain1()
1109 test
= Test5(dut
, resultfn_12
, data
=data
)
1110 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe12.vcd")
1111 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1112 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1113 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1114 vl
= rtlil
.convert(dut
, ports
=ports
)
1115 with
open("test_bufpipe12.il", "w") as f
:
1119 dut
= ExampleUnBufDelayedPipe()
1120 data
= data_chain1()
1121 test
= Test5(dut
, resultfn_12
, data
=data
)
1122 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_unbufpipe13.vcd")
1123 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1124 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1125 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1126 vl
= rtlil
.convert(dut
, ports
=ports
)
1127 with
open("test_unbufpipe13.il", "w") as f
:
1131 dut
= ExampleBufModeAdd1Pipe()
1132 data
= data_chain1()
1133 test
= Test5(dut
, resultfn_12
, data
=data
)
1134 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufunbuf15.vcd")
1135 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1136 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1137 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1138 vl
= rtlil
.convert(dut
, ports
=ports
)
1139 with
open("test_bufunbuf15.il", "w") as f
:
1143 dut
= ExampleBufModeUnBufPipe()
1144 data
= data_chain1()
1145 test
= Test5(dut
, resultfn_9
, data
=data
)
1146 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufunbuf16.vcd")
1147 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1148 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1149 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1150 vl
= rtlil
.convert(dut
, ports
=ports
)
1151 with
open("test_bufunbuf16.il", "w") as f
:
1155 dut
= ExampleUnBufAdd1Pipe2()
1156 data
= data_chain1()
1157 test
= Test5(dut
, resultfn_12
, data
=data
)
1158 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_unbufpipe17.vcd")
1159 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1160 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1161 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1162 vl
= rtlil
.convert(dut
, ports
=ports
)
1163 with
open("test_unbufpipe17.il", "w") as f
:
1167 dut
= PassThroughTest()
1168 data
= data_chain1()
1169 test
= Test5(dut
, resultfn_identical
, data
=data
)
1170 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_passthru18.vcd")
1171 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1172 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1173 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1174 vl
= rtlil
.convert(dut
, ports
=ports
)
1175 with
open("test_passthru18.il", "w") as f
:
1179 dut
= ExampleBufPassThruPipe()
1180 data
= data_chain1()
1181 test
= Test5(dut
, resultfn_9
, data
=data
)
1182 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpass19.vcd")
1183 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1184 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1185 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1186 vl
= rtlil
.convert(dut
, ports
=ports
)
1187 with
open("test_bufpass19.il", "w") as f
:
1192 data
= data_chain1()
1193 test
= Test5(dut
, resultfn_identical
, data
=data
)
1194 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_fifo20.vcd")
1195 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1196 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1197 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1198 vl
= rtlil
.convert(dut
, ports
=ports
)
1199 with
open("test_fifo20.il", "w") as f
:
1203 dut
= ExampleFIFOPassThruPipe1()
1204 data
= data_chain1()
1205 test
= Test5(dut
, resultfn_12
, data
=data
)
1206 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_fifopass21.vcd")
1207 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1208 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1209 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1210 vl
= rtlil
.convert(dut
, ports
=ports
)
1211 with
open("test_fifopass21.il", "w") as f
:
1215 dut
= ExampleRecordHandshakeAddClass()
1217 test
= Test5(dut
, resultfn_8
, data
=data
)
1218 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord22.vcd")
1219 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1220 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1221 [dut
.p
.i_data
.op1
, dut
.p
.i_data
.op2
] + \
1223 vl
= rtlil
.convert(dut
, ports
=ports
)
1224 with
open("test_addrecord22.il", "w") as f
:
1228 dut
= ExampleFIFORecordObjectPipe()
1230 test
= Test5(dut
, resultfn_8
, data
=data
)
1231 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord23.vcd")
1232 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1233 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1234 [dut
.p
.i_data
.op1
, dut
.p
.i_data
.op2
] + \
1236 vl
= rtlil
.convert(dut
, ports
=ports
)
1237 with
open("test_addrecord23.il", "w") as f
:
1241 dut
= FIFOTestRecordAddStageControl()
1243 test
= Test5(dut
, resultfn_8
, data
=data
)
1244 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1245 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1246 [dut
.p
.i_data
.op1
, dut
.p
.i_data
.op2
] + \
1248 vl
= rtlil
.convert(dut
, ports
=ports
)
1249 with
open("test_addrecord24.il", "w") as f
:
1251 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord24.vcd")
1254 dut
= ExampleFIFOAdd2Pipe()
1255 data
= data_chain1()
1256 test
= Test5(dut
, resultfn_9
, data
=data
)
1257 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_add2pipe25.vcd")
1258 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1259 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1260 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1261 vl
= rtlil
.convert(dut
, ports
=ports
)
1262 with
open("test_add2pipe25.il", "w") as f
:
1266 dut
= ExampleBufPassThruPipe2()
1267 data
= data_chain1()
1268 test
= Test5(dut
, resultfn_9
, data
=data
)
1269 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpass997.vcd")
1270 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1271 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1272 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1273 vl
= rtlil
.convert(dut
, ports
=ports
)
1274 with
open("test_bufpass997.il", "w") as f
:
1277 print ("test 998 (fails, bug)")
1278 dut
= ExampleBufPipe3()
1279 data
= data_chain1()
1280 test
= Test5(dut
, resultfn_9
, data
=data
)
1281 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe14.vcd")
1282 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1283 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1284 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1285 vl
= rtlil
.convert(dut
, ports
=ports
)
1286 with
open("test_bufpipe14.il", "w") as f
:
1289 print ("test 999 (expected to fail, which is a bug)")
1290 dut
= ExampleBufUnBufPipe()
1291 data
= data_chain1()
1292 test
= Test5(dut
, resultfn_9
, data
=data
)
1293 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufunbuf999.vcd")
1294 ports
= [dut
.p
.i_valid
, dut
.n
.i_ready
,
1295 dut
.n
.o_valid
, dut
.p
.o_ready
] + \
1296 [dut
.p
.i_data
] + [dut
.n
.o_data
]
1297 vl
= rtlil
.convert(dut
, ports
=ports
)
1298 with
open("test_bufunbuf999.il", "w") as f
: