morph regfiles to add hazard vector make_vecs function
[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 # Factory style classes
188 regkls = [('int', IntRegs),
189 ('cr', CRRegs),
190 ('xer', XERRegs),
191 ('fast', FastRegs),
192 ('state', StateRegs),
193 ('spr', SPRRegs),]
194 def __init__(self, pspec, make_hazard_vecs=False):
195 # test is SVP64 is to be enabled
196 svp64_en = hasattr(pspec, "svp64") and (pspec.svp64 == True)
197
198 # and regfile port reduction
199 regreduce_en = hasattr(pspec, "regreduce") and \
200 (pspec.regreduce == True)
201
202 self.rf = {} # register file dict
203 # create regfiles here, Factory style
204 for (name, kls) in RegFiles.regkls:
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 self.rv, self.wv = {}, {}
210 if make_hazard_vecs:
211 # create a read-hazard and write-hazard vectors for this regfile
212 self.wv = make_vecs(self, "wr") # global write vectors
213 self.rv = make_vecs(self, "rd") # global read vectors
214
215 def make_vecs(self, name):
216 vec = {}
217 # create regfiles here, Factory style
218 for (name, kls) in RegFiles.regkls:
219 vec[name] = self.make_hazard_vec(rf, name)
220 return vec
221
222 def make_hazard_vec(self, rf, name):
223 if isinstance(rf, VirtualRegPort):
224 vec = RegFileArray(rf.bitwidth, 1)
225 else:
226 vec = RegFileArray(rf.depth, 1)
227 if name in ['int', 'cr', 'xer']:
228 n_wrs = 3
229 elif name in ['fast']:
230 n_wrs = 2
231 else:
232 n_wrs = 1
233 # add write ports
234 vec.w_ports = {}
235 for i in range(n_wrs):
236 pname = "wr%d" % i
237 vec.w_ports[pname] = vec.write_port("%s_%s" % (name, pname))
238 # add read port
239 vec.r_ports = {}
240 pname = "rd%d" % 0
241 vec.r_ports[pname] = vec.read_port("%s_%s" % (name, pname))
242 return vec
243
244 def elaborate_into(self, m, platform):
245 for (name, rf) in self.rf.items():
246 setattr(m.submodules, name, rf)
247 for (name, rv) in self.rv.items():
248 setattr(m.submodules, "rv_"+name, rv)
249 for (name, wv) in self.wv.items():
250 setattr(m.submodules, "wv_"+name, wv)
251 return m
252
253 if __name__ == '__main__':
254 m = Module()
255 from soc.config.test.test_loadstore import TestMemPspec
256 pspec = TestMemPspec()
257 rf = RegFiles(pspec, make_hazard_vecs=True)
258 rf.elaborate_into(m, None)
259 vl = rtlil.convert(m)
260 with open("test_regfiles.il", "w") as f:
261 f.write(vl)
262