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
, vals
, single_op
):
18 self
.single_op
= single_op
21 self
.tlen
= len(vals
) // dut
.num_rows
23 for muxid
in range(dut
.num_rows
):
26 for i
in range(self
.tlen
):
29 res
= self
.fpop(self
.fpkls(op1
))
30 self
.di
[muxid
][i
] = (op1
, )
32 (op1
, op2
, ) = vals
.pop(0)
33 res
= self
.fpop(self
.fpkls(op1
), self
.fpkls(op2
))
34 self
.di
[muxid
][i
] = (op1
, op2
)
35 self
.do
[muxid
].append(res
.bits
)
37 def send(self
, muxid
):
38 for i
in range(self
.tlen
):
40 op1
, = self
.di
[muxid
][i
]
42 op1
, op2
= self
.di
[muxid
][i
]
43 rs
= self
.dut
.p
[muxid
]
44 yield rs
.valid_i
.eq(1)
45 yield rs
.data_i
.a
.eq(op1
)
46 if not self
.single_op
:
47 yield rs
.data_i
.b
.eq(op2
)
48 yield rs
.data_i
.muxid
.eq(muxid
)
50 o_p_ready
= yield rs
.ready_o
53 o_p_ready
= yield rs
.ready_o
56 fop1
= self
.fpkls(op1
)
58 print ("send", muxid
, i
, hex(op1
), hex(res
.bits
),
61 fop1
= self
.fpkls(op1
)
62 fop2
= self
.fpkls(op2
)
63 res
= self
.fpop(fop1
, fop2
)
64 print ("send", muxid
, i
, hex(op1
), hex(op2
), hex(res
.bits
),
67 yield rs
.valid_i
.eq(0)
68 # wait random period of time before queueing another value
69 for i
in range(randint(0, 3)):
72 yield rs
.valid_i
.eq(0)
75 print ("send ended", muxid
)
77 ## wait random period of time before queueing another value
78 #for i in range(randint(0, 3)):
81 #send_range = randint(0, 3)
85 # send = randint(0, send_range) != 0
89 #stall_range = randint(0, 3)
90 #for j in range(randint(1,10)):
91 # stall = randint(0, stall_range) != 0
92 # yield self.dut.n[0].ready_i.eq(stall)
97 o_n_valid
= yield n
.valid_o
98 i_n_ready
= yield n
.ready_i
99 if not o_n_valid
or not i_n_ready
:
102 out_muxid
= yield n
.data_o
.muxid
103 out_z
= yield n
.data_o
.z
107 print ("recv", out_muxid
, hex(out_z
), "expected",
108 hex(self
.do
[muxid
][out_i
] ))
110 # see if this output has occurred already, delete it if it has
111 assert muxid
== out_muxid
, "out_muxid %d not correct %d" % \
113 assert self
.do
[muxid
][out_i
] == out_z
114 del self
.do
[muxid
][out_i
]
116 # check if there's any more outputs
117 if len(self
.do
[muxid
]) == 0:
119 print ("recv ended", muxid
)
122 class InputTestRandom(InputTest
):
123 def __init__(self
, dut
, width
, fpkls
, fpop
, single_op
=False, n_vals
=10):
125 for muxid
in range(dut
.num_rows
):
126 for i
in range(n_vals
):
128 op1
= randint(0, (1<<width
)-1)
131 op1
= randint(0, (1<<width
)-1)
132 op2
= randint(0, (1<<width
)-1)
133 vals
.append((op1
, op2
,))
135 InputTest
.__init
__(self
, dut
, width
, fpkls
, fpop
, vals
, single_op
)
138 def runfp(dut
, width
, name
, fpkls
, fpop
, single_op
=False, n_vals
=10):
139 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
140 with
open("%s.il" % name
, "w") as f
:
143 test
= InputTestRandom(dut
, width
, fpkls
, fpop
, single_op
, n_vals
)
144 run_simulation(dut
, [test
.rcv(1), test
.rcv(0),
145 test
.rcv(3), test
.rcv(2),
146 test
.send(0), test
.send(1),
147 test
.send(3), test
.send(2),
149 vcd_name
="%s.vcd" % name
)