diff options
| author | Jiuyang Liu | 2021-11-30 08:54:07 +0800 |
|---|---|---|
| committer | GitHub | 2021-11-29 16:54:07 -0800 |
| commit | b7dd35e9cdeecb2d5125ef1d8802d5af17bff4ab (patch) | |
| tree | 2220995b3a36df4b0b8ee18185cb75414ba48d5b | |
| parent | 82da33135fcac1a81e8ea95f47626e80b4e80fd1 (diff) | |
[deprecation clean up] remove firrtl.ExecutionOptionsManager (#2422)
Also remove all related APIs:
ComposableOptions
HasParser
CommonOptions
HasCommonOptions
FirrtlExecutionOptions
HasFirrtlOptions
FirrtlExecutionResult
FirrtlExecutionSuccess
FirrtlExecutionFailure
ExecutionOptionsManager
firrtl.stage.DriverCompatibility.firrtlResultView
logger.Logger.makeScope
OutputConfig
SingleFile
OneFilePerModule
* Change default LogLevel to None which means "unset"
Logger.getGlobalLevel then returns LogLevel.Warn when the current value
is LogLevel.None. This preserves the behavior of the default being
"Warn" but now uses LogLevel.None to indicate "I'm not setting the
value." This resolves issues where it was not possible to tell if
annotations were actually setting the log level or if the default level
of warn was just being filled in.
Co-authored-by: sinofp <sinofp@tuta.io>
Co-authored-by: Jack Koenig <koenig@sifive.com>
| -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 |
