hdl.mem: coerce memory init values to integers.
authorwhitequark <whitequark@whitequark.org>
Tue, 11 Jun 2019 03:38:44 +0000 (03:38 +0000)
committerwhitequark <whitequark@whitequark.org>
Tue, 11 Jun 2019 03:38:44 +0000 (03:38 +0000)
The coercion is carefully chosen to accept (other than normal ints)
instances of e.g. np.int64, but reject instances of e.g. float.
See https://stackoverflow.com/a/48940855/254415 for details.

Fixes #93.

nmigen/hdl/mem.py
nmigen/test/test_hdl_mem.py

index 076d2849323a306ed140463c6bc7668ce232514f..b07018e0de5fcbaf3b31d0dcd0f8ec82c3deb789 100644 (file)
@@ -1,3 +1,5 @@
+import operator
+
 from .. import tracer
 from .ast import *
 from .ir import Elaboratable, Instance
@@ -40,11 +42,15 @@ class Memory:
             raise ValueError("Memory initialization value count exceed memory depth ({} > {})"
                              .format(len(self.init), self.depth))
 
-        for addr in range(len(self._array)):
-            if addr < len(self._init):
-                self._array[addr].reset = self._init[addr]
-            else:
-                self._array[addr].reset = 0
+        try:
+            for addr in range(len(self._array)):
+                if addr < len(self._init):
+                    self._array[addr].reset = operator.index(self._init[addr])
+                else:
+                    self._array[addr].reset = 0
+        except TypeError as e:
+            raise TypeError("Memory initialization value at address {:x}: {}"
+                            .format(addr, e)) from None
 
     def read_port(self, domain="sync", synchronous=True, transparent=True):
         if not synchronous and not transparent:
index 0b37d482159dcd7c0b5f1341f084cdd3675ec43e..9bbe762662874a15610ca7505b4109f7b849bff2 100644 (file)
@@ -29,11 +29,17 @@ class MemoryTestCase(FHDLTestCase):
         m = Memory(width=8, depth=4, init=range(4))
         self.assertEqual(m.init, [0, 1, 2, 3])
 
-    def test_init_wrong(self):
+    def test_init_wrong_count(self):
         with self.assertRaises(ValueError,
                 msg="Memory initialization value count exceed memory depth (8 > 4)"):
             m = Memory(width=8, depth=4, init=range(8))
 
+    def test_init_wrong_type(self):
+        with self.assertRaises(TypeError,
+                msg="Memory initialization value at address 1: "
+                    "'str' object cannot be interpreted as an integer"):
+            m = Memory(width=8, depth=4, init=[1, "0"])
+
     def test_read_port_transparent(self):
         mem    = Memory(width=8, depth=4)
         rdport = mem.read_port()