From 4278652edae7ddf07a2ca2471508e9f6964b2e51 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 29 Sep 2021 16:53:32 +0100 Subject: [PATCH] add redirection of __Part__ to allow overrides for advanced behaviour without changing fundamental language characteristics or semantics of nmigen https://bugs.libre-soc.org/show_bug.cgi?id=458 --- nmigen/hdl/ast.py | 15 ++++++++++++--- nmigen/hdl/xfrm.py | 2 +- tests/test_hdl_ast.py | 10 +++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index 9d0cbc2..1df331e 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -16,6 +16,7 @@ __all__ = [ "Value", "Const", "C", "AnyConst", "AnySeq", "Operator", "Mux", "Part", "Slice", "Cat", "Repl", "Array", "ArrayProxy", "_InternalSwitch", "_InternalAssign", "_InternalRepl", "_InternalCat", + "_InternalPart", "Signal", "ClockSignal", "ResetSignal", "UserValue", "ValueCastable", "Sample", "Past", "Stable", "Rose", "Fell", "Initial", @@ -156,6 +157,10 @@ class Value(metaclass=ABCMeta): # *MUST NOT* use "Type (2) - dsl.Module" nmigen language constructs # (m.If, m.Else, m.Switch, m.FSM): it creates complications in dsl.Module. + def __Part__(self, offset, width, stride, *, src_loc_at=0): + return _InternalPart(self, offset, width, stride, src_loc_at=src_loc_at) + def __Repl__(self, count, *, src_loc_at=0): + return _InternalRepl(self, count, src_loc_at=src_loc_at) def __Repl__(self, count, *, src_loc_at=0): return _InternalRepl(self, count, src_loc_at=src_loc_at) def __Cat__(self, *args, src_loc_at=0): @@ -803,7 +808,11 @@ class Slice(Value): @final -class Part(Value): +def Part(value, offset, width, stride=1, *, src_loc_at=0): + return value.__Part__(offset, width, stride, src_loc_at=src_loc_at) + + +class _InternalPart(Value): def __init__(self, value, offset, width, stride=1, *, src_loc_at=0): if not isinstance(width, int) or width < 0: raise TypeError("Part width must be a non-negative integer, not {!r}".format(width)) @@ -1703,7 +1712,7 @@ class ValueKey: tuple(ValueKey(o) for o in self.value.operands))) elif isinstance(self.value, Slice): self._hash = hash((ValueKey(self.value.value), self.value.start, self.value.stop)) - elif isinstance(self.value, Part): + elif isinstance(self.value, _InternalPart): self._hash = hash((ValueKey(self.value.value), ValueKey(self.value.offset), self.value.width, self.value.stride)) elif isinstance(self.value, _InternalCat): @@ -1743,7 +1752,7 @@ class ValueKey: return (ValueKey(self.value.value) == ValueKey(other.value.value) and self.value.start == other.value.start and self.value.stop == other.value.stop) - elif isinstance(self.value, Part): + elif isinstance(self.value, _InternalPart): return (ValueKey(self.value.value) == ValueKey(other.value.value) and ValueKey(self.value.offset) == ValueKey(other.value.offset) and self.value.width == other.value.width and diff --git a/nmigen/hdl/xfrm.py b/nmigen/hdl/xfrm.py index a073617..cd75531 100644 --- a/nmigen/hdl/xfrm.py +++ b/nmigen/hdl/xfrm.py @@ -102,7 +102,7 @@ class ValueVisitor(metaclass=ABCMeta): new_value = self.on_Operator(value) elif type(value) is Slice: new_value = self.on_Slice(value) - elif type(value) is Part: + elif type(value) is _InternalPart: new_value = self.on_Part(value) elif type(value) is _InternalCat: new_value = self.on_Cat(value) diff --git a/tests/test_hdl_ast.py b/tests/test_hdl_ast.py index 7b12398..28a12a5 100644 --- a/tests/test_hdl_ast.py +++ b/tests/test_hdl_ast.py @@ -663,16 +663,16 @@ class BitSelectTestCase(FHDLTestCase): def test_shape(self): s1 = self.c.bit_select(self.s, 2) - self.assertIsInstance(s1, Part) + self.assertIsInstance(s1, _InternalPart) self.assertEqual(s1.shape(), unsigned(2)) self.assertIsInstance(s1.shape(), Shape) s2 = self.c.bit_select(self.s, 0) - self.assertIsInstance(s2, Part) + self.assertIsInstance(s2, _InternalPart) self.assertEqual(s2.shape(), unsigned(0)) def test_stride(self): s1 = self.c.bit_select(self.s, 2) - self.assertIsInstance(s1, Part) + self.assertIsInstance(s1, _InternalPart) self.assertEqual(s1.stride, 1) def test_const(self): @@ -696,13 +696,13 @@ class WordSelectTestCase(FHDLTestCase): def test_shape(self): s1 = self.c.word_select(self.s, 2) - self.assertIsInstance(s1, Part) + self.assertIsInstance(s1, _InternalPart) self.assertEqual(s1.shape(), unsigned(2)) self.assertIsInstance(s1.shape(), Shape) def test_stride(self): s1 = self.c.word_select(self.s, 2) - self.assertIsInstance(s1, Part) + self.assertIsInstance(s1, _InternalPart) self.assertEqual(s1.stride, 2) def test_const(self): -- 2.30.2