diff --git a/src/main/scala/rocketchip/Generator.scala b/src/main/scala/rocketchip/Generator.scala index 669da10a..04c47db7 100644 --- a/src/main/scala/rocketchip/Generator.scala +++ b/src/main/scala/rocketchip/Generator.scala @@ -8,17 +8,21 @@ import cde._ import coreplex._ import java.io.{File, FileWriter} +/** Representation of the information this Generator needs to collect from external sources. */ case class ParsedInputNames( targetDir: String, - topProject: String, + topModuleProject: String, topModuleClass: String, configProject: String, configs: String) { val configClasses: Seq[String] = configs.split('_') val fullConfigClasses: Seq[String] = configClasses.map(configProject + "." + _) - val fullTopModuleClass: String = topProject + "." + topModuleClass + val fullTopModuleClass: String = 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(names: ParsedInputNames): Config = { names.fullConfigClasses.foldRight(new Config()) { case (currentName, config) => @@ -56,40 +60,68 @@ trait HasGeneratorUtilities { } } -object ConfigStringOutput { - var contents: Option[String] = None -} +/** Standardized command line interface for Scala entry point */ trait Generator extends App with HasGeneratorUtilities { - lazy val names = { + lazy val names: ParsedInputNames = { require(args.size == 5, "Usage: sbt> " + "run TargetDir TopModuleProjectName TopModuleName ConfigProjectName ConfigNameString") ParsedInputNames( targetDir = args(0), - topProject = args(1), + topModuleProject = args(1), topModuleClass = args(2), configProject = args(3), configs = args(4)) } + // Canonical ways of building various JVM elaboration-time structures lazy val td = names.targetDir lazy val config = getConfig(names) lazy val world = config.toInstance lazy val params = Parameters.root(world) lazy val circuit = elaborate(names, params) - lazy val longName = names.topProject + "." + names.configs - def writeOutputFiles() { + val longName: String // Exhaustive name used to interface with external build tool targets + + /** Output FIRRTL, which an external compiler can turn into Verilog. */ + def generateFirrtl { + Driver.dumpFirrtl(circuit, Some(new File(td, s"$longName.fir"))) // FIRRTL + } + + /** Output software test Makefrags, which provide targets for integration testing. */ + def generateTestSuiteMakefrags { TestGeneration.addSuite(new RegressionTestSuite(params(RegressionTestNames))) writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Coreplex-specific test suites - writeOutputFile(td, s"$longName.prm", ParameterDump.getDump) // Parameters flagged with Dump() + } + + /** Output Design Space Exploration knobs and constraints. */ + def generateDSEConstraints { writeOutputFile(td, s"${names.configs}.knb", world.getKnobs) // Knobs for DSE writeOutputFile(td, s"${names.configs}.cst", world.getConstraints) // Constraints for DSE + } + + /** Output a global Parameter dump, which an external script can turn into Verilog headers. */ + def generateParameterDump { + writeOutputFile(td, s"$longName.prm", ParameterDump.getDump) // Parameters flagged with Dump() + } + + /** Output a global ConfigString, for use by the RISC-V software ecosystem. */ + def generateConfigString { ConfigStringOutput.contents.foreach(c => writeOutputFile(td, s"${names.configs}.cfg", c)) // String for software } } -object RocketChipGenerator extends Generator { - Driver.dumpFirrtl(circuit, Some(new File(td, s"$longName.fir"))) // FIRRTL - writeOutputFiles() +object ConfigStringOutput { + var contents: Option[String] = None +} + +/** An example Generator */ +object RocketChipGenerator extends Generator +{ + val longName = names.topModuleProject + "." + names.configs + generateFirrtl + generateTestSuiteMakefrags + generateDSEConstraints + generateConfigString + generateParameterDump }