got sv.bc working for pospopcount
[openpower-isa.git] / src / openpower / decoder / power_svp64_extra.py
index 620f0660c4b7113327f8b0a04bb3c6aacfbf6741..71903f0a3d7df2b2e12eca09452b5b60f4077b8b 100644 (file)
@@ -8,7 +8,7 @@ from nmutil.util import sel
 
 from openpower.decoder.power_enums import (SVEXTRA, SVEType)
 from openpower.consts import (SPEC, EXTRA2, EXTRA3, SVP64P, field,
-                        SPEC_SIZE, SPECb, SPEC_AUG_SIZE, SVP64CROffs)
+                              SPEC_SIZE, SPECb, SPEC_AUG_SIZE, SVP64CROffs)
 
 
 class SVP64ExtraSpec(Elaboratable):
@@ -18,11 +18,12 @@ class SVP64ExtraSpec(Elaboratable):
 
     see https://libre-soc.org/openpower/sv/svp64/
     """
+
     def __init__(self):
-        self.extra   = Signal(9, reset_less=True)
-        self.etype   = Signal(SVEType, reset_less=True) # 2 or 3 bits
-        self.idx     = Signal(SVEXTRA, reset_less=True) # which part of extra
-        self.spec  = Signal(3) # EXTRA spec for the register
+        self.extra = Signal(9, reset_less=True)
+        self.etype = Signal(SVEType, reset_less=True)  # 2 or 3 bits
+        self.idx = Signal(SVEXTRA, reset_less=True)  # which part of extra
+        self.spec = Signal(3)  # EXTRA spec for the register
 
     def elaborate(self, platform):
         m = Module()
@@ -37,19 +38,25 @@ class SVP64ExtraSpec(Elaboratable):
         with m.Switch(self.etype):
             # 2-bit index selection mode
             with m.Case(SVEType.EXTRA2):
+                extra2_lsb = Signal(1)
                 with m.Switch(self.idx):
                     with m.Case(SVEXTRA.Idx0):  # 1st 2 bits [0:1]
                         comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX0_VEC])
-                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX0_MSB])
+                        comb += extra2_lsb.eq(extra[EXTRA2.IDX0_MSB])
                     with m.Case(SVEXTRA.Idx1):  # 2nd 2 bits [2:3]
                         comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX1_VEC])
-                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX1_MSB])
+                        comb += extra2_lsb.eq(extra[EXTRA2.IDX1_MSB])
                     with m.Case(SVEXTRA.Idx2):  # 3rd 2 bits [4:5]
                         comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX2_VEC])
-                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX2_MSB])
+                        comb += extra2_lsb.eq(extra[EXTRA2.IDX2_MSB])
                     with m.Case(SVEXTRA.Idx3):  # 4th 2 bits [6:7]
                         comb += spec[SPEC.VEC].eq(extra[EXTRA2.IDX3_VEC])
-                        comb += spec[SPEC.MSB].eq(extra[EXTRA2.IDX3_MSB])
+                        comb += extra2_lsb.eq(extra[EXTRA2.IDX3_MSB])
+                with m.If(spec[SPEC.VEC]):  # vector mode
+                    # can express reg numbers range(0, 127, 2)
+                    comb += spec[SPEC.MSB].eq(extra2_lsb)
+                with m.Else():  # scalar mode: can express r0-63
+                    comb += spec[SPEC.LSB].eq(extra2_lsb)
             # 3-bit index selection mode
             with m.Case(SVEType.EXTRA3):
                 with m.Switch(self.idx):
@@ -78,14 +85,15 @@ class SVP64RegExtra(SVP64ExtraSpec):
 
     see https://libre-soc.org/openpower/sv/svp64/
     """
+
     def __init__(self):
         SVP64ExtraSpec.__init__(self)
-        self.reg_in  = Signal(5) # incoming reg number (5 bits, RA, RB)
-        self.reg_out = Signal(7) # extra-augmented output (7 bits)
-        self.isvec   = Signal(1) # reg is marked as vector if true
+        self.reg_in = Signal(5)  # incoming reg number (5 bits, RA, RB)
+        self.reg_out = Signal(7)  # extra-augmented output (7 bits)
+        self.isvec = Signal(1)  # reg is marked as vector if true
 
     def elaborate(self, platform):
-        m = super().elaborate(platform) # select required EXTRA2/3
+        m = super().elaborate(platform)  # select required EXTRA2/3
         comb = m.d.comb
 
         # first get the spec.  if not changed it's "scalar identity behaviour"
@@ -105,11 +113,8 @@ class SVP64RegExtra(SVP64ExtraSpec):
         with m.If(self.isvec):
             # Vector: shifted up, extra in LSBs (RA << 2) | spec[1:2]
             comb += self.reg_out.eq(Cat(spec_aug, self.reg_in))
-        with m.Elif(self.etype == SVEType.EXTRA2):
-            # Scalar EXTRA2: not shifted up, extra in MSBs RA | (spec[1] << 5)
-            comb += self.reg_out.eq(Cat(self.reg_in, spec_aug[1]))
-        with m.Elif(self.etype == SVEType.EXTRA3):
-            # Scalar EXTRA3: not shifted up, extra in MSBs RA | (spec[1:2] << 5)
+        with m.Else():
+            # Scalar: not shifted up, extra in MSBs RA | (spec[1:2] << 5)
             comb += self.reg_out.eq(Cat(self.reg_in, spec_aug))
 
         return m
@@ -128,14 +133,15 @@ class SVP64CRExtra(SVP64ExtraSpec):
 
     see https://libre-soc.org/openpower/sv/svp64/appendix
     """
+
     def __init__(self):
         SVP64ExtraSpec.__init__(self)
-        self.cr_in  = Signal(3) # incoming CR number (3 bits, BA[0:2], BFA)
-        self.cr_out = Signal(7) # extra-augmented CR output (7 bits)
-        self.isvec  = Signal(1) # reg is marked as vector if true
+        self.cr_in = Signal(3)  # incoming CR number (3 bits, BA[0:2], BFA)
+        self.cr_out = Signal(7)  # extra-augmented CR output (7 bits)
+        self.isvec = Signal(1)  # reg is marked as vector if true
 
     def elaborate(self, platform):
-        m = super().elaborate(platform) # select required EXTRA2/3
+        m = super().elaborate(platform)  # select required EXTRA2/3
         comb = m.d.comb
 
         # first get the spec.  if not changed it's "scalar identity behaviour"