From 8e048c5a7ce0f6ca2c4ccebd64361a1029aa9637 Mon Sep 17 00:00:00 2001 From: Robin Heinemann Date: Sun, 18 Aug 2019 21:56:25 +0200 Subject: [PATCH] build.dsl: add conn argument to Connector. --- nmigen/build/dsl.py | 19 +++++++++++++++---- nmigen/test/test_build_dsl.py | 13 +++++++++++++ nmigen/test/test_build_res.py | 21 +++++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/nmigen/build/dsl.py b/nmigen/build/dsl.py index f080e9b..7bcb9aa 100644 --- a/nmigen/build/dsl.py +++ b/nmigen/build/dsl.py @@ -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) diff --git a/nmigen/test/test_build_dsl.py b/nmigen/test/test_build_dsl.py index e6d37ad..bff2721 100644 --- a/nmigen/test/test_build_dsl.py +++ b/nmigen/test/test_build_dsl.py @@ -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 []"): diff --git a/nmigen/test/test_build_res.py b/nmigen/test/test_build_res.py index 42e762f..4338770 100644 --- a/nmigen/test/test_build_res.py +++ b/nmigen/test/test_build_res.py @@ -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") -- 2.30.2