return self.o # conform to Stage API: return last-loop output
-class StageHandler(Elaboratable):
- """ Stage handling class
+class StageHandler: # (Elaboratable):
+ """ Stage handling (wrapper) class: makes e.g. static classes "real"
+ (instances) and provides a way to allocate data_i and data_o
"""
- def __init__(self, ctrl, stage):
- """
- """
- if stage is not None:
- self.new_data(self, self, "data")
+ def __init__(self, stage): self.stage = stage
+ def ispec(self, name): return _spec(self.stage.ispec, name)
+ def ospec(self, name): return _spec(self.stage.ospec, name)
+ def process(self, i): return self.stage.process(i)
- @property
- def data_r(self):
- return self.stage.process(self.p.data_i)
+ def setup(self, m, i):
+ if self.stage is None or not hasattr(self.stage, "setup"):
+ return
+ self.stage.setup(m, i)
def _postprocess(self, i): # XXX DISABLED
return i # RETURNS INPUT
def new_data(self, p, n, name):
""" allocates new data_i and data_o
"""
- self.p.data_i = _spec(p.stage.ispec, "%s_i" % name)
- self.n.data_o = _spec(n.stage.ospec, "%s_o" % name)
-
- def elaborate(self, platform):
- """ handles case where stage has dynamic ready/valid functions
- """
- m = Module()
- m.submodules.p = self.p
- m.submodules.n = self.n
+ return (_spec(p.stage.ispec, "%s_i" % name),
+ _spec(n.stage.ospec, "%s_o" % name))
- if self.stage is not None and hasattr(self.stage, "setup"):
- self.stage.setup(m, self.p.data_i)
- if not self.p.stage_ctl:
- return m
-
- # intercept the previous (outgoing) "ready", combine with stage ready
- m.d.comb += self.p.s_ready_o.eq(self.p._ready_o & self.stage.d_ready)
-
- # intercept the next (incoming) "ready" and combine it with data valid
- sdv = self.stage.d_valid(self.n.ready_i)
- m.d.comb += self.n.d_valid.eq(self.n.ready_i & sdv)
-
- return m
-
-
-class ControlBase(StageHandler):
+class ControlBase(StageHandler, Elaboratable):
""" Common functions for Pipeline API. Note: a "pipeline stage" only
exists (conceptually) when a ControlBase derivative is handed
a Stage (combinatorial block)
* add data_i member to PrevControl (p) and
* add data_o member to NextControl (n)
"""
- self.stage = stage
-
# set up input and output IO ACK (prev/next ready/valid)
self.p = PrevControl(in_multi, stage_ctl)
self.n = NextControl(stage_ctl)
- StageHandler.__init__(self, self, stage)
+ self.sh = StageHandler(stage)
+ if stage is not None:
+ self.new_data(self, self, "data")
+
+ def new_data(self, p, n, name):
+ """ allocates new data_i and data_o
+ """
+ self.p.data_i, self.n.data_o = self.sh.new_data(p.sh, n.sh, name)
+
+ @property
+ def data_r(self):
+ return self.sh.process(self.p.data_i)
def connect_to_next(self, nxt):
""" helper function to connect to the next stage data/valid/ready.
return eqs
+ def elaborate(self, platform):
+ """ handles case where stage has dynamic ready/valid functions
+ """
+ m = Module()
+ m.submodules.p = self.p
+ m.submodules.n = self.n
+
+ self.sh.setup(m, self.p.data_i)
+
+ if not self.p.stage_ctl:
+ return m
+
+ stage = self.sh.stage
+
+ # intercept the previous (outgoing) "ready", combine with stage ready
+ m.d.comb += self.p.s_ready_o.eq(self.p._ready_o & stage.d_ready)
+
+ # intercept the next (incoming) "ready" and combine it with data valid
+ sdv = stage.d_valid(self.n.ready_i)
+ m.d.comb += self.n.d_valid.eq(self.n.ready_i & sdv)
+
+ return m
+
def set_input(self, i):
""" helper function to set the input data
"""
def elaborate(self, platform):
self.m = ControlBase.elaborate(self, platform)
- result = _spec(self.stage.ospec, "r_tmp")
- r_data = _spec(self.stage.ospec, "r_data")
+ result = _spec(self.sh.ospec, "r_tmp")
+ r_data = _spec(self.sh.ospec, "r_data")
# establish some combinatorial temporaries
o_n_validn = Signal(reset_less=True)
self.m = m = ControlBase.elaborate(self, platform)
r_busy = Signal()
- result = _spec(self.stage.ospec, "r_tmp")
+ result = _spec(self.sh.ospec, "r_tmp")
# establish some combinatorial temporaries
n_ready_i = Signal(reset_less=True, name="n_i_rdy_data")
self.m = m = ControlBase.elaborate(self, platform)
data_valid = Signal() # is data valid or not
- r_data = _spec(self.stage.ospec, "r_tmp") # output type
+ r_data = _spec(self.sh.ospec, "r_tmp") # output type
# some temporaries
p_valid_i = Signal(reset_less=True)
self.m = m = ControlBase.elaborate(self, platform)
buf_full = Signal() # is data valid or not
- buf = _spec(self.stage.ospec, "r_tmp") # output type
+ buf = _spec(self.sh.ospec, "r_tmp") # output type
# some temporaries
p_valid_i = Signal(reset_less=True)
def elaborate(self, platform):
self.m = m = ControlBase.elaborate(self, platform)
- r_data = _spec(self.stage.ospec, "r_tmp") # output type
+ r_data = _spec(self.sh.ospec, "r_tmp") # output type
# temporaries
p_valid_i = Signal(reset_less=True)
m.submodules.fifo = fifo
# store result of processing in combinatorial temporary
- result = _spec(self.stage.ospec, "r_temp")
+ result = _spec(self.sh.ospec, "r_temp")
m.d.comb += nmoperator.eq(result, self.data_r)
# connect previous rdy/valid/data - do cat on data_i
class ExampleBufDelayedPipe(BufferedHandshake):
def __init__(self):
- stage = ExampleStageDelayCls(valid_trigger=2)
- BufferedHandshake.__init__(self, stage, stage_ctl=True)
+ self.stage = ExampleStageDelayCls(valid_trigger=2)
+ BufferedHandshake.__init__(self, self.stage, stage_ctl=True)
def elaborate(self, platform):
m = BufferedHandshake.elaborate(self, platform)
class ExampleUnBufDelayedPipe(BufferedHandshake):
def __init__(self):
- stage = ExampleStageDelayCls(valid_trigger=3)
- BufferedHandshake.__init__(self, stage, stage_ctl=True)
+ self.stage = ExampleStageDelayCls(valid_trigger=3)
+ BufferedHandshake.__init__(self, self.stage, stage_ctl=True)
def elaborate(self, platform):
m = BufferedHandshake.elaborate(self, platform)