update comments
[ieee754fpu.git] / src / add / queue.py
index 015c357e9e9b466bd05b360c41939312477f645f..0038953d6ea8b3d33fd21273219f4922a725101b 100644 (file)
@@ -23,7 +23,7 @@
 # TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
 # MODIFICATIONS.
 
-from nmigen import Module, Signal, Memory, Mux
+from nmigen import Module, Signal, Memory, Mux, Elaboratable
 from nmigen.tools import bits_for
 from nmigen.cli import main
 from nmigen.lib.fifo import FIFOInterface
@@ -31,17 +31,20 @@ from nmigen.lib.fifo import FIFOInterface
 # translated from https://github.com/freechipsproject/chisel3/blob/a4a29e29c3f1eed18f851dcf10bdc845571dfcb6/src/main/scala/chisel3/util/Decoupled.scala#L185   # noqa
 
 
-class Queue(FIFOInterface):
+class Queue(FIFOInterface, Elaboratable):
     def __init__(self, width, depth, fwft=True, pipe=False):
         """ Queue (FIFO) with pipe mode and first-write fall-through capability
 
-            * width: width of Queue data in/out
-            * depth: queue depth.  NOTE: may be set to 0 (this is ok)
-            * fwft : first-write, fall-through mode (Chisel Queue "flow" mode)
-            * pipe : pipe mode.  NOTE: this mode can cause unanticipated
-                     problems.  when read is enabled, so is writeable.
-                     therefore if read is enabled, the data ABSOLUTELY MUST
-                     be read.
+            * :width: width of Queue data in/out
+            * :depth: queue depth.  NOTE: may be set to 0 (this is ok)
+            * :fwft : first-write, fall-through mode (Chisel Queue "flow" mode)
+            * :pipe : pipe mode.  NOTE: this mode can cause unanticipated
+                      problems.  when read is enabled, so is writeable.
+                      therefore if read is enabled, the data ABSOLUTELY MUST
+                      be read.
+
+            fwft mode = True basically means that the data may be transferred
+            combinatorially from input to output.
 
             Attributes:
             * level: available free space (number of unread entries)
@@ -63,12 +66,12 @@ class Queue(FIFOInterface):
         m.submodules.ram_write = ram_write = ram.write_port()
 
         # convenience names
-        p_o_ready = self.writable
-        p_i_valid = self.we
+        p_ready_o = self.writable
+        p_valid_i = self.we
         enq_data = self.din
 
-        n_o_valid = self.readable
-        n_i_ready = self.re
+        n_valid_o = self.readable
+        n_ready_i = self.re
         deq_data = self.dout
 
         # intermediaries
@@ -93,12 +96,12 @@ class Queue(FIFOInterface):
                      deq_max.eq(deq_ptr == self.depth - 1),
                      empty.eq(ptr_match & ~maybe_full),
                      full.eq(ptr_match & maybe_full),
-                     do_enq.eq(p_o_ready & p_i_valid), # write conditions ok
-                     do_deq.eq(n_i_ready & n_o_valid), # read conditions ok
+                     do_enq.eq(p_ready_o & p_valid_i), # write conditions ok
+                     do_deq.eq(n_ready_i & n_valid_o), # read conditions ok
 
                      # set readable and writable (NOTE: see pipe mode below)
-                     n_o_valid.eq(~empty), # cannot read if empty!
-                     p_o_ready.eq(~full),  # cannot write if full!
+                     n_valid_o.eq(~empty), # cannot read if empty!
+                     p_ready_o.eq(~full),  # cannot write if full!
 
                      # set up memory and connect to input and output
                      ram_write.addr.eq(enq_ptr),
@@ -127,18 +130,19 @@ class Queue(FIFOInterface):
         # this done combinatorially to give the exact same characteristics
         # as Memory "write-through"... without relying on a changing API
         if self.fwft:
-            with m.If(p_i_valid):
-                m.d.comb += n_o_valid.eq(1)
+            with m.If(p_valid_i):
+                m.d.comb += n_valid_o.eq(1)
             with m.If(empty):
                 m.d.comb += deq_data.eq(enq_data)
                 m.d.comb += do_deq.eq(0)
-                with m.If(n_i_ready):
+                with m.If(n_ready_i):
                     m.d.comb += do_enq.eq(0)
 
-        # pipe mode: read-enabled requires writability.
+        # pipe mode: if next stage says it's ready (readable), we
+        #            *must* declare the input ready (writeable).
         if self.pipe:
-            with m.If(n_i_ready):
-                m.d.comb += p_o_ready.eq(1)
+            with m.If(n_ready_i):
+                m.d.comb += p_ready_o.eq(1)
 
         # set the count (available free space), optimise on power-of-two
         if self.depth == 1 << ptr_width:  # is depth a power of 2
@@ -178,6 +182,7 @@ if __name__ == "__main__":
             m.d.comb += port.eq(signal)
             retval.append(signal)
         return retval
+
     m.submodules.reg_stage = reg_stage
     ports += queue_ports(reg_stage, "reg_stage_")
     m.submodules.break_ready_chain_stage = break_ready_chain_stage