From: Luke Kenneth Casson Leighton Date: Fri, 28 Jun 2019 05:57:55 +0000 (+0100) Subject: add div1 and div2 cookie-cut with TODO messages X-Git-Tag: ls180-24jan2020~972 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a20b5907adca7d74ad2238052444c23e007e7455;p=ieee754fpu.git add div1 and div2 cookie-cut with TODO messages --- diff --git a/src/ieee754/fpdiv/div1.py b/src/ieee754/fpdiv/div1.py new file mode 100644 index 00000000..52edde60 --- /dev/null +++ b/src/ieee754/fpdiv/div1.py @@ -0,0 +1,65 @@ +"""IEEE754 Floating Point Divider + +Relevant bugreport: http://bugs.libre-riscv.org/show_bug.cgi?id=99 +""" + +from nmigen import Module, Signal, Cat, Elaboratable +from nmigen.cli import main, verilog + +from ieee754.fpcommon.fpbase import FPNumBaseRecord +from ieee754.fpcommon.fpbase import FPState +from ieee754.fpcommon.denorm import FPSCData +from .div0 import FPDivStage0Data + + +class FPDivStage1Mod(Elaboratable): + + def __init__(self, width, id_wid): + self.width = width + self.id_wid = id_wid + self.i = self.ispec() + self.o = self.ospec() + + def ispec(self): + return FPDivStage0Data(self.width, self.id_wid) + + def ospec(self): + return FPDivStage0Data(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.div0 = self + m.d.comb += self.i.eq(i) + + def elaborate(self, platform): + m = Module() + + # XXX TODO, actual DIV code here. this class would be + # "step two" and is the main "chain". tons of these needed. + # here is where Q and R are used, TODO: those are in FPDivStage0Data. + + # 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 += [ + am0.eq(Cat(self.i.a.m, 0)), + bm0.eq(Cat(self.i.b.m, 0)) + ] + # same-sign (both negative or both positive) div 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), + # TODO: no, not product, first stage Q and R etc. etc. + # go here. + 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.mid.eq(self.i.mid) + return m + diff --git a/src/ieee754/fpdiv/div2.py b/src/ieee754/fpdiv/div2.py new file mode 100644 index 00000000..7acb01b4 --- /dev/null +++ b/src/ieee754/fpdiv/div2.py @@ -0,0 +1,92 @@ +"""IEEE Floating Point Divider + +Relevant bugreport: http://bugs.libre-riscv.org/show_bug.cgi?id=99 +""" + +from nmigen import Module, Signal, Elaboratable +from nmigen.cli import main, verilog + +from ieee754.fpcommon.fpbase import FPState +from ieee754.fpcommon.postcalc import FPAddStage1Data +from .div0 import FPDivStage0Data + + +class FPDivStage1Mod(FPState, Elaboratable): + """ Second stage of div: preparation for normalisation. + """ + + def __init__(self, width, id_wid): + self.width = width + self.id_wid = id_wid + self.i = self.ispec() + self.o = self.ospec() + + def ispec(self): + return FPDivStage0Data(self.width, self.id_wid) + + 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.div1 = self + #m.submodules.div1_out_overflow = self.o.of + + m.d.comb += self.i.eq(i) + + def elaborate(self, platform): + m = Module() + + # copies sign and exponent and mantissa (mantissa to be overridden + # below) + m.d.comb += self.o.z.eq(self.i.z) + + # TODO: this is "phase 3" of divide (the very end of the pipeline) + # takes the Q and R data (whatever) and performs + # last-stage guard/round/sticky and copies mantissa into z. + # post-processing stages take care of things from that point. + + with m.If(~self.i.out_do_z): + mw = self.o.z.m_width + m.d.comb += [ + self.o.z.m.eq(self.i.product[mw+2:]), + self.o.of.m0.eq(self.i.product[mw+2]), + self.o.of.guard.eq(self.i.product[mw+1]), + self.o.of.round_bit.eq(self.i.product[mw]), + self.o.of.sticky.eq(self.i.product[0:mw].bool()) + ] + + 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) + + return m + + +class FPDivStage1(FPState): + + def __init__(self, width, id_wid): + FPState.__init__(self, "divider_1") + self.mod = FPDivStage1Mod(width) + self.out_z = FPNumBaseRecord(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 div1 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" +