aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/passes/memlib/SetDefaultReadUnderWrite.scala
diff options
context:
space:
mode:
authorAlbert Magyar2021-04-05 14:26:34 -0700
committerGitHub2021-04-05 14:26:34 -0700
commited5e03f960d89c8b5c999e030b2ae4586fa4a976 (patch)
treee67a43a77c4c0fe4b729705d2c725c9e0c11943f /src/main/scala/firrtl/passes/memlib/SetDefaultReadUnderWrite.scala
parentca8b670eac0b0def66249738e52ef8137d30a8b5 (diff)
parent1afa3b40f78d781ca1f242b49ca3a56d6cbc57e4 (diff)
Merge pull request #2111 from chipsalliance/fpga-backend
Add -fpga flag to enable FPGA-oriented compilation strategies (currently for memories)
Diffstat (limited to 'src/main/scala/firrtl/passes/memlib/SetDefaultReadUnderWrite.scala')
-rw-r--r--src/main/scala/firrtl/passes/memlib/SetDefaultReadUnderWrite.scala57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/passes/memlib/SetDefaultReadUnderWrite.scala b/src/main/scala/firrtl/passes/memlib/SetDefaultReadUnderWrite.scala
new file mode 100644
index 00000000..d5646099
--- /dev/null
+++ b/src/main/scala/firrtl/passes/memlib/SetDefaultReadUnderWrite.scala
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package firrtl.passes
+package memlib
+
+import firrtl._
+import firrtl.ir._
+import firrtl.options.{Dependency, OptionsException}
+import firrtl.annotations.NoTargetAnnotation
+
+sealed trait DefaultReadUnderWriteAnnotation extends NoTargetAnnotation
+
+/** This annotation directs the [[SetDefaultReadUnderWrite]] transform to assign a default value of 'old' (read-first
+ * behavior) to all synchronous-read memories with 'undefined' read-under-write parameters.
+ */
+case object DefaultReadFirstAnnotation extends DefaultReadUnderWriteAnnotation
+
+/** This annotation directs the [[SetDefaultReadUnderWrite]] transform to assign a default value of 'new' (write-first
+ * behavior) to all synchronous-read memories with 'undefined' read-under-write parameters.
+ */
+case object DefaultWriteFirstAnnotation extends DefaultReadUnderWriteAnnotation
+
+/**
+ * Adding a [[DefaultReadUnderWriteAnnotation]] and running the [[SetDefaultReadUnderWrite]] transform will cause all
+ * synchronous-read memories with 'undefined' read-under-write parameters to be assigned a default parameter value,
+ * either 'old' (read-first behavior) or 'new' (write-first behavior). This can help generate Verilog that is amenable
+ * to RAM macro inference for various FPGA tools, or it can be used to satisfy other downstream design constraints.
+ */
+class SetDefaultReadUnderWrite extends Transform with DependencyAPIMigration {
+ override def prerequisites = firrtl.stage.Forms.HighForm
+ override def optionalPrerequisites = Seq(Dependency[InferReadWrite])
+ override def optionalPrerequisiteOf = Seq(Dependency(VerilogMemDelays))
+ override def invalidates(a: Transform): Boolean = false
+
+ private def onStmt(defaultRUW: ReadUnderWrite.Value)(stmt: Statement): Statement = stmt match {
+ case mem: DefMemory if (mem.readLatency > 0 && mem.readUnderWrite == ReadUnderWrite.Undefined) =>
+ mem.copy(readUnderWrite = defaultRUW)
+ case s => s.mapStmt(onStmt(defaultRUW))
+ }
+
+ override def execute(state: CircuitState): CircuitState = {
+ val c = state.circuit
+ val ruwDefaults = state.annotations
+ .collect({
+ case DefaultReadFirstAnnotation => ReadUnderWrite.Old
+ case DefaultWriteFirstAnnotation => ReadUnderWrite.New
+ })
+ .toSet
+ if (ruwDefaults.size == 0) {
+ state
+ } else if (ruwDefaults.size == 1) {
+ state.copy(circuit = c.copy(modules = c.modules.map(m => m.mapStmt(onStmt(ruwDefaults.head)))))
+ } else {
+ throw new OptionsException("Conflicting default read-under-write settings.")
+ }
+ }
+}