From 98497b207520fceef1e98c660857727d7264fc66 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 2 Jun 2019 23:36:21 +0000 Subject: [PATCH] build.dsl: require a dict for extras instead of a stringly array. Fixes #72. --- nmigen/build/dsl.py | 33 ++++++++++++++++++--------- nmigen/test/test_build_dsl.py | 22 +++++++++++------- nmigen/test/test_build_res.py | 10 ++++---- nmigen/vendor/ice40_hx1k_blink_evn.py | 18 +++++++-------- nmigen/vendor/icestick.py | 18 +++++++-------- nmigen/vendor/tinyfpga_bx.py | 12 +++++----- 6 files changed, 65 insertions(+), 48 deletions(-) diff --git a/nmigen/build/dsl.py b/nmigen/build/dsl.py index f27a312..7b3c38d 100644 --- a/nmigen/build/dsl.py +++ b/nmigen/build/dsl.py @@ -47,7 +47,7 @@ class DiffPairs: class Subsignal: - def __init__(self, name, *io, extras=()): + def __init__(self, name, *io, extras=None): self.name = name if not io: @@ -67,25 +67,35 @@ class Subsignal: raise TypeError("A Subsignal can only be followed by more Subsignals, but " "{!r} is followed by {!r}" .format(io[0], c)) - self.io = io - - for c in extras: - if not isinstance(c, str): - raise TypeError("Extra constraint must be a string, not {!r}".format(c)) - self.extras = list(extras) + self.io = io + self.extras = {} + + if extras is not None: + if not isinstance(extras, dict): + raise TypeError("Extra constraints must be a dict, not {!r}" + .format(extras)) + for extra_key, extra_value in extras.items(): + if not isinstance(extra_key, str): + raise TypeError("Extra constraint key must be a string, not {!r}" + .format(extra_key)) + if not isinstance(extra_value, str): + raise TypeError("Extra constraint value must be a string, not {!r}" + .format(extra_value)) + self.extras[extra_key] = extra_value if isinstance(self.io[0], Subsignal): for sub in self.io: - sub.extras += self.extras + sub.extras.update(self.extras) def __repr__(self): return "(subsignal {} {} {})".format(self.name, " ".join(map(repr, self.io)), - " ".join(self.extras)) + " ".join("{}={}".format(k, v) + for k, v in self.extras.items())) class Resource(Subsignal): - def __init__(self, name, number, *io, extras=()): + def __init__(self, name, number, *io, extras=None): super().__init__(name, *io, extras=extras) self.number = number @@ -93,4 +103,5 @@ class Resource(Subsignal): def __repr__(self): return "(resource {} {} {} {})".format(self.name, self.number, " ".join(map(repr, self.io)), - " ".join(self.extras)) + " ".join("{}={}".format(k, v) + for k, v in self.extras.items())) diff --git a/nmigen/test/test_build_dsl.py b/nmigen/test/test_build_dsl.py index 6a1c1cc..15ef9ad 100644 --- a/nmigen/test/test_build_dsl.py +++ b/nmigen/test/test_build_dsl.py @@ -45,7 +45,7 @@ class DiffPairsTestCase(FHDLTestCase): class SubsignalTestCase(FHDLTestCase): def test_basic_pins(self): - s = Subsignal("a", Pins("A0"), extras=["IOSTANDARD=LVCMOS33"]) + s = Subsignal("a", Pins("A0"), extras={"IOSTANDARD": "LVCMOS33"}) self.assertEqual(repr(s), "(subsignal a (pins io A0) IOSTANDARD=LVCMOS33)") def test_basic_diffpairs(self): @@ -62,11 +62,11 @@ class SubsignalTestCase(FHDLTestCase): def test_extras(self): s = Subsignal("a", Subsignal("b", Pins("A0")), - Subsignal("c", Pins("A0"), extras=["SLEW=FAST"]), - extras=["IOSTANDARD=LVCMOS33"]) - self.assertEqual(s.extras, ["IOSTANDARD=LVCMOS33"]) - self.assertEqual(s.io[0].extras, ["IOSTANDARD=LVCMOS33"]) - self.assertEqual(s.io[1].extras, ["SLEW=FAST", "IOSTANDARD=LVCMOS33"]) + Subsignal("c", Pins("A0"), extras={"SLEW": "FAST"}), + extras={"IOSTANDARD": "LVCMOS33"}) + self.assertEqual(s.extras, {"IOSTANDARD": "LVCMOS33"}) + self.assertEqual(s.io[0].extras, {"IOSTANDARD": "LVCMOS33"}) + self.assertEqual(s.io[1].extras, {"SLEW": "FAST", "IOSTANDARD": "LVCMOS33"}) def test_empty_io(self): with self.assertRaises(TypeError, msg="Missing I/O constraints"): @@ -98,8 +98,14 @@ class SubsignalTestCase(FHDLTestCase): def test_wrong_extras(self): with self.assertRaises(TypeError, - msg="Extra constraint must be a string, not (pins io B0)"): + msg="Extra constraints must be a dict, not [(pins io B0)]"): s = Subsignal("a", Pins("A0"), extras=[Pins("B0")]) + with self.assertRaises(TypeError, + msg="Extra constraint key must be a string, not 1"): + s = Subsignal("a", Pins("A0"), extras={1: 2}) + with self.assertRaises(TypeError, + msg="Extra constraint value must be a string, not 2"): + s = Subsignal("a", Pins("A0"), extras={"1": 2}) class ResourceTestCase(FHDLTestCase): @@ -107,7 +113,7 @@ class ResourceTestCase(FHDLTestCase): r = Resource("serial", 0, Subsignal("tx", Pins("A0", dir="o")), Subsignal("rx", Pins("A1", dir="i")), - extras=["IOSTANDARD=LVCMOS33"]) + extras={"IOSTANDARD": "LVCMOS33"}) self.assertEqual(repr(r), "(resource serial 0" " (subsignal tx (pins o A0) IOSTANDARD=LVCMOS33)" " (subsignal rx (pins i A1) IOSTANDARD=LVCMOS33)" diff --git a/nmigen/test/test_build_res.py b/nmigen/test/test_build_res.py index dac5ad5..5ffdac8 100644 --- a/nmigen/test/test_build_res.py +++ b/nmigen/test/test_build_res.py @@ -66,7 +66,7 @@ class ConstraintManagerTestCase(FHDLTestCase): self.assertEqual(len(ports), 1) self.assertEqual(list(self.cm.iter_port_constraints()), [ - ("user_led_0_io", ["A0"], []) + ("user_led_0_io", ["A0"], {}) ]) def test_request_with_dir(self): @@ -90,8 +90,8 @@ class ConstraintManagerTestCase(FHDLTestCase): (i2c.sda, sda), ]) self.assertEqual(list(self.cm.iter_port_constraints()), [ - ("i2c_0__scl_io", ["N10"], []), - ("i2c_0__sda_io", ["N11"], []) + ("i2c_0__scl_io", ["N10"], {}), + ("i2c_0__sda_io", ["N11"], {}) ]) def test_request_diffpairs(self): @@ -112,8 +112,8 @@ class ConstraintManagerTestCase(FHDLTestCase): (clk100, p, n), ]) self.assertEqual(list(self.cm.iter_port_constraints()), [ - ("clk100_0_p", ["H1"], []), - ("clk100_0_n", ["H2"], []) + ("clk100_0_p", ["H1"], {}), + ("clk100_0_n", ["H2"], {}) ]) def test_add_clock(self): diff --git a/nmigen/vendor/ice40_hx1k_blink_evn.py b/nmigen/vendor/ice40_hx1k_blink_evn.py index ee7c5f6..1f44882 100644 --- a/nmigen/vendor/ice40_hx1k_blink_evn.py +++ b/nmigen/vendor/ice40_hx1k_blink_evn.py @@ -12,15 +12,15 @@ class ICE40HX1KBlinkEVNPlatform(IceBurnProgrammerMixin, LatticeICE40Platform): ("clk3p3", 3.3e6), ] resources = [ - Resource("clk3p3", 0, Pins("13", dir="i"), extras=["IO_STANDARD=SB_LVCMOS33"]), + Resource("clk3p3", 0, Pins("13", dir="i"), extras={"IO_STANDARD": "SB_LVCMOS33"}), - Resource("user_led", 0, Pins("59", dir="o"), extras=["IO_STANDARD=SB_LVCMOS33"]), - Resource("user_led", 1, Pins("56", dir="o"), extras=["IO_STANDARD=SB_LVCMOS33"]), - Resource("user_led", 2, Pins("53", dir="o"), extras=["IO_STANDARD=SB_LVCMOS33"]), - Resource("user_led", 3, Pins("51", dir="o"), extras=["IO_STANDARD=SB_LVCMOS33"]), + Resource("user_led", 0, Pins("59", dir="o"), extras={"IO_STANDARD": "SB_LVCMOS33"}), + Resource("user_led", 1, Pins("56", dir="o"), extras={"IO_STANDARD": "SB_LVCMOS33"}), + Resource("user_led", 2, Pins("53", dir="o"), extras={"IO_STANDARD": "SB_LVCMOS33"}), + Resource("user_led", 3, Pins("51", dir="o"), extras={"IO_STANDARD": "SB_LVCMOS33"}), - Resource("user_btn", 0, Pins("60"), extras=["IO_STANDARD=SB_LVCMOS33"]), - Resource("user_btn", 1, Pins("57"), extras=["IO_STANDARD=SB_LVCMOS33"]), - Resource("user_btn", 2, Pins("54"), extras=["IO_STANDARD=SB_LVCMOS33"]), - Resource("user_btn", 3, Pins("52"), extras=["IO_STANDARD=SB_LVCMOS33"]), + Resource("user_btn", 0, Pins("60"), extras={"IO_STANDARD": "SB_LVCMOS33"}), + Resource("user_btn", 1, Pins("57"), extras={"IO_STANDARD": "SB_LVCMOS33"}), + Resource("user_btn", 2, Pins("54"), extras={"IO_STANDARD": "SB_LVCMOS33"}), + Resource("user_btn", 3, Pins("52"), extras={"IO_STANDARD": "SB_LVCMOS33"}), ] diff --git a/nmigen/vendor/icestick.py b/nmigen/vendor/icestick.py index 5827baa..4d1ecfd 100644 --- a/nmigen/vendor/icestick.py +++ b/nmigen/vendor/icestick.py @@ -12,13 +12,13 @@ class ICEStickPlatform(IceStormProgrammerMixin, LatticeICE40Platform): ("clk12", 12e6), ] resources = [ - Resource("clk12", 0, Pins("21", dir="i"), extras=["IO_STANDARD=SB_LVCMOS33"]), + Resource("clk12", 0, Pins("21", dir="i"), extras={"IO_STANDARD": "SB_LVCMOS33"}), - Resource("user_led", 0, Pins("99", dir="o"), extras=["IO_STANDARD=SB_LVCMOS33"]), - Resource("user_led", 1, Pins("98", dir="o"), extras=["IO_STANDARD=SB_LVCMOS33"]), - Resource("user_led", 2, Pins("97", dir="o"), extras=["IO_STANDARD=SB_LVCMOS33"]), - Resource("user_led", 3, Pins("96", dir="o"), extras=["IO_STANDARD=SB_LVCMOS33"]), - Resource("user_led", 4, Pins("95", dir="o"), extras=["IO_STANDARD=SB_LVCMOS33"]), + Resource("user_led", 0, Pins("99", dir="o"), extras={"IO_STANDARD": "SB_LVCMOS33"}), + Resource("user_led", 1, Pins("98", dir="o"), extras={"IO_STANDARD": "SB_LVCMOS33"}), + Resource("user_led", 2, Pins("97", dir="o"), extras={"IO_STANDARD": "SB_LVCMOS33"}), + Resource("user_led", 3, Pins("96", dir="o"), extras={"IO_STANDARD": "SB_LVCMOS33"}), + Resource("user_led", 4, Pins("95", dir="o"), extras={"IO_STANDARD": "SB_LVCMOS33"}), Resource("serial", 0, Subsignal("rx", Pins("9", dir="i")), @@ -28,14 +28,14 @@ class ICEStickPlatform(IceStormProgrammerMixin, LatticeICE40Platform): Subsignal("dtr", Pins("3", dir="o")), Subsignal("dsr", Pins("2", dir="i")), Subsignal("dcd", Pins("1", dir="i")), - extras=["IO_STANDARD=SB_LVTTL", "PULLUP=1"], + extras={"IO_STANDARD": "SB_LVTTL", "PULLUP": "1"} ), Resource("irda", 0, Subsignal("rx", Pins("106", dir="i")), Subsignal("tx", Pins("105", dir="o")), Subsignal("sd", Pins("107", dir="o")), - extras=["IO_STANDARD=SB_LVCMOS33"] + extras={"IO_STANDARD": "SB_LVCMOS33"} ), Resource("spiflash", 0, @@ -43,7 +43,7 @@ class ICEStickPlatform(IceStormProgrammerMixin, LatticeICE40Platform): Subsignal("clk", Pins("70", dir="o")), Subsignal("mosi", Pins("67", dir="io")), Subsignal("miso", Pins("68", dir="io")), - extras=["IO_STANDARD=SB_LVCMOS33"] + extras={"IO_STANDARD": "SB_LVCMOS33"} ), ] prog_mode = "flash" diff --git a/nmigen/vendor/tinyfpga_bx.py b/nmigen/vendor/tinyfpga_bx.py index ccaa2b3..50ced5d 100644 --- a/nmigen/vendor/tinyfpga_bx.py +++ b/nmigen/vendor/tinyfpga_bx.py @@ -12,15 +12,15 @@ class TinyFPGABXPlatform(TinyProgrammerMixin, LatticeICE40Platform): ("clk16", 16e6), ] resources = [ - Resource("clk16", 0, Pins("B2", dir="i"), extras=["IO_STANDARD=SB_LVCMOS33"]), + Resource("clk16", 0, Pins("B2", dir="i"), extras={"IO_STANDARD": "SB_LVCMOS33"}), - Resource("user_led", 0, Pins("B3", dir="o"), extras=["IO_STANDARD=SB_LVCMOS33"]), + Resource("user_led", 0, Pins("B3", dir="o"), extras={"IO_STANDARD": "SB_LVCMOS33"}), Resource("usb", 0, - Subsignal("d_p", Pins("B4", dir="io")), - Subsignal("d_n", Pins("A4", dir="io")), + Subsignal("d_p", Pins("B4", dir="io")), + Subsignal("d_n", Pins("A4", dir="io")), Subsignal("pull_up", Pins("A3", dir="o")), - extras=["IO_STANDARD=SB_LVCMOS33"] + extras={"IO_STANDARD": "SB_LVCMOS33"} ), Resource("spiflash", 0, @@ -28,6 +28,6 @@ class TinyFPGABXPlatform(TinyProgrammerMixin, LatticeICE40Platform): Subsignal("clk", Pins("G7", dir="o")), Subsignal("mosi", Pins("G6", dir="io")), Subsignal("miso", Pins("H7", dir="io")), - extras=["IO_STANDARD=SB_LVCMOS33"] + extras={"IO_STANDARD": "SB_LVCMOS33"} ), ] -- 2.30.2