1 """ key strategic example showing how to do multi-input fan-in into a
2 multi-stage pipeline, then multi-output fanout.
4 the multiplex ID from the fan-in is passed in to the pipeline, preserved,
5 and used as a routing ID on the fanout.
8 from random
import randint
9 from nmigen
.compat
.sim
import run_simulation
10 from nmigen
.cli
import verilog
, rtlil
14 def __init__(self
, dut
, width
, fpkls
, fpop
, single_op
=False):
18 self
.single_op
= single_op
23 for muxid
in range(dut
.num_rows
):
26 for i
in range(self
.tlen
):
27 op1
= randint(0, (1<<self
.width
)-1)
28 op2
= randint(0, (1<<self
.width
)-1)
36 #op2 = 0xb4658540 # expect 0x8016147c
40 res
= self
.fpop(self
.fpkls(op1
))
41 self
.di
[muxid
][i
] = (op1
, op2
)
43 res
= self
.fpop(self
.fpkls(op1
), self
.fpkls(op2
))
44 self
.di
[muxid
][i
] = (op1
, op2
)
45 self
.do
[muxid
].append(res
.bits
)
47 def send(self
, muxid
):
48 for i
in range(self
.tlen
):
49 op1
, op2
= self
.di
[muxid
][i
]
50 rs
= self
.dut
.p
[muxid
]
51 yield rs
.valid_i
.eq(1)
52 yield rs
.data_i
.a
.eq(op1
)
53 yield rs
.data_i
.b
.eq(op2
)
54 yield rs
.data_i
.muxid
.eq(muxid
)
56 o_p_ready
= yield rs
.ready_o
59 o_p_ready
= yield rs
.ready_o
62 fop1
= self
.fpkls(op1
)
64 print ("send", muxid
, i
, hex(op1
), hex(res
.bits
),
67 fop1
= self
.fpkls(op1
)
68 fop2
= self
.fpkls(op2
)
69 res
= self
.fpop(fop1
, fop2
)
70 print ("send", muxid
, i
, hex(op1
), hex(op2
), hex(res
.bits
),
73 yield rs
.valid_i
.eq(0)
74 # wait random period of time before queueing another value
75 for i
in range(randint(0, 3)):
78 yield rs
.valid_i
.eq(0)
81 print ("send ended", muxid
)
83 ## wait random period of time before queueing another value
84 #for i in range(randint(0, 3)):
87 #send_range = randint(0, 3)
91 # send = randint(0, send_range) != 0
95 #stall_range = randint(0, 3)
96 #for j in range(randint(1,10)):
97 # stall = randint(0, stall_range) != 0
98 # yield self.dut.n[0].ready_i.eq(stall)
100 n
= self
.dut
.n
[muxid
]
101 yield n
.ready_i
.eq(1)
103 o_n_valid
= yield n
.valid_o
104 i_n_ready
= yield n
.ready_i
105 if not o_n_valid
or not i_n_ready
:
108 out_muxid
= yield n
.data_o
.muxid
109 out_z
= yield n
.data_o
.z
113 print ("recv", out_muxid
, hex(out_z
), "expected",
114 hex(self
.do
[muxid
][out_i
] ))
116 # see if this output has occurred already, delete it if it has
117 assert muxid
== out_muxid
, "out_muxid %d not correct %d" % \
119 assert self
.do
[muxid
][out_i
] == out_z
120 del self
.do
[muxid
][out_i
]
122 # check if there's any more outputs
123 if len(self
.do
[muxid
]) == 0:
125 print ("recv ended", muxid
)
128 def runfp(dut
, width
, name
, fpkls
, fpop
, single_op
=False):
129 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
130 with
open("%s.il" % name
, "w") as f
:
133 test
= InputTest(dut
, width
, fpkls
, fpop
, single_op
)
134 run_simulation(dut
, [test
.rcv(1), test
.rcv(0),
135 test
.rcv(3), test
.rcv(2),
136 test
.send(0), test
.send(1),
137 test
.send(3), test
.send(2),
139 vcd_name
="%s.vcd" % name
)