Skip to content

Commit

Permalink
back.pysim: implement blocking assignment semantics correctly.
Browse files Browse the repository at this point in the history
  • Loading branch information
whitequark committed Dec 14, 2018
1 parent 120d817 commit 70ebc6f
Showing 1 changed file with 33 additions and 13 deletions.
46 changes: 33 additions & 13 deletions nmigen/back/pysim.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import math
import inspect
from contextlib import contextmanager
from vcd import VCDWriter
from vcd.gtkw import GTKWSave

Expand All @@ -24,9 +25,6 @@ def __init__(self):
self.curr_dirty = ValueSet()
self.next_dirty = ValueSet()

def get(self, signal):
return self.curr[signal]

def set(self, signal, value):
assert isinstance(value, int)
if self.next[signal] != value:
Expand All @@ -47,15 +45,21 @@ def commit(self, signal):


class _RHSValueCompiler(ValueTransformer):
def __init__(self, sensitivity):
def __init__(self, sensitivity=None):
self.sensitivity = sensitivity
self.signal_mode = "next"

def on_Const(self, value):
return lambda state: value.value

def on_Signal(self, value):
self.sensitivity.add(value)
return lambda state: state.get(value)
if self.sensitivity:
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):
raise NotImplementedError # :nocov:
Expand Down Expand Up @@ -147,6 +151,14 @@ def __init__(self):
self.sensitivity = ValueSet()
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):
# TODO
return lambda state, arg: state.set(value, arg)
Expand Down Expand Up @@ -342,20 +354,28 @@ def add_fragment(fragment, scope=("top",)):
self._sync_signals.update(signals)
self._domain_signals[domain].update(signals)

statements = []
initial_stmts = []
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():
statements.append(signal.eq(signal))
statements += fragment.statements
initial_stmts.append(signal.eq(signal))

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):
if signal not in self._funclets:
self._funclets[signal] = set()
self._funclets[signal].add(funclet)

compiler = _StatementCompiler()
funclet = compiler(statements)
for signal in compiler.sensitivity:
add_funclet(signal, funclet)
for domain, cd in fragment.domains.items():
Expand Down Expand Up @@ -464,7 +484,7 @@ def format_process(process):
self._passive.add(process)

elif isinstance(cmd, Value):
funclet = _RHSValueCompiler(sensitivity=ValueSet())(cmd)
funclet = _RHSValueCompiler()(cmd)
cmd = process.send(funclet(self._state))
continue

Expand Down

0 comments on commit 70ebc6f

Please sign in to comment.