Improve PTP model resolution by using Decimal types and wider internal fns accumulators
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
36
README.md
36
README.md
@@ -603,6 +603,10 @@ To use this module, import it and connect it to the DUT:
|
|||||||
|
|
||||||
Once the clock is instantiated, it will generate a continuous stream of monotonically increasing PTP timestamps on every clock edge.
|
Once the clock is instantiated, it will generate a continuous stream of monotonically increasing PTP timestamps on every clock edge.
|
||||||
|
|
||||||
|
Internally, the `PtpClock` module uses 32-bit fractional ns fields for higher frequency resolution. Only the upper 16 bits are returned in the timestamps, but the full fns value can be accessed with the _ts_tod_fns_ and _ts_rel_fns_ attributes.
|
||||||
|
|
||||||
|
All APIs that handle fractional values use the `Decimal` type for maximum precision, as the combination of timestamp range and resolution is usually too much for normal floating point numbers to handle without significant loss of precision.
|
||||||
|
|
||||||
#### Signals
|
#### Signals
|
||||||
|
|
||||||
* `ts_tod`: 96-bit time-of-day timestamp (48 bit seconds, 32 bit ns, 16 bit fractional ns)
|
* `ts_tod`: 96-bit time-of-day timestamp (48 bit seconds, 32 bit ns, 16 bit fractional ns)
|
||||||
@@ -633,24 +637,26 @@ Once the clock is instantiated, it will generate a continuous stream of monotoni
|
|||||||
|
|
||||||
* `set_period(ns, fns)`: set clock period from separate fields
|
* `set_period(ns, fns)`: set clock period from separate fields
|
||||||
* `set_drift(num, denom)`: set clock drift from separate fields
|
* `set_drift(num, denom)`: set clock drift from separate fields
|
||||||
* `set_period_ns(t)`: set clock period in ns (float)
|
* `set_period_ns(t)`: set clock period and drift in ns (Decimal)
|
||||||
* `get_period_ns()`: return current clock period in ns (float)
|
* `get_period_ns()`: return current clock period in ns (Decimal)
|
||||||
* `set_ts_tod(ts_s, ts_ns, ts_fns)`: set 96-bit ToD timestamp from separate fields
|
* `set_ts_tod(ts_s, ts_ns, ts_fns)`: set 96-bit ToD timestamp from separate fields
|
||||||
* `set_ts_tod_96(ts)`: set 96-bit ToD timestamp from integer
|
* `set_ts_tod_96(ts)`: set 96-bit ToD timestamp from integer
|
||||||
* `set_ts_tod_ns(t)`: set 96-bit ToD timestamp from ns (float)
|
* `set_ts_tod_ns(t)`: set 96-bit ToD timestamp from ns (Decimal)
|
||||||
* `set_ts_tod_s(t)`: set 96-bit ToD timestamp from seconds (float)
|
* `set_ts_tod_s(t)`: set 96-bit ToD timestamp from seconds (Decimal)
|
||||||
|
* `set_ts_tod_sim_time()`: set 96-bit ToD timestamp from sim time
|
||||||
* `get_ts_tod()`: return current 96-bit ToD timestamp as separate fields
|
* `get_ts_tod()`: return current 96-bit ToD timestamp as separate fields
|
||||||
* `get_ts_tod_96()`: return current 96-bit ToD timestamp as an integer
|
* `get_ts_tod_96()`: return current 96-bit ToD timestamp as an integer
|
||||||
* `get_ts_tod_ns()`: return current 96-bit ToD timestamp in ns (float)
|
* `get_ts_tod_ns()`: return current 96-bit ToD timestamp in ns (Decimal)
|
||||||
* `get_ts_tod_s()`: return current 96-bit ToD timestamp in seconds (float)
|
* `get_ts_tod_s()`: return current 96-bit ToD timestamp in seconds (Decimal)
|
||||||
* `set_ts_rel(ts_ns, ts_fns)`: set 64-bit relative timestamp from separate fields
|
* `set_ts_rel(ts_ns, ts_fns)`: set 64-bit relative timestamp from separate fields
|
||||||
* `set_ts_rel_64(ts)`: set 64-bit relative timestamp from integer
|
* `set_ts_rel_64(ts)`: set 64-bit relative timestamp from integer
|
||||||
* `set_ts_rel_ns(t)`: set 64-bit relative timestamp from ns (float)
|
* `set_ts_rel_ns(t)`: set 64-bit relative timestamp from ns (Decimal)
|
||||||
* `set_ts_rel_s(t)`: set 64-bit relative timestamp from seconds (float)
|
* `set_ts_rel_s(t)`: set 64-bit relative timestamp from seconds (Decimal)
|
||||||
|
* `set_ts_rel_sim_time()`: set 64-bit relative timestamp from sim time
|
||||||
* `get_ts_rel()`: return current 64-bit relative timestamp as separate fields
|
* `get_ts_rel()`: return current 64-bit relative timestamp as separate fields
|
||||||
* `get_ts_rel_64()`: return current 64-bit relative timestamp as an integer
|
* `get_ts_rel_64()`: return current 64-bit relative timestamp as an integer
|
||||||
* `get_ts_rel_ns()`: return current 64-bit relative timestamp in ns (float)
|
* `get_ts_rel_ns()`: return current 64-bit relative timestamp in ns (Decimal)
|
||||||
* `get_ts_rel_s()`: return current 64-bit relative timestamp in seconds (float)
|
* `get_ts_rel_s()`: return current 64-bit relative timestamp in seconds (Decimal)
|
||||||
|
|
||||||
### PTP clock (sim time)
|
### PTP clock (sim time)
|
||||||
|
|
||||||
@@ -669,6 +675,8 @@ To use this module, import it and connect it to the DUT:
|
|||||||
|
|
||||||
Once the clock is instantiated, it will generate a continuous stream of monotonically increasing PTP timestamps on every clock edge.
|
Once the clock is instantiated, it will generate a continuous stream of monotonically increasing PTP timestamps on every clock edge.
|
||||||
|
|
||||||
|
All APIs that handle fractional values use the `Decimal` type for maximum precision, as the combination of timestamp range and resolution is usually too much for normal floating point numbers to handle without significant loss of precision.
|
||||||
|
|
||||||
#### Signals
|
#### Signals
|
||||||
|
|
||||||
* `ts_tod`: 96-bit time-of-day timestamp (48 bit seconds, 32 bit ns, 16 bit fractional ns)
|
* `ts_tod`: 96-bit time-of-day timestamp (48 bit seconds, 32 bit ns, 16 bit fractional ns)
|
||||||
@@ -694,9 +702,9 @@ Once the clock is instantiated, it will generate a continuous stream of monotoni
|
|||||||
|
|
||||||
* `get_ts_tod()`: return current 96-bit ToD timestamp as separate fields
|
* `get_ts_tod()`: return current 96-bit ToD timestamp as separate fields
|
||||||
* `get_ts_tod_96()`: return current 96-bit ToD timestamp as an integer
|
* `get_ts_tod_96()`: return current 96-bit ToD timestamp as an integer
|
||||||
* `get_ts_tod_ns()`: return current 96-bit ToD timestamp in ns (float)
|
* `get_ts_tod_ns()`: return current 96-bit ToD timestamp in ns (Decimal)
|
||||||
* `get_ts_tod_s()`: return current 96-bit ToD timestamp in seconds (float)
|
* `get_ts_tod_s()`: return current 96-bit ToD timestamp in seconds (Decimal)
|
||||||
* `get_ts_rel()`: return current 64-bit relative timestamp as separate fields
|
* `get_ts_rel()`: return current 64-bit relative timestamp as separate fields
|
||||||
* `get_ts_rel_96()`: return current 64-bit relative timestamp as an integer
|
* `get_ts_rel_96()`: return current 64-bit relative timestamp as an integer
|
||||||
* `get_ts_rel_ns()`: return current 64-bit relative timestamp in ns (float)
|
* `get_ts_rel_ns()`: return current 64-bit relative timestamp in ns (Decimal)
|
||||||
* `get_ts_rel_s()`: return current 64-bit relative timestamp in seconds (float)
|
* `get_ts_rel_s()`: return current 64-bit relative timestamp in seconds (Decimal)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ THE SOFTWARE.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import math
|
from decimal import Decimal, Context
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
|
||||||
import cocotb
|
import cocotb
|
||||||
@@ -56,13 +56,6 @@ class PtpClock(Reset):
|
|||||||
self.clock = clock
|
self.clock = clock
|
||||||
self.reset = reset
|
self.reset = reset
|
||||||
|
|
||||||
self.period_ns = 0
|
|
||||||
self.period_fns = 0
|
|
||||||
self.drift_num = 0
|
|
||||||
self.drift_denom = 0
|
|
||||||
self.drift_cnt = 0
|
|
||||||
self.set_period_ns(period_ns)
|
|
||||||
|
|
||||||
self.log.info("PTP clock")
|
self.log.info("PTP clock")
|
||||||
self.log.info("cocotbext-eth version %s", __version__)
|
self.log.info("cocotbext-eth version %s", __version__)
|
||||||
self.log.info("Copyright (c) 2020 Alex Forencich")
|
self.log.info("Copyright (c) 2020 Alex Forencich")
|
||||||
@@ -70,6 +63,15 @@ class PtpClock(Reset):
|
|||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.ctx = Context(prec=60)
|
||||||
|
|
||||||
|
self.period_ns = 0
|
||||||
|
self.period_fns = 0
|
||||||
|
self.drift_num = 0
|
||||||
|
self.drift_denom = 0
|
||||||
|
self.drift_cnt = 0
|
||||||
|
self.set_period_ns(period_ns)
|
||||||
|
|
||||||
self.ts_tod_s = 0
|
self.ts_tod_s = 0
|
||||||
self.ts_tod_ns = 0
|
self.ts_tod_ns = 0
|
||||||
self.ts_tod_fns = 0
|
self.ts_tod_fns = 0
|
||||||
@@ -94,26 +96,29 @@ class PtpClock(Reset):
|
|||||||
|
|
||||||
def set_period(self, ns, fns):
|
def set_period(self, ns, fns):
|
||||||
self.period_ns = int(ns)
|
self.period_ns = int(ns)
|
||||||
self.period_fns = int(fns) & 0xffff
|
self.period_fns = int(fns) & 0xffffffff
|
||||||
|
|
||||||
def set_drift(self, num, denom):
|
def set_drift(self, num, denom):
|
||||||
self.drift_num = int(num)
|
self.drift_num = int(num)
|
||||||
self.drift_denom = int(denom)
|
self.drift_denom = int(denom)
|
||||||
|
|
||||||
def set_period_ns(self, t):
|
def set_period_ns(self, t):
|
||||||
drift, period = math.modf(t*2**16)
|
t = Decimal(t)
|
||||||
|
period, drift = self.ctx.divmod(Decimal(t) * Decimal(2**32), Decimal(1))
|
||||||
period = int(period)
|
period = int(period)
|
||||||
frac = Fraction(drift).limit_denominator(2**16)
|
frac = Fraction(drift).limit_denominator(2**16-1)
|
||||||
self.period_ns = period >> 16
|
self.set_period(period >> 32, period & 0xffffffff)
|
||||||
self.period_fns = period & 0xffff
|
self.set_drift(frac.numerator, frac.denominator)
|
||||||
self.drift_num = frac.numerator
|
|
||||||
self.drift_denom = frac.denominator
|
self.log.info("Set period: %s ns", t)
|
||||||
|
self.log.info("Period: 0x%x ns 0x%08x fns", self.period_ns, self.period_fns)
|
||||||
|
self.log.info("Drift: 0x%04x / 0x%04x fns", self.drift_num, self.drift_denom)
|
||||||
|
|
||||||
def get_period_ns(self):
|
def get_period_ns(self):
|
||||||
p = ((self.period_ns << 16) | self.period_fns) / 2**16
|
p = Decimal((self.period_ns << 32) | self.period_fns)
|
||||||
if self.drift_denom:
|
if self.drift_denom:
|
||||||
return p + self.drift_num / self.drift_rate / 2**16
|
p += Decimal(self.drift_num) / Decimal(self.drift_denom)
|
||||||
return p
|
return p / Decimal(2**32)
|
||||||
|
|
||||||
def set_ts_tod(self, ts_s, ts_ns, ts_fns):
|
def set_ts_tod(self, ts_s, ts_ns, ts_fns):
|
||||||
self.ts_tod_s = int(ts_s)
|
self.ts_tod_s = int(ts_s)
|
||||||
@@ -123,31 +128,37 @@ class PtpClock(Reset):
|
|||||||
|
|
||||||
def set_ts_tod_96(self, ts):
|
def set_ts_tod_96(self, ts):
|
||||||
ts = int(ts)
|
ts = int(ts)
|
||||||
self.set_ts_tod(ts >> 48, (ts >> 32) & 0x3fffffff, ts & 0xffff)
|
self.set_ts_tod(ts >> 48, (ts >> 32) & 0x3fffffff, (ts & 0xffff) << 16)
|
||||||
|
|
||||||
def set_ts_tod_ns(self, t):
|
def set_ts_tod_ns(self, t):
|
||||||
self.set_ts_tod_s(t*1e-9)
|
ts_s, ts_ns = self.ctx.divmod(Decimal(t), Decimal(1000000000))
|
||||||
|
ts_s = ts_s.scaleb(-9).to_integral_value()
|
||||||
|
ts_ns, ts_fns = self.ctx.divmod(ts_ns, Decimal(1))
|
||||||
|
ts_ns = ts_ns.to_integral_value()
|
||||||
|
ts_fns = (ts_fns * Decimal(2**32)).to_integral_value()
|
||||||
|
self.set_ts_tod(ts_s, ts_ns, ts_fns)
|
||||||
|
|
||||||
def set_ts_tod_s(self, t):
|
def set_ts_tod_s(self, t):
|
||||||
ts_ns, ts_s = math.modf(t)
|
self.set_ts_tod_ns(Decimal(t).scaleb(9, self.ctx))
|
||||||
ts_ns *= 1e9
|
|
||||||
ts_fns, ts_ns = math.modf(ts_ns)
|
def set_ts_tod_sim_time(self):
|
||||||
ts_fns *= 2**16
|
self.set_ts_tod_ns(Decimal(get_sim_time('fs')).scaleb(-6))
|
||||||
self.set_ts_tod(ts_s, ts_ns, ts_fns)
|
|
||||||
|
|
||||||
def get_ts_tod(self):
|
def get_ts_tod(self):
|
||||||
return (self.ts_tod_s, self.ts_tod_ns, self.ts_tod_fns)
|
return (self.ts_tod_s, self.ts_tod_ns, self.ts_tod_fns)
|
||||||
|
|
||||||
def get_ts_tod_96(self):
|
def get_ts_tod_96(self):
|
||||||
ts_s, ts_ns, ts_fns = self.get_ts_tod()
|
ts_s, ts_ns, ts_fns = self.get_ts_tod()
|
||||||
return (ts_s << 48) | (ts_ns << 16) | ts_fns
|
return (ts_s << 48) | (ts_ns << 16) | (ts_fns >> 16)
|
||||||
|
|
||||||
def get_ts_tod_ns(self):
|
def get_ts_tod_ns(self):
|
||||||
ts_s, ts_ns, ts_fns = self.get_ts_tod()
|
ts_s, ts_ns, ts_fns = self.get_ts_tod()
|
||||||
return ts_s*1e9+ts_ns+ts_fns/2**16
|
ns = Decimal(ts_fns) / Decimal(2**32)
|
||||||
|
ns = self.ctx.add(ns, Decimal(ts_ns))
|
||||||
|
return self.ctx.add(ns, Decimal(ts_s).scaleb(9))
|
||||||
|
|
||||||
def get_ts_tod_s(self):
|
def get_ts_tod_s(self):
|
||||||
return self.get_ts_tod_ns()*1e-9
|
return self.get_ts_tod_ns().scaleb(-9, self.ctx)
|
||||||
|
|
||||||
def set_ts_rel(self, ts_ns, ts_fns):
|
def set_ts_rel(self, ts_ns, ts_fns):
|
||||||
self.ts_rel_ns = int(ts_ns)
|
self.ts_rel_ns = int(ts_ns)
|
||||||
@@ -159,12 +170,16 @@ class PtpClock(Reset):
|
|||||||
self.set_ts_rel(ts >> 16, (ts & 0xffff) << 16)
|
self.set_ts_rel(ts >> 16, (ts & 0xffff) << 16)
|
||||||
|
|
||||||
def set_ts_rel_ns(self, t):
|
def set_ts_rel_ns(self, t):
|
||||||
ts_fns, ts_ns = math.modf(t)
|
ts_ns, ts_fns = self.ctx.divmod(Decimal(t), Decimal(1))
|
||||||
ts_fns *= 2**16
|
ts_ns = ts_ns.to_integral_value()
|
||||||
|
ts_fns = (ts_fns * Decimal(2**32)).to_integral_value()
|
||||||
self.set_ts_rel(ts_ns, ts_fns)
|
self.set_ts_rel(ts_ns, ts_fns)
|
||||||
|
|
||||||
def set_ts_rel_s(self, t):
|
def set_ts_rel_s(self, t):
|
||||||
self.set_ts_rel_ns(t*1e9)
|
self.set_ts_rel_ns(Decimal(t).scaleb(9, self.ctx))
|
||||||
|
|
||||||
|
def set_ts_rel_sim_time(self):
|
||||||
|
self.set_ts_rel_ns(Decimal(get_sim_time('fs')).scaleb(-6))
|
||||||
|
|
||||||
def get_ts_rel(self):
|
def get_ts_rel(self):
|
||||||
return (self.ts_rel_ns, self.ts_rel_fns)
|
return (self.ts_rel_ns, self.ts_rel_fns)
|
||||||
@@ -175,10 +190,10 @@ class PtpClock(Reset):
|
|||||||
|
|
||||||
def get_ts_rel_ns(self):
|
def get_ts_rel_ns(self):
|
||||||
ts_ns, ts_fns = self.get_ts_rel()
|
ts_ns, ts_fns = self.get_ts_rel()
|
||||||
return ts_ns + ts_fns/2**16
|
return self.ctx.add(Decimal(ts_fns) / Decimal(2**32), Decimal(ts_ns))
|
||||||
|
|
||||||
def get_ts_rel_s(self):
|
def get_ts_rel_s(self):
|
||||||
return self.get_ts_rel()*1e-9
|
return self.get_ts_rel_ns().scaleb(-9, self.ctx)
|
||||||
|
|
||||||
def _handle_reset(self, state):
|
def _handle_reset(self, state):
|
||||||
if state:
|
if state:
|
||||||
@@ -219,36 +234,39 @@ class PtpClock(Reset):
|
|||||||
if self.pps is not None:
|
if self.pps is not None:
|
||||||
self.pps.value = 0
|
self.pps.value = 0
|
||||||
|
|
||||||
# increment 96 bit timestamp
|
# increment tod bit timestamp
|
||||||
if self.ts_tod is not None or self.pps is not None:
|
self.ts_tod_fns += (self.period_ns << 32) + self.period_fns
|
||||||
t = ((self.ts_tod_ns << 16) + self.ts_tod_fns) + ((self.period_ns << 16) + self.period_fns)
|
|
||||||
|
|
||||||
if self.drift_denom and self.drift_cnt == 0:
|
if self.drift_denom and self.drift_cnt == 0:
|
||||||
t += self.drift_num
|
self.ts_tod_fns += self.drift_num
|
||||||
|
|
||||||
if t > (1000000000 << 16):
|
ns_inc = self.ts_tod_fns >> 32
|
||||||
self.ts_tod_s += 1
|
self.ts_tod_fns &= 0xffffffff
|
||||||
t -= (1000000000 << 16)
|
|
||||||
if self.pps is not None:
|
|
||||||
self.pps.value = 1
|
|
||||||
|
|
||||||
self.ts_tod_fns = t & 0xffff
|
self.ts_tod_ns += ns_inc
|
||||||
self.ts_tod_ns = t >> 16
|
|
||||||
|
|
||||||
if self.ts_tod is not None:
|
if self.ts_tod_ns >= 1000000000:
|
||||||
self.ts_tod.value = (self.ts_tod_s << 48) | (self.ts_tod_ns << 16) | (self.ts_tod_fns)
|
self.ts_tod_s += 1
|
||||||
|
self.ts_tod_ns -= 1000000000
|
||||||
|
if self.pps is not None:
|
||||||
|
self.pps.value = 1
|
||||||
|
|
||||||
|
if self.ts_tod is not None:
|
||||||
|
self.ts_tod.value = (self.ts_tod_s << 48) | (self.ts_tod_ns << 16) | (self.ts_tod_fns >> 16)
|
||||||
|
|
||||||
|
# increment rel bit timestamp
|
||||||
|
self.ts_rel_fns += (self.period_ns << 32) + self.period_fns
|
||||||
|
|
||||||
|
if self.drift_denom and self.drift_cnt == 0:
|
||||||
|
self.ts_rel_fns += self.drift_num
|
||||||
|
|
||||||
|
ns_inc = self.ts_rel_fns >> 32
|
||||||
|
self.ts_rel_fns &= 0xffffffff
|
||||||
|
|
||||||
|
self.ts_rel_ns = (self.ts_rel_ns + ns_inc) & 0xffffffffffff
|
||||||
|
|
||||||
# increment 64 bit timestamp
|
|
||||||
if self.ts_rel is not None:
|
if self.ts_rel is not None:
|
||||||
t = ((self.ts_rel_ns << 16) + self.ts_rel_fns) + ((self.period_ns << 16) + self.period_fns)
|
self.ts_rel.value = (self.ts_rel_ns << 16) | (self.ts_rel_fns >> 16)
|
||||||
|
|
||||||
if self.drift_denom and self.drift_cnt == 0:
|
|
||||||
t += self.drift_num
|
|
||||||
|
|
||||||
self.ts_rel_fns = t & 0xffff
|
|
||||||
self.ts_rel_ns = t >> 16
|
|
||||||
|
|
||||||
self.ts_rel.value = (self.ts_rel_ns << 16) | self.ts_rel_fns
|
|
||||||
|
|
||||||
if self.drift_denom:
|
if self.drift_denom:
|
||||||
if self.drift_cnt > 0:
|
if self.drift_cnt > 0:
|
||||||
@@ -273,6 +291,8 @@ class PtpClockSimTime:
|
|||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.ctx = Context(prec=60)
|
||||||
|
|
||||||
self.ts_tod_s = 0
|
self.ts_tod_s = 0
|
||||||
self.ts_tod_ns = 0
|
self.ts_tod_ns = 0
|
||||||
self.ts_tod_fns = 0
|
self.ts_tod_fns = 0
|
||||||
@@ -296,11 +316,16 @@ class PtpClockSimTime:
|
|||||||
|
|
||||||
def get_ts_tod_96(self):
|
def get_ts_tod_96(self):
|
||||||
ts_s, ts_ns, ts_fns = self.get_ts_tod()
|
ts_s, ts_ns, ts_fns = self.get_ts_tod()
|
||||||
return (ts_s << 48) | (ts_ns << 16) | ts_fns
|
return (ts_s << 48) | (ts_ns << 16) | (ts_fns >> 16)
|
||||||
|
|
||||||
def get_ts_tod_ns(self):
|
def get_ts_tod_ns(self):
|
||||||
ts_s, ts_ns, ts_fns = self.get_ts_tod()
|
ts_s, ts_ns, ts_fns = self.get_ts_tod()
|
||||||
return ts_s*1e9+ts_ns+ts_fns/2**16
|
ns = Decimal(ts_fns) / Decimal(2**32)
|
||||||
|
ns = self.ctx.add(ns, Decimal(ts_ns))
|
||||||
|
return self.ctx.add(ns, Decimal(ts_s).scaleb(9))
|
||||||
|
|
||||||
|
def get_ts_tod_s(self):
|
||||||
|
return self.get_ts_tod_ns().scaleb(-9, self.ctx)
|
||||||
|
|
||||||
def get_ts_rel(self):
|
def get_ts_rel(self):
|
||||||
return (self.ts_rel_ns, self.ts_rel_fns)
|
return (self.ts_rel_ns, self.ts_rel_fns)
|
||||||
@@ -311,10 +336,10 @@ class PtpClockSimTime:
|
|||||||
|
|
||||||
def get_ts_rel_ns(self):
|
def get_ts_rel_ns(self):
|
||||||
ts_ns, ts_fns = self.get_ts_rel()
|
ts_ns, ts_fns = self.get_ts_rel()
|
||||||
return ts_ns + ts_fns/2**16
|
return self.ctx.add(Decimal(ts_fns) / Decimal(2**32), Decimal(ts_ns))
|
||||||
|
|
||||||
def get_ts_rel_s(self):
|
def get_ts_rel_s(self):
|
||||||
return self.get_ts_rel()*1e-9
|
return self.get_ts_rel_ns().scaleb(-9, self.ctx)
|
||||||
|
|
||||||
async def _run(self):
|
async def _run(self):
|
||||||
clock_edge_event = RisingEdge(self.clock)
|
clock_edge_event = RisingEdge(self.clock)
|
||||||
@@ -322,12 +347,15 @@ class PtpClockSimTime:
|
|||||||
while True:
|
while True:
|
||||||
await clock_edge_event
|
await clock_edge_event
|
||||||
|
|
||||||
self.ts_rel_fns, self.ts_rel_ns = math.modf(get_sim_time('ns'))
|
ts_ns, ts_fns = self.ctx.divmod(Decimal(get_sim_time('fs')).scaleb(-6), Decimal(1))
|
||||||
|
|
||||||
self.ts_rel_ns = int(self.ts_rel_ns)
|
self.ts_rel_ns = int(ts_ns.to_integral_value()) & 0xffffffffffff
|
||||||
self.ts_rel_fns = int(self.ts_rel_fns*0x10000)
|
self.ts_rel_fns = int((ts_fns * Decimal(2**16)).to_integral_value())
|
||||||
|
|
||||||
self.ts_tod_s, self.ts_tod_ns = divmod(self.ts_rel_ns, 1000000000)
|
ts_s, ts_ns = self.ctx.divmod(ts_ns, Decimal(1000000000))
|
||||||
|
|
||||||
|
self.ts_tod_s = int(ts_s.scaleb(-9).to_integral_value())
|
||||||
|
self.ts_tod_ns = int(ts_ns.to_integral_value())
|
||||||
self.ts_tod_fns = self.ts_rel_fns
|
self.ts_tod_fns = self.ts_rel_fns
|
||||||
|
|
||||||
if self.ts_tod is not None:
|
if self.ts_tod is not None:
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
import cocotb_test.simulator
|
import cocotb_test.simulator
|
||||||
|
|
||||||
@@ -66,6 +67,14 @@ class TB:
|
|||||||
await RisingEdge(self.dut.clk)
|
await RisingEdge(self.dut.clk)
|
||||||
await RisingEdge(self.dut.clk)
|
await RisingEdge(self.dut.clk)
|
||||||
|
|
||||||
|
def get_ts_tod_ns(self):
|
||||||
|
ts = self.dut.ts_tod.value.integer
|
||||||
|
return Decimal(ts >> 48).scaleb(9) + (Decimal(ts & 0xffffffffffff) / Decimal(2**16))
|
||||||
|
|
||||||
|
def get_ts_rel_ns(self):
|
||||||
|
ts = self.dut.ts_rel.value.integer
|
||||||
|
return Decimal(ts) / Decimal(2**16)
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test()
|
@cocotb.test()
|
||||||
async def run_default_rate(dut):
|
async def run_default_rate(dut):
|
||||||
@@ -75,32 +84,32 @@ async def run_default_rate(dut):
|
|||||||
await tb.reset()
|
await tb.reset()
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
start_time = get_sim_time('sec')
|
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
start_ts_tod = tb.get_ts_tod_ns()
|
||||||
start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
start_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
await ClockCycles(dut.clk, 10000)
|
await ClockCycles(dut.clk, 10000)
|
||||||
|
|
||||||
stop_time = get_sim_time('sec')
|
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
stop_ts_tod = tb.get_ts_tod_ns()
|
||||||
stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
stop_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
time_delta = stop_time-start_time
|
time_delta = stop_time-start_time
|
||||||
ts_tod_delta = stop_ts_tod-start_ts_tod
|
ts_tod_delta = stop_ts_tod-start_ts_tod
|
||||||
ts_rel_delta = stop_ts_rel-start_ts_rel
|
ts_rel_delta = stop_ts_rel-start_ts_rel
|
||||||
|
|
||||||
tb.log.info("sim time delta : %g s", time_delta)
|
tb.log.info("sim time delta : %s ns", time_delta)
|
||||||
tb.log.info("ToD ts delta : %g s", ts_tod_delta)
|
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
|
||||||
tb.log.info("rel ts delta : %g s", ts_rel_delta)
|
tb.log.info("rel ts delta : %s ns", ts_rel_delta)
|
||||||
|
|
||||||
ts_tod_diff = time_delta - ts_tod_delta
|
ts_tod_diff = time_delta - ts_tod_delta
|
||||||
ts_rel_diff = time_delta - ts_rel_delta
|
ts_rel_diff = time_delta - ts_rel_delta
|
||||||
|
|
||||||
tb.log.info("ToD ts diff : %g s", ts_tod_diff)
|
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
|
||||||
tb.log.info("rel ts diff : %g s", ts_rel_diff)
|
tb.log.info("rel ts diff : %s ns", ts_rel_diff)
|
||||||
|
|
||||||
assert abs(ts_tod_diff) < 1e-12
|
assert abs(ts_tod_diff) < 1e-3
|
||||||
assert abs(ts_rel_diff) < 1e-12
|
assert abs(ts_rel_diff) < 1e-3
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
@@ -118,36 +127,36 @@ async def run_load_timestamps(dut):
|
|||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
|
|
||||||
assert dut.ts_tod.value.integer == 12345678*2**16 + (tb.ptp_clock.period_ns << 16) + tb.ptp_clock.period_fns
|
assert dut.ts_tod.value.integer == (12345678 << 16) + (tb.ptp_clock.period_ns << 16) + (tb.ptp_clock.period_fns >> 16)
|
||||||
assert dut.ts_rel.value.integer == 12345678*2**16 + (tb.ptp_clock.period_ns << 16) + tb.ptp_clock.period_fns
|
assert dut.ts_rel.value.integer == (12345678 << 16) + (tb.ptp_clock.period_ns << 16) + (tb.ptp_clock.period_fns >> 16)
|
||||||
assert dut.ts_step.value.integer == 1
|
assert dut.ts_step.value.integer == 1
|
||||||
|
|
||||||
start_time = get_sim_time('sec')
|
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
start_ts_tod = tb.get_ts_tod_ns()
|
||||||
start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
start_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
await ClockCycles(dut.clk, 2000)
|
await ClockCycles(dut.clk, 2000)
|
||||||
|
|
||||||
stop_time = get_sim_time('sec')
|
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
stop_ts_tod = tb.get_ts_tod_ns()
|
||||||
stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
stop_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
time_delta = stop_time-start_time
|
time_delta = stop_time-start_time
|
||||||
ts_tod_delta = stop_ts_tod-start_ts_tod
|
ts_tod_delta = stop_ts_tod-start_ts_tod
|
||||||
ts_rel_delta = stop_ts_rel-start_ts_rel
|
ts_rel_delta = stop_ts_rel-start_ts_rel
|
||||||
|
|
||||||
tb.log.info("sim time delta : %g s", time_delta)
|
tb.log.info("sim time delta : %s ns", time_delta)
|
||||||
tb.log.info("ToD ts delta : %g s", ts_tod_delta)
|
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
|
||||||
tb.log.info("rel ts delta : %g s", ts_rel_delta)
|
tb.log.info("rel ts delta : %s ns", ts_rel_delta)
|
||||||
|
|
||||||
ts_tod_diff = time_delta - ts_tod_delta
|
ts_tod_diff = time_delta - ts_tod_delta
|
||||||
ts_rel_diff = time_delta - ts_rel_delta
|
ts_rel_diff = time_delta - ts_rel_delta
|
||||||
|
|
||||||
tb.log.info("ToD ts diff : %g s", ts_tod_diff)
|
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
|
||||||
tb.log.info("rel ts diff : %g s", ts_rel_diff)
|
tb.log.info("rel ts diff : %s ns", ts_rel_diff)
|
||||||
|
|
||||||
assert abs(ts_tod_diff) < 1e-12
|
assert abs(ts_tod_diff) < 1e-3
|
||||||
assert abs(ts_rel_diff) < 1e-12
|
assert abs(ts_rel_diff) < 1e-3
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
@@ -166,9 +175,9 @@ async def run_seconds_increment(dut):
|
|||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
|
|
||||||
start_time = get_sim_time('sec')
|
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
start_ts_tod = tb.get_ts_tod_ns()
|
||||||
start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
start_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
saw_pps = False
|
saw_pps = False
|
||||||
|
|
||||||
@@ -182,26 +191,26 @@ async def run_seconds_increment(dut):
|
|||||||
|
|
||||||
assert saw_pps
|
assert saw_pps
|
||||||
|
|
||||||
stop_time = get_sim_time('sec')
|
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
stop_ts_tod = tb.get_ts_tod_ns()
|
||||||
stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
stop_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
time_delta = stop_time-start_time
|
time_delta = stop_time-start_time
|
||||||
ts_tod_delta = stop_ts_tod-start_ts_tod
|
ts_tod_delta = stop_ts_tod-start_ts_tod
|
||||||
ts_rel_delta = stop_ts_rel-start_ts_rel
|
ts_rel_delta = stop_ts_rel-start_ts_rel
|
||||||
|
|
||||||
tb.log.info("sim time delta : %g s", time_delta)
|
tb.log.info("sim time delta : %s ns", time_delta)
|
||||||
tb.log.info("ToD ts delta : %g s", ts_tod_delta)
|
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
|
||||||
tb.log.info("rel ts delta : %g s", ts_rel_delta)
|
tb.log.info("rel ts delta : %s ns", ts_rel_delta)
|
||||||
|
|
||||||
ts_tod_diff = time_delta - ts_tod_delta
|
ts_tod_diff = time_delta - ts_tod_delta
|
||||||
ts_rel_diff = time_delta - ts_rel_delta
|
ts_rel_diff = time_delta - ts_rel_delta
|
||||||
|
|
||||||
tb.log.info("ToD ts diff : %g s", ts_tod_diff)
|
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
|
||||||
tb.log.info("rel ts diff : %g s", ts_rel_diff)
|
tb.log.info("rel ts diff : %s ns", ts_rel_diff)
|
||||||
|
|
||||||
assert abs(ts_tod_diff) < 1e-12
|
assert abs(ts_tod_diff) < 1e-3
|
||||||
assert abs(ts_rel_diff) < 1e-12
|
assert abs(ts_rel_diff) < 1e-3
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
@@ -214,36 +223,35 @@ async def run_frequency_adjustment(dut):
|
|||||||
|
|
||||||
await tb.reset()
|
await tb.reset()
|
||||||
|
|
||||||
tb.ptp_clock.period_ns = 0x6
|
tb.ptp_clock.set_period(0x6, 0x66240000)
|
||||||
tb.ptp_clock.period_fns = 0x6624
|
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
start_time = get_sim_time('sec')
|
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
start_ts_tod = tb.get_ts_tod_ns()
|
||||||
start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
start_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
await ClockCycles(dut.clk, 10000)
|
await ClockCycles(dut.clk, 10000)
|
||||||
|
|
||||||
stop_time = get_sim_time('sec')
|
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
stop_ts_tod = tb.get_ts_tod_ns()
|
||||||
stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
stop_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
time_delta = stop_time-start_time
|
time_delta = stop_time-start_time
|
||||||
ts_tod_delta = stop_ts_tod-start_ts_tod
|
ts_tod_delta = stop_ts_tod-start_ts_tod
|
||||||
ts_rel_delta = stop_ts_rel-start_ts_rel
|
ts_rel_delta = stop_ts_rel-start_ts_rel
|
||||||
|
|
||||||
tb.log.info("sim time delta : %g s", time_delta)
|
tb.log.info("sim time delta : %s ns", time_delta)
|
||||||
tb.log.info("ToD ts delta : %g s", ts_tod_delta)
|
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
|
||||||
tb.log.info("rel ts delta : %g s", ts_rel_delta)
|
tb.log.info("rel ts delta : %s ns", ts_rel_delta)
|
||||||
|
|
||||||
ts_tod_diff = time_delta - ts_tod_delta * 6.4/(6+(0x6624+2/5)/2**16)
|
ts_tod_diff = time_delta - ts_tod_delta * Decimal(6.4)/tb.ptp_clock.get_period_ns()
|
||||||
ts_rel_diff = time_delta - ts_rel_delta * 6.4/(6+(0x6624+2/5)/2**16)
|
ts_rel_diff = time_delta - ts_rel_delta * Decimal(6.4)/tb.ptp_clock.get_period_ns()
|
||||||
|
|
||||||
tb.log.info("ToD ts diff : %g s", ts_tod_diff)
|
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
|
||||||
tb.log.info("rel ts diff : %g s", ts_rel_diff)
|
tb.log.info("rel ts diff : %s ns", ts_rel_diff)
|
||||||
|
|
||||||
assert abs(ts_tod_diff) < 1e-12
|
assert abs(ts_tod_diff) < 1e-3
|
||||||
assert abs(ts_rel_diff) < 1e-12
|
assert abs(ts_rel_diff) < 1e-3
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
@@ -256,36 +264,35 @@ async def run_drift_adjustment(dut):
|
|||||||
|
|
||||||
await tb.reset()
|
await tb.reset()
|
||||||
|
|
||||||
tb.ptp_clock.drift_num = 20
|
tb.ptp_clock.set_drift(20000, 5)
|
||||||
tb.ptp_clock.drift_denom = 5
|
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
start_time = get_sim_time('sec')
|
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
start_ts_tod = tb.get_ts_tod_ns()
|
||||||
start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
start_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
await ClockCycles(dut.clk, 10000)
|
await ClockCycles(dut.clk, 10000)
|
||||||
|
|
||||||
stop_time = get_sim_time('sec')
|
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
stop_ts_tod = tb.get_ts_tod_ns()
|
||||||
stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
stop_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
time_delta = stop_time-start_time
|
time_delta = stop_time-start_time
|
||||||
ts_tod_delta = stop_ts_tod-start_ts_tod
|
ts_tod_delta = stop_ts_tod-start_ts_tod
|
||||||
ts_rel_delta = stop_ts_rel-start_ts_rel
|
ts_rel_delta = stop_ts_rel-start_ts_rel
|
||||||
|
|
||||||
tb.log.info("sim time delta : %g s", time_delta)
|
tb.log.info("sim time delta : %s ns", time_delta)
|
||||||
tb.log.info("ToD ts delta : %g s", ts_tod_delta)
|
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
|
||||||
tb.log.info("rel ts delta : %g s", ts_rel_delta)
|
tb.log.info("rel ts delta : %s ns", ts_rel_delta)
|
||||||
|
|
||||||
ts_tod_diff = time_delta - ts_tod_delta * 6.4/(6+(0x6666+20/5)/2**16)
|
ts_tod_diff = time_delta - ts_tod_delta * Decimal(6.4)/tb.ptp_clock.get_period_ns()
|
||||||
ts_rel_diff = time_delta - ts_rel_delta * 6.4/(6+(0x6666+20/5)/2**16)
|
ts_rel_diff = time_delta - ts_rel_delta * Decimal(6.4)/tb.ptp_clock.get_period_ns()
|
||||||
|
|
||||||
tb.log.info("ToD ts diff : %g s", ts_tod_diff)
|
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
|
||||||
tb.log.info("rel ts diff : %g s", ts_rel_diff)
|
tb.log.info("rel ts diff : %s ns", ts_rel_diff)
|
||||||
|
|
||||||
assert abs(ts_tod_diff) < 1e-12
|
assert abs(ts_tod_diff) < 1e-3
|
||||||
assert abs(ts_rel_diff) < 1e-12
|
assert abs(ts_rel_diff) < 1e-3
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
import cocotb_test.simulator
|
import cocotb_test.simulator
|
||||||
|
|
||||||
@@ -52,6 +53,14 @@ class TB:
|
|||||||
clock=dut.clk
|
clock=dut.clk
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_ts_tod_ns(self):
|
||||||
|
ts = self.dut.ts_tod.value.integer
|
||||||
|
return Decimal(ts >> 48).scaleb(9) + (Decimal(ts & 0xffffffffffff) / Decimal(2**16))
|
||||||
|
|
||||||
|
def get_ts_rel_ns(self):
|
||||||
|
ts = self.dut.ts_rel.value.integer
|
||||||
|
return Decimal(ts) / Decimal(2**16)
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test()
|
@cocotb.test()
|
||||||
async def run_test(dut):
|
async def run_test(dut):
|
||||||
@@ -62,32 +71,32 @@ async def run_test(dut):
|
|||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
start_time = get_sim_time('sec')
|
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
start_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
start_ts_tod = tb.get_ts_tod_ns()
|
||||||
start_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
start_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
await ClockCycles(dut.clk, 10000)
|
await ClockCycles(dut.clk, 10000)
|
||||||
|
|
||||||
stop_time = get_sim_time('sec')
|
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
|
||||||
stop_ts_tod = (dut.ts_tod.value.integer >> 48) + ((dut.ts_tod.value.integer & 0xffffffffffff)/2**16*1e-9)
|
stop_ts_tod = tb.get_ts_tod_ns()
|
||||||
stop_ts_rel = dut.ts_rel.value.integer/2**16*1e-9
|
stop_ts_rel = tb.get_ts_rel_ns()
|
||||||
|
|
||||||
time_delta = stop_time-start_time
|
time_delta = stop_time-start_time
|
||||||
ts_tod_delta = stop_ts_tod-start_ts_tod
|
ts_tod_delta = stop_ts_tod-start_ts_tod
|
||||||
ts_rel_delta = stop_ts_rel-start_ts_rel
|
ts_rel_delta = stop_ts_rel-start_ts_rel
|
||||||
|
|
||||||
tb.log.info("sim time delta : %g s", time_delta)
|
tb.log.info("sim time delta : %s ns", time_delta)
|
||||||
tb.log.info("ToD ts delta : %g s", ts_tod_delta)
|
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
|
||||||
tb.log.info("rel ts delta : %g s", ts_rel_delta)
|
tb.log.info("rel ts delta : %s ns", ts_rel_delta)
|
||||||
|
|
||||||
ts_tod_diff = time_delta - ts_tod_delta
|
ts_tod_diff = time_delta - ts_tod_delta
|
||||||
ts_rel_diff = time_delta - ts_rel_delta
|
ts_rel_diff = time_delta - ts_rel_delta
|
||||||
|
|
||||||
tb.log.info("ToD ts diff : %g s", ts_tod_diff)
|
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
|
||||||
tb.log.info("rel ts diff : %g s", ts_rel_diff)
|
tb.log.info("rel ts diff : %s ns", ts_rel_diff)
|
||||||
|
|
||||||
assert abs(ts_tod_diff) < 1e-12
|
assert abs(ts_tod_diff) < 1e-3
|
||||||
assert abs(ts_rel_diff) < 1e-12
|
assert abs(ts_rel_diff) < 1e-3
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
|
|||||||
Reference in New Issue
Block a user