whoops missed _x_r rename
[openpower-isa.git] / src / openpower / decoder / isa / remapyield.py
1 # a "yield" version of the REMAP algorithm. a little easier to read
2 # than the Finite State Machine version
3
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
11
12 # get indices to iterate over, in the required order
13 xd = SVSHAPE.lims[0]
14 yd = SVSHAPE.lims[1]
15 zd = SVSHAPE.lims[2]
16 # create lists of indices to iterate over in each dimension
17 _x_r = list(range(xd))
18 _y_r = list(range(yd))
19 z_r = list(range(zd))
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
26 while True:
27 for zi, z in enumerate(z_r): # loop over 1st order dimension
28 z_end = z == z_r[-1]
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
33 y_end = y == y_r[-1]
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
37 x_end = x == x_r[-1]
38 # ok work out which order to construct things in.
39 # start by creating a list of tuples of the dimension
40 # and its limit
41 vals = [(SVSHAPE.lims[0], x, "x"),
42 (SVSHAPE.lims[1], y, "y"),
43 (SVSHAPE.lims[2], z, "z")
44 ]
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]]
51 ]
52 # ok now we can construct the result, using bits of
53 # "order" to say which ones get stacked on
54 result = 0
55 mult = 1
56 if in_offs:
57 if SVSHAPE.submode2 & 0b001 == 0b001: # cols
58 ix, ddbg = yi, "x"
59 else:
60 ix, ddbg = xi, "y"
61
62 for i in range(3):
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,
69 # xi, yi, zi)
70 # modulo+offset?
71 if in_offs and dbg == ddbg:
72 ni = (idx + ix*SVSHAPE.offset) % lim
73 #print ("mod", idx, ni, yi, SVSHAPE.offset, lim)
74 idx = ni
75
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
82
83 loopends = (x_end |
84 ((y_end and x_end)<<1) |
85 ((y_end and x_end and z_end)<<2))
86
87 if hasattr(SVSHAPE, "postprocess"): # for Indexed mode
88 result = SVSHAPE.postprocess(result, step)
89 if not in_offs:
90 result += SVSHAPE.offset
91 yield result, loopends
92 step += 1
93
94
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=' ')
100 if end == 0b111:
101 print()
102 break
103 triangle = SVSHAPE.mode == 0b11 and SVSHAPE.submode & 0b10 == 0b10
104 if triangle:
105 if SVSHAPE.lims[0] == 1: end &= ~0b001
106 if triangle:
107 if SVSHAPE.lims[1] == 1: end &= ~0b010
108 if end != 0:
109 print()
110
111
112 def demo():
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)
115
116 class SVSHAPE: pass # dummy class
117
118 # set up an SVSHAPE with matrix mode
119 print("matrix", xdim, ydim, zdim)
120 SVSHAPE0 = SVSHAPE()
121 SVSHAPE0.lims = [xdim, ydim, zdim]
122 SVSHAPE0.order = [1,0,2] # experiment with different permutations, here
123 SVSHAPE0.mode = 0b00
124 SVSHAPE0.skip = 0b00
125 SVSHAPE0.submode2 = 0b000 #
126 SVSHAPE0.offset = 0 # experiment with different offset, here
127 SVSHAPE0.invxyz = [0,0,0] # inversion if desired
128
129 dump_shape(SVSHAPE0)
130
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)
134 SVSHAPE0 = SVSHAPE()
135 SVSHAPE0.lims = [xdim, ydim, zdim]
136 SVSHAPE0.order = [0,1,2] # experiment with different permutations, here
137 SVSHAPE0.mode = 0b11
138 SVSHAPE0.submode = 0b01 # rhombus mode
139 SVSHAPE0.submode2 = 0b000 #
140 SVSHAPE0.skip = 0b00
141 SVSHAPE0.offset = 0 # experiment with different offset, here
142 SVSHAPE0.invxyz = [0,0,0] # inversion if desired
143
144 dump_shape(SVSHAPE0)
145
146 # triangle
147 print("\ntriangle", xdim, ydim, zdim)
148 xdim, ydim, zdim = 1, 3, 5 # set the dimension sizes here
149 SVSHAPE0 = SVSHAPE()
150 SVSHAPE0.lims = [xdim, ydim, zdim]
151 SVSHAPE0.order = [0,1,2] # experiment with different permutations, here
152 SVSHAPE0.mode = 0b11
153 SVSHAPE0.submode = 0b10 # triangle mode
154 SVSHAPE0.submode2 = 0b000 #
155 SVSHAPE0.skip = 0b00
156 SVSHAPE0.offset = 0 # experiment with different offset, here
157 SVSHAPE0.invxyz = [0,0,0] # inversion if desired
158
159 # triangle
160 print("\ntriangle-bigmul", xdim, ydim, zdim)
161 xdim, ydim, zdim = 1, 3, 5 # set the dimension sizes here
162 SVSHAPE0 = SVSHAPE()
163 SVSHAPE0.lims = [xdim, ydim, zdim]
164 SVSHAPE0.order = [0,1,2] # experiment with different permutations, here
165 SVSHAPE0.mode = 0b11
166 SVSHAPE0.submode = 0b11 # triangle mode, with sum
167 SVSHAPE0.submode2 = 0b000 #
168 SVSHAPE0.skip = 0b00
169 SVSHAPE0.offset = 0 # experiment with different offset, here
170 SVSHAPE0.invxyz = [0,0,0] # inversion if desired
171
172 dump_shape(SVSHAPE0)
173
174 VL = 12 # modulo
175
176 # matrix modulo
177 xdim, ydim, zdim = 4, 3, 1 # set the dimension sizes here
178 print("\nmatrix modulo(%d)" % VL, xdim, ydim, zdim)
179 SVSHAPE0 = SVSHAPE()
180 SVSHAPE0.lims = [xdim, ydim, zdim]
181 SVSHAPE0.order = [1,0,2] # experiment with different permutations, here
182 SVSHAPE0.mode = 0b11
183 SVSHAPE0.submode = 0b00 #
184 SVSHAPE0.skip = 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
188
189 dump_shape(SVSHAPE0, VL=VL)
190
191
192 # run the demo
193 if __name__ == '__main__':
194 demo()