diff options
| -rw-r--r-- | src/main/scala/firrtl/ExecutionOptionsManager.scala | 705 | ||||
| -rw-r--r-- | src/main/scala/firrtl/options/StageAnnotations.scala | 1 | ||||
| -rw-r--r-- | src/main/scala/firrtl/stage/FirrtlAnnotations.scala | 1 | ||||
| -rw-r--r-- | src/main/scala/firrtl/stage/package.scala | 37 | ||||
| -rw-r--r-- | src/main/scala/firrtl/stage/phases/DriverCompatibility.scala | 10 | ||||
| -rw-r--r-- | src/main/scala/logger/Logger.scala | 63 | ||||
| -rw-r--r-- | src/main/scala/logger/LoggerAnnotations.scala | 2 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/ExecutionOptionsManagerSpec.scala | 54 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/ParserSpec.scala | 3 | ||||
| -rw-r--r-- | src/test/scala/loggertests/LoggerSpec.scala | 20 |
10 files changed, 15 insertions, 881 deletions
diff --git a/src/main/scala/firrtl/ExecutionOptionsManager.scala b/src/main/scala/firrtl/ExecutionOptionsManager.scala deleted file mode 100644 index b8c0dedd..00000000 --- a/src/main/scala/firrtl/ExecutionOptionsManager.scala +++ /dev/null @@ -1,705 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package firrtl - -import logger.LogLevel -import logger.{ClassLogLevelAnnotation, LogClassNamesAnnotation, LogFileAnnotation, LogLevelAnnotation} -import firrtl.annotations._ -import firrtl.Parser.{AppendInfo, GenInfo, IgnoreInfo, InfoMode, UseInfo} -import firrtl.ir.Circuit -import firrtl.passes.memlib.{InferReadWriteAnnotation, ReplSeqMemAnnotation} -import firrtl.passes.clocklist.ClockListAnnotation -import firrtl.transforms.NoCircuitDedupAnnotation -import scopt.OptionParser -import firrtl.stage.{ - CompilerAnnotation, - FirrtlCircuitAnnotation, - FirrtlFileAnnotation, - FirrtlSourceAnnotation, - InfoModeAnnotation, - OutputFileAnnotation, - RunFirrtlTransformAnnotation -} -import firrtl.stage.phases.DriverCompatibility.{EmitOneFilePerModuleAnnotation, TopNameAnnotation} -import firrtl.options.{InputAnnotationFileAnnotation, OutputAnnotationFileAnnotation, ProgramArgsAnnotation, StageUtils} -import firrtl.transforms.{DontCheckCombLoopsAnnotation, NoDCEAnnotation} - -import scala.collection.Seq - -/** - * Use this trait to define an options class that can add its private command line options to a externally - * declared parser. - * '''NOTE''' In all derived trait/classes, if you intend on maintaining backwards compatibility, - * be sure to add new options at the end of the current ones and don't remove any existing ones. - */ -@deprecated("Use firrtl.options.HasScoptOptions and/or library/transform registration", "FIRRTL 1.2") -trait ComposableOptions - -@deprecated("Use firrtl.options.{ExecutionOptionsManager, TerminateOnExit, DuplicateHandling}", "FIRRTL 1.2") -abstract class HasParser(applicationName: String) { - final val parser = new OptionParser[Unit](applicationName) { - var terminateOnExit = true - override def terminate(exitState: Either[String, Unit]): Unit = { - if (terminateOnExit) sys.exit(0) - } - } - - /** - * By default scopt calls sys.exit when --help is in options, this defeats that - */ - def doNotExitOnHelp(): Unit = { - parser.terminateOnExit = false - } - - /** - * By default scopt calls sys.exit when --help is in options, this un-defeats doNotExitOnHelp - */ - def exitOnHelp(): Unit = { - parser.terminateOnExit = true - } -} - -/** - * Most of the chisel toolchain components require a topName which defines a circuit or a device under test. - * Much of the work that is done takes place in a directory. - * It would be simplest to require topName to be defined but in practice it is preferred to defer this. - * For example, in chisel, by deferring this it is possible for the execute there to first elaborate the - * circuit and then set the topName from that if it has not already been set. - */ -@deprecated("Use a FirrtlOptionsView, LoggerOptionsView, or construct your own view of an AnnotationSeq", "FIRRTL 1.2") -case class CommonOptions( - topName: String = "", - targetDirName: String = ".", - globalLogLevel: LogLevel.Value = LogLevel.None, - logToFile: Boolean = false, - logClassNames: Boolean = false, - classLogLevels: Map[String, LogLevel.Value] = Map.empty, - programArgs: Seq[String] = Seq.empty) - extends ComposableOptions { - - def getLogFileName(optionsManager: ExecutionOptionsManager): String = { - if (topName.isEmpty) { - optionsManager.getBuildFileName("log", "firrtl") - } else { - optionsManager.getBuildFileName("log") - } - } - - def toAnnotations: AnnotationSeq = List() ++ (if (topName.nonEmpty) Seq(TopNameAnnotation(topName)) else Seq()) ++ - (if (targetDirName != ".") Some(TargetDirAnnotation(targetDirName)) else None) ++ - Some(LogLevelAnnotation(globalLogLevel)) ++ - (if (logToFile) { Some(LogFileAnnotation(None)) } - else { None }) ++ - (if (logClassNames) { Some(LogClassNamesAnnotation) } - else { None }) ++ - classLogLevels.map { case (c, v) => ClassLogLevelAnnotation(c, v) } ++ - programArgs.map(a => ProgramArgsAnnotation(a)) -} - -@deprecated("Specify command line arguments in an Annotation mixing in HasScoptOptions", "FIRRTL 1.2") -trait HasCommonOptions { - self: ExecutionOptionsManager => - var commonOptions = CommonOptions() - - parser.note("common options") - - parser - .opt[String]("top-name") - .abbr("tn") - .valueName("<top-level-circuit-name>") - .foreach { x => - commonOptions = commonOptions.copy(topName = x) - } - .text("This options defines the top level circuit, defaults to dut when possible") - - parser - .opt[String]("target-dir") - .abbr("td") - .valueName("<target-directory>") - .foreach { x => - commonOptions = commonOptions.copy(targetDirName = x) - } - .text(s"This options defines a work directory for intermediate files, default is ${commonOptions.targetDirName}") - - parser - .opt[String]("log-level") - .abbr("ll") - .valueName("<error|warn|info|debug|trace>") - .foreach { x => - val level = x.toLowerCase match { - case "error" => LogLevel.Error - case "warn" => LogLevel.Warn - case "info" => LogLevel.Info - case "debug" => LogLevel.Debug - case "trace" => LogLevel.Trace - } - commonOptions = commonOptions.copy(globalLogLevel = level) - } - .validate { x => - if (Array("error", "warn", "info", "debug", "trace").contains(x.toLowerCase)) parser.success - else parser.failure(s"$x bad value must be one of error|warn|info|debug|trace") - } - .text(s"This options defines global log level, default is ${commonOptions.globalLogLevel}") - - parser - .opt[Seq[String]]("class-log-level") - .abbr("cll") - .valueName("<FullClassName:[error|warn|info|debug|trace]>[,...]") - .foreach { x => - val logAssignments = x.map { y => - val className :: levelName :: _ = y.split(":").toList - - val level = levelName.toLowerCase match { - case "error" => LogLevel.Error - case "warn" => LogLevel.Warn - case "info" => LogLevel.Info - case "debug" => LogLevel.Debug - case "trace" => LogLevel.Trace - case _ => - throw new Exception(s"Error: bad command line arguments for --class-log-level $x") - } - className -> level - } - - commonOptions = commonOptions.copy(classLogLevels = commonOptions.classLogLevels ++ logAssignments) - - } - .text(s"This options defines class log level, default is ${commonOptions.classLogLevels}") - - parser - .opt[Unit]("log-to-file") - .abbr("ltf") - .foreach { _ => - commonOptions = commonOptions.copy(logToFile = true) - } - .text(s"default logs to stdout, this flags writes to topName.log or firrtl.log if no topName") - - parser - .opt[Unit]("log-class-names") - .abbr("lcn") - .foreach { _ => - commonOptions = commonOptions.copy(logClassNames = true) - } - .text(s"shows class names and log level in logging output, useful for target --class-log-level") - - parser.help("help").text("prints this usage text") - - parser - .arg[String]("<arg>...") - .unbounded() - .optional() - .action((x, c) => commonOptions = commonOptions.copy(programArgs = commonOptions.programArgs :+ x)) - .text("optional unbounded args") - -} - -/** Firrtl output configuration specified by [[FirrtlExecutionOptions]] - * - * Derived from the fields of the execution options - * @see [[FirrtlExecutionOptions.getOutputConfig]] - */ -sealed abstract class OutputConfig -final case class SingleFile(targetFile: String) extends OutputConfig -final case class OneFilePerModule(targetDir: String) extends OutputConfig - -/** - * The options that firrtl supports in callable component sense - * - * @param inputFileNameOverride default is targetDir/topName.fir - * @param outputFileNameOverride default is targetDir/topName.v the .v is based on the compilerName parameter - * @param compilerName which compiler to use - * @param annotations annotations to pass to compiler - */ -@deprecated("Use a FirrtlOptionsView or construct your own view of an AnnotationSeq", "FIRRTL 1.2") -case class FirrtlExecutionOptions( - inputFileNameOverride: String = "", - outputFileNameOverride: String = "", - compilerName: String = "verilog", - infoModeName: String = "append", - inferRW: Seq[String] = Seq.empty, - firrtlSource: Option[String] = None, - customTransforms: Seq[Transform] = List.empty, - annotations: List[Annotation] = List.empty, - annotationFileNameOverride: String = "", - outputAnnotationFileName: String = "", - emitOneFilePerModule: Boolean = false, - dontCheckCombLoops: Boolean = false, - noDCE: Boolean = false, - annotationFileNames: List[String] = List.empty, - firrtlCircuit: Option[Circuit] = None) - extends ComposableOptions { - - require( - !(emitOneFilePerModule && outputFileNameOverride.nonEmpty), - "Cannot both specify the output filename and emit one file per module!!!" - ) - - def infoMode: InfoMode = { - infoModeName match { - case "use" => UseInfo - case "ignore" => IgnoreInfo - case "gen" => GenInfo(inputFileNameOverride) - case "append" => AppendInfo(inputFileNameOverride) - case other => UseInfo - } - } - - def compiler: Compiler = { - compilerName match { - case "none" => new NoneCompiler() - case "high" => new HighFirrtlCompiler() - case "low" => new LowFirrtlCompiler() - case "middle" => new MiddleFirrtlCompiler() - case "verilog" => new VerilogCompiler() - case "mverilog" => new MinimumVerilogCompiler() - case "sverilog" => new SystemVerilogCompiler() - } - } - - def outputSuffix: String = { - compilerName match { - case "verilog" | "mverilog" => "v" - case "sverilog" => "sv" - case "low" => "lo.fir" - case "middle" => "mid.fir" - case "high" => "hi.fir" - case "none" => "fir" - case _ => - throw new Exception(s"Illegal compiler name $compilerName") - } - } - - /** Get the name of the input file - * - * @note Does not implicitly add a file extension to the input file - * @param optionsManager this is needed to access build function and its common options - * @return a properly constructed input file name - */ - def getInputFileName(optionsManager: ExecutionOptionsManager): String = { - if (inputFileNameOverride.nonEmpty) inputFileNameOverride - else optionsManager.getBuildFileName("fir", inputFileNameOverride) - } - - /** Get the user-specified [[OutputConfig]] - * - * @param optionsManager this is needed to access build function and its common options - * @return the output configuration - */ - def getOutputConfig(optionsManager: ExecutionOptionsManager): OutputConfig = { - if (emitOneFilePerModule) OneFilePerModule(optionsManager.targetDirName) - else SingleFile(optionsManager.getBuildFileName(outputSuffix, outputFileNameOverride)) - } - - /** Get the user-specified targetFile assuming [[OutputConfig]] is [[SingleFile]] - * - * @param optionsManager this is needed to access build function and its common options - * @return the targetFile as a String - */ - def getTargetFile(optionsManager: ExecutionOptionsManager): String = { - getOutputConfig(optionsManager) match { - case SingleFile(targetFile) => targetFile - case other => throw new Exception("OutputConfig is not SingleFile!") - } - } - - /** Gives annotations based on the output configuration - * - * @param optionsManager this is needed to access build function and its common options - * @return Annotations that will be consumed by emitter Transforms - */ - def getEmitterAnnos(optionsManager: ExecutionOptionsManager): Seq[Annotation] = { - // TODO should this be a public function? - val emitter = compilerName match { - case "none" => classOf[ChirrtlEmitter] - case "high" => classOf[HighFirrtlEmitter] - case "middle" => classOf[MiddleFirrtlEmitter] - case "low" => classOf[LowFirrtlEmitter] - case "verilog" => classOf[VerilogEmitter] - case "mverilog" => classOf[MinimumVerilogEmitter] - case "sverilog" => classOf[VerilogEmitter] - } - getOutputConfig(optionsManager) match { - case SingleFile(_) => Seq(EmitCircuitAnnotation(emitter)) - case OneFilePerModule(_) => Seq(EmitAllModulesAnnotation(emitter)) - } - } - - /** - * build the annotation file name, taking overriding parameters - * - * @param optionsManager this is needed to access build function and its common options - * @return - */ - @deprecated("Use FirrtlOptions.annotationFileNames instead", "FIRRTL 1.1") - def getAnnotationFileName(optionsManager: ExecutionOptionsManager): String = { - optionsManager.getBuildFileName("anno", annotationFileNameOverride) - } - - def toAnnotations: AnnotationSeq = { - if (inferRW.nonEmpty) { - StageUtils.dramaticWarning("User set FirrtlExecutionOptions.inferRW, but inferRW has no effect!") - } - - List() ++ (if (inputFileNameOverride.nonEmpty) Seq(FirrtlFileAnnotation(inputFileNameOverride)) else Seq()) ++ - (if (outputFileNameOverride.nonEmpty) { Some(OutputFileAnnotation(outputFileNameOverride)) } - else { None }) ++ - Some(RunFirrtlTransformAnnotation.stringToEmitter(compilerName)) ++ - Some(InfoModeAnnotation(infoModeName)) ++ - firrtlSource.map(FirrtlSourceAnnotation(_)) ++ - customTransforms.map(t => RunFirrtlTransformAnnotation(t)) ++ - annotations ++ - (if (annotationFileNameOverride.nonEmpty) { Some(InputAnnotationFileAnnotation(annotationFileNameOverride)) } - else { None }) ++ - (if (outputAnnotationFileName.nonEmpty) { Some(OutputAnnotationFileAnnotation(outputAnnotationFileName)) } - else { None }) ++ - (if (emitOneFilePerModule) { Some(EmitOneFilePerModuleAnnotation) } - else { None }) ++ - (if (dontCheckCombLoops) { Some(DontCheckCombLoopsAnnotation) } - else { None }) ++ - (if (noDCE) { Some(NoDCEAnnotation) } - else { None }) ++ - annotationFileNames.map(InputAnnotationFileAnnotation(_)) ++ - firrtlCircuit.map(FirrtlCircuitAnnotation(_)) - } -} - -@deprecated("Specify command line arguments in an Annotation mixing in HasScoptOptions", "FIRRTL 1.2") -trait HasFirrtlOptions { - self: ExecutionOptionsManager => - var firrtlOptions = FirrtlExecutionOptions() - - parser.note("firrtl options") - - parser - .opt[String]("input-file") - .abbr("i") - .valueName("<firrtl-source>") - .foreach { x => - firrtlOptions = firrtlOptions.copy(inputFileNameOverride = x) - } - .text { - "use this to override the default input file name , default is empty" - } - - parser - .opt[String]("output-file") - .abbr("o") - .valueName("<output>") - .validate { x => - if (firrtlOptions.emitOneFilePerModule) - parser.failure("Cannot override output-file if split-modules is specified") - else parser.success - } - .foreach { x => - firrtlOptions = firrtlOptions.copy(outputFileNameOverride = x) - } - .text { - "use this to override the default output file name, default is empty" - } - - parser - .opt[String]("annotation-file") - .abbr("faf") - .unbounded() - .valueName("<input-anno-file>") - .foreach { x => - val annoFiles = x +: firrtlOptions.annotationFileNames - firrtlOptions = firrtlOptions.copy(annotationFileNames = annoFiles) - } - .text("Used to specify annotation files (can appear multiple times)") - - parser - .opt[Unit]("force-append-anno-file") - .abbr("ffaaf") - .hidden() - .foreach { _ => - val msg = "force-append-anno-file is deprecated and will soon be removed\n" + - (" " * 9) + "(It does not do anything anymore)" - StageUtils.dramaticWarning(msg) - } - - parser - .opt[String]("output-annotation-file") - .abbr("foaf") - .valueName("<output-anno-file>") - .foreach { x => - firrtlOptions = firrtlOptions.copy(outputAnnotationFileName = x) - } - .text { - "use this to set the annotation output file" - } - - parser - .opt[String]("compiler") - .abbr("X") - .valueName("<high|middle|low|verilog|mverilog|sverilog|none>") - .foreach { x => - firrtlOptions = firrtlOptions.copy(compilerName = x) - } - .validate { x => - if (Array("high", "middle", "low", "verilog", "mverilog", "sverilog", "none").contains(x.toLowerCase)) { - parser.success - } else { - parser.failure(s"$x not a legal compiler") - } - } - .text { - s"compiler to use, default is ${firrtlOptions.compilerName}" - } - - parser - .opt[String]("info-mode") - .valueName("<ignore|use|gen|append>") - .foreach { x => - firrtlOptions = firrtlOptions.copy(infoModeName = x.toLowerCase) - } - .validate { x => - if (Array("ignore", "use", "gen", "append").contains(x.toLowerCase)) parser.success - else parser.failure(s"$x bad value must be one of ignore|use|gen|append") - } - .text { - s"specifies the source info handling, default is ${firrtlOptions.infoModeName}" - } - - parser - .opt[Seq[String]]("custom-transforms") - .abbr("fct") - .valueName("<package>.<class>") - .foreach { customTransforms: Seq[String] => - firrtlOptions = firrtlOptions.copy( - customTransforms = firrtlOptions.customTransforms ++ - (customTransforms.map { x: String => - Class.forName(x).asInstanceOf[Class[_ <: Transform]].newInstance() - }) - ) - } - .text { - """runs these custom transforms during compilation.""" - } - - parser - .opt[Seq[String]]("inline") - .abbr("fil") - .valueName("<circuit>[.<module>[.<instance>]][,..],") - .foreach { x => - val newAnnotations = x.map { value => - value.split('.') match { - case Array(circuit) => - passes.InlineAnnotation(CircuitName(circuit)) - case Array(circuit, module) => - passes.InlineAnnotation(ModuleName(module, CircuitName(circuit))) - case Array(circuit, module, inst) => - passes.InlineAnnotation(ComponentName(inst, ModuleName(module, CircuitName(circuit)))) - } - } - firrtlOptions = firrtlOptions.copy( - annotations = firrtlOptions.annotations ++ newAnnotations, - customTransforms = firrtlOptions.customTransforms :+ new passes.InlineInstances - ) - } - .text { - """Inline one or more module (comma separated, no spaces) module looks like "MyModule" or "MyModule.myinstance""" - } - - parser - .opt[Unit]("infer-rw") - .abbr("firw") - .foreach { x => - firrtlOptions = firrtlOptions.copy( - annotations = firrtlOptions.annotations :+ InferReadWriteAnnotation, - customTransforms = firrtlOptions.customTransforms :+ new passes.memlib.InferReadWrite - ) - } - .text { - "Enable readwrite port inference for the target circuit" - } - - parser - .opt[String]("repl-seq-mem") - .abbr("frsq") - .valueName("-c:<circuit>:-i:<filename>:-o:<filename>") - .foreach { x => - firrtlOptions = firrtlOptions.copy( - annotations = firrtlOptions.annotations :+ ReplSeqMemAnnotation.parse(x), - customTransforms = firrtlOptions.customTransforms :+ new passes.memlib.ReplSeqMem - ) - } - .text { - "Replace sequential memories with blackboxes + configuration file" - } - - parser - .opt[String]("list-clocks") - .abbr("clks") - .valueName("-c:<circuit>:-m:<module>:-o:<filename>") - .foreach { x => - firrtlOptions = firrtlOptions.copy( - annotations = firrtlOptions.annotations :+ ClockListAnnotation.parse(x), - customTransforms = firrtlOptions.customTransforms :+ new passes.clocklist.ClockListTransform - ) - } - .text { - "List which signal drives each clock of every descendent of specified module" - } - - parser - .opt[Unit]("split-modules") - .abbr("fsm") - .validate { x => - if (firrtlOptions.outputFileNameOverride.nonEmpty) - parser.failure("Cannot split-modules if output-file is specified") - else parser.success - } - .foreach { _ => - firrtlOptions = firrtlOptions.copy(emitOneFilePerModule = true) - } - .text { - "Emit each module to its own file in the target directory." - } - - parser - .opt[Unit]("no-check-comb-loops") - .foreach { _ => - firrtlOptions = firrtlOptions.copy(dontCheckCombLoops = true) - } - .text { - "Do NOT check for combinational loops (not recommended)" - } - - parser - .opt[Unit]("no-dce") - .foreach { _ => - firrtlOptions = firrtlOptions.copy(noDCE = true) - } - .text { - "Do NOT run dead code elimination" - } - - parser - .opt[Unit]("no-dedup") - .foreach { _ => - firrtlOptions = firrtlOptions.copy( - annotations = firrtlOptions.annotations :+ NoCircuitDedupAnnotation - ) - } - .text { - "Do NOT dedup modules" - } - - parser.note("") -} - -@deprecated("Use FirrtlStage and examine the output AnnotationSeq directly", "FIRRTL 1.2") -sealed trait FirrtlExecutionResult - -@deprecated("Use FirrtlStage and examine the output AnnotationSeq directly", "FIRRTL 1.2") -object FirrtlExecutionSuccess { - def apply( - emitType: String, - emitted: String, - circuitState: CircuitState - ): FirrtlExecutionSuccess = new FirrtlExecutionSuccess(emitType, emitted, circuitState) - - def unapply(arg: FirrtlExecutionSuccess): Option[(String, String)] = { - Some((arg.emitType, arg.emitted)) - } -} - -/** - * Indicates a successful execution of the firrtl compiler, returning the compiled result and - * the type of compile - * - * @param emitType The name of the compiler used, currently "high", "middle", "low", "verilog", "mverilog", or - * "sverilog" - * @param emitted The emitted result of compilation - */ -@deprecated("Use FirrtlStage and examine the output AnnotationSeq directly", "FIRRTL 1.2") -class FirrtlExecutionSuccess( - val emitType: String, - val emitted: String, - val circuitState: CircuitState) - extends FirrtlExecutionResult - -/** - * The firrtl compilation failed. - * - * @param message Some kind of hint as to what went wrong. - */ -@deprecated("Use FirrtlStage and examine the output AnnotationSeq directly", "FIRRTL 1.2") -case class FirrtlExecutionFailure(message: String) extends FirrtlExecutionResult - -/** - * @param applicationName The name shown in the usage - */ -@deprecated("Use new FirrtlStage infrastructure", "FIRRTL 1.2") -class ExecutionOptionsManager(val applicationName: String) extends HasParser(applicationName) with HasCommonOptions { - - def parse(args: Array[String]): Boolean = { - parser.parse(args) - } - - def showUsageAsError(): Unit = parser.showUsageAsError() - - /** - * make sure that all levels of targetDirName exist - * - * @return true if directory exists - */ - def makeTargetDir(): Boolean = { - FileUtils.makeDirectory(commonOptions.targetDirName) - } - - def targetDirName: String = commonOptions.targetDirName - - /** - * this function sets the topName in the commonOptions. - * It would be nicer to not need this but many chisel tools cannot determine - * the name of the device under test until other options have been parsed. - * Havin this function allows the code to set the TopName after it has been - * determined - * - * @param newTopName the topName to be used - */ - def setTopName(newTopName: String): Unit = { - commonOptions = commonOptions.copy(topName = newTopName) - } - def setTopNameIfNotSet(newTopName: String): Unit = { - if (commonOptions.topName.isEmpty) { - setTopName(newTopName) - } - } - def topName: String = commonOptions.topName - def setTargetDirName(newTargetDirName: String): Unit = { - commonOptions = commonOptions.copy(targetDirName = newTargetDirName) - } - - /** - * return a file based on targetDir, topName and suffix - * Will not add the suffix if the topName already ends with that suffix - * - * @param suffix suffix to add, removes . if present - * @param fileNameOverride this will override the topName if nonEmpty, when using this targetDir is ignored - * @return - */ - def getBuildFileName(suffix: String, fileNameOverride: String = ""): String = { - makeTargetDir() - - val baseName = if (fileNameOverride.nonEmpty) fileNameOverride else topName - val directoryName = { - if (fileNameOverride.nonEmpty) { - "" - } else if (baseName.startsWith("./") || baseName.startsWith("/")) { - "" - } else { - if (targetDirName.endsWith("/")) targetDirName else targetDirName + "/" - } - } - val normalizedSuffix = { - val dottedSuffix = if (suffix.startsWith(".")) suffix else s".$suffix" - if (baseName.endsWith(dottedSuffix)) "" else dottedSuffix - } - val path = directoryName + baseName.split("/").dropRight(1).mkString("/") - FileUtils.makeDirectory(path) - s"$directoryName$baseName$normalizedSuffix" - } -} diff --git a/src/main/scala/firrtl/options/StageAnnotations.scala b/src/main/scala/firrtl/options/StageAnnotations.scala index 584f2842..1642e248 100644 --- a/src/main/scala/firrtl/options/StageAnnotations.scala +++ b/src/main/scala/firrtl/options/StageAnnotations.scala @@ -138,7 +138,6 @@ object ProgramArgsAnnotation { } /** 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 */ diff --git a/src/main/scala/firrtl/stage/FirrtlAnnotations.scala b/src/main/scala/firrtl/stage/FirrtlAnnotations.scala index 6dbb0434..515c8af9 100644 --- a/src/main/scala/firrtl/stage/FirrtlAnnotations.scala +++ b/src/main/scala/firrtl/stage/FirrtlAnnotations.scala @@ -208,7 +208,6 @@ object CompilerAnnotation extends HasShellOptions { } /** Holds the unambiguous class name of a [[Transform]] to run - * - will be append to [[FirrtlExecutionOptions.customTransforms]] * - set with `-fct/--custom-transforms` * @param transform the full class name of the transform */ diff --git a/src/main/scala/firrtl/stage/package.scala b/src/main/scala/firrtl/stage/package.scala index b3fe2473..b409fba3 100644 --- a/src/main/scala/firrtl/stage/package.scala +++ b/src/main/scala/firrtl/stage/package.scala @@ -39,41 +39,4 @@ package object stage { } } } - - private[firrtl] implicit object FirrtlExecutionResultView - extends OptionsView[FirrtlExecutionResult] - with LazyLogging { - - def view(options: AnnotationSeq): FirrtlExecutionResult = { - val emittedRes = options.collect { case a: EmittedAnnotation[_] => a.value.value } - .mkString("\n") - - val emitters = options.collect { case RunFirrtlTransformAnnotation(e: Emitter) => e } - if (emitters.length > 1) { - logger.warn( - "More than one emitter used which cannot be accurately represented" + - "in the deprecated FirrtlExecutionResult: " + emitters.map(_.name).mkString(", ") - ) - } - val compilers = options.collect { case CompilerAnnotation(c) => c } - val emitType = emitters.headOption.orElse(compilers.headOption).map(_.name).getOrElse("N/A") - val form = emitters.headOption.orElse(compilers.headOption).map(_.outputForm).getOrElse(UnknownForm) - - options.collectFirst { case a: FirrtlCircuitAnnotation => a.circuit } match { - case None => FirrtlExecutionFailure("No circuit found in AnnotationSeq!") - case Some(a) => - FirrtlExecutionSuccess( - emitType = emitType, - emitted = emittedRes, - circuitState = CircuitState( - circuit = a, - form = form, - annotations = options, - renames = None - ) - ) - } - } - } - } diff --git a/src/main/scala/firrtl/stage/phases/DriverCompatibility.scala b/src/main/scala/firrtl/stage/phases/DriverCompatibility.scala index a18fe08d..546a18f5 100644 --- a/src/main/scala/firrtl/stage/phases/DriverCompatibility.scala +++ b/src/main/scala/firrtl/stage/phases/DriverCompatibility.scala @@ -4,7 +4,7 @@ package firrtl.stage.phases import firrtl.stage._ -import firrtl.{AnnotationSeq, EmitAllModulesAnnotation, EmitCircuitAnnotation, Emitter, FirrtlExecutionResult, Parser} +import firrtl.{AnnotationSeq, EmitAllModulesAnnotation, EmitCircuitAnnotation, Emitter, Parser} import firrtl.annotations.NoTargetAnnotation import firrtl.FileUtils import firrtl.proto.FromProto @@ -36,14 +36,6 @@ object DriverCompatibility { s"""|Option '$a' was removed as part of the FIRRTL Stage refactor. Use an explicit input/output options instead. |This error will be removed in 1.3.""".stripMargin - /** Convert an [[firrtl.AnnotationSeq AnnotationSeq]] to a ''deprecated'' [[firrtl.FirrtlExecutionResult - * FirrtlExecutionResult]]. - * @param annotations a sequence of [[firrtl.annotations.Annotation Annotation]] - */ - @deprecated("FirrtlExecutionResult is deprecated as part of the Stage/Phase refactor. Migrate to FirrtlStage.", "1.2") - def firrtlResultView(annotations: AnnotationSeq): FirrtlExecutionResult = - Viewer[FirrtlExecutionResult].view(annotations) - /** Holds the name of the top (main) module in an input circuit * @param value top module name */ diff --git a/src/main/scala/logger/Logger.scala b/src/main/scala/logger/Logger.scala index 09fc0924..f14eec71 100644 --- a/src/main/scala/logger/Logger.scala +++ b/src/main/scala/logger/Logger.scala @@ -4,7 +4,7 @@ package logger import java.io.{ByteArrayOutputStream, File, FileOutputStream, PrintStream} -import firrtl.{AnnotationSeq, ExecutionOptionsManager} +import firrtl.AnnotationSeq import firrtl.options.Viewer.view import logger.phases.{AddDefaults, Checks} @@ -13,8 +13,6 @@ import scala.util.DynamicVariable /** * This provides a facility for a log4scala* type logging system. Why did we write our own? Because * the canned ones are just too darned hard to turn on, particularly when embedded in a distribution. - * This one can be turned on programmatically or with the options exposed in the [[firrtl.CommonOptions]] - * and [[ExecutionOptionsManager]] APIs in firrtl. * There are 4 main options: * * A simple global option to turn on all in scope (and across threads, might want to fix this) * * Turn on specific levels for specific fully qualified class names @@ -30,8 +28,11 @@ import scala.util.DynamicVariable * The supported log levels, what do they mean? Whatever you want them to. */ object LogLevel extends Enumeration { + // None indicates "not set" val Error, Warn, Info, Debug, Trace, None = Value + def default = Warn + def apply(s: String): LogLevel.Value = s.toLowerCase match { case "error" => LogLevel.Error case "warn" => LogLevel.Warn @@ -55,7 +56,7 @@ trait LazyLogging { * when used in multi-threaded environments */ private class LoggerState { - var globalLevel = LogLevel.Warn + var globalLevel = LogLevel.None val classLevels = new scala.collection.mutable.HashMap[String, LogLevel.Value] val classToLevelCache = new scala.collection.mutable.HashMap[String, LogLevel.Value] var logClassNames = false @@ -114,44 +115,13 @@ object Logger { } } - /** - * This creates a block of code that will have access to the - * thread specific logger. The state will be set according to the - * logging options set in the common options of the manager - * @param manager source of logger settings - * @param codeBlock code to be run with these logger settings - * @tparam A The return type of codeBlock - * @return Whatever block returns - */ - @deprecated("Use makeScope(opts: FirrtlOptions)", "FIRRTL 1.2") - def makeScope[A](manager: ExecutionOptionsManager)(codeBlock: => A): A = - makeScope(manager.commonOptions.toAnnotations)(codeBlock) - - /** - * See makeScope using manager. This creates a manager from a command line arguments style - * list of strings - * @param args List of strings - * @param codeBlock the block to call - * @tparam A return type of codeBlock - * @return - */ - @deprecated("Use makescope(opts: FirrtlOptions)", "FIRRTL 1.2") - def makeScope[A](args: Array[String] = Array.empty)(codeBlock: => A): A = { - val executionOptionsManager = new ExecutionOptionsManager("logger") - if (executionOptionsManager.parse(args)) { - makeScope(executionOptionsManager)(codeBlock) - } else { - throw new Exception(s"logger invoke failed to parse args ${args.mkString(", ")}") - } - } - /** Set a scope for this logger based on available annotations * @param options a sequence annotations * @param codeBlock some Scala code over which to define this scope * @tparam A return type of the code block * @return the original return of the code block */ - def makeScope[A](options: AnnotationSeq)(codeBlock: => A): A = { + def makeScope[A](options: AnnotationSeq = Seq.empty)(codeBlock: => A): A = { val runState: LoggerState = { val newRunState = updatableLoggerState.value.getOrElse(new LoggerState) if (newRunState.fromInvoke) { @@ -237,17 +207,16 @@ object Logger { case Some(true) => logIt() case Some(false) => case None => - if ( - (state.globalLevel == LogLevel.None && level == LogLevel.Error) || - (state.globalLevel != LogLevel.None && state.globalLevel >= level) - ) { + if (getGlobalLevel >= level) { logIt() } } } - def getGlobalLevel: LogLevel.Value = { - state.globalLevel + def getGlobalLevel: LogLevel.Value = state.globalLevel match { + // None means "not set" so use default in that case + case LogLevel.None => LogLevel.default + case other => other } /** @@ -349,15 +318,6 @@ object Logger { state.classLevels ++= namesToLevel } - /** - * This is used to set the options that have been set in a optionsManager or are coming - * from the command line via an options manager - * @param optionsManager manager - */ - @deprecated("Use setOptions(annotations: AnnotationSeq)", "FIRRTL 1.2") - def setOptions(optionsManager: ExecutionOptionsManager): Unit = - setOptions(optionsManager.commonOptions.toAnnotations) - /** Set logger options based on the content of an [[firrtl.AnnotationSeq AnnotationSeq]] * @param inputAnnotations annotation sequence containing logger options */ @@ -372,7 +332,6 @@ object Logger { case (x, LogLevel.None) => x case (LogLevel.None, x) => x case (_, x) => x - case _ => LogLevel.Error } setClassLogLevels(lopts.classLogLevels) diff --git a/src/main/scala/logger/LoggerAnnotations.scala b/src/main/scala/logger/LoggerAnnotations.scala index c292db87..0185492e 100644 --- a/src/main/scala/logger/LoggerAnnotations.scala +++ b/src/main/scala/logger/LoggerAnnotations.scala @@ -13,7 +13,7 @@ sealed trait LoggerOption { this: Annotation => } * - 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.Warn) +case class LogLevelAnnotation(globalLogLevel: LogLevel.Value = LogLevel.None) extends NoTargetAnnotation with LoggerOption diff --git a/src/test/scala/firrtlTests/ExecutionOptionsManagerSpec.scala b/src/test/scala/firrtlTests/ExecutionOptionsManagerSpec.scala deleted file mode 100644 index f176fe38..00000000 --- a/src/test/scala/firrtlTests/ExecutionOptionsManagerSpec.scala +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package firrtlTests - -import firrtl._ -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -class ExecutionOptionsManagerSpec extends AnyFreeSpec with Matchers { - "ExecutionOptionsManager is a container for one more more ComposableOptions Block" - { - "It has a default CommonOptionsBlock" in { - val manager = new ExecutionOptionsManager("test") - manager.topName should be("") - manager.targetDirName should be(".") - manager.commonOptions.topName should be("") - manager.commonOptions.targetDirName should be(".") - } - "But can override defaults like this" in { - val manager = new ExecutionOptionsManager("test") { - commonOptions = CommonOptions(topName = "dog", targetDirName = "a/b/c") - } - manager.commonOptions shouldBe a[CommonOptions] - manager.topName should be("dog") - manager.targetDirName should be("a/b/c") - manager.commonOptions.topName should be("dog") - manager.commonOptions.targetDirName should be("a/b/c") - } - "The add method should put a new version of a given type the manager" in { - val manager = new ExecutionOptionsManager("test") { - commonOptions = CommonOptions(topName = "dog", targetDirName = "a/b/c") - } - val initialCommon = manager.commonOptions - initialCommon.topName should be("dog") - initialCommon.targetDirName should be("a/b/c") - - manager.commonOptions = CommonOptions(topName = "cat", targetDirName = "d/e/f") - - val afterCommon = manager.commonOptions - afterCommon.topName should be("cat") - afterCommon.targetDirName should be("d/e/f") - initialCommon.topName should be("dog") - initialCommon.targetDirName should be("a/b/c") - } - "multiple composable blocks should be separable" in { - val manager = new ExecutionOptionsManager("test") with HasFirrtlOptions { - commonOptions = CommonOptions(topName = "spoon") - firrtlOptions = FirrtlExecutionOptions(inputFileNameOverride = "fork") - } - - manager.firrtlOptions.inputFileNameOverride should be("fork") - manager.commonOptions.topName should be("spoon") - } - } -} diff --git a/src/test/scala/firrtlTests/ParserSpec.scala b/src/test/scala/firrtlTests/ParserSpec.scala index 57b468ea..89e73cb7 100644 --- a/src/test/scala/firrtlTests/ParserSpec.scala +++ b/src/test/scala/firrtlTests/ParserSpec.scala @@ -312,9 +312,6 @@ class ParserSpec extends FirrtlFlatSpec { | bar.a <- a | b <- bar.b """.stripMargin - val manager = new ExecutionOptionsManager("test") with HasFirrtlOptions { - firrtlOptions = FirrtlExecutionOptions(firrtlSource = Some(input)) - } a[SyntaxErrorsException] shouldBe thrownBy { (new FirrtlStage).execute(Array(), Seq(FirrtlSourceAnnotation(input))) } diff --git a/src/test/scala/loggertests/LoggerSpec.scala b/src/test/scala/loggertests/LoggerSpec.scala index d9feb931..e0a7b43d 100644 --- a/src/test/scala/loggertests/LoggerSpec.scala +++ b/src/test/scala/loggertests/LoggerSpec.scala @@ -41,7 +41,7 @@ class LoggerSpec extends AnyFreeSpec with Matchers with OneInstancePerTest with "Logger is a simple but powerful logging system" - { "Following tests show how global level can control logging" - { - "setting level to None will result in only error messages" in { + "setting level to None will result in warn messages" in { Logger.makeScope() { val captor = new OutputCaptor Logger.setOutput(captor.printStream) @@ -52,7 +52,7 @@ class LoggerSpec extends AnyFreeSpec with Matchers with OneInstancePerTest with val messagesLogged = captor.getOutputAsString messagesLogged.contains(LoggerSpec.ErrorMsg) should be(true) - messagesLogged.contains(LoggerSpec.WarnMsg) should be(false) + messagesLogged.contains(LoggerSpec.WarnMsg) should be(true) messagesLogged.contains(LoggerSpec.InfoMsg) should be(false) messagesLogged.contains(LoggerSpec.DebugMsg) should be(false) messagesLogged.contains(LoggerSpec.TraceMsg) should be(false) @@ -274,22 +274,6 @@ class LoggerSpec extends AnyFreeSpec with Matchers with OneInstancePerTest with messagesLogged.contains("logger3") should be(true) } } - "Show logging can be set with command options" in { - val captor = new Logger.OutputCaptor - - Logger.makeScope(Array("--class-log-level", "loggertests.LogsInfo3:info")) { - Logger.setOutput(captor.printStream) - val r2 = new LogsInfo2 - val r3 = new LogsInfo3 - r2.run() - r3.run() - - val messagesLogged = captor.getOutputAsString - - messagesLogged.contains("logger2") should be(false) - messagesLogged.contains("logger3") should be(true) - } - } "Show that printstream remains across makeScopes" in { Logger.makeScope() { val captor = new Logger.OutputCaptor |
