From b701ec472e2548cf999a1f09742ea07a66786462 Mon Sep 17 00:00:00 2001 From: Carlos de Paula Date: Mon, 8 Mar 2021 20:10:14 -0300 Subject: [PATCH] Create annotation to allow inline readmem in Verilog This PR adds a new annotation allowing inline loading for memory files in Verilog code. --- src/main/scala/firrtl/EmissionOption.scala | 3 +++ .../annotations/MemoryInitAnnotation.scala | 20 ++++++++++++++++++- .../backends/verilog/VerilogEmitter.scala | 16 ++++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/main/scala/firrtl/EmissionOption.scala b/src/main/scala/firrtl/EmissionOption.scala index 074d9c2886..90eb585186 100644 --- a/src/main/scala/firrtl/EmissionOption.scala +++ b/src/main/scala/firrtl/EmissionOption.scala @@ -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] @@ -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 diff --git a/src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala b/src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala index 44656e0d08..f27f10263c 100644 --- a/src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala +++ b/src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala @@ -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. @@ -33,3 +40,14 @@ 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 { + override def duplicate(n: ReferenceTarget): Annotation = copy(n) + override def initValue: MemoryInitValue = MemoryFileInlineInit(filename, hexOrBinary) + override def isRandomInit: Boolean = false +} diff --git a/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala b/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala index f1650ad741..21792ee58b 100644 --- a/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala +++ b/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala @@ -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, ReferenceTarget, SingleTargetAnnotation, MemoryLoadFileType} import firrtl.passes.LowerTypes import firrtl.passes.MemPortUtils._ import firrtl.stage.TransformManager @@ -849,6 +849,20 @@ class VerilogEmitter extends SeqTransform with Emitter { rstring, ";" ) + case MemoryFileInlineInit(filename, hexOrBinary) => + if (filename.trim().isEmpty()) { + throw new Exception(s"empty filename not allowed in MemoryFileInlineAnnotation") + } + + val readmem = hexOrBinary match { + case MemoryLoadFileType.Binary => "$readmemb" + case MemoryLoadFileType.Hex => "$readmemh" + } + val inlineLoad = s""" + |initial begin + | $readmem("$filename", ${s.name}); + |end""".stripMargin + memoryInitials += Seq(inlineLoad) } }