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