add 2-stage FIFO (add1) example
[ieee754fpu.git] / src / add / test_buf_pipe.py
1 """ Unit tests for Buffered and Unbuffered pipelines
2
3 contains useful worked examples of how to use the Pipeline API,
4 including:
5
6 * Combinatorial Stage "Chaining"
7 * class-based data stages
8 * nmigen module-based data stages
9 * special nmigen module-based data stage, where the stage *is* the module
10 * Record-based data stages
11 * static-class data stages
12 * multi-stage pipelines (and how to connect them)
13 * how to *use* the pipelines (see Test5) - how to get data in and out
14
15 """
16
17 from nmigen import Module, Signal, Mux, Const
18 from nmigen.hdl.rec import Record
19 from nmigen.compat.sim import run_simulation
20 from nmigen.cli import verilog, rtlil
21
22 from example_buf_pipe import ExampleBufPipe, ExampleBufPipeAdd
23 from example_buf_pipe import ExamplePipeline, UnbufferedPipeline
24 from example_buf_pipe import ExampleStageCls
25 from example_buf_pipe import PrevControl, NextControl, BufferedHandshake
26 from example_buf_pipe import StageChain, ControlBase, StageCls
27 from singlepipe import UnbufferedPipeline2
28 from singlepipe import SimpleHandshake
29 from singlepipe import PassThroughHandshake
30 from singlepipe import PassThroughStage
31 from singlepipe import FIFOControl
32 from singlepipe import RecordObject
33
34 from random import randint, seed
35
36 #seed(4)
37
38
39 def check_o_n_valid(dut, val):
40 o_n_valid = yield dut.n.o_valid
41 assert o_n_valid == val
42
43 def check_o_n_valid2(dut, val):
44 o_n_valid = yield dut.n.o_valid
45 assert o_n_valid == val
46
47
48 def tbench(dut):
49 #yield dut.i_p_rst.eq(1)
50 yield dut.n.i_ready.eq(0)
51 yield dut.p.o_ready.eq(0)
52 yield
53 yield
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)
58 yield
59
60 yield dut.p.i_data.eq(7)
61 yield from check_o_n_valid(dut, 0) # effects of i_p_valid delayed
62 yield
63 yield from check_o_n_valid(dut, 1) # ok *now* i_p_valid effect is felt
64
65 yield dut.p.i_data.eq(2)
66 yield
67 yield dut.n.i_ready.eq(0) # begin going into "stall" (next stage says ready)
68 yield dut.p.i_data.eq(9)
69 yield
70 yield dut.p.i_valid.eq(0)
71 yield dut.p.i_data.eq(12)
72 yield
73 yield dut.p.i_data.eq(32)
74 yield dut.n.i_ready.eq(1)
75 yield
76 yield from check_o_n_valid(dut, 1) # buffer still needs to output
77 yield
78 yield from check_o_n_valid(dut, 1) # buffer still needs to output
79 yield
80 yield from check_o_n_valid(dut, 0) # buffer outputted, *now* we're done.
81 yield
82
83
84 def tbench2(dut):
85 #yield dut.p.i_rst.eq(1)
86 yield dut.n.i_ready.eq(0)
87 #yield dut.p.o_ready.eq(0)
88 yield
89 yield
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)
94 yield
95
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
98 yield
99 yield from check_o_n_valid2(dut, 0) # effects of i_p_valid delayed 2 clocks
100
101 yield dut.p.i_data.eq(2)
102 yield
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)
106 yield
107 yield dut.p.i_valid.eq(0)
108 yield dut.p.i_data.eq(12)
109 yield
110 yield dut.p.i_data.eq(32)
111 yield dut.n.i_ready.eq(1)
112 yield
113 yield from check_o_n_valid2(dut, 1) # buffer still needs to output
114 yield
115 yield from check_o_n_valid2(dut, 1) # buffer still needs to output
116 yield
117 yield from check_o_n_valid2(dut, 1) # buffer still needs to output
118 yield
119 yield from check_o_n_valid2(dut, 0) # buffer outputted, *now* we're done.
120 yield
121 yield
122 yield
123
124
125 class Test3:
126 def __init__(self, dut, resultfn):
127 self.dut = dut
128 self.resultfn = resultfn
129 self.data = []
130 for i in range(num_tests):
131 #data.append(randint(0, 1<<16-1))
132 self.data.append(i+1)
133 self.i = 0
134 self.o = 0
135
136 def send(self):
137 while self.o != len(self.data):
138 send_range = randint(0, 3)
139 for j in range(randint(1,10)):
140 if send_range == 0:
141 send = True
142 else:
143 send = randint(0, send_range) != 0
144 o_p_ready = yield self.dut.p.o_ready
145 if not o_p_ready:
146 yield
147 continue
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])
151 self.i += 1
152 else:
153 yield self.dut.p.i_valid.eq(0)
154 yield
155
156 def rcv(self):
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)
162 yield
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:
166 continue
167 o_data = yield self.dut.n.o_data
168 self.resultfn(o_data, self.data[self.o], self.i, self.o)
169 self.o += 1
170 if self.o == len(self.data):
171 break
172
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)
177
178 def data_placeholder():
179 data = []
180 for i in range(num_tests):
181 d = PlaceHolder()
182 d.src1 = randint(0, 1<<16-1)
183 d.src2 = randint(0, 1<<16-1)
184 data.append(d)
185 return data
186
187 def data_dict():
188 data = []
189 for i in range(num_tests):
190 data.append({'src1': randint(0, 1<<16-1),
191 'src2': randint(0, 1<<16-1)})
192 return data
193
194
195 class Test5:
196 def __init__(self, dut, resultfn, data=None, stage_ctl=False):
197 self.dut = dut
198 self.resultfn = resultfn
199 self.stage_ctl = stage_ctl
200 if data:
201 self.data = data
202 else:
203 self.data = []
204 for i in range(num_tests):
205 self.data.append((randint(0, 1<<16-1), randint(0, 1<<16-1)))
206 self.i = 0
207 self.o = 0
208
209 def send(self):
210 while self.o != len(self.data):
211 send_range = randint(0, 3)
212 for j in range(randint(1,10)):
213 if send_range == 0:
214 send = True
215 else:
216 send = randint(0, send_range) != 0
217 send = True
218 o_p_ready = yield self.dut.p.o_ready
219 if not o_p_ready:
220 yield
221 continue
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]):
225 yield v
226 self.i += 1
227 else:
228 yield self.dut.p.i_valid.eq(0)
229 yield
230
231 def rcv(self):
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
236 ready = True
237 yield self.dut.n.i_ready.eq(ready)
238 yield
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:
242 continue
243 if isinstance(self.dut.n.o_data, Record):
244 o_data = {}
245 dod = self.dut.n.o_data
246 for k, v in dod.fields.items():
247 o_data[k] = yield v
248 else:
249 o_data = yield self.dut.n.o_data
250 self.resultfn(o_data, self.data[self.o], self.i, self.o)
251 self.o += 1
252 if self.o == len(self.data):
253 break
254
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))
260
261 def tbench4(dut):
262 data = []
263 for i in range(num_tests):
264 #data.append(randint(0, 1<<16-1))
265 data.append(i+1)
266 i = 0
267 o = 0
268 while True:
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
273 if o_p_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])
277 i += 1
278 else:
279 yield dut.p.i_valid.eq(0)
280 yield
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])
287 o += 1
288 if o == len(data):
289 break
290
291 ######################################################################
292 # Test 2 and 4
293 ######################################################################
294
295 class ExampleBufPipe2(ControlBase):
296 """ Example of how to do chained pipeline stages.
297 """
298
299 def elaborate(self, platform):
300 m = Module()
301
302 pipe1 = ExampleBufPipe()
303 pipe2 = ExampleBufPipe()
304
305 m.submodules.pipe1 = pipe1
306 m.submodules.pipe2 = pipe2
307
308 m.d.comb += self.connect([pipe1, pipe2])
309
310 return m
311
312
313 ######################################################################
314 # Test 9
315 ######################################################################
316
317 class ExampleBufPipeChain2(BufferedHandshake):
318 """ connects two stages together as a *single* combinatorial stage.
319 """
320 def __init__(self):
321 stage1 = ExampleStageCls()
322 stage2 = ExampleStageCls()
323 combined = StageChain([stage1, stage2])
324 BufferedHandshake.__init__(self, combined)
325
326
327 def data_chain2():
328 data = []
329 for i in range(num_tests):
330 data.append(randint(0, 1<<16-2))
331 return data
332
333
334 def resultfn_9(o_data, expected, i, o):
335 res = expected + 2
336 assert o_data == res, \
337 "%d-%d received data %x not match expected %x\n" \
338 % (i, o, o_data, res)
339
340
341 ######################################################################
342 # Test 6 and 10
343 ######################################################################
344
345 class SetLessThan:
346 def __init__(self, width, signed):
347 self.m = Module()
348 self.src1 = Signal((width, signed), name="src1")
349 self.src2 = Signal((width, signed), name="src2")
350 self.output = Signal(width, name="out")
351
352 def elaborate(self, platform):
353 self.m.d.comb += self.output.eq(Mux(self.src1 < self.src2, 1, 0))
354 return self.m
355
356
357 class LTStage(StageCls):
358 """ module-based stage example
359 """
360 def __init__(self):
361 self.slt = SetLessThan(16, True)
362
363 def ispec(self):
364 return (Signal(16, name="sig1"), Signal(16, "sig2"))
365
366 def ospec(self):
367 return Signal(16, "out")
368
369 def setup(self, m, i):
370 self.o = Signal(16)
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)
375
376 def process(self, i):
377 return self.o
378
379
380 class LTStageDerived(SetLessThan, StageCls):
381 """ special version of a nmigen module where the module is also a stage
382
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
386 """
387
388 def __init__(self):
389 SetLessThan.__init__(self, 16, True)
390
391 def ispec(self):
392 return (Signal(16), Signal(16))
393
394 def ospec(self):
395 return Signal(16)
396
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])
401
402 def process(self, i):
403 return self.output
404
405
406 class ExampleLTPipeline(UnbufferedPipeline):
407 """ an example of how to use the unbuffered pipeline.
408 """
409
410 def __init__(self):
411 stage = LTStage()
412 UnbufferedPipeline.__init__(self, stage)
413
414
415 class ExampleLTBufferedPipeDerived(BufferedHandshake):
416 """ an example of how to use the buffered pipeline.
417 """
418
419 def __init__(self):
420 stage = LTStageDerived()
421 BufferedHandshake.__init__(self, stage)
422
423
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))
429
430
431 ######################################################################
432 # Test 7
433 ######################################################################
434
435 class ExampleAddRecordStage(StageCls):
436 """ example use of a Record
437 """
438
439 record_spec = [('src1', 16), ('src2', 16)]
440 def ispec(self):
441 """ returns a Record using the specification
442 """
443 return Record(self.record_spec)
444
445 def ospec(self):
446 return Record(self.record_spec)
447
448 def process(self, i):
449 """ process the input data, returning a dictionary with key names
450 that exactly match the Record's attributes.
451 """
452 return {'src1': i.src1 + 1,
453 'src2': i.src2 + 1}
454
455 ######################################################################
456 # Test 11
457 ######################################################################
458
459 class ExampleAddRecordPlaceHolderStage(StageCls):
460 """ example use of a Record, with a placeholder as the processing result
461 """
462
463 record_spec = [('src1', 16), ('src2', 16)]
464 def ispec(self):
465 """ returns a Record using the specification
466 """
467 return Record(self.record_spec)
468
469 def ospec(self):
470 return Record(self.record_spec)
471
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.
475 """
476 o = PlaceHolder()
477 o.src1 = i.src1 + 1
478 o.src2 = i.src2 + 1
479 return o
480
481
482 class PlaceHolder: pass
483
484
485 class ExampleAddRecordPipe(UnbufferedPipeline):
486 """ an example of how to use the combinatorial pipeline.
487 """
488
489 def __init__(self):
490 stage = ExampleAddRecordStage()
491 UnbufferedPipeline.__init__(self, stage)
492
493
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))
499
500
501 class ExampleAddRecordPlaceHolderPipe(UnbufferedPipeline):
502 """ an example of how to use the combinatorial pipeline.
503 """
504
505 def __init__(self):
506 stage = ExampleAddRecordPlaceHolderStage()
507 UnbufferedPipeline.__init__(self, stage)
508
509
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))
516
517
518 ######################################################################
519 # Test 8
520 ######################################################################
521
522
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
526 """
527
528 def __init__(self):
529 self.op1 = Signal(16)
530 self.op2 = Signal(16)
531
532 def eq(self, i):
533 return [self.op1.eq(i.op1), self.op2.eq(i.op2)]
534
535
536 class ExampleAddClassStage(StageCls):
537 """ an example of how to use the buffered pipeline, as a class instance
538 """
539
540 def ispec(self):
541 """ returns an instance of an Example2OpClass.
542 """
543 return Example2OpClass()
544
545 def ospec(self):
546 """ returns an output signal which will happen to contain the sum
547 of the two inputs
548 """
549 return Signal(16)
550
551 def process(self, i):
552 """ process the input data (sums the values in the tuple) and returns it
553 """
554 return i.op1 + i.op2
555
556
557 class ExampleBufPipeAddClass(BufferedHandshake):
558 """ an example of how to use the buffered pipeline, using a class instance
559 """
560
561 def __init__(self):
562 addstage = ExampleAddClassStage()
563 BufferedHandshake.__init__(self, addstage)
564
565
566 class TestInputAdd:
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
571 """
572 def __init__(self, op1, op2):
573 self.op1 = op1
574 self.op2 = op2
575
576
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))
582
583 def data_2op():
584 data = []
585 for i in range(num_tests):
586 data.append(TestInputAdd(randint(0, 1<<16-1), randint(0, 1<<16-1)))
587 return data
588
589
590 ######################################################################
591 # Test 12
592 ######################################################################
593
594 class ExampleStageDelayCls(StageCls):
595 """ an example of how to use the buffered pipeline, in a static class
596 fashion
597 """
598
599 def __init__(self, valid_trigger=2):
600 self.count = Signal(2)
601 self.valid_trigger = valid_trigger
602
603 def ispec(self):
604 return Signal(16, name="example_input_signal")
605
606 def ospec(self):
607 return Signal(16, name="example_output_signal")
608
609 @property
610 def d_ready(self):
611 return (self.count == 1)# | (self.count == 3)
612 return Const(1)
613
614 def d_valid(self, i_ready):
615 return self.count == self.valid_trigger
616 return Const(1)
617
618 def process(self, i):
619 """ process the input data and returns it (adds 1)
620 """
621 return i + 1
622
623 def elaborate(self, platform):
624 m = Module()
625 m.d.sync += self.count.eq(self.count + 1)
626 return m
627
628
629 class ExampleBufDelayedPipe(BufferedHandshake):
630
631 def __init__(self):
632 stage = ExampleStageDelayCls(valid_trigger=2)
633 BufferedHandshake.__init__(self, stage, stage_ctl=True)
634
635 def elaborate(self, platform):
636 m = BufferedHandshake.elaborate(self, platform)
637 m.submodules.stage = self.stage
638 return m
639
640
641 def data_chain1():
642 data = []
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]))
647 return data
648
649
650 def resultfn_12(o_data, expected, i, o):
651 res = expected + 1
652 assert o_data == res, \
653 "%d-%d data %x not match %x\n" \
654 % (i, o, o_data, res)
655
656
657 ######################################################################
658 # Test 13
659 ######################################################################
660
661 class ExampleUnBufDelayedPipe(BufferedHandshake):
662
663 def __init__(self):
664 stage = ExampleStageDelayCls(valid_trigger=3)
665 BufferedHandshake.__init__(self, stage, stage_ctl=True)
666
667 def elaborate(self, platform):
668 m = BufferedHandshake.elaborate(self, platform)
669 m.submodules.stage = self.stage
670 return m
671
672 ######################################################################
673 # Test 15
674 ######################################################################
675
676 class ExampleBufModeAdd1Pipe(SimpleHandshake):
677
678 def __init__(self):
679 stage = ExampleStageCls()
680 SimpleHandshake.__init__(self, stage)
681
682
683 ######################################################################
684 # Test 16
685 ######################################################################
686
687 class ExampleBufModeUnBufPipe(ControlBase):
688
689 def elaborate(self, platform):
690 m = ControlBase._elaborate(self, platform)
691
692 pipe1 = ExampleBufModeAdd1Pipe()
693 pipe2 = ExampleBufAdd1Pipe()
694
695 m.submodules.pipe1 = pipe1
696 m.submodules.pipe2 = pipe2
697
698 m.d.comb += self.connect([pipe1, pipe2])
699
700 return m
701
702 ######################################################################
703 # Test 17
704 ######################################################################
705
706 class ExampleUnBufAdd1Pipe2(UnbufferedPipeline2):
707
708 def __init__(self):
709 stage = ExampleStageCls()
710 UnbufferedPipeline2.__init__(self, stage)
711
712
713 ######################################################################
714 # Test 18
715 ######################################################################
716
717 class PassThroughTest(PassThroughHandshake):
718
719 def iospecfn(self):
720 return Signal(16, "out")
721
722 def __init__(self):
723 stage = PassThroughStage(self.iospecfn)
724 PassThroughHandshake.__init__(self, stage)
725
726 def resultfn_identical(o_data, expected, i, o):
727 res = expected
728 assert o_data == res, \
729 "%d-%d data %x not match %x\n" \
730 % (i, o, o_data, res)
731
732
733 ######################################################################
734 # Test 19
735 ######################################################################
736
737 class ExamplePassAdd1Pipe(PassThroughHandshake):
738
739 def __init__(self):
740 stage = ExampleStageCls()
741 PassThroughHandshake.__init__(self, stage)
742
743
744 class ExampleBufPassThruPipe(ControlBase):
745
746 def elaborate(self, platform):
747 m = ControlBase._elaborate(self, platform)
748
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()
754
755 m.submodules.pipe1 = pipe1
756 m.submodules.pipe2 = pipe2
757
758 m.d.comb += self.connect([pipe1, pipe2])
759
760 return m
761
762
763 ######################################################################
764 # Test 20
765 ######################################################################
766
767 def iospecfn():
768 return Signal(16, name="d_in")
769
770 class FIFOTest16(FIFOControl):
771
772 def __init__(self):
773 stage = PassThroughStage(iospecfn)
774 FIFOControl.__init__(self, 2, stage)
775
776
777 ######################################################################
778 # Test 21
779 ######################################################################
780
781 class ExampleFIFOPassThruPipe1(ControlBase):
782
783 def elaborate(self, platform):
784 m = ControlBase._elaborate(self, platform)
785
786 pipe1 = FIFOTest16()
787 pipe2 = ExamplePassAdd1Pipe()
788
789 m.submodules.pipe1 = pipe1
790 m.submodules.pipe2 = pipe2
791
792 m.d.comb += self.connect([pipe1, pipe2])
793
794 return m
795
796
797 ######################################################################
798 # Test 22
799 ######################################################################
800
801 class Example2OpRecord(RecordObject):
802 def __init__(self):
803 RecordObject.__init__(self)
804 self.op1 = Signal(16)
805 self.op2 = Signal(16)
806
807
808 class ExampleAddRecordObjectStage(StageCls):
809
810 def ispec(self):
811 """ returns an instance of an Example2OpRecord.
812 """
813 return Example2OpRecord()
814
815 def ospec(self):
816 """ returns an output signal which will happen to contain the sum
817 of the two inputs
818 """
819 return Signal(16)
820
821 def process(self, i):
822 """ process the input data (sums the values in the tuple) and returns it
823 """
824 return i.op1 + i.op2
825
826
827 class ExampleRecordHandshakeAddClass(SimpleHandshake):
828
829 def __init__(self):
830 addstage = ExampleAddRecordObjectStage()
831 SimpleHandshake.__init__(self, stage=addstage)
832
833
834 ######################################################################
835 # Test 23
836 ######################################################################
837
838 def iospecfnrecord():
839 return Example2OpRecord()
840
841 class FIFOTestRecordControl(FIFOControl):
842
843 def __init__(self):
844 stage = PassThroughStage(iospecfnrecord)
845 FIFOControl.__init__(self, 2, stage)
846
847
848 class ExampleFIFORecordObjectPipe(ControlBase):
849
850 def elaborate(self, platform):
851 m = ControlBase._elaborate(self, platform)
852
853 pipe1 = FIFOTestRecordControl()
854 pipe2 = ExampleRecordHandshakeAddClass()
855
856 m.submodules.pipe1 = pipe1
857 m.submodules.pipe2 = pipe2
858
859 m.d.comb += self.connect([pipe1, pipe2])
860
861 return m
862
863
864 ######################################################################
865 # Test 24
866 ######################################################################
867
868 class FIFOTestRecordAddStageControl(FIFOControl):
869
870 def __init__(self):
871 stage = ExampleAddRecordObjectStage()
872 FIFOControl.__init__(self, 2, stage)
873
874
875
876 ######################################################################
877 # Test 25
878 ######################################################################
879
880 class FIFOTestAdd16(FIFOControl):
881
882 def __init__(self):
883 stage = ExampleStageCls()
884 FIFOControl.__init__(self, 2, stage)
885
886
887 class ExampleFIFOAdd2Pipe(ControlBase):
888
889 def elaborate(self, platform):
890 m = ControlBase._elaborate(self, platform)
891
892 pipe1 = FIFOTestAdd16()
893 pipe2 = FIFOTestAdd16()
894
895 m.submodules.pipe1 = pipe1
896 m.submodules.pipe2 = pipe2
897
898 m.d.comb += self.connect([pipe1, pipe2])
899
900 return m
901
902
903 ######################################################################
904 # Test 26
905 ######################################################################
906
907 def iospecfn24():
908 return (Signal(16, name="src1"), Signal(16, name="src2"))
909
910 class FIFOTest2x16(FIFOControl):
911
912 def __init__(self):
913 stage = PassThroughStage(iospecfn2)
914 FIFOControl.__init__(self, 2, stage)
915
916
917 ######################################################################
918 # Test 997
919 ######################################################################
920
921 class ExampleBufPassThruPipe2(ControlBase):
922
923 def elaborate(self, platform):
924 m = ControlBase._elaborate(self, platform)
925
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()
933
934 m.submodules.pipe1 = pipe1
935 m.submodules.pipe2 = pipe2
936
937 m.d.comb += self.connect([pipe1, pipe2])
938
939 return m
940
941
942 ######################################################################
943 # Test 998
944 ######################################################################
945
946 class ExampleBufPipe3(ControlBase):
947 """ Example of how to do delayed pipeline, where the stage signals
948 whether it is ready.
949 """
950
951 def elaborate(self, platform):
952 m = ControlBase._elaborate(self, platform)
953
954 pipe1 = ExampleBufDelayedPipe()
955 pipe2 = ExampleBufPipe()
956
957 m.submodules.pipe1 = pipe1
958 m.submodules.pipe2 = pipe2
959
960 m.d.comb += self.connect([pipe1, pipe2])
961
962 return m
963
964 ######################################################################
965 # Test 999 - XXX FAILS
966 # http://bugs.libre-riscv.org/show_bug.cgi?id=57
967 ######################################################################
968
969 class ExampleBufAdd1Pipe(BufferedHandshake):
970
971 def __init__(self):
972 stage = ExampleStageCls()
973 BufferedHandshake.__init__(self, stage)
974
975
976 class ExampleUnBufAdd1Pipe(UnbufferedPipeline):
977
978 def __init__(self):
979 stage = ExampleStageCls()
980 UnbufferedPipeline.__init__(self, stage)
981
982
983 class ExampleBufUnBufPipe(ControlBase):
984
985 def elaborate(self, platform):
986 m = ControlBase._elaborate(self, platform)
987
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()
995
996 m.submodules.pipe1 = pipe1
997 m.submodules.pipe2 = pipe2
998
999 m.d.comb += self.connect([pipe1, pipe2])
1000
1001 return m
1002
1003
1004 ######################################################################
1005 # Unit Tests
1006 ######################################################################
1007
1008 num_tests = 10
1009
1010 if __name__ == '__main__':
1011 print ("test 1")
1012 dut = ExampleBufPipe()
1013 run_simulation(dut, tbench(dut), vcd_name="test_bufpipe.vcd")
1014
1015 print ("test 2")
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:
1023 f.write(vl)
1024
1025
1026 print ("test 3")
1027 dut = ExampleBufPipe()
1028 test = Test3(dut, resultfn_3)
1029 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe3.vcd")
1030
1031 print ("test 3.5")
1032 dut = ExamplePipeline()
1033 test = Test3(dut, resultfn_3)
1034 run_simulation(dut, [test.send, test.rcv], vcd_name="test_combpipe3.vcd")
1035
1036 print ("test 4")
1037 dut = ExampleBufPipe2()
1038 run_simulation(dut, tbench4(dut), vcd_name="test_bufpipe4.vcd")
1039
1040 print ("test 5")
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")
1044
1045 print ("test 6")
1046 dut = ExampleLTPipeline()
1047 test = Test5(dut, resultfn_6)
1048 run_simulation(dut, [test.send, test.rcv], vcd_name="test_ltcomb6.vcd")
1049
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:
1055 f.write(vl)
1056
1057 print ("test 7")
1058 dut = ExampleAddRecordPipe()
1059 data=data_dict()
1060 test = Test5(dut, resultfn_7, data=data)
1061 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord.vcd")
1062
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:
1069 f.write(vl)
1070
1071 print ("test 8")
1072 dut = ExampleBufPipeAddClass()
1073 data=data_2op()
1074 test = Test5(dut, resultfn_8, data=data)
1075 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe8.vcd")
1076
1077 print ("test 9")
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:
1084 f.write(vl)
1085
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")
1090
1091 print ("test 10")
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:
1097 f.write(vl)
1098
1099 print ("test 11")
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")
1104
1105
1106 print ("test 12")
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:
1116 f.write(vl)
1117
1118 print ("test 13")
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:
1128 f.write(vl)
1129
1130 print ("test 15")
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:
1140 f.write(vl)
1141
1142 print ("test 16")
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:
1152 f.write(vl)
1153
1154 print ("test 17")
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:
1164 f.write(vl)
1165
1166 print ("test 18")
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:
1176 f.write(vl)
1177
1178 print ("test 19")
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:
1188 f.write(vl)
1189
1190 print ("test 20")
1191 dut = FIFOTest16()
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:
1200 f.write(vl)
1201
1202 print ("test 21")
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:
1212 f.write(vl)
1213
1214 print ("test 22")
1215 dut = ExampleRecordHandshakeAddClass()
1216 data=data_2op()
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] + \
1222 [dut.n.o_data]
1223 vl = rtlil.convert(dut, ports=ports)
1224 with open("test_addrecord22.il", "w") as f:
1225 f.write(vl)
1226
1227 print ("test 23")
1228 dut = ExampleFIFORecordObjectPipe()
1229 data=data_2op()
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] + \
1235 [dut.n.o_data]
1236 vl = rtlil.convert(dut, ports=ports)
1237 with open("test_addrecord23.il", "w") as f:
1238 f.write(vl)
1239
1240 print ("test 24")
1241 dut = FIFOTestRecordAddStageControl()
1242 data=data_2op()
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] + \
1247 [dut.n.o_data]
1248 vl = rtlil.convert(dut, ports=ports)
1249 with open("test_addrecord24.il", "w") as f:
1250 f.write(vl)
1251 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord24.vcd")
1252
1253 print ("test 25")
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:
1263 f.write(vl)
1264
1265 print ("test 997")
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:
1275 f.write(vl)
1276
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:
1287 f.write(vl)
1288
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:
1299 f.write(vl)
1300