else:
clk_state = self.state.slots[self.slot]
clk_state.set(not clk_state.curr)
- self.state.wait_interval(self, self.period / 2)
+ self.state.wait_interval(self, self.period // 2)
return
elif type(command) is Delay:
- self.state.wait_interval(self, command.interval)
+ # Internal timeline is in 1ps integeral units, intervals are public API and in floating point
+ interval = int(command.interval * 1e12) if command.interval is not None else None
+ self.state.wait_interval(self, interval)
return
elif type(command) is Passive:
if domain in self._clocked:
raise ValueError("Domain {!r} already has a clock driving it"
.format(domain.name))
+
+ # We represent times internally in 1 ps units, but users supply float quantities of seconds
+ period = int(period * 1e12)
if phase is None:
# By default, delay the first edge by half period. This causes any synchronous activity
# to happen at a non-zero time, distinguishing it from the reset values in the waveform
# viewer.
- phase = period / 2
+ phase = period // 2
self._engine.add_clock_process(domain.clk, phase=phase, period=period)
self._clocked.add(domain)
If the simulation stops advancing, this function will never return.
"""
+ # Convert deadline in seconds into internal 1 ps units
+ deadline = deadline * 1e12
assert self._engine.now <= deadline
while (self.advance() or run_passive) and self._engine.now < deadline:
pass
traces : iterable of Signal
Signals to display traces for.
"""
- if self._engine.now != 0.0:
+ if self._engine.now != 0:
for file in (vcd_file, gtkw_file):
if hasattr(file, "close"):
file.close()
class _VCDWriter:
- @staticmethod
- def timestamp_to_vcd(timestamp):
- return timestamp * (10 ** 10) # 1/(100 ps)
-
@staticmethod
def decode_to_vcd(signal, value):
return signal.decoder(value).expandtabs().replace(" ", "_")
self.vcd_vars = SignalDict()
self.vcd_file = vcd_file
self.vcd_writer = vcd_file and VCDWriter(self.vcd_file,
- timescale="100 ps", comment="Generated by nMigen")
+ timescale="1 ps", comment="Generated by nMigen")
self.gtkw_names = SignalDict()
self.gtkw_file = gtkw_file
if vcd_var is None:
return
- vcd_timestamp = self.timestamp_to_vcd(timestamp)
if signal.decoder:
var_value = self.decode_to_vcd(signal, value)
else:
var_value = value
- self.vcd_writer.change(vcd_var, vcd_timestamp, var_value)
+ self.vcd_writer.change(vcd_var, timestamp, var_value)
def close(self, timestamp):
if self.vcd_writer is not None:
- self.vcd_writer.close(self.timestamp_to_vcd(timestamp))
+ self.vcd_writer.close(timestamp)
if self.gtkw_save is not None:
self.gtkw_save.dumpfile(self.vcd_file.name)
class _Timeline:
def __init__(self):
- self.now = 0.0
+ self.now = 0
self.deadlines = dict()
def reset(self):
- self.now = 0.0
+ self.now = 0
self.deadlines.clear()
def at(self, run_at, process):
self.fail()
sim.add_process(process)
+ def test_run_until_fail(self):
+ m = Module()
+ s = Signal()
+ m.d.sync += s.eq(0)
+ with self.assertRaises(AssertionError):
+ with self.assertSimulation(m, deadline=100e-6) as sim:
+ sim.add_clock(1e-6)
+ def process():
+ for _ in range(99):
+ yield Delay(1e-6)
+ self.fail()
+ sim.add_process(process)
+
def test_add_process_wrong(self):
with self.assertSimulation(Module()) as sim:
with self.assertRaisesRegex(TypeError,