From 47c5d1a99299494a1ec7a5a1dd61e2615bd26d23 Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Thu, 22 Sep 2016 14:31:45 -0700 Subject: [PATCH] [WIP] Move RocketTestSuite generation into RocketchipGenerator --- src/main/scala/coreplex/Configs.scala | 58 ------ src/main/scala/groundtest/Configs.scala | 3 - src/main/scala/rocketchip/BaseTop.scala | 2 +- src/main/scala/rocketchip/Generator.scala | 180 +++++++----------- .../RocketTestSuite.scala | 9 +- src/main/scala/unittest/Configs.scala | 35 ++-- src/main/scala/util/GeneratorUtils.scala | 125 ++++++++++++ 7 files changed, 214 insertions(+), 198 deletions(-) rename src/main/scala/{coreplex => rocketchip}/RocketTestSuite.scala (97%) create mode 100644 src/main/scala/util/GeneratorUtils.scala diff --git a/src/main/scala/coreplex/Configs.scala b/src/main/scala/coreplex/Configs.scala index f763d5b6..b2756fbc 100644 --- a/src/main/scala/coreplex/Configs.scala +++ b/src/main/scala/coreplex/Configs.scala @@ -13,8 +13,6 @@ import rocket._ import rocket.Util._ import util.ConfigUtils._ import rocketchip.{GlobalAddrMap, NCoreplexExtClients} -import scala.collection.mutable.{LinkedHashSet, ListBuffer} -import DefaultTestSuites._ import cde.{Parameters, Config, Dump, Knob, CDEMatchError} class BaseCoreplexConfig extends Config ( @@ -71,28 +69,6 @@ class BaseCoreplexConfig extends Config ( case NUncachedTileLinkPorts => 1 //Tile Constants case BuildTiles => { - val env = if(site(UseVM)) List("p","v") else List("p") - site(FPUKey) foreach { case cfg => - if (site(XLen) == 32) { - TestGeneration.addSuites(env.map(rv32ufNoDiv)) - } else { - TestGeneration.addSuite(rv32udBenchmarks) - TestGeneration.addSuites(env.map(rv64ufNoDiv)) - TestGeneration.addSuites(env.map(rv64udNoDiv)) - if (cfg.divSqrt) { - TestGeneration.addSuites(env.map(rv64uf)) - TestGeneration.addSuites(env.map(rv64ud)) - } - } - } - if (site(UseAtomics)) TestGeneration.addSuites(env.map(if (site(XLen) == 64) rv64ua else rv32ua)) - if (site(UseCompressed)) TestGeneration.addSuites(env.map(if (site(XLen) == 64) rv64uc else rv32uc)) - val (rvi, rvu) = - if (site(XLen) == 64) ((if (site(UseVM)) rv64i else rv64pi), rv64u) - else ((if (site(UseVM)) rv32i else rv32pi), rv32u) - TestGeneration.addSuites(rvi.map(_("p"))) - TestGeneration.addSuites((if(site(UseVM)) List("v") else List()).flatMap(env => rvu.map(_(env)))) - TestGeneration.addSuite(benchmarks) List.tabulate(site(NTiles)){ i => (r: Bool, p: Parameters) => Module(new RocketTile(resetSignal = r)(p.alterPartial({ case TileId => i @@ -187,32 +163,6 @@ class BaseCoreplexConfig extends Config ( case CacheBlockBytes => Dump("CACHE_BLOCK_BYTES", 64) case CacheBlockOffsetBits => log2Up(here(CacheBlockBytes)) case EnableL2Logging => false - case RegressionTestNames => 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") case _ => throw new CDEMatchError }}, knobValues = { @@ -327,14 +277,6 @@ class WithRV32 extends Config( (pname,site,here) => pname match { case XLen => 32 case FPUKey => Some(FPUConfig(divSqrt = false)) - case RegressionTestNames => LinkedHashSet( - "rv32mi-p-ma_addr", - "rv32mi-p-csr", - "rv32ui-p-sh", - "rv32ui-p-lh", - "rv32uc-p-rvc", - "rv32mi-p-sbreak", - "rv32ui-p-sll") case _ => throw new CDEMatchError } ) diff --git a/src/main/scala/groundtest/Configs.scala b/src/main/scala/groundtest/Configs.scala index 2a450de7..d05a63d8 100644 --- a/src/main/scala/groundtest/Configs.scala +++ b/src/main/scala/groundtest/Configs.scala @@ -7,8 +7,6 @@ import uncore.coherence._ import uncore.agents._ import uncore.devices.NTiles import junctions._ -import scala.collection.mutable.LinkedHashSet -import scala.collection.immutable.HashMap import cde.{Parameters, Config, Dump, Knob, CDEMatchError} import scala.math.max import coreplex._ @@ -125,7 +123,6 @@ class WithGroundTest extends Config( case FPUKey => None case UseAtomics => false case UseCompressed => false - case RegressionTestNames => LinkedHashSet("rv64ui-p-simple") case _ => throw new CDEMatchError }) diff --git a/src/main/scala/rocketchip/BaseTop.scala b/src/main/scala/rocketchip/BaseTop.scala index 0e18916b..de28f432 100644 --- a/src/main/scala/rocketchip/BaseTop.scala +++ b/src/main/scala/rocketchip/BaseTop.scala @@ -8,7 +8,7 @@ import junctions._ import uncore.tilelink._ import uncore.tilelink2._ import uncore.devices._ -import util.ParameterizedBundle +import util.{ParameterizedBundle, ConfigStringOutput} import rocket._ import rocket.Util._ import coreplex._ diff --git a/src/main/scala/rocketchip/Generator.scala b/src/main/scala/rocketchip/Generator.scala index 04c47db7..f2063ecf 100644 --- a/src/main/scala/rocketchip/Generator.scala +++ b/src/main/scala/rocketchip/Generator.scala @@ -3,121 +3,79 @@ package rocketchip import Chisel._ -import scala.collection.mutable.{LinkedHashSet,LinkedHashMap} -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, - topModuleProject: String, - topModuleClass: String, - configProject: String, - configs: String) { - val configClasses: Seq[String] = configs.split('_') - val fullConfigClasses: Seq[String] = configClasses.map(configProject + "." + _) - 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) => - val currentConfig = try { - Class.forName(currentName).newInstance.asInstanceOf[Config] - } catch { - case e: java.lang.ClassNotFoundException => - throwException(s"""Unable to find part "$currentName" from "${names.configs}", did you misspell it?""", e) - } - currentConfig ++ config - } - } - - def getParameters(names: ParsedInputNames): Parameters = getParameters(getConfig(names)) - - def getParameters(config: Config): Parameters = Parameters.root(config.toInstance) - - import chisel3.internal.firrtl.Circuit - def elaborate(names: ParsedInputNames, params: Parameters): Circuit = { - val gen = () => - Class.forName(names.fullTopModuleClass) - .getConstructor(classOf[cde.Parameters]) - .newInstance(params) - .asInstanceOf[Module] - - Driver.elaborate(gen) - } - - def writeOutputFile(targetDir: String, fname: String, contents: String): File = { - val f = new File(targetDir, fname) - val fw = new FileWriter(f) - fw.write(contents) - fw.close - f - } -} - - -/** Standardized command line interface for Scala entry point */ -trait Generator extends App with HasGeneratorUtilities { - lazy val names: ParsedInputNames = { - require(args.size == 5, "Usage: sbt> " + - "run TargetDir TopModuleProjectName TopModuleName ConfigProjectName ConfigNameString") - ParsedInputNames( - targetDir = args(0), - 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) - - 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 - } - - /** 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 ConfigStringOutput { - var contents: Option[String] = None -} +import rocket.{XLen, UseVM, UseAtomics, UseCompressed, FPUKey} +import util.Generator +import scala.collection.mutable.LinkedHashSet /** An example Generator */ object RocketChipGenerator extends Generator { + val rv64RegrTestNames = 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") + + val rv32RegrTestNames = LinkedHashSet( + "rv32mi-p-ma_addr", + "rv32mi-p-csr", + "rv32ui-p-sh", + "rv32ui-p-lh", + "rv32uc-p-rvc", + "rv32mi-p-sbreak", + "rv32ui-p-sll") + + override def addTestSuites { + import DefaultTestSuites._ + val xlen = params(XLen) + val vm = params(UseVM) + val env = if (vm) List("p","v") else List("p") + params(FPUKey) foreach { case cfg => + if (xlen == 32) { + TestGeneration.addSuites(env.map(rv32ufNoDiv)) + } else { + TestGeneration.addSuite(rv32udBenchmarks) + TestGeneration.addSuites(env.map(rv64ufNoDiv)) + TestGeneration.addSuites(env.map(rv64udNoDiv)) + if (cfg.divSqrt) { + TestGeneration.addSuites(env.map(rv64uf)) + TestGeneration.addSuites(env.map(rv64ud)) + } + } + } + if (params(UseAtomics)) TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) + if (params(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) + TestGeneration.addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames)) + } + val longName = names.topModuleProject + "." + names.configs generateFirrtl generateTestSuiteMakefrags diff --git a/src/main/scala/coreplex/RocketTestSuite.scala b/src/main/scala/rocketchip/RocketTestSuite.scala similarity index 97% rename from src/main/scala/coreplex/RocketTestSuite.scala rename to src/main/scala/rocketchip/RocketTestSuite.scala index 98a5a2b6..27a4522c 100644 --- a/src/main/scala/coreplex/RocketTestSuite.scala +++ b/src/main/scala/rocketchip/RocketTestSuite.scala @@ -1,12 +1,9 @@ // See LICENSE for license details. -package coreplex +package rocketchip import Chisel._ -import scala.collection.mutable.{LinkedHashSet,LinkedHashMap} -import cde.{Parameters, ParameterDump, Config, Field, CDEMatchError} - -case object RegressionTestNames extends Field[LinkedHashSet[String]] +import scala.collection.mutable.{LinkedHashSet, LinkedHashMap} abstract class RocketTestSuite { val dir: String @@ -175,6 +172,8 @@ object DefaultTestSuites { val emptyBmarks = new BenchmarkTestSuite("empty", "$(RISCV)/riscv64-unknown-elf/share/riscv-tests/benchmarks", LinkedHashSet.empty) + val singleRegression = new RegressionTestSuite(LinkedHashSet("rv64iu-p-simple")) + val mtBmarks = new BenchmarkTestSuite("mt", "$(RISCV)/riscv64-unknown-elf/share/riscv-tests/mt", LinkedHashSet(((0 to 4).map("vvadd"+_) ++ List("ad","ae","af","ag","ai","ak","al","am","an","ap","aq","ar","at","av","ay","az", diff --git a/src/main/scala/unittest/Configs.scala b/src/main/scala/unittest/Configs.scala index 9273b440..682713e6 100644 --- a/src/main/scala/unittest/Configs.scala +++ b/src/main/scala/unittest/Configs.scala @@ -4,37 +4,32 @@ package unittest import Chisel._ import cde.{Parameters, Config, CDEMatchError} -import coreplex.{TestGeneration, DefaultTestSuites} -import rocketchip.BaseConfig +import rocketchip.{BaseConfig, BasePlatformConfig} class WithJunctionsUnitTests extends Config( (pname, site, here) => pname match { - case UnitTests => (p: Parameters) => { - TestGeneration.addSuite(DefaultTestSuites.groundtest64("p")) // TODO why - TestGeneration.addSuite(DefaultTestSuites.emptyBmarks) - Seq( - Module(new junctions.MultiWidthFifoTest), - Module(new junctions.NastiMemoryDemuxTest()(p)), - Module(new junctions.HastiTest()(p))) - } + case junctions.PAddrBits => 32 + case rocket.XLen => 64 + case UnitTests => (p: Parameters) => Seq( + Module(new junctions.MultiWidthFifoTest), + Module(new junctions.NastiMemoryDemuxTest()(p)), + Module(new junctions.HastiTest()(p))) case _ => throw new CDEMatchError }) +class JunctionsUnitTestConfig extends Config(new WithJunctionsUnitTests ++ new BasePlatformConfig) + class WithUncoreUnitTests extends Config( (pname, site, here) => pname match { case rocketchip.NCoreplexExtClients => 0 case uncore.tilelink.TLId => "L1toL2" - case UnitTests => (p: Parameters) => { - TestGeneration.addSuite(DefaultTestSuites.groundtest64("p")) // TODO why - TestGeneration.addSuite(DefaultTestSuites.emptyBmarks) - Seq( - Module(new uncore.devices.ROMSlaveTest()(p)), - Module(new uncore.devices.TileLinkRAMTest()(p)), - Module(new uncore.tilelink2.TLFuzzRAMTest) - ) - } + case UnitTests => (p: Parameters) => Seq( + Module(new uncore.devices.ROMSlaveTest()(p)), + Module(new uncore.devices.TileLinkRAMTest()(p)), + Module(new uncore.tilelink2.TLFuzzRAMTest)) case _ => throw new CDEMatchError } ) -class UnitTestConfig extends Config(new WithUncoreUnitTests ++ new WithJunctionsUnitTests ++ new BaseConfig) +class UncoreUnitTestConfig extends Config(new WithUncoreUnitTests ++ new BaseConfig) + diff --git a/src/main/scala/util/GeneratorUtils.scala b/src/main/scala/util/GeneratorUtils.scala new file mode 100644 index 00000000..3b91b578 --- /dev/null +++ b/src/main/scala/util/GeneratorUtils.scala @@ -0,0 +1,125 @@ +// See LICENSE for license details. + +package util + +import Chisel._ +import cde._ +import java.io.{File, FileWriter} + +/** 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) { + val configClasses: Seq[String] = configs.split('_') + val fullConfigClasses: Seq[String] = configClasses.map(configProject + "." + _) + 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) => + val currentConfig = try { + Class.forName(currentName).newInstance.asInstanceOf[Config] + } catch { + case e: java.lang.ClassNotFoundException => + throwException(s"""Unable to find part "$currentName" from "${names.configs}", did you misspell it?""", e) + } + currentConfig ++ config + } + } + + def getParameters(names: ParsedInputNames): Parameters = getParameters(getConfig(names)) + + def getParameters(config: Config): Parameters = Parameters.root(config.toInstance) + + import chisel3.internal.firrtl.Circuit + def elaborate(names: ParsedInputNames, params: Parameters): Circuit = { + val gen = () => + Class.forName(names.fullTopModuleClass) + .getConstructor(classOf[cde.Parameters]) + .newInstance(params) + .asInstanceOf[Module] + + Driver.elaborate(gen) + } + + def writeOutputFile(targetDir: String, fname: String, contents: String): File = { + val f = new File(targetDir, fname) + val fw = new FileWriter(f) + fw.write(contents) + fw.close + f + } +} + + +/** Standardized command line interface for Scala entry point */ +trait Generator extends App with HasGeneratorUtilities { + lazy val names: ParsedInputNames = { + require(args.size == 5, "Usage: sbt> " + + "run TargetDir TopModuleProjectName TopModuleName " + + "ConfigProjectName ConfigNameString") + ParsedInputNames( + targetDir = args(0), + 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) + + 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 { + addTestSuites + writeOutputFile(td, s"$longName.d", rocketchip.TestGeneration.generateMakefrag) // Coreplex-specific test suites + } + + def addTestSuites { + // TODO: better job of Makefrag generation + // for non-RocketChip testing platforms + import rocketchip.{DefaultTestSuites, TestGeneration} + TestGeneration.addSuite(DefaultTestSuites.groundtest64("p")) + TestGeneration.addSuite(DefaultTestSuites.emptyBmarks) + TestGeneration.addSuite(DefaultTestSuites.singleRegression) + } + + /** 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)) + } +} + +object ConfigStringOutput { + var contents: Option[String] = None +} +