From: Luke Kenneth Casson Leighton Date: Fri, 29 Mar 2019 11:35:44 +0000 (+0000) Subject: split out prenormalisation to separate module X-Git-Tag: ls180-24jan2020~1404 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1416f59026d2935dbef7d3431051eaccc316ef55;p=ieee754fpu.git split out prenormalisation to separate module --- diff --git a/src/add/fpcommon/prenormalise.py b/src/add/fpcommon/prenormalise.py new file mode 100644 index 00000000..b09591f5 --- /dev/null +++ b/src/add/fpcommon/prenormalise.py @@ -0,0 +1,89 @@ +# IEEE Floating Point Adder (Single Precision) +# Copyright (C) Jonathan P Dawson 2013 +# 2013-12-12 + +from nmigen import Module, Signal, Cat, Mux, Array, Const +from nmigen.lib.coding import PriorityEncoder +from nmigen.cli import main, verilog +from math import log + +from fpbase import FPNumIn, FPNumOut, FPOp, Overflow, FPBase, FPNumBase +from fpbase import MultiShiftRMerge, Trigger +from singlepipe import (ControlBase, StageChain, UnbufferedPipeline, + PassThroughStage) +from multipipe import CombMuxOutPipe +from multipipe import PriorityCombMuxInPipe + +from fpbase import FPState +from fpcommon.getop import (FPGetOpMod, FPGetOp, FPNumBase2Ops, FPADDBaseData, FPGet2OpMod, FPGet2Op) +from fpcommon.denorm import (FPSCData, FPAddDeNormMod, FPAddDeNorm) + + +class FPNormaliseModSingle: + + def __init__(self, width): + self.width = width + self.in_z = self.ispec() + self.out_z = self.ospec() + + def ispec(self): + return FPNumBase(self.width, False) + + def ospec(self): + return FPNumBase(self.width, False) + + def setup(self, m, i): + """ links module to inputs and outputs + """ + m.submodules.normalise = self + m.d.comb += self.i.eq(i) + + def elaborate(self, platform): + m = Module() + + mwid = self.out_z.m_width+2 + pe = PriorityEncoder(mwid) + m.submodules.norm_pe = pe + + m.submodules.norm1_out_z = self.out_z + m.submodules.norm1_in_z = self.in_z + + in_z = FPNumBase(self.width, False) + in_of = Overflow() + m.submodules.norm1_insel_z = in_z + m.submodules.norm1_insel_overflow = in_of + + espec = (len(in_z.e), True) + ediff_n126 = Signal(espec, reset_less=True) + msr = MultiShiftRMerge(mwid, espec) + m.submodules.multishift_r = msr + + m.d.comb += in_z.eq(self.in_z) + m.d.comb += in_of.eq(self.in_of) + # initialise out from in (overridden below) + m.d.comb += self.out_z.eq(in_z) + m.d.comb += self.out_of.eq(in_of) + # normalisation decrease condition + decrease = Signal(reset_less=True) + m.d.comb += decrease.eq(in_z.m_msbzero) + # decrease exponent + with m.If(decrease): + # *sigh* not entirely obvious: count leading zeros (clz) + # with a PriorityEncoder: to find from the MSB + # we reverse the order of the bits. + temp_m = Signal(mwid, reset_less=True) + temp_s = Signal(mwid+1, reset_less=True) + clz = Signal((len(in_z.e), True), reset_less=True) + m.d.comb += [ + # cat round and guard bits back into the mantissa + temp_m.eq(Cat(in_of.round_bit, in_of.guard, in_z.m)), + pe.i.eq(temp_m[::-1]), # inverted + clz.eq(pe.o), # count zeros from MSB down + temp_s.eq(temp_m << clz), # shift mantissa UP + self.out_z.e.eq(in_z.e - clz), # DECREASE exponent + self.out_z.m.eq(temp_s[2:]), # exclude bits 0&1 + ] + + return m + + diff --git a/src/add/nmigen_add_experiment.py b/src/add/nmigen_add_experiment.py index 7be57bf2..0141abf3 100644 --- a/src/add/nmigen_add_experiment.py +++ b/src/add/nmigen_add_experiment.py @@ -661,74 +661,6 @@ class FPAddStage1(FPState): m.next = "normalise_1" -class FPNormaliseModSingle: - - def __init__(self, width): - self.width = width - self.in_z = self.ispec() - self.out_z = self.ospec() - - def ispec(self): - return FPNumBase(self.width, False) - - def ospec(self): - return FPNumBase(self.width, False) - - def setup(self, m, i): - """ links module to inputs and outputs - """ - m.submodules.normalise = self - m.d.comb += self.i.eq(i) - - def elaborate(self, platform): - m = Module() - - mwid = self.out_z.m_width+2 - pe = PriorityEncoder(mwid) - m.submodules.norm_pe = pe - - m.submodules.norm1_out_z = self.out_z - m.submodules.norm1_in_z = self.in_z - - in_z = FPNumBase(self.width, False) - in_of = Overflow() - m.submodules.norm1_insel_z = in_z - m.submodules.norm1_insel_overflow = in_of - - espec = (len(in_z.e), True) - ediff_n126 = Signal(espec, reset_less=True) - msr = MultiShiftRMerge(mwid, espec) - m.submodules.multishift_r = msr - - m.d.comb += in_z.eq(self.in_z) - m.d.comb += in_of.eq(self.in_of) - # initialise out from in (overridden below) - m.d.comb += self.out_z.eq(in_z) - m.d.comb += self.out_of.eq(in_of) - # normalisation decrease condition - decrease = Signal(reset_less=True) - m.d.comb += decrease.eq(in_z.m_msbzero) - # decrease exponent - with m.If(decrease): - # *sigh* not entirely obvious: count leading zeros (clz) - # with a PriorityEncoder: to find from the MSB - # we reverse the order of the bits. - temp_m = Signal(mwid, reset_less=True) - temp_s = Signal(mwid+1, reset_less=True) - clz = Signal((len(in_z.e), True), reset_less=True) - m.d.comb += [ - # cat round and guard bits back into the mantissa - temp_m.eq(Cat(in_of.round_bit, in_of.guard, in_z.m)), - pe.i.eq(temp_m[::-1]), # inverted - clz.eq(pe.o), # count zeros from MSB down - temp_s.eq(temp_m << clz), # shift mantissa UP - self.out_z.e.eq(in_z.e - clz), # DECREASE exponent - self.out_z.m.eq(temp_s[2:]), # exclude bits 0&1 - ] - - return m - - class FPNorm1Data: def __init__(self, width, id_wid):