reorganise loop
[ieee754fpu.git] / src / ieee754 / fpdiv / pipeline.py
index 21f746ba982287208138d71b60a103ab25d8c1f7..cf2a04c20f774d110ba54a8cfcc574525e481ef7 100644 (file)
@@ -11,7 +11,7 @@ scnorm   - FPDIVSpecialCasesDeNorm ispec FPADDBaseData
                             FPAddDeNormMod
 
 pipediv0 - FPDivStagesSetup        ispec FPSCData
---------                           ospec DivPipeCoreInterstageData
+--------                           ospec DivPipeInterstageData
 
                 StageChain: FPDivStage0Mod,
                             DivPipeSetupStage,
@@ -19,8 +19,8 @@ pipediv0 - FPDivStagesSetup        ispec FPSCData
                             ...
                             DivPipeCalculateStage
 
-pipediv1 - FPDivStagesIntermediate ispec DivPipeCoreInterstageData
---------                           ospec DivPipeCoreInterstageData
+pipediv1 - FPDivStagesIntermediate ispec DivPipeInterstageData
+--------                           ospec DivPipeInterstageData
 
                 StageChain: DivPipeCalculateStage,
                             ...
@@ -64,63 +64,80 @@ from nmutil.concurrentunit import ReservationStations, num_bits
 
 from ieee754.fpcommon.getop import FPADDBaseData
 from ieee754.fpcommon.denorm import FPSCData
+from ieee754.fpcommon.fpbase import FPFormat
 from ieee754.fpcommon.pack import FPPackData
 from ieee754.fpcommon.normtopack import FPNormToPack
-from .specialcases import FPDIVSpecialCasesDeNorm
-from .divstages import (FPDivStagesSetup,
-                        FPDivStagesIntermediate,
-                        FPDivStagesFinal)
+from ieee754.fpdiv.specialcases import FPDIVSpecialCasesDeNorm
+from ieee754.fpdiv.divstages import (FPDivStagesSetup,
+                                     FPDivStagesIntermediate,
+                                     FPDivStagesFinal)
+from ieee754.pipeline import PipelineSpec
+from ieee754.div_rem_sqrt_rsqrt.core import DivPipeCoreConfig
 
 
 class FPDIVBasePipe(ControlBase):
-    def __init__(self, width, pspec):
-        ControlBase.__init__(self)
-        self.width = width
+    def __init__(self, pspec):
         self.pspec = pspec
-
-    def elaborate(self, platform):
-        m = ControlBase.elaborate(self, platform)
+        ControlBase.__init__(self)
 
         pipechain = []
-        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".
+        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".
+
+        # get number of stages, set up loop.
+        n_stages = pspec.core_config.n_stages
+        print ("n_stages", n_stages)
+        stage_idx = 0
 
-        for i in range(n_stages):
+        end = False
+        while not end:
 
             # needs to convert input from pipestart ospec
-            if i == 0:
-                kls = FPDivStagesSetup
-                n_comb_stages -= 1 # reduce due to work done at start
+            if stage_idx == 0:
+                kls = FPDivStagesSetup # does n_comb_stages-1 calcs as well
 
             # 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?
+            elif stage_idx + n_comb_stages >= n_stages:
+                kls = FPDivStagesFinal # does n_comb_stages-1 calcs as well
+                end = True
+                n_comb_stages = n_stages - stage_idx
 
             # intermediary stage
             else:
-                kls = FPDivStagesIntermediate
+                kls = FPDivStagesIntermediate # does n_comb_stages calcs
+
+            # create (in each pipe) a StageChain n_comb_stages in length
+            pipechain.append(kls(self.pspec, n_comb_stages, stage_idx))
+            stage_idx += n_comb_stages # increment so that each CalcStage
+                                       # gets a (correct) unique index
 
-            pipechain.append(kls(self.width, self.pspec, n_comb_stages))
+        self.pipechain = pipechain
 
         # start and end: unpack/specialcases then normalisation/packing
-        pipestart = FPDIVSpecialCasesDeNorm(self.width, self.pspec)
-        pipeend = FPNormToPack(self.width, self.pspec)
+        self.pipestart = pipestart = FPDIVSpecialCasesDeNorm(self.pspec)
+        self.pipeend = pipeend = FPNormToPack(self.pspec)
+
+        self._eqs = self.connect([pipestart] + pipechain + [pipeend])
+
+    def elaborate(self, platform):
+        m = ControlBase.elaborate(self, platform)
 
         # add submodules
-        m.submodules.scnorm = pipestart
-        for i, p in enumerate(pipechain):
+        m.submodules.scnorm = self.pipestart
+        for i, p in enumerate(self.pipechain):
             setattr(m.submodules, "pipediv%d" % i, p)
-        m.submodules.normpack = pipeend
+        m.submodules.normpack = self.pipeend
 
         # ControlBase.connect creates the "eqs" needed to connect each pipe
-        m.d.comb += self.connect([pipestart] + pipechain + [pipeend])
+        m.d.comb += self._eqs
 
         return m
 
+def roundup(x, mod):
+    return x if x % mod == 0 else x + mod - x % mod
+
 
 class FPDIVMuxInOut(ReservationStations):
     """ Reservation-Station version of FPDIV pipeline.
@@ -134,15 +151,42 @@ class FPDIVMuxInOut(ReservationStations):
         :op_wid: - set this to the width of an operator which can
                    then be used to change the behaviour of the pipeline.
     """
-    def __init__(self, width, num_rows, op_wid=0):
-        self.width = width
+
+    def __init__(self, width, num_rows, op_wid=1):
         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 = PipelineSpec(width, self.id_wid, op_wid)
+        # get the standard mantissa width, store in the pspec HOWEVER...
+        fmt = FPFormat.standard(width)
+        log2_radix = 2
+
+        # ...5 extra bits on the mantissa: MSB is zero, MSB-1 is 1
+        # then there is guard, round and sticky at the LSB end.
+        # also: round up to nearest radix
+        if width == 16:
+            extra = 5
+        elif width == 32:
+            extra = 6
+        elif width == 64:
+            extra = 5
+        fmt.m_width = roundup(fmt.m_width + extra, log2_radix)
+        print ("width", fmt.m_width)
+
+        cfg = DivPipeCoreConfig(fmt.m_width, fmt.fraction_width, log2_radix)
+
+        self.pspec.fpformat = fmt
+        self.pspec.log2_radix = log2_radix
+        self.pspec.core_config = cfg
+
+        # XXX TODO - a class (or function?) that takes the pspec (right here)
+        # and creates... "something".  that "something" MUST have an eq function
+        # new_pspec = deepcopy(self.pspec)
+        # new_pspec.opkls = DivPipeCoreOperation
+        # self.alu = FPDIVBasePipe(new_pspec)
+        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)