-
Notifications
You must be signed in to change notification settings - Fork 689
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
Allow "lite" Chipyard builds with a minimal subset of submodules #2212
base: main
Are you sure you want to change the base?
Conversation
This is a really cool idea! Some thoughts that come to mind:
The other thought is, how to support people integrating new generators according to the rules, now that the rule also includes editing the shell script and a slightly different sbt process? Since all the effort to refactor things just collapses if people add their new submodules to default build anyway. Or maybe that doesn't matter as long proper integration is enforced when upstreaming? (+mandatory "idrk" disclaimer xD) |
Default should probably be full.
Some submodules have internal submodules, which might need to be initialized as well. I think the speed improvement will be noticeable once all the optional blocks are not initialized. Another motivation for this is to lower the barrier-to-entry for adding new generators to chipyard. We can add new projects without having to rationalize that the usefulness outweighs the additional bloat.
Yes, I haven't gone through the process of adding the flags to build-setup. I've only added them to init-submodules for now. Feedback here on the right user interface would be appreciated.
Yes, the documentation for adding new generators, and the process for doing so, should be simplified. |
I like CY-lite. It would be ideal if we can flatten stuff like testchipip, rocketchip, inclusive l2 during this process, but I know it is a lot of work... |
Flattening RC and RC-LLC are non-starters (and I don't think this buys anything). |
06340bd
to
740c9ea
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.
- Is it better to have the default be full Chipyard or lean Chipyard? The default for conda build right now is full, with lean being a flag, so it feels like a potential confusion to have Chipyard be the opposite.
Default should probably be full.
- So might be worth exploring which submodules should be part of a minimal build. Are there enough of them unused to have a speedup/size reduction?
Some submodules have internal submodules, which might need to be initialized as well. I think the speed improvement will be noticeable once all the optional blocks are not initialized.
Another motivation for this is to lower the barrier-to-entry for adding new generators to chipyard. We can add new projects without having to rationalize that the usefulness outweighs the additional bloat.
- Maybe there could be a separate --lean flag which allows a more stripped down baseline, the --full flag which adds everything everything in, and the default is some in between which hopefully covers most existing use cases.
Assuming some people clone "minimal" Chipyard, then the default flow would be to run the init-submod...*
script to add those submodules back in? IMO a minimal Chipyard makes a lot of sense as the default, then we tell users to use the said script to re-build it up to what they want (most initial users probably only care about the core submodules - Rocket + L2 + testchipip + etc - for the most part)
Yes, I haven't gone through the process of adding the flags to build-setup. I've only added them to init-submodules for now. Feedback here on the right user interface would be appreciated.
Spitballing the minimal setup, build-setup
is defaulting to minimal Chipyard. Then we move the init-submodules to the top-level of the repo and clean up it's API/name to make it clear this is how to add/remove packages (i.e. submodules). Then users after build-setup can modify the packages using that script.
The other thought is, how to support people integrating new generators according to the rules, now that the rule also includes editing the shell script and a slightly different sbt process? Since all the effort to refactor things just collapses if people add their new submodules to default build anyway. Or maybe that doesn't matter as long proper integration is enforced when upstreaming?
Yes, the documentation for adding new generators, and the process for doing so, should be simplified.
I personally am not a fan of the symlinking but I don't know of a better way to do this right now.
include $(base_dir)/generators/tracegen/tracegen.mk | ||
include $(base_dir)/generators/nvdla/nvdla.mk | ||
include $(base_dir)/generators/radiance/radiance.mk | ||
include $(base_dir)/tools/torture.mk |
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.
Nit: Do we want to also ignore unfound files for the other repositories?
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 PR will eventually make those repos also optional
|
||
######################################################################################### | ||
# Prerequisite lists | ||
######################################################################################### | ||
# Returns a list of files in directories $1 with single file extension $2. | ||
# If available, use 'fd' to find the list of files, which is faster than 'find'. | ||
ifeq ($(shell which fd 2> /dev/null),) | ||
lookup_srcs = $(shell find -L $(1)/ -name target -prune -o \( -iname "*.$(2)" ! -iname ".*" \) -print 2> /dev/null) | ||
lookup_srcs = $(shell find -L $(1)/ -name target -prune -o \( ! -xtype l -a -iname "*.$(2)" ! -iname ".*" \) -print 2> /dev/null) |
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 we make this find expression easier to read, i.e. not a symlink and (name is $(2) and not name .*)
. Currently, this is quite hard to parse.
common.mk
Outdated
else | ||
lookup_srcs = $(shell fd -L -t f -e $(2) . $(1)) | ||
endif | ||
|
||
# Returns a list of files in directories $1 with *any* of the file extensions in $2 | ||
lookup_srcs_by_multiple_type = $(foreach type,$(2),$(call lookup_srcs,$(1),$(type))) | ||
|
||
CHECK_SUBMODULES_COMMAND = echo "Checking all submodules in generators/ are initialized. Uninitialized submodules will be displayed" ; ! git submodule status $(base_dir)/generators | grep ^- | ||
CHECK_SUBMODULES_COMMAND = echo "Checking required submodules in generators/ are initialized. Uninitialized submodules will be displayed" ; ! git submodule status $(base_dir)/generators | grep '^-.*' | grep -vE "(ara|caliptra|compress)" |
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 to me seems brittle, I expect users to forget to add things to this list. Can we auto-generate this list based on something else (maybe we just specify the core set of submodules instead excluding the extension submodules)
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 would need a "Single-source-of-truth" for listing what submodules are required/optional. I don't believe build.sbt sould be that single-source-of-truth... it would be another consumer
We could define a yaml/json somewhere in chipyard that all the scripts reference.
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 the intent that this YAML/JSON feeds into the build.sbt
, which then parses this file? If so, then we need to encode dependencies, which, in my opinion, is too heavy-handed. If it's separate then you need to update the YAML/JSON and the build.sbt
which also leads to the same issue (de-sync from both sets of inputs).
Brainstorming: We have a map[string -> SBTProjects]
in the build.sbt
. Users must add their project to this map
, then there is a required list[string]
that says the default required submodules. This is then passed to the main Chipyard project? Then you just need to parse that build.sbt
line (this would still be janky).
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.
So there are three options I see:
- Heavy-handed approach, with new YAML/JSON that serves as single-source-of-truth that all the other scripts and build.sbt parse
- Use build.sbt as single-source-of-truth, require parsing build.sbt in various scripts... (very ugly)
- No single-source-of-truth
I'm of the opinion that approach 1 makes the most sense, but makes the most engineering. Approach 3 is the easiest for now. I'm not a fan of the intermediate approach 2.
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.
FWIW I don't think (2) is that bad (bad but significantly less effort than (1). For example:
val projectNames: Seq[String] = Seq(
"projectA",
"projectB",
"projectC",
"projectD"
)
val projects = projectNames.map(name => project(name).settings(
// Add common settings here, if needed.
version := "1.0.0",
scalaVersion := "2.13.8" // or your desired Scala version
))
With that being said, I vote for (3) for now, if people want to fix this later (when they have time - or get annoyed enough) then they can.
compressacc, saturn, ara, firrtl2_bridge, vexiiriscv, tacit) | ||
.settings(libraryDependencies ++= rocketLibDeps.value) | ||
.settings( | ||
lazy val chipyard = { |
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.
Surprisingly not horrible. I wonder if we can encode this a bit better though... maybe we can write a quick SBT plugin to do this for us for any Chipyard submodule). Dropping https://github.com/sbt/sbt-sriracha/blob/master/src/main/scala/SrirachaPlugin.scala for a reference on how to write a plugin. Or maybe we can write a quick SBT function to wrap this (like freshProject
).
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.
SBT function seems fine.
libraryDependencies ++= Seq( | ||
"org.reflections" % "reflections" % "0.10.2" | ||
) | ||
) | ||
.settings(commonSettings) | ||
.settings(Compile / unmanagedSourceDirectories += file("tools/stage/src/main/scala")) | ||
|
||
val includeAra = file("generators/ara/.git").exists() |
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.
For now, why not add this for every SBT project Chipyard depends on (for most this would automatically add the dependency).
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 scheme currently supports only leaf projects, so we can't blanket apply this.
Co-authored-by: Abraham Gonzalez <[email protected]>
There are a lot of submodules in generators/. Currently they are all cloned, initialized, and compiled, even though most people only use a small subset of these at a time.
This PR demonstrates a path towards a "modular generator submodule" approach, here some submodules can be left uninitialized, with the consequence being that configs which depend on those submodules will not appear on the classpath, and will not be available to the user.
This PR demonstrates this with some submodules, but the approach should scale to any submodule that does not have a crazy dependency structure. Currently modularized submods are:
The changes are:
I rate the hackiness of this approach as a 4/10, mostly due to the symlinking. I don't want to mess with the directory structure, package structure, or the way the generator searches the classpath for the Config to build. Changing those could make this less hacky.
Related PRs / Issues:
Type of change:
Impact:
Contributor Checklist:
main
as the base branch?changelog:<topic>
label?changelog:
label?.conda-lock.yml
file if you updated the conda requirements file?Please Backport
?CI Help:
Add the following labels to modify the CI for a set of features.
Generally, a label added only affect subsequent changes to the PR (i.e. new commits, force pushing, closing/reopening).
See
ci:*
for full list of labels:ci:fpga-deploy
- Run FPGA-based E2E testingci:local-fpga-buildbitstream-deploy
- Build local FPGA bitstreams for platforms that are releasedci:disable
- Disable CI