reducing regfile port usage by sharing read ports
[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 - PC, MSR, CTR, LR, TAR, SRR1, SRR2
11
12 Note: this should NOT have name conventions hard-coded (dedicated ports per
13 regname). However it is convenient for now.
14
15 Links:
16
17 * https://bugs.libre-soc.org/show_bug.cgi?id=345
18 * https://bugs.libre-soc.org/show_bug.cgi?id=351
19 * https://libre-soc.org/3d_gpu/architecture/regfile/
20 * https://libre-soc.org/openpower/isatables/sprs.csv
21 """
22
23 # TODO
24
25 from soc.regfile.regfile import RegFile, RegFileArray
26 from soc.regfile.virtual_port import VirtualRegPort
27 from soc.decoder.power_enums import SPR
28 from nmigen import Memory, Elaboratable
29
30
31 # Integer Regfile
32 class IntRegs(RegFileArray):
33 """IntRegs
34
35 * QTY 32of 64-bit registers
36 * 3R2W
37 * Array-based unary-indexed (not binary-indexed)
38 * write-through capability (read on same cycle as write)
39 """
40 def __init__(self):
41 super().__init__(64, 32)
42 self.w_ports = {'o': self.write_port("dest1"),
43 'o1': self.write_port("dest2")} # for now (LD/ST update)
44 self.r_ports = {'ra': self.read_port("src1"),
45 'rbc': self.read_port("src3"),
46 'dmi': self.read_port("dmi")} # needed for Debug (DMI)
47
48
49 # Fast SPRs Regfile
50 class FastRegs(RegFileArray):
51 """FastRegs
52
53 FAST regfile - PC, MSR, CTR, LR, TAR, SRR1, SRR2
54
55 * QTY 8of 64-bit registers
56 * 3R2W
57 * Array-based unary-indexed (not binary-indexed)
58 * write-through capability (read on same cycle as write)
59
60 Note: d_wr1 d_rd1 are for use by the decoder, to get at the PC.
61 will probably have to also add one so it can get at the MSR as well.
62 (d_rd2)
63 """
64 PC = 0
65 MSR = 1
66 CTR = 2
67 LR = 3
68 TAR = 4
69 SRR0 = 5
70 SRR1 = 6
71 def __init__(self):
72 super().__init__(64, 8)
73 self.w_ports = {'nia': self.write_port("nia"),
74 'msr': self.write_port("dest2"),
75 'fast1': self.write_port("dest3"),
76 'fast2': self.write_port("dest4"),
77 'd_wr1': self.write_port("d_wr1")} # writing PC (issuer)
78 self.r_ports = {'cia': self.read_port("cia"), # reading PC (issuer)
79 'msr': self.read_port("msr"), # reading MSR (issuer)
80 'fast1': self.read_port("src1"),
81 }
82
83
84 # CR Regfile
85 class CRRegs(VirtualRegPort):
86 """Condition Code Registers (CR0-7)
87
88 * QTY 8of 8-bit registers
89 * 3R1W 4-bit-wide with additional 1R1W for the "full" 32-bit width
90 * Array-based unary-indexed (not binary-indexed)
91 * write-through capability (read on same cycle as write)
92 """
93 def __init__(self):
94 super().__init__(32, 8)
95 self.w_ports = {'full_cr': self.full_wr, # 32-bit (masked, 8-en lines)
96 'cr_a': self.write_port("dest1"), # 4-bit, unary-indexed
97 'cr_b': self.write_port("dest2")} # 4-bit, unary-indexed
98 self.r_ports = {'full_cr': self.full_rd, # 32-bit (masked, 8-en lines)
99 'cr_a': self.read_port("src1"),
100 'cr_b': self.read_port("src2"),
101 'cr_c': self.read_port("src3")}
102
103
104 # XER Regfile
105 class XERRegs(VirtualRegPort):
106 """XER Registers (SO, CA/CA32, OV/OV32)
107
108 * QTY 3of 2-bit registers
109 * 3R3W 2-bit-wide with additional 1R1W for the "full" 6-bit width
110 * Array-based unary-indexed (not binary-indexed)
111 * write-through capability (read on same cycle as write)
112 """
113 SO=0 # this is actually 2-bit but we ignore 1 bit of it
114 CA=1 # CA and CA32
115 OV=2 # OV and OV32
116 def __init__(self):
117 super().__init__(6, 3)
118 self.w_ports = {'full_xer': self.full_wr, # 6-bit (masked, 3-en lines)
119 'xer_so': self.write_port("dest1"),
120 'xer_ca': self.write_port("dest2"),
121 'xer_ov': self.write_port("dest3")}
122 self.r_ports = {'full_xer': self.full_rd, # 6-bit (masked, 3-en lines)
123 'xer_so': self.read_port("src1"),
124 'xer_ca': self.read_port("src2"),
125 'xer_ov': self.read_port("src3")}
126
127
128 # SPR Regfile
129 class SPRRegs(Memory, Elaboratable):
130 """SPRRegs
131
132 * QTY len(SPRs) 64-bit registers
133 * 1R1W
134 * binary-indexed but REQUIRES MAPPING
135 * write-through capability (read on same cycle as write)
136 """
137 def __init__(self):
138 n_sprs = len(SPR)
139 super().__init__(width=64, depth=n_sprs)
140 self.w_ports = {'spr1': self.write_port()}
141 self.r_ports = {'spr1': self.read_port()}
142
143 self.w_ports['spr1'].wen = self.w_ports['spr1'].en
144 self.w_ports['spr1'].data_i = self.w_ports['spr1'].data
145
146 self.r_ports['spr1'].ren = self.w_ports['spr1'].en
147 self.r_ports['spr1'].data_o = self.w_ports['spr1'].data
148
149
150 # class containing all regfiles: int, cr, xer, fast, spr
151 class RegFiles:
152 def __init__(self):
153 self.rf = {}
154 for (name, kls) in [('int', IntRegs),
155 ('cr', CRRegs),
156 ('xer', XERRegs),
157 ('fast', FastRegs),
158 ('spr', SPRRegs),]:
159 rf = self.rf[name] = kls()
160 setattr(self, name, rf)
161
162 def elaborate_into(self, m, platform):
163 for (name, rf) in self.rf.items():
164 setattr(m.submodules, name, rf)
165 return m
166