reorganise MultiOutPipe, seems to be near-identical to UnbufferedPipeline
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 27 Mar 2019 14:54:57 +0000 (14:54 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 27 Mar 2019 14:54:57 +0000 (14:54 +0000)
src/add/multipipe.py
src/add/test_outmux_pipe.py

index af52ad9c450439cc45f90319370672338b481f13..f0c9aeacd34d97761da25fe27ba8794edf7b29e2 100644 (file)
@@ -156,42 +156,27 @@ class CombMultiOutPipeline(MultiOutControlBase):
     def elaborate(self, platform):
         m = Module()
 
-        #m.submodules += self.n_mux
+        if hasattr(self.n_mux, "elaborate"): # TODO: identify submodule?
+            m.submodules += self.n_mux
 
         # need buffer register conforming to *input* spec
         r_data = self.stage.ispec() # input type
         if hasattr(self.stage, "setup"):
             self.stage.setup(m, r_data)
 
-        data_valid = []
-        n_i_readyn = []
-        n_len = len(self.n)
-        for i in range(n_len):
-            data_valid.append(Signal(name="data_valid", reset_less=True))
-            n_i_readyn.append(Signal(name="n_i_readyn", reset_less=True))
-        n_i_readyn = Array(n_i_readyn)
-        data_valid = Array(data_valid)
+        mid = self.n_mux.m_id
 
+        data_valid = Signal() # is data valid or not
         p_i_valid = Signal(reset_less=True)
         m.d.comb += p_i_valid.eq(self.p.i_valid_logic())
 
-        mid = self.n_mux.m_id
-
-        for i in range(n_len):
-            m.d.comb += data_valid[i].eq(0)
-            m.d.comb += n_i_readyn[i].eq(1)
+        for i in range(len(self.n)):
             m.d.comb += self.n[i].o_valid.eq(0)
-        m.d.comb += self.n[mid].o_valid.eq(data_valid[mid])
-        m.d.comb += n_i_readyn[mid].eq(~self.n[mid].i_ready & data_valid[mid])
-        anyvalid = Signal(i, reset_less=True)
-        av = []
-        for i in range(n_len):
-            av.append(~data_valid[i] | self.n[i].i_ready)
-        anyvalid = Cat(*av)
-        m.d.comb += self.p.o_ready.eq(anyvalid.bool())
-        m.d.comb += data_valid[mid].eq(p_i_valid | \
-                                    (n_i_readyn[mid] & data_valid[mid]))
-
+        data_valid = self.n[mid].o_valid
+        #m.d.comb += self.n[mid].o_valid.eq(data_valid)
+        m.d.comb += self.p.o_ready.eq(~data_valid | self.n[mid].i_ready)
+        m.d.comb += data_valid.eq(p_i_valid | \
+                                    (~self.n[mid].i_ready & data_valid))
         with m.If(self.p.i_valid & self.p.o_ready):
             m.d.comb += eq(r_data, self.p.i_data)
         m.d.comb += eq(self.n[mid].o_data, self.stage.process(r_data))
index a95d2d6847bd37734a7bf982ee20384c2bc27a9e..837a1eb25683d8026a010b3a31f3cb5a2f296243 100644 (file)
@@ -142,9 +142,12 @@ class OutputTest:
         self.dut = dut
         self.di = []
         self.do = {}
-        self.tlen = 3
+        self.tlen = 10
         for i in range(self.tlen * dut.num_rows):
-            mid = randint(0, dut.num_rows-1)
+            if i < dut.num_rows:
+                mid = i
+            else:
+                mid = randint(0, dut.num_rows-1)
             data = randint(0, 255) + (mid<<8)
             if mid not in self.do:
                 self.do[mid] = []
@@ -177,15 +180,10 @@ class OutputTest:
     def rcv(self, mid):
         out_i = 0
         count = 0
-        while out_i != self.tlen:
+        stall_range = randint(0, 3)
+        while out_i != len(self.do[mid]):
             count += 1
-            if count == 1000:
-                break
-            #stall_range = randint(0, 3)
-            #for j in range(randint(1,10)):
-            #    stall = randint(0, stall_range) != 0
-            #    yield self.dut.n[0].i_ready.eq(stall)
-            #    yield
+            assert count != 2000, "timeout: too long"
             n = self.dut.n[mid]
             yield n.i_ready.eq(1)
             yield
@@ -202,6 +200,14 @@ class OutputTest:
 
             out_i += 1
 
+            if randint(0, 5) == 0:
+                stall_range = randint(0, 3)
+            stall = randint(0, stall_range) != 0
+            if stall:
+                yield n.i_ready.eq(0)
+                for i in range(stall_range):
+                    yield
+
 
 class TestPriorityMuxPipe(MuxUnbufferedPipeline):
     def __init__(self):