From f7aa7270105a0e3eec01fa8dad558f9071127efb Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sat, 3 Aug 2019 02:06:22 +0100 Subject: [PATCH] mask sort-of working as long as "ready" is always true --- src/nmutil/singlepipe.py | 22 +++-- src/nmutil/test/test_buf_pipe.py | 160 +++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+), 7 deletions(-) diff --git a/src/nmutil/singlepipe.py b/src/nmutil/singlepipe.py index 37f6f101..600f0c53 100644 --- a/src/nmutil/singlepipe.py +++ b/src/nmutil/singlepipe.py @@ -128,7 +128,7 @@ https://github.com/ZipCPU/dbgbus/blob/master/hexbus/rtl/hbdeword.v """ -from nmigen import Signal, Mux, Module, Elaboratable +from nmigen import Signal, Mux, Module, Elaboratable, Const from nmigen.cli import verilog, rtlil from nmigen.hdl.rec import Record @@ -179,7 +179,7 @@ class ControlBase(StageHelper, Elaboratable): *BYPASSES* a ControlBase instance ready/valid signalling, which clearly should not be done without a really, really good reason. """ - def __init__(self, stage=None, in_multi=None, stage_ctl=False): + def __init__(self, stage=None, in_multi=None, stage_ctl=False, maskwid=0): """ Base class containing ready/valid/data to previous and next stages * p: contains ready/valid to the previous stage @@ -194,8 +194,8 @@ class ControlBase(StageHelper, Elaboratable): StageHelper.__init__(self, 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.p = PrevControl(in_multi, stage_ctl, maskwid=maskwid) + self.n = NextControl(stage_ctl, maskwid=maskwid) # set up the input and output data if stage is not None: @@ -415,6 +415,9 @@ class MaskCancellable(ControlBase): | | +--process->--^ """ + def __init__(self, stage, maskwid, in_multi=None, stage_ctl=False): + ControlBase.__init__(self, stage, in_multi, stage_ctl, maskwid) + def elaborate(self, platform): self.m = m = ControlBase.elaborate(self, platform) @@ -428,18 +431,23 @@ class MaskCancellable(ControlBase): # XXX EXCEPTIONAL CIRCUMSTANCES: inspection of the data payload # is NOT "normal" for the Stage API. p_valid_i = Signal(reset_less=True) - m.d.comb += p_valid_i.eq((self.p.data_i.ctx.idmask & \ - ~self.cancelmask).bool()) # nonzero + print ("self.p.data_i", self.p.data_i) + m.d.comb += p_valid_i.eq((self.p.mask_i.bool())) + #m.d.comb += p_valid_i.eq((self.p.data_i.ctx.idmask & \ + # ~self.cancelmask)) # nonzero # if idmask nonzero, data gets passed on. m.d.sync += self.n.valid_o.eq(p_valid_i) with m.If(p_valid_i): + m.d.sync += self.n.mask_o.eq(self.p.mask_i) data_o = self._postprocess(result) # XXX TBD, does nothing right now m.d.sync += nmoperator.eq(self.n.data_o, data_o) # update output + with m.Else(): + m.d.sync += self.n.mask_o.eq(0) # output valid if # input always "ready" - m.d.comb += self.p._ready_o.eq(1) + m.d.comb += self.p._ready_o.eq(Const(1)) return self.m diff --git a/src/nmutil/test/test_buf_pipe.py b/src/nmutil/test/test_buf_pipe.py index e27f382b..450852be 100644 --- a/src/nmutil/test/test_buf_pipe.py +++ b/src/nmutil/test/test_buf_pipe.py @@ -32,6 +32,7 @@ from nmutil.singlepipe import PassThroughHandshake from nmutil.singlepipe import PassThroughStage from nmutil.singlepipe import FIFOControl from nmutil.singlepipe import RecordObject +from nmutil.singlepipe import MaskCancellable from random import randint, seed @@ -254,6 +255,71 @@ class Test5: if self.o == len(self.data): break +class TestMask: + def __init__(self, dut, resultfn, maskwid, data=None, stage_ctl=False): + self.dut = dut + self.resultfn = resultfn + self.stage_ctl = stage_ctl + self.maskwid = maskwid + if data: + self.data = data + else: + self.data = [] + for i in range(num_tests): + self.data.append((randint(0, 1<<16-1), randint(0, 1<<16-1))) + self.i = 0 + self.o = 0 + + def send(self): + while self.o != len(self.data): + send_range = randint(0, 3) + for j in range(randint(1,10)): + if send_range == 0: + send = True + else: + send = randint(0, send_range) != 0 + #send = True + o_p_ready = yield self.dut.p.ready_o + if not o_p_ready: + yield + continue + if send and self.i != len(self.data): + print ("send", self.i, self.data[self.i]) + yield self.dut.p.valid_i.eq(1) + yield self.dut.p.mask_i.eq(1<