diff options
| author | Albert Magyar | 2021-03-09 22:25:55 -0800 |
|---|---|---|
| committer | Albert Magyar | 2021-04-05 12:00:02 -0700 |
| commit | 8a9dfa8b0324b3f52e676b9d27912656c43dd327 (patch) | |
| tree | 2c4b12eef16d70443300535b37865ff45eea57e6 /src | |
| parent | a90cf1105467cab7c6708ea3faae35e1454cb0fd (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.scala | 41 |
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))) + } } |
