Disable Assert statements until they are natively supported in nMigen
[gram.git] / gram / common.py
index b733f353776fdf4b627f4ed8cb9236b1a05c5b6e..a3d2025a02c812a3198f4af9282252c697994225 100644 (file)
@@ -1,6 +1,7 @@
 # This file is Copyright (c) 2016-2019 Florent Kermarrec <florent@enjoy-digital.fr>
 # This file is Copyright (c) 2018 John Sully <john@csquare.ca>
 # This file is Copyright (c) 2018 bunnie <bunnie@kosagi.com>
+# This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
 # License: BSD
 
 import math
@@ -25,17 +26,18 @@ burst_lengths = {
     "DDR4":  8
 }
 
+
 def get_cl_cw(memtype, tck):
     f_to_cl_cwl = OrderedDict()
     if memtype == "DDR2":
-        f_to_cl_cwl[400e6]  = (3, 2)
-        f_to_cl_cwl[533e6]  = (4, 3)
-        f_to_cl_cwl[677e6]  = (5, 4)
-        f_to_cl_cwl[800e6]  = (6, 5)
+        f_to_cl_cwl[400e6] = (3, 2)
+        f_to_cl_cwl[533e6] = (4, 3)
+        f_to_cl_cwl[677e6] = (5, 4)
+        f_to_cl_cwl[800e6] = (6, 5)
         f_to_cl_cwl[1066e6] = (7, 5)
     elif memtype == "DDR3":
-        f_to_cl_cwl[800e6]  = ( 6, 5)
-        f_to_cl_cwl[1066e6] = ( 7, 6)
+        f_to_cl_cwl[800e6] = (6, 5)
+        f_to_cl_cwl[1066e6] = (7, 6)
         f_to_cl_cwl[1333e6] = (10, 7)
         f_to_cl_cwl[1600e6] = (11, 8)
     elif memtype == "DDR4":
@@ -47,16 +49,19 @@ def get_cl_cw(memtype, tck):
             return cl, cwl
     raise ValueError
 
+
 def get_sys_latency(nphases, cas_latency):
     return math.ceil(cas_latency/nphases)
 
+
 def get_sys_phases(nphases, sys_latency, cas_latency):
     dat_phase = sys_latency*nphases - cas_latency
-    cmd_phase = (dat_phase - 1)%nphases
+    cmd_phase = (dat_phase - 1) % nphases
     return cmd_phase, dat_phase
 
 # PHY Pads Transformers ----------------------------------------------------------------------------
 
+
 class PHYPadsReducer:
     """PHY Pads Reducer
 
@@ -65,20 +70,22 @@ class PHYPadsReducer:
     For testing purposes, we often need to use only some of the DRAM modules. PHYPadsReducer allows
     selecting specific modules and avoid re-definining dram pins in the Platform for this.
     """
+
     def __init__(self, pads, modules):
-        self.pads    = pads
+        self.pads = pads
         self.modules = modules
 
     def __getattr__(self, name):
         if name in ["dq"]:
             return Array([getattr(self.pads, name)[8*i + j]
-                for i in self.modules
-                for j in range(8)])
+                          for i in self.modules
+                          for j in range(8)])
         if name in ["dm", "dqs", "dqs_p", "dqs_n"]:
             return Array([getattr(self.pads, name)[i] for i in self.modules])
         else:
             return getattr(self.pads, name)
 
+
 class PHYPadsCombiner:
     """PHY Pads Combiner
 
@@ -89,6 +96,7 @@ class PHYPadsCombiner:
     and this combiner can be used to re-create a single pads structure (that will be compatible with
     LiteDRAM's PHYs) to create a single DRAM controller from multiple fully dissociated DRAMs chips.
     """
+
     def __init__(self, pads):
         if not isinstance(pads, list):
             self.groups = [pads]
