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.4.x' into 1.4-release
Browse files Browse the repository at this point in the history
  • Loading branch information
jackkoenig committed Apr 1, 2021
2 parents 3cad2a7 + e931172 commit 9c484be
Show file tree
Hide file tree
Showing 38 changed files with 1,461 additions and 217 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ jobs:
- name: Cache Scala
uses: coursier/cache-action@v5
- name: Check Formatting (Scala 2.12 only)
if: matrix.scala == '2.12.12'
if: startsWith(matrix.scala, '2.12')
run: sbt ++${{ matrix.scala }} scalafmtCheckAll
- name: Unidoc
run: sbt ++${{ matrix.scala }} unidoc
- name: Sanity check benchmarking scripts (Scala 2.12 only)
if: matrix.scala == '2.12.12'
- name: Sanity check benchmarking scripts (Scala 2.13 only)
if: startsWith(matrix.scala, '2.13')
run: |
benchmark/scripts/benchmark_cold_compile.py -N 2 --designs regress/ICache.fir --versions HEAD
benchmark/scripts/find_heap_bound.py -- -cp firrtl*jar firrtl.stage.FirrtlMain -i regress/ICache.fir -o out -X verilog
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@ project/metals.sbt

*~
*#*#
.vscode
9 changes: 6 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ lazy val firrtlSettings = Seq(

import com.typesafe.tools.mima.core._
lazy val mimaSettings = Seq(
mimaPreviousArtifacts := Set("edu.berkeley.cs" %% "firrtl" % "1.4.1"),
mimaPreviousArtifacts := Set("edu.berkeley.cs" %% "firrtl" % "1.4.2"),
// Public method on private object
mimaBinaryIssueFilters ++= Seq(
ProblemFilters.exclude[IncompatibleMethTypeProblem]("firrtl.passes.DestructTypes.destructInstance")
ProblemFilters.exclude[IncompatibleMethTypeProblem]("firrtl.passes.DestructTypes.destructInstance"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("firrtl.FirrtlProtos#Firrtl#StatementOrBuilder.hasVerification"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("firrtl.FirrtlProtos#Firrtl#StatementOrBuilder.getVerification"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("firrtl.FirrtlProtos#Firrtl#StatementOrBuilder.getVerificationOrBuilder")
)
)

Expand Down Expand Up @@ -163,7 +166,7 @@ lazy val docSettings = Seq(
} else {
s"v${version.value}"
}
s"https://github.com/freechipsproject/firrtl/tree/$branch€{FILE_PATH}.scala"
s"https://github.com/chipsalliance/firrtl/tree/$branch€{FILE_PATH_EXT}#L€{FILE_LINE}"
}
) ++ scalacDocOptionsVersion(scalaVersion.value)
)
Expand Down
1 change: 1 addition & 0 deletions src/main/proto/firrtl.proto
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ message Firrtl {
IsInvalid is_invalid = 17;
MemoryPort memory_port = 18;
Attach attach = 20;
Verification verification = 21;
}

SourceInfo source_info = 19;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ firrtl.transforms.CheckCombLoops
firrtl.passes.InlineInstances
firrtl.passes.clocklist.ClockListTransform
firrtl.transforms.formal.AssertSubmoduleAssumptions
firrtl.transforms.ConstantPropagation
3 changes: 3 additions & 0 deletions src/main/scala/firrtl/EmissionOption.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

package firrtl

import firrtl.annotations.MemoryLoadFileType

/**
* Base type for emission customization options
* NOTE: all the following traits must be mixed with SingleTargetAnnotation[T <: Named]
Expand All @@ -18,6 +20,7 @@ sealed trait MemoryInitValue
case object MemoryRandomInit extends MemoryInitValue
case class MemoryScalarInit(value: BigInt) extends MemoryInitValue
case class MemoryArrayInit(values: Seq[BigInt]) extends MemoryInitValue
case class MemoryFileInlineInit(filename: String, hexOrBinary: MemoryLoadFileType.FileType) extends MemoryInitValue

/** default Emitter behavior for memories */
case object MemoryEmissionOptionDefault extends MemoryEmissionOption
Expand Down
32 changes: 32 additions & 0 deletions src/main/scala/firrtl/Utils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package firrtl
import firrtl.ir._
import firrtl.PrimOps._
import firrtl.Mappers._
import firrtl.traversals.Foreachers._
import firrtl.WrappedExpression._

import scala.collection.mutable
Expand Down Expand Up @@ -210,6 +211,24 @@ object Utils extends LazyLogging {
case _ => false
}

/** Selects all the elements of this list ignoring the duplicates as determined by == after
* applying the transforming function f
*
* @note In Scala Standard Library starting in 2.13
*/
def distinctBy[A, B](xs: List[A])(f: A => B): List[A] = {
val buf = new mutable.ListBuffer[A]
val seen = new mutable.HashSet[B]
for (x <- xs) {
val y = f(x)
if (!seen(y)) {
buf += x
seen += y
}
}
buf.toList
}

/** Provide a nice name to create a temporary * */
def niceName(e: Expression): String = niceName(1)(e)
def niceName(depth: Int)(e: Expression): String = {
Expand Down Expand Up @@ -649,6 +668,19 @@ object Utils extends LazyLogging {
case _ => NoInfo
}

/** Finds all root References in a nested Expression */
def getAllRefs(expr: Expression): Seq[Reference] = {
val refs = mutable.ListBuffer.empty[Reference]
def rec(e: Expression): Unit = {
e match {
case ref: Reference => refs += ref
case other => other.foreach(rec)
}
}
rec(expr)
refs.toList
}

/** Splits an Expression into root Ref and tail
*
* @example
Expand Down
21 changes: 20 additions & 1 deletion src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

package firrtl.annotations

import firrtl.{MemoryArrayInit, MemoryEmissionOption, MemoryInitValue, MemoryRandomInit, MemoryScalarInit}
import firrtl.{
MemoryArrayInit,
MemoryEmissionOption,
MemoryFileInlineInit,
MemoryInitValue,
MemoryRandomInit,
MemoryScalarInit
}

/**
* Represents the initial value of the annotated memory.
Expand Down Expand Up @@ -33,3 +40,15 @@ case class MemoryArrayInitAnnotation(target: ReferenceTarget, values: Seq[BigInt
override def initValue: MemoryInitValue = MemoryArrayInit(values)
override def isRandomInit: Boolean = false
}

/** Initialize the `target` memory with inline readmem[hb] statement. */
case class MemoryFileInlineAnnotation(
target: ReferenceTarget,
filename: String,
hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex)
extends MemoryInitAnnotation {
require(filename.trim.nonEmpty, "empty filename not allowed in MemoryFileInlineAnnotation")
override def duplicate(n: ReferenceTarget): Annotation = copy(n)
override def initValue: MemoryInitValue = MemoryFileInlineInit(filename, hexOrBinary)
override def isRandomInit: Boolean = false
}
21 changes: 17 additions & 4 deletions src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import firrtl.PrimOps._
import firrtl.Utils._
import firrtl.WrappedExpression._
import firrtl.traversals.Foreachers._
import firrtl.annotations.{CircuitTarget, ReferenceTarget, SingleTargetAnnotation}
import firrtl.annotations.{CircuitTarget, MemoryLoadFileType, ReferenceTarget, SingleTargetAnnotation}
import firrtl.passes.LowerTypes
import firrtl.passes.MemPortUtils._
import firrtl.stage.TransformManager
Expand Down Expand Up @@ -57,6 +57,13 @@ object VerilogEmitter {
private def precedenceGt(op1: PrimOp, op2: PrimOp): Boolean = {
precedenceMap(op1) < precedenceMap(op2)
}

/** Identifies PrimOps that never need parentheses
*
* These PrimOps emit either {..., a0, ...} or a0 so they never need parentheses
*/
private val neverParens: PrimOp => Boolean =
Set(Shl, Cat, Cvt, AsUInt, AsSInt, AsClock, AsAsyncReset, Pad)
}

class VerilogEmitter extends SeqTransform with Emitter {
Expand Down Expand Up @@ -229,8 +236,7 @@ class VerilogEmitter extends SeqTransform with Emitter {
// to ensure Verilog operations are signed.
def op_stream(doprim: DoPrim): Seq[Any] = {
def parenthesize(e: Expression, isFirst: Boolean): Any = doprim.op match {
// these PrimOps emit either {..., a0, ...} or a0 so they never need parentheses
case Shl | Cat | Cvt | AsUInt | AsSInt | AsClock | AsAsyncReset => e
case op if neverParens(op) => e
case _ =>
e match {
case e: DoPrim =>
Expand All @@ -247,7 +253,8 @@ class VerilogEmitter extends SeqTransform with Emitter {
*/
case other =>
val noParens =
precedenceGt(e.op, doprim.op) ||
neverParens(e.op) ||
precedenceGt(e.op, doprim.op) ||
(isFirst && precedenceEq(e.op, doprim.op) && !isUnaryOp(e.op))
if (noParens) other else Seq("(", other, ")")
}
Expand Down Expand Up @@ -849,6 +856,12 @@ class VerilogEmitter extends SeqTransform with Emitter {
rstring,
";"
)
case MemoryFileInlineInit(filename, hexOrBinary) =>
val readmem = hexOrBinary match {
case MemoryLoadFileType.Binary => "$readmemb"
case MemoryLoadFileType.Hex => "$readmemh"
}
memoryInitials += Seq(s"""$readmem("$filename", ${s.name});""")
}
}

Expand Down
46 changes: 46 additions & 0 deletions src/main/scala/firrtl/graph/DiGraph.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package firrtl.graph

import scala.collection.{mutable, Map, Set}
import scala.collection.mutable.{LinkedHashMap, LinkedHashSet}
import firrtl.options.DependencyManagerUtils.{CharSet, PrettyCharSet}

/** An exception that is raised when an assumed DAG has a cycle */
class CyclicException(val node: Any) extends Exception(s"No valid linearization for cyclic graph, found at $node")
Expand Down Expand Up @@ -31,6 +32,16 @@ object DiGraph {
}
new DiGraph(edgeDataCopy)
}

/** Create a DiGraph from edges */
def apply[T](edges: (T, T)*): DiGraph[T] = {
val edgeMap = new LinkedHashMap[T, LinkedHashSet[T]]
for ((from, to) <- edges) {
val set = edgeMap.getOrElseUpdate(from, new LinkedHashSet[T])
set += to
}
new DiGraph(edgeMap)
}
}

/** Represents common behavior of all directed graphs */
Expand Down Expand Up @@ -386,6 +397,41 @@ class DiGraph[T](private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]]) {
that.edges.foreach({ case (k, v) => eprime.getOrElseUpdate(k, new LinkedHashSet[T]) ++= v })
new DiGraph(eprime)
}

/** Serializes a `DiGraph[String]` as a pretty tree
*
* Multiple roots are supported, but cycles are not.
*/
def prettyTree(charSet: CharSet = PrettyCharSet)(implicit ev: T =:= String): String = {
// Set up characters for building the tree
val (l, n, c) = (charSet.lastNode, charSet.notLastNode, charSet.continuation)
val ctab = " " * c.size + " "

// Recursively adds each node of the DiGraph to accumulating List[String]
// Uses List because prepend is cheap and this prevents quadratic behavior of String
// concatenations or even flatMapping on Seqs
def rec(tab: String, node: T, mark: String, prev: List[String]): List[String] = {
val here = s"$mark$node"
val children = this.getEdges(node)
val last = children.size - 1
children.toList // Convert LinkedHashSet to List to avoid determinism issues
.zipWithIndex // Find last
.foldLeft(here :: prev) {
case (acc, (nodex, idx)) =>
val nextTab = if (idx == last) tab + ctab else tab + c + " "
val nextMark = if (idx == last) tab + l else tab + n
rec(nextTab, nodex, nextMark + " ", acc)
}
}
this.findSources.toList // Convert LinkedHashSet to List to avoid determinism issues
.sortBy(_.toString) // Make order deterministic
.foldLeft(Nil: List[String]) {
case (acc, root) => rec("", root, "", acc)
}
.reverse
.mkString("\n")
}

}

