0266e3f8bda51263b71e66a23bb7c000575ea40c
[openpower-isa.git] / src / openpower / decoder / power_regspec_map.py
1 """regspec_decode
2
3 functions for the relationship between regspecs and Decode2Execute1Type
4
5 these functions encodes the understanding (relationship) between
6 Regfiles, Computation Units, and the Power ISA Decoder (PowerDecoder2).
7
8 based on the regspec, which contains the register file name and register
9 name, return a tuple of:
10
11 * how the decoder should determine whether the Function Unit needs
12 access to a given Regport or not
13 * which Regfile number on that port should be read to get that data
14 * when it comes to writing: likewise, which Regfile num should be written
15
16 Note that some of the port numbering encoding is *unary*. in the case
17 of "Full Condition Register", it's a full 8-bit mask of read/write-enables.
18 This actually matches directly with the XFX field in MTCR, and at
19 some point that 8-bit mask from the instruction could actually be passed
20 directly through to full_cr (TODO).
21
22 For the INT and CR numbering, these are expressed in binary in the
23 instruction and need to be converted to unary (1<<read_reg1.data).
24 Note however that XFX in MTCR is unary-masked!
25
26 XER regs are implicitly-encoded (hard-coded) based on whether the
27 operation has carry or overflow.
28
29 FAST regfile is, again, implicitly encoded, back in PowerDecode2, based
30 on the type of operation (see DecodeB for an example, where fast_out
31 is set, then carried into read_fast2 in PowerDecode2).
32
33 The SPR regfile on the other hand is *binary*-encoded, and, furthermore,
34 has to be "remapped" to internal SPR Enum indices (see SPRMap in PowerDecode2)
35 see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
36 """
37 from nmigen import Const, Signal
38 from openpower.consts import XERRegsEnum, FastRegsEnum, StateRegsEnum
39 from openpower.decoder.power_enums import CryIn
40 from openpower.util import log
41 from collections import namedtuple
42
43 RegDecodeInfo = namedtuple("RedDecodeInfo", ['okflag', 'regport', 'portlen'])
44
45 # XXX TODO: these portlen numbers *must* increase / adapt for SVP64.
46
47 def regspec_decode_read(m, e, regfile, name):
48 """regspec_decode_read
49 """
50
51 rd = None
52
53 # INT regfile
54
55 if regfile == 'INT':
56 # Int register numbering is *unary* encoded
57 if name == 'ra': # RA
58 rd = RegDecodeInfo(e.read_reg1.ok, e.read_reg1.data, 5)
59 if name == 'rb': # RB
60 rd = RegDecodeInfo(e.read_reg2.ok, e.read_reg2.data, 5)
61 if name == 'rc': # RS
62 rd = RegDecodeInfo(e.read_reg3.ok, e.read_reg3.data, 5)
63
64 # CR regfile
65
66 if regfile == 'CR':
67 # CRRegs register numbering is *unary* encoded
68 if name == 'full_cr': # full CR (from FXM field)
69 rd = RegDecodeInfo(e.do.read_cr_whole.ok,
70 e.do.read_cr_whole.data, 8)
71 if name == 'cr_a': # CR A
72 rd = RegDecodeInfo(e.read_cr1.ok, 1<<(7-e.read_cr1.data), 8)
73 if name == 'cr_b': # CR B
74 rd = RegDecodeInfo(e.read_cr2.ok, 1<<(7-e.read_cr2.data), 8)
75 if name == 'cr_c': # CR C
76 rd = RegDecodeInfo(e.read_cr3.ok, 1<<(7-e.read_cr3.data), 8)
77
78 # XER regfile
79
80 if regfile == 'XER':
81 # XERRegsEnum register numbering is *unary* encoded
82 SO = 1<<XERRegsEnum.SO
83 CA = 1<<XERRegsEnum.CA
84 OV = 1<<XERRegsEnum.OV
85 if name == 'xer_so':
86 # SO needs to be read for overflow *and* for creation
87 # of CR0 and also for MFSPR
88 rd = RegDecodeInfo(((e.do.oe.oe[0] & e.do.oe.ok) |
89 (e.xer_in & SO == SO)|
90 (e.do.rc.rc & e.do.rc.ok)), SO, 3)
91 if name == 'xer_ov':
92 rd = RegDecodeInfo(((e.do.oe.oe[0] & e.do.oe.ok) |
93 (e.xer_in & CA == CA)), OV, 3)
94 if name == 'xer_ca':
95 rd = RegDecodeInfo(((e.do.input_carry == CryIn.CA.value) |
96 (e.xer_in & OV == OV)), CA, 3)
97
98 # STATE regfile
99
100 if regfile == 'STATE':
101 # STATE register numbering is *unary* encoded
102 PC = 1<<StateRegsEnum.PC
103 MSR = 1<<StateRegsEnum.MSR
104 SVSTATE = 1<<StateRegsEnum.SVSTATE
105 if name in ['cia', 'nia']:
106 # TODO: detect read-conditions
107 rd = RegDecodeInfo(Const(1), PC, 3)
108 if name == 'msr':
109 # TODO: detect read-conditions
110 rd = RegDecodeInfo(Const(1), MSR, 3)
111 if name == 'svstate':
112 # TODO: detect read-conditions
113 rd = RegDecodeInfo(Const(1), SVSTATE, 3)
114
115 # FAST regfile
116
117 if regfile == 'FAST':
118 # FAST register numbering is *unary* encoded
119 if name == 'fast1':
120 rd = RegDecodeInfo(e.read_fast1.ok, e.read_fast1.data, 4)
121 if name == 'fast2':
122 rd = RegDecodeInfo(e.read_fast2.ok, e.read_fast2.data, 4)
123 if name == 'fast3':
124 rd = RegDecodeInfo(e.read_fast3.ok, e.read_fast3.data, 4)
125
126 # SPR regfile
127
128 if regfile == 'SPR':
129 # SPR register numbering is *binary* encoded
130 if name == 'spr1':
131 rd = RegDecodeInfo(e.read_spr1.ok, e.read_spr1.data, 10)
132
133 assert rd is not None, "regspec not found %s %s" % (regfile, name)
134
135 rname="rd_decode_%s_%s" % (regfile, name)
136 ok = Signal(name=rname+"_ok", reset_less=True)
137 data = Signal(rd.portlen, name=rname+"_port", reset_less=True)
138 m.d.comb += ok.eq(rd.okflag)
139 m.d.comb += data.eq(rd.regport)
140
141 return RegDecodeInfo(ok, data, rd.portlen)
142
143
144 def regspec_decode_write(m, e, regfile, name):
145 """regspec_decode_write
146 """
147
148 #log("regspec_decode_write", regfile, name, e.__class__.__name__)
149
150 # INT regfile
151
152 if regfile == 'INT':
153 # Int register numbering is *unary* encoded
154 if name == 'o': # RT
155 rd = RegDecodeInfo(e.write_reg.ok, e.write_reg.data, 5)
156 if name == 'o1': # RA (update mode: LD/ST EA)
157 rd = RegDecodeInfo(e.write_ea.ok, e.write_ea.data, 5)
158
159 # CR regfile
160
161 if regfile == 'CR':
162 # CRRegs register numbering is *unary* encoded
163 # *sigh*. numbering inverted on part-CRs. because POWER.
164 if name == 'full_cr': # full CR (from FXM field)
165 rd = RegDecodeInfo(e.do.write_cr_whole.ok,
166 e.do.write_cr_whole.data, 8)
167 if name == 'cr_a': # CR A
168 rd = RegDecodeInfo(e.write_cr.ok,
169 1<<(7-e.write_cr.data), 8)
170
171 # XER regfile
172
173 if regfile == 'XER':
174 # XERRegsEnum register numbering is *unary* encoded
175 SO = 1<<XERRegsEnum.SO
176 CA = 1<<XERRegsEnum.CA
177 OV = 1<<XERRegsEnum.OV
178 if name == 'xer_so':
179 rd = RegDecodeInfo(e.xer_out | (e.do.oe.oe[0] & e.do.oe.ok),
180 SO, 3) # hmmm
181 if name == 'xer_ov':
182 rd = RegDecodeInfo(e.xer_out | (e.do.oe.oe[0] & e.do.oe.ok),
183 OV, 3) # hmmm
184 if name == 'xer_ca':
185 rd = RegDecodeInfo(e.xer_out | (e.do.output_carry),
186 CA, 3) # hmmm
187
188 # STATE regfile
189
190 if regfile == 'STATE':
191 # STATE register numbering is *unary* encoded
192 PC = 1<<StateRegsEnum.PC
193 MSR = 1<<StateRegsEnum.MSR
194 SVSTATE = 1<<StateRegsEnum.SVSTATE
195 if name in ['cia', 'nia']:
196 rd = RegDecodeInfo(None, PC, 3) # hmmm
197 if name == 'msr':
198 rd = RegDecodeInfo(None, MSR, 3) # hmmm
199 if name == 'svstate':
200 rd = RegDecodeInfo(None, SVSTATE, 3) # hmmm
201
202 # FAST regfile
203
204 if regfile == 'FAST':
205 # FAST register numbering is *unary* encoded
206 if name == 'fast1':
207 rd = RegDecodeInfo(e.write_fast1.ok, e.write_fast1.data, 4)
208 if name == 'fast2':
209 rd = RegDecodeInfo(e.write_fast2.ok, e.write_fast2.data, 4)
210 if name == 'fast3':
211 rd = RegDecodeInfo(e.write_fast3.ok, e.write_fast3.data, 4)
212
213 # SPR regfile
214
215 if regfile == 'SPR':
216 # SPR register numbering is *binary* encoded
217 if name == 'spr1': # SPR1
218 rd = RegDecodeInfo(e.write_spr.ok, e.write_spr.data, 10)
219
220 assert rd is not None, "regspec not found %s %s" % (regfile, name)
221
222 return rd
223
224
225 def regspec_decode(m, readmode, e, regfile, name):
226 if readmode:
227 return regspec_decode_read(m, e, regfile, name)
228 return regspec_decode_write(m, e, regfile, name)
229