build.dsl: add conn argument to Connector.
authorRobin Heinemann <robin.ole.heinemann@t-online.de>
Sun, 18 Aug 2019 19:56:25 +0000 (21:56 +0200)
committerwhitequark <cz@m-labs.hk>
Sun, 18 Aug 2019 19:56:25 +0000 (19:56 +0000)
nmigen/build/dsl.py
nmigen/test/test_build_dsl.py
nmigen/test/test_build_res.py

index f080e9b28d8eaf470650002f5afa9c3efd398d08..7bcb9aa72281e0f7570a92ea8215536d7e87ad45 100644 (file)
@@ -210,10 +210,10 @@ class Resource(Subsignal):
 
 
 class Connector:
-    def __init__(self, name, number, io):
+    def __init__(self, name, number, io, *, conn=None):
         self.name    = name
         self.number  = number
-        self.mapping = OrderedDict()
+        mapping = OrderedDict()
 
         if isinstance(io, dict):
             for conn_pin, plat_pin in io.items():
@@ -223,18 +223,29 @@ class Connector:
                 if not isinstance(plat_pin, str):
                     raise TypeError("Platform pin name must be a string, not {!r}"
                                     .format(plat_pin))
-                self.mapping[conn_pin] = plat_pin
+                mapping[conn_pin] = plat_pin
 
         elif isinstance(io, str):
             for conn_pin, plat_pin in enumerate(io.split(), start=1):
                 if plat_pin == "-":
                     continue
-                self.mapping[str(conn_pin)] = plat_pin
 
+                mapping[str(conn_pin)] = plat_pin
         else:
             raise TypeError("Connector I/Os must be a dictionary or a string, not {!r}"
                             .format(io))
 
+        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}"
+                                .format(conn))
+
+            for conn_pin, plat_pin in mapping.items():
+                mapping[conn_pin] = "{}_{}:{}".format(conn_name, conn_number, plat_pin)
+
+        self.mapping = mapping
+
     def __repr__(self):
         return "(connector {} {} {})".format(self.name, self.number,
                                              " ".join("{}=>{}".format(conn, plat)
index e6d37adfc7faa3e391ded635c337bcb828964156..bff27211928f4c38ade13c90115cf8a848c45361 100644 (file)
@@ -278,6 +278,19 @@ class ConnectorTestCase(FHDLTestCase):
             ("DP1", "A1"),
         ]))
 
+    def test_conn(self):
+        c = Connector("pmod", 0, "0 1 2 3 - - 4 5 6 7 - -", conn=("expansion", 0))
+        self.assertEqual(c.mapping, OrderedDict([
+            ("1", "expansion_0:0"),
+            ("2", "expansion_0:1"),
+            ("3", "expansion_0:2"),
+            ("4", "expansion_0:3"),
+            ("7", "expansion_0:4"),
+            ("8", "expansion_0:5"),
+            ("9", "expansion_0:6"),
+            ("10", "expansion_0:7"),
+        ]))
+
     def test_wrong_io(self):
         with self.assertRaises(TypeError,
                 msg="Connector I/Os must be a dictionary or a string, not []"):
index 42e762f28ae7e75ea0f3e8c17f9cd2c3a1cb1899..4338770ca51cbf4d271e00f37b4789aab9697ac9 100644 (file)
@@ -168,6 +168,27 @@ class ResourceManagerTestCase(FHDLTestCase):
             ("spi_0__mosi__io", ["B3"], {}),
         ])
 
+    def test_request_via_nested_connector(self):
+        new_connectors = [
+            Connector("pmod_extension", 0, "1 2 3 4 - -", conn=("pmod", 0)),
+        ]
+        self.cm.add_connectors(new_connectors)
+        self.cm.add_resources([
+            Resource("spi", 0,
+                Subsignal("ss",   Pins("1", conn=("pmod_extension", 0))),
+                Subsignal("clk",  Pins("2", conn=("pmod_extension", 0))),
+                Subsignal("miso", Pins("3", conn=("pmod_extension", 0))),
+                Subsignal("mosi", Pins("4", conn=("pmod_extension", 0))),
+            )
+        ])
+        spi0 = self.cm.request("spi", 0)
+        self.assertEqual(list(self.cm.iter_port_constraints()), [
+            ("spi_0__ss__io",   ["B0"], {}),
+            ("spi_0__clk__io",  ["B1"], {}),
+            ("spi_0__miso__io", ["B2"], {}),
+            ("spi_0__mosi__io", ["B3"], {}),
+        ])
+
     def test_request_clock(self):
         clk100 = self.cm.request("clk100", 0)
         clk50 = self.cm.request("clk50", 0, dir="i")