aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/passes/Passes.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/firrtl/passes/Passes.scala')
-rw-r--r--src/main/scala/firrtl/passes/Passes.scala367
1 files changed, 0 insertions, 367 deletions
diff --git a/src/main/scala/firrtl/passes/Passes.scala b/src/main/scala/firrtl/passes/Passes.scala
deleted file mode 100644
index a8d37758..00000000
--- a/src/main/scala/firrtl/passes/Passes.scala
+++ /dev/null
@@ -1,367 +0,0 @@
-// See LICENSE for license details.
-
-package firrtl.passes
-
-import firrtl._
-import firrtl.ir._
-import firrtl.Utils._
-import firrtl.Mappers._
-import firrtl.PrimOps._
-import firrtl.options.{Dependency, PreservesAll}
-import firrtl.transforms.ConstantPropagation
-
-import scala.collection.mutable
-
-/** [[Pass]] is simple transform that is generally part of a larger [[Transform]]
- * Has an [[UnknownForm]], because larger [[Transform]] should specify form
- */
-trait Pass extends Transform {
- def inputForm: CircuitForm = UnknownForm
- def outputForm: CircuitForm = UnknownForm
- def run(c: Circuit): Circuit
- def execute(state: CircuitState): CircuitState = {
- val result = (state.form, inputForm) match {
- case (_, UnknownForm) => run(state.circuit)
- case (UnknownForm, _) => run(state.circuit)
- case (x, y) if x > y =>
- error(s"[$name]: Input form must be lower or equal to $inputForm. Got ${state.form}")
- case _ => run(state.circuit)
- }
- CircuitState(result, outputForm, state.annotations, state.renames)
- }
-}
-
-// Error handling
-class PassException(message: String) extends FirrtlUserException(message)
-class PassExceptions(val exceptions: Seq[PassException]) extends FirrtlUserException("\n" + exceptions.mkString("\n"))
-class Errors {
- val errors = collection.mutable.ArrayBuffer[PassException]()
- def append(pe: PassException) = errors.append(pe)
- def trigger() = errors.size match {
- case 0 =>
- case 1 => throw errors.head
- case _ =>
- append(new PassException(s"${errors.length} errors detected!"))
- throw new PassExceptions(errors)
- }
-}
-
-// These should be distributed into separate files
-object ToWorkingIR extends Pass with PreservesAll[Transform] {
-
- override val prerequisites = firrtl.stage.Forms.MinimalHighForm
-
- def toExp(e: Expression): Expression = e map toExp match {
- case ex: Reference => WRef(ex.name, ex.tpe, UnknownKind, UnknownFlow)
- case ex: SubField => WSubField(ex.expr, ex.name, ex.tpe, UnknownFlow)
- case ex: SubIndex => WSubIndex(ex.expr, ex.value, ex.tpe, UnknownFlow)
- case ex: SubAccess => WSubAccess(ex.expr, ex.index, ex.tpe, UnknownFlow)
- case ex => ex // This might look like a case to use case _ => e, DO NOT!
- }
-
- def toStmt(s: Statement): Statement = s map toExp match {
- case sx: DefInstance => WDefInstance(sx.info, sx.name, sx.module, UnknownType)
- case sx => sx map toStmt
- }
-
- def run (c:Circuit): Circuit =
- c copy (modules = c.modules map (_ map toStmt))
-}
-
-object PullMuxes extends Pass with PreservesAll[Transform] {
-
- override val prerequisites = firrtl.stage.Forms.Deduped
-
- def run(c: Circuit): Circuit = {
- def pull_muxes_e(e: Expression): Expression = e map pull_muxes_e match {
- case ex: WSubField => ex.expr match {
- case exx: Mux => Mux(exx.cond,
- WSubField(exx.tval, ex.name, ex.tpe, ex.flow),
- WSubField(exx.fval, ex.name, ex.tpe, ex.flow), ex.tpe)
- case exx: ValidIf => ValidIf(exx.cond,
- WSubField(exx.value, ex.name, ex.tpe, ex.flow), ex.tpe)
- case _ => ex // case exx => exx causes failed tests
- }
- case ex: WSubIndex => ex.expr match {
- case exx: Mux => Mux(exx.cond,
- WSubIndex(exx.tval, ex.value, ex.tpe, ex.flow),
- WSubIndex(exx.fval, ex.value, ex.tpe, ex.flow), ex.tpe)
- case exx: ValidIf => ValidIf(exx.cond,
- WSubIndex(exx.value, ex.value, ex.tpe, ex.flow), ex.tpe)
- case _ => ex // case exx => exx causes failed tests
- }
- case ex: WSubAccess => ex.expr match {
- case exx: Mux => Mux(exx.cond,
- WSubAccess(exx.tval, ex.index, ex.tpe, ex.flow),
- WSubAccess(exx.fval, ex.index, ex.tpe, ex.flow), ex.tpe)
- case exx: ValidIf => ValidIf(exx.cond,
- WSubAccess(exx.value, ex.index, ex.tpe, ex.flow), ex.tpe)
- case _ => ex // case exx => exx causes failed tests
- }
- case ex => ex
- }
- def pull_muxes(s: Statement): Statement = s map pull_muxes map pull_muxes_e
- val modulesx = c.modules.map {
- case (m:Module) => Module(m.info, m.name, m.ports, pull_muxes(m.body))
- case (m:ExtModule) => m
- }
- Circuit(c.info, modulesx, c.main)
- }
-}
-
-object ExpandConnects extends Pass with PreservesAll[Transform] {
-
- override val prerequisites =
- Seq( Dependency(PullMuxes),
- Dependency(ReplaceAccesses) ) ++ firrtl.stage.Forms.Deduped
-
- def run(c: Circuit): Circuit = {
- def expand_connects(m: Module): Module = {
- val flows = collection.mutable.LinkedHashMap[String,Flow]()
- def expand_s(s: Statement): Statement = {
- def set_flow(e: Expression): Expression = e map set_flow match {
- case ex: WRef => WRef(ex.name, ex.tpe, ex.kind, flows(ex.name))
- case ex: WSubField =>
- val f = get_field(ex.expr.tpe, ex.name)
- val flowx = times(flow(ex.expr), f.flip)
- WSubField(ex.expr, ex.name, ex.tpe, flowx)
- case ex: WSubIndex => WSubIndex(ex.expr, ex.value, ex.tpe, flow(ex.expr))
- case ex: WSubAccess => WSubAccess(ex.expr, ex.index, ex.tpe, flow(ex.expr))
- case ex => ex
- }
- s match {
- case sx: DefWire => flows(sx.name) = DuplexFlow; sx
- case sx: DefRegister => flows(sx.name) = DuplexFlow; sx
- case sx: WDefInstance => flows(sx.name) = SourceFlow; sx
- case sx: DefMemory => flows(sx.name) = SourceFlow; sx
- case sx: DefNode => flows(sx.name) = SourceFlow; sx
- case sx: IsInvalid =>
- val invalids = create_exps(sx.expr).flatMap { case expx =>
- flow(set_flow(expx)) match {
- case DuplexFlow => Some(IsInvalid(sx.info, expx))
- case SinkFlow => Some(IsInvalid(sx.info, expx))
- case _ => None
- }
- }
- invalids.size match {
- case 0 => EmptyStmt
- case 1 => invalids.head
- case _ => Block(invalids)
- }
- case sx: Connect =>
- val locs = create_exps(sx.loc)
- val exps = create_exps(sx.expr)
- Block(locs.zip(exps).map { case (locx, expx) =>
- to_flip(flow(locx)) match {
- case Default => Connect(sx.info, locx, expx)
- case Flip => Connect(sx.info, expx, locx)
- }
- })
- case sx: PartialConnect =>
- val ls = get_valid_points(sx.loc.tpe, sx.expr.tpe, Default, Default)
- val locs = create_exps(sx.loc)
- val exps = create_exps(sx.expr)
- val stmts = ls map { case (x, y) =>
- locs(x).tpe match {
- case AnalogType(_) => Attach(sx.info, Seq(locs(x), exps(y)))
- case _ =>
- to_flip(flow(locs(x))) match {
- case Default => Connect(sx.info, locs(x), exps(y))
- case Flip => Connect(sx.info, exps(y), locs(x))
- }
- }
- }
- Block(stmts)
- case sx => sx map expand_s
- }
- }
-
- m.ports.foreach { p => flows(p.name) = to_flow(p.direction) }
- Module(m.info, m.name, m.ports, expand_s(m.body))
- }
-
- val modulesx = c.modules.map {
- case (m: ExtModule) => m
- case (m: Module) => expand_connects(m)
- }
- Circuit(c.info, modulesx, c.main)
- }
-}
-
-
-// Replace shr by amount >= arg width with 0 for UInts and MSB for SInts
-// TODO replace UInt with zero-width wire instead
-object Legalize extends Pass with PreservesAll[Transform] {
-
- override val prerequisites = firrtl.stage.Forms.MidForm :+ Dependency(LowerTypes)
-
- override val optionalPrerequisites = Seq.empty
-
- override val dependents = Seq.empty
-
- private def legalizeShiftRight(e: DoPrim): Expression = {
- require(e.op == Shr)
- e.args.head match {
- case _: UIntLiteral | _: SIntLiteral => ConstantPropagation.foldShiftRight(e)
- case _ =>
- val amount = e.consts.head.toInt
- val width = bitWidth(e.args.head.tpe)
- lazy val msb = width - 1
- if (amount >= width) {
- e.tpe match {
- case UIntType(_) => zero
- case SIntType(_) =>
- val bits = DoPrim(Bits, e.args, Seq(msb, msb), BoolType)
- DoPrim(AsSInt, Seq(bits), Seq.empty, SIntType(IntWidth(1)))
- case t => error(s"Unsupported type $t for Primop Shift Right")
- }
- } else {
- e
- }
- }
- }
- private def legalizeBitExtract(expr: DoPrim): Expression = {
- expr.args.head match {
- case _: UIntLiteral | _: SIntLiteral => ConstantPropagation.constPropBitExtract(expr)
- case _ => expr
- }
- }
- private def legalizePad(expr: DoPrim): Expression = expr.args.head match {
- case UIntLiteral(value, IntWidth(width)) if width < expr.consts.head =>
- UIntLiteral(value, IntWidth(expr.consts.head))
- case SIntLiteral(value, IntWidth(width)) if width < expr.consts.head =>
- SIntLiteral(value, IntWidth(expr.consts.head))
- case _ => expr
- }
- private def legalizeConnect(c: Connect): Statement = {
- val t = c.loc.tpe
- val w = bitWidth(t)
- if (w >= bitWidth(c.expr.tpe)) {
- c
- } else {
- val bits = DoPrim(Bits, Seq(c.expr), Seq(w - 1, 0), UIntType(IntWidth(w)))
- val expr = t match {
- case UIntType(_) => bits
- case SIntType(_) => DoPrim(AsSInt, Seq(bits), Seq(), SIntType(IntWidth(w)))
- case FixedType(_, IntWidth(p)) => DoPrim(AsFixedPoint, Seq(bits), Seq(p), t)
- }
- Connect(c.info, c.loc, expr)
- }
- }
- def run (c: Circuit): Circuit = {
- def legalizeE(expr: Expression): Expression = expr map legalizeE match {
- case prim: DoPrim => prim.op match {
- case Shr => legalizeShiftRight(prim)
- case Pad => legalizePad(prim)
- case Bits | Head | Tail => legalizeBitExtract(prim)
- case _ => prim
- }
- case e => e // respect pre-order traversal
- }
- def legalizeS (s: Statement): Statement = {
- val legalizedStmt = s match {
- case c: Connect => legalizeConnect(c)
- case _ => s
- }
- legalizedStmt map legalizeS map legalizeE
- }
- c copy (modules = c.modules map (_ map legalizeS))
- }
-}
-
-/** Makes changes to the Firrtl AST to make Verilog emission easier
- *
- * - For each instance, adds wires to connect to each port
- * - Note that no Namespace is required because Uniquify ensures that there will be no
- * collisions with the lowered names of instance ports
- * - Also removes Attaches where a single Port OR Wire connects to 1 or more instance ports
- * - These are expressed in the portCons of WDefInstConnectors
- *
- * @note The result of this pass is NOT legal Firrtl
- */
-object VerilogPrep extends Pass with PreservesAll[Transform] {
-
- override val prerequisites = firrtl.stage.Forms.LowFormMinimumOptimized ++
- Seq( Dependency[firrtl.transforms.BlackBoxSourceHelper],
- Dependency[firrtl.transforms.FixAddingNegativeLiterals],
- Dependency[firrtl.transforms.ReplaceTruncatingArithmetic],
- Dependency[firrtl.transforms.InlineBitExtractionsTransform],
- Dependency[firrtl.transforms.InlineCastsTransform],
- Dependency[firrtl.transforms.LegalizeClocksTransform],
- Dependency[firrtl.transforms.FlattenRegUpdate],
- Dependency(passes.VerilogModulusCleanup),
- Dependency[firrtl.transforms.VerilogRename] )
-
- override val optionalPrerequisites = firrtl.stage.Forms.LowFormOptimized
-
- override val dependents = Seq.empty
-
- type AttachSourceMap = Map[WrappedExpression, Expression]
-
- // Finds attaches with only a single source (Port or Wire)
- // - Creates a map of attached expressions to their source
- // - Removes the Attach
- private def collectAndRemoveAttach(m: DefModule): (DefModule, AttachSourceMap) = {
- val sourceMap = mutable.HashMap.empty[WrappedExpression, Expression]
- lazy val namespace = Namespace(m)
-
- def onStmt(stmt: Statement): Statement = stmt map onStmt match {
- case attach: Attach =>
- val wires = attach.exprs groupBy kind
- val sources = wires.getOrElse(PortKind, Seq.empty) ++ wires.getOrElse(WireKind, Seq.empty)
- val instPorts = wires.getOrElse(InstanceKind, Seq.empty)
- // Sanity check (Should be caught by CheckTypes)
- assert(sources.size + instPorts.size == attach.exprs.size)
-
- sources match {
- case Seq() => // Zero sources, can add a wire to connect and remove
- val name = namespace.newTemp
- val wire = DefWire(NoInfo, name, instPorts.head.tpe)
- val ref = WRef(wire)
- for (inst <- instPorts) sourceMap(inst) = ref
- wire // Replace the attach with new source wire definition
- case Seq(source) => // One source can be removed
- assert(!sourceMap.contains(source)) // should have been merged
- for (inst <- instPorts) sourceMap(inst) = source
- EmptyStmt
- case moreThanOne =>
- attach
- }
- case s => s
- }
-
- (m map onStmt, sourceMap.toMap)
- }
-
- def run(c: Circuit): Circuit = {
- def lowerE(e: Expression): Expression = e match {
- case (_: WRef | _: WSubField) if kind(e) == InstanceKind =>
- WRef(LowerTypes.loweredName(e), e.tpe, kind(e), flow(e))
- case _ => e map lowerE
- }
-
- def lowerS(attachMap: AttachSourceMap)(s: Statement): Statement = s match {
- case WDefInstance(info, name, module, tpe) =>
- val portRefs = create_exps(WRef(name, tpe, ExpKind, SourceFlow))
- val (portCons, wires) = portRefs.map { p =>
- attachMap.get(p) match {
- // If it has a source in attachMap use that
- case Some(ref) => (p -> ref, None)
- // If no source, create a wire corresponding to the port and connect it up
- case None =>
- val wire = DefWire(info, LowerTypes.loweredName(p), p.tpe)
- (p -> WRef(wire), Some(wire))
- }
- }.unzip
- val newInst = WDefInstanceConnector(info, name, module, tpe, portCons)
- Block(wires.flatten :+ newInst)
- case other => other map lowerS(attachMap) map lowerE
- }
-
- val modulesx = c.modules map { mod =>
- val (modx, attachMap) = collectAndRemoveAttach(mod)
- modx map lowerS(attachMap)
- }
- c.copy(modules = modulesx)
- }
-}