replace i_valid with valid_i
[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, 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 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.ready_o.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.valid_i.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.valid_i.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.ready_o.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.valid_i.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.valid_i.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.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.i_data.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.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.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.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.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.i_data.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.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 = 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(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(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, Elaboratable):
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(o_data, expected, i, o):
426 res = 1 if expected[0] < expected[1] else 0
427 assert o_data == res, \
428 "%d-%d data %x not match %s\n" \
429 % (i, o, o_data, 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 class PlaceHolder: pass
484
485
486 class ExampleAddRecordPipe(UnbufferedPipeline):
487 """ an example of how to use the combinatorial pipeline.
488 """
489
490 def __init__(self):
491 stage = ExampleAddRecordStage()
492 UnbufferedPipeline.__init__(self, stage)
493
494
495 def resultfn_7(o_data, expected, i, o):
496 res = (expected['src1'] + 1, expected['src2'] + 1)
497 assert o_data['src1'] == res[0] and o_data['src2'] == res[1], \
498 "%d-%d data %s not match %s\n" \
499 % (i, o, repr(o_data), repr(expected))
500
501
502 class ExampleAddRecordPlaceHolderPipe(UnbufferedPipeline):
503 """ an example of how to use the combinatorial pipeline.
504 """
505
506 def __init__(self):
507 stage = ExampleAddRecordPlaceHolderStage()
508 UnbufferedPipeline.__init__(self, stage)
509
510
511 def resultfn_test11(o_data, expected, i, o):
512 res1 = expected.src1 + 1
513 res2 = expected.src2 + 1
514 assert o_data['src1'] == res1 and o_data['src2'] == res2, \
515 "%d-%d data %s not match %s\n" \
516 % (i, o, repr(o_data), repr(expected))
517
518
519 ######################################################################
520 # Test 8
521 ######################################################################
522
523
524 class Example2OpClass:
525 """ an example of a class used to store 2 operands.
526 requires an eq function, to conform with the pipeline stage API
527 """
528
529 def __init__(self):
530 self.op1 = Signal(16)
531 self.op2 = Signal(16)
532
533 def eq(self, i):
534 return [self.op1.eq(i.op1), self.op2.eq(i.op2)]
535
536
537 class ExampleAddClassStage(StageCls):
538 """ an example of how to use the buffered pipeline, as a class instance
539 """
540
541 def ispec(self):
542 """ returns an instance of an Example2OpClass.
543 """
544 return Example2OpClass()
545
546 def ospec(self):
547 """ returns an output signal which will happen to contain the sum
548 of the two inputs
549 """
550 return Signal(16)
551
552 def process(self, i):
553 """ process the input data (sums the values in the tuple) and returns it
554 """
555 return i.op1 + i.op2
556
557
558 class ExampleBufPipeAddClass(BufferedHandshake):
559 """ an example of how to use the buffered pipeline, using a class instance
560 """
561
562 def __init__(self):
563 addstage = ExampleAddClassStage()
564 BufferedHandshake.__init__(self, addstage)
565
566
567 class TestInputAdd:
568 """ the eq function, called by set_input, needs an incoming object
569 that conforms to the Example2OpClass.eq function requirements
570 easiest way to do that is to create a class that has the exact
571 same member layout (self.op1, self.op2) as Example2OpClass
572 """
573 def __init__(self, op1, op2):
574 self.op1 = op1
575 self.op2 = op2
576
577
578 def resultfn_8(o_data, expected, i, o):
579 res = expected.op1 + expected.op2 # these are a TestInputAdd instance
580 assert o_data == res, \
581 "%d-%d data %s res %x not match %s\n" \
582 % (i, o, repr(o_data), res, repr(expected))
583
584 def data_2op():
585 data = []
586 for i in range(num_tests):
587 data.append(TestInputAdd(randint(0, 1<<16-1), randint(0, 1<<16-1)))
588 return data
589
590
591 ######################################################################
592 # Test 12
593 ######################################################################
594
595 class ExampleStageDelayCls(StageCls, Elaboratable):
596 """ an example of how to use the buffered pipeline, in a static class
597 fashion
598 """
599
600 def __init__(self, valid_trigger=2):
601 self.count = Signal(2)
602 self.valid_trigger = valid_trigger
603
604 def ispec(self):
605 return Signal(16, name="example_input_signal")
606
607 def ospec(self):
608 return Signal(16, name="example_output_signal")
609
610 @property
611 def d_ready(self):
612 """ data is ready to be accepted when this is true
613 """
614 return (self.count == 1)# | (self.count == 3)
615 return Const(1)
616
617 def d_valid(self, i_ready):
618 """ data is valid at output when this is true
619 """
620 return self.count == self.valid_trigger
621 return Const(1)
622
623 def process(self, i):
624 """ process the input data and returns it (adds 1)
625 """
626 return i + 1
627
628 def elaborate(self, platform):
629 m = Module()
630 m.d.sync += self.count.eq(self.count + 1)
631 return m
632
633
634 class ExampleBufDelayedPipe(BufferedHandshake):
635
636 def __init__(self):
637 stage = ExampleStageDelayCls(valid_trigger=2)
638 BufferedHandshake.__init__(self, stage, stage_ctl=True)
639
640 def elaborate(self, platform):
641 m = BufferedHandshake.elaborate(self, platform)
642 m.submodules.stage = self.stage
643 return m
644
645
646 def data_chain1():
647 data = []
648 for i in range(num_tests):
649 data.append(1<<((i*3)%15))
650 #data.append(randint(0, 1<<16-2))
651 #print (hex(data[-1]))
652 return data
653
654
655 def resultfn_12(o_data, expected, i, o):
656 res = expected + 1
657 assert o_data == res, \
658 "%d-%d data %x not match %x\n" \
659 % (i, o, o_data, res)
660
661
662 ######################################################################
663 # Test 13
664 ######################################################################
665
666 class ExampleUnBufDelayedPipe(BufferedHandshake):
667
668 def __init__(self):
669 stage = ExampleStageDelayCls(valid_trigger=3)
670 BufferedHandshake.__init__(self, stage, stage_ctl=True)
671
672 def elaborate(self, platform):
673 m = BufferedHandshake.elaborate(self, platform)
674 m.submodules.stage = self.stage
675 return m
676
677 ######################################################################
678 # Test 15
679 ######################################################################
680
681 class ExampleBufModeAdd1Pipe(SimpleHandshake):
682
683 def __init__(self):
684 stage = ExampleStageCls()
685 SimpleHandshake.__init__(self, stage)
686
687
688 ######################################################################
689 # Test 16
690 ######################################################################
691
692 class ExampleBufModeUnBufPipe(ControlBase):
693
694 def elaborate(self, platform):
695 m = ControlBase.elaborate(self, platform)
696
697 pipe1 = ExampleBufModeAdd1Pipe()
698 pipe2 = ExampleBufAdd1Pipe()
699
700 m.submodules.pipe1 = pipe1
701 m.submodules.pipe2 = pipe2
702
703 m.d.comb += self.connect([pipe1, pipe2])
704
705 return m
706
707 ######################################################################
708 # Test 17
709 ######################################################################
710
711 class ExampleUnBufAdd1Pipe2(UnbufferedPipeline2):
712
713 def __init__(self):
714 stage = ExampleStageCls()
715 UnbufferedPipeline2.__init__(self, stage)
716
717
718 ######################################################################
719 # Test 18
720 ######################################################################
721
722 class PassThroughTest(PassThroughHandshake):
723
724 def iospecfn(self):
725 return Signal(16, "out")
726
727 def __init__(self):
728 stage = PassThroughStage(self.iospecfn)
729 PassThroughHandshake.__init__(self, stage)
730
731 def resultfn_identical(o_data, expected, i, o):
732 res = expected
733 assert o_data == res, \
734 "%d-%d data %x not match %x\n" \
735 % (i, o, o_data, res)
736
737
738 ######################################################################
739 # Test 19
740 ######################################################################
741
742 class ExamplePassAdd1Pipe(PassThroughHandshake):
743
744 def __init__(self):
745 stage = ExampleStageCls()
746 PassThroughHandshake.__init__(self, stage)
747
748
749 class ExampleBufPassThruPipe(ControlBase):
750
751 def elaborate(self, platform):
752 m = ControlBase.elaborate(self, platform)
753
754 # XXX currently fails: any other permutation works fine.
755 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
756 # also fails using UnbufferedPipeline as well
757 pipe1 = ExampleBufModeAdd1Pipe()
758 pipe2 = ExamplePassAdd1Pipe()
759
760 m.submodules.pipe1 = pipe1
761 m.submodules.pipe2 = pipe2
762
763 m.d.comb += self.connect([pipe1, pipe2])
764
765 return m
766
767
768 ######################################################################
769 # Test 20
770 ######################################################################
771
772 def iospecfn():
773 return Signal(16, name="d_in")
774
775 class FIFOTest16(FIFOControl):
776
777 def __init__(self):
778 stage = PassThroughStage(iospecfn)
779 FIFOControl.__init__(self, 2, stage)
780
781
782 ######################################################################
783 # Test 21
784 ######################################################################
785
786 class ExampleFIFOPassThruPipe1(ControlBase):
787
788 def elaborate(self, platform):
789 m = ControlBase.elaborate(self, platform)
790
791 pipe1 = FIFOTest16()
792 pipe2 = ExamplePassAdd1Pipe()
793
794 m.submodules.pipe1 = pipe1
795 m.submodules.pipe2 = pipe2
796
797 m.d.comb += self.connect([pipe1, pipe2])
798
799 return m
800
801
802 ######################################################################
803 # Test 22
804 ######################################################################
805
806 class Example2OpRecord(RecordObject):
807 def __init__(self):
808 RecordObject.__init__(self)
809 self.op1 = Signal(16)
810 self.op2 = Signal(16)
811
812
813 class ExampleAddRecordObjectStage(StageCls):
814
815 def ispec(self):
816 """ returns an instance of an Example2OpRecord.
817 """
818 return Example2OpRecord()
819
820 def ospec(self):
821 """ returns an output signal which will happen to contain the sum
822 of the two inputs
823 """
824 return Signal(16)
825
826 def process(self, i):
827 """ process the input data (sums the values in the tuple) and returns it
828 """
829 return i.op1 + i.op2
830
831
832 class ExampleRecordHandshakeAddClass(SimpleHandshake):
833
834 def __init__(self):
835 addstage = ExampleAddRecordObjectStage()
836 SimpleHandshake.__init__(self, stage=addstage)
837
838
839 ######################################################################
840 # Test 23
841 ######################################################################
842
843 def iospecfnrecord():
844 return Example2OpRecord()
845
846 class FIFOTestRecordControl(FIFOControl):
847
848 def __init__(self):
849 stage = PassThroughStage(iospecfnrecord)
850 FIFOControl.__init__(self, 2, stage)
851
852
853 class ExampleFIFORecordObjectPipe(ControlBase):
854
855 def elaborate(self, platform):
856 m = ControlBase.elaborate(self, platform)
857
858 pipe1 = FIFOTestRecordControl()
859 pipe2 = ExampleRecordHandshakeAddClass()
860
861 m.submodules.pipe1 = pipe1
862 m.submodules.pipe2 = pipe2
863
864 m.d.comb += self.connect([pipe1, pipe2])
865
866 return m
867
868
869 ######################################################################
870 # Test 24
871 ######################################################################
872
873 class FIFOTestRecordAddStageControl(FIFOControl):
874
875 def __init__(self):
876 stage = ExampleAddRecordObjectStage()
877 FIFOControl.__init__(self, 2, stage)
878
879
880
881 ######################################################################
882 # Test 25
883 ######################################################################
884
885 class FIFOTestAdd16(FIFOControl):
886
887 def __init__(self):
888 stage = ExampleStageCls()
889 FIFOControl.__init__(self, 2, stage)
890
891
892 class ExampleFIFOAdd2Pipe(ControlBase):
893
894 def elaborate(self, platform):
895 m = ControlBase.elaborate(self, platform)
896
897 pipe1 = FIFOTestAdd16()
898 pipe2 = FIFOTestAdd16()
899
900 m.submodules.pipe1 = pipe1
901 m.submodules.pipe2 = pipe2
902
903 m.d.comb += self.connect([pipe1, pipe2])
904
905 return m
906
907
908 ######################################################################
909 # Test 26
910 ######################################################################
911
912 def iospecfn24():
913 return (Signal(16, name="src1"), Signal(16, name="src2"))
914
915 class FIFOTest2x16(FIFOControl):
916
917 def __init__(self):
918 stage = PassThroughStage(iospecfn2)
919 FIFOControl.__init__(self, 2, stage)
920
921
922 ######################################################################
923 # Test 997
924 ######################################################################
925
926 class ExampleBufPassThruPipe2(ControlBase):
927
928 def elaborate(self, platform):
929 m = ControlBase.elaborate(self, platform)
930
931 # XXX currently fails: any other permutation works fine.
932 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
933 # also fails using UnbufferedPipeline as well
934 #pipe1 = ExampleUnBufAdd1Pipe()
935 #pipe2 = ExampleBufAdd1Pipe()
936 pipe1 = ExampleBufAdd1Pipe()
937 pipe2 = ExamplePassAdd1Pipe()
938
939 m.submodules.pipe1 = pipe1
940 m.submodules.pipe2 = pipe2
941
942 m.d.comb += self.connect([pipe1, pipe2])
943
944 return m
945
946
947 ######################################################################
948 # Test 998
949 ######################################################################
950
951 class ExampleBufPipe3(ControlBase):
952 """ Example of how to do delayed pipeline, where the stage signals
953 whether it is ready.
954 """
955
956 def elaborate(self, platform):
957 m = ControlBase.elaborate(self, platform)
958
959 pipe1 = ExampleBufDelayedPipe()
960 pipe2 = ExampleBufPipe()
961
962 m.submodules.pipe1 = pipe1
963 m.submodules.pipe2 = pipe2
964
965 m.d.comb += self.connect([pipe1, pipe2])
966
967 return m
968
969 ######################################################################
970 # Test 999 - XXX FAILS
971 # http://bugs.libre-riscv.org/show_bug.cgi?id=57
972 ######################################################################
973
974 class ExampleBufAdd1Pipe(BufferedHandshake):
975
976 def __init__(self):
977 stage = ExampleStageCls()
978 BufferedHandshake.__init__(self, stage)
979
980
981 class ExampleUnBufAdd1Pipe(UnbufferedPipeline):
982
983 def __init__(self):
984 stage = ExampleStageCls()
985 UnbufferedPipeline.__init__(self, stage)
986
987
988 class ExampleBufUnBufPipe(ControlBase):
989
990 def elaborate(self, platform):
991 m = ControlBase.elaborate(self, platform)
992
993 # XXX currently fails: any other permutation works fine.
994 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
995 # also fails using UnbufferedPipeline as well
996 #pipe1 = ExampleUnBufAdd1Pipe()
997 #pipe2 = ExampleBufAdd1Pipe()
998 pipe1 = ExampleBufAdd1Pipe()
999 pipe2 = ExampleUnBufAdd1Pipe()
1000
1001 m.submodules.pipe1 = pipe1
1002 m.submodules.pipe2 = pipe2
1003
1004 m.d.comb += self.connect([pipe1, pipe2])
1005
1006 return m
1007
1008
1009 ######################################################################
1010 # Unit Tests
1011 ######################################################################
1012
1013 num_tests = 10
1014
1015 if __name__ == '__main__':
1016 if False:
1017 print ("test 1")
1018 dut = ExampleBufPipe()
1019 run_simulation(dut, tbench(dut), vcd_name="test_bufpipe.vcd")
1020
1021 print ("test 2")
1022 dut = ExampleBufPipe2()
1023 run_simulation(dut, tbench2(dut), vcd_name="test_bufpipe2.vcd")
1024 ports = [dut.p.valid_i, dut.n.i_ready,
1025 dut.n.o_valid, dut.p.ready_o] + \
1026 [dut.p.i_data] + [dut.n.o_data]
1027 vl = rtlil.convert(dut, ports=ports)
1028 with open("test_bufpipe2.il", "w") as f:
1029 f.write(vl)
1030
1031
1032 print ("test 3")
1033 dut = ExampleBufPipe()
1034 test = Test3(dut, resultfn_3)
1035 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe3.vcd")
1036
1037 print ("test 3.5")
1038 dut = ExamplePipeline()
1039 test = Test3(dut, resultfn_3)
1040 run_simulation(dut, [test.send, test.rcv], vcd_name="test_combpipe3.vcd")
1041
1042 print ("test 4")
1043 dut = ExampleBufPipe2()
1044 run_simulation(dut, tbench4(dut), vcd_name="test_bufpipe4.vcd")
1045
1046 print ("test 5")
1047 dut = ExampleBufPipeAdd()
1048 test = Test5(dut, resultfn_5, stage_ctl=True)
1049 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe5.vcd")
1050
1051 print ("test 6")
1052 dut = ExampleLTPipeline()
1053 test = Test5(dut, resultfn_6)
1054 run_simulation(dut, [test.send, test.rcv], vcd_name="test_ltcomb6.vcd")
1055
1056 ports = [dut.p.valid_i, dut.n.i_ready,
1057 dut.n.o_valid, dut.p.ready_o] + \
1058 list(dut.p.i_data) + [dut.n.o_data]
1059 vl = rtlil.convert(dut, ports=ports)
1060 with open("test_ltcomb_pipe.il", "w") as f:
1061 f.write(vl)
1062
1063 print ("test 7")
1064 dut = ExampleAddRecordPipe()
1065 data=data_dict()
1066 test = Test5(dut, resultfn_7, data=data)
1067 ports = [dut.p.valid_i, dut.n.i_ready,
1068 dut.n.o_valid, dut.p.ready_o,
1069 dut.p.i_data.src1, dut.p.i_data.src2,
1070 dut.n.o_data.src1, dut.n.o_data.src2]
1071 vl = rtlil.convert(dut, ports=ports)
1072 with open("test_recordcomb_pipe.il", "w") as f:
1073 f.write(vl)
1074 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord.vcd")
1075
1076 print ("test 8")
1077 dut = ExampleBufPipeAddClass()
1078 data=data_2op()
1079 test = Test5(dut, resultfn_8, data=data)
1080 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe8.vcd")
1081
1082 print ("test 9")
1083 dut = ExampleBufPipeChain2()
1084 ports = [dut.p.valid_i, dut.n.i_ready,
1085 dut.n.o_valid, dut.p.ready_o] + \
1086 [dut.p.i_data] + [dut.n.o_data]
1087 vl = rtlil.convert(dut, ports=ports)
1088 with open("test_bufpipechain2.il", "w") as f:
1089 f.write(vl)
1090
1091 data = data_chain2()
1092 test = Test5(dut, resultfn_9, data=data)
1093 run_simulation(dut, [test.send, test.rcv],
1094 vcd_name="test_bufpipechain2.vcd")
1095
1096 print ("test 10")
1097 dut = ExampleLTBufferedPipeDerived()
1098 test = Test5(dut, resultfn_6)
1099 run_simulation(dut, [test.send, test.rcv], vcd_name="test_ltbufpipe10.vcd")
1100 vl = rtlil.convert(dut, ports=ports)
1101 with open("test_ltbufpipe10.il", "w") as f:
1102 f.write(vl)
1103
1104 print ("test 11")
1105 dut = ExampleAddRecordPlaceHolderPipe()
1106 data=data_placeholder()
1107 test = Test5(dut, resultfn_test11, data=data)
1108 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord.vcd")
1109
1110
1111 print ("test 12")
1112 dut = ExampleBufDelayedPipe()
1113 data = data_chain1()
1114 test = Test5(dut, resultfn_12, data=data)
1115 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe12.vcd")
1116 ports = [dut.p.valid_i, dut.n.i_ready,
1117 dut.n.o_valid, dut.p.ready_o] + \
1118 [dut.p.i_data] + [dut.n.o_data]
1119 vl = rtlil.convert(dut, ports=ports)
1120 with open("test_bufpipe12.il", "w") as f:
1121 f.write(vl)
1122
1123 print ("test 13")
1124 dut = ExampleUnBufDelayedPipe()
1125 data = data_chain1()
1126 test = Test5(dut, resultfn_12, data=data)
1127 run_simulation(dut, [test.send, test.rcv], vcd_name="test_unbufpipe13.vcd")
1128 ports = [dut.p.valid_i, dut.n.i_ready,
1129 dut.n.o_valid, dut.p.ready_o] + \
1130 [dut.p.i_data] + [dut.n.o_data]
1131 vl = rtlil.convert(dut, ports=ports)
1132 with open("test_unbufpipe13.il", "w") as f:
1133 f.write(vl)
1134
1135 print ("test 15")
1136 dut = ExampleBufModeAdd1Pipe()
1137 data = data_chain1()
1138 test = Test5(dut, resultfn_12, data=data)
1139 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufunbuf15.vcd")
1140 ports = [dut.p.valid_i, dut.n.i_ready,
1141 dut.n.o_valid, dut.p.ready_o] + \
1142 [dut.p.i_data] + [dut.n.o_data]
1143 vl = rtlil.convert(dut, ports=ports)
1144 with open("test_bufunbuf15.il", "w") as f:
1145 f.write(vl)
1146
1147 print ("test 16")
1148 dut = ExampleBufModeUnBufPipe()
1149 data = data_chain1()
1150 test = Test5(dut, resultfn_9, data=data)
1151 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufunbuf16.vcd")
1152 ports = [dut.p.valid_i, dut.n.i_ready,
1153 dut.n.o_valid, dut.p.ready_o] + \
1154 [dut.p.i_data] + [dut.n.o_data]
1155 vl = rtlil.convert(dut, ports=ports)
1156 with open("test_bufunbuf16.il", "w") as f:
1157 f.write(vl)
1158
1159 print ("test 17")
1160 dut = ExampleUnBufAdd1Pipe2()
1161 data = data_chain1()
1162 test = Test5(dut, resultfn_12, data=data)
1163 run_simulation(dut, [test.send, test.rcv], vcd_name="test_unbufpipe17.vcd")
1164 ports = [dut.p.valid_i, dut.n.i_ready,
1165 dut.n.o_valid, dut.p.ready_o] + \
1166 [dut.p.i_data] + [dut.n.o_data]
1167 vl = rtlil.convert(dut, ports=ports)
1168 with open("test_unbufpipe17.il", "w") as f:
1169 f.write(vl)
1170
1171 print ("test 18")
1172 dut = PassThroughTest()
1173 data = data_chain1()
1174 test = Test5(dut, resultfn_identical, data=data)
1175 run_simulation(dut, [test.send, test.rcv], vcd_name="test_passthru18.vcd")
1176 ports = [dut.p.valid_i, dut.n.i_ready,
1177 dut.n.o_valid, dut.p.ready_o] + \
1178 [dut.p.i_data] + [dut.n.o_data]
1179 vl = rtlil.convert(dut, ports=ports)
1180 with open("test_passthru18.il", "w") as f:
1181 f.write(vl)
1182
1183 print ("test 19")
1184 dut = ExampleBufPassThruPipe()
1185 data = data_chain1()
1186 test = Test5(dut, resultfn_9, data=data)
1187 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpass19.vcd")
1188 ports = [dut.p.valid_i, dut.n.i_ready,
1189 dut.n.o_valid, dut.p.ready_o] + \
1190 [dut.p.i_data] + [dut.n.o_data]
1191 vl = rtlil.convert(dut, ports=ports)
1192 with open("test_bufpass19.il", "w") as f:
1193 f.write(vl)
1194
1195 print ("test 20")
1196 dut = FIFOTest16()
1197 data = data_chain1()
1198 test = Test5(dut, resultfn_identical, data=data)
1199 run_simulation(dut, [test.send, test.rcv], vcd_name="test_fifo20.vcd")
1200 ports = [dut.p.valid_i, dut.n.i_ready,
1201 dut.n.o_valid, dut.p.ready_o] + \
1202 [dut.p.i_data] + [dut.n.o_data]
1203 vl = rtlil.convert(dut, ports=ports)
1204 with open("test_fifo20.il", "w") as f:
1205 f.write(vl)
1206
1207 print ("test 21")
1208 dut = ExampleFIFOPassThruPipe1()
1209 data = data_chain1()
1210 test = Test5(dut, resultfn_12, data=data)
1211 run_simulation(dut, [test.send, test.rcv], vcd_name="test_fifopass21.vcd")
1212 ports = [dut.p.valid_i, dut.n.i_ready,
1213 dut.n.o_valid, dut.p.ready_o] + \
1214 [dut.p.i_data] + [dut.n.o_data]
1215 vl = rtlil.convert(dut, ports=ports)
1216 with open("test_fifopass21.il", "w") as f:
1217 f.write(vl)
1218
1219 print ("test 22")
1220 dut = ExampleRecordHandshakeAddClass()
1221 data=data_2op()
1222 test = Test5(dut, resultfn_8, data=data)
1223 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord22.vcd")
1224 ports = [dut.p.valid_i, dut.n.i_ready,
1225 dut.n.o_valid, dut.p.ready_o] + \
1226 [dut.p.i_data.op1, dut.p.i_data.op2] + \
1227 [dut.n.o_data]
1228 vl = rtlil.convert(dut, ports=ports)
1229 with open("test_addrecord22.il", "w") as f:
1230 f.write(vl)
1231
1232 print ("test 23")
1233 dut = ExampleFIFORecordObjectPipe()
1234 data=data_2op()
1235 test = Test5(dut, resultfn_8, data=data)
1236 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord23.vcd")
1237 ports = [dut.p.valid_i, dut.n.i_ready,
1238 dut.n.o_valid, dut.p.ready_o] + \
1239 [dut.p.i_data.op1, dut.p.i_data.op2] + \
1240 [dut.n.o_data]
1241 vl = rtlil.convert(dut, ports=ports)
1242 with open("test_addrecord23.il", "w") as f:
1243 f.write(vl)
1244
1245 print ("test 24")
1246 dut = FIFOTestRecordAddStageControl()
1247 data=data_2op()
1248 test = Test5(dut, resultfn_8, data=data)
1249 ports = [dut.p.valid_i, dut.n.i_ready,
1250 dut.n.o_valid, dut.p.ready_o] + \
1251 [dut.p.i_data.op1, dut.p.i_data.op2] + \
1252 [dut.n.o_data]
1253 vl = rtlil.convert(dut, ports=ports)
1254 with open("test_addrecord24.il", "w") as f:
1255 f.write(vl)
1256 run_simulation(dut, [test.send, test.rcv], vcd_name="test_addrecord24.vcd")
1257
1258 print ("test 25")
1259 dut = ExampleFIFOAdd2Pipe()
1260 data = data_chain1()
1261 test = Test5(dut, resultfn_9, data=data)
1262 run_simulation(dut, [test.send, test.rcv], vcd_name="test_add2pipe25.vcd")
1263 ports = [dut.p.valid_i, dut.n.i_ready,
1264 dut.n.o_valid, dut.p.ready_o] + \
1265 [dut.p.i_data] + [dut.n.o_data]
1266 vl = rtlil.convert(dut, ports=ports)
1267 with open("test_add2pipe25.il", "w") as f:
1268 f.write(vl)
1269
1270 print ("test 997")
1271 dut = ExampleBufPassThruPipe2()
1272 data = data_chain1()
1273 test = Test5(dut, resultfn_9, data=data)
1274 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpass997.vcd")
1275 ports = [dut.p.valid_i, dut.n.i_ready,
1276 dut.n.o_valid, dut.p.ready_o] + \
1277 [dut.p.i_data] + [dut.n.o_data]
1278 vl = rtlil.convert(dut, ports=ports)
1279 with open("test_bufpass997.il", "w") as f:
1280 f.write(vl)
1281
1282 print ("test 998 (fails, bug)")
1283 dut = ExampleBufPipe3()
1284 data = data_chain1()
1285 test = Test5(dut, resultfn_9, data=data)
1286 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe14.vcd")
1287 ports = [dut.p.valid_i, dut.n.i_ready,
1288 dut.n.o_valid, dut.p.ready_o] + \
1289 [dut.p.i_data] + [dut.n.o_data]
1290 vl = rtlil.convert(dut, ports=ports)
1291 with open("test_bufpipe14.il", "w") as f:
1292 f.write(vl)
1293
1294 print ("test 999 (expected to fail, which is a bug)")
1295 dut = ExampleBufUnBufPipe()
1296 data = data_chain1()
1297 test = Test5(dut, resultfn_9, data=data)
1298 run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufunbuf999.vcd")
1299 ports = [dut.p.valid_i, dut.n.i_ready,
1300 dut.n.o_valid, dut.p.ready_o] + \
1301 [dut.p.i_data] + [dut.n.o_data]
1302 vl = rtlil.convert(dut, ports=ports)
1303 with open("test_bufunbuf999.il", "w") as f:
1304 f.write(vl)
1305