X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fieee754%2Ffpdiv%2Fspecialcases.py;h=e0c9b07843aafb2dc1bbd778341d3dce91ae4c11;hb=f207376407e0b7049b76128ecff9d89a772bd0f8;hp=47e87abb6821292b1ad5923b3f5336476006df76;hpb=3e65b565b5ff8fd0fd8f1fe3090202ed4bf39de5;p=ieee754fpu.git diff --git a/src/ieee754/fpdiv/specialcases.py b/src/ieee754/fpdiv/specialcases.py index 47e87abb..e0c9b078 100644 --- a/src/ieee754/fpdiv/specialcases.py +++ b/src/ieee754/fpdiv/specialcases.py @@ -1,4 +1,13 @@ -# IEEE Floating Point Multiplier +""" IEEE Floating Point Divider + +Copyright (C) 2019 Luke Kenneth Casson Leighton +Copyright (C) 2019 Jacob Lifshay + +Relevant bugreports: +* http://bugs.libre-riscv.org/show_bug.cgi?id=99 +* http://bugs.libre-riscv.org/show_bug.cgi?id=43 +* http://bugs.libre-riscv.org/show_bug.cgi?id=44 +""" from nmigen import Module, Signal, Cat, Const, Elaboratable from nmigen.cli import main, verilog @@ -45,15 +54,15 @@ class FPDIVSpecialCasesMod(Elaboratable): #m.submodules.sc_out_z = self.o.z # decode: XXX really should move to separate stage - a1 = FPNumBaseRecord(self.pspec.width, False) - b1 = FPNumBaseRecord(self.pspec.width, False) + a1 = FPNumBaseRecord(self.pspec.width, False, name="a1") + b1 = FPNumBaseRecord(self.pspec.width, False, name="b1") m.submodules.sc_decode_a = a1 = FPNumDecode(None, a1) m.submodules.sc_decode_b = b1 = FPNumDecode(None, b1) m.d.comb += [a1.v.eq(self.i.a), b1.v.eq(self.i.b), self.o.a.eq(a1), self.o.b.eq(b1) - ] + ] sabx = Signal(reset_less=True) # sign a xor b (sabx, get it?) m.d.comb += sabx.eq(a1.s ^ b1.s) @@ -64,7 +73,8 @@ class FPDIVSpecialCasesMod(Elaboratable): abinf = Signal(reset_less=True) m.d.comb += abinf.eq(a1.is_inf & b1.is_inf) - with m.If(self.i.ctx.op == 0): # DIV + with m.If(self.i.ctx.op == 0): # DIV + # if a is NaN or b is NaN return NaN with m.If(abnan): m.d.comb += self.o.out_do_z.eq(1) @@ -102,10 +112,15 @@ class FPDIVSpecialCasesMod(Elaboratable): with m.Else(): m.d.comb += self.o.out_do_z.eq(0) - with m.If(self.i.ctx.op == 1): # SQRT + with m.If(self.i.ctx.op == 1): # SQRT + + # if a is zero return zero + with m.If(a1.is_zero): + m.d.comb += self.o.out_do_z.eq(1) + m.d.comb += self.o.z.zero(a1.s) # -ve number is NaN - with m.If(a1.s): + with m.Elif(a1.s): m.d.comb += self.o.out_do_z.eq(1) m.d.comb += self.o.z.nan(0) @@ -114,8 +129,35 @@ class FPDIVSpecialCasesMod(Elaboratable): m.d.comb += self.o.out_do_z.eq(1) m.d.comb += self.o.z.inf(sabx) - # if a is zero return zero + # if a is NaN return NaN + with m.Elif(a1.is_nan): + m.d.comb += self.o.out_do_z.eq(1) + m.d.comb += self.o.z.nan(0) + + # Denormalised Number checks next, so pass a/b data through + with m.Else(): + m.d.comb += self.o.out_do_z.eq(0) + + with m.If(self.i.ctx.op == 2): # RSQRT + + # if a is NaN return canonical NaN + with m.If(a1.is_nan): + m.d.comb += self.o.out_do_z.eq(1) + m.d.comb += self.o.z.nan(0) + + # if a is +/- zero return +/- INF with m.Elif(a1.is_zero): + m.d.comb += self.o.out_do_z.eq(1) + # this includes the "weird" case 1/sqrt(-0) == -Inf + m.d.comb += self.o.z.inf(a1.s) + + # -ve number is canonical NaN + with m.Elif(a1.s): + m.d.comb += self.o.out_do_z.eq(1) + m.d.comb += self.o.z.nan(0) + + # if a is inf return zero (-ve already excluded, above) + with m.Elif(a1.is_inf): m.d.comb += self.o.out_do_z.eq(1) m.d.comb += self.o.z.zero(0) @@ -123,7 +165,6 @@ class FPDIVSpecialCasesMod(Elaboratable): with m.Else(): m.d.comb += self.o.out_do_z.eq(0) - m.d.comb += self.o.oz.eq(self.o.z.v) m.d.comb += self.o.ctx.eq(self.i.ctx) @@ -146,7 +187,7 @@ class FPDIVSpecialCases(FPState): """ links module to inputs and outputs """ self.mod.setup(m, i, self.out_do_z) - m.d.sync += self.out_z.v.eq(self.mod.out_z.v) # only take the output + m.d.sync += self.out_z.v.eq(self.mod.out_z.v) # only take the output m.d.sync += self.out_z.mid.eq(self.mod.o.mid) # (and mid) def action(self, m): @@ -164,14 +205,14 @@ class FPDIVSpecialCasesDeNorm(FPState, SimpleHandshake): def __init__(self, pspec): FPState.__init__(self, "special_cases") self.pspec = pspec - SimpleHandshake.__init__(self, self) # pipe is its own stage + SimpleHandshake.__init__(self, self) # pipe is its own stage self.out = self.ospec() def ispec(self): - return FPADDBaseData(self.pspec) # SpecialCases ispec + return FPADDBaseData(self.pspec) # SpecialCases ispec def ospec(self): - return FPSCData(self.pspec, False) # Align ospec + return FPSCData(self.pspec, False) # Align ospec def setup(self, m, i): """ links module to inputs and outputs @@ -198,5 +239,3 @@ class FPDIVSpecialCasesDeNorm(FPState, SimpleHandshake): #with m.Else(): m.d.sync += self.out.eq(self.process(None)) m.next = "align" - -