blob: d56460990a2e43691e0e0a89689d09269566e12d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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.")
}
}
}
|