-
Notifications
You must be signed in to change notification settings - Fork 615
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The namespace disambiguates requests for the same name with _<idx>. 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 "_<idx>". 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.
- Loading branch information
1 parent
269ce47
commit 36b81f7
Showing
2 changed files
with
136 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <prefix>_# names before <prefix> 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 <prefix>_# names in the middle of <prefix> 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 <prefix>_# names in the middle of longer <prefix> 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") | ||
} | ||
} |