-
Notifications
You must be signed in to change notification settings - Fork 604
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
Implement module prefix API #2155
base: main
Are you sure you want to change the base?
Conversation
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.
Overall looks great, nice clean implementation!
|
||
/** Elaborates a Chisel module into a circuit, but return that circuit in module form | ||
* @param gen a call-by-name Chisel module | ||
*/ | ||
def construct[T <: RawModule](gen: => T): T = { | ||
val phase = new ChiselPhase { | ||
override val targets = Seq( Dependency[chisel3.stage.phases.Checks], | ||
Dependency[chisel3.stage.phases.Elaborate] ) | ||
} | ||
|
||
phase | ||
.transform(Seq(ChiselGeneratorAnnotation(() => gen), NoRunFirrtlCompilerAnnotation)) | ||
.collectFirst { | ||
case DesignAnnotation(a) => a.asInstanceOf[T] | ||
} | ||
.get | ||
} |
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.
/** Elaborates a Chisel module into a circuit, but return that circuit in module form | |
* @param gen a call-by-name Chisel module | |
*/ | |
def construct[T <: RawModule](gen: => T): T = { | |
val phase = new ChiselPhase { | |
override val targets = Seq( Dependency[chisel3.stage.phases.Checks], | |
Dependency[chisel3.stage.phases.Elaborate] ) | |
} | |
phase | |
.transform(Seq(ChiselGeneratorAnnotation(() => gen), NoRunFirrtlCompilerAnnotation)) | |
.collectFirst { | |
case DesignAnnotation(a) => a.asInstanceOf[T] | |
} | |
.get | |
} |
This is a very large public API to add just for testing. If we want to add this, we need to be pretty thoughtful about it and with the current architecture of Chisel3, not much value comes from having references to elaborated module objects. Although arguably that should change, that's well beyond the scope of this PR.
@@ -23,6 +23,7 @@ import chisel3.internal.{firrtl => cir, ErrorLog} | |||
import chisel3.stage.CircuitSerializationAnnotation.FirrtlFileFormat | |||
|
|||
import java.io.{StringWriter, PrintWriter} | |||
import chisel3.Module |
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.
import chisel3.Module |
Related to comment about `ChiselStage.construct
@@ -200,4 +200,43 @@ class ModuleSpec extends ChiselPropSpec with Utils { | |||
val s = Source.fromFile("generated/PlusOne.v").mkString("") | |||
assert(s.contains("assign io_out = io_in + 32'h1")) | |||
} | |||
|
|||
property("withModulePrefix should prefix modules within it") { | |||
val m = ChiselStage.construct(new Module { |
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.
val m = ChiselStage.construct(new Module { | |
val m = elaborateAndGetModule(new Module { |
Related to deletion of ChiselStage.construct
, chiselTests.ChiselRunners
already defines what you need here: elaborateAndGetModule
} | ||
|
||
property("withModulePrefix should support nested module prefixing") { | ||
val m = ChiselStage.construct(new Module { |
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.
val m = ChiselStage.construct(new Module { | |
val m = elaborateAndGetModule(new Module { |
Related to deletion of ChiselStage.construct
, chiselTests.ChiselRunners
already defines what you need here: elaborateAndGetModule
@@ -88,6 +88,8 @@ object Module extends SourceInfoDoc { | |||
def reset: Reset = Builder.forcedReset | |||
/** Returns the current Module */ | |||
def currentModule: Option[BaseModule] = Builder.currentModule | |||
/** Returns the current nested module prefix */ | |||
def currentPrefix: String = Builder.getModulePrefix |
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.
def currentPrefix: String = Builder.getModulePrefix | |
def currentModulePrefix: String = Builder.getModulePrefix |
Just to avoid confusion with other uses of "prefix" which is usually referring to the intra-Module component prefixing rather than the global namespace Module prefixing.
|
||
property("withModulePrefix should prefix modules within it") { | ||
val m = ChiselStage.construct(new Module { | ||
val io = IO(new Bundle { }) |
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.
val io = IO(new Bundle { }) |
io is no longer needed, please delete from all the added Modules.
}) | ||
|
||
m.child.nestedChild.name should be ("FooBarModule") | ||
} |
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.
Because this is a generator, people may want to have generated prefixes, including empty ones. I believe this works but can you add a test showing that an empty prefix (withModulePrefix("")
) does not change the resulting modules 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.
is there any desire to "flush" the prefixing? Or is "nested" the only option?
Eg given:
Module TestHarness
Module DUT
Module A
Module B
Module VIP
If I say I want everything in TestHarness to be prefixed "TestHarness", e.g. I want TestHarnessVIP, it seems there is no way to "reset" the prefixes for DUT using withPrefix
. Is there any other API to "clear out" the prefix stack? So that I don't end up with TestHarnessDUT?
} | ||
}) | ||
|
||
m.child.nestedChild.name should be ("FooBarModule") |
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 please add a test which includes a SeqMem
and run the ReplSeqMem? What is the prefixing behavior for the seq mems?
And also please add a test for blackbox/inline black box, which should NOT get prefixes applied
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.
Agreed with all of the tests. I'll note that prefixing of SyncReadMems
is going to be tricky. I think maybe we should add a test for it but have it as ignore
right now because I'm not yet sure how we should handle it.
Discussed this again with @jackkoenig . The main limitation of this PR as it is is that we lose the "what is the prefix (ad-hoc namespace)" and "what is the leaf name" distinction. I'd suggest we do one of (in increasing order of complexity / design thought required):
|
Contributor Checklist
docs/src
?Type of Improvement
API Impact
Adds new API
Backend Code Generation Impact
No impact
Desired Merge Strategy
Squash and merge
Release Notes
Implement Module Prefix API
withModulePrefix(prefix)
, that prefixes all instantiated modules within its scope with theprefix
argumentReviewer Checklist (only modified by reviewer)
3.3.x
, [small] API extension:3.4.x
, API modification or big change:3.5.0
)?Please Merge
?