@@ -102,44 +110,17 @@ class PHYPadsCombiner:
     def __getattr__(self, name):
         if name in ["dm", "dq", "dqs", "dqs_p", "dqs_n"]:
             return Array([getattr(self.groups[j], name)[i]
-                for i in range(len(getattr(self.groups[0], name)))
-                for j in range(len(self.groups))])
+                          for i in range(len(getattr(self.groups[0], name)))
+                          for j in range(len(self.groups))])
         else:
             return getattr(self.groups[self.sel], name)
 
-# BitSlip ------------------------------------------------------------------------------------------
-
-class BitSlip(Elaboratable):
-    def __init__(self, dw, rst=None, slp=None, cycles=1):
-        self.i = Signal(dw)
-        self.o = Signal(dw)
-        self.rst = Signal() if rst is None else rst
-        self.slp = Signal() if slp is None else slp
-        self._cycles = cycles
-
-    def elaborate(self, platform):
-        m = Module()
-
-        value = Signal(range(self._cycles*dw))
-        with m.If(self.slp):
-            m.d.sync += value.eq(value+1)
-        with m.Elif(self.rst):
-            m.d.sync += value.eq(0)
-
-        r = Signal((self._cycles+1)*dw, reset_less=True)
-        m.d.sync += r.eq(Cat(r[dw:], self.i))
-        cases = {}
-        for i in range(self._cycles*dw):
-            cases[i] = self.o.eq(r[i:dw+i])
-        m.d.comb += Case(value, cases)
-
-        return m
-
 # DQS Pattern --------------------------------------------------------------------------------------
 
+
 class DQSPattern(Elaboratable):
     def __init__(self, preamble=None, postamble=None, wlevel_en=0, wlevel_strobe=0, register=False):
-        self.preamble  = Signal() if preamble  is None else preamble
+        self.preamble = Signal() if preamble is None else preamble
         self.postamble = Signal() if postamble is None else postamble
         self.o = Signal(8)
         self._wlevel_en = wlevel_en
@@ -170,6 +151,7 @@ class DQSPattern(Elaboratable):
 
 # Settings -----------------------------------------------------------------------------------------
 
+
 class Settings:
     def set_attributes(self, attributes):
         for k, v in attributes.items():
@@ -200,6 +182,7 @@ class PhySettings(Settings):
         self.is_rdimm = True
         self.set_attributes(locals())
 
+
 class GeomSettings(Settings):
     def __init__(self, bankbits, rowbits, colbits):
         self.set_attributes(locals())
@@ -212,18 +195,20 @@ class TimingSettings(Settings):
 
 # Layouts/Interface --------------------------------------------------------------------------------
 
+
 def cmd_layout(address_width):
     return [
         ("valid",            1, DIR_FANOUT),
         ("ready",            1, DIR_FANIN),
         ("we",               1, DIR_FANOUT),
         ("addr", address_width, DIR_FANOUT),
-        ("lock",             1, DIR_FANIN), # only used internally
+        ("lock",             1, DIR_FANIN),  # only used internally
 
         ("wdata_ready",      1, DIR_FANIN),
         ("rdata_valid",      1, DIR_FANIN)
     ]
 
+
 def data_layout(data_width):
     return [
         ("wdata",       data_width, DIR_FANOUT),
@@ -231,21 +216,25 @@ def data_layout(data_width):
         ("rdata",       data_width, DIR_FANIN)
     ]
 
+
 def cmd_description(address_width):
     return [
         ("we",   1),
         ("addr", address_width)
     ]
 
