From cb34e4a8972dae9221ef5ea7ec67113571ff8795 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 17 Jul 2020 13:55:26 -0700 Subject: [PATCH] start adding FSMDivCore* --- src/soc/fu/div/fsm.py | 105 ++++++++++++++++++++++++++++++++++++ src/soc/fu/div/pipe_data.py | 66 +++++++++++++++++------ src/soc/fu/div/pipeline.py | 1 + 3 files changed, 155 insertions(+), 17 deletions(-) create mode 100644 src/soc/fu/div/fsm.py diff --git a/src/soc/fu/div/fsm.py b/src/soc/fu/div/fsm.py new file mode 100644 index 00000000..bae1a43e --- /dev/null +++ b/src/soc/fu/div/fsm.py @@ -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) diff --git a/src/soc/fu/div/pipe_data.py b/src/soc/fu/div/pipe_data.py index b029f04b..000ac0a9 100644 --- a/src/soc/fu/div/pipe_data.py +++ b/src/soc/fu/div/pipe_data.py @@ -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): diff --git a/src/soc/fu/div/pipeline.py b/src/soc/fu/div/pipeline.py index 05cece6b..2ea291e9 100644 --- a/src/soc/fu/div/pipeline.py +++ b/src/soc/fu/div/pipeline.py @@ -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 = [] -- 2.30.2