firrtl
firrtl copied to clipboard
Support synthesis directives thru annotations (/* ... */)
Checklist
- [x] Did you write out a description of the feature you want to see?
- [x] Did you look around for any related features?
- [x] Did you specify relevant external information?
Feature Description
This feature request objective is to provide an annotation type to allow adding synthesis directives into the generated Verilog code for the synthesys tools.
The idea is that the annotation would allow generic, unfiltered text bound to a target. The targets could be reg
, module
, input
, output
, case
, wire
and maybe others.
Below some examples collected from synthesis manuals:
reg net_reg1 /* synthesis syn_preserve = 1 */ ;
reg net_reg2 /* verilator clock_enable */ ;
reg [3:0] curstate /* synthesis syn_state_machine=0 */ ;
reg [5:0] q, q_a, q_b, q_c, q_d /* synthesis syn_preserve=1 */;
reg [1:0] mem [7:0] /* synthesis syn_ramstyle="no_rw_check" */;
reg [1:0] mem [7:0] /* synthesis ram_init_file = "memoryFile.hex" */;
module fifo(out, in) /* synthesis syn_hier = "hard“ */;
// To attach multiple attributes or directives to the same object, separate the attributes with white spaces
case state /* synthesis full_case parallel_case */;
wire in1a /*synthesis syn_keep = 1*/;
input wire [3:0] ina /* synthesis ace_useioff=1 */;
output reg z0 /* synthesis ace_useioff=1 */;
The content of this annotation is user's responsibility and in Firrtl we could add some validations like avoiding multiple synthesys
words in case of multiple attributes.
Firrtl annotation would be exposed similarly as below in Chisel code:
val mem = SyncReadMem(words, UInt(bitWidth.W))
if (memoryFile.trim().nonEmpty) {
loadMemoryFromFileInline(mem, memoryFile)
}
annotate(new ChiselAnnotation {
override def toFirrtl = SynthesizerDirective(
mem.toTarget,
s"""synthesis ram_init_file = "$memoryFile""""
)
})
An easier interface could be added afterwards in Chisel.
Type of Feature
- new feature/API
I have already started a draft implementation of this feature but the main problem where I'm stuck is how to place these directives inline with the declaration before the object's ;
.
I might need some help here.
I think you can take a look at AttributeAnnotation
implementation:
Basically, you need to extend from DescriptionAnnotation
. check the the all DescriptionAnnotation
usages in VerilogEmitter
:
Here are some places you can take a look:
https://github.com/chipsalliance/firrtl/blob/master/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala#L410
https://github.com/chipsalliance/firrtl/blob/master/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala#L526-L527
https://github.com/chipsalliance/firrtl/blob/94d1bee4c23bd3d8f99dae3ca431ffaa5dc1410d/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala#L960
You may need to add your implementation at:
https://github.com/chipsalliance/firrtl/blob/94d1bee4c23bd3d8f99dae3ca431ffaa5dc1410d/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala#L643 : reg / wire
https://github.com/chipsalliance/firrtl/blob/94d1bee4c23bd3d8f99dae3ca431ffaa5dc1410d/src/main/scala/firrtl/backends/verilog/VerilogEmitter.scala#L944-L957 : ports
I plan on looking into this again, I wonder what's the best approach and syntax to use this, Verilog-1995 or Verilog-2001.
As an example here: https://www.intel.com/content/www/us/en/support/programmable/articles/000074381.html:
Verilog-1995:
output reg my_reg /* synthesis syn_preserve = 1 */;
Verilog-2001
(* syn_preserve *) output reg my_reg;
Which is used by the Verilog emitter? While looking at [VerilogEmitterTests.scala], I saw that Verilog-2001 syntax is used in AttributeAnnotation. I wonder if it's the same thing.