X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fieee754%2Fpipeline.py;h=2e57245920126fdd75c97b2c6fe4792f25e8ca43;hb=9d91ad05b8944ea652cfd4f050dbe6837e4332f8;hp=f914e978b34e9f1e273ffd5559d287137946e8b2;hpb=c574ea5ba019f0df2d16368447918f4427bf1c69;p=ieee754fpu.git diff --git a/src/ieee754/pipeline.py b/src/ieee754/pipeline.py index f914e978..2e572459 100644 --- a/src/ieee754/pipeline.py +++ b/src/ieee754/pipeline.py @@ -1,6 +1,12 @@ # 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: """ Pipeline Specification base class. @@ -19,9 +25,61 @@ class PipelineSpec: """ - def __init__(self, width, id_width, op_wid=0, opkls=None): + def __init__(self, width, id_width, op_wid=0, opkls=None, pipekls=None): """ Create a PipelineSpec. """ self.width = width self.id_wid = id_width self.op_wid = op_wid self.opkls = opkls + 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) + + +# 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) +