big (single-purpose) update: move width arg into pspec
[ieee754fpu.git] / src / ieee754 / fpdiv / pipeline.py
index 824f6d274579c6d4aeb2008aa842a75758f5f602..58fa8e9b0df0e73e64799d7d1ce57dd07d78ddf8 100644 (file)
@@ -4,38 +4,56 @@ Relevant bugreport: http://bugs.libre-riscv.org/show_bug.cgi?id=99
 
 Stack looks like this:
 
-scnorm   - FPDIVSpecialCasesDeNorm ispec FPADDBaseData  ospec FPSCData
-            StageChain: FPDIVSpecialCasesMod,
-                        FPAddDeNormMod
-
-pipediv0 - FPDivStages(start=true) ispec FPSCData       ospec FPDivStage0Data
-            StageChain: FPDivStage0Mod,
-                        FPDivStage1Mod,
-                        ...
-                        FPDivStage1Mod
-
-pipediv1 - FPDivStages()           ispec FPDivStage0Data ospec FPDivStage0Data
-            StageChain: FPDivStage1Mod,
-                        ...
-                        FPDivStage1Mod
+scnorm   - FPDIVSpecialCasesDeNorm ispec FPADDBaseData
+------                             ospec FPSCData
+
+                StageChain: FPDIVSpecialCasesMod,
+                            FPAddDeNormMod
+
+pipediv0 - FPDivStagesSetup        ispec FPSCData
+--------                           ospec DivPipeCoreInterstageData
+
+                StageChain: FPDivStage0Mod,
+                            DivPipeSetupStage,
+                            DivPipeCalculateStage,
+                            ...
+                            DivPipeCalculateStage
+
+pipediv1 - FPDivStagesIntermediate ispec DivPipeCoreInterstageData
+--------                           ospec DivPipeCoreInterstageData
+
+                StageChain: DivPipeCalculateStage,
+                            ...
+                            DivPipeCalculateStage
 ...
 ...
 
-pipediv5 - FPDivStages(end=true    ispec FPDivStage0Data ospec FPAddStage1Data
-            StageChain: FPDivStage1Mod,
-                        ...
-                        FPDivStage1Mod,
-                        FPDivStage2Mod
+pipediv5 - FPDivStageFinal         ispec FPDivStage0Data
+--------                           ospec FPAddStage1Data
+
+                StageChain: DivPipeCalculateStage,
+                            ...
+                            DivPipeCalculateStage,
+                            DivPipeFinalStage,
+                            FPDivStage2Mod
 
-normpack - FPNormToPack            ispec FPAddStage1Data ospec FPPackData
-            StageChain: Norm1ModSingle,
-                        RoundMod,
-                        CorrectionsMod,
-                        PackMod
+normpack - FPNormToPack            ispec FPAddStage1Data
+--------                           ospec FPPackData
 
-the number of combinatorial StageChains (n_combinatorial_stages) in
+                StageChain: Norm1ModSingle,
+                            RoundMod,
+                            CorrectionsMod,
+                            PackMod
+
+the number of combinatorial StageChains (n_comb_stages) in
 FPDivStages is an argument arranged to get the length of the whole
 pipeline down to sane numbers.
+
+the reason for keeping the number of stages down is that for every
+pipeline clock delay, a corresponding ReservationStation is needed.
+if there are 24 pipeline stages, we need a whopping TWENTY FOUR
+RS's.  that's far too many.  6 is just about an acceptable number.
+even 8 is starting to get alarmingly high.
 """
 
 from nmigen import Module
@@ -49,35 +67,57 @@ from ieee754.fpcommon.denorm import FPSCData
 from ieee754.fpcommon.pack import FPPackData
 from ieee754.fpcommon.normtopack import FPNormToPack
 from .specialcases import FPDIVSpecialCasesDeNorm
-from .divstages import FPDivStages
-
+from .divstages import (FPDivStagesSetup,
+                        FPDivStagesIntermediate,
+                        FPDivStagesFinal)
 
 
 class FPDIVBasePipe(ControlBase):
-    def __init__(self, width, pspec):
+    def __init__(self, pspec):
         ControlBase.__init__(self)
-        self.pipestart = FPDIVSpecialCasesDeNorm(width, pspec)
+        self.pspec = pspec
+
+    def elaborate(self, platform):
+        m = ControlBase.elaborate(self, platform)
+
         pipechain = []
-        n_stages = 6 # TODO
-        n_combinatorial_stages = 2 # TODO
+        n_stages = 6      # TODO (depends on width)
+        n_comb_stages = 3 # TODO (depends on how many RS's we want)
+                          # to which the answer: "as few as possible"
+                          # is required.  too many ReservationStations
+                          # means "big problems".
+
         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, pspec,
-                                         n_combinatorial_stages,
-                                         begin, end))
-        self.pipechain = pipechain
-        self.pipeend = FPNormToPack(width, pspec)
 
-        self._eqs = self.connect([self.pipestart] + pipechain + [self.pipeend])
+            # needs to convert input from pipestart ospec
+            if i == 0:
+                kls = FPDivStagesSetup
+                n_comb_stages -= 1 # reduce due to work done at start
 
-    def elaborate(self, platform):
-        m = ControlBase.elaborate(self, platform)
-        m.submodules.scnorm = self.pipestart
-        for i, p in enumerate(self.pipechain):
+            # needs to convert output to pipeend ispec
+            elif i == n_stages - 1:
+                kls = FPDivStagesFinal
+                n_comb_stages -= 1 # FIXME - reduce due to work done at end?
+
+            # intermediary stage
+            else:
+                kls = FPDivStagesIntermediate
+
+            pipechain.append(kls(self.pspec, n_comb_stages))
+
+        # start and end: unpack/specialcases then normalisation/packing
+        pipestart = FPDIVSpecialCasesDeNorm(self.pspec)
+        pipeend = FPNormToPack(self.pspec)
+
+        # add submodules
+        m.submodules.scnorm = pipestart
+        for i, p in enumerate(pipechain):
             setattr(m.submodules, "pipediv%d" % i, p)
-        m.submodules.normpack = self.pipeend
-        m.d.comb += self._eqs
+        m.submodules.normpack = pipeend
+
+        # ControlBase.connect creates the "eqs" needed to connect each pipe
+        m.d.comb += self.connect([pipestart] + pipechain + [pipeend])
+
         return m
 
 
@@ -94,14 +134,13 @@ class FPDIVMuxInOut(ReservationStations):
                    then be used to change the behaviour of the pipeline.
     """
     def __init__(self, width, num_rows, op_wid=0):
-        self.width = width
         self.id_wid = num_bits(width)
-        self.pspec = {'id_wid': self.id_wid, 'op_wid': op_wid}
-        self.alu = FPDIVBasePipe(width, self.pspec)
+        self.pspec = {'width': width, 'id_wid': self.id_wid, 'op_wid': op_wid}
+        self.alu = FPDIVBasePipe(self.pspec)
         ReservationStations.__init__(self, num_rows)
 
     def i_specfn(self):
-        return FPADDBaseData(self.width, self.pspec)
+        return FPADDBaseData(self.pspec)
 
     def o_specfn(self):
-        return FPPackData(self.width, self.pspec)
+        return FPPackData(self.pspec)