Search code examples
chiselfirrtl

In Chisel3, how to add `mark_debug = "true"` attribute to an internal signal in the output SystemVerilog file?


As stated in the title, I want to easily make any internal signals in my design to be available for debugging in Vivado (mostly ILA). In version 3.5.3 I was able to use a snippet to do it, however in much more recent versions (for example 6.6.0), it seems that the whole HDL code generation has been revamped, and now I can't find a way to do it. FYI, here's the snippet:

object markDebug {
  /** Mark a signal as debug to Chisel and FIRRTL, and avoid optimization if specified.
   */
  def apply[T <: Data](data: T, markDontTouch: Boolean = false): T = {
    annotate(new ChiselAnnotation { def toFirrtl = AttributeAnnotation(data.toNamed, "mark_debug = \"true\"") })
    if (markDontTouch) dontTouch(data) else data
  }
}

I tried looking into Chisel's source code, but most firrtl-related stuff were gone. And I guess the answer at https://stackoverflow.com/a/76223005/8777949 can solve part of my problem?


Solution

  • In chisel 7.x, you can use addAttribute:

    chisel3.util.addAttribute(data, "mark_debug = \"true\""`)
    

    It hasn’t been backported to the 6.x branch (I don’t know why), but the firtool backend has always supported it, so you just need to define the annotation with the right name in your code:

    
    package firrtl {
      import firrtl.annotations._
    
      /** used by [[addAttribute]] to add SystemVerilog attributes to a [[Target]].
        *
        * The class name `firrtl.AttributeAnnotation` is recognized by firtool
        *
        * @param target
        * @param description
        */
      case class AttributeAnnotation(target: Target, description: String) extends SingleTargetAnnotation[Target] {
        def targets = Seq(target)
        def duplicate(n: Target) = this.copy(n, description)
    
        override def serialize: String = s"AttributeAnnotation(${target.serialize}, $description)"
      }
    }
    

    And:

    
    object addAttribute { // scalastyle:ignore object.name
        def apply[T <: chisel3.InstanceId](instance: T, attributes: (String, Any)*): T = {
    
          for ((attr, value) <- attributes) {
            apply(instance, attr, value)
          }
          instance
        }
    
        def apply[T <: InstanceId](inst: T, attribute: String, value: Any): T = {
          chisel3.experimental.annotate(
            new chisel3.experimental.ChiselAnnotation {
              val valueStr = value match {
                case _: String => s"\"$value\""
                case _ => value.toString
              }
              override def toFirrtl = new firrtl.AttributeAnnotation(inst.toTarget, s"$attribute = $valueStr")
    
            }
          )
          inst
        }
      }
    
    

    Note that firtool does not support handling SV attributes on ports ATM.