Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: b67f5cfa6564
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6b843b5be6fd
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Jul 2, 2019

  1. hdl.rec: implement Record.like.

    Fixes #120.
    whitequark committed Jul 2, 2019
    Copy the full SHA
    34f1101 View commit details
  2. hdl.rec: implement slicing by component names.

    Fixes #121.
    whitequark committed Jul 2, 2019
    Copy the full SHA
    6b843b5 View commit details
Showing with 54 additions and 2 deletions.
  1. +25 −2 nmigen/hdl/rec.py
  2. +29 −0 nmigen/test/test_hdl_rec.py
27 changes: 25 additions & 2 deletions nmigen/hdl/rec.py
Original file line number Diff line number Diff line change
@@ -56,8 +56,15 @@ def __init__(self, fields):
shape = (shape, False)
self.fields[name] = (shape, direction)

def __getitem__(self, name):
return self.fields[name]
def __getitem__(self, item):
if isinstance(item, tuple):
return Layout([
(name, shape, dir)
for (name, (shape, dir)) in self.fields.items()
if name in item
])

return self.fields[item]

def __iter__(self):
for name, (shape, dir) in self.fields.items():
@@ -69,6 +76,16 @@ def __eq__(self, other):

# Unlike most Values, Record *can* be subclassed.
class Record(Value):
@classmethod
def like(cls, other, name=None, name_suffix=None, src_loc_at=0):
if name is not None:
new_name = str(name)
elif name_suffix is not None:
new_name = other.name + str(name_suffix)
else:
new_name = tracer.get_var_name(depth=2 + src_loc_at, default=None)
return cls(other.layout, new_name)

def __init__(self, layout, name=None, *, fields=None):
if name is None:
name = tracer.get_var_name(default=None)
@@ -111,6 +128,12 @@ def __getitem__(self, item):
reference = "Record '{}'".format(self.name)
raise AttributeError("{} does not have a field '{}'. Did you mean one of: {}?"
.format(reference, item, ", ".join(self.fields))) from None
elif isinstance(item, tuple):
return Record(self.layout[item], fields={
field_name: field_value
for field_name, field_value in self.fields.items()
if field_name in item
})
else:
return super().__getitem__(item)

29 changes: 29 additions & 0 deletions nmigen/test/test_hdl_rec.py
Original file line number Diff line number Diff line change
@@ -25,6 +25,18 @@ def test_fields(self):
self.assertEqual(sublayout["a"], ((1, False), DIR_NONE))
self.assertEqual(sublayout["b"], ((1, False), DIR_NONE))

def test_slice_tuple(self):
layout = Layout.wrap([
("a", 1),
("b", 2),
("c", 3)
])
expect = Layout.wrap([
("a", 1),
("c", 3)
])
self.assertEqual(layout["a", "c"], expect)

def test_wrong_field(self):
with self.assertRaises(TypeError,
msg="Field (1,) has invalid layout: should be either (name, shape) or "
@@ -129,6 +141,23 @@ def test_construct_with_fields(self):
self.assertIs(r.stb, ns)
self.assertIs(r.info, nr)

def test_like(self):
r1 = Record([("a", 1), ("b", 2)])
r2 = Record.like(r1)
self.assertEqual(r1.layout, r2.layout)
self.assertEqual(r2.name, "r2")
r3 = Record.like(r1, name="foo")
self.assertEqual(r3.name, "foo")
r4 = Record.like(r1, name_suffix="foo")
self.assertEqual(r4.name, "r1foo")

def test_slice_tuple(self):
r1 = Record([("a", 1), ("b", 2), ("c", 3)])
r2 = r1["a", "c"]
self.assertEqual(r2.layout, Layout([("a", 1), ("c", 3)]))
self.assertIs(r2.a, r1.a)
self.assertIs(r2.c, r1.c)


class ConnectTestCase(FHDLTestCase):
def setUp_flat(self):