from nmigen import Module
from nmigen.cli import main, verilog
-from nmutil.singlepipe import (StageChain, SimpleHandshake,
- PassThroughStage)
+from nmutil.singlepipe import StageChain
+from ieee754.pipeline import DynamicPipe
from ieee754.fpcommon.fpbase import FPState
from ieee754.fpcommon.denorm import FPSCData
from ieee754.fpadd.add0 import FPAddStage0Mod
from ieee754.fpadd.add1 import FPAddStage1Mod
-
-class FPAddAlignSingleAdd(FPState, SimpleHandshake):
+class FPAddAlignSingleAdd(DynamicPipe):
def __init__(self, pspec):
- FPState.__init__(self, "align")
+ #FPState.__init__(self, "align")
self.pspec = pspec
- SimpleHandshake.__init__(self, self) # pipeline is its own stage
+ super().__init__(pspec)
self.a1o = self.ospec()
def ispec(self):
# 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:
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)
from nmutil.iocontrol import (PrevControl, NextControl, Object, RecordObject)
from nmutil.stageapi import (_spec, StageCls, Stage, StageChain, StageHelper)
from nmutil import nmoperator
-
+
class RecordBasedStage(Stage):
""" convenience class which provides a Records-based layout.
* add data_o member to NextControl (n)
Calling ControlBase._new_data is a good way to do that.
"""
+ print ("ControlBase", self, stage, in_multi, stage_ctl)
StageHelper.__init__(self, stage)
# set up input and output IO ACK (prev/next ready/valid)