1 """provides convenient field mappings for SVSHAPE in different modes
3 the trickiest is Indexed mode which sits inside Matrix using two of
4 permute options to activate.
6 https://libre-soc.org/openpower/sv/remap
9 from openpower
.decoder
.selectable_int
import (FieldSelectableInt
, SelectableInt
,
11 from openpower
.decoder
.isa
.remapyield
import iterate_indices
12 from openpower
.decoder
.isa
.remap_preduce_yield
import (iterate_indices
as
13 iterate_preduce_indices
)
14 from openpower
.decoder
.isa
.remap_preduce_yield
import (iterate_indices2
as
15 iterate_pprefix_indices
)
16 from openpower
.decoder
.isa
.remap_fft_yield
import iterate_butterfly_indices
17 from openpower
.decoder
.isa
.remap_dct_yield
import (
18 iterate_dct_inner_butterfly_indices
,
19 iterate_dct_inner_costable_indices
,
20 iterate_dct_outer_butterfly_indices
,
21 iterate_dct_inner_halfswap_loadstore
)
22 from openpower
.sv
.svp64
import SVP64SHAPE
24 from copy
import deepcopy
25 from openpower
.util
import log
28 class SVSHAPE(SelectableInt
):
29 def __init__(self
, value
, gpr
=None):
30 SelectableInt
.__init
__(self
, value
, 32)
31 self
.gpr
= gpr
# for Indexed mode
33 # set up sub-fields from Record layout
35 l
= deepcopy(SVP64SHAPE
.layout
)
37 for field
, width
in l
:
39 fs
= tuple(range(offs
, end
))
40 v
= FieldSelectableInt(self
, fs
)
42 log("SVSHAPE setup field", field
, offs
, end
)
46 return SVSHAPE(self
.value
, self
.gpr
)
50 return self
.mode
== 0b00 and self
.submode2
in [0b110, 0b111]
54 return self
.fsi
['permute'].asint(msb0
=True)
57 def submode2(self
, value
):
58 self
.fsi
['permute'].eq(value
)
62 permute
= self
.fsi
['permute'].asint(msb0
=True)
64 permute
= (permute
-0b110)*2 # xyz or yxz
65 return SVP64SHAPE
.order(permute
)
68 def order(self
, value
):
69 rorder
= SVP64SHAPE
.rorder(value
)
70 self
.fsi
['permute'].eq(rorder
)
74 return self
.fsi
['xdimsz'].asint(msb0
=True)+1
77 def xdimsz(self
, value
):
78 self
.fsi
['xdimsz'].eq(value
-1)
82 return self
.fsi
['ydimsz'].asint(msb0
=True)+1
85 def ydimsz(self
, value
):
86 self
.fsi
['ydimsz'].eq(value
-1)
90 return self
.fsi
['zdimsz'].asint(msb0
=True) << 1
94 z
= self
.fsi
['zdimsz'].asint(msb0
=True)+1
96 z
= 1 # no z dimension when indexed
100 def zdimsz(self
, value
):
101 self
.fsi
['zdimsz'].eq(value
-1)
105 return [self
.xdimsz
, self
.ydimsz
, self
.zdimsz
]
108 def lims(self
, value
):
109 self
.xdimsz
= value
[0]
110 self
.ydimsz
= value
[1]
111 self
.zdimsz
= value
[2]
115 inv
= self
.fsi
['invxyz'].asint(msb0
=True)
116 if self
.is_indexed():
117 inv
&= 0b011 # no 3rd z in indexed mode
118 return [(inv
& 0b1), (inv
& 0b10) >> 1, (inv
& 0b100) >> 2]
121 def invxyz(self
, value
):
122 self
.fsi
['invxyz'].eq(value
[0] |
(value
[1]<<1) |
(value
[2]<<2))
126 return self
.fsi
['mode'].asint(msb0
=True)
129 def mode(self
, value
):
130 self
.fsi
['mode'].eq(value
)
134 return self
.fsi
['skip'].asint(msb0
=True)
138 if self
.is_indexed():
139 inv
= self
.fsi
['invxyz'].asint(msb0
=True)
140 return (inv
& 0b100) >> 2
141 return self
.fsi
['skip'].asint(msb0
=True)
144 def skip(self
, value
):
145 assert not self
.is_indexed() # TODO
146 self
.fsi
['skip'].eq(value
)
150 return self
.fsi
['offset'].asint(msb0
=True)
153 def offset(self
, value
):
154 self
.fsi
['offset'].eq(value
)
156 def postprocess(self
, idx
, step
):
157 if self
.mode
!= 0b00 or not self
.is_indexed():
161 if self
.xdimsz
== 1 and self
.ydimsz
== 1:
162 idx
= step
# no Index 1/2D reshaping, only Indexing
163 ew_src
= 8 << (3-int(self
.elwid
)) # convert to bitlength
164 remap
= self
.gpr(self
.svgpr
, True, idx
, ew_src
).value
165 log ("indexed_iterator", self
.svgpr
, idx
, remap
, ew_src
)
168 def get_iterator(self
):
169 log ("SVSHAPE get_iterator", self
.mode
, self
.ydimsz
, self
.is_indexed())
170 if self
.mode
== 0b00:
171 iterate_fn
= iterate_indices
172 elif self
.mode
== 0b10:
173 # further sub-selection
175 iterate_fn
= iterate_pprefix_indices
# parallel-prefix
177 iterate_fn
= iterate_preduce_indices
# parallel-reduce
178 elif self
.mode
in [0b01, 0b11]:
179 # further sub-selection
181 iterate_fn
= iterate_butterfly_indices
182 elif self
.ydimsz
in [2, 4]:
183 iterate_fn
= iterate_dct_inner_butterfly_indices
184 elif self
.ydimsz
== 3:
185 iterate_fn
= iterate_dct_outer_butterfly_indices
186 elif self
.ydimsz
in [5, 13]:
187 iterate_fn
= iterate_dct_inner_costable_indices
188 elif self
.ydimsz
in [6, 14, 15]:
189 iterate_fn
= iterate_dct_inner_halfswap_loadstore
190 # create a **NEW** iterator each time this is called
191 return iterate_fn(self
.copy())
194 if __name__
== '__main__':
195 os
.environ
['SILENCELOG'] = "1"
199 SVSHAPE0
= SVSHAPE(0)
200 SVSHAPE0
.lims
= [xdim
, ydim
, zdim
]
201 SVSHAPE0
.submode2
= 0b110 # yx indexed
204 SVSHAPE0
.offset
= 0 # experiment with different offset, here
205 SVSHAPE0
.invxyz
= [0,0,1] # xy inversion (indices 0,1) , skip if desired (2)
207 VL
= 6 # xdim * ydim * zdim
209 print ("Matrix Indexed Mode", SVSHAPE0
.order
, SVSHAPE0
.invxyz
)
210 for idx
, new_idx
in enumerate(SVSHAPE0
.get_iterator()):
213 print ("%d->%s" % (idx
, repr(new_idx
)))
220 SVSHAPE0
= SVSHAPE(0)
221 SVSHAPE0
.lims
= [xdim
, ydim
, zdim
]
222 SVSHAPE0
.order
= [1,0,2] # experiment with different permutations, here
225 SVSHAPE0
.offset
= 0 # experiment with different offset, here
226 SVSHAPE0
.invxyz
= [0,1,0] # inversion if desired
228 VL
= xdim
* ydim
* zdim
230 print ("Matrix Mode")
231 for idx
, new_idx
in enumerate(SVSHAPE0
.get_iterator()):
234 print ("%d->%s" % (idx
, repr(new_idx
)))
239 # set the dimension sizes here
241 ydim
= 0 # not needed
242 zdim
= 0 # again, not needed
244 # set total. err don't know how to calculate how many there are...
245 # do it manually for now
252 tablestep
= n
// size
253 for i
in range(0, n
, size
):
254 for j
in range(i
, i
+ halfsize
):
259 SVSHAPE0
= SVSHAPE(0)
260 SVSHAPE0
.lims
= [xdim
, ydim
, zdim
]
261 SVSHAPE0
.order
= [0,1,2] # experiment with different permutations, here
263 SVSHAPE0
.offset
= 0 # experiment with different offset, here
264 SVSHAPE0
.invxyz
= [0,0,0] # inversion if desired
265 # j+halfstep schedule
266 SVSHAPE1
= SVSHAPE(0)
267 SVSHAPE1
.lims
= [xdim
, ydim
, zdim
]
268 SVSHAPE1
.order
= [0,1,2] # experiment with different permutations, here
270 SVSHAPE1
.offset
= 0 # experiment with different offset, here
271 SVSHAPE1
.invxyz
= [0,0,0] # inversion if desired
273 SVSHAPE2
= SVSHAPE(0)
274 SVSHAPE2
.lims
= [xdim
, ydim
, zdim
]
275 SVSHAPE2
.order
= [0,1,2] # experiment with different permutations, here
277 SVSHAPE2
.offset
= 0 # experiment with different offset, here
278 SVSHAPE2
.invxyz
= [0,0,0] # inversion if desired
280 # enumerate over the iterator function, getting new indices
282 for idx
, (jl
, jh
, k
) in enumerate(zip(iterate_indices(SVSHAPE0
),
283 iterate_indices(SVSHAPE1
),
284 iterate_indices(SVSHAPE2
))):
287 schedule
.append((jl
[0], jh
[0], k
[0]))
289 # ok now pretty-print the results, with some debug output
294 tablestep
= n
// size
295 print ("size %d halfsize %d tablestep %d" % \
296 (size
, halfsize
, tablestep
))
297 for i
in range(0, n
, size
):
298 prefix
= "i %d\t" % i
300 for j
in range(i
, i
+ halfsize
):
301 jl
, jh
, ks
= schedule
[idx
]
302 print (" %-3d\t%s j=%-2d jh=%-2d k=%-2d -> "
303 "j[jl=%-2d] j[jh=%-2d] exptable[k=%d]" % \
304 (idx
, prefix
, j
, j
+halfsize
, k
,