more random experimenting
[ieee754fpu.git] / src / ieee754 / fpdiv / pipeline.py
index 3473e4c69842eca874c9381a68aa10dfa94b4a56..119db0f57f626438d4100e7a331d13cb125fc6b3 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,6 +64,7 @@ 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 ieee754.fpdiv.specialcases import FPDIVSpecialCasesDeNorm
@@ -71,35 +72,38 @@ 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, pspec):
-        ControlBase.__init__(self)
         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)
-        stage_idx = 0
+        max_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".
 
+        # XXX BUG - subtracting 4 from number of stages stops assert
+        # probably related to having to add 4 in FPDivMuxInOut
+        radix = pspec.log2_radix
+        n_stages = pspec.core_config.n_stages // max_n_comb_stages
+        stage_idx = 0
+
         for i in range(n_stages):
 
+            n_comb_stages = max_n_comb_stages
             # needs to convert input from pipestart ospec
             if i == 0:
                 kls = FPDivStagesSetup
-                n_comb_stages -= 1  # reduce due to work done at start
+                #n_comb_stages -= 1  # reduce due to work done at start?
 
             # 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?
+                #n_comb_stages -= 1  # FIXME - reduce due to work done at end?
 
             # intermediary stage
             else:
@@ -109,21 +113,31 @@ class FPDIVBasePipe(ControlBase):
             stage_idx += n_comb_stages # increment so that each CalcStage
                                        # gets a (correct) unique index
 
+        self.pipechain = pipechain
+
         # start and end: unpack/specialcases then normalisation/packing
-        pipestart = FPDIVSpecialCasesDeNorm(self.pspec)
-        pipeend = FPNormToPack(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.
@@ -138,9 +152,24 @@ class FPDIVMuxInOut(ReservationStations):
                    then be used to change the behaviour of the pipeline.
     """
 
-    def __init__(self, width, num_rows, op_wid=0):
+    def __init__(self, width, num_rows, op_wid=1):
         self.id_wid = num_bits(width)
         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
+        fmt.m_width = roundup(fmt.m_width + 5, log2_radix)
+
+        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)