1395d3fb2c39739259ef8f7727fc0f876cb107e3
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
20 from openpower
.decoder
.isa
.maxloc
import m2
27 return "<lt %d gt %d eq %d>" % (self
.lt
, self
.gt
, self
.eq
)
29 return (CRf
.lt
<<3) |
(CRf
.gt
<<2) |
(CRf
.eq
<<1)
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
):
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
]
48 return i
, CR0
# new VL
51 class DDFFirstTestCase(FHDLTestCase
):
53 def _check_regs(self
, sim
, expected
):
55 self
.assertEqual(sim
.gpr(i
), SelectableInt(expected
[i
], 64))
57 def test_sv_maxloc_1(self
):
58 self
.sv_maxloc([1,3,3,3])
60 def tst_sv_maxloc_2(self
):
61 self
.sv_maxloc([3,4,1,5])
63 def tst_sv_maxloc_3(self
):
64 self
.sv_maxloc([2,9,8,0])
66 def tst_sv_maxloc_4(self
):
67 self
.sv_maxloc([2,1,3,0])
69 def sv_maxloc(self
, ra
):
71 m, nm, i, n = 0, 0, 0, len(a)
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
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, -0x4c" # CR0 lt bit clear, branch back
104 svstate
= SVP64State()
105 vl
= len(ra
) # VL is length of array ra
107 svstate
.maxvl
= vl
# MAXVL
108 print("SVSTATE", bin(svstate
.asint()))
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
115 log("maxu ddff", i
, gprs
[10+i
])
120 #expected_vl, expected_cr = sv_maxu(res, cr_res, vl, 10, 4, 4)
121 #log("sv_maxu", expected_vl, cr_res)
123 with
Program(lst
, bigendian
=False) as program
:
124 sim
= self
.run_tst_program(program
, initial_regs
=gprs
,
127 val
= sim
.gpr(i
).value
133 crf
= sim
.crl
[i
].get_range().value
134 log("crf", i
, bin(crf
))
136 # confirm that the results are as expected
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
))
144 for i
, v
in enumerate(res
):
145 self
.assertEqual(v
, res
[i
])
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)
152 def run_tst_program(self
, prog
, initial_regs
=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
,
170 if __name__
== "__main__":