diff --git a/tapeout/src/main/scala/barstools/tapeout/transforms/EnumerateModules.scala b/tapeout/src/main/scala/barstools/tapeout/transforms/EnumerateModules.scala index 182b0071..47dae82c 100644 --- a/tapeout/src/main/scala/barstools/tapeout/transforms/EnumerateModules.scala +++ b/tapeout/src/main/scala/barstools/tapeout/transforms/EnumerateModules.scala @@ -35,7 +35,6 @@ class EnumerateModules(enumerate: (Module) => Unit) def transforms: Seq[Transform] = Seq(new EnumerateModulesPass(enumerate)) def execute(state: CircuitState): CircuitState = { - val ret = runTransforms(state) - CircuitState(ret.circuit, outputForm, ret.annotations, ret.renames) + runTransforms(state) } } diff --git a/tapeout/src/main/scala/barstools/tapeout/transforms/Generate.scala b/tapeout/src/main/scala/barstools/tapeout/transforms/Generate.scala index 01ea56e0..e20f72e5 100644 --- a/tapeout/src/main/scala/barstools/tapeout/transforms/Generate.scala +++ b/tapeout/src/main/scala/barstools/tapeout/transforms/Generate.scala @@ -1,274 +1,274 @@ -package barstools.tapeout.transforms - -import firrtl._ -import firrtl.annotations._ -import firrtl.ir._ -import firrtl.passes.memlib.ReplSeqMemAnnotation -import firrtl.stage.FirrtlCircuitAnnotation -import firrtl.transforms.BlackBoxResourceFileNameAnno -import logger.LazyLogging - -trait HasTapeoutOptions { self: ExecutionOptionsManager with HasFirrtlOptions => - var tapeoutOptions = TapeoutOptions() - - parser.note("tapeout options") - - parser - .opt[String]("harness-o") - .abbr("tho") - .valueName("") - .foreach { x => - tapeoutOptions = tapeoutOptions.copy( - harnessOutput = Some(x) - ) - } - .text { - "use this to generate a harness at " - } - - parser - .opt[String]("syn-top") - .abbr("tst") - .valueName("") - .foreach { x => - tapeoutOptions = tapeoutOptions.copy( - synTop = Some(x) - ) - } - .text { - "use this to set synTop" - } - - parser - .opt[String]("top-fir") - .abbr("tsf") - .valueName("") - .foreach { x => - tapeoutOptions = tapeoutOptions.copy( - topFir = Some(x) - ) - } - .text { - "use this to set topFir" - } - - parser - .opt[String]("top-anno-out") - .abbr("tsaof") - .valueName("") - .foreach { x => - tapeoutOptions = tapeoutOptions.copy( - topAnnoOut = Some(x) - ) - } - .text { - "use this to set topAnnoOut" - } - - parser - .opt[String]("top-dotf-out") - .abbr("tdf") - .valueName("") - .foreach { x => - tapeoutOptions = tapeoutOptions.copy( - topDotfOut = Some(x) - ) - } - .text { - "use this to set the filename for the top resource .f file" - } - - parser - .opt[String]("harness-top") - .abbr("tht") - .valueName("") - .foreach { x => - tapeoutOptions = tapeoutOptions.copy( - harnessTop = Some(x) - ) - } - .text { - "use this to set harnessTop" - } - - parser - .opt[String]("harness-fir") - .abbr("thf") - .valueName("") - .foreach { x => - tapeoutOptions = tapeoutOptions.copy( - harnessFir = Some(x) - ) - } - .text { - "use this to set harnessFir" - } - - parser - .opt[String]("harness-anno-out") - .abbr("thaof") - .valueName("") - .foreach { x => - tapeoutOptions = tapeoutOptions.copy( - harnessAnnoOut = Some(x) - ) - } - .text { - "use this to set harnessAnnoOut" - } - - parser - .opt[String]("harness-dotf-out") - .abbr("hdf") - .valueName("") - .foreach { x => - tapeoutOptions = tapeoutOptions.copy( - harnessDotfOut = Some(x) - ) - } - .text { - "use this to set the filename for the harness resource .f file" - } - - parser - .opt[String]("harness-conf") - .abbr("thconf") - .valueName("") - .foreach { x => - tapeoutOptions = tapeoutOptions.copy( - harnessConf = Some(x) - ) - } - .text { - "use this to set the harness conf file location" - } - -} - -case class TapeoutOptions( - harnessOutput: Option[String] = None, - synTop: Option[String] = None, - topFir: Option[String] = None, - topAnnoOut: Option[String] = None, - topDotfOut: Option[String] = None, - harnessTop: Option[String] = None, - harnessFir: Option[String] = None, - harnessAnnoOut: Option[String] = None, - harnessDotfOut: Option[String] = None, - harnessConf: Option[String] = None) - extends LazyLogging - -// Requires two phases, one to collect modules below synTop in the hierarchy -// and a second to remove those modules to generate the test harness -sealed trait GenerateTopAndHarnessApp extends LazyLogging { this: App => - lazy val optionsManager = { - val optionsManager = new ExecutionOptionsManager("tapeout") with HasFirrtlOptions with HasTapeoutOptions - if (!optionsManager.parse(args)) { - throw new Exception("Error parsing options!") - } - optionsManager - } - lazy val tapeoutOptions = optionsManager.tapeoutOptions - // Tapeout options - lazy val synTop = tapeoutOptions.synTop - lazy val harnessTop = tapeoutOptions.harnessTop - lazy val firrtlOptions = optionsManager.firrtlOptions - // FIRRTL options - lazy val annoFiles = firrtlOptions.annotationFileNames - - // order is determined by DependencyAPIMigration - val topTransforms = Seq( - new ReParentCircuit, - new RemoveUnusedModules - ) - - lazy val rootCircuitTarget = CircuitTarget(harnessTop.get) - - lazy val topAnnos = synTop.map(st => ReParentCircuitAnnotation(rootCircuitTarget.module(st))) ++ - tapeoutOptions.topDotfOut.map(BlackBoxResourceFileNameAnno(_)) - - lazy val topOptions = firrtlOptions.copy( - customTransforms = firrtlOptions.customTransforms ++ topTransforms, - annotations = firrtlOptions.annotations ++ topAnnos - ) - - // order is determined by DependencyAPIMigration - val harnessTransforms = Seq( - new ConvertToExtMod, - new RemoveUnusedModules, - new AvoidExtModuleCollisions, - new AddSuffixToModuleNames - ) - - // Dump firrtl and annotation files - protected def dump(res: FirrtlExecutionSuccess, firFile: Option[String], annoFile: Option[String]): Unit = { - firFile.foreach { firPath => - val outputFile = new java.io.PrintWriter(firPath) - outputFile.write(res.circuitState.circuit.serialize) - outputFile.close() - } - annoFile.foreach { annoPath => - val outputFile = new java.io.PrintWriter(annoPath) - outputFile.write(JsonProtocol.serialize(res.circuitState.annotations.filter(_ match { - case da: DeletedAnnotation => false - case ec: EmittedComponent => false - case ea: EmittedAnnotation[_] => false - case fca: FirrtlCircuitAnnotation => false - case _ => true - }))) - outputFile.close() - } - } - - // Top Generation - protected def executeTop(): Seq[ExtModule] = { - optionsManager.firrtlOptions = topOptions - val result = firrtl.Driver.execute(optionsManager) - result match { - case x: FirrtlExecutionSuccess => - dump(x, tapeoutOptions.topFir, tapeoutOptions.topAnnoOut) - x.circuitState.circuit.modules.collect { case e: ExtModule => e } - case x => - throw new Exception(s"executeTop failed while executing FIRRTL!\n${x}") - } - } - - // Top and harness generation - protected def executeTopAndHarness(): Unit = { - // Execute top and get list of ExtModules to avoid collisions - val topExtModules = executeTop() - - val harnessAnnos = - tapeoutOptions.harnessDotfOut.map(BlackBoxResourceFileNameAnno(_)).toSeq ++ - harnessTop.map(ht => ModuleNameSuffixAnnotation(rootCircuitTarget, s"_in${ht}")) ++ - synTop.map(st => ConvertToExtModAnnotation(rootCircuitTarget.module(st))) :+ - LinkExtModulesAnnotation(topExtModules) - - // For harness run, change some firrtlOptions (below) for harness phase - // customTransforms: setup harness transforms, add AvoidExtModuleCollisions - // outputFileNameOverride: change to harnessOutput - // conf file must change to harnessConf by mapping annotations - optionsManager.firrtlOptions = firrtlOptions.copy( - customTransforms = firrtlOptions.customTransforms ++ harnessTransforms, - outputFileNameOverride = tapeoutOptions.harnessOutput.get, - annotations = firrtlOptions.annotations.map({ - case ReplSeqMemAnnotation(i, o) => ReplSeqMemAnnotation(i, tapeoutOptions.harnessConf.get) - case a => a - }) ++ harnessAnnos - ) - val harnessResult = firrtl.Driver.execute(optionsManager) - harnessResult match { - case x: FirrtlExecutionSuccess => dump(x, tapeoutOptions.harnessFir, tapeoutOptions.harnessAnnoOut) - case x => throw new Exception(s"executeHarness failed while executing FIRRTL!\n${x}") - } - } -} - -object GenerateTop extends App with GenerateTopAndHarnessApp { - // Only need a single phase to generate the top module - executeTop() -} - -object GenerateTopAndHarness extends App with GenerateTopAndHarnessApp { - executeTopAndHarness() -} +//package barstools.tapeout.transforms +// +//import firrtl._ +//import firrtl.annotations._ +//import firrtl.ir._ +//import firrtl.passes.memlib.ReplSeqMemAnnotation +//import firrtl.stage.FirrtlCircuitAnnotation +//import firrtl.transforms.BlackBoxResourceFileNameAnno +//import logger.LazyLogging +// +//trait HasTapeoutOptions { self: ExecutionOptionsManager with HasFirrtlOptions => +// var tapeoutOptions = TapeoutOptions() +// +// parser.note("tapeout options") +// +// parser +// .opt[String]("harness-o") +// .abbr("tho") +// .valueName("") +// .foreach { x => +// tapeoutOptions = tapeoutOptions.copy( +// harnessOutput = Some(x) +// ) +// } +// .text { +// "use this to generate a harness at " +// } +// +// parser +// .opt[String]("syn-top") +// .abbr("tst") +// .valueName("") +// .foreach { x => +// tapeoutOptions = tapeoutOptions.copy( +// synTop = Some(x) +// ) +// } +// .text { +// "use this to set synTop" +// } +// +// parser +// .opt[String]("top-fir") +// .abbr("tsf") +// .valueName("") +// .foreach { x => +// tapeoutOptions = tapeoutOptions.copy( +// topFir = Some(x) +// ) +// } +// .text { +// "use this to set topFir" +// } +// +// parser +// .opt[String]("top-anno-out") +// .abbr("tsaof") +// .valueName("") +// .foreach { x => +// tapeoutOptions = tapeoutOptions.copy( +// topAnnoOut = Some(x) +// ) +// } +// .text { +// "use this to set topAnnoOut" +// } +// +// parser +// .opt[String]("top-dotf-out") +// .abbr("tdf") +// .valueName("") +// .foreach { x => +// tapeoutOptions = tapeoutOptions.copy( +// topDotfOut = Some(x) +// ) +// } +// .text { +// "use this to set the filename for the top resource .f file" +// } +// +// parser +// .opt[String]("harness-top") +// .abbr("tht") +// .valueName("") +// .foreach { x => +// tapeoutOptions = tapeoutOptions.copy( +// harnessTop = Some(x) +// ) +// } +// .text { +// "use this to set harnessTop" +// } +// +// parser +// .opt[String]("harness-fir") +// .abbr("thf") +// .valueName("") +// .foreach { x => +// tapeoutOptions = tapeoutOptions.copy( +// harnessFir = Some(x) +// ) +// } +// .text { +// "use this to set harnessFir" +// } +// +// parser +// .opt[String]("harness-anno-out") +// .abbr("thaof") +// .valueName("") +// .foreach { x => +// tapeoutOptions = tapeoutOptions.copy( +// harnessAnnoOut = Some(x) +// ) +// } +// .text { +// "use this to set harnessAnnoOut" +// } +// +// parser +// .opt[String]("harness-dotf-out") +// .abbr("hdf") +// .valueName("") +// .foreach { x => +// tapeoutOptions = tapeoutOptions.copy( +// harnessDotfOut = Some(x) +// ) +// } +// .text { +// "use this to set the filename for the harness resource .f file" +// } +// +// parser +// .opt[String]("harness-conf") +// .abbr("thconf") +// .valueName("") +// .foreach { x => +// tapeoutOptions = tapeoutOptions.copy( +// harnessConf = Some(x) +// ) +// } +// .text { +// "use this to set the harness conf file location" +// } +// +//} +// +//case class TapeoutOptions( +// harnessOutput: Option[String] = None, +// synTop: Option[String] = None, +// topFir: Option[String] = None, +// topAnnoOut: Option[String] = None, +// topDotfOut: Option[String] = None, +// harnessTop: Option[String] = None, +// harnessFir: Option[String] = None, +// harnessAnnoOut: Option[String] = None, +// harnessDotfOut: Option[String] = None, +// harnessConf: Option[String] = None) +// extends LazyLogging +// +//// Requires two phases, one to collect modules below synTop in the hierarchy +//// and a second to remove those modules to generate the test harness +//sealed trait GenerateTopAndHarnessApp extends LazyLogging { this: App => +// lazy val optionsManager = { +// val optionsManager = new ExecutionOptionsManager("tapeout") with HasFirrtlOptions with HasTapeoutOptions +// if (!optionsManager.parse(args)) { +// throw new Exception("Error parsing options!") +// } +// optionsManager +// } +// lazy val tapeoutOptions = optionsManager.tapeoutOptions +// // Tapeout options +// lazy val synTop = tapeoutOptions.synTop +// lazy val harnessTop = tapeoutOptions.harnessTop +// lazy val firrtlOptions = optionsManager.firrtlOptions +// // FIRRTL options +// lazy val annoFiles = firrtlOptions.annotationFileNames +// +// // order is determined by DependencyAPIMigration +// val topTransforms = Seq( +// new ReParentCircuit, +// new RemoveUnusedModules +// ) +// +// lazy val rootCircuitTarget = CircuitTarget(harnessTop.get) +// +// lazy val topAnnos = synTop.map(st => ReParentCircuitAnnotation(rootCircuitTarget.module(st))) ++ +// tapeoutOptions.topDotfOut.map(BlackBoxResourceFileNameAnno(_)) +// +// lazy val topOptions = firrtlOptions.copy( +// customTransforms = firrtlOptions.customTransforms ++ topTransforms, +// annotations = firrtlOptions.annotations ++ topAnnos +// ) +// +// // order is determined by DependencyAPIMigration +// val harnessTransforms = Seq( +// new ConvertToExtMod, +// new RemoveUnusedModules, +// new AvoidExtModuleCollisions, +// new AddSuffixToModuleNames +// ) +// +// // Dump firrtl and annotation files +// protected def dump(res: FirrtlExecutionSuccess, firFile: Option[String], annoFile: Option[String]): Unit = { +// firFile.foreach { firPath => +// val outputFile = new java.io.PrintWriter(firPath) +// outputFile.write(res.circuitState.circuit.serialize) +// outputFile.close() +// } +// annoFile.foreach { annoPath => +// val outputFile = new java.io.PrintWriter(annoPath) +// outputFile.write(JsonProtocol.serialize(res.circuitState.annotations.filter(_ match { +// case da: DeletedAnnotation => false +// case ec: EmittedComponent => false +// case ea: EmittedAnnotation[_] => false +// case fca: FirrtlCircuitAnnotation => false +// case _ => true +// }))) +// outputFile.close() +// } +// } +// +// // Top Generation +// protected def executeTop(): Seq[ExtModule] = { +// optionsManager.firrtlOptions = topOptions +// val result = firrtl.Driver.execute(optionsManager) +// result match { +// case x: FirrtlExecutionSuccess => +// dump(x, tapeoutOptions.topFir, tapeoutOptions.topAnnoOut) +// x.circuitState.circuit.modules.collect { case e: ExtModule => e } +// case x => +// throw new Exception(s"executeTop failed while executing FIRRTL!\n${x}") +// } +// } +// +// // Top and harness generation +// protected def executeTopAndHarness(): Unit = { +// // Execute top and get list of ExtModules to avoid collisions +// val topExtModules = executeTop() +// +// val harnessAnnos = +// tapeoutOptions.harnessDotfOut.map(BlackBoxResourceFileNameAnno(_)).toSeq ++ +// harnessTop.map(ht => ModuleNameSuffixAnnotation(rootCircuitTarget, s"_in${ht}")) ++ +// synTop.map(st => ConvertToExtModAnnotation(rootCircuitTarget.module(st))) :+ +// LinkExtModulesAnnotation(topExtModules) +// +// // For harness run, change some firrtlOptions (below) for harness phase +// // customTransforms: setup harness transforms, add AvoidExtModuleCollisions +// // outputFileNameOverride: change to harnessOutput +// // conf file must change to harnessConf by mapping annotations +// optionsManager.firrtlOptions = firrtlOptions.copy( +// customTransforms = firrtlOptions.customTransforms ++ harnessTransforms, +// outputFileNameOverride = tapeoutOptions.harnessOutput.get, +// annotations = firrtlOptions.annotations.map({ +// case ReplSeqMemAnnotation(i, o) => ReplSeqMemAnnotation(i, tapeoutOptions.harnessConf.get) +// case a => a +// }) ++ harnessAnnos +// ) +// val harnessResult = firrtl.Driver.execute(optionsManager) +// harnessResult match { +// case x: FirrtlExecutionSuccess => dump(x, tapeoutOptions.harnessFir, tapeoutOptions.harnessAnnoOut) +// case x => throw new Exception(s"executeHarness failed while executing FIRRTL!\n${x}") +// } +// } +//} +// +////object GenerateTop extends App with GenerateTopAndHarnessApp { +//// // Only need a single phase to generate the top module +//// executeTop() +////} +//// +////object GenerateTopAndHarness extends App with GenerateTopAndHarnessApp { +//// executeTopAndHarness() +////} diff --git a/tapeout/src/main/scala/barstools/tapeout/transforms/GenerateTopAndHarness.scala b/tapeout/src/main/scala/barstools/tapeout/transforms/GenerateTopAndHarness.scala new file mode 100644 index 00000000..108d3c13 --- /dev/null +++ b/tapeout/src/main/scala/barstools/tapeout/transforms/GenerateTopAndHarness.scala @@ -0,0 +1,127 @@ +package barstools.tapeout.transforms + +import barstools.tapeout.transforms.stage._ +import firrtl._ +import firrtl.annotations._ +import firrtl.ir._ +import firrtl.options.{Dependency, InputAnnotationFileAnnotation, StageMain} +import firrtl.passes.memlib.ReplSeqMemAnnotation +import firrtl.stage.{FirrtlCircuitAnnotation, FirrtlStage, OutputFileAnnotation, RunFirrtlTransformAnnotation} +import firrtl.transforms.BlackBoxResourceFileNameAnno +import logger.LazyLogging + +// Requires two phases, one to collect modules below synTop in the hierarchy +// and a second to remove those modules to generate the test harness +private class GenerateTopAndHarness(annotations: AnnotationSeq) extends LazyLogging { + val synTop: Option[String] = annotations.collectFirst { case SynTopAnnotation(s) => s } + val topFir: Option[String] = annotations.collectFirst { case TopFirAnnotation(s) => s } + val topAnnoOut: Option[String] = annotations.collectFirst { case TopAnnoOutAnnotation(s) => s } + val harnessTop: Option[String] = annotations.collectFirst { case HarnessTopAnnotation(h) => h } + val harnessConf: Option[String] = annotations.collectFirst { case HarnessConfAnnotation(h) => h } + val harnessOutput: Option[String] = annotations.collectFirst { case HarnessOutputAnnotation(h) => h } + val topDotfOut: Option[String] = annotations.collectFirst { case TopDotfOutAnnotation(h) => h } + val harnessDotfOut: Option[String] = annotations.collectFirst { case HarnessDotfOutAnnotation(h) => h } + + val annoFiles: List[String] = annotations.flatMap { + case InputAnnotationFileAnnotation(f) => Some(f) + case _ => None + }.toList + + // order is determined by DependencyAPIMigration + val topTransforms = Seq( + new ReParentCircuit, + new RemoveUnusedModules + ) + + lazy val rootCircuitTarget = CircuitTarget(harnessTop.get) + + val topAnnos = synTop.map(st => ReParentCircuitAnnotation(rootCircuitTarget.module(st))) ++ + topDotfOut.map(BlackBoxResourceFileNameAnno) + + // order is determined by DependencyAPIMigration + val harnessTransforms = Seq( + new ConvertToExtMod, + new RemoveUnusedModules, + new AvoidExtModuleCollisions, + new AddSuffixToModuleNames + ) + + // Dump firrtl and annotation files + protected def dump( + circuit: Circuit, + annotations: AnnotationSeq, + firFile: Option[String], + annoFile: Option[String] + ): Unit = { + firFile.foreach { firPath => + val outputFile = new java.io.PrintWriter(firPath) + outputFile.write(circuit.serialize) + outputFile.close() + } + annoFile.foreach { annoPath => + val outputFile = new java.io.PrintWriter(annoPath) + outputFile.write(JsonProtocol.serialize(annotations.filter(_ match { + case _: DeletedAnnotation => false + case _: EmittedComponent => false + case _: EmittedAnnotation[_] => false + case _: FirrtlCircuitAnnotation => false + case _ => true + }))) + outputFile.close() + } + } + + // Top Generation + def executeTop(): Seq[ExtModule] = { + val annos = new FirrtlStage().execute(Array.empty, annotations) + annos.collectFirst { case FirrtlCircuitAnnotation(circuit) => circuit } match { + case Some(circuit) => + dump(circuit, annos, topFir, topAnnoOut) + circuit.modules.collect { case e: ExtModule => e } + case _ => + throw new Exception(s"executeTop failed while executing FIRRTL!\n") + } + } + + // Top and harness generation + def executeTopAndHarness(): Unit = { + // Execute top and get list of ExtModules to avoid collisions + val topExtModules = executeTop() + + val harnessAnnos = + harnessDotfOut.map(BlackBoxResourceFileNameAnno).toSeq ++ + harnessTop.map(ht => ModuleNameSuffixAnnotation(rootCircuitTarget, s"_in${ht}")) ++ + synTop.map(st => ConvertToExtModAnnotation(rootCircuitTarget.module(st))) ++ + Seq( + LinkExtModulesAnnotation(topExtModules), + RunFirrtlTransformAnnotation(Dependency[ConvertToExtMod]), + RunFirrtlTransformAnnotation(Dependency[RemoveUnusedModules]), + RunFirrtlTransformAnnotation(Dependency[AvoidExtModuleCollisions]), + RunFirrtlTransformAnnotation(Dependency[AddSuffixToModuleNames]) + ) + + // For harness run, change some firrtlOptions (below) for harness phase + // customTransforms: setup harness transforms, add AvoidExtModuleCollisions + // outputFileNameOverride: change to harnessOutput + // conf file must change to harnessConf by mapping annotations + + val generatorAnnotations = annotations.map { + case ReplSeqMemAnnotation(i, _) => ReplSeqMemAnnotation(i, harnessConf.get) + case HarnessOutputAnnotation(s) => OutputFileAnnotation(s) + case anno => anno + } ++ harnessAnnos + + val annos = new FirrtlStage().execute(Array.empty, generatorAnnotations) + annos.collectFirst { case FirrtlCircuitAnnotation(circuit) => circuit } match { + case Some(circuit) => + dump(circuit, annos, topFir, topAnnoOut) + case _ => + throw new Exception(s"executeTop failed while executing FIRRTL!\n") + } + } +} + + +object GenerateTop extends StageMain(new TapeoutStage(doHarness = false)) + +object GenerateTopAndHarness extends StageMain(new TapeoutStage(doHarness = true)) diff --git a/tapeout/src/main/scala/barstools/tapeout/transforms/RemoveUnusedModules.scala b/tapeout/src/main/scala/barstools/tapeout/transforms/RemoveUnusedModules.scala index 5d1cbc6c..d6d7b80d 100644 --- a/tapeout/src/main/scala/barstools/tapeout/transforms/RemoveUnusedModules.scala +++ b/tapeout/src/main/scala/barstools/tapeout/transforms/RemoveUnusedModules.scala @@ -23,7 +23,7 @@ class RemoveUnusedModules extends Transform with DependencyAPIMigration { def execute(state: CircuitState): CircuitState = { val modulesByName = state.circuit.modules.map { - case m: Module => (m.name, Some(m)) + case m: Module => (m.name, Some(m)) case m: ExtModule => (m.name, None) }.toMap diff --git a/tapeout/src/main/scala/barstools/tapeout/transforms/stage/TapeoutStage.scala b/tapeout/src/main/scala/barstools/tapeout/transforms/stage/TapeoutStage.scala new file mode 100644 index 00000000..1c50a82e --- /dev/null +++ b/tapeout/src/main/scala/barstools/tapeout/transforms/stage/TapeoutStage.scala @@ -0,0 +1,181 @@ +// See LICENSE for license details. + +package barstools.tapeout.transforms.stage + +import barstools.tapeout.transforms.GenerateTopAndHarness +import chisel3.stage.ChiselCli +import firrtl.AnnotationSeq +import firrtl.annotations.{Annotation, NoTargetAnnotation} +import firrtl.options.{HasShellOptions, Shell, ShellOption, Stage, Unserializable} +import firrtl.stage.FirrtlCli +import logger.Logger + +sealed trait TapeoutOption extends Unserializable { + this: Annotation => +} + +case class HarnessOutputAnnotation(harnessOutput: String) extends NoTargetAnnotation with TapeoutOption + +object HarnessOutputAnnotation extends HasShellOptions { + val options: Seq[ShellOption[_]] = Seq( + new ShellOption[String]( + longOption = "harness-o", + shortOption = Some("tho"), + toAnnotationSeq = (s: String) => Seq(HarnessOutputAnnotation(s)), + helpText = "use this to generate a harness at " + ) + ) +} + +case class SynTopAnnotation(synTop: String) extends NoTargetAnnotation with TapeoutOption + +object SynTopAnnotation extends HasShellOptions { + val options: Seq[ShellOption[_]] = Seq( + new ShellOption[String]( + longOption = "syn-top", + shortOption = Some("tst"), + toAnnotationSeq = (s: String) => Seq(SynTopAnnotation(s)), + helpText = "use this to set synTop" + ) + ) +} + +case class TopFirAnnotation(topFir: String) extends NoTargetAnnotation with TapeoutOption + +object TopFirAnnotation extends HasShellOptions { + val options: Seq[ShellOption[_]] = Seq( + new ShellOption[String]( + longOption = "top-fir", + shortOption = Some("tsf"), + toAnnotationSeq = (s: String) => Seq(TopFirAnnotation(s)), + helpText = "use this to set topFir" + ) + ) +} + +case class TopAnnoOutAnnotation(topAnnoOut: String) extends NoTargetAnnotation with TapeoutOption + +object TopAnnoOutAnnotation extends HasShellOptions { + val options: Seq[ShellOption[_]] = Seq( + new ShellOption[String]( + longOption = "top-anno-out", + shortOption = Some("tsaof"), + toAnnotationSeq = (s: String) => Seq(TopAnnoOutAnnotation(s)), + helpText = "use this to set topAnnoOut" + ) + ) +} + +case class TopDotfOutAnnotation(topDotfOut: String) extends NoTargetAnnotation with TapeoutOption + +object TopDotfOutAnnotation extends HasShellOptions { + val options: Seq[ShellOption[_]] = Seq( + new ShellOption[String]( + longOption = "top-dotf-out", + shortOption = Some("tdf"), + toAnnotationSeq = (s: String) => Seq(TopDotfOutAnnotation(s)), + helpText = "use this to set the filename for the top resource .f file" + ) + ) +} + +case class HarnessTopAnnotation(harnessTop: String) extends NoTargetAnnotation with TapeoutOption + +object HarnessTopAnnotation extends HasShellOptions { + val options: Seq[ShellOption[_]] = Seq( + new ShellOption[String]( + longOption = "harness-top", + shortOption = Some("tht"), + toAnnotationSeq = (s: String) => Seq(HarnessTopAnnotation(s)), + helpText = "use this to set harnessTop" + ) + ) +} + +case class HarnessFirAnnotation(harnessFir: String) extends NoTargetAnnotation with TapeoutOption + +object HarnessFirAnnotation extends HasShellOptions { + val options: Seq[ShellOption[_]] = Seq( + new ShellOption[String]( + longOption = "harness-fir", + shortOption = Some("thf"), + toAnnotationSeq = (s: String) => Seq(HarnessFirAnnotation(s)), + helpText = "use this to set harnessFir" + ) + ) +} + +case class HarnessAnnoOutAnnotation(harnessAnnoOut: String) extends NoTargetAnnotation with TapeoutOption + +object HarnessAnnoOutAnnotation extends HasShellOptions { + val options: Seq[ShellOption[_]] = Seq( + new ShellOption[String]( + longOption = "harness-anno-out", + shortOption = Some("thaof"), + toAnnotationSeq = (s: String) => Seq(HarnessAnnoOutAnnotation(s)), + helpText = "use this to set harnessAnnoOut" + ) + ) +} + +case class HarnessDotfOutAnnotation(harnessDotfOut: String) extends NoTargetAnnotation with TapeoutOption + +object HarnessDotfOutAnnotation extends HasShellOptions { + val options: Seq[ShellOption[_]] = Seq( + new ShellOption[String]( + longOption = "harness-dotf-out", + shortOption = Some("hdf"), + toAnnotationSeq = (s: String) => Seq(HarnessDotfOutAnnotation(s)), + helpText = "use this to set the filename for the harness resource .f file" + ) + ) +} + +case class HarnessConfAnnotation(harnessConf: String) extends NoTargetAnnotation with TapeoutOption + +object HarnessConfAnnotation extends HasShellOptions { + val options: Seq[ShellOption[_]] = Seq( + new ShellOption[String]( + longOption = "harness-conf", + shortOption = Some("thconf"), + toAnnotationSeq = (s: String) => Seq(HarnessConfAnnotation(s)), + helpText = "use this to set the harness conf file location" + ) + ) +} + +trait TapeoutCli { + this: Shell => + parser.note("Tapeout specific options") + + Seq( + HarnessOutputAnnotation, + SynTopAnnotation, + TopFirAnnotation, + TopAnnoOutAnnotation, + TopDotfOutAnnotation, + HarnessTopAnnotation, + HarnessFirAnnotation, + HarnessAnnoOutAnnotation, + HarnessDotfOutAnnotation, + HarnessConfAnnotation + ).foreach(_.addOptions(parser)) +} + +class TapeoutStage(doHarness: Boolean) extends Stage { + override val shell: Shell = new Shell(applicationName = "tapeout") with TapeoutCli with ChiselCli with FirrtlCli + + override def run(annotations: AnnotationSeq): AnnotationSeq = { + Logger.makeScope(annotations) { + val generator = new GenerateTopAndHarness(annotations) + + if (doHarness) { + generator.executeTopAndHarness() + } else { + generator.executeTop() + } + } + annotations + } +} + diff --git a/tapeout/src/test/scala/barstools/tapeout/transforms/GenerateTopSpec.scala b/tapeout/src/test/scala/barstools/tapeout/transforms/GenerateTopSpec.scala new file mode 100644 index 00000000..db84230d --- /dev/null +++ b/tapeout/src/test/scala/barstools/tapeout/transforms/GenerateTopSpec.scala @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 + +package barstools.tapeout.transforms + +import org.scalatest.freespec.AnyFreeSpec +import org.scalatest.matchers.should.Matchers + +import java.io.{ByteArrayOutputStream, PrintStream} + +class GenerateTopSpec extends AnyFreeSpec with Matchers { + "Generate top and harness" - { + "should include the following transforms" in { + val buffer = new ByteArrayOutputStream() + Console.withOut(new PrintStream(buffer)) { + GenerateTopAndHarness.main(Array("-i", "ExampleModuleNeedsResetInverted.fir", "-ll", "info")) + } + val output = buffer.toString + output should include("barstools.tapeout.transforms.AddSuffixToModuleNames") + output should include("barstools.tapeout.transforms.ConvertToExtMod") + output should include("barstools.tapeout.transforms.RemoveUnusedModules") + output should include("barstools.tapeout.transforms.AvoidExtModuleCollisions") + println(output) + } + } + + "generate harness should " in { + val buffer = new ByteArrayOutputStream() + Console.withOut(new PrintStream(buffer)) { + GenerateTopAndHarness.main( + Array( + "--target-dir", "test_run_dir/generate_top_spec", + "-i", "/Users/chick/Adept/dev/masters/barstools/tapeout/src/test/resources/BlackBoxFloatTester.fir", +// "-X", "low", +// "-ll", "info", +// "--help" + ) + ) + } + val output = buffer.toString + println(output) + } +}