add f8 fma tests -- f16 takes >8hr to run with bitwuzla
authorJacob Lifshay <programmerjake@gmail.com>
Mon, 4 Jul 2022 23:14:36 +0000 (16:14 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Mon, 4 Jul 2022 23:14:36 +0000 (16:14 -0700)
src/ieee754/fpcommon/fpbase.py
src/ieee754/fpcommon/pack.py
src/ieee754/fpcommon/postnormalise.py
src/ieee754/fpcommon/roundz.py
src/ieee754/fpfma/main_stage.py
src/ieee754/fpfma/norm.py
src/ieee754/fpfma/special_cases.py
src/ieee754/fpfma/test/test_fma_formal.py
src/ieee754/fpfma/util.py

index 84768edc158e2a15323f2baef6984ca2f6f874e6..950b17c1101296ce0827ff27482d3d1f4f353748 100644 (file)
@@ -458,6 +458,20 @@ class FPFormat:
         """ Get the number of mantissa bits that are fraction bits. """
         return self.m_width - self.has_int_bit
 
+    @staticmethod
+    def from_pspec(pspec):
+        width = getattr(pspec, "width", None)
+        assert width is None or isinstance(width, int)
+        fpformat = getattr(pspec, "fpformat", None)
+        if fpformat is None:
+            assert width is not None, \
+                "neither pspec.width nor pspec.fpformat were set"
+            fpformat = FPFormat.standard(width)
+        else:
+            assert isinstance(fpformat, FPFormat)
+        assert width == fpformat.width
+        return fpformat
+
 
 class TestFPFormat(unittest.TestCase):
     """ very quick test for FPFormat
@@ -594,15 +608,28 @@ class FPNumBaseRecord:
     the module.
     """
 
-    def __init__(self, width, m_extra=True, e_extra=False, name=None):
+    def __init__(self, width=None, m_extra=True, e_extra=False, name=None,
+                 fpformat=None):
         if name is None:
             name = ""
             # assert false, "missing name"
         else:
             name += "_"
+        if fpformat is None:
+            assert isinstance(width, int)
+            fpformat = FPFormat.standard(width)
+        else:
+            assert isinstance(fpformat, FPFormat)
+            if width is None:
+                width = fpformat.width
+            assert isinstance(width, int)
+            assert width == fpformat.width
         self.width = width
-        m_width = {16: 11, 32: 24, 64: 53}[width]  # 1 extra bit (overflow)
-        e_width = {16: 7,  32: 10, 64: 13}[width]  # 2 extra bits (overflow)
+        self.fpformat = fpformat
+        assert not fpformat.has_int_bit
+        assert fpformat.has_sign
+        m_width = fpformat.m_width + 1  # 1 extra bit (overflow)
+        e_width = fpformat.e_width + 2  # 2 extra bits (overflow)
         e_max = 1 << (e_width-3)
         self.rmw = m_width - 1  # real mantissa width (not including extras)
         self.e_max = e_max
index 56c4457d281e9bd3b6ca41eb0ab6009cfe1033a7..45e803a4c9c3f0d02ab1d111147b662ada81b9af 100644 (file)
@@ -5,7 +5,8 @@
 from nmigen import Module, Signal
 
 from nmutil.pipemodbase import PipeModBase
-from ieee754.fpcommon.fpbase import FPNumBaseRecord, FPNumBase, FPRoundingMode
+from ieee754.fpcommon.fpbase import FPFormat, FPNumBaseRecord, FPNumBase, \
+    FPRoundingMode
 from ieee754.fpcommon.roundz import FPRoundData
 from ieee754.fpcommon.packdata import FPPackData
 
@@ -25,7 +26,8 @@ class FPPackMod(PipeModBase):
         m = Module()
         comb = m.d.comb
 
-        z = FPNumBaseRecord(self.pspec.width, False, name="z")
+        z = FPNumBaseRecord(m_extra=False, name="z",
+                            fpformat=FPFormat.from_pspec(self.pspec))
         m.submodules.pack_in_z = in_z = FPNumBase(self.i.z)
         overflow_array = FPRoundingMode.make_array(
             lambda rm: rm.overflow_rounds_to_inf(self.i.z.s))
index 3c582b4f1ffcb90c1efffe12e0f072ac5bc4ddcf..4bd96639c2787cc66cec0785b6f7e5e6628e0577 100644 (file)
@@ -6,7 +6,7 @@ from nmigen import Module, Signal, Cat
 
 from nmutil.pipemodbase import PipeModBase
 from ieee754.fpcommon.fpbase import (FPRoundingMode, Overflow, OverflowMod,
-                                     FPNumBase, FPNumBaseRecord)
+                                     FPNumBase, FPNumBaseRecord, FPFormat)
 from ieee754.fpcommon.fpbase import FPState
 from ieee754.fpcommon.getop import FPPipeContext
 from ieee754.fpcommon.msbhigh import FPMSBHigh
