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