The Chisel plugin provides some operations that are too difficult, or not possbile, to implement through regular Scala code.
These are the two things that the compile plugin does.
- Automatically generates the
cloneTypemethods of Bundle - Changes the underlying mechanics of the
Bundleselementsmethod in a way that does not require the use of reflection - Future work: Make having a Seq[Data] in a bundle be a compiler error. See "Detecting Bundles with Seq[Data]" below.
As of Mar 18, 2021, PR #1826, generating the cloneType method (1. above) is now the default behavior.
The cloneType method used to be a tricky thing to write for chisel developers.
For historical purposes, here is the flag was used to control that prior to full adoption.
-P:chiselplugin:useBundlePlugin
A Bundle has a default elements method that relies on reflection, which is slow and brittle, to access the list of
fields the bundle contains.
When enabled this second operation of the plugin examines
the Bundles AST in order to determine the fields and then re-writes the underlying code of elements.
Technically, rewriting a lower level private method _elementsImpl.
It is expected that the using this feature will shortly become the default.
The plugin should not be enabled for the
mainchisel3 project because of internal considerations. It is enabled for theTestsection.
In the meantime, advanced users can try using the feature by adding the following flag to the scalac options in their chisel projects.
-P:chiselplugin:buildElementAccessor
For example in an build.sbt file adding the line
scalacOptions += "-P:chiselplugin:genBundleElements",
in the appropriate place.
Trying to have a val Seq[Data] (as opposed to a val Vec[Data] in a Bundle is a run time error.
Here is a block of code that could be added to the plugin to detect this case at compile time (with some refinement in
the detection mechanism):
if (member.isAccessor && typeIsSeqOfData(member.tpe) && !isIgnoreSeqInBundle(bundleSymbol)) {
global.reporter.error(
member.pos,
s"Bundle.field ${bundleSymbol.name}.${member.name} cannot be a Seq[Data]. " +
"Use Vec or MixedVec or mix in trait IgnoreSeqInBundle"
)
}In general the easiest way to develop and debug new code in the plugin is to use println statements.
Naively this can result in reams of text that can be very hard to look through.
What I found to be useful was creating some wrappers for println that only printed when the Bundles had a particular name pattern.
- Create a regular expression string in the
BundleComponentclass - Add a printf wrapper name
showthat checks theBundle's name against the regex - For recursive code in
getAllBundleFieldscreate a different wrapperindentShowthat indents debug lines - Sprinkle calls to these wrappers as needed for debugging
val bundleNameDebugRegex = "MyBundle.*"show should be inside case bundle block of the transform method in order to have access to the current Bundle
def show(string: => String): Unit = {
if (bundle.symbol.name.toString.matches(bundleNameDebugRegex)) {
println(string)
}
}This method can be added into BundleComponent.scala in the transform method after case Bundle
Inside of getAllBundleFields I added the following code that indented for each recursion up the current
Bundle's hierarchy.
def indentShow(s: => String): Unit = {
val indentString = ("-" * depth) * 2 + "> "
s.split("\n").foreach { line =>
show(indentString + line)
}
}