a22b0d6d8bf64ea2a435705927a0e4c123bf0315
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
23 # example sv.cmpi/ff=lt 0, 1, *10, 5
24 # see https://bugs.libre-soc.org/show_bug.cgi?id=1183#c3
25 def sv_maxu(gpr
, CR
, vl
, ra
, rb
, rt
):
28 CR
[0] = cmpd(gpr
[ra
+i
], gpr
[rb
])
29 log("sv_maxss test", i
, gpr
[ra
+ i
], gpr
[rb
], CR
[0], int(CR
[0]))
30 gpr
[rt
] = gpr
[ra
+i
] if CR
[0].lt
else gpr
[rb
]
37 class DDFFirstTestCase(FHDLTestCase
):
39 def _check_regs(self
, sim
, expected
):
41 self
.assertEqual(sim
.gpr(i
), SelectableInt(expected
[i
], 64))
43 def test_sv_maxloc_1(self
):
44 self
.sv_maxloc([1,2,3,4])
46 def tst_sv_maxloc_2(self
):
47 self
.sv_maxloc([3,4,1,0])
49 def tst_sv_maxloc_3(self
):
50 self
.sv_maxloc([2,9,8,0])
52 def tst_sv_maxloc_4(self
):
53 self
.sv_maxloc([2,1,3,0])
55 def sv_maxloc(self
, ra
):
56 lst
= SVP64Asm(["sv.minmax./ff=le 4, *10, 4, 1" # scalar RB=RT
61 svstate
= SVP64State()
62 vl
= len(ra
) # VL is length of array ra
64 svstate
.maxvl
= vl
# MAXVL
65 print("SVSTATE", bin(svstate
.asint()))
68 gprs
[4] = rb
# (RT&RB) accumulator in r4
69 for i
, ra
in enumerate(ra
): # vector in ra starts at r10
71 log("maxu ddff", i
, gprs
[10+i
])
76 expected_vl
= sv_maxu(res
, cr_res
, vl
, 10, 4, 4)
77 log("sv_maxu", expected_vl
, cr_res
)
79 with
Program(lst
, bigendian
=False) as program
:
80 sim
= self
.run_tst_program(program
, initial_regs
=gprs
,
83 val
= sim
.gpr(i
).value
87 # confirm that the results are as expected
89 for i
, v
in enumerate(cr_res
[:vl
]):
90 crf
= sim
.crl
[i
].get_range().value
91 log("crf", i
, res
[i
], bin(crf
), bin(int(v
)))
92 self
.assertEqual(crf
, int(v
))
94 for i
, v
in enumerate(res
):
95 self
.assertEqual(v
, res
[i
])
97 self
.assertEqual(sim
.svstate
.vl
, expected_vl
)
98 self
.assertEqual(sim
.svstate
.maxvl
, 4)
99 self
.assertEqual(sim
.svstate
.srcstep
, 0)
100 self
.assertEqual(sim
.svstate
.dststep
, 0)
103 lst
= SVP64Asm(["sv.cmpi/ff=lt 0, 1, *10, 5"
108 svstate
= SVP64State()
111 svstate
.maxvl
= vl
# MAXVL
112 print("SVSTATE", bin(svstate
.asint()))
122 newvl
= sv_cmpi(gprs
, cr_res
, vl
, 10, 5)
123 log("sv_cmpi", newvl
, cr_res
)
125 with
Program(lst
, bigendian
=False) as program
:
126 sim
= self
.run_tst_program(program
, initial_regs
=gprs
,
129 val
= sim
.gpr(i
).value
133 # confirm that the results are as expected
134 expected
= deepcopy(vec
)
137 # calculate expected result and expected CR field
138 result
= vec
[i
] - gprs
[8]
139 crf
= ((result
==0)<<1) |
((result
> 0)<<2) |
((result
< 0) << 3)
143 # VLi=0 - test comes FIRST!
145 # only write out if successful
148 for i
, v
in enumerate(cr_res
):
149 crf
= sim
.crl
[i
].get_range().value
150 print ("crf", i
, res
[i
], bin(crf
), bin(v
))
151 self
.assertEqual(crf
, v
)
153 for i
, v
in enumerate(res
):
154 self
.assertEqual(v
, expected
[i
])
156 self
.assertEqual(sim
.svstate
.vl
, expected_vl
)
157 self
.assertEqual(sim
.svstate
.maxvl
, 4)
158 self
.assertEqual(sim
.svstate
.srcstep
, 0)
159 self
.assertEqual(sim
.svstate
.dststep
, 0)
161 def test_sv_addi_ffirst_le(self
):
162 lst
= SVP64Asm(["sv.subf./ff=le *0,8,*0"
167 svstate
= SVP64State()
169 svstate
.maxvl
= 4 # MAXVL
170 print("SVSTATE", bin(svstate
.asint()))
179 for i
, x
in enumerate(vec
):
182 with
Program(lst
, bigendian
=False) as program
:
183 sim
= self
.run_tst_program(program
, initial_regs
=gprs
,
186 val
= sim
.gpr(i
).value
190 # confirm that the results are as expected
191 expected
= deepcopy(vec
)
194 # calculate expected result and expected CR field
195 result
= vec
[i
] - gprs
[8]
196 crf
= ((result
==0)<<1) |
((result
> 0)<<2) |
((result
< 0) << 3)
200 # VLi=0 - test comes FIRST!
202 # only write out if successful
205 for i
, v
in enumerate(cr_res
):
206 crf
= sim
.crl
[i
].get_range().value
207 print ("crf", i
, res
[i
], bin(crf
), bin(v
))
208 self
.assertEqual(crf
, v
)
210 for i
, v
in enumerate(res
):
211 self
.assertEqual(v
, expected
[i
])
213 self
.assertEqual(sim
.svstate
.vl
, expected_vl
)
214 self
.assertEqual(sim
.svstate
.maxvl
, 4)
215 self
.assertEqual(sim
.svstate
.srcstep
, 0)
216 self
.assertEqual(sim
.svstate
.dststep
, 0)
218 def test_sv_addi_ffirst(self
):
219 lst
= SVP64Asm(["sv.subf./ff=eq *0,8,*0"
224 svstate
= SVP64State()
226 svstate
.maxvl
= 4 # MAXVL
227 print("SVSTATE", bin(svstate
.asint()))
236 for i
, x
in enumerate(vec
):
239 with
Program(lst
, bigendian
=False) as program
:
240 sim
= self
.run_tst_program(program
, initial_regs
=gprs
,
243 val
= sim
.gpr(i
).value
247 # confirm that the results are as expected
248 expected
= deepcopy(vec
)
250 result
= vec
[i
] - gprs
[8]
251 crf
= ((result
==0)<<1) |
((result
> 0)<<2) |
((result
< 0) << 3)
255 # VLi=0 - test comes FIRST!
257 for i
, v
in enumerate(cr_res
):
258 crf
= sim
.crl
[i
].get_range().value
259 print ("crf", i
, res
[i
], bin(crf
), bin(v
))
260 self
.assertEqual(crf
, v
)
262 for i
, v
in enumerate(res
):
263 self
.assertEqual(v
, expected
[i
])
265 self
.assertEqual(sim
.svstate
.vl
, 2)
266 self
.assertEqual(sim
.svstate
.maxvl
, 4)
267 self
.assertEqual(sim
.svstate
.srcstep
, 0)
268 self
.assertEqual(sim
.svstate
.dststep
, 0)
270 def test_sv_addi_ffirst_rc1(self
):
271 lst
= SVP64Asm(["sv.subf/ff=RC1 *0,8,*0" # RC1 auto-sets EQ (and Rc=1)
276 svstate
= SVP64State()
278 svstate
.maxvl
= 4 # MAXVL
279 print("SVSTATE", bin(svstate
.asint()))
287 for i
, x
in enumerate(vec
):
290 with
Program(lst
, bigendian
=False) as program
:
291 sim
= self
.run_tst_program(program
, initial_regs
=gprs
,
294 val
= sim
.gpr(i
).value
297 # confirm that the results are as expected
298 expected
= deepcopy(vec
)
300 result
= expected
[i
] - gprs
[8]
303 # VLi=0 - test comes FIRST!
305 for i
, v
in enumerate(res
):
306 self
.assertEqual(v
, expected
[i
])
308 self
.assertEqual(sim
.svstate
.vl
, 2)
309 self
.assertEqual(sim
.svstate
.maxvl
, 4)
310 self
.assertEqual(sim
.svstate
.srcstep
, 0)
311 self
.assertEqual(sim
.svstate
.dststep
, 0)
313 def test_sv_addi_ffirst_vli(self
):
314 """data-dependent fail-first with VLi=1, the test comes *after* write
316 lst
= SVP64Asm(["sv.subf/ff=RC1/vli *0,8,*0"
321 svstate
= SVP64State()
323 svstate
.maxvl
= 4 # MAXVL
324 print("SVSTATE", bin(svstate
.asint()))
332 for i
, x
in enumerate(vec
):
335 with
Program(lst
, bigendian
=False) as program
:
336 sim
= self
.run_tst_program(program
, initial_regs
=gprs
,
339 val
= sim
.gpr(i
).value
342 # confirm that the results are as expected
343 expected
= deepcopy(vec
)
345 # VLi=1 - test comes AFTER write!
346 expected
[i
] -= gprs
[8]
349 for i
, v
in enumerate(res
):
350 self
.assertEqual(v
, expected
[i
])
352 self
.assertEqual(sim
.svstate
.vl
, 3)
353 self
.assertEqual(sim
.svstate
.maxvl
, 4)
354 self
.assertEqual(sim
.svstate
.srcstep
, 0)
355 self
.assertEqual(sim
.svstate
.dststep
, 0)
357 def run_tst_program(self
, prog
, initial_regs
=None,
361 if initial_regs
is None:
362 initial_regs
= [0] * 32
363 simulator
= run_tst(prog
, initial_regs
, mem
=initial_mem
,
364 initial_fprs
=initial_fprs
,
375 if __name__
== "__main__":