build.dsl: allow strings to be used as connector numbers.
authorJaro Habiger <jarohabiger@googlemail.com>
Sun, 26 Jan 2020 17:35:41 +0000 (18:35 +0100)
committerwhitequark <whitequark@whitequark.org>
Fri, 31 Jan 2020 03:11:34 +0000 (03:11 +0000)
Fixes #311.

nmigen/build/dsl.py
nmigen/test/test_build_dsl.py

index 721f980ebc74f1b0ca41953f78d69693042f5913..9924e126a39a37639896d776b6cabdeae8960e19 100644 (file)
@@ -14,8 +14,9 @@ class Pins:
 
         if conn is not None:
             conn_name, conn_number = conn
-            if not (isinstance(conn_name, str) and isinstance(conn_number, int)):
-                raise TypeError("Connector must be None or a pair of string and integer, not {!r}"
+            if not (isinstance(conn_name, str) and isinstance(conn_number, (int, str))):
+                raise TypeError("Connector must be None or a pair of string (connector name) and "
+                                "integer/string (connector number), not {!r}"
                                 .format(conn))
             names = ["{}_{}:{}".format(conn_name, conn_number, name) for name in names]
 
@@ -236,8 +237,9 @@ class Connector:
 
         if conn is not None:
             conn_name, conn_number = conn
-            if not (isinstance(conn_name, str) and isinstance(conn_number, int)):
-                raise TypeError("Connector must be None or a pair of string and integer, not {!r}"
+            if not (isinstance(conn_name, str) and isinstance(conn_number, (int, str))):
+                raise TypeError("Connector must be None or a pair of string (connector name) and "
+                                "integer/string (connector number), not {!r}"
                                 .format(conn))
 
             for conn_pin, plat_pin in mapping.items():
index a613d12795c76be64d60805fb0bb9048315dbf77..bf901bfc0d87844f38ad40f246b428defdc36079 100644 (file)
@@ -25,6 +25,8 @@ class PinsTestCase(FHDLTestCase):
     def test_conn(self):
         p = Pins("0 1 2", conn=("pmod", 0))
         self.assertEqual(list(p), ["pmod_0:0", "pmod_0:1", "pmod_0:2"])
+        p = Pins("0 1 2", conn=("pmod", "a"))
+        self.assertEqual(list(p), ["pmod_a:0", "pmod_a:1", "pmod_a:2"])
 
     def test_map_names(self):
         p = Pins("0 1 2", conn=("pmod", 0))
@@ -53,6 +55,12 @@ class PinsTestCase(FHDLTestCase):
                 msg="Direction must be one of \"i\", \"o\", \"oe\", or \"io\", not 'wrong'"):
             p = Pins("A0 A1", dir="wrong")
 
+    def test_wrong_conn(self):
+        with self.assertRaises(TypeError,
+                msg="Connector must be None or a pair of string (connector name) and "
+                    "integer/string (connector number), not ('foo', None)"):
+            p = Pins("A0 A1", conn=("foo", None))
+
     def test_wrong_map_names(self):
         p = Pins("0 1 2", conn=("pmod", 0))
         mapping = {
@@ -295,6 +303,17 @@ class ConnectorTestCase(FHDLTestCase):
             ("10", "expansion_0:7"),
         ]))
 
+    def test_str_name(self):
+        c = Connector("ext", "A", "0 1 2")
+        self.assertEqual(c.name, "ext")
+        self.assertEqual(c.number, "A")
+
+    def test_conn_wrong_name(self):
+        with self.assertRaises(TypeError,
+                msg="Connector must be None or a pair of string (connector name) and "
+                    "integer/string (connector number), not ('foo', None)"):
+            Connector("ext", "A", "0 1 2", conn=("foo", None))
+
     def test_wrong_io(self):
         with self.assertRaises(TypeError,
                 msg="Connector I/Os must be a dictionary or a string, not []"):