From 51269ad4a037f7789a44cf1d1dd3256f447cd619 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 26 Oct 2019 00:09:53 +0000 Subject: [PATCH] hdl.ast: simplify {bit,word}_select with constant offset. We don't have any other convenient shortcut for x[off*w:(off+1)*w], but using word_select to extract a single static range would result in severe bloat of emitted code through expansion to dead branches. Recognize and simplify this pattern. --- nmigen/hdl/ast.py | 6 ++++++ nmigen/test/test_hdl_ast.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index e0314cd..3bc9cb0 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -304,6 +304,9 @@ class Value(metaclass=ABCMeta): Part, out Selected part of the ``Value`` """ + offset = Value.cast(offset) + if type(offset) is Const and isinstance(width, int): + return self[offset.value:offset.value + width] return Part(self, offset, width, stride=1, src_loc_at=1) def word_select(self, offset, width): @@ -324,6 +327,9 @@ class Value(metaclass=ABCMeta): Part, out Selected part of the ``Value`` """ + offset = Value.cast(offset) + if type(offset) is Const and isinstance(width, int): + return self[offset.value * width:(offset.value + 1) * width] return Part(self, offset, width, stride=width, src_loc_at=1) def matches(self, *patterns): diff --git a/nmigen/test/test_hdl_ast.py b/nmigen/test/test_hdl_ast.py index 6968910..84f8184 100644 --- a/nmigen/test/test_hdl_ast.py +++ b/nmigen/test/test_hdl_ast.py @@ -533,15 +533,23 @@ class BitSelectTestCase(FHDLTestCase): def test_shape(self): s1 = self.c.bit_select(self.s, 2) + self.assertIsInstance(s1, Part) self.assertEqual(s1.shape(), unsigned(2)) self.assertIsInstance(s1.shape(), Shape) s2 = self.c.bit_select(self.s, 0) + self.assertIsInstance(s2, Part) self.assertEqual(s2.shape(), unsigned(0)) def test_stride(self): s1 = self.c.bit_select(self.s, 2) + self.assertIsInstance(s1, Part) self.assertEqual(s1.stride, 1) + def test_const(self): + s1 = self.c.bit_select(1, 2) + self.assertIsInstance(s1, Slice) + self.assertRepr(s1, """(slice (const 8'd0) 1:3)""") + def test_width_wrong(self): with self.assertRaises(TypeError): self.c.bit_select(self.s, -1) @@ -558,13 +566,20 @@ class WordSelectTestCase(FHDLTestCase): def test_shape(self): s1 = self.c.word_select(self.s, 2) + self.assertIsInstance(s1, Part) 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.assertEqual(s1.stride, 2) + def test_const(self): + s1 = self.c.word_select(1, 2) + self.assertIsInstance(s1, Slice) + self.assertRepr(s1, """(slice (const 8'd0) 2:4)""") + def test_width_wrong(self): with self.assertRaises(TypeError): self.c.word_select(self.s, 0) -- 2.30.2