fix SVSHAPE iterator for index case, stop deepcopy
[openpower-isa.git] / src / openpower / decoder / isa / svshape.py
index 03dbbb0b1513e86ffca786434c2a584d32387688..7e9ad3227a1431aeaff5b827fceb5bd985b5246b 100644 (file)
@@ -1,33 +1,68 @@
+"""provides convenient field mappings for SVSHAPE in different modes
+
+the trickiest is Indexed mode which sits inside Matrix using two of
+permute options to activate.
+
+https://libre-soc.org/openpower/sv/remap
+"""
+
 from openpower.decoder.selectable_int import (FieldSelectableInt, SelectableInt,
                                         selectconcat)
 from openpower.decoder.isa.remapyield import iterate_indices
 from openpower.decoder.isa.remap_fft_yield import iterate_butterfly_indices
-from openpower.sv.svp64 import SVP64REMAP
+from openpower.decoder.isa.remap_dct_yield import (
+                                iterate_dct_inner_butterfly_indices,
+                                iterate_dct_inner_costable_indices,
+                                iterate_dct_outer_butterfly_indices,
+                                iterate_dct_inner_halfswap_loadstore)
+from openpower.sv.svp64 import SVP64SHAPE
 import os
 from copy import deepcopy
+from openpower.util import log
 
 
 class SVSHAPE(SelectableInt):
-    def __init__(self, value):
+    def __init__(self, value, gpr=None):
         SelectableInt.__init__(self, value, 32)
+        self.gpr = gpr # for Indexed mode
         offs = 0
         # set up sub-fields from Record layout
         self.fsi = {}
-        l = deepcopy(SVP64REMAP.layout)
+        l = deepcopy(SVP64SHAPE.layout)
         l.reverse()
         for field, width in l:
-            v = FieldSelectableInt(self, tuple(range(offs, offs+width)))
+            end =  offs+width
+            fs = tuple(range(offs, end))
+            v = FieldSelectableInt(self, fs)
             self.fsi[field] = v
-            offs += width
+            log("SVSHAPE setup field", field, offs, end)
+            offs = end
+
+    def copy(self):
+        return SVSHAPE(self.value, self.gpr)
+
+    def is_indexed(self):
+        "REMAP Indexed Mode"
+        return self.mode == 0b00 and self.submode2 in [0b110, 0b111]
+
+    @property
+    def submode2(self):
+        return self.fsi['permute'].asint(msb0=True)
+
+    @submode2.setter
+    def submode2(self, value):
+        self.fsi['permute'].eq(value)
 
     @property
     def order(self):
         permute = self.fsi['permute'].asint(msb0=True)
-        return SVP64REMAP.order(permute)
+        if self.is_indexed():
+            permute = (permute-0b110)*2 # xyz or yxz
+        return SVP64SHAPE.order(permute)
 
     @order.setter
     def order(self, value):
-        rorder = SVP64REMAP.rorder(value)
+        rorder = SVP64SHAPE.rorder(value)
         self.fsi['permute'].eq(rorder)
 
     @property
@@ -46,9 +81,16 @@ class SVSHAPE(SelectableInt):
     def ydimsz(self, value):
         self.fsi['ydimsz'].eq(value-1)
 
+    @property
+    def svgpr(self):
+        return self.fsi['zdimsz'].asint(msb0=True) << 1
+
     @property
     def zdimsz(self):
-        return self.fsi['zdimsz'].asint(msb0=True)+1
+        z = self.fsi['zdimsz'].asint(msb0=True)+1
+        if self.is_indexed():
+            z = 1 # no z dimension when indexed
+        return z
 
     @zdimsz.setter
     def zdimsz(self, value):
@@ -67,6 +109,8 @@ class SVSHAPE(SelectableInt):
     @property
     def invxyz(self):
         inv = self.fsi['invxyz'].asint(msb0=True)
+        if self.is_indexed():
+            inv &= 0b011 # no 3rd z in indexed mode
         return [(inv & 0b1), (inv & 0b10) >> 1, (inv & 0b100) >> 2]
 
     @invxyz.setter
