1 """SVP64 EXTRA field decoder
4 from nmigen
import Module
, Elaboratable
, Signal
, Mux
, Const
, Cat
5 from nmigen
.cli
import rtlil
6 from nmutil
.util
import sel
9 from soc
.decoder
.power_enums
import (SVEXTRA
, SVEtype
)
10 from soc
.consts
import (SPEC
, EXTRA2
, EXTRA3
, SVP64P
, field
,
11 SPEC_SIZE
, SPECb
, SPEC_AUG_SIZE
, SVP64CROffs
)
14 class SVP64ExtraSpec(Elaboratable
):
15 """SVP64ExtraSpec - decodes SVP64 Extra specification.
17 selects the required EXTRA2/3 field.
19 see https://libre-soc.org/openpower/sv/svp64/
22 self
.extra
= Signal(9, reset_less
=True)
23 self
.etype
= Signal(SVEtype
, reset_less
=True) # 2 or 3 bits
24 self
.idx
= Signal(SVEXTRA
, reset_less
=True) # which part of extra
25 self
.spec
= Signal(3) # EXTRA spec for the register
27 def elaborate(self
, platform
):
33 # back in the LDSTRM-* and RM-* files generated by sv_analysis.py
34 # we marked every op with an Etype: EXTRA2 or EXTRA3, and also said
35 # which of the 4 (or 3 for EXTRA3) sub-fields of bits 10:18 contain
36 # the register-extension information. extract those now
37 with m
.Switch(self
.etype
):
38 # 2-bit index selection mode
39 with m
.Case(SVEtype
.EXTRA2
):
40 with m
.Switch(self
.idx
):
41 with m
.Case(SVEXTRA
.Idx0
): # 1st 2 bits [0:1]
42 comb
+= spec
[SPEC
.VEC
].eq(extra
[EXTRA2
.IDX0_VEC
])
43 comb
+= spec
[SPEC
.MSB
].eq(extra
[EXTRA2
.IDX0_MSB
])
44 with m
.Case(SVEXTRA
.Idx1
): # 2nd 2 bits [2:3]
45 comb
+= spec
[SPEC
.VEC
].eq(extra
[EXTRA2
.IDX1_VEC
])
46 comb
+= spec
[SPEC
.MSB
].eq(extra
[EXTRA2
.IDX1_MSB
])
47 with m
.Case(SVEXTRA
.Idx2
): # 3rd 2 bits [4:5]
48 comb
+= spec
[SPEC
.VEC
].eq(extra
[EXTRA2
.IDX2_VEC
])
49 comb
+= spec
[SPEC
.MSB
].eq(extra
[EXTRA2
.IDX2_MSB
])
50 with m
.Case(SVEXTRA
.Idx3
): # 4th 2 bits [6:7]
51 comb
+= spec
[SPEC
.VEC
].eq(extra
[EXTRA2
.IDX3_VEC
])
52 comb
+= spec
[SPEC
.MSB
].eq(extra
[EXTRA2
.IDX3_MSB
])
53 # 3-bit index selection mode
54 with m
.Case(SVEtype
.EXTRA3
):
55 with m
.Switch(self
.idx
):
56 with m
.Case(SVEXTRA
.Idx0
): # 1st 3 bits [0:2]
57 extra3_idx0
= sel(m
, extra
, EXTRA3
.IDX0
)
58 comb
+= spec
.eq(extra3_idx0
)
59 with m
.Case(SVEXTRA
.Idx1
): # 2nd 3 bits [3:5]
60 extra3_idx1
= sel(m
, extra
, EXTRA3
.IDX1
)
61 comb
+= spec
.eq(extra3_idx1
)
62 with m
.Case(SVEXTRA
.Idx2
): # 3rd 3 bits [6:8]
63 extra3_idx2
= sel(m
, extra
, EXTRA3
.IDX2
)
64 comb
+= spec
.eq(extra3_idx2
)
65 # cannot fit more than 9 bits so there is no 4th thing
70 class SVP64RegExtra(SVP64ExtraSpec
):
71 """SVP64RegExtra - decodes SVP64 Extra fields to determine reg extension
73 incoming 5-bit GPR/FP is turned into a 7-bit and marked as scalar/vector
74 depending on info in one of the positions in the EXTRA field.
76 designed so that "no change" to the 5-bit register number occurs if
77 SV either does not apply or the relevant EXTRA2/3 field bits are zero.
79 see https://libre-soc.org/openpower/sv/svp64/
82 SVP64ExtraSpec
.__init
__(self
)
83 self
.reg_in
= Signal(5) # incoming reg number (5 bits, RA, RB)
84 self
.reg_out
= Signal(7) # extra-augmented output (7 bits)
85 self
.isvec
= Signal(1) # reg is marked as vector if true
87 def elaborate(self
, platform
):
88 m
= super().elaborate(platform
) # select required EXTRA2/3
91 # first get the spec. if not changed it's "scalar identity behaviour"
92 # which is zero which is ok.
95 # now decode it. bit 0 is "scalar/vector". note that spec could be zero
96 # from above, which (by design) has the effect of "no change", below.
98 # simple: isvec is top bit of spec
99 comb
+= self
.isvec
.eq(spec
[SPEC
.VEC
])
100 # extra bits for register number augmentation
101 spec_aug
= Signal(SPEC_AUG_SIZE
)
102 comb
+= spec_aug
.eq(field(spec
, SPECb
.MSB
, SPECb
.LSB
, SPEC_SIZE
))
104 # decode vector differently from scalar
105 with m
.If(self
.isvec
):
106 # Vector: shifted up, extra in LSBs (RA << 2) | spec[1:2]
107 comb
+= self
.reg_out
.eq(Cat(spec_aug
, self
.reg_in
))
109 # Scalar: not shifted up, extra in MSBs RA | (spec[1:2] << 5)
110 comb
+= self
.reg_out
.eq(Cat(self
.reg_in
, spec_aug
))
115 class SVP64CRExtra(SVP64ExtraSpec
):
116 """SVP64CRExtra - decodes SVP64 Extra fields to determine CR extension
118 incoming 3-bit CR is turned into a 7-bit and marked as scalar/vector
119 depending on info in one of the positions in the EXTRA field.
121 yes, really, 128 CRs. INT is 128, FP is 128, therefore CRs are 128.
123 designed so that "no change" to the 3-bit CR register number occurs if
124 SV either does not apply or the relevant EXTRA2/3 field bits are zero.
126 see https://libre-soc.org/openpower/sv/svp64/appendix
129 SVP64ExtraSpec
.__init
__(self
)
130 self
.cr_in
= Signal(3) # incoming CR number (3 bits, BA[0:2], BFA)
131 self
.cr_out
= Signal(7) # extra-augmented CR output (7 bits)
132 self
.isvec
= Signal(1) # reg is marked as vector if true
134 def elaborate(self
, platform
):
135 m
= super().elaborate(platform
) # select required EXTRA2/3
138 # first get the spec. if not changed it's "scalar identity behaviour"
139 # which is zero which is ok.
142 # now decode it. bit 0 is "scalar/vector". note that spec could be zero
143 # from above, which (by design) has the effect of "no change", below.
145 # simple: isvec is top bit of spec
146 comb
+= self
.isvec
.eq(spec
[SPEC
.VEC
])
147 # extra bits for register number augmentation
148 spec_aug
= Signal(SPEC_AUG_SIZE
)
149 comb
+= spec_aug
.eq(field(spec
, SPECb
.MSB
, SPECb
.LSB
, SPEC_SIZE
))
151 # decode vector differently from scalar, insert bits 1 and 2 accordingly
152 with m
.If(self
.isvec
):
153 # Vector: shifted up, extra in LSBs (CR << 4) | (spec[1:2] << 2)
154 comb
+= self
.cr_out
.eq(Cat(Const(0, 2), spec_aug
, self
.cr_in
))
156 # Scalar: not shifted up, extra in MSBs CR | (spec[1:2] << 3)
157 comb
+= self
.cr_out
.eq(Cat(self
.cr_in
, spec_aug
))
162 if __name__
== '__main__':
163 pdecode
= create_pdecode()
164 dec2
= PowerDecode2(pdecode
)
165 vl
= rtlil
.convert(dec2
, ports
=dec2
.ports() + pdecode
.ports())
166 with
open("dec2.il", "w") as f
: