back.rtlil: emit \src attributes for processes via Switch and Assign.
The locations are unfortunately not very precise, but they provide some improvement over status quo.
This commit is contained in:
parent
e351e27206
commit
82903e493a
|
@ -55,9 +55,9 @@ class _Bufferer:
|
|||
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):
|
||||
|
@ -142,7 +142,7 @@ class _ProcessBuilder(_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
|
||||
|
||||
|
@ -222,6 +222,10 @@ def src(src_loc):
|
|||
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
|
||||
|
@ -579,6 +583,34 @@ class _LHSValueCompiler(_ValueCompiler):
|
|||
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
|
||||
|
@ -689,6 +721,7 @@ def convert_fragment(builder, fragment, hierarchy):
|
|||
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
|
||||
|
@ -778,8 +811,10 @@ def convert_fragment(builder, fragment, hierarchy):
|
|||
|
||||
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
|
||||
|
@ -796,7 +831,7 @@ def convert_fragment(builder, fragment, hierarchy):
|
|||
# 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,
|
||||
|
|
|
@ -178,7 +178,7 @@ class Value(metaclass=ABCMeta):
|
|||
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):
|
||||
|
@ -975,7 +975,9 @@ class Statement:
|
|||
|
||||
@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)
|
||||
|
||||
|
@ -1027,7 +1029,9 @@ class Assume(Property):
|
|||
|
||||
# @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():
|
||||
|
|
|
@ -304,6 +304,10 @@ class Module(_ModuleBuilderRoot, Elaboratable):
|
|||
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":
|
||||
|
@ -323,12 +327,12 @@ class Module(_ModuleBuilderRoot, Elaboratable):
|
|||
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 = \
|
||||
|
@ -342,7 +346,8 @@ class Module(_ModuleBuilderRoot, Elaboratable):
|
|||
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):
|
||||
|
|
|
@ -211,8 +211,8 @@ class StatementVisitor(metaclass=ABCMeta):
|
|||
new_stmt.src_loc = stmt.src_loc
|
||||
return new_stmt
|
||||
|
||||
def __call__(self, value):
|
||||
return self.on_statement(value)
|
||||
def __call__(self, stmt):
|
||||
return self.on_statement(stmt)
|
||||
|
||||
|
||||
class StatementTransformer(StatementVisitor):
|
||||
|
|
Loading…
Reference in a new issue