Add chisel6 stage
This commit is contained in:
66
tools/stage/src/main/scala/ChipyardAnnotations.scala
Normal file
66
tools/stage/src/main/scala/ChipyardAnnotations.scala
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
// Based on Rocket Chip's stage implementation
|
||||||
|
|
||||||
|
package chipyard.stage
|
||||||
|
|
||||||
|
import chisel3.experimental.BaseModule
|
||||||
|
import firrtl.annotations.{Annotation, NoTargetAnnotation}
|
||||||
|
import firrtl.options.{HasShellOptions, ShellOption, Unserializable}
|
||||||
|
|
||||||
|
trait ChipyardOption extends Unserializable { this: Annotation => }
|
||||||
|
|
||||||
|
/** This hijacks the existing ConfigAnnotation to accept the legacy _-delimited format */
|
||||||
|
private[stage] object UnderscoreDelimitedConfigsAnnotation extends HasShellOptions {
|
||||||
|
override val options = Seq(
|
||||||
|
new ShellOption[String](
|
||||||
|
longOption = "legacy-configs",
|
||||||
|
toAnnotationSeq = a => {
|
||||||
|
val split = a.split(':')
|
||||||
|
assert(split.length == 2, s"'${a}' split by ':' doesn't yield two things")
|
||||||
|
val packageName = split.head
|
||||||
|
val configs = split.last.split("_")
|
||||||
|
Seq(new ConfigsAnnotation(configs map { config => if (config contains ".") s"${config}" else s"${packageName}.${config}" } ))
|
||||||
|
},
|
||||||
|
helpText = "A string of underscore-delimited configs (configs have decreasing precendence from left to right).",
|
||||||
|
shortOption = Some("LC")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Paths to config classes */
|
||||||
|
case class ConfigsAnnotation(configNames: Seq[String]) extends NoTargetAnnotation with ChipyardOption
|
||||||
|
private[stage] object ConfigsAnnotation extends HasShellOptions {
|
||||||
|
override val options = Seq(
|
||||||
|
new ShellOption[Seq[String]](
|
||||||
|
longOption = "configs",
|
||||||
|
toAnnotationSeq = a => Seq(ConfigsAnnotation(a)),
|
||||||
|
helpText = "<comma-delimited configs>",
|
||||||
|
shortOption = Some("C")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
case class TopModuleAnnotation(clazz: Class[_ <: Any]) extends NoTargetAnnotation with ChipyardOption
|
||||||
|
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 = "<top module>",
|
||||||
|
shortOption = Some("T")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Optional base name for generated files' filenames */
|
||||||
|
case class OutputBaseNameAnnotation(outputBaseName: String) extends NoTargetAnnotation with ChipyardOption
|
||||||
|
private[stage] object OutputBaseNameAnnotation extends HasShellOptions {
|
||||||
|
override val options = Seq(
|
||||||
|
new ShellOption[String](
|
||||||
|
longOption = "name",
|
||||||
|
toAnnotationSeq = a => Seq(OutputBaseNameAnnotation(a)),
|
||||||
|
helpText = "<base name of output files>",
|
||||||
|
shortOption = Some("n")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
17
tools/stage/src/main/scala/ChipyardCli.scala
Normal file
17
tools/stage/src/main/scala/ChipyardCli.scala
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
// Based on Rocket Chip's stage implementation
|
||||||
|
|
||||||
|
package chipyard.stage
|
||||||
|
|
||||||
|
import firrtl.options.Shell
|
||||||
|
|
||||||
|
trait ChipyardCli { this: Shell =>
|
||||||
|
|
||||||
|
parser.note("Chipyard Generator Options")
|
||||||
|
Seq(
|
||||||
|
TopModuleAnnotation,
|
||||||
|
ConfigsAnnotation,
|
||||||
|
OutputBaseNameAnnotation,
|
||||||
|
UnderscoreDelimitedConfigsAnnotation
|
||||||
|
).foreach(_.addOptions(parser))
|
||||||
|
}
|
||||||
40
tools/stage/src/main/scala/ChipyardOptions.scala
Normal file
40
tools/stage/src/main/scala/ChipyardOptions.scala
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// See LICENSE
|
||||||
|
|
||||||
|
package chipyard.stage
|
||||||
|
|
||||||
|
class ChipyardOptions 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,
|
||||||
|
): ChipyardOptions = {
|
||||||
|
|
||||||
|
new ChipyardOptions(
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
71
tools/stage/src/main/scala/ChipyardStage.scala
Normal file
71
tools/stage/src/main/scala/ChipyardStage.scala
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
// Based on Rocket Chip's stage implementation
|
||||||
|
|
||||||
|
package chipyard.stage
|
||||||
|
|
||||||
|
import circt.stage.{ChiselStage}
|
||||||
|
import firrtl.options.PhaseManager.PhaseDependency
|
||||||
|
import firrtl.options.{Shell}
|
||||||
|
import firrtl.{AnnotationSeq}
|
||||||
|
import firrtl.options.{Phase, PhaseManager, Shell, Stage, StageError, StageMain, Dependency}
|
||||||
|
|
||||||
|
final class ChipyardChiselStage extends ChiselStage {
|
||||||
|
override def run(annotations: AnnotationSeq): AnnotationSeq = {
|
||||||
|
|
||||||
|
val pm = new PhaseManager(
|
||||||
|
targets = Seq(
|
||||||
|
Dependency[chisel3.stage.phases.Checks],
|
||||||
|
Dependency[chisel3.stage.phases.AddImplicitOutputFile],
|
||||||
|
Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile],
|
||||||
|
Dependency[chisel3.stage.phases.MaybeAspectPhase],
|
||||||
|
Dependency[chisel3.stage.phases.AddSerializationAnnotations],
|
||||||
|
Dependency[chisel3.stage.phases.Convert],
|
||||||
|
Dependency[chisel3.stage.phases.AddDedupGroupAnnotations],
|
||||||
|
Dependency[chisel3.stage.phases.MaybeInjectingPhase],
|
||||||
|
Dependency[circt.stage.phases.AddImplicitOutputFile],
|
||||||
|
Dependency[circt.stage.phases.Checks],
|
||||||
|
Dependency[circt.stage.phases.CIRCT]
|
||||||
|
),
|
||||||
|
currentState = Seq(
|
||||||
|
Dependency[firrtl.stage.phases.AddDefaults],
|
||||||
|
Dependency[firrtl.stage.phases.Checks]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
pm.transform(annotations)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChipyardStage extends ChiselStage {
|
||||||
|
override val shell = new Shell("chipyard") with ChipyardCli with circt.stage.CLI
|
||||||
|
override def run(annotations: AnnotationSeq): AnnotationSeq = {
|
||||||
|
|
||||||
|
val pm = new PhaseManager(
|
||||||
|
targets = Seq(
|
||||||
|
Dependency[chipyard.stage.phases.Checks],
|
||||||
|
Dependency[chipyard.stage.phases.TransformAnnotations],
|
||||||
|
Dependency[chipyard.stage.phases.PreElaboration],
|
||||||
|
Dependency[ChipyardChiselStage],
|
||||||
|
Dependency[chipyard.stage.phases.GenerateFirrtlAnnos],
|
||||||
|
Dependency[chipyard.stage.phases.AddDefaultTests],
|
||||||
|
Dependency[chipyard.stage.phases.GenerateTestSuiteMakefrags],
|
||||||
|
Dependency[chipyard.stage.phases.GenerateArtefacts],
|
||||||
|
),
|
||||||
|
currentState = Seq(
|
||||||
|
Dependency[firrtl.stage.phases.AddDefaults],
|
||||||
|
Dependency[firrtl.stage.phases.Checks]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
pm.transform(annotations)
|
||||||
|
}
|
||||||
|
// override val targets: Seq[PhaseDependency] = Seq(
|
||||||
|
// Dependency[chipyard.stage.phases.Checks],
|
||||||
|
// Dependency[chipyard.stage.phases.TransformAnnotations],
|
||||||
|
// Dependency[chipyard.stage.phases.PreElaboration],
|
||||||
|
// Dependency[ChipyardChiselStage],
|
||||||
|
// Dependency[chipyard.stage.phases.GenerateFirrtlAnnos],
|
||||||
|
// Dependency[chipyard.stage.phases.AddDefaultTests],
|
||||||
|
// Dependency[chipyard.stage.phases.GenerateTestSuiteMakefrags],
|
||||||
|
// Dependency[chipyard.stage.phases.GenerateArtefacts],
|
||||||
|
// )
|
||||||
|
override final def invalidates(a: Phase): Boolean = false
|
||||||
|
}
|
||||||
32
tools/stage/src/main/scala/StageUtils.scala
Normal file
32
tools/stage/src/main/scala/StageUtils.scala
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// See LICENSE
|
||||||
|
|
||||||
|
package chipyard.stage
|
||||||
|
|
||||||
|
import java.io.{File, FileWriter}
|
||||||
|
|
||||||
|
import org.chipsalliance.cde.config.{Config, Parameters}
|
||||||
|
import freechips.rocketchip.util.{BlackBoxedROM, ROMGenerator}
|
||||||
|
|
||||||
|
trait HasChipyardStageUtils {
|
||||||
|
|
||||||
|
def getConfig(fullConfigClassNames: Seq[String]): Config = {
|
||||||
|
new Config(fullConfigClassNames.foldRight(Parameters.empty) { case (currentName, config) =>
|
||||||
|
val currentConfig = try {
|
||||||
|
Class.forName(currentName).newInstance.asInstanceOf[Config]
|
||||||
|
} catch {
|
||||||
|
case e: java.lang.ClassNotFoundException =>
|
||||||
|
throw new Exception(s"""Unable to find part "$currentName" from "$fullConfigClassNames", did you misspell it or specify the wrong package path?""", e)
|
||||||
|
}
|
||||||
|
currentConfig ++ config
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
24
tools/stage/src/main/scala/package.scala
Normal file
24
tools/stage/src/main/scala/package.scala
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// See LICENSE
|
||||||
|
|
||||||
|
package chipyard
|
||||||
|
|
||||||
|
import firrtl.AnnotationSeq
|
||||||
|
import firrtl.options.OptionsView
|
||||||
|
|
||||||
|
package object stage {
|
||||||
|
|
||||||
|
implicit object ChipyardOptionsView extends OptionsView[ChipyardOptions] {
|
||||||
|
|
||||||
|
def view(annotations: AnnotationSeq): ChipyardOptions = annotations
|
||||||
|
.collect { case a: ChipyardOption => a }
|
||||||
|
.foldLeft(new ChipyardOptions()){ (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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
53
tools/stage/src/main/scala/phases/AddDefaultTests.scala
Normal file
53
tools/stage/src/main/scala/phases/AddDefaultTests.scala
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
// Based on Rocket Chip's stage implementation
|
||||||
|
|
||||||
|
package chipyard.stage.phases
|
||||||
|
|
||||||
|
import scala.util.Try
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
import org.chipsalliance.cde.config.Parameters
|
||||||
|
import chisel3.stage.phases.Elaborate
|
||||||
|
import firrtl.AnnotationSeq
|
||||||
|
import firrtl.annotations.{Annotation, NoTargetAnnotation}
|
||||||
|
import firrtl.options._
|
||||||
|
import firrtl.options.Viewer._
|
||||||
|
import freechips.rocketchip.system.{RocketTestSuite, TestGeneration}
|
||||||
|
import freechips.rocketchip.subsystem.{TilesLocated, InSubsystem}
|
||||||
|
import freechips.rocketchip.tile.XLen
|
||||||
|
|
||||||
|
import chipyard.TestSuiteHelper
|
||||||
|
import chipyard.TestSuitesKey
|
||||||
|
import chipyard.stage._
|
||||||
|
|
||||||
|
/** Annotation that contains a list of [[RocketTestSuite]]s to run */
|
||||||
|
case class ChipyardTestSuiteAnnotation(tests: Seq[RocketTestSuite]) extends NoTargetAnnotation with Unserializable
|
||||||
|
|
||||||
|
|
||||||
|
class AddDefaultTests extends Phase with PreservesAll with HasChipyardStageUtils {
|
||||||
|
override val prerequisites = Seq(Dependency[ChipyardChiselStage])
|
||||||
|
override val optionalPrerequisiteOf = Seq(Dependency[GenerateTestSuiteMakefrags])
|
||||||
|
|
||||||
|
private def addTestSuiteAnnotations(implicit p: Parameters): Seq[Annotation] = {
|
||||||
|
val annotations = mutable.ArrayBuffer[Annotation]()
|
||||||
|
val suiteHelper = new TestSuiteHelper
|
||||||
|
// Use Xlen as a proxy for detecting if we are a processor-like target
|
||||||
|
// The underlying test suites expect this field to be defined
|
||||||
|
val tileParams = p(TilesLocated(InSubsystem)) map (tp => tp.tileParams)
|
||||||
|
if (p.lift(XLen).nonEmpty)
|
||||||
|
// If a custom test suite is set up, use the custom test suite
|
||||||
|
annotations += CustomMakefragSnippet(p(TestSuitesKey).apply(tileParams, suiteHelper, p))
|
||||||
|
|
||||||
|
ChipyardTestSuiteAnnotation(suiteHelper.suites.values.toSeq) +: annotations.toSeq
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||||
|
val (testSuiteAnnos, oAnnos) = annotations.partition {
|
||||||
|
case ChipyardTestSuiteAnnotation(_) => true
|
||||||
|
case o => false
|
||||||
|
}
|
||||||
|
implicit val p = getConfig(view[ChipyardOptions](annotations).configNames.get).toInstance
|
||||||
|
addTestSuiteAnnotations(p) ++ oAnnos
|
||||||
|
}
|
||||||
|
}
|
||||||
47
tools/stage/src/main/scala/phases/Checks.scala
Normal file
47
tools/stage/src/main/scala/phases/Checks.scala
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// See LICENSE
|
||||||
|
|
||||||
|
package chipyard.stage.phases
|
||||||
|
|
||||||
|
import firrtl.AnnotationSeq
|
||||||
|
import firrtl.annotations.Annotation
|
||||||
|
import firrtl.options.{OptionsException, Phase, TargetDirAnnotation}
|
||||||
|
import chipyard.stage._
|
||||||
|
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
/** Checks for the correct type and number of command line arguments */
|
||||||
|
class Checks extends Phase with PreservesAll {
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
26
tools/stage/src/main/scala/phases/GenerateArtefacts.scala
Normal file
26
tools/stage/src/main/scala/phases/GenerateArtefacts.scala
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// See LICENSE
|
||||||
|
|
||||||
|
package chipyard.stage.phases
|
||||||
|
|
||||||
|
import firrtl.AnnotationSeq
|
||||||
|
import firrtl.options.{Dependency, Phase, StageOptions}
|
||||||
|
import firrtl.options.Viewer.view
|
||||||
|
import chipyard.stage._
|
||||||
|
import freechips.rocketchip.util.{ElaborationArtefacts}
|
||||||
|
|
||||||
|
/** Writes [[ElaborationArtefacts]] into files */
|
||||||
|
class GenerateArtefacts extends Phase with PreservesAll with HasChipyardStageUtils {
|
||||||
|
|
||||||
|
override val prerequisites = Seq(Dependency[chipyard.stage.ChipyardChiselStage])
|
||||||
|
|
||||||
|
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||||
|
val targetDir = view[StageOptions](annotations).targetDir
|
||||||
|
|
||||||
|
ElaborationArtefacts.files.foreach { case (extension, contents) =>
|
||||||
|
writeOutputFile(targetDir, s"${view[ChipyardOptions](annotations).longName.get}.${extension}", contents ())
|
||||||
|
}
|
||||||
|
|
||||||
|
annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
34
tools/stage/src/main/scala/phases/GenerateFirrtlAnnos.scala
Normal file
34
tools/stage/src/main/scala/phases/GenerateFirrtlAnnos.scala
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// See LICENSE
|
||||||
|
|
||||||
|
package chipyard.stage.phases
|
||||||
|
|
||||||
|
import firrtl.AnnotationSeq
|
||||||
|
import firrtl.annotations.{JsonProtocol}
|
||||||
|
import firrtl.options.Viewer.view
|
||||||
|
import firrtl.options._
|
||||||
|
import chipyard.stage._
|
||||||
|
|
||||||
|
/** Writes FIRRTL annotations into a file */
|
||||||
|
class GenerateFirrtlAnnos extends Phase with PreservesAll with HasChipyardStageUtils {
|
||||||
|
|
||||||
|
override val prerequisites = Seq(Dependency[chipyard.stage.ChipyardChiselStage])
|
||||||
|
|
||||||
|
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||||
|
val targetDir = view[StageOptions](annotations).targetDir
|
||||||
|
val fileName = s"${view[ChipyardOptions](annotations).longName.get}.anno.json"
|
||||||
|
|
||||||
|
val annos = annotations.view.flatMap {
|
||||||
|
// Remove TargetDirAnnotation so that we can pass as argument to FIRRTL
|
||||||
|
// Remove CustomFileEmission, those are serialized automatically by Stages
|
||||||
|
case (_: Unserializable | _: TargetDirAnnotation | _: CustomFileEmission) =>
|
||||||
|
None
|
||||||
|
case a =>
|
||||||
|
Some(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
writeOutputFile(targetDir, fileName, JsonProtocol.serialize(annos.toSeq))
|
||||||
|
|
||||||
|
annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
// Based on Rocket Chip's stage implementation
|
||||||
|
|
||||||
|
package chipyard.stage.phases
|
||||||
|
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
import firrtl.AnnotationSeq
|
||||||
|
import firrtl.annotations.{Annotation, NoTargetAnnotation}
|
||||||
|
import firrtl.options.{Phase, StageOptions, Unserializable, Dependency}
|
||||||
|
import firrtl.options.Viewer.view
|
||||||
|
import chipyard.stage._
|
||||||
|
import freechips.rocketchip.system.TestGeneration
|
||||||
|
|
||||||
|
trait MakefragSnippet { self: Annotation =>
|
||||||
|
def toMakefrag: String
|
||||||
|
}
|
||||||
|
|
||||||
|
case class CustomMakefragSnippet(val toMakefrag: String) extends NoTargetAnnotation with MakefragSnippet with Unserializable
|
||||||
|
|
||||||
|
/** Generates a make script to run tests in [[RocketTestSuiteAnnotation]]. */
|
||||||
|
class GenerateTestSuiteMakefrags extends Phase with HasChipyardStageUtils {
|
||||||
|
|
||||||
|
// Our annotations tend not to be serializable, but are not marked as such.
|
||||||
|
override val prerequisites = Seq(Dependency[chipyard.stage.phases.GenerateFirrtlAnnos],
|
||||||
|
Dependency[chipyard.stage.phases.AddDefaultTests])
|
||||||
|
|
||||||
|
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||||
|
val targetDir = view[StageOptions](annotations).targetDir
|
||||||
|
val fileName = s"${view[ChipyardOptions](annotations).longName.get}.d"
|
||||||
|
|
||||||
|
val makefragBuilder = new mutable.StringBuilder()
|
||||||
|
val outputAnnotations = annotations.flatMap {
|
||||||
|
case ChipyardTestSuiteAnnotation(tests) =>
|
||||||
|
// Unfortunately the gen method of TestGeneration is rocketchip package
|
||||||
|
// private, so we either have to copy code in or use the stateful form
|
||||||
|
TestGeneration.addSuites(tests)
|
||||||
|
None
|
||||||
|
case a: MakefragSnippet =>
|
||||||
|
makefragBuilder :+ ("\n" + a.toMakefrag)
|
||||||
|
None
|
||||||
|
case a => Some(a)
|
||||||
|
}
|
||||||
|
writeOutputFile(targetDir, fileName, TestGeneration.generateMakeFrag ++ makefragBuilder.toString)
|
||||||
|
outputAnnotations
|
||||||
|
}
|
||||||
|
|
||||||
|
override final def invalidates(a: Phase): Boolean = false
|
||||||
|
}
|
||||||
43
tools/stage/src/main/scala/phases/PreElaboration.scala
Normal file
43
tools/stage/src/main/scala/phases/PreElaboration.scala
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// See LICENSE
|
||||||
|
|
||||||
|
package chipyard.stage.phases
|
||||||
|
|
||||||
|
import chisel3.RawModule
|
||||||
|
import chisel3.stage.ChiselGeneratorAnnotation
|
||||||
|
import firrtl.AnnotationSeq
|
||||||
|
import firrtl.options.Viewer.view
|
||||||
|
import firrtl.options.{Dependency, Phase, StageOptions}
|
||||||
|
import org.chipsalliance.cde.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import chipyard.stage._
|
||||||
|
|
||||||
|
case object TargetDirKey extends Field[String](".")
|
||||||
|
|
||||||
|
/** Constructs a generator function that returns a top module with given config parameters */
|
||||||
|
class PreElaboration extends Phase with PreservesAll with HasChipyardStageUtils {
|
||||||
|
|
||||||
|
override val prerequisites = Seq(Dependency[Checks])
|
||||||
|
override val optionalPrerequisiteOf = Seq(Dependency[chisel3.stage.phases.Elaborate])
|
||||||
|
|
||||||
|
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||||
|
|
||||||
|
val stageOpts = view[StageOptions](annotations)
|
||||||
|
val rOpts = view[ChipyardOptions](annotations)
|
||||||
|
val topMod = rOpts.topModule.get
|
||||||
|
|
||||||
|
val config = getConfig(rOpts.configNames.get).alterPartial {
|
||||||
|
case TargetDirKey => stageOpts.targetDir
|
||||||
|
}
|
||||||
|
|
||||||
|
val gen = () =>
|
||||||
|
topMod
|
||||||
|
.getConstructor(classOf[Parameters])
|
||||||
|
.newInstance(config) match {
|
||||||
|
case a: RawModule => a
|
||||||
|
case a: LazyModule => LazyModule(a).module
|
||||||
|
}
|
||||||
|
|
||||||
|
ChiselGeneratorAnnotation(gen) +: annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
8
tools/stage/src/main/scala/phases/PreservesAll.scala
Normal file
8
tools/stage/src/main/scala/phases/PreservesAll.scala
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package chipyard.stage.phases
|
||||||
|
|
||||||
|
import firrtl.AnnotationSeq
|
||||||
|
import firrtl.options.{Dependency, DependencyManagerException, Phase, PhaseManager}
|
||||||
|
|
||||||
|
trait PreservesAll { this: Phase =>
|
||||||
|
override def invalidates(phase: Phase) = false
|
||||||
|
}
|
||||||
21
tools/stage/src/main/scala/phases/TransformAnnotations.scala
Normal file
21
tools/stage/src/main/scala/phases/TransformAnnotations.scala
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// See LICENSE
|
||||||
|
|
||||||
|
package chipyard.stage.phases
|
||||||
|
|
||||||
|
import chisel3.stage.ChiselOutputFileAnnotation
|
||||||
|
import firrtl.AnnotationSeq
|
||||||
|
import firrtl.options.Viewer.view
|
||||||
|
import firrtl.options.{Dependency, Phase}
|
||||||
|
import chipyard.stage._
|
||||||
|
|
||||||
|
/** Transforms RocketChipAnnotations into those used by other stages */
|
||||||
|
class TransformAnnotations extends Phase with PreservesAll with HasChipyardStageUtils {
|
||||||
|
|
||||||
|
override val prerequisites = Seq(Dependency[Checks])
|
||||||
|
override val optionalPrerequisiteOf = Seq(Dependency[chisel3.stage.phases.AddImplicitOutputFile])
|
||||||
|
|
||||||
|
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||||
|
/** Construct output file annotation for emission */
|
||||||
|
new ChiselOutputFileAnnotation(view[ChipyardOptions](annotations).longName.get) +: annotations
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user