+"""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_dct_yield import (
iterate_dct_inner_butterfly_indices,
iterate_dct_inner_costable_indices,
- iterate_dct_outer_butterfly_indices)
+ iterate_dct_outer_butterfly_indices,
+ iterate_dct_inner_halfswap_loadstore)
from openpower.sv.svp64 import SVP64SHAPE
import os
from copy import deepcopy
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 = {}
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)
@property
def order(self):
permute = self.fsi['permute'].asint(msb0=True)
+ if self.is_indexed():
+ permute = (permute-0b110)*2 # xyz or yxz
return SVP64SHAPE.order(permute)
@order.setter
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):
@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
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
def offset(self, value):
self.fsi['offset'].eq(value)
+ def postprocess(self, idx, step):
+ if self.mode != 0b00 or not self.is_indexed():
+ return idx
+ if self.gpr is None:
+ return idx
+ if self.xdimsz == 1 and self.ydimsz == 1:
+ idx = step # no Index remapping
+ 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)
+ log ("SVSHAPE get_iterator", self.mode, self.ydimsz, self.is_indexed())
if self.mode == 0b00:
iterate_fn = iterate_indices
- elif self.mode == 0b01:
+ elif self.mode in [0b01, 0b11]:
# further sub-selection
if self.ydimsz == 1:
iterate_fn = iterate_butterfly_indices
iterate_fn = iterate_dct_inner_butterfly_indices
elif self.ydimsz == 3:
iterate_fn = iterate_dct_outer_butterfly_indices
- elif self.ydimsz == 5:
+ 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 = 3
+ ydim = 2000
+ 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] # xy inversion (indices 0,1) , skip if desired (2)
+
+ VL = 6 # 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
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
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")
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