9035d932124d855066ba24bf42a86b3374cb3651
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
, Elaboratable
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 nmutil
.singlepipe
import UnbufferedPipeline2
28 from nmutil
.singlepipe
import SimpleHandshake
29 from nmutil
.singlepipe
import PassThroughHandshake
30 from nmutil
.singlepipe
import PassThroughStage
31 from nmutil
.singlepipe
import FIFOControl
32 from nmutil
.singlepipe
import RecordObject
34 from random
import randint
, seed
39 def check_o_n_valid(dut
, val
):
40 o_n_valid
= yield dut
.n
.valid_o
41 assert o_n_valid
== val
43 def check_o_n_valid2(dut
, val
):
44 o_n_valid
= yield dut
.n
.valid_o
45 assert o_n_valid
== val
49 #yield dut.i_p_rst.eq(1)
50 yield dut
.n
.ready_i
.eq(0)
51 #yield dut.p.ready_o.eq(0)
54 #yield dut.i_p_rst.eq(0)
55 yield dut
.n
.ready_i
.eq(1)
56 yield dut
.p
.data_i
.eq(5)
57 yield dut
.p
.valid_i
.eq(1)
60 yield dut
.p
.data_i
.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
.data_i
.eq(2)
67 yield dut
.n
.ready_i
.eq(0) # begin going into "stall" (next stage says ready)
68 yield dut
.p
.data_i
.eq(9)
70 yield dut
.p
.valid_i
.eq(0)
71 yield dut
.p
.data_i
.eq(12)
73 yield dut
.p
.data_i
.eq(32)
74 yield dut
.n
.ready_i
.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
.ready_i
.eq(0)
87 #yield dut.p.ready_o.eq(0)
90 #yield dut.p.i_rst.eq(0)
91 yield dut
.n
.ready_i
.eq(1)
92 yield dut
.p
.data_i
.eq(5)
93 yield dut
.p
.valid_i
.eq(1)
96 yield dut
.p
.data_i
.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
.data_i
.eq(2)
103 yield from check_o_n_valid2(dut
, 1) # ok *now* i_p_valid effect is felt
104 yield dut
.n
.ready_i
.eq(0) # begin going into "stall" (next stage says ready)
105 yield dut
.p
.data_i
.eq(9)
107 yield dut
.p
.valid_i
.eq(0)
108 yield dut
.p
.data_i
.eq(12)
110 yield dut
.p
.data_i
.eq(32)
111 yield dut
.n
.ready_i
.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
.ready_o
148 if send
and self
.i
!= len(self
.data
):
149 yield self
.dut
.p
.valid_i
.eq(1)
150 yield self
.dut
.p
.data_i
.eq(self
.data
[self
.i
])
153 yield self
.dut
.p
.valid_i
.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
.ready_i
.eq(stall
)
163 o_n_valid
= yield self
.dut
.n
.valid_o
164 i_n_ready
= yield self
.dut
.n
.ready_i_test
165 if not o_n_valid
or not i_n_ready
:
167 data_o
= yield self
.dut
.n
.data_o
168 self
.resultfn(data_o
, self
.data
[self
.o
], self
.i
, self
.o
)
170 if self
.o
== len(self
.data
):
173 def resultfn_3(data_o
, expected
, i
, o
):
174 assert data_o
== expected
+ 1, \
175 "%d-%d data %x not match %x\n" \
176 % (i
, o
, data_o
, 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
.ready_o
222 if send
and self
.i
!= len(self
.data
):
223 yield self
.dut
.p
.valid_i
.eq(1)
224 for v
in self
.dut
.set_input(self
.data
[self
.i
]):
228 yield self
.dut
.p
.valid_i
.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
.ready_i
.eq(ready
)
239 o_n_valid
= yield self
.dut
.n
.valid_o
240 i_n_ready
= yield self
.dut
.n
.ready_i_test
241 if not o_n_valid
or not i_n_ready
:
243 if isinstance(self
.dut
.n
.data_o
, Record
):
245 dod
= self
.dut
.n
.data_o
246 for k
, v
in dod
.fields
.items():
249 data_o
= yield self
.dut
.n
.data_o
250 self
.resultfn(data_o
, self
.data
[self
.o
], self
.i
, self
.o
)
252 if self
.o
== len(self
.data
):
255 def resultfn_5(data_o
, expected
, i
, o
):
256 res
= expected
[0] + expected
[1]
257 assert data_o
== res
, \
258 "%d-%d data %x not match %s\n" \
259 % (i
, o
, data_o
, 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
.ready_i
.eq(stall
)
272 o_p_ready
= yield dut
.p
.ready_o
274 if send
and i
!= len(data
):
275 yield dut
.p
.valid_i
.eq(1)
276 yield dut
.p
.data_i
.eq(data
[i
])
279 yield dut
.p
.valid_i
.eq(0)
281 o_n_valid
= yield dut
.n
.valid_o
282 i_n_ready
= yield dut
.n
.ready_i_test
283 if o_n_valid
and i_n_ready
:
284 data_o
= yield dut
.n
.data_o
285 assert data_o
== data
[o
] + 2, "%d-%d data %x not match %x\n" \
286 % (i
, o
, data_o
, data
[o
])
291 ######################################################################
293 ######################################################################
295 class ExampleBufPipe2(ControlBase
):
296 """ Example of how to do chained pipeline stages.
299 def elaborate(self
, platform
):
300 m
= ControlBase
.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(data_o
, expected
, i
, o
):
336 assert data_o
== res
, \
337 "%d-%d received data %x not match expected %x\n" \
338 % (i
, o
, data_o
, res
)
341 ######################################################################
343 ######################################################################
345 class SetLessThan(Elaboratable
):
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)
363 def ispec(self
, name
):
364 return (Signal(16, name
="%s_sig1" % name
),
365 Signal(16, name
="%s_sig2" % name
))
367 def ospec(self
, name
):
368 return Signal(16, "%s_out" % name
)
370 def setup(self
, m
, i
):
372 m
.submodules
.slt
= self
.slt
373 m
.d
.comb
+= self
.slt
.src1
.eq(i
[0])
374 m
.d
.comb
+= self
.slt
.src2
.eq(i
[1])
375 m
.d
.comb
+= self
.o
.eq(self
.slt
.output
)
377 def process(self
, i
):
381 class LTStageDerived(SetLessThan
, StageCls
):
382 """ special version of a nmigen module where the module is also a stage
384 shows that you don't actually need to combinatorially connect
385 to the outputs, or add the module as a submodule: just return
386 the module output parameter(s) from the Stage.process() function
390 SetLessThan
.__init
__(self
, 16, True)
393 return (Signal(16), Signal(16))
398 def setup(self
, m
, i
):
399 m
.submodules
.slt
= self
400 m
.d
.comb
+= self
.src1
.eq(i
[0])
401 m
.d
.comb
+= self
.src2
.eq(i
[1])
403 def process(self
, i
):
407 class ExampleLTPipeline(UnbufferedPipeline
):
408 """ an example of how to use the unbuffered pipeline.
413 UnbufferedPipeline
.__init
__(self
, stage
)
416 class ExampleLTBufferedPipeDerived(BufferedHandshake
):
417 """ an example of how to use the buffered pipeline.
421 stage
= LTStageDerived()
422 BufferedHandshake
.__init
__(self
, stage
)
425 def resultfn_6(data_o
, expected
, i
, o
):
426 res
= 1 if expected
[0] < expected
[1] else 0
427 assert data_o
== res
, \
428 "%d-%d data %x not match %s\n" \
429 % (i
, o
, data_o
, repr(expected
))
432 ######################################################################
434 ######################################################################
436 class ExampleAddRecordStage(StageCls
):
437 """ example use of a Record
440 record_spec
= [('src1', 16), ('src2', 16)]
442 """ returns a Record using the specification
444 return Record(self
.record_spec
)
447 return Record(self
.record_spec
)
449 def process(self
, i
):
450 """ process the input data, returning a dictionary with key names
451 that exactly match the Record's attributes.
453 return {'src1': i
.src1
+ 1,
456 ######################################################################
458 ######################################################################
460 class ExampleAddRecordPlaceHolderStage(StageCls
):
461 """ example use of a Record, with a placeholder as the processing result
464 record_spec
= [('src1', 16), ('src2', 16)]
466 """ returns a Record using the specification
468 return Record(self
.record_spec
)
471 return Record(self
.record_spec
)
473 def process(self
, i
):
474 """ process the input data, returning a PlaceHolder class instance
475 with attributes that exactly match those of the Record.
483 # a dummy class that may have stuff assigned to instances once created
484 class PlaceHolder
: pass
487 class ExampleAddRecordPipe(UnbufferedPipeline
):
488 """ an example of how to use the combinatorial pipeline.
492 stage
= ExampleAddRecordStage()
493 UnbufferedPipeline
.__init
__(self
, stage
)
496 def resultfn_7(data_o
, expected
, i
, o
):
497 res
= (expected
['src1'] + 1, expected
['src2'] + 1)
498 assert data_o
['src1'] == res
[0] and data_o
['src2'] == res
[1], \
499 "%d-%d data %s not match %s\n" \
500 % (i
, o
, repr(data_o
), repr(expected
))
503 class ExampleAddRecordPlaceHolderPipe(UnbufferedPipeline
):
504 """ an example of how to use the combinatorial pipeline.
508 stage
= ExampleAddRecordPlaceHolderStage()
509 UnbufferedPipeline
.__init
__(self
, stage
)
512 def resultfn_11(data_o
, expected
, i
, o
):
513 res1
= expected
.src1
+ 1
514 res2
= expected
.src2
+ 1
515 assert data_o
['src1'] == res1
and data_o
['src2'] == res2
, \
516 "%d-%d data %s not match %s\n" \
517 % (i
, o
, repr(data_o
), repr(expected
))
520 ######################################################################
522 ######################################################################
525 class Example2OpClass
:
526 """ an example of a class used to store 2 operands.
527 requires an eq function, to conform with the pipeline stage API
531 self
.op1
= Signal(16)
532 self
.op2
= Signal(16)
535 return [self
.op1
.eq(i
.op1
), self
.op2
.eq(i
.op2
)]
538 class ExampleAddClassStage(StageCls
):
539 """ an example of how to use the buffered pipeline, as a class instance
543 """ returns an instance of an Example2OpClass.
545 return Example2OpClass()
548 """ returns an output signal which will happen to contain the sum
551 return Signal(16, name
="add2_out")
553 def process(self
, i
):
554 """ process the input data (sums the values in the tuple) and returns it
559 class ExampleBufPipeAddClass(BufferedHandshake
):
560 """ an example of how to use the buffered pipeline, using a class instance
564 addstage
= ExampleAddClassStage()
565 BufferedHandshake
.__init
__(self
, addstage
)
569 """ the eq function, called by set_input, needs an incoming object
570 that conforms to the Example2OpClass.eq function requirements
571 easiest way to do that is to create a class that has the exact
572 same member layout (self.op1, self.op2) as Example2OpClass
574 def __init__(self
, op1
, op2
):
579 def resultfn_8(data_o
, expected
, i
, o
):
580 res
= expected
.op1
+ expected
.op2
# these are a TestInputAdd instance
581 assert data_o
== res
, \
582 "%d-%d data %s res %x not match %s\n" \
583 % (i
, o
, repr(data_o
), res
, repr(expected
))
587 for i
in range(num_tests
):
588 data
.append(TestInputAdd(randint(0, 1<<16-1), randint(0, 1<<16-1)))
592 ######################################################################
594 ######################################################################
596 class ExampleStageDelayCls(StageCls
, Elaboratable
):
597 """ an example of how to use the buffered pipeline, in a static class
601 def __init__(self
, valid_trigger
=2):
602 self
.count
= Signal(2)
603 self
.valid_trigger
= valid_trigger
606 return Signal(16, name
="example_input_signal")
609 return Signal(16, name
="example_output_signal")
613 """ data is ready to be accepted when this is true
615 return (self
.count
== 1)# | (self.count == 3)
618 def d_valid(self
, ready_i
):
619 """ data is valid at output when this is true
621 return self
.count
== self
.valid_trigger
624 def process(self
, i
):
625 """ process the input data and returns it (adds 1)
629 def elaborate(self
, platform
):
631 m
.d
.sync
+= self
.count
.eq(self
.count
+ 1)
635 class ExampleBufDelayedPipe(BufferedHandshake
):
638 stage
= ExampleStageDelayCls(valid_trigger
=2)
639 BufferedHandshake
.__init
__(self
, stage
, stage_ctl
=True)
641 def elaborate(self
, platform
):
642 m
= BufferedHandshake
.elaborate(self
, platform
)
643 m
.submodules
.stage
= self
.stage
649 for i
in range(num_tests
):
650 data
.append(1<<((i
*3)%15))
651 #data.append(randint(0, 1<<16-2))
652 #print (hex(data[-1]))
656 def resultfn_12(data_o
, expected
, i
, o
):
658 assert data_o
== res
, \
659 "%d-%d data %x not match %x\n" \
660 % (i
, o
, data_o
, res
)
663 ######################################################################
665 ######################################################################
667 class ExampleUnBufDelayedPipe(BufferedHandshake
):
670 stage
= ExampleStageDelayCls(valid_trigger
=3)
671 BufferedHandshake
.__init
__(self
, stage
, stage_ctl
=True)
673 def elaborate(self
, platform
):
674 m
= BufferedHandshake
.elaborate(self
, platform
)
675 m
.submodules
.stage
= self
.stage
678 ######################################################################
680 ######################################################################
682 class ExampleBufModeAdd1Pipe(SimpleHandshake
):
685 stage
= ExampleStageCls()
686 SimpleHandshake
.__init
__(self
, stage
)
689 ######################################################################
691 ######################################################################
693 class ExampleBufModeUnBufPipe(ControlBase
):
695 def elaborate(self
, platform
):
696 m
= ControlBase
.elaborate(self
, platform
)
698 pipe1
= ExampleBufModeAdd1Pipe()
699 pipe2
= ExampleBufAdd1Pipe()
701 m
.submodules
.pipe1
= pipe1
702 m
.submodules
.pipe2
= pipe2
704 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
708 ######################################################################
710 ######################################################################
712 class ExampleUnBufAdd1Pipe2(UnbufferedPipeline2
):
715 stage
= ExampleStageCls()
716 UnbufferedPipeline2
.__init__(self
, stage
)
719 ######################################################################
721 ######################################################################
723 class PassThroughTest(PassThroughHandshake
):
726 return Signal(16, "out")
729 stage
= PassThroughStage(self
.iospecfn
)
730 PassThroughHandshake
.__init
__(self
, stage
)
732 def resultfn_identical(data_o
, expected
, i
, o
):
734 assert data_o
== res
, \
735 "%d-%d data %x not match %x\n" \
736 % (i
, o
, data_o
, res
)
739 ######################################################################
741 ######################################################################
743 class ExamplePassAdd1Pipe(PassThroughHandshake
):
746 stage
= ExampleStageCls()
747 PassThroughHandshake
.__init
__(self
, stage
)
750 class ExampleBufPassThruPipe(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
= ExampleBufModeAdd1Pipe()
759 pipe2
= ExamplePassAdd1Pipe()
761 m
.submodules
.pipe1
= pipe1
762 m
.submodules
.pipe2
= pipe2
764 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
769 ######################################################################
771 ######################################################################
774 return Signal(16, name
="d_in")
776 class FIFOTest16(FIFOControl
):
779 stage
= PassThroughStage(iospecfn
)
780 FIFOControl
.__init
__(self
, 2, stage
)
783 ######################################################################
785 ######################################################################
787 class ExampleFIFOPassThruPipe1(ControlBase
):
789 def elaborate(self
, platform
):
790 m
= ControlBase
.elaborate(self
, platform
)
794 pipe3
= ExamplePassAdd1Pipe()
796 m
.submodules
.pipe1
= pipe1
797 m
.submodules
.pipe2
= pipe2
798 m
.submodules
.pipe3
= pipe3
800 m
.d
.comb
+= self
.connect([pipe1
, pipe2
, pipe3
])
805 ######################################################################
807 ######################################################################
809 class Example2OpRecord(RecordObject
):
811 RecordObject
.__init
__(self
)
812 self
.op1
= Signal(16)
813 self
.op2
= Signal(16)
816 class ExampleAddRecordObjectStage(StageCls
):
819 """ returns an instance of an Example2OpRecord.
821 return Example2OpRecord()
824 """ returns an output signal which will happen to contain the sum
829 def process(self
, i
):
830 """ process the input data (sums the values in the tuple) and returns it
835 class ExampleRecordHandshakeAddClass(SimpleHandshake
):
838 addstage
= ExampleAddRecordObjectStage()
839 SimpleHandshake
.__init
__(self
, stage
=addstage
)
842 ######################################################################
844 ######################################################################
846 def iospecfnrecord():
847 return Example2OpRecord()
849 class FIFOTestRecordControl(FIFOControl
):
852 stage
= PassThroughStage(iospecfnrecord
)
853 FIFOControl
.__init
__(self
, 2, stage
)
856 class ExampleFIFORecordObjectPipe(ControlBase
):
858 def elaborate(self
, platform
):
859 m
= ControlBase
.elaborate(self
, platform
)
861 pipe1
= FIFOTestRecordControl()
862 pipe2
= ExampleRecordHandshakeAddClass()
864 m
.submodules
.pipe1
= pipe1
865 m
.submodules
.pipe2
= pipe2
867 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
872 ######################################################################
874 ######################################################################
876 class FIFOTestRecordAddStageControl(FIFOControl
):
879 stage
= ExampleAddRecordObjectStage()
880 FIFOControl
.__init
__(self
, 2, stage
)
884 ######################################################################
886 ######################################################################
888 class FIFOTestAdd16(FIFOControl
):
891 stage
= ExampleStageCls()
892 FIFOControl
.__init
__(self
, 2, stage
)
895 class ExampleFIFOAdd2Pipe(ControlBase
):
897 def elaborate(self
, platform
):
898 m
= ControlBase
.elaborate(self
, platform
)
900 pipe1
= FIFOTestAdd16()
901 pipe2
= FIFOTestAdd16()
903 m
.submodules
.pipe1
= pipe1
904 m
.submodules
.pipe2
= pipe2
906 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
911 ######################################################################
913 ######################################################################
916 return (Signal(16, name
="src1"), Signal(16, name
="src2"))
918 class FIFOTest2x16(FIFOControl
):
921 stage
= PassThroughStage(iospecfn2
)
922 FIFOControl
.__init
__(self
, 2, stage
)
925 ######################################################################
927 ######################################################################
929 class ExampleBufPassThruPipe2(ControlBase
):
931 def elaborate(self
, platform
):
932 m
= ControlBase
.elaborate(self
, platform
)
934 # XXX currently fails: any other permutation works fine.
935 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
936 # also fails using UnbufferedPipeline as well
937 #pipe1 = ExampleUnBufAdd1Pipe()
938 #pipe2 = ExampleBufAdd1Pipe()
939 pipe1
= ExampleBufAdd1Pipe()
940 pipe2
= ExamplePassAdd1Pipe()
942 m
.submodules
.pipe1
= pipe1
943 m
.submodules
.pipe2
= pipe2
945 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
950 ######################################################################
952 ######################################################################
954 class ExampleBufPipe3(ControlBase
):
955 """ Example of how to do delayed pipeline, where the stage signals
959 def elaborate(self
, platform
):
960 m
= ControlBase
.elaborate(self
, platform
)
962 pipe1
= ExampleBufDelayedPipe()
963 pipe2
= ExampleBufPipe()
965 m
.submodules
.pipe1
= pipe1
966 m
.submodules
.pipe2
= pipe2
968 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
972 ######################################################################
973 # Test 999 - XXX FAILS
974 # http://bugs.libre-riscv.org/show_bug.cgi?id=57
975 ######################################################################
977 class ExampleBufAdd1Pipe(BufferedHandshake
):
980 stage
= ExampleStageCls()
981 BufferedHandshake
.__init
__(self
, stage
)
984 class ExampleUnBufAdd1Pipe(UnbufferedPipeline
):
987 stage
= ExampleStageCls()
988 UnbufferedPipeline
.__init
__(self
, stage
)
991 class ExampleBufUnBufPipe(ControlBase
):
993 def elaborate(self
, platform
):
994 m
= ControlBase
.elaborate(self
, platform
)
996 # XXX currently fails: any other permutation works fine.
997 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
998 # also fails using UnbufferedPipeline as well
999 #pipe1 = ExampleUnBufAdd1Pipe()
1000 #pipe2 = ExampleBufAdd1Pipe()
1001 pipe1
= ExampleBufAdd1Pipe()
1002 pipe2
= ExampleUnBufAdd1Pipe()
1004 m
.submodules
.pipe1
= pipe1
1005 m
.submodules
.pipe2
= pipe2
1007 m
.d
.comb
+= self
.connect([pipe1
, pipe2
])
1012 ######################################################################
1014 ######################################################################
1020 dut
= ExampleBufPipe()
1021 run_simulation(dut
, tbench(dut
), vcd_name
="test_bufpipe.vcd")
1025 dut
= ExampleBufPipe2()
1026 run_simulation(dut
, tbench2(dut
), vcd_name
="test_bufpipe2.vcd")
1027 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1028 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1029 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1030 vl
= rtlil
.convert(dut
, ports
=ports
)
1031 with
open("test_bufpipe2.il", "w") as f
:
1036 dut
= ExampleBufPipe()
1037 test
= Test3(dut
, resultfn_3
)
1038 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe3.vcd")
1042 dut
= ExamplePipeline()
1043 test
= Test3(dut
, resultfn_3
)
1044 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_combpipe3.vcd")
1048 dut
= ExampleBufPipe2()
1049 run_simulation(dut
, tbench4(dut
), vcd_name
="test_bufpipe4.vcd")
1053 dut
= ExampleBufPipeAdd()
1054 test
= Test5(dut
, resultfn_5
, stage_ctl
=True)
1055 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe5.vcd")
1059 dut
= ExampleLTPipeline()
1060 test
= Test5(dut
, resultfn_6
)
1061 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_ltcomb6.vcd")
1063 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1064 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1065 list(dut
.p
.data_i
) + [dut
.n
.data_o
]
1066 vl
= rtlil
.convert(dut
, ports
=ports
)
1067 with
open("test_ltcomb_pipe.il", "w") as f
:
1072 dut
= ExampleAddRecordPipe()
1074 test
= Test5(dut
, resultfn_7
, data
=data
)
1075 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1076 dut
.n
.valid_o
, dut
.p
.ready_o
,
1077 dut
.p
.data_i
.src1
, dut
.p
.data_i
.src2
,
1078 dut
.n
.data_o
.src1
, dut
.n
.data_o
.src2
]
1079 vl
= rtlil
.convert(dut
, ports
=ports
)
1080 with
open("test_recordcomb_pipe.il", "w") as f
:
1082 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord.vcd")
1086 dut
= ExampleBufPipeAddClass()
1088 test
= Test5(dut
, resultfn_8
, data
=data
)
1089 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe8.vcd")
1093 dut
= ExampleBufPipeChain2()
1094 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1095 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1096 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1097 vl
= rtlil
.convert(dut
, ports
=ports
)
1098 with
open("test_bufpipechain2.il", "w") as f
:
1101 data
= data_chain2()
1102 test
= Test5(dut
, resultfn_9
, data
=data
)
1103 run_simulation(dut
, [test
.send
, test
.rcv
],
1104 vcd_name
="test_bufpipechain2.vcd")
1108 dut
= ExampleLTBufferedPipeDerived()
1109 test
= Test5(dut
, resultfn_6
)
1110 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_ltbufpipe10.vcd")
1112 vl
= rtlil
.convert(dut
, ports
=ports
)
1113 with
open("test_ltbufpipe10.il", "w") as f
:
1118 dut
= ExampleAddRecordPlaceHolderPipe()
1119 data
=data_placeholder()
1120 test
= Test5(dut
, resultfn_11
, data
=data
)
1121 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord.vcd")
1126 dut
= ExampleBufDelayedPipe()
1127 data
= data_chain1()
1128 test
= Test5(dut
, resultfn_12
, data
=data
)
1129 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe12.vcd")
1130 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1131 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1132 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1133 vl
= rtlil
.convert(dut
, ports
=ports
)
1134 with
open("test_bufpipe12.il", "w") as f
:
1139 dut
= ExampleUnBufDelayedPipe()
1140 data
= data_chain1()
1141 test
= Test5(dut
, resultfn_12
, data
=data
)
1142 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_unbufpipe13.vcd")
1143 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1144 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1145 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1146 vl
= rtlil
.convert(dut
, ports
=ports
)
1147 with
open("test_unbufpipe13.il", "w") as f
:
1152 dut
= ExampleBufModeAdd1Pipe()
1153 data
= data_chain1()
1154 test
= Test5(dut
, resultfn_12
, data
=data
)
1155 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufunbuf15.vcd")
1156 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1157 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1158 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1159 vl
= rtlil
.convert(dut
, ports
=ports
)
1160 with
open("test_bufunbuf15.il", "w") as f
:
1165 dut
= ExampleBufModeUnBufPipe()
1166 data
= data_chain1()
1167 test
= Test5(dut
, resultfn_9
, data
=data
)
1168 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufunbuf16.vcd")
1169 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1170 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1171 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1172 vl
= rtlil
.convert(dut
, ports
=ports
)
1173 with
open("test_bufunbuf16.il", "w") as f
:
1178 dut
= ExampleUnBufAdd1Pipe2()
1179 data
= data_chain1()
1180 test
= Test5(dut
, resultfn_12
, data
=data
)
1181 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_unbufpipe17.vcd")
1182 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1183 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1184 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1185 vl
= rtlil
.convert(dut
, ports
=ports
)
1186 with
open("test_unbufpipe17.il", "w") as f
:
1191 dut
= PassThroughTest()
1192 data
= data_chain1()
1193 test
= Test5(dut
, resultfn_identical
, data
=data
)
1194 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_passthru18.vcd")
1195 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1196 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1197 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1198 vl
= rtlil
.convert(dut
, ports
=ports
)
1199 with
open("test_passthru18.il", "w") as f
:
1204 dut
= ExampleBufPassThruPipe()
1205 data
= data_chain1()
1206 test
= Test5(dut
, resultfn_9
, data
=data
)
1207 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpass19.vcd")
1208 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1209 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1210 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1211 vl
= rtlil
.convert(dut
, ports
=ports
)
1212 with
open("test_bufpass19.il", "w") as f
:
1218 data
= data_chain1()
1219 test
= Test5(dut
, resultfn_identical
, data
=data
)
1220 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_fifo20.vcd")
1221 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1222 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1223 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1224 vl
= rtlil
.convert(dut
, ports
=ports
)
1225 with
open("test_fifo20.il", "w") as f
:
1230 dut
= ExampleFIFOPassThruPipe1()
1231 data
= data_chain1()
1232 test
= Test5(dut
, resultfn_12
, data
=data
)
1233 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_fifopass21.vcd")
1234 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1235 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1236 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1237 vl
= rtlil
.convert(dut
, ports
=ports
)
1238 with
open("test_fifopass21.il", "w") as f
:
1243 dut
= ExampleRecordHandshakeAddClass()
1245 test
= Test5(dut
, resultfn_8
, data
=data
)
1246 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord22.vcd")
1247 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1248 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1249 [dut
.p
.data_i
.op1
, dut
.p
.data_i
.op2
] + \
1251 vl
= rtlil
.convert(dut
, ports
=ports
)
1252 with
open("test_addrecord22.il", "w") as f
:
1257 dut
= ExampleFIFORecordObjectPipe()
1259 test
= Test5(dut
, resultfn_8
, data
=data
)
1260 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord23.vcd")
1261 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1262 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1263 [dut
.p
.data_i
.op1
, dut
.p
.data_i
.op2
] + \
1265 vl
= rtlil
.convert(dut
, ports
=ports
)
1266 with
open("test_addrecord23.il", "w") as f
:
1271 dut
= FIFOTestRecordAddStageControl()
1273 test
= Test5(dut
, resultfn_8
, data
=data
)
1274 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1275 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1276 [dut
.p
.data_i
.op1
, dut
.p
.data_i
.op2
] + \
1278 vl
= rtlil
.convert(dut
, ports
=ports
)
1279 with
open("test_addrecord24.il", "w") as f
:
1281 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_addrecord24.vcd")
1285 dut
= ExampleFIFOAdd2Pipe()
1286 data
= data_chain1()
1287 test
= Test5(dut
, resultfn_9
, data
=data
)
1288 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_add2pipe25.vcd")
1289 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1290 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1291 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1292 vl
= rtlil
.convert(dut
, ports
=ports
)
1293 with
open("test_add2pipe25.il", "w") as f
:
1298 dut
= ExampleBufPassThruPipe2()
1299 data
= data_chain1()
1300 test
= Test5(dut
, resultfn_9
, data
=data
)
1301 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpass997.vcd")
1302 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1303 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1304 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1305 vl
= rtlil
.convert(dut
, ports
=ports
)
1306 with
open("test_bufpass997.il", "w") as f
:
1310 print ("test 998 (fails, bug)")
1311 dut
= ExampleBufPipe3()
1312 data
= data_chain1()
1313 test
= Test5(dut
, resultfn_9
, data
=data
)
1314 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufpipe14.vcd")
1315 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1316 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1317 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1318 vl
= rtlil
.convert(dut
, ports
=ports
)
1319 with
open("test_bufpipe14.il", "w") as f
:
1323 print ("test 999 (expected to fail, which is a bug)")
1324 dut
= ExampleBufUnBufPipe()
1325 data
= data_chain1()
1326 test
= Test5(dut
, resultfn_9
, data
=data
)
1327 run_simulation(dut
, [test
.send
, test
.rcv
], vcd_name
="test_bufunbuf999.vcd")
1328 ports
= [dut
.p
.valid_i
, dut
.n
.ready_i
,
1329 dut
.n
.valid_o
, dut
.p
.ready_o
] + \
1330 [dut
.p
.data_i
] + [dut
.n
.data_o
]
1331 vl
= rtlil
.convert(dut
, ports
=ports
)
1332 with
open("test_bufunbuf999.il", "w") as f
: