convert from public static functions/properties for regspecs
[soc.git] / src / soc / fu / div / pipe_data.py
index d8dd73931e14bfb8841ab06d1ead1e3f05b5b89c..dd4d1bedc0eecb3fee67632dccd0b04480fd0f72 100644 (file)
@@ -1,13 +1,15 @@
+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 (
     DivPipeCoreConfig, DivPipeCoreInputData, DP,
-    DivPipeCoreInterstageData, DivPipeCoreOutputData)
+    DivPipeCoreInterstageData, DivPipeCoreOutputData,
+    DivPipeCoreSetupStage, DivPipeCoreCalculateStage, DivPipeCoreFinalStage)
 
 
-class DivInputData(IntegerData):
+class DivInputData(FUBaseData):
     regspec = [('INT', 'ra', '0:63'),  # RA
                ('INT', 'rb', '0:63'),  # RB/immediate
                ('XER', 'xer_so', '32'), ]  # XER bit 32: SO
@@ -19,7 +21,7 @@ class DivInputData(IntegerData):
 
 
 # output stage shared between div and mul: like ALUOutputData but no CA/32
-class DivMulOutputData(IntegerData):
+class DivMulOutputData(FUBaseData):
     regspec = [('INT', 'o', '0:63'),
                ('CR', 'cr_a', '0:3'),
                ('XER', 'xer_ov', '33,44'),  # bit0: ov, bit1: ov32
@@ -31,15 +33,130 @@ class DivMulOutputData(IntegerData):
         self.cr0 = self.cr_a
 
 
+class DivPipeKindConfigBase:
+    def __init__(self,
+                 core_config,
+                 core_input_data_class,
+                 core_interstage_data_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()
+    # use nmigen's built-in div and rem operators -- only suitable for
+    # simulation
+    SimOnly = enum.auto()
+    # use a FSM-based div core
+    FSMDivCore = enum.auto()
+
+    @property
+    def config(self):
+        if self == DivPipeKind.DivPipeCore:
+            return DivPipeKindConfigCombPipe(
+                core_config=DivPipeCoreConfig(
+                    bit_width=64,
+                    fract_width=64,
+                    log2_radix=1,
+                    supported=[DP.UDivRem]
+                ),
+                core_input_data_class=DivPipeCoreInputData,
+                core_interstage_data_class=DivPipeCoreInterstageData,
+                core_output_data_class=DivPipeCoreOutputData,
+                core_setup_stage_class=DivPipeCoreSetupStage,
+                core_calculate_stage_class=DivPipeCoreCalculateStage,
+                core_final_stage_class=DivPipeCoreFinalStage)
+        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 DivPipeKindConfigCombPipe(
+                core_config=SimOnlyCoreConfig(),
+                core_input_data_class=SimOnlyCoreInputData,
+                core_interstage_data_class=SimOnlyCoreInterstageData,
+                core_output_data_class=SimOnlyCoreOutputData,
+                core_setup_stage_class=SimOnlyCoreSetupStage,
+                core_calculate_stage_class=SimOnlyCoreCalculateStage,
+                core_final_stage_class=SimOnlyCoreFinalStage)
+        # 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):
-    regspec = (DivInputData.regspec, DivMulOutputData.regspec)
+    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
+
+    regspecklses = (DivInputData, DivMulOutputData)
     opsubsetkls = CompLogicalOpSubset
-    core_config = DivPipeCoreConfig(
-        bit_width=64,
-        fract_width=64,
-        log2_radix=1,
-        supported=[DP.UDivRem]
-    )
+
+
+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):
@@ -76,14 +193,20 @@ class CoreBaseData(DivInputData):
 
 class CoreInputData(CoreBaseData):
     def __init__(self, pspec):
-        super().__init__(pspec, DivPipeCoreInputData)
+        super().__init__(pspec,
+                         pspec.div_pipe_kind.config.core_input_data_class)
 
 
 class CoreInterstageData(CoreBaseData):
     def __init__(self, pspec):
-        super().__init__(pspec, DivPipeCoreInterstageData)
+        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):
     def __init__(self, pspec):
-        super().__init__(pspec, DivPipeCoreOutputData)
+        super().__init__(pspec,
+                         pspec.div_pipe_kind.config.core_output_data_class)