back.pysim: implement blocking assignment semantics correctly.
This commit is contained in:
parent
120d817123
commit
70ebc6f2c1
|
@ -1,5 +1,6 @@
|
||||||
import math
|
import math
|
||||||
import inspect
|
import inspect
|
||||||
|
from contextlib import contextmanager
|
||||||
from vcd import VCDWriter
|
from vcd import VCDWriter
|
||||||
from vcd.gtkw import GTKWSave
|
from vcd.gtkw import GTKWSave
|
||||||
|
|
||||||
|
@ -24,9 +25,6 @@ class _State:
|
||||||
self.curr_dirty = ValueSet()
|
self.curr_dirty = ValueSet()
|
||||||
self.next_dirty = ValueSet()
|
self.next_dirty = ValueSet()
|
||||||
|
|
||||||
def get(self, signal):
|
|
||||||
return self.curr[signal]
|
|
||||||
|
|
||||||
def set(self, signal, value):
|
def set(self, signal, value):
|
||||||
assert isinstance(value, int)
|
assert isinstance(value, int)
|
||||||
if self.next[signal] != value:
|
if self.next[signal] != value:
|
||||||
|
@ -47,15 +45,21 @@ normalize = Const.normalize
|
||||||
|
|
||||||
|
|
||||||
class _RHSValueCompiler(ValueTransformer):
|
class _RHSValueCompiler(ValueTransformer):
|
||||||
def __init__(self, sensitivity):
|
def __init__(self, sensitivity=None):
|
||||||
self.sensitivity = sensitivity
|
self.sensitivity = sensitivity
|
||||||
|
self.signal_mode = "next"
|
||||||
|
|
||||||
def on_Const(self, value):
|
def on_Const(self, value):
|
||||||
return lambda state: value.value
|
return lambda state: value.value
|
||||||
|
|
||||||
def on_Signal(self, value):
|
def on_Signal(self, value):
|
||||||
self.sensitivity.add(value)
|
if self.sensitivity:
|
||||||
return lambda state: state.get(value)
|
self.sensitivity.add(value)
|
||||||
|
if self.signal_mode == "curr":
|
||||||
|
return lambda state: state.curr[value]
|
||||||
|
if self.signal_mode == "next":
|
||||||
|
return lambda state: state.next[value]
|
||||||
|
raise NotImplementedError # :nocov:
|
||||||
|
|
||||||
def on_ClockSignal(self, value):
|
def on_ClockSignal(self, value):
|
||||||
raise NotImplementedError # :nocov:
|
raise NotImplementedError # :nocov:
|
||||||
|
@ -147,6 +151,14 @@ class _StatementCompiler(StatementTransformer):
|
||||||
self.sensitivity = ValueSet()
|
self.sensitivity = ValueSet()
|
||||||
self.rhs_compiler = _RHSValueCompiler(self.sensitivity)
|
self.rhs_compiler = _RHSValueCompiler(self.sensitivity)
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def initial(self):
|
||||||
|
try:
|
||||||
|
self.rhs_compiler.signal_mode = "curr"
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
self.rhs_compiler.signal_mode = "next"
|
||||||
|
|
||||||
def lhs_compiler(self, value):
|
def lhs_compiler(self, value):
|
||||||
# TODO
|
# TODO
|
||||||
return lambda state, arg: state.set(value, arg)
|
return lambda state, arg: state.set(value, arg)
|
||||||
|
@ -342,20 +354,28 @@ class Simulator:
|
||||||
self._sync_signals.update(signals)
|
self._sync_signals.update(signals)
|
||||||
self._domain_signals[domain].update(signals)
|
self._domain_signals[domain].update(signals)
|
||||||
|
|
||||||
statements = []
|
initial_stmts = []
|
||||||
for signal in fragment.iter_comb():
|
for signal in fragment.iter_comb():
|
||||||
statements.append(signal.eq(signal.reset))
|
initial_stmts.append(signal.eq(signal.reset))
|
||||||
for domain, signal in fragment.iter_sync():
|
for domain, signal in fragment.iter_sync():
|
||||||
statements.append(signal.eq(signal))
|
initial_stmts.append(signal.eq(signal))
|
||||||
statements += fragment.statements
|
|
||||||
|
compiler = _StatementCompiler()
|
||||||
|
def make_funclet():
|
||||||
|
with compiler.initial():
|
||||||
|
funclet_init = compiler(initial_stmts)
|
||||||
|
funclet_frag = compiler(fragment.statements)
|
||||||
|
def funclet(state):
|
||||||
|
funclet_init(state)
|
||||||
|
funclet_frag(state)
|
||||||
|
return funclet
|
||||||
|
funclet = make_funclet()
|
||||||
|
|
||||||
def add_funclet(signal, funclet):
|
def add_funclet(signal, funclet):
|
||||||
if signal not in self._funclets:
|
if signal not in self._funclets:
|
||||||
self._funclets[signal] = set()
|
self._funclets[signal] = set()
|
||||||
self._funclets[signal].add(funclet)
|
self._funclets[signal].add(funclet)
|
||||||
|
|
||||||
compiler = _StatementCompiler()
|
|
||||||
funclet = compiler(statements)
|
|
||||||
for signal in compiler.sensitivity:
|
for signal in compiler.sensitivity:
|
||||||
add_funclet(signal, funclet)
|
add_funclet(signal, funclet)
|
||||||
for domain, cd in fragment.domains.items():
|
for domain, cd in fragment.domains.items():
|
||||||
|
@ -464,7 +484,7 @@ class Simulator:
|
||||||
self._passive.add(process)
|
self._passive.add(process)
|
||||||
|
|
||||||
elif isinstance(cmd, Value):
|
elif isinstance(cmd, Value):
|
||||||
funclet = _RHSValueCompiler(sensitivity=ValueSet())(cmd)
|
funclet = _RHSValueCompiler()(cmd)
|
||||||
cmd = process.send(funclet(self._state))
|
cmd = process.send(funclet(self._state))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue