Chisel:在最终 Verilog 中获取信号名称

Chisel: getting signal name in final Verilog

我想尽可能多地自动从 Chisel 代码中直接对 ILA 进行实例化。这意味着实例化一个看起来像这样的模块:

i_ila my_ila(
.clk(clock),
.probe0(a_signal_to_monitor),
.probe1(another_signal_to_monitor),
// and so on
);

我打算将我想要监视的信号存储在 UInt 的列表中,以便在模块详细说明结束时我可以生成上面的实例化代码,我将 copy/paste 在最终的 Verilog 代码中(或编写一个自动执行此操作的 Python 脚本)。

首先,是否有更好的方法来执行此操作,也许是在 FIRRTL 级别?

即使我采用这种半手动方法,我也需要知道最终 Verilog 中的信号名称是什么,这不一定是代码中 UInt 值的名称(此外,我不知道如何自动获取而不必在某处将变量名称重新键入为字符串)。我怎样才能得到它们?

我想提供一个更完整的例子,但我想确保至少写点东西。这也需要在网站上充实为适当的 example/tutorial。

FIRRTL 对跨 built-in 和自定义转换跟踪信号名称提供了强大的支持。在这种情况下,基础架构就在那里,但它是一个超级用户 API。简而言之,您可以创建 FIRRTL Annotations that will track Targets。然后您可以发出自定义元数据文件或使用普通的 FIRRTL 注释文件(尝试 CLI 选项 -foaf / --output-annotation-file)。

FIRRTL 注释示例将在编译结束时发出自定义元数据文件:

// Example FIRRTL annotation with Custom serialization
// FIRRTL will track the name of this signal through compilation
case class MyMetadataAnno(target: ReferenceTarget)
    extends SingleTargetAnnotation[ReferenceTarget]
    with CustomFileEmission {
  def duplicate(n: ReferenceTarget) = this.copy(n)

  // API for serializing a custom metadata file
  // Note that multiple of this annotation will collide which is an error, not handled in this example
  protected def baseFileName(annotations: AnnotationSeq): String = "my_metadata"
  protected def suffix: Option[String] = Some(".txt")
  def getBytes: Iterable[Byte] =
    s"Annotated signal: ${target.serialize}".getBytes
}

case class声明和duplicate方法足以通过编译跟踪单个信号。 CustomFileEmission 和相关的 baseFileNamesuffixgetBytes 方法定义了如何序列化我的自定义元数据文件。正如评论中提到的,如本示例中所实现的,我们只能拥有此 MyMetadataAnno 的 1 个实例,否则他们将尝试写入相同的文件,这是一个错误。这可以通过根据 Target 自定义文件名或编写 FIRRTL 转换以将多个此注释聚合为单个注释来处理。

然后我们需要一种在 Chisel 中创建此注释的方法:

  def markSignal[T <: Data](x: T): T = {
    annotate(new ChiselAnnotation {
      // We can't call .toTarget until end of Chisel elaboration
      // .toFirrtl is called by Chisel at the end of elaboration
      def toFirrtl = MyMetadataAnno(x.toTarget)
    })
    x
  }

现在我们需要做的就是在我们的 Chisel

中使用这个简单的 API
// Simple example with a marked signal
class Foo extends MultiIOModule {
  val in = IO(Flipped(Decoupled(UInt(8.W))))
  val out = IO(Decoupled(UInt(8.W)))

  markSignal(out.valid)

  out <> in
}

这将导致将文件 my_metadata.txt 写入目标目录,内容为:

Annotated signal: ~Foo|Foo>out_valid

请注意,这是特殊的 FIRRTL 目标语法,表示 out_valid 是模块 Foo 中的注释信号。

可执行示例中的完整代码: https://scastie.scala-lang.org/moEiIqZPTRCR5mLQNrV3zA