f7b508b214662b1856528caab4ecb4fe961c8374
[openpower-isa.git] / src / openpower / decoder / isa / test_caller_svp64_maxloc.py
1 """Implementation of FORTRAN MAXLOC SVP64
2 Copyright (C) 2022,2023 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 Licensed under the LGPLv3+
4 Funded by NLnet NGI-ASSURE under EU grant agreement No 957073.
5 * https://nlnet.nl/project/Libre-SOC-OpenPOWER-ISA
6 * https://bugs.libre-soc.org/show_bug.cgi?id=676
7 * https://libre-soc.org/openpower/sv/cookbook/fortran_maxloc/
8 """
9
10 import unittest
11 from copy import deepcopy
12
13 from nmutil.formaltest import FHDLTestCase
14 from openpower.decoder.isa.caller import SVP64State
15 from openpower.decoder.isa.test_caller import run_tst
16 from openpower.decoder.selectable_int import SelectableInt
17 from openpower.simulator.program import Program
18 from openpower.insndb.asm import SVP64Asm
19 from openpower.util import log
20 from openpower.decoder.isa.maxloc import m2
21
22
23
24 def cmpd(x, y):
25 class CRfield:
26 def __repr__(self):
27 return "<lt %d gt %d eq %d>" % (self.lt, self.gt, self.eq)
28 def __int__(self):
29 return (CRf.lt<<3) | (CRf.gt<<2) | (CRf.eq<<1)
30 CRf = CRfield()
31 CRf.lt = x < y
32 CRf.gt = x > y
33 CRf.eq = x == y
34 return CRf
35
36
37 # example sv.minmax/ff=lt 0, 1, *10, 5
38 # see https://bugs.libre-soc.org/show_bug.cgi?id=1183#c3
39 def sv_maxu(gpr, vl, ra, rb, rt):
40 CR0, i = None, 0
41 while i < vl:
42 CR0 = cmpd(gpr[ra+i], gpr[rb])
43 log("sv_maxss test", i, gpr[ra + i], gpr[rb], CR0, int(CR0))
44 gpr[rt] = gpr[ra+i] if CR0.lt else gpr[rb]
45 if not CR0.gt:
46 break
47 i += 1
48 return i, CR0 # new VL
49
50
51 class DDFFirstTestCase(FHDLTestCase):
52
53 def _check_regs(self, sim, expected):
54 for i in range(32):
55 self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64))
56
57 def test_sv_maxloc_1(self):
58 self.sv_maxloc([1,3,3,3])
59
60 def tst_sv_maxloc_2(self):
61 self.sv_maxloc([3,4,1,5])
62
63 def tst_sv_maxloc_3(self):
64 self.sv_maxloc([2,9,8,0])
65
66 def tst_sv_maxloc_4(self):
67 self.sv_maxloc([2,1,3,0])
68
69 def sv_maxloc(self, ra):
70 """
71 m, nm, i, n = 0, 0, 0, len(a)
72 while (i<n):
73 while (i<n and a[i]<=m) : i += 1
74 while (i<n and a[i] > m): m, nm, i = a[i], i, i+1
75 return nm
76 """
77
78 lst = SVP64Asm([
79 "mtspr 9, 3", # move r3 to CTR
80 "addi 0, 0, 0", # r0=0
81 #"addi 5, 4, 0", # copy m(r4) to r5
82 # VL = MIN(CTR,MAXVL=4)
83 "mtcrf 255,0", # clear CR entirely
84 "setvl 2,0,4,0,1,1", # set MVL=4, VL=MIN(MVL,CTR)
85 # while (i<n and a[i]<=m) : i += 1
86 "sv.cmp/ff=gt/m=ge *0,0,*10,4", # truncates VL to min
87 "sv.creqv *16,*16,*16", # set mask on already-tested
88 "setvl 2,0,4,0,1,1", # set MVL=4, VL=MIN(MVL,CTR)
89 "mtcrf 128, 0", # clear CR0 (in case VL=0?)
90 # while (i<n and a[i]>m):
91 "sv.minmax./ff=le/m=ge 4, *10, 4, 1", # uses r4 as accumulator
92 "crternlogi 0,1,2,127", # test greater/equal or VL=0
93 #"cror 0,1,0", # test for greater or equal, or VL=0
94 #"cror 0,2,0", # test for greater or equal, or VL=0
95 "sv.creqv *19,*16,*16", # set mask on already-tested
96 "sv.crand *19,*19,0", # clear if CR0=0
97 "sv.svstep/mr/m=so 1, 0, 6, 1", # svstep: get vector dststep
98 "sv.creqv *16,*16,*16", # set mask on already-tested
99 "bc 12,0, -0x48" # CR0 lt bit clear, branch back
100 ])
101 lst = list(lst)
102
103 # SVSTATE
104 svstate = SVP64State()
105 vl = len(ra) # VL is length of array ra
106 svstate.vl = vl # VL
107 svstate.maxvl = vl # MAXVL
108 print("SVSTATE", bin(svstate.asint()))
109
110 gprs = [0] * 32
111 gprs[3] = vl # variable n: to go into CTR
112 gprs[4] = 2 # variable m: max current number found
113 for i, ra in enumerate(ra): # vector in ra starts at r10
114 gprs[10+i] = ra
115 log("maxu ddff", i, gprs[10+i])
116
117 cr_res = [0]*8
118 res = deepcopy(gprs)
119
120 #expected_vl, expected_cr = sv_maxu(res, cr_res, vl, 10, 4, 4)
121 #log("sv_maxu", expected_vl, cr_res)
122
123 with Program(lst, bigendian=False) as program:
124 sim = self.run_tst_program(program, initial_regs=gprs,
125 svstate=svstate)
126 for i in range(vl):
127 val = sim.gpr(i).value
128 res.append(val)
129 cr_res.append(0)
130 log("i", i, val)
131
132 for i in range(vl):
133 crf = sim.crl[i].get_range().value
134 log("crf", i, bin(crf))
135
136 # confirm that the results are as expected
137 return
138
139 for i, v in enumerate(cr_res[:vl]):
140 crf = sim.crl[i].get_range().value
141 log("crf", i, res[i], bin(crf), bin(int(v)))
142 self.assertEqual(crf, int(v))
143
144 for i, v in enumerate(res):
145 self.assertEqual(v, res[i])
146
147 #self.assertEqual(sim.svstate.vl, expected_vl)
148 #self.assertEqual(sim.svstate.maxvl, 4)
149 #self.assertEqual(sim.svstate.srcstep, 0)
150 #self.assertEqual(sim.svstate.dststep, 0)
151
152 def run_tst_program(self, prog, initial_regs=None,
153 svstate=None,
154 initial_mem=None,
155 initial_fprs=None):
156 if initial_regs is None:
157 initial_regs = [0] * 32
158 simulator = run_tst(prog, initial_regs, mem=initial_mem,
159 initial_fprs=initial_fprs,
160 svstate=svstate)
161
162 print("GPRs")
163 simulator.gpr.dump()
164 print("FPRs")
165 simulator.fpr.dump()
166
167 return simulator
168
169
170 if __name__ == "__main__":
171 unittest.main()