X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fadd%2Fexample_buf_pipe.py;h=a1f5d04f565c1ec3cd1d2f813ca3fd9436fa6216;hb=749ea1efc895d5259e49062bd9025dd6b1051636;hp=45bed19301a5c46b3213c8ae0217405182f6a215;hpb=6ba0c1a42bfc8362af281aaae60858f05acc991b;p=ieee754fpu.git diff --git a/src/add/example_buf_pipe.py b/src/add/example_buf_pipe.py index 45bed193..a1f5d04f 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 ready (o.p_ready) 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 ready (i.n_ready) 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 @@ -45,46 +45,151 @@ from nmigen import Signal, Cat, Const, Mux, Module from nmigen.cli import verilog, rtlil +from nmigen.hdl.rec import Record, Layout + from collections.abc import Sequence -class IOAckIn: +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.p_valid = Signal() # >>in - comes in from PREVIOUS stage - self.n_ready = Signal() # in<< - comes in from the NEXT stage + self.i_valid = Signal(name="p_i_valid") # prev >>in self + self.o_ready = Signal(name="p_o_ready") # prev <> - goes out to the NEXT stage - self.p_ready = Signal() # <> next + self.i_ready = Signal(name="n_i_ready") # self <>in stage o.n_valid out>> stage+1 - stage-1 o.p_ready <>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 --->----^ | | +-- r_data ->-+ - input data i_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 @@ -99,111 +204,66 @@ class BufferedPipeline: input may begin to be processed and transferred directly to output. """ def __init__(self, stage): - """ pass in a "stage" which may be either a static class or a class - instance, which has three functions: - * ispec: returns input signals according to the input specification - * ispec: returns output signals to the output specification - * process: takes an input instance and returns processed data - - i_data -> process() -> result --> o.data - | ^ - | | - +-> r_data -+ - """ - # input: strobe comes in from previous stage, ready comes in from next - self.i = IOAckIn() - #self.i.p_valid = Signal() # >>in - comes in from PREVIOUS stage - #self.i.n_ready = Signal() # in<< - comes in from the NEXT stage - - # output: strobe goes out to next stage, ready comes in from previous - self.o = IOAckOut() - #self.o.n_valid = Signal() # out>> - goes out to the NEXT stage - #self.o.p_ready = Signal() # <