1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
|
// SPDX-License-Identifier: Apache-2.0
package firrtl.stage
import firrtl._
import firrtl.ir.Circuit
import firrtl.annotations.{Annotation, NoTargetAnnotation}
import firrtl.options.{Dependency, HasShellOptions, OptionsException, ShellOption, Unserializable}
import java.io.{File, FileNotFoundException}
import java.nio.file.{NoSuchFileException, NotDirectoryException}
import firrtl.stage.TransformManager.TransformDependency
/** Indicates that this is an [[firrtl.annotations.Annotation Annotation]] directly used in the construction of a
* [[FirrtlOptions]] view.
*/
sealed trait FirrtlOption extends Unserializable { this: Annotation => }
/** Indicates that this [[firrtl.annotations.Annotation Annotation]] contains information that is directly convertable
* to a FIRRTL [[firrtl.ir.Circuit Circuit]].
*/
sealed trait CircuitOption extends Unserializable { this: Annotation =>
/** Convert this [[firrtl.annotations.Annotation Annotation]] to a [[FirrtlCircuitAnnotation]]
*/
def toCircuit(info: Parser.InfoMode): FirrtlCircuitAnnotation
}
/** An explicit input FIRRTL file to read
* - set with `-i/--input-file`
* - If unset, an [[FirrtlFileAnnotation]] with the default input file __will not be generated__
* @param file input filename
*/
case class FirrtlFileAnnotation(file: String) extends NoTargetAnnotation with CircuitOption {
def toCircuit(info: Parser.InfoMode): FirrtlCircuitAnnotation = {
val circuit =
try {
FirrtlStageUtils.getFileExtension(file) match {
case ProtoBufFile => proto.FromProto.fromFile(file)
case FirrtlFile => Parser.parseFile(file, info)
}
} catch {
case a @ (_: FileNotFoundException | _: NoSuchFileException) =>
throw new OptionsException(s"Input file '$file' not found! (Did you misspell it?)", a)
}
FirrtlCircuitAnnotation(circuit)
}
}
object FirrtlFileAnnotation extends HasShellOptions {
val options = Seq(
new ShellOption[String](
longOption = "input-file",
toAnnotationSeq = a => Seq(FirrtlFileAnnotation(a)),
helpText = "An input FIRRTL file",
shortOption = Some("i"),
helpValueName = Some("<file>")
)
)
}
/** Read a directory of ProtoBufs
* - set with `-I/--input-directory`
*
* TODO: Does not currently support FIRRTL files.
* @param dir input directory name
*/
case class FirrtlDirectoryAnnotation(dir: String) extends NoTargetAnnotation with CircuitOption {
def toCircuit(info: Parser.InfoMode): FirrtlCircuitAnnotation = {
val circuit =
try {
proto.FromProto.fromDirectory(dir)
} catch {
case a @ (_: FileNotFoundException | _: NoSuchFileException) =>
throw new OptionsException(s"Directory '$dir' not found! (Did you misspell it?)", a)
case _: NotDirectoryException =>
throw new OptionsException(s"Directory '$dir' is not a directory")
}
FirrtlCircuitAnnotation(circuit)
}
}
object FirrtlDirectoryAnnotation extends HasShellOptions {
val options = Seq(
new ShellOption[String](
longOption = "input-directory",
toAnnotationSeq = a => Seq(FirrtlDirectoryAnnotation(a)),
helpText = "A directory of FIRRTL files",
shortOption = Some("I"),
helpValueName = Some("<directory>")
)
)
}
/** An explicit output file the emitter will write to
* - set with `-o/--output-file`
* @param file output filename
*/
case class OutputFileAnnotation(file: String) extends NoTargetAnnotation with FirrtlOption
object OutputFileAnnotation extends HasShellOptions {
val options = Seq(
new ShellOption[String](
longOption = "output-file",
toAnnotationSeq = a => Seq(OutputFileAnnotation(a)),
helpText = "The output FIRRTL file",
shortOption = Some("o"),
helpValueName = Some("<file>")
)
)
}
/** Sets the info mode style
* - set with `--info-mode`
* @param mode info mode name
* @note This cannote be directly converted to [[Parser.InfoMode]] as that depends on an optional [[FirrtlFileAnnotation]]
*/
case class InfoModeAnnotation(modeName: String = "use") extends NoTargetAnnotation with FirrtlOption {
require(
modeName match { case "use" | "ignore" | "gen" | "append" => true; case _ => false },
s"Unknown info mode '$modeName'! (Did you misspell it?)"
)
/** Return the [[Parser.InfoMode]] equivalent for this [[firrtl.annotations.Annotation Annotation]]
* @param infoSource the name of a file to use for "gen" or "append" info modes
*/
def toInfoMode(infoSource: Option[String] = None): Parser.InfoMode = modeName match {
case "use" => Parser.UseInfo
case "ignore" => Parser.IgnoreInfo
case _ =>
val a = infoSource.getOrElse("unknown source")
modeName match {
case "gen" => Parser.GenInfo(a)
case "append" => Parser.AppendInfo(a)
}
}
}
object InfoModeAnnotation extends HasShellOptions {
val options = Seq(
new ShellOption[String](
longOption = "info-mode",
toAnnotationSeq = a => Seq(InfoModeAnnotation(a)),
helpText = s"Source file info handling mode (default: ${apply().modeName})",
helpValueName = Some("<ignore|use|gen|append>")
)
)
}
/** Holds a [[scala.Predef.String String]] containing FIRRTL source to read as input
* - set with `--firrtl-source`
* @param value FIRRTL source as a [[scala.Predef.String String]]
*/
case class FirrtlSourceAnnotation(source: String) extends NoTargetAnnotation with CircuitOption {
def toCircuit(info: Parser.InfoMode): FirrtlCircuitAnnotation =
FirrtlCircuitAnnotation(Parser.parseString(source, info))
}
object FirrtlSourceAnnotation extends HasShellOptions {
val options = Seq(
new ShellOption[String](
longOption = "firrtl-source",
toAnnotationSeq = a => Seq(FirrtlSourceAnnotation(a)),
helpText = "An input FIRRTL circuit string",
helpValueName = Some("<string>")
)
)
}
/** helpValueName a [[Compiler]] that should be run
* - set stringly with `-X/--compiler`
* - If unset, a [[CompilerAnnotation]] with the default [[VerilogCompiler]]
* @param compiler compiler name
*/
@deprecated("Use a RunFirrtlTransformAnnotation targeting a specific Emitter.", "FIRRTL 1.4.0")
case class CompilerAnnotation(compiler: Compiler = new VerilogCompiler()) extends NoTargetAnnotation with FirrtlOption
@deprecated("Use a RunFirrtlTransformAnnotation targeting a specific Emitter.", "FIRRTL 1.4.0")
object CompilerAnnotation extends HasShellOptions {
val options = Seq(
new ShellOption[String](
longOption = "compiler",
toAnnotationSeq = a => Seq(RunFirrtlTransformAnnotation.stringToEmitter(a)),
helpText = "The FIRRTL compiler to use (default: verilog)",
shortOption = Some("X"),
helpValueName = Some("<none|mhigh|high|middle|low|verilog|mverilog|sverilog>")
)
)
}
/** Holds the unambiguous class name of a [[Transform]] to run
* - set with `-fct/--custom-transforms`
* @param transform the full class name of the transform
*/
case class RunFirrtlTransformAnnotation(transform: Transform) extends NoTargetAnnotation
object RunFirrtlTransformAnnotation extends HasShellOptions {
def apply(transform: TransformDependency): RunFirrtlTransformAnnotation =
RunFirrtlTransformAnnotation(transform.getObject())
private[firrtl] def stringToEmitter(a: String): RunFirrtlTransformAnnotation = {
val emitter = a match {
case "none" => new ChirrtlEmitter
case "mhigh" => new MinimumHighFirrtlEmitter
case "high" => new HighFirrtlEmitter
case "low" => new LowFirrtlEmitter
case "middle" => new MiddleFirrtlEmitter
case "verilog" => new VerilogEmitter
case "mverilog" => new MinimumVerilogEmitter
case "sverilog" => new SystemVerilogEmitter
case _ => throw new OptionsException(s"Unknown compiler name '$a'! (Did you misspell it?)")
}
RunFirrtlTransformAnnotation(emitter)
}
val options = Seq(
new ShellOption[Seq[String]](
longOption = "custom-transforms",
toAnnotationSeq = _.map(txName =>
try {
val tx = Class.forName(txName).asInstanceOf[Class[_ <: Transform]].newInstance()
RunFirrtlTransformAnnotation(tx)
} catch {
case e: ClassNotFoundException =>
throw new OptionsException(s"Unable to locate custom transform $txName (did you misspell it?)", e)
case e: InstantiationException =>
throw new OptionsException(
s"Unable to create instance of Transform $txName (is this an anonymous class?)",
e
)
case e: Throwable => throw new OptionsException(s"Unknown error when instantiating class $txName", e)
}
),
helpText = "Run these transforms during compilation",
shortOption = Some("fct"),
helpValueName = Some("<package>.<class>")
),
new ShellOption[String](
longOption = "change-name-case",
toAnnotationSeq = _ match {
case "lower" => Seq(RunFirrtlTransformAnnotation(new firrtl.features.LowerCaseNames))
case "upper" => Seq(RunFirrtlTransformAnnotation(new firrtl.features.UpperCaseNames))
case a => throw new OptionsException(s"Unknown case '$a'. Did you misspell it?")
},
helpText = "Convert all FIRRTL names to a specific case",
helpValueName = Some("<lower|upper>")
),
new ShellOption[String](
longOption = "compiler",
toAnnotationSeq = a => Seq(stringToEmitter(a)),
helpText = "The FIRRTL compiler to use (default: verilog)",
shortOption = Some("X"),
helpValueName = Some("<none|high|middle|low|verilog|mverilog|sverilog>")
)
)
}
/** Holds a FIRRTL [[firrtl.ir.Circuit Circuit]]
* @param circuit a circuit
*/
case class FirrtlCircuitAnnotation(circuit: Circuit) extends NoTargetAnnotation with FirrtlOption {
/* Caching the hashCode for a large circuit is necessary due to repeated queries, e.g., in
* [[Compiler.propagateAnnotations]]. Not caching the hashCode will cause severe performance degredations for large
* [[Annotations]].
* @note Uses the hashCode of the name of the circuit. Creating a HashMap with different Circuits
* that nevertheless have the same name is extremely uncommon so collisions are not a concern.
* Include productPrefix so that this doesn't collide with other types that use a similar
* strategy and hash the same String.
*/
override lazy val hashCode: Int = (this.productPrefix + circuit.main).hashCode
}
/** Suppresses warning about Scala 2.11 deprecation
*
* - set with `--warn:no-scala-version-deprecation`
*/
@deprecated("Support for Scala 2.11 has been dropped, this object no longer does anything", "FIRRTL 1.5")
case object WarnNoScalaVersionDeprecation extends NoTargetAnnotation with FirrtlOption with HasShellOptions {
def longOption: String = "warn:no-scala-version-deprecation"
val options = Seq(
new ShellOption[Unit](
longOption = longOption,
toAnnotationSeq = { _ =>
val msg = s"'$longOption' no longer does anything and will be removed in FIRRTL 1.6"
firrtl.options.StageUtils.dramaticWarning(msg)
Seq(this)
},
helpText = "(deprecated, this option does nothing)"
)
)
}
/** Turn off all expression inlining
*
* @note this primarily applies to emitted Verilog
*/
case object PrettyNoExprInlining extends NoTargetAnnotation with FirrtlOption with HasShellOptions {
def longOption: String = "pretty:no-expr-inlining"
val options = Seq(
new ShellOption[Unit](
longOption = longOption,
toAnnotationSeq = { _ => Seq(this) },
helpText = "Disable expression inlining"
)
)
}
case object AllowUnrecognizedAnnotations extends NoTargetAnnotation with FirrtlOption with HasShellOptions {
val options = Seq(
new ShellOption[Unit](
longOption = "allow-unrecognized-annotations",
toAnnotationSeq = _ => Seq(this),
helpText = "Allow annotation files to contain unrecognized annotations"
)
)
}
/** Turn off folding a specific primitive operand
* @param op the op that should never be folded
*/
case class DisableFold(op: ir.PrimOp) extends NoTargetAnnotation with FirrtlOption
@deprecated("will be removed and merged into ConstantPropagation in 1.5", "1.4")
object DisableFold extends HasShellOptions {
private val mapping: Map[String, ir.PrimOp] = PrimOps.builtinPrimOps.map { case op => op.toString -> op }.toMap
override val options = Seq(
new ShellOption[String](
longOption = "dont-fold",
toAnnotationSeq = a => {
mapping
.get(a)
.orElse(throw new OptionsException(s"Unknown primop '$a'. (Did you misspell it?)"))
.map(DisableFold(_))
.toSeq
},
helpText = "Disable folding of specific primitive operations",
helpValueName = Some("<primop>")
)
)
}
/** Indicate to the FIRRTL compiler that specific transforms have already been run.
*
* The intended use of this is for advanced users who want to skip specific transforms in the FIRRTL compiler. It is
* far safer for users to use the command line options to the FIRRTL compiler via `--start-from = <form>`.
* @param currentState a sequence of transforms that have already been run on the circuit
*/
case class CurrentFirrtlStateAnnotation(currentState: Seq[TransformDependency])
extends NoTargetAnnotation
with FirrtlOption
private[stage] object CurrentFirrtlStateAnnotation extends HasShellOptions {
/** This is just the transforms necessary for resolving types and checking that everything is okay. */
private val dontSkip: Set[TransformDependency] = Set(
Dependency[firrtl.stage.transforms.CheckScalaVersion],
Dependency(passes.ResolveKinds),
Dependency(passes.InferTypes),
Dependency(passes.ResolveFlows)
) ++ Forms.Checks
override val options = Seq(
new ShellOption[String](
longOption = "start-from",
toAnnotationSeq = a =>
(a match {
case "chirrtl" => Seq.empty
case "mhigh" => Forms.MinimalHighForm
case "high" => Forms.HighForm
case "middle" => Forms.MidForm
case "low" => Forms.LowForm
case "low-opt" => Forms.LowFormOptimized
case _ => throw new OptionsException(s"Unknown start-from argument '$a'! (Did you misspell it?)")
}).filterNot(dontSkip) match {
case b if a.isEmpty => Seq.empty
case b => Seq(CurrentFirrtlStateAnnotation(b))
},
helpText = "",
helpValueName = Some("<chirrtl|mhigh|high|middle|low|low-opt>")
)
)
}
|