create classes for STB/BUSY, split in from out
[ieee754fpu.git] / src / add / example_buf_pipe.py
index 6678a6713f05280828d7b3a5ef4fd4f3adffaa96..37f866c36d1b463eba75c07f2bd7506d0a4acf1d 100644 (file)
     where data will flow on *every* clock when the conditions are right.
 
     input acceptance conditions are when:
     where data will flow on *every* clock when the conditions are right.
 
     input acceptance conditions are when:
-        * incoming previous-stage strobe (i_p_stb) is HIGH
-        * outgoing previous-stage busy   (o_p_busy) is LOW
+        * incoming previous-stage strobe (i.p_stb) is HIGH
+        * outgoing previous-stage busy   (o.p_busy) is LOW
 
     output transmission conditions are when:
 
     output transmission conditions are when:
-        * outgoing next-stage strobe (o_n_stb) is HIGH
-        * outgoing next-stage busy   (i_n_busy) is LOW
+        * outgoing next-stage strobe (o.n_stb) is HIGH
+        * outgoing next-stage busy   (i.n_busy) 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
 
     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
@@ -100,12 +100,25 @@ class ExampleStage:
     def ports(self):
         return [self.i_data, self.o_data]
 
     def ports(self):
         return [self.i_data, self.o_data]
 
+class IOAckIn:
+
+    def __init__(self):
+        self.p_stb = Signal()  # >>in - comes in from PREVIOUS stage
+        self.n_busy = Signal() # in<< - comes in from the NEXT stage
+
+
+class IOAckOut:
+
+    def __init__(self):
+        self.n_stb = Signal()  # out>> - goes out to the NEXT stage
+        self.p_busy = Signal() # <<out - goes out to the PREVIOUS stage
+
 
 class BufferedPipeline:
     """ buffered pipeline stage
 
 
 class BufferedPipeline:
     """ buffered pipeline stage
 
-        stage-1   i_p_stb  >>in   stage   o_n_stb  out>>   stage+1
-        stage-1   o_p_busy <<out  stage   i_n_busy <<in    stage+1
+        stage-1   i.p_stb  >>in   stage   o.n_stb  out>>   stage+1
+        stage-1   o.p_busy <<out  stage   i.n_busy <<in    stage+1
         stage-1   i_data   >>in   stage   o_data   out>>   stage+1
                               |             |
                               +------->  process
         stage-1   i_data   >>in   stage   o_data   out>>   stage+1
                               |             |
                               +------->  process
@@ -114,13 +127,14 @@ class BufferedPipeline:
     """
     def __init__(self):
         # input: strobe comes in from previous stage, busy comes in from next
     """
     def __init__(self):
         # input: strobe comes in from previous stage, busy comes in from next
-        #self.i_p_rst = Signal()    # >>in - comes in from PREVIOUS stage
-        self.i_p_stb = Signal()    # >>in - comes in from PREVIOUS stage
-        self.i_n_busy = Signal()   # in<< - comes in from the NEXT stage
+        self.i = IOAckIn()
+        #self.i.p_stb = Signal()    # >>in - comes in from PREVIOUS stage
+        #self.i.n_busy = Signal()   # in<< - comes in from the NEXT stage
 
         # output: strobe goes out to next stage, busy comes in from previous
 
         # output: strobe goes out to next stage, busy comes in from previous
-        self.o_n_stb = Signal()    # out>> - goes out to the NEXT stage
-        self.o_p_busy = Signal()   # <<out - goes out to the PREVIOUS stage
+        self.o = IOAckOut()
+        #self.o.n_stb = Signal()    # out>> - goes out to the NEXT stage
+        #self.o.p_busy = Signal()   # <<out - goes out to the PREVIOUS stage
 
     def elaborate(self, platform):
         m = Module()
 
     def elaborate(self, platform):
         m = Module()
@@ -130,54 +144,54 @@ class BufferedPipeline:
         o_n_stbn = Signal(reset_less=True)
         i_n_busyn = Signal(reset_less=True)
         i_p_stb_o_p_busyn = Signal(reset_less=True)
         o_n_stbn = Signal(reset_less=True)
         i_n_busyn = Signal(reset_less=True)
         i_p_stb_o_p_busyn = Signal(reset_less=True)
-        m.d.comb += [i_n_busyn.eq(~self.i_n_busy),
-                     o_n_stbn.eq(~self.o_n_stb),
-                     o_p_busyn.eq(~self.o_p_busy),
-                     i_p_stb_o_p_busyn.eq(self.i_p_stb & o_p_busyn),
+        m.d.comb += [i_n_busyn.eq(~self.i.n_busy),
+                     o_n_stbn.eq(~self.o.n_stb),
+                     o_p_busyn.eq(~self.o.p_busy),
+                     i_p_stb_o_p_busyn.eq(self.i.p_stb & o_p_busyn),
         ]
 
         # store result of processing in combinatorial temporary
         ]
 
         # store result of processing in combinatorial temporary
-        with m.If(self.i_p_stb): # input is valid: process it
+        with m.If(self.i.p_stb): # input is valid: process it
             m.d.comb += self.stage.process()
         # if not in stall condition, update the temporary register
         with m.If(o_p_busyn): # not stalled
             m.d.sync += self.stage.update_buffer()
 
             m.d.comb += self.stage.process()
         # if not in stall condition, update the temporary register
         with m.If(o_p_busyn): # not stalled
             m.d.sync += self.stage.update_buffer()
 
-        #with m.If(self.i_p_rst): # reset
-        #    m.d.sync += self.o_n_stb.eq(0)
-        #    m.d.sync += self.o_p_busy.eq(0)
+        #with m.If(self.i.p_rst): # reset
+        #    m.d.sync += self.o.n_stb.eq(0)
+        #    m.d.sync += self.o.p_busy.eq(0)
         with m.If(i_n_busyn): # next stage is not busy
             with m.If(o_p_busyn): # not stalled
                 # nothing in buffer: send (processed) input direct to output
         with m.If(i_n_busyn): # next stage is not busy
             with m.If(o_p_busyn): # not stalled
                 # nothing in buffer: send (processed) input direct to output
-                m.d.sync += [self.o_n_stb.eq(self.i_p_stb),
+                m.d.sync += [self.o.n_stb.eq(self.i.p_stb),
                              self.stage.update_output(),
                             ]
                              self.stage.update_output(),
                             ]
-            with m.Else(): # o_p_busy is true, and something is in our buffer.
+            with m.Else(): # o.p_busy is true, and something is in our buffer.
                 # Flush the [already processed] buffer to the output port.
                 # Flush the [already processed] buffer to the output port.
-                m.d.sync += [self.o_n_stb.eq(1),
+                m.d.sync += [self.o.n_stb.eq(1),
                              self.stage.flush_buffer(),
                              # clear stall condition, declare register empty.
                              self.stage.flush_buffer(),
                              # clear stall condition, declare register empty.
-                             self.o_p_busy.eq(0),
+                             self.o.p_busy.eq(0),
                             ]
                             ]
-                # ignore input, since o_p_busy is also true.
+                # ignore input, since o.p_busy is also true.
 
 
-        # (i_n_busy) is true here: next stage is busy
+        # (i.n_busy) is true here: next stage is busy
         with m.Elif(o_n_stbn): # next stage being told "not busy"
         with m.Elif(o_n_stbn): # next stage being told "not busy"
-            m.d.sync += [self.o_n_stb.eq(self.i_p_stb),
-                         self.o_p_busy.eq(0), # Keep the buffer empty
+            m.d.sync += [self.o.n_stb.eq(self.i.p_stb),
+                         self.o.p_busy.eq(0), # Keep the buffer empty
                          # set the output data (from comb result)
                          self.stage.update_output(),
                         ]
                          # set the output data (from comb result)
                          self.stage.update_output(),
                         ]
-        # (i_n_busy) and (o_n_stb) both true:
+        # (i.n_busy) and (o.n_stb) both true:
         with m.Elif(i_p_stb_o_p_busyn):
             # If next stage *is* busy, and not stalled yet, accept input
         with m.Elif(i_p_stb_o_p_busyn):
             # If next stage *is* busy, and not stalled yet, accept input
-            m.d.sync += self.o_p_busy.eq(self.i_p_stb & self.o_n_stb)
+            m.d.sync += self.o.p_busy.eq(self.i.p_stb & self.o.n_stb)
 
         return m
 
     def ports(self):
 
         return m
 
     def ports(self):
-        return [self.i_p_stb, self.i_n_busy,
-                self.o_n_stb, self.o_p_busy,
+        return [self.i.p_stb, self.i.n_busy,
+                self.o.n_stb, self.o.p_busy,
                ]
 
 
                ]