-
Notifications
You must be signed in to change notification settings - Fork 639
Define leading '_' as API for creating temporaries #2580
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I've marked this 3.6 because it has a fairly large impact on code gen stability when bumping and I am not sure that's a great thing to do in a minor release. That being said I could be convinced that this makes sense in 3.5.4. |
@@ -66,15 +66,15 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) extends | |||
if (id.isSynthesizable) { | |||
id.topBinding match { | |||
case OpBinding(_, _) => | |||
id.forceName(Some(""), default = "T", _namespace) | |||
id.forceName(None, default = "_T", _namespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realized that my changes here make the "defaultPrefix" argument of _computeName
redundant so I need to further clean that up.
@@ -186,7 +186,7 @@ private[chisel3] trait HasId extends InstanceId { | |||
} else { | |||
defaultSeed.map { default => | |||
defaultPrefix match { | |||
case Some(p) => buildName(default, p :: naming_prefix.reverse) | |||
case Some(p) => buildName(default, naming_prefix.reverse) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code can get a lot simpler now, TODO fix.
This release notes info is great. WDYT about codifying some of this into a Chisel spec? Possibly useful, but the way this is evolving on the FIRRTL Dialect side is that ops have a name kind enum that qualify the utility of keeping a name around and let the compiler reason about this for different optimization levels. Currently there are two values: (1) interesting and (2) droppable. This matches the existing non-underscore (droppable) and named (interesting) convention, but allows for further enumeration going forward and avoids permanently encoding this information in the leading character of a string. |
9bce4d1
to
9204d39
Compare
9204d39
to
0c23a9c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
forgot to hit "submit review" maybe you already addressed this
docs/src/explanations/naming.md
Outdated
@@ -202,6 +225,84 @@ class Example8 extends Module { | |||
ChiselStage.emitVerilog(new Example8) | |||
``` | |||
|
|||
Note that using `.suggestName` does *not* affect prefixes derived from val names; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you give an example of this val name
case not affecting suggestName results?
Maybe this whole section should be warning-ed with " this is how suggestName works today, its behavior of is subject to change..."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example is right below this line 😉, pasting from the mdoc-output of this section:
EDIT: See updated version in comment below
Note that using .suggestName
does not affect prefixes derived from val names; however, it can affect prefixes derived from connections (eg. :=)
:
class ConnectionPrefixExample extends Module {
val in0 = IO(Input(UInt(2.W)))
val in1 = IO(Input(UInt(2.W)))
val out0 = IO(Output(UInt()))
val out1 = IO(Output(UInt()))
out0 := {
// out0_sum
val sum = in0 + in1
sum + 1.U
}
// Comes after so does *not* affect prefix above
out0.suggestName("foo")
// Comes before so *does* affect prefix below
out1.suggestName("bar")
out1 := {
// bar_diff
val diff = in0 - in1
diff + 1.U
}
}
module ConnectionPrefixExample(
input clock,
input reset,
input [1:0] in0,
input [1:0] in1,
output [1:0] foo,
output [1:0] bar
);
wire [1:0] out0_sum = in0 + in1; // @[naming.md 235:19]
wire [1:0] bar_diff = in0 - in1; // @[naming.md 245:20]
assign foo = out0_sum + 2'h1; // @[naming.md 236:9]
assign bar = bar_diff + 2'h1; // @[naming.md 246:10]
endmodule
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but neither of these examples is showing the suggestName on diff
itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but i think you covered that with the link to the "already covered" case about suggestName
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait sorry my response was to the wrong point, be back in a sec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just looking for an example to demonstrate what you are saying in " Note that using .suggestName
does not affect prefixes derived from val names"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added another example to that case, here's the updated text:
Note that using .suggestName
does not affect prefixes derived from val names;
however, it can affect prefixes derived from connections (eg. :=
):
class ConnectionPrefixExample extends Module {
val in0 = IO(Input(UInt(2.W)))
val in1 = IO(Input(UInt(2.W)))
val out0 = {
val port = IO(Output(UInt()))
// Even though this suggestName is before mul, the prefix used in this scope
// is derived from `val out0`, so this does not affect the name of mul
port.suggestName("foo")
// out0_mul
val mul = in0 * in1
port := mul + 1.U
port
}
val out1 = IO(Output(UInt()))
val out2 = IO(Output(UInt()))
out1 := {
// out1_sum
val sum = in0 + in1
sum + 1.U
}
// Comes after so does *not* affect prefix above
out1.suggestName("bar")
// Comes before so *does* affect prefix below
out2.suggestName("fizz")
out2 := {
// fizz_diff
val diff = in0 - in1
diff + 1.U
}
}
module ConnectionPrefixExample(
input clock,
input reset,
input [1:0] in0,
input [1:0] in1,
output [3:0] foo,
output [1:0] bar,
output [1:0] fizz
);
wire [3:0] out0_mul = in0 * in1; // @[naming.md 235:19]
wire [1:0] out1_sum = in0 + in1; // @[naming.md 245:19]
wire [1:0] fizz_diff = in0 - in1; // @[naming.md 255:20]
assign foo = out0_mul + 4'h1; // @[naming.md 236:17]
assign bar = out1_sum + 2'h1; // @[naming.md 246:9]
assign fizz = fizz_diff + 2'h1; // @[naming.md 256:10]
endmodule
As this example illustrates, this behavior is slightly inconsistent so is subject to change in a future version of Chisel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I'm going to tweak it to make it even more obvious by putting the .suggestName
on port
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay further updated
@seldridge I think that would be a good thing to do. It would be fairly straightforward to specify the semantics/rules for emitting FIRRTL at least. It's a bit more difficult for defining down to Verilog until we have stronger guarantees on how things lower from FIRRTL to Verilog but perhaps it's time to at least get the ball rolling. |
Chisel and FIRRTL have long used signals with names beginning with an underscore as an API to specify that the name does not really matter. Tools like Verilator follow a similar convention and exclude signals with underscore names from waveform dumps by default. With the introduction of compiler-plugin prefixing in Chisel 3.4, the convention remained but was hard for users to use unless the unnnamed signal existed outside of any prefix domain. Notably, unnamed signals are most useful when creating wires inside of utility methods which almost always results in the signal ending up with a prefix. With this commit, Chisel explicitly recognizes signals whos val names start with an underscore and preserve that underscore regardless of any prefixing. Chisel will also ignore such underscores when generating prefixes based on the temporary signal, preventing accidental double underscores in the names of signals that are prefixed by the temporary.
0c23a9c
to
ec178aa
Compare
@mwachs5 I think this is ready to |
Note this is 3.6.0 though, might be nice to backport some of the docs changes to 3.5 so it shows up on the website |
Prefixing can also be derived from the name of signals on the left-hand side of a connection. | ||
While this is not implemented via the compiler plugin, the behavior should feel similar: | ||
|
||
```scala mdoc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is very helpful in an explanation doc!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is all crazy complicated but happy to approve the better docs of the status quo if we are open to changing them!
Note this is 3.6.0 though, might be nice to backport some of the docs changes to 3.5 so it shows up on the website I agree -- if we can backport the docs and tests without the |
Before we merge this, let me check if this actually impacts names that much. If the impact is very minor, we can backport the full PR. If the impact is huge, then I'll just backport the docs improvements. |
Okay this actually has zero impact on naming unless you intentionally name things with leading |
…2581) * Define leading '_' as API for creating temporaries Chisel and FIRRTL have long used signals with names beginning with an underscore as an API to specify that the name does not really matter. Tools like Verilator follow a similar convention and exclude signals with underscore names from waveform dumps by default. With the introduction of compiler-plugin prefixing in Chisel 3.4, the convention remained but was hard for users to use unless the unnnamed signal existed outside of any prefix domain. Notably, unnamed signals are most useful when creating wires inside of utility methods which almost always results in the signal ending up with a prefix. With this commit, Chisel explicitly recognizes signals whos val names start with an underscore and preserve that underscore regardless of any prefixing. Chisel will also ignore such underscores when generating prefixes based on the temporary signal, preventing accidental double underscores in the names of signals that are prefixed by the temporary. (cherry picked from commit bd94366) * Remove unused defaultPrefix argument from _computeName (cherry picked from commit ec178aa) # Conflicts: # core/src/main/scala/chisel3/Module.scala # core/src/main/scala/chisel3/experimental/hierarchy/ModuleClone.scala * Resolve backport conflicts * Waive false positive binary compatibility errors Co-authored-by: Jack Koenig <koenig@sifive.com>
Note, I've rendered the updated docs here.
Chisel and FIRRTL have long used signals with names beginning with an
underscore as an API to specify that the name does not really matter.
Tools like Verilator follow a similar convention and exclude signals
with underscore names from waveform dumps by default. With the
introduction of compiler-plugin prefixing in Chisel 3.4, the convention
remained but was hard for users to use unless the unnnamed signal
existed outside of any prefix domain. Notably, unnamed signals are most
useful when creating wires inside of utility methods which almost always
results in the signal ending up with a prefix.
With this commit, Chisel explicitly recognizes signals whos val names
start with an underscore and preserve that underscore regardless of any
prefixing. Chisel will also ignore such underscores when generating
prefixes based on the temporary signal, preventing accidental double
underscores in the names of signals that are prefixed by the temporary.
Here's a specific example of the change this makes, Given:
Chisel master (and 3.4.3) currently compile this to:
Now this is compiled to:
Note that
out__sum
andout__sum2
become_out_sum
and_out_sum2
. This change comes from Chisel effectively recognizing the leading_
is not actually part of the name, but is the signifier of a temporary so it is stripped from the "seed" and moved to the front of the final name.Also note that
_out__sum2_T
becomes_out_sum2_T
. This functionality looks similar to the previous paragraph, but is actually a totally different change where Chisel, again recognizing that_
is the signifier of a temporary and not really part of the name, actually ignores the leading_
for generating prefixes from signals.Between these two changes, I think the naming behavior is a pretty nice improvement over the current behavior.
Contributor Checklist
docs/src
?Type of Improvement
API Impact
This adds a new API to let users creating "temporary" signals. I will note that this might have a s
Backend Code Generation Impact
This only changes names when there are vals in user's Chisel code which names that start with
_
. This is an extremely uncommon pattern so given the power this unlocks and the improved user API, I think this is appropriate for release in v3.5.4.Desired Merge Strategy
Release Notes
Define leading '_' as API for creating temporaries. Chisel will now preserve the leading
_
for any val-named signal which signifies to FIRRTL and other backend tools that the name does not matter. Chisel also now ignores the leading_
in prefixes generated from such "unnamed signals" which reduces the number of cases of double__
in the middle of signal names.Reviewer Checklist (only modified by reviewer)
3.4.x
, [small] API extension:3.5.x
, API modification or big change:3.6.0
)?Enable auto-merge (squash)
, clean up the commit message, and label withPlease Merge
.Create a merge commit
.