aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSchuyler Eldridge2018-11-07 15:30:17 -0500
committerGitHub2018-11-07 15:30:17 -0500
commit75284395ba7ef285daefd2da38e720590b465ad7 (patch)
tree7ae4e04a16eb87ce306a9d891acabbd4c6b1c8b7
parent17b4e9835bd95dcf91c5ea5a4d7c52280031ea93 (diff)
parentb05eaea3e59c64d619a544c63311d510f335f7e5 (diff)
Merge pull request #919 from seldridge/f764.6
- Add, but do not use Options-mirroring Annotations
-rw-r--r--src/main/resources/META-INF/services/firrtl.options.RegisteredLibrary1
-rw-r--r--src/main/resources/META-INF/services/firrtl.options.RegisteredTransform4
-rw-r--r--src/main/scala/firrtl/Driver.scala1
-rw-r--r--src/main/scala/firrtl/ExecutionOptionsManager.scala3
-rw-r--r--src/main/scala/firrtl/annotations/JsonProtocol.scala13
-rw-r--r--src/main/scala/firrtl/package.scala4
-rw-r--r--src/main/scala/firrtl/passes/Inline.scala24
-rw-r--r--src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala15
-rw-r--r--src/main/scala/firrtl/passes/memlib/InferReadWrite.scala19
-rw-r--r--src/main/scala/firrtl/passes/memlib/MemLibOptions.scala15
-rw-r--r--src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala19
-rw-r--r--src/main/scala/firrtl/stage/FirrtlAnnotations.scala290
-rw-r--r--src/main/scala/firrtl/transforms/CheckCombLoops.scala10
-rw-r--r--src/main/scala/firrtl/transforms/DeadCodeElimination.scala10
-rw-r--r--src/test/scala/firrtlTests/annotationTests/TargetDirAnnotationSpec.scala1
15 files changed, 415 insertions, 14 deletions
diff --git a/src/main/resources/META-INF/services/firrtl.options.RegisteredLibrary b/src/main/resources/META-INF/services/firrtl.options.RegisteredLibrary
new file mode 100644
index 00000000..abfcceb0
--- /dev/null
+++ b/src/main/resources/META-INF/services/firrtl.options.RegisteredLibrary
@@ -0,0 +1 @@
+firrtl.passes.memlib.MemLibOptions
diff --git a/src/main/resources/META-INF/services/firrtl.options.RegisteredTransform b/src/main/resources/META-INF/services/firrtl.options.RegisteredTransform
new file mode 100644
index 00000000..638404be
--- /dev/null
+++ b/src/main/resources/META-INF/services/firrtl.options.RegisteredTransform
@@ -0,0 +1,4 @@
+firrtl.transforms.DeadCodeElimination
+firrtl.transforms.CheckCombLoops
+firrtl.passes.InlineInstances
+firrtl.passes.clocklist.ClockListTransform
diff --git a/src/main/scala/firrtl/Driver.scala b/src/main/scala/firrtl/Driver.scala
index d96bb903..47841cec 100644
--- a/src/main/scala/firrtl/Driver.scala
+++ b/src/main/scala/firrtl/Driver.scala
@@ -17,6 +17,7 @@ import firrtl.annotations.AnnotationYamlProtocol._
import firrtl.passes.{PassException, PassExceptions}
import firrtl.transforms._
import firrtl.Utils.throwInternalError
+import firrtl.stage.TargetDirAnnotation
/**
diff --git a/src/main/scala/firrtl/ExecutionOptionsManager.scala b/src/main/scala/firrtl/ExecutionOptionsManager.scala
index 1754338c..2f7178bb 100644
--- a/src/main/scala/firrtl/ExecutionOptionsManager.scala
+++ b/src/main/scala/firrtl/ExecutionOptionsManager.scala
@@ -68,9 +68,6 @@ case class CommonOptions(
}
}
-/** Annotation that contains the [[CommonOptions]] target directory */
-case class TargetDirAnnotation(value: String) extends NoTargetAnnotation
-
trait HasCommonOptions {
self: ExecutionOptionsManager =>
var commonOptions = CommonOptions()
diff --git a/src/main/scala/firrtl/annotations/JsonProtocol.scala b/src/main/scala/firrtl/annotations/JsonProtocol.scala
index 36699151..acb2d957 100644
--- a/src/main/scala/firrtl/annotations/JsonProtocol.scala
+++ b/src/main/scala/firrtl/annotations/JsonProtocol.scala
@@ -34,6 +34,17 @@ object JsonProtocol {
{ case JString(s) => AnnotationUtils.toNamed(s).asInstanceOf[ComponentName] },
{ case named: ComponentName => JString(named.serialize) }
))
+ class TransformSerializer extends CustomSerializer[Transform](format => (
+ { case JString(s) =>
+ try {
+ Class.forName(s).asInstanceOf[Class[_ <: Transform]].newInstance()
+ } catch {
+ case e: java.lang.InstantiationException => throw new FIRRTLException(
+ "NoSuchMethodException during construction of serialized Transform. Is your Transform an inner class?", e)
+ case t: Throwable => throw t
+ }},
+ { case x: Transform => JString(x.getClass.getName) }
+ ))
class TargetSerializer extends CustomSerializer[Target](format => (
@@ -67,7 +78,7 @@ object JsonProtocol {
new TransformClassSerializer + new NamedSerializer + new CircuitNameSerializer +
new ModuleNameSerializer + new ComponentNameSerializer + new TargetSerializer +
new GenericTargetSerializer + new CircuitTargetSerializer + new ModuleTargetSerializer +
- new InstanceTargetSerializer + new ReferenceTargetSerializer
+ new InstanceTargetSerializer + new ReferenceTargetSerializer + new TransformSerializer
}
/** Serialize annotations to a String for emission */
diff --git a/src/main/scala/firrtl/package.scala b/src/main/scala/firrtl/package.scala
index c0b79462..9b7fce38 100644
--- a/src/main/scala/firrtl/package.scala
+++ b/src/main/scala/firrtl/package.scala
@@ -5,4 +5,8 @@ import firrtl.annotations.Annotation
package object firrtl {
implicit def seqToAnnoSeq(xs: Seq[Annotation]) = AnnotationSeq(xs)
implicit def annoSeqToSeq(as: AnnotationSeq): Seq[Annotation] = as.underlying
+
+ /* Options as annotations compatibility items */
+ @deprecated("Use firrtl.stage.TargetDirAnnotation", "3.2")
+ val TargetDirAnnotation = firrtl.stage.TargetDirAnnotation
}
diff --git a/src/main/scala/firrtl/passes/Inline.scala b/src/main/scala/firrtl/passes/Inline.scala
index feda80f2..dcee0ee2 100644
--- a/src/main/scala/firrtl/passes/Inline.scala
+++ b/src/main/scala/firrtl/passes/Inline.scala
@@ -7,6 +7,9 @@ import firrtl.ir._
import firrtl.Mappers._
import firrtl.annotations._
import firrtl.analyses.InstanceGraph
+import firrtl.stage.RunFirrtlTransformAnnotation
+import firrtl.options.RegisteredTransform
+import scopt.OptionParser
// Datastructures
import scala.collection.mutable
@@ -20,11 +23,30 @@ case class InlineAnnotation(target: Named) extends SingleTargetAnnotation[Named]
* @note Only use on legal Firrtl. Specifically, the restriction of instance loops must have been checked, or else this
* pass can infinitely recurse.
*/
-class InlineInstances extends Transform {
+class InlineInstances extends Transform with RegisteredTransform {
def inputForm = LowForm
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""")
+
private def collectAnns(circuit: Circuit, anns: Iterable[Annotation]): (Set[ModuleName], Set[ComponentName]) =
anns.foldLeft(Set.empty[ModuleName], Set.empty[ComponentName]) {
case ((modNames, instNames), ann) => ann match {
diff --git a/src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala b/src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala
index 6c7b2e18..8d70f211 100644
--- a/src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala
+++ b/src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala
@@ -14,6 +14,9 @@ import Utils._
import memlib.AnalysisUtils._
import memlib._
import Mappers._
+import firrtl.options.RegisteredTransform
+import scopt.OptionParser
+import firrtl.stage.RunFirrtlTransformAnnotation
case class ClockListAnnotation(target: ModuleName, outputConfig: String) extends
SingleTargetAnnotation[ModuleName] {
@@ -54,9 +57,19 @@ Usage:
}
}
-class ClockListTransform extends Transform {
+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")
+
def passSeq(top: String, writer: Writer): Seq[Pass] =
Seq(new ClockList(top, writer))
def execute(state: CircuitState): CircuitState = {
diff --git a/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala b/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala
index 2d1d7f6b..3494de45 100644
--- a/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala
+++ b/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala
@@ -8,10 +8,14 @@ import firrtl.ir._
import firrtl.Mappers._
import firrtl.PrimOps._
import firrtl.Utils.{one, zero, BoolType}
+import firrtl.options.HasScoptOptions
import MemPortUtils.memPortField
import firrtl.passes.memlib.AnalysisUtils.{Connects, getConnects, getOrigin}
import WrappedExpression.weq
import annotations._
+import scopt.OptionParser
+import firrtl.stage.RunFirrtlTransformAnnotation
+
case object InferReadWriteAnnotation extends NoTargetAnnotation
@@ -72,10 +76,10 @@ object InferReadWritePass extends Pass {
def replaceStmt(repl: Netlist)(s: Statement): Statement =
s map replaceStmt(repl) map replaceExp(repl) match {
- case Connect(_, EmptyExpression, _) => EmptyStmt
+ case Connect(_, EmptyExpression, _) => EmptyStmt
case sx => sx
}
-
+
def inferReadWriteStmt(connects: Connects,
repl: Netlist,
stmts: Statements)
@@ -143,9 +147,18 @@ 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 {
+class InferReadWrite extends Transform with SeqTransformBased with HasScoptOptions {
def inputForm = MidForm
def outputForm = MidForm
+
+ def addOptions(parser: OptionParser[AnnotationSeq]): Unit = parser
+ .opt[Unit]("infer-rw")
+ .abbr("firw")
+ .valueName ("<circuit>")
+ .action( (_, c) => c ++ Seq(InferReadWriteAnnotation, RunFirrtlTransformAnnotation(new InferReadWrite)) )
+ .maxOccurs(1)
+ .text("Enable readwrite port inference for the target circuit")
+
def transforms = Seq(
InferReadWritePass,
CheckInitialization,
diff --git a/src/main/scala/firrtl/passes/memlib/MemLibOptions.scala b/src/main/scala/firrtl/passes/memlib/MemLibOptions.scala
new file mode 100644
index 00000000..2f26e4e5
--- /dev/null
+++ b/src/main/scala/firrtl/passes/memlib/MemLibOptions.scala
@@ -0,0 +1,15 @@
+// See LICENSE for license details.
+
+package firrtl.passes.memlib
+
+import firrtl._
+import firrtl.options.RegisteredLibrary
+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))
+}
diff --git a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
index 311813db..f2e6cd4e 100644
--- a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
+++ b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
@@ -6,10 +6,13 @@ package memlib
import firrtl._
import firrtl.ir._
import firrtl.annotations._
+import firrtl.options.HasScoptOptions
import AnalysisUtils._
import Utils.error
import java.io.{File, CharArrayWriter, PrintWriter}
import wiring._
+import scopt.OptionParser
+import firrtl.stage.RunFirrtlTransformAnnotation
sealed trait PassOption
case object InputConfigFileName extends PassOption
@@ -19,11 +22,11 @@ case object PassModuleName extends PassOption
object PassConfigUtil {
type PassOptionMap = Map[PassOption, String]
-
+
def getPassOptions(t: String, usage: String = "") = {
// can't use space to delimit sub arguments (otherwise, Driver.scala will throw error)
val passArgList = t.split(":").toList
-
+
def nextPassOption(map: PassOptionMap, list: List[String]): PassOptionMap = {
list match {
case Nil => map
@@ -103,9 +106,19 @@ 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 {
+class ReplSeqMem extends Transform with HasScoptOptions {
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) => c ++ Seq(passes.memlib.ReplSeqMemAnnotation.parse(x),
+ RunFirrtlTransformAnnotation(new ReplSeqMem)) )
+ .maxOccurs(1)
+ .text("Replace sequential memories with blackboxes + configuration file")
+
def transforms(inConfigFile: Option[YamlFileReader], outConfigFile: ConfWriter): Seq[Transform] =
Seq(new SimpleMidTransform(Legalize),
new SimpleMidTransform(ToMemIR),
diff --git a/src/main/scala/firrtl/stage/FirrtlAnnotations.scala b/src/main/scala/firrtl/stage/FirrtlAnnotations.scala
new file mode 100644
index 00000000..e13daf79
--- /dev/null
+++ b/src/main/scala/firrtl/stage/FirrtlAnnotations.scala
@@ -0,0 +1,290 @@
+// See LICENSE for license details
+
+package firrtl.stage
+
+import firrtl._
+import firrtl.ir.Circuit
+import firrtl.annotations.NoTargetAnnotation
+import firrtl.transforms.BlackBoxTargetDirAnno
+import firrtl.options.HasScoptOptions
+
+import logger.LogLevel
+
+import scopt.OptionParser
+
+/** Indicates that a subclass is an [[firrtl.annotations Annotation]] that includes a command line option
+ *
+ * This must be mixed into a subclass of [[annotations.Annotation]]
+ */
+sealed trait FirrtlOption extends HasScoptOptions
+
+/** Holds the name of the top module
+ * - set on the command line with `-tn/--top-name`
+ * @param value top module name
+ */
+case class TopNameAnnotation(topName: String) extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("top-name")
+ .abbr("tn")
+ .valueName("<top-level-circuit-name>")
+ .action( (x, c) => c :+ TopNameAnnotation(x) )
+ .unbounded() // See [Note 1]
+ .text("This options defines the top level circuit, defaults to dut when possible")
+}
+
+object TopNameAnnotation {
+ private [firrtl] def apply(): TopNameAnnotation = TopNameAnnotation(topName = "")
+}
+
+/** Holds the name of the target directory
+ * - set with `-td/--target-dir`
+ * - if unset, a [[TargetDirAnnotation]] will be generated with the
+ * @param value target directory name
+ */
+case class TargetDirAnnotation(targetDirName: String = ".") extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("target-dir")
+ .abbr("td")
+ .valueName("<target-directory>")
+ .action( (x, c) => c ++ Seq(TargetDirAnnotation(x)) )
+ .unbounded() // See [Note 1]
+ .text(s"Work directory for intermediate files/blackboxes, default is ${CommonOptions().targetDirName}")
+}
+
+/** Describes the verbosity of information to log
+ * - set with `-ll/--log-level`
+ * - if unset, a [[LogLevelAnnotation]] with the default log level will be emitted
+ * @param level the level of logging
+ */
+case class LogLevelAnnotation(globalLogLevel: LogLevel.Value = LogLevel.None) extends NoTargetAnnotation with FirrtlOption {
+ val value = globalLogLevel.toString
+
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("log-level")
+ .abbr("ll")
+ .valueName("<Error|Warn|Info|Debug|Trace>")
+ .action( (x, c) => c :+ LogLevelAnnotation(LogLevel(x)) )
+ .validate{ x =>
+ lazy val msg = s"$x bad value must be one of error|warn|info|debug|trace"
+ if (Array("error", "warn", "info", "debug", "trace").contains(x.toLowerCase)) { p.success }
+ else { p.failure(msg) }}
+ .unbounded() // See [Note 1]
+ .text(s"Sets the verbosity level of logging, default is ${CommonOptions().globalLogLevel}")
+}
+
+/** Describes a mapping of a class to a specific log level
+ * - set with `-cll/--class-log-level`
+ * @param name the class name to log
+ * @param level the verbosity level
+ */
+case class ClassLogLevelAnnotation(className: String, level: LogLevel.Value) extends NoTargetAnnotation
+ with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[Seq[String]]("class-log-level")
+ .abbr("cll")
+ .valueName("<FullClassName:[Error|Warn|Info|Debug|Trace]>[,...]")
+ .action( (x, c) => c ++ (x.map { y =>
+ val className :: levelName :: _ = y.split(":").toList
+ val level = LogLevel(levelName)
+ ClassLogLevelAnnotation(className, level) }) )
+ .unbounded() // This can actually occur any number of times safely
+ .text(s"This defines per-class verbosity of logging")
+}
+
+object ClassLogLevelAnnotation {
+ private [firrtl] def apply(): ClassLogLevelAnnotation = ClassLogLevelAnnotation("", LogLevel.None)
+}
+
+/** Enables logging to a file (as opposed to STDOUT)
+ * - enabled with `-ltf/--log-to-file`
+ */
+case object LogToFileAnnotation extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[Unit]("log-to-file")
+ .abbr("ltf")
+ .action( (x, c) => c :+ LogToFileAnnotation )
+ .unbounded()
+ .text(s"default logs to stdout, this flags writes to topName.log or firrtl.log if no topName")
+}
+
+/** Enables class names in log output
+ * - enabled with `-lcn/--log-class-names`
+ */
+case object LogClassNamesAnnotation extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[Unit]("log-class-names")
+ .abbr("lcn")
+ .action( (x, c) => c :+ LogClassNamesAnnotation )
+ .unbounded()
+ .text(s"shows class names and log level in logging output, useful for target --class-log-level")
+}
+
+/** Additional arguments
+ * - set with any trailing option on the command line
+ * @param value one [[scala.String]] argument
+ */
+case class ProgramArgsAnnotation(value: String) extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.arg[String]("<arg>...")
+ .unbounded()
+ .optional()
+ .action( (x, c) => c :+ ProgramArgsAnnotation(x) )
+ .text("optional unbounded args")
+}
+
+object ProgramArgsAnnotation {
+ private [firrtl] def apply(): ProgramArgsAnnotation = ProgramArgsAnnotation("")
+}
+
+/** An explicit input FIRRTL file to read
+ * - set with `-i/--input-file`
+ * - If unset, an [[InputFileAnnotation]] with the default input file __will not be generated__
+ * @param value input filename
+ */
+case class InputFileAnnotation(value: String) extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("input-file")
+ .abbr("i")
+ .valueName ("<firrtl-source>")
+ .action( (x, c) => c :+ InputFileAnnotation(x) )
+ .unbounded() // See [Note 1]
+ .text("use this to override the default input file name, default is empty")
+}
+
+object InputFileAnnotation {
+ private [firrtl] def apply(): InputFileAnnotation = InputFileAnnotation("")
+}
+
+/** An explicit output file the emitter will write to
+ * - set with `-o/--output-file`
+ * @param value output filename
+ */
+case class OutputFileAnnotation(value: String) extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("output-file")
+ .abbr("o")
+ .valueName("<output>")
+ .action( (x, c) => c :+ OutputFileAnnotation(x) )
+ .unbounded()
+ .text("use this to override the default output file name, default is empty")
+}
+
+object OutputFileAnnotation {
+ private [firrtl] def apply(): OutputFileAnnotation = OutputFileAnnotation("")
+}
+
+/** An explicit output _annotation_ file to write to
+ * - set with `-foaf/--output-annotation-file`
+ * @param value output annotation filename
+ */
+case class OutputAnnotationFileAnnotation(value: String) extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("output-annotation-file")
+ .abbr("foaf")
+ .valueName ("<output-anno-file>")
+ .action( (x, c) => c :+ OutputAnnotationFileAnnotation(x) )
+ .unbounded() // See [Note 1]
+ .text("use this to set the annotation output file")
+}
+
+object OutputAnnotationFileAnnotation {
+ private [firrtl] def apply(): OutputAnnotationFileAnnotation = OutputAnnotationFileAnnotation("")
+}
+
+/** Sets the info mode style
+ * - set with `--info-mode`
+ * @param value info mode name
+ */
+case class InfoModeAnnotation(value: String = "append") extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("info-mode")
+ .valueName ("<ignore|use|gen|append>")
+ .action( (x, c) => c :+ InfoModeAnnotation(x.toLowerCase) )
+ .unbounded() // See [Note 1]
+ .text(s"specifies the source info handling, default is ${FirrtlExecutionOptions().infoModeName}")
+}
+
+/** Holds a [[scala.String]] containing FIRRTL source to read as input
+ * - set with `--firrtl-source`
+ * @param value FIRRTL source as a [[scala.String]]
+ */
+case class FirrtlSourceAnnotation(value: String) extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("firrtl-source")
+ .valueName ("A FIRRTL string")
+ .action( (x, c) => c :+ FirrtlSourceAnnotation(x) )
+ .unbounded() // See [Note 1]
+ .text(s"A FIRRTL circuit as a string")
+}
+
+object FirrtlSourceAnnotation {
+ private [firrtl] def apply(): FirrtlSourceAnnotation = FirrtlSourceAnnotation("")
+}
+
+/** Indicates that an emitted circuit (FIRRTL, Verilog, etc.) will be one file per module
+ * - set with `--split-modules`
+ */
+case object EmitOneFilePerModuleAnnotation extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[Unit]("split-modules")
+ .abbr("fsm")
+ .action( (x, c) => c :+ EmitOneFilePerModuleAnnotation )
+ .unbounded()
+ .text ("Emit each module to its own file in the target directory.")
+}
+
+/** Holds a filename containing one or more [[annotations.Annotation]] to be read
+ * - this is not stored in [[FirrtlExecutionOptions]]
+ * - set with `-faf/--annotation-file`
+ * @param value input annotation filename
+ */
+case class InputAnnotationFileAnnotation(value: String) extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("annotation-file")
+ .abbr("faf")
+ .unbounded()
+ .valueName("<input-anno-file>")
+ .action( (x, c) => c :+ InputAnnotationFileAnnotation(x) )
+ .text("Used to specify annotation file")
+}
+
+object InputAnnotationFileAnnotation {
+ private [firrtl] def apply(): InputAnnotationFileAnnotation = InputAnnotationFileAnnotation("")
+}
+
+/** Holds the name of the compiler to run
+ * - set with `-X/--compiler`
+ * - If unset, a [[CompilerNameAnnotation]] with the default compiler ("verilog") __will be generated__
+ * @param value compiler name
+ */
+case class CompilerNameAnnotation(value: String = "verilog") extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = p.opt[String]("compiler")
+ .abbr("X")
+ .valueName ("<high|middle|low|verilog|sverilog>")
+ .action( (x, c) => c :+ CompilerNameAnnotation(x) )
+ .unbounded() // See [Note 1]
+ .text(s"compiler to use, default is 'verilog'")
+}
+
+/** Holds the unambiguous class name of a [[Transform]] to run
+ * - will be append to [[FirrtlExecutionOptions.customTransforms]]
+ * - set with `-fct/--custom-transforms`
+ * @param value the full class name of the transform
+ */
+case class RunFirrtlTransformAnnotation(transform: Transform) extends NoTargetAnnotation with FirrtlOption {
+ 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 FIRRTLException(
+ s"Unable to locate custom transform $txName (did you misspell it?)", e)
+ case e: InstantiationException => throw new FIRRTLException(
+ s"Unable to create instance of Transform $txName (is this an anonymous class?)", e)
+ case e: Throwable => throw new FIRRTLException(
+ s"Unknown error when instantiating class $txName", e) } )
+ p.success } )
+ .action( (x, c) => c ++ x.map(txName =>
+ RunFirrtlTransformAnnotation(Class.forName(txName).asInstanceOf[Class[_ <: Transform]].newInstance())) )
+ .unbounded()
+ .text("runs these custom transforms during compilation.")
+}
+
+object RunFirrtlTransformAnnotation {
+ private [firrtl] def apply(): RunFirrtlTransformAnnotation = RunFirrtlTransformAnnotation(new firrtl.transforms.VerilogRename)
+}
+
+/** Holds a FIRRTL [[Circuit]]
+ * @param value a circuit
+ */
+case class FirrtlCircuitAnnotation(value: Circuit) extends NoTargetAnnotation with FirrtlOption {
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit = Unit
+}
diff --git a/src/main/scala/firrtl/transforms/CheckCombLoops.scala b/src/main/scala/firrtl/transforms/CheckCombLoops.scala
index 44785c62..1a5861c5 100644
--- a/src/main/scala/firrtl/transforms/CheckCombLoops.scala
+++ b/src/main/scala/firrtl/transforms/CheckCombLoops.scala
@@ -15,6 +15,8 @@ import firrtl.annotations._
import firrtl.Utils.throwInternalError
import firrtl.graph.{MutableDiGraph,DiGraph}
import firrtl.analyses.InstanceGraph
+import firrtl.options.RegisteredTransform
+import scopt.OptionParser
object CheckCombLoops {
class CombLoopException(info: Info, mname: String, cycle: Seq[String]) extends PassException(
@@ -42,12 +44,18 @@ case class CombinationalPath(sink: ComponentName, sources: Seq[ComponentName]) e
* @note The pass cannot find loops that pass through ExtModules
* @note The pass will throw exceptions on "false paths"
*/
-class CheckCombLoops extends Transform {
+class CheckCombLoops extends Transform with RegisteredTransform {
def inputForm = LowForm
def outputForm = LowForm
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)")
+
/*
* A case class that represents a net in the circuit. This is
* necessary since combinational loop checking is an analysis on the
diff --git a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
index 523c997b..8f9fad46 100644
--- a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
+++ b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
@@ -11,6 +11,8 @@ import firrtl.Mappers._
import firrtl.WrappedExpression._
import firrtl.Utils.{throwInternalError, toWrappedExpression, kind}
import firrtl.MemoizedHash._
+import firrtl.options.RegisteredTransform
+import scopt.OptionParser
import collection.mutable
import java.io.{File, FileWriter}
@@ -30,10 +32,16 @@ import java.io.{File, FileWriter}
* circumstances of their instantiation in their parent module, they will still not be removed. To
* remove such modules, use the [[NoDedupAnnotation]] to prevent deduplication.
*/
-class DeadCodeElimination extends Transform with ResolvedAnnotationPaths {
+class DeadCodeElimination extends Transform with ResolvedAnnotationPaths with RegisteredTransform {
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")
+
/** Based on LogicNode ins CheckCombLoops, currently kind of faking it */
private type LogicNode = MemoizedHash[WrappedExpression]
private object LogicNode {
diff --git a/src/test/scala/firrtlTests/annotationTests/TargetDirAnnotationSpec.scala b/src/test/scala/firrtlTests/annotationTests/TargetDirAnnotationSpec.scala
index eb061d8f..8f157131 100644
--- a/src/test/scala/firrtlTests/annotationTests/TargetDirAnnotationSpec.scala
+++ b/src/test/scala/firrtlTests/annotationTests/TargetDirAnnotationSpec.scala
@@ -5,6 +5,7 @@ package annotationTests
import firrtlTests._
import firrtl._
+import firrtl.stage.TargetDirAnnotation
/** Looks for [[TargetDirAnnotation]] */
class FindTargetDirTransform(expected: String) extends Transform {