diff options
| author | Carlos Eduardo | 2021-04-01 18:55:03 -0300 |
|---|---|---|
| committer | GitHub | 2021-04-01 14:55:03 -0700 |
| commit | d0d3cd4ec4348eea381fe463ac9c96956fdd5eba (patch) | |
| tree | 3a035449ef49e5e7bca8f620339e18163285255e /src | |
| parent | ffe83fa43b9269f1e899122ba7825025df173b5a (diff) | |
Add memory initialization options for synthesis (#2166)
This PR adds options for memory initialization inside or outside the
`ifndef SYNTHESIS` block.
Diffstat (limited to 'src')
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) |
