1 from nmigen
.compat
.sim
import run_simulation
2 from nmigen
.cli
import verilog
, rtlil
3 from nmigen
import Module
, Signal
, Array
, Elaboratable
5 from scoreboard
.fu_fu_matrix
import FUFUDepMatrix
6 from scoreboard
.mdm
import FUMemMatchMatrix
9 class MemFunctionUnits(Elaboratable
):
11 def __init__(self
, n_ldsts
, addrbitwid
):
12 self
.n_ldsts
= n_ldsts
13 self
.bitwid
= addrbitwid
15 self
.st_i
= Signal(n_ldsts
, reset_less
=True) # Dest R# in
16 self
.ld_i
= Signal(n_ldsts
, reset_less
=True) # oper1 R# in
18 self
.g_int_ld_pend_o
= Signal(n_ldsts
, reset_less
=True)
19 self
.g_int_st_pend_o
= Signal(n_ldsts
, reset_less
=True)
21 self
.st_rsel_o
= Signal(n_ldsts
, reset_less
=True) # dest reg (bot)
22 self
.ld_rsel_o
= Signal(n_ldsts
, reset_less
=True) # src1 reg (bot)
24 self
.loadable_o
= Signal(n_ldsts
, reset_less
=True)
25 self
.storable_o
= Signal(n_ldsts
, reset_less
=True)
27 self
.go_ld_i
= Signal(n_ldsts
, reset_less
=True)
28 self
.go_st_i
= Signal(n_ldsts
, reset_less
=True)
29 self
.go_die_i
= Signal(n_ldsts
, reset_less
=True)
30 self
.fn_issue_i
= Signal(n_ldsts
, reset_less
=True)
33 self
.addrs_i
= Array(Signal(self
.bitwid
, name
="addrs_i%d" % i
) \
34 for i
in range(n_ldsts
))
35 self
.addr_we_i
= Signal(n_ldsts
) # write-enable for incoming address
36 self
.addr_en_i
= Signal(n_ldsts
) # address activated (0 == ignore)
38 # Note: FURegs st_pend_o is also outputted from here, for use in WaWGrid
40 def elaborate(self
, platform
):
47 # Integer FU-FU Dep Matrix
48 intfudeps
= FUFUDepMatrix(n_fus
, n_fus
)
49 m
.submodules
.intfudeps
= intfudeps
50 # Integer FU-Reg Dep Matrix
51 intregdeps
= FUMemMatchMatrix(n_fus
, self
.bitwid
)
52 m
.submodules
.intregdeps
= intregdeps
54 # ok, because we do not know in advance what the AGEN (address gen)
55 # is, we have to make a transitive dependency set. i.e. the LD
56 # (or ST) being requested now must depend on ALL prior LDs *AND* STs.
57 # these get dropped very rapidly once AGEN is carried out.
60 # connect fureg matrix as a mem system
61 comb
+= self
.g_int_ld_pend_o
.eq(intregdeps
.v_rd_rsel_o
)
62 comb
+= self
.g_int_st_pend_o
.eq(intregdeps
.v_wr_rsel_o
)
64 comb
+= intregdeps
.rd_pend_i
.eq(intregdeps
.v_rd_rsel_o
)
65 comb
+= intregdeps
.wr_pend_i
.eq(intregdeps
.v_wr_rsel_o
)
67 comb
+= intfudeps
.rd_pend_i
.eq(intregdeps
.rd_pend_o
)
68 comb
+= intfudeps
.wr_pend_i
.eq(intregdeps
.wr_pend_o
)
69 self
.st_pend_o
= intregdeps
.wr_pend_o
# also output for use in WaWGrid
71 comb
+= intfudeps
.issue_i
.eq(self
.fn_issue_i
)
72 comb
+= intfudeps
.go_rd_i
.eq(self
.go_ld_i
)
73 comb
+= intfudeps
.go_wr_i
.eq(self
.go_st_i
)
74 comb
+= intfudeps
.go_die_i
.eq(self
.go_die_i
)
75 comb
+= self
.loadable_o
.eq(intfudeps
.readable_o
)
76 comb
+= self
.storable_o
.eq(intfudeps
.writable_o
)
78 # Connect function issue / arrays, and dest/src1/src2
79 comb
+= intregdeps
.dest_i
.eq(self
.st_i
)
80 comb
+= intregdeps
.src_i
[0].eq(self
.ld_i
)
82 comb
+= intregdeps
.go_rd_i
.eq(self
.go_ld_i
)
83 comb
+= intregdeps
.go_wr_i
.eq(self
.go_st_i
)
84 comb
+= intregdeps
.go_die_i
.eq(self
.go_die_i
)
85 comb
+= intregdeps
.issue_i
.eq(self
.fn_issue_i
)
87 comb
+= self
.st_rsel_o
.eq(intregdeps
.dest_rsel_o
)
88 comb
+= self
.ld_rsel_o
.eq(intregdeps
.src_rsel_o
[0])
90 # connect address matching: these get connected to the Addr CUs
91 for i
in range(self
.n_ldsts
):
92 comb
+= intregdeps
.addrs_i
[i
].eq(self
.addrs_i
[i
])
93 comb
+= intregdeps
.addr_we_i
.eq(self
.addr_we_i
)
94 comb
+= intregdeps
.addr_en_i
.eq(self
.addr_en_i
)
101 yield self
.g_int_st_pend_o
102 yield self
.g_int_ld_pend_o
105 yield self
.loadable_o
106 yield self
.storable_o
110 yield self
.fn_issue_i
111 yield from self
.addrs_i