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(2) # set the same seed (consistent test)
84 array
.append(random
.randint(0, 20))
85 with self
.subTest(name
="test_sv_maxloc_random_%d" % i
, 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 "sv.crnand/m=lt/zz *19,*16,0", # combine LT if CR0.eq=0
114 # nm = i (count masked bits. could use crweirds here TODO)
115 "sv.svstep/mr/m=so 1, 0, 6, 1", # svstep: get vector dststep
116 "sv.creqv *16,*16,*16", # set mask on already-tested
117 "bc 12,0, -0x3c" # CR0 lt bit clear, branch back
122 svstate
= SVP64State()
123 vl
= len(ra
) # VL is length of array ra
125 svstate
.maxvl
= vl
# MAXVL
126 print("SVSTATE", bin(svstate
.asint()))
129 gprs
[3] = vl
# variable n: to go into CTR
130 gprs
[4] = 2 # variable m: max current number found
131 for i
, ra
in enumerate(ra
): # vector in ra starts at r10
133 log("maxu ddff", i
, gprs
[10+i
])
138 #expected_vl, expected_cr = sv_maxu(res, cr_res, vl, 10, 4, 4)
139 #log("sv_maxu", expected_vl, cr_res)
141 with
Program(lst
, bigendian
=False) as program
:
142 sim
= self
.run_tst_program(program
, initial_regs
=gprs
,
145 val
= sim
.gpr(i
).value
151 crf
= sim
.crl
[i
].get_range().value
152 log("crf", i
, bin(crf
))
154 # confirm that the results are as expected
157 for i
, v
in enumerate(cr_res
[:vl
]):
158 crf
= sim
.crl
[i
].get_range().value
159 log("crf", i
, res
[i
], bin(crf
), bin(int(v
)))
160 self
.assertEqual(crf
, int(v
))
162 for i
, v
in enumerate(res
):
163 self
.assertEqual(v
, res
[i
])
165 #self.assertEqual(sim.svstate.vl, expected_vl)
166 #self.assertEqual(sim.svstate.maxvl, 4)
167 #self.assertEqual(sim.svstate.srcstep, 0)
168 #self.assertEqual(sim.svstate.dststep, 0)
170 def run_tst_program(self
, prog
, initial_regs
=None,
174 if initial_regs
is None:
175 initial_regs
= [0] * 32
176 simulator
= run_tst(prog
, initial_regs
, mem
=initial_mem
,
177 initial_fprs
=initial_fprs
,
188 if __name__
== "__main__":