diff options
| author | Adam Izraelevitz | 2016-11-23 11:57:02 -0800 |
|---|---|---|
| committer | Jack Koenig | 2016-11-23 11:57:02 -0800 |
| commit | 66d3ec0498a73319a914eeffcb4e0b1109b5f4c5 (patch) | |
| tree | 325066fd05cc72b544d3b4d78d646e1a864119f3 /src/main/scala/firrtl/Annotations.scala | |
| parent | 9a967a27aa8bb51f4b62969d2889f9a9caa48e31 (diff) | |
Stringified annotations (#367)
Restricts annotations to be string-based (and thus less typesafe)
Makes annotations more easily serializable and interact with Chisel
Diffstat (limited to 'src/main/scala/firrtl/Annotations.scala')
| -rw-r--r-- | src/main/scala/firrtl/Annotations.scala | 239 |
1 files changed, 0 insertions, 239 deletions
diff --git a/src/main/scala/firrtl/Annotations.scala b/src/main/scala/firrtl/Annotations.scala deleted file mode 100644 index b502e055..00000000 --- a/src/main/scala/firrtl/Annotations.scala +++ /dev/null @@ -1,239 +0,0 @@ -// See LICENSE for license details. - -package firrtl - -import firrtl.ir._ - -import scala.collection.mutable -import java.io.Writer - - -/** - * Firrtl Annotation Library - * - * WARNING(izraelevitz): Untested, and requires unit tests, which require the - * LowerTypes pass and ConstProp pass to correctly populate its RenameMap. - * - * The following tables explain how Tenacity and Permissibility interact - * with different RenameMap scenarios: - * x -> x : a component named "x" is renamed to the same name, "x" - * x -> y : a component named "x" is renamed to a different name, "y" - * x -> y,z : a component named "x" is split into two components named "y" and "z" - * x -> () : a component named "x" is removed - * - * Tenacity Propagation Behavior: - * ----------|----------|----------|------------|-----------| - * | x -> x | x -> y | x -> y,z | x -> () | - * ----------|----------|----------|------------|-----------| - * Unstable | x | () | () | () | - * Fickle | x | y | () | () | - * Insistent | x | y | y | () | - * Sticky | x | y | y,z | () | - * ----------|----------|----------|------------|-----------| - * - * Permissibility Accepted Ranges: - * ----------|----------|----------|------------|-----------| - * | x -> x | x -> y | x -> y,z | x -> () | - * ----------|----------|----------|------------|-----------| - * Strict | ok | error | error | error | - * Rigid | ok | ok | error | error | - * Firm | ok | ok | ok | error | - * Loose | ok | ok | ok | ok | - * ----------|----------|----------|------------|-----------| - */ -object Annotations { - /** Returns true if a valid Module name */ - val SerializedModuleName = """([a-zA-Z_][a-zA-Z_0-9~!@#$%^*\-+=?/]*)""".r - def validModuleName(s: String): Boolean = s match { - case SerializedModuleName(name) => true - case _ => false - } - - /** Returns true if a valid component/subcomponent name */ - val SerializedComponentName = """([a-zA-Z_][a-zA-Z_0-9\[\]\.~!@#$%^*\-+=?/]*)""".r - def validComponentName(s: String): Boolean = s match { - case SerializedComponentName(name) => true - case _ => false - } - - /** Tokenizes a string with '[', ']', '.' as tokens, e.g.: - * "foo.bar[boo.far]" becomes Seq("foo" "." "bar" "[" "boo" "." "far" "]") - */ - def tokenize(s: String): Seq[String] = s.find(c => "[].".contains(c)) match { - case Some(_) => - val i = s.indexWhere(c => "[].".contains(c)) - Seq(s.slice(0, i), s(i).toString) ++ tokenize(s.drop(i + 1)) - case None => Seq(s) - } - - /** Given a serialized component/subcomponent reference, subindex, subaccess, - * or subfield, return the corresponding IR expression. - */ - def toExp(s: String): Expression = { - def parse(tokens: Seq[String]): Expression = { - val DecPattern = """([1-9]\d*)""".r - def findClose(tokens: Seq[String], index: Int, nOpen: Int): Seq[String] = - if(index >= tokens.size) { - error("Cannot find closing bracket ]") - } else tokens(index) match { - case "[" => findClose(tokens, index + 1, nOpen + 1) - case "]" if nOpen == 1 => tokens.slice(1, index) - case _ => findClose(tokens, index + 1, nOpen) - } - def buildup(e: Expression, tokens: Seq[String]): Expression = tokens match { - case "[" :: tail => - val indexOrAccess = findClose(tokens, 0, 0) - indexOrAccess.head match { - case DecPattern(d) => SubIndex(e, d.toInt, UnknownType) - case _ => buildup(SubAccess(e, parse(indexOrAccess), UnknownType), tokens.slice(1, indexOrAccess.size)) - } - case "." :: tail => - buildup(SubField(e, tokens(1), UnknownType), tokens.drop(2)) - case Nil => e - } - val root = Reference(tokens.head, UnknownType) - buildup(root, tokens.tail) - } - if(validComponentName(s)) { - parse(tokenize(s)) - } else error(s"Cannot convert $s into an expression.") - } - - case class AnnotationException(message: String) extends Exception(message) - - /** - * Named classes associate an annotation with a component in a Firrtl circuit - */ - trait Named { def name: String } - case class CircuitName(name: String) extends Named { - if(!validModuleName(name)) throw AnnotationException(s"Illegal circuit name: $name") - } - case class ModuleName(name: String, circuit: CircuitName) extends Named { - if(!validModuleName(name)) throw AnnotationException(s"Illegal module name: $name") - } - case class ComponentName(name: String, module: ModuleName) extends Named { - if(!validComponentName(name)) throw AnnotationException(s"Illegal component name: $name") - def expr: Expression = toExp(name) - } - - /** - * Permissibility defines the range of acceptable changes to the annotated component. - */ - trait Permissibility { - def check(from: Named, tos: Seq[Named], which: Annotation): Unit - } - /** - * Annotated component cannot be renamed, expanded, or removed. - */ - trait Strict extends Permissibility { - def check(from: Named, tos: Seq[Named], which: Annotation): Unit = tos.size match { - case 0 => - throw new AnnotationException(s"Cannot remove the strict annotation ${which.serialize} on ${from.name}") - case 1 if from != tos.head => - throw new AnnotationException(s"Cannot rename the strict annotation ${which.serialize} on ${from.name} -> ${tos.head.name}") - case _ => - throw new AnnotationException(s"Cannot expand a strict annotation on ${from.name} -> ${tos.map(_.name)}") - } - } - - /** - * Annotated component can be renamed, but cannot be expanded or removed. - */ - trait Rigid extends Permissibility { - def check(from: Named, tos: Seq[Named], which: Annotation): Unit = tos.size match { - case 0 => throw new AnnotationException(s"Cannot remove the rigid annotation ${which.serialize} on ${from.name}") - case 1 => - case _ => throw new AnnotationException(s"Cannot expand a rigid annotation on ${from.name} -> ${tos.map(_.name)}") - } - } - - /** - * Annotated component can be renamed, and expanded, but not removed. - */ - trait Firm extends Permissibility { - def check(from: Named, tos: Seq[Named], which: Annotation): Unit = tos.size match { - case 0 => throw new AnnotationException(s"Cannot remove the firm annotation ${which.serialize} on ${from.name}") - case _ => - } - } - - /** - * Annotated component can be renamed, and expanded, and removed. - */ - trait Loose extends Permissibility { - def check(from: Named, tos: Seq[Named], which: Annotation): Unit = {} - } - - /** - * Tenacity defines how the annotation propagates when changes to the - * annotated component occur. - */ - trait Tenacity { - protected def propagate(from: Named, tos: Seq[Named], dup: Named=>Annotation): Seq[Annotation] - } - - /** - * Annotation propagates to all new components - */ - trait Sticky extends Tenacity { - protected def propagate(from: Named, tos: Seq[Named], dup: Named=>Annotation): Seq[Annotation] = tos.map(dup(_)) - } - - /** - * Annotation propagates to the first of all new components - */ - trait Insistent extends Tenacity { - protected def propagate(from: Named, tos: Seq[Named], dup: Named=>Annotation): Seq[Annotation] = tos.headOption match { - case None => Seq.empty - case Some(n) => Seq(dup(n)) - } - } - - /** - * Annotation propagates only if there is one new component. - */ - trait Fickle extends Tenacity { - protected def propagate(from: Named, tos: Seq[Named], dup: Named=>Annotation): Seq[Annotation] = tos.size match { - case 1 => Seq(dup(tos.head)) - case _ => Seq.empty - } - } - - /** - * Annotation propagates only the new component shares the same name. - */ - trait Unstable extends Tenacity { - protected def propagate(from: Named, tos: Seq[Named], dup: Named=>Annotation): Seq[Annotation] = tos.size match { - case 1 if tos.head == from => Seq(dup(tos.head)) - case _ => Seq.empty - } - } - - /** - * Annotation associates with a given named circuit component (target) and a - * given transformation (transform). Also defined are the legal ranges of changes - * to the associated component (Permissibility) and how the annotation - * propagates under such changes (Tenacity). Subclasses must implement the - * duplicate function to create the same annotation associated with a new - * component. - */ - trait Annotation extends Permissibility with Tenacity { - def target: Named - def transform: Class[_ <: Transform] - protected def duplicate(n: Named): Annotation - def serialize: String = this.toString - def update(tos: Seq[Named]): Seq[Annotation] = { - check(target, tos, this) - propagate(target, tos, duplicate) - } - } - - /** - * Container of all annotations for a Firrtl compiler. - */ - case class AnnotationMap(annotations: Seq[Annotation]) { - def get(id: Class[_]): Seq[Annotation] = annotations.filter(a => a.transform == id) - def get(named: Named): Seq[Annotation] = annotations.filter(n => n == named) - } -} - |
