28f8172d74774bdc8c0a95a4406a21520256f7d6
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
36 from nmutil
.latch
import SRLatch
39 def create_ports(rf
, wr_spec
, rd_spec
):
40 """create_ports: creates register file ports based on requested specs
42 rf
.r_ports
, rf
.w_ports
= {}, {}
43 # create read ports based on read specs
44 for key
, name
in rd_spec
.items():
45 if hasattr(rf
, name
): # some regfiles already have a port
46 rf
.r_ports
[key
] = getattr(rf
, name
)
48 rf
.r_ports
[key
] = rf
.read_port(name
)
49 # create write ports based on write specs
50 for key
, name
in wr_spec
.items():
51 if hasattr(rf
, name
): # some regfiles already have a port
52 rf
.w_ports
[key
] = getattr(rf
, name
)
54 rf
.w_ports
[key
] = rf
.write_port(name
)
58 class StateRegs(RegFileArray
, StateRegsEnum
):
61 State regfile - PC, MSR, SVSTATE (for SimpleV)
63 * QTY 3of 64-bit registers
65 * Array-based unary-indexed (not binary-indexed)
66 * write-through capability (read on same cycle as write)
68 Note: d_wr1 d_rd1 are for use by the decoder, to get at the PC.
69 will probably have to also add one so it can get at the MSR as well.
73 def __init__(self
, svp64_en
=False, regreduce_en
=False):
74 super().__init
__(64, StateRegsEnum
.N_REGS
)
75 wr_spec
, rd_spec
= self
.get_port_specs()
76 create_ports(self
, wr_spec
, rd_spec
)
78 def get_port_specs(self
):
79 w_port_spec
= {'nia': "nia",
82 'sv': "sv", # writing SVSTATE (issuer)
83 'd_wr1': "d_wr1"} # writing PC (issuer)
84 r_port_spec
= {'cia': "cia", # reading PC (issuer)
85 'msr': "msr", # reading MSR (issuer)
86 'sv': "sv", # reading SV (issuer)
88 return w_port_spec
, r_port_spec
92 class IntRegs(RegFileMem
): #class IntRegs(RegFileArray):
95 * QTY 32of 64-bit registers
97 * Array-based unary-indexed (not binary-indexed)
98 * write-through capability (read on same cycle as write)
100 def __init__(self
, svp64_en
=False, regreduce_en
=False):
101 super().__init
__(64, 32, fwd_bus_mode
=False)
102 self
.svp64_en
= svp64_en
103 self
.regreduce_en
= regreduce_en
104 wr_spec
, rd_spec
= self
.get_port_specs()
105 create_ports(self
, wr_spec
, rd_spec
)
107 def get_port_specs(self
):
108 w_port_spec
= {'o': "dest1",
110 r_port_spec
= { 'dmi': "dmi" # needed for Debug (DMI)
113 r_port_spec
['pred'] = "pred" # for predicate mask
114 if not self
.regreduce_en
:
115 w_port_spec
['o1'] = "dest2" # (LD/ST update)
116 r_port_spec
['ra'] = "src1"
117 r_port_spec
['rb'] = "src2"
118 r_port_spec
['rc'] = "src3"
120 r_port_spec
['rabc'] = "src1"
121 return w_port_spec
, r_port_spec
125 class FastRegs(RegFileMem
, FastRegsEnum
): #RegFileArray):
128 FAST regfile - CTR, LR, TAR, SRR1, SRR2, XER, TB, DEC, SVSRR0
130 * QTY 6of 64-bit registers
132 * Array-based unary-indexed (not binary-indexed)
133 * write-through capability (read on same cycle as write)
135 Note: r/w issue are used by issuer to increment/decrement TB/DEC.
137 def __init__(self
, svp64_en
=False, regreduce_en
=False):
138 super().__init
__(64, FastRegsEnum
.N_REGS
, fwd_bus_mode
=False)
139 self
.svp64_en
= svp64_en
140 self
.regreduce_en
= regreduce_en
141 wr_spec
, rd_spec
= self
.get_port_specs()
142 create_ports(self
, wr_spec
, rd_spec
)
144 def get_port_specs(self
):
145 w_port_spec
= {'fast1': "dest1",
146 'issue': "issue", # writing DEC/TB
148 r_port_spec
= {'fast1': "src1",
149 'issue': "issue", # reading DEC/TB
151 if not self
.regreduce_en
:
152 r_port_spec
['fast2'] = "src2"
153 r_port_spec
['fast3'] = "src3"
154 w_port_spec
['fast2'] = "dest2"
155 w_port_spec
['fast3'] = "dest3"
157 return w_port_spec
, r_port_spec
161 class CRRegs(VirtualRegPort
):
162 """Condition Code Registers (CR0-7)
164 * QTY 8of 8-bit registers
165 * 3R1W 4-bit-wide with additional 1R1W for the "full" 32-bit width
166 * Array-based unary-indexed (not binary-indexed)
167 * write-through capability (read on same cycle as write)
169 def __init__(self
, svp64_en
=False, regreduce_en
=False):
170 super().__init
__(32, 8, rd2
=True)
171 self
.svp64_en
= svp64_en
172 self
.regreduce_en
= regreduce_en
173 wr_spec
, rd_spec
= self
.get_port_specs()
174 create_ports(self
, wr_spec
, rd_spec
)
176 def get_port_specs(self
):
177 w_port_spec
= {'full_cr': "full_wr", # 32-bit (masked, 8-en lines)
178 'cr_a': "dest1", # 4-bit, unary-indexed
179 'cr_b': "dest2"} # 4-bit, unary-indexed
180 r_port_spec
= {'full_cr': "full_rd", # 32-bit (masked, 8-en lines)
181 'full_cr_dbg': "full_rd2", # for DMI
186 r_port_spec
['cr_pred'] = "cr_pred" # for predicate
188 return w_port_spec
, r_port_spec
192 class XERRegs(VirtualRegPort
, XERRegsEnum
):
193 """XER Registers (SO, CA/CA32, OV/OV32)
195 * QTY 3of 2-bit registers
196 * 3R3W 2-bit-wide with additional 1R1W for the "full" 6-bit width
197 * Array-based unary-indexed (not binary-indexed)
198 * write-through capability (read on same cycle as write)
200 SO
=0 # this is actually 2-bit but we ignore 1 bit of it
203 def __init__(self
, svp64_en
=False, regreduce_en
=False):
204 super().__init
__(6, XERRegsEnum
.N_REGS
)
205 self
.svp64_en
= svp64_en
206 self
.regreduce_en
= regreduce_en
207 wr_spec
, rd_spec
= self
.get_port_specs()
208 create_ports(self
, wr_spec
, rd_spec
)
210 def get_port_specs(self
):
211 w_port_spec
= {'full_xer': "full_wr", # 6-bit (masked, 3-en lines)
215 r_port_spec
= {'full_xer': "full_rd", # 6-bit (masked, 3-en lines)
219 return w_port_spec
, r_port_spec
223 class SPRRegs(RegFileMem
):
226 * QTY len(SPRs) 64-bit registers
228 * binary-indexed but REQUIRES MAPPING
229 * write-through capability (read on same cycle as write)
231 def __init__(self
, svp64_en
=False, regreduce_en
=False):
233 n_sprs
= len(SPRreduced
)
235 n_sprs
= len(SPRfull
)
236 super().__init
__(width
=64, depth
=n_sprs
,
238 self
.svp64_en
= svp64_en
239 self
.regreduce_en
= regreduce_en
240 wr_spec
, rd_spec
= self
.get_port_specs()
241 create_ports(self
, wr_spec
, rd_spec
)
243 def get_port_specs(self
):
244 w_port_spec
= {'spr1': "spr1"}
245 r_port_spec
= {'spr1': "spr1"}
246 return w_port_spec
, r_port_spec
249 # class containing all regfiles: int, cr, xer, fast, spr
251 # Factory style classes
252 regkls
= [('int', IntRegs
),
256 ('state', StateRegs
),
258 def __init__(self
, pspec
, make_hazard_vecs
=False):
259 # test is SVP64 is to be enabled
260 svp64_en
= hasattr(pspec
, "svp64") and (pspec
.svp64
== True)
262 # and regfile port reduction
263 regreduce_en
= hasattr(pspec
, "regreduce") and \
264 (pspec
.regreduce
== True)
266 self
.rf
= {} # register file dict
267 # create regfiles here, Factory style
268 for (name
, kls
) in RegFiles
.regkls
:
269 rf
= self
.rf
[name
] = kls(svp64_en
, regreduce_en
)
270 # also add these as instances, self.state, self.fast, self.cr etc.
271 setattr(self
, name
, rf
)
273 self
.rv
, self
.wv
= {}, {}
275 # create a read-hazard and write-hazard vectors for this regfile
276 self
.wv
= self
.make_vecs("wr") # global write vectors
277 self
.rv
= self
.make_vecs("rd") # global read vectors
279 def make_vecs(self
, name
):
281 # create regfiles here, Factory style
282 for (name
, kls
) in RegFiles
.regkls
:
284 vec
[name
] = self
.make_hazard_vec(rf
, name
)
287 def make_hazard_vec(self
, rf
, name
):
288 if isinstance(rf
, VirtualRegPort
):
289 vec
= SRLatch(sync
=False, llen
=rf
.nregs
, name
=name
)
291 vec
= SRLatch(sync
=False, llen
=rf
.depth
, name
=name
)
294 def elaborate_into(self
, m
, platform
):
295 for (name
, rf
) in self
.rf
.items():
296 setattr(m
.submodules
, name
, rf
)
297 for (name
, rv
) in self
.rv
.items():
298 setattr(m
.submodules
, "rv_"+name
, rv
)
299 for (name
, wv
) in self
.wv
.items():
300 setattr(m
.submodules
, "wv_"+name
, wv
)
303 if __name__
== '__main__':
305 from soc
.config
.test
.test_loadstore
import TestMemPspec
306 pspec
= TestMemPspec()
307 rf
= RegFiles(pspec
, make_hazard_vecs
=True)
308 rf
.elaborate_into(m
, None)
309 vl
= rtlil
.convert(m
)
310 with
open("test_regfiles.il", "w") as f
: