start adding FSMDivCore*
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 17 Jul 2020 20:55:26 +0000 (13:55 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Fri, 17 Jul 2020 20:55:26 +0000 (13:55 -0700)
src/soc/fu/div/fsm.py [new file with mode: 0644]
src/soc/fu/div/pipe_data.py
src/soc/fu/div/pipeline.py

diff --git a/src/soc/fu/div/fsm.py b/src/soc/fu/div/fsm.py
new file mode 100644 (file)
index 0000000..bae1a43
--- /dev/null
@@ -0,0 +1,105 @@
+import enum
+from nmigen import Elaboratable, Module, Signal
+from soc.fu.div.pipe_data import CoreInputData, CoreOutputData
+
+
+class FSMDivCoreConfig:
+    n_stages = 1
+    bit_width = 64
+    fract_width = 64
+
+
+class FSMDivCoreInputData:
+    def __init__(self, core_config, reset_less=True):
+        self.core_config = core_config
+        self.dividend = Signal(128, reset_less=reset_less)
+        self.divisor_radicand = Signal(64, reset_less=reset_less)
+        self.operation = DivPipeCoreOperation.create_signal(
+            reset_less=reset_less)
+
+    def __iter__(self):
+        """ Get member signals. """
+        yield self.dividend
+        yield self.divisor_radicand
+        yield self.operation
+
+    def eq(self, rhs):
+        """ Assign member signals. """
+        return [self.dividend.eq(rhs.dividend),
+                self.divisor_radicand.eq(rhs.divisor_radicand),
+                self.operation.eq(rhs.operation),
+                ]
+
+
+class FSMDivCoreOutputData:
+    def __init__(self, core_config, reset_less=True):
+        self.core_config = core_config
+        self.quotient_root = Signal(64, reset_less=reset_less)
+        self.remainder = Signal(3 * 64, reset_less=reset_less)
+
+    def __iter__(self):
+        """ Get member signals. """
+        yield self.quotient_root
+        yield self.remainder
+        return
+
+    def eq(self, rhs):
+        """ Assign member signals. """
+        return [self.quotient_root.eq(rhs.quotient_root),
+                self.remainder.eq(rhs.remainder)]
+
+
+class FSMDivCorePrev:
+    def __init__(self, pspec):
+        self.data_i = CoreInputData(pspec)
+        self.valid_i = Signal()
+        self.ready_o = Signal()
+
+    def __iter__(self):
+        yield from self.data_i
+        yield self.valid_i
+        yield self.ready_o
+
+
+class FSMDivCoreNext:
+    def __init__(self, pspec):
+        self.data_o = CoreOutputData(pspec)
+        self.valid_o = Signal()
+        self.ready_i = Signal()
+
+    def __iter__(self):
+        yield from self.data_o
+        yield self.valid_o
+        yield self.ready_i
+
+
+class DivState(enum.Enum):
+    Empty = 0
+    Computing = 1
+    WaitingOnOutput = 2
+
+
+class FSMDivCoreStage(Elaboratable):
+    def __init__(self, pspec):
+        self.p = FSMDivCorePrev(pspec)
+        self.n = FSMDivCoreNext(pspec)
+        self.saved_input_data = CoreInputData(pspec)
+        self.canceled = Signal()
+        self.state = Signal(DivState, reset=DivState.Empty)
+
+    def elaborate(self, platform):
+        m = Module()
+
+        # TODO: calculate self.canceled from self.p.data_i.ctx
+        m.d.comb += self.canceled.eq(False)
+
+        # TODO(programmerjake): finish
+
+        return m
+
+    def __iter__(self):
+        yield from self.p
+        yield from self.n
+
+    def ports(self):
+        return list(self)
index b029f04bf86b3c2a18607c84cab6f847fd65c639..000ac0a9abb0f9f3167a4c777fa6d9ddb7561955 100644 (file)
@@ -33,24 +33,46 @@ class DivMulOutputData(IntegerData):
         self.cr0 = self.cr_a
 
 
-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 +80,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 +98,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,12 +113,19 @@ 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):
@@ -149,8 +178,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):
index 05cece6bc70abf9002208dd809080a0db895b948..2ea291e996146e9992577f4307b724a92724d1e1 100644 (file)
@@ -41,6 +41,7 @@ class DivStagesEnd(PipeModBaseChain):
 class DivBasePipe(ControlBase):
     def __init__(self, pspec, compute_steps_per_stage=4):
         ControlBase.__init__(self)
+        self.pspec = pspec
         self.pipe_start = DivStagesStart(pspec)
         compute_steps = pspec.core_config.n_stages
         self.pipe_middles = []