1 # a "yield" version of the REMAP algorithm. a little easier to read
2 # than the Finite State Machine version
4 # python "yield" can be iterated. use this to make it clear how
5 # the indices are generated by using natural-looking nested loops
6 def iterate_indices(SVSHAPE
, VL
=None):
7 # establish if this is triangular mode
8 triangle
= SVSHAPE
.mode
== 0b11 and SVSHAPE
.submode
& 0b10 == 0b10
9 bigmul
= SVSHAPE
.mode
== 0b11 and SVSHAPE
.submode
& 0b01 == 0b01
10 in_offs
= VL
is not None and SVSHAPE
.mode
== 0b11
12 # get indices to iterate over, in the required order
16 # create lists of indices to iterate over in each dimension
17 _x_r
= list(range(xd
))
18 _y_r
= list(range(yd
))
20 # invert the indices if needed
21 if SVSHAPE
.invxyz
[0]: _x_r
.reverse()
22 if SVSHAPE
.invxyz
[1]: _y_r
.reverse()
23 if SVSHAPE
.invxyz
[2]: z_r
.reverse()
24 # start an infinite (wrapping) loop
25 step
= 0 # track src/dst step
27 for zi
, z
in enumerate(z_r
): # loop over 1st order dimension
29 # triangle uses a truncated copy
30 y_r
= list(_y_r
[:zi
+1] if triangle
else _y_r
)
31 y_end
= True # if list is empty
32 for yi
, y
in enumerate(y_r
): # loop over 2nd order dimension
34 x_r
= list(_x_r
[:yi
+1] if triangle
else _x_r
)
35 x_end
= True # if list is empty
36 for xi
, x
in enumerate(x_r
): # loop over 3rd order dimension
38 # ok work out which order to construct things in.
39 # start by creating a list of tuples of the dimension
41 vals
= [(SVSHAPE
.lims
[0], x
, "x"),
42 (SVSHAPE
.lims
[1], y
, "y"),
43 (SVSHAPE
.lims
[2], z
, "z")
45 # now select those by order. this allows us to
46 # create schedules for [z][x], [x][y], or [y][z]
47 # for matrix multiply.
48 vals
= [vals
[SVSHAPE
.order
[0]],
49 vals
[SVSHAPE
.order
[1]],
50 vals
[SVSHAPE
.order
[2]]
52 # ok now we can construct the result, using bits of
53 # "order" to say which ones get stacked on
57 if SVSHAPE
.submode2
& 0b001 == 0b001: # cols
63 lim
, idx
, dbg
= vals
[i
]
64 # some of the dimensions can be "skipped". the order
65 # was actually selected above on all 3 dimensions,
66 # e.g. [z][x][y] or [y][z][x]. "skip" allows one of
67 # those to be knocked out
68 #print ("select %d %s idx %d" % (i, dbg, idx), VL,
71 if in_offs
and dbg
== ddbg
:
72 ni
= (idx
+ ix
*SVSHAPE
.offset
) % lim
73 #print ("mod", idx, ni, yi, SVSHAPE.offset, lim)
76 if not bigmul
: # Matrix Mode
77 if SVSHAPE
.skip
== i
+1: continue
78 idx
*= mult
# shifts up by previous dimension(s)
79 result
+= idx
# adds on this dimension
80 if not bigmul
: # Matrix Mode
81 mult
*= lim
# for the next dimension
84 ((y_end
and x_end
)<<1) |
85 ((y_end
and x_end
and z_end
)<<2))
87 if hasattr(SVSHAPE
, "postprocess"): # for Indexed mode
88 result
= SVSHAPE
.postprocess(result
, step
)
90 result
+= SVSHAPE
.offset
91 yield result
, loopends
95 def dump_shape(SVSHAPE
, VL
=None):
96 # enumerate over the iterator function, getting new indices
97 for idx
, (new_idx
, end
) in enumerate(iterate_indices(SVSHAPE
, VL
=VL
)):
98 estring
= bin(end
)[2:] if end
else ''
99 print ("%2d->%-2d" % (idx
, new_idx
), "%2s" % estring
, end
=' ')
103 triangle
= SVSHAPE
.mode
== 0b11 and SVSHAPE
.submode
& 0b10 == 0b10
105 if SVSHAPE
.lims
[0] == 1: end
&= ~
0b001
107 if SVSHAPE
.lims
[1] == 1: end
&= ~
0b010
113 xdim
, ydim
, zdim
= 3, 2, 4 # set the dimension sizes here
114 VL
= xdim
* ydim
* zdim
# set total (can repeat, e.g. VL=x*y*z*4)
116 class SVSHAPE
: pass # dummy class
118 # set up an SVSHAPE with matrix mode
119 print("matrix", xdim
, ydim
, zdim
)
121 SVSHAPE0
.lims
= [xdim
, ydim
, zdim
]
122 SVSHAPE0
.order
= [1,0,2] # experiment with different permutations, here
125 SVSHAPE0
.submode2
= 0b000 #
126 SVSHAPE0
.offset
= 0 # experiment with different offset, here
127 SVSHAPE0
.invxyz
= [0,0,0] # inversion if desired
131 # rhombus - see https://bugs.libre-soc.org/show_bug.cgi?id=1155#c17
132 xdim
, ydim
, zdim
= 3, 4, 1 # set the dimension sizes here
133 print("\nrhombus", xdim
, ydim
, zdim
)
135 SVSHAPE0
.lims
= [xdim
, ydim
, zdim
]
136 SVSHAPE0
.order
= [0,1,2] # experiment with different permutations, here
138 SVSHAPE0
.submode
= 0b01 # rhombus mode
139 SVSHAPE0
.submode2
= 0b000 #
141 SVSHAPE0
.offset
= 0 # experiment with different offset, here
142 SVSHAPE0
.invxyz
= [0,0,0] # inversion if desired
147 print("\ntriangle", xdim
, ydim
, zdim
)
148 xdim
, ydim
, zdim
= 1, 3, 5 # set the dimension sizes here
150 SVSHAPE0
.lims
= [xdim
, ydim
, zdim
]
151 SVSHAPE0
.order
= [0,1,2] # experiment with different permutations, here
153 SVSHAPE0
.submode
= 0b10 # triangle mode
154 SVSHAPE0
.submode2
= 0b000 #
156 SVSHAPE0
.offset
= 0 # experiment with different offset, here
157 SVSHAPE0
.invxyz
= [0,0,0] # inversion if desired
160 print("\ntriangle-bigmul", xdim
, ydim
, zdim
)
161 xdim
, ydim
, zdim
= 1, 3, 5 # set the dimension sizes here
163 SVSHAPE0
.lims
= [xdim
, ydim
, zdim
]
164 SVSHAPE0
.order
= [0,1,2] # experiment with different permutations, here
166 SVSHAPE0
.submode
= 0b11 # triangle mode, with sum
167 SVSHAPE0
.submode2
= 0b000 #
169 SVSHAPE0
.offset
= 0 # experiment with different offset, here
170 SVSHAPE0
.invxyz
= [0,0,0] # inversion if desired
177 xdim
, ydim
, zdim
= 4, 3, 1 # set the dimension sizes here
178 print("\nmatrix modulo(%d)" % VL
, xdim
, ydim
, zdim
)
180 SVSHAPE0
.lims
= [xdim
, ydim
, zdim
]
181 SVSHAPE0
.order
= [1,0,2] # experiment with different permutations, here
183 SVSHAPE0
.submode
= 0b00 #
185 SVSHAPE0
.submode2
= 0b000 # cols or rows modulo
186 SVSHAPE0
.offset
= 1 # experiment with different offset, here
187 SVSHAPE0
.invxyz
= [0,0,0] # inversion if desired
189 dump_shape(SVSHAPE0
, VL
=VL
)
193 if __name__
== '__main__':