Remove wants_zqcs signal
[gram.git] / gram / core / multiplexer.py
index 867e852fa2bb491e8882322dc78f6e884c2494aa..4296dca9138872a75946cbe9e60eb5b0ab54a37c 100644 (file)
@@ -11,6 +11,7 @@ from functools import reduce
 from operator import or_, and_
 
 from nmigen import *
+from nmigen.asserts import Assert, Assume
 
 from gram.common import *
 import gram.stream as stream
@@ -70,8 +71,7 @@ class _CommandChooser(Elaboratable):
             write = request.is_write == self.want_writes
             m.d.comb += valids[i].eq(request.valid & (command | (read & write)))
 
-        arbiter = RoundRobin(n)
-        m.submodules += arbiter
+        m.submodules.arbiter = arbiter = RoundRobin(n)
         choices = Array(valids[i] for i in range(n))
         m.d.comb += [
             arbiter.request.eq(valids),
@@ -143,11 +143,10 @@ class _Steerer(Elaboratable):
     """
 
     def __init__(self, commands, dfi):
+        assert len(commands) == 4
         self._commands = commands
         self._dfi = dfi
-        ncmd = len(commands)
-        nph = len(dfi.phases)
-        self.sel = [Signal(range(ncmd)) for i in range(nph)]
+        self.sel = [Signal(range(len(commands))) for i in range(len(dfi.phases))]
 
     def elaborate(self, platform):
         m = Module()
@@ -162,10 +161,10 @@ class _Steerer(Elaboratable):
                 return cmd.valid & cmd.ready & getattr(cmd, attr)
 
         for i, (phase, sel) in enumerate(zip(dfi.phases, self.sel)):
-            nranks = len(phase.cs_n)
+            nranks = len(phase.cs)
             rankbits = log2_int(nranks)
-            if hasattr(phase, "reset_n"):
-                m.d.comb += phase.reset_n.eq(1)
+            if hasattr(phase, "reset"):
+                m.d.comb += phase.reset.eq(0)
             m.d.comb += phase.clk_en.eq(Repl(Signal(reset=1), nranks))
             if hasattr(phase, "odt"):
                 # FIXME: add dynamic drive for multi-rank (will be needed for high frequencies)
@@ -177,27 +176,24 @@ class _Steerer(Elaboratable):
                     (Array(cmd.ba[-rankbits:] for cmd in commands)[sel]))
                 if i == 0:  # Select all ranks on refresh.
                     with m.If(sel == STEER_REFRESH):
-                        m.d.sync += phase.cs_n.eq(0)
+                        m.d.sync += phase.cs.eq(1)
                     with m.Else():
-                        m.d.sync += phase.cs_n.eq(~rank_decoder.o)
+                        m.d.sync += phase.cs.eq(rank_decoder.o)
                 else:
-                    m.d.sync += phase.cs_n.eq(~rank_decoder.o)
+                    m.d.sync += phase.cs.eq(rank_decoder.o)
                 m.d.sync += phase.bank.eq(Array(cmd.ba[:-rankbits]
                                                 for cmd in commands)[sel])
             else:
                 m.d.sync += [
-                    phase.cs_n.eq(0),
+                    phase.cs.eq(1),
                     phase.bank.eq(Array(cmd.ba[:] for cmd in commands)[sel]),
                 ]
 
             m.d.sync += [
                 phase.address.eq(Array(cmd.a for cmd in commands)[sel]),
-                phase.cas_n.eq(~Array(valid_and(cmd, "cas")
-                                      for cmd in commands)[sel]),
-                phase.ras_n.eq(~Array(valid_and(cmd, "ras")
-                                      for cmd in commands)[sel]),
-                phase.we_n.eq(~Array(valid_and(cmd, "we")
-                                     for cmd in commands)[sel])
+                phase.cas.eq(Array(valid_and(cmd, "cas") for cmd in commands)[sel]),
+                phase.ras.eq(Array(valid_and(cmd, "ras") for cmd in commands)[sel]),
+                phase.we.eq(Array(valid_and(cmd, "we") for cmd in commands)[sel])
             ]
 
             rddata_ens = Array(valid_and(cmd, "is_read") for cmd in commands)
@@ -209,8 +205,38 @@ class _Steerer(Elaboratable):
 
         return m
 
-# Multiplexer --------------------------------------------------------------------------------------
+class _AntiStarvation(Elaboratable):
+    def __init__(self, timeout):
+        self.en = Signal()
+        self.max_time = Signal(reset=1)
+        self._timeout = timeout
 
+    def elaborate(self, platform):
+        m = Module()
+
+        # TODO: timeout=1 fails formal checks
+        assert self._timeout != 1
+
+        if self._timeout > 0:
+            time = Signal(range(self._timeout))
+            with m.If(~self.en):
+                m.d.sync += [
+                    time.eq(self._timeout-1),
+                    self.max_time.eq(0),
+                ]
+            with m.Elif(time != 0):
+                m.d.sync += time.eq(time-1)
+                with m.If(time == 1):
+                    m.d.sync += self.max_time.eq(1)
+                with m.Else():
+                    m.d.sync += self.max_time.eq(0)
+        else:
+            m.d.comb += self.max_time.eq(0)
+
+        if platform == "formal" and self._timeout > 0:
+            m.d.comb += Assert(self.max_time == (time == 0))
+
+        return m
 
 class Multiplexer(Elaboratable):
     """Multplexes requets from BankMachines to DFI
@@ -277,8 +303,7 @@ class Multiplexer(Elaboratable):
                                         log2_int(len(bank_machines))))
         # nop must be 1st
         commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd]