+
 def wdata_description(data_width):
     return [
         ("data", data_width),
         ("we",   data_width//8)
     ]
 
+
 def rdata_description(data_width):
     return [("data", data_width)]
 
+
 def cmd_request_layout(a, ba):
     return [
         ("a",     a),
@@ -255,6 +244,7 @@ def cmd_request_layout(a, ba):
         ("we",    1)
     ]
 
+
 def cmd_request_rw_layout(a, ba):
     return cmd_request_layout(a, ba) + [
         ("is_cmd", 1),
@@ -267,35 +257,33 @@ class gramInterface(Record):
     def __init__(self, address_align, settings):
         rankbits = log2_int(settings.phy.nranks)
         self.address_align = address_align
-        self.address_width = settings.geom.rowbits + settings.geom.colbits + rankbits - address_align
-        self.data_width    = settings.phy.dfi_databits*settings.phy.nphases
-        self.nbanks   = settings.phy.nranks*(2**settings.geom.bankbits)
-        self.nranks   = settings.phy.nranks
+        self.address_width = settings.geom.rowbits + \
+            settings.geom.colbits + rankbits - address_align
+        self.data_width = settings.phy.dfi_databits*settings.phy.nphases
+        self.nbanks = settings.phy.nranks*(2**settings.geom.bankbits)
+        self.nranks = settings.phy.nranks
         self.settings = settings
 
-        layout = [("bank"+str(i), cmd_layout(self.address_width)) for i in range(self.nbanks)]
+        layout = [("bank"+str(i), cmd_layout(self.address_width))
+                  for i in range(self.nbanks)]
         layout += data_layout(self.data_width)
         Record.__init__(self, layout)
 
 # Ports --------------------------------------------------------------------------------------------
 
+
 class gramNativePort(Settings):
-    def __init__(self, mode, address_width, data_width, clock_domain="sys", id=0):
+    def __init__(self, mode, address_width, data_width, clock_domain="sync", id=0):
         self.set_attributes(locals())
 
         self.lock = Signal()
 
-        self.cmd   = stream.Endpoint(cmd_description(address_width))
+        self.cmd = stream.Endpoint(cmd_description(address_width))
         self.wdata = stream.Endpoint(wdata_description(data_width))
         self.rdata = stream.Endpoint(rdata_description(data_width))
 
         self.flush = Signal()
 
-        # retro-compatibility # FIXME: remove
-        self.aw = self.address_width
-        self.dw = self.data_width
-        self.cd = self.clock_domain
-
     def get_bank_address(self, bank_bits, cba_shift):
         cba_upper = cba_shift + bank_bits
         return self.cmd.addr[cba_shift:cba_upper]
@@ -313,12 +301,12 @@ class gramNativePort(Settings):
 
 class gramNativeWritePort(gramNativePort):
     def __init__(self, *args, **kwargs):
-        LiteDRAMNativePort.__init__(self, "write", *args, **kwargs)
+        gramNativePort.__init__(self, "write", *args, **kwargs)
 
 
 class gramNativeReadPort(gramNativePort):
     def __init__(self, *args, **kwargs):
-        LiteDRAMNativePort.__init__(self, "read", *args, **kwargs)
+        gramNativePort.__init__(self, "read", *args, **kwargs)
 
 
 # Timing Controllers -------------------------------------------------------------------------------
@@ -326,8 +314,7 @@ class gramNativeReadPort(gramNativePort):
 class tXXDController(Elaboratable):
     def __init__(self, txxd):
         self.valid = Signal()
-        self.ready = ready = Signal(reset=txxd is None)
-        #ready.attr.add("no_retiming") TODO
+        self.ready = ready = Signal(reset=txxd is None, attrs={"no_retiming": True})
         self._txxd = txxd
 
     def elaborate(self, platform):
@@ -350,18 +337,18 @@ class tXXDController(Elaboratable):
 class tFAWController(Elaboratable):
     def __init__(self, tfaw):
         self.valid = Signal()
-        self.ready = Signal(reset=1)
-        #ready.attr.add("no_retiming") TODO
+        self.ready = Signal(reset=1, attrs={"no_retiming": True})
         self._tfaw = tfaw
 
     def elaborate(self, platform):
         m = Module()
 
         if self._tfaw is not None:
-            count  = Signal(range(max(self._tfaw, 2)))
+            count = Signal(range(max(self._tfaw, 2)))
             window = Signal(self._tfaw)
             m.d.sync += window.eq(Cat(self.valid, window))
-            m.d.comb += count.eq(reduce(add, [window[i] for i in range(self._tfaw)]))
+            m.d.comb += count.eq(reduce(add, [window[i]
+                                              for i in range(self._tfaw)]))
             with m.If(count < 4):
                 with m.If(count == 3):
                     m.d.sync += self.ready.eq(~self.valid)