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
|
// SPDX-License-Identifier: Apache-2.0
package firrtl
package annotations
import java.io.File
import firrtl.ir._
case class InvalidAnnotationFileException(file: File, cause: FirrtlUserException = null)
extends FirrtlUserException(s"$file", cause)
case class UnrecogizedAnnotationsException(msg: String) extends FirrtlUserException(s"Unrecognized annotations $msg")
case class InvalidAnnotationJSONException(msg: String) extends FirrtlUserException(msg)
case class AnnotationFileNotFoundException(file: File)
extends FirrtlUserException(
s"Annotation file $file not found!"
)
case class AnnotationClassNotFoundException(className: String)
extends FirrtlUserException(
s"Annotation class $className not found! Please check spelling and classpath"
)
class UnserializableAnnotationException private (msg: String) extends FirrtlUserException(msg)
object UnserializableAnnotationException {
private def toMessage(pair: (Annotation, Throwable)): String =
s"Failed to serialiaze annotation of type ${pair._1.getClass.getName} because '${pair._2.getMessage}'"
private[firrtl] def apply(badAnnos: Seq[(Annotation, Throwable)]) = {
require(badAnnos.nonEmpty)
val msg = badAnnos.map(toMessage).mkString("\n ", "\n ", "\n")
new UnserializableAnnotationException(msg)
}
}
object AnnotationUtils {
/** 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))
s.slice(0, i) match {
case "" => s(i).toString +: tokenize(s.drop(i + 1))
case x => x +: s(i).toString +: tokenize(s.drop(i + 1))
}
case None if s == "" => Nil
case None => Seq(s)
}
def toNamed(s: String): Named = s.split("\\.", 3) match {
case Array(n) => CircuitName(n)
case Array(c, m) => ModuleName(m, CircuitName(c))
case Array(c, m, x) => ComponentName(x, ModuleName(m, CircuitName(c)))
}
/** Converts a serialized FIRRTL component into a sequence of target tokens
* @param s
* @return
*/
def toSubComponents(s: String): Seq[TargetToken] = {
import TargetToken._
def exp2subcomp(e: ir.Expression): Seq[TargetToken] = e match {
case ir.Reference(name, _, _, _) => Seq(Ref(name))
case ir.SubField(expr, name, _, _) => exp2subcomp(expr) :+ Field(name)
case ir.SubIndex(expr, idx, _, _) => exp2subcomp(expr) :+ Index(idx)
case ir.SubAccess(expr, idx, _, _) =>
Utils.throwInternalError(s"For string $s, cannot convert a subaccess $e into a Target")
}
exp2subcomp(toExp(s))
}
/** Given a serialized component/subcomponent reference, subindex, subaccess,
* or subfield, return the corresponding IR expression.
* E.g. "foo.bar" becomes SubField(Reference("foo", UnknownType), "bar", UnknownType)
*/
def toExp(s: String): Expression = {
def parse(tokens: Seq[String]): Expression = {
val DecPattern = """(\d+)""".r
def findClose(tokens: Seq[String], index: Int, nOpen: Int): Seq[String] = {
if (index >= tokens.size) {
Utils.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 - 1)
case _ => findClose(tokens, index + 1, nOpen)
}
}
def buildup(e: Expression, tokens: Seq[String]): Expression = tokens match {
case "[" :: tail =>
val indexOrAccess = findClose(tokens, 0, 0)
val exp = indexOrAccess.head match {
case DecPattern(d) => SubIndex(e, d.toInt, UnknownType)
case _ => SubAccess(e, parse(indexOrAccess), UnknownType)
}
buildup(exp, tokens.drop(2 + 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 {
Utils.error(s"Cannot convert $s into an expression.")
}
}
}
|