aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/Compiler.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/firrtl/Compiler.scala')
-rw-r--r--src/main/scala/firrtl/Compiler.scala200
1 files changed, 116 insertions, 84 deletions
diff --git a/src/main/scala/firrtl/Compiler.scala b/src/main/scala/firrtl/Compiler.scala
index 80ba42c4..9044c5a8 100644
--- a/src/main/scala/firrtl/Compiler.scala
+++ b/src/main/scala/firrtl/Compiler.scala
@@ -4,23 +4,121 @@ package firrtl
import logger._
import java.io.Writer
-
-import firrtl.RenameMap.{CircularRenameException, IllegalRenameException}
-
+import annotations._
import scala.collection.mutable
-import firrtl.annotations._
-import firrtl.ir.{Circuit, Expression}
+
+import firrtl.annotations._ // Note that wildcard imports are not great....
+import firrtl.ir.Circuit
import firrtl.Utils.{error, throwInternalError}
-import firrtl.annotations.TargetToken
-import firrtl.annotations.TargetToken.{Field, Index}
-import firrtl.annotations.transforms.{EliminateTargetPaths, ResolvePaths}
+
+object RenameMap {
+ def apply(map: Map[Named, Seq[Named]]) = {
+ val rm = new RenameMap
+ rm.addMap(map)
+ rm
+ }
+ def apply() = new RenameMap
+}
+/** Map old names to new names
+ *
+ * Transforms that modify names should return a [[RenameMap]] with the [[CircuitState]]
+ * These are mutable datastructures for convenience
+ */
+// TODO This should probably be refactored into immutable and mutable versions
+final class RenameMap private () {
+ private val underlying = mutable.HashMap[Named, Seq[Named]]()
+
+ /** Get renames of a [[CircuitName]]
+ * @note A [[CircuitName]] can only be renamed to a single [[CircuitName]]
+ */
+ def get(key: CircuitName): Option[CircuitName] = underlying.get(key).map {
+ case Seq(c: CircuitName) => c
+ case other => error(s"Unsupported Circuit rename to $other!")
+ }
+ /** Get renames of a [[ModuleName]]
+ * @note A [[ModuleName]] can only be renamed to one-or-more [[ModuleName]]s
+ */
+ def get(key: ModuleName): Option[Seq[ModuleName]] = {
+ def nestedRename(m: ModuleName): Option[Seq[ModuleName]] =
+ this.get(m.circuit).map(cname => Seq(ModuleName(m.name, cname)))
+ underlying.get(key) match {
+ case Some(names) => Some(names.flatMap {
+ case m: ModuleName =>
+ nestedRename(m).getOrElse(Seq(m))
+ case other => error(s"Unsupported Module rename of $key to $other")
+ })
+ case None => nestedRename(key)
+ }
+ }
+ /** Get renames of a [[ComponentName]]
+ * @note A [[ComponentName]] can only be renamed to one-or-more [[ComponentName]]s
+ */
+ def get(key: ComponentName): Option[Seq[ComponentName]] = {
+ def nestedRename(c: ComponentName): Option[Seq[ComponentName]] =
+ this.get(c.module).map { modules =>
+ modules.map(mname => ComponentName(c.name, mname))
+ }
+ underlying.get(key) match {
+ case Some(names) => Some(names.flatMap {
+ case c: ComponentName =>
+ nestedRename(c).getOrElse(Seq(c))
+ case other => error(s"Unsupported Component rename of $key to $other")
+ })
+ case None => nestedRename(key)
+ }
+ }
+ /** Get new names for an old name
+ *
+ * This is analogous to get on standard Scala collection Maps
+ * None indicates the key was not renamed
+ * Empty indicates the name was deleted
+ */
+ def get(key: Named): Option[Seq[Named]] = key match {
+ case c: ComponentName => this.get(c)
+ case m: ModuleName => this.get(m)
+ // The CircuitName version returns Option[CircuitName]
+ case c: CircuitName => this.get(c).map(Seq(_))
+ }
+
+ // Mutable helpers
+ private var circuitName: String = ""
+ private var moduleName: String = ""
+ def setModule(s: String) =
+ moduleName = s
+ def setCircuit(s: String) =
+ circuitName = s
+ def rename(from: String, to: String): Unit = rename(from, Seq(to))
+ def rename(from: String, tos: Seq[String]): Unit = {
+ val fromName = ComponentName(from, ModuleName(moduleName, CircuitName(circuitName)))
+ val tosName = tos map { to =>
+ ComponentName(to, ModuleName(moduleName, CircuitName(circuitName)))
+ }
+ rename(fromName, tosName)
+ }
+ def rename(from: Named, to: Named): Unit = rename(from, Seq(to))
+ def rename(from: Named, tos: Seq[Named]): Unit = (from, tos) match {
+ case (x, Seq(y)) if x == y => // TODO is this check expensive in common case?
+ case _ =>
+ underlying(from) = underlying.getOrElse(from, Seq.empty) ++ tos
+ }
+ def delete(names: Seq[String]): Unit = names.foreach(delete(_))
+ def delete(name: String): Unit =
+ delete(ComponentName(name, ModuleName(moduleName, CircuitName(circuitName))))
+ def delete(name: Named): Unit =
+ underlying(name) = Seq.empty
+ def addMap(map: Map[Named, Seq[Named]]) =
+ underlying ++= map
+ def serialize: String = underlying.map { case (k, v) =>
+ k.serialize + "=>" + v.map(_.serialize).mkString(", ")
+ }.mkString("\n")
+}
/** Container of all annotations for a Firrtl compiler */
class AnnotationSeq private (private[firrtl] val underlying: List[Annotation]) {
def toSeq: Seq[Annotation] = underlying.toSeq
}
object AnnotationSeq {
- def apply(xs: Seq[Annotation]): AnnotationSeq = new AnnotationSeq(xs.toList)
+ def apply(xs: Seq[Annotation]) = new AnnotationSeq(xs.toList)
}
/** Current State of the Circuit
@@ -47,45 +145,15 @@ case class CircuitState(
case None =>
throw new FIRRTLException(s"No EmittedCircuit found! Did you delete any annotations?\n$deletedAnnotations")
}
-
/** Helper function for extracting emitted components from annotations */
def emittedComponents: Seq[EmittedComponent] =
annotations.collect { case emitted: EmittedAnnotation[_] => emitted.value }
def deletedAnnotations: Seq[Annotation] =
annotations.collect { case anno: DeletedAnnotation => anno }
-
- /** Returns a new CircuitState with all targets being resolved.
- * Paths through instances are replaced with a uniquified final target
- * Includes modifying the circuit and annotations
- * @param targets
- * @return
- */
- def resolvePaths(targets: Seq[CompleteTarget]): CircuitState = {
- val newCS = new EliminateTargetPaths().runTransform(this.copy(annotations = ResolvePaths(targets) +: annotations ))
- newCS.copy(form = form)
- }
-
- /** Returns a new CircuitState with the targets of every annotation of a type in annoClasses
- * @param annoClasses
- * @return
- */
- def resolvePathsOf(annoClasses: Class[_]*): CircuitState = {
- val targets = getAnnotationsOf(annoClasses:_*).flatMap(_.getTargets)
- if(targets.nonEmpty) resolvePaths(targets.flatMap{_.getComplete}) else this
- }
-
- /** Returns all annotations which are of a class in annoClasses
- * @param annoClasses
- * @return
- */
- def getAnnotationsOf(annoClasses: Class[_]*): AnnotationSeq = {
- annotations.collect { case a if annoClasses.contains(a.getClass) => a }
- }
}
-
object CircuitState {
def apply(circuit: Circuit, form: CircuitForm): CircuitState = apply(circuit, form, Seq())
- def apply(circuit: Circuit, form: CircuitForm, annotations: AnnotationSeq): CircuitState =
+ def apply(circuit: Circuit, form: CircuitForm, annotations: AnnotationSeq) =
new CircuitState(circuit, form, annotations, None)
}
@@ -102,9 +170,6 @@ sealed abstract class CircuitForm(private val value: Int) extends Ordered[Circui
// Note that value is used only to allow comparisons
def compare(that: CircuitForm): Int = this.value - that.value
}
-
-// scalastyle:off magic.number
-// These magic numbers give an ordering to CircuitForm
/** Chirrtl Form
*
* The form of the circuit emitted by Chisel. Not a true Firrtl form.
@@ -113,7 +178,7 @@ sealed abstract class CircuitForm(private val value: Int) extends Ordered[Circui
*
* See [[CDefMemory]] and [[CDefMPort]]
*/
-final case object ChirrtlForm extends CircuitForm(value = 3)
+final case object ChirrtlForm extends CircuitForm(3)
/** High Form
*
* As detailed in the Firrtl specification
@@ -151,7 +216,6 @@ final case object LowForm extends CircuitForm(0)
final case object UnknownForm extends CircuitForm(-1) {
override def compare(that: CircuitForm): Int = { sys.error("Illegal to compare UnknownForm"); 0 }
}
-// scalastyle:on magic.number
/** The basic unit of operating on a Firrtl AST */
abstract class Transform extends LazyLogging {
@@ -182,12 +246,6 @@ abstract class Transform extends LazyLogging {
state.annotations.collect { case a: LegacyAnnotation if a.transform == this.getClass => a }
}
- /** Executes before any transform's execute method
- * @param state
- * @return
- */
- private[firrtl] def prepare(state: CircuitState): CircuitState = state
-
/** Perform the transform and update annotations.
*
* @param state Input Firrtl AST
@@ -196,7 +254,7 @@ abstract class Transform extends LazyLogging {
final def runTransform(state: CircuitState): CircuitState = {
logger.info(s"======== Starting Transform $name ========")
- val (timeMillis, result) = Utils.time { execute(prepare(state)) }
+ val (timeMillis, result) = Utils.time { execute(state) }
logger.info(s"""----------------------------${"-" * name.size}---------\n""")
logger.info(f"Time: $timeMillis%.1f ms")
@@ -238,23 +296,10 @@ abstract class Transform extends LazyLogging {
// For each annotation, rename all annotations.
val renames = renameOpt.getOrElse(RenameMap())
- val remapped2original = mutable.LinkedHashMap[Annotation, mutable.LinkedHashSet[Annotation]]()
- val keysOfNote = mutable.LinkedHashSet[Annotation]()
- val finalAnnotations = newAnnotations.flatMap { anno =>
- val remappedAnnos = anno.update(renames)
- remappedAnnos.foreach { remapped =>
- val set = remapped2original.getOrElseUpdate(remapped, mutable.LinkedHashSet.empty[Annotation])
- set += anno
- if(set.size > 1) keysOfNote += remapped
- }
- remappedAnnos
- }.toSeq
- keysOfNote.foreach { key =>
- logger.debug(s"""The following original annotations are renamed to the same new annotation.""")
- logger.debug(s"""Original Annotations:\n ${remapped2original(key).mkString("\n ")}""")
- logger.debug(s"""New Annotation:\n $key""")
- }
- finalAnnotations
+ for {
+ anno <- newAnnotations.toSeq
+ newAnno <- anno.update(renames)
+ } yield newAnno
}
}
@@ -276,19 +321,6 @@ abstract class SeqTransform extends Transform with SeqTransformBased {
}
}
-/** Extend for transforms that require resolved targets in their annotations
- * Ensures all targets in annotations of a class in annotationClasses are resolved before the execute method
- */
-trait ResolvedAnnotationPaths {
- this: Transform =>
-
- val annotationClasses: Traversable[Class[_]]
-
- override def prepare(state: CircuitState): CircuitState = {
- state.resolvePathsOf(annotationClasses.toSeq:_*)
- }
-}
-
/** Defines old API for Emission. Deprecated */
trait Emitter extends Transform {
@deprecated("Use emission annotations instead", "firrtl 1.0")
@@ -374,8 +406,8 @@ trait Compiler extends LazyLogging {
def transforms: Seq[Transform]
// Similar to (input|output)Form on [[Transform]] but derived from this Compiler's transforms
- def inputForm: CircuitForm = transforms.head.inputForm
- def outputForm: CircuitForm = transforms.last.outputForm
+ def inputForm = transforms.head.inputForm
+ def outputForm = transforms.last.outputForm
private def transformsLegal(xforms: Seq[Transform]): Boolean =
if (xforms.size < 2) {