Bump Chipyard
This commit is contained in:
parent
16e962f591
commit
a021b16f7a
|
@ -16,7 +16,7 @@ export SBT_OPTS ?= -Dsbt.ivy.home=$(base_dir)/.ivy2 -Dsbt.global.base=$(base_dir
|
|||
sbt_sources = $(shell find -L $(base_dir) -name target -prune -o -iname "*.sbt" -print 2> /dev/null)
|
||||
SCALA_BUILDTOOL_DEPS ?= $(sbt_sources)
|
||||
|
||||
SBT ?= java -jar $(rocketchip_dir)/sbt-launch.jar $(SBT_OPTS)
|
||||
SBT ?= java -jar $(chipyard_dir)/scripts/sbt-launch.jar $(SBT_OPTS)
|
||||
|
||||
# (1) - classpath of the fat jar
|
||||
# (2) - main class
|
||||
|
|
|
@ -6,5 +6,5 @@ simif_dir = $(firesim_base_dir)/midas/src/main/cc
|
|||
midas_h = $(shell find $(simif_dir) -name "*.h")
|
||||
midas_cc = $(shell find $(simif_dir) -name "*.cc")
|
||||
|
||||
common_cxx_flags := $(TARGET_CXX_FLAGS) -Wno-unused-variable
|
||||
common_cxx_flags := $(TARGET_CXX_FLAGS) -Wno-unused-variable -DFIRESIM
|
||||
common_ld_flags := $(TARGET_LD_FLAGS) -lrt
|
||||
|
|
|
@ -32,7 +32,7 @@ subst_prefix=,midas.unittest.
|
|||
|
||||
$(GEN_DIR)/$(DESIGN).fir $(GEN_DIR)/$(DESIGN).behav_srams.v: $(scala_srcs)
|
||||
mkdir -p $(@D)
|
||||
cd $(BASE_DIR) && $(SBT) "project $(SBT_PROJECT); runMain freechips.rocketchip.system.Generator \
|
||||
cd $(BASE_DIR) && $(SBT) "project $(SBT_PROJECT); runMain midas.chiselstage.Generator \
|
||||
--target-dir $(GEN_DIR) \
|
||||
--name $(DESIGN) \
|
||||
--top-module freechips.rocketchip.unittest.TestHarness \
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package midas.chiselstage
|
||||
|
||||
import firrtl.options.StageMain
|
||||
|
||||
object Generator extends StageMain(new midas.chiselstage.stage.MidasStage)
|
|
@ -0,0 +1,68 @@
|
|||
// See LICENSE for license details.
|
||||
// Based on Rocket Chip's stage implementation
|
||||
|
||||
package midas.chiselstage.stage
|
||||
|
||||
import chisel3.experimental.BaseModule
|
||||
import firrtl.annotations.{Annotation, NoTargetAnnotation}
|
||||
import firrtl.options.{HasShellOptions, ShellOption, Unserializable}
|
||||
|
||||
trait MidasOption 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 MidasOption
|
||||
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 MidasOption
|
||||
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 MidasOption
|
||||
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"),
|
||||
)
|
||||
)
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// See LICENSE for license details.
|
||||
// Based on Rocket Chip's stage implementation
|
||||
|
||||
package midas.chiselstage.stage
|
||||
|
||||
import firrtl.options.Shell
|
||||
|
||||
trait MidasCli { this: Shell =>
|
||||
|
||||
parser.note("Midas Generator Options")
|
||||
Seq(
|
||||
TopModuleAnnotation,
|
||||
ConfigsAnnotation,
|
||||
OutputBaseNameAnnotation,
|
||||
UnderscoreDelimitedConfigsAnnotation,
|
||||
).foreach(_.addOptions(parser))
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// See LICENSE
|
||||
|
||||
package midas.chiselstage.stage
|
||||
|
||||
class MidasOptions 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,
|
||||
): MidasOptions = {
|
||||
|
||||
new MidasOptions(
|
||||
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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// See LICENSE for license details.
|
||||
// Based on Rocket Chip's stage implementation
|
||||
|
||||
package midas.chiselstage.stage
|
||||
|
||||
import chisel3.stage.{ChiselCli, ChiselStage}
|
||||
import firrtl.options.PhaseManager.PhaseDependency
|
||||
import firrtl.stage.FirrtlCli
|
||||
import firrtl.options.{Dependency, Phase, Shell}
|
||||
|
||||
final class MidasChiselStage extends ChiselStage {
|
||||
override val targets = Seq(
|
||||
Dependency[chisel3.stage.phases.Checks],
|
||||
Dependency[chisel3.stage.phases.Elaborate],
|
||||
Dependency[chisel3.stage.phases.AddImplicitOutputFile],
|
||||
Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile],
|
||||
Dependency[chisel3.stage.phases.MaybeAspectPhase],
|
||||
Dependency[chisel3.stage.phases.Emitter],
|
||||
Dependency[chisel3.stage.phases.Convert],
|
||||
)
|
||||
}
|
||||
|
||||
class MidasStage extends ChiselStage {
|
||||
override val shell = new Shell("midas") with MidasCli with ChiselCli with FirrtlCli
|
||||
override val targets: Seq[PhaseDependency] = Seq(
|
||||
Dependency[midas.chiselstage.stage.phases.Checks],
|
||||
Dependency[midas.chiselstage.stage.phases.TransformAnnotations],
|
||||
Dependency[midas.chiselstage.stage.phases.PreElaboration],
|
||||
Dependency[MidasChiselStage],
|
||||
Dependency[midas.chiselstage.stage.phases.GenerateFirrtlAnnos],
|
||||
Dependency[midas.chiselstage.stage.phases.GenerateArtefacts],
|
||||
)
|
||||
override final def invalidates(a: Phase): Boolean = false
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// See LICENSE
|
||||
|
||||
package midas.chiselstage.stage
|
||||
|
||||
import java.io.{File, FileWriter}
|
||||
|
||||
import org.chipsalliance.cde.config.{Config, Parameters}
|
||||
import chisel3.internal.firrtl.Circuit
|
||||
import freechips.rocketchip.util.{BlackBoxedROM, ROMGenerator}
|
||||
|
||||
trait HasMidasStageUtils {
|
||||
|
||||
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 enumerateROMs(circuit: Circuit): String = {
|
||||
val res = new StringBuilder
|
||||
val configs =
|
||||
circuit.components.flatMap { m =>
|
||||
m.id match {
|
||||
case rom: BlackBoxedROM => Some((rom.name, ROMGenerator.lookup(rom)))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
configs.foreach { case (name, c) =>
|
||||
res.append(s"name ${name} depth ${c.depth} width ${c.width}\n")
|
||||
}
|
||||
res.toString
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// See LICENSE
|
||||
|
||||
package midas.chiselstage
|
||||
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.options.OptionsView
|
||||
|
||||
package object stage {
|
||||
|
||||
implicit object MidasOptionsView extends OptionsView[MidasOptions] {
|
||||
|
||||
def view(annotations: AnnotationSeq): MidasOptions = annotations
|
||||
.collect { case a: MidasOption => a }
|
||||
.foldLeft(new MidasOptions()) { (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))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// See LICENSE
|
||||
|
||||
package midas.chiselstage.stage.phases
|
||||
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.annotations.Annotation
|
||||
import firrtl.options.{OptionsException, Phase, PreservesAll, TargetDirAnnotation}
|
||||
import midas.chiselstage.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
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// See LICENSE
|
||||
|
||||
package midas.chiselstage.stage.phases
|
||||
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.options.{Dependency, Phase, PreservesAll, StageOptions}
|
||||
import firrtl.options.Viewer.view
|
||||
import midas.chiselstage.stage._
|
||||
import freechips.rocketchip.util.ElaborationArtefacts
|
||||
|
||||
/** Writes [[ElaborationArtefacts]] into files */
|
||||
class GenerateArtefacts extends Phase with PreservesAll[Phase] with HasMidasStageUtils {
|
||||
|
||||
override val prerequisites = Seq(Dependency[midas.chiselstage.stage.MidasChiselStage])
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
val targetDir = view[StageOptions](annotations).targetDir
|
||||
|
||||
ElaborationArtefacts.files.foreach { case (extension, contents) =>
|
||||
writeOutputFile(targetDir, s"${view[MidasOptions](annotations).longName.get}.${extension}", contents())
|
||||
}
|
||||
|
||||
annotations
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// See LICENSE
|
||||
|
||||
package midas.chiselstage.stage.phases
|
||||
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.annotations.{DeletedAnnotation, JsonProtocol}
|
||||
import firrtl.options.Viewer.view
|
||||
import firrtl.options._
|
||||
import midas.chiselstage.stage._
|
||||
|
||||
/** Writes FIRRTL annotations into a file */
|
||||
class GenerateFirrtlAnnos extends Phase with PreservesAll[Phase] with HasMidasStageUtils {
|
||||
|
||||
override val prerequisites = Seq(Dependency[midas.chiselstage.stage.MidasChiselStage])
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
val targetDir = view[StageOptions](annotations).targetDir
|
||||
val fileName = s"${view[MidasOptions](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 DeletedAnnotation(_, (_: Unserializable | _: CustomFileEmission)) =>
|
||||
None
|
||||
case a =>
|
||||
Some(a)
|
||||
}
|
||||
|
||||
writeOutputFile(targetDir, fileName, JsonProtocol.serialize(annos.toSeq))
|
||||
|
||||
annotations
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// See LICENSE
|
||||
|
||||
package midas.chiselstage.stage.phases
|
||||
|
||||
import chisel3.RawModule
|
||||
import chisel3.stage.ChiselGeneratorAnnotation
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.options.Viewer.view
|
||||
import firrtl.options.{Dependency, Phase, PreservesAll, StageOptions}
|
||||
import org.chipsalliance.cde.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import midas.chiselstage.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[Phase] with HasMidasStageUtils {
|
||||
|
||||
override val prerequisites = Seq(Dependency[Checks])
|
||||
override val dependents = Seq(Dependency[chisel3.stage.phases.Elaborate])
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
|
||||
val stageOpts = view[StageOptions](annotations)
|
||||
val rOpts = view[MidasOptions](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
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// See LICENSE
|
||||
|
||||
package midas.chiselstage.stage.phases
|
||||
|
||||
import chisel3.stage.ChiselOutputFileAnnotation
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.options.Viewer.view
|
||||
import firrtl.options.{Dependency, Phase, PreservesAll}
|
||||
import midas.chiselstage.stage._
|
||||
|
||||
/** Transforms RocketChipAnnotations into those used by other stages */
|
||||
class TransformAnnotations extends Phase with PreservesAll[Phase] with HasMidasStageUtils {
|
||||
|
||||
override val prerequisites = Seq(Dependency[Checks])
|
||||
override val dependents = Seq(Dependency[chisel3.stage.phases.AddImplicitOutputFile])
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
|
||||
/** Construct output file annotation for emission */
|
||||
new ChiselOutputFileAnnotation(view[MidasOptions](annotations).longName.get) +: annotations
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ vcs_args = +vcs+initreg+0 +vcs+initmem+0
|
|||
|
||||
$(FIRRTL_FILE) $(ANNO_FILE): $(TARGET_CP)
|
||||
@mkdir -p $(@D)
|
||||
$(call run_jar_scala_main,$(TARGET_CP),freechips.rocketchip.system.Generator,\
|
||||
$(call run_jar_scala_main,$(TARGET_CP),midas.chiselstage.Generator,\
|
||||
--target-dir $(GENERATED_DIR) \
|
||||
--name $(long_name) \
|
||||
--top-module $(DESIGN_PACKAGE).$(DESIGN) \
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
$(FIRRTL_FILE) $(ANNO_FILE): $(TARGET_CP)
|
||||
@mkdir -p $(@D)
|
||||
$(call run_jar_scala_main,$(TARGET_CP),freechips.rocketchip.system.Generator,\
|
||||
$(call run_jar_scala_main,$(TARGET_CP),midas.chiselstage.Generator,\
|
||||
--target-dir $(GENERATED_DIR) \
|
||||
--name $(long_name) \
|
||||
--top-module $(DESIGN_PACKAGE).$(DESIGN) \
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
$(FIRRTL_FILE) $(ANNO_FILE): $(TARGET_CP)
|
||||
@mkdir -p $(@D)
|
||||
$(call run_jar_scala_main,$(TARGET_CP),freechips.rocketchip.system.Generator,\
|
||||
$(call run_jar_scala_main,$(TARGET_CP),midas.chiselstage.Generator,\
|
||||
--target-dir $(GENERATED_DIR) \
|
||||
--name $(long_name) \
|
||||
--top-module $(DESIGN_PACKAGE).$(DESIGN) \
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 65ed3c162cc3d57c19d19621803a830a5f867e97
|
||||
Subproject commit 074c995a31ec04e1a920d4e8c353de8e84f34f4e
|
Loading…
Reference in New Issue