From 47537cef175dc213da2bb76ddadbfd38d6bee619 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Mon, 18 Mar 2019 11:55:42 +0000 Subject: [PATCH] create helper functions to connect input to output on pipeline stages --- src/add/example_buf_pipe.py | 28 ++++++++++++ src/add/test_buf_pipe.py | 87 ++++++++++++++++--------------------- 2 files changed, 66 insertions(+), 49 deletions(-) diff --git a/src/add/example_buf_pipe.py b/src/add/example_buf_pipe.py index 45bed193..37cf38ba 100644 --- a/src/add/example_buf_pipe.py +++ b/src/add/example_buf_pipe.py @@ -127,7 +127,35 @@ class BufferedPipeline: self.o.data = stage.ospec() self.stage = stage + def connect_next(self, nxt): + """ helper function to connect the next stage data/valid/ready + """ + return [nxt.i.p_valid.eq(self.o.n_valid), + self.i.n_ready.eq(nxt.o.p_ready), + eq(nxt.i.data, self.o.data), + ] + + def connect_in(self, prev): + """ helper function to connect stage to an input source. do not + use to connect stage-to-stage! + """ + return [self.i.p_valid.eq(prev.i.p_valid), + prev.o.p_ready.eq(self.o.p_ready), + eq(self.i.data, prev.i.data), + ] + + def connect_out(self, nxt): + """ helper function to connect stage to an output source. do not + use to connect stage-to-stage! + """ + return [nxt.o.n_valid.eq(self.o.n_valid), + self.i.n_ready.eq(nxt.i.n_ready), + eq(nxt.o.data, self.o.data), + ] + def set_input(self, i): + """ helper function to set the input data + """ return eq(self.i.data, i) def update_buffer(self): diff --git a/src/add/test_buf_pipe.py b/src/add/test_buf_pipe.py index 0b23d637..d5026b1b 100644 --- a/src/add/test_buf_pipe.py +++ b/src/add/test_buf_pipe.py @@ -1,6 +1,7 @@ from nmigen import Module, Signal from nmigen.compat.sim import run_simulation from example_buf_pipe import ExampleBufPipe, ExampleBufPipeAdd +from example_buf_pipe import IOAckIn, IOAckOut from random import randint @@ -8,10 +9,6 @@ def check_o_n_valid(dut, val): o_n_valid = yield dut.o.n_valid assert o_n_valid == val -def check_o_n_valid2(dut, val): - o_n_valid = yield dut.o_n_valid - assert o_n_valid == val - def testbench(dut): #yield dut.i_p_rst.eq(1) @@ -51,40 +48,40 @@ def testbench(dut): def testbench2(dut): #yield dut.i.p_rst.eq(1) - yield dut.i_n_ready.eq(0) + yield dut.i.n_ready.eq(0) #yield dut.o.p_ready.eq(0) yield yield #yield dut.i.p_rst.eq(0) - yield dut.i_n_ready.eq(1) - yield dut.i_data.eq(5) - yield dut.i_p_valid.eq(1) + yield dut.i.n_ready.eq(1) + yield dut.i.data.eq(5) + yield dut.i.p_valid.eq(1) yield - yield dut.i_data.eq(7) - yield from check_o_n_valid2(dut, 0) # effects of i_p_valid delayed 2 clocks + yield dut.i.data.eq(7) + yield from check_o_n_valid(dut, 0) # effects of i_p_valid delayed 2 clocks yield - yield from check_o_n_valid2(dut, 0) # effects of i_p_valid delayed 2 clocks + yield from check_o_n_valid(dut, 0) # effects of i_p_valid delayed 2 clocks - yield dut.i_data.eq(2) + yield dut.i.data.eq(2) yield - yield from check_o_n_valid2(dut, 1) # ok *now* i_p_valid effect is felt - yield dut.i_n_ready.eq(0) # begin going into "stall" (next stage says ready) - yield dut.i_data.eq(9) + yield from check_o_n_valid(dut, 1) # ok *now* i_p_valid effect is felt + yield dut.i.n_ready.eq(0) # begin going into "stall" (next stage says ready) + yield dut.i.data.eq(9) yield - yield dut.i_p_valid.eq(0) - yield dut.i_data.eq(12) + yield dut.i.p_valid.eq(0) + yield dut.i.data.eq(12) yield - yield dut.i_data.eq(32) - yield dut.i_n_ready.eq(1) + yield dut.i.data.eq(32) + yield dut.i.n_ready.eq(1) yield - yield from check_o_n_valid2(dut, 1) # buffer still needs to output + yield from check_o_n_valid(dut, 1) # buffer still needs to output yield - yield from check_o_n_valid2(dut, 1) # buffer still needs to output + yield from check_o_n_valid(dut, 1) # buffer still needs to output yield - yield from check_o_n_valid2(dut, 1) # buffer still needs to output + yield from check_o_n_valid(dut, 1) # buffer still needs to output yield - yield from check_o_n_valid2(dut, 0) # buffer outputted, *now* we're done. + yield from check_o_n_valid(dut, 0) # buffer outputted, *now* we're done. yield yield yield @@ -201,20 +198,20 @@ def testbench4(dut): while True: stall = randint(0, 3) != 0 send = randint(0, 5) != 0 - yield dut.i_n_ready.eq(stall) - o_p_ready = yield dut.o_p_ready + yield dut.i.n_ready.eq(stall) + o_p_ready = yield dut.o.p_ready if o_p_ready: if send and i != len(data): - yield dut.i_p_valid.eq(1) - yield dut.i_data.eq(data[i]) + yield dut.i.p_valid.eq(1) + yield dut.i.data.eq(data[i]) i += 1 else: - yield dut.i_p_valid.eq(0) + yield dut.i.p_valid.eq(0) yield - o_n_valid = yield dut.o_n_valid - i_n_ready = yield dut.i_n_ready + o_n_valid = yield dut.o.n_valid + i_n_ready = yield dut.i.n_ready if o_n_valid and i_n_ready: - o_data = yield dut.o_data + o_data = yield dut.o.data assert o_data == data[o] + 2, "%d-%d data %x not match %x\n" \ % (i, o, o_data, data[o]) o += 1 @@ -226,23 +223,21 @@ class ExampleBufPipe2: """ connect these: ------|---------------| v v - i_p_valid >>in pipe1 o_n_valid out>> i_p_valid >>in pipe2 + i_p_valid >>in pipe1 o_n_valid out>> i_p_valid >>in pipe2 o_p_ready <>in pipe1 o_data out>> i_data >>in pipe2 + i_data >>in pipe1 o_data out>> i_data >>in pipe2 """ def __init__(self): self.pipe1 = ExampleBufPipe() self.pipe2 = ExampleBufPipe() # input - self.i_p_valid = Signal() # >>in - comes in from PREVIOUS stage - self.i_n_ready = Signal() # in<< - comes in from the NEXT stage - self.i_data = Signal(32) # >>in - comes in from the PREVIOUS stage + self.i = IOAckIn() + self.i.data = Signal(32) # >>in - comes in from the PREVIOUS stage # output - self.o_n_valid = Signal() # out>> - goes out to the NEXT stage - self.o_p_ready = Signal() # <> - goes out to the NEXT stage + self.o = IOAckOut() + self.o.data = Signal(32) # out>> - goes out to the NEXT stage def elaborate(self, platform): m = Module() @@ -250,23 +245,17 @@ class ExampleBufPipe2: m.submodules.pipe2 = self.pipe2 # connect inter-pipe input/output valid/ready/data - m.d.comb += self.pipe2.i.p_valid.eq(self.pipe1.o.n_valid) - m.d.comb += self.pipe1.i.n_ready.eq(self.pipe2.o.p_ready) - m.d.comb += self.pipe2.i.data.eq(self.pipe1.o.data) + m.d.comb += self.pipe1.connect_next(self.pipe2) # inputs/outputs to the module: pipe1 connections here (LHS) - m.d.comb += self.pipe1.i.p_valid.eq(self.i_p_valid) - m.d.comb += self.o_p_ready.eq(self.pipe1.o.p_ready) - m.d.comb += self.pipe1.i.data.eq(self.i_data) + m.d.comb += self.pipe1.connect_in(self) # now pipe2 connections (RHS) - m.d.comb += self.o_n_valid.eq(self.pipe2.o.n_valid) - m.d.comb += self.pipe2.i.n_ready.eq(self.i_n_ready) - m.d.comb += self.o_data.eq(self.pipe2.o.data) + m.d.comb += self.pipe2.connect_out(self) return m -num_tests = 10000 +num_tests = 1000 if __name__ == '__main__': print ("test 1") -- 2.30.2