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
39 class StateRegs(RegFileArray
, StateRegsEnum
):
42 State regfile - PC, MSR, SVSTATE (for SimpleV)
44 * QTY 3of 64-bit registers
46 * Array-based unary-indexed (not binary-indexed)
47 * write-through capability (read on same cycle as write)
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.
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)
68 class IntRegs(RegFileMem
): #class IntRegs(RegFileArray):
71 * QTY 32of 64-bit registers
73 * Array-based unary-indexed (not binary-indexed)
74 * write-through capability (read on same cycle as write)
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"),
81 'dmi': self
.read_port("dmi")} # needed for Debug (DMI)
83 self
.r_ports
['pred'] = self
.read_port("pred") # for predicate mask
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")
90 self
.r_ports
['rabc'] = self
.read_port("src1")
94 class FastRegs(RegFileMem
, FastRegsEnum
): #RegFileArray):
97 FAST regfile - CTR, LR, TAR, SRR1, SRR2, XER, TB, DEC, SVSRR0
99 * QTY 6of 64-bit registers
101 * Array-based unary-indexed (not binary-indexed)
102 * write-through capability (read on same cycle as write)
104 Note: r/w issue are used by issuer to increment/decrement TB/DEC.
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
111 self
.r_ports
= {'fast1': self
.read_port("src1"),
112 'issue': self
.read_port("issue"), # reading DEC/TB
115 self
.r_ports
['fast2'] = self
.read_port("src2")
119 class CRRegs(VirtualRegPort
):
120 """Condition Code Registers (CR0-7)
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)
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")}
138 self
.r_ports
['cr_pred'] = self
.read_port("cr_pred") # for predicate
142 class XERRegs(VirtualRegPort
, XERRegsEnum
):
143 """XER Registers (SO, CA/CA32, OV/OV32)
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)
150 SO
=0 # this is actually 2-bit but we ignore 1 bit of it
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")}
166 class SPRRegs(RegFileMem
):
169 * QTY len(SPRs) 64-bit registers
171 * binary-indexed but REQUIRES MAPPING
172 * write-through capability (read on same cycle as write)
174 def __init__(self
, svp64_en
=False, regreduce_en
=False):
176 n_sprs
= len(SPRreduced
)
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")}
185 # class containing all regfiles: int, cr, xer, fast, spr
187 # Factory style classes
188 regkls
= [('int', IntRegs
),
192 ('state', StateRegs
),
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)
198 # and regfile port reduction
199 regreduce_en
= hasattr(pspec
, "regreduce") and \
200 (pspec
.regreduce
== True)
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
)
209 self
.rv
, self
.wv
= {}, {}
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
215 def make_vecs(self
, name
):
217 # create regfiles here, Factory style
218 for (name
, kls
) in RegFiles
.regkls
:
219 vec
[name
] = self
.make_hazard_vec(rf
, name
)
222 def make_hazard_vec(self
, rf
, name
):
223 if isinstance(rf
, VirtualRegPort
):
224 vec
= RegFileArray(rf
.bitwidth
, 1)
226 vec
= RegFileArray(rf
.depth
, 1)
227 if name
in ['int', 'cr', 'xer']:
229 elif name
in ['fast']:
235 for i
in range(n_wrs
):
237 vec
.w_ports
[pname
] = vec
.write_port("%s_%s" % (name
, pname
))
241 vec
.r_ports
[pname
] = vec
.read_port("%s_%s" % (name
, pname
))
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
)
253 if __name__
== '__main__':
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
: