6c779a358b8ec4bb7b1f4ffc88cdfc135c2665c5
[soc.git] / src / scoreboard / dependence_cell.py
1 from nmigen.compat.sim import run_simulation
2 from nmigen.cli import verilog, rtlil
3 from nmigen import Module, Signal, Elaboratable, Array, Cat
4 from nmutil.latch import SRLatch
5
6
7 class DependenceCell(Elaboratable):
8 """ implements 11.4.7 mitch alsup dependence cell, p27
9 """
10 def __init__(self):
11 # inputs
12 self.dest_i = Signal(reset_less=True) # Dest in (top)
13 self.src1_i = Signal(reset_less=True) # oper1 in (top)
14 self.src2_i = Signal(reset_less=True) # oper2 in (top)
15 self.issue_i = Signal(reset_less=True) # Issue in (top)
16
17 self.go_wr_i = Signal(reset_less=True) # Go Write in (left)
18 self.go_rd_i = Signal(reset_less=True) # Go Read in (left)
19
20 # for Register File Select Lines (vertical)
21 self.dest_rsel_o = Signal(reset_less=True) # dest reg sel (bottom)
22 self.src1_rsel_o = Signal(reset_less=True) # src1 reg sel (bottom)
23 self.src2_rsel_o = Signal(reset_less=True) # src2 reg sel (bottom)
24
25 # for Function Unit "forward progress" (horizontal)
26 self.dest_fwd_o = Signal(reset_less=True) # dest FU fw (right)
27 self.src1_fwd_o = Signal(reset_less=True) # src1 FU fw (right)
28 self.src2_fwd_o = Signal(reset_less=True) # src2 FU fw (right)
29
30 def elaborate(self, platform):
31 m = Module()
32 m.submodules.dest_l = dest_l = SRLatch(sync=False) # clock-sync'd
33 m.submodules.src1_l = src1_l = SRLatch(sync=False) # clock-sync'd
34 m.submodules.src2_l = src2_l = SRLatch(sync=False) # clock-sync'd
35
36 # destination latch: reset on go_wr HI, set on dest and issue
37 m.d.comb += dest_l.s.eq(self.issue_i & self.dest_i)
38 m.d.comb += dest_l.r.eq(self.go_wr_i)
39
40 # src1 latch: reset on go_rd HI, set on src1_i and issue
41 m.d.comb += src1_l.s.eq(self.issue_i & self.src1_i)
42 m.d.comb += src1_l.r.eq(self.go_rd_i)
43
44 # src2 latch: reset on go_rd HI, set on op2_i and issue
45 m.d.comb += src2_l.s.eq(self.issue_i & self.src2_i)
46 m.d.comb += src2_l.r.eq(self.go_rd_i)
47
48 # FU "Forward Progress" (read out horizontally)
49 m.d.comb += self.dest_fwd_o.eq(dest_l.q & self.go_wr_i)
50 m.d.comb += self.src1_fwd_o.eq(src1_l.q & self.go_rd_i)
51 m.d.comb += self.src2_fwd_o.eq(src2_l.q & self.go_rd_i)
52
53 # Register File Select (read out vertically)
54 m.d.sync += self.dest_rsel_o.eq(dest_l.q & self.dest_i)
55 m.d.sync += self.src1_rsel_o.eq(src1_l.q & self.src1_i)
56 m.d.sync += self.src2_rsel_o.eq(src2_l.q & self.src2_i)
57
58 return m
59
60 def __iter__(self):
61 yield self.dest_i
62 yield self.src1_i
63 yield self.src2_i
64 yield self.issue_i
65 yield self.go_wr_i
66 yield self.go_rd_i
67 yield self.dest_rsel_o
68 yield self.src1_rsel_o
69 yield self.src2_rsel_o
70 yield self.dest_fwd_o
71 yield self.src1_fwd_o
72 yield self.src2_fwd_o
73
74 def ports(self):
75 return list(self)
76
77
78 class DependencyRow(Elaboratable):
79 def __init__(self, n_reg_col):
80 self.n_reg_col = n_reg_col
81
82 # ----
83 # fields all match DependencyCell precisely
84
85 self.dest_i = Signal(n_reg_col, reset_less=True)
86 self.src1_i = Signal(n_reg_col, reset_less=True)
87 self.src2_i = Signal(n_reg_col, reset_less=True)
88
89 self.issue_i = Signal(reset_less=True)
90 self.go_wr_i = Signal(reset_less=True)
91 self.go_rd_i = Signal(reset_less=True)
92
93 self.dest_rsel_o = Signal(n_reg_col, reset_less=True)
94 self.src1_rsel_o = Signal(n_reg_col, reset_less=True)
95 self.src2_rsel_o = Signal(n_reg_col, reset_less=True)
96
97 self.dest_fwd_o = Signal(n_reg_col, reset_less=True)
98 self.src1_fwd_o = Signal(n_reg_col, reset_less=True)
99 self.src2_fwd_o = Signal(n_reg_col, reset_less=True)
100
101 def elaborate(self, platform):
102 m = Module()
103 rcell = Array(DependenceCell() for f in range(self.n_reg_col))
104 for rn in range(self.n_reg_col):
105 setattr(m.submodules, "dm_r%d" % rn, rcell[rn])
106
107 # ---
108 # connect Dep dest/src to module dest/src
109 # ---
110 dest_i = []
111 src1_i = []
112 src2_i = []
113 for rn in range(self.n_reg_col):
114 dc = rcell[rn]
115 # accumulate cell inputs dest/src1/src2
116 dest_i.append(dc.dest_i)
117 src1_i.append(dc.src1_i)
118 src2_i.append(dc.src2_i)
119 # wire up inputs from module to row cell inputs (Cat is gooood)
120 m.d.comb += [Cat(*dest_i).eq(self.dest_i),
121 Cat(*src1_i).eq(self.src1_i),
122 Cat(*src2_i).eq(self.src2_i),
123 ]
124
125 # ---
126 # connect Dep issue_i/go_rd_i/go_wr_i to module issue_i/go_rd/go_wr
127 # ---
128 for rn in range(self.n_reg_col):
129 dc = rcell[rn]
130 m.d.comb += [dc.go_rd_i.eq(self.go_rd_i),
131 dc.go_wr_i.eq(self.go_wr_i),
132 dc.issue_i.eq(self.issue_i),
133 ]
134
135 # ---
136 # connect Function Unit vector
137 # ---
138 dest_fwd_o = []
139 src1_fwd_o = []
140 src2_fwd_o = []
141 for rn in range(self.n_reg_col):
142 dc = rcell[rn]
143 # accumulate cell fwd outputs for dest/src1/src2
144 dest_fwd_o.append(dc.dest_fwd_o)
145 src1_fwd_o.append(dc.src1_fwd_o)
146 src2_fwd_o.append(dc.src2_fwd_o)
147 # connect cell fwd outputs to FU Vector Out [Cat is gooood]
148 m.d.comb += [self.dest_fwd_o.eq(Cat(*dest_fwd_o)),
149 self.src1_fwd_o.eq(Cat(*src1_fwd_o)),
150 self.src2_fwd_o.eq(Cat(*src2_fwd_o))
151 ]
152
153 # ---
154 # connect Reg Selection vector
155 # ---
156 dest_rsel_o = []
157 src1_rsel_o = []
158 src2_rsel_o = []
159 for rn in range(self.n_reg_col):
160 dc = rcell[rn]
161 # accumulate cell reg-select outputs dest/src1/src2
162 dest_rsel_o.append(dc.dest_rsel_o)
163 src1_rsel_o.append(dc.src1_rsel_o)
164 src2_rsel_o.append(dc.src2_rsel_o)
165 # connect cell reg-select outputs to Reg Vector Out
166 m.d.comb += self.dest_rsel_o.eq(Cat(*dest_rsel_o))
167 m.d.comb += self.src1_rsel_o.eq(Cat(*src1_rsel_o))
168 m.d.comb += self.src2_rsel_o.eq(Cat(*src2_rsel_o))
169
170 return m
171
172 def __iter__(self):
173 yield self.dest_i
174 yield self.src1_i
175 yield self.src2_i
176 yield self.issue_i
177 yield self.go_wr_i
178 yield self.go_rd_i
179 yield self.dest_rsel_o
180 yield self.src1_rsel_o
181 yield self.src2_rsel_o
182 yield self.dest_fwd_o
183 yield self.src1_fwd_o
184 yield self.src2_fwd_o
185
186 def ports(self):
187 return list(self)
188
189
190 def dcell_sim(dut):
191 yield dut.dest_i.eq(1)
192 yield dut.issue_i.eq(1)
193 yield
194 yield dut.issue_i.eq(0)
195 yield
196 yield dut.src1_i.eq(1)
197 yield dut.issue_i.eq(1)
198 yield
199 yield
200 yield
201 yield dut.issue_i.eq(0)
202 yield
203 yield dut.go_rd_i.eq(1)
204 yield
205 yield dut.go_rd_i.eq(0)
206 yield
207 yield dut.go_wr_i.eq(1)
208 yield
209 yield dut.go_wr_i.eq(0)
210 yield
211
212 def test_dcell():
213 dut = DependencyRow(4)
214 vl = rtlil.convert(dut, ports=dut.ports())
215 with open("test_drow.il", "w") as f:
216 f.write(vl)
217
218 dut = DependenceCell()
219 vl = rtlil.convert(dut, ports=dut.ports())
220 with open("test_dcell.il", "w") as f:
221 f.write(vl)
222
223 run_simulation(dut, dcell_sim(dut), vcd_name='test_dcell.vcd')
224
225 if __name__ == '__main__':
226 test_dcell()