diff --git a/Makefrag b/Makefrag index d4b65209254..f1d8d8efa2e 100644 --- a/Makefrag +++ b/Makefrag @@ -6,14 +6,9 @@ endif MODEL ?= TestHarness PROJECT ?= freechips.rocketchip.system CFG_PROJECT ?= $(PROJECT) -CONFIG ?= $(CFG_PROJECT).DefaultConfig +CONFIG ?= DefaultConfig # TODO: For now must match rocketchip.Generator -comma := , -space := $() $() -splitConfigs := $(subst $(comma), ,$(CONFIG)) -configBases := $(foreach config,$(splitConfigs),$(lastword $(subst ., ,$(config)))) -CONFIG_STR := $(subst $(space),_,$(configBases)) -long_name = $(PROJECT).$(CONFIG_STR) +long_name = $(PROJECT).$(CONFIG) VLSI_MEM_GEN ?= $(base_dir)/scripts/vlsi_mem_gen diff --git a/README.md b/README.md index f5486623539..7cc69911c9b 100644 --- a/README.md +++ b/README.md @@ -284,25 +284,14 @@ Chisel generated Verilog code and its associated C++ code generated by Verilator. $ ls $ROCKETCHIP/emulator/generated-src + DefaultConfig.dts + DefaultConfig.graphml + DefaultConfig.json + DefaultConfig.memmap.json freechips.rocketchip.system.DefaultConfig - freechips.rocketchip.system.DefaultConfig.0x0.0.regmap.json - freechips.rocketchip.system.DefaultConfig.0x0.1.regmap.json - freechips.rocketchip.system.DefaultConfig.0x2000000.0.regmap.json - freechips.rocketchip.system.DefaultConfig.0x40.0.regmap.json - freechips.rocketchip.system.DefaultConfig.0xc000000.0.regmap.json - freechips.rocketchip.system.DefaultConfig.anno.json - freechips.rocketchip.system.DefaultConfig.behav_srams.v - freechips.rocketchip.system.DefaultConfig.conf freechips.rocketchip.system.DefaultConfig.d - freechips.rocketchip.system.DefaultConfig.dts freechips.rocketchip.system.DefaultConfig.fir - freechips.rocketchip.system.DefaultConfig.graphml - freechips.rocketchip.system.DefaultConfig.json - freechips.rocketchip.system.DefaultConfig.memmap.json - freechips.rocketchip.system.DefaultConfig.plusArgs - freechips.rocketchip.system.DefaultConfig.rom.conf freechips.rocketchip.system.DefaultConfig.v - TestHarness.anno.json $ ls $ROCKETCHIP/emulator/generated-src/freechips.rocketchip.system.DefaultConfig VTestHarness__1.cpp VTestHarness__2.cpp @@ -334,7 +323,7 @@ writeback stage, perhaps, because of a instruction cache miss at PC You can generate synthesizable Verilog with the following commands: $ cd $ROCKETCHIP/vsim - $ make verilog CONFIG=freechips.rocketchip.system.DefaultFPGAConfig + $ make verilog CONFIG=DefaultFPGAConfig The Verilog used for the FPGA tools will be generated in vsim/generated-src. Please proceed further with the directions shown in @@ -348,7 +337,7 @@ tests and benchmarks in simulation with the following commands (again assuming you have N cores on your host machine): $ cd $ROCKETCHIP/vsim - $ make -jN run CONFIG=freechips.rocketchip.system.DefaultFPGAConfig + $ make -jN run CONFIG=DefaultFPGAConfig The generated output looks similar to those generated from the emulator. Look into vsim/output/\*.out for the output of the executed assembly @@ -365,25 +354,15 @@ Now take a look at vsim/generated-src, and the contents of the Top.DefaultConfig.conf file: $ cd $ROCKETCHIP/vsim/generated-src - freechips.rocketchip.system.DefaultConfig - freechips.rocketchip.system.DefaultConfig.0x0.0.regmap.json - freechips.rocketchip.system.DefaultConfig.0x0.1.regmap.json - freechips.rocketchip.system.DefaultConfig.0x2000000.0.regmap.json - freechips.rocketchip.system.DefaultConfig.0x40.0.regmap.json - freechips.rocketchip.system.DefaultConfig.0xc000000.0.regmap.json - freechips.rocketchip.system.DefaultConfig.anno.json + DefaultConfig.dts + DefaultConfig.graphml + DefaultConfig.json + DefaultConfig.memmap.json freechips.rocketchip.system.DefaultConfig.behav_srams.v freechips.rocketchip.system.DefaultConfig.conf freechips.rocketchip.system.DefaultConfig.d - freechips.rocketchip.system.DefaultConfig.dts freechips.rocketchip.system.DefaultConfig.fir - freechips.rocketchip.system.DefaultConfig.graphml - freechips.rocketchip.system.DefaultConfig.json - freechips.rocketchip.system.DefaultConfig.memmap.json - freechips.rocketchip.system.DefaultConfig.plusArgs - freechips.rocketchip.system.DefaultConfig.rom.conf freechips.rocketchip.system.DefaultConfig.v - TestHarness.anno.json $ cat $ROCKETCHIP/vsim/generated-src/*.conf name data_arrays_0_ext depth 512 width 256 ports mrw mask_gran 8 name tag_array_ext depth 64 width 88 ports mrw mask_gran 22 @@ -416,26 +395,26 @@ tests and benchmarks. ## How can I parameterize my Rocket chip? By now, you probably figured out that all generated files have a configuration -name attached, e.g. `freechips.rocketchip.system.DefaultConfig`. Take a look at -`src/main/scala/system/Configs.scala`. Search for `NSets` and `NWays` defined in -`BaseConfig`. You can change those numbers to get a Rocket core with different +name attached, e.g. DefaultConfig. Take a look at +src/main/scala/system/Configs.scala. Search for NSets and NWays defined in +BaseConfig. You can change those numbers to get a Rocket core with different cache parameters. For example, by changing L1I, NWays to 4, you will get a 32KB 4-way set-associative L1 instruction cache rather than a 16KB 2-way set-associative L1 instruction cache. -Towards the end, you can also find that `DefaultSmallConfig` inherits all -parameters from `BaseConfig` but overrides the same parameters of -`WithNSmallCores`. +Towards the end, you can also find that DefaultSmallConfig inherits all +parameters from BaseConfig but overrides the same parameters of +WithNSmallCores. -Now take a look at `vsim/Makefile`. Search for the `CONFIG` variable. -By default, it is set to `freechips.rocketchip.system.DefaultConfig`. You can also change the +Now take a look at vsim/Makefile. Search for the CONFIG variable. +By default, it is set to DefaultConfig. You can also change the CONFIG variable on the make command line: $ cd $ROCKETCHIP/vsim - $ make -jN CONFIG=freechips.rocketchip.system.DefaultSmallConfig run-asm-tests + $ make -jN CONFIG=DefaultSmallConfig run-asm-tests Or, even by defining CONFIG as an environment variable: - $ export CONFIG=freechips.rocketchip.system.DefaultSmallConfig + $ export CONFIG=DefaultSmallConfig $ make -jN run-asm-tests This parameterization is one of the many strengths of processor @@ -452,7 +431,7 @@ you can create your own Configuration(s) and compose them with Config's ++ opera } class MyConfig extends Config (new WithNExtInterrupts(16) ++ new DefaultSmallConfig) -Then you can build as usual with `CONFIG=.MyConfig`. +Then you can build as usual with CONFIG=MyConfig. ## Debugging with GDB @@ -471,11 +450,11 @@ For that we need to add a Remote Bit-Bang client to the emulator. We can do so b To build the emulator with `DefaultConfigRBB` configuration we use the command: rocket-chip$ cd emulator - emulator$ CONFIG=freechips.rocketchip.system.DefaultConfigRBB make + emulator$ CONFIG=DefaultConfigRBB make We can also build a debug version capable of generating VCD waveforms using the command: - emulator$ CONFIG=freechips.rocketchip.system.DefaultConfigRBB make debug + emulator$ CONFIG=DefaultConfigRBB make debug By default the emulator is generated under the name `emulator-freechips.rocketchip.system-DefaultConfigRBB` in the first case and `emulator-freechips.rocketchip.system-DefaultConfigRBB-debug` in the second. diff --git a/build.sbt b/build.sbt index dc204983cad..dd06845b7dc 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,9 @@ // See LICENSE.Berkeley for license details. +import sbt.complete._ import sbt.complete.DefaultParsers._ -import scala.sys.process._ +import xerial.sbt.pack._ +import sys.process._ enablePlugins(PackPlugin) @@ -14,7 +16,6 @@ lazy val commonSettings = Seq( scalacOptions ++= Seq("-deprecation","-unchecked","-Xsource:2.11"), libraryDependencies ++= Seq("org.scala-lang" % "scala-reflect" % scalaVersion.value), libraryDependencies ++= Seq("org.json4s" %% "json4s-jackson" % "3.6.1"), - libraryDependencies ++= Seq("org.scalatest" %% "scalatest" % "3.0.8" % "test"), addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full), resolvers ++= Seq( Resolver.sonatypeRepo("snapshots"), diff --git a/emulator/Makefrag-verilator b/emulator/Makefrag-verilator index 8011a42aef6..d6423ada0ad 100644 --- a/emulator/Makefrag-verilator +++ b/emulator/Makefrag-verilator @@ -10,7 +10,7 @@ verilog = \ $(generated_dir)/%.fir $(generated_dir)/%.d: $(FIRRTL_JAR) $(chisel_srcs) $(bootrom_img) mkdir -p $(dir $@) - cd $(base_dir) && $(SBT) "runMain $(PROJECT).Generator -td $(generated_dir) -T $(PROJECT).$(MODEL) -C $(CONFIG)" + cd $(base_dir) && $(SBT) "runMain $(PROJECT).Generator $(generated_dir) $(PROJECT) $(MODEL) $(CFG_PROJECT) $(CONFIG)" %.v %.conf: %.fir $(FIRRTL_JAR) mkdir -p $(dir $@) @@ -69,7 +69,7 @@ VERILATOR_FLAGS := --top-module $(MODEL) \ --threads $(VERILATOR_THREADS) -Wno-UNOPTTHREADS \ -Wno-STMTDLY --x-assign unique \ -I$(vsrc) \ - -O3 -CFLAGS "$(CXXFLAGS) -DVERILATOR -DTEST_HARNESS=V$(MODEL) -include $(csrc)/verilator.h -include $(generated_dir)/$(long_name).plusArgs" + -O3 -CFLAGS "$(CXXFLAGS) -DVERILATOR -DTEST_HARNESS=V$(MODEL) -include $(csrc)/verilator.h -include $(generated_dir)/$(PROJECT).$(CONFIG).plusArgs" cppfiles = $(addprefix $(csrc)/, $(addsuffix .cc, $(CXXSRCS))) headers = $(wildcard $(csrc)/*.h) diff --git a/regression/Makefile b/regression/Makefile index 3b660c9ccd5..67983ad9e7f 100644 --- a/regression/Makefile +++ b/regression/Makefile @@ -46,22 +46,22 @@ endif ifeq ($(SUITE),RocketSuiteA) PROJECT=freechips.rocketchip.system -CONFIGS=$(PROJECT).DefaultConfig +CONFIGS=DefaultConfig endif ifeq ($(SUITE),RocketSuiteB) PROJECT=freechips.rocketchip.system -CONFIGS=$(PROJECT).DefaultBufferlessConfig +CONFIGS=DefaultBufferlessConfig endif ifeq ($(SUITE),RocketSuiteC) PROJECT=freechips.rocketchip.system -CONFIGS=$(PROJECT).TinyConfig +CONFIGS=TinyConfig endif ifeq ($(SUITE),UnittestSuite) PROJECT=freechips.rocketchip.unittest -CONFIGS=$(PROJECT).AMBAUnitTestConfig $(PROJECT).TLSimpleUnitTestConfig $(PROJECT).TLWidthUnitTestConfig +CONFIGS=AMBAUnitTestConfig TLSimpleUnitTestConfig TLWidthUnitTestConfig endif ifeq ($(SUITE), JtagDtmSuite) @@ -69,13 +69,13 @@ PROJECT=freechips.rocketchip.system export JTAG_DTM_ENABLE_SBA ?= off ifeq ($(JTAG_DTM_ENABLE_SBA), off) -CONFIGS_32=$(PROJECT).WithJtagDTMSystem,$(PROJECT).DefaultRV32Config -CONFIGS_64=$(PROJECT).WithJtagDTMSystem,$(PROJECT).DefaultConfig +CONFIGS_32=WithJtagDTMSystem_DefaultRV32Config +CONFIGS_64=WithJtagDTMSystem_DefaultConfig endif ifeq ($(JTAG_DTM_ENABLE_SBA), on) -CONFIGS_32=$(PROJECT).WithJtagDTMSystem,$(PROJECT).WithDebugSBASystem,$(PROJECT).DefaultRV32Config -CONFIGS_64=$(PROJECT).WithJtagDTMSystem,$(PROJECT).WithDebugSBASystem,$(PROJECT).DefaultConfig +CONFIGS_32=WithJtagDTMSystem_WithDebugSBASystem_DefaultRV32Config +CONFIGS_64=WithJtagDTMSystem_WithDebugSBASystem_DefaultConfig endif CONFIGS += $(CONFIGS_32) @@ -89,18 +89,18 @@ endif ifeq ($(SUITE), Miscellaneous) PROJECT=freechips.rocketchip.system CONFIGS=\ - $(PROJECT).DefaultSmallConfig \ - $(PROJECT).DualBankConfig \ - $(PROJECT).DualChannelConfig \ - $(PROJECT).DualChannelDualBankConfig \ - $(PROJECT).RoccExampleConfig \ - $(PROJECT).Edge128BitConfig \ - $(PROJECT).Edge32BitConfig \ - $(PROJECT).QuadChannelBenchmarkConfig \ - $(PROJECT).EightChannelConfig \ - $(PROJECT).DualCoreConfig \ - $(PROJECT).MemPortOnlyConfig \ - $(PROJECT).MMIOPortOnlyConfig + DefaultSmallConfig \ + DualBankConfig \ + DualChannelConfig \ + DualChannelDualBankConfig \ + RoccExampleConfig \ + Edge128BitConfig \ + Edge32BitConfig \ + QuadChannelBenchmarkConfig \ + EightChannelConfig \ + DualCoreConfig \ + MemPortOnlyConfig \ + MMIOPortOnlyConfig endif # These are the named regression targets. While it's expected you run them in diff --git a/src/main/scala/groundtest/Generator.scala b/src/main/scala/groundtest/Generator.scala index 6279c67b4e3..b3ffeb8616b 100644 --- a/src/main/scala/groundtest/Generator.scala +++ b/src/main/scala/groundtest/Generator.scala @@ -2,7 +2,11 @@ package freechips.rocketchip.groundtest -import firrtl.options.StageMain -import freechips.rocketchip.system.RocketChipStage +import freechips.rocketchip.util.GeneratorApp -object Generator extends StageMain(new RocketChipStage) +object Generator extends GeneratorApp { + generateFirrtl + generateAnno + generateTestSuiteMakefrags // TODO: Needed only for legacy make targets + generateArtefacts +} diff --git a/src/main/scala/stage/RocketChipAnnotations.scala b/src/main/scala/stage/RocketChipAnnotations.scala deleted file mode 100644 index f0c2c1302cf..00000000000 --- a/src/main/scala/stage/RocketChipAnnotations.scala +++ /dev/null @@ -1,52 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage - -import chisel3.experimental.BaseModule -import firrtl.annotations.{Annotation, NoTargetAnnotation} -import firrtl.options.{HasShellOptions, ShellOption, Unserializable} - -sealed trait RocketChipOption extends Unserializable { this: Annotation => } - -/* required options */ - -/** Path to top module class */ -case class TopModuleAnnotation(clazz: Class[_ <: Any]) extends NoTargetAnnotation with RocketChipOption -private[stage] object TopModuleAnnotation extends HasShellOptions { - override val options = Seq( - new ShellOption[String]( - longOption = "top-module", - toAnnotationSeq = a => Seq(TopModuleAnnotation(Class.forName(a).asInstanceOf[Class[_ <: BaseModule]])), - helpText = "", - shortOption = Some("T") - ) - ) -} - -/** Paths to config classes */ -case class ConfigsAnnotation(configNames: Seq[String]) extends NoTargetAnnotation with RocketChipOption -private[stage] object ConfigsAnnotation extends HasShellOptions { - override val options = Seq( - new ShellOption[Seq[String]]( - longOption = "configs", - toAnnotationSeq = a => Seq(ConfigsAnnotation(a)), - helpText = "", - shortOption = Some("C") - ) - ) -} - -/* optional options */ - -/** Optional base name for generated files' filenames */ -case class OutputBaseNameAnnotation(outputBaseName: String) extends NoTargetAnnotation with RocketChipOption -private[stage] object OutputBaseNameAnnotation extends HasShellOptions { - override val options = Seq( - new ShellOption[String]( - longOption = "name", - toAnnotationSeq = a => Seq(OutputBaseNameAnnotation(a)), - helpText = "", - shortOption = Some("n") - ) - ) -} diff --git a/src/main/scala/stage/RocketChipCli.scala b/src/main/scala/stage/RocketChipCli.scala deleted file mode 100644 index 30becb6ceeb..00000000000 --- a/src/main/scala/stage/RocketChipCli.scala +++ /dev/null @@ -1,17 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage - -import firrtl.options.Shell - -trait RocketChipCli { this: Shell => - - parser.note("Rocket Chip Compiler Options") - Seq( - TopModuleAnnotation, - ConfigsAnnotation, - OutputBaseNameAnnotation, - ) - .foreach(_.addOptions(parser)) - -} diff --git a/src/main/scala/stage/RocketChipOptions.scala b/src/main/scala/stage/RocketChipOptions.scala deleted file mode 100644 index 2fac6a276ff..00000000000 --- a/src/main/scala/stage/RocketChipOptions.scala +++ /dev/null @@ -1,41 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage - -class RocketChipOptions private[stage] ( - val topModule: Option[Class[_ <: Any]] = None, - val configNames: Option[Seq[String]] = None, - val outputBaseName: Option[String] = None) { - - private[stage] def copy( - topModule: Option[Class[_ <: Any]] = topModule, - configNames: Option[Seq[String]] = configNames, - outputBaseName: Option[String] = outputBaseName, - ): RocketChipOptions = { - - new RocketChipOptions( - topModule=topModule, - configNames=configNames, - outputBaseName=outputBaseName, - ) - } - - lazy val topPackage: Option[String] = topModule match { - case Some(a) => Some(a.getPackage.getName) - case _ => None - } - - lazy val configClass: Option[String] = configNames match { - case Some(names) => - val classNames = names.map{ n => n.split('.').last } - Some(classNames.mkString("_")) - case _ => None - } - - lazy val longName: Option[String] = outputBaseName match { - case Some(name) => Some(name) - case _ => - if (!topPackage.isEmpty && !configClass.isEmpty) Some(s"${topPackage.get}.${configClass.get}") else None - } -} - diff --git a/src/main/scala/stage/package.scala b/src/main/scala/stage/package.scala deleted file mode 100644 index db5b42234d1..00000000000 --- a/src/main/scala/stage/package.scala +++ /dev/null @@ -1,24 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip - -import firrtl.AnnotationSeq -import firrtl.options.OptionsView - -package object stage { - - implicit object RocketChipOptionsView extends OptionsView[RocketChipOptions] { - - def view(annotations: AnnotationSeq): RocketChipOptions = annotations - .collect { case a: RocketChipOption => a } - .foldLeft(new RocketChipOptions()){ (c, x) => - x match { - case TopModuleAnnotation(a) => c.copy(topModule = Some(a)) - case ConfigsAnnotation(a) => c.copy(configNames = Some(a)) - case OutputBaseNameAnnotation(a) => c.copy(outputBaseName = Some(a)) - } - } - - } - -} diff --git a/src/main/scala/stage/phases/AddDefaultTests.scala b/src/main/scala/stage/phases/AddDefaultTests.scala deleted file mode 100644 index 1fdd8b9a44a..00000000000 --- a/src/main/scala/stage/phases/AddDefaultTests.scala +++ /dev/null @@ -1,140 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage.phases - - -import chipsalliance.rocketchip.config.Parameters -import chisel3.stage.phases.Elaborate -import firrtl.AnnotationSeq -import firrtl.annotations.NoTargetAnnotation -import firrtl.options.{Phase, PreservesAll} -import firrtl.options.Viewer.view -import freechips.rocketchip.stage.RocketChipOptions -import freechips.rocketchip.subsystem.RocketTilesKey -import freechips.rocketchip.system.{DefaultTestSuites, RegressionTestSuite, RocketTestSuite, TestGeneration} -import freechips.rocketchip.tile.XLen -import freechips.rocketchip.util.HasRocketChipStageUtils -import freechips.rocketchip.system.DefaultTestSuites._ - -import scala.collection.mutable - -/** Annotation that contains a list of [[RocketTestSuite]]s to run */ -case class RocketTestSuiteAnnotation(tests: Seq[RocketTestSuite]) extends NoTargetAnnotation - -/** Generates [[RocketTestSuiteAnnotation]] depending on whether the top-module project is part of - * [[freechips.rocketchip.system]] or not (e.g. for unit tests). - */ -class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { - - override val prerequisites = Seq(classOf[Checks], classOf[Elaborate]) - override val dependents = Seq(classOf[GenerateTestSuiteMakefrags]) - - def GenerateDefaultTestSuites(): List[RocketTestSuite] = { - List(DefaultTestSuites.groundtest64("p"), DefaultTestSuites.emptyBmarks, DefaultTestSuites.singleRegression) - } - - def GenerateSystemTestSuites(annotations: AnnotationSeq): scala.collection.mutable.Buffer[RocketTestSuite] = { - val params: Parameters = getConfig(view[RocketChipOptions](annotations).configNames.get).toInstance - val xlen = params(XLen) - val tests = scala.collection.mutable.Buffer[RocketTestSuite]() - - val regressionTests = mutable.LinkedHashSet( - "rv64ud-v-fcvt", - "rv64ud-p-fdiv", - "rv64ud-v-fadd", - "rv64uf-v-fadd", - "rv64um-v-mul", - "rv64mi-p-breakpoint", - "rv64uc-v-rvc", - "rv64ud-v-structural", - "rv64si-p-wfi", - "rv64um-v-divw", - "rv64ua-v-lrsc", - "rv64ui-v-fence_i", - "rv64ud-v-fcvt_w", - "rv64uf-v-fmin", - "rv64ui-v-sb", - "rv64ua-v-amomax_d", - "rv64ud-v-move", - "rv64ud-v-fclass", - "rv64ua-v-amoand_d", - "rv64ua-v-amoxor_d", - "rv64si-p-sbreak", - "rv64ud-v-fmadd", - "rv64uf-v-ldst", - "rv64um-v-mulh", - "rv64si-p-dirty", - "rv32mi-p-ma_addr", - "rv32mi-p-csr", - "rv32ui-p-sh", - "rv32ui-p-lh", - "rv32uc-p-rvc", - "rv32mi-p-sbreak", - "rv32ui-p-sll") - - // TODO: for now only generate tests for the first core in the first subsystem - params(RocketTilesKey).headOption.map { tileParams => - val coreParams = tileParams.core - val vm = coreParams.useVM - val env = if (vm) List("p", "v") else List("p") - coreParams.fpu foreach { case cfg => - if (xlen == 32) { - tests ++= env.map(rv32uf) - if (cfg.fLen >= 64) - tests ++= env.map(rv32ud) - } else { - tests += rv32udBenchmarks - tests ++= env.map(rv64uf) - if (cfg.fLen >= 64) - tests ++= env.map(rv64ud) - } - } - if (coreParams.useAtomics) { - if (tileParams.dcache.flatMap(_.scratch).isEmpty) - tests ++= env.map(if (xlen == 64) rv64ua else rv32ua) - else - tests ++= env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC) - } - if (coreParams.useCompressed) tests ++= env.map(if (xlen == 64) rv64uc else rv32uc) - val (rvi, rvu) = - if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) - else ((if (vm) rv32i else rv32pi), rv32u) - - tests ++= rvi.map(_ ("p")) - tests ++= (if (vm) List("v") else List()).flatMap(env => rvu.map(_ (env))) - tests += benchmarks - - /* Filter the regression tests based on what the Rocket Chip configuration supports */ - val extensions = { - val fd = coreParams.fpu.map { - case cfg if cfg.fLen >= 64 => "fd" - case _ => "f" - } - val m = coreParams.mulDiv.map { case _ => "m" } - fd ++ m ++ Seq(if (coreParams.useRVE) Some("e") else Some("i"), - if (coreParams.useAtomics) Some("a") else None, - if (coreParams.useCompressed) Some("c") else None) - .flatten - .mkString("") - } - val re = s"""^rv$xlen[usm][$extensions].+""".r - regressionTests.retain { - case re() => true - case _ => false - } - tests += new RegressionTestSuite(regressionTests) - } - tests - } - - override def transform(annotations: AnnotationSeq): AnnotationSeq = { - val ropts = view[RocketChipOptions](annotations) - val tests = ropts.topPackage.get match { - case "freechips.rocketchip.system" => GenerateSystemTestSuites(annotations) - case _ => GenerateDefaultTestSuites() - } - - RocketTestSuiteAnnotation(tests) +: annotations - } - -} diff --git a/src/main/scala/stage/phases/Checks.scala b/src/main/scala/stage/phases/Checks.scala deleted file mode 100644 index fbfd8bb757a..00000000000 --- a/src/main/scala/stage/phases/Checks.scala +++ /dev/null @@ -1,47 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage.phases - -import firrtl.AnnotationSeq -import firrtl.annotations.Annotation -import firrtl.options.{OptionsException, Phase, PreservesAll, TargetDirAnnotation} -import freechips.rocketchip.stage._ - -import scala.collection.mutable - -/** Checks for the correct type and number of command line arguments */ -class Checks extends Phase with PreservesAll[Phase] { - - override def transform(annotations: AnnotationSeq): AnnotationSeq = { - val targetDir, topModule, configNames, outputBaseName = mutable.ListBuffer[Annotation]() - - annotations.foreach { - case a: TargetDirAnnotation => a +=: targetDir - case a: TopModuleAnnotation => a +=: topModule - case a: ConfigsAnnotation => a +=: configNames - case a: OutputBaseNameAnnotation => a +=: outputBaseName - case _ => - } - - def required(annoList: mutable.ListBuffer[Annotation], option: String): Unit = { - if (annoList.size != 1) { - throw new OptionsException(s"Exactly one $option required") - } - } - - def optional(annoList: mutable.ListBuffer[Annotation], option: String): Unit = { - if (annoList.size > 1) { - throw new OptionsException(s"Too many $option options have been specified") - } - } - - required(targetDir, "target directory") - required(topModule, "top module") - required(configNames, "configs string (','-delimited)") - - optional(outputBaseName, "output base name") - - annotations - } - -} diff --git a/src/main/scala/stage/phases/GenerateArtefacts.scala b/src/main/scala/stage/phases/GenerateArtefacts.scala deleted file mode 100644 index b678906d2d3..00000000000 --- a/src/main/scala/stage/phases/GenerateArtefacts.scala +++ /dev/null @@ -1,27 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage.phases - -import chisel3.stage.phases.Elaborate -import firrtl.AnnotationSeq -import firrtl.options.{Phase, PreservesAll, StageOptions} -import firrtl.options.Viewer.view -import freechips.rocketchip.stage.RocketChipOptions -import freechips.rocketchip.util.{ElaborationArtefacts, HasRocketChipStageUtils} - -/** Writes [[ElaborationArtefacts]] into files */ -class GenerateArtefacts extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { - - override val prerequisites = Seq(classOf[Checks], classOf[Elaborate]) - - override def transform(annotations: AnnotationSeq): AnnotationSeq = { - val targetDir = view[StageOptions](annotations).targetDir - - ElaborationArtefacts.files.foreach { case (extension, contents) => - writeOutputFile(targetDir, s"${view[RocketChipOptions](annotations).longName.get}.${extension}", contents ()) - } - - annotations - } - -} diff --git a/src/main/scala/stage/phases/GenerateFirrtlAnnos.scala b/src/main/scala/stage/phases/GenerateFirrtlAnnos.scala deleted file mode 100644 index c6641ef8048..00000000000 --- a/src/main/scala/stage/phases/GenerateFirrtlAnnos.scala +++ /dev/null @@ -1,42 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage.phases - -import chisel3.stage.phases.{Convert, Elaborate, MaybeAspectPhase} -import firrtl.AnnotationSeq -import firrtl.annotations.{Annotation, DeletedAnnotation, JsonProtocol} -import firrtl.options.Viewer.view -import firrtl.options.{Phase, PreservesAll, StageOptions, TargetDirAnnotation, Unserializable} -import freechips.rocketchip.stage.RocketChipOptions -import freechips.rocketchip.util.HasRocketChipStageUtils - -/** Writes FIRRTL annotations into a file */ -class GenerateFirrtlAnnos extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { - - override val prerequisites = Seq(classOf[Checks], classOf[Elaborate], classOf[Convert], classOf[MaybeAspectPhase]) - - override def transform(annotations: AnnotationSeq): AnnotationSeq = { - val targetDir = view[StageOptions](annotations).targetDir - val fileName = s"${view[RocketChipOptions](annotations).longName.get}.anno.json" - - val annos = scala.collection.mutable.Buffer[Annotation]() - annotations.flatMap { - case a: Unserializable => - Some(a) - case a: TargetDirAnnotation => - /** Don't serialize, in case of downstream FIRRTL call */ - Some(a) - case a @ DeletedAnnotation(_, _: Unserializable) => - /** [[DeletedAnnotation]]s of unserializable annotations cannot be serialized */ - Some(a) - case a => - annos += a - Some(a) - } - - writeOutputFile(targetDir, fileName, JsonProtocol.serialize(annos)) - - annotations - } - -} diff --git a/src/main/scala/stage/phases/GenerateROMs.scala b/src/main/scala/stage/phases/GenerateROMs.scala deleted file mode 100644 index 7203cb2caa1..00000000000 --- a/src/main/scala/stage/phases/GenerateROMs.scala +++ /dev/null @@ -1,31 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage.phases - -import chisel3.stage.ChiselCircuitAnnotation -import chisel3.stage.phases.{Convert, Elaborate} -import firrtl.AnnotationSeq -import firrtl.options.{Phase, PreservesAll, StageOptions} -import firrtl.options.Viewer.view -import freechips.rocketchip.stage.RocketChipOptions -import freechips.rocketchip.util.HasRocketChipStageUtils - -/** Dumps ROM information into a file */ -class GenerateROMs extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { - - override val prerequisites = Seq(classOf[Checks], classOf[Elaborate]) - override val dependents = Seq(classOf[Convert]) - - override def transform(annotations: AnnotationSeq): AnnotationSeq = { - val targetDir = view[StageOptions](annotations).targetDir - val fileName = s"${view[RocketChipOptions](annotations).longName.get}.rom.conf" - - annotations.flatMap { - case a: ChiselCircuitAnnotation => - writeOutputFile(targetDir, fileName, enumerateROMs(a.circuit)) - Some(a) - case a => Some(a) - } - } - -} diff --git a/src/main/scala/stage/phases/GenerateTestSuiteMakefrags.scala b/src/main/scala/stage/phases/GenerateTestSuiteMakefrags.scala deleted file mode 100644 index 94f7866770d..00000000000 --- a/src/main/scala/stage/phases/GenerateTestSuiteMakefrags.scala +++ /dev/null @@ -1,33 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage.phases - -import chisel3.stage.phases.Elaborate -import firrtl.AnnotationSeq -import firrtl.options.{Phase, PreservesAll, StageOptions} -import firrtl.options.Viewer.view -import freechips.rocketchip.stage.RocketChipOptions -import freechips.rocketchip.system.TestGeneration -import freechips.rocketchip.util.HasRocketChipStageUtils - -/** Generates a make script to run tests in [[RocketTestSuiteAnnotation]]. */ -class GenerateTestSuiteMakefrags extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { - - override val prerequisites = Seq(classOf[Checks], classOf[Elaborate]) - - override def transform(annotations: AnnotationSeq): AnnotationSeq = { - val targetDir = view[StageOptions](annotations).targetDir - val fileName = s"${view[RocketChipOptions](annotations).longName.get}.d" - - annotations.flatMap { - case a: RocketTestSuiteAnnotation => - val makefrag = a.tests.groupBy(_.kind) - .map { case (kind, s) => TestGeneration.gen(kind, s) } - .mkString("\n") - writeOutputFile(targetDir, fileName, makefrag) - Some(a) - case a => Some(a) - } - } - -} diff --git a/src/main/scala/stage/phases/PreElaboration.scala b/src/main/scala/stage/phases/PreElaboration.scala deleted file mode 100644 index 3a9435dca15..00000000000 --- a/src/main/scala/stage/phases/PreElaboration.scala +++ /dev/null @@ -1,39 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage.phases - -import chisel3.RawModule -import chisel3.stage.ChiselGeneratorAnnotation -import firrtl.AnnotationSeq -import firrtl.options.Viewer.view -import firrtl.options.{Phase, PreservesAll} -import freechips.rocketchip.config.Parameters -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.stage.RocketChipOptions -import freechips.rocketchip.util.HasRocketChipStageUtils - -/** Constructs a generator function that returns a top module with given config parameters */ -class PreElaboration extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { - - override val prerequisites = Seq(classOf[Checks]) - override val dependents = Seq(classOf[chisel3.stage.phases.Elaborate]) - - override def transform(annotations: AnnotationSeq): AnnotationSeq = { - - val rOpts = view[RocketChipOptions](annotations) - val topMod = rOpts.topModule.get - - val config = getConfig(rOpts.configNames.get) - - val gen = () => - topMod - .getConstructor(classOf[Parameters]) - .newInstance(config) match { - case a: RawModule => a - case a: LazyModule => LazyModule(a).module - } - - ChiselGeneratorAnnotation(gen) +: annotations - } - -} diff --git a/src/main/scala/stage/phases/TransformAnnotations.scala b/src/main/scala/stage/phases/TransformAnnotations.scala deleted file mode 100644 index a49bd55a10b..00000000000 --- a/src/main/scala/stage/phases/TransformAnnotations.scala +++ /dev/null @@ -1,23 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.stage.phases - -import chisel3.stage.ChiselOutputFileAnnotation -import chisel3.stage.phases.Emitter -import firrtl.AnnotationSeq -import firrtl.options.Viewer.view -import firrtl.options.{Phase, PreservesAll} -import freechips.rocketchip.stage.RocketChipOptions -import freechips.rocketchip.util.HasRocketChipStageUtils - -/** Transforms RocketChipAnnotations into those used by other stages */ -class TransformAnnotations extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { - - override val prerequisites = Seq(classOf[Checks]) - override val dependents = Seq(classOf[Emitter]) - - override def transform(annotations: AnnotationSeq): AnnotationSeq = { - /** Construct output file annotation for emission */ - new ChiselOutputFileAnnotation(view[RocketChipOptions](annotations).longName.get) +: annotations - } -} diff --git a/src/main/scala/system/Generator.scala b/src/main/scala/system/Generator.scala new file mode 100644 index 00000000000..f430d985f09 --- /dev/null +++ b/src/main/scala/system/Generator.scala @@ -0,0 +1,111 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.system + +import freechips.rocketchip.subsystem.RocketTilesKey +import freechips.rocketchip.tile.XLen +import freechips.rocketchip.util.GeneratorApp + +import scala.collection.mutable.LinkedHashSet + +/** A Generator for platforms containing Rocket Subsystemes */ +object Generator extends GeneratorApp { + + override def addTestSuites { + import DefaultTestSuites._ + val xlen = params(XLen) + + val regressionTests = LinkedHashSet( + "rv64ud-v-fcvt", + "rv64ud-p-fdiv", + "rv64ud-v-fadd", + "rv64uf-v-fadd", + "rv64um-v-mul", + "rv64mi-p-breakpoint", + "rv64uc-v-rvc", + "rv64ud-v-structural", + "rv64si-p-wfi", + "rv64um-v-divw", + "rv64ua-v-lrsc", + "rv64ui-v-fence_i", + "rv64ud-v-fcvt_w", + "rv64uf-v-fmin", + "rv64ui-v-sb", + "rv64ua-v-amomax_d", + "rv64ud-v-move", + "rv64ud-v-fclass", + "rv64ua-v-amoand_d", + "rv64ua-v-amoxor_d", + "rv64si-p-sbreak", + "rv64ud-v-fmadd", + "rv64uf-v-ldst", + "rv64um-v-mulh", + "rv64si-p-dirty", + "rv32mi-p-ma_addr", + "rv32mi-p-csr", + "rv32ui-p-sh", + "rv32ui-p-lh", + "rv32uc-p-rvc", + "rv32mi-p-sbreak", + "rv32ui-p-sll") + + // TODO: for now only generate tests for the first core in the first subsystem + params(RocketTilesKey).headOption.map { tileParams => + val coreParams = tileParams.core + val vm = coreParams.useVM + val env = if (vm) List("p","v") else List("p") + coreParams.fpu foreach { case cfg => + if (xlen == 32) { + TestGeneration.addSuites(env.map(rv32uf)) + if (cfg.fLen >= 64) + TestGeneration.addSuites(env.map(rv32ud)) + } else { + TestGeneration.addSuite(rv32udBenchmarks) + TestGeneration.addSuites(env.map(rv64uf)) + if (cfg.fLen >= 64) + TestGeneration.addSuites(env.map(rv64ud)) + } + } + if (coreParams.useAtomics) { + if (tileParams.dcache.flatMap(_.scratch).isEmpty) + TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) + else + TestGeneration.addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC)) + } + if (coreParams.useCompressed) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) + val (rvi, rvu) = + if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) + else ((if (vm) rv32i else rv32pi), rv32u) + + TestGeneration.addSuites(rvi.map(_("p"))) + TestGeneration.addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env)))) + TestGeneration.addSuite(benchmarks) + + /* Filter the regression tests based on what the Rocket Chip configuration supports */ + val extensions = { + val fd = coreParams.fpu.map { + case cfg if cfg.fLen >= 64 => "fd" + case _ => "f" + } + val m = coreParams.mulDiv.map{ case _ => "m" } + fd ++ m ++ Seq( if (coreParams.useRVE) Some("e") else Some("i"), + if (coreParams.useAtomics) Some("a") else None, + if (coreParams.useCompressed) Some("c") else None ) + .flatten + .mkString("") + } + val re = s"""^rv$xlen[usm][$extensions].+""".r + regressionTests.retain{ + case re() => true + case _ => false + } + TestGeneration.addSuite(new RegressionTestSuite(regressionTests)) + } + } + + generateFirrtl + generateAnno + generateTestSuiteMakefrags + generateROMs + generateArtefacts +} diff --git a/src/main/scala/system/RocketChipStageGenerator.scala b/src/main/scala/system/RocketChipStageGenerator.scala deleted file mode 100644 index ddfb60edc54..00000000000 --- a/src/main/scala/system/RocketChipStageGenerator.scala +++ /dev/null @@ -1,35 +0,0 @@ -// See LICENSE.SiFive for license details. - -package freechips.rocketchip.system - -import chisel3.stage.{ChiselCli, ChiselStage} -import firrtl.options.PhaseManager.PhaseDependency -import firrtl.options.{Phase, PreservesAll, Shell, StageMain} -import firrtl.stage.FirrtlCli -import freechips.rocketchip.stage.RocketChipCli - -class RocketChipStage extends ChiselStage with PreservesAll[Phase] { - - override val shell = new Shell("rocket-chip") with RocketChipCli with ChiselCli with FirrtlCli - override val targets: Seq[PhaseDependency] = Seq( - classOf[freechips.rocketchip.stage.phases.Checks], - classOf[freechips.rocketchip.stage.phases.TransformAnnotations], - classOf[freechips.rocketchip.stage.phases.PreElaboration], - classOf[chisel3.stage.phases.Checks], - classOf[chisel3.stage.phases.Elaborate], - classOf[freechips.rocketchip.stage.phases.GenerateROMs], - classOf[chisel3.stage.phases.AddImplicitOutputFile], - classOf[chisel3.stage.phases.AddImplicitOutputAnnotationFile], - classOf[chisel3.stage.phases.MaybeAspectPhase], - classOf[chisel3.stage.phases.Emitter], - classOf[chisel3.stage.phases.Convert], - classOf[freechips.rocketchip.stage.phases.GenerateFirrtlAnnos], - classOf[freechips.rocketchip.stage.phases.AddDefaultTests], - classOf[freechips.rocketchip.stage.phases.GenerateTestSuiteMakefrags], - classOf[freechips.rocketchip.stage.phases.GenerateArtefacts], - ) - - // TODO: need a RunPhaseAnnotation to inject phases into ChiselStage -} - -object Generator extends StageMain(new RocketChipStage) diff --git a/src/main/scala/system/RocketTestSuite.scala b/src/main/scala/system/RocketTestSuite.scala index 3129e83e11e..d4c809c9714 100644 --- a/src/main/scala/system/RocketTestSuite.scala +++ b/src/main/scala/system/RocketTestSuite.scala @@ -61,15 +61,16 @@ object TestGeneration { def addSuites(s: Seq[RocketTestSuite]) { s.foreach(addSuite) } - private[rocketchip] def gen(kind: String, s: Seq[RocketTestSuite]) = { - if(s.length > 0) { - val envs = s.groupBy(_.envName) - val targets = s.map(t => s"$$(${t.makeTargetName})").mkString(" ") - s.map(_.toString).mkString("\n") + - envs.filterKeys(_ != "").map( { - case (env,envsuites) => { - val suites = envsuites.map(t => s"$$(${t.makeTargetName})").mkString(" ") - s""" + def generateMakefrag: String = { + def gen(kind: String, s: Seq[RocketTestSuite]) = { + if(s.length > 0) { + val envs = s.groupBy(_.envName) + val targets = s.map(t => s"$$(${t.makeTargetName})").mkString(" ") + s.map(_.toString).mkString("\n") + + envs.filterKeys(_ != "").map( { + case (env,envsuites) => { + val suites = envsuites.map(t => s"$$(${t.makeTargetName})").mkString(" ") + s""" run-$kind-$env-tests: $$(addprefix $$(output_dir)/, $$(addsuffix .out, $suites)) \t@echo; perl -ne 'print " [$$$$1] $$$$ARGV \\t$$$$2\\n" if( /\\*{3}(.{8})\\*{3}(.*)/ || /ASSERTION (FAILED):(.*)/i )' $$^ /dev/null | perl -pe 'BEGIN { $$$$failed = 0 } $$$$failed = 1 if(/FAILED/i); END { exit($$$$failed) }' run-$kind-$env-tests-debug: $$(addprefix $$(output_dir)/, $$(addsuffix .vpd, $suites)) @@ -88,10 +89,9 @@ run-$kind-tests-fst: $$(addprefix $$(output_dir)/, $$(addsuffix .fst, $targets)) run-$kind-tests-fast: $$(addprefix $$(output_dir)/, $$(addsuffix .run, $targets)) \t@echo; perl -ne 'print " [$$$$1] $$$$ARGV \\t$$$$2\\n" if( /\\*{3}(.{8})\\*{3}(.*)/ || /ASSERTION (FAILED):(.*)/i )' $$^ /dev/null | perl -pe 'BEGIN { $$$$failed = 0 } $$$$failed = 1 if(/FAILED/i); END { exit($$$$failed) }' """ - } else { "\n" } - } + } else { "\n" } + } - def generateMakeFrag: String = { suites.values.toSeq.groupBy(_.kind).map { case (kind, s) => gen(kind, s) }.mkString("\n") } @@ -99,7 +99,7 @@ run-$kind-tests-fast: $$(addprefix $$(output_dir)/, $$(addsuffix .run, $targets) object DefaultTestSuites { val rv32uiNames = LinkedHashSet( - "simple", "add", "addi", "and", "andi", "auipc", "beq", "bge", "bgeu", "blt", "bltu", "bne", "fence_i", + "simple", "add", "addi", "and", "andi", "auipc", "beq", "bge", "bgeu", "blt", "bltu", "bne", "fence_i", "jal", "jalr", "lb", "lbu", "lh", "lhu", "lui", "lw", "or", "ori", "sb", "sh", "sw", "sll", "slli", "slt", "slti", "sra", "srai", "srl", "srli", "sub", "xor", "xori") val rv32ui = new AssemblyTestSuite("rv32ui", rv32uiNames)(_) diff --git a/src/main/scala/unittest/Generator.scala b/src/main/scala/unittest/Generator.scala index 01ef16886e5..1fd96632f4c 100644 --- a/src/main/scala/unittest/Generator.scala +++ b/src/main/scala/unittest/Generator.scala @@ -2,7 +2,9 @@ package freechips.rocketchip.unittest -import firrtl.options.StageMain -import freechips.rocketchip.system.RocketChipStage - -object Generator extends StageMain(new RocketChipStage) +object Generator extends freechips.rocketchip.util.GeneratorApp { + generateFirrtl + generateAnno + generateTestSuiteMakefrags // TODO: Needed only for legacy make targets + generateArtefacts +} diff --git a/src/main/scala/util/GeneratorUtils.scala b/src/main/scala/util/GeneratorUtils.scala index 8d00dd85066..4578906ffb1 100644 --- a/src/main/scala/util/GeneratorUtils.scala +++ b/src/main/scala/util/GeneratorUtils.scala @@ -2,14 +2,36 @@ package freechips.rocketchip.util +import Chisel._ +import chisel3.RawModule +import chisel3.internal.firrtl.Circuit +// TODO: better job of Makefrag generation for non-RocketChip testing platforms import java.io.{File, FileWriter} -import Chisel.throwException -import chipsalliance.rocketchip.config.{Config, Parameters} -import chisel3.internal.firrtl.Circuit +import firrtl.annotations.JsonProtocol +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.system.{DefaultTestSuites, TestGeneration} -trait HasRocketChipStageUtils { +/** Representation of the information this Generator needs to collect from external sources. */ +case class ParsedInputNames( + targetDir: String, + topModuleProject: String, + topModuleClass: String, + configProject: String, + configs: String, + outputBaseName: Option[String]) { + val configClasses: Seq[String] = configs.split('_') + def prepend(prefix: String, suffix: String) = + if (prefix == "" || prefix == "_root_") suffix else (prefix + "." + suffix) + val fullConfigClasses: Seq[String] = configClasses.map(x => prepend(configProject, x)) + val fullTopModuleClass: String = prepend(topModuleProject, topModuleClass) +} +/** Common utilities we supply to all Generators. In particular, supplies the + * canonical ways of building various JVM elaboration-time structures. + */ +trait HasGeneratorUtilities { def getConfig(fullConfigClassNames: Seq[String]): Config = { new Config(fullConfigClassNames.foldRight(Parameters.empty) { case (currentName, config) => val currentConfig = try { @@ -22,6 +44,22 @@ trait HasRocketChipStageUtils { }) } + def getParameters(names: Seq[String]): Parameters = getParameters(getConfig(names)) + + def getParameters(config: Config): Parameters = config.toInstance + + def elaborate(fullTopModuleClassName: String, params: Parameters): Circuit = { + val top = () => + Class.forName(fullTopModuleClassName) + .getConstructor(classOf[Parameters]) + .newInstance(params) match { + case m: RawModule => m + case l: LazyModule => LazyModule(l).module + } + + Driver.elaborate(top) + } + def enumerateROMs(circuit: Circuit): String = { val res = new StringBuilder val configs = @@ -36,6 +74,73 @@ trait HasRocketChipStageUtils { } res.toString } +} + +/** Standardized command line interface for Scala entry point */ +trait GeneratorApp extends App with HasGeneratorUtilities { + lazy val names: ParsedInputNames = { + require(args.size == 5 || args.size == 6, "Usage: sbt> " + + "run TargetDir TopModuleProjectName TopModuleName " + + "ConfigProjectName ConfigNameString [OutputFilesBaseName]") + val base = + ParsedInputNames( + targetDir = args(0), + topModuleProject = args(1), + topModuleClass = args(2), + configProject = args(3), + configs = args(4), + outputBaseName = None) + + if (args.size == 6) { + base.copy(outputBaseName = Some(args(5))) + } else { + base + } + } + + // Canonical ways of building various JVM elaboration-time structures + lazy val td: String = names.targetDir + lazy val config: Config = getConfig(names.fullConfigClasses) + lazy val params: Parameters = config.toInstance + lazy val circuit: Circuit = elaborate(names.fullTopModuleClass, params) + + // Exhaustive name used to interface with external build tool targets + lazy val longName: String = names.outputBaseName.getOrElse(names.configProject + "." + names.configs) + + /** Output FIRRTL, which an external compiler can turn into Verilog. */ + def generateFirrtl { + Driver.dumpFirrtl(circuit, Some(new File(td, s"$longName.fir"))) // FIRRTL + } + + def generateAnno { + val annotationFile = new File(td, s"$longName.anno.json") + val af = new FileWriter(annotationFile) + af.write(JsonProtocol.serialize(circuit.annotations.map(_.toFirrtl))) + af.close() + } + + /** Output software test Makefrags, which provide targets for integration testing. */ + def generateTestSuiteMakefrags { + addTestSuites + writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Subsystem-specific test suites + } + + def addTestSuites { + TestGeneration.addSuite(DefaultTestSuites.groundtest64("p")) + TestGeneration.addSuite(DefaultTestSuites.emptyBmarks) + TestGeneration.addSuite(DefaultTestSuites.singleRegression) + } + + def generateROMs { + writeOutputFile(td, s"$longName.rom.conf", enumerateROMs(circuit)) + } + + /** Output files created as a side-effect of elaboration */ + def generateArtefacts { + ElaborationArtefacts.files.foreach { case (extension, contents) => + writeOutputFile(td, s"$longName.$extension", contents ()) + } + } def writeOutputFile(targetDir: String, fname: String, contents: String): File = { val f = new File(targetDir, fname) @@ -44,7 +149,6 @@ trait HasRocketChipStageUtils { fw.close f } - } object ElaborationArtefacts { diff --git a/src/test/scala/generatorTests/StageGeneratorSpec.scala b/src/test/scala/generatorTests/StageGeneratorSpec.scala deleted file mode 100644 index e5487a19185..00000000000 --- a/src/test/scala/generatorTests/StageGeneratorSpec.scala +++ /dev/null @@ -1,44 +0,0 @@ -// See LICENSE.SiFive for license details. - -package generatorTests - -import java.io.File - -import chisel3.aop.injecting.InjectingAspect -import chisel3._ -import firrtl.options.TargetDirAnnotation -import freechips.rocketchip.stage.{ConfigsAnnotation, TopModuleAnnotation} -import freechips.rocketchip.system.{RocketChipStage, TestHarness} -import org.scalatest.FlatSpec - -/** run via SBT with - * > testOnly generatorTests.StageGeneratorSpec - * - * Output can be viewed in the testbuild directory. The wire named "hello" should show up in the generated - * *.anno.json file. - */ -class StageGeneratorSpec extends FlatSpec { - - val dummyAspect = InjectingAspect( - {dut: TestHarness => Seq(dut.dut)}, - {dut: freechips.rocketchip.system.ExampleRocketSystemModuleImp[freechips.rocketchip.system.ExampleRocketSystem] => - val dummyWire = Wire(UInt(3.W)).suggestName("hello") - dummyWire := 5.U - dontTouch(dummyWire) - } - ) - - "Test" should "pass" in { - val dirName = System.getProperty("user.dir") + "/testbuild" - val dir = new File(dirName) - if (!dir.exists()) dir.mkdirs() - - new RocketChipStage().run(Seq( - new TargetDirAnnotation(dirName), - new TopModuleAnnotation(Class.forName("freechips.rocketchip.system.TestHarness")), - new ConfigsAnnotation(Seq("freechips.rocketchip.system.DefaultConfig")), - dummyAspect - )) - } - -} \ No newline at end of file diff --git a/vsim/Makefrag b/vsim/Makefrag index 278384769af..f28f192a210 100644 --- a/vsim/Makefrag +++ b/vsim/Makefrag @@ -64,14 +64,14 @@ VCS_OPTS = -notice -line +lint=all,noVCDE,noONGS,noUI -error=PCWM-L -timescale=1 # Build the simulator #-------------------------------------------------------------------- -simv = $(sim_dir)/simv-$(PROJECT)-$(CONFIG_STR) +simv = $(sim_dir)/simv-$(PROJECT)-$(CONFIG) $(simv) : $(sim_vsrcs) $(sim_csrcs) cd $(sim_dir) && \ rm -rf csrc && \ $(VCS) $(VCS_OPTS) -o $(simv) \ -debug_pp \ -simv_debug = $(sim_dir)/simv-$(PROJECT)-$(CONFIG_STR)-debug +simv_debug = $(sim_dir)/simv-$(PROJECT)-$(CONFIG)-debug $(simv_debug) : $(sim_vsrcs) $(sim_csrcs) cd $(sim_dir) && \ rm -rf csrc && \ diff --git a/vsim/Makefrag-verilog b/vsim/Makefrag-verilog index 13e35373d37..9b0afa159a2 100644 --- a/vsim/Makefrag-verilog +++ b/vsim/Makefrag-verilog @@ -10,7 +10,7 @@ verilog = $(generated_dir)/$(long_name).v $(generated_dir)/%.fir $(generated_dir)/%.d: $(FIRRTL_JAR) $(chisel_srcs) $(bootrom_img) mkdir -p $(dir $@) - cd $(base_dir) && $(SBT) "runMain $(PROJECT).Generator -td $(generated_dir) -T $(PROJECT).$(MODEL) -C $(CONFIG)" + cd $(base_dir) && $(SBT) "runMain $(PROJECT).Generator $(generated_dir) $(PROJECT) $(MODEL) $(CFG_PROJECT) $(CONFIG)" $(generated_dir)/%.v $(generated_dir)/%.conf: $(generated_dir)/%.fir $(FIRRTL_JAR) mkdir -p $(dir $@)