From: whitequark Date: Mon, 17 Dec 2018 01:15:23 +0000 (+0000) Subject: back.rtlil: implement Array. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=827dfa49a6e56b23daf96cdc4ea54ad29940bd62;p=nmigen.git back.rtlil: implement Array. --- diff --git a/examples/gpio.py b/examples/gpio.py new file mode 100644 index 0000000..557a852 --- /dev/null +++ b/examples/gpio.py @@ -0,0 +1,31 @@ +from types import SimpleNamespace +from nmigen import * +from nmigen.back import rtlil, verilog, pysim + + +class GPIO: + def __init__(self, pins, bus): + self.pins = pins + self.bus = bus + + def get_fragment(self, platform): + m = Module() + m.d.comb += self.bus.dat_r.eq(self.pins[self.bus.adr]) + with m.If(self.bus.we): + m.d.sync += self.pins[self.bus.adr].eq(self.bus.dat_w) + return m.lower(platform) + + +# TODO: use Record +bus = SimpleNamespace( + adr=Signal(max=8), + dat_r=Signal(), + dat_w=Signal(), + we=Signal() +) +pins = Signal(8) +gpio = GPIO(Array(pins), bus) +frag = gpio.get_fragment(platform=None) + +# print(rtlil.convert(frag, ports=[pins, bus.adr, bus.dat_r, bus.dat_w, bus.we])) +print(verilog.convert(frag, ports=[pins, bus.adr, bus.dat_r, bus.dat_w, bus.we])) diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index 3965511..6737130 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -264,6 +264,8 @@ class _ValueCompilerState: return wire_curr def expand(self, value): + if not self.expansions: + return value return self.expansions.get(value, value) @contextmanager @@ -311,6 +313,16 @@ class _ValueCompiler(xfrm.AbstractValueTransformer): else: return "{} [{}:{}]".format(sigspec, value.end - 1, value.start) + def on_ArrayProxy(self, value): + index = self.s.expand(value.index) + if isinstance(index, ast.Const): + if index.value < len(value.elems): + return self(value.elems[index.value]) + else: + return self(value.elems[-1]) + else: + raise LegalizeValue(value.index, range(len(value.elems))) + class _RHSValueCompiler(_ValueCompiler): operator_map = { @@ -473,9 +485,6 @@ class _RHSValueCompiler(_ValueCompiler): def on_Repl(self, value): return "{{ {} }}".format(" ".join(self(value.value) for _ in range(value.count))) - def on_ArrayProxy(self, value): - raise NotImplementedError - class _LHSValueCompiler(_ValueCompiler): def on_Const(self, value): @@ -499,14 +508,11 @@ class _LHSValueCompiler(_ValueCompiler): if isinstance(offset, ast.Const): return self(ast.Slice(value.value, offset.value, offset.value + value.width)) else: - raise LegalizeValue(value.offset, range(0, (1 << len(value.offset) - 1))) + raise LegalizeValue(value.offset, range((1 << len(value.offset)) - 1)) def on_Repl(self, value): raise TypeError # :nocov: - def on_ArrayProxy(self, value): - raise NotImplementedError - class _StatementCompiler(xfrm.AbstractStatementTransformer): def __init__(self, state, rhs_compiler, lhs_compiler): diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index 049a68c..9ad7b90 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -902,6 +902,9 @@ class ValueKey: self.value.width)) elif isinstance(self.value, Cat): return hash(tuple(ValueKey(o) for o in self.value.operands)) + elif isinstance(self.value, ArrayProxy): + return hash((ValueKey(self.value.index), + tuple(ValueKey(e) for e in self.value._iter_as_values()))) else: # :nocov: raise TypeError("Object '{!r}' cannot be used as a key in value collections" .format(self.value)) @@ -932,6 +935,12 @@ class ValueKey: elif isinstance(self.value, Cat): return all(ValueKey(a) == ValueKey(b) for a, b in zip(self.value.operands, other.value.operands)) + elif isinstance(self.value, ArrayProxy): + return (ValueKey(self.value.index) == ValueKey(other.value.index) and + len(self.value.elems) == len(other.value.elems) and + all(ValueKey(a) == ValueKey(b) + for a, b in zip(self.value._iter_as_values(), + other.value._iter_as_values()))) else: # :nocov: raise TypeError("Object '{!r}' cannot be used as a key in value collections" .format(self.value))