Clean up remap matrix instruction sections
[libreriscv.git] / openpower / sv / 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 for y in y_r: # loop over 2nd order dimension
23 for x in x_r: # loop over 3rd order dimension
24 # ok work out which order to construct things in.
25 # start by creating a list of tuples of the dimension
26 # and its limit
27 vals = [(SVSHAPE.lims[0], x, "x"),
28 (SVSHAPE.lims[1], y, "y"),
29 (SVSHAPE.lims[2], z, "z")
30 ]
31 # now select those by order. this allows us to
32 # create schedules for [z][x], [x][y], or [y][z]
33 # for matrix multiply.
34 vals = [vals[SVSHAPE.order[0]],
35 vals[SVSHAPE.order[1]],
36 vals[SVSHAPE.order[2]]
37 ]
38 # some of the dimensions can be "skipped". the order
39 # was actually selected above on all 3 dimensions,
40 # e.g. [z][x][y] or [y][z][x]. "skip" allows one of
41 # those to be knocked out
42 if SVSHAPE.skip == 0b00:
43 select = 0b111
44 elif SVSHAPE.skip == 0b11:
45 select = 0b011
46 elif SVSHAPE.skip == 0b01:
47 select = 0b110
48 elif SVSHAPE.skip == 0b10:
49 select = 0b101
50 else:
51 select = 0b111
52 result = 0
53 mult = 1
54 # ok now we can construct the result, using bits of
55 # "order" to say which ones get stacked on
56 for i in range(3):
57 lim, idx, dbg = vals[i]
58 if select & (1<<i):
59 #print ("select %d %s" % (i, dbg))
60 idx *= mult # shifts up by previous dimension(s)
61 result += idx # adds on this dimension
62 mult *= lim # for the next dimension
63
64 yield result + SVSHAPE.offset
65
66 def demo():
67 # set the dimension sizes here
68 xdim = 3
69 ydim = 2
70 zdim = 1
71
72 # set total (can repeat, e.g. VL=x*y*z*4)
73 VL = xdim * ydim * zdim
74
75 # set up an SVSHAPE
76 class SVSHAPE:
77 pass
78 SVSHAPE0 = SVSHAPE()
79 SVSHAPE0.lims = [xdim, ydim, zdim]
80 SVSHAPE0.order = [1,0,2] # experiment with different permutations, here
81 SVSHAPE0.mode = 0b00
82 SVSHAPE0.offset = 0 # experiment with different offset, here
83 SVSHAPE0.invxyz = [0,0,0] # inversion if desired
84
85 # enumerate over the iterator function, getting new indices
86 for idx, new_idx in enumerate(iterate_indices(SVSHAPE0)):
87 if idx >= VL:
88 break
89 print ("%d->%d" % (idx, new_idx))
90
91 # run the demo
92 if __name__ == '__main__':
93 demo()