f3531e092a335fb7ef2baa0e306af5fb1b72370d
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, resets
=None):
74 super().__init
__(64, StateRegsEnum
.N_REGS
, resets
=resets
)
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
= { # these 3 allow writing state by Function Units
80 # strictly speaking this should not be allowed,
81 # the information should be passed back to Issuer
82 # to work out what to do
86 # these 3 allow writing state by Issuer
87 'sv': "sv", # writing SVSTATE
88 'd_wr1': "d_wr1", # writing PC
89 'd_wr2': "d_wr2"} # writing MSR
90 r_port_spec
= { # these are for reading state by Issuer but
91 # the FUs do not read them: they are passed in
92 # because of multi-issue / pipelining / etc.
93 # the state could be totally different and is
94 # only known *at* issue time, *by* the issuer
95 'cia': "cia", # reading PC (issuer)
96 'msr': "msr", # reading MSR (issuer)
97 'sv': "sv", # reading SV (issuer)
99 return w_port_spec
, r_port_spec
103 class IntRegs(RegFileMem
): #class IntRegs(RegFileArray):
106 * QTY 32of 64-bit registers
108 * Array-based unary-indexed (not binary-indexed)
109 * write-through capability (read on same cycle as write)
111 def __init__(self
, svp64_en
=False, regreduce_en
=False):
112 super().__init
__(64, 32, fwd_bus_mode
=False)
113 self
.svp64_en
= svp64_en
114 self
.regreduce_en
= regreduce_en
115 wr_spec
, rd_spec
= self
.get_port_specs()
116 create_ports(self
, wr_spec
, rd_spec
)
118 def get_port_specs(self
):
119 w_port_spec
= {'o': "dest1",
121 r_port_spec
= { 'dmi': "dmi" # needed for Debug (DMI)
124 r_port_spec
['pred'] = "pred" # for predicate mask
125 if not self
.regreduce_en
:
126 w_port_spec
['o1'] = "dest2" # (LD/ST update)
127 r_port_spec
['ra'] = "src1"
128 r_port_spec
['rb'] = "src2"
129 r_port_spec
['rc'] = "src3"
131 r_port_spec
['rabc'] = "src1"
132 return w_port_spec
, r_port_spec
136 class FastRegs(RegFileMem
, FastRegsEnum
): #RegFileArray):
139 FAST regfile - CTR, LR, TAR, SRR1, SRR2, XER, TB, DEC, SVSRR0
141 * QTY 6of 64-bit registers
143 * Array-based unary-indexed (not binary-indexed)
144 * write-through capability (read on same cycle as write)
146 Note: r/w issue are used by issuer to increment/decrement TB/DEC.
148 def __init__(self
, svp64_en
=False, regreduce_en
=False):
149 super().__init
__(64, FastRegsEnum
.N_REGS
, fwd_bus_mode
=False)
150 self
.svp64_en
= svp64_en
151 self
.regreduce_en
= regreduce_en
152 wr_spec
, rd_spec
= self
.get_port_specs()
153 create_ports(self
, wr_spec
, rd_spec
)
155 def get_port_specs(self
):
156 w_port_spec
= {'fast1': "dest1",
157 'issue': "issue", # writing DEC/TB
159 r_port_spec
= {'fast1': "src1",
160 'issue': "issue", # reading DEC/TB
161 'dmi': "dmi" # needed for Debug (DMI)
163 if not self
.regreduce_en
:
164 r_port_spec
['fast2'] = "src2"
165 r_port_spec
['fast3'] = "src3"
166 w_port_spec
['fast2'] = "dest2"
167 w_port_spec
['fast3'] = "dest3"
169 return w_port_spec
, r_port_spec
173 class CRRegs(VirtualRegPort
):
174 """Condition Code Registers (CR0-7)
176 * QTY 8of 8-bit registers
177 * 3R1W 4-bit-wide with additional 1R1W for the "full" 32-bit width
178 * Array-based unary-indexed (not binary-indexed)
179 * write-through capability (read on same cycle as write)
181 def __init__(self
, svp64_en
=False, regreduce_en
=False):
182 super().__init
__(32, 8, rd2
=True)
183 self
.svp64_en
= svp64_en
184 self
.regreduce_en
= regreduce_en
185 wr_spec
, rd_spec
= self
.get_port_specs()
186 create_ports(self
, wr_spec
, rd_spec
)
188 def get_port_specs(self
):
189 w_port_spec
= {'full_cr': "full_wr", # 32-bit (masked, 8-en lines)
190 'cr_a': "dest1", # 4-bit, unary-indexed
191 'cr_b': "dest2"} # 4-bit, unary-indexed
192 r_port_spec
= {'full_cr': "full_rd", # 32-bit (masked, 8-en lines)
193 'full_cr_dbg': "full_rd2", # for DMI
198 r_port_spec
['cr_pred'] = "cr_pred" # for predicate
200 return w_port_spec
, r_port_spec
204 class XERRegs(VirtualRegPort
, XERRegsEnum
):
205 """XER Registers (SO, CA/CA32, OV/OV32)
207 * QTY 3of 2-bit registers
208 * 3R3W 2-bit-wide with additional 1R1W for the "full" 6-bit width
209 * Array-based unary-indexed (not binary-indexed)
210 * write-through capability (read on same cycle as write)
212 SO
=0 # this is actually 2-bit but we ignore 1 bit of it
215 def __init__(self
, svp64_en
=False, regreduce_en
=False):
216 super().__init
__(6, XERRegsEnum
.N_REGS
)
217 self
.svp64_en
= svp64_en
218 self
.regreduce_en
= regreduce_en
219 wr_spec
, rd_spec
= self
.get_port_specs()
220 create_ports(self
, wr_spec
, rd_spec
)
222 def get_port_specs(self
):
223 w_port_spec
= {'full_xer': "full_wr", # 6-bit (masked, 3-en lines)
227 r_port_spec
= {'full_xer': "full_rd", # 6-bit (masked, 3-en lines)
231 return w_port_spec
, r_port_spec
235 class SPRRegs(RegFileMem
):
238 * QTY len(SPRs) 64-bit registers
240 * binary-indexed but REQUIRES MAPPING
241 * write-through capability (read on same cycle as write)
243 def __init__(self
, svp64_en
=False, regreduce_en
=False):
245 n_sprs
= len(SPRreduced
)
247 n_sprs
= len(SPRfull
)
248 super().__init
__(width
=64, depth
=n_sprs
,
250 self
.svp64_en
= svp64_en
251 self
.regreduce_en
= regreduce_en
252 wr_spec
, rd_spec
= self
.get_port_specs()
253 create_ports(self
, wr_spec
, rd_spec
)
255 def get_port_specs(self
):
256 w_port_spec
= {'spr1': "spr1"}
257 r_port_spec
= {'spr1': "spr1"}
258 return w_port_spec
, r_port_spec
261 # class containing all regfiles: int, cr, xer, fast, spr
263 # Factory style classes
264 regkls
= [('int', IntRegs
),
268 ('state', StateRegs
),
270 def __init__(self
, pspec
, make_hazard_vecs
=False,
271 state_resets
=None): # state file reset values
272 # test is SVP64 is to be enabled
273 svp64_en
= hasattr(pspec
, "svp64") and (pspec
.svp64
== True)
275 # and regfile port reduction
276 regreduce_en
= hasattr(pspec
, "regreduce") and \
277 (pspec
.regreduce
== True)
279 self
.rf
= {} # register file dict
280 # create regfiles here, Factory style
281 for (name
, kls
) in RegFiles
.regkls
:
282 kwargs
= {'svp64_en': svp64_en
, 'regreduce_en': regreduce_en
}
284 kwargs
['resets'] = state_resets
285 rf
= self
.rf
[name
] = kls(**kwargs
)
286 # also add these as instances, self.state, self.fast, self.cr etc.
287 setattr(self
, name
, rf
)
289 self
.rv
, self
.wv
= {}, {}
291 # create a read-hazard and write-hazard vectors for this regfile
292 self
.wv
= self
.make_vecs("wr") # global write vectors
293 self
.rv
= self
.make_vecs("rd") # global read vectors
295 def make_vecs(self
, name
):
297 # create regfiles here, Factory style
298 for (name
, kls
) in RegFiles
.regkls
:
300 vec
[name
] = self
.make_hazard_vec(rf
, name
)
303 def make_hazard_vec(self
, rf
, name
):
304 if isinstance(rf
, VirtualRegPort
):
305 vec
= SRLatch(sync
=False, llen
=rf
.nregs
, name
=name
)
307 vec
= SRLatch(sync
=False, llen
=rf
.depth
, name
=name
)
310 def elaborate_into(self
, m
, platform
):
311 for (name
, rf
) in self
.rf
.items():
312 setattr(m
.submodules
, name
, rf
)
313 for (name
, rv
) in self
.rv
.items():
314 setattr(m
.submodules
, "rv_"+name
, rv
)
315 for (name
, wv
) in self
.wv
.items():
316 setattr(m
.submodules
, "wv_"+name
, wv
)
319 if __name__
== '__main__':
321 from soc
.config
.test
.test_loadstore
import TestMemPspec
322 pspec
= TestMemPspec()
323 rf
= RegFiles(pspec
, make_hazard_vecs
=True)
324 rf
.elaborate_into(m
, None)
325 vl
= rtlil
.convert(m
)
326 with
open("test_regfiles.il", "w") as f
: