from nmigen import Module, Signal, Cat, Elaboratable
 from nmigen.cli import main, verilog
 
-from ieee754.fpcommon.fpbase import FPNumBaseRecord
+from ieee754.fpcommon.fpbase import (FPNumBaseRecord, Overflow)
 from ieee754.fpcommon.fpbase import FPState
 from ieee754.fpcommon.denorm import FPSCData
 
         self.z = FPNumBaseRecord(width, False)
         self.out_do_z = Signal(reset_less=True)
         self.oz = Signal(width, reset_less=True)
+        self.of = Overflow()
 
         # TODO: here is where Q and R would be put, and passed
         # down to Stage1 processing.
 
     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.of.eq(i.of),
                 self.product.eq(i.product), self.mid.eq(i.mid)]
 
 
 
 
 class FPDivStages(FPState, SimpleHandshake):
 
-    def __init__(self, width, id_wid):
+    def __init__(self, width, id_wid, n_stages, begin, end):
         FPState.__init__(self, "align")
         self.width = width
         self.id_wid = id_wid
+        self.n_stages = n_stages # number of combinatorial stages
+        self.begin = begin # "begin" mode
+        self.end = end # "end" mode
         SimpleHandshake.__init__(self, self) # pipeline is its own stage
         self.m1o = self.ospec()
 
     def ispec(self):
-        return FPSCData(self.width, self.id_wid, False)
+        if self.begin:
+            return FPSCData(self.width, self.id_wid, False)
+        return FPAddStage1Data(self.width, self.id_wid) # AddStage1 ospec
 
     def ospec(self):
+        if self.end: # TODO
+            return FPAddStage1Data(self.width, self.id_wid) # AddStage1 ospec
         return FPAddStage1Data(self.width, self.id_wid) # AddStage1 ospec
 
     def setup(self, m, i):
         """ links module to inputs and outputs
         """
 
-        # TODO.  clearly, this would be a for-loop, here, creating
-        # a huge number of stages (if radix-2 is used).  interestingly
-        # the number of stages will be data-dependent.
-        divstages = [FPDivStage0Mod(self.width, self.id_wid)]
-        for i in range(self.width): # XXX TODO: work out actual number needed
+        # start mode accepts data from the FP normalisation stage
+        # and does a bit of munging of the data.  it will be chained
+        # into the first DIV combinatorial block,
+
+        # end mode takes the DIV pipeline/chain data and munges it
+        # into the format that the normalisation can accept.
+
+        divstages = []
+
+        if self.begin: # XXX check this
+            divstages.append(FPDivStage0Mod(self.width, self.id_wid))
+
+        for count in range(self.n_stages): # number of combinatorial stages
             divstages.append(FPDivStage1Mod(self.width, self.id_wid))
-        divstages.append(FPDivStage2Mod(self.width, self.id_wid))
+
+        if self.end: # XXX check this
+            divstages.append(FPDivStage2Mod(self.width, self.id_wid))
 
         chain = StageChain(divstages)
         chain.setup(m, i)
 
-        self.o = m1mod.o
+        # output is from the last pipe stage
+        self.o = divstages[-1].o
 
     def process(self, i):
         return self.o
 
 class FPDIVBasePipe(ControlBase):
     def __init__(self, width, id_wid):
         ControlBase.__init__(self)
-        self.pipe1 = FPDIVSpecialCasesDeNorm(width, id_wid)
-        self.pipe2 = FPDivStages(width, id_wid)
-        self.pipe3 = FPNormToPack(width, id_wid)
+        self.pipestart = FPDIVSpecialCasesDeNorm(width, id_wid)
+        pipechain = []
+        n_stages = 6 # TODO
+        n_combinatorial_stages = 2 # TODO
+        for i in range(n_stages):
+            begin = i == 0 # needs to convert input from pipestart ospec
+            end = i == n_stages - 1 # needs to convert output to pipeend ispec
+            pipechain.append(FPDivStages(width, id_wid,
+                                         n_combinatorial_stages,
+                                         begin, end))
+        self.pipechain = pipechain
+        self.pipeend = FPNormToPack(width, id_wid)
 
-        self._eqs = self.connect([self.pipe1, self.pipe2, self.pipe3])
+        self._eqs = self.connect([self.pipestart] + pipechain + [self.pipeend])
 
     def elaborate(self, platform):
         m = ControlBase.elaborate(self, platform)
-        m.submodules.scnorm = self.pipe1
-        m.submodules.divstages = self.pipe2
-        m.submodules.normpack = self.pipe3
+        m.submodules.scnorm = self.pipestart
+        for i, p in enumerate(self.pipechain):
+            setattr(m.submodules, "pipediv%d" % i, p)
+        m.submodules.normpack = self.pipeend
         m.d.comb += self._eqs
         return m