X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fadd%2Fexample_buf_pipe.py;h=8b9c74f78f8abc4ef1be278e374eb6e024cfa55f;hb=25357c032b55274ce620a331ecc1dc0874f5fdac;hp=51c95520c46a12d2703fa09c3e500ca6f2e72d84;hpb=837eb17472ba4f9cc43f47d0939415a6b9ad61ab;p=ieee754fpu.git diff --git a/src/add/example_buf_pipe.py b/src/add/example_buf_pipe.py index 51c95520..8b9c74f7 100644 --- a/src/add/example_buf_pipe.py +++ b/src/add/example_buf_pipe.py @@ -49,18 +49,54 @@ from collections.abc import Sequence class PrevControl: + """ contains signals that come *from* the previous stage (both in and out) + * i_valid: input from previous stage indicating incoming data is valid + * o_ready: output to next stage indicating readiness to accept data + * i_data : an input - added by the user of this class + """ def __init__(self): self.i_valid = Signal(name="p_i_valid") # >>in self.o_ready = Signal(name="p_o_ready") # <> self.i_ready = Signal(name="n_i_ready") # <>in stage n.o_valid out>> stage+1 stage-1 p.o_ready <>in stage n.data out>> stage+1 + stage-1 p.i_data >>in stage n.o_data out>> stage+1 | | process --->----^ | | +-- r_data ->-+ - input data p.data is read (only), is processed and goes into an + input data p.i_data is read (only), is processed and goes into an intermediate result store [process()]. this is updated combinatorially. in a non-stall condition, the intermediate result will go into the @@ -105,10 +141,10 @@ class BufferedPipeline: * ispec: returns output signals to the output specification * process: takes an input instance and returns processed data - p.data -> process() -> result --> n.data - | ^ - | | - +-> r_data -+ + p.i_data -> process() -> result --> n.o_data + | ^ + | | + +-> r_data -+ """ self.stage = stage @@ -117,42 +153,32 @@ class BufferedPipeline: self.n = NextControl() # set up the input and output data - self.p.data = stage.ispec() # input type - self.r_data = stage.ospec() # all these are output type - self.result = stage.ospec() - self.n.data = stage.ospec() + self.p.i_data = stage.ispec() # input type + self.r_data = stage.ospec() # all these are output type + self.result = stage.ospec() + self.n.o_data = stage.ospec() - def connect_next(self, nxt): + def connect_to_next(self, nxt): """ helper function to connect to the next stage data/valid/ready. - data/valid is passed *TO* nxt, and ready comes *IN* from nxt. """ - return [nxt.p.i_valid.eq(self.n.o_valid), - self.n.i_ready.eq(nxt.p.o_ready), - eq(nxt.p.data, self.n.data), - ] + return self.n.connect_to_next(nxt.p) def connect_in(self, prev): """ helper function to connect stage to an input source. do not use to connect stage-to-stage! """ - return [self.p.i_valid.eq(prev.p.i_valid), - prev.p.o_ready.eq(self.p.o_ready), - eq(self.p.data, prev.p.data), - ] + return self.p.connect_in(prev.p) def connect_out(self, nxt): """ helper function to connect stage to an output source. do not use to connect stage-to-stage! """ - return [nxt.n.o_valid.eq(self.n.o_valid), - self.n.i_ready.eq(nxt.n.i_ready), - eq(nxt.n.data, self.n.data), - ] + return self.n.connect_out(nxt.n) def set_input(self, i): """ helper function to set the input data """ - return eq(self.p.data, i) + return eq(self.p.i_data, i) def update_buffer(self): """ copies the result into the intermediate register r_data, @@ -164,20 +190,20 @@ class BufferedPipeline: def update_output(self): """ copies the (combinatorial) result into the output """ - return eq(self.n.data, self.result) + return eq(self.n.o_data, self.result) def flush_buffer(self): """ copies the *intermediate* register r_data into the output """ - return eq(self.n.data, self.r_data) + return eq(self.n.o_data, self.r_data) def ports(self): - return [self.p.data, self.n.data] + return [self.p.i_data, self.n.o_data] def elaborate(self, platform): m = Module() if hasattr(self.stage, "setup"): - self.stage.setup(m, self.p.data) + self.stage.setup(m, self.p.i_data) # establish some combinatorial temporaries o_n_validn = Signal(reset_less=True) @@ -188,7 +214,7 @@ class BufferedPipeline: # store result of processing in combinatorial temporary with m.If(self.p.i_valid): # input is valid: process it - m.d.comb += eq(self.result, self.stage.process(self.p.data)) + m.d.comb += eq(self.result, self.stage.process(self.p.i_data)) # if not in stall condition, update the temporary register with m.If(self.p.o_ready): # not stalled m.d.sync += self.update_buffer() @@ -319,16 +345,16 @@ class CombPipe: self.n = NextControl() # set up the input and output data - self.p.data = stage.ispec() # input type + self.p.i_data = stage.ispec() # input type self.r_data = stage.ispec() # input type self.result = stage.ospec() # output data - self.n.data = stage.ospec() # output type - self.n.data.name = "outdata" + self.n.o_data = stage.ospec() # output type + self.n.o_data.name = "outdata" def set_input(self, i): """ helper function to set the input data """ - return eq(self.p.data, i) + return eq(self.p.i_data, i) def elaborate(self, platform): m = Module() @@ -340,12 +366,12 @@ class CombPipe: m.d.sync += self._data_valid.eq(self.p.i_valid | \ (~self.n.i_ready & self._data_valid)) with m.If(self.p.i_valid & self.p.o_ready): - m.d.sync += eq(self.r_data, self.p.data) - m.d.comb += eq(self.n.data, self.result) + m.d.sync += eq(self.r_data, self.p.i_data) + m.d.comb += eq(self.n.o_data, self.result) return m def ports(self): - return [self.p.data, self.n.data] + return [self.p.i_data, self.n.o_data] class ExampleCombPipe(CombPipe):