From: Luke Kenneth Casson Leighton Date: Sun, 28 Jul 2019 20:23:51 +0000 (+0100) Subject: move fpcvt downsize to separate module X-Git-Tag: ls180-24jan2020~685 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=34302a7bc349283eb9d5d5a7505babec065f70ae;p=ieee754fpu.git move fpcvt downsize to separate module --- diff --git a/src/ieee754/fcvt/downsize.py b/src/ieee754/fcvt/downsize.py new file mode 100644 index 00000000..64fd0962 --- /dev/null +++ b/src/ieee754/fcvt/downsize.py @@ -0,0 +1,150 @@ +# IEEE754 Floating Point Conversion +# Copyright (C) 2019 Luke Kenneth Casson Leighton + + +import sys +import functools + +from nmigen import Module, Signal, Cat, Const, Mux, Elaboratable +from nmigen.cli import main, verilog + +from nmutil.singlepipe import ControlBase +from nmutil.concurrentunit import ReservationStations, num_bits + +from ieee754.fpcommon.fpbase import Overflow +from ieee754.fpcommon.getop import FPADDBaseData +from ieee754.fpcommon.pack import FPPackData +from ieee754.fpcommon.normtopack import FPNormToPack +from ieee754.fpcommon.postcalc import FPAddStage1Data +from ieee754.fpcommon.msbhigh import FPMSBHigh +from ieee754.fpcommon.exphigh import FPEXPHigh + + +from nmigen import Module, Signal, Elaboratable +from math import log + +from ieee754.fpcommon.fpbase import FPNumIn, FPNumOut, FPNumBaseRecord +from ieee754.fpcommon.fpbase import FPState, FPNumBase +from ieee754.fpcommon.getop import FPPipeContext + +from ieee754.fpcommon.fpbase import FPNumDecode, FPNumBaseRecord +from nmutil.singlepipe import SimpleHandshake, StageChain + +from ieee754.fpcommon.fpbase import FPState +from ieee754.pipeline import PipelineSpec + + +class FPCVTDownConvertMod(Elaboratable): + """ FP down-conversion (higher to lower bitwidth) + """ + def __init__(self, in_pspec, out_pspec): + self.in_pspec = in_pspec + self.out_pspec = out_pspec + self.i = self.ispec() + self.o = self.ospec() + + def ispec(self): + return FPADDBaseData(self.in_pspec) + + def ospec(self): + return FPAddStage1Data(self.out_pspec, e_extra=True) + + def setup(self, m, i): + """ links module to inputs and outputs + """ + m.submodules.downconvert = 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 + + #m.submodules.sc_out_z = self.o.z + + # decode: XXX really should move to separate stage + print("in_width out", self.in_pspec.width, + self.out_pspec.width) + a1 = FPNumBaseRecord(self.in_pspec.width, False) + print("a1", a1.width, a1.rmw, a1.e_width, a1.e_start, a1.e_end) + m.submodules.sc_decode_a = a1 = FPNumDecode(None, a1) + comb += a1.v.eq(self.i.a) + z1 = self.o.z + print("z1", z1.width, z1.rmw, z1.e_width, z1.e_start, z1.e_end) + + me = a1.rmw + ms = a1.rmw - self.o.z.rmw + print("ms-me", ms, me) + + # intermediaries + exp_sub_n126 = Signal((a1.e_width, True), reset_less=True) + exp_gt127 = Signal(reset_less=True) + # constants from z1, at the bit-width of a1. + N126 = Const(z1.fp.N126.value, (a1.e_width, True)) + P127 = Const(z1.fp.P127.value, (a1.e_width, True)) + comb += exp_sub_n126.eq(a1.e - N126) + comb += exp_gt127.eq(a1.e > P127) + + # if a zero, return zero (signed) + with m.If(a1.exp_n127): + comb += self.o.z.zero(a1.s) + comb += self.o.out_do_z.eq(1) + + # if a range outside z's min range (-126) + with m.Elif(exp_sub_n126 < 0): + comb += self.o.of.guard.eq(a1.m[ms-1]) + comb += self.o.of.round_bit.eq(a1.m[ms-2]) + comb += self.o.of.sticky.eq(a1.m[:ms-2].bool()) + comb += self.o.of.m0.eq(a1.m[ms]) # bit of a1 + + comb += self.o.z.s.eq(a1.s) + comb += self.o.z.e.eq(a1.e) + comb += self.o.z.m.eq(a1.m[-self.o.z.rmw-1:]) + comb += self.o.z.m[-1].eq(1) + + # if a is inf return inf + with m.Elif(a1.is_inf): + comb += self.o.z.inf(a1.s) + comb += self.o.out_do_z.eq(1) + + # if a is NaN return NaN + with m.Elif(a1.is_nan): + comb += self.o.z.nan(0) + comb += self.o.out_do_z.eq(1) + + # if a mantissa greater than 127, return inf + with m.Elif(exp_gt127): + print("inf", self.o.z.inf(a1.s)) + comb += self.o.z.inf(a1.s) + comb += self.o.out_do_z.eq(1) + + # ok after all that, anything else should fit fine (whew) + with m.Else(): + comb += self.o.of.guard.eq(a1.m[ms-1]) + comb += self.o.of.round_bit.eq(a1.m[ms-2]) + comb += self.o.of.sticky.eq(a1.m[:ms-2].bool()) + comb += self.o.of.m0.eq(a1.m[ms]) # bit of a1 + + # XXX TODO: this is basically duplicating FPRoundMod. hmmm... + print("alen", a1.e_start, z1.fp.N126, N126) + print("m1", self.o.z.rmw, a1.m[-self.o.z.rmw-1:]) + mo = Signal(self.o.z.m_width-1) + comb += mo.eq(a1.m[ms:me]) + with m.If(self.o.of.roundz): + with m.If((~mo == 0)): # all 1s + comb += self.o.z.create(a1.s, a1.e+1, mo+1) + with m.Else(): + comb += self.o.z.create(a1.s, a1.e, mo+1) + with m.Else(): + comb += self.o.z.create(a1.s, a1.e, a1.m[-self.o.z.rmw-1:]) + comb += self.o.out_do_z.eq(1) + + # copy the context (muxid, operator) + comb += self.o.oz.eq(self.o.z.v) + comb += self.o.ctx.eq(self.i.ctx) + + return m + + diff --git a/src/ieee754/fcvt/pipeline.py b/src/ieee754/fcvt/pipeline.py index cc5fdbc2..13e3e61a 100644 --- a/src/ieee754/fcvt/pipeline.py +++ b/src/ieee754/fcvt/pipeline.py @@ -36,6 +36,7 @@ from ieee754.pipeline import PipelineSpec from ieee754.fcvt.float2int import FPCVTFloatToIntMod from ieee754.fcvt.int2float import FPCVTIntToFloatMod from ieee754.fcvt.upsize import FPCVTUpConvertMod +from ieee754.fcvt.downsize import FPCVTDownConvertMod class SignedOp: @@ -46,120 +47,6 @@ class SignedOp: return [self.signed.eq(i)] -class FPCVTDownConvertMod(Elaboratable): - """ FP down-conversion (higher to lower bitwidth) - """ - def __init__(self, in_pspec, out_pspec): - self.in_pspec = in_pspec - self.out_pspec = out_pspec - self.i = self.ispec() - self.o = self.ospec() - - def ispec(self): - return FPADDBaseData(self.in_pspec) - - def ospec(self): - return FPAddStage1Data(self.out_pspec, e_extra=True) - - def setup(self, m, i): - """ links module to inputs and outputs - """ - m.submodules.downconvert = self - comb += self.i.eq(i) - - def process(self, i): - return self.o - - def elaborate(self, platform): - m = Module() - comb = m.d.comb - - #m.submodules.sc_out_z = self.o.z - - # decode: XXX really should move to separate stage - print("in_width out", self.in_pspec.width, - self.out_pspec.width) - a1 = FPNumBaseRecord(self.in_pspec.width, False) - print("a1", a1.width, a1.rmw, a1.e_width, a1.e_start, a1.e_end) - m.submodules.sc_decode_a = a1 = FPNumDecode(None, a1) - comb += a1.v.eq(self.i.a) - z1 = self.o.z - print("z1", z1.width, z1.rmw, z1.e_width, z1.e_start, z1.e_end) - - me = a1.rmw - ms = a1.rmw - self.o.z.rmw - print("ms-me", ms, me) - - # intermediaries - exp_sub_n126 = Signal((a1.e_width, True), reset_less=True) - exp_gt127 = Signal(reset_less=True) - # constants from z1, at the bit-width of a1. - N126 = Const(z1.fp.N126.value, (a1.e_width, True)) - P127 = Const(z1.fp.P127.value, (a1.e_width, True)) - comb += exp_sub_n126.eq(a1.e - N126) - comb += exp_gt127.eq(a1.e > P127) - - # if a zero, return zero (signed) - with m.If(a1.exp_n127): - comb += self.o.z.zero(a1.s) - comb += self.o.out_do_z.eq(1) - - # if a range outside z's min range (-126) - with m.Elif(exp_sub_n126 < 0): - comb += self.o.of.guard.eq(a1.m[ms-1]) - comb += self.o.of.round_bit.eq(a1.m[ms-2]) - comb += self.o.of.sticky.eq(a1.m[:ms-2].bool()) - comb += self.o.of.m0.eq(a1.m[ms]) # bit of a1 - - comb += self.o.z.s.eq(a1.s) - comb += self.o.z.e.eq(a1.e) - comb += self.o.z.m.eq(a1.m[-self.o.z.rmw-1:]) - comb += self.o.z.m[-1].eq(1) - - # if a is inf return inf - with m.Elif(a1.is_inf): - comb += self.o.z.inf(a1.s) - comb += self.o.out_do_z.eq(1) - - # if a is NaN return NaN - with m.Elif(a1.is_nan): - comb += self.o.z.nan(0) - comb += self.o.out_do_z.eq(1) - - # if a mantissa greater than 127, return inf - with m.Elif(exp_gt127): - print("inf", self.o.z.inf(a1.s)) - comb += self.o.z.inf(a1.s) - comb += self.o.out_do_z.eq(1) - - # ok after all that, anything else should fit fine (whew) - with m.Else(): - comb += self.o.of.guard.eq(a1.m[ms-1]) - comb += self.o.of.round_bit.eq(a1.m[ms-2]) - comb += self.o.of.sticky.eq(a1.m[:ms-2].bool()) - comb += self.o.of.m0.eq(a1.m[ms]) # bit of a1 - - # XXX TODO: this is basically duplicating FPRoundMod. hmmm... - print("alen", a1.e_start, z1.fp.N126, N126) - print("m1", self.o.z.rmw, a1.m[-self.o.z.rmw-1:]) - mo = Signal(self.o.z.m_width-1) - comb += mo.eq(a1.m[ms:me]) - with m.If(self.o.of.roundz): - with m.If((~mo == 0)): # all 1s - comb += self.o.z.create(a1.s, a1.e+1, mo+1) - with m.Else(): - comb += self.o.z.create(a1.s, a1.e, mo+1) - with m.Else(): - comb += self.o.z.create(a1.s, a1.e, a1.m[-self.o.z.rmw-1:]) - comb += self.o.out_do_z.eq(1) - - # copy the context (muxid, operator) - comb += self.o.oz.eq(self.o.z.v) - comb += self.o.ctx.eq(self.i.ctx) - - return m - - class FPCVTConvertDeNorm(FPState, SimpleHandshake): """ FPConversion and De-norm """