X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fadd%2Fexample_buf_pipe.py;h=f760ce3948e0e96f3b7d18d18636f50d0f93c2c7;hb=ea57d805517010e494dbde828dd5e1230ff9afc4;hp=aab10a917e4c53b59439c122d5dde9950fbc1488;hpb=0ebc09c0a7b74e4807ccdb60ca0a10cbb605666a;p=ieee754fpu.git diff --git a/src/add/example_buf_pipe.py b/src/add/example_buf_pipe.py index aab10a91..f760ce39 100644 --- a/src/add/example_buf_pipe.py +++ b/src/add/example_buf_pipe.py @@ -12,12 +12,12 @@ where data will flow on *every* clock when the conditions are right. input acceptance conditions are when: - * incoming previous-stage strobe (i.p_valid) is HIGH - * outgoing previous-stage busy (o.p_busy) is LOW + * incoming previous-stage strobe (p.i_valid) is HIGH + * outgoing previous-stage ready (p.o_ready) is LOW output transmission conditions are when: - * outgoing next-stage strobe (o.n_valid) is HIGH - * outgoing next-stage busy (i.n_busy) is LOW + * outgoing next-stage strobe (n.o_valid) is HIGH + * outgoing next-stage ready (n.i_ready) is LOW the tricky bit is when the input has valid data and the output is not ready to accept it. if it wasn't for the clock synchronisation, it @@ -33,7 +33,7 @@ we now effectively have *two* possible pieces of data to "choose" from: the buffered data, and the incoming data. the decision as to which to process and output is based on whether we are in "stall" or not. - i.e. when the next stage is no longer busy, the output comes from + i.e. when the next stage is no longer ready, the output comes from the buffer if a stall had previously occurred, otherwise it comes direct from processing the input. @@ -45,168 +45,332 @@ from nmigen import Signal, Cat, Const, Mux, Module from nmigen.cli import verilog, rtlil +from collections.abc import Sequence -class ExampleStage: - """ an example of how to use the buffered pipeline. actual names of - variables (i_data, r_data, o_data, result) below do not matter: - the functions however do. +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 + """ - input data i_data is read (only), is processed and goes into an - intermediate result store [process()]. this is updated combinatorially. + 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 - comes in from PREVIOUS stage - self.n_busy = Signal() # in<< - comes in from the NEXT stage + 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.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 self.n.connect_out(nxt.n) -class IOAckOut: + def set_input(self, i): + """ helper function to set the input data + """ + return eq(self.p.i_data, i) - def __init__(self): - self.n_valid = Signal() # out>> - goes out to the NEXT stage - self.p_busy = Signal() # <>in stage o.n_valid out>> stage+1 - stage-1 o.p_busy <>in stage o_data out>> stage+1 + stage-1 p.i_valid >>in stage n.o_valid out>> stage+1 + stage-1 p.o_ready <>in stage n.o_data out>> stage+1 | | - +-------> process + process --->----^ | | - +-- r_data ---+ + +-- r_data ->-+ + + 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 + output (update_output). however if ever there is a stall, it goes + into r_data instead [update_buffer()]. + + when the non-stall condition is released, r_data is the first + to be transferred to the output [flush_buffer()], and the stall + condition cleared. + + on the next cycle (as long as stall is not raised again) the + input may begin to be processed and transferred directly to output. """ - def __init__(self): - # input: strobe comes in from previous stage, busy comes in from next - self.i = IOAckIn() - #self.i.p_valid = Signal() # >>in - comes in from PREVIOUS stage - #self.i.n_busy = Signal() # in<< - comes in from the NEXT stage + def __init__(self, stage): + PipelineBase.__init__(self, stage) - # output: strobe goes out to next stage, busy comes in from previous - self.o = IOAckOut() - #self.o.n_valid = Signal() # out>> - goes out to the NEXT stage - #self.o.p_busy = Signal() # <