From: whitequark Date: Sun, 16 Dec 2018 22:26:58 +0000 (+0000) Subject: back.rtlil: extract _StatementCompiler. NFC. X-Git-Tag: working~198 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=91b7561a00ce969ae5de585f365c3cc89808f751;p=nmigen.git back.rtlil: extract _StatementCompiler. NFC. --- diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index c04c531..1836d75 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -462,11 +462,42 @@ class _LHSValueCompiler(_ValueCompiler): 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. @@ -509,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.