aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala6
-rw-r--r--src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala41
-rw-r--r--src/test/scala/firrtlTests/MemoryInitSpec.scala40
3 files changed, 83 insertions, 4 deletions
diff --git a/src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala b/src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala
index 62dc96f4..1e81301d 100644
--- a/src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala
+++ b/src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala
@@ -52,3 +52,9 @@ case class MemoryFileInlineAnnotation(
override def initValue: MemoryInitValue = MemoryFileInlineInit(filename, hexOrBinary)
override def isRandomInit: Boolean = false
}
+
+/** Initializes the memory inside the `ifndef SYNTHESIS` block (default) */
+case object MemoryNoSynthInit extends NoTargetAnnotation
+
+/** Initializes the memory outside the `ifndef SYNTHESIS` block */
+case object MemorySynthInit extends NoTargetAnnotation
diff --git a/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala b/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala
index 33c6b9a8..f854b33a 100644
--- a/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala
+++ b/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala
@@ -7,7 +7,14 @@ import firrtl.PrimOps._
import firrtl.Utils._
import firrtl.WrappedExpression._
import firrtl.traversals.Foreachers._
-import firrtl.annotations.{CircuitTarget, MemoryLoadFileType, ReferenceTarget, SingleTargetAnnotation}
+import firrtl.annotations.{
+ CircuitTarget,
+ MemoryLoadFileType,
+ MemoryNoSynthInit,
+ MemorySynthInit,
+ ReferenceTarget,
+ SingleTargetAnnotation
+}
import firrtl.passes.LowerTypes
import firrtl.passes.MemPortUtils._
import firrtl.stage.TransformManager
@@ -482,6 +489,21 @@ class VerilogEmitter extends SeqTransform with Emitter {
def getConnectEmissionOption(target: ReferenceTarget): ConnectEmissionOption =
connectEmissionOption(target)
+ // Defines the memory initialization based on the annotation
+ // Defaults to having the memories inside the `ifndef SYNTHESIS` block
+ def emitMemoryInitAsNoSynth: Boolean = {
+ val annos = annotations.collect { case a @ (MemoryNoSynthInit | MemorySynthInit) => a }
+ annos match {
+ case Seq() => true
+ case Seq(MemoryNoSynthInit) => true
+ case Seq(MemorySynthInit) => false
+ case other =>
+ throw new FirrtlUserException(
+ "There should only be at most one memory initialization option annotation, got $other"
+ )
+ }
+ }
+
private val emissionAnnos = annotations.collect {
case m: SingleTargetAnnotation[ReferenceTarget] @unchecked with EmissionOption => m
}
@@ -861,7 +883,14 @@ class VerilogEmitter extends SeqTransform with Emitter {
case MemoryLoadFileType.Binary => "$readmemb"
case MemoryLoadFileType.Hex => "$readmemh"
}
- memoryInitials += Seq(s"""$readmem("$filename", ${s.name});""")
+ 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)
+ }
}
}
@@ -1200,13 +1229,19 @@ class VerilogEmitter extends SeqTransform with Emitter {
for (x <- initials) emit(Seq(tab, x))
for (x <- asyncInitials) emit(Seq(tab, x))
emit(Seq(" `endif // RANDOMIZE"))
- for (x <- memoryInitials) emit(Seq(tab, x))
+
+ if (emissionOptions.emitMemoryInitAsNoSynth) {
+ for (x <- memoryInitials) emit(Seq(tab, x))
+ }
emit(Seq("end // initial"))
// User-defined macro of code to run after an initial block
emit(Seq("`ifdef FIRRTL_AFTER_INITIAL"))
emit(Seq("`FIRRTL_AFTER_INITIAL"))
emit(Seq("`endif"))
emit(Seq("`endif // SYNTHESIS"))
+ if (!emissionOptions.emitMemoryInitAsNoSynth) {
+ for (x <- memoryInitials) emit(Seq(tab, x))
+ }
}
if (formals.keys.nonEmpty) {
diff --git a/src/test/scala/firrtlTests/MemoryInitSpec.scala b/src/test/scala/firrtlTests/MemoryInitSpec.scala
index a7c9966a..44f0162e 100644
--- a/src/test/scala/firrtlTests/MemoryInitSpec.scala
+++ b/src/test/scala/firrtlTests/MemoryInitSpec.scala
@@ -4,7 +4,7 @@ package firrtlTests
import firrtl._
import firrtl.annotations._
-import firrtl.testutils.FirrtlCheckers.containLine
+import firrtl.testutils.FirrtlCheckers.{containLine, containLines}
import firrtl.testutils.FirrtlFlatSpec
import firrtlTests.execution._
@@ -182,6 +182,44 @@ class MemInitSpec extends FirrtlFlatSpec {
compile(Seq(MemoryFileInlineAnnotation(mRef, filename = "")))
}
}
+
+ "MemoryInitialization" should "emit readmem in `ifndef SYNTHESIS` block by default" in {
+ val annos = Seq(
+ MemoryFileInlineAnnotation(mRef, filename = "text.hex", hexOrBinary = MemoryLoadFileType.Hex)
+ )
+ val result = compile(annos)
+ result should containLines(
+ """`endif // RANDOMIZE""",
+ """$readmemh("text.hex", """ + mRef.name + """);""",
+ """end // initial"""
+ )
+ }
+
+ "MemoryInitialization" should "emit readmem outside `ifndef SYNTHESIS` block with MemorySynthInit annotation" in {
+ val annos = Seq(
+ MemoryFileInlineAnnotation(mRef, filename = "text.hex", hexOrBinary = MemoryLoadFileType.Hex)
+ ) ++ Seq(MemorySynthInit)
+ val result = compile(annos)
+ result should containLines(
+ """`endif // SYNTHESIS""",
+ """initial begin""",
+ """$readmemh("text.hex", """ + mRef.name + """);""",
+ """end"""
+ )
+ }
+
+ "MemoryInitialization" should "emit readmem outside `ifndef SYNTHESIS` block with MemoryNoSynthInit annotation" in {
+ val annos = Seq(
+ MemoryFileInlineAnnotation(mRef, filename = "text.hex", hexOrBinary = MemoryLoadFileType.Hex)
+ ) ++ Seq(MemoryNoSynthInit)
+
+ val result = compile(annos)
+ result should containLines(
+ """`endif // RANDOMIZE""",
+ """$readmemh("text.hex", """ + mRef.name + """);""",
+ """end // initial"""
+ )
+ }
}
abstract class MemInitExecutionSpec(values: Seq[Int], init: ReferenceTarget => Annotation)