From cd612ca337bbedb950be3dc3066cc189a32225ce Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 29 Mar 2019 11:47:10 +0000 Subject: [PATCH] split out rounding to separate module --- src/add/fpcommon/roundz.py | 90 ++++++++++++++++++++++++++++++++ src/add/nmigen_add_experiment.py | 73 +------------------------- 2 files changed, 91 insertions(+), 72 deletions(-) create mode 100644 src/add/fpcommon/roundz.py diff --git a/src/add/fpcommon/roundz.py b/src/add/fpcommon/roundz.py new file mode 100644 index 00000000..85272011 --- /dev/null +++ b/src/add/fpcommon/roundz.py @@ -0,0 +1,90 @@ +# 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, FPID +from fpcommon.postnormalise import FPNorm1Data + + +class FPRoundData: + + def __init__(self, width, id_wid): + self.z = FPNumBase(width, False) + self.out_do_z = Signal(reset_less=True) + self.oz = Signal(width, reset_less=True) + self.mid = Signal(id_wid, reset_less=True) + + def eq(self, i): + return [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), + self.mid.eq(i.mid)] + + +class FPRoundMod: + + def __init__(self, width, id_wid): + self.width = width + self.id_wid = id_wid + self.i = self.ispec() + self.out_z = self.ospec() + + def ispec(self): + return FPNorm1Data(self.width, self.id_wid) + + def ospec(self): + return FPRoundData(self.width, self.id_wid) + + def process(self, i): + return self.out_z + + def setup(self, m, i): + m.submodules.roundz = self + m.d.comb += self.i.eq(i) + + def elaborate(self, platform): + m = Module() + m.d.comb += self.out_z.eq(self.i) # copies mid, z, out_do_z + with m.If(~self.i.out_do_z): + with m.If(self.i.roundz): + m.d.comb += self.out_z.z.m.eq(self.i.z.m + 1) # mantissa up + with m.If(self.i.z.m == self.i.z.m1s): # all 1s + m.d.comb += self.out_z.z.e.eq(self.i.z.e + 1) # exponent up + + return m + + +class FPRound(FPState): + + def __init__(self, width, id_wid): + FPState.__init__(self, "round") + self.mod = FPRoundMod(width) + self.out_z = self.ospec() + + def ispec(self): + return self.mod.ispec() + + def ospec(self): + return self.mod.ospec() + + def setup(self, m, i): + """ links module to inputs and outputs + """ + self.mod.setup(m, i) + + self.idsync(m) + m.d.sync += self.out_z.eq(self.mod.out_z) + m.d.sync += self.out_z.mid.eq(self.mod.o.mid) + + def action(self, m): + m.next = "corrections" diff --git a/src/add/nmigen_add_experiment.py b/src/add/nmigen_add_experiment.py index e85235fc..bb3c9702 100644 --- a/src/add/nmigen_add_experiment.py +++ b/src/add/nmigen_add_experiment.py @@ -20,6 +20,7 @@ from fpcommon.denorm import (FPSCData, FPAddDeNormMod, FPAddDeNorm) from fpcommon.postcalc import FPAddStage1Data from fpcommon.postnormalise import (FPNorm1Data, FPNorm1ModSingle, FPNorm1ModMulti, FPNorm1Single, FPNorm1Multi) +from fpcommon.roundz import (FPRoundData, FPRoundMod, FPRound) class FPAddSpecialCasesMod: @@ -671,78 +672,6 @@ class FPNormToPack(FPState, UnbufferedPipeline): m.next = "pack_put_z" -class FPRoundData: - - def __init__(self, width, id_wid): - self.z = FPNumBase(width, False) - self.out_do_z = Signal(reset_less=True) - self.oz = Signal(width, reset_less=True) - self.mid = Signal(id_wid, reset_less=True) - - def eq(self, i): - return [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), - self.mid.eq(i.mid)] - - -class FPRoundMod: - - def __init__(self, width, id_wid): - self.width = width - self.id_wid = id_wid - self.i = self.ispec() - self.out_z = self.ospec() - - def ispec(self): - return FPNorm1Data(self.width, self.id_wid) - - def ospec(self): - return FPRoundData(self.width, self.id_wid) - - def process(self, i): - return self.out_z - - def setup(self, m, i): - m.submodules.roundz = self - m.d.comb += self.i.eq(i) - - def elaborate(self, platform): - m = Module() - m.d.comb += self.out_z.eq(self.i) # copies mid, z, out_do_z - with m.If(~self.i.out_do_z): - with m.If(self.i.roundz): - m.d.comb += self.out_z.z.m.eq(self.i.z.m + 1) # mantissa up - with m.If(self.i.z.m == self.i.z.m1s): # all 1s - m.d.comb += self.out_z.z.e.eq(self.i.z.e + 1) # exponent up - - return m - - -class FPRound(FPState): - - def __init__(self, width, id_wid): - FPState.__init__(self, "round") - self.mod = FPRoundMod(width) - self.out_z = self.ospec() - - def ispec(self): - return self.mod.ispec() - - def ospec(self): - return self.mod.ospec() - - def setup(self, m, i): - """ links module to inputs and outputs - """ - self.mod.setup(m, i) - - self.idsync(m) - m.d.sync += self.out_z.eq(self.mod.out_z) - m.d.sync += self.out_z.mid.eq(self.mod.o.mid) - - def action(self, m): - m.next = "corrections" - - class FPCorrectionsMod: def __init__(self, width, id_wid): -- 2.30.2