add extra offset for FRB, for FFT Cooley-Tukey twin mul/add-sub
[openpower-isa.git] / src / openpower / decoder / isa / test_caller_svp64_fft.py
1 from nmigen import Module, Signal
2 from nmigen.back.pysim import Simulator, Delay, Settle
3 from nmutil.formaltest import FHDLTestCase
4 import unittest
5 from openpower.decoder.isa.caller import ISACaller
6 from openpower.decoder.power_decoder import (create_pdecode)
7 from openpower.decoder.power_decoder2 import (PowerDecode2)
8 from openpower.simulator.program import Program
9 from openpower.decoder.isa.caller import ISACaller, SVP64State
10 from openpower.decoder.selectable_int import SelectableInt
11 from openpower.decoder.orderedset import OrderedSet
12 from openpower.decoder.isa.all import ISA
13 from openpower.decoder.isa.test_caller import Register, run_tst
14 from openpower.sv.trans.svp64 import SVP64Asm
15 from openpower.consts import SVP64CROffs
16 from copy import deepcopy
17 from openpower.decoder.helpers import fp64toselectable
18 from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE
19
20 class DecoderTestCase(FHDLTestCase):
21
22 def _check_regs(self, sim, expected):
23 for i in range(32):
24 self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64))
25
26 def test_sv_fpmadds_fft(self):
27 """>>> lst = ["sv.ffmadds 2.v, 2.v, 2.v, 10.v"
28 ]
29 four in-place vector mul-adds, four in-place vector mul-subs
30
31 this is the twin "butterfly" mul-add-sub from Cooley-Tukey
32 https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm#Data_reordering,_bit_reversal,_and_in-place_algorithms
33
34 there is the *option* to target a different location (non-in-place)
35 just in case.
36
37 SVP64 "FFT" mode will *automatically* offset FRB and an implicit
38 FRS to perform the two multiplies. one add, one subtract.
39
40 sv.ffmadds FRT, FRA, FRC, FRB actually does:
41 fmadds FRT , FRA, FRC, FRA
42 fnmsubs FRT+vl, FRA, FRC, FRB+vl
43 """
44 lst = SVP64Asm(["sv.ffmadds 2.v, 2.v, 2.v, 10.v"
45 ])
46 lst = list(lst)
47
48 fprs = [0] * 32
49 av = [7.0, -9.8, 2.0, -32.3] # first half of array 0..3
50 bv = [-2.0, 2.0, -9.8, 32.3] # second half of array 4..7
51 coe = [-1.0, 4.0, 3.1, 6.2] # coefficients
52 res = []
53 # work out the results with the twin mul/add-sub
54 for i, (a, b, c) in enumerate(zip(av, bv, coe)):
55 fprs[i+2] = fp64toselectable(a)
56 fprs[i+6] = fp64toselectable(b)
57 fprs[i+10] = fp64toselectable(c)
58 mul = a * c
59 t = a + mul
60 u = b - mul
61 t = DOUBLE2SINGLE(fp64toselectable(t)) # convert to Power single
62 u = DOUBLE2SINGLE(fp64toselectable(u)) # from double
63 res.append((t, u))
64 print ("FFT", i, "in", a, b, "coeff", c, "mul", mul, "res", t, u)
65
66 # SVSTATE (in this case, VL=2)
67 svstate = SVP64State()
68 svstate.vl[0:7] = 4 # VL
69 svstate.maxvl[0:7] = 4 # MAXVL
70 print ("SVSTATE", bin(svstate.spr.asint()))
71
72 with Program(lst, bigendian=False) as program:
73 sim = self.run_tst_program(program, svstate=svstate,
74 initial_fprs=fprs)
75 # confirm that the results are as expected
76 for i, (t, u) in enumerate(res):
77 self.assertEqual(sim.fpr(i+2), t)
78 self.assertEqual(sim.fpr(i+6), u)
79
80 def run_tst_program(self, prog, initial_regs=None,
81 svstate=None,
82 initial_mem=None,
83 initial_fprs=None):
84 if initial_regs is None:
85 initial_regs = [0] * 32
86 simulator = run_tst(prog, initial_regs, mem=initial_mem,
87 initial_fprs=initial_fprs,
88 svstate=svstate)
89
90 print ("GPRs")
91 simulator.gpr.dump()
92 print ("FPRs")
93 simulator.fpr.dump()
94
95 return simulator
96
97
98 if __name__ == "__main__":
99 unittest.main()