diff options
| -rw-r--r-- | spec/spec.pdf | bin | 270198 -> 274502 bytes | |||
| -rw-r--r-- | spec/spec.tex | 50 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Compiler.scala | 2 | ||||
| -rw-r--r-- | src/main/scala/firrtl/annotations/JsonProtocol.scala | 2 | ||||
| -rw-r--r-- | src/main/scala/firrtl/options/DependencyManager.scala | 8 | ||||
| -rw-r--r-- | src/main/scala/firrtl/stage/package.scala | 2 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/CustomTransformSpec.scala | 27 |
7 files changed, 81 insertions, 10 deletions
diff --git a/spec/spec.pdf b/spec/spec.pdf Binary files differindex a5e99700..833fb8cf 100644 --- a/spec/spec.pdf +++ b/spec/spec.pdf diff --git a/spec/spec.tex b/spec/spec.tex index a335709d..6bbd798f 100644 --- a/spec/spec.tex +++ b/spec/spec.tex @@ -162,7 +162,7 @@ Types are used to specify the structure of the data held by each circuit compone \subsection{Ground Types} -There are three ground types in FIRRTL: an unsigned integer type, a signed integer type, and a clock type. +There are four ground types in FIRRTL: an unsigned integer type, a signed integer type, a clock type, and an analog type. \subsubsection{Integer Types} @@ -189,6 +189,34 @@ The clock type is specified as follows: Clock \end{lstlisting} +\subsubsection{Analog Type} + +The analog type specifies that a wire or port can be attached to multiple drivers. \verb|Analog| +cannot be used as the type of a node or register, nor can it be used as the datatype of a memory. In +this respect, it is similar to how \verb|inout| ports are used in Verilog, and FIRRTL analog signals +are often used to interface with external Verilog or VHDL IP. + +In contrast with all other ground types, analog signals cannot appear on either side of a connection +statement. Instead, analog signals are attached to each other with the commutative \verb|attach| +statement. An analog signal may appear in any number of attach statements, and a legal circuit may +also contain analog signals that are never attached. The only primitive operations that may be +applied to analog signals are casts to other signal types. + +When an analog signal appears as a field of an aggregate type, the aggregate cannot appear in a +standard connection statement; however, the partial connection statement will \verb|attach| +corresponding analog fields of its operands according to the partial connection algorithm described +in Section \ref{partial_connection_algorithm}. + +As with integer types, an analog type can represent a multi-bit signal. When analog signals are not +given a concrete width, their widths are inferred according to a highly restrictive width inference +rule, which requires that the widths of all arguments to a given attach operation be identical. + +\begin{lstlisting} +Analog<1> ; 1-bit analog type +Analog<32> ; 32-bit analog type +Analog ; analog type with inferred width +\end{lstlisting} + \subsection{Vector Types} A vector type is used to express an ordered sequence of elements of a given type. The length of the sequence must be non-negative and known. @@ -356,7 +384,7 @@ For details on the syntax and semantics of the subfield expression, subindex exp \subsubsection{The Partial Connection Algorithm} \label{partial_connection_algorithm} -A partial connect statement between two ground type components connects the right-hand side expression to the left-hand side expression. Conversely, a {\em reverse} partial connect statement between two ground type components connects the left-hand side expression to the right-hand side expression. +A partial connect statement between two non-analog ground type components connects the right-hand side expression to the left-hand side expression. Conversely, a {\em reverse} partial connect statement between two non-analog ground type components connects the left-hand side expression to the right-hand side expression. A partial connect statement between two analog-typed components performs an attach between the two signals. A partial (or reverse partial) connect statement between two vector typed components applies a partial (or reverse partial) connect from the first n subelements in the right-hand side expression to the first n corresponding subelements in the left-hand side expression, where n is the length of the shorter vector. @@ -513,6 +541,24 @@ Invalidating a component with a vector type recursively invalidates each subelem Invalidating a component with a bundle type recursively invalidates each subelement in the bundle. +\subsection{Attaches} + +The \verb|attach| statement is used to attach two or more analog signals, defining that their +values be the same in a commutative fashion that lacks the directionality of a regular connection. +It can only be applied to signals with analog type, and each analog signal may be attached zero or +more times. + +\begin{lstlisting} +wire x: Analog<2> +wire y: Analog<2> +wire z: Analog<2> +attach(x, y) ; binary attach +attach(z, y, x) ; attach all three signals +\end{lstlisting} + +When signals of aggregate types that contain analog-typed fields are used as operators of a partial +connection, corresponding fields of analog type are attached, rather than connected. + \subsection{Nodes} A node is simply a named intermediate value in a circuit. The node must be initialized to a value with a passive type and cannot be connected to. Nodes are often used to split a complicated compound expression into named subexpressions. diff --git a/src/main/scala/firrtl/Compiler.scala b/src/main/scala/firrtl/Compiler.scala index 600b991e..9014d213 100644 --- a/src/main/scala/firrtl/Compiler.scala +++ b/src/main/scala/firrtl/Compiler.scala @@ -171,7 +171,7 @@ final case object UnknownForm extends CircuitForm(-1) { /** The basic unit of operating on a Firrtl AST */ abstract class Transform extends TransformLike[CircuitState] { /** A convenience function useful for debugging and error messages */ - def name: String = this.getClass.getSimpleName + def name: String = this.getClass.getName /** The [[firrtl.CircuitForm]] that this transform requires to operate on */ def inputForm: CircuitForm /** The [[firrtl.CircuitForm]] that this transform outputs */ diff --git a/src/main/scala/firrtl/annotations/JsonProtocol.scala b/src/main/scala/firrtl/annotations/JsonProtocol.scala index c3853650..9992400a 100644 --- a/src/main/scala/firrtl/annotations/JsonProtocol.scala +++ b/src/main/scala/firrtl/annotations/JsonProtocol.scala @@ -109,7 +109,7 @@ object JsonProtocol { val annos = parsed match { case JArray(objs) => objs case x => throw new InvalidAnnotationJSONException( - s"Annotations must be serialized as a JArray, got ${x.getClass.getSimpleName} instead!") + s"Annotations must be serialized as a JArray, got ${x.getClass.getName} instead!") } // Recursively gather typeHints by pulling the "class" field from JObjects // Json4s should emit this as the first field in all serialized classes diff --git a/src/main/scala/firrtl/options/DependencyManager.scala b/src/main/scala/firrtl/options/DependencyManager.scala index 1de8095b..604a1b10 100644 --- a/src/main/scala/firrtl/options/DependencyManager.scala +++ b/src/main/scala/firrtl/options/DependencyManager.scala @@ -291,7 +291,7 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends val nodes = (prerequisiteGraph + dependentsGraph + invalidateGraph + otherDependents) .getVertices - .map(v => s"""${transformName(v)} [label="${v.getClass.getSimpleName}"]""") + .map(v => s"""${transformName(v)} [label="${v.getClass.getName}"]""") s"""|digraph DependencyManager { | graph [rankdir=BT] @@ -315,8 +315,8 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends def rec(pm: DependencyManager[A, B], cm: Seq[String], tab: String = "", id: Int = 0): (String, Int) = { var offset = id - val targets = pm._targets.toSeq.map(_.getSimpleName).mkString(", ") - val state = pm._currentState.toSeq.map(_.getSimpleName).mkString(", ") + val targets = pm._targets.toSeq.map(_.getName).mkString(", ") + val state = pm._currentState.toSeq.map(_.getName).mkString(", ") val header = s"""|${tab}subgraph cluster_$id { |$tab label="targets: $targets\\nstate: $state" @@ -331,7 +331,7 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends case a => val name = s"""${transformName(a, "_" + id)}""" sorted += name - s"""$tab $name [label="${a.getClass.getSimpleName}"]""" + s"""$tab $name [label="${a.getClass.getName}"]""" }.mkString("\n") (Seq(header, body, s"$tab}").mkString("\n"), offset) diff --git a/src/main/scala/firrtl/stage/package.scala b/src/main/scala/firrtl/stage/package.scala index 89a61914..d0a481fb 100644 --- a/src/main/scala/firrtl/stage/package.scala +++ b/src/main/scala/firrtl/stage/package.scala @@ -49,7 +49,7 @@ package object stage { options.collectFirst{ case a: FirrtlCircuitAnnotation => a.circuit } match { case None => FirrtlExecutionFailure("No circuit found in AnnotationSeq!") case Some(a) => FirrtlExecutionSuccess( - emitType = fopts.compiler.getClass.getSimpleName, + emitType = fopts.compiler.getClass.getName, emitted = emittedRes, circuitState = CircuitState( circuit = a, diff --git a/src/test/scala/firrtlTests/CustomTransformSpec.scala b/src/test/scala/firrtlTests/CustomTransformSpec.scala index 1b0e8190..e0ed6fdb 100644 --- a/src/test/scala/firrtlTests/CustomTransformSpec.scala +++ b/src/test/scala/firrtlTests/CustomTransformSpec.scala @@ -6,6 +6,8 @@ import firrtl.ir.Circuit import firrtl._ import firrtl.passes.Pass import firrtl.ir._ +import firrtl.annotations.{Annotation, NoTargetAnnotation} +import firrtl.stage.{FirrtlSourceAnnotation, FirrtlStage, RunFirrtlTransformAnnotation} class CustomTransformSpec extends FirrtlFlatSpec { behavior of "Custom Transforms" @@ -71,5 +73,28 @@ class CustomTransformSpec extends FirrtlFlatSpec { Driver.execute(optionsManager) }).getMessage should include (errorString) } -} + object Foo { + class A extends Transform { + def inputForm = HighForm + def outputForm = HighForm + def execute(s: CircuitState) = { + println(name) + s + } + } + } + + they should "work if placed inside an object" in { + val input = + """|circuit Foo: + | module Foo: + | node a = UInt<1>(0) + |""".stripMargin + val annotations = Seq( + RunFirrtlTransformAnnotation(new Foo.A), + FirrtlSourceAnnotation(input) + ) + (new FirrtlStage).execute(Array.empty, annotations) + } +} |