@@ -19,7 +19,8 @@ class FPNorm1Data:
     def __init__(self, pspec):
         width = pspec.width
         self.roundz = Signal(reset_less=True, name="norm1_roundz")
-        self.z = FPNumBaseRecord(width, False, name="z")
+        self.z = FPNumBaseRecord(m_extra=False, name="z",
+                                 fpformat=FPFormat.from_pspec(pspec))
         self.out_do_z = Signal(reset_less=True)
         self.oz = Signal(width, reset_less=True)
         self.ctx = FPPipeContext(pspec)
index 22b1d7f35e9be56bd69465f7e2a51da3b909cd28..fd4c7208e357217d8866d4e3d527292e276032b4 100644 (file)
@@ -5,7 +5,7 @@
 from nmigen import Module, Signal, Mux
 
 from nmutil.pipemodbase import PipeModBase
-from ieee754.fpcommon.fpbase import FPNumBaseRecord, FPRoundingMode
+from ieee754.fpcommon.fpbase import FPFormat, FPNumBaseRecord, FPRoundingMode
 from ieee754.fpcommon.getop import FPPipeContext
 from ieee754.fpcommon.postnormalise import FPNorm1Data
 
@@ -14,7 +14,8 @@ class FPRoundData:
 
     def __init__(self, pspec):
         width = pspec.width
-        self.z = FPNumBaseRecord(width, False, name="z")
+        self.z = FPNumBaseRecord(m_extra=False, name="z",
+                                 fpformat=FPFormat.from_pspec(pspec))
         self.ctx = FPPipeContext(pspec)
         self.muxid = self.ctx.muxid
         # pipeline bypass [data comes from specialcases]
