diff options
| author | Kevin Laeufer | 2020-06-22 19:35:41 +0000 |
|---|---|---|
| committer | GitHub | 2020-06-22 19:35:41 +0000 |
| commit | 732d08761a97faedb878f022927c2cb429398d6f (patch) | |
| tree | b1aa4fe6e55906da5217719ea860bce15f470327 /src/main/scala/firrtl/passes | |
| parent | a25b1af3b6b842b8ce8de36e5f0c11b88756f09e (diff) | |
Support Memory Initialization for Simulation and FPGA Flows (#1645)
* Support Memory Initialization for Simulation and FPGA Flows
This adds a minimal annotation that allows users to
influence if memories are randomly initialized,
if all entries are initialized to the same scalar or
if each entry should be initialized to a different value.
We use the init block in order to initialize memories
which is supported by verilator as well as yosys
and has previously been used to randomize the initial
memory contents.
* LowerTypes: error when trying to split up a memory with MemoryInitAnnotation
Currently the MemoryInitAnnotation only works for
ground-type memories.
We catch misuse of this annotation at the point of
the firrtl compiler at which memories on non-ground type
get split up, i.e., the LowerTypes transform.
Chisel should try to prevent annotating non-ground
type memories in the frontend, but it is nice to
have an additional check.
* MemoryInitSpec: test JSON deserialization
* MemoryInitAnnotation: split up into three different annotations instead of exposing MemoryInitValue
Co-authored-by: Albert Magyar <albert.magyar@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Diffstat (limited to 'src/main/scala/firrtl/passes')
| -rw-r--r-- | src/main/scala/firrtl/passes/LowerTypes.scala | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/src/main/scala/firrtl/passes/LowerTypes.scala b/src/main/scala/firrtl/passes/LowerTypes.scala index 4a87ff8b..ccfe5828 100644 --- a/src/main/scala/firrtl/passes/LowerTypes.scala +++ b/src/main/scala/firrtl/passes/LowerTypes.scala @@ -8,6 +8,7 @@ import firrtl.ir._ import firrtl.Utils._ import MemPortUtils.memType import firrtl.Mappers._ +import firrtl.annotations.MemoryInitAnnotation /** Removes all aggregate types from a [[firrtl.ir.Circuit]] * @@ -166,9 +167,9 @@ object LowerTypes extends Transform with DependencyAPIMigration { case e @ (_: UIntLiteral | _: SIntLiteral) => e } def lowerTypesStmt(memDataTypeMap: MemDataTypeMap, - minfo: Info, mname: String, renames: RenameMap)(s: Statement): Statement = { + minfo: Info, mname: String, renames: RenameMap, initializedMems: Set[(String, String)])(s: Statement): Statement = { val info = get_info(s) match {case NoInfo => minfo case x => x} - s map lowerTypesStmt(memDataTypeMap, info, mname, renames) match { + s map lowerTypesStmt(memDataTypeMap, info, mname, renames, initializedMems) match { case s: DefWire => s.tpe match { case _: GroundType => s case _ => @@ -210,6 +211,10 @@ object LowerTypes extends Transform with DependencyAPIMigration { sx.dataType match { case _: GroundType => sx case _ => + // right now only ground type memories can be initialized + if(initializedMems.contains((mname, sx.name))) { + error(s"Cannot initialize memory of non ground type ${sx.dataType.serialize}")(info, mname) + } // Rename ports val seen: mutable.Set[String] = mutable.Set[String]() create_exps(sx.name, memType(sx)) foreach { e => @@ -264,7 +269,7 @@ object LowerTypes extends Transform with DependencyAPIMigration { } } - def lowerTypes(renames: RenameMap)(m: DefModule): DefModule = { + def lowerTypes(renames: RenameMap, initializedMems: Set[(String, String)])(m: DefModule): DefModule = { val memDataTypeMap = new MemDataTypeMap renames.setModule(m.name) // Lower Ports @@ -280,15 +285,19 @@ object LowerTypes extends Transform with DependencyAPIMigration { case m: ExtModule => m copy (ports = portsx) case m: Module => - m copy (ports = portsx) map lowerTypesStmt(memDataTypeMap, m.info, m.name, renames) + m copy (ports = portsx) map lowerTypesStmt(memDataTypeMap, m.info, m.name, renames, initializedMems) } } def execute(state: CircuitState): CircuitState = { + // remember which memories need to be initialized, for these memories, lowering non-ground types is not supported + val initializedMems = state.annotations.collect{ + case m : MemoryInitAnnotation if !m.isRandomInit => + (m.target.encapsulatingModule, m.target.ref) }.toSet val c = state.circuit val renames = RenameMap() renames.setCircuit(c.main) - val result = c copy (modules = c.modules map lowerTypes(renames)) + val result = c copy (modules = c.modules map lowerTypes(renames, initializedMems)) CircuitState(result, outputForm, state.annotations, Some(renames)) } } |
