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/
12 from copy
import deepcopy
14 from nmutil
.formaltest
import FHDLTestCase
15 from openpower
.decoder
.isa
.caller
import SVP64State
16 from openpower
.decoder
.isa
.test_caller
import run_tst
17 from openpower
.decoder
.selectable_int
import SelectableInt
18 from openpower
.simulator
.program
import Program
19 from openpower
.insndb
.asm
import SVP64Asm
20 from openpower
.util
import log
21 from openpower
.decoder
.isa
.maxloc
import m2
28 return "<lt %d gt %d eq %d>" % (self
.lt
, self
.gt
, self
.eq
)
30 return (CRf
.lt
<<3) |
(CRf
.gt
<<2) |
(CRf
.eq
<<1)
38 # example sv.minmax/ff=lt 0, 1, *10, 5
39 # see https://bugs.libre-soc.org/show_bug.cgi?id=1183#c3
40 def sv_maxu(gpr
, vl
, ra
, rb
, rt
):
43 CR0
= cmpd(gpr
[ra
+i
], gpr
[rb
])
44 log("sv_maxss test", i
, gpr
[ra
+ i
], gpr
[rb
], CR0
, int(CR0
))
45 gpr
[rt
] = gpr
[ra
+i
] if CR0
.lt
else gpr
[rb
]
49 return i
, CR0
# new VL
52 class DDFFirstTestCase(FHDLTestCase
):
54 def _check_regs(self
, sim
, expected
):
56 self
.assertEqual(sim
.gpr(i
), SelectableInt(expected
[i
], 64))
58 def test_sv_maxloc_1(self
):
59 self
.sv_maxloc([1,3,3,3])
61 def test_sv_maxloc_2(self
):
62 self
.sv_maxloc([3,4,1,5])
64 def test_sv_maxloc_3(self
):
65 self
.sv_maxloc([2,9,8,0])
67 def test_sv_maxloc_4(self
):
68 self
.sv_maxloc([2,1,3,0])
70 def test_sv_maxloc_5(self
):
71 self
.sv_maxloc([0,0,0,0])
73 def test_sv_maxloc_6(self
):
74 self
.sv_maxloc([0,9,9,3])
76 def test_sv_maxloc_7(self
):
77 self
.sv_maxloc([9,0,10,11])
79 def test_sv_maxloc_random(self
):
80 random
.seed(1) # set the same seed (consistent test)
84 array
.append(random
.randint(0, 20))
85 with self
.subTest(i
=i
):
88 def sv_maxloc(self
, ra
):
90 m, nm, i, n = 0, 0, 0, len(a)
92 while (i<n and a[i]<=m) : i += 1
93 while (i<n and a[i] > m): m, nm, i = a[i], i, i+1
97 # note that m (above) is r4. sv.cmp can be used in the first
98 # while loop because m (r4) does not change. sv.minmax. has
99 # to be used in the key while loop because r4 is sequentially
100 # replaced (mapreduce mode) each time. also note that i is
101 # represented as a bitmask (CR bits 16,20,24,28)
105 "setvl 2,0,4,0,1,1", # set MVL=4, VL=MIN(MVL,CTR)
106 # while (i<n and a[i]<=m) : i += 1
107 "sv.cmp/ff=gt/m=ge *0,0,*10,4", # truncates VL to min
108 "sv.creqv *16,*16,*16", # set mask on already-tested
109 "setvl 2,0,4,0,1,1", # set MVL=4, VL=MIN(MVL,CTR)
110 "mtcrf 128, 0", # clear CR0 (in case VL=0?)
111 # while (i<n and a[i]>m):
112 "sv.minmax./ff=le/m=ge/mr 4,*10,4,1", # uses r4 as accumulator
113 "crternlogi 0,1,2,127", # test greater/equal or VL=0
114 "sv.crand *19,*16,0", # clear if CR0.eq=0
115 # nm = i (count masked bits. could use crweirds here TODO)
116 "sv.svstep/mr/m=so 1, 0, 6, 1", # svstep: get vector dststep
117 "sv.creqv *16,*16,*16", # set mask on already-tested
118 "bc 12,0, -0x40" # CR0 lt bit clear, branch back
123 svstate
= SVP64State()
124 vl
= len(ra
) # VL is length of array ra
126 svstate
.maxvl
= vl
# MAXVL
127 print("SVSTATE", bin(svstate
.asint()))
130 gprs
[3] = vl
# variable n: to go into CTR
131 gprs
[4] = 2 # variable m: max current number found
132 for i
, ra
in enumerate(ra
): # vector in ra starts at r10
134 log("maxu ddff", i
, gprs
[10+i
])
139 #expected_vl, expected_cr = sv_maxu(res, cr_res, vl, 10, 4, 4)
140 #log("sv_maxu", expected_vl, cr_res)
142 with
Program(lst
, bigendian
=False) as program
:
143 sim
= self
.run_tst_program(program
, initial_regs
=gprs
,
146 val
= sim
.gpr(i
).value
152 crf
= sim
.crl
[i
].get_range().value
153 log("crf", i
, bin(crf
))
155 # confirm that the results are as expected
158 for i
, v
in enumerate(cr_res
[:vl
]):
159 crf
= sim
.crl
[i
].get_range().value
160 log("crf", i
, res
[i
], bin(crf
), bin(int(v
)))
161 self
.assertEqual(crf
, int(v
))
163 for i
, v
in enumerate(res
):
164 self
.assertEqual(v
, res
[i
])
166 #self.assertEqual(sim.svstate.vl, expected_vl)
167 #self.assertEqual(sim.svstate.maxvl, 4)
168 #self.assertEqual(sim.svstate.srcstep, 0)
169 #self.assertEqual(sim.svstate.dststep, 0)
171 def run_tst_program(self
, prog
, initial_regs
=None,
175 if initial_regs
is None:
176 initial_regs
= [0] * 32
177 simulator
= run_tst(prog
, initial_regs
, mem
=initial_mem
,
178 initial_fprs
=initial_fprs
,
189 if __name__
== "__main__":