start on converting MUL and DIV pipelines to XLEN
[soc.git] / src / soc / fu / div / pipe_data.py
index b029f04bf86b3c2a18607c84cab6f847fd65c639..1c807dc05492f5b654cf70f1443e55cef99774bb 100644 (file)
@@ -1,6 +1,6 @@
 import enum
 from nmigen import Signal, Const
-from soc.fu.pipe_data import IntegerData
+from soc.fu.pipe_data import FUBaseData
 from soc.fu.alu.pipe_data import CommonPipeSpec
 from soc.fu.logical.logical_input_record import CompLogicalOpSubset
 from ieee754.div_rem_sqrt_rsqrt.core import (
@@ -9,48 +9,75 @@ from ieee754.div_rem_sqrt_rsqrt.core import (
     DivPipeCoreSetupStage, DivPipeCoreCalculateStage, DivPipeCoreFinalStage)
 
 
-class DivInputData(IntegerData):
-    regspec = [('INT', 'ra', '0:63'),  # RA
-               ('INT', 'rb', '0:63'),  # RB/immediate
-               ('XER', 'xer_so', '32'), ]  # XER bit 32: SO
-
+class DivInputData(FUBaseData):
     def __init__(self, pspec):
         super().__init__(pspec, False)
         # convenience
         self.a, self.b = self.ra, self.rb
 
+    @property
+    def regspec(self):
+        return [('INT', 'ra', self.intrange),  # RA
+               ('INT', 'rb', self.intrange),  # RB/immediate
+               ('XER', 'xer_so', '32'), ]  # XER bit 32: SO
+
 
 # output stage shared between div and mul: like ALUOutputData but no CA/32
-class DivMulOutputData(IntegerData):
-    regspec = [('INT', 'o', '0:63'),
-               ('CR', 'cr_a', '0:3'),
-               ('XER', 'xer_ov', '33,44'),  # bit0: ov, bit1: ov32
-               ('XER', 'xer_so', '32')]
+class DivMulOutputData(FUBaseData):
 
     def __init__(self, pspec):
         super().__init__(pspec, True)
         # convenience
         self.cr0 = self.cr_a
 
+    @property
+    def regspec(self):
+        return [('INT', 'o', self.intrange),
+               ('CR', 'cr_a', '0:3'),
+               ('XER', 'xer_ov', '33,44'),  # bit0: ov, bit1: ov32
+               ('XER', 'xer_so', '32')]
+
 
-class DivPipeKindConfig:
+class DivPipeKindConfigBase:
     def __init__(self,
                  core_config,
                  core_input_data_class,
                  core_interstage_data_class,
-                 core_output_data_class,
-                 core_setup_stage_class,
-                 core_calculate_stage_class,
-                 core_final_stage_class):
+                 core_output_data_class):
         self.core_config = core_config
         self.core_input_data_class = core_input_data_class
         self.core_interstage_data_class = core_interstage_data_class
         self.core_output_data_class = core_output_data_class
+
+
+class DivPipeKindConfigCombPipe(DivPipeKindConfigBase):
+    def __init__(self,
+                 core_config,
+                 core_input_data_class,
+                 core_interstage_data_class,
+                 core_output_data_class,
+                 core_setup_stage_class,
+                 core_calculate_stage_class,
+                 core_final_stage_class):
+        super().__init__(core_config, core_input_data_class,
+                         core_interstage_data_class, core_output_data_class)
         self.core_setup_stage_class = core_setup_stage_class
         self.core_calculate_stage_class = core_calculate_stage_class
         self.core_final_stage_class = core_final_stage_class
 
 
+class DivPipeKindConfigFSM(DivPipeKindConfigBase):
+    def __init__(self,
+                 core_config,
+                 core_input_data_class,
+                 core_output_data_class,
+                 core_stage_class):
+        core_interstage_data_class = None
+        super().__init__(core_config, core_input_data_class,
+                         core_interstage_data_class, core_output_data_class)
+        self.core_stage_class = core_stage_class
+
+
 class DivPipeKind(enum.Enum):
     # use ieee754.div_rem_sqrt_rsqrt.core.DivPipeCore*
     DivPipeCore = enum.auto()
@@ -58,12 +85,12 @@ class DivPipeKind(enum.Enum):
     # simulation
     SimOnly = enum.auto()
     # use a FSM-based div core
-    FSMCore = enum.auto()
+    FSMDivCore = enum.auto()
 
     @property
     def config(self):
         if self == DivPipeKind.DivPipeCore:
