From 4b4de22d0feff0c5b66c722c46bb6d3a39806fcd Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Mon, 18 Mar 2019 17:16:43 +0000 Subject: [PATCH] add combinatorial pipe example --- src/add/example_buf_pipe.py | 70 +++++++++++++++++++++++++++++++++++++ src/add/test_buf_pipe.py | 6 ++++ 2 files changed, 76 insertions(+) diff --git a/src/add/example_buf_pipe.py b/src/add/example_buf_pipe.py index 0f4fb20c..c0b8ff73 100644 --- a/src/add/example_buf_pipe.py +++ b/src/add/example_buf_pipe.py @@ -284,8 +284,78 @@ class ExampleBufPipe(BufferedPipeline): BufferedPipeline.__init__(self, ExampleStage) +class CombPipe: + """A simple pipeline stage containing combinational logic that can execute + completely in one clock cycle. + + Parameters: + ----------- + input_shape : int or tuple or None + the shape of ``input.data`` and ``comb_input`` + output_shape : int or tuple or None + the shape of ``output.data`` and ``comb_output`` + name : str + the name + + Attributes: + ----------- + input : StageInput + The pipeline input + output : StageOutput + The pipeline output + comb_input : Signal, input_shape + The input to the combinatorial logic + comb_output: Signal, output_shape + The output of the combinatorial logic + """ + + def __init__(self, stage): + self.stage = stage + self._data_valid = Signal() + # set up input and output IO ACK (prev/next ready/valid) + self.i = IOAckIn() + self.o = IOAckOut() + + # set up the input and output data + self.i.data = stage.ispec() # input type + self.r_data = stage.ispec() # input type + self.i.comb = stage.ispec() # input type + self.o.comb = stage.ospec() # output data + self.o.data = stage.ospec() # output type + self.o.data.name = "outdata" + + def elaborate(self, platform): + m = Module() + m.d.comb += eq(self.o.comb, self.stage.process(self.i.comb)) + m.d.comb += self.o.n_valid.eq(self._data_valid) + m.d.comb += self.o.p_ready.eq(~self._data_valid | self.i.n_ready) + m.d.sync += self._data_valid.eq(self.i.p_valid | \ + (~self.i.n_ready & self._data_valid)) + with m.If(self.i.p_valid & self.o.p_ready): + m.d.sync += eq(self.r_data, self.i.data) + m.d.comb += eq(self.i.comb, self.r_data) + m.d.comb += eq(self.o.data, self.o.comb) + return m + + def ports(self): + return [self.i.data, self.o.data] + + +class ExampleCombPipe(CombPipe): + """ an example of how to use the combinatorial pipeline. + """ + + def __init__(self): + CombPipe.__init__(self, ExampleStage) + + if __name__ == '__main__': dut = ExampleBufPipe() vl = rtlil.convert(dut, ports=dut.ports()) with open("test_bufpipe.il", "w") as f: f.write(vl) + + dut = ExampleCombPipe() + vl = rtlil.convert(dut, ports=dut.ports()) + with open("test_combpipe.il", "w") as f: + f.write(vl) diff --git a/src/add/test_buf_pipe.py b/src/add/test_buf_pipe.py index d5026b1b..3d140be4 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 ExampleCombPipe from example_buf_pipe import IOAckIn, IOAckOut from random import randint @@ -271,6 +272,11 @@ if __name__ == '__main__': test = Test3(dut) run_simulation(dut, [test.send, test.rcv], vcd_name="test_bufpipe3.vcd") + print ("test 3.5") + dut = ExampleCombPipe() + test = Test3(dut) + run_simulation(dut, [test.send, test.rcv], vcd_name="test_combpipe3.vcd") + print ("test 4") dut = ExampleBufPipe2() run_simulation(dut, testbench4(dut), vcd_name="test_bufpipe4.vcd") -- 2.30.2