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
.int_store_i
= Signal(reset_less
=True) # instruction is a store
28 self
.int_dest_i
= Signal(max=n_regs
, reset_less
=True) # Dest R# in
29 self
.int_src1_i
= Signal(max=n_regs
, reset_less
=True) # oper1 R# in
30 self
.int_src2_i
= Signal(max=n_regs
, reset_less
=True) # oper2 R# in
33 self
.intregs
= RegFileArray(rwid
, n_regs
)
34 self
.int_dest
= self
.intregs
.write_port("dest")
35 self
.int_src1
= self
.intregs
.read_port("src1")
36 self
.int_src2
= self
.intregs
.read_port("src2")
38 self
.fpregs
= RegFileArray(rwid
, n_regs
)
39 self
.fp_dest
= self
.fpregs
.write_port("dest")
40 self
.fp_src1
= self
.fpregs
.read_port("src1")
41 self
.fp_src2
= self
.fpregs
.read_port("src2")
43 def elaborate(self
, platform
):
45 m
.submodules
.intregs
= self
.intregs
46 m
.submodules
.fpregs
= self
.fpregs
49 m
.submodules
.adder
= adder
= Adder(self
.rwid
)
50 m
.submodules
.subtractor
= sub
= Subtractor(self
.rwid
)
51 int_alus
= [adder
, sub
]
57 for i
, a
in enumerate(int_alus
):
58 # set up Integer Function Unit, add to module (and python list)
59 fu
= IntFnUnit(self
.rwid
, shadow_wid
=0)
60 setattr(m
.submodules
, "intfu%d" % i
, fu
)
62 # collate the read/write pending vectors (to go into global pending)
63 int_rd_pend_v
.append(fu
.int_rd_pend_o
)
64 int_wr_pend_v
.append(fu
.int_wr_pend_o
)
67 # Count of number of FUs
69 n_fp_fus
= 0 # for now
71 n_fus
= n_int_fus
+ n_fp_fus
# plus FP FUs
73 # XXX replaced by array of FUs? *FnUnit
74 # # Integer FU-FU Dep Matrix
75 # m.submodules.intfudeps = FUFUDepMatrix(n_int_fus, n_int_fus)
77 # Integer FU-Reg Dep Matrix
78 intregdeps
= FURegDepMatrix(self
.n_regs
, n_int_fus
)
79 m
.submodules
.intregdeps
= intregdeps
81 # Integer Priority Picker 1: Adder + Subtractor
82 intpick1
= GroupPicker(2) # picks between add and sub
83 m
.submodules
.intpick1
= intpick1
85 # Global Pending Vectors (INT and FP)
86 # NOTE: number of vectors is NOT same as number of FUs.
87 g_int_rd_pend_v
= GlobalPending(self
.rwid
, int_rd_pend_v
)
88 g_int_wr_pend_v
= GlobalPending(self
.rwid
, int_wr_pend_v
)
89 m
.submodules
.g_int_rd_pend_v
= g_int_rd_pend_v
90 m
.submodules
.g_int_wr_pend_v
= g_int_wr_pend_v
93 issueunit
= IntFPIssueUnit(self
.rwid
, n_int_fus
, n_fp_fus
)
94 m
.submodules
.issueunit
= issueunit
97 # ok start wiring things together...
98 # "now hear de word of de looord... dem bones dem bones dem dryy bones"
99 # https://www.youtube.com/watch?v=pYb8Wm6-QfA
103 # Issue Unit is where it starts. set up some in/outs for this module
105 m
.d
.comb
+= [issueunit
.i
.store_i
.eq(self
.int_store_i
),
106 issueunit
.i
.dest_i
.eq(self
.int_dest_i
),
107 issueunit
.i
.src1_i
.eq(self
.int_src1_i
),
108 issueunit
.i
.src2_i
.eq(self
.int_src2_i
)
110 self
.int_insn_i
= issueunit
.i
.insn_i
# enabled by instruction decode
112 # connect global rd/wr pending vectors
113 m
.d
.comb
+= issueunit
.i
.g_wr_pend_i
.eq(g_int_wr_pend_v
.g_pend_o
)
114 # TODO: issueunit.f (FP)
116 # and int function issue / busy arrays, and dest/src1/src2
119 for i
, fu
in enumerate(il
):
120 fissue_l
.append(fu
.issue_i
)
121 fbusy_l
.append(fu
.busy_o
)
122 m
.d
.comb
+= fu
.issue_i
.eq(issueunit
.i
.fn_issue_o
[i
])
123 m
.d
.comb
+= fu
.dest_i
.eq(issueunit
.i
.dest_i
)
124 m
.d
.comb
+= fu
.src1_i
.eq(issueunit
.i
.src1_i
)
125 m
.d
.comb
+= fu
.src2_i
.eq(issueunit
.i
.src2_i
)
126 m
.d
.comb
+= issueunit
.i
.busy_i
[i
].eq(fu
.busy_o
)
129 # connect Function Units
132 # Group Picker... done manually for now. TODO: cat array of pick sigs
133 m
.d
.comb
+= il
[0].go_rd_i
.eq(intpick1
.go_rd_o
[0]) # add rd
134 m
.d
.comb
+= il
[0].go_wr_i
.eq(intpick1
.go_wr_o
[0]) # add wr
135 # TODO m.d.comb += il[0].req_rel_i.eq(adder.ready_o) # pipe out ready
137 m
.d
.comb
+= il
[1].go_rd_i
.eq(intpick1
.go_rd_o
[1]) # subtract rd
138 m
.d
.comb
+= il
[1].go_wr_i
.eq(intpick1
.go_wr_o
[1]) # subtract wr
139 # TODO m.d.comb += il[1].req_rel_i.eq(sub.ready_o) # pipe out ready
141 # Connect INT Fn Unit global wr/rd pending
143 m
.d
.comb
+= fu
.g_int_wr_pend_i
.eq(g_int_wr_pend_v
.g_pend_o
)
144 m
.d
.comb
+= fu
.g_int_rd_pend_i
.eq(g_int_rd_pend_v
.g_pend_o
)
148 # m.d.comb += intpick.req_rel_i[0].eq(add.ready_o) # pipe out ready
149 # m.d.comb += intpick.req_rel_i[1].eq(sub.ready_o) # pipe out ready
150 m
.d
.comb
+= intpick1
.readable_i
[0].eq(il
[0].int_readable_o
) # add rdable
151 m
.d
.comb
+= intpick1
.writable_i
[0].eq(il
[0].int_writable_o
) # add rdable
152 m
.d
.comb
+= intpick1
.readable_i
[1].eq(il
[1].int_readable_o
) # sub rdable
153 m
.d
.comb
+= intpick1
.writable_i
[1].eq(il
[1].int_writable_o
) # sub rdable
159 yield from self
.intregs
160 yield from self
.fpregs
161 #yield from self.int_src1
162 #yield from self.int_dest
163 #yield from self.int_src1
164 #yield from self.int_src2
165 #yield from self.fp_dest
166 #yield from self.fp_src1
167 #yield from self.fp_src2
173 def scoreboard_sim(dut
):
174 yield dut
.dest_i
.eq(1)
175 yield dut
.issue_i
.eq(1)
177 yield dut
.issue_i
.eq(0)
179 yield dut
.src1_i
.eq(1)
180 yield dut
.issue_i
.eq(1)
184 yield dut
.issue_i
.eq(0)
186 yield dut
.go_read_i
.eq(1)
188 yield dut
.go_read_i
.eq(0)
190 yield dut
.go_write_i
.eq(1)
192 yield dut
.go_write_i
.eq(0)
195 def test_scoreboard():
196 dut
= Scoreboard(32, 8)
197 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
198 with
open("test_scoreboard.il", "w") as f
:
201 run_simulation(dut
, scoreboard_sim(dut
), vcd_name
='test_scoreboard.vcd')
203 if __name__
== '__main__':