Unverified Commit 83b31f4f authored by enjoy-digital's avatar enjoy-digital Committed by GitHub

Merge pull request #231 from antmicro/jboc/module-timings

Allow to pass all module timings in the format (ck, ns)
parents 9d80829e 12d66c11
...@@ -294,6 +294,12 @@ def parse_spd_hexdump(filename): ...@@ -294,6 +294,12 @@ def parse_spd_hexdump(filename):
# SDRAMModule -------------------------------------------------------------------------------------- # SDRAMModule --------------------------------------------------------------------------------------
Frac = namedtuple("Frac", ["num", "denom"])
class Timing(namedtuple("Timing", ["ck", "ns"])):
def __add__(self, other):
return Timing(self.ck + other.ck, self.ns + other.ns)
class SDRAMModule: class SDRAMModule:
"""SDRAM module geometry and timings. """SDRAM module geometry and timings.
...@@ -320,68 +326,82 @@ class SDRAMModule: ...@@ -320,68 +326,82 @@ class SDRAMModule:
if (fine_refresh_mode is None) and (self.memtype == "DDR4"): if (fine_refresh_mode is None) and (self.memtype == "DDR4"):
fine_refresh_mode = "1x" fine_refresh_mode = "1x"
self.timing_settings = TimingSettings( self.timing_settings = TimingSettings(
tRP = self.ns_to_cycles(self.get("tRP")), tRP = self.ck_ns_to_cycles(self.get("tRP")),
tRCD = self.ns_to_cycles(self.get("tRCD")), tRCD = self.ck_ns_to_cycles(self.get("tRCD")),
tWR = self.ns_to_cycles(self.get("tWR")), tWR = self.ck_ns_to_cycles(self.get("tWR")),
tREFI = self.ns_to_cycles(self.get("tREFI", fine_refresh_mode), False), tREFI = self.ck_ns_to_cycles(self.get("tREFI", fine_refresh_mode), margin=False),
tRFC = self.ck_ns_to_cycles(*self.get("tRFC", fine_refresh_mode)), tRFC = self.ck_ns_to_cycles(self.get("tRFC", fine_refresh_mode)),
tWTR = self.ck_ns_to_cycles(*self.get("tWTR")), tWTR = self.ck_ns_to_cycles(self.get("tWTR")),
tFAW = None if self.get("tFAW") is None else self.ck_ns_to_cycles(*self.get("tFAW")), tFAW = None if self.get("tFAW") is None else self.ck_ns_to_cycles(self.get("tFAW")),
tCCD = None if self.get("tCCD") is None else self.ck_ns_to_cycles(*self.get("tCCD")), tCCD = None if self.get("tCCD") is None else self.ck_ns_to_cycles(self.get("tCCD")),
tRRD = None if self.get("tRRD") is None else self.ck_ns_to_cycles(*self.get("tRRD")), tRRD = None if self.get("tRRD") is None else self.ck_ns_to_cycles(self.get("tRRD")),
tRC = None if self.get("tRAS") is None else self.ns_to_cycles(self.get("tRP") + self.get("tRAS")), tRC = None if self.get("tRAS") is None else self.ck_ns_to_cycles(self.get("tRP") + self.get("tRAS")),
tRAS = None if self.get("tRAS") is None else self.ns_to_cycles(self.get("tRAS")), tRAS = None if self.get("tRAS") is None else self.ck_ns_to_cycles(self.get("tRAS")),
tZQCS = None if self.get("tZQCS") is None else self.ck_ns_to_cycles(*self.get("tZQCS")) tZQCS = None if self.get("tZQCS") is None else self.ck_ns_to_cycles(self.get("tZQCS"))
) )
self.timing_settings.fine_refresh_mode = fine_refresh_mode self.timing_settings.fine_refresh_mode = fine_refresh_mode
def get(self, name, key=None): def get(self, name, key=None):
r = None assert name in _speedgrade_timings + _technology_timings, "Unknown name: {}".format(name)
timing = self.get_timing(name)
if timing is None:
return None
if (timing is not None) and (key is not None):
timing = timing[key]
if isinstance(timing, tuple):
ck, ns = timing
else:
ck, ns = 0, timing
ck = ck or 0
ns = ns or 0
return Timing(ck, ns)
def get_timing(self, name):
if name in _speedgrade_timings: if name in _speedgrade_timings:
if hasattr(self, "speedgrade_timings"): return self.get_speedgrade_timing(name)
speedgrade = "default" if self.speedgrade is None else self.speedgrade return self.get_technology_timing(name)
r = getattr(self.speedgrade_timings[speedgrade], name)
else: def get_speedgrade_timing(self, name):
name = name + "_" + self.speedgrade if self.speedgrade is not None else name if hasattr(self, "speedgrade_timings"):
try: speedgrade = "default" if self.speedgrade is None else self.speedgrade
r = getattr(self, name) return getattr(self.speedgrade_timings[speedgrade], name)
except: name = name + "_" + self.speedgrade if self.speedgrade is not None else name
pass try:
return getattr(self, name)
except:
pass
def get_technology_timing(self, name):
if hasattr(self, "technology_timings"):
return getattr(self.technology_timings, name)
else: else:
if hasattr(self, "technology_timings"): try:
r = getattr(self.technology_timings, name) return getattr(self, name)
else: except:
try: pass
r = getattr(self, name)
except:
pass
if (r is not None) and (key is not None):
r = r[key]
return r
def ns_to_cycles(self, t, margin=True): def ns_to_cycles(self, t, margin=True):
clk_period_ns = 1e9/self.clk_freq clk_period_ns = 1e9/self.clk_freq
if margin: t += self.margin if margin else 0
margins = {
"1:1" : 0,
"1:2" : clk_period_ns/2,
"1:4" : 3*clk_period_ns/4
}
t += margins[self.rate]
return ceil(t/clk_period_ns) return ceil(t/clk_period_ns)
def ck_to_cycles(self, c): def ck_to_cycles(self, c):
d = { return ceil(c/self.rate_frac.denom)
"1:1" : 1,
"1:2" : 2, def ck_ns_to_cycles(self, timing, **kwargs):
"1:4" : 4 return max(self.ck_to_cycles(timing.ck), self.ns_to_cycles(timing.ns, **kwargs))
}
return ceil(c/d[self.rate]) @property
def rate_frac(self):
def ck_ns_to_cycles(self, c, t): num, denom = map(int, self.rate.split(":"))
c = 0 if c is None else c assert num == 1, "Rate: numerator must be 1: {}".format(self.rate)
t = 0 if t is None else t return Frac(num, denom)
return max(self.ck_to_cycles(c), self.ns_to_cycles(t))
@property
def margin(self):
clk_period_ns = 1e9 / self.clk_freq
frac = self.rate_frac
return clk_period_ns * (1 - frac.num/frac.denom)
@classmethod @classmethod
def from_spd_data(cls, spd_data, clk_freq, fine_refresh_mode=None): def from_spd_data(cls, spd_data, clk_freq, fine_refresh_mode=None):
......
...@@ -212,10 +212,10 @@ class DFITimingsChecker(Module): ...@@ -212,10 +212,10 @@ class DFITimingsChecker(Module):
if val is None: if val is None:
val = 0 val = 0
elif key in CK_NS: elif key == "tCK":
val = self.ck_ns_to_ps(val, tck)
else:
val = self.ns_to_ps(val) val = self.ns_to_ps(val)
else:
val = self.ck_ns_to_ps(val, tck)
new_timings[key] = val new_timings[key] = val
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment