add option to reduce number of regfile ports (get DFFs down in ls180)
[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 soc.decoder.power_enums import SPR
30
31
32 # "State" Regfile
33 class StateRegs(RegFileArray):
34 """StateRegs
35
36 State regfile - PC, MSR, SVSTATE (for SimpleV)
37
38 * QTY 3of 64-bit registers
39 * 4R3W
40 * Array-based unary-indexed (not binary-indexed)
41 * write-through capability (read on same cycle as write)
42
43 Note: d_wr1 d_rd1 are for use by the decoder, to get at the PC.
44 will probably have to also add one so it can get at the MSR as well.
45 (d_rd2)
46
47 """
48 PC = 0
49 MSR = 1
50 SVSTATE = 2
51 def __init__(self, svp64_en=False, regreduce_en=False):
52 super().__init__(64, 3)
53 self.w_ports = {'nia': self.write_port("nia"),
54 'msr': self.write_port("msr"),
55 'sv': self.write_port("sv"), # writing SVSTATE (issuer)
56 'd_wr1': self.write_port("d_wr1")} # writing PC (issuer)
57 self.r_ports = {'cia': self.read_port("cia"), # reading PC (issuer)
58 'msr': self.read_port("msr"), # reading MSR (issuer)
59 'sv': self.read_port("sv"), # reading SV (issuer)
60 }
61
62
63 # Integer Regfile
64 class IntRegs(RegFileMem): #class IntRegs(RegFileArray):
65 """IntRegs
66
67 * QTY 32of 64-bit registers
68 * 3R2W
69 * Array-based unary-indexed (not binary-indexed)
70 * write-through capability (read on same cycle as write)
71 """
72 def __init__(self, svp64_en=False, regreduce_en=False):
73 super().__init__(64, 32)
74 self.w_ports = {'o': self.write_port("dest1"),
75 }
76 self.r_ports = {
77 'dmi': self.read_port("dmi")} # needed for Debug (DMI)
78 if svp64_en:
79 self.r_ports['pred'] = self.read_port("pred") # for predicate mask
80 if not regreduce_en:
81 self.w_ports['o1'] = self.write_port("dest2") # (LD/ST update)
82 self.r_ports['ra'] = self.read_port("src1")
83 self.r_ports['rb'] = self.read_port("src2")
84 self.r_ports['rc'] = self.read_port("src3")
85 else:
86 self.r_ports['rabc'] = self.read_port("src")
87
88
89 # Fast SPRs Regfile
90 class FastRegs(RegFileMem): #RegFileArray):
91 """FastRegs
92
93 FAST regfile - CTR, LR, TAR, SRR1, SRR2, XER, TB, DEC
94
95 * QTY 6of 64-bit registers
96 * 3R2W
97 * Array-based unary-indexed (not binary-indexed)
98 * write-through capability (read on same cycle as write)
99
100 Note: r/w issue are used by issuer to increment/decrement TB/DEC.
101 """
102 CTR = 0
103 LR = 1
104 TAR = 2
105 SRR0 = 3
106 SRR1 = 4
107 XER = 5 # non-XER bits
108 DEC = 6
109 TB = 7
110 N_REGS = 8 # maximum number of regs
111 def __init__(self, svp64_en=False, regreduce_en=False):
112 super().__init__(64, self.N_REGS)
113 self.w_ports = {'fast1': self.write_port("dest1"),
114 'issue': self.write_port("issue"), # writing DEC/TB
115 }
116 self.r_ports = {'fast1': self.read_port("src1"),
117 'issue': self.read_port("issue"), # reading DEC/TB
118 }
119 if not regreduce_en:
120 self.r_ports['fast2'] = self.read_port("src2")
121
122
123 # CR Regfile
124 class CRRegs(VirtualRegPort):
125 """Condition Code Registers (CR0-7)
126
127 * QTY 8of 8-bit registers
128 * 3R1W 4-bit-wide with additional 1R1W for the "full" 32-bit width
129 * Array-based unary-indexed (not binary-indexed)
130 * write-through capability (read on same cycle as write)
131 """
132 def __init__(self, svp64_en=False, regreduce_en=False):
133 super().__init__(32, 8, rd2=True)
134 self.w_ports = {'full_cr': self.full_wr, # 32-bit (masked, 8-en lines)
135 'cr_a': self.write_port("dest1"), # 4-bit, unary-indexed
136 'cr_b': self.write_port("dest2")} # 4-bit, unary-indexed
137 self.r_ports = {'full_cr': self.full_rd, # 32-bit (masked, 8-en lines)
138 'full_cr_dbg': self.full_rd2, # for DMI
139 'cr_a': self.read_port("src1"),
140 'cr_b': self.read_port("src2"),
141 'cr_c': self.read_port("src3")}
142 if svp64_en:
143 self.r_ports['cr_pred'] = self.read_port("cr_pred") # for predicate
144
145
146 # XER Regfile
147 class XERRegs(VirtualRegPort):
148 """XER Registers (SO, CA/CA32, OV/OV32)
149
150 * QTY 3of 2-bit registers
151 * 3R3W 2-bit-wide with additional 1R1W for the "full" 6-bit width
152 * Array-based unary-indexed (not binary-indexed)
153 * write-through capability (read on same cycle as write)
154 """
155 SO=0 # this is actually 2-bit but we ignore 1 bit of it
156 CA=1 # CA and CA32
157 OV=2 # OV and OV32
158 def __init__(self, svp64_en=False, regreduce_en=False):
159 super().__init__(6, 3)
160 self.w_ports = {'full_xer': self.full_wr, # 6-bit (masked, 3-en lines)
161 'xer_so': self.write_port("dest1"),
162 'xer_ca': self.write_port("dest2"),
163 'xer_ov': self.write_port("dest3")}
164 self.r_ports = {'full_xer': self.full_rd, # 6-bit (masked, 3-en lines)
165 'xer_so': self.read_port("src1"),
166 'xer_ca': self.read_port("src2"),
167 'xer_ov': self.read_port("src3")}
168
169
170 # SPR Regfile
171 class SPRRegs(RegFileMem):
172 """SPRRegs
173
174 * QTY len(SPRs) 64-bit registers
175 * 1R1W
176 * binary-indexed but REQUIRES MAPPING
177 * write-through capability (read on same cycle as write)
178 """
179 def __init__(self, svp64_en=False, regreduce_en=False):
180 n_sprs = len(SPR)
181 super().__init__(width=64, depth=n_sprs)
182 self.w_ports = {'spr1': self.write_port("spr1")}
183 self.r_ports = {'spr1': self.read_port("spr1")}
184
185
186 # class containing all regfiles: int, cr, xer, fast, spr
187 class RegFiles:
188 def __init__(self, pspec):
189 # test is SVP64 is to be enabled
190 svp64_en = hasattr(pspec, "svp64") and (pspec.svp64 == True)
191
192 # and regfile port reduction
193 regreduce_en = hasattr(pspec, "regreduce") and \
194 (pspec.regreduce == True)
195
196 self.rf = {}
197 # create regfiles here, Factory style
198 for (name, kls) in [('int', IntRegs),
199 ('cr', CRRegs),
200 ('xer', XERRegs),
201 ('fast', FastRegs),
202 ('state', StateRegs),
203 ('spr', SPRRegs),]:
204 rf = self.rf[name] = kls(svp64_en, regreduce_en)
205 # also add these as instances, self.state, self.fast, self.cr etc.
206 setattr(self, name, rf)
207
208 def elaborate_into(self, m, platform):
209 for (name, rf) in self.rf.items():
210 setattr(m.submodules, name, rf)
211 return m
212