X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fieee754%2Ffpadd%2Fadd1.py;h=c57534c0f4c575009d201d66b77f2880ca0c3818;hb=f9f55e1c0f3593bc23d91ba8bf7ef0489da2cfd6;hp=679f5176d2d9227c41637d9fb9db2d6c08c6845d;hpb=b1b03478dedc69a06b76e2da3357884369883063;p=ieee754fpu.git diff --git a/src/ieee754/fpadd/add1.py b/src/ieee754/fpadd/add1.py index 679f5176..c57534c0 100644 --- a/src/ieee754/fpadd/add1.py +++ b/src/ieee754/fpadd/add1.py @@ -1,95 +1,67 @@ -# IEEE Floating Point Adder (Single Precision) -# Copyright (C) Jonathan P Dawson 2013 -# 2013-12-12 +"""IEEE754 Floating Point Multiplier Pipeline -from nmigen import Module, Signal, Elaboratable +Copyright (C) 2019 Luke Kenneth Casson Leighton + +""" + +from nmigen import Module, Signal, Mux, Cat from nmigen.cli import main, verilog from math import log -from fpbase import FPState -from fpcommon.postcalc import FPAddStage1Data -from fpadd.add0 import FPAddStage0Data +from nmutil.pipemodbase import PipeModBase +from ieee754.fpcommon.postcalc import FPPostCalcData +from ieee754.fpadd.add0 import FPAddStage0Data -class FPAddStage1Mod(FPState, Elaboratable): +class FPAddStage1Mod(PipeModBase): """ Second stage of add: preparation for normalisation. detects when tot sum is too big (tot[27] is kinda a carry bit) + + if sum is too big (MSB is set), the mantissa needs shifting + down and the exponent increased by 1. + + we also need to extract the overflow info: sticky "accumulates" + the bottom 2 LSBs if the shift occurs. """ - def __init__(self, width, id_wid): - self.width = width - self.id_wid = id_wid - self.i = self.ispec() - self.o = self.ospec() + def __init__(self, pspec): + super().__init__(pspec, "add1") def ispec(self): - return FPAddStage0Data(self.width, self.id_wid) + return FPAddStage0Data(self.pspec) def ospec(self): - return FPAddStage1Data(self.width, self.id_wid) - - def process(self, i): - return self.o - - def setup(self, m, i): - """ links module to inputs and outputs - """ - m.submodules.add1 = self - m.submodules.add1_out_overflow = self.o.of - - m.d.comb += self.i.eq(i) + return FPPostCalcData(self.pspec) def elaborate(self, platform): m = Module() - m.d.comb += self.o.z.eq(self.i.z) - # tot[-1] (MSB) gets set when the sum overflows. shift result down - with m.If(~self.i.out_do_z): - with m.If(self.i.tot[-1]): - m.d.comb += [ - self.o.z.m.eq(self.i.tot[4:]), - self.o.of.m0.eq(self.i.tot[4]), - self.o.of.guard.eq(self.i.tot[3]), - self.o.of.round_bit.eq(self.i.tot[2]), - self.o.of.sticky.eq(self.i.tot[1] | self.i.tot[0]), - self.o.z.e.eq(self.i.z.e + 1) - ] - # tot[-1] (MSB) zero case - with m.Else(): - m.d.comb += [ - self.o.z.m.eq(self.i.tot[3:]), - self.o.of.m0.eq(self.i.tot[3]), - self.o.of.guard.eq(self.i.tot[2]), - self.o.of.round_bit.eq(self.i.tot[1]), - self.o.of.sticky.eq(self.i.tot[0]) - ] - - 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.mid.eq(self.i.mid) + comb = m.d.comb + z = self.i.z + tot = self.i.tot + + # intermediaries + msb = Signal(reset_less=True) + to = Signal.like(self.i.tot, reset_less=True) + + comb += self.o.z.s.eq(z.s) # copy sign + comb += msb.eq(self.i.tot[-1]) # get mantissa MSB + + # mantissa shifted down, exponent increased - if MSB set + comb += self.o.z.e.eq(Mux(msb, z.e + 1, z.e)) + comb += to.eq(Mux(msb, Cat(tot, 0), Cat(0, tot))) + + # this works by adding an extra zero LSB if the MSB is *not* set + comb += [ + self.o.z.m.eq(to[4:]), + self.o.of.m0.eq(to[4]), + self.o.of.guard.eq(to[3]), + self.o.of.round_bit.eq(to[2]), + # sticky sourced from LSB and shifted if MSB hi, else unshifted + self.o.of.sticky.eq(Mux(msb, to[1] | tot[0], to[1])) + ] + + 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 - - -class FPAddStage1(FPState): - - def __init__(self, width, id_wid): - FPState.__init__(self, "add_1") - self.mod = FPAddStage1Mod(width) - self.out_z = FPNumBase(width, False) - self.out_of = Overflow() - self.norm_stb = Signal() - - def setup(self, m, i): - """ links module to inputs and outputs - """ - self.mod.setup(m, i) - - m.d.sync += self.norm_stb.eq(0) # sets to zero when not in add1 state - - m.d.sync += self.out_of.eq(self.mod.out_of) - m.d.sync += self.out_z.eq(self.mod.out_z) - m.d.sync += self.norm_stb.eq(1) - - def action(self, m): - m.next = "normalise_1" -