From 4c847e8b366cf3c7923e74fccbab6210b2f33b54 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sat, 3 Aug 2019 06:17:26 +0100 Subject: [PATCH] add maskable in/out cancellable test --- src/nmutil/multipipe.py | 39 +++++++++++------- .../test/test_inout_unary_mux_cancel_pipe.py | 40 +++++++++++-------- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/nmutil/multipipe.py b/src/nmutil/multipipe.py index 3fc58e79..6c858cd8 100644 --- a/src/nmutil/multipipe.py +++ b/src/nmutil/multipipe.py @@ -26,7 +26,7 @@ from .iocontrol import NextControl, PrevControl class MultiInControlBase(Elaboratable): """ Common functions for Pipeline API """ - def __init__(self, in_multi=None, p_len=1): + def __init__(self, in_multi=None, p_len=1, maskmode=False): """ Multi-input Control class. Conforms to same API as ControlBase... mostly. has additional indices to the *multiple* input stages @@ -38,11 +38,13 @@ class MultiInControlBase(Elaboratable): * add data_o member to NextControl """ # set up input and output IO ACK (prev/next ready/valid) + maskwid = p_len if maskmode else 0 + print ("multi_in", maskwid, maskmode, p_len) p = [] for i in range(p_len): - p.append(PrevControl(in_multi)) + p.append(PrevControl(in_multi, maskwid=maskwid)) self.p = Array(p) - self.n = NextControl() + self.n = NextControl(maskwid=maskwid) def connect_to_next(self, nxt, p_idx=0): """ helper function to connect to the next stage data/valid/ready. @@ -89,7 +91,7 @@ class MultiInControlBase(Elaboratable): class MultiOutControlBase(Elaboratable): """ Common functions for Pipeline API """ - def __init__(self, n_len=1, in_multi=None): + def __init__(self, n_len=1, in_multi=None, maskmode=False): """ Multi-output Control class. Conforms to same API as ControlBase... mostly. has additional indices to the multiple *output* stages [MultiInControlBase has multiple *input* stages] @@ -103,10 +105,11 @@ class MultiOutControlBase(Elaboratable): """ # set up input and output IO ACK (prev/next ready/valid) - self.p = PrevControl(in_multi) + maskwid = n_len if maskmode else 0 + self.p = PrevControl(in_multi, maskwid=maskwid) n = [] for i in range(n_len): - n.append(NextControl()) + n.append(NextControl(maskwid=maskwid)) self.n = Array(n) def connect_to_next(self, nxt, n_idx=0): @@ -158,9 +161,10 @@ class CombMultiOutPipeline(MultiOutControlBase): n.data_o : stage output data array. shaped according to ospec """ - def __init__(self, stage, n_len, n_mux): - MultiOutControlBase.__init__(self, n_len=n_len) + def __init__(self, stage, n_len, n_mux, maskmode=False): + MultiOutControlBase.__init__(self, n_len=n_len, maskmode=maskmode) self.stage = stage + self.maskmode = maskmode self.n_mux = n_mux # set up the input and output data @@ -205,6 +209,8 @@ class CombMultiOutPipeline(MultiOutControlBase): m.d.comb += data_valid.eq(p_valid_i | \ (~self.n[muxid].ready_i & data_valid)) with m.If(pv): + if self.maskmode: + m.d.comb += self.n[muxid].mask_o.eq(self.p.mask_i) m.d.comb += eq(r_data, self.p.data_i) m.d.comb += eq(self.n[muxid].data_o, self.process(r_data)) @@ -226,9 +232,10 @@ class CombMultiInPipeline(MultiInControlBase): SYNCHRONOUSLY. """ - def __init__(self, stage, p_len, p_mux): - MultiInControlBase.__init__(self, p_len=p_len) + def __init__(self, stage, p_len, p_mux, maskmode=False): + MultiInControlBase.__init__(self, p_len=p_len, maskmode=maskmode) self.stage = stage + self.maskmode = maskmode self.p_mux = p_mux # set up the input and output data @@ -293,6 +300,8 @@ class CombMultiInPipeline(MultiInControlBase): m.d.comb += vr.eq(self.p[i].valid_i & self.p[i].ready_o) with m.If(vr): m.d.comb += eq(r_data[i], self.p[i].data_i) + if self.maskmode: + m.d.comb += self.n.mask_o.eq(self.p[i].mask_i) m.d.comb += eq(self.n.data_o, self.process(r_data[mid])) @@ -300,9 +309,10 @@ class CombMultiInPipeline(MultiInControlBase): class CombMuxOutPipe(CombMultiOutPipeline): - def __init__(self, stage, n_len): + def __init__(self, stage, n_len, maskmode=False): # HACK: stage is also the n-way multiplexer - CombMultiOutPipeline.__init__(self, stage, n_len=n_len, n_mux=stage) + CombMultiOutPipeline.__init__(self, stage, n_len=n_len, + n_mux=stage, maskmode=maskmode) # HACK: n-mux is also the stage... so set the muxid equal to input muxid print ("combmuxout", self.p.data_i.muxid) @@ -349,9 +359,10 @@ class PriorityCombMuxInPipe(CombMultiInPipeline): """ an example of how to use the combinatorial pipeline. """ - def __init__(self, stage, p_len=2): + def __init__(self, stage, p_len=2, maskmode=False): p_mux = InputPriorityArbiter(self, p_len) - CombMultiInPipeline.__init__(self, stage, p_len, p_mux) + CombMultiInPipeline.__init__(self, stage, p_len, p_mux, + maskmode=maskmode) if __name__ == '__main__': diff --git a/src/nmutil/test/test_inout_unary_mux_cancel_pipe.py b/src/nmutil/test/test_inout_unary_mux_cancel_pipe.py index 03fddde0..bde4fe98 100644 --- a/src/nmutil/test/test_inout_unary_mux_cancel_pipe.py +++ b/src/nmutil/test/test_inout_unary_mux_cancel_pipe.py @@ -1,5 +1,6 @@ """ key strategic example showing how to do multi-input fan-in into a - multi-stage pipeline, then multi-output fanout. + multi-stage pipeline, then multi-output fanout, with an unary muxid + and cancellation the multiplex ID from the fan-in is passed in to the pipeline, preserved, and used as a routing ID on the fanout. @@ -13,7 +14,7 @@ from nmigen.cli import verilog, rtlil from nmutil.multipipe import CombMultiOutPipeline, CombMuxOutPipe from nmutil.multipipe import PriorityCombMuxInPipe -from nmutil.singlepipe import SimpleHandshake, RecordObject, Object +from nmutil.singlepipe import MaskCancellable, RecordObject, Object class PassData2(RecordObject): @@ -44,9 +45,10 @@ class PassThroughStage: -class PassThroughPipe(SimpleHandshake): - def __init__(self): - SimpleHandshake.__init__(self, PassThroughStage()) +class PassThroughPipe(MaskCancellable): + def __init__(self, maskwid, cancelmask): + self.cancelmask = cancelmask + MaskCancellable.__init__(self, PassThroughStage(), maskwid) class InputTest: @@ -54,7 +56,7 @@ class InputTest: self.dut = dut self.di = {} self.do = {} - self.tlen = 100 + self.tlen = 10 for muxid in range(dut.num_rows): self.di[muxid] = {} self.do[muxid] = {} @@ -70,6 +72,7 @@ class InputTest: yield rs.data_i.data.eq(op2) yield rs.data_i.idx.eq(i) yield rs.data_i.muxid.eq(muxid) + yield rs.mask_i.eq(1<