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/
11 from copy
import deepcopy
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
26 return "<lt %d gt %d eq %d>" % (self
.lt
, self
.gt
, self
.eq
)
28 return (CRf
.lt
<<3) |
(CRf
.gt
<<2) |
(CRf
.eq
<<1)
36 # example sv.minmax/ff=lt 0, 1, *10, 5
37 # see https://bugs.libre-soc.org/show_bug.cgi?id=1183#c3
38 def sv_maxu(gpr
, vl
, ra
, rb
, rt
):
41 CR0
= cmpd(gpr
[ra
+i
], gpr
[rb
])
42 log("sv_maxss test", i
, gpr
[ra
+ i
], gpr
[rb
], CR0
, int(CR0
))
43 gpr
[rt
] = gpr
[ra
+i
] if CR0
.lt
else gpr
[rb
]
47 return i
, CR0
# new VL
50 class DDFFirstTestCase(FHDLTestCase
):
52 def _check_regs(self
, sim
, expected
):
54 self
.assertEqual(sim
.gpr(i
), SelectableInt(expected
[i
], 64))
56 def tst_sv_maxloc_1(self
):
57 self
.sv_maxloc([1,2,3,4])
59 def test_sv_maxloc_2(self
):
60 self
.sv_maxloc([3,4,1,5])
62 def tst_sv_maxloc_3(self
):
63 self
.sv_maxloc([2,9,8,0])
65 def tst_sv_maxloc_4(self
):
66 self
.sv_maxloc([2,1,3,0])
68 def sv_maxloc(self
, ra
):
70 m, nm, i, n = 0, 0, 0, len(a)
72 while (i<n and a[i]<=m) : i += 1
73 while (i<n and a[i] > m): m, nm, i = a[i], i, i+1
78 "mtspr 9, 3", # move r3 to CTR
79 "addi 0, 0, 0", # r0=0
80 #"addi 5, 4, 0", # copy m(r4) to r5
81 # VL = MIN(CTR,MAXVL=4)
82 "mtcrf 255,0", # clear CR entirely
83 "setvl 3,0,4,0,1,1", # set MVL=4, VL=MIN(MVL,CTR)
84 # load VL bytes (update r4 addr) but compressed (dw=8)
85 #"addi 6, 0, 0", # initialise r6 to zero
86 #"sv.lbzu/pi/dw=8 *6, 1(4)", # should be /lf here as well
87 # while (i<n and a[i]<=m) : i += 1
88 "sv.minmax./ff=ge *5, *10, *4, 1", # scalar RB=RT
89 "sv.mcrf/m=ge *4,*0", # masked-copy CR0-CR3 to CR4-CR7
90 "setvl 3,0,4,0,1,1", # set MVL=4, VL=MIN(MVL,CTR)
91 "sv.addi/mr/m=lt 4, *5, 0", # r4 = last non-masked value
92 "sv.minmax./ff=lt/m=ge 4, *10, 4, 1", # scalar RB=RT
93 "sv.svstep/mr 3, 0, 6, 1", # svstep: get vector dststep
94 "setvl 3,0,4,0,1,1", # set MVL=4, VL=MIN(MVL,CTR)
95 "sv.bc/all/m=ge 24, 19, -0x38", # until r10[i]>r4 (and dec CTR)
100 svstate
= SVP64State()
101 vl
= len(ra
) # VL is length of array ra
103 svstate
.maxvl
= vl
# MAXVL
104 print("SVSTATE", bin(svstate
.asint()))
107 gprs
[3] = vl
# variable n: to go into CTR
108 gprs
[4] = 0 # variable m: max current number found
109 for i
, ra
in enumerate(ra
): # vector in ra starts at r10
111 log("maxu ddff", i
, gprs
[10+i
])
116 #expected_vl, expected_cr = sv_maxu(res, cr_res, vl, 10, 4, 4)
117 #log("sv_maxu", expected_vl, cr_res)
119 with
Program(lst
, bigendian
=False) as program
:
120 sim
= self
.run_tst_program(program
, initial_regs
=gprs
,
123 val
= sim
.gpr(i
).value
129 crf
= sim
.crl
[i
].get_range().value
130 log("crf", i
, bin(crf
))
132 # confirm that the results are as expected
135 for i
, v
in enumerate(cr_res
[:vl
]):
136 crf
= sim
.crl
[i
].get_range().value
137 log("crf", i
, res
[i
], bin(crf
), bin(int(v
)))
138 self
.assertEqual(crf
, int(v
))
140 for i
, v
in enumerate(res
):
141 self
.assertEqual(v
, res
[i
])
143 #self.assertEqual(sim.svstate.vl, expected_vl)
144 #self.assertEqual(sim.svstate.maxvl, 4)
145 #self.assertEqual(sim.svstate.srcstep, 0)
146 #self.assertEqual(sim.svstate.dststep, 0)
148 def run_tst_program(self
, prog
, initial_regs
=None,
152 if initial_regs
is None:
153 initial_regs
= [0] * 32
154 simulator
= run_tst(prog
, initial_regs
, mem
=initial_mem
,
155 initial_fprs
=initial_fprs
,
166 if __name__
== "__main__":