Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: b471e33d7f79
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 82903e493a63
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on Jul 3, 2019

  1. hdl.ast: fix src_loc_at for Mux().

    whitequark committed Jul 3, 2019
    Copy the full SHA
    e351e27 View commit details
  2. 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.
    whitequark committed Jul 3, 2019
    Copy the full SHA
    82903e4 View commit details
Showing with 58 additions and 14 deletions.
  1. +40 −5 nmigen/back/rtlil.py
  2. +8 −4 nmigen/hdl/ast.py
  3. +8 −3 nmigen/hdl/dsl.py
  4. +2 −2 nmigen/hdl/xfrm.py
45 changes: 40 additions & 5 deletions nmigen/back/rtlil.py
Original file line number Diff line number Diff line change
@@ -55,9 +55,9 @@ def attribute(self, name, value, indent=0):
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 @@ def __init__(self, rtlil, name, src):
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 @@ def on_Repl(self, 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
@@ -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,
12 changes: 8 additions & 4 deletions nmigen/hdl/ast.py
Original file line number Diff line number Diff line change
@@ -178,7 +178,7 @@ def eq(self, value):
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):
@@ -390,7 +390,7 @@ def Mux(sel, val1, val0):
Value, out
Output ``Value``. If ``sel`` is asserted, the Mux returns ``val1``, else ``val0``.
"""
return Operator("m", [sel, val1, val0], src_loc_at=1)
return Operator("m", [sel, val1, val0])


@final
@@ -975,7 +975,9 @@ def wrap(obj):

@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():
11 changes: 8 additions & 3 deletions nmigen/hdl/dsl.py
Original file line number Diff line number Diff line change
@@ -304,6 +304,10 @@ def next(self, name):
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 @@ def _pop_ctrl(self):
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 @@ def _pop_ctrl(self):
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):
4 changes: 2 additions & 2 deletions nmigen/hdl/xfrm.py
Original file line number Diff line number Diff line change
@@ -211,8 +211,8 @@ def on_statement(self, stmt):
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):