From 72d19420fa77353dd0e7cf7e0a7284311c79e6fc Mon Sep 17 00:00:00 2001
From: Kia <kia@special-circumstanc.es>
Date: Wed, 3 Mar 2021 19:52:59 -0700
Subject: [PATCH] first draft of flowcontroller

---
 gearbox.py | 47 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 39 insertions(+), 8 deletions(-)

diff --git a/gearbox.py b/gearbox.py
index cebcfe3..b190ca3 100755
--- a/gearbox.py
+++ b/gearbox.py
@@ -75,6 +75,7 @@ class GearboxFlowControl(Elaboratable):
 
     def elaborate(self, platform):
             m = Module()
+            internalfault = Signal()
 
             # The top-level flow control logic works as follows.
             # First, we determine which operations are *possible* based on the read/write indices
@@ -87,11 +88,23 @@ class GearboxFlowControl(Elaboratable):
             #    If so, we set valid_out to signal to downstream we're ready to produce
             can_read_this_cycle = Signal(1)
             # Then, we look at the flow-control signals from upstream/downstream to see which
-            # transactions will happen, and set the following two internal signals, which are
+            # transactions will happen, and set the following two bus signals, which are
             # used to gate the read/write index updates:
+            # write_happens_this_cycle
+            # read_happens_this_cycle
 
-            write_happens_this_cycle = Signal(1)
-            read_happens_this_cycle = Signal(1)
+
+            # We replicate signals to avoid repeating "self.bus."
+
+            read_ptr = Signal(range(self.len_storage))
+            m.d.comb += read_ptr.eq(self.bus.read_ptr)
+
+            write_ptr = Signal(range(self.len_storage))
+            m.d.comb += write_ptr.eq(self.bus.write_ptr)
+
+            len_storage = self.len_storage
+
+            disambiguator = Signal(IndexDisambiguator, reset=IndexDisambiguator.LAST_OP_WAS_READ)
 
 
             with m.If(read_ptr == write_ptr): # the special case first
@@ -99,7 +112,7 @@ class GearboxFlowControl(Elaboratable):
                     with m.Case(IndexDisambiguator.LAST_OP_UNKNOWN): # fault
                         m.d.comb += can_read_this_cycle.eq(0)
                         m.d.comb += can_write_this_cycle.eq(0)
-                        m.d.comb += self.bus.fault.eq(1)
+                        m.d.sync += internalfault.eq(1)
                     with m.Case(IndexDisambiguator.LAST_OP_WAS_WRITE): # completely full
                         m.d.comb += can_read_this_cycle.eq(1)
                         m.d.comb += can_write_this_cycle.eq(0)
@@ -128,8 +141,29 @@ class GearboxFlowControl(Elaboratable):
                 with m.If(numinvalid >= self.in_width):
                     m.d.comb += can_write_this_cycle.eq(1)
 
+            with m.Elif(read_ptr > write_ptr):
+                # write_ptr < read_ptr. Here, the valid bits wrap, and the invalid bits do not wrap.
+                # The valid bits are:   inclusive [read_ptr, K] inclusive, union with inclusive [0, write_ptr) exclusive
+                # the invalid bits are  inclusive [write_ptr, read_ptr) exclusive
 
+                # We first calculate the number of valid bits:
+                numvalid = Signal(range(len_storage))
 
+                m.d.comb += numvalid.eq(len_storage - read_ptr + write_ptr)
+
+                with m.If(numvalid >= self.out_width):
+                    m.d.comb += can_read_this_cycle.eq(1)
+
+                # We calculate the number of invalid bits:
+                numinvalid = Signal(range(len_storage))
+
+                m.d.comb += numinvalid.eq(read_ptr - write_ptr)
+
+                with m.If(numinvalid >= self.in_width):
+                    m.d.comb += can_write_this_cycle.eq(1)
+            with m.Else(): # should never happen
+                m.d.sync += internalfault.eq(1)
+            return m
 
 
 class ArbitraryGearbox(Elaboratable):
@@ -154,7 +188,6 @@ class ArbitraryGearbox(Elaboratable):
             write_ptr = Signal(range(len_storage))
             read_ptr  = Signal(range(len_storage))
 
-            disambiguator = Signal(IndexDisambiguator, reset=IndexDisambiguator.LAST_OP_WAS_READ)
 
             # The buffer is composed of two different flavor of bits:
 
@@ -176,9 +209,7 @@ class ArbitraryGearbox(Elaboratable):
 
             # There are multiple cases for read_ptr and write_ptr:
 
-            # write_ptr < read_ptr. Here, the valid bits wrap, and the invalid bits do not wrap.
-            # The valid bits are:   inclusive [read_ptr, K] inclusive, union with inclusive [0, write_ptr) exclusive
-            # the invalid bits are  inclusive [write_ptr, read_ptr) exclusive
+
 
             # Naturally, there is a tricky edge case which requires an extra bit (literally) of disambiguation.
             # If write_ptr == read_ptr we don't know if the buffer is entirely full or entirely empty.
-- 
GitLab