add much more exhaustive maddsubrs unit tests
[openpower-isa.git] / src / openpower / test / alu / maddsubrs_cases.py
index 7958e5695f71be4276b7f2119a720a2af8a81b12..fecac44e51fe24f70bbc93838f144907c40ec034 100644 (file)
@@ -1,19 +1,15 @@
 from openpower.insndb.asm import SVP64Asm
-import random
 from openpower.test.common import TestAccumulatorBase, skip_case
 from openpower.endian import bigendian
 from openpower.simulator.program import Program
-from openpower.decoder.selectable_int import SelectableInt
-from openpower.decoder.power_enums import XER_bits
 from openpower.decoder.isa.caller import SVP64State
-from openpower.decoder.helpers import exts
 from openpower.test.state import ExpectedState
-import unittest
+from nmutil.sim_util import hash_256
 import math
+from fractions import Fraction
 
 
 class MADDSUBRSTestCase(TestAccumulatorBase):
-
     def case_0_maddsubrs(self):
         isa = SVP64Asm(["maddsubrs 1,10,14,11"])
         lst = list(isa)
@@ -140,6 +136,65 @@ class MADDSUBRSTestCase(TestAccumulatorBase):
 
         self.add_case(p, initial_regs, expected=e, initial_svstate=svstate)
 
+    def maddsubrs_many_helper(self, width, shift, prog, case_idx):
+        # if {'width': width, 'shift': shift, 'case_idx': case_idx} \
+        #         != {'width': 8, 'shift': 1, 'case_idx': 0}:
+        #     return  # for debugging
+        gprs = [0] * 32
+        # make some reproducible random inputs
+        k = f"maddsubrs {width} {shift} {case_idx}"
+        gprs[10] = hash_256(k + " r10") % 2**64
+        gprs[20] = hash_256(k + " r20") % 2**64
+        gprs[30] = hash_256(k + " r30") % 2**64
+
+        svstate = SVP64State()
+        svstate.vl = 64 // width  # one full 64-bit register
+        svstate.maxvl = 64 // width
+
+        e = ExpectedState(pc=8, int_regs=gprs)
+        e.intregs[10] = 0
+        e.intregs[11] = 0
+        for i in range(svstate.vl):
+            # extract elements
+            rt = (gprs[10] >> (i * width)) % 2 ** width
+            ra = (gprs[20] >> (i * width)) % 2 ** width
+            rb = (gprs[30] >> (i * width)) % 2 ** width
+            if rt >= 2 ** (width - 1):
+                rt -= 2 ** width  # sign extend rt
+            if ra >= 2 ** (width - 1):
+                ra -= 2 ** width  # sign extend ra
+            if rb >= 2 ** (width - 1):
+                rb -= 2 ** width  # sign extend rb
+            s = rt + ra
+            d = rt - ra
+            factor = Fraction(1, 2 ** shift)  # shr factor
+            round_up = Fraction(1, 2)
+            # mul & round & shr
+            rt = math.floor((s * rb) * factor + round_up)
+            rs = math.floor((d * rb) * factor + round_up)
+            # insert elements
+            e.intregs[10] |= (rt % 2 ** width) << (width * i)
+            e.intregs[11] |= (rs % 2 ** width) << (width * i)
+
+        with self.subTest(
+            width=width, shift=shift, case_idx=case_idx,
+            RT_in=hex(gprs[10]), RA_in=hex(gprs[20]), RB_in=hex(gprs[30]),
+            expected_RT=hex(e.intregs[10]), expected_RS=hex(e.intregs[11]),
+        ):
+            self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
+
+    def case_maddsubrs_many(self):
+        for width in 8, 16, 32, 64:
+            shift_end = min(32, width)
+            for shift in range(0, shift_end, shift_end // 8):
+                w = "" if width == 64 else f"/w={width}"
+                prog = Program(list(SVP64Asm([
+                    f"sv.maddsubrs{w} *10,*20,{shift},*30",
+                ])), bigendian)
+
+                for case_idx in range(25):
+                    self.maddsubrs_many_helper(width, shift, prog, case_idx)
+
     def case_0_maddrs(self):
         isa = SVP64Asm(["maddsubrs 1,10,0,11",
                         "maddrs 1,10,0,12"])