From bdfa527601e7b64de434a5b029d13805f87fc755 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 16 Jul 2021 18:15:31 +0100 Subject: [PATCH] add fsins and fcoss to simulator WARNING: THESE ARE **NOT** APPROVED BY OPF ISA WG, CONSIDER TO BE DRAFT in particular, they have had to be added to minor opcode 59 (alongside fcfids) because there is not enough space to add them to "sandbox" 22 --- openpower/isa/svfparith.mdwn | 38 ++++++++++ openpower/isatables/RM-2P-1S1D.csv | 2 + openpower/isatables/minor_59.csv | 2 + src/openpower/decoder/helpers.py | 21 ++++++ src/openpower/decoder/isa/caller.py | 8 ++ .../isa/test_caller_transcendentals.py | 74 +++++++++++++++++++ src/openpower/decoder/power_enums.py | 1 + src/openpower/decoder/pseudo/pywriter.py | 1 + src/openpower/sv/trans/svp64.py | 30 ++++++++ 9 files changed, 177 insertions(+) create mode 100644 src/openpower/decoder/isa/test_caller_transcendentals.py diff --git a/openpower/isa/svfparith.mdwn b/openpower/isa/svfparith.mdwn index 021a7c3d..46591332 100644 --- a/openpower/isa/svfparith.mdwn +++ b/openpower/isa/svfparith.mdwn @@ -5,6 +5,8 @@ + + # Floating Add FFT/DCT [Single] A-Form @@ -233,3 +235,39 @@ Special Registers Altered: VXSNAN VXISI VXIMZ CR1 (if Rc=1) +# Floating SIN [Single] + +X-Form + +* fsins FRT,FRB (Rc=0) +* fsins. FRT,FRB (Rc=1) + +Pseudo-code: + + FRT <- FPSIN32(FRB) + +Special Registers Altered: + + FPRF FR FI + FX OX UX XX + VXSNAN VXISI VXIMZ + CR1 (if Rc=1) + +# Floating COS [Single] + +X-Form + +* fcoss FRT,FRB (Rc=0) +* fcoss. FRT,FRB (Rc=1) + +Pseudo-code: + + FRT <- FPCOS32(FRB) + +Special Registers Altered: + + FPRF FR FI + FX OX UX XX + VXSNAN VXISI VXIMZ + CR1 (if Rc=1) + diff --git a/openpower/isatables/RM-2P-1S1D.csv b/openpower/isatables/RM-2P-1S1D.csv index fa161379..f2f0ae6b 100644 --- a/openpower/isatables/RM-2P-1S1D.csv +++ b/openpower/isatables/RM-2P-1S1D.csv @@ -37,6 +37,8 @@ extsw,,2P,EXTRA3,d:RA;d:CR0,s:RS,0,0,RS,0,0,RA,0,CR0,0 fsqrts,,2P,EXTRA3,d:FRT;d:CR1,s:FRB,0,0,0,FRB,0,FRT,0,CR1,0 fres,,2P,EXTRA3,d:FRT;d:CR1,s:FRB,0,0,0,FRB,0,FRT,0,CR1,0 frsqrtes,,2P,EXTRA3,d:FRT;d:CR1,s:FRB,0,0,0,FRB,0,FRT,0,CR1,0 +fsins,,2P,EXTRA3,d:FRT;d:CR1,s:FRB,0,0,0,FRB,0,FRT,0,CR1,0 +fcoss,,2P,EXTRA3,d:FRT;d:CR1,s:FRB,0,0,0,FRB,0,FRT,0,CR1,0 fcfids,,2P,EXTRA3,d:FRT;d:CR1,s:FRB,0,0,0,FRB,0,FRT,0,CR1,0 fcfidus,,2P,EXTRA3,d:FRT;d:CR1,s:FRB,0,0,0,FRB,0,FRT,0,CR1,0 fsqrt,,2P,EXTRA3,d:FRT;d:CR1,s:FRB,0,0,0,FRB,0,FRT,0,CR1,0 diff --git a/openpower/isatables/minor_59.csv b/openpower/isatables/minor_59.csv index 1605a58d..731245ad 100644 --- a/openpower/isatables/minor_59.csv +++ b/openpower/isatables/minor_59.csv @@ -17,3 +17,5 @@ opcode,unit,internal op,in1,in2,in3,out,CR in,CR out,inv A,inv out,cry in,cry ou -----00110,FPU,OP_FP_MADD,FRA,FRB,FRC,FRT,NONE,CR1,0,0,ZERO,0,NONE,0,0,0,0,1,0,RC,0,0,ffnmsubs,A, -----00111,FPU,OP_FP_MADD,FRA,FRB,FRC,FRT,NONE,CR1,0,0,ZERO,0,NONE,0,0,0,0,1,0,RC,0,0,ffnmadds,A, -----01101,FPU,OP_FPOP,FRA,FRB,NONE,FRT,NONE,CR1,0,0,ZERO,0,NONE,0,0,0,0,1,0,RC,0,0,ffadds,A, +1000001100,FPU,OP_FPOP,NONE,FRB,NONE,FRT,NONE,CR1,0,0,ZERO,0,NONE,0,0,0,0,1,0,RC,0,0,fsins,X, +1000101100,FPU,OP_FPOP,NONE,FRB,NONE,FRT,NONE,CR1,0,0,ZERO,0,NONE,0,0,0,0,1,0,RC,0,0,fcoss,X, diff --git a/src/openpower/decoder/helpers.py b/src/openpower/decoder/helpers.py index 5fe5fce5..405b65e0 100644 --- a/src/openpower/decoder/helpers.py +++ b/src/openpower/decoder/helpers.py @@ -9,6 +9,7 @@ from openpower.decoder.selectable_int import selectgtu as gtu from openpower.decoder.selectable_int import check_extsign from openpower.util import log +import math trunc_div = floordiv trunc_rem = mod @@ -260,6 +261,26 @@ def fp64toselectable(frt): return SelectableInt(val, 64) +def FPSIN32(FRB): + from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE + #FRB = DOUBLE(SINGLE(FRB)) + result = math.sin(float(FRB)) + cvt = fp64toselectable(result) + cvt = DOUBLE2SINGLE(cvt) + log ("FPSIN32", FRB, float(FRB), "=", result, cvt) + return cvt + + +def FPCOS32(FRB): + from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE + #FRB = DOUBLE(SINGLE(FRB)) + result = math.cos(float(FRB)) + cvt = fp64toselectable(result) + cvt = DOUBLE2SINGLE(cvt) + log ("FPCOS32", FRB, float(FRB), "=", result, cvt) + return cvt + + def FPADD32(FRA, FRB): from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE #return FPADD64(FRA, FRB) diff --git a/src/openpower/decoder/isa/caller.py b/src/openpower/decoder/isa/caller.py index 47da1022..c57434cb 100644 --- a/src/openpower/decoder/isa/caller.py +++ b/src/openpower/decoder/isa/caller.py @@ -1087,6 +1087,14 @@ class ISACaller: illegal = False name = 'svshape' + # and fsin and fcos + if asmop == 'fsins': + illegal = False + name = 'fsins' + if asmop == 'fcoss': + illegal = False + name = 'fcoss' + # sigh also deal with ffmadds not being supported by binutils (.long) if asmop == 'ffmadds': illegal = False diff --git a/src/openpower/decoder/isa/test_caller_transcendentals.py b/src/openpower/decoder/isa/test_caller_transcendentals.py new file mode 100644 index 00000000..a571dace --- /dev/null +++ b/src/openpower/decoder/isa/test_caller_transcendentals.py @@ -0,0 +1,74 @@ +from nmigen import Module, Signal +from nmigen.back.pysim import Simulator, Delay, Settle +from nmutil.formaltest import FHDLTestCase +import unittest +from openpower.decoder.isa.caller import ISACaller +from openpower.decoder.power_decoder import (create_pdecode) +from openpower.decoder.power_decoder2 import (PowerDecode2) +from openpower.simulator.program import Program +from openpower.decoder.isa.caller import ISACaller, SVP64State +from openpower.decoder.selectable_int import SelectableInt +from openpower.decoder.orderedset import OrderedSet +from openpower.decoder.isa.all import ISA +from openpower.decoder.isa.test_caller import Register, run_tst +from copy import deepcopy +from openpower.sv.trans.svp64 import SVP64Asm +from openpower.decoder.helpers import fp64toselectable +from openpower.decoder.isafunctions.double2single import DOUBLE2SINGLE + +import math + +class FPTranscendentalsTestCase(FHDLTestCase): + + def _check_regs(self, sim, expected_int, expected_fpr): + for i in range(32): + self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64)) + for i in range(32): + self.assertEqual(sim.fpr(i), SelectableInt(expected_fpr[i], 64)) + + def test_fp_sins_coss(self): + """>>> lst = ["fsins 1, 2", + "fcoss 3, 2", + ] + """ + lst = SVP64Asm(["fsins 1, 2", + "fcoss 3, 2", + ]) + lst = list(lst) + + with Program(lst, bigendian=False) as program: + fprs = [0] * 32 + for i in range(-8, 9): + a = math.pi * (i / 8.0) * 2.0 + fprs[2] = fp64toselectable(a) + t = math.sin(a) + u = math.cos(a) + a1 = fp64toselectable(a) # convert to Power single + t = DOUBLE2SINGLE(fp64toselectable(t)) # convert to Power single + u = DOUBLE2SINGLE(fp64toselectable(u)) # convert to Power single + + with self.subTest(): + sim = self.run_tst_program(program, initial_fprs=fprs) + print("FPR 1", sim.fpr(1)) + print("FPR 2", sim.fpr(2)) + print("FPR 3", sim.fpr(3)) + self.assertEqual(sim.fpr(2), SelectableInt(a1, 64)) + self.assertEqual(sim.fpr(1), SelectableInt(t, 64)) + self.assertEqual(sim.fpr(3), SelectableInt(u, 64)) + + def run_tst_program(self, prog, initial_regs=None, + initial_mem=None, + initial_fprs=None): + if initial_regs is None: + initial_regs = [0] * 32 + simulator = run_tst(prog, initial_regs, mem=initial_mem, + initial_fprs=initial_fprs) + print ("GPRs") + simulator.gpr.dump() + print ("FPRs") + simulator.fpr.dump() + return simulator + + +if __name__ == "__main__": + unittest.main() diff --git a/src/openpower/decoder/power_enums.py b/src/openpower/decoder/power_enums.py index 97a5dc52..478b1451 100644 --- a/src/openpower/decoder/power_enums.py +++ b/src/openpower/decoder/power_enums.py @@ -247,6 +247,7 @@ _insns = [ "ffmsubs", "ffmadds", "ffnmsubs", "ffnmadds", # FFT FP 3-arg "fmul", "fmuls", "fdiv", "fdivs", # FP mul / div "fmr", "fabs", "fnabs", "fneg", "fcpsgn", # FP move/abs/neg + "fsins", "fcoss", # FP SIN/COS "hrfid", "icbi", "icbt", "isel", "isync", "lbarx", "lbz", "lbzu", "lbzux", "lbzx", # load byte "ld", "ldarx", "ldbrx", "ldu", "ldux", "ldx", # load double diff --git a/src/openpower/decoder/pseudo/pywriter.py b/src/openpower/decoder/pseudo/pywriter.py index 11a30e39..aa043fd4 100644 --- a/src/openpower/decoder/pseudo/pywriter.py +++ b/src/openpower/decoder/pseudo/pywriter.py @@ -39,6 +39,7 @@ from openpower.decoder.helpers import ( FPADD32, FPSUB32, FPMUL32, FPDIV32, FPADD64, FPSUB64, FPMUL64, FPDIV64, FPMULADD32, + FPSIN32, FPCOS32, ) from openpower.decoder.isafunctions.fpfromint import INT2FP diff --git a/src/openpower/sv/trans/svp64.py b/src/openpower/sv/trans/svp64.py index 6ea5009a..3b5eebfa 100644 --- a/src/openpower/sv/trans/svp64.py +++ b/src/openpower/sv/trans/svp64.py @@ -230,6 +230,36 @@ class SVP64Asm: yield ".long 0x%x" % insn return + # and fsins + # XXX WARNING THESE ARE NOT APPROVED BY OPF ISA WG + # however we are out of space with opcode 22 + if opcode.startswith('fsins'): + fields = list(map(int, fields)) + insn = 59 << (31-5) # opcode 59, bits 0-5 + insn |= fields[0] << (31-10) # RT , bits 6-10 + insn |= fields[1] << (31-20) # RB , bits 16-20 + insn |= 0b1000001100 << (31-30) # XO , bits 21..30 + if opcode == 'fsins.': + insn |= 1 << (31-31) # Rc=1 , bit 31 + log ("fsins", bin(insn)) + yield ".long 0x%x" % insn + return + + # and fcoss + # XXX WARNING THESE ARE NOT APPROVED BY OPF ISA WG + # however we are out of space with opcode 22 + if opcode.startswith('fcoss'): + fields = list(map(int, fields)) + insn = 59 << (31-5) # opcode 59, bits 0-5 + insn |= fields[0] << (31-10) # RT , bits 6-10 + insn |= fields[1] << (31-20) # RB , bits 16-20 + insn |= 0b1000101100 << (31-30) # XO , bits 21..30 + if opcode == 'fsins.': + insn |= 1 << (31-31) # Rc=1 , bit 31 + log ("fsins", bin(insn)) + yield ".long 0x%x" % insn + return + # identify if is a svp64 mnemonic if not opcode.startswith('sv.'): yield insn # unaltered -- 2.30.2