From: Luke Kenneth Casson Leighton Date: Fri, 29 Mar 2019 01:24:17 +0000 (+0000) Subject: new ObjectProxy class for use in pipelines X-Git-Tag: ls180-24jan2020~1408 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b5cc29bb05ba25c95c820e001e76e78bb56cd89a;p=ieee754fpu.git new ObjectProxy class for use in pipelines --- diff --git a/src/add/pipeline.py b/src/add/pipeline.py index 617fa896..fc5faa91 100644 --- a/src/add/pipeline.py +++ b/src/add/pipeline.py @@ -1,8 +1,13 @@ """ Example 5: Making use of PyRTL and Introspection. """ from nmigen import Signal +from nmigen.hdl.rec import Record +from nmigen import tracer from nmigen.compat.fhdl.bitcontainer import value_bits_sign +from singlepipe import eq + + # 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 @@ -10,7 +15,59 @@ from nmigen.compat.fhdl.bitcontainer import value_bits_sign # stages, and new members with names not starting with "_" are to be registered # for the next stage. -from singlepipe import eq + +class ObjectProxy: + def __init__(self, pipe, name=None): + self._pipe = pipe + if name is None: + name = tracer.get_var_name(default=None) + self.name = name + + @classmethod + def like(cls, pipe, value, name=None, src_loc_at=0, **kwargs): + name = name or tracer.get_var_name(depth=2 + src_loc_at, + default="$like") + + src_loc_at_1 = 1 + src_loc_at + r = ObjectProxy(pipe, value.name) + for a in value.ports(): + aname = a.name + setattr(r, aname, a) + return r + + def eq(self, i): + res = [] + for a in self.ports(): + aname = a.name + ai = getattr(i, aname) + res.append(a.eq(ai)) + return res + + def ports(self): + res = [] + for aname in dir(self): + a = getattr(self, aname) + if isinstance(a, Signal) or isinstance(a, ObjectProxy) or \ + isinstance(a, Record): + res.append(a) + return res + + def __setattr__(self, name, value): + if name.startswith('_') or name == 'name': + # do not do anything tricky with variables starting with '_' + object.__setattr__(self, name, value) + return + #rname = "%s_%s" % (self.name, name) + rname = name + if isinstance(value, ObjectProxy): + new_pipereg = ObjectProxy.like(self._pipe, value, + name=rname, reset_less=True) + else: + new_pipereg = Signal.like(value, name=rname, reset_less=True) + + object.__setattr__(self, name, new_pipereg) + self._pipe.sync += eq(new_pipereg, value) + class SimplePipeline(object): """ Pipeline builder with auto generation of pipeline registers. @@ -49,7 +106,11 @@ class SimplePipeline(object): rname = 'pipereg_' + pipereg_id + '_' + name #new_pipereg = Signal(value_bits_sign(value), name=rname, # reset_less=True) - new_pipereg = Signal.like(value, name=rname, reset_less = True) + if isinstance(value, ObjectProxy): + new_pipereg = ObjectProxy.like(self._pipe, value, + name=rname, reset_less = True) + else: + new_pipereg = Signal.like(value, name=rname, reset_less = True) if next_stage not in self._pipeline_register_map: self._pipeline_register_map[next_stage] = {} self._pipeline_register_map[next_stage][name] = new_pipereg diff --git a/src/add/pipeline_example.py b/src/add/pipeline_example.py index 590e1db6..44d453da 100644 --- a/src/add/pipeline_example.py +++ b/src/add/pipeline_example.py @@ -4,7 +4,7 @@ from nmigen import Module, Signal from nmigen.cli import main, verilog -from pipeline import SimplePipeline +from pipeline import SimplePipeline, ObjectProxy class SimplePipelineExample(SimplePipeline): @@ -13,24 +13,36 @@ class SimplePipelineExample(SimplePipeline): def __init__(self, pipe): SimplePipeline.__init__(self, pipe) self._loopback = Signal(4) + self._obj = ObjectProxy(pipe) + self._obj.a = Signal(4) + self._obj.b = Signal(4) self._setup() def stage0(self): self.n = ~self._loopback + self.o = self._obj def stage1(self): - self.n = self.n + 1 + self.n = self.n + self.o.a + self.o = self.o + self.o.a = self.n + self.o.b = self.o.b def stage2(self): localv = Signal(4) self._pipe.comb += localv.eq(2) self.n = self.n << localv + self.o = self.o + self.o.b = self.n + self.o.a + self.o.b def stage3(self): self.n = ~self.n + self.o = self.o + self.o.b = self.o.b + self.n def stage4(self): - self._pipe.sync += self._loopback.eq(self.n + 3) + self.o.b = self.o.b + self._pipe.sync += self._loopback.eq(self.n + 3 + self.o.b) class PipeModule: