class DivCoreSetupStage(DivCoreBaseStage):
def __init__(self, pspec):
- super().__init__(pspec, "core_setup_stage", DivPipeCoreSetupStage)
+ super().__init__(pspec, "core_setup_stage",
+ pspec.div_pipe_kind.config.core_setup_stage_class)
def ispec(self):
return CoreInputData(self.pspec)
class DivCoreCalculateStage(DivCoreBaseStage):
def __init__(self, pspec, stage_index):
+ stage = pspec.div_pipe_kind.config.core_calculate_stage_class
super().__init__(pspec, f"core_calculate_stage_{stage_index}",
- DivPipeCoreCalculateStage, stage_index)
+ stage, stage_index)
def ispec(self):
return CoreInterstageData(self.pspec)
class DivCoreFinalStage(DivCoreBaseStage):
def __init__(self, pspec):
- super().__init__(pspec, "core_final_stage", DivPipeCoreFinalStage)
+ super().__init__(pspec, "core_final_stage",
+ pspec.div_pipe_kind.config.core_final_stage_class)
def ispec(self):
return CoreInterstageData(self.pspec)
+import enum
from nmigen import Signal, Const
from soc.fu.pipe_data import IntegerData
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):
self.cr0 = self.cr_a
+class DivPipeKindConfig:
+ 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):
+ 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
+ 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 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
+ FSMCore = enum.auto()
+
+ @property
+ def config(self):
+ if self == DivPipeKind.DivPipeCore:
+ return DivPipeKindConfig(
+ 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)
+ elif 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(
+ 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)
+ 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()
+
+
class DivPipeSpec(CommonPipeSpec):
+ def __init__(self, id_wid, div_pipe_kind):
+ super().__init__(id_wid=id_wid)
+ self.div_pipe_kind = div_pipe_kind
+ self.core_config = div_pipe_kind.config.core_config
+
regspec = (DivInputData.regspec, DivMulOutputData.regspec)
opsubsetkls = CompLogicalOpSubset
- core_config = DivPipeCoreConfig(
- bit_width=64,
- fract_width=64,
- log2_radix=1,
- supported=[DP.UDivRem]
- )
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)
+ super().__init__(pspec, pspec.div_pipe_kind.config.core_interstage_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)
--- /dev/null
+from nmigen import Signal, Elaboratable, Module
+from ieee754.div_rem_sqrt_rsqrt.core import DivPipeCoreOperation
+
+
+class SimOnlyCoreConfig:
+ n_stages = 1
+ bit_width = 64
+ fract_width = 64
+
+
+class SimOnlyCoreInputData:
+ 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 SimOnlyCoreInterstageData:
+ def __init__(self, core_config, reset_less=True):
+ self.core_config = core_config
+ self.dividend = Signal(128, reset_less=reset_less)
+ self.divisor = Signal(64, reset_less=reset_less)
+
+ def __iter__(self):
+ """ Get member signals. """
+ yield self.dividend
+ yield self.divisor
+
+ def eq(self, rhs):
+ """ Assign member signals. """
+ return [self.dividend.eq(rhs.dividend),
+ self.divisor.eq(rhs.divisor)]
+
+
+class SimOnlyCoreOutputData:
+ 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 SimOnlyCoreSetupStage(Elaboratable):
+ def __init__(self, core_config):
+ self.core_config = core_config
+ self.i = self.ispec()
+ self.o = self.ospec()
+
+ def ispec(self):
+ """ Get the input spec for this pipeline stage."""
+ return SimOnlyCoreInputData(self.core_config)
+
+ def ospec(self):
+ """ Get the output spec for this pipeline stage."""
+ return SimOnlyCoreInterstageData(self.core_config)
+
+ def setup(self, m, i):
+ """ Pipeline stage setup. """
+ m.submodules.sim_only_core_setup = self
+ m.d.comb += self.i.eq(i)
+
+ def process(self, i):
+ """ Pipeline stage process. """
+ return self.o # return processed data (ignore i)
+
+ def elaborate(self, platform):
+ """ Elaborate into ``Module``. """
+ m = Module()
+ comb = m.d.comb
+
+ comb += self.o.divisor.eq(self.i.divisor_radicand)
+ comb += self.o.dividend.eq(self.i.dividend)
+
+ return m
+
+
+class SimOnlyCoreCalculateStage(Elaboratable):
+ def __init__(self, core_config, stage_index):
+ assert stage_index == 0
+ self.core_config = core_config
+ self.stage_index = stage_index
+ self.i = self.ispec()
+ self.o = self.ospec()
+
+ def ispec(self):
+ """ Get the input spec for this pipeline stage. """
+ return SimOnlyCoreInterstageData(self.core_config)
+
+ def ospec(self):
+ """ Get the output spec for this pipeline stage. """
+ return SimOnlyCoreInterstageData(self.core_config)
+
+ def setup(self, m, i):
+ """ Pipeline stage setup. """
+ setattr(m.submodules,
+ f"sim_only_core_calculate_{self.stage_index}",
+ self)
+ m.d.comb += self.i.eq(i)
+
+ def process(self, i):
+ """ Pipeline stage process. """
+ return self.o
+
+ def elaborate(self, platform):
+ """ Elaborate into ``Module``. """
+ m = Module()
+ m.d.comb += self.o.eq(self.i)
+ return m
+
+
+class SimOnlyCoreFinalStage(Elaboratable):
+ """ Final Stage of the core of the div/rem/sqrt/rsqrt pipeline. """
+
+ def __init__(self, core_config):
+ """ Create a ``SimOnlyCoreFinalStage`` instance."""
+ self.core_config = core_config
+ self.i = self.ispec()
+ self.o = self.ospec()
+
+ def ispec(self):
+ """ Get the input spec for this pipeline stage."""
+ return SimOnlyCoreInterstageData(self.core_config)
+
+ def ospec(self):
+ """ Get the output spec for this pipeline stage."""
+ return SimOnlyCoreOutputData(self.core_config)
+
+ def setup(self, m, i):
+ """ Pipeline stage setup. """
+ m.submodules.sim_only_core_final = self
+ m.d.comb += self.i.eq(i)
+
+ def process(self, i):
+ """ Pipeline stage process. """
+ return self.o # return processed data (ignore i)
+
+ def elaborate(self, platform):
+ """ Elaborate into ``Module``. """
+ m = Module()
+ remainder_shift = self.core_config.fract_width
+ with m.If(self.i.divisor != 0):
+ quotient = self.i.dividend // self.i.divisor
+ remainder = self.i.dividend % self.i.divisor
+ m.d.comb += self.o.quotient_root.eq(quotient)
+ m.d.comb += self.o.remainder.eq(remainder << remainder_shift)
+ with m.Else():
+ m.d.comb += self.o.quotient_root.eq(-1)
+ m.d.comb += self.o.remainder.eq(self.i.dividend << remainder_shift)
+
+ return m
from soc.fu.test.common import (TestCase, ALUHelpers)
from soc.fu.div.pipeline import DivBasePipe
-from soc.fu.div.pipe_data import DivPipeSpec
+from soc.fu.div.pipe_data import DivPipeSpec, DivPipeKind
import random
m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
- pspec = DivPipeSpec(id_wid=2)
+ # TODO(programmerjake): thread div_pipe_kind through somehow to allow testing other cases
+ pspec = DivPipeSpec(id_wid=2, div_pipe_kind=DivPipeKind.SimOnly)
m.submodules.alu = alu = DivBasePipe(pspec)
comb += alu.p.data_i.ctx.op.eq_from_execute1(pdecode2.e)