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
|
// SPDX-License-Identifier: Apache-2.0
package firrtl.stage
import firrtl.transforms._
import firrtl.passes.memlib._
import firrtl.options.{HasShellOptions, ShellOption}
import firrtl.annotations.MemorySynthInit
/**
* This flag enables a set of options that guide the FIRRTL compilation flow to ultimately generate Verilog that is
* more amenable to using for synthesized FPGA designs. Currently, this flag affects only memories, as the need to emit
* memories that support downstream inference of hardened RAM macros. These options are not intended to be specialized
* to any particular vendor; instead, they aim to emit simple Verilog that more closely reflects traditional
* human-written definitions of synchronous-read memories.
*
* 1) Enable the [[firrtl.passes.memlib.InferReadWrite]] transform to reduce port count, where applicable.
*
* 2) Use the [[firrtl.transforms.SimplifyMems]] transform to Lower aggregate-typed memories with always-high masks to
* packed memories without splitting them into multiple independent ground-typed memories.
*
* 3) Use the [[firrtl.passes.memlib.SeparateWriteClocks]] transform to ensure that each write port of a
* multiple-write, synchronous-read memory with 'undefined' collision behavior ultimately maps to a separate clocked
* process in the emitted Verilog. This avoids the issue of implicitly constraining cross-port collision and write
* ordering behavior and helps simplify inference of true dual-port RAM macros.
*
* 4) Use the [[firrtl.passes.memlib.SetDefaultReadUnderWrite]] to specify that memories with undefined
* read-under-write behavior should map to emitted microarchitectures characteristic of "read-first" ports by
* default. This eliminates the difficulty of inferring a RAM macro that matches the strict semantics of
* "write-first" ports.
*
* 5) Add a [[firrtl.passes.memlib.PassthroughSimpleSyncReadMemsAnnotation]] to allow some synchronous-read memories
* and readwrite ports to pass through [[firrtl.passes.memlib.VerilogMemDelays]] without introducing explicit
* pipeline registers or splitting ports.
*
* 6) Add a [[firrtl.annotations.MemorySynthInit]] to enable memory initialization values to be synthesized.
*/
object OptimizeForFPGA extends HasShellOptions {
private val fpgaAnnos = Seq(
InferReadWriteAnnotation,
RunFirrtlTransformAnnotation(new InferReadWrite),
RunFirrtlTransformAnnotation(new SeparateWriteClocks),
DefaultReadFirstAnnotation,
RunFirrtlTransformAnnotation(new SetDefaultReadUnderWrite),
RunFirrtlTransformAnnotation(new SimplifyMems),
PassthroughSimpleSyncReadMemsAnnotation,
MemorySynthInit
)
val options = Seq(
new ShellOption[Unit](
longOption = "target:fpga",
toAnnotationSeq = a => fpgaAnnos,
helpText = "Choose compilation strategies that generally favor FPGA targets"
)
)
}
|