class MutableDiGraph[T] extends DiGraph[T](new LinkedHashMap[T, LinkedHashSet[T]]) {
Expand Down
18 changes: 16 additions & 2 deletions src/main/scala/firrtl/passes/Legalize.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
package firrtl.passes

import firrtl.PrimOps._
import firrtl.Utils.{error, zero, BoolType}
import firrtl.Utils.{error, getGroundZero, zero, BoolType}
import firrtl.ir._
import firrtl.options.Dependency
import firrtl.transforms.ConstantPropagation
import firrtl.{bitWidth, Transform}
import firrtl.{bitWidth, getWidth, Transform}
import firrtl.Mappers._

// Replace shr by amount >= arg width with 0 for UInts and MSB for SInts
Expand Down Expand Up @@ -56,6 +56,19 @@ object Legalize extends Pass {
SIntLiteral(value, IntWidth(expr.consts.head))
case _ => expr
}
// Convert `-x` to `0 - x`
private def legalizeNeg(expr: DoPrim): Expression = {
val arg = expr.args.head
arg.tpe match {
case tpe: SIntType =>
val zero = getGroundZero(tpe)
DoPrim(Sub, Seq(zero, arg), Nil, expr.tpe)
case tpe: UIntType =>
val zero = getGroundZero(tpe)
val sub = DoPrim(Sub, Seq(zero, arg), Nil, UIntType(tpe.width + IntWidth(1)))
DoPrim(AsSInt, Seq(sub), Nil, expr.tpe)
}
}
private def legalizeConnect(c: Connect): Statement = {
val t = c.loc.tpe
val w = bitWidth(t)
Expand All @@ -78,6 +91,7 @@ object Legalize extends Pass {
case Shr => legalizeShiftRight(prim)
case Pad => legalizePad(prim)
case Bits | Head | Tail => legalizeBitExtract(prim)
case Neg => legalizeNeg(prim)
case _ => prim
}
case e => e // respect pre-order traversal
Expand Down
Loading

0 comments on commit 9c484be

Please sign in to comment.