aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlbert Magyar2021-03-09 22:25:55 -0800
committerAlbert Magyar2021-04-05 12:00:02 -0700
commit8a9dfa8b0324b3f52e676b9d27912656c43dd327 (patch)
tree2c4b12eef16d70443300535b37865ff45eea57e6 /src
parenta90cf1105467cab7c6708ea3faae35e1454cb0fd (diff)
Optionally allow simple SyncReadMems to pass through VerilogMemDelays
* This is enabled by adding a PassthroughSimpleSyncReadMemsAnnotation * Can be emitted directly with new changes to the Verilog emitter * Add some new deprecations to VerilogMemDelays * Run scalafmt on VerilogMemDelays
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/passes/memlib/VerilogMemDelays.scala41
1 files changed, 37 insertions, 4 deletions
diff --git a/src/main/scala/firrtl/passes/memlib/VerilogMemDelays.scala b/src/main/scala/firrtl/passes/memlib/VerilogMemDelays.scala
index 143b925a..a9b42eba 100644
--- a/src/main/scala/firrtl/passes/memlib/VerilogMemDelays.scala
+++ b/src/main/scala/firrtl/passes/memlib/VerilogMemDelays.scala
@@ -10,12 +10,22 @@ import firrtl.Mappers._
import firrtl.traversals.Foreachers._
import firrtl.transforms
import firrtl.options.Dependency
+import firrtl.annotations.NoTargetAnnotation
import MemPortUtils._
import WrappedExpression._
import collection.mutable
+/**
+ * Adding this annotation will allow the [[VerilogMemDelays]] transform to let 'simple' synchronous-read memories to
+ * pass through without explicitly breaking them apart into combinational-read memories and pipeline registers. Here,
+ * 'simple' memories are defined as those that have one-cycle read and write latencies AND either no readwrite ports or
+ * read-under-write behavior that is either 'undefined' or 'old'. This second restriction avoids the particularly
+ * complex case of blending FIRRTL readwrite port semantics with cross-port 'bypassing' of new data on collisions.
+ */
+case object PassthroughSimpleSyncReadMemsAnnotation extends NoTargetAnnotation
+
object MemDelayAndReadwriteTransformer {
// Representation of a group of signals and associated valid signals
case class WithValid(valid: Expression, payload: Seq[Expression])
@@ -77,13 +87,14 @@ object MemDelayAndReadwriteTransformer {
*
* @note The final transformed module is found in the (sole public) field [[transformed]]
*/
-class MemDelayAndReadwriteTransformer(m: DefModule) {
+class MemDelayAndReadwriteTransformer(m: DefModule, passthroughSimpleSyncReadMems: Boolean = false) {
import MemDelayAndReadwriteTransformer._
private val ns = Namespace(m)
private val netlist = new collection.mutable.HashMap[WrappedExpression, Expression]
private val exprReplacements = new collection.mutable.HashMap[WrappedExpression, Expression]
private val newConns = new mutable.ArrayBuffer[Connect]
+ private val passthroughMems = new collection.mutable.HashSet[WrappedExpression]
private def findMemConns(s: Statement): Unit = s match {
case Connect(_, loc, expr) if (kind(loc) == MemKind) => netlist(we(loc)) = expr
@@ -95,7 +106,15 @@ class MemDelayAndReadwriteTransformer(m: DefModule) {
case ex => ex
}
+ def canPassthrough(mem: DefMemory): Boolean = {
+ (mem.readLatency <= 1 && mem.writeLatency == 1 &&
+ (mem.readwriters.isEmpty || (mem.readLatency == 1 && mem.readUnderWrite != ReadUnderWrite.New)))
+ }
+
private def transform(s: Statement): Statement = s.map(transform) match {
+ case mem: DefMemory if passthroughSimpleSyncReadMems && canPassthrough(mem) =>
+ passthroughMems += WRef(mem)
+ mem
case mem: DefMemory =>
// Per-memory bookkeeping
val portNS = Namespace(mem.readers ++ mem.writers)
@@ -163,7 +182,13 @@ class MemDelayAndReadwriteTransformer(m: DefModule) {
newConns ++= (readStmts ++ writeStmts).flatMap(_.conns)
Block(newMem +: (readStmts ++ writeStmts).flatMap(_.decls))
- case sx: Connect if kind(sx.loc) == MemKind => EmptyStmt // Filter old mem connections
+ case sx: Connect if kind(sx.loc) == MemKind =>
+ val (memRef, _) = Utils.splitRef(sx.loc)
+ // Filter old mem connections for *transformed* memories only
+ if (passthroughMems(WrappedExpression(memRef)))
+ sx
+ else
+ EmptyStmt
case sx => sx.map(swapMemRefs)
}
@@ -188,6 +213,14 @@ object VerilogMemDelays extends Pass {
case _ => false
}
- def transform(m: DefModule): DefModule = (new MemDelayAndReadwriteTransformer(m)).transformed
- def run(c: Circuit): Circuit = c.copy(modules = c.modules.map(transform))
+ private def transform(m: DefModule): DefModule = (new MemDelayAndReadwriteTransformer(m)).transformed
+
+ @deprecated("VerilogMemDelays will change from a Pass to a Transform in FIRRTL 1.6.", "FIRRTL 1.5")
+ def run(c: Circuit): Circuit = c.copy(modules = c.modules.map(transform))
+
+ override def execute(state: CircuitState): CircuitState = {
+ val enablePassthrough = state.annotations.contains(PassthroughSimpleSyncReadMemsAnnotation)
+ def transform(m: DefModule) = (new MemDelayAndReadwriteTransformer(m, enablePassthrough)).transformed
+ state.copy(circuit = state.circuit.copy(modules = state.circuit.modules.map(transform)))
+ }
}