chipsalliance / firrtl

Flexible Intermediate Representation for RTL
https://www.chisel-lang.org/firrtl/
Apache License 2.0
726 stars 177 forks source link

Support synthesis directives thru annotations (/* ... */) #2131

Open carlosedp opened 3 years ago

carlosedp commented 3 years ago

Checklist

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

carlosedp commented 3 years ago

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.

sequencer commented 3 years ago

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

carlosedp commented 2 years ago

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.