3 functions for the relationship between regspecs and Decode2Execute1Type
5 these functions encodes the understanding (relationship) between
6 Regfiles, Computation Units, and the Power ISA Decoder (PowerDecoder2).
8 based on the regspec, which contains the register file name and register
9 name, return a tuple of:
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
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).
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!
26 XER regs are implicitly-encoded (hard-coded) based on whether the
27 operation has carry or overflow.
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).
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-so:.org/3d_gpu/architecture/regfile/ section on regspecs
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
43 RegDecodeInfo
= namedtuple("RedDecodeInfo", ['okflag', 'regport', 'portlen'])
45 # XXX TODO: these portlen numbers *must* increase / adapt for SVP64.
47 def regspec_decode_read(m
, e
, regfile
, name
):
48 """regspec_decode_read
56 # Int register numbering is *unary* encoded
58 rd
= RegDecodeInfo(e
.read_reg1
.ok
, e
.read_reg1
.data
, 5)
60 rd
= RegDecodeInfo(e
.read_reg2
.ok
, e
.read_reg2
.data
, 5)
62 rd
= RegDecodeInfo(e
.read_reg3
.ok
, e
.read_reg3
.data
, 5)
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)
81 # XERRegsEnum register numbering is *unary* encoded
82 SO
= 1<<XERRegsEnum
.SO
83 CA
= 1<<XERRegsEnum
.CA
84 OV
= 1<<XERRegsEnum
.OV
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)
92 rd
= RegDecodeInfo(((e
.do
.oe
.oe
[0] & e
.do
.oe
.ok
) |
93 (e
.xer_in
& CA
== CA
)), OV
, 3)
95 rd
= RegDecodeInfo(((e
.do
.input_carry
== CryIn
.CA
.value
) |
96 (e
.xer_in
& OV
== OV
)), CA
, 3)
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)
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)
117 if regfile
== 'FAST':
118 # FAST register numbering is *unary* encoded
120 rd
= RegDecodeInfo(e
.read_fast1
.ok
, e
.read_fast1
.data
, 4)
122 rd
= RegDecodeInfo(e
.read_fast2
.ok
, e
.read_fast2
.data
, 4)
124 rd
= RegDecodeInfo(e
.read_fast3
.ok
, e
.read_fast3
.data
, 4)
129 # SPR register numbering is *binary* encoded
131 rd
= RegDecodeInfo(e
.read_spr1
.ok
, e
.read_spr1
.data
, 10)
133 assert rd
is not None, "regspec not found %s %s" % (regfile
, name
)
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
)
141 return RegDecodeInfo(ok
, data
, rd
.portlen
)
144 def regspec_decode_write(m
, e
, regfile
, name
):
145 """regspec_decode_write
148 #log("regspec_decode_write", regfile, name, e.__class__.__name__)
154 # Int register numbering is *unary* encoded
156 wr
= RegDecodeInfo(e
.write_reg
.ok
, e
.write_reg
.data
, 5)
157 if name
== 'o1': # RA (update mode: LD/ST EA)
158 wr
= RegDecodeInfo(e
.write_ea
.ok
, e
.write_ea
.data
, 5)
163 # CRRegs register numbering is *unary* encoded
164 # *sigh*. numbering inverted on part-CRs. because POWER.
165 if name
== 'full_cr': # full CR (from FXM field)
166 wr
= RegDecodeInfo(e
.do
.write_cr_whole
.ok
,
167 e
.do
.write_cr_whole
.data
, 8)
168 if name
== 'cr_a': # CR A
169 wr
= RegDecodeInfo(e
.write_cr
.ok
,
170 1<<(7-e
.write_cr
.data
), 8)
175 # XERRegsEnum register numbering is *unary* encoded
176 SO
= 1<<XERRegsEnum
.SO
177 CA
= 1<<XERRegsEnum
.CA
178 OV
= 1<<XERRegsEnum
.OV
180 wr
= RegDecodeInfo(e
.xer_out |
(e
.do
.oe
.oe
[0] & e
.do
.oe
.ok
),
183 wr
= RegDecodeInfo(e
.xer_out |
(e
.do
.oe
.oe
[0] & e
.do
.oe
.ok
),
186 wr
= RegDecodeInfo(e
.xer_out |
(e
.do
.output_carry
),
191 if regfile
== 'STATE':
192 # STATE register numbering is *unary* encoded
193 PC
= 1<<StateRegsEnum
.PC
194 MSR
= 1<<StateRegsEnum
.MSR
195 SVSTATE
= 1<<StateRegsEnum
.SVSTATE
196 if name
in ['cia', 'nia']:
197 wr
= RegDecodeInfo(None, PC
, 3) # hmmm
199 wr
= RegDecodeInfo(None, MSR
, 3) # hmmm
200 if name
== 'svstate':
201 wr
= RegDecodeInfo(None, SVSTATE
, 3) # hmmm
205 if regfile
== 'FAST':
206 # FAST register numbering is *unary* encoded
208 wr
= RegDecodeInfo(e
.write_fast1
.ok
, e
.write_fast1
.data
, 4)
210 wr
= RegDecodeInfo(e
.write_fast2
.ok
, e
.write_fast2
.data
, 4)
212 wr
= RegDecodeInfo(e
.write_fast3
.ok
, e
.write_fast3
.data
, 4)
217 # SPR register numbering is *binary* encoded
218 if name
== 'spr1': # SPR1
219 wr
= RegDecodeInfo(e
.write_spr
.ok
, e
.write_spr
.data
, 10)
221 assert wr
is not None, "regspec not found %s %s" % (regfile
, name
)
223 rname
="wr_decode_%s_%s" % (regfile
, name
)
224 if wr
.okflag
is not None:
225 ok
= Signal(name
=rname
+"_ok", reset_less
=True)
226 m
.d
.comb
+= ok
.eq(wr
.okflag
)
228 # XXX urrrr, really do have to deal with this some time
230 data
= Signal(wr
.portlen
, name
=rname
+"_port", reset_less
=True)
231 m
.d
.comb
+= data
.eq(wr
.regport
)
233 return RegDecodeInfo(ok
, data
, wr
.portlen
)
236 def regspec_decode(m
, readmode
, e
, regfile
, name
):
238 return regspec_decode_read(m
, e
, regfile
, name
)
239 return regspec_decode_write(m
, e
, regfile
, name
)