self._append("{}attribute \\{} {}\n",
" " * indent, name, int(value))
- def _src(self, src):
+ def _src(self, src, **kwargs):
if src:
- self.attribute("src", src)
+ self.attribute("src", src, **kwargs)
class _Builder(_Namer, _Bufferer):
self.src = src
def __enter__(self):
- self._src(self.src)
+ self._src(self.src, indent=1)
self._append(" process {}\n", self.name)
return self
return "{}:{}".format(file, line)
+def srcs(src_locs):
+ return "|".join(sorted(map(src, src_locs)))
+
+
class LegalizeValue(Exception):
def __init__(self, value, branches):
self.value = value
raise TypeError # :nocov:
+class _StatementLocator(xfrm.StatementVisitor):
+ def __init__(self):
+ self.src_locs = set()
+
+ def on_Assign(self, stmt):
+ self.src_locs.add(stmt.src_loc)
+
+ def on_Switch(self, stmt):
+ self.src_locs.add(stmt.src_loc)
+ for stmts in stmt.cases.values():
+ self.on_statements(stmts)
+
+ def on_ignored(self, stmt):
+ pass
+
+ on_Assert = on_ignored
+ on_Assume = on_ignored
+
+ def on_statements(self, stmts):
+ for stmt in stmts:
+ self.on_statement(stmt)
+
+ def __call__(self, stmt):
+ self.on_statement(stmt)
+ src_locs, self.src_locs = self.src_locs, set()
+ return src_locs
+
+
class _StatementCompiler(xfrm.StatementVisitor):
def __init__(self, state, rhs_compiler, lhs_compiler):
self.state = state
compiler_state = _ValueCompilerState(module)
rhs_compiler = _RHSValueCompiler(compiler_state)
lhs_compiler = _LHSValueCompiler(compiler_state)
+ stmt_locator = _StatementLocator()
stmt_compiler = _StatementCompiler(compiler_state, rhs_compiler, lhs_compiler)
verilog_trigger = None
for group, group_signals in lhs_grouper.groups().items():
lhs_group_filter = xfrm.LHSGroupFilter(group_signals)
+ group_stmts = lhs_group_filter(fragment.statements)
- with module.process(name="$group_{}".format(group)) as process:
+ with module.process(name="$group_{}".format(group),
+ src=srcs(stmt_locator(group_stmts))) as process:
with process.case() as case:
# For every signal in comb domain, assign \sig$next to the reset value.
# For every signal in sync domains, assign \sig$next to the current
# Convert statements into decision trees.
stmt_compiler._case = case
stmt_compiler._has_rhs = False
- stmt_compiler(lhs_group_filter(fragment.statements))
+ stmt_compiler(group_stmts)
# Verilog `always @*` blocks will not run if `*` does not match anything, i.e.
# if the implicit sensitivity list is empty. We check this while translating,
Assign
Assignment statement that can be used in combinatorial or synchronous context.
"""
- return Assign(self, value)
+ return Assign(self, value, src_loc_at=1)
@abstractmethod
def shape(self):
@final
class Assign(Statement):
- def __init__(self, lhs, rhs):
+ def __init__(self, lhs, rhs, src_loc_at=0):
+ self.src_loc = tracer.get_src_loc(src_loc_at)
+
self.lhs = Value.wrap(lhs)
self.rhs = Value.wrap(rhs)
# @final
class Switch(Statement):
- def __init__(self, test, cases):
+ def __init__(self, test, cases, src_loc_at=0):
+ self.src_loc = tracer.get_src_loc(src_loc_at)
+
self.test = Value.wrap(test)
self.cases = OrderedDict()
for keys, stmts in cases.items():
raise SyntaxError("`m.next = <...>` is only permitted inside an FSM state")
def _pop_ctrl(self):
+ # FIXME: the src_loc extraction unfortunately doesn't work very well here; src_loc_at=3 is
+ # correct, but the resulting src_loc points at the *last* line of the `with` block.
+ # Unfortunately, it is not clear how this can be fixed.
+
name, data = self._ctrl_stack.pop()
if name == "If":
match = None
cases[match] = if_case
- self._statements.append(Switch(Cat(tests), cases))
+ self._statements.append(Switch(Cat(tests), cases, src_loc_at=3))
if name == "Switch":
switch_test, switch_cases = data["test"], data["cases"]
- self._statements.append(Switch(switch_test, switch_cases))
+ self._statements.append(Switch(switch_test, switch_cases, src_loc_at=3))
if name == "FSM":
fsm_signal, fsm_reset, fsm_encoding, fsm_decoding, fsm_states = \
fsm_decoding.update((n, s) for s, n in fsm_encoding.items())
fsm_signal.decoder = lambda n: "{}/{}".format(fsm_decoding[n], n)
self._statements.append(Switch(fsm_signal,
- OrderedDict((fsm_encoding[name], stmts) for name, stmts in fsm_states.items())))
+ OrderedDict((fsm_encoding[name], stmts) for name, stmts in fsm_states.items()),
+ src_loc_at=3))
def _add_statement(self, assigns, domain, depth, compat_mode=False):
def domain_name(domain):