return self.o # conform to Stage API: return last-loop output
-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
+class StageHandler(Elaboratable):
+ """ Stage handling class
"""
- 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)
+ def __init__(self, ctrl, stage):
+ """
+ """
+ if stage is not None:
+ self.new_data(self, self, "data")
- def setup(self, m, i):
- if self.stage is None or not hasattr(self.stage, "setup"):
- return
- self.stage.setup(m, i)
+ @property
+ def data_r(self):
+ return self.stage.process(self.p.data_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
"""
- return (_spec(p.stage.ispec, "%s_i" % name),
- _spec(n.stage.ospec, "%s_o" % name))
+ 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
+ if self.stage is not None and hasattr(self.stage, "setup"):
+ self.stage.setup(m, self.p.data_i)
-class ControlBase(StageHandler, Elaboratable):
+ 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):
""" 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)
- 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)
+ StageHandler.__init__(self, self, stage)
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.sh.ospec, "r_tmp")
- r_data = _spec(self.sh.ospec, "r_data")
+ result = _spec(self.stage.ospec, "r_tmp")
+ r_data = _spec(self.stage.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.sh.ospec, "r_tmp")
+ result = _spec(self.stage.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.sh.ospec, "r_tmp") # output type
+ r_data = _spec(self.stage.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.sh.ospec, "r_tmp") # output type
+ buf = _spec(self.stage.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.sh.ospec, "r_tmp") # output type
+ r_data = _spec(self.stage.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.sh.ospec, "r_temp")
+ result = _spec(self.stage.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):
- self.stage = ExampleStageDelayCls(valid_trigger=2)
- BufferedHandshake.__init__(self, self.stage, stage_ctl=True)
+ stage = ExampleStageDelayCls(valid_trigger=2)
+ BufferedHandshake.__init__(self, stage, stage_ctl=True)
def elaborate(self, platform):
m = BufferedHandshake.elaborate(self, platform)
class ExampleUnBufDelayedPipe(BufferedHandshake):
def __init__(self):
- self.stage = ExampleStageDelayCls(valid_trigger=3)
- BufferedHandshake.__init__(self, self.stage, stage_ctl=True)
+ stage = ExampleStageDelayCls(valid_trigger=3)
+ BufferedHandshake.__init__(self, stage, stage_ctl=True)
def elaborate(self, platform):
m = BufferedHandshake.elaborate(self, platform)