index 7a028107e40d1c52ae363b42019b2c550f91e91f..5823ffe8f1b86a2634e807c74421005b85af8533 100644 (file)
@@ -4,18 +4,18 @@ computes `z = (a * c) + b` but only rounds once at the end
 """
 
 from nmutil.pipemodbase import PipeModBase, PipeModBaseChain
-from ieee754.fpcommon.fpbase import FPRoundingMode
+from ieee754.fpcommon.fpbase import FPRoundingMode, FPFormat
 from ieee754.fpfma.special_cases import FPFMASpecialCasesDeNormOutData
 from nmigen.hdl.dsl import Module
 from nmigen.hdl.ast import Signal, signed, unsigned, Mux, Cat
 from ieee754.fpfma.util import expanded_exponent_shape, \
-    expanded_mantissa_shape, get_fpformat, EXPANDED_MANTISSA_EXTRA_LSBS
+    expanded_mantissa_shape, EXPANDED_MANTISSA_EXTRA_LSBS
 from ieee754.fpcommon.getop import FPPipeContext
 
 
 class FPFMAPostCalcData:
     def __init__(self, pspec):
-        fpf = get_fpformat(pspec)
+        fpf = FPFormat.from_pspec(pspec)
 
         self.sign = Signal()
         """sign"""
@@ -74,7 +74,7 @@ class FPFMAMain(PipeModBase):
 
     def elaborate(self, platform):
         m = Module()
-        fpf = get_fpformat(self.pspec)
+        fpf = FPFormat.from_pspec(self.pspec)
         assert fpf.has_sign
         inp = self.i
         out = self.o
index 21022c81a5866e4a677e60a1d639c4dec46eed49..735eb07fcdc919a07c60646f6c6b842a91347a40 100644 (file)
@@ -1,5 +1,5 @@
 from nmutil.pipemodbase import PipeModBaseChain, PipeModBase
-from ieee754.fpcommon.fpbase import OverflowMod
+from ieee754.fpcommon.fpbase import OverflowMod, FPFormat
 from ieee754.fpcommon.postnormalise import FPNorm1Data
 from ieee754.fpcommon.roundz import FPRoundMod
 from ieee754.fpcommon.corrections import FPCorrectionsMod
@@ -7,7 +7,6 @@ from ieee754.fpcommon.pack import FPPackMod
 from ieee754.fpfma.main_stage import FPFMAPostCalcData
 from nmigen.hdl.dsl import Module
 from nmigen.hdl.ast import Signal
-from ieee754.fpfma.util import get_fpformat
 from nmigen.lib.coding import PriorityEncoder
 
 
@@ -23,7 +22,7 @@ class FPFMANorm(PipeModBase):
 
     def elaborate(self, platform):
         m = Module()
-        fpf = get_fpformat(self.pspec)
+        fpf = FPFormat.from_pspec(self.pspec)
         assert fpf.has_sign
         inp: FPFMAPostCalcData = self.i
         out: FPNorm1Data = self.o
index 826c32a8e80f2a121a585d7c83bb65e436e97d50..96d011e348aa1f66642306107722f903eb19a48c 100644 (file)
@@ -8,9 +8,9 @@ from ieee754.fpcommon.basedata import FPBaseData
 from nmigen.hdl.ast import Signal
 from nmigen.hdl.dsl import Module
 from ieee754.fpcommon.getop import FPPipeContext
-from ieee754.fpcommon.fpbase import FPRoundingMode, MultiShiftRMerge
+from ieee754.fpcommon.fpbase import FPRoundingMode, MultiShiftRMerge, FPFormat
 from ieee754.fpfma.util import expanded_exponent_shape, \
-    expanded_mantissa_shape, get_fpformat, multiplicand_mantissa_shape, \
+    expanded_mantissa_shape, multiplicand_mantissa_shape, \
     EXPANDED_MANTISSA_EXTRA_MSBS, EXPANDED_MANTISSA_EXTRA_LSBS, \
     product_mantissa_shape
 
@@ -43,7 +43,7 @@ class FPFMAInputData(FPBaseData):
 
 class FPFMASpecialCasesDeNormOutData:
     def __init__(self, pspec):
-        fpf = get_fpformat(pspec)
+        fpf = FPFormat.from_pspec(pspec)
 
         self.sign = Signal()
         """sign"""
@@ -119,7 +119,7 @@ class FPFMASpecialCasesDeNorm(PipeModBase):
 
     def elaborate(self, platform):
         m = Module()
-        fpf = get_fpformat(self.pspec)
+        fpf = FPFormat.from_pspec(self.pspec)
         assert fpf.has_sign
         inp = self.i
         out = self.o
@@ -244,7 +244,7 @@ class FPFMASpecialCasesDeNorm(PipeModBase):
             # zero + x
             m.d.comb += [
                 Signal(name="case_zero_plus_x", attrs=keep).eq(True),
-                out.bypassed_z.eq(inp.b),
+                out.bypassed_z.eq(inp.b ^ fpf.zero(inp.negate_addend)),
                 out.do_bypass.eq(True),
             ]
         with m.Else():
index 7cea7b8e708261c6ee953869cdf19ec53ac43db2..bb437d2d3c8c00843ea2df76964f3d396f84858f 100644 (file)
@@ -10,11 +10,11 @@ from ieee754.fpcommon.fpbase import FPFormat, FPRoundingMode
 from ieee754.pipeline import PipelineSpec
 import os
 
+ENABLE_FMA_F16_FORMAL = os.getenv("ENABLE_FMA_F16_FORMAL") is not None
 ENABLE_FMA_F32_FORMAL = os.getenv("ENABLE_FMA_F32_FORMAL") is not None
 
 
 class TestFMAFormal(FHDLTestCase):
-    @unittest.skip("not finished implementing")  # FIXME: remove skip
     def tst_fma_formal(self, sort, rm, negate_addend, negate_product):
         assert isinstance(sort, SmtSortFloatingPoint)
         assert isinstance(rm, FPRoundingMode)
@@ -121,114 +121,310 @@ class TestFMAFormal(FHDLTestCase):
 
     # FIXME: check exception flags
 
+    def test_fmadd_f8_rne_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RNE,
+                            negate_addend=False, negate_product=False)
+
+    def test_fmsub_f8_rne_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RNE,
+                            negate_addend=True, negate_product=False)
+
+    def test_fnmadd_f8_rne_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RNE,
+                            negate_addend=True, negate_product=True)
+
+    def test_fnmsub_f8_rne_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RNE,
+                            negate_addend=False, negate_product=True)
+
+    def test_fmadd_f8_rtz_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTZ,
+                            negate_addend=False, negate_product=False)
+
+    def test_fmsub_f8_rtz_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTZ,
+                            negate_addend=True, negate_product=False)
+
+    def test_fnmadd_f8_rtz_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTZ,
+                            negate_addend=True, negate_product=True)
+
+    def test_fnmsub_f8_rtz_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTZ,
+                            negate_addend=False, negate_product=True)
+
+    def test_fmadd_f8_rtp_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTP,
+                            negate_addend=False, negate_product=False)
+
+    def test_fmsub_f8_rtp_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTP,
+                            negate_addend=True, negate_product=False)
+
+    def test_fnmadd_f8_rtp_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTP,
+                            negate_addend=True, negate_product=True)
+
+    def test_fnmsub_f8_rtp_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTP,
+                            negate_addend=False, negate_product=True)
+
+    def test_fmadd_f8_rtn_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTN,
+                            negate_addend=False, negate_product=False)
+
+    def test_fmsub_f8_rtn_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTN,
+                            negate_addend=True, negate_product=False)
+
+    def test_fnmadd_f8_rtn_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTN,
+                            negate_addend=True, negate_product=True)
+
+    def test_fnmsub_f8_rtn_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTN,
+                            negate_addend=False, negate_product=True)
+
+    def test_fmadd_f8_rna_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RNA,
+                            negate_addend=False, negate_product=False)
+
+    def test_fmsub_f8_rna_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RNA,
+                            negate_addend=True, negate_product=False)
+
+    def test_fnmadd_f8_rna_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RNA,
+                            negate_addend=True, negate_product=True)
+
+    def test_fnmsub_f8_rna_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RNA,
+                            negate_addend=False, negate_product=True)
+
+    def test_fmadd_f8_rtop_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTOP,
+                            negate_addend=False, negate_product=False)
+
+    def test_fmsub_f8_rtop_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTOP,
+                            negate_addend=True, negate_product=False)
+
+    def test_fnmadd_f8_rtop_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTOP,
+                            negate_addend=True, negate_product=True)
+
+    def test_fnmsub_f8_rtop_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTOP,
+                            negate_addend=False, negate_product=True)
+
+    def test_fmadd_f8_rton_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTON,
+                            negate_addend=False, negate_product=False)
+
+    def test_fmsub_f8_rton_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTON,
+                            negate_addend=True, negate_product=False)
+
+    def test_fnmadd_f8_rton_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTON,
+                            negate_addend=True, negate_product=True)
+
+    def test_fnmsub_f8_rton_formal(self):
+        self.tst_fma_formal(sort=SmtSortFloatingPoint(eb=5, sb=3),
+                            rm=FPRoundingMode.RTON,
+                            negate_addend=False, negate_product=True)
+
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmadd_f16_rne_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RNE,
                             negate_addend=False, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmsub_f16_rne_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RNE,
                             negate_addend=True, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmadd_f16_rne_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RNE,
                             negate_addend=True, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmsub_f16_rne_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RNE,
                             negate_addend=False, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmadd_f16_rtz_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTZ,
                             negate_addend=False, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmsub_f16_rtz_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTZ,
                             negate_addend=True, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmadd_f16_rtz_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTZ,
                             negate_addend=True, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmsub_f16_rtz_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTZ,
                             negate_addend=False, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmadd_f16_rtp_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTP,
                             negate_addend=False, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmsub_f16_rtp_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTP,
                             negate_addend=True, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmadd_f16_rtp_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTP,
                             negate_addend=True, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmsub_f16_rtp_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTP,
                             negate_addend=False, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmadd_f16_rtn_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTN,
                             negate_addend=False, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmsub_f16_rtn_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTN,
                             negate_addend=True, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmadd_f16_rtn_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTN,
                             negate_addend=True, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmsub_f16_rtn_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTN,
                             negate_addend=False, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmadd_f16_rna_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RNA,
                             negate_addend=False, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmsub_f16_rna_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RNA,
                             negate_addend=True, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmadd_f16_rna_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RNA,
                             negate_addend=True, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmsub_f16_rna_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RNA,
                             negate_addend=False, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmadd_f16_rtop_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTOP,
                             negate_addend=False, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmsub_f16_rtop_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTOP,
                             negate_addend=True, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmadd_f16_rtop_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTOP,
                             negate_addend=True, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmsub_f16_rtop_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTOP,
                             negate_addend=False, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmadd_f16_rton_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTON,
                             negate_addend=False, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fmsub_f16_rton_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTON,
                             negate_addend=True, negate_product=False)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmadd_f16_rton_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTON,
                             negate_addend=True, negate_product=True)
 
+    @unittest.skipUnless(ENABLE_FMA_F16_FORMAL,
+                         "ENABLE_FMA_F16_FORMAL not in environ")
     def test_fnmsub_f16_rton_formal(self):
         self.tst_fma_formal(sort=SmtSortFloat16(), rm=FPRoundingMode.RTON,
                             negate_addend=False, negate_product=True)
@@ -542,7 +738,7 @@ class TestFMAFormal(FHDLTestCase):
                             negate_addend=False, negate_product=True)
 
     def test_all_rounding_modes_covered(self):
-        for width in 16, 32, 64:
+        for width in 8, 16, 32, 64:
             for rm in FPRoundingMode:
                 rm_s = rm.name.lower()
                 name = f"test_fmadd_f{width}_{rm_s}_formal"
index 518a5d9e6e4dba4b1c9f75f8558b0d2788fefe8d..5f2ec62906872703894242de95777019cbf46e02 100644 (file)
@@ -59,15 +59,3 @@ def multiplicand_mantissa_shape(fpformat):
 def product_mantissa_shape(fpformat):
     assert isinstance(fpformat, FPFormat)
     return unsigned(multiplicand_mantissa_shape(fpformat).width * 2)
-
-
-def get_fpformat(pspec):
-    width = pspec.width
-    assert isinstance(width, int)
-    fpformat = getattr(pspec, "fpformat", None)
-    if fpformat is None:
-        fpformat = FPFormat.standard(width)
-    else:
-        assert isinstance(fpformat, FPFormat)
-    assert width == fpformat.width
-    return fpformat