add hazard vectors to Regfiles
[soc.git] / src / soc / regfile / regfiles.py
1 # POWER9 Register Files
2 """POWER9 regfiles
3
4 Defines the following register files:
5
6 * INT regfile - 32x 64-bit
7 * SPR regfile - 110x 64-bit
8 * CR regfile - CR0-7
9 * XER regfile - XER.so, XER.ca/ca32, XER.ov/ov32
10 * FAST regfile - CTR, LR, TAR, SRR1, SRR2
11 * STATE regfile - PC, MSR, (SimpleV VL later)
12
13 Note: this should NOT have name conventions hard-coded (dedicated ports per
14 regname). However it is convenient for now.
15
16 Links:
17
18 * https://bugs.libre-soc.org/show_bug.cgi?id=345
19 * https://bugs.libre-soc.org/show_bug.cgi?id=351
20 * https://libre-soc.org/3d_gpu/architecture/regfile/
21 * https://libre-soc.org/openpower/isatables/sprs.csv
22 * https://libre-soc.org/openpower/sv/sprs/ (SVSTATE)
23 """
24
25 # TODO
26
27 from soc.regfile.regfile import RegFile, RegFileArray, RegFileMem
28 from soc.regfile.virtual_port import VirtualRegPort
29 from openpower.decoder.power_enums import SPRfull, SPRreduced
30
31 # XXX MAKE DAMN SURE TO KEEP THESE UP-TO-DATE if changing/adding regs
32 from openpower.consts import StateRegsEnum, XERRegsEnum, FastRegsEnum
33
34 from nmigen import Module
35 from nmigen.cli import rtlil
36
37
38 # "State" Regfile
39 class StateRegs(RegFileArray, StateRegsEnum):
40 """StateRegs
41
42 State regfile - PC, MSR, SVSTATE (for SimpleV)
43
44 * QTY 3of 64-bit registers
45 * 4R3W
46 * Array-based unary-indexed (not binary-indexed)
47 * write-through capability (read on same cycle as write)
48
49 Note: d_wr1 d_rd1 are for use by the decoder, to get at the PC.
50 will probably have to also add one so it can get at the MSR as well.
51 (d_rd2)
52
53 """
54 def __init__(self, svp64_en=False, regreduce_en=False):
55 super().__init__(64, StateRegsEnum.N_REGS)
56 self.w_ports = {'nia': self.write_port("nia"),
57 'msr': self.write_port("msr"),
58 'svstate': self.write_port("svstate"),
59 'sv': self.write_port("sv"), # writing SVSTATE (issuer)
60 'd_wr1': self.write_port("d_wr1")} # writing PC (issuer)
61 self.r_ports = {'cia': self.read_port("cia"), # reading PC (issuer)
62 'msr': self.read_port("msr"), # reading MSR (issuer)
63 'sv': self.read_port("sv"), # reading SV (issuer)
64 }
65
66
67 # Integer Regfile
68 class IntRegs(RegFileMem): #class IntRegs(RegFileArray):
69 """IntRegs
70
71 * QTY 32of 64-bit registers
72 * 3R2W
73 * Array-based unary-indexed (not binary-indexed)
74 * write-through capability (read on same cycle as write)
75 """
76 def __init__(self, svp64_en=False, regreduce_en=False):
77 super().__init__(64, 32, fwd_bus_mode=not regreduce_en)
78 self.w_ports = {'o': self.write_port("dest1"),
79 }
80 self.r_ports = {
81 'dmi': self.read_port("dmi")} # needed for Debug (DMI)
82 if svp64_en:
83 self.r_ports['pred'] = self.read_port("pred") # for predicate mask
84 if not regreduce_en:
85 self.w_ports['o1'] = self.write_port("dest2") # (LD/ST update)
86 self.r_ports['ra'] = self.read_port("src1")
87 self.r_ports['rb'] = self.read_port("src2")
88 self.r_ports['rc'] = self.read_port("src3")
89 else:
90 self.r_ports['rabc'] = self.read_port("src1")
91
92
93 # Fast SPRs Regfile
94 class FastRegs(RegFileMem, FastRegsEnum): #RegFileArray):
95 """FastRegs
96
97 FAST regfile - CTR, LR, TAR, SRR1, SRR2, XER, TB, DEC, SVSRR0
98
99 * QTY 6of 64-bit registers
100 * 3R2W
101 * Array-based unary-indexed (not binary-indexed)
102 * write-through capability (read on same cycle as write)
103
104 Note: r/w issue are used by issuer to increment/decrement TB/DEC.
105 """
106 def __init__(self, svp64_en=False, regreduce_en=False):
107 super().__init__(64, FastRegsEnum.N_REGS, fwd_bus_mode=not regreduce_en)
108 self.w_ports = {'fast1': self.write_port("dest1"),
109 'issue': self.write_port("issue"), # writing DEC/TB
110 }
111 self.r_ports = {'fast1': self.read_port("src1"),
112 'issue': self.read_port("issue"), # reading DEC/TB
113 }
114 if not regreduce_en:
115 self.r_ports['fast2'] = self.read_port("src2")
116
117
118 # CR Regfile
119 class CRRegs(VirtualRegPort):
120 """Condition Code Registers (CR0-7)
121
122 * QTY 8of 8-bit registers
123 * 3R1W 4-bit-wide with additional 1R1W for the "full" 32-bit width
124 * Array-based unary-indexed (not binary-indexed)
125 * write-through capability (read on same cycle as write)
126 """
127 def __init__(self, svp64_en=False, regreduce_en=False):
128 super().__init__(32, 8, rd2=True)
129 self.w_ports = {'full_cr': self.full_wr, # 32-bit (masked, 8-en lines)
130 'cr_a': self.write_port("dest1"), # 4-bit, unary-indexed
131 'cr_b': self.write_port("dest2")} # 4-bit, unary-indexed
132 self.r_ports = {'full_cr': self.full_rd, # 32-bit (masked, 8-en lines)
133 'full_cr_dbg': self.full_rd2, # for DMI
134 'cr_a': self.read_port("src1"),
135 'cr_b': self.read_port("src2"),
136 'cr_c': self.read_port("src3")}
137 if svp64_en:
138 self.r_ports['cr_pred'] = self.read_port("cr_pred") # for predicate
139
140
141 # XER Regfile
142 class XERRegs(VirtualRegPort, XERRegsEnum):
143 """XER Registers (SO, CA/CA32, OV/OV32)
144
145 * QTY 3of 2-bit registers
146 * 3R3W 2-bit-wide with additional 1R1W for the "full" 6-bit width
147 * Array-based unary-indexed (not binary-indexed)
148 * write-through capability (read on same cycle as write)
149 """
150 SO=0 # this is actually 2-bit but we ignore 1 bit of it
151 CA=1 # CA and CA32
152 OV=2 # OV and OV32
153 def __init__(self, svp64_en=False, regreduce_en=False):
154 super().__init__(6, XERRegsEnum.N_REGS)
155 self.w_ports = {'full_xer': self.full_wr, # 6-bit (masked, 3-en lines)
156 'xer_so': self.write_port("dest1"),
157 'xer_ca': self.write_port("dest2"),
158 'xer_ov': self.write_port("dest3")}
159 self.r_ports = {'full_xer': self.full_rd, # 6-bit (masked, 3-en lines)
160 'xer_so': self.read_port("src1"),
161 'xer_ca': self.read_port("src2"),
162 'xer_ov': self.read_port("src3")}
163
164
165 # SPR Regfile
166 class SPRRegs(RegFileMem):
167 """SPRRegs
168
169 * QTY len(SPRs) 64-bit registers
170 * 1R1W
171 * binary-indexed but REQUIRES MAPPING
172 * write-through capability (read on same cycle as write)
173 """
174 def __init__(self, svp64_en=False, regreduce_en=False):
175 if regreduce_en:
176 n_sprs = len(SPRreduced)
177 else:
178 n_sprs = len(SPRfull)
179 super().__init__(width=64, depth=n_sprs,
180 fwd_bus_mode=not regreduce_en)
181 self.w_ports = {'spr1': self.write_port("spr1")}
182 self.r_ports = {'spr1': self.read_port("spr1")}
183
184
185 # class containing all regfiles: int, cr, xer, fast, spr
186 class RegFiles:
187 def __init__(self, pspec, make_hazard_vecs=False):
188 # test is SVP64 is to be enabled
189 svp64_en = hasattr(pspec, "svp64") and (pspec.svp64 == True)
190
191 # and regfile port reduction
192 regreduce_en = hasattr(pspec, "regreduce") and \
193 (pspec.regreduce == True)
194
195 self.rf = {} # register file dict
196 self.wv = {} # global write vectors
197 self.rv = {} # global read vectors
198 # create regfiles here, Factory style
199 for (name, kls) in [('int', IntRegs),
200 ('cr', CRRegs),
201 ('xer', XERRegs),
202 ('fast', FastRegs),
203 ('state', StateRegs),
204 ('spr', SPRRegs),]:
205 rf = self.rf[name] = kls(svp64_en, regreduce_en)
206 # also add these as instances, self.state, self.fast, self.cr etc.
207 setattr(self, name, rf)
208
209 # create a read-hazard and write-hazard vectors for this regfile
210 if make_hazard_vecs:
211 self.rv[name] = self.make_hazard_vec(rf, "rd")
212 self.wv[name] = self.make_hazard_vec(rf, "wr")
213
214 def make_hazard_vec(self, rf, name):
215 if isinstance(rf, VirtualRegPort):
216 vec = RegFileArray(rf.bitwidth, 1)
217 else:
218 vec = RegFileArray(rf.depth, 1)
219 if name in ['int', 'cr', 'xer']:
220 n_wrs = 3
221 elif name in ['fast']:
222 n_wrs = 2
223 else:
224 n_wrs = 1
225 # add write ports
226 vec.w_ports = {}
227 for i in range(n_wrs):
228 pname = "wr%d" % i
229 vec.w_ports[pname] = vec.write_port("%s_%s" % (name, pname))
230 # add read port
231 vec.r_ports = {}
232 pname = "rd%d" % 0
233 vec.r_ports[pname] = vec.read_port("%s_%s" % (name, pname))
234 return vec
235
236 def elaborate_into(self, m, platform):
237 for (name, rf) in self.rf.items():
238 setattr(m.submodules, name, rf)
239 for (name, rv) in self.rv.items():
240 setattr(m.submodules, "rv_"+name, rv)
241 for (name, wv) in self.wv.items():
242 setattr(m.submodules, "wv_"+name, wv)
243 return m
244
245 if __name__ == '__main__':
246 m = Module()
247 from soc.config.test.test_loadstore import TestMemPspec
248 pspec = TestMemPspec()
249 rf = RegFiles(pspec, make_hazard_vecs=True)
250 rf.elaborate_into(m, None)
251 vl = rtlil.convert(m)
252 with open("test_regfiles.il", "w") as f:
253 f.write(vl)
254