From e36c05f058f869dd1400b88419ed9e846b5b01d6 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 31 Jul 2019 12:54:41 +0100 Subject: [PATCH] cleanup fpmul --- src/ieee754/fpmul/align.py | 54 +++++++++++++--------------------- src/ieee754/fpmul/mul0.py | 28 +++++++----------- src/ieee754/fpmul/mul1.py | 34 ++++++++------------- src/ieee754/fpmul/mulstages.py | 1 - 4 files changed, 43 insertions(+), 74 deletions(-) diff --git a/src/ieee754/fpmul/align.py b/src/ieee754/fpmul/align.py index a32024e0..9284926b 100644 --- a/src/ieee754/fpmul/align.py +++ b/src/ieee754/fpmul/align.py @@ -1,26 +1,22 @@ # IEEE Floating Point Multiplier -from nmigen import Module, Signal, Cat, Mux, Elaboratable +from nmigen import Module, Signal, Cat, Mux from nmigen.cli import main, verilog from math import log -from nmutil.singlepipe import StageChain - -from ieee754.fpcommon.fpbase import (Overflow, OverflowMod, - FPNumBase, FPNumBaseRecord) +from ieee754.fpcommon.modbase import FPModBase +from ieee754.fpcommon.fpbase import FPNumBase from ieee754.fpcommon.getop import FPPipeContext from ieee754.fpcommon.msbhigh import FPMSBHigh from ieee754.fpcommon.denorm import FPSCData from ieee754.fpcommon.postcalc import FPAddStage1Data -class FPAlignModSingle(Elaboratable): +class FPAlignModSingle(FPModBase): def __init__(self, pspec, e_extra=False): - self.pspec = pspec self.e_extra = e_extra - self.i = self.ispec() - self.o = self.ospec() + super().__init__(pspec, "align") def ispec(self): return FPSCData(self.pspec, False) @@ -28,17 +24,9 @@ class FPAlignModSingle(Elaboratable): def ospec(self): return FPSCData(self.pspec, False) - def setup(self, m, i): - """ links module to inputs and outputs - """ - m.submodules.align = self - m.d.comb += self.i.eq(i) - - def process(self, i): - return self.o - def elaborate(self, platform): m = Module() + comb = m.d.comb self.o.a.m.name = "o_a_m" self.o.b.m.name = "o_b_m" @@ -55,38 +43,36 @@ class FPAlignModSingle(Elaboratable): m.submodules.norm_pe_b = msb_b # connect to msb_a/b module - m.d.comb += msb_a.m_in.eq(insel_a.m) - m.d.comb += msb_a.e_in.eq(insel_a.e) - m.d.comb += msb_b.m_in.eq(insel_b.m) - m.d.comb += msb_b.e_in.eq(insel_b.e) + comb += msb_a.m_in.eq(insel_a.m) + comb += msb_a.e_in.eq(insel_a.e) + comb += msb_b.m_in.eq(insel_b.m) + comb += msb_b.e_in.eq(insel_b.e) # copy input to output (overridden below) - m.d.comb += self.o.a.eq(insel_a) - m.d.comb += self.o.b.eq(insel_b) + comb += self.o.a.eq(insel_a) + comb += self.o.b.eq(insel_b) # normalisation increase/decrease conditions decrease_a = Signal(reset_less=True) decrease_b = Signal(reset_less=True) - m.d.comb += decrease_a.eq(insel_a.m_msbzero) - m.d.comb += decrease_b.eq(insel_b.m_msbzero) + comb += decrease_a.eq(insel_a.m_msbzero) + comb += decrease_b.eq(insel_b.m_msbzero) - # ok this is near-identical to FPNorm. TODO: modularise + # ok this is near-identical to FPNorm: use same class (FPMSBHigh) with m.If(~self.i.out_do_z): with m.If(decrease_a): - m.d.comb += [ + comb += [ self.o.a.e.eq(msb_a.e_out), self.o.a.m.eq(msb_a.m_out), ] with m.If(decrease_b): - m.d.comb += [ + comb += [ self.o.b.e.eq(msb_b.e_out), self.o.b.m.eq(msb_b.m_out), ] - m.d.comb += self.o.ctx.eq(self.i.ctx) - m.d.comb += self.o.out_do_z.eq(self.i.out_do_z) - m.d.comb += self.o.oz.eq(self.i.oz) + comb += self.o.ctx.eq(self.i.ctx) + comb += self.o.out_do_z.eq(self.i.out_do_z) + comb += self.o.oz.eq(self.i.oz) return m - - diff --git a/src/ieee754/fpmul/mul0.py b/src/ieee754/fpmul/mul0.py index 916d7898..0ed25035 100644 --- a/src/ieee754/fpmul/mul0.py +++ b/src/ieee754/fpmul/mul0.py @@ -7,6 +7,7 @@ Copyright (C) 2019 Luke Kenneth Casson Leighton from nmigen import Module, Signal, Cat, Elaboratable from nmigen.cli import main, verilog +from ieee754.fpcommon.modbase import FPModBase from ieee754.fpcommon.fpbase import FPNumBaseRecord from ieee754.fpcommon.denorm import FPSCData from ieee754.fpcommon.getop import FPPipeContext @@ -29,12 +30,10 @@ class FPMulStage0Data: self.product.eq(i.product), self.ctx.eq(i.ctx)] -class FPMulStage0Mod(Elaboratable): +class FPMulStage0Mod(FPModBase): def __init__(self, pspec): - self.pspec = pspec - self.i = self.ispec() - self.o = self.ospec() + super().__init__(pspec, "mul0") def ispec(self): return FPSCData(self.pspec, False) @@ -42,33 +41,26 @@ class FPMulStage0Mod(Elaboratable): def ospec(self): return FPMulStage0Data(self.pspec) - def process(self, i): - return self.o - - def setup(self, m, i): - """ links module to inputs and outputs - """ - m.submodules.mul0 = self - m.d.comb += self.i.eq(i) - def elaborate(self, platform): m = Module() + comb = m.d.comb # store intermediate tests (and zero-extended mantissas) am0 = Signal(len(self.i.a.m)+1, reset_less=True) bm0 = Signal(len(self.i.b.m)+1, reset_less=True) - m.d.comb += [ + comb += [ am0.eq(Cat(self.i.a.m, 0)), bm0.eq(Cat(self.i.b.m, 0)) ] # same-sign (both negative or both positive) mul mantissas with m.If(~self.i.out_do_z): - m.d.comb += [self.o.z.e.eq(self.i.a.e + self.i.b.e + 1), + comb += [self.o.z.e.eq(self.i.a.e + self.i.b.e + 1), self.o.product.eq(am0 * bm0 * 4), self.o.z.s.eq(self.i.a.s ^ self.i.b.s) ] - m.d.comb += self.o.oz.eq(self.i.oz) - m.d.comb += self.o.out_do_z.eq(self.i.out_do_z) - m.d.comb += self.o.ctx.eq(self.i.ctx) + comb += self.o.oz.eq(self.i.oz) + comb += self.o.out_do_z.eq(self.i.out_do_z) + comb += self.o.ctx.eq(self.i.ctx) + return m diff --git a/src/ieee754/fpmul/mul1.py b/src/ieee754/fpmul/mul1.py index 6aa20561..98374fa5 100644 --- a/src/ieee754/fpmul/mul1.py +++ b/src/ieee754/fpmul/mul1.py @@ -7,18 +7,17 @@ Copyright (C) 2019 Luke Kenneth Casson Leighton from nmigen import Module, Signal, Elaboratable from nmigen.cli import main, verilog +from ieee754.fpcommon.modbase import FPModBase from ieee754.fpcommon.postcalc import FPAddStage1Data from ieee754.fpmul.mul0 import FPMulStage0Data -class FPMulStage1Mod(Elaboratable): +class FPMulStage1Mod(FPModBase): """ Second stage of mul: preparation for normalisation. """ def __init__(self, pspec): - self.pspec = pspec - self.i = self.ispec() - self.o = self.ospec() + super().__init__(pspec, "mul1") def ispec(self): return FPMulStage0Data(self.pspec) @@ -26,18 +25,11 @@ class FPMulStage1Mod(Elaboratable): def ospec(self): return FPAddStage1Data(self.pspec) - def process(self, i): - return self.o - - def setup(self, m, i): - """ links module to inputs and outputs - """ - m.submodules.mul1 = self - m.d.comb += self.i.eq(i) - def elaborate(self, platform): m = Module() - m.d.comb += self.o.z.eq(self.i.z) + comb = m.d.comb + + comb += self.o.z.eq(self.i.z) with m.If(~self.i.out_do_z): # results are in the range 0.25 to 0.999999999999 # sometimes the MSB will be zero, (0.5 * 0.5 = 0.25 which @@ -45,16 +37,16 @@ class FPMulStage1Mod(Elaboratable): # to shift the mantissa up (and reduce the exponent by 1) p = Signal(len(self.i.product), reset_less=True) with m.If(self.i.product[-1]): - m.d.comb += p.eq(self.i.product) + comb += p.eq(self.i.product) with m.Else(): # get 1 bit of extra accuracy if the mantissa top bit is zero - m.d.comb += p.eq(self.i.product<<1) - m.d.comb += self.o.z.e.eq(self.i.z.e-1) + comb += p.eq(self.i.product<<1) + comb += self.o.z.e.eq(self.i.z.e-1) # top bits are mantissa, then guard and round, and the rest of # the product is sticky mw = self.o.z.m_width - m.d.comb += [ + comb += [ self.o.z.m.eq(p[mw+2:]), # mantissa self.o.of.m0.eq(p[mw+2]), # copy of LSB self.o.of.guard.eq(p[mw+1]), # guard @@ -62,8 +54,8 @@ class FPMulStage1Mod(Elaboratable): self.o.of.sticky.eq(p[0:mw].bool()) # sticky ] - m.d.comb += self.o.out_do_z.eq(self.i.out_do_z) - m.d.comb += self.o.oz.eq(self.i.oz) - m.d.comb += self.o.ctx.eq(self.i.ctx) + comb += self.o.out_do_z.eq(self.i.out_do_z) + comb += self.o.oz.eq(self.i.oz) + comb += self.o.ctx.eq(self.i.ctx) return m diff --git a/src/ieee754/fpmul/mulstages.py b/src/ieee754/fpmul/mulstages.py index 2e96ed3b..5ce17c1f 100644 --- a/src/ieee754/fpmul/mulstages.py +++ b/src/ieee754/fpmul/mulstages.py @@ -17,7 +17,6 @@ class FPMulStages(DynamicPipe): def __init__(self, pspec): self.pspec = pspec super().__init__(pspec) - self.m1o = self.ospec() def ispec(self): return FPSCData(self.pspec, False) -- 2.30.2