break test_buf_pipe.py down into individual tests
[ieee754fpu.git] / src / nmutil / test / 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, Elaboratable
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 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
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.valid_o
41 assert o_n_valid == val
42
43 def check_o_n_valid2(dut, val):
44 o_n_valid = yield dut.n.valid_o
45 assert o_n_valid == val
46
47
48 def tbench(dut):
49 #yield dut.i_p_rst.eq(1)
50 yield dut.n.ready_i.eq(0)
51 #yield dut.p.ready_o.eq(0)
52 yield
53 yield
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)
58 yield
59
60 yield dut.p.data_i.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.data_i.eq(2)
66 yield
67 yield dut.n.ready_i.eq(0) # begin going into "stall" (next stage says ready)
68 yield dut.p.data_i.eq(9)
69 yield
70 yield dut.p.valid_i.eq(0)
71 yield dut.p.data_i.eq(12)
72 yield
73 yield dut.p.data_i.eq(32)
74 yield dut.n.ready_i.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.ready_i.eq(0)
87 #yield dut.p.ready_o.eq(0)
88 yield
89 yield
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)
94 yield
95
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
98 yield
99 yield from check_o_n_valid2(dut, 0) # effects of i_p_valid delayed 2 clocks
100
101 yield dut.p.data_i.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.ready_i.eq(0) # begin going into "stall" (next stage says ready)
105 yield dut.p.data_i.eq(9)
106 yield
107 yield dut.p.valid_i.eq(0)
108 yield dut.p.data_i.eq(12)
109 yield
110 yield dut.p.data_i.eq(32)
111 yield dut.n.ready_i.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.ready_o
145 if not o_p_ready:
146 yield
147 continue
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])
151 self.i += 1
152 else:
153 yield self.dut.p.valid_i.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.ready_i.eq(stall)
162 yield
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:
166 continue
167 data_o = yield self.dut.n.data_o
168 self.resultfn(data_o, 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(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)
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.ready_o
219 if not o_p_ready:
220 yield
221 continue
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]):
225 yield v
226 self.i += 1
227 else:
228 yield self.dut.p.valid_i.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.ready_i.eq(ready)
238 yield
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:
242 continue
243 if isinstance(self.dut.n.data_o, Record):
244 data_o = {}
245 dod = self.dut.n.data_o
246 for k, v in dod.fields.items():
247 data_o[k] = yield v
248 else:
249 data_o = yield self.dut.n.data_o
250 self.resultfn(data_o, 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(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))
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.ready_i.eq(stall)
272 o_p_ready = yield dut.p.ready_o
273 if o_p_ready:
274 if send and i != len(data):
275 yield dut.p.valid_i.eq(1)
276 yield dut.p.data_i.eq(data[i])
277 i += 1
278 else:
279 yield dut.p.valid_i.eq(0)
280 yield
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])
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 = ControlBase.elaborate(self, platform)
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(data_o, expected, i, o):
335 res = expected + 2
336 assert data_o == res, \
337 "%d-%d received data %x not match expected %x\n" \
338 % (i, o, data_o, res)
339
340
341 ######################################################################
342 # Test 6 and 10
343 ######################################################################
344
345 class SetLessThan(Elaboratable):
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, name):
364 return (Signal(16, name="%s_sig1" % name),
365 Signal(16, name="%s_sig2" % name))
366
367 def ospec(self, name):
368 return Signal(16, "%s_out" % name)
369
370 def setup(self, m, i):
371 self.o = Signal(16)
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)
376
377 def process(self, i):
378 return self.o
379
380
381 class LTStageDerived(SetLessThan, StageCls):
382 """ special version of a nmigen module where the module is also a stage
383
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
387 """
388
389 def __init__(self):
390 SetLessThan.__init__(self, 16, True)
391
392 def ispec(self):
393 return (Signal(16), Signal(16))
394
395 def ospec(self):
396 return Signal(16)
397
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])
402
403 def process(self, i):
404 return self.output
405
406
407 class ExampleLTPipeline(UnbufferedPipeline):
408 """ an example of how to use the unbuffered pipeline.
409 """
410
411 def __init__(self):
412 stage = LTStage()
413 UnbufferedPipeline.__init__(self, stage)
414
415
416 class ExampleLTBufferedPipeDerived(BufferedHandshake):
417 """ an example of how to use the buffered pipeline.
418 """
419
420 def __init__(self):
421 stage = LTStageDerived()
422 BufferedHandshake.__init__(self, stage)
423
424
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))
430
431
432 ######################################################################
433 # Test 7
434 ######################################################################
435
436 class ExampleAddRecordStage(StageCls):
437 """ example use of a Record
438 """
439
440 record_spec = [('src1', 16), ('src2', 16)]
441 def ispec(self):
442 """ returns a Record using the specification
443 """
444 return Record(self.record_spec)
445
446 def ospec(self):
447 return Record(self.record_spec)
448
449 def process(self, i):
450 """ process the input data, returning a dictionary with key names
451 that exactly match the Record's attributes.
452 """
453 return {'src1': i.src1 + 1,
454 'src2': i.src2 + 1}
455
456 ######################################################################
457 # Test 11
458 ######################################################################
459
460 class ExampleAddRecordPlaceHolderStage(StageCls):
461 """ example use of a Record, with a placeholder as the processing result
462 """
463
464 record_spec = [('src1', 16), ('src2', 16)]
465 def ispec(self):
466 """ returns a Record using the specification
467 """
468 return Record(self.record_spec)
469
470 def ospec(self):
471 return Record(self.record_spec)
472
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.
476 """
477 o = PlaceHolder()
478 o.src1 = i.src1 + 1
479 o.src2 = i.src2 + 1
480 return o
481
482
483 # a dummy class that may have stuff assigned to instances once created
484 class PlaceHolder: pass
485
486
487 class ExampleAddRecordPipe(UnbufferedPipeline):
488 """ an example of how to use the combinatorial pipeline.
489 """
490
491 def __init__(self):
492 stage = ExampleAddRecordStage()
493 UnbufferedPipeline.__init__(self, stage)
494
495
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))
501
502
503 class ExampleAddRecordPlaceHolderPipe(UnbufferedPipeline):
504 """ an example of how to use the combinatorial pipeline.
505 """
506
507 def __init__(self):
508 stage = ExampleAddRecordPlaceHolderStage()
509 UnbufferedPipeline.__init__(self, stage)
510
511
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))
518
519
520 ######################################################################
521 # Test 8
522 ######################################################################
523
524
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
528 """
529
530 def __init__(self):
531 self.op1 = Signal(16)
532 self.op2 = Signal(16)
533
534 def eq(self, i):
535 return [self.op1.eq(i.op1), self.op2.eq(i.op2)]
536
537
538 class ExampleAddClassStage(StageCls):
539 """ an example of how to use the buffered pipeline, as a class instance
540 """
541
542 def ispec(self):
543 """ returns an instance of an Example2OpClass.
544 """
545 return Example2OpClass()
546
547 def ospec(self):
548 """ returns an output signal which will happen to contain the sum
549 of the two inputs
550 """
551 return Signal(16, name="add2_out")
552
553 def process(self, i):
554 """ process the input data (sums the values in the tuple) and returns it
555 """
556 return i.op1 + i.op2
557
558
559 class ExampleBufPipeAddClass(BufferedHandshake):
560 """ an example of how to use the buffered pipeline, using a class instance
561 """
562
563 def __init__(self):
564 addstage = ExampleAddClassStage()
565 BufferedHandshake.__init__(self, addstage)
566
567
568 class TestInputAdd:
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
573 """
574 def __init__(self, op1, op2):
575 self.op1 = op1
576 self.op2 = op2
577
578
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))
584
585 def data_2op():
586 data = []
587 for i in range(num_tests):
588 data.append(TestInputAdd(randint(0, 1<<16-1), randint(0, 1<<16-1)))
589 return data
590
591
592 ######################################################################
593 # Test 12
594 ######################################################################
595
596 class ExampleStageDelayCls(StageCls, Elaboratable):
597 """ an example of how to use the buffered pipeline, in a static class
598 fashion
599 """
600
601 def __init__(self, valid_trigger=2):
602 self.count = Signal(2)
603 self.valid_trigger = valid_trigger
604
605 def ispec(self):
606 return Signal(16, name="example_input_signal")
607
608 def ospec(self):
609 return Signal(16, name="example_output_signal")
610
611 @property
612 def d_ready(self):
613 """ data is ready to be accepted when this is true
614 """
615 return (self.count == 1)# | (self.count == 3)
616 return Const(1)
617
618 def d_valid(self, ready_i):
619 """ data is valid at output when this is true
620 """
621 return self.count == self.valid_trigger
622 return Const(1)
623
624 def process(self, i):
625 """ process the input data and returns it (adds 1)
626 """
627 return i + 1
628
629 def elaborate(self, platform):
630 m = Module()
631 m.d.sync += self.count.eq(self.count + 1)
632 return m
633
634
635 class ExampleBufDelayedPipe(BufferedHandshake):
636
637 def __init__(self):
638 stage = ExampleStageDelayCls(valid_trigger=2)
639 BufferedHandshake.__init__(self, stage, stage_ctl=True)
640
641 def elaborate(self, platform):
642 m = BufferedHandshake.elaborate(self, platform)
643 m.submodules.stage = self.stage
644 return m
645
646
647 def data_chain1():
648 data = []
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]))
653 return data
654
655
656 def resultfn_12(data_o, expected, i, o):
657 res = expected + 1
658 assert data_o == res, \
659 "%d-%d data %x not match %x\n" \
660 % (i, o, data_o, res)
661
662
663 ######################################################################
664 # Test 13
665 ######################################################################
666
667 class ExampleUnBufDelayedPipe(BufferedHandshake):
668
669 def __init__(self):
670 stage = ExampleStageDelayCls(valid_trigger=3)
671 BufferedHandshake.__init__(self, stage, stage_ctl=True)
672
673 def elaborate(self, platform):
674 m = BufferedHandshake.elaborate(self, platform)
675 m.submodules.stage = self.stage
676 return m
677
678 ######################################################################
679 # Test 15
680 ######################################################################
681
682 class ExampleBufModeAdd1Pipe(SimpleHandshake):
683
684 def __init__(self):
685 stage = ExampleStageCls()
686 SimpleHandshake.__init__(self, stage)
687
688
689 ######################################################################
690 # Test 16
691 ######################################################################
692
693 class ExampleBufModeUnBufPipe(ControlBase):
694
695 def elaborate(self, platform):
696 m = ControlBase.elaborate(self, platform)
697
698 pipe1 = ExampleBufModeAdd1Pipe()
699 pipe2 = ExampleBufAdd1Pipe()
700
701 m.submodules.pipe1 = pipe1
702 m.submodules.pipe2 = pipe2
703
704 m.d.comb += self.connect([pipe1, pipe2])
705
706 return m
707
708 ######################################################################
709 # Test 17
710 ######################################################################
711
712 class ExampleUnBufAdd1Pipe2(UnbufferedPipeline2):
713
714 def __init__(self):
715 stage = ExampleStageCls()
716 UnbufferedPipeline2.__init__(self, stage)
717
718
719 ######################################################################
720 # Test 18
721 ######################################################################
722
723 class PassThroughTest(PassThroughHandshake):
724
725 def iospecfn(self):
726 return Signal(16, "out")
727
728 def __init__(self):
729 stage = PassThroughStage(self.iospecfn)
730 PassThroughHandshake.__init__(self, stage)
731
732 def resultfn_identical(data_o, expected, i, o):
733 res = expected
734 assert data_o == res, \
735 "%d-%d data %x not match %x\n" \
736 % (i, o, data_o, res)
737
738
739 ######################################################################
740 # Test 19
741 ######################################################################
742
743 class ExamplePassAdd1Pipe(PassThroughHandshake):
744
745 def __init__(self):
746 stage = ExampleStageCls()
747 PassThroughHandshake.__init__(self, stage)
748
749
750 class ExampleBufPassThruPipe(ControlBase):
751
752 def elaborate(self, platform):
753 m = ControlBase.elaborate(self, platform)
754
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()
760
761 m.submodules.pipe1 = pipe1
762 m.submodules.pipe2 = pipe2
763
764 m.d.comb += self.connect([pipe1, pipe2])
765
766 return m
767
768
769 ######################################################################
770 # Test 20
771 ######################################################################
772
773 def iospecfn():
774 return Signal(16, name="d_in")
775
776 class FIFOTest16(FIFOControl):
777
778 def __init__(self):
779 stage = PassThroughStage(iospecfn)
780 FIFOControl.__init__(self, 2, stage)
781
782
783 ######################################################################
784 # Test 21
785 ######################################################################
786
787 class ExampleFIFOPassThruPipe1(ControlBase):
788
789 def elaborate(self, platform):
790 m = ControlBase.elaborate(self, platform)
791
792 pipe1 = FIFOTest16()
793 pipe2 = FIFOTest16()
794 pipe3 = ExamplePassAdd1Pipe()
795
796 m.submodules.pipe1 = pipe1
797 m.submodules.pipe2 = pipe2
798 m.submodules.pipe3 = pipe3
799
800 m.d.comb += self.connect([pipe1, pipe2, pipe3])
801
802 return m
803
804
805 ######################################################################
806 # Test 22
807 ######################################################################
808
809 class Example2OpRecord(RecordObject):
810 def __init__(self):
811 RecordObject.__init__(self)
812 self.op1 = Signal(16)
813 self.op2 = Signal(16)
814
815
816 class ExampleAddRecordObjectStage(StageCls):
817
818 def ispec(self):
819 """ returns an instance of an Example2OpRecord.
820 """
821 return Example2OpRecord()
822
823 def ospec(self):
824 """ returns an output signal which will happen to contain the sum
825 of the two inputs
826 """
827 return Signal(16)
828
829 def process(self, i):
830 """ process the input data (sums the values in the tuple) and returns it
831 """
832 return i.op1 + i.op2
833
834
835 class ExampleRecordHandshakeAddClass(SimpleHandshake):
836
837 def __init__(self):
838 addstage = ExampleAddRecordObjectStage()
839 SimpleHandshake.__init__(self, stage=addstage)
840
841
842 ######################################################################
843 # Test 23
844 ######################################################################
845
846 def iospecfnrecord():
847 return Example2OpRecord()
848
849 class FIFOTestRecordControl(FIFOControl):
850
851 def __init__(self):
852 stage = PassThroughStage(iospecfnrecord)
853 FIFOControl.__init__(self, 2, stage)
854
855
856 class ExampleFIFORecordObjectPipe(ControlBase):
857
858 def elaborate(self, platform):
859 m = ControlBase.elaborate(self, platform)
860
861 pipe1 = FIFOTestRecordControl()
862 pipe2 = ExampleRecordHandshakeAddClass()
863
864 m.submodules.pipe1 = pipe1
865 m.submodules.pipe2 = pipe2
866
867 m.d.comb += self.connect([pipe1, pipe2])
868
869 return m
870
871
872 ######################################################################
873 # Test 24
874 ######################################################################
875
876 class FIFOTestRecordAddStageControl(FIFOControl):
877
878 def __init__(self):
879 stage = ExampleAddRecordObjectStage()
880 FIFOControl.__init__(self, 2, stage)
881
882
883
884 ######################################################################
885 # Test 25
886 ######################################################################
887
888 class FIFOTestAdd16(FIFOControl):
889
890 def __init__(self):
891 stage = ExampleStageCls()
892 FIFOControl.__init__(self, 2, stage)
893
894
895 class ExampleFIFOAdd2Pipe(ControlBase):
896
897 def elaborate(self, platform):
898 m = ControlBase.elaborate(self, platform)
899
900 pipe1 = FIFOTestAdd16()
901 pipe2 = FIFOTestAdd16()
902
903 m.submodules.pipe1 = pipe1
904 m.submodules.pipe2 = pipe2
905
906 m.d.comb += self.connect([pipe1, pipe2])
907
908 return m
909
910
911 ######################################################################
912 # Test 26
913 ######################################################################
914
915 def iospecfn24():
916 return (Signal(16, name="src1"), Signal(16, name="src2"))
917
918 class FIFOTest2x16(FIFOControl):
919
920 def __init__(self):
921 stage = PassThroughStage(iospecfn2)
922 FIFOControl.__init__(self, 2, stage)
923
924
925 ######################################################################
926 # Test 997
927 ######################################################################
928
929 class ExampleBufPassThruPipe2(ControlBase):
930
931 def elaborate(self, platform):
932 m = ControlBase.elaborate(self, platform)
933
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()
941
942 m.submodules.pipe1 = pipe1
943 m.submodules.pipe2 = pipe2
944
945 m.d.comb += self.connect([pipe1, pipe2])
946
947 return m
948
949
950 ######################################################################
951 # Test 998
952 ######################################################################
953
954 class ExampleBufPipe3(ControlBase):
955 """ Example of how to do delayed pipeline, where the stage signals
956 whether it is ready.
957 """
958
959 def elaborate(self, platform):
960 m = ControlBase.elaborate(self, platform)
961
962 pipe1 = ExampleBufDelayedPipe()
963 pipe2 = ExampleBufPipe()
964
965 m.submodules.pipe1 = pipe1
966 m.submodules.pipe2 = pipe2
967
968 m.d.comb += self.connect([pipe1, pipe2])
969
970 return m
971
972 ######################################################################
973 # Test 999 - XXX FAILS
974 # http://bugs.libre-riscv.org/show_bug.cgi?id=57
975 ######################################################################
976
977 class ExampleBufAdd1Pipe(BufferedHandshake):
978
979 def __init__(self):
980 stage = ExampleStageCls()
981 BufferedHandshake.__init__(self, stage)
982
983
984 class ExampleUnBufAdd1Pipe(UnbufferedPipeline):
985
986 def __init__(self):
987 stage = ExampleStageCls()
988 UnbufferedPipeline.__init__(self, stage)
989
990
991 class ExampleBufUnBufPipe(ControlBase):
992
993 def elaborate(self, platform):
994 m = ControlBase.elaborate(self, platform)
995
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()
1003
1004 m.submodules.pipe1 = pipe1
1005 m.submodules.pipe2 = pipe2
1006
1007 m.d.comb += self.connect([pipe1, pipe2])
1008
1009 return m
1010
1011
1012 ######################################################################
1013 # Unit Tests
1014 ######################################################################
1015
1016 num_tests = 10
1017
1018 def notworking1():
1019 print ("test 1")
1020 dut = ExampleBufPipe()
1021 run_simulation(dut, tbench(dut), vcd_name="test_bufpipe.vcd")
1022
1023 def notworking2():
1024 print ("test 2")
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:
1032 f.write(vl)
1033
1034 def test3():
1035 print ("test 3")
1036 dut = ExampleBufPipe()
1037 test = Test3(dut, resultfn_3)
1038 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe3.vcd")
1039
1040 def test3_5():
1041 print ("test 3.5")
1042 dut = ExamplePipeline()
1043 test = Test3(dut, resultfn_3)
1044 run_simulation(dut, [test.send, test.rcv], vcd_name="test_combpipe3.vcd")
1045
1046 def test4():
1047 print ("test 4")
1048 dut = ExampleBufPipe2()
1049 run_simulation(dut, tbench4(dut), vcd_name="test_bufpipe4.vcd")
1050
1051 def test5():
1052 print ("test 5")
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")
1056
1057 def test6():
1058 print ("test 6")
1059 dut = ExampleLTPipeline()
1060 test = Test5(dut, resultfn_6)
1061 run_simulation(dut, [test.send, test.rcv], vcd_name="test_ltcomb6.vcd")
1062
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:
1068 f.write(vl)
1069
1070 def test7():
1071 print ("test 7")
1072 dut = ExampleAddRecordPipe()
1073 data=data_dict()
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:
1081 f.write(vl)
1082 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord.vcd")
1083
1084 def test8():
1085 print ("test 8")
1086 dut = ExampleBufPipeAddClass()
1087 data=data_2op()
1088 test = Test5(dut, resultfn_8, data=data)
1089 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe8.vcd")
1090
1091 def test9():
1092 print ("test 9")
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:
1099 f.write(vl)
1100
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")
1105
1106 def test10():
1107 print ("test 10")
1108 dut = ExampleLTBufferedPipeDerived()
1109 test = Test5(dut, resultfn_6)
1110 run_simulation(dut, [test.send, test.rcv], vcd_name="test_ltbufpipe10.vcd")
1111 ports = dut.ports()
1112 vl = rtlil.convert(dut, ports=ports)
1113 with open("test_ltbufpipe10.il", "w") as f:
1114 f.write(vl)
1115
1116 def test11():
1117 print ("test 11")
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")
1122
1123
1124 def test12():
1125 print ("test 12")
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:
1135 f.write(vl)
1136
1137 def test13():
1138 print ("test 13")
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:
1148 f.write(vl)
1149
1150 def test15():
1151 print ("test 15")
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:
1161 f.write(vl)
1162
1163 def test16():
1164 print ("test 16")
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:
1174 f.write(vl)
1175
1176 def test17():
1177 print ("test 17")
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:
1187 f.write(vl)
1188
1189 def test18():
1190 print ("test 18")
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:
1200 f.write(vl)
1201
1202 def test19():
1203 print ("test 19")
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:
1213 f.write(vl)
1214
1215 def test20():
1216 print ("test 20")
1217 dut = FIFOTest16()
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:
1226 f.write(vl)
1227
1228 def test21():
1229 print ("test 21")
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:
1239 f.write(vl)
1240
1241 def test22():
1242 print ("test 22")
1243 dut = ExampleRecordHandshakeAddClass()
1244 data=data_2op()
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] + \
1250 [dut.n.data_o]
1251 vl = rtlil.convert(dut, ports=ports)
1252 with open("test_addrecord22.il", "w") as f:
1253 f.write(vl)
1254
1255 def test23():
1256 print ("test 23")
1257 dut = ExampleFIFORecordObjectPipe()
1258 data=data_2op()
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] + \
1264 [dut.n.data_o]
1265 vl = rtlil.convert(dut, ports=ports)
1266 with open("test_addrecord23.il", "w") as f:
1267 f.write(vl)
1268
1269 def test24():
1270 print ("test 24")
1271 dut = FIFOTestRecordAddStageControl()
1272 data=data_2op()
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] + \
1277 [dut.n.data_o]
1278 vl = rtlil.convert(dut, ports=ports)
1279 with open("test_addrecord24.il", "w") as f:
1280 f.write(vl)
1281 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord24.vcd")
1282
1283 def test25():
1284 print ("test 25")
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:
1294 f.write(vl)
1295
1296 def test997():
1297 print ("test 997")
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:
1307 f.write(vl)
1308
1309 def test998():
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:
1320 f.write(vl)
1321
1322 def test999():
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:
1333 f.write(vl)
1334