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