@@ -81,8 +125,15 @@ class SVSHAPE(SelectableInt):
     def mode(self, value):
         self.fsi['mode'].eq(value)
 
+    @property
+    def elwid(self):
+        return self.fsi['skip'].asint(msb0=True)
+
     @property
     def skip(self):
+        if self.is_indexed():
+            inv = self.fsi['invxyz'].asint(msb0=True)
+            return (inv & 0b100) >> 2
         return self.fsi['skip'].asint(msb0=True)
 
     @skip.setter
@@ -97,17 +148,59 @@ class SVSHAPE(SelectableInt):
     def offset(self, value):
         self.fsi['offset'].eq(value)
 
+    def postprocess(self, idx):
+        if self.mode != 0b00 or not self.is_indexed():
+            return idx
+        if self.gpr is None:
+            return idx
+        remap = self.gpr(self.svgpr+idx).value # TODO: elwidths
+        log ("indexed_iterator", self.svgpr, idx, remap)
+        return remap
+
     def get_iterator(self):
+        log ("SVSHAPE get_iterator", self.mode, self.ydimsz, self.is_indexed())
         if self.mode == 0b00:
             iterate_fn = iterate_indices
-        elif self.mode == 0b01:
-            iterate_fn = iterate_butterfly_indices
+        elif self.mode in [0b01, 0b11]:
+            # further sub-selection
+            if self.ydimsz == 1:
+                iterate_fn = iterate_butterfly_indices
+            elif self.ydimsz in [2, 4]:
+                iterate_fn = iterate_dct_inner_butterfly_indices
+            elif self.ydimsz == 3:
+                iterate_fn = iterate_dct_outer_butterfly_indices
+            elif self.ydimsz in [5, 13]:
+                iterate_fn = iterate_dct_inner_costable_indices
+            elif self.ydimsz in [6, 14, 15]:
+                iterate_fn = iterate_dct_inner_halfswap_loadstore
         # create a **NEW** iterator each time this is called
-        return iterate_fn(deepcopy(self))
+        return iterate_fn(self.copy())
 
 
 if __name__ == '__main__':
     os.environ['SILENCELOG'] = "1"
+    xdim = 2
+    ydim = 3
+    zdim = 1
+    SVSHAPE0 = SVSHAPE(0)
+    SVSHAPE0.lims = [xdim, ydim, zdim]
+    SVSHAPE0.submode2 = 0b110 # yx indexed
+    SVSHAPE0.mode = 0b00
+    SVSHAPE0.skip = 0b00
+    SVSHAPE0.offset = 0       # experiment with different offset, here
+    SVSHAPE0.invxyz = [0,0,1] # inversion if desired
+
+    VL = xdim * ydim * zdim
+
+    print ("Matrix Indexed Mode", SVSHAPE0.order, SVSHAPE0.invxyz)
+    for idx, new_idx in enumerate(SVSHAPE0.get_iterator()):
+        if idx >= VL:
+            break
+        print ("%d->%s" % (idx, repr(new_idx)))
+
+    print ("")
+
+
     xdim = 3
     ydim = 2
     zdim = 1
@@ -117,7 +210,7 @@ if __name__ == '__main__':
     SVSHAPE0.mode = 0b00
     SVSHAPE0.skip = 0b00
     SVSHAPE0.offset = 0       # experiment with different offset, here
-    SVSHAPE0.invxyz = [0,0,0] # inversion if desired
+    SVSHAPE0.invxyz = [0,1,0] # inversion if desired
 
     VL = xdim * ydim * zdim
 
@@ -125,7 +218,7 @@ if __name__ == '__main__':
     for idx, new_idx in enumerate(SVSHAPE0.get_iterator()):
         if idx >= VL:
             break
-        print ("%d->%d" % (idx, new_idx))
+        print ("%d->%s" % (idx, repr(new_idx)))
 
     print ("")
     print ("FFT Mode")
@@ -178,7 +271,7 @@ if __name__ == '__main__':
                                           iterate_indices(SVSHAPE2))):
         if idx >= VL:
             break
-        schedule.append((jl, jh, k))
+        schedule.append((jl[0], jh[0], k[0]))
 
     # ok now pretty-print the results, with some debug output
     size = 2