back.pysim: implement ArrayProxy.
authorwhitequark <whitequark@whitequark.org>
Sat, 15 Dec 2018 19:37:36 +0000 (19:37 +0000)
committerwhitequark <whitequark@whitequark.org>
Sat, 15 Dec 2018 19:37:36 +0000 (19:37 +0000)
nmigen/back/pysim.py
nmigen/hdl/ast.py
nmigen/hdl/xfrm.py
nmigen/test/test_sim.py

index 634dd207375f6a487dcf480b10fb9b8aa7619d2c..a3c09d1fc4952e3f2a800f4b966c90db8bef963e 100644 (file)
@@ -148,6 +148,12 @@ class _RHSValueCompiler(ValueTransformer):
             return normalize(result, shape)
         return eval
 
+    def on_ArrayProxy(self, value):
+        shape  = value.shape()
+        elems  = list(map(self, value.elems))
+        index  = self(value.index)
+        return lambda state: normalize(elems[index(state)](state), shape)
+
 
 class _StatementCompiler(StatementTransformer):
     def __init__(self):
index a9623249ebe605eaf8bd83df5a27824af72970f7..42923f4e33783a0814a54405a1209a0108261320 100644 (file)
@@ -776,10 +776,12 @@ class ArrayProxy(Value):
         return bits, sign
 
     def _lhs_signals(self):
-        return union((elem._lhs_signals() for elem in self._iter_as_values()), start=ValueSet())
+        signals = union((elem._lhs_signals() for elem in self._iter_as_values()), start=ValueSet())
+        return signals
 
     def _rhs_signals(self):
-        return union((elem._rhs_signals() for elem in self._iter_as_values()), start=ValueSet())
+        signals = union((elem._rhs_signals() for elem in self._iter_as_values()), start=ValueSet())
+        return self.index._rhs_signals() | signals
 
     def __repr__(self):
         return "(proxy (array [{}]) {!r})".format(", ".join(map(repr, self.elems)), self.index)
index 1ef32751e1cbbcecfcb1fb533a736ddc8dbfbe6e..8d09ac83145915af79446241b1a680200958c411 100644 (file)
@@ -40,6 +40,10 @@ class ValueTransformer:
     def on_Repl(self, value):
         return Repl(self.on_value(value.value), value.count)
 
+    def on_ArrayProxy(self, value):
+        return ArrayProxy([self.on_value(elem) for elem in value._iter_as_values()],
+                          self.on_value(value.index))
+
     def on_unknown_value(self, value):
         raise TypeError("Cannot transform value '{!r}'".format(value)) # :nocov:
 
@@ -62,6 +66,8 @@ class ValueTransformer:
             new_value = self.on_Cat(value)
         elif isinstance(value, Repl):
             new_value = self.on_Repl(value)
+        elif isinstance(value, ArrayProxy):
+            new_value = self.on_ArrayProxy(value)
         else:
             new_value = self.on_unknown_value(value)
         if isinstance(new_value, Value):
index f6446e979d88ae2741fd23f688afb637acd0df1e..7cecfd736f87896efc6a1b20db62de0781b63525 100644 (file)
@@ -136,3 +136,26 @@ class SimulatorUnitTestCase(FHDLTestCase):
     def test_repl(self):
         stmt = lambda a: Repl(a, 3)
         self.assertOperator(stmt, [C(0b10, 2)], C(0b101010, 6))
+
+    def test_array(self):
+        array = Array([1, 4, 10])
+        stmt = lambda a: array[a]
+        self.assertOperator(stmt, [C(0)], C(1))
+        self.assertOperator(stmt, [C(1)], C(4))
+        self.assertOperator(stmt, [C(2)], C(10))
+
+    def test_array_index(self):
+        array = Array(Array(x * y for y in range(10)) for x in range(10))
+        stmt = lambda a, b: array[a][b]
+        for x in range(10):
+            for y in range(10):
+                self.assertOperator(stmt, [C(x), C(y)], C(x * y))
+
+    def test_array_attr(self):
+        from collections import namedtuple
+        pair = namedtuple("pair", ("p", "n"))
+
+        array = Array(pair(x, -x) for x in range(10))
+        stmt = lambda a: array[a].p + array[a].n
+        for i in range(10):
+            self.assertOperator(stmt, [C(i)], C(0))