3 from functools
import reduce
5 from nmutil
.formaltest
import FHDLTestCase
6 from openpower
.decoder
.helpers
import fp64toselectable
7 from openpower
.decoder
.isa
.test_caller
import run_tst
8 from openpower
.decoder
.selectable_int
import SelectableInt
9 from openpower
.simulator
.program
import Program
10 from openpower
.insndb
.asm
import SVP64Asm
12 def setup_result_matrix(rows
, cols
):
14 for i
in range(0, rows
):
16 for k
in range(0, cols
):
20 # Outer product - normal method learned at school
21 def matmult_outer(a
,b
):
22 # Result matrix has same number of rows as matrix a
23 # and same number of columns as matrix b
24 result
= setup_result_matrix(len(a
), len(b
[0]))
26 for i
in range(len(a
)): # Number of rows in matrix a
27 for k
in range(len(b
[0])): # Number of columns in matrix b
28 # Number of columns in matrix a or rows in mat b
29 for j
in range(0, len(a
[0])):
30 result
[i
][k
] += a
[i
][j
] * b
[j
][k
]
34 # Inner product - slight re-arrangement to reduce stalling
36 def matmult_inner(a
,b
):
37 result
= setup_result_matrix(len(a
), len(b
[0]))
39 for i
in range(len(a
)): # Number of rows in matrix a
40 # Number of columns in matrix a or rows in mat b
41 for j
in range(0, len(a
[0])):
42 for k
in range(len(b
[0])): # Number of columns in matrix b
43 result
[i
][k
] += a
[i
][j
] * b
[j
][k
]
47 # Flatten list of lists matrix down to single list
49 return [item
for sublist
in l
for item
in sublist
]
52 class DecoderTestCase(FHDLTestCase
):
54 def _check_regs(self
, sim
, expected
):
56 self
.assertEqual(sim
.gpr(i
), SelectableInt(expected
[i
], 64))
58 def test_sv_maddld_remap1(self
):
59 """perform an integer matrix multiply using maddld
60 lst = ["svshape 2, 2, 3, 0, 0",
61 "svremap 31, 1, 2, 3, 0, 0, 0",
62 "sv.maddld *0, *8, *16, *0"
64 REMAP maddld RT, RA, RB, RC
66 lst
= SVP64Asm(["svshape 2, 2, 3, 0, 0",
67 "svremap 31, 1, 2, 3, 0, 0, 0",
68 "sv.maddld *0, *16, *32, *0"
86 expected
= matmult_outer(X
, Y
)
87 expected2
= matmult_inner(X
, Y
)
88 expected
= flatten(expected
)
89 expected2
= flatten(expected2
)
90 print("expected-matrix (outer):")
92 print("expected-matrix (inner):")
95 xf
= reduce(operator
.add
, X
)
96 yf
= reduce(operator
.add
, Y
)
97 expected
= reduce(operator
.add
, expected
)
98 print("flattened X,Y,expected")
101 print("\t", expected
)
103 # and create a linear result2, same scheme
104 #result1 = [0] * (ydim1*xdim2)
107 # store GPR x-flattened and y-flattened in GPRs
108 for i
, x
in enumerate(xf
):
109 gprs
[i
+16] = x
# X matrix
110 for i
, y
in enumerate(yf
):
111 gprs
[i
+32] = y
# Y matrix
113 with
Program(lst
, bigendian
=False) as program
:
114 sim
= self
.run_tst_program(program
, initial_regs
=gprs
)
115 print("spr svshape0", sim
.spr
['SVSHAPE0'])
116 print(" xdimsz", sim
.spr
['SVSHAPE0'].xdimsz
)
117 print(" ydimsz", sim
.spr
['SVSHAPE0'].ydimsz
)
118 print(" zdimsz", sim
.spr
['SVSHAPE0'].zdimsz
)
119 print("spr svshape1", sim
.spr
['SVSHAPE1'])
120 print("spr svshape2", sim
.spr
['SVSHAPE2'])
121 print("spr svshape3", sim
.spr
['SVSHAPE3'])
123 total
= len(X
)*len(Y
[0])
124 for i
in range(total
):
125 results
.append(sim
.gpr(i
).asint())
126 for i
in range(total
):
127 print("maddld-matrix i", i
, results
[i
])
128 # confirm that the results are as expected
129 self
.assertEqual(results
, expected
)
131 def test_sv_remap1(self
):
132 """>>> lst = ["svshape 2, 2, 3, 0, 0",
133 "svremap 31, 1, 2, 3, 0, 0, 0",
134 "sv.fmadds *0, *8, *16, *0"
136 REMAP fmadds FRT, FRA, FRC, FRB
138 lst
= SVP64Asm(["svshape 2, 2, 3, 0, 0",
139 "svremap 31, 1, 2, 3, 0, 0, 0",
140 "sv.fmadds *0, *16, *32, *0"
158 xf
= reduce(operator
.add
, X
)
159 yf
= reduce(operator
.add
, Y
)
160 print("flattened X,Y")
164 # and create a linear result2, same scheme
165 #result1 = [0] * (ydim1*xdim2)
169 for i
, x
in enumerate(xf
):
170 fprs
[i
+16] = fp64toselectable(float(x
)) # X matrix
171 for i
, y
in enumerate(yf
):
172 fprs
[i
+32] = fp64toselectable(float(y
)) # Y matrix
174 # t = DOUBLE2SINGLE(fp64toselectable(t)) # convert to Power single
175 # u = DOUBLE2SINGLE(fp64toselectable(u)) # from double
177 # print ("FFT", i, "in", a, b, "coeff", c, "mul",
180 with
Program(lst
, bigendian
=False) as program
:
181 sim
= self
.run_tst_program(program
, initial_fprs
=fprs
)
182 print("spr svshape0", sim
.spr
['SVSHAPE0'])
183 print(" xdimsz", sim
.spr
['SVSHAPE0'].xdimsz
)
184 print(" ydimsz", sim
.spr
['SVSHAPE0'].ydimsz
)
185 print(" zdimsz", sim
.spr
['SVSHAPE0'].zdimsz
)
186 print("spr svshape1", sim
.spr
['SVSHAPE1'])
187 print("spr svshape2", sim
.spr
['SVSHAPE2'])
188 print("spr svshape3", sim
.spr
['SVSHAPE3'])
190 print("ffmadds-matrix i", i
, float(sim
.fpr(i
)))
191 # confirm that the results are as expected
192 # for i, (t, u) in enumerate(res):
193 # self.assertEqual(sim.fpr(i+2), t)
194 # self.assertEqual(sim.fpr(i+6), u)
196 def test_sv_remap2(self
):
197 """>>> lst = ["svshape 5, 4, 3, 0, 0",
198 "svremap 31, 1, 2, 3, 0, 0, 0",
199 "sv.fmadds *0, *8, *16, *0"
201 REMAP fmadds FRT, FRA, FRC, FRB
203 lst
= SVP64Asm(["svshape 4, 3, 3, 0, 0",
204 "svremap 31, 1, 2, 3, 0, 0, 0",
205 "sv.fmadds *0, *16, *32, *0"
237 Y3
= [[5, 8, 1, 2, 3],
244 # get the dimensions of the 2 matrices
250 print("xdim2 ydim1 ydim2", xdim2
, ydim1
, ydim2
)
252 xf
= reduce(operator
.add
, X
)
253 yf
= reduce(operator
.add
, Y
)
254 print("flattened X,Y")
258 # and create a linear result2, same scheme
259 #result1 = [0] * (ydim1*xdim2)
264 for i
, x
in enumerate(xf
):
265 fprs
[i
+16] = fp64toselectable(float(x
)) # X matrix
266 for i
, y
in enumerate(yf
):
267 fprs
[i
+32] = fp64toselectable(float(y
)) # Y matrix
269 # t = DOUBLE2SINGLE(fp64toselectable(t)) # convert to Power single
270 # u = DOUBLE2SINGLE(fp64toselectable(u)) # from double
272 # print ("FFT", i, "in", a, b, "coeff", c, "mul",
275 with
Program(lst
, bigendian
=False) as program
:
276 sim
= self
.run_tst_program(program
, initial_fprs
=fprs
)
277 print("spr svshape0", sim
.spr
['SVSHAPE0'])
278 print(" xdimsz", sim
.spr
['SVSHAPE0'].xdimsz
)
279 print(" ydimsz", sim
.spr
['SVSHAPE0'].ydimsz
)
280 print(" zdimsz", sim
.spr
['SVSHAPE0'].zdimsz
)
281 print("spr svshape1", sim
.spr
['SVSHAPE1'])
282 print("spr svshape2", sim
.spr
['SVSHAPE2'])
283 print("spr svshape3", sim
.spr
['SVSHAPE3'])
285 print("i", i
, float(sim
.fpr(i
)))
286 # confirm that the results are as expected
287 # for i, (t, u) in enumerate(res):
288 # self.assertEqual(sim.fpr(i+2), t)
289 # self.assertEqual(sim.fpr(i+6), u)
291 def test_sv_remap3_horizontal_or(self
):
292 """>>> lst = ["svshape 3, 2, 1, 0, 0",
293 "svremap 31, 1, 3, 1, 1, 1, 0",
296 REMAP horizontal-or using "or RA,RS,RB"
297 same trick can be applied to do horizontal-add
298 or horizontal-multiply. just remember for multiply
299 to pre-load 1 (1.0) into the results first (or any other
302 sv.or is horribly obscure because RA (the destination)
303 actually gets treated as RT by the REMAP subsystem.
305 The purpose here is to demonstrate a horizontal mapreduce
306 by using/abusing Matrix REMAP (ignoring the B-Matrix entirely)
308 if data is laid out in R G B R G B R G B format and
309 comprises tuples (R<<16 G<<8 B<<0) then a horizontal-or
310 may reduce down to (R<<16) | (G<<8> | (B<<0) on a per-row
313 # 3x4 matrix of data to be ORed together by row.
314 # Add any number of extra rows (up to 6) here (6 because sv.or *0,*0,*6)
315 X1
= [[0x1, 0x10, 0x100], # 0x111
316 [0x2, 0x40, 0x300], # 0x342
317 [0x9, 0x70, 0x800], # 0x879
318 [0x3, 0x71, 0x460], # overlaps (still ORed) - 0x473
321 # get the dimensions of the array
325 lst
= SVP64Asm(["svshape %d, %d, 1, 0, 0" % (xdim1
, ydim1
),
327 # "svremap 31, 3, 0, 3, 1, 2, 0",
328 # "sv.ternlogi *12, *0, *6, 250" # 0b11111110
329 "svremap 31, 1, 3, 1, 1, 1, 0",
334 print("xdim1, ydim1", xdim1
, ydim1
)
336 expected
= [0] * ydim1
337 for i
, row
in enumerate(X1
):
338 expected
[i
] = reduce(operator
.or_
, row
)
339 print("\texpected ORed", hex(expected
[i
]))
340 xf
= reduce(operator
.add
, X1
)
347 for i
, x
in enumerate(xf
):
350 with
Program(lst
, bigendian
=False) as program
:
351 sim
= self
.run_tst_program(program
, gprs
)
352 print("spr svshape0", sim
.spr
['SVSHAPE0'])
353 print(" xdimsz", sim
.spr
['SVSHAPE0'].xdimsz
)
354 print(" ydimsz", sim
.spr
['SVSHAPE0'].ydimsz
)
355 print(" zdimsz", sim
.spr
['SVSHAPE0'].zdimsz
)
356 print("spr svshape1", sim
.spr
['SVSHAPE1'])
357 print("spr svshape2", sim
.spr
['SVSHAPE2'])
358 print("spr svshape3", sim
.spr
['SVSHAPE3'])
359 for i
in range(ydim1
):
360 print("i", i
, sim
.gpr(0+i
), hex(expected
[i
]))
361 for i
in range(ydim1
):
362 self
.assertEqual(sim
.gpr(0+i
), SelectableInt(expected
[i
], 64))
364 def run_tst_program(self
, prog
, initial_regs
=None,
368 if initial_regs
is None:
369 initial_regs
= [0] * 32
370 simulator
= run_tst(prog
, initial_regs
, mem
=initial_mem
,
371 initial_fprs
=initial_fprs
,
382 if __name__
== "__main__":