1 from nmigen
.compat
.sim
import run_simulation
2 from nmigen
.cli
import verilog
, rtlil
3 from nmigen
import Module
, Signal
, Const
, Elaboratable
, Array
4 from nmutil
.latch
import SRLatch
6 from functools
import reduce
7 from operator
import or_
10 class FUDependenceCell(Elaboratable
):
11 """ implements 11.4.7 mitch alsup dependence cell, p27
13 def __init__(self
, dummy
, n_fu
, n_src
, n_dest
):
17 self
.dummy
= Const(~
(1<<dummy
), n_fu
)
19 self
.rd_pend_i
= Signal(n_fu
, reset_less
=True) # read pend in (left)
20 self
.wr_pend_i
= Signal(n_fu
, reset_less
=True) # write pend in (left)
21 self
.issue_i
= Signal(n_fu
, reset_less
=True) # Issue in (top)
23 # set up go_wr and go_wr array
25 for i
in range(n_src
):
26 j
= i
+ 1 # name numbering to match src1/src2
27 rd
.append(Signal(n_fu
, name
="gord%d_i" % j
, reset_less
=True))
29 for i
in range(n_src
):
30 j
= i
+ 1 # name numbering to match src1/src2
31 wr
.append(Signal(n_fu
, name
="gowr%d_i" % j
, reset_less
=True))
33 self
.go_wr_i
= Array(wr
) # Go Write in (left)
34 self
.go_rd_i
= Array(rd
) # Go Read in (left)
36 self
.go_die_i
= Signal(n_fu
, reset_less
=True) # Go Die in (left)
38 # outputs (latched rd/wr wait)
39 self
.rd_wait_o
= Signal(n_fu
, reset_less
=True) # read wait out (right)
40 self
.wr_wait_o
= Signal(n_fu
, reset_less
=True) # write wait out (right)
42 def elaborate(self
, platform
):
45 # set up rd/wr latches
47 for i
in range(self
.n_src
):
48 rd_l
= SRLatch(sync
=False, name
="rd%d_c" % i
, llen
=self
.n_fu
)
49 setattr(m
.submodules
, "src%d_c" % (i
+1), rd_l
)
52 for i
in range(self
.n_dest
):
53 wr_l
= SRLatch(sync
=False, name
="wr%d_c" % i
, llen
=self
.n_fu
)
54 setattr(m
.submodules
, "dst%d_c" % (i
+1), wr_l
)
57 # reset on go HI, set on dest and issue
59 # connect go_wr / pend
60 for i
in range(self
.n_dest
):
61 m
.d
.comb
+= wr_c
[i
].r
.eq(self
.go_wr_i
[i
] | self
.go_die_i
)
62 m
.d
.comb
+= wr_c
[i
].s
.eq(self
.issue_i
& self
.wr_pend_i
& self
.dummy
)
64 # connect go_rd / pend_i
65 for i
in range(self
.n_src
):
66 m
.d
.comb
+= rd_c
[i
].r
.eq(self
.go_rd_i
[i
] | self
.go_die_i
)
67 m
.d
.comb
+= rd_c
[i
].s
.eq(self
.issue_i
& self
.rd_pend_i
& self
.dummy
)
69 # connect output with OR-reduce (DO NOT USE bool()!)
70 # read-wait (and write-wait) only go off when all GORD (and GOWR) fire
72 for i
in range(self
.n_src
):
73 rd_q
.append(rd_c
[i
].qlq
)
74 m
.d
.comb
+= self
.rd_wait_o
.eq(reduce(or_
, rd_q
) & ~self
.issue_i
)
76 for i
in range(self
.n_dest
):
77 wr_q
.append(wr_c
[i
].qlq
)
78 m
.d
.comb
+= self
.wr_wait_o
.eq(reduce(or_
, wr_q
) & ~self
.issue_i
)
86 yield from self
.go_wr_i
87 yield from self
.go_rd_i
97 yield dut
.dest_i
.eq(1)
98 yield dut
.issue_i
.eq(1)
100 yield dut
.issue_i
.eq(0)
102 yield dut
.src1_i
.eq(1)
103 yield dut
.issue_i
.eq(1)
105 yield dut
.issue_i
.eq(0)
107 yield dut
.go_rd_i
.eq(1)
109 yield dut
.go_rd_i
.eq(0)
111 yield dut
.go_wr_i
.eq(1)
113 yield dut
.go_wr_i
.eq(0)
117 dut
= FUDependenceCell(dummy
=4, n_fu
=4, n_src
=2, n_dest
=2)
118 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
119 with
open("test_fu_dcell.il", "w") as f
:
122 run_simulation(dut
, dcell_sim(dut
), vcd_name
='test_fu_dcell.vcd')
124 if __name__
== '__main__':