random modifications got semi-correct output
[ieee754fpu.git] / src / ieee754 / fpdiv / div2.py
index 1b54db47294a2fe021e62301113a93b3df6e3147..83b1e4f4aee7bf639bb292b83a00fda6812198b5 100644 (file)
@@ -3,29 +3,30 @@
 Relevant bugreport: http://bugs.libre-riscv.org/show_bug.cgi?id=99
 """
 
-from nmigen import Module, Signal, Elaboratable
+from nmigen import Module, Signal, Elaboratable, Cat
 from nmigen.cli import main, verilog
 
 from ieee754.fpcommon.fpbase import FPState
 from ieee754.fpcommon.postcalc import FPAddStage1Data
-from .div0 import FPDivStage0Data
+from ieee754.div_rem_sqrt_rsqrt.div_pipe import DivPipeOutputData
 
 
 class FPDivStage2Mod(FPState, Elaboratable):
     """ Second stage of div: preparation for normalisation.
     """
 
-    def __init__(self, width, id_wid):
-        self.width = width
-        self.id_wid = id_wid
+    def __init__(self, pspec):
+        self.pspec = pspec
         self.i = self.ispec()
         self.o = self.ospec()
 
     def ispec(self):
-        return FPDivStage0Data(self.width, self.id_wid) # Q/Rem in...
+        return DivPipeOutputData(self.pspec) # Q/Rem in...
 
     def ospec(self):
-        return FPAddStage1Data(self.width, self.id_wid) # out to post-process
+        # XXX REQUIRED.  MUST NOT BE CHANGED.  this is the format
+        # required for ongoing processing (normalisation, correction etc.)
+        return FPAddStage1Data(self.pspec) # out to post-process
 
     def process(self, i):
         return self.o
@@ -34,8 +35,6 @@ class FPDivStage2Mod(FPState, Elaboratable):
         """ 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):
@@ -53,29 +52,52 @@ class FPDivStage2Mod(FPState, Elaboratable):
         # NOTE: this phase does NOT do ACTUAL DIV processing, it ONLY
         # does "conversion" *out* of the Q/REM last stage
 
+        # NOTE: see FPDivStage0Mod comment.  the quotient is assumed
+        # to be in the range 0.499999-recurring to 1.999998.  normalisation
+        # will take care of that, *however*, it *might* be necessary to
+        # subtract 1 from the exponent and have one extra bit in the
+        # mantissa to compensate.  this is pretty much exactly what's
+        # done in FPMUL, due to 0.5-0.9999 * 0.5-0.9999 also producing
+        # values within the range 0.5 to 1.999998
+
         with m.If(~self.i.out_do_z):
             mw = self.o.z.m_width
+            # TODO: compensate for answer being in range 0.49999 to 1.99998
+            pl = len(self.i.quotient_root) + len(self.i.remainder)
+            pt = Signal(pl, reset_less=True)
+            m.d.comb += pt.eq(Cat(self.i.remainder, self.i.quotient_root))
+            p = Signal(pl, reset_less=True)
+            with m.If(self.i.quotient_root[-1]):
+                m.d.comb += p.eq(pt)
+            with m.Else():
+                # get 1 bit of extra accuracy if the mantissa top bit is zero
+                m.d.comb += p.eq(pt << 1)
+                m.d.comb += self.o.z.e.eq(self.i.z.e-1)
+
+            # TODO: use p here instead of quotient_root, direct.
+            # XXX what to do about remainder? shift that as well?
+            # hmm, how about concatenate remainder and quotient...
             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())
+                self.o.z.m.eq(p[-mw-2:]),
+                self.o.of.m0.eq(p[-mw-2]), # copy of LSB
+                self.o.of.guard.eq(p[-mw-1]),
+                self.o.of.round_bit.eq(p[-mw]),
+                self.o.of.sticky.eq(p[:-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)
+        m.d.comb += self.o.ctx.eq(self.i.ctx)
 
         return m
 
 
 class FPDivStage2(FPState):
 
-    def __init__(self, width, id_wid):
+    def __init__(self, pspec):
         FPState.__init__(self, "divider_1")
-        self.mod = FPDivStage2Mod(width)
-        self.out_z = FPNumBaseRecord(width, False)
+        self.mod = FPDivStage2Mod(pspec)
+        self.out_z = FPNumBaseRecord(pspec, False)
         self.out_of = Overflow()
         self.norm_stb = Signal()