Merge pull request #1424 from ucb-bar/new-cfg-finder
New Scala-based Config Finder
This commit is contained in:
@@ -149,7 +149,12 @@ lazy val chipyard = (project in file("generators/chipyard"))
|
||||
gemmini, icenet, tracegen, cva6, nvdla, sodor, ibex, fft_generator,
|
||||
constellation, mempress)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
.settings(
|
||||
libraryDependencies ++= Seq(
|
||||
"org.reflections" % "reflections" % "0.10.2"
|
||||
)
|
||||
)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val mempress = (project in file("generators/mempress"))
|
||||
.dependsOn(rocketchip, midasTargetUtils)
|
||||
|
||||
10
common.mk
10
common.mk
@@ -50,7 +50,7 @@ HELP_COMMANDS += \
|
||||
" run-tests = run all assembly and benchmark tests" \
|
||||
" launch-sbt = start sbt terminal" \
|
||||
" {shutdown,start}-sbt-server = shutdown or start sbt server if using ENABLE_SBT_THIN_CLIENT" \
|
||||
" find-config-fragments = list all config. fragments and their locations (recursive up to CONFIG_FRAG_LEVELS=$(CONFIG_FRAG_LEVELS))"
|
||||
" find-config-fragments = list all config. fragments"
|
||||
|
||||
#########################################################################################
|
||||
# include additional subproject make fragments
|
||||
@@ -406,13 +406,9 @@ define \n
|
||||
|
||||
endef
|
||||
|
||||
CONFIG_FRAG_LEVELS ?= 3
|
||||
.PHONY: find-config-fragments
|
||||
find-config-fragments: private IN_F := $(shell mktemp -d -t cy-XXXXXXXX)/scala_files.f
|
||||
find-config-fragments: $(SCALA_SOURCES)
|
||||
@$(foreach file,$(SCALA_SOURCES),echo $(file) >> $(IN_F)${\n})
|
||||
$(base_dir)/scripts/config-finder.py -l $(CONFIG_FRAG_LEVELS) $(IN_F)
|
||||
@rm -rf $(dir $(IN_F))
|
||||
find-config-fragments:
|
||||
$(call run_scala_main,chipyard,chipyard.ConfigFinder,)
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
|
||||
@@ -79,5 +79,4 @@ We can use this config fragment when composing our configs.
|
||||
Chipyard Config Fragments
|
||||
-------------------------
|
||||
|
||||
For discoverability, users can run ``make find-config-fragments`` to see a list of config. fragments
|
||||
(config. fragments that match "class NAME extends CONFIG\n" on a single line and a subset of their children) and their file path in a fully initialized Chipyard repository.
|
||||
For discoverability, users can run ``make find-config-fragments`` to see a list of config. fragments.
|
||||
|
||||
19
generators/chipyard/src/main/scala/ConfigFinder.scala
Normal file
19
generators/chipyard/src/main/scala/ConfigFinder.scala
Normal file
@@ -0,0 +1,19 @@
|
||||
package chipyard
|
||||
|
||||
import org.reflections.Reflections
|
||||
import org.reflections.scanners.Scanners.SubTypes
|
||||
import scala.jdk.CollectionConverters._
|
||||
import scala.collection.{SortedSet}
|
||||
|
||||
import freechips.rocketchip.config.{Config}
|
||||
|
||||
object ConfigFinder {
|
||||
def main(args: Array[String]) = {
|
||||
val reflections = new Reflections()
|
||||
val classes = reflections.get(SubTypes.of(classOf[Config]).asClass()).asScala
|
||||
val sortedClasses = SortedSet[String]() ++ classes.map(_.getName)
|
||||
for (cls <- sortedClasses) {
|
||||
println(cls)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import subprocess
|
||||
from collections import defaultdict
|
||||
import re
|
||||
from copy import deepcopy
|
||||
import os
|
||||
|
||||
cy_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
|
||||
# from https://gist.github.com/angstwad/bf22d1822c38a92ec0a9
|
||||
def deep_merge(a: dict, b: dict) -> dict:
|
||||
"""Merge two dicts and return a singular dict"""
|
||||
result = deepcopy(a)
|
||||
for bk, bv in b.items():
|
||||
av = result.get(bk)
|
||||
if isinstance(av, dict) and isinstance(bv, dict):
|
||||
result[bk] = deep_merge(av, bv)
|
||||
else:
|
||||
result[bk] = deepcopy(bv)
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Pretty print all configs given a filelist of scala files')
|
||||
parser.add_argument('FILE', type=str, help='Filelist of scala files to search within')
|
||||
parser.add_argument('-l', '--levels', default=0, type=int, help='Number of levels to recursively look for configs')
|
||||
args = parser.parse_args()
|
||||
|
||||
files = []
|
||||
with open(args.FILE, 'r') as f:
|
||||
files = f.read().splitlines()
|
||||
|
||||
cmd = ['grep', '-o', r"class \+.* \+extends \+Config"] + files
|
||||
r = subprocess.run(cmd, check=True, capture_output=True)
|
||||
|
||||
base_file_path_dict = defaultdict(list)
|
||||
for l in r.stdout.decode("UTF-8").splitlines():
|
||||
match = re.match(r"^(.*):class +([a-zA-Z_$][a-zA-Z\d_$]*).* +extends", l)
|
||||
if match:
|
||||
base_file_path_dict[match.group(1)].append(match.group(2))
|
||||
|
||||
levels = []
|
||||
for level in range(args.levels):
|
||||
if level == 0:
|
||||
# use the base
|
||||
dict_to_use = base_file_path_dict
|
||||
else:
|
||||
# use the level-1 dict
|
||||
assert len(levels) > 0
|
||||
dict_to_use = levels[-1]
|
||||
|
||||
file_path_dict = defaultdict(list)
|
||||
|
||||
for configs in dict_to_use.values():
|
||||
for config in configs:
|
||||
cmd = ['grep', '-o', r"class \+.* \+extends \+" + f"{config}"] + files
|
||||
r = subprocess.run(cmd, capture_output=True)
|
||||
|
||||
for l in r.stdout.decode("UTF-8").splitlines():
|
||||
match = re.match(r"^(.*):class +([a-zA-Z_$][a-zA-Z\d_$]*).* +extends", l)
|
||||
if match:
|
||||
file_path_dict[match.group(1)].append(match.group(2))
|
||||
|
||||
levels.append(file_path_dict)
|
||||
|
||||
final_dict = base_file_path_dict
|
||||
for dct in levels:
|
||||
final_dict = deep_merge(final_dict, dct)
|
||||
|
||||
print(f"Finding all one-line config. fragments (up to {args.levels} levels)\n")
|
||||
for k, v in final_dict.items():
|
||||
print(f"{k.replace(cy_path, 'chipyard')}:")
|
||||
for e in v:
|
||||
print(f" {e}")
|
||||
print("")
|
||||
Reference in New Issue
Block a user