From: Luke Kenneth Casson Leighton Date: Sat, 16 Feb 2019 07:02:06 +0000 (+0000) Subject: add pipeline class and example X-Git-Tag: ls180-24jan2020~1977 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=48dd87dd2ec6c5f6f6ef16a86bbe39a2f66496da;p=ieee754fpu.git add pipeline class and example --- diff --git a/src/add/pipeline.py b/src/add/pipeline.py new file mode 100644 index 00000000..bf35b6b3 --- /dev/null +++ b/src/add/pipeline.py @@ -0,0 +1,53 @@ +""" Example 5: Making use of PyRTL and Introspection. """ + +from nmigen import Signal +from nmigen.compat.fhdl.bitcontainer import value_bits_sign + +# The following example shows how pyrtl can be used to make some interesting +# hardware structures using python introspection. In particular, this example +# makes a N-stage pipeline structure. Any specific pipeline is then a derived +# class of SimplePipeline where methods with names starting with "stage" are +# stages, and new members with names not starting with "_" are to be registered +# for the next stage. + +class SimplePipeline(object): + """ Pipeline builder with auto generation of pipeline registers. + """ + + def __init__(self, pipe): + self._pipe = pipe + self._pipeline_register_map = {} + self._current_stage_num = 0 + + def _setup(self): + stage_list = [] + for method in dir(self): + if method.startswith('stage'): + stage_list.append(method) + for stage in sorted(stage_list): + stage_method = getattr(self, stage) + stage_method() + self._current_stage_num += 1 + + def __getattr__(self, name): + try: + return self._pipeline_register_map[self._current_stage_num][name] + except KeyError: + raise AttributeError( + 'error, no pipeline register "%s" defined for stage %d' + % (name, self._current_stage_num)) + + def __setattr__(self, name, value): + if name.startswith('_'): + # do not do anything tricky with variables starting with '_' + object.__setattr__(self, name, value) + else: + next_stage = self._current_stage_num + 1 + pipereg_id = str(self._current_stage_num) + 'to' + str(next_stage) + rname = 'pipereg_' + pipereg_id + '_' + name + new_pipereg = Signal(value_bits_sign(value), name=rname) + if next_stage not in self._pipeline_register_map: + self._pipeline_register_map[next_stage] = {} + self._pipeline_register_map[next_stage][name] = new_pipereg + self._pipe.sync += new_pipereg.eq(value) + diff --git a/src/add/pipeline_example.py b/src/add/pipeline_example.py new file mode 100644 index 00000000..2198523f --- /dev/null +++ b/src/add/pipeline_example.py @@ -0,0 +1,51 @@ +""" Example 5: Making use of PyRTL and Introspection. """ + +from copy import deepcopy +from nmigen import Module, Signal +from nmigen.cli import main, verilog + + +from pipeline import SimplePipeline + + +class SimplePipelineExample(SimplePipeline): + """ A very simple pipeline to show how registers are inferred. """ + + def __init__(self, pipe): + SimplePipeline.__init__(self, pipe) + self._loopback = Signal(4) + self._setup() + + def stage0(self): + self.n = ~self._loopback + + def stage1(self): + self.n = self.n + 1 + + def stage2(self): + self.n = self.n << 1 + + def stage3(self): + self.n = ~self.n + + def stage4(self): + self._pipe.sync += self._loopback.eq(self.n + 3) + +class PipeModule: + + def __init__(self): + self.m = Module() + self.p = SimplePipelineExample(self.m.d) + + def get_fragment(self, platform=None): + return self.m + +if __name__ == "__main__": + example = PipeModule() + main(example, ports=[ + example.p._loopback, + ]) + + print(verilog.convert(example, ports=[ + example.p._loopback, + ]))