whoops, no ability to add comments in between functions in pseudocode
[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):
7 # get indices to iterate over, in the required order
8 xd = SVSHAPE.lims[0]
9 yd = SVSHAPE.lims[1]
10 zd = SVSHAPE.lims[2]
11 # create lists of indices to iterate over in each dimension
12 x_r = list(range(xd))
13 y_r = list(range(yd))
14 z_r = list(range(zd))
15 # invert the indices if needed
16 if SVSHAPE.invxyz[0]: x_r.reverse()
17 if SVSHAPE.invxyz[1]: y_r.reverse()
18 if SVSHAPE.invxyz[2]: z_r.reverse()
19 # start an infinite (wrapping) loop
20 while True:
21 for z in z_r: # loop over 1st order dimension
22 z_end = z == z_r[-1]
23 for y in y_r: # loop over 2nd order dimension
24 y_end = y == y_r[-1]
25 for x in x_r: # loop over 3rd order dimension
26 x_end = x == x_r[-1]
27 # ok work out which order to construct things in.
28 # start by creating a list of tuples of the dimension
29 # and its limit
30 vals = [(SVSHAPE.lims[0], x, "x"),
31 (SVSHAPE.lims[1], y, "y"),
32 (SVSHAPE.lims[2], z, "z")
33 ]
34 # now select those by order. this allows us to
35 # create schedules for [z][x], [x][y], or [y][z]
36 # for matrix multiply.
37 vals = [vals[SVSHAPE.order[0]],
38 vals[SVSHAPE.order[1]],
39 vals[SVSHAPE.order[2]]
40 ]
41 # some of the dimensions can be "skipped". the order
42 # was actually selected above on all 3 dimensions,
43 # e.g. [z][x][y] or [y][z][x]. "skip" allows one of
44 # those to be knocked out
45 if SVSHAPE.skip == 0b00:
46 select = 0b111
47 elif SVSHAPE.skip == 0b11:
48 select = 0b011
49 elif SVSHAPE.skip == 0b01:
50 select = 0b110
51 elif SVSHAPE.skip == 0b10:
52 select = 0b101
53 else:
54 select = 0b111
55 result = 0
56 mult = 1
57 # ok now we can construct the result, using bits of
58 # "order" to say which ones get stacked on
59 for i in range(3):
60 lim, idx, dbg = vals[i]
61 if select & (1<<i):
62 #print ("select %d %s" % (i, dbg))
63 idx *= mult # shifts up by previous dimension(s)
64 result += idx # adds on this dimension
65 mult *= lim # for the next dimension
66
67 loopends = (x_end |
68 ((y_end and x_end)<<1) |
69 ((y_end and x_end and z_end)<<2))
70
71 yield result + SVSHAPE.offset, loopends
72
73 def demo():
74 # set the dimension sizes here
75 xdim = 3
76 ydim = 2
77 zdim = 4
78
79 # set total (can repeat, e.g. VL=x*y*z*4)
80 VL = xdim * ydim * zdim
81
82 # set up an SVSHAPE
83 class SVSHAPE:
84 pass
85 SVSHAPE0 = SVSHAPE()
86 SVSHAPE0.lims = [xdim, ydim, zdim]
87 SVSHAPE0.order = [1,0,2] # experiment with different permutations, here
88 SVSHAPE0.mode = 0b00
89 SVSHAPE0.skip = 0b00
90 SVSHAPE0.offset = 0 # experiment with different offset, here
91 SVSHAPE0.invxyz = [0,0,0] # inversion if desired
92
93 # enumerate over the iterator function, getting new indices
94 for idx, (new_idx, end) in enumerate(iterate_indices(SVSHAPE0)):
95 if idx >= VL:
96 break
97 print ("%d->%d" % (idx, new_idx), "end", bin(end)[2:])
98
99 # run the demo
100 if __name__ == '__main__':
101 demo()