aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl
diff options
context:
space:
mode:
authorSchuyler Eldridge2019-04-22 21:20:08 -0400
committerSchuyler Eldridge2019-04-25 16:24:15 -0400
commitef8f06f23b9ee6cf86de2450752dfd0fcd32da80 (patch)
tree79e2e8c5753903ca6d14e9b952c26a07442bd980 /src/main/scala/firrtl
parent47fe781c4ace38dff7f31da7e78f772e131d689e (diff)
Add ShellOption, DeletedWrapper
Abstracts away option writing such that users no longer have to understand scopt semantics. This adds a ShellOption class and a HasShellOptions trait for something which provides one or more ShellOptions. This refactors the FIRRTL codebase to use this style of option specification. Adds and uses DeletedWrapper to automatically generate DeletedAnnotations. Signed-off-by: Schuyler Eldridge <schuyler.eldridge@ibm.com>
Diffstat (limited to 'src/main/scala/firrtl')
-rw-r--r--src/main/scala/firrtl/Driver.scala19
-rw-r--r--src/main/scala/firrtl/Emitter.scala48
-rw-r--r--src/main/scala/firrtl/options/Phase.scala16
-rw-r--r--src/main/scala/firrtl/options/Registration.scala58
-rw-r--r--src/main/scala/firrtl/options/Shell.scala12
-rw-r--r--src/main/scala/firrtl/options/Stage.scala11
-rw-r--r--src/main/scala/firrtl/options/StageAnnotations.scala66
-rw-r--r--src/main/scala/firrtl/options/phases/DeletedWrapper.scala43
-rw-r--r--src/main/scala/firrtl/passes/Inline.scala36
-rw-r--r--src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala18
-rw-r--r--src/main/scala/firrtl/passes/memlib/InferReadWrite.scala17
-rw-r--r--src/main/scala/firrtl/passes/memlib/MemLibOptions.scala11
-rw-r--r--src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala20
-rw-r--r--src/main/scala/firrtl/stage/FirrtlAnnotations.scala125
-rw-r--r--src/main/scala/firrtl/stage/FirrtlStage.scala23
-rw-r--r--src/main/scala/firrtl/stage/phases/DriverCompatibility.scala7
-rw-r--r--src/main/scala/firrtl/transforms/CheckCombLoops.scala12
-rw-r--r--src/main/scala/firrtl/transforms/DeadCodeElimination.scala12
18 files changed, 318 insertions, 236 deletions
diff --git a/src/main/scala/firrtl/Driver.scala b/src/main/scala/firrtl/Driver.scala
index c8713e09..66e09e86 100644
--- a/src/main/scala/firrtl/Driver.scala
+++ b/src/main/scala/firrtl/Driver.scala
@@ -18,8 +18,8 @@ import firrtl.transforms._
import firrtl.Utils.throwInternalError
import firrtl.stage.{FirrtlExecutionResultView, FirrtlStage}
import firrtl.stage.phases.DriverCompatibility
-import firrtl.options.{StageUtils, Phase}
-import firrtl.options.Viewer
+import firrtl.options.{StageUtils, Phase, Viewer}
+import firrtl.options.phases.DeletedWrapper
/**
@@ -216,15 +216,16 @@ object Driver {
val annos = optionsManager.firrtlOptions.toAnnotations ++ optionsManager.commonOptions.toAnnotations
- val phases: Seq[Phase] = Seq(
- new DriverCompatibility.AddImplicitAnnotationFile,
- new DriverCompatibility.AddImplicitFirrtlFile,
- new DriverCompatibility.AddImplicitOutputFile,
- new DriverCompatibility.AddImplicitEmitter,
- new FirrtlStage )
+ val phases: Seq[Phase] =
+ Seq( new DriverCompatibility.AddImplicitAnnotationFile,
+ new DriverCompatibility.AddImplicitFirrtlFile,
+ new DriverCompatibility.AddImplicitOutputFile,
+ new DriverCompatibility.AddImplicitEmitter,
+ new FirrtlStage )
+ .map(DeletedWrapper(_))
val annosx = try {
- phases.foldLeft(annos)( (a, p) => p.runTransform(a) )
+ phases.foldLeft(annos)( (a, p) => p.transform(a) )
} catch {
case e: firrtl.options.OptionsException => return FirrtlExecutionFailure(e.message)
}
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
index 44190b39..3bbba289 100644
--- a/src/main/scala/firrtl/Emitter.scala
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -19,7 +19,7 @@ import firrtl.PrimOps._
import firrtl.WrappedExpression._
import Utils._
import MemPortUtils.{memPortField, memType}
-import firrtl.options.{HasScoptOptions, StageUtils, PhaseException}
+import firrtl.options.{HasShellOptions, ShellOption, StageUtils, PhaseException}
import firrtl.stage.RunFirrtlTransformAnnotation
import scopt.OptionParser
// Datastructures
@@ -34,14 +34,12 @@ sealed trait EmitAnnotation extends NoTargetAnnotation {
case class EmitCircuitAnnotation(emitter: Class[_ <: Emitter]) extends EmitAnnotation
case class EmitAllModulesAnnotation(emitter: Class[_ <: Emitter]) extends EmitAnnotation
-object EmitCircuitAnnotation extends HasScoptOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p
- .opt[String]("emit-circuit")
- .abbr("E")
- .valueName("<chirrtl|high|middle|low|verilog|mverilog|sverilog>")
- .unbounded()
- .action{ (x, c) =>
- val xx = x match {
+object EmitCircuitAnnotation extends HasShellOptions {
+
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "emit-circuit",
+ toAnnotationSeq = (a: String) => a match {
case "chirrtl" => Seq(RunFirrtlTransformAnnotation(new ChirrtlEmitter),
EmitCircuitAnnotation(classOf[ChirrtlEmitter]))
case "high" => Seq(RunFirrtlTransformAnnotation(new HighFirrtlEmitter),
@@ -54,20 +52,19 @@ object EmitCircuitAnnotation extends HasScoptOptions {
EmitCircuitAnnotation(classOf[VerilogEmitter]))
case "sverilog" => Seq(RunFirrtlTransformAnnotation(new SystemVerilogEmitter),
EmitCircuitAnnotation(classOf[SystemVerilogEmitter]))
- case _ => throw new PhaseException(s"Unknown emitter '$x'! (Did you misspell it?)")
- }
- xx ++ c }
- .text("Run the specified circuit emitter (all modules in one file)")
+ case _ => throw new PhaseException(s"Unknown emitter '$a'! (Did you misspell it?)") },
+ helpText = "Run the specified circuit emitter (all modules in one file)",
+ shortOption = Some("E"),
+ helpValueName = Some("<chirrtl|high|middle|low|verilog|mverilog|sverilog>") ) )
+
}
-object EmitAllModulesAnnotation extends HasScoptOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p
- .opt[String]("emit-modules")
- .abbr("e")
- .valueName("<none|high|middle|low|verilog|mverilog|sverilog>")
- .unbounded()
- .action{ (x, c) =>
- val xx = x match {
+object EmitAllModulesAnnotation extends HasShellOptions {
+
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "emit-modules",
+ toAnnotationSeq = (a: String) => a match {
case "chirrtl" => Seq(RunFirrtlTransformAnnotation(new ChirrtlEmitter),
EmitAllModulesAnnotation(classOf[ChirrtlEmitter]))
case "high" => Seq(RunFirrtlTransformAnnotation(new HighFirrtlEmitter),
@@ -80,10 +77,11 @@ object EmitAllModulesAnnotation extends HasScoptOptions {
EmitAllModulesAnnotation(classOf[VerilogEmitter]))
case "sverilog" => Seq(RunFirrtlTransformAnnotation(new SystemVerilogEmitter),
EmitAllModulesAnnotation(classOf[SystemVerilogEmitter]))
- case _ => throw new PhaseException(s"Unknown emitter '$x'! (Did you misspell it?)")
- }
- xx ++ c }
- .text("Run the specified module emitter (one file per module)")
+ case _ => throw new PhaseException(s"Unknown emitter '$a'! (Did you misspell it?)") },
+ helpText = "Run the specified module emitter (one file per module)",
+ shortOption = Some("e"),
+ helpValueName = Some("<chirrtl|high|middle|low|verilog|mverilog|sverilog>") ) )
+
}
// ***** Annotations for results of emission *****
diff --git a/src/main/scala/firrtl/options/Phase.scala b/src/main/scala/firrtl/options/Phase.scala
index a660d08a..34739053 100644
--- a/src/main/scala/firrtl/options/Phase.scala
+++ b/src/main/scala/firrtl/options/Phase.scala
@@ -39,22 +39,6 @@ abstract class Phase extends TransformLike[AnnotationSeq] {
*/
lazy val name: String = this.getClass.getName
- /** Perform the transform of [[transform]] on an [[firrtl.AnnotationSeq AnnotationSeq]] and add
- * [[firrtl.annotations.DeletedAnnotation DeletedAnnotation]]s for any deleted [[firrtl.annotations.Annotation
- * Annotation]]s.
- * @param a
- */
- final def runTransform(annotations: AnnotationSeq): AnnotationSeq = {
- val ax = transform(annotations)
-
- val (in, out) = (mutable.LinkedHashSet() ++ annotations, mutable.LinkedHashSet() ++ ax)
-
- (in -- out).map {
- case DeletedAnnotation(n, a) => DeletedAnnotation(s"$n+$name", a)
- case a => DeletedAnnotation(name, a)
- }.toSeq ++ ax
- }
-
}
/** A [[TransformLike]] that internally ''translates'' the input type to some other type, transforms the internal type,
diff --git a/src/main/scala/firrtl/options/Registration.scala b/src/main/scala/firrtl/options/Registration.scala
index a826ec50..c832ec7c 100644
--- a/src/main/scala/firrtl/options/Registration.scala
+++ b/src/main/scala/firrtl/options/Registration.scala
@@ -4,40 +4,70 @@ package firrtl.options
import firrtl.{AnnotationSeq, Transform}
-import scopt.OptionParser
+import scopt.{OptionDef, OptionParser, Read}
+
+/** Contains information about a [[Shell]] command line option
+ * @tparam the type of the command line argument
+ * @param longOption a long, double-dash option
+ * @param toAnnotationSeq a function to convert the type into an [[firrtl.AnnotationSeq AnnotationSeq]]
+ * @param helpText help text
+ * @param shortOption an optional single-dash option
+ * @param helpValueName a string to show as a placeholder argument in help text
+ */
+final class ShellOption[A: Read] (
+ val longOption: String,
+ val toAnnotationSeq: A => AnnotationSeq,
+ val helpText: String,
+ val shortOption: Option[String] = None,
+ val helpValueName: Option[String] = None
+) {
+
+ /** Add this specific shell (command line) option to an option parser
+ * @param p an option parser
+ */
+ final def addOption(p: OptionParser[AnnotationSeq]): Unit = {
+ val f = Seq(
+ (p: OptionDef[A, AnnotationSeq]) => p.action( (x, c) => toAnnotationSeq(x).reverse ++ c ),
+ (p: OptionDef[A, AnnotationSeq]) => p.text(helpText),
+ (p: OptionDef[A, AnnotationSeq]) => p.unbounded()) ++
+ shortOption.map( a => (p: OptionDef[A, AnnotationSeq]) => p.abbr(a) ) ++
+ helpValueName.map( a => (p: OptionDef[A, AnnotationSeq]) => p.valueName(a) )
+
+ f.foldLeft(p.opt[A](longOption))( (a, b) => b(a) )
+ }
+}
/** Indicates that this class/object includes options (but does not add these as a registered class)
*/
-trait HasScoptOptions {
+trait HasShellOptions {
- /** This method will be called to add options to an OptionParser ('''OPTIONS SHOULD BE PREPENDED''')
- *
- *
- * '''The ordering of [[firrtl.annotations.Annotation Annotation]] is important and has meaning for parallel
- * compilations. For deterministic behavior, you should always prepend any annotations to the [[firrtl.AnnotationSeq
- * AnnotationSeq]]. The [[firrtl.AnnotationSeq AnnotationSeq]] will be automatically reversed after a [[Stage]]
- * parses it.'''
- *
+ /** A sequence of options provided
+ */
+ def options: Seq[ShellOption[_]]
+
+ /** Add all shell (command line) options to an option parser
* @param p an option parser
*/
- def addOptions(p: OptionParser[AnnotationSeq]): Unit
+ final def addOptions(p: OptionParser[AnnotationSeq]): Unit = options.foreach(_.addOption(p))
+
}
-/** A [[Transform]] that includes options that should be exposed at the top level.
+/** A [[Transform]] that includes an option that should be exposed at the top level.
*
* @note To complete registration, include an entry in
* src/main/resources/META-INF/services/firrtl.options.RegisteredTransform */
-trait RegisteredTransform extends HasScoptOptions { this: Transform => }
+trait RegisteredTransform extends HasShellOptions { this: Transform => }
/** A class that includes options that should be exposed as a group at the top level.
*
* @note To complete registration, include an entry in
* src/main/resources/META-INF/services/firrtl.options.RegisteredLibrary */
-trait RegisteredLibrary extends HasScoptOptions {
+trait RegisteredLibrary extends HasShellOptions {
/** The name of this library.
*
* This will be used when generating help text.
*/
def name: String
+
}
diff --git a/src/main/scala/firrtl/options/Shell.scala b/src/main/scala/firrtl/options/Shell.scala
index dbc403a5..28c0554a 100644
--- a/src/main/scala/firrtl/options/Shell.scala
+++ b/src/main/scala/firrtl/options/Shell.scala
@@ -16,10 +16,10 @@ import java.util.ServiceLoader
class Shell(val applicationName: String) {
/** Command line argument parser (OptionParser) with modifications */
- final val parser = new OptionParser[AnnotationSeq](applicationName) with DuplicateHandling with ExceptOnError
+ protected val parser = new OptionParser[AnnotationSeq](applicationName) with DuplicateHandling with ExceptOnError
/** Contains all discovered [[RegisteredLibrary]] */
- lazy val registeredLibraries: Seq[RegisteredLibrary] = {
+ final lazy val registeredLibraries: Seq[RegisteredLibrary] = {
val libraries = scala.collection.mutable.ArrayBuffer[RegisteredLibrary]()
val iter = ServiceLoader.load(classOf[RegisteredLibrary]).iterator()
while (iter.hasNext) {
@@ -33,7 +33,7 @@ class Shell(val applicationName: String) {
}
/** Contains all discovered [[RegisteredTransform]] */
- lazy val registeredTransforms: Seq[RegisteredTransform] = {
+ final lazy val registeredTransforms: Seq[RegisteredTransform] = {
val transforms = scala.collection.mutable.ArrayBuffer[RegisteredTransform]()
val iter = ServiceLoader.load(classOf[RegisteredTransform]).iterator()
if (iter.hasNext) { parser.note("FIRRTL Transform Options") }
@@ -61,11 +61,11 @@ class Shell(val applicationName: String) {
}
parser.note("Shell Options")
+ ProgramArgsAnnotation.addOptions(parser)
Seq( TargetDirAnnotation,
- ProgramArgsAnnotation,
InputAnnotationFileAnnotation,
OutputAnnotationFileAnnotation )
- .map(_.addOptions(parser))
+ .foreach(_.addOptions(parser))
parser.opt[Unit]("show-registrations")
.action{ (_, c) =>
@@ -85,5 +85,5 @@ class Shell(val applicationName: String) {
ClassLogLevelAnnotation,
LogFileAnnotation,
LogClassNamesAnnotation )
- .map(_.addOptions(parser))
+ .foreach(_.addOptions(parser))
}
diff --git a/src/main/scala/firrtl/options/Stage.scala b/src/main/scala/firrtl/options/Stage.scala
index 38cc9d42..f2780761 100644
--- a/src/main/scala/firrtl/options/Stage.scala
+++ b/src/main/scala/firrtl/options/Stage.scala
@@ -31,16 +31,19 @@ abstract class Stage extends Phase {
* @throws OptionsException if command line or annotation validation fails
*/
final def transform(annotations: AnnotationSeq): AnnotationSeq = {
- val annotationsx = Seq( new phases.GetIncludes,
- new phases.ConvertLegacyAnnotations )
- .foldLeft(annotations)((a, p) => p.runTransform(a))
+ val annotationsx =
+ Seq( new phases.GetIncludes,
+ new phases.ConvertLegacyAnnotations )
+ .map(phases.DeletedWrapper(_))
+ .foldLeft(annotations)((a, p) => p.transform(a))
Logger.makeScope(annotationsx) {
Seq( new phases.AddDefaults,
new phases.Checks,
new Phase { def transform(a: AnnotationSeq) = run(a) },
new phases.WriteOutputAnnotations )
- .foldLeft(annotationsx)((a, p) => p.runTransform(a))
+ .map(phases.DeletedWrapper(_))
+ .foldLeft(annotationsx)((a, p) => p.transform(a))
}
}
diff --git a/src/main/scala/firrtl/options/StageAnnotations.scala b/src/main/scala/firrtl/options/StageAnnotations.scala
index e8a1a288..e35a6afa 100644
--- a/src/main/scala/firrtl/options/StageAnnotations.scala
+++ b/src/main/scala/firrtl/options/StageAnnotations.scala
@@ -21,13 +21,16 @@ trait Unserializable { this: Annotation => }
*/
case class TargetDirAnnotation(directory: String = ".") extends NoTargetAnnotation with StageOption
-object TargetDirAnnotation extends HasScoptOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("target-dir")
- .abbr("td")
- .valueName("<target-directory>")
- .action( (x, c) => TargetDirAnnotation(x) +: c )
- .unbounded() // See [Note 1]
- .text(s"Work directory for intermediate files/blackboxes, default is '.' (current directory)")
+object TargetDirAnnotation extends HasShellOptions {
+
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "target-dir",
+ toAnnotationSeq = (a: String) => Seq(TargetDirAnnotation(a)),
+ helpText = "Work directory (default: '.')",
+ shortOption = Some("td"),
+ helpValueName = Some("<directory>") ) )
+
}
/** Additional arguments
@@ -36,7 +39,8 @@ object TargetDirAnnotation extends HasScoptOptions {
*/
case class ProgramArgsAnnotation(arg: String) extends NoTargetAnnotation with StageOption
-object ProgramArgsAnnotation extends HasScoptOptions {
+object ProgramArgsAnnotation {
+
def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.arg[String]("<arg>...")
.unbounded()
.optional()
@@ -51,13 +55,16 @@ object ProgramArgsAnnotation extends HasScoptOptions {
*/
case class InputAnnotationFileAnnotation(file: String) extends NoTargetAnnotation with StageOption
-object InputAnnotationFileAnnotation extends HasScoptOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("annotation-file")
- .abbr("faf")
- .unbounded()
- .valueName("<input-anno-file>")
- .action( (x, c) => InputAnnotationFileAnnotation(x) +: c )
- .text("Used to specify annotation file")
+object InputAnnotationFileAnnotation extends HasShellOptions {
+
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "annotation-file",
+ toAnnotationSeq = (a: String) => Seq(InputAnnotationFileAnnotation(a)),
+ helpText = "An input annotation file",
+ shortOption = Some("faf"),
+ helpValueName = Some("<file>") ) )
+
}
/** An explicit output _annotation_ file to write to
@@ -66,13 +73,16 @@ object InputAnnotationFileAnnotation extends HasScoptOptions {
*/
case class OutputAnnotationFileAnnotation(file: String) extends NoTargetAnnotation with StageOption
-object OutputAnnotationFileAnnotation extends HasScoptOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("output-annotation-file")
- .abbr("foaf")
- .valueName ("<output-anno-file>")
- .action( (x, c) => OutputAnnotationFileAnnotation(x) +: c )
- .unbounded()
- .text("use this to set the annotation output file")
+object OutputAnnotationFileAnnotation extends HasShellOptions {
+
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "output-annotation-file",
+ toAnnotationSeq = (a: String) => Seq(OutputAnnotationFileAnnotation(a)),
+ helpText = "An output annotation file",
+ shortOption = Some("foaf"),
+ helpValueName = Some("<file>") ) )
+
}
/** If this [[firrtl.annotations.Annotation Annotation]] exists in an [[firrtl.AnnotationSeq AnnotationSeq]], then a
@@ -80,12 +90,12 @@ object OutputAnnotationFileAnnotation extends HasScoptOptions {
* [[firrtl.annotations.DeletedAnnotation DeletedAnnotation]]s when it writes to a file.
* - set with '--write-deleted'
*/
-case object WriteDeletedAnnotation extends NoTargetAnnotation with StageOption with HasScoptOptions {
+case object WriteDeletedAnnotation extends NoTargetAnnotation with StageOption with HasShellOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p
- .opt[Unit]("write-deleted")
- .unbounded()
- .action( (_, c) => WriteDeletedAnnotation +: c )
- .text("Include deleted annotations in the output annotation file")
+ val options = Seq(
+ new ShellOption[Unit](
+ longOption = "write-deleted",
+ toAnnotationSeq = (_: Unit) => Seq(WriteDeletedAnnotation),
+ helpText = "Include deleted annotations in the output annotation file" ) )
}
diff --git a/src/main/scala/firrtl/options/phases/DeletedWrapper.scala b/src/main/scala/firrtl/options/phases/DeletedWrapper.scala
new file mode 100644
index 00000000..0a959f32
--- /dev/null
+++ b/src/main/scala/firrtl/options/phases/DeletedWrapper.scala
@@ -0,0 +1,43 @@
+// See LICENSE for license details.
+
+package firrtl.options.phases
+
+import firrtl.AnnotationSeq
+import firrtl.annotations.DeletedAnnotation
+import firrtl.options.{Phase, Translator}
+
+import scala.collection.mutable
+
+/** Wrap a [[firrtl.options.Phase Phase]] such that any [[firrtl.annotations.Annotation Annotation]] removed by the
+ * wrapped [[firrtl.options.Phase Phase]] will be added as [[firrtl.annotations.DeletedAnnotation DeletedAnnotation]]s.
+ * @param p a [[firrtl.options.Phase Phase]] to wrap
+ */
+class DeletedWrapper(p: Phase) extends Phase with Translator[AnnotationSeq, (AnnotationSeq, AnnotationSeq)] {
+
+ override lazy val name: String = p.name
+
+ def aToB(a: AnnotationSeq): (AnnotationSeq, AnnotationSeq) = (a, a)
+
+ def bToA(b: (AnnotationSeq, AnnotationSeq)): AnnotationSeq = {
+
+ val (in, out) = (mutable.LinkedHashSet() ++ b._1, mutable.LinkedHashSet() ++ b._2)
+
+ (in -- out).map {
+ case DeletedAnnotation(n, a) => DeletedAnnotation(s"$n+$name", a)
+ case a => DeletedAnnotation(name, a)
+ }.toSeq ++ b._2
+
+ }
+
+ def internalTransform(b: (AnnotationSeq, AnnotationSeq)): (AnnotationSeq, AnnotationSeq) = (b._1, p.transform(b._2))
+
+}
+
+object DeletedWrapper {
+
+ /** Wrap a [[firrtl.options.Phase Phase]] in a [[DeletedWrapper]]
+ * @param p a [[firrtl.options.Phase Phase]] to wrap
+ */
+ def apply(p: Phase): DeletedWrapper = new DeletedWrapper(p)
+
+}
diff --git a/src/main/scala/firrtl/passes/Inline.scala b/src/main/scala/firrtl/passes/Inline.scala
index dcee0ee2..0806563c 100644
--- a/src/main/scala/firrtl/passes/Inline.scala
+++ b/src/main/scala/firrtl/passes/Inline.scala
@@ -8,7 +8,7 @@ import firrtl.Mappers._
import firrtl.annotations._
import firrtl.analyses.InstanceGraph
import firrtl.stage.RunFirrtlTransformAnnotation
-import firrtl.options.RegisteredTransform
+import firrtl.options.{RegisteredTransform, ShellOption}
import scopt.OptionParser
// Datastructures
@@ -28,24 +28,22 @@ class InlineInstances extends Transform with RegisteredTransform {
def outputForm = LowForm
private [firrtl] val inlineDelim: String = "_"
- def addOptions(parser: OptionParser[AnnotationSeq]): Unit = parser
- .opt[Seq[String]]("inline")
- .abbr("fil")
- .valueName ("<circuit>[.<module>[.<instance>]][,..],")
- .action( (x, c) => {
- val newAnnotations = x.map { value =>
- value.split('.') match {
- case Array(circuit) =>
- InlineAnnotation(CircuitName(circuit))
- case Array(circuit, module) =>
- InlineAnnotation(ModuleName(module, CircuitName(circuit)))
- case Array(circuit, module, inst) =>
- InlineAnnotation(ComponentName(inst, ModuleName(module, CircuitName(circuit))))
- }
- }
- c ++ newAnnotations :+ RunFirrtlTransformAnnotation(new InlineInstances) } )
- .text(
- """Inline one or more module (comma separated, no spaces) module looks like "MyModule" or "MyModule.myinstance""")
+ val options = Seq(
+ new ShellOption[Seq[String]](
+ longOption = "inline",
+ toAnnotationSeq = (a: Seq[String]) => a.map { value =>
+ value.split('.') match {
+ case Array(circuit) =>
+ InlineAnnotation(CircuitName(circuit))
+ case Array(circuit, module) =>
+ InlineAnnotation(ModuleName(module, CircuitName(circuit)))
+ case Array(circuit, module, inst) =>
+ InlineAnnotation(ComponentName(inst, ModuleName(module, CircuitName(circuit))))
+ }
+ } :+ RunFirrtlTransformAnnotation(new InlineInstances),
+ helpText = "Inline selected modules",
+ shortOption = Some("fil"),
+ helpValueName = Some("<circuit>[.<module>[.<instance>]][,...]") ) )
private def collectAnns(circuit: Circuit, anns: Iterable[Annotation]): (Set[ModuleName], Set[ComponentName]) =
anns.foldLeft(Set.empty[ModuleName], Set.empty[ComponentName]) {
diff --git a/src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala b/src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala
index de9f6c52..f95787bd 100644
--- a/src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala
+++ b/src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala
@@ -13,7 +13,7 @@ import ClockListUtils._
import Utils._
import memlib.AnalysisUtils._
import memlib._
-import firrtl.options.RegisteredTransform
+import firrtl.options.{RegisteredTransform, ShellOption}
import scopt.OptionParser
import firrtl.stage.RunFirrtlTransformAnnotation
@@ -60,14 +60,14 @@ class ClockListTransform extends Transform with RegisteredTransform {
def inputForm = LowForm
def outputForm = LowForm
- def addOptions(parser: OptionParser[AnnotationSeq]): Unit = parser
- .opt[String]("list-clocks")
- .abbr("clks")
- .valueName ("-c:<circuit>:-m:<module>:-o:<filename>")
- .action( (x, c) => c ++ Seq(passes.clocklist.ClockListAnnotation.parse(x),
- RunFirrtlTransformAnnotation(new ClockListTransform)) )
- .maxOccurs(1)
- .text("List which signal drives each clock of every descendent of specified module")
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "list-clocks",
+ toAnnotationSeq = (a: String) => Seq( passes.clocklist.ClockListAnnotation.parse(a),
+ RunFirrtlTransformAnnotation(new ClockListTransform) ),
+ helpText = "List which signal drives each clock of every descendent of specified modules",
+ shortOption = Some("clks"),
+ helpValueName = Some("-c:<circuit>:-m:<module>:-o:<filename>") ) )
def passSeq(top: String, writer: Writer): Seq[Pass] =
Seq(new ClockList(top, writer))
diff --git a/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala b/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala
index f524d60b..0602e4f1 100644
--- a/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala
+++ b/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala
@@ -8,7 +8,7 @@ import firrtl.ir._
import firrtl.Mappers._
import firrtl.PrimOps._
import firrtl.Utils.{one, zero, BoolType}
-import firrtl.options.HasScoptOptions
+import firrtl.options.{HasShellOptions, ShellOption}
import MemPortUtils.memPortField
import firrtl.passes.memlib.AnalysisUtils.{Connects, getConnects, getOrigin}
import WrappedExpression.weq
@@ -147,17 +147,16 @@ object InferReadWritePass extends Pass {
// Transform input: Middle Firrtl. Called after "HighFirrtlToMidleFirrtl"
// To use this transform, circuit name should be annotated with its TransId.
-class InferReadWrite extends Transform with SeqTransformBased with HasScoptOptions {
+class InferReadWrite extends Transform with SeqTransformBased with HasShellOptions {
def inputForm = MidForm
def outputForm = MidForm
- def addOptions(parser: OptionParser[AnnotationSeq]): Unit = parser
- .opt[Unit]("infer-rw")
- .abbr("firw")
- .valueName ("<circuit>")
- .action( (_, c) => Seq(InferReadWriteAnnotation, RunFirrtlTransformAnnotation(new InferReadWrite)) ++ c )
- .maxOccurs(1)
- .text("Enable readwrite port inference for the target circuit")
+ val options = Seq(
+ new ShellOption[Unit](
+ longOption = "infer-rw",
+ toAnnotationSeq = (_: Unit) => Seq(InferReadWriteAnnotation, RunFirrtlTransformAnnotation(new InferReadWrite)),
+ helpText = "Enable read/write port inference for memories",
+ shortOption = Some("firw") ) )
def transforms = Seq(
InferReadWritePass,
diff --git a/src/main/scala/firrtl/passes/memlib/MemLibOptions.scala b/src/main/scala/firrtl/passes/memlib/MemLibOptions.scala
index 2f26e4e5..4076d5d6 100644
--- a/src/main/scala/firrtl/passes/memlib/MemLibOptions.scala
+++ b/src/main/scala/firrtl/passes/memlib/MemLibOptions.scala
@@ -3,13 +3,14 @@
package firrtl.passes.memlib
import firrtl._
-import firrtl.options.RegisteredLibrary
+import firrtl.options.{RegisteredLibrary, ShellOption}
import scopt.OptionParser
class MemLibOptions extends RegisteredLibrary {
val name: String = "MemLib Options"
- def addOptions(p: OptionParser[AnnotationSeq]): Unit =
- Seq( new InferReadWrite,
- new ReplSeqMem )
- .map(_.addOptions(p))
+
+ val options: Seq[ShellOption[_]] = Seq( new InferReadWrite,
+ new ReplSeqMem )
+ .flatMap(_.options)
+
}
diff --git a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
index 32d83181..a9d0cc7c 100644
--- a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
+++ b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
@@ -6,7 +6,7 @@ package memlib
import firrtl._
import firrtl.ir._
import firrtl.annotations._
-import firrtl.options.HasScoptOptions
+import firrtl.options.{HasShellOptions, ShellOption}
import AnalysisUtils._
import Utils.error
import java.io.{File, CharArrayWriter, PrintWriter}
@@ -102,18 +102,18 @@ class SimpleTransform(p: Pass, form: CircuitForm) extends Transform {
class SimpleMidTransform(p: Pass) extends SimpleTransform(p, MidForm)
// SimpleRun instead of PassBased because of the arguments to passSeq
-class ReplSeqMem extends Transform with HasScoptOptions {
+class ReplSeqMem extends Transform with HasShellOptions {
def inputForm = MidForm
def outputForm = MidForm
- def addOptions(parser: OptionParser[AnnotationSeq]): Unit = parser
- .opt[String]("repl-seq-mem")
- .abbr("frsq")
- .valueName ("-c:<circuit>:-i:<filename>:-o:<filename>")
- .action( (x, c) => Seq(passes.memlib.ReplSeqMemAnnotation.parse(x),
- RunFirrtlTransformAnnotation(new ReplSeqMem)) ++ c )
- .maxOccurs(1)
- .text("Replace sequential memories with blackboxes + configuration file")
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "repl-seq-mem",
+ toAnnotationSeq = (a: String) => Seq( passes.memlib.ReplSeqMemAnnotation.parse(a),
+ RunFirrtlTransformAnnotation(new ReplSeqMem) ),
+ helpText = "Blackbox and emit a configuration file for each sequential memory",
+ shortOption = Some("frsq"),
+ helpValueName = Some("-c:<circuit>:-i:<file>:-o:<file>") ) )
def transforms(inConfigFile: Option[YamlFileReader], outConfigFile: ConfWriter): Seq[Transform] =
Seq(new SimpleMidTransform(Legalize),
diff --git a/src/main/scala/firrtl/stage/FirrtlAnnotations.scala b/src/main/scala/firrtl/stage/FirrtlAnnotations.scala
index 600e825b..ed5415f6 100644
--- a/src/main/scala/firrtl/stage/FirrtlAnnotations.scala
+++ b/src/main/scala/firrtl/stage/FirrtlAnnotations.scala
@@ -5,7 +5,7 @@ package firrtl.stage
import firrtl._
import firrtl.ir.Circuit
import firrtl.annotations.{Annotation, NoTargetAnnotation}
-import firrtl.options.{HasScoptOptions, OptionsException}
+import firrtl.options.{HasShellOptions, OptionsException, ShellOption}
import scopt.OptionParser
@@ -49,13 +49,16 @@ case class FirrtlFileAnnotation(file: String) extends NoTargetAnnotation with Ci
}
-object FirrtlFileAnnotation extends HasScoptOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("input-file")
- .abbr("i")
- .valueName ("<firrtl-source>")
- .action( (x, c) => FirrtlFileAnnotation(x) +: c )
- .unbounded()
- .text("use this to override the default input file name, default is empty")
+object FirrtlFileAnnotation extends HasShellOptions {
+
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "input-file",
+ toAnnotationSeq = a => Seq(FirrtlFileAnnotation(a)),
+ helpText = "An input FIRRTL file",
+ shortOption = Some("i"),
+ helpValueName = Some("<file>") ) )
+
}
/** An explicit output file the emitter will write to
@@ -64,13 +67,16 @@ object FirrtlFileAnnotation extends HasScoptOptions {
*/
case class OutputFileAnnotation(file: String) extends NoTargetAnnotation with FirrtlOption
-object OutputFileAnnotation extends HasScoptOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("output-file")
- .abbr("o")
- .valueName("<output>")
- .action( (x, c) => OutputFileAnnotation(x) +: c )
- .unbounded()
- .text("use this to override the default output file name, default is empty")
+object OutputFileAnnotation extends HasShellOptions {
+
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "output-file",
+ toAnnotationSeq = a => Seq(OutputFileAnnotation(a)),
+ helpText = "The output FIRRTL file",
+ shortOption = Some("o"),
+ helpValueName = Some("<file>") ) )
+
}
/** Sets the info mode style
@@ -97,12 +103,15 @@ case class InfoModeAnnotation(modeName: String = "use") extends NoTargetAnnotati
}
}
-object InfoModeAnnotation extends HasScoptOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("info-mode")
- .valueName ("<ignore|use|gen|append>")
- .action( (x, c) => InfoModeAnnotation(x) +: c )
- .unbounded()
- .text(s"specifies the source info handling, default is ${apply().modeName}")
+object InfoModeAnnotation extends HasShellOptions {
+
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "info-mode",
+ toAnnotationSeq = a => Seq(InfoModeAnnotation(a)),
+ helpText = s"Source file info handling mode (default: ${apply().modeName})",
+ shortOption = Some("<ignore|use|gen|append>") ) )
+
}
/** Holds a [[scala.Predef.String String]] containing FIRRTL source to read as input
@@ -116,22 +125,25 @@ case class FirrtlSourceAnnotation(source: String) extends NoTargetAnnotation wit
}
-object FirrtlSourceAnnotation extends HasScoptOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("firrtl-source")
- .valueName ("A FIRRTL string")
- .action( (x, c) => FirrtlSourceAnnotation(x) +: c )
- .unbounded()
- .text(s"A FIRRTL circuit as a string")
+object FirrtlSourceAnnotation extends HasShellOptions {
+
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "firrtl-source",
+ toAnnotationSeq = a => Seq(FirrtlSourceAnnotation(a)),
+ helpText = "An input FIRRTL circuit string",
+ shortOption = Some("<string>") ) )
+
}
-/** Holds a [[Compiler]] that should be run
+/** helpValueName a [[Compiler]] that should be run
* - set stringly with `-X/--compiler`
* - If unset, a [[CompilerAnnotation]] with the default [[VerilogCompiler]]
* @param compiler compiler name
*/
case class CompilerAnnotation(compiler: Compiler = new VerilogCompiler()) extends NoTargetAnnotation with FirrtlOption
-object CompilerAnnotation extends HasScoptOptions {
+object CompilerAnnotation extends HasShellOptions {
private [firrtl] def apply(compilerName: String): CompilerAnnotation = {
val c = compilerName match {
@@ -147,12 +159,14 @@ object CompilerAnnotation extends HasScoptOptions {
CompilerAnnotation(c)
}
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("compiler")
- .abbr("X")
- .valueName ("<none|high|middle|low|verilog|mverilog|sverilog>")
- .action{ (x, c) => CompilerAnnotation(x) +: c }
- .unbounded()
- .text(s"compiler to use, default is 'verilog'")
+ val options = Seq(
+ new ShellOption[String](
+ longOption = "compiler",
+ toAnnotationSeq = a => Seq(CompilerAnnotation(a)),
+ helpText = "The FIRRTL compiler to use (default: verilog)",
+ shortOption = Some("X"),
+ helpValueName = Some("<none|high|middle|low|verilog|mverilog|sverilog>") ) )
+
}
/** Holds the unambiguous class name of a [[Transform]] to run
@@ -162,27 +176,26 @@ object CompilerAnnotation extends HasScoptOptions {
*/
case class RunFirrtlTransformAnnotation(transform: Transform) extends NoTargetAnnotation
-object RunFirrtlTransformAnnotation extends HasScoptOptions {
- def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[Seq[String]]("custom-transforms")
- .abbr("fct")
- .valueName ("<package>.<class>")
- .validate( x => {
- x.map(txName =>
- try { Class.forName(txName).asInstanceOf[Class[_ <: Transform]].newInstance() }
- catch {
- case e: ClassNotFoundException => throw new OptionsException(
- s"Unable to locate custom transform $txName (did you misspell it?)", e)
- case e: InstantiationException => throw new OptionsException(
- s"Unable to create instance of Transform $txName (is this an anonymous class?)", e)
- case e: Throwable => throw new OptionsException(
- s"Unknown error when instantiating class $txName", e) } )
- p.success } )
- .action( (x, c) =>
- x.map(txName =>
- RunFirrtlTransformAnnotation(Class.forName(txName).asInstanceOf[Class[_ <: Transform]].newInstance()))
- .reverse ++ c )
- .unbounded()
- .text("runs these custom transforms during compilation.")
+object RunFirrtlTransformAnnotation extends HasShellOptions {
+
+ val options = Seq(
+ new ShellOption[Seq[String]](
+ longOption = "custom-transforms",
+ toAnnotationSeq = _.map(txName =>
+ try {
+ val tx = Class.forName(txName).asInstanceOf[Class[_ <: Transform]].newInstance()
+ RunFirrtlTransformAnnotation(tx)
+ } catch {
+ case e: ClassNotFoundException => throw new OptionsException(
+ s"Unable to locate custom transform $txName (did you misspell it?)", e)
+ case e: InstantiationException => throw new OptionsException(
+ s"Unable to create instance of Transform $txName (is this an anonymous class?)", e)
+ case e: Throwable => throw new OptionsException(
+ s"Unknown error when instantiating class $txName", e) }),
+ helpText = "Run these transforms during compilation",
+ shortOption = Some("fct"),
+ helpValueName = Some("<package>.<class>") ) )
+
}
/** Holds a FIRRTL [[firrtl.ir.Circuit Circuit]]
diff --git a/src/main/scala/firrtl/stage/FirrtlStage.scala b/src/main/scala/firrtl/stage/FirrtlStage.scala
index e4620913..5d121322 100644
--- a/src/main/scala/firrtl/stage/FirrtlStage.scala
+++ b/src/main/scala/firrtl/stage/FirrtlStage.scala
@@ -3,7 +3,8 @@
package firrtl.stage
import firrtl.{AnnotationSeq, CustomTransformException, FIRRTLException, Utils}
-import firrtl.options.{Phase, PhaseException, Shell, Stage, StageMain, OptionsException}
+import firrtl.options.{Stage, Phase, PhaseException, Shell, OptionsException, StageMain}
+import firrtl.options.phases.DeletedWrapper
import firrtl.passes.{PassException, PassExceptions}
import scala.util.control.ControlThrowable
@@ -13,18 +14,18 @@ import java.io.PrintWriter
class FirrtlStage extends Stage {
val shell: Shell = new Shell("firrtl") with FirrtlCli
- private val phases: Seq[Phase] = Seq(
- new firrtl.stage.phases.AddDefaults,
- new firrtl.stage.phases.AddImplicitEmitter,
- new firrtl.stage.phases.Checks,
- new firrtl.stage.phases.AddCircuit,
- new firrtl.stage.phases.AddImplicitOutputFile,
- new firrtl.stage.phases.Compiler,
- new firrtl.stage.phases.WriteEmitted
- )
+ private val phases: Seq[Phase] =
+ Seq( new firrtl.stage.phases.AddDefaults,
+ new firrtl.stage.phases.AddImplicitEmitter,
+ new firrtl.stage.phases.Checks,
+ new firrtl.stage.phases.AddCircuit,
+ new firrtl.stage.phases.AddImplicitOutputFile,
+ new firrtl.stage.phases.Compiler,
+ new firrtl.stage.phases.WriteEmitted )
+ .map(DeletedWrapper(_))
def run(annotations: AnnotationSeq): AnnotationSeq = try {
- phases.foldLeft(annotations)((a, f) => f.runTransform(a))
+ phases.foldLeft(annotations)((a, f) => f.transform(a))
} catch {
/* Rethrow the exceptions which are expected or due to the runtime environment (out of memory, stack overflow, etc.).
* Any UNEXPECTED exceptions should be treated as internal errors. */
diff --git a/src/main/scala/firrtl/stage/phases/DriverCompatibility.scala b/src/main/scala/firrtl/stage/phases/DriverCompatibility.scala
index 310e0bd4..cb6a135d 100644
--- a/src/main/scala/firrtl/stage/phases/DriverCompatibility.scala
+++ b/src/main/scala/firrtl/stage/phases/DriverCompatibility.scala
@@ -7,8 +7,8 @@ import firrtl.stage._
import firrtl.{AnnotationSeq, EmitAllModulesAnnotation, EmitCircuitAnnotation, FirrtlExecutionResult, Parser}
import firrtl.annotations.NoTargetAnnotation
import firrtl.proto.FromProto
-import firrtl.options.{HasScoptOptions, InputAnnotationFileAnnotation, OptionsException, Phase, StageOptions,
- StageUtils}
+import firrtl.options.{HasShellOptions, InputAnnotationFileAnnotation, OptionsException, Phase, ShellOption,
+ StageOptions, StageUtils}
import firrtl.options.Viewer
import scopt.OptionParser
@@ -49,7 +49,8 @@ object DriverCompatibility {
@deprecated(""""top-name" is deprecated as part of the Stage/Phase refactor. Use explicit input/output files.""", "1.2")
case class TopNameAnnotation(topName: String) extends NoTargetAnnotation
- object TopNameAnnotation extends HasScoptOptions {
+ object TopNameAnnotation {
+
def addOptions(p: OptionParser[AnnotationSeq]): Unit = p
.opt[Unit]("top-name")
.abbr("tn")
diff --git a/src/main/scala/firrtl/transforms/CheckCombLoops.scala b/src/main/scala/firrtl/transforms/CheckCombLoops.scala
index 0a9ec0e3..17e1569b 100644
--- a/src/main/scala/firrtl/transforms/CheckCombLoops.scala
+++ b/src/main/scala/firrtl/transforms/CheckCombLoops.scala
@@ -17,7 +17,7 @@ import firrtl.annotations._
import firrtl.Utils.throwInternalError
import firrtl.graph.{MutableDiGraph,DiGraph}
import firrtl.analyses.InstanceGraph
-import firrtl.options.RegisteredTransform
+import firrtl.options.{RegisteredTransform, ShellOption}
import scopt.OptionParser
object CheckCombLoops {
@@ -69,11 +69,11 @@ class CheckCombLoops extends Transform with RegisteredTransform {
import CheckCombLoops._
- def addOptions(parser: OptionParser[AnnotationSeq]): Unit = parser
- .opt[Unit]("no-check-comb-loops")
- .action( (x, c) => c :+ DontCheckCombLoopsAnnotation )
- .maxOccurs(1)
- .text("Do NOT check for combinational loops (not recommended)")
+ val options = Seq(
+ new ShellOption[Unit](
+ longOption = "no-check-comb-loops",
+ toAnnotationSeq = (_: Unit) => Seq(DontCheckCombLoopsAnnotation),
+ helpText = "Disable combinational loop checking" ) )
/*
* A case class that represents a net in the circuit. This is
diff --git a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
index deb7299d..0c357267 100644
--- a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
+++ b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
@@ -11,7 +11,7 @@ import firrtl.Mappers._
import firrtl.WrappedExpression._
import firrtl.Utils.{throwInternalError, toWrappedExpression, kind}
import firrtl.MemoizedHash._
-import firrtl.options.RegisteredTransform
+import firrtl.options.{RegisteredTransform, ShellOption}
import scopt.OptionParser
import collection.mutable
@@ -36,11 +36,11 @@ class DeadCodeElimination extends Transform with ResolvedAnnotationPaths with Re
def inputForm = LowForm
def outputForm = LowForm
- def addOptions(parser: OptionParser[AnnotationSeq]): Unit = parser
- .opt[Unit]("no-dce")
- .action( (x, c) => c :+ NoDCEAnnotation )
- .maxOccurs(1)
- .text("Do NOT run dead code elimination")
+ val options = Seq(
+ new ShellOption[Unit](
+ longOption = "no-dce",
+ toAnnotationSeq = (_: Unit) => Seq(NoDCEAnnotation),
+ helpText = "Disable dead code elimination" ) )
/** Based on LogicNode ins CheckCombLoops, currently kind of faking it */
private type LogicNode = MemoizedHash[WrappedExpression]