aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorSchuyler Eldridge2018-08-22 16:39:07 -0400
committerSchuyler Eldridge2018-11-07 13:49:16 -0500
commit61ab5a323da77dd03a24cfda3948830c3bb286c9 (patch)
tree2ca1c57d67c571b1a414849c9c55aac4d44d44fd /src/main
parent17b4e9835bd95dcf91c5ea5a4d7c52280031ea93 (diff)
Add FirrtlOptions
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@ibm.com>
Diffstat (limited to 'src/main')
-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/clocklist/ClockListTransform.scala3
-rw-r--r--src/main/scala/firrtl/passes/memlib/InferReadWrite.scala6
-rw-r--r--src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala6
-rw-r--r--src/main/scala/firrtl/stage/FirrtlAnnotations.scala290
8 files changed, 318 insertions, 8 deletions
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/clocklist/ClockListTransform.scala b/src/main/scala/firrtl/passes/clocklist/ClockListTransform.scala
index 6c7b2e18..6b265239 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] {
diff --git a/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala b/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala
index 2d1d7f6b..c83194e8 100644
--- a/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala
+++ b/src/main/scala/firrtl/passes/memlib/InferReadWrite.scala
@@ -12,6 +12,8 @@ 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 +74,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)
diff --git a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
index 311813db..c49c0051 100644
--- a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
+++ b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
@@ -10,6 +10,8 @@ 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 +21,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
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
+}