From b64a31255c700f9f8b2a3a39bd77f8dac71eb029 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 3 Jun 2019 02:12:01 +0000 Subject: [PATCH] hdl.ir: accept expanded (kind, name, value) tuples in Instance. This is useful for e.g. programmatically generating parameters without having to mess with kwargs dicts. --- nmigen/hdl/ir.py | 17 ++++++++++++--- nmigen/test/test_hdl_ir.py | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/nmigen/hdl/ir.py b/nmigen/hdl/ir.py index 8836b25..eb32282 100644 --- a/nmigen/hdl/ir.py +++ b/nmigen/hdl/ir.py @@ -517,13 +517,23 @@ class Fragment: class Instance(Fragment): - def __init__(self, type, **kwargs): + def __init__(self, type, *args, **kwargs): super().__init__() self.type = type self.parameters = OrderedDict() self.named_ports = OrderedDict() + for (kind, name, value) in args: + if kind == "p": + self.parameters[name] = value + elif kind in ("i", "o", "io"): + self.named_ports[name] = (value, kind) + else: + raise NameError("Instance argument {!r} should be a tuple (kind, name, value) " + "where kind is one of \"p\", \"i\", \"o\", or \"io\"" + .format((kind, name, value))) + for kw, arg in kwargs.items(): if kw.startswith("p_"): self.parameters[kw[2:]] = arg @@ -534,5 +544,6 @@ class Instance(Fragment): elif kw.startswith("io_"): self.named_ports[kw[3:]] = (arg, "io") else: - raise NameError("Instance argument '{}' does not start with p_, i_, o_, or io_" - .format(arg)) + raise NameError("Instance keyword argument {}={!r} does not start with one of " + "\"p_\", \"i_\", \"o_\", or \"io_\"" + .format(kw, arg)) diff --git a/nmigen/test/test_hdl_ir.py b/nmigen/test/test_hdl_ir.py index e2426cf..850e5f4 100644 --- a/nmigen/test/test_hdl_ir.py +++ b/nmigen/test/test_hdl_ir.py @@ -547,6 +547,50 @@ class FragmentHierarchyConflictTestCase(FHDLTestCase): class InstanceTestCase(FHDLTestCase): + def test_construct(self): + s1 = Signal() + s2 = Signal() + s3 = Signal() + s4 = Signal() + s5 = Signal() + s6 = Signal() + inst = Instance("foo", + ("p", "PARAM1", 0x1234), + ("i", "s1", s1), + ("o", "s2", s2), + ("io", "s3", s3), + p_PARAM2=0x5678, + i_s4=s4, + o_s5=s5, + io_s6=s6, + ) + self.assertEqual(inst.parameters, OrderedDict([ + ("PARAM1", 0x1234), + ("PARAM2", 0x5678), + ])) + self.assertEqual(inst.named_ports, OrderedDict([ + ("s1", (s1, "i")), + ("s2", (s2, "o")), + ("s3", (s3, "io")), + ("s4", (s4, "i")), + ("s5", (s5, "o")), + ("s6", (s6, "io")), + ])) + + def test_wrong_construct_arg(self): + s = Signal() + with self.assertRaises(NameError, + msg="Instance argument ('', 's1', (sig s)) should be a tuple " + "(kind, name, value) where kind is one of \"p\", \"i\", \"o\", or \"io\""): + Instance("foo", ("", "s1", s)) + + def test_wrong_construct_kwarg(self): + s = Signal() + with self.assertRaises(NameError, + msg="Instance keyword argument x_s1=(sig s) does not start with one of " + "\"p_\", \"i_\", \"o_\", or \"io_\""): + Instance("foo", x_s1=s) + def setUp_cpu(self): self.rst = Signal() self.stb = Signal() -- 2.30.2