From: Luke Kenneth Casson Leighton Date: Fri, 23 Nov 2018 03:44:24 +0000 (+0000) Subject: add example pipeline.py X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=06b76ae69bd4cd33f0f074a1430d078b988b65c4;p=rv32.git add example pipeline.py --- diff --git a/pipestage.py b/pipestage.py new file mode 100644 index 0000000..dfa2a3e --- /dev/null +++ b/pipestage.py @@ -0,0 +1,88 @@ +""" Example 5: Making use of PyRTL and Introspection. """ + +from copy import deepcopy +from migen import * +from migen.fhdl import verilog + + +# 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 = [method for method in dir(self) if method.startswith('stage')] + 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 = pyrtl.Register(bitwidth=len(value), name=rname) + new_pipereg = Signal(len(value), name_override=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) + + +class SimplePipelineExample(SimplePipeline): + """ A very simple pipeline to show how registers are inferred. """ + + def __init__(self, pipe): + super(SimplePipelineExample, self).__init__(pipe) + self._loopback = Signal() + self._setup() + + def stage0(self): + n = Signal() + self.n = ~self._loopback + + def stage1(self): + self.n = self.n + + def stage2(self): + self.n = self.n + + def stage3(self): + self.n = self.n + + def stage4(self): + self._pipe.sync += self._loopback.eq(self.n) + +class PipeModule(Module): + def __init__(self): + Module.__init__(self) + +if __name__ == "__main__": + example = PipeModule() + pipe = SimplePipelineExample(example) + print(verilog.convert(example, + { + pipe._loopback, + }))