o = self.chain[idx].ospec() # only the last assignment survives
m.d.comb += eq(o, c.process(i)) # process input into "o"
if idx != len(self.chain)-1:
- i = self.chain[idx+1] # becomes new input on next loop
- self.o = o # last loop is the output
+ ni = self.chain[idx+1].ispec() # becomes new input on next loop
+ m.d.comb += eq(ni, o) # assign output to next input
+ i = ni
+ self.o = o # last loop is the output
def process(self, i):
return self.o
return i + 1
+class ExampleStageCls:
+ """ an example of how to use the buffered pipeline, in a static class
+ fashion
+ """
+
+ def ispec(self):
+ return Signal(16, name="example_input_signal")
+
+ def ospec(self):
+ return Signal(16, name="example_output_signal")
+
+ def process(self, i):
+ """ process the input data and returns it (adds 1)
+ """
+ return i + 1
+
+
class ExampleBufPipe(BufferedPipeline):
""" an example of how to use the buffered pipeline.
"""
from nmigen.cli import verilog, rtlil
from example_buf_pipe import ExampleBufPipe, ExampleBufPipeAdd
-from example_buf_pipe import ExampleCombPipe, CombPipe
+from example_buf_pipe import ExampleCombPipe, CombPipe, ExampleStageCls
from example_buf_pipe import PrevControl, NextControl, BufferedPipeline
+from example_buf_pipe import StageChain
+
from random import randint
return m
+
+class ExampleBufPipeChain2(BufferedPipeline):
+ """ connects two stages together as a *single* combinatorial stage.
+ """
+ def __init__(self):
+ stage1 = ExampleStageCls()
+ stage2 = ExampleStageCls()
+ combined = StageChain([stage1, stage2])
+ BufferedPipeline.__init__(self, combined)
+
+
+def data_chain2():
+ data = []
+ for i in range(num_tests):
+ data.append(randint(0, 1<<16-2))
+ return data
+
+
+def test9_resultfn(o_data, expected, i, o):
+ res = expected + 2
+ assert o_data == res, \
+ "%d-%d data %x not match %s\n" \
+ % (i, o, o_data, repr(expected))
+
+
class SetLessThan:
def __init__(self, width, signed):
self.src1 = Signal((width, signed))
class TestInputAdd:
+ """ the eq function, called by set_input, needs an incoming object
+ that conforms to the Example2OpClass.eq function requirements
+ easiest way to do that is to create a class that has the exact
+ same member layout (self.op1, self.op2) as Example2OpClass
+ """
def __init__(self, op1, op2):
self.op1 = op1
self.op2 = op2
def test8_resultfn(o_data, expected, i, o):
- res = expected.op1 + expected.op2
+ res = expected.op1 + expected.op2 # these are a TestInputAdd instance
assert o_data == res, \
"%d-%d data %x not match %s\n" \
% (i, o, o_data, repr(expected))
test = Test5(dut, test8_resultfn, data=data)
run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe8.vcd")
+ print ("test 9")
+ dut = ExampleBufPipeChain2()
+ ports = [dut.p.i_valid, dut.n.i_ready,
+ dut.n.o_valid, dut.p.o_ready] + \
+ [dut.p.i_data] + [dut.n.o_data]
+ vl = rtlil.convert(dut, ports=ports)
+ with open("test_bufpipechain2.il", "w") as f:
+ f.write(vl)
+
+ data = data_chain2()
+ test = Test5(dut, test9_resultfn, data=data)
+ run_simulation(dut, [test.send, test.rcv],
+ vcd_name="test_bufpipechain2.vcd")
+