From caa4f0c699f07af415fd347d323d0926b08b7564 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Mon, 29 Apr 2019 03:16:36 +0100 Subject: [PATCH] Revert "move wrapping of stage into StageHandler" This reverts commit 2b26be5b974d43047bf096a555408a62bab2c4eb. --- src/add/iocontrol.py | 87 ++++++++++++++++++---------------------- src/add/singlepipe.py | 14 +++---- src/add/test_buf_pipe.py | 8 ++-- 3 files changed, 49 insertions(+), 60 deletions(-) diff --git a/src/add/iocontrol.py b/src/add/iocontrol.py index 423694b9..dfa04797 100644 --- a/src/add/iocontrol.py +++ b/src/add/iocontrol.py @@ -436,19 +436,18 @@ class StageChain(StageCls): 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 @@ -459,11 +458,33 @@ class StageHandler: # (Elaboratable): 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) @@ -478,22 +499,13 @@ class ControlBase(StageHandler, Elaboratable): * 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. @@ -570,29 +582,6 @@ class ControlBase(StageHandler, Elaboratable): 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 """ diff --git a/src/add/singlepipe.py b/src/add/singlepipe.py index 5be2d919..5f7dc66b 100644 --- a/src/add/singlepipe.py +++ b/src/add/singlepipe.py @@ -184,8 +184,8 @@ class BufferedHandshake(ControlBase): 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) @@ -280,7 +280,7 @@ class SimpleHandshake(ControlBase): 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") @@ -388,7 +388,7 @@ class UnbufferedPipeline(ControlBase): 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) @@ -474,7 +474,7 @@ class UnbufferedPipeline2(ControlBase): 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) @@ -543,7 +543,7 @@ class PassThroughHandshake(ControlBase): 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) @@ -621,7 +621,7 @@ class FIFOControl(ControlBase): 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 diff --git a/src/add/test_buf_pipe.py b/src/add/test_buf_pipe.py index 1408164a..7155c908 100644 --- a/src/add/test_buf_pipe.py +++ b/src/add/test_buf_pipe.py @@ -635,8 +635,8 @@ class ExampleStageDelayCls(StageCls, Elaboratable): 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) @@ -667,8 +667,8 @@ def resultfn_12(data_o, expected, i, o): 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) -- 2.30.2