Skip to content
This repository has been archived by the owner on Aug 20, 2024. It is now read-only.

Commit

Permalink
Create annotation to allow inline readmem in Verilog
Browse files Browse the repository at this point in the history
This PR adds a new annotation allowing inline loading for memory files
in Verilog code.
  • Loading branch information
carlosedp committed Mar 9, 2021
1 parent 8a4c156 commit b3d5edc
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@ project/metals.sbt

*~
*#*#
.vscode
3 changes: 3 additions & 0 deletions src/main/scala/firrtl/EmissionOption.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
Expand Down
21 changes: 20 additions & 1 deletion src/main/scala/firrtl/annotations/MemoryInitAnnotation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
12 changes: 11 additions & 1 deletion src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
}

Expand Down
17 changes: 17 additions & 0 deletions src/test/scala/firrtlTests/MemoryInitSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit b3d5edc

Please sign in to comment.