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.5.x' into 1.5-release
Browse files Browse the repository at this point in the history
  • Loading branch information
jackkoenig committed Feb 8, 2022
2 parents 36bee6f + 2f007ce commit 254c396
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 88 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
push:
branches:
- master
- 1.5.x
- 1.4.x
- 1.3.x
- 1.2.x
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ lazy val firrtlSettings = Seq(
)

lazy val mimaSettings = Seq(
mimaPreviousArtifacts := Set()
mimaPreviousArtifacts := Set("edu.berkeley.cs" %% "firrtl" % "1.5.0")
)

lazy val protobufSettings = Seq(
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/firrtl/Emitter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,10 @@ object EmitAllModulesAnnotation extends HasShellOptions {
toAnnotationSeq = s =>
s.split(",")
.map {
case "disableMemRandomization" =>
case "disableRegisterRandomization" =>
CustomDefaultRegisterEmission(useInitAsPreset = false, disableRandomization = true)
case "disableRegisterRandomization" => CustomDefaultMemoryEmission(MemoryNoInit)
case a => throw new PhaseException(s"Unknown emission options '$a'! (Did you misspell it?)")
case "disableMemRandomization" => CustomDefaultMemoryEmission(MemoryNoInit)
case a => throw new PhaseException(s"Unknown emission options '$a'! (Did you misspell it?)")
}
.toSeq,
helpText = "Options to disable random initialization for memory and registers",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,8 @@ private class InstrumentMems(

private def isInBounds(depth: BigInt, addr: Expression): Expression = {
val width = getWidth(addr)
// depth >= addr
DoPrim(PrimOps.Geq, List(UIntLiteral(depth, width), addr), List(), BoolType)
// depth > addr (e.g. if the depth is 3, then the address must be in {0, 1, 2})
DoPrim(PrimOps.Gt, List(UIntLiteral(depth, width), addr), List(), BoolType)
}

private def isPow2(v: BigInt): Boolean = ((v - 1) & v) == 0
Expand Down
14 changes: 5 additions & 9 deletions src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -900,14 +900,8 @@ class VerilogEmitter extends SeqTransform with Emitter {
case MemoryLoadFileType.Binary => "$readmemb"
case MemoryLoadFileType.Hex => "$readmemh"
}
if (emissionOptions.emitMemoryInitAsNoSynth) {
memoryInitials += Seq(s"""$readmem("$filename", ${s.name});""")
} else {
val inlineLoad = s"""initial begin
| $readmem("$filename", ${s.name});
| end""".stripMargin
memoryInitials += Seq(inlineLoad)
}
memoryInitials += Seq(s"""$readmem("$filename", ${s.name});""")

case MemoryNoInit =>
// do nothing
}
Expand Down Expand Up @@ -1292,8 +1286,10 @@ class VerilogEmitter extends SeqTransform with Emitter {
emit(Seq("`FIRRTL_AFTER_INITIAL"))
emit(Seq("`endif"))
emit(Seq("`endif // SYNTHESIS"))
if (!emissionOptions.emitMemoryInitAsNoSynth) {
if (!emissionOptions.emitMemoryInitAsNoSynth && !memoryInitials.isEmpty) {
emit(Seq("initial begin"))
for (x <- memoryInitials) emit(Seq(tab, x))
emit(Seq("end"))
}
}

Expand Down
25 changes: 17 additions & 8 deletions src/main/scala/firrtl/transforms/PropagatePresetAnnotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import firrtl.options.Dependency
import scala.collection.mutable

object PropagatePresetAnnotations {
@deprecated("This message will be removed in the next release.", "FIRRTL 1.5")
val advice =
"Please Note that a Preset-annotated AsyncReset shall NOT be casted to other types with any of the following functions: asInterval, asUInt, asSInt, asClock, asFixedPoint, asAsyncReset."
@deprecated("This exception will no longer be thrown.", "FIRRTL 1.5")
case class TreeCleanUpOrphanException(message: String)
extends FirrtlUserException(s"Node left an orphan during tree cleanup: $message $advice")
}
Expand Down Expand Up @@ -366,15 +368,22 @@ class PropagatePresetAnnotations extends Transform with DependencyAPIMigration {
}
}

// replaces all references to removed (clean up) preset signals with zero
def replaceCleanUpRefs(e: ir.Expression): ir.Expression = e match {
case r: ir.RefLikeExpression =>
getRef(r) match {
case rt: ReferenceTarget if toCleanUp.contains(rt) =>
Utils.getGroundZero(r.tpe.asInstanceOf[ir.GroundType])
case _ => r.mapExpr(replaceCleanUpRefs)
}
case other => other.mapExpr(replaceCleanUpRefs)
}

def processNode(n: DefNode): Statement = {
if (toCleanUp.contains(moduleTarget.ref(n.name))) {
EmptyStmt
} else {
getRef(n.value) match {
case rt: ReferenceTarget if (toCleanUp.contains(rt)) =>
throw TreeCleanUpOrphanException(s"Orphan (${moduleTarget.ref(n.name)}) the way.")
case _ => n
}
n
}
}

Expand All @@ -383,7 +392,7 @@ class PropagatePresetAnnotations extends Transform with DependencyAPIMigration {
case rhs: ReferenceTarget if (toCleanUp.contains(rhs)) =>
getRef(c.loc) match {
case lhs: ReferenceTarget if (!toCleanUp.contains(lhs)) =>
throw TreeCleanUpOrphanException(s"Orphan ${lhs} connected deleted node $rhs.")
c
case _ => EmptyStmt
}
case _ => c
Expand All @@ -402,14 +411,14 @@ class PropagatePresetAnnotations extends Transform with DependencyAPIMigration {
}

def processStatements(statement: Statement): Statement = {
statement match {
(statement match {
case i: WDefInstance => processInstance(i)
case r: DefRegister => processRegister(r)
case w: DefWire => processWire(w)
case n: DefNode => processNode(n)
case c: Connect => processConnect(c)
case s => s.mapStmt(processStatements)
}
}).mapExpr(replaceCleanUpRefs)
}

m match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class UndefinedMemoryBehaviorSpec extends LeanTransformSpec(Seq(Dependency(Undef

assert(
result.contains(
"""assert(m_a_clk, geq(UInt<5>("h1e"), m_a_addr), UInt<1>("h1"), "out of bounds read")"""
"""assert(m_a_clk, gt(UInt<5>("h1e"), m_a_addr), UInt<1>("h1"), "out of bounds read")"""
)
)
}
Expand All @@ -102,7 +102,7 @@ class UndefinedMemoryBehaviorSpec extends LeanTransformSpec(Seq(Dependency(Undef
val result = circuit.serialize.split('\n').map(_.trim)

// an out of bounds read happens if the depth is not greater or equal to the address
assert(result.contains("node m_r_oob = not(geq(UInt<5>(\"h1e\"), m_r_addr))"))
assert(result.contains("node m_r_oob = not(gt(UInt<5>(\"h1e\"), m_r_addr))"))

// the source of randomness needs to be triggered when there is an out of bounds read
assert(result.contains("rand m_r_rand_data : UInt<32>, m_r_clk when m_r_oob"))
Expand Down Expand Up @@ -137,7 +137,7 @@ class UndefinedMemoryBehaviorSpec extends LeanTransformSpec(Seq(Dependency(Undef
assert(result.contains("node m_r_disabled = not(m_r_en)"))

// an out of bounds read happens if the depth is not greater or equal to the address and the memory is enabled
assert(result.contains("node m_r_oob = and(m_r_en, not(geq(UInt<5>(\"h1e\"), m_r_addr)))"))
assert(result.contains("node m_r_oob = and(m_r_en, not(gt(UInt<5>(\"h1e\"), m_r_addr)))"))

// the two possible issues are combined into a single signal
assert(result.contains("node m_r_do_rand = or(m_r_disabled, m_r_oob)"))
Expand Down
Loading

0 comments on commit 254c396

Please sign in to comment.