(no commit message)
authorlkcl <lkcl@web>
Sat, 15 Apr 2023 12:26:47 +0000 (13:26 +0100)
committerIkiWiki <ikiwiki.info>
Sat, 15 Apr 2023 12:26:47 +0000 (13:26 +0100)
openpower/sv/rfc/ls009.mdwn

index 8ab6438c53aca45bbbca9c4b9e4b6c90f9d10873..c3f41edf1e970615f791e06799ef6238ca8e46a2 100644 (file)
@@ -1566,4 +1566,107 @@ Add the following to Book I, 1.6.2
 | SVM2 | I    | #    | 3.0B    | svshape2 | REMAP shape instruction (2) |
 | SVI  | I    | #    | 3.0B    | svindex | REMAP General-purpose Indexing |
 
+## REMAP 2D/3D Matrix pseudocode
+
+Written in python3 the following stand-alone executable source code is the Canonical
+Specification for Matrix (2D/3D) REMAP. Vectors of "loopends" are returned when Rc=1
+in Vectors of CR Fields on `sv.svstep.`, or a single CR Field CR0 on
+`svstep.` in Vertical-First Mode.  The `SVSTATE.srcstep` or `SVSTATE.dststep` sequential
+offset is put through this algorithm to determine the actual Element Offset.
+
+```
+# python "yield" can be iterated. use this to make it clear how
+# the indices are generated by using natural-looking nested loops
+def iterate_indices(SVSHAPE):
+    # get indices to iterate over, in the required order
+    xd = SVSHAPE.lims[0]
+    yd = SVSHAPE.lims[1]
+    zd = SVSHAPE.lims[2]
+    # create lists of indices to iterate over in each dimension
+    x_r = list(range(xd))
+    y_r = list(range(yd))
+    z_r = list(range(zd))
+    # invert the indices if needed
+    if SVSHAPE.invxyz[0]: x_r.reverse()
+    if SVSHAPE.invxyz[1]: y_r.reverse()
+    if SVSHAPE.invxyz[2]: z_r.reverse()
+    # start an infinite (wrapping) loop
+    step = 0 # track src/dst step
+    while True:
+        for z in z_r:   # loop over 1st order dimension
+            z_end = z == z_r[-1]
+            for y in y_r:       # loop over 2nd order dimension
+                y_end = y == y_r[-1]
+                for x in x_r:           # loop over 3rd order dimension
+                    x_end = x == x_r[-1]
+                    # ok work out which order to construct things in.
+                    # start by creating a list of tuples of the dimension
+                    # and its limit
+                    vals = [(SVSHAPE.lims[0], x, "x"),
+                            (SVSHAPE.lims[1], y, "y"),
+                            (SVSHAPE.lims[2], z, "z")
+                           ]
+                    # now select those by order.  this allows us to
+                    # create schedules for [z][x], [x][y], or [y][z]
+                    # for matrix multiply.
+                    vals = [vals[SVSHAPE.order[0]],
+                            vals[SVSHAPE.order[1]],
+                            vals[SVSHAPE.order[2]]
+                           ]
+                    # ok now we can construct the result, using bits of
+                    # "order" to say which ones get stacked on
+                    result = 0
+                    mult = 1
+                    for i in range(3):
+                        lim, idx, dbg = vals[i]
+                        # some of the dimensions can be "skipped".  the order
+                        # was actually selected above on all 3 dimensions,
+                        # e.g. [z][x][y] or [y][z][x].  "skip" allows one of
+                        # those to be knocked out
+                        if SVSHAPE.skip == i+1: continue
+                        #print ("select %d %s" % (i, dbg))
+                        idx *= mult   # shifts up by previous dimension(s)
+                        result += idx # adds on this dimension
+                        mult *= lim   # for the next dimension
+
+                    loopends = (x_end |
+                               ((y_end and x_end)<<1) |
+                                ((y_end and x_end and z_end)<<2))
+
+                    if hasattr(SVSHAPE, "postprocess"): # for Indexed mode
+                        result = SVSHAPE.postprocess(result, step)
+                    yield result + SVSHAPE.offset, loopends
+                    step += 1
+
+def demo():
+    # set the dimension sizes here
+    xdim = 3
+    ydim = 2
+    zdim = 4
+
+    # set total (can repeat, e.g. VL=x*y*z*4)
+    VL = xdim * ydim * zdim
+
+    # set up an SVSHAPE
+    class SVSHAPE:
+        pass
+    SVSHAPE0 = SVSHAPE()
+    SVSHAPE0.lims = [xdim, ydim, zdim]
+    SVSHAPE0.order = [1,0,2]  # experiment with different permutations, here
+    SVSHAPE0.mode = 0b00
+    SVSHAPE0.skip = 0b00
+    SVSHAPE0.offset = 0       # experiment with different offset, here
+    SVSHAPE0.invxyz = [0,0,0] # inversion if desired
+
+    # enumerate over the iterator function, getting new indices
+    for idx, (new_idx, end) in enumerate(iterate_indices(SVSHAPE0)):
+        if idx >= VL:
+            break
+        print ("%d->%d" % (idx, new_idx), "end", bin(end)[2:])
+
+# run the demo
+if __name__ == '__main__':
+    demo()
+```
+
 [[!tag opf_rfc]]