X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fieee754%2Fpipeline.py;fp=src%2Fieee754%2Fpipeline.py;h=2e57245920126fdd75c97b2c6fe4792f25e8ca43;hb=9d91ad05b8944ea652cfd4f050dbe6837e4332f8;hp=b1e3b0ba111b08eca8e0d5b17a172b0a8350041c;hpb=2e2db1ecc444223ff4d7094cb65613d8f9e795f0;p=ieee754fpu.git diff --git a/src/ieee754/pipeline.py b/src/ieee754/pipeline.py index b1e3b0ba..2e572459 100644 --- a/src/ieee754/pipeline.py +++ b/src/ieee754/pipeline.py @@ -1,7 +1,11 @@ # SPDX-License-Identifier: LGPL-2.1-or-later # See Notices.txt for copyright information +from abc import ABCMeta +from nmigen import Elaboratable + from nmutil.singlepipe import SimpleHandshake +import threading class PipelineSpec: @@ -27,18 +31,55 @@ class PipelineSpec: self.id_wid = id_width self.op_wid = op_wid self.opkls = opkls - self.pipekls = pipekls or SimpleHandshake + self.pipekls = pipekls or SimpleHandshakeRedir self.core_config = None self.fpformat = None self.n_comb_stages = None +# with many thanks to jsbueno on stackexchange for this one +# https://stackoverflow.com/questions/57273070/ + +class Meta(ABCMeta): + registry = {} + recursing = threading.local() + recursing.check = False + mlock = threading.Lock() + + def __call__(cls, *args, **kw): + mcls = cls.__class__ + if mcls.recursing.check: + return super().__call__(*args, **kw) + spec = args[0] + base = spec.pipekls + + if (cls, base) not in mcls.registry: + print ("__call__", args, kw, cls, base, base.__bases__, cls.__bases__) + mcls.registry[cls, base] = type( + cls.__name__, + (cls, base) + cls.__bases__[1:], + {} + ) + real_cls = mcls.registry[cls, base] + + with mcls.mlock: + mcls.recursing.check = True + instance = real_cls.__class__.__call__(real_cls, *args, **kw) + mcls.recursing.check = False + return instance + + +class DynamicPipe(metaclass=Meta): + def __init__(self, *args): + print ("DynamicPipe init", super(), args) + super().__init__(self, *args) + -def DynamicPipeCreate(pspec, *args, **kwargs): - superclass = pspec.pipekls - class DynamicPipe(superclass): - def __init__(self, *args, **kwargs): - print(superclass) - superclass.__init__(self, *args, **kwargs) - pass - return DynamicPipe(*args, **kwargs) +# bad hack: the DynamicPipe metaclass ends up creating an __init__ signature +# for the dynamically-derived class. luckily, SimpleHandshake only needs +# "self" as the 1st argument (it is its own "Stage"). anything else +# could hypothetically be passed through the pspec. +class SimpleHandshakeRedir(SimpleHandshake): + def __init__(self, pspec, *args): + print ("redir", pspec, args) + SimpleHandshake.__init__(self, self)