""" Stage API
Associated development bugs:
+ * http://bugs.libre-riscv.org/show_bug.cgi?id=148
* http://bugs.libre-riscv.org/show_bug.cgi?id=64
* http://bugs.libre-riscv.org/show_bug.cgi?id=57
all the optional bits.
"""
+from nmigen import Elaboratable
from abc import ABCMeta, abstractmethod
import inspect
if stage is not None:
self.set_specs(self, self)
- def ospec(self, name):
+ def ospec(self, name=None):
assert self._ospecfn is not None
return _spec(self._ospecfn, name)
- def ispec(self, name):
+ def ispec(self, name=None):
assert self._ispecfn is not None
return _spec(self._ispecfn, name)
class StageChain(StageHelper):
- """ pass in a list of stages, and they will automatically be
- chained together via their input and output specs into a
- combinatorial chain, to create one giant combinatorial block.
+ """ pass in a list of stages (combinatorial blocks), and they will
+ automatically be chained together via their input and output specs
+ into a combinatorial chain, to create one giant combinatorial
+ block.
- the end result basically conforms to the exact same Stage API.
+ the end result conforms to the exact same Stage API.
* input to this class will be the input of the first stage
* output of first stage goes into input of second
NOTE: whilst this is very similar to ControlBase.connect(), it is
*really* important to appreciate that StageChain is pure
combinatorial and bypasses (does not involve, at all, ready/valid
- signalling of any kind).
+ signalling OF ANY KIND).
ControlBase.connect on the other hand respects, connects, and uses
ready/valid signalling.
"driving from two sources, module is being flattened"
will be issued.
- NOTE: do NOT use StageChain with combinatorial blocks that have
+ NOTE: DO NOT use StageChain with combinatorial blocks that have
side-effects (state-based / clock-based input) or conditional
(inter-chain) dependencies, unless you really know what you are doing.
"""
assert len(chain) > 0, "stage chain must be non-zero length"
self.chain = chain
StageHelper.__init__(self, None)
- self.setup = self._sa_setup if specallocate else self._na_setup
+ if specallocate:
+ self.setup = self._sa_setup
+ else:
+ self.setup = self._na_setup
self.set_specs(self.chain[0], self.chain[-1])
def _sa_setup(self, m, i):
if hasattr(c, "setup"):
c.setup(m, i) # stage may have some module stuff
ofn = self.chain[idx].ospec # last assignment survives
- o = _spec(ofn, 'chainin%d' % idx)
+ cname = 'chainin%d' % idx
+ o = _spec(ofn, cname)
+ if isinstance(o, Elaboratable):
+ setattr(m.submodules, cname, o)
m.d.comb += nmoperator.eq(o, c.process(i)) # process input into "o"
if idx == len(self.chain)-1:
break