5e015016be7f5d56e5202baf212dee71b8023e52
[openpower-isa.git] / src / openpower / decoder / isa / test_caller_svp64_matrix.py
1 import operator
2 import unittest
3 from functools import reduce
4
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
11
12
13 # Pure Python implementation of matrix multiply
14 # Example values
15 # x = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
16 # y = [[1,2],[1,2],[3,4]]
17 def matmult(a, b):
18 zip_b = list(zip(*b)) # transpose b matrix
19 return [[sum(ele_a*ele_b for ele_a, ele_b in zip(row_a, col_b))
20 for col_b in zip_b] for row_a in a]
21
22
23 class DecoderTestCase(FHDLTestCase):
24
25 def _check_regs(self, sim, expected):
26 for i in range(32):
27 self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64))
28
29 def test_sv_maddld_remap1(self):
30 """perform an integer matrix multiply using maddld
31 lst = ["svshape 2, 2, 3, 0, 0",
32 "svremap 31, 1, 2, 3, 0, 0, 0",
33 "sv.maddld *0, *8, *16, *0"
34 ]
35 REMAP maddld RT, RA, RB, RC
36 """
37 lst = SVP64Asm(["svshape 2, 2, 3, 0, 0",
38 "svremap 31, 1, 2, 3, 0, 0, 0",
39 "sv.maddld *0, *16, *32, *0"
40 ])
41 lst = list(lst)
42
43 gprs = [0] * 64
44 # 3x2 matrix
45 X1 = [[1, 2, 3],
46 [3, 4, 5],
47 ]
48 # 2x3 matrix
49 Y1 = [[6, 7],
50 [8, 9],
51 [10, 11],
52 ]
53
54 X = X1
55 Y = Y1
56
57 xf = reduce(operator.add, X)
58 yf = reduce(operator.add, Y)
59 print("flattened X,Y")
60 print("\t", xf)
61 print("\t", yf)
62
63 # and create a linear result2, same scheme
64 #result1 = [0] * (ydim1*xdim2)
65
66 res = []
67 # store FPs
68 for i, x in enumerate(xf):
69 gprs[i+16] = x # X matrix
70 for i, y in enumerate(yf):
71 gprs[i+32] = y # Y matrix
72 continue
73 # t = DOUBLE2SINGLE(fp64toselectable(t)) # convert to Power single
74 # u = DOUBLE2SINGLE(fp64toselectable(u)) # from double
75 #res.append((t, u))
76 # print ("FFT", i, "in", a, b, "coeff", c, "mul",
77 # mul, "res", t, u)
78
79 with Program(lst, bigendian=False) as program:
80 sim = self.run_tst_program(program, initial_regs=gprs)
81 print("spr svshape0", sim.spr['SVSHAPE0'])
82 print(" xdimsz", sim.spr['SVSHAPE0'].xdimsz)
83 print(" ydimsz", sim.spr['SVSHAPE0'].ydimsz)
84 print(" zdimsz", sim.spr['SVSHAPE0'].zdimsz)
85 print("spr svshape1", sim.spr['SVSHAPE1'])
86 print("spr svshape2", sim.spr['SVSHAPE2'])
87 print("spr svshape3", sim.spr['SVSHAPE3'])
88 expected = []
89 for i in range(4):
90 expected.append(sim.gpr(i).asint())
91 for i in range(4):
92 print("maddld-matrix i", i, expected[i])
93 # confirm that the results are as expected
94 # for i, (t, u) in enumerate(res):
95 # self.assertEqual(sim.fpr(i+2), t)
96 # self.assertEqual(sim.fpr(i+6), u)
97
98 def test_sv_remap1(self):
99 """>>> lst = ["svshape 2, 2, 3, 0, 0",
100 "svremap 31, 1, 2, 3, 0, 0, 0",
101 "sv.fmadds *0, *8, *16, *0"
102 ]
103 REMAP fmadds FRT, FRA, FRC, FRB
104 """
105 lst = SVP64Asm(["svshape 2, 2, 3, 0, 0",
106 "svremap 31, 1, 2, 3, 0, 0, 0",
107 "sv.fmadds *0, *16, *32, *0"
108 ])
109 lst = list(lst)
110
111 fprs = [0] * 64
112 # 3x2 matrix
113 X1 = [[1, 2, 3],
114 [3, 4, 5],
115 ]
116 # 2x3 matrix
117 Y1 = [[6, 7],
118 [8, 9],
119 [10, 11],
120 ]
121
122 X = X1
123 Y = Y1
124
125 xf = reduce(operator.add, X)
126 yf = reduce(operator.add, Y)
127 print("flattened X,Y")
128 print("\t", xf)
129 print("\t", yf)
130
131 # and create a linear result2, same scheme
132 #result1 = [0] * (ydim1*xdim2)
133
134 res = []
135 # store FPs
136 for i, x in enumerate(xf):
137 fprs[i+16] = fp64toselectable(float(x)) # X matrix
138 for i, y in enumerate(yf):
139 fprs[i+32] = fp64toselectable(float(y)) # Y matrix
140 continue
141 # t = DOUBLE2SINGLE(fp64toselectable(t)) # convert to Power single
142 # u = DOUBLE2SINGLE(fp64toselectable(u)) # from double
143 #res.append((t, u))
144 # print ("FFT", i, "in", a, b, "coeff", c, "mul",
145 # mul, "res", t, u)
146
147 with Program(lst, bigendian=False) as program:
148 sim = self.run_tst_program(program, initial_fprs=fprs)
149 print("spr svshape0", sim.spr['SVSHAPE0'])
150 print(" xdimsz", sim.spr['SVSHAPE0'].xdimsz)
151 print(" ydimsz", sim.spr['SVSHAPE0'].ydimsz)
152 print(" zdimsz", sim.spr['SVSHAPE0'].zdimsz)
153 print("spr svshape1", sim.spr['SVSHAPE1'])
154 print("spr svshape2", sim.spr['SVSHAPE2'])
155 print("spr svshape3", sim.spr['SVSHAPE3'])
156 for i in range(4):
157 print("ffmadds-matrix i", i, float(sim.fpr(i)))
158 # confirm that the results are as expected
159 # for i, (t, u) in enumerate(res):
160 # self.assertEqual(sim.fpr(i+2), t)
161 # self.assertEqual(sim.fpr(i+6), u)
162
163 def test_sv_remap2(self):
164 """>>> lst = ["svshape 5, 4, 3, 0, 0",
165 "svremap 31, 1, 2, 3, 0, 0, 0",
166 "sv.fmadds *0, *8, *16, *0"
167 ]
168 REMAP fmadds FRT, FRA, FRC, FRB
169 """
170 lst = SVP64Asm(["svshape 4, 3, 3, 0, 0",
171 "svremap 31, 1, 2, 3, 0, 0, 0",
172 "sv.fmadds *0, *16, *32, *0"
173 ])
174 lst = list(lst)
175
176 # 3x2 matrix
177 X1 = [[1, 2, 3],
178 [3, 4, 5],
179 ]
180 # 2x3 matrix
181 Y1 = [[6, 7],
182 [8, 9],
183 [10, 11],
184 ]
185
186 # test matrices 2
187 # 3x3 matrix
188 X2 = [[12, 7, 3],
189 [4, 5, 6],
190 [7, 8, 9],
191 ]
192 # 3x4 matrix
193 Y2 = [[5, 8, 1, 2],
194 [6, 7, 3, 0],
195 [4, 5, 9, 1]]
196
197 # test matrices 3
198 # 3x4 matrix
199 X3 = [[12, 7, 3],
200 [4, 5, 6],
201 [7, 8, 9],
202 [2, 0, 1]]
203 # 5x3 matrix
204 Y3 = [[5, 8, 1, 2, 3],
205 [6, 7, 3, 0, 9],
206 [4, 5, 9, 1, 2]]
207
208 X = X2
209 Y = Y2
210
211 # get the dimensions of the 2 matrices
212 xdim1 = len(X[0])
213 ydim1 = len(X)
214 xdim2 = len(Y[0])
215 ydim2 = len(Y)
216
217 print("xdim2 ydim1 ydim2", xdim2, ydim1, ydim2)
218
219 xf = reduce(operator.add, X)
220 yf = reduce(operator.add, Y)
221 print("flattened X,Y")
222 print("\t", xf)
223 print("\t", yf)
224
225 # and create a linear result2, same scheme
226 #result1 = [0] * (ydim1*xdim2)
227
228 res = []
229 # store FPs
230 fprs = [0] * 64
231 for i, x in enumerate(xf):
232 fprs[i+16] = fp64toselectable(float(x)) # X matrix
233 for i, y in enumerate(yf):
234 fprs[i+32] = fp64toselectable(float(y)) # Y matrix
235 continue
236 # t = DOUBLE2SINGLE(fp64toselectable(t)) # convert to Power single
237 # u = DOUBLE2SINGLE(fp64toselectable(u)) # from double
238 #res.append((t, u))
239 # print ("FFT", i, "in", a, b, "coeff", c, "mul",
240 # mul, "res", t, u)
241
242 with Program(lst, bigendian=False) as program:
243 sim = self.run_tst_program(program, initial_fprs=fprs)
244 print("spr svshape0", sim.spr['SVSHAPE0'])
245 print(" xdimsz", sim.spr['SVSHAPE0'].xdimsz)
246 print(" ydimsz", sim.spr['SVSHAPE0'].ydimsz)
247 print(" zdimsz", sim.spr['SVSHAPE0'].zdimsz)
248 print("spr svshape1", sim.spr['SVSHAPE1'])
249 print("spr svshape2", sim.spr['SVSHAPE2'])
250 print("spr svshape3", sim.spr['SVSHAPE3'])
251 for i in range(16):
252 print("i", i, float(sim.fpr(i)))
253 # confirm that the results are as expected
254 # for i, (t, u) in enumerate(res):
255 # self.assertEqual(sim.fpr(i+2), t)
256 # self.assertEqual(sim.fpr(i+6), u)
257
258 def test_sv_remap3_horizontal_or(self):
259 """>>> lst = ["svshape 3, 2, 1, 0, 0",
260 "svremap 31, 1, 3, 1, 1, 1, 0",
261 "sv.or *0, *0, *6"
262 ]
263 REMAP horizontal-or using "or RA,RS,RB"
264 same trick can be applied to do horizontal-add
265 or horizontal-multiply. just remember for multiply
266 to pre-load 1 (1.0) into the results first (or any other
267 scaling factor).
268
269 sv.or is horribly obscure because RA (the destination)
270 actually gets treated as RT by the REMAP subsystem.
271
272 The purpose here is to demonstrate a horizontal mapreduce
273 by using/abusing Matrix REMAP (ignoring the B-Matrix entirely)
274
275 if data is laid out in R G B R G B R G B format and
276 comprises tuples (R<<16 G<<8 B<<0) then a horizontal-or
277 may reduce down to (R<<16) | (G<<8> | (B<<0) on a per-row
278 basis.
279 """
280 # 3x4 matrix of data to be ORed together by row.
281 # Add any number of extra rows (up to 6) here (6 because sv.or *0,*0,*6)
282 X1 = [[0x1, 0x10, 0x100], # 0x111
283 [0x2, 0x40, 0x300], # 0x342
284 [0x9, 0x70, 0x800], # 0x879
285 [0x3, 0x71, 0x460], # overlaps (still ORed) - 0x473
286 ]
287
288 # get the dimensions of the array
289 xdim1 = len(X1[0])
290 ydim1 = len(X1)
291
292 lst = SVP64Asm(["svshape %d, %d, 1, 0, 0" % (xdim1, ydim1),
293 # also works:
294 # "svremap 31, 3, 0, 3, 1, 2, 0",
295 # "sv.ternlogi *12, *0, *6, 250" # 0b11111110
296 "svremap 31, 1, 3, 1, 1, 1, 0",
297 "sv.or *0, *0, *6"
298 ])
299 lst = list(lst)
300
301 print("xdim1, ydim1", xdim1, ydim1)
302
303 expected = [0] * ydim1
304 for i, row in enumerate(X1):
305 expected[i] = reduce(operator.or_, row)
306 print("\texpected ORed", hex(expected[i]))
307 xf = reduce(operator.add, X1)
308 print("flattened X")
309 print("\t", xf)
310
311 res = []
312 # store FPs
313 gprs = [0] * 64
314 for i, x in enumerate(xf):
315 gprs[i+6] = x
316
317 with Program(lst, bigendian=False) as program:
318 sim = self.run_tst_program(program, gprs)
319 print("spr svshape0", sim.spr['SVSHAPE0'])
320 print(" xdimsz", sim.spr['SVSHAPE0'].xdimsz)
321 print(" ydimsz", sim.spr['SVSHAPE0'].ydimsz)
322 print(" zdimsz", sim.spr['SVSHAPE0'].zdimsz)
323 print("spr svshape1", sim.spr['SVSHAPE1'])
324 print("spr svshape2", sim.spr['SVSHAPE2'])
325 print("spr svshape3", sim.spr['SVSHAPE3'])
326 for i in range(ydim1):
327 print("i", i, sim.gpr(0+i), hex(expected[i]))
328 for i in range(ydim1):
329 self.assertEqual(sim.gpr(0+i), SelectableInt(expected[i], 64))
330
331 def run_tst_program(self, prog, initial_regs=None,
332 svstate=None,
333 initial_mem=None,
334 initial_fprs=None):
335 if initial_regs is None:
336 initial_regs = [0] * 32
337 simulator = run_tst(prog, initial_regs, mem=initial_mem,
338 initial_fprs=initial_fprs,
339 svstate=svstate)
340
341 print("GPRs")
342 simulator.gpr.dump()
343 print("FPRs")
344 simulator.fpr.dump()
345
346 return simulator
347
348
349 if __name__ == "__main__":
350 unittest.main()