1 from nmigen
import Module
, Signal
2 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
3 from nmutil
.formaltest
import FHDLTestCase
5 from openpower
.decoder
.power_decoder
import (create_pdecode
)
6 from openpower
.simulator
.program
import Program
7 from openpower
.decoder
.isa
.caller
import SVP64State
8 from openpower
.decoder
.selectable_int
import SelectableInt
9 from openpower
.decoder
.isa
.test_caller
import run_tst
10 from openpower
.sv
.trans
.svp64
import SVP64Asm
11 from copy
import deepcopy
12 from openpower
.decoder
.helpers
import fp64toselectable
, SINGLE
13 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
16 class DCTTestCase(FHDLTestCase
):
18 def _check_regs(self
, sim
, expected
):
20 self
.assertEqual(sim
.gpr(i
), SelectableInt(expected
[i
], 64))
22 def test_sv_ffadds_dct(self
):
23 """>>> lst = ["sv.fdmadds 0.v, 8.v, 0.v, 0.v"
25 four in-place vector adds, four in-place vector mul-subs
27 SVP64 "DCT" mode will *automatically* offset FRB and an implicit
28 FRS to perform the two multiplies. one add, one subtract.
30 sv.fdadds FRT, FRA, FRC, FRB actually does:
32 fsubs FRT+vl, FRA, FRB+vl
34 lst
= SVP64Asm(["sv.fdmadds 0.v, 8.v, 0.v, 0.v"
39 av
= [7.0, -9.8, 2.0, -32.3] # first half of array 0..3
40 bv
= [-2.0, 2.0, -9.8, 32.3] # second half of array 4..7
41 cv
= [-1.0, 0.5, 2.3, -3.2] # coefficients
43 # work out the results with the twin add-sub
44 for i
, (a
, b
, c
) in enumerate(zip(av
, bv
, cv
)):
45 fprs
[i
+0] = fp64toselectable(a
)
46 fprs
[i
+4] = fp64toselectable(b
)
47 fprs
[i
+8] = fp64toselectable(c
)
50 t
= DOUBLE2SINGLE(fp64toselectable(t
)) # convert to Power single
51 u
= DOUBLE2SINGLE(fp64toselectable(u
)) # from double
53 print ("FFT", i
, "in", a
, b
, "c", c
, "res", t
, u
)
55 # SVSTATE (in this case, VL=2)
56 svstate
= SVP64State()
58 svstate
.maxvl
= 4 # MAXVL
59 print ("SVSTATE", bin(svstate
.asint()))
61 with
Program(lst
, bigendian
=False) as program
:
62 sim
= self
.run_tst_program(program
, svstate
=svstate
,
64 # confirm that the results are as expected
65 for i
, (t
, u
) in enumerate(res
):
66 a
= float(sim
.fpr(i
+0))
67 b
= float(sim
.fpr(i
+4))
70 print ("FFT", i
, "in", a
, b
, "res", t
, u
)
71 for i
, (t
, u
) in enumerate(res
):
72 self
.assertEqual(sim
.fpr(i
+2), t
)
73 self
.assertEqual(sim
.fpr(i
+6), u
)
75 def tst_sv_remap_fpmadds_dct(self
):
76 """>>> lst = ["svshape 4, 1, 1, 2, 0",
77 "svremap 31, 1, 0, 2, 0, 1, 0",
78 "sv.ffmadds 0.v, 0.v, 0.v, 8.v"
80 runs a full in-place O(N log2 N) butterfly schedule for
83 SVP64 "REMAP" in Butterfly Mode is applied to a twin +/- FMAC
86 lst
= SVP64Asm( ["svshape 4, 1, 1, 2, 0",
87 "svremap 31, 1, 0, 2, 0, 1, 0",
88 "sv.ffmadds 0.v, 0.v, 0.v, 8.v"
92 # array and coefficients to test
93 av
= [7.0, -9.8, 3.0, -32.3]
94 coe
= [-0.25, 0.5, 3.1, 6.2, 0.1, -0.2] # 6 coefficients
98 for i
, c
in enumerate(coe
):
99 fprs
[i
+8] = fp64toselectable(c
)
100 for i
, a
in enumerate(av
):
101 fprs
[i
+0] = fp64toselectable(a
)
103 with
Program(lst
, bigendian
=False) as program
:
104 sim
= self
.run_tst_program(program
, initial_fprs
=fprs
)
105 print ("spr svshape0", sim
.spr
['SVSHAPE0'])
106 print (" xdimsz", sim
.spr
['SVSHAPE0'].xdimsz
)
107 print (" ydimsz", sim
.spr
['SVSHAPE0'].ydimsz
)
108 print (" zdimsz", sim
.spr
['SVSHAPE0'].zdimsz
)
109 print ("spr svshape1", sim
.spr
['SVSHAPE1'])
110 print ("spr svshape2", sim
.spr
['SVSHAPE2'])
111 print ("spr svshape3", sim
.spr
['SVSHAPE3'])
115 # work out the results with the twin mul/add-sub
116 res
= transform_radix2(av
, coe
)
118 for i
, expected
in enumerate(res
):
119 print ("i", i
, float(sim
.fpr(i
)), "expected", expected
)
120 for i
, expected
in enumerate(res
):
121 # convert to Power single
122 expected
= DOUBLE2SINGLE(fp64toselectable(expected
))
123 expected
= float(expected
)
124 actual
= float(sim
.fpr(i
))
125 # approximate error calculation, good enough test
126 # reason: we are comparing FMAC against FMUL-plus-FADD-or-FSUB
127 # and the rounding is different
128 err
= abs(actual
- expected
) / expected
129 self
.assertTrue(err
< 1e-7)
131 def run_tst_program(self
, prog
, initial_regs
=None,
135 if initial_regs
is None:
136 initial_regs
= [0] * 32
137 simulator
= run_tst(prog
, initial_regs
, mem
=initial_mem
,
138 initial_fprs
=initial_fprs
,
149 if __name__
== "__main__":