From a434759860b4e6a92c4c46d4842e767ae5b680e3 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 4 Jul 2022 16:14:36 -0700 Subject: [PATCH] add f8 fma tests -- f16 takes >8hr to run with bitwuzla --- src/ieee754/fpcommon/fpbase.py | 33 +++- src/ieee754/fpcommon/pack.py | 6 +- src/ieee754/fpcommon/postnormalise.py | 5 +- src/ieee754/fpcommon/roundz.py | 5 +- src/ieee754/fpfma/main_stage.py | 8 +- src/ieee754/fpfma/norm.py | 5 +- src/ieee754/fpfma/special_cases.py | 10 +- src/ieee754/fpfma/test/test_fma_formal.py | 200 +++++++++++++++++++++- src/ieee754/fpfma/util.py | 12 -- 9 files changed, 249 insertions(+), 35 deletions(-) diff --git a/src/ieee754/fpcommon/fpbase.py b/src/ieee754/fpcommon/fpbase.py index 84768edc..950b17c1 100644 --- a/src/ieee754/fpcommon/fpbase.py +++ b/src/ieee754/fpcommon/fpbase.py @@ -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 diff --git a/src/ieee754/fpcommon/pack.py b/src/ieee754/fpcommon/pack.py index 56c4457d..45e803a4 100644 --- a/src/ieee754/fpcommon/pack.py +++ b/src/ieee754/fpcommon/pack.py @@ -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)) diff --git a/src/ieee754/fpcommon/postnormalise.py b/src/ieee754/fpcommon/postnormalise.py index 3c582b4f..4bd96639 100644 --- a/src/ieee754/fpcommon/postnormalise.py +++ b/src/ieee754/fpcommon/postnormalise.py @@ -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) diff --git a/src/ieee754/fpcommon/roundz.py b/src/ieee754/fpcommon/roundz.py index 22b1d7f3..fd4c7208 100644 --- a/src/ieee754/fpcommon/roundz.py +++ b/src/ieee754/fpcommon/roundz.py @@ -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] diff --git a/src/ieee754/fpfma/main_stage.py b/src/ieee754/fpfma/main_stage.py index 7a028107..5823ffe8 100644 --- a/src/ieee754/fpfma/main_stage.py +++ b/src/ieee754/fpfma/main_stage.py @@ -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 diff --git a/src/ieee754/fpfma/norm.py b/src/ieee754/fpfma/norm.py index 21022c81..735eb07f 100644 --- a/src/ieee754/fpfma/norm.py +++ b/src/ieee754/fpfma/norm.py @@ -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 diff --git a/src/ieee754/fpfma/special_cases.py b/src/ieee754/fpfma/special_cases.py index 826c32a8..96d011e3 100644 --- a/src/ieee754/fpfma/special_cases.py +++ b/src/ieee754/fpfma/special_cases.py @@ -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(): diff --git a/src/ieee754/fpfma/test/test_fma_formal.py b/src/ieee754/fpfma/test/test_fma_formal.py index 7cea7b8e..bb437d2d 100644 --- a/src/ieee754/fpfma/test/test_fma_formal.py +++ b/src/ieee754/fpfma/test/test_fma_formal.py @@ -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" diff --git a/src/ieee754/fpfma/util.py b/src/ieee754/fpfma/util.py index 518a5d9e..5f2ec629 100644 --- a/src/ieee754/fpfma/util.py +++ b/src/ieee754/fpfma/util.py @@ -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 -- 2.30.2