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: 635094350ff4
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: b2f828387a3d
Choose a head ref
  • 3 commits
  • 2 files changed
  • 1 contributor

Commits on Dec 16, 2018

  1. back.rtlil: simplify. NFC.

    whitequark committed Dec 16, 2018
    Copy the full SHA
    b9a0af8 View commit details
  2. back.rtlil: extract _StatementCompiler. NFC.

    whitequark committed Dec 16, 2018
    Copy the full SHA
    91b7561 View commit details
  3. hdl.dsl: cleanup. NFC.

    whitequark committed Dec 16, 2018
    Copy the full SHA
    b2f8283 View commit details
Showing with 45 additions and 48 deletions.
  1. +45 −44 nmigen/back/rtlil.py
  2. +0 −4 nmigen/hdl/dsl.py
89 changes: 45 additions & 44 deletions nmigen/back/rtlil.py
Original file line number Diff line number Diff line change
@@ -210,7 +210,6 @@ def __init__(self, rtlil):
self.wires = ast.ValueDict()
self.driven = ast.ValueDict()
self.ports = ast.ValueDict()
self.sub_name = None

def add_driven(self, signal, sync):
self.driven[signal] = sync
@@ -225,16 +224,16 @@ def add_port(self, signal, kind):
kind = "inout"
self.ports[signal] = (len(self.ports), kind)

def resolve(self, signal):
def resolve(self, signal, prefix=None):
if signal in self.wires:
return self.wires[signal]

if signal in self.ports:
port_id, port_kind = self.ports[signal]
else:
port_id = port_kind = None
if self.sub_name:
wire_name = "{}_{}".format(self.sub_name, signal.name)
if prefix is not None:
wire_name = "{}_{}".format(prefix, signal.name)
else:
wire_name = signal.name

@@ -252,18 +251,10 @@ def resolve(self, signal):

return wire_curr, wire_next

def resolve_curr(self, signal):
wire_curr, wire_next = self.resolve(signal)
def resolve_curr(self, signal, prefix=None):
wire_curr, wire_next = self.resolve(signal, prefix)
return wire_curr

@contextmanager
def hierarchy(self, sub_name):
try:
self.sub_name = sub_name
yield
finally:
self.sub_name = None


class _ValueCompiler(xfrm.AbstractValueTransformer):
def __init__(self, state):
@@ -471,11 +462,42 @@ def on_ArrayProxy(self, value):
raise NotImplementedError


class _StatementCompiler(xfrm.AbstractStatementTransformer):
def __init__(self, rhs_compiler, lhs_compiler):
self.rhs_compiler = rhs_compiler
self.lhs_compiler = lhs_compiler

def on_Assign(self, stmt):
if isinstance(stmt, ast.Assign):
lhs_bits, lhs_sign = stmt.lhs.shape()
rhs_bits, rhs_sign = stmt.rhs.shape()
if lhs_bits == rhs_bits:
rhs_sigspec = self.rhs_compiler(stmt.rhs)
else:
# In RTLIL, LHS and RHS of assignment must have exactly same width.
rhs_sigspec = self.rhs_compiler.match_shape(
stmt.rhs, lhs_bits, rhs_sign)
self.case.assign(self.lhs_compiler(stmt.lhs), rhs_sigspec)

def on_Switch(self, stmt):
with self.case.switch(self.rhs_compiler(stmt.test)) as switch:
for value, stmts in stmt.cases.items():
old_case = self.case
with switch.case(value) as self.case:
self.on_statements(stmts)
self.case = old_case

def on_statements(self, stmts):
for stmt in stmts:
self.on_statement(stmt)


def convert_fragment(builder, fragment, name, top):
with builder.module(name or "anonymous", attrs={"top": 1} if top else {}) as module:
compiler_state = _ValueCompilerState(module)
rhs_compiler = _RHSValueCompiler(compiler_state)
lhs_compiler = _LHSValueCompiler(compiler_state)
stmt_compiler = _StatementCompiler(rhs_compiler, lhs_compiler)

# Register all signals driven in the current fragment. This must be done first, as it
# affects further codegen; e.g. whether sig$next signals will be generated and used.
@@ -486,25 +508,25 @@ def convert_fragment(builder, fragment, name, top):
# any hierarchy, to make sure they get sensible (non-prefixed) names.
for signal in fragment.ports:
compiler_state.add_port(signal, fragment.ports[signal])
rhs_compiler(signal)
compiler_state.resolve_curr(signal)

# Transform all clocks clocks and resets eagerly and outside of any hierarchy, to make
# sure they get sensible (non-prefixed) names. This does not affect semantics.
for domain, _ in fragment.iter_sync():
cd = fragment.domains[domain]
rhs_compiler(cd.clk)
rhs_compiler(cd.rst)
compiler_state.resolve_curr(cd.clk)
compiler_state.resolve_curr(cd.rst)

# Transform all subfragments to their respective cells. Transforming signals connected
# to their ports into wires eagerly makes sure they get sensible (prefixed with submodule
# name) names.
for subfragment, sub_name in fragment.subfragments:
sub_name, sub_port_map = \
convert_fragment(builder, subfragment, top=False, name=sub_name)
with compiler_state.hierarchy(sub_name):
module.cell(sub_name, name=sub_name, ports={
p: rhs_compiler(s) for p, s in sub_port_map.items()
})
module.cell(sub_name, name=sub_name, ports={
port: compiler_state.resolve_curr(signal, prefix=sub_name)
for port, signal in sub_port_map.items()
})

with module.process() as process:
with process.case() as case:
@@ -518,29 +540,8 @@ def convert_fragment(builder, fragment, name, top):
case.assign(lhs_compiler(signal), rhs_compiler(prev_value))

# Convert statements into decision trees.
def _convert_stmts(case, stmts):
for stmt in stmts:
if isinstance(stmt, ast.Assign):
lhs_bits, lhs_sign = stmt.lhs.shape()
rhs_bits, rhs_sign = stmt.rhs.shape()
if lhs_bits == rhs_bits:
rhs_sigspec = rhs_compiler(stmt.rhs)
else:
# In RTLIL, LHS and RHS of assignment must have exactly same width.
rhs_sigspec = rhs_compiler.match_shape(
stmt.rhs, lhs_bits, rhs_sign)
case.assign(lhs_compiler(stmt.lhs), rhs_sigspec)

elif isinstance(stmt, ast.Switch):
with case.switch(rhs_compiler(stmt.test)) as switch:
for value, nested_stmts in stmt.cases.items():
with switch.case(value) as nested_case:
_convert_stmts(nested_case, nested_stmts)

else:
raise TypeError

_convert_stmts(case, fragment.statements)
stmt_compiler.case = case
stmt_compiler(fragment.statements)

# For every signal in the sync domain, assign \sig's initial value (which will end up
# as the \init reg attribute) to the reset value.
4 changes: 0 additions & 4 deletions nmigen/hdl/dsl.py
Original file line number Diff line number Diff line change
@@ -92,10 +92,6 @@ def __init__(self):
self._statements = Statement.wrap([])
self._ctrl_context = None
self._ctrl_stack = []
self._stmt_if_cond = []
self._stmt_if_bodies = []
self._stmt_switch_test = None
self._stmt_switch_cases = OrderedDict()

def _check_context(self, construct, context):
if self._ctrl_context != context: