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: d4e8d3e95a9d
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: ed3974888980
Choose a head ref
  • 3 commits
  • 6 files changed
  • 1 contributor

Commits on Dec 16, 2018

  1. compat.fhdl: reexport Array.

    whitequark committed Dec 16, 2018
    Copy the full SHA
    286a800 View commit details
  2. hdl.xfrm: separate AST traversal from AST identity mapping.

    This is useful because backends don't generally want or need AST
    identity mapping (unlike all other transforms) and when adding a new
    node, it results in confusing type errors.
    whitequark committed Dec 16, 2018
    Copy the full SHA
    2be76fd View commit details
  3. back.rtlil: fix naming. NFC.

    whitequark committed Dec 16, 2018
    Copy the full SHA
    ed39748 View commit details
Showing with 161 additions and 96 deletions.
  1. +2 −2 doc/COMPAT_SUMMARY.md
  2. +4 −4 nmigen/back/pysim.py
  3. +74 −65 nmigen/back/rtlil.py
  4. +2 −5 nmigen/compat/fhdl/structure.py
  5. +1 −1 nmigen/hdl/ast.py
  6. +78 −19 nmigen/hdl/xfrm.py
4 changes: 2 additions & 2 deletions doc/COMPAT_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -77,8 +77,8 @@ Compatibility summary
- (-) `_check_statement` **obs**`Statement.wrap`
- (+) `If` **obs**`.hdl.dsl.Module.If`
- (+) `Case` **obs**`.hdl.dsl.Module.Switch`
- () `_ArrayProxy` ?
- () `Array` ?
- (+) `_ArrayProxy` `.hdl.ast.ArrayProxy`, `choices=``elems=`, `key=``index=`
- (+) `Array` id
- (+) `ClockDomain``.hdl.cd.ClockDomain`
- (−) `_ClockDomainList` ?
- (−) `SPECIAL_INPUT`/`SPECIAL_OUTPUT`/`SPECIAL_INOUT` ?
8 changes: 4 additions & 4 deletions nmigen/back/pysim.py
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@

from ..tools import flatten
from ..hdl.ast import *
from ..hdl.xfrm import ValueTransformer, StatementTransformer
from ..hdl.xfrm import AbstractValueTransformer, AbstractStatementTransformer


__all__ = ["Simulator", "Delay", "Tick", "Passive", "DeadlineError"]
@@ -44,7 +44,7 @@ def commit(self, signal):
normalize = Const.normalize


class _RHSValueCompiler(ValueTransformer):
class _RHSValueCompiler(AbstractValueTransformer):
def __init__(self, sensitivity=None, mode="rhs"):
self.sensitivity = sensitivity
self.signal_mode = mode
@@ -165,7 +165,7 @@ def on_ArrayProxy(self, value):
return lambda state: normalize(elems[index(state)](state), shape)


class _LHSValueCompiler(ValueTransformer):
class _LHSValueCompiler(AbstractValueTransformer):
def __init__(self, rhs_compiler):
self.rhs_compiler = rhs_compiler

@@ -234,7 +234,7 @@ def eval(state, rhs):
return eval


class _StatementCompiler(StatementTransformer):
class _StatementCompiler(AbstractStatementTransformer):
def __init__(self):
self.sensitivity = ValueSet()
self.rrhs_compiler = _RHSValueCompiler(self.sensitivity, mode="rhs")
139 changes: 74 additions & 65 deletions nmigen/back/rtlil.py
Original file line number Diff line number Diff line change
@@ -195,7 +195,7 @@ def src(src_loc):
return "{}:{}".format(file, line)


class _ValueTransformer(xfrm.ValueTransformer):
class _ValueTransformer(xfrm.AbstractValueTransformer):
operator_map = {
(1, "~"): "$not",
(1, "-"): "$neg",
@@ -257,85 +257,91 @@ def hierarchy(self, sub_name):
finally:
self.sub_name = None

def on_unknown(self, node):
if node is None:
def on_unknown(self, value):
if value is None:
return None
else:
super().visit_unknown(node)
super().on_unknown(value)

def on_Const(self, node):
if isinstance(node.value, str):
return "{}'{}".format(node.nbits, node.value)
def on_Const(self, value):
if isinstance(value.value, str):
return "{}'{}".format(value.nbits, value.value)
else:
return "{}'{:b}".format(node.nbits, node.value)
return "{}'{:b}".format(value.nbits, value.value)

def on_Signal(self, node):
if node in self.wires:
wire_curr, wire_next = self.wires[node]
def on_Signal(self, value):
if value in self.wires:
wire_curr, wire_next = self.wires[value]
else:
if node in self.ports:
port_id, port_kind = self.ports[node]
if value in self.ports:
port_id, port_kind = self.ports[value]
else:
port_id = port_kind = None
if self.sub_name:
wire_name = "{}_{}".format(self.sub_name, node.name)
wire_name = "{}_{}".format(self.sub_name, value.name)
else:
wire_name = node.name
for attr_name, attr_value in node.attrs.items():
wire_name = value.name
for attr_name, attr_value in value.attrs.items():
self.rtlil.attribute(attr_name, attr_value)
wire_curr = self.rtlil.wire(width=node.nbits, name=wire_name,
wire_curr = self.rtlil.wire(width=value.nbits, name=wire_name,
port_id=port_id, port_kind=port_kind,
src=src(node.src_loc))
if node in self.driven:
wire_next = self.rtlil.wire(width=node.nbits, name=wire_curr + "$next",
src=src(node.src_loc))
src=src(value.src_loc))
if value in self.driven:
wire_next = self.rtlil.wire(width=value.nbits, name=wire_curr + "$next",
src=src(value.src_loc))
else:
wire_next = None
self.wires[node] = (wire_curr, wire_next)
self.wires[value] = (wire_curr, wire_next)

if self.is_lhs:
if wire_next is None:
raise ValueError("Cannot return lhs for non-driven signal {}".format(repr(node)))
raise ValueError("Cannot return lhs for non-driven signal {}".format(repr(value)))
return wire_next
else:
return wire_curr

def on_Operator_unary(self, node):
arg, = node.operands
def on_ClockSignal(self, value):
raise NotImplementedError # :nocov:

def on_ResetSignal(self, value):
raise NotImplementedError # :nocov:

def on_Operator_unary(self, value):
arg, = value.operands
arg_bits, arg_sign = arg.shape()
res_bits, res_sign = node.shape()
res_bits, res_sign = value.shape()
res = self.rtlil.wire(width=res_bits)
self.rtlil.cell(self.operator_map[(1, node.op)], ports={
self.rtlil.cell(self.operator_map[(1, value.op)], ports={
"\\A": self(arg),
"\\Y": res,
}, params={
"A_SIGNED": arg_sign,
"A_WIDTH": arg_bits,
"Y_WIDTH": res_bits,
}, src=src(node.src_loc))
}, src=src(value.src_loc))
return res

def match_shape(self, node, new_bits, new_sign):
if isinstance(node, ast.Const):
return self(ast.Const(node.value, (new_bits, new_sign)))
def match_shape(self, value, new_bits, new_sign):
if isinstance(value, ast.Const):
return self(ast.Const(value.value, (new_bits, new_sign)))

node_bits, node_sign = node.shape()
if new_bits > node_bits:
value_bits, value_sign = value.shape()
if new_bits > value_bits:
res = self.rtlil.wire(width=new_bits)
self.rtlil.cell("$pos", ports={
"\\A": self(node),
"\\A": self(value),
"\\Y": res,
}, params={
"A_SIGNED": node_sign,
"A_WIDTH": node_bits,
"A_SIGNED": value_sign,
"A_WIDTH": value_bits,
"Y_WIDTH": new_bits,
}, src=src(node.src_loc))
}, src=src(value.src_loc))
return res
else:
return "{} [{}:0]".format(self(node), new_bits - 1)
return "{} [{}:0]".format(self(value), new_bits - 1)

def on_Operator_binary(self, node):
lhs, rhs = node.operands
def on_Operator_binary(self, value):
lhs, rhs = value.operands
lhs_bits, lhs_sign = lhs.shape()
rhs_bits, rhs_sign = rhs.shape()
if lhs_sign == rhs_sign:
@@ -346,9 +352,9 @@ def on_Operator_binary(self, node):
lhs_bits = rhs_bits = max(lhs_bits, rhs_bits)
lhs_wire = self.match_shape(lhs, lhs_bits, lhs_sign)
rhs_wire = self.match_shape(rhs, rhs_bits, rhs_sign)
res_bits, res_sign = node.shape()
res_bits, res_sign = value.shape()
res = self.rtlil.wire(width=res_bits)
self.rtlil.cell(self.operator_map[(2, node.op)], ports={
self.rtlil.cell(self.operator_map[(2, value.op)], ports={
"\\A": lhs_wire,
"\\B": rhs_wire,
"\\Y": res,
@@ -358,14 +364,14 @@ def on_Operator_binary(self, node):
"B_SIGNED": rhs_sign,
"B_WIDTH": rhs_bits,
"Y_WIDTH": res_bits,
}, src=src(node.src_loc))
}, src=src(value.src_loc))
return res

def on_Operator_mux(self, node):
sel, lhs, rhs = node.operands
def on_Operator_mux(self, value):
sel, lhs, rhs = value.operands
lhs_bits, lhs_sign = lhs.shape()
rhs_bits, rhs_sign = rhs.shape()
res_bits, res_sign = node.shape()
res_bits, res_sign = value.shape()
lhs_bits = rhs_bits = res_bits = max(lhs_bits, rhs_bits, res_bits)
lhs_wire = self.match_shape(lhs, lhs_bits, lhs_sign)
rhs_wire = self.match_shape(rhs, rhs_bits, rhs_sign)
@@ -377,34 +383,37 @@ def on_Operator_mux(self, node):
"\\Y": res,
}, params={
"WIDTH": res_bits
}, src=src(node.src_loc))
}, src=src(value.src_loc))
return res

def on_Operator(self, node):
if len(node.operands) == 1:
return self.on_Operator_unary(node)
elif len(node.operands) == 2:
return self.on_Operator_binary(node)
elif len(node.operands) == 3:
assert node.op == "m"
return self.on_Operator_mux(node)
def on_Operator(self, value):
if len(value.operands) == 1:
return self.on_Operator_unary(value)
elif len(value.operands) == 2:
return self.on_Operator_binary(value)
elif len(value.operands) == 3:
assert value.op == "m"
return self.on_Operator_mux(value)
else:
raise TypeError

def on_Slice(self, node):
if node.end == node.start + 1:
return "{} [{}]".format(self(node.value), node.start)
def on_Slice(self, value):
if value.end == value.start + 1:
return "{} [{}]".format(self(value.value), value.start)
else:
return "{} [{}:{}]".format(self(node.value), node.end - 1, node.start)
return "{} [{}:{}]".format(self(value.value), value.end - 1, value.start)

def on_Part(self, value):
raise NotImplementedError

# def on_Part(self, node):
# return _Part(self(node.value), self(node.offset), node.width)
def on_Cat(self, value):
return "{{ {} }}".format(" ".join(reversed([self(o) for o in value.operands])))

def on_Cat(self, node):
return "{{ {} }}".format(" ".join(reversed([self(o) for o in node.operands])))
def on_Repl(self, value):
return "{{ {} }}".format(" ".join(self(value.value) for _ in range(value.count)))

def on_Repl(self, node):
return "{{ {} }}".format(" ".join(self(node.value) for _ in range(node.count)))
def on_ArrayProxy(self, value):
raise NotImplementedError


def convert_fragment(builder, fragment, name, top):
7 changes: 2 additions & 5 deletions nmigen/compat/fhdl/structure.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,8 @@

from ...tools import deprecated
from ...hdl import ast
from ...hdl.ast import DUID, Value, Signal, Mux, Cat, Repl, Const, C, ClockSignal, ResetSignal
from ...hdl.ast import (DUID, Value, Signal, Mux, Cat, Repl, Const, C, ClockSignal, ResetSignal,
Array, ArrayProxy as _ArrayProxy)
from ...hdl.cd import ClockDomain


@@ -84,8 +85,4 @@ def makedefault(self, key=None):
return self


def Array(*args):
raise NotImplementedError


(SPECIAL_INPUT, SPECIAL_OUTPUT, SPECIAL_INOUT) = range(3)
2 changes: 1 addition & 1 deletion nmigen/hdl/ast.py
Original file line number Diff line number Diff line change
@@ -713,7 +713,7 @@ class Array(MutableSequence):
master.dat_r.eq(buses[sel].dat_r),
]
"""
def __init__(self, iterable):
def __init__(self, iterable=()):
self._inner = list(iterable)
self._proxy_at = None
self._mutable = True
Loading