-            return DivPipeKindConfig(
+            return DivPipeKindConfigCombPipe(
                 core_config=DivPipeCoreConfig(
                     bit_width=64,
                     fract_width=64,
@@ -76,14 +103,14 @@ class DivPipeKind(enum.Enum):
                 core_setup_stage_class=DivPipeCoreSetupStage,
                 core_calculate_stage_class=DivPipeCoreCalculateStage,
                 core_final_stage_class=DivPipeCoreFinalStage)
-        elif self == DivPipeKind.SimOnly:
+        if self == DivPipeKind.SimOnly:
             # import here to avoid import loop
             from soc.fu.div.sim_only_core import (
                 SimOnlyCoreConfig, SimOnlyCoreInputData,
                 SimOnlyCoreInterstageData, SimOnlyCoreOutputData,
                 SimOnlyCoreSetupStage, SimOnlyCoreCalculateStage,
                 SimOnlyCoreFinalStage)
-            return DivPipeKindConfig(
+            return DivPipeKindConfigCombPipe(
                 core_config=SimOnlyCoreConfig(),
                 core_input_data_class=SimOnlyCoreInputData,
                 core_interstage_data_class=SimOnlyCoreInterstageData,
@@ -91,24 +118,52 @@ class DivPipeKind(enum.Enum):
                 core_setup_stage_class=SimOnlyCoreSetupStage,
                 core_calculate_stage_class=SimOnlyCoreCalculateStage,
                 core_final_stage_class=SimOnlyCoreFinalStage)
-        else:
-            # ensure we didn't forget any cases
-            # -- I wish Python had a switch/match statement
-            assert self == DivPipeKind.FSMCore
-            # TODO(programmerjake): implement
-            raise NotImplementedError()
+        # ensure we didn't forget any cases
+        # -- I wish Python had a switch/match statement
+        assert self == DivPipeKind.FSMDivCore
+
+        # import here to avoid import loop
+        from soc.fu.div.fsm import (
+            FSMDivCoreConfig, FSMDivCoreInputData,
+            FSMDivCoreOutputData, FSMDivCoreStage)
+        return DivPipeKindConfigFSM(
+            core_config=FSMDivCoreConfig(),
+            core_input_data_class=FSMDivCoreInputData,
+            core_output_data_class=FSMDivCoreOutputData,
+            core_stage_class=FSMDivCoreStage)
 
 
 class DivPipeSpec(CommonPipeSpec):
-    def __init__(self, id_wid, div_pipe_kind):
-        super().__init__(id_wid=id_wid)
+    def __init__(self, id_wid, parent_pspec, div_pipe_kind):
+        super().__init__(id_wid=id_wid, parent_pspec=parent_pspec)
         self.div_pipe_kind = div_pipe_kind
         self.core_config = div_pipe_kind.config.core_config
 
-    regspec = (DivInputData.regspec, DivMulOutputData.regspec)
+    regspecklses = (DivInputData, DivMulOutputData)
     opsubsetkls = CompLogicalOpSubset
 
 
+class DivPipeSpecDivPipeCore(DivPipeSpec):
+    def __init__(self, id_wid, parent_pspec):
+        super().__init__(id_wid=id_wid,
+                         parent_pspec=parent_pspec,
+                         div_pipe_kind=DivPipeKind.DivPipeCore)
+
+
+class DivPipeSpecFSMDivCore(DivPipeSpec):
+    def __init__(self, id_wid, parent_pspec):
+        super().__init__(id_wid=id_wid,
+                         parent_pspec=parent_pspec,
+                         div_pipe_kind=DivPipeKind.FSMDivCore)
+
+
+class DivPipeSpecSimOnly(DivPipeSpec):
+    def __init__(self, id_wid, parent_pspec):
+        super().__init__(id_wid=id_wid,
+                         parent_pspec=parent_pspec,
+                         div_pipe_kind=DivPipeKind.SimOnly)
+
+
 class CoreBaseData(DivInputData):
     def __init__(self, pspec, core_data_class):
         super().__init__(pspec)
@@ -149,8 +204,11 @@ class CoreInputData(CoreBaseData):
 
 class CoreInterstageData(CoreBaseData):
     def __init__(self, pspec):
-        super().__init__(pspec,
-                         pspec.div_pipe_kind.config.core_interstage_data_class)
+        data_class = pspec.div_pipe_kind.config.core_interstage_data_class
+        if data_class is None:
+            raise ValueError(
+                f"CoreInterstageData not supported for {pspec.div_pipe_kind}")
+        super().__init__(pspec, data_class)
 
 
 class CoreOutputData(CoreBaseData):