aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/main/scala/firrtl/EmissionOption.scala3
-rw-r--r--src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala21
-rw-r--r--src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala12
-rw-r--r--src/test/scala/firrtlTests/MemoryInitSpec.scala17
5 files changed, 52 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 8b3d51a6..dd2f998b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -66,3 +66,4 @@ project/metals.sbt
*~
*#*#
+.vscode
diff --git a/src/main/scala/firrtl/EmissionOption.scala b/src/main/scala/firrtl/EmissionOption.scala
index 074d9c28..90eb5851 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 44656e0d..62dc96f4 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,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
+}
diff --git a/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala b/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala
index f1650ad7..bc4996df 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, MemoryLoadFileType, ReferenceTarget, SingleTargetAnnotation}
import firrtl.passes.LowerTypes
import firrtl.passes.MemPortUtils._
import firrtl.stage.TransformManager
@@ -849,6 +849,16 @@ class VerilogEmitter extends SeqTransform with Emitter {
rstring,
";"
)
+ case MemoryFileInlineInit(filename, hexOrBinary) =>
+ 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)
}
}
diff --git a/src/test/scala/firrtlTests/MemoryInitSpec.scala b/src/test/scala/firrtlTests/MemoryInitSpec.scala
index 18f2b7ff..a7c9966a 100644
--- a/src/test/scala/firrtlTests/MemoryInitSpec.scala
+++ b/src/test/scala/firrtlTests/MemoryInitSpec.scala
@@ -165,6 +165,23 @@ class MemInitSpec extends FirrtlFlatSpec {
assert(annos == Seq(MemoryArrayInitAnnotation(mRef, largeSeq)))
}
+ "MemoryFileInlineAnnotation" should "emit $readmemh for text.hex" in {
+ val annos = Seq(MemoryFileInlineAnnotation(mRef, filename = "text.hex"))
+ val result = compile(annos)
+ result should containLine("""$readmemh("text.hex", """ + mRef.name + """);""")
+ }
+
+ "MemoryFileInlineAnnotation" should "emit $readmemb for text.bin" in {
+ val annos = Seq(MemoryFileInlineAnnotation(mRef, filename = "text.bin", hexOrBinary = MemoryLoadFileType.Binary))
+ val result = compile(annos)
+ result should containLine("""$readmemb("text.bin", """ + mRef.name + """);""")
+ }
+
+ "MemoryFileInlineAnnotation" should "fail with blank filename" in {
+ assertThrows[Exception] {
+ compile(Seq(MemoryFileInlineAnnotation(mRef, filename = "")))
+ }
+ }
}
abstract class MemInitExecutionSpec(values: Seq[Int], init: ReferenceTarget => Annotation)