1 # POWER9 Register Files
4 Defines the following register files:
6 * INT regfile - 32x 64-bit
7 * SPR regfile - 110x 64-bit
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)
13 Note: this should NOT have name conventions hard-coded (dedicated ports per
14 regname). However it is convenient for now.
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)
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
31 # XXX MAKE DAMN SURE TO KEEP THESE UP-TO-DATE if changing/adding regs
32 from openpower
.consts
import StateRegsEnum
, XERRegsEnum
, FastRegsEnum
34 from nmigen
import Module
35 from nmigen
.cli
import rtlil
38 def create_ports(rf
, wr_spec
, rd_spec
):
39 """create_ports: creates register file ports based on requested specs
41 rf
.r_ports
, rf
.w_ports
= {}, {}
42 # create read ports based on read specs
43 for key
, name
in rd_spec
.items():
44 if hasattr(rf
, name
): # some regfiles already have a port
45 rf
.r_ports
[key
] = getattr(rf
, name
)
47 rf
.r_ports
[key
] = rf
.read_port(name
)
48 # create write ports based on write specs
49 for key
, name
in wr_spec
.items():
50 if hasattr(rf
, name
): # some regfiles already have a port
51 rf
.w_ports
[key
] = getattr(rf
, name
)
53 rf
.w_ports
[key
] = rf
.write_port(name
)
57 class StateRegs(RegFileArray
, StateRegsEnum
):
60 State regfile - PC, MSR, SVSTATE (for SimpleV)
62 * QTY 3of 64-bit registers
64 * Array-based unary-indexed (not binary-indexed)
65 * write-through capability (read on same cycle as write)
67 Note: d_wr1 d_rd1 are for use by the decoder, to get at the PC.
68 will probably have to also add one so it can get at the MSR as well.
72 def __init__(self
, svp64_en
=False, regreduce_en
=False):
73 super().__init
__(64, StateRegsEnum
.N_REGS
)
74 wr_spec
, rd_spec
= self
.get_port_specs()
75 create_ports(self
, wr_spec
, rd_spec
)
77 def get_port_specs(self
):
78 w_port_spec
= {'nia': "nia",
81 'sv': "sv", # writing SVSTATE (issuer)
82 'd_wr1': "d_wr1"} # writing PC (issuer)
83 r_port_spec
= {'cia': "cia", # reading PC (issuer)
84 'msr': "msr", # reading MSR (issuer)
85 'sv': "sv", # reading SV (issuer)
87 return w_port_spec
, r_port_spec
91 class IntRegs(RegFileMem
): #class IntRegs(RegFileArray):
94 * QTY 32of 64-bit registers
96 * Array-based unary-indexed (not binary-indexed)
97 * write-through capability (read on same cycle as write)
99 def __init__(self
, svp64_en
=False, regreduce_en
=False):
100 super().__init
__(64, 32, fwd_bus_mode
=not regreduce_en
)
101 self
.svp64_en
= svp64_en
102 self
.regreduce_en
= regreduce_en
103 wr_spec
, rd_spec
= self
.get_port_specs()
104 create_ports(self
, wr_spec
, rd_spec
)
106 def get_port_specs(self
):
107 w_port_spec
= {'o': "dest1",
109 r_port_spec
= { 'dmi': "dmi" # needed for Debug (DMI)
112 r_port_spec
['pred'] = "pred" # for predicate mask
113 if not self
.regreduce_en
:
114 w_port_spec
['o1'] = "dest2" # (LD/ST update)
115 r_port_spec
['ra'] = "src1"
116 r_port_spec
['rb'] = "src2"
117 r_port_spec
['rc'] = "src3"
119 r_port_spec
['rabc'] = "src1"
120 return w_port_spec
, r_port_spec
124 class FastRegs(RegFileMem
, FastRegsEnum
): #RegFileArray):
127 FAST regfile - CTR, LR, TAR, SRR1, SRR2, XER, TB, DEC, SVSRR0
129 * QTY 6of 64-bit registers
131 * Array-based unary-indexed (not binary-indexed)
132 * write-through capability (read on same cycle as write)
134 Note: r/w issue are used by issuer to increment/decrement TB/DEC.
136 def __init__(self
, svp64_en
=False, regreduce_en
=False):
137 super().__init
__(64, FastRegsEnum
.N_REGS
, fwd_bus_mode
=not regreduce_en
)
138 self
.svp64_en
= svp64_en
139 self
.regreduce_en
= regreduce_en
140 wr_spec
, rd_spec
= self
.get_port_specs()
141 create_ports(self
, wr_spec
, rd_spec
)
143 def get_port_specs(self
):
144 w_port_spec
= {'fast1': "dest1",
145 'issue': "issue", # writing DEC/TB
147 r_port_spec
= {'fast1': "src1",
148 'issue': "issue", # reading DEC/TB
150 if not self
.regreduce_en
:
151 r_port_spec
['fast2'] = "src2"
153 return w_port_spec
, r_port_spec
157 class CRRegs(VirtualRegPort
):
158 """Condition Code Registers (CR0-7)
160 * QTY 8of 8-bit registers
161 * 3R1W 4-bit-wide with additional 1R1W for the "full" 32-bit width
162 * Array-based unary-indexed (not binary-indexed)
163 * write-through capability (read on same cycle as write)
165 def __init__(self
, svp64_en
=False, regreduce_en
=False):
166 super().__init
__(32, 8, rd2
=True)
167 self
.svp64_en
= svp64_en
168 self
.regreduce_en
= regreduce_en
169 wr_spec
, rd_spec
= self
.get_port_specs()
170 create_ports(self
, wr_spec
, rd_spec
)
172 def get_port_specs(self
):
173 w_port_spec
= {'full_cr': "full_wr", # 32-bit (masked, 8-en lines)
174 'cr_a': "dest1", # 4-bit, unary-indexed
175 'cr_b': "dest2"} # 4-bit, unary-indexed
176 r_port_spec
= {'full_cr': "full_rd", # 32-bit (masked, 8-en lines)
177 'full_cr_dbg': "full_rd2", # for DMI
182 r_port_spec
['cr_pred'] = "cr_pred" # for predicate
184 return w_port_spec
, r_port_spec
188 class XERRegs(VirtualRegPort
, XERRegsEnum
):
189 """XER Registers (SO, CA/CA32, OV/OV32)
191 * QTY 3of 2-bit registers
192 * 3R3W 2-bit-wide with additional 1R1W for the "full" 6-bit width
193 * Array-based unary-indexed (not binary-indexed)
194 * write-through capability (read on same cycle as write)
196 SO
=0 # this is actually 2-bit but we ignore 1 bit of it
199 def __init__(self
, svp64_en
=False, regreduce_en
=False):
200 super().__init
__(6, XERRegsEnum
.N_REGS
)
201 self
.svp64_en
= svp64_en
202 self
.regreduce_en
= regreduce_en
203 wr_spec
, rd_spec
= self
.get_port_specs()
204 create_ports(self
, wr_spec
, rd_spec
)
206 def get_port_specs(self
):
207 w_port_spec
= {'full_xer': "full_wr", # 6-bit (masked, 3-en lines)
211 r_port_spec
= {'full_xer': "full_rd", # 6-bit (masked, 3-en lines)
215 return w_port_spec
, r_port_spec
219 class SPRRegs(RegFileMem
):
222 * QTY len(SPRs) 64-bit registers
224 * binary-indexed but REQUIRES MAPPING
225 * write-through capability (read on same cycle as write)
227 def __init__(self
, svp64_en
=False, regreduce_en
=False):
229 n_sprs
= len(SPRreduced
)
231 n_sprs
= len(SPRfull
)
232 super().__init
__(width
=64, depth
=n_sprs
,
233 fwd_bus_mode
=not regreduce_en
)
234 self
.svp64_en
= svp64_en
235 self
.regreduce_en
= regreduce_en
236 wr_spec
, rd_spec
= self
.get_port_specs()
237 create_ports(self
, wr_spec
, rd_spec
)
239 def get_port_specs(self
):
240 w_port_spec
= {'spr1': "spr1"}
241 r_port_spec
= {'spr1': "spr1"}
242 return w_port_spec
, r_port_spec
245 # class containing all regfiles: int, cr, xer, fast, spr
247 # Factory style classes
248 regkls
= [('int', IntRegs
),
252 ('state', StateRegs
),
254 def __init__(self
, pspec
, make_hazard_vecs
=False):
255 # test is SVP64 is to be enabled
256 svp64_en
= hasattr(pspec
, "svp64") and (pspec
.svp64
== True)
258 # and regfile port reduction
259 regreduce_en
= hasattr(pspec
, "regreduce") and \
260 (pspec
.regreduce
== True)
262 self
.rf
= {} # register file dict
263 # create regfiles here, Factory style
264 for (name
, kls
) in RegFiles
.regkls
:
265 rf
= self
.rf
[name
] = kls(svp64_en
, regreduce_en
)
266 # also add these as instances, self.state, self.fast, self.cr etc.
267 setattr(self
, name
, rf
)
269 self
.rv
, self
.wv
= {}, {}
271 # create a read-hazard and write-hazard vectors for this regfile
272 self
.wv
= make_vecs(self
, "wr") # global write vectors
273 self
.rv
= make_vecs(self
, "rd") # global read vectors
275 def make_vecs(self
, name
):
277 # create regfiles here, Factory style
278 for (name
, kls
) in RegFiles
.regkls
:
279 vec
[name
] = self
.make_hazard_vec(rf
, name
)
282 def make_hazard_vec(self
, rf
, name
):
283 if isinstance(rf
, VirtualRegPort
):
284 vec
= RegFileArray(rf
.bitwidth
, 1)
286 vec
= RegFileArray(rf
.depth
, 1)
287 if name
in ['int', 'cr', 'xer']:
289 elif name
in ['fast']:
295 for i
in range(n_wrs
):
297 vec
.w_ports
[pname
] = vec
.write_port("%s_%s" % (name
, pname
))
301 vec
.r_ports
[pname
] = vec
.read_port("%s_%s" % (name
, pname
))
304 def elaborate_into(self
, m
, platform
):
305 for (name
, rf
) in self
.rf
.items():
306 setattr(m
.submodules
, name
, rf
)
307 for (name
, rv
) in self
.rv
.items():
308 setattr(m
.submodules
, "rv_"+name
, rv
)
309 for (name
, wv
) in self
.wv
.items():
310 setattr(m
.submodules
, "wv_"+name
, wv
)
313 if __name__
== '__main__':
315 from soc
.config
.test
.test_loadstore
import TestMemPspec
316 pspec
= TestMemPspec()
317 rf
= RegFiles(pspec
, make_hazard_vecs
=True)
318 rf
.elaborate_into(m
, None)
319 vl
= rtlil
.convert(m
)
320 with
open("test_regfiles.il", "w") as f
: