Skip to content
This repository has been archived by the owner on Aug 20, 2024. It is now read-only.

Commit

Permalink
Merge branch '1.1.3+' into 1.1.3
Browse files Browse the repository at this point in the history
 - selected changes from master for 1.1.3 release
 - bump version in build.sbt
  • Loading branch information
ucbjrl committed Sep 10, 2018
2 parents 99095ab + 6932ea8 commit 6006cc8
Show file tree
Hide file tree
Showing 26 changed files with 692 additions and 90 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ sudo: false
cache:
directories:
$HOME/.ivy2
$HOME/.sbt
$INSTALL_DIR

git:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ sbt assembly

#### Other Tools
* Firrtl syntax highlighting for Vim users: https://github.com/azidar/firrtl-syntax
* Firrtl syntax highlighting for Sublime Text 3 users: https://github.com/codelec/highlight-firrtl
* Firrtl mode for Emacs users: https://github.com/ibm/firrtl-mode
* Chisel3, an embedded hardware DSL that generates Firrtl: https://github.com/ucb-bar/chisel3
* Firrtl Interpreter: https://github.com/ucb-bar/firrtl-interpreter
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ organization := "edu.berkeley.cs"

name := "firrtl"

version := "1.1.2"
version := "1.1.3"

scalaVersion := "2.11.12"

Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/firrtl/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ abstract class Transform extends LazyLogging {
resAnno: AnnotationSeq,
renameOpt: Option[RenameMap]): AnnotationSeq = {
val newAnnotations = {
val inSet = inAnno.toSet
val resSet = resAnno.toSet
val inSet = mutable.LinkedHashSet() ++ inAnno
val resSet = mutable.LinkedHashSet() ++ resAnno
val deleted = (inSet -- resSet).map {
case DeletedAnnotation(xFormName, delAnno) => DeletedAnnotation(s"$xFormName+$name", delAnno)
case anno => DeletedAnnotation(name, anno)
Expand Down
21 changes: 16 additions & 5 deletions src/main/scala/firrtl/Emitter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class VerilogEmitter extends SeqTransform with Emitter {
case (e: WSubAccess) => w write s"${LowerTypes.loweredName(e.expr)}[${LowerTypes.loweredName(e.index)}]"
case (e: WSubIndex) => w write e.serialize
case (e: Literal) => v_print(e)
case (e: VRandom) => w write s"{${e.nWords}{$$random}}"
case (e: VRandom) => w write s"{${e.nWords}{`RANDOM}}"
case (t: GroundType) => w write stringify(t)
case (t: VectorType) =>
emit(t.tpe, top + 1)
Expand Down Expand Up @@ -655,14 +655,25 @@ class VerilogEmitter extends SeqTransform with Emitter {
emit(Seq("`ifdef RANDOMIZE_MEM_INIT"))
emit(Seq("`define RANDOMIZE"))
emit(Seq("`endif"))
emit(Seq("`ifndef RANDOM"))
emit(Seq("`define RANDOM $random"))
emit(Seq("`endif"))
emit(Seq("`ifdef RANDOMIZE"))
emit(Seq(" integer initvar;"))
emit(Seq(" initial begin"))
// This enables test benches to set the random values at time 0.001,
// then start the simulation later
emit(Seq(" `ifdef INIT_RANDOM"))
emit(Seq(" `INIT_RANDOM"))
emit(Seq(" `endif"))
// This enables testbenches to seed the random values at some time
// before `RANDOMIZE_DELAY (or the legacy value 0.002 if
// `RANDOMIZE_DELAY is not defined).
// Verilator does not support delay statements, so they are omitted.
emit(Seq(" `ifndef verilator"))
emit(Seq(" #0.002 begin end"))
emit(Seq(" `ifndef VERILATOR"))
emit(Seq(" `ifdef RANDOMIZE_DELAY"))
emit(Seq(" #`RANDOMIZE_DELAY begin end"))
emit(Seq(" `else"))
emit(Seq(" #0.002 begin end"))
emit(Seq(" `endif"))
emit(Seq(" `endif"))
for (x <- initials) emit(Seq(tab, x))
emit(Seq(" end"))
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/firrtl/ExecutionOptionsManager.scala
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ extends ComposableOptions {
case "low" => new LowFirrtlCompiler()
case "middle" => new MiddleFirrtlCompiler()
case "verilog" => new VerilogCompiler()
case "sverilog" => new VerilogCompiler()
case "sverilog" => new SystemVerilogCompiler()
}
}

Expand Down
21 changes: 21 additions & 0 deletions src/main/scala/firrtl/LoweringCompilers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ class LowFirrtlOptimization extends CoreTransform {
passes.CommonSubexpressionElimination,
new firrtl.transforms.DeadCodeElimination)
}
/** Runs runs only the optimization passes needed for Verilog emission */
class MinimumLowFirrtlOptimization extends CoreTransform {
def inputForm = LowForm
def outputForm = LowForm
def transforms = Seq(
passes.Legalize,
passes.memlib.VerilogMemDelays, // TODO move to Verilog emitter
passes.SplitExpressions)
}


import CompilerUtils.getLoweringTransforms
Expand Down Expand Up @@ -142,3 +151,15 @@ class VerilogCompiler extends Compiler {
def transforms: Seq[Transform] = getLoweringTransforms(ChirrtlForm, LowForm) ++
Seq(new LowFirrtlOptimization, new BlackBoxSourceHelper)
}

/** Emits Verilog without optimizations */
class MinimumVerilogCompiler extends Compiler {
def emitter = new VerilogEmitter
def transforms: Seq[Transform] = getLoweringTransforms(ChirrtlForm, LowForm) ++
Seq(new MinimumLowFirrtlOptimization, new BlackBoxSourceHelper)
}

/** Currently just an alias for the [[VerilogCompiler]] */
class SystemVerilogCompiler extends VerilogCompiler {
Driver.dramaticWarning("SystemVerilog Compiler behaves the same as the Verilog Compiler!")
}
2 changes: 2 additions & 0 deletions src/main/scala/firrtl/WIR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ object WRef {
def apply(wire: DefWire): WRef = new WRef(wire.name, wire.tpe, WireKind, UNKNOWNGENDER)
/** Creates a WRef from a Register */
def apply(reg: DefRegister): WRef = new WRef(reg.name, reg.tpe, RegKind, UNKNOWNGENDER)
/** Creates a WRef from a Node */
def apply(node: DefNode): WRef = new WRef(node.name, node.value.tpe, NodeKind, MALE)
def apply(n: String, t: Type = UnknownType, k: Kind = ExpKind): WRef = new WRef(n, t, k, UNKNOWNGENDER)
}
case class WSubField(expr: Expression, name: String, tpe: Type, gender: Gender) extends Expression {
Expand Down
22 changes: 22 additions & 0 deletions src/main/scala/firrtl/analyses/GetNamespace.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// See LICENSE for license details.

package firrtl.analyses

import firrtl.annotations.NoTargetAnnotation
import firrtl.{CircuitState, LowForm, Namespace, Transform}

case class ModuleNamespaceAnnotation(namespace: Namespace) extends NoTargetAnnotation

/** Create a namespace with this circuit
*
* namespace is used by RenameModules to get unique names
*/
class GetNamespace extends Transform {
def inputForm: LowForm.type = LowForm
def outputForm: LowForm.type = LowForm

def execute(state: CircuitState): CircuitState = {
val namespace = Namespace(state.circuit)
state.copy(annotations = new ModuleNamespaceAnnotation(namespace) +: state.annotations)
}
}
13 changes: 4 additions & 9 deletions src/main/scala/firrtl/passes/Passes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
package firrtl.passes

import com.typesafe.scalalogging.LazyLogging

import firrtl._
import firrtl.ir._
import firrtl.Utils._
import firrtl.Mappers._
import firrtl.PrimOps._
import firrtl.transforms.ConstantPropagation

import scala.collection.mutable

Expand Down Expand Up @@ -198,14 +198,9 @@ object Legalize extends Pass {
e
}
}
private def legalizeBits(expr: DoPrim): Expression = {
lazy val (hi, low) = (expr.consts.head, expr.consts(1))
lazy val mask = (BigInt(1) << (hi - low + 1).toInt) - 1
lazy val width = IntWidth(hi - low + 1)
private def legalizeBitExtract(expr: DoPrim): Expression = {
expr.args.head match {
case UIntLiteral(value, _) => UIntLiteral((value >> low.toInt) & mask, width)
case SIntLiteral(value, _) => SIntLiteral((value >> low.toInt) & mask, width)
//case FixedLiteral
case _: UIntLiteral | _: SIntLiteral => ConstantPropagation.constPropBitExtract(expr)
case _ => expr
}
}
Expand Down Expand Up @@ -236,7 +231,7 @@ object Legalize extends Pass {
case prim: DoPrim => prim.op match {
case Shr => legalizeShiftRight(prim)
case Pad => legalizePad(prim)
case Bits => legalizeBits(prim)
case Bits | Head | Tail => legalizeBitExtract(prim)
case _ => prim
}
case e => e // respect pre-order traversal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,6 @@ object AnalysisUtils {
}
case _ => e
}

/** Checks whether the two memories are equivalent in all respects except name
*/
def eqMems(a: DefAnnotatedMemory, b: DefAnnotatedMemory, noDeDupeMems: Seq[String]): Boolean =
a == b.copy(info = a.info, name = a.name, memRef = a.memRef) &&
!(noDeDupeMems.contains(a.name) || noDeDupeMems.contains(b.name))
}

/** Determines if a write mask is needed (wmode/en and wmask are equivalent).
Expand Down
52 changes: 39 additions & 13 deletions src/main/scala/firrtl/passes/memlib/ResolveMemoryReference.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package firrtl.passes
package memlib
import firrtl._
import firrtl.ir._
import AnalysisUtils.eqMems
import firrtl.Mappers._
import firrtl.annotations._

Expand All @@ -19,30 +18,57 @@ class ResolveMemoryReference extends Transform {
def inputForm = MidForm
def outputForm = MidForm

type AnnotatedMemories = collection.mutable.ArrayBuffer[(String, DefAnnotatedMemory)]
/** Helper class for determining when two memories are equivalent while igoring
* irrelevant details like name and info
*/
private class WrappedDefAnnoMemory(val underlying: DefAnnotatedMemory) {
// Remove irrelevant details for comparison
private def generic = underlying.copy(info = NoInfo, name = "", memRef = None)
override def hashCode: Int = generic.hashCode
override def equals(that: Any): Boolean = that match {
case mem: WrappedDefAnnoMemory => this.generic == mem.generic
case _ => false
}
}
private def wrap(mem: DefAnnotatedMemory) = new WrappedDefAnnoMemory(mem)

// Values are Tuple of Module Name and Memory Instance Name
private type AnnotatedMemories = collection.mutable.HashMap[WrappedDefAnnoMemory, (String, String)]

private def dedupable(noDedups: Map[String, Set[String]], module: String, memory: String): Boolean =
noDedups.get(module).map(!_.contains(memory)).getOrElse(true)

/** If a candidate memory is identical except for name to another, add an
* annotation that references the name of the other memory.
*/
def updateMemStmts(mname: String, uniqueMems: AnnotatedMemories, noDeDupeMems: Seq[String])(s: Statement): Statement = s match {
case m: DefAnnotatedMemory =>
uniqueMems find (x => eqMems(x._2, m, noDeDupeMems)) match {
def updateMemStmts(mname: String,
existingMems: AnnotatedMemories,
noDedupMap: Map[String, Set[String]])
(s: Statement): Statement = s match {
// If not dedupable, no need to add to existing (since nothing can dedup with it)
// We just return the DefAnnotatedMemory as is in the default case below
case m: DefAnnotatedMemory if dedupable(noDedupMap, mname, m.name) =>
val wrapped = wrap(m)
existingMems.get(wrapped) match {
case proto @ Some(_) =>
m.copy(memRef = proto)
case None =>
uniqueMems += (mname -> m)
existingMems(wrapped) = (mname, m.name)
m
case Some((module, proto)) => m copy (memRef = Some(module -> proto.name))
}
case s => s map updateMemStmts(mname, uniqueMems, noDeDupeMems)
case s => s.map(updateMemStmts(mname, existingMems, noDedupMap))
}

def run(c: Circuit, noDeDupeMems: Seq[String]) = {
val uniqueMems = new AnnotatedMemories
c copy (modules = c.modules map (m => m map updateMemStmts(m.name, uniqueMems, noDeDupeMems)))
def run(c: Circuit, noDedupMap: Map[String, Set[String]]) = {
val existingMems = new AnnotatedMemories
val modulesx = c.modules.map(m => m.map(updateMemStmts(m.name, existingMems, noDedupMap)))
c.copy(modules = modulesx)
}
def execute(state: CircuitState): CircuitState = {
val noDedups = state.annotations.collect {
case NoDedupMemAnnotation(ComponentName(cn, _)) => cn
case NoDedupMemAnnotation(ComponentName(cn, ModuleName(mn, _))) => mn -> cn
}
state.copy(circuit=run(state.circuit, noDedups))
val noDedupMap: Map[String, Set[String]] = noDedups.groupBy(_._1).mapValues(_.map(_._2).toSet)
state.copy(circuit = run(state.circuit, noDedupMap))
}
}
Loading

0 comments on commit 6006cc8

Please sign in to comment.