From c21f31d09f2511497cea5cb03bd6ddba440c55fe Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Tue, 29 Nov 2022 17:24:38 +0000 Subject: Implement compressed Namespace (backport #2856) (#2860) * Implement compressed Namespace (#2856) The namespace disambiguates requests for the same name with _. Rather than storing every disambiguated name in the underlying HashMap, it now only stores the base along with the "next available" index. This makes the logic for checking if a name is already contained in the namespace slightly more sophisticated because users can name things in a way that will collide with disambiguated names from a common substring. For example, in naming the sequence "foo", "foo", "foo_1", the 2nd "foo" takes the name "foo_1" so the following "foo_1" gets disambiguated to "foo_1_1". But since we compressed that original "foo_1" into the same HashMap entry as just "foo", we have to do a form of "prefix checking" whenever naming something that ends in "_". In practice, the saved memory allocations more than make up for the more complicated logic to disambiguate names because the common case is still fast. (cherry picked from commit 1654d87a02ca799bf12805a611a91e7524d49843) # Conflicts: # core/src/main/scala/chisel3/internal/Builder.scala * Resolve backport conflicts Co-authored-by: Jack Koenig --- .../scala/chisel3/internal/NamespaceSpec.scala | 81 ++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/test/scala/chisel3/internal/NamespaceSpec.scala (limited to 'src') diff --git a/src/test/scala/chisel3/internal/NamespaceSpec.scala b/src/test/scala/chisel3/internal/NamespaceSpec.scala new file mode 100644 index 00000000..fd808ff0 --- /dev/null +++ b/src/test/scala/chisel3/internal/NamespaceSpec.scala @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.internal + +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers._ + +class NamespaceSpec extends AnyFlatSpec { + behavior.of("Namespace") + + they should "support basic disambiguation" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x") should be("x") + name("x") should be("x_1") + name("x") should be("x_2") + } + + they should "support explicit _# names before names" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x_1") should be("x_1") + name("x_2") should be("x_2") + name("x") should be("x") + name("x") should be("x_3") + } + + they should "support explicit _# names in the middle of names" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x") should be("x") + name("x") should be("x_1") + name("x_1") should be("x_1_1") + name("x_2") should be("x_2") + name("x") should be("x_3") + } + + // For some reason, multi-character names tickled a different failure mode than single character + they should "support explicit _# names in the middle of longer names" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("foo") should be("foo") + name("foo") should be("foo_1") + name("foo_1") should be("foo_1_1") + name("foo_2") should be("foo_2") + name("foo") should be("foo_3") + } + + they should "support collisions in recursively growing names" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x") should be("x") + name("x") should be("x_1") + name("x_1") should be("x_1_1") + name("x_1") should be("x_1_2") + name("x_1_1") should be("x_1_1_1") + name("x_1_1") should be("x_1_1_2") + } + + they should "support collisions in recursively shrinking names" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x_1_1") should be("x_1_1") + name("x_1_1") should be("x_1_1_1") + name("x_1") should be("x_1") + name("x_1") should be("x_1_2") + name("x") should be("x") + name("x") should be("x_2") + } + + // The namespace never generates names with _0 so it's actually a false collision case + they should "properly handle false collisions with signals ending in _0" in { + val namespace = Namespace.empty + val name = namespace.name(_, false) + name("x") should be("x") + name("x") should be("x_1") + name("x_0") should be("x_0") + name("x") should be("x_2") + name("x_0") should be("x_0_1") + } +} -- cgit v1.2.3