1 # SPDX-License-Identifier: LGPL-2.1-or-later
2 # See Notices.txt for copyright information
4 from abc
import ABCMeta
5 from nmigen
import Elaboratable
7 from nmutil
.singlepipe
import SimpleHandshake
12 """ Pipeline Specification base class.
14 :attribute width: the IEEE754 FP bitwidth
15 :attribute id_wid: the Reservation Station muxid bitwidth
16 :attribute op_wid: an "operand bitwidth" passed down all stages
17 :attribute opkls: an optional class that is instantiated as the "operand"
19 See ieee754/fpcommon/getop FPPipeContext for how (where) PipelineSpec
20 is used. FPPipeContext is passed down *every* stage of a pipeline
21 and contains the Reservation Station multiplexer ID as well as
22 an optional "operand". This "operand" may be used to *change*
23 the behaviour of the pipeline. In RISC-V terminology it would
24 typically be set to e.g. funct7 or parts thereof.
28 def __init__(self
, width
, id_width
, op_wid
=0, opkls
=None, pipekls
=None):
29 """ Create a PipelineSpec. """
31 self
.id_wid
= id_width
34 self
.pipekls
= pipekls
or SimpleHandshakeRedir
35 self
.core_config
= None
37 self
.n_comb_stages
= None
39 # with many thanks to jsbueno on stackexchange for this one
40 # https://stackoverflow.com/questions/57273070/
44 recursing
= threading
.local()
45 recursing
.check
= False
46 mlock
= threading
.Lock()
48 def __call__(cls
, *args
, **kw
):
50 if mcls
.recursing
.check
:
51 return super().__call
__(*args
, **kw
)
55 if (cls
, base
) not in mcls
.registry
:
56 print ("__call__", args
, kw
, cls
, base
, base
.__bases
__, cls
.__bases
__)
57 mcls
.registry
[cls
, base
] = type(
59 (cls
, base
) + cls
.__bases
__[1:],
62 real_cls
= mcls
.registry
[cls
, base
]
65 mcls
.recursing
.check
= True
66 instance
= real_cls
.__class
__.__call
__(real_cls
, *args
, **kw
)
67 mcls
.recursing
.check
= False
71 class DynamicPipe(metaclass
=Meta
):
72 def __init__(self
, *args
):
73 print ("DynamicPipe init", super(), args
)
74 super().__init
__(self
, *args
)
77 # bad hack: the DynamicPipe metaclass ends up creating an __init__ signature
78 # for the dynamically-derived class. luckily, SimpleHandshake only needs
79 # "self" as the 1st argument (it is its own "Stage"). anything else
80 # could hypothetically be passed through the pspec.
81 class SimpleHandshakeRedir(SimpleHandshake
):
82 def __init__(self
, pspec
, *args
):
83 print ("redir", pspec
, args
)
84 SimpleHandshake
.__init
__(self
, self
)