disable fpissue
[soc.git] / src / scoreboard / issue_unit.py
1 from nmigen.compat.sim import run_simulation
2 from nmigen.cli import verilog, rtlil
3 from nmigen import Module, Signal, Cat, Array, Const, Record, Elaboratable
4 from nmutil.latch import SRLatch
5 from nmigen.lib.coding import Decoder
6
7 from .shadow_fn import ShadowFn
8
9
10 class IssueUnit(Elaboratable):
11 """ implements 11.4.14 issue unit, p50
12
13 Inputs
14
15 * :wid: register file width
16 * :n_insns: number of instructions in this issue unit.
17 """
18 def __init__(self, wid, n_insns):
19 self.reg_width = wid
20 self.n_insns = n_insns
21
22 # inputs
23 self.store_i = Signal(reset_less=True) # instruction is a store
24 self.dest_i = Signal(max=wid, reset_less=True) # Dest R# in
25 self.src1_i = Signal(max=wid, reset_less=True) # oper1 R# in
26 self.src2_i = Signal(max=wid, reset_less=True) # oper2 R# in
27
28 self.g_wr_pend_i = Signal(wid, reset_less=True) # write pending vector
29
30 self.insn_i = Array(Signal(reset_less=True, name="insn_i") \
31 for i in range(n_insns))
32 self.busy_i = Array(Signal(reset_less=True, name="busy_i") \
33 for i in range(n_insns))
34
35 # outputs
36 self.fn_issue_o = Array(Signal(reset_less=True, name="fn_issue_o") \
37 for i in range(n_insns))
38 self.g_issue_o = Signal(reset_less=True)
39
40 def elaborate(self, platform):
41 m = Module()
42 m.submodules.dest_d = dest_d = Decoder(self.reg_width)
43
44 if self.n_insns == 0:
45 return m
46
47 # temporaries
48 waw_stall = Signal(reset_less=True)
49 fu_stall = Signal(reset_less=True)
50 pend = Signal(self.reg_width, reset_less=True)
51
52 # dest decoder: write-pending
53 m.d.comb += dest_d.i.eq(self.dest_i)
54 m.d.comb += dest_d.n.eq(~self.store_i) # decode is inverted
55 m.d.comb += pend.eq(dest_d.o & self.g_wr_pend_i)
56 m.d.comb += waw_stall.eq(pend.bool())
57
58 ib_l = []
59 for i in range(self.n_insns):
60 ib_l.append(self.insn_i[i] & self.busy_i[i])
61 m.d.comb += fu_stall.eq(Cat(*ib_l).bool())
62 m.d.comb += self.g_issue_o.eq(~(waw_stall | fu_stall))
63 for i in range(self.n_insns):
64 m.d.comb += self.fn_issue_o[i].eq(self.g_issue_o & self.insn_i[i])
65
66 return m
67
68 def __iter__(self):
69 yield self.store_i
70 yield self.dest_i
71 yield self.src1_i
72 yield self.src2_i
73 yield self.g_wr_pend_i
74 yield from self.insn_i
75 yield from self.busy_i
76 yield from self.fn_issue_o
77 yield self.g_issue_o
78
79 def ports(self):
80 return list(self)
81
82
83 class IntFPIssueUnit(Elaboratable):
84 def __init__(self, wid, n_int_insns, n_fp_insns):
85 self.i = IssueUnit(wid, n_int_insns)
86 self.f = IssueUnit(wid, n_fp_insns)
87 self.issue_o = Signal(reset_less=True)
88
89 # some renames
90 self.int_write_pending_i = self.i.g_wr_pend_i
91 self.fp_write_pending_i = self.f.g_wr_pend_i
92 self.int_write_pending_i.name = 'int_write_pending_i'
93 self.fp_write_pending_i.name = 'fp_write_pending_i'
94
95 def elaborate(self, platform):
96 m = Module()
97 m.submodules.intissue = self.i
98 m.submodules.fpissue = self.f
99
100 m.d.comb += self.issue_o.eq(self.i.g_issue_o | self.f.g_issue_o)
101
102 return m
103
104 def ports(self):
105 yield self.issue_o
106 yield from self.i
107 yield from self.f
108
109
110 def issue_unit_sim(dut):
111 yield dut.dest_i.eq(1)
112 yield dut.issue_i.eq(1)
113 yield
114 yield dut.issue_i.eq(0)
115 yield
116 yield dut.src1_i.eq(1)
117 yield dut.issue_i.eq(1)
118 yield
119 yield
120 yield
121 yield dut.issue_i.eq(0)
122 yield
123 yield dut.go_rd_i.eq(1)
124 yield
125 yield dut.go_rd_i.eq(0)
126 yield
127 yield dut.go_wr_i.eq(1)
128 yield
129 yield dut.go_wr_i.eq(0)
130 yield
131
132 def test_issue_unit():
133 dut = IssueUnit(32, 3)
134 vl = rtlil.convert(dut, ports=dut.ports())
135 with open("test_issue_unit.il", "w") as f:
136 f.write(vl)
137
138 dut = IntFPIssueUnit(32, 3, 3)
139 vl = rtlil.convert(dut, ports=dut.ports())
140 with open("test_intfp_issue_unit.il", "w") as f:
141 f.write(vl)
142
143 run_simulation(dut, issue_unit_sim(dut), vcd_name='test_issue_unit.vcd')
144
145 if __name__ == '__main__':
146 test_issue_unit()