back.pysim: accept any valid assignments from processes.
This commit is contained in:
parent
240a40c2c2
commit
105113f1d8
|
@ -68,10 +68,10 @@ class _RHSValueCompiler(ValueTransformer):
|
||||||
return lambda state: state.get(value)
|
return lambda state: state.get(value)
|
||||||
|
|
||||||
def on_ClockSignal(self, value):
|
def on_ClockSignal(self, value):
|
||||||
raise NotImplementedError
|
raise NotImplementedError # :nocov:
|
||||||
|
|
||||||
def on_ResetSignal(self, value):
|
def on_ResetSignal(self, value):
|
||||||
raise NotImplementedError
|
raise NotImplementedError # :nocov:
|
||||||
|
|
||||||
def on_Operator(self, value):
|
def on_Operator(self, value):
|
||||||
shape = value.shape()
|
shape = value.shape()
|
||||||
|
@ -406,46 +406,57 @@ class Simulator:
|
||||||
self._commit_signal(signal, domains)
|
self._commit_signal(signal, domains)
|
||||||
|
|
||||||
# Wake up any simulator processes that wait for a domain tick.
|
# Wake up any simulator processes that wait for a domain tick.
|
||||||
for proc, wait_domain in list(self._wait_tick.items()):
|
for process, wait_domain in list(self._wait_tick.items()):
|
||||||
if domain == wait_domain:
|
if domain == wait_domain:
|
||||||
del self._wait_tick[proc]
|
del self._wait_tick[process]
|
||||||
self._suspended.remove(proc)
|
self._suspended.remove(process)
|
||||||
|
|
||||||
# Unless handling synchronous logic above has triggered more synchronous logic (which
|
# Unless handling synchronous logic above has triggered more synchronous logic (which
|
||||||
# can happen e.g. if a domain is clocked off a clock divisor in fabric), we're done.
|
# can happen e.g. if a domain is clocked off a clock divisor in fabric), we're done.
|
||||||
# Otherwise, do one more round of updates.
|
# Otherwise, do one more round of updates.
|
||||||
|
|
||||||
def _force_signal(self, signal, value):
|
def _run_process(self, process):
|
||||||
assert signal in self._user_signals
|
|
||||||
self._state.set_next(signal, value)
|
|
||||||
|
|
||||||
domains = set()
|
|
||||||
self._commit_signal(signal, domains)
|
|
||||||
self._commit_sync_signals(domains)
|
|
||||||
|
|
||||||
def _run_process(self, proc):
|
|
||||||
try:
|
try:
|
||||||
stmt = proc.send(None)
|
stmt = process.send(None)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
self._processes.remove(proc)
|
self._processes.remove(process)
|
||||||
self._passive.discard(proc)
|
self._passive.discard(process)
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(stmt, Delay):
|
if isinstance(stmt, Delay):
|
||||||
self._wait_deadline[proc] = self._timestamp + stmt.interval
|
self._wait_deadline[process] = self._timestamp + stmt.interval
|
||||||
self._suspended.add(proc)
|
self._suspended.add(process)
|
||||||
|
|
||||||
elif isinstance(stmt, Tick):
|
elif isinstance(stmt, Tick):
|
||||||
self._wait_tick[proc] = stmt.domain
|
self._wait_tick[process] = stmt.domain
|
||||||
self._suspended.add(proc)
|
self._suspended.add(process)
|
||||||
|
|
||||||
elif isinstance(stmt, Passive):
|
elif isinstance(stmt, Passive):
|
||||||
self._passive.add(proc)
|
self._passive.add(process)
|
||||||
|
|
||||||
elif isinstance(stmt, Assign):
|
elif isinstance(stmt, Assign):
|
||||||
assert isinstance(stmt.lhs, Signal)
|
lhs_signals = stmt.lhs._lhs_signals()
|
||||||
assert isinstance(stmt.rhs, Const)
|
for signal in lhs_signals:
|
||||||
self._force_signal(stmt.lhs, normalize(stmt.rhs.value, stmt.lhs.shape()))
|
if not signal in self._signals:
|
||||||
|
raise ValueError("Process {!r} sent a request to set signal '{!r}', "
|
||||||
|
"which is not a part of simulation"
|
||||||
|
.format(process, signal))
|
||||||
|
if signal in self._comb_signals:
|
||||||
|
raise ValueError("Process {!r} sent a request to set signal '{!r}', "
|
||||||
|
"which is a part of combinatorial assignment in simulation"
|
||||||
|
.format(process, signal))
|
||||||
|
|
||||||
|
funclet = _StatementCompiler()(stmt)
|
||||||
|
funclet(self._state)
|
||||||
|
|
||||||
|
domains = set()
|
||||||
|
for signal in lhs_signals:
|
||||||
|
self._commit_signal(signal, domains)
|
||||||
|
self._commit_sync_signals(domains)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise TypeError("Received unsupported statement '{!r}' from process {}"
|
raise TypeError("Received unsupported statement '{!r}' from process {!r}"
|
||||||
.format(stmt, proc))
|
.format(stmt, process))
|
||||||
|
|
||||||
def step(self, run_passive=False):
|
def step(self, run_passive=False):
|
||||||
deadline = None
|
deadline = None
|
||||||
|
@ -470,8 +481,8 @@ class Simulator:
|
||||||
# Are there any processes that haven't had a chance to run yet?
|
# Are there any processes that haven't had a chance to run yet?
|
||||||
if len(self._processes) > len(self._suspended):
|
if len(self._processes) > len(self._suspended):
|
||||||
# Schedule an arbitrary one.
|
# Schedule an arbitrary one.
|
||||||
proc = (self._processes - set(self._suspended)).pop()
|
process = (self._processes - set(self._suspended)).pop()
|
||||||
self._run_process(proc)
|
self._run_process(process)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# All processes are suspended. Are any of them active?
|
# All processes are suspended. Are any of them active?
|
||||||
|
@ -479,11 +490,11 @@ class Simulator:
|
||||||
# Are any of them suspended before a deadline?
|
# Are any of them suspended before a deadline?
|
||||||
if self._wait_deadline:
|
if self._wait_deadline:
|
||||||
# Schedule the one with the lowest deadline.
|
# Schedule the one with the lowest deadline.
|
||||||
proc, deadline = min(self._wait_deadline.items(), key=lambda x: x[1])
|
process, deadline = min(self._wait_deadline.items(), key=lambda x: x[1])
|
||||||
del self._wait_deadline[proc]
|
del self._wait_deadline[process]
|
||||||
self._suspended.remove(proc)
|
self._suspended.remove(process)
|
||||||
self._timestamp = deadline
|
self._timestamp = deadline
|
||||||
self._run_process(proc)
|
self._run_process(process)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# No processes, or all processes are passive. Nothing to do!
|
# No processes, or all processes are passive. Nothing to do!
|
||||||
|
|
Loading…
Reference in a new issue