a52964085b929f3405d579d33f4a13943870ce81
[nmutil.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 nmutil.test.example_buf_pipe import ExampleBufPipe, ExampleBufPipeAdd
23 from nmutil.test.example_buf_pipe import ExamplePipeline, UnbufferedPipeline
24 from nmutil.test.example_buf_pipe import ExampleStageCls
25 from nmutil.iocontrol import PrevControl, NextControl
26 from nmutil.stageapi import StageChain, StageCls
27 from nmutil.singlepipe import ControlBase
28 from nmutil.singlepipe import UnbufferedPipeline2
29 from nmutil.singlepipe import SimpleHandshake
30 from nmutil.singlepipe import BufferedHandshake
31 from nmutil.singlepipe import PassThroughHandshake
32 from nmutil.singlepipe import PassThroughStage
33 from nmutil.singlepipe import FIFOControl
34 from nmutil.singlepipe import RecordObject
35 from nmutil.singlepipe import MaskCancellable
36
37 from random import randint, seed
38
39 import unittest
40
41 # seed(4)
42
43
44 def check_o_n_valid(dut, val):
45 o_n_valid = yield dut.n.o_valid
46 assert o_n_valid == val
47
48
49 def check_o_n_valid2(dut, val):
50 o_n_valid = yield dut.n.o_valid
51 assert o_n_valid == val
52
53
54 def tbench(dut):
55 # yield dut.i_p_rst.eq(1)
56 yield dut.n.i_ready.eq(0)
57 # yield dut.p.o_ready.eq(0)
58 yield
59 yield
60 # yield dut.i_p_rst.eq(0)
61 yield dut.n.i_ready.eq(1)
62 yield dut.p.data_i.eq(5)
63 yield dut.p.i_valid.eq(1)
64 yield
65
66 yield dut.p.data_i.eq(7)
67 yield from check_o_n_valid(dut, 0) # effects of i_p_valid delayed
68 yield
69 yield from check_o_n_valid(dut, 1) # ok *now* i_p_valid effect is felt
70
71 yield dut.p.data_i.eq(2)
72 yield
73 # begin going into "stall" (next stage says ready)
74 yield dut.n.i_ready.eq(0)
75 yield dut.p.data_i.eq(9)
76 yield
77 yield dut.p.i_valid.eq(0)
78 yield dut.p.data_i.eq(12)
79 yield
80 yield dut.p.data_i.eq(32)
81 yield dut.n.i_ready.eq(1)
82 yield
83 yield from check_o_n_valid(dut, 1) # buffer still needs to output
84 yield
85 yield from check_o_n_valid(dut, 1) # buffer still needs to output
86 yield
87 yield from check_o_n_valid(dut, 0) # buffer outputted, *now* we're done.
88 yield
89
90
91 def tbench2(dut):
92 # yield dut.p.i_rst.eq(1)
93 yield dut.n.i_ready.eq(0)
94 # yield dut.p.o_ready.eq(0)
95 yield
96 yield
97 # yield dut.p.i_rst.eq(0)
98 yield dut.n.i_ready.eq(1)
99 yield dut.p.data_i.eq(5)
100 yield dut.p.i_valid.eq(1)
101 yield
102
103 yield dut.p.data_i.eq(7)
104 # effects of i_p_valid delayed 2 clocks
105 yield from check_o_n_valid2(dut, 0)
106 yield
107 # effects of i_p_valid delayed 2 clocks
108 yield from check_o_n_valid2(dut, 0)
109
110 yield dut.p.data_i.eq(2)
111 yield
112 yield from check_o_n_valid2(dut, 1) # ok *now* i_p_valid effect is felt
113 # begin going into "stall" (next stage says ready)
114 yield dut.n.i_ready.eq(0)
115 yield dut.p.data_i.eq(9)
116 yield
117 yield dut.p.i_valid.eq(0)
118 yield dut.p.data_i.eq(12)
119 yield
120 yield dut.p.data_i.eq(32)
121 yield dut.n.i_ready.eq(1)
122 yield
123 yield from check_o_n_valid2(dut, 1) # buffer still needs to output
124 yield
125 yield from check_o_n_valid2(dut, 1) # buffer still needs to output
126 yield
127 yield from check_o_n_valid2(dut, 1) # buffer still needs to output
128 yield
129 yield from check_o_n_valid2(dut, 0) # buffer outputted, *now* we're done.
130 yield
131 yield
132 yield
133
134
135 class Test3:
136 def __init__(self, dut, resultfn):
137 self.dut = dut
138 self.resultfn = resultfn
139 self.data = []
140 for i in range(num_tests):
141 #data.append(randint(0, 1<<16-1))
142 self.data.append(i+1)
143 self.i = 0
144 self.o = 0
145
146 def send(self):
147 while self.o != len(self.data):
148 send_range = randint(0, 3)
149 for j in range(randint(1, 10)):
150 if send_range == 0:
151 send = True
152 else:
153 send = randint(0, send_range) != 0
154 o_p_ready = yield self.dut.p.o_ready
155 if not o_p_ready:
156 yield
157 continue
158 if send and self.i != len(self.data):
159 yield self.dut.p.i_valid.eq(1)
160 yield self.dut.p.data_i.eq(self.data[self.i])
161 self.i += 1
162 else:
163 yield self.dut.p.i_valid.eq(0)
164 yield
165
166 def rcv(self):
167 while self.o != len(self.data):
168 stall_range = randint(0, 3)
169 for j in range(randint(1, 10)):
170 stall = randint(0, stall_range) != 0
171 yield self.dut.n.i_ready.eq(stall)
172 yield
173 o_n_valid = yield self.dut.n.o_valid
174 i_n_ready = yield self.dut.n.i_ready_test
175 if not o_n_valid or not i_n_ready:
176 continue
177 data_o = yield self.dut.n.data_o
178 self.resultfn(data_o, self.data[self.o], self.i, self.o)
179 self.o += 1
180 if self.o == len(self.data):
181 break
182
183
184 def resultfn_3(data_o, expected, i, o):
185 assert data_o == expected + 1, \
186 "%d-%d data %x not match %x\n" \
187 % (i, o, data_o, expected)
188
189
190 def data_placeholder():
191 data = []
192 for i in range(num_tests):
193 d = PlaceHolder()
194 d.src1 = randint(0, 1 << 16-1)
195 d.src2 = randint(0, 1 << 16-1)
196 data.append(d)
197 return data
198
199
200 def data_dict():
201 data = []
202 for i in range(num_tests):
203 data.append({'src1': randint(0, 1 << 16-1),
204 'src2': randint(0, 1 << 16-1)})
205 return data
206
207
208 class Test5:
209 def __init__(self, dut, resultfn, data=None, stage_ctl=False):
210 self.dut = dut
211 self.resultfn = resultfn
212 self.stage_ctl = stage_ctl
213 if data:
214 self.data = data
215 else:
216 self.data = []
217 for i in range(num_tests):
218 self.data.append(
219 (randint(0, 1 << 16-1), randint(0, 1 << 16-1)))
220 self.i = 0
221 self.o = 0
222
223 def send(self):
224 while self.o != len(self.data):
225 send_range = randint(0, 3)
226 for j in range(randint(1, 10)):
227 if send_range == 0:
228 send = True
229 else:
230 send = randint(0, send_range) != 0
231 #send = True
232 o_p_ready = yield self.dut.p.o_ready
233 if not o_p_ready:
234 yield
235 continue
236 if send and self.i != len(self.data):
237 yield self.dut.p.i_valid.eq(1)
238 for v in self.dut.set_input(self.data[self.i]):
239 yield v
240 self.i += 1
241 else:
242 yield self.dut.p.i_valid.eq(0)
243 yield
244
245 def rcv(self):
246 while self.o != len(self.data):
247 stall_range = randint(0, 3)
248 for j in range(randint(1, 10)):
249 ready = randint(0, stall_range) != 0
250 #ready = True
251 yield self.dut.n.i_ready.eq(ready)
252 yield
253 o_n_valid = yield self.dut.n.o_valid
254 i_n_ready = yield self.dut.n.i_ready_test
255 if not o_n_valid or not i_n_ready:
256 continue
257 if isinstance(self.dut.n.data_o, Record):
258 data_o = {}
259 dod = self.dut.n.data_o
260 for k, v in dod.fields.items():
261 data_o[k] = yield v
262 else:
263 data_o = yield self.dut.n.data_o
264 self.resultfn(data_o, self.data[self.o], self.i, self.o)
265 self.o += 1
266 if self.o == len(self.data):
267 break
268
269
270 class TestMask:
271 def __init__(self, dut, resultfn, maskwid, data=None, stage_ctl=False,
272 latching=False):
273 self.dut = dut
274 self.resultfn = resultfn
275 self.stage_ctl = stage_ctl
276 self.maskwid = maskwid
277 self.latching = latching
278 self.latchmode = 0
279 if data:
280 self.data = data
281 else:
282 self.data = []
283 for i in range(num_tests):
284 self.data.append(
285 (randint(0, 1 << 16-1), randint(0, 1 << 16-1)))
286 self.i = 0
287 self.o = 0
288
289 def send(self):
290 while self.o != len(self.data):
291 send_range = randint(0, 3)
292 for j in range(randint(1, 10)):
293 if send_range == 0:
294 send = True
295 else:
296 send = randint(0, send_range) != 0
297 #send = True
298 o_p_ready = yield self.dut.p.o_ready
299 if not o_p_ready:
300 yield
301 continue
302
303 if self.latching:
304 latchtest = randint(0, 3) == 0
305 if latchtest:
306 yield self.dut.p.i_valid.eq(0)
307 yield self.dut.p.mask_i.eq(0)
308 # wait for pipeline to flush, then invert state
309 for i in range(10):
310 yield
311 self.latchmode = 1 - self.latchmode
312 yield self.dut.latchmode.eq(self.latchmode)
313 mode = yield self.dut.latchmode
314 print("latching", mode)
315
316 if send and self.i != len(self.data):
317 print("send", self.i, self.data[self.i])
318 yield self.dut.p.i_valid.eq(1)
319 yield self.dut.p.mask_i.eq(1 << self.i) # XXX TODO
320 for v in self.dut.set_input(self.data[self.i]):
321 yield v
322 self.i += 1
323 else:
324 yield self.dut.p.i_valid.eq(0)
325 yield self.dut.p.mask_i.eq(0) # XXX TODO
326 yield
327
328 def rcv(self):
329 while self.o != len(self.data):
330 stall_range = randint(0, 3)
331 for j in range(randint(1, 10)):
332 ready = randint(0, stall_range) != 0
333 ready = True
334 yield self.dut.n.i_ready.eq(ready)
335 yield
336 o_n_valid = yield self.dut.n.o_valid
337 i_n_ready = yield self.dut.n.i_ready_test
338 if not o_n_valid or not i_n_ready:
339 continue
340 if isinstance(self.dut.n.data_o, Record):
341 data_o = {}
342 dod = self.dut.n.data_o
343 for k, v in dod.fields.items():
344 data_o[k] = yield v
345 else:
346 data_o = yield self.dut.n.data_o
347 print("recv", self.o, data_o)
348 self.resultfn(data_o, self.data[self.o], self.i, self.o)
349 self.o += 1
350 if self.o == len(self.data):
351 break
352
353
354 def resultfn_5(data_o, expected, i, o):
355 res = expected[0] + expected[1]
356 assert data_o == res, \
357 "%d-%d data %x not match %s\n" \
358 % (i, o, data_o, repr(expected))
359
360
361 def tbench4(dut):
362 data = []
363 for i in range(num_tests):
364 #data.append(randint(0, 1<<16-1))
365 data.append(i+1)
366 i = 0
367 o = 0
368 while True:
369 stall = randint(0, 3) != 0
370 send = randint(0, 5) != 0
371 yield dut.n.i_ready.eq(stall)
372 o_p_ready = yield dut.p.o_ready
373 if o_p_ready:
374 if send and i != len(data):
375 yield dut.p.i_valid.eq(1)
376 yield dut.p.data_i.eq(data[i])
377 i += 1
378 else:
379 yield dut.p.i_valid.eq(0)
380 yield
381 o_n_valid = yield dut.n.o_valid
382 i_n_ready = yield dut.n.i_ready_test
383 if o_n_valid and i_n_ready:
384 data_o = yield dut.n.data_o
385 assert data_o == data[o] + 2, "%d-%d data %x not match %x\n" \
386 % (i, o, data_o, data[o])
387 o += 1
388 if o == len(data):
389 break
390
391 ######################################################################
392 # Test 2 and 4
393 ######################################################################
394
395
396 class ExampleBufPipe2(ControlBase):
397 """ Example of how to do chained pipeline stages.
398 """
399
400 def elaborate(self, platform):
401 m = ControlBase.elaborate(self, platform)
402
403 pipe1 = ExampleBufPipe()
404 pipe2 = ExampleBufPipe()
405
406 m.submodules.pipe1 = pipe1
407 m.submodules.pipe2 = pipe2
408
409 m.d.comb += self.connect([pipe1, pipe2])
410
411 return m
412
413
414 ######################################################################
415 # Test 9
416 ######################################################################
417
418 class ExampleBufPipeChain2(BufferedHandshake):
419 """ connects two stages together as a *single* combinatorial stage.
420 """
421
422 def __init__(self):
423 stage1 = ExampleStageCls()
424 stage2 = ExampleStageCls()
425 combined = StageChain([stage1, stage2])
426 BufferedHandshake.__init__(self, combined)
427
428
429 def data_chain2():
430 data = []
431 for i in range(num_tests):
432 data.append(randint(0, 1 << 16-2))
433 return data
434
435
436 def resultfn_9(data_o, expected, i, o):
437 res = expected + 2
438 assert data_o == res, \
439 "%d-%d received data %x not match expected %x\n" \
440 % (i, o, data_o, res)
441
442
443 ######################################################################
444 # Test 6 and 10
445 ######################################################################
446
447 class SetLessThan(Elaboratable):
448 def __init__(self, width, signed):
449 self.m = Module()
450 self.src1 = Signal((width, signed), name="src1")
451 self.src2 = Signal((width, signed), name="src2")
452 self.output = Signal(width, name="out")
453
454 def elaborate(self, platform):
455 self.m.d.comb += self.output.eq(Mux(self.src1 < self.src2, 1, 0))
456 return self.m
457
458
459 class LTStage(StageCls):
460 """ module-based stage example
461 """
462
463 def __init__(self):
464 self.slt = SetLessThan(16, True)
465
466 def ispec(self, name):
467 return (Signal(16, name="%s_sig1" % name),
468 Signal(16, name="%s_sig2" % name))
469
470 def ospec(self, name):
471 return Signal(16, name="%s_out" % name)
472
473 def setup(self, m, i):
474 self.o = Signal(16)
475 m.submodules.slt = self.slt
476 m.d.comb += self.slt.src1.eq(i[0])
477 m.d.comb += self.slt.src2.eq(i[1])
478 m.d.comb += self.o.eq(self.slt.output)
479
480 def process(self, i):
481 return self.o
482
483
484 class LTStageDerived(SetLessThan, StageCls):
485 """ special version of a nmigen module where the module is also a stage
486
487 shows that you don't actually need to combinatorially connect
488 to the outputs, or add the module as a submodule: just return
489 the module output parameter(s) from the Stage.process() function
490 """
491
492 def __init__(self):
493 SetLessThan.__init__(self, 16, True)
494
495 def ispec(self):
496 return (Signal(16), Signal(16))
497
498 def ospec(self):
499 return Signal(16)
500
501 def setup(self, m, i):
502 m.submodules.slt = self
503 m.d.comb += self.src1.eq(i[0])
504 m.d.comb += self.src2.eq(i[1])
505
506 def process(self, i):
507 return self.output
508
509
510 class ExampleLTPipeline(UnbufferedPipeline):
511 """ an example of how to use the unbuffered pipeline.
512 """
513
514 def __init__(self):
515 stage = LTStage()
516 UnbufferedPipeline.__init__(self, stage)
517
518
519 class ExampleLTBufferedPipeDerived(BufferedHandshake):
520 """ an example of how to use the buffered pipeline.
521 """
522
523 def __init__(self):
524 stage = LTStageDerived()
525 BufferedHandshake.__init__(self, stage)
526
527
528 def resultfn_6(data_o, expected, i, o):
529 res = 1 if expected[0] < expected[1] else 0
530 assert data_o == res, \
531 "%d-%d data %x not match %s\n" \
532 % (i, o, data_o, repr(expected))
533
534
535 ######################################################################
536 # Test 7
537 ######################################################################
538
539 class ExampleAddRecordStage(StageCls):
540 """ example use of a Record
541 """
542
543 record_spec = [('src1', 16), ('src2', 16)]
544
545 def ispec(self):
546 """ returns a Record using the specification
547 """
548 return Record(self.record_spec)
549
550 def ospec(self):
551 return Record(self.record_spec)
552
553 def process(self, i):
554 """ process the input data, returning a dictionary with key names
555 that exactly match the Record's attributes.
556 """
557 return {'src1': i.src1 + 1,
558 'src2': i.src2 + 1}
559
560 ######################################################################
561 # Test 11
562 ######################################################################
563
564
565 class ExampleAddRecordPlaceHolderStage(StageCls):
566 """ example use of a Record, with a placeholder as the processing result
567 """
568
569 record_spec = [('src1', 16), ('src2', 16)]
570
571 def ispec(self):
572 """ returns a Record using the specification
573 """
574 return Record(self.record_spec)
575
576 def ospec(self):
577 return Record(self.record_spec)
578
579 def process(self, i):
580 """ process the input data, returning a PlaceHolder class instance
581 with attributes that exactly match those of the Record.
582 """
583 o = PlaceHolder()
584 o.src1 = i.src1 + 1
585 o.src2 = i.src2 + 1
586 return o
587
588
589 # a dummy class that may have stuff assigned to instances once created
590 class PlaceHolder:
591 pass
592
593
594 class ExampleAddRecordPipe(UnbufferedPipeline):
595 """ an example of how to use the combinatorial pipeline.
596 """
597
598 def __init__(self):
599 stage = ExampleAddRecordStage()
600 UnbufferedPipeline.__init__(self, stage)
601
602
603 def resultfn_7(data_o, expected, i, o):
604 res = (expected['src1'] + 1, expected['src2'] + 1)
605 assert data_o['src1'] == res[0] and data_o['src2'] == res[1], \
606 "%d-%d data %s not match %s\n" \
607 % (i, o, repr(data_o), repr(expected))
608
609
610 class ExampleAddRecordPlaceHolderPipe(UnbufferedPipeline):
611 """ an example of how to use the combinatorial pipeline.
612 """
613
614 def __init__(self):
615 stage = ExampleAddRecordPlaceHolderStage()
616 UnbufferedPipeline.__init__(self, stage)
617
618
619 def resultfn_11(data_o, expected, i, o):
620 res1 = expected.src1 + 1
621 res2 = expected.src2 + 1
622 assert data_o['src1'] == res1 and data_o['src2'] == res2, \
623 "%d-%d data %s not match %s\n" \
624 % (i, o, repr(data_o), repr(expected))
625
626
627 ######################################################################
628 # Test 8
629 ######################################################################
630
631
632 class Example2OpClass:
633 """ an example of a class used to store 2 operands.
634 requires an eq function, to conform with the pipeline stage API
635 """
636
637 def __init__(self):
638 self.op1 = Signal(16)
639 self.op2 = Signal(16)
640
641 def eq(self, i):
642 return [self.op1.eq(i.op1), self.op2.eq(i.op2)]
643
644
645 class ExampleAddClassStage(StageCls):
646 """ an example of how to use the buffered pipeline, as a class instance
647 """
648
649 def ispec(self):
650 """ returns an instance of an Example2OpClass.
651 """
652 return Example2OpClass()
653
654 def ospec(self):
655 """ returns an output signal which will happen to contain the sum
656 of the two inputs
657 """
658 return Signal(16, name="add2_out")
659
660 def process(self, i):
661 """ process the input data (sums the values in the tuple) and returns it
662 """
663 return i.op1 + i.op2
664
665
666 class ExampleBufPipeAddClass(BufferedHandshake):
667 """ an example of how to use the buffered pipeline, using a class instance
668 """
669
670 def __init__(self):
671 addstage = ExampleAddClassStage()
672 BufferedHandshake.__init__(self, addstage)
673
674
675 class TestInputAdd:
676 """ the eq function, called by set_input, needs an incoming object
677 that conforms to the Example2OpClass.eq function requirements
678 easiest way to do that is to create a class that has the exact
679 same member layout (self.op1, self.op2) as Example2OpClass
680 """
681
682 def __init__(self, op1, op2):
683 self.op1 = op1
684 self.op2 = op2
685
686
687 def resultfn_8(data_o, expected, i, o):
688 res = expected.op1 + expected.op2 # these are a TestInputAdd instance
689 assert data_o == res, \
690 "%d-%d data %s res %x not match %s\n" \
691 % (i, o, repr(data_o), res, repr(expected))
692
693
694 def data_2op():
695 data = []
696 for i in range(num_tests):
697 data.append(TestInputAdd(randint(0, 1 << 16-1), randint(0, 1 << 16-1)))
698 return data
699
700
701 ######################################################################
702 # Test 12
703 ######################################################################
704
705 class ExampleStageDelayCls(StageCls, Elaboratable):
706 """ an example of how to use the buffered pipeline, in a static class
707 fashion
708 """
709
710 def __init__(self, valid_trigger=2):
711 self.count = Signal(2)
712 self.valid_trigger = valid_trigger
713
714 def ispec(self):
715 return Signal(16, name="example_input_signal")
716
717 def ospec(self):
718 return Signal(16, name="example_output_signal")
719
720 @property
721 def d_ready(self):
722 """ data is ready to be accepted when this is true
723 """
724 return (self.count == 1) # | (self.count == 3)
725 return Const(1)
726
727 def d_valid(self, i_ready):
728 """ data is valid at output when this is true
729 """
730 return self.count == self.valid_trigger
731 return Const(1)
732
733 def process(self, i):
734 """ process the input data and returns it (adds 1)
735 """
736 return i + 1
737
738 def elaborate(self, platform):
739 m = Module()
740 m.d.sync += self.count.eq(self.count + 1)
741 return m
742
743
744 class ExampleBufDelayedPipe(BufferedHandshake):
745
746 def __init__(self):
747 stage = ExampleStageDelayCls(valid_trigger=2)
748 BufferedHandshake.__init__(self, stage, stage_ctl=True)
749
750 def elaborate(self, platform):
751 m = BufferedHandshake.elaborate(self, platform)
752 m.submodules.stage = self.stage
753 return m
754
755
756 def data_chain1():
757 data = []
758 for i in range(num_tests):
759 data.append(1 << ((i*3) % 15))
760 #data.append(randint(0, 1<<16-2))
761 #print (hex(data[-1]))
762 return data
763
764
765 def resultfn_12(data_o, expected, i, o):
766 res = expected + 1
767 assert data_o == res, \
768 "%d-%d data %x not match %x\n" \
769 % (i, o, data_o, res)
770
771
772 ######################################################################
773 # Test 13
774 ######################################################################
775
776 class ExampleUnBufDelayedPipe(BufferedHandshake):
777
778 def __init__(self):
779 stage = ExampleStageDelayCls(valid_trigger=3)
780 BufferedHandshake.__init__(self, stage, stage_ctl=True)
781
782 def elaborate(self, platform):
783 m = BufferedHandshake.elaborate(self, platform)
784 m.submodules.stage = self.stage
785 return m
786
787 ######################################################################
788 # Test 15
789 ######################################################################
790
791
792 class ExampleBufModeAdd1Pipe(SimpleHandshake):
793
794 def __init__(self):
795 stage = ExampleStageCls()
796 SimpleHandshake.__init__(self, stage)
797
798
799 ######################################################################
800 # Test 16
801 ######################################################################
802
803 class ExampleBufModeUnBufPipe(ControlBase):
804
805 def elaborate(self, platform):
806 m = ControlBase.elaborate(self, platform)
807
808 pipe1 = ExampleBufModeAdd1Pipe()
809 pipe2 = ExampleBufAdd1Pipe()
810
811 m.submodules.pipe1 = pipe1
812 m.submodules.pipe2 = pipe2
813
814 m.d.comb += self.connect([pipe1, pipe2])
815
816 return m
817
818 ######################################################################
819 # Test 17
820 ######################################################################
821
822
823 class ExampleUnBufAdd1Pipe2(UnbufferedPipeline2):
824
825 def __init__(self):
826 stage = ExampleStageCls()
827 UnbufferedPipeline2.__init__(self, stage)
828
829
830 ######################################################################
831 # Test 18
832 ######################################################################
833
834 class PassThroughTest(PassThroughHandshake):
835
836 def iospecfn(self):
837 return Signal(16, name="out")
838
839 def __init__(self):
840 stage = PassThroughStage(self.iospecfn)
841 PassThroughHandshake.__init__(self, stage)
842
843
844 def resultfn_identical(data_o, expected, i, o):
845 res = expected
846 assert data_o == res, \
847 "%d-%d data %x not match %x\n" \
848 % (i, o, data_o, res)
849
850
851 ######################################################################
852 # Test 19
853 ######################################################################
854
855 class ExamplePassAdd1Pipe(PassThroughHandshake):
856
857 def __init__(self):
858 stage = ExampleStageCls()
859 PassThroughHandshake.__init__(self, stage)
860
861
862 class ExampleBufPassThruPipe(ControlBase):
863
864 def elaborate(self, platform):
865 m = ControlBase.elaborate(self, platform)
866
867 # XXX currently fails: any other permutation works fine.
868 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
869 # also fails using UnbufferedPipeline as well
870 pipe1 = ExampleBufModeAdd1Pipe()
871 pipe2 = ExamplePassAdd1Pipe()
872
873 m.submodules.pipe1 = pipe1
874 m.submodules.pipe2 = pipe2
875
876 m.d.comb += self.connect([pipe1, pipe2])
877
878 return m
879
880
881 ######################################################################
882 # Test 20
883 ######################################################################
884
885 def iospecfn():
886 return Signal(16, name="d_in")
887
888
889 class FIFOTest16(FIFOControl):
890
891 def __init__(self):
892 stage = PassThroughStage(iospecfn)
893 FIFOControl.__init__(self, 2, stage)
894
895
896 ######################################################################
897 # Test 21
898 ######################################################################
899
900 class ExampleFIFOPassThruPipe1(ControlBase):
901
902 def elaborate(self, platform):
903 m = ControlBase.elaborate(self, platform)
904
905 pipe1 = FIFOTest16()
906 pipe2 = FIFOTest16()
907 pipe3 = ExamplePassAdd1Pipe()
908
909 m.submodules.pipe1 = pipe1
910 m.submodules.pipe2 = pipe2
911 m.submodules.pipe3 = pipe3
912
913 m.d.comb += self.connect([pipe1, pipe2, pipe3])
914
915 return m
916
917
918 ######################################################################
919 # Test 22
920 ######################################################################
921
922 class Example2OpRecord(RecordObject):
923 def __init__(self):
924 RecordObject.__init__(self)
925 self.op1 = Signal(16)
926 self.op2 = Signal(16)
927
928
929 class ExampleAddRecordObjectStage(StageCls):
930
931 def ispec(self):
932 """ returns an instance of an Example2OpRecord.
933 """
934 return Example2OpRecord()
935
936 def ospec(self):
937 """ returns an output signal which will happen to contain the sum
938 of the two inputs
939 """
940 return Signal(16)
941
942 def process(self, i):
943 """ process the input data (sums the values in the tuple) and returns it
944 """
945 return i.op1 + i.op2
946
947
948 class ExampleRecordHandshakeAddClass(SimpleHandshake):
949
950 def __init__(self):
951 addstage = ExampleAddRecordObjectStage()
952 SimpleHandshake.__init__(self, stage=addstage)
953
954
955 ######################################################################
956 # Test 23
957 ######################################################################
958
959 def iospecfnrecord():
960 return Example2OpRecord()
961
962
963 class FIFOTestRecordControl(FIFOControl):
964
965 def __init__(self):
966 stage = PassThroughStage(iospecfnrecord)
967 FIFOControl.__init__(self, 2, stage)
968
969
970 class ExampleFIFORecordObjectPipe(ControlBase):
971
972 def elaborate(self, platform):
973 m = ControlBase.elaborate(self, platform)
974
975 pipe1 = FIFOTestRecordControl()
976 pipe2 = ExampleRecordHandshakeAddClass()
977
978 m.submodules.pipe1 = pipe1
979 m.submodules.pipe2 = pipe2
980
981 m.d.comb += self.connect([pipe1, pipe2])
982
983 return m
984
985
986 ######################################################################
987 # Test 24
988 ######################################################################
989
990 class FIFOTestRecordAddStageControl(FIFOControl):
991
992 def __init__(self):
993 stage = ExampleAddRecordObjectStage()
994 FIFOControl.__init__(self, 2, stage)
995
996
997 ######################################################################
998 # Test 25
999 ######################################################################
1000
1001 class FIFOTestAdd16(FIFOControl):
1002
1003 def __init__(self):
1004 stage = ExampleStageCls()
1005 FIFOControl.__init__(self, 2, stage)
1006
1007
1008 class ExampleFIFOAdd2Pipe(ControlBase):
1009
1010 def elaborate(self, platform):
1011 m = ControlBase.elaborate(self, platform)
1012
1013 pipe1 = FIFOTestAdd16()
1014 pipe2 = FIFOTestAdd16()
1015
1016 m.submodules.pipe1 = pipe1
1017 m.submodules.pipe2 = pipe2
1018
1019 m.d.comb += self.connect([pipe1, pipe2])
1020
1021 return m
1022
1023
1024 ######################################################################
1025 # Test 26
1026 ######################################################################
1027
1028 def iospecfn24():
1029 return (Signal(16, name="src1"), Signal(16, name="src2"))
1030
1031
1032 class FIFOTest2x16(FIFOControl):
1033
1034 def __init__(self):
1035 stage = PassThroughStage(iospecfn2)
1036 FIFOControl.__init__(self, 2, stage)
1037
1038
1039 ######################################################################
1040 # Test 997
1041 ######################################################################
1042
1043 class ExampleBufPassThruPipe2(ControlBase):
1044
1045 def elaborate(self, platform):
1046 m = ControlBase.elaborate(self, platform)
1047
1048 # XXX currently fails: any other permutation works fine.
1049 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
1050 # also fails using UnbufferedPipeline as well
1051 #pipe1 = ExampleUnBufAdd1Pipe()
1052 #pipe2 = ExampleBufAdd1Pipe()
1053 pipe1 = ExampleBufAdd1Pipe()
1054 pipe2 = ExamplePassAdd1Pipe()
1055
1056 m.submodules.pipe1 = pipe1
1057 m.submodules.pipe2 = pipe2
1058
1059 m.d.comb += self.connect([pipe1, pipe2])
1060
1061 return m
1062
1063
1064 ######################################################################
1065 # Test 998
1066 ######################################################################
1067
1068 class ExampleBufPipe3(ControlBase):
1069 """ Example of how to do delayed pipeline, where the stage signals
1070 whether it is ready.
1071 """
1072
1073 def elaborate(self, platform):
1074 m = ControlBase.elaborate(self, platform)
1075
1076 pipe1 = ExampleBufDelayedPipe()
1077 pipe2 = ExampleBufPipe()
1078
1079 m.submodules.pipe1 = pipe1
1080 m.submodules.pipe2 = pipe2
1081
1082 m.d.comb += self.connect([pipe1, pipe2])
1083
1084 return m
1085
1086 ######################################################################
1087 # Test 999 - XXX FAILS
1088 # http://bugs.libre-riscv.org/show_bug.cgi?id=57
1089 ######################################################################
1090
1091
1092 class ExampleBufAdd1Pipe(BufferedHandshake):
1093
1094 def __init__(self):
1095 stage = ExampleStageCls()
1096 BufferedHandshake.__init__(self, stage)
1097
1098
1099 class ExampleUnBufAdd1Pipe(UnbufferedPipeline):
1100
1101 def __init__(self):
1102 stage = ExampleStageCls()
1103 UnbufferedPipeline.__init__(self, stage)
1104
1105
1106 class ExampleBufUnBufPipe(ControlBase):
1107
1108 def elaborate(self, platform):
1109 m = ControlBase.elaborate(self, platform)
1110
1111 # XXX currently fails: any other permutation works fine.
1112 # p1=u,p2=b ok p1=u,p2=u ok p1=b,p2=b ok
1113 # also fails using UnbufferedPipeline as well
1114 #pipe1 = ExampleUnBufAdd1Pipe()
1115 #pipe2 = ExampleBufAdd1Pipe()
1116 pipe1 = ExampleBufAdd1Pipe()
1117 pipe2 = ExampleUnBufAdd1Pipe()
1118
1119 m.submodules.pipe1 = pipe1
1120 m.submodules.pipe2 = pipe2
1121
1122 m.d.comb += self.connect([pipe1, pipe2])
1123
1124 return m
1125
1126
1127 ######################################################################
1128 # Test 0
1129 ######################################################################
1130
1131 class ExampleMaskRecord(RecordObject):
1132 """ an example of a class used to store 2 operands.
1133 requires an eq function, to conform with the pipeline stage API
1134 """
1135
1136 def __init__(self):
1137 RecordObject.__init__(self)
1138 self.src1 = Signal(16)
1139 self.src2 = Signal(16)
1140
1141 def __eq(self, i):
1142 return [self.src1.eq(i.src1), self.src2.eq(i.src2)]
1143
1144
1145 class TestInputMask:
1146 """ the eq function, called by set_input, needs an incoming object
1147 that conforms to the Example2OpClass.eq function requirements
1148 easiest way to do that is to create a class that has the exact
1149 same member layout (self.op1, self.op2) as Example2OpClass
1150 """
1151
1152 def __init__(self, src1, src2):
1153 self.src1 = src1
1154 self.src2 = src2
1155
1156 def __repr__(self):
1157 return "<TestInputMask %x %x" % (self.src1, self.src2)
1158
1159
1160 class ExampleMaskCancellable(StageCls):
1161
1162 def ispec(self):
1163 """ returns an instance of an ExampleMaskRecord.
1164 """
1165 return ExampleMaskRecord()
1166
1167 def ospec(self):
1168 """ returns the same
1169 """
1170 return ExampleMaskRecord()
1171
1172 def process(self, i):
1173 """ process the input data: increase op1 and op2
1174 """
1175 return TestInputMask(i.src1 + 1, i.src2 + 1)
1176
1177
1178 class MaskCancellablePipe(MaskCancellable):
1179
1180 """ connects two stages together as a *single* combinatorial stage.
1181 """
1182
1183 def __init__(self, dynamic=False, maskwid=16):
1184 stage1 = ExampleMaskCancellable()
1185 stage2 = ExampleMaskCancellable()
1186 combined = StageChain([stage1, stage2])
1187 MaskCancellable.__init__(self, combined, maskwid, dynamic=dynamic)
1188
1189
1190 class MaskCancellablePipe1(MaskCancellable):
1191
1192 """ connects a stage to a cancellable pipe with "dynamic" mode on.
1193 """
1194
1195 def __init__(self, dynamic=True, maskwid=16):
1196 stage = ExampleMaskCancellable()
1197 MaskCancellable.__init__(self, stage, maskwid, dynamic=dynamic)
1198
1199
1200 class MaskCancellableDynamic(ControlBase):
1201
1202 def __init__(self, maskwid):
1203 self.maskwid = maskwid
1204 ControlBase.__init__(self, None, maskwid=maskwid)
1205
1206 def elaborate(self, platform):
1207 m = ControlBase.elaborate(self, platform)
1208
1209 pipe1 = MaskCancellablePipe1(maskwid=self.maskwid)
1210 pipe2 = MaskCancellablePipe1(maskwid=self.maskwid)
1211
1212 m.submodules.pipe1 = pipe1
1213 m.submodules.pipe2 = pipe2
1214
1215 m.d.comb += self.connect([pipe1, pipe2])
1216
1217 self.latchmode = Signal()
1218 m.d.comb += pipe1.latchmode.eq(self.latchmode)
1219 m.d.comb += pipe2.latchmode.eq(self.latchmode)
1220 #m.d.comb += self.latchmode.eq(1)
1221
1222 return m
1223
1224
1225 def data_chain0(n_tests):
1226 data = []
1227 for i in range(n_tests):
1228 data.append(TestInputMask(randint(0, 1 << 16-1),
1229 randint(0, 1 << 16-1)))
1230 return data
1231
1232
1233 def resultfn_0(data_o, expected, i, o):
1234 assert data_o['src1'] == expected.src1 + 2, \
1235 "src1 %x-%x received data no match\n" \
1236 % (data_o['src1'], expected.src1 + 2)
1237 assert data_o['src2'] == expected.src2 + 2, \
1238 "src2 %x-%x received data no match\n" \
1239 % (data_o['src2'], expected.src2 + 2)
1240
1241
1242 ######################################################################
1243 # Unit Tests
1244 ######################################################################
1245
1246 num_tests = 10
1247
1248
1249 def test0():
1250 maskwid = num_tests
1251 print("test 0")
1252 dut = MaskCancellablePipe(maskwid)
1253 ports = [dut.p.i_valid, dut.n.i_ready,
1254 dut.n.o_valid, dut.p.o_ready] + \
1255 dut.p.data_i.ports() + dut.n.data_o.ports()
1256 vl = rtlil.convert(dut, ports=ports)
1257 with open("test_maskchain0.il", "w") as f:
1258 f.write(vl)
1259 data = data_chain0(maskwid)
1260 test = TestMask(dut, resultfn_0, maskwid, data=data)
1261 run_simulation(dut, [test.send(), test.rcv()],
1262 vcd_name="test_maskchain0.vcd")
1263
1264
1265 def test0_1():
1266 maskwid = 32
1267 print("test 0.1")
1268 dut = MaskCancellableDynamic(maskwid=maskwid)
1269 ports = [dut.p.i_valid, dut.n.i_ready,
1270 dut.n.o_valid, dut.p.o_ready] # + \
1271 #dut.p.data_i.ports() + dut.n.data_o.ports()
1272 vl = rtlil.convert(dut, ports=ports)
1273 with open("test_maskchain0_dynamic.il", "w") as f:
1274 f.write(vl)
1275 data = data_chain0(maskwid)
1276 test = TestMask(dut, resultfn_0, maskwid, data=data, latching=True)
1277 run_simulation(dut, [test.send(), test.rcv()],
1278 vcd_name="test_maskchain0_dynamic.vcd")
1279
1280
1281 def notworking1():
1282 print("test 1")
1283 dut = ExampleBufPipe()
1284 run_simulation(dut, tbench(dut), vcd_name="test_bufpipe.vcd")
1285
1286
1287 def notworking2():
1288 print("test 2")
1289 dut = ExampleBufPipe2()
1290 run_simulation(dut, tbench2(dut), vcd_name="test_bufpipe2.vcd")
1291 ports = [dut.p.i_valid, dut.n.i_ready,
1292 dut.n.o_valid, dut.p.o_ready] + \
1293 [dut.p.data_i] + [dut.n.data_o]
1294 vl = rtlil.convert(dut, ports=ports)
1295 with open("test_bufpipe2.il", "w") as f:
1296 f.write(vl)
1297
1298
1299 def test3():
1300 print("test 3")
1301 dut = ExampleBufPipe()
1302 test = Test3(dut, resultfn_3)
1303 run_simulation(dut, [test.send(), test.rcv()],
1304 vcd_name="test_bufpipe3.vcd")
1305
1306
1307 def test3_5():
1308 print("test 3.5")
1309 dut = ExamplePipeline()
1310 test = Test3(dut, resultfn_3)
1311 run_simulation(dut, [test.send(), test.rcv()],
1312 vcd_name="test_combpipe3.vcd")
1313
1314
1315 def test4():
1316 print("test 4")
1317 dut = ExampleBufPipe2()
1318 run_simulation(dut, tbench4(dut), vcd_name="test_bufpipe4.vcd")
1319
1320
1321 def test5():
1322 print("test 5")
1323 dut = ExampleBufPipeAdd()
1324 test = Test5(dut, resultfn_5, stage_ctl=True)
1325 run_simulation(dut, [test.send(), test.rcv()],
1326 vcd_name="test_bufpipe5.vcd")
1327
1328
1329 def test6():
1330 print("test 6")
1331 dut = ExampleLTPipeline()
1332 test = Test5(dut, resultfn_6)
1333 run_simulation(dut, [test.send(), test.rcv()], vcd_name="test_ltcomb6.vcd")
1334
1335 ports = [dut.p.i_valid, dut.n.i_ready,
1336 dut.n.o_valid, dut.p.o_ready] + \
1337 list(dut.p.data_i) + [dut.n.data_o]
1338 vl = rtlil.convert(dut, ports=ports)
1339 with open("test_ltcomb_pipe.il", "w") as f:
1340 f.write(vl)
1341
1342
1343 def test7():
1344 print("test 7")
1345 dut = ExampleAddRecordPipe()
1346 data = data_dict()
1347 test = Test5(dut, resultfn_7, data=data)
1348 ports = [dut.p.i_valid, dut.n.i_ready,
1349 dut.n.o_valid, dut.p.o_ready,
1350 dut.p.data_i.src1, dut.p.data_i.src2,
1351 dut.n.data_o.src1, dut.n.data_o.src2]
1352 vl = rtlil.convert(dut, ports=ports)
1353 with open("test_recordcomb_pipe.il", "w") as f:
1354 f.write(vl)
1355 run_simulation(dut, [test.send(), test.rcv()],
1356 vcd_name="test_addrecord.vcd")
1357
1358
1359 def test8():
1360 print("test 8")
1361 dut = ExampleBufPipeAddClass()
1362 data = data_2op()
1363 test = Test5(dut, resultfn_8, data=data)
1364 run_simulation(dut, [test.send(), test.rcv()],
1365 vcd_name="test_bufpipe8.vcd")
1366
1367
1368 def test9():
1369 print("test 9")
1370 dut = ExampleBufPipeChain2()
1371 ports = [dut.p.i_valid, dut.n.i_ready,
1372 dut.n.o_valid, dut.p.o_ready] + \
1373 [dut.p.data_i] + [dut.n.data_o]
1374 vl = rtlil.convert(dut, ports=ports)
1375 with open("test_bufpipechain2.il", "w") as f:
1376 f.write(vl)
1377
1378 data = data_chain2()
1379 test = Test5(dut, resultfn_9, data=data)
1380 run_simulation(dut, [test.send(), test.rcv()],
1381 vcd_name="test_bufpipechain2.vcd")
1382
1383
1384 @unittest.skip("broken") # FIXME
1385 def test10():
1386 print("test 10")
1387 dut = ExampleLTBufferedPipeDerived()
1388 test = Test5(dut, resultfn_6)
1389 run_simulation(dut, [test.send(), test.rcv()],
1390 vcd_name="test_ltbufpipe10.vcd")
1391 ports = dut.ports()
1392 vl = rtlil.convert(dut, ports=ports)
1393 with open("test_ltbufpipe10.il", "w") as f:
1394 f.write(vl)
1395
1396
1397 def test11():
1398 print("test 11")
1399 dut = ExampleAddRecordPlaceHolderPipe()
1400 data = data_placeholder()
1401 test = Test5(dut, resultfn_11, data=data)
1402 run_simulation(dut, [test.send(), test.rcv()],
1403 vcd_name="test_addrecord.vcd")
1404
1405
1406 def test12():
1407 print("test 12")
1408 dut = ExampleBufDelayedPipe()
1409 data = data_chain1()
1410 test = Test5(dut, resultfn_12, data=data)
1411 run_simulation(dut, [test.send(), test.rcv()],
1412 vcd_name="test_bufpipe12.vcd")
1413 ports = [dut.p.i_valid, dut.n.i_ready,
1414 dut.n.o_valid, dut.p.o_ready] + \
1415 [dut.p.data_i] + [dut.n.data_o]
1416 vl = rtlil.convert(dut, ports=ports)
1417 with open("test_bufpipe12.il", "w") as f:
1418 f.write(vl)
1419
1420
1421 def test13():
1422 print("test 13")
1423 dut = ExampleUnBufDelayedPipe()
1424 data = data_chain1()
1425 test = Test5(dut, resultfn_12, data=data)
1426 run_simulation(dut, [test.send(), test.rcv()],
1427 vcd_name="test_unbufpipe13.vcd")
1428 ports = [dut.p.i_valid, dut.n.i_ready,
1429 dut.n.o_valid, dut.p.o_ready] + \
1430 [dut.p.data_i] + [dut.n.data_o]
1431 vl = rtlil.convert(dut, ports=ports)
1432 with open("test_unbufpipe13.il", "w") as f:
1433 f.write(vl)
1434
1435
1436 def test15():
1437 print("test 15")
1438 dut = ExampleBufModeAdd1Pipe()
1439 data = data_chain1()
1440 test = Test5(dut, resultfn_12, data=data)
1441 run_simulation(dut, [test.send(), test.rcv()],
1442 vcd_name="test_bufunbuf15.vcd")
1443 ports = [dut.p.i_valid, dut.n.i_ready,
1444 dut.n.o_valid, dut.p.o_ready] + \
1445 [dut.p.data_i] + [dut.n.data_o]
1446 vl = rtlil.convert(dut, ports=ports)
1447 with open("test_bufunbuf15.il", "w") as f:
1448 f.write(vl)
1449
1450
1451 def test16():
1452 print("test 16")
1453 dut = ExampleBufModeUnBufPipe()
1454 data = data_chain1()
1455 test = Test5(dut, resultfn_9, data=data)
1456 run_simulation(dut, [test.send(), test.rcv()],
1457 vcd_name="test_bufunbuf16.vcd")
1458 ports = [dut.p.i_valid, dut.n.i_ready,
1459 dut.n.o_valid, dut.p.o_ready] + \
1460 [dut.p.data_i] + [dut.n.data_o]
1461 vl = rtlil.convert(dut, ports=ports)
1462 with open("test_bufunbuf16.il", "w") as f:
1463 f.write(vl)
1464
1465
1466 def test17():
1467 print("test 17")
1468 dut = ExampleUnBufAdd1Pipe2()
1469 data = data_chain1()
1470 test = Test5(dut, resultfn_12, data=data)
1471 run_simulation(dut, [test.send(), test.rcv()],
1472 vcd_name="test_unbufpipe17.vcd")
1473 ports = [dut.p.i_valid, dut.n.i_ready,
1474 dut.n.o_valid, dut.p.o_ready] + \
1475 [dut.p.data_i] + [dut.n.data_o]
1476 vl = rtlil.convert(dut, ports=ports)
1477 with open("test_unbufpipe17.il", "w") as f:
1478 f.write(vl)
1479
1480
1481 def test18():
1482 print("test 18")
1483 dut = PassThroughTest()
1484 data = data_chain1()
1485 test = Test5(dut, resultfn_identical, data=data)
1486 run_simulation(dut, [test.send(), test.rcv()],
1487 vcd_name="test_passthru18.vcd")
1488 ports = [dut.p.i_valid, dut.n.i_ready,
1489 dut.n.o_valid, dut.p.o_ready] + \
1490 [dut.p.data_i] + [dut.n.data_o]
1491 vl = rtlil.convert(dut, ports=ports)
1492 with open("test_passthru18.il", "w") as f:
1493 f.write(vl)
1494
1495
1496 def test19():
1497 print("test 19")
1498 dut = ExampleBufPassThruPipe()
1499 data = data_chain1()
1500 test = Test5(dut, resultfn_9, data=data)
1501 run_simulation(dut, [test.send(), test.rcv()],
1502 vcd_name="test_bufpass19.vcd")
1503 ports = [dut.p.i_valid, dut.n.i_ready,
1504 dut.n.o_valid, dut.p.o_ready] + \
1505 [dut.p.data_i] + [dut.n.data_o]
1506 vl = rtlil.convert(dut, ports=ports)
1507 with open("test_bufpass19.il", "w") as f:
1508 f.write(vl)
1509
1510
1511 def test20():
1512 print("test 20")
1513 dut = FIFOTest16()
1514 data = data_chain1()
1515 test = Test5(dut, resultfn_identical, data=data)
1516 run_simulation(dut, [test.send(), test.rcv()], vcd_name="test_fifo20.vcd")
1517 ports = [dut.p.i_valid, dut.n.i_ready,
1518 dut.n.o_valid, dut.p.o_ready] + \
1519 [dut.p.data_i] + [dut.n.data_o]
1520 vl = rtlil.convert(dut, ports=ports)
1521 with open("test_fifo20.il", "w") as f:
1522 f.write(vl)
1523
1524
1525 def test21():
1526 print("test 21")
1527 dut = ExampleFIFOPassThruPipe1()
1528 data = data_chain1()
1529 test = Test5(dut, resultfn_12, data=data)
1530 run_simulation(dut, [test.send(), test.rcv()],
1531 vcd_name="test_fifopass21.vcd")
1532 ports = [dut.p.i_valid, dut.n.i_ready,
1533 dut.n.o_valid, dut.p.o_ready] + \
1534 [dut.p.data_i] + [dut.n.data_o]
1535 vl = rtlil.convert(dut, ports=ports)
1536 with open("test_fifopass21.il", "w") as f:
1537 f.write(vl)
1538
1539
1540 def test22():
1541 print("test 22")
1542 dut = ExampleRecordHandshakeAddClass()
1543 data = data_2op()
1544 test = Test5(dut, resultfn_8, data=data)
1545 run_simulation(dut, [test.send(), test.rcv()],
1546 vcd_name="test_addrecord22.vcd")
1547 ports = [dut.p.i_valid, dut.n.i_ready,
1548 dut.n.o_valid, dut.p.o_ready] + \
1549 [dut.p.data_i.op1, dut.p.data_i.op2] + \
1550 [dut.n.data_o]
1551 vl = rtlil.convert(dut, ports=ports)
1552 with open("test_addrecord22.il", "w") as f:
1553 f.write(vl)
1554
1555
1556 def test23():
1557 print("test 23")
1558 dut = ExampleFIFORecordObjectPipe()
1559 data = data_2op()
1560 test = Test5(dut, resultfn_8, data=data)
1561 run_simulation(dut, [test.send(), test.rcv()],
1562 vcd_name="test_addrecord23.vcd")
1563 ports = [dut.p.i_valid, dut.n.i_ready,
1564 dut.n.o_valid, dut.p.o_ready] + \
1565 [dut.p.data_i.op1, dut.p.data_i.op2] + \
1566 [dut.n.data_o]
1567 vl = rtlil.convert(dut, ports=ports)
1568 with open("test_addrecord23.il", "w") as f:
1569 f.write(vl)
1570
1571
1572 def test24():
1573 print("test 24")
1574 dut = FIFOTestRecordAddStageControl()
1575 data = data_2op()
1576 test = Test5(dut, resultfn_8, data=data)
1577 ports = [dut.p.i_valid, dut.n.i_ready,
1578 dut.n.o_valid, dut.p.o_ready] + \
1579 [dut.p.data_i.op1, dut.p.data_i.op2] + \
1580 [dut.n.data_o]
1581 vl = rtlil.convert(dut, ports=ports)
1582 with open("test_addrecord24.il", "w") as f:
1583 f.write(vl)
1584 run_simulation(dut, [test.send(), test.rcv()],
1585 vcd_name="test_addrecord24.vcd")
1586
1587
1588 def test25():
1589 print("test 25")
1590 dut = ExampleFIFOAdd2Pipe()
1591 data = data_chain1()
1592 test = Test5(dut, resultfn_9, data=data)
1593 run_simulation(dut, [test.send(), test.rcv()],
1594 vcd_name="test_add2pipe25.vcd")
1595 ports = [dut.p.i_valid, dut.n.i_ready,
1596 dut.n.o_valid, dut.p.o_ready] + \
1597 [dut.p.data_i] + [dut.n.data_o]
1598 vl = rtlil.convert(dut, ports=ports)
1599 with open("test_add2pipe25.il", "w") as f:
1600 f.write(vl)
1601
1602
1603 def test997():
1604 print("test 997")
1605 dut = ExampleBufPassThruPipe2()
1606 data = data_chain1()
1607 test = Test5(dut, resultfn_9, data=data)
1608 run_simulation(dut, [test.send(), test.rcv()],
1609 vcd_name="test_bufpass997.vcd")
1610 ports = [dut.p.i_valid, dut.n.i_ready,
1611 dut.n.o_valid, dut.p.o_ready] + \
1612 [dut.p.data_i] + [dut.n.data_o]
1613 vl = rtlil.convert(dut, ports=ports)
1614 with open("test_bufpass997.il", "w") as f:
1615 f.write(vl)
1616
1617
1618 @unittest.skip("buggy -- fails due to exceeding step count limit") # FIXME
1619 def test998():
1620 print("test 998 (fails, bug)")
1621 dut = ExampleBufPipe3()
1622 data = data_chain1()
1623 test = Test5(dut, resultfn_9, data=data)
1624 run_simulation(dut, [test.send(), test.rcv()],
1625 vcd_name="test_bufpipe14.vcd")
1626 ports = [dut.p.i_valid, dut.n.i_ready,
1627 dut.n.o_valid, dut.p.o_ready] + \
1628 [dut.p.data_i] + [dut.n.data_o]
1629 vl = rtlil.convert(dut, ports=ports)
1630 with open("test_bufpipe14.il", "w") as f:
1631 f.write(vl)
1632
1633
1634 def test999():
1635 print("test 999 (expected to fail, which is a bug)")
1636 dut = ExampleBufUnBufPipe()
1637 data = data_chain1()
1638 test = Test5(dut, resultfn_9, data=data)
1639 run_simulation(dut, [test.send(), test.rcv()],
1640 vcd_name="test_bufunbuf999.vcd")
1641 ports = [dut.p.i_valid, dut.n.i_ready,
1642 dut.n.o_valid, dut.p.o_ready] + \
1643 [dut.p.data_i] + [dut.n.data_o]
1644 vl = rtlil.convert(dut, ports=ports)
1645 with open("test_bufunbuf999.il", "w") as f:
1646 f.write(vl)
1647
1648
1649 if __name__ == '__main__':
1650 test0()
1651 test0_1()