1 from nmigen
.compat
.sim
import run_simulation
2 from nmigen
.cli
import verilog
, rtlil
3 from nmigen
import Module
, Signal
, Array
, Cat
, Elaboratable
5 from regfile
.regfile
import RegFileArray
6 from scoreboard
.fn_unit
import IntFnUnit
, FPFnUnit
, LDFnUnit
, STFnUnit
7 from scoreboard
.fu_fu_matrix
import FUFUDepMatrix
8 from scoreboard
.fu_reg_matrix
import FURegDepMatrix
9 from scoreboard
.global_pending
import GlobalPending
10 from scoreboard
.group_picker
import GroupPicker
11 from scoreboard
.issue_unit
import IntFPIssueUnit
14 from alu_hier
import Adder
, Subtractor
16 class Scoreboard(Elaboratable
):
17 def __init__(self
, rwid
, n_regs
):
20 * :rwid: bit width of register file(s) - both FP and INT
21 * :n_regs: depth of register file(s) - number of FP and INT regs
27 self
.intregs
= RegFileArray(rwid
, n_regs
)
28 self
.fpregs
= RegFileArray(rwid
, n_regs
)
31 self
.int_store_i
= Signal(reset_less
=True) # instruction is a store
32 self
.int_dest_i
= Signal(max=n_regs
, reset_less
=True) # Dest R# in
33 self
.int_src1_i
= Signal(max=n_regs
, reset_less
=True) # oper1 R# in
34 self
.int_src2_i
= Signal(max=n_regs
, reset_less
=True) # oper2 R# in
36 def elaborate(self
, platform
):
39 m
.submodules
.intregs
= self
.intregs
40 m
.submodules
.fpregs
= self
.fpregs
43 int_dest
= self
.intregs
.write_port("dest")
44 int_src1
= self
.intregs
.read_port("src1")
45 int_src2
= self
.intregs
.read_port("src2")
47 fp_dest
= self
.fpregs
.write_port("dest")
48 fp_src1
= self
.fpregs
.read_port("src1")
49 fp_src2
= self
.fpregs
.read_port("src2")
52 m
.submodules
.adder
= adder
= Adder(self
.rwid
)
53 m
.submodules
.subtractor
= sub
= Subtractor(self
.rwid
)
54 int_alus
= [adder
, sub
]
60 for i
, a
in enumerate(int_alus
):
61 # set up Integer Function Unit, add to module (and python list)
62 fu
= IntFnUnit(self
.rwid
, shadow_wid
=0)
63 setattr(m
.submodules
, "intfu%d" % i
, fu
)
65 # collate the read/write pending vectors (to go into global pending)
66 int_rd_pend_v
.append(fu
.int_rd_pend_o
)
67 int_wr_pend_v
.append(fu
.int_wr_pend_o
)
70 # Count of number of FUs
72 n_fp_fus
= 0 # for now
74 n_fus
= n_int_fus
+ n_fp_fus
# plus FP FUs
76 # XXX replaced by array of FUs? *FnUnit
77 # # Integer FU-FU Dep Matrix
78 # m.submodules.intfudeps = FUFUDepMatrix(n_int_fus, n_int_fus)
79 # Integer FU-Reg Dep Matrix
80 # intregdeps = FURegDepMatrix(self.n_regs, n_int_fus)
81 # m.submodules.intregdeps = intregdeps
83 # Integer Priority Picker 1: Adder + Subtractor
84 intpick1
= GroupPicker(2) # picks between add and sub
85 m
.submodules
.intpick1
= intpick1
87 # Global Pending Vectors (INT and FP)
88 # NOTE: number of vectors is NOT same as number of FUs.
89 g_int_rd_pend_v
= GlobalPending(self
.rwid
, int_rd_pend_v
)
90 g_int_wr_pend_v
= GlobalPending(self
.rwid
, int_wr_pend_v
)
91 m
.submodules
.g_int_rd_pend_v
= g_int_rd_pend_v
92 m
.submodules
.g_int_wr_pend_v
= g_int_wr_pend_v
95 issueunit
= IntFPIssueUnit(self
.rwid
, n_int_fus
, n_fp_fus
)
96 m
.submodules
.issueunit
= issueunit
99 # ok start wiring things together...
100 # "now hear de word of de looord... dem bones dem bones dem dryy bones"
101 # https://www.youtube.com/watch?v=pYb8Wm6-QfA
105 # Issue Unit is where it starts. set up some in/outs for this module
107 m
.d
.comb
+= [issueunit
.i
.store_i
.eq(self
.int_store_i
),
108 issueunit
.i
.dest_i
.eq(self
.int_dest_i
),
109 issueunit
.i
.src1_i
.eq(self
.int_src1_i
),
110 issueunit
.i
.src2_i
.eq(self
.int_src2_i
)
112 self
.int_insn_i
= issueunit
.i
.insn_i
# enabled by instruction decode
114 # connect global rd/wr pending vectors
115 m
.d
.comb
+= issueunit
.i
.g_wr_pend_i
.eq(g_int_wr_pend_v
.g_pend_o
)
116 # TODO: issueunit.f (FP)
118 # and int function issue / busy arrays, and dest/src1/src2
121 for i
, fu
in enumerate(il
):
122 fissue_l
.append(fu
.issue_i
)
123 fbusy_l
.append(fu
.busy_o
)
124 m
.d
.comb
+= fu
.issue_i
.eq(issueunit
.i
.fn_issue_o
[i
])
125 m
.d
.comb
+= fu
.dest_i
.eq(issueunit
.i
.dest_i
)
126 m
.d
.comb
+= fu
.src1_i
.eq(issueunit
.i
.src1_i
)
127 m
.d
.comb
+= fu
.src2_i
.eq(issueunit
.i
.src2_i
)
128 m
.d
.comb
+= issueunit
.i
.busy_i
[i
].eq(fu
.busy_o
)
131 # connect Function Units
134 # Group Picker... done manually for now. TODO: cat array of pick sigs
135 m
.d
.comb
+= il
[0].go_rd_i
.eq(intpick1
.go_rd_o
[0]) # add rd
136 m
.d
.comb
+= il
[0].go_wr_i
.eq(intpick1
.go_wr_o
[0]) # add wr
137 # TODO m.d.comb += il[0].req_rel_i.eq(adder.ready_o) # pipe out ready
139 m
.d
.comb
+= il
[1].go_rd_i
.eq(intpick1
.go_rd_o
[1]) # subtract rd
140 m
.d
.comb
+= il
[1].go_wr_i
.eq(intpick1
.go_wr_o
[1]) # subtract wr
141 # TODO m.d.comb += il[1].req_rel_i.eq(sub.ready_o) # pipe out ready
143 # Connect INT Fn Unit global wr/rd pending
145 m
.d
.comb
+= fu
.g_int_wr_pend_i
.eq(g_int_wr_pend_v
.g_pend_o
)
146 m
.d
.comb
+= fu
.g_int_rd_pend_i
.eq(g_int_rd_pend_v
.g_pend_o
)
150 # m.d.comb += intpick.req_rel_i[0].eq(add.ready_o) # pipe out ready
151 # m.d.comb += intpick.req_rel_i[1].eq(sub.ready_o) # pipe out ready
152 m
.d
.comb
+= intpick1
.readable_i
[0].eq(il
[0].int_readable_o
) # add rdable
153 m
.d
.comb
+= intpick1
.writable_i
[0].eq(il
[0].int_writable_o
) # add rdable
154 m
.d
.comb
+= intpick1
.readable_i
[1].eq(il
[1].int_readable_o
) # sub rdable
155 m
.d
.comb
+= intpick1
.writable_i
[1].eq(il
[1].int_writable_o
) # sub rdable
158 # Connect Register File(s)
160 m
.d
.comb
+= int_dest
.wen
.eq(g_int_wr_pend_v
.g_pend_o
)
161 m
.d
.comb
+= int_src1
.ren
.eq(g_int_rd_pend_v
.g_pend_o
)
162 m
.d
.comb
+= int_src2
.ren
.eq(g_int_rd_pend_v
.g_pend_o
)
168 yield from self
.intregs
169 yield from self
.fpregs
170 #yield from self.int_src1
171 #yield from self.int_dest
172 #yield from self.int_src1
173 #yield from self.int_src2
174 #yield from self.fp_dest
175 #yield from self.fp_src1
176 #yield from self.fp_src2
182 def scoreboard_sim(dut
):
183 yield dut
.dest_i
.eq(1)
184 yield dut
.issue_i
.eq(1)
186 yield dut
.issue_i
.eq(0)
188 yield dut
.src1_i
.eq(1)
189 yield dut
.issue_i
.eq(1)
193 yield dut
.issue_i
.eq(0)
195 yield dut
.go_read_i
.eq(1)
197 yield dut
.go_read_i
.eq(0)
199 yield dut
.go_write_i
.eq(1)
201 yield dut
.go_write_i
.eq(0)
204 def test_scoreboard():
205 dut
= Scoreboard(32, 8)
206 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
207 with
open("test_scoreboard.il", "w") as f
:
210 run_simulation(dut
, scoreboard_sim(dut
), vcd_name
='test_scoreboard.vcd')
212 if __name__
== '__main__':