-        steerer = _Steerer(commands, dfi)
-        m.submodules += steerer
+        m.submodules.steerer = steerer = _Steerer(commands, dfi)
 
         # tRRD timing (Row to Row delay) -----------------------------------------------------------
         m.submodules.trrdcon = trrdcon = tXXDController(settings.timing.tRRD)
@@ -317,28 +342,11 @@ class Multiplexer(Elaboratable):
         ]
 
         # Anti Starvation --------------------------------------------------------------------------
-
-        def anti_starvation(timeout):
-            en = Signal()
-            max_time = Signal()
-            if timeout:
-                t = timeout - 1
-                time = Signal(range(t+1))
-                m.d.comb += max_time.eq(time == 0)
-                with m.If(~en):
-                    m.d.sync += time.eq(t)
-                with m.Elif(~max_time):
-                    m.d.sync += time.eq(time - 1)
-            else:
-                m.d.comb += max_time.eq(0)
-            return en, max_time
-
-        read_time_en,   max_read_time = anti_starvation(settings.read_time)
-        write_time_en, max_write_time = anti_starvation(settings.write_time)
+        m.submodules.read_antistarvation = read_antistarvation = _AntiStarvation(settings.read_time)
+        m.submodules.write_antistarvation = write_antistarvation = _AntiStarvation(settings.write_time)
 
         # Refresh ----------------------------------------------------------------------------------
-        m.d.comb += [bm.refresh_req.eq(refresher.cmd.valid)
-                     for bm in bank_machines]
+        m.d.comb += [bm.refresh_req.eq(refresher.cmd.valid) for bm in bank_machines]
         go_to_refresh = Signal()
         bm_refresh_gnts = [bm.refresh_gnt for bm in bank_machines]
         m.d.comb += go_to_refresh.eq(reduce(and_, bm_refresh_gnts))
@@ -376,7 +384,7 @@ class Multiplexer(Elaboratable):
         with m.FSM():
             with m.State("Read"):
                 m.d.comb += [
-                    read_time_en.eq(1),
+                    read_antistarvation.en.eq(1),
                     choose_req.want_reads.eq(1),
                     steerer_sel(steerer, "read"),
                 ]
@@ -394,7 +402,7 @@ class Multiplexer(Elaboratable):
 
                 with m.If(write_available):
                     # TODO: switch only after several cycles of ~read_available?
-                    with m.If(~read_available | max_read_time):
+                    with m.If(~read_available | read_antistarvation.max_time):
                         m.next = "RTW"
 
                 with m.If(go_to_refresh):
@@ -402,7 +410,7 @@ class Multiplexer(Elaboratable):
 
             with m.State("Write"):
                 m.d.comb += [
-                    write_time_en.eq(1),
+                    write_antistarvation.en.eq(1),
                     choose_req.want_writes.eq(1),
                     steerer_sel(steerer, "write"),
                 ]
@@ -419,7 +427,7 @@ class Multiplexer(Elaboratable):
                     ]
 
                 with m.If(read_available):
-                    with m.If(~write_available | max_write_time):
+                    with m.If(~write_available | write_antistarvation.max_time):
                         m.next = "WTR"
 
                 with m.If(go_to_refresh):