add fsins and fcoss to simulator
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 16 Jul 2021 17:15:31 +0000 (18:15 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 16 Jul 2021 17:15:31 +0000 (18:15 +0100)
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
openpower/isatables/RM-2P-1S1D.csv
openpower/isatables/minor_59.csv
src/openpower/decoder/helpers.py
src/openpower/decoder/isa/caller.py
src/openpower/decoder/isa/test_caller_transcendentals.py [new file with mode: 0644]
src/openpower/decoder/power_enums.py
src/openpower/decoder/pseudo/pywriter.py
src/openpower/sv/trans/svp64.py

index 021a7c3d1d9c8a13872ee38d7769b05a9e1d8b5b..46591332eec0cb18222795e64ed2bd53eeca4f76 100644 (file)
@@ -5,6 +5,8 @@
 <!-- FRS is automatically calculated by SVP64 to FRT+VL (default elwidth) -->
 <!-- (Vector FRS data sequentially starts immediately after FRT vectors) -->
 
+<!-- PLEASE NOTE THESE ARE UNAPPROVED AND DRAFT, NOT SUBMITTED TO OPF ISA WG -->
+
 # 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)
+
index fa16137904ee2eed6fe0f80d26a8f9987da6fc3d..f2f0ae6b1cea5c4660fef984b66aba6214bd1458 100644 (file)
@@ -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
index 1605a58d4dfbab13cf25fd6fe2225bced0f76840..731245ade59c64dcf27825551f0c3ece9aa6d97c 100644 (file)
@@ -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,
index 5fe5fce5020aa1d71e3a00f56b43b28d4d7e20fd..405b65e09aafe05861ee7449bb334bfc3c4f6719 100644 (file)
@@ -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)
index 47da1022d34fbd396d3e1dbc9dddae348e6ccb50..c57434cb6a15e7367ca801f81de852ea7bf40534 100644 (file)
@@ -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 (file)
index 0000000..a571dac
--- /dev/null
@@ -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()
index 97a5dc521c50540b8888281c4be2ee1eb701aa64..478b1451913aeed5fa3fbf21338c19326128b42f 100644 (file)
@@ -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
index 11a30e39a5a144e7396b2b68dbb66d4deb466d24..aa043fd467c4027a2cdcfbc236c34b284b253583 100644 (file)
@@ -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
 
index 6ea5009af1b316595a20e5910b3f6e15ffcbc482..3b5eebfa74fad817de31eeb5188af9f8b575380d 100644 (file)
@@ -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