我想提供一个更完整的示例,但我想确保至少写一些东西。这也需要充实为网站上的适当示例/教程。
FIRRTL 对跨内置和自定义转换跟踪信号名称提供了强大的支持。在这种情况下,基础设施都在那里,但它在很大程度上是一个高级用户 API。简而言之,您可以创建 FIRRTL Annotations 来跟踪 Targets。然后,您可以发出自定义元数据文件或使用普通的 FIRRTL 注释文件(尝试 CLI 选项 -foaf / --output-annotation-file)。
一个示例 FIRRTL Annotation 将在编译结束时发出一个自定义元数据文件:
// 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 和相关的 baseFileName、suffix 和 getBytes 方法定义了如何序列化我的自定义元数据文件。正如评论中提到的,正如在这个例子中实现的那样,我们只能有这个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