back.rtlil: implement Array.
authorwhitequark <whitequark@whitequark.org>
Mon, 17 Dec 2018 01:15:23 +0000 (01:15 +0000)
committerwhitequark <whitequark@whitequark.org>
Mon, 17 Dec 2018 01:15:23 +0000 (01:15 +0000)
examples/gpio.py [new file with mode: 0644]
nmigen/back/rtlil.py
nmigen/hdl/ast.py

diff --git a/examples/gpio.py b/examples/gpio.py
new file mode 100644 (file)
index 0000000..557a852
--- /dev/null
@@ -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]))
index 3965511702a0318ead64b2e3d2956ff67df9be1f..67371308d91ce65c5dfb2697006543740fe62cef 100644 (file)
@@ -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):
index 049a68cc84f9b4b7da4732ca092945bea8036939..9ad7b90394ac04aaec637901925dc02e3e7334dc 100644 (file)
@@ -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))