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
= subtractor
= Subtractor(self
.rwid
)
51 int_alus
= [adder
, subtractor
]
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 # Integer FU-FU Dep Matrix
74 m
.submodules
.intfudeps
= intfudeps
= FUFUDepMatrix(n_int_fus
, n_int_fus
)
76 # Integer FU-Reg Dep Matrix
77 intregdeps
= FUFUDepMatrix(self
.n_regs
, n_int_fus
)
78 m
.submodules
.intregdeps
= intregdeps
80 # Integer Priority Picker 1: Adder + Subtractor
81 intpick1
= GroupPicker(2) # picks between add and sub
82 m
.submodules
.intpick1
= intpick1
84 # Global Pending Vectors (INT and FP)
85 # NOTE: number of vectors is NOT same as number of FUs.
86 g_int_rd_pend_v
= GlobalPending(self
.rwid
, int_rd_pend_v
)
87 g_int_wr_pend_v
= GlobalPending(self
.rwid
, int_wr_pend_v
)
88 m
.submodules
.g_int_rd_pend_v
= g_int_rd_pend_v
89 m
.submodules
.g_int_wr_pend_v
= g_int_wr_pend_v
92 issueunit
= IntFPIssueUnit(self
.rwid
, n_int_fus
, n_fp_fus
)
93 m
.submodules
.issueunit
= issueunit
96 # ok start wiring things together...
97 # "now hear de word of de looord... dem bones dem bones dem dryy bones"
98 # https://www.youtube.com/watch?v=pYb8Wm6-QfA
102 # Issue Unit is where it starts. set up some in/outs for this module
104 m
.d
.comb
+= [issueunit
.i
.store_i
.eq(self
.int_store_i
),
105 issueunit
.i
.dest_i
.eq(self
.int_dest_i
),
106 issueunit
.i
.src1_i
.eq(self
.int_src1_i
),
107 issueunit
.i
.src2_i
.eq(self
.int_src2_i
)
109 self
.int_insn_i
= issueunit
.i
.insn_i
# enabled by instruction decode
111 # connect global rd/wr pending vectors
112 m
.d
.comb
+= issueunit
.i
.g_wr_pend_i
.eq(g_int_wr_pend_v
.g_pend_o
)
113 # TODO: issueunit.f (FP)
115 # and int function issue / busy arrays, and dest/src1/src2
118 for i
, fu
in enumerate(il
):
119 fissue_l
.append(fu
.issue_i
)
120 fbusy_l
.append(fu
.busy_o
)
121 m
.d
.comb
+= fu
.issue_i
.eq(issueunit
.i
.fn_issue_o
[i
])
122 m
.d
.comb
+= fu
.dest_i
.eq(issueunit
.i
.dest_i
)
123 m
.d
.comb
+= fu
.src1_i
.eq(issueunit
.i
.src1_i
)
124 m
.d
.comb
+= fu
.src2_i
.eq(issueunit
.i
.src2_i
)
125 m
.d
.comb
+= issueunit
.i
.busy_i
[i
].eq(fu
.busy_o
)
128 # connect Function Units
131 # Group Picker... done manually for now. TODO: cat array of pick sigs
132 m
.d
.comb
+= il
[0].go_rd_i
.eq(intpick1
.go_rd_o
[0]) # add
133 m
.d
.comb
+= il
[1].go_rd_i
.eq(intpick1
.go_rd_o
[1]) # subtract
134 m
.d
.comb
+= il
[0].go_wr_i
.eq(intpick1
.go_wr_o
[0]) # add
135 m
.d
.comb
+= il
[1].go_wr_i
.eq(intpick1
.go_wr_o
[1]) # subtract
141 yield from self
.intregs
142 yield from self
.fpregs
143 #yield from self.int_src1
144 #yield from self.int_dest
145 #yield from self.int_src1
146 #yield from self.int_src2
147 #yield from self.fp_dest
148 #yield from self.fp_src1
149 #yield from self.fp_src2
155 def scoreboard_sim(dut
):
156 yield dut
.dest_i
.eq(1)
157 yield dut
.issue_i
.eq(1)
159 yield dut
.issue_i
.eq(0)
161 yield dut
.src1_i
.eq(1)
162 yield dut
.issue_i
.eq(1)
166 yield dut
.issue_i
.eq(0)
168 yield dut
.go_read_i
.eq(1)
170 yield dut
.go_read_i
.eq(0)
172 yield dut
.go_write_i
.eq(1)
174 yield dut
.go_write_i
.eq(0)
177 def test_scoreboard():
178 dut
= Scoreboard(32, 8)
179 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
180 with
open("test_scoreboard.il", "w") as f
:
183 run_simulation(dut
, scoreboard_sim(dut
), vcd_name
='test_scoreboard.vcd')
185 if __name__
== '__main__':