LazyModule 和 LazyModuleImp 之间的差异
Differences between LazyModule and LazyModuleImp
LazyModule 和 LazyModuleImp 有什么区别?
就像rocket-chip/doc下的外交演示说的那样:The desired hardware for the module must be written inside LazyModuleImp.
但考虑以下代码:
class A(implicit p: Parameters) extends LazyModule {
val b = LazyModule(new Leaf)
val c = LazyModule(new Leaf)
val input = b.input
val output = c.output
val bOutput = b.output.makeSink
val cInput = BundleBridgeSource[Bool](() => Bool())
c.input := cInput
lazy val module = new LazyModuleImp(this) {
cInput.bundle := bOutput.bundle
}
}
:=
是硬件操作,在LazyModuleImp内部和外部都会出现,那么LazyModuleImp应该放哪段代码?
考虑 LazyModule 的最佳方式 (IMO) 是 LazyModule 本质上有两个部分
- 非硬件实现(
LazyModuleImp
之外的所有内容)这是我们定义 Nodes
、解析参数、执行任何人们认为是“软件”的地方
- 硬件实现(
LazyModuleImp
中的所有内容)这是我们创建实际硬件的地方。我们一般都是用外面解析出来的参数来搭建一些硬件。
在外交方面,:=
实际上是Node
联系。您在其中连接两个外交节点。执行此连接时,您实际上是在“绘制”从一个节点到另一个节点的路径。在外交演示的情况下,您将把 AdderDriverNode
连接到 AdderNode
。这是在 LazyModuleImp
的 外部 执行的,因为我们需要在 之前定义此节点图 我们可以构建硬件。
例如,如果您查看 AdderTestHarness
,您可以在 LazyModuleImp
之外看到以下内容
// create edges via binding operators between nodes in order to define a complete graph
drivers.foreach{ driver => adder.node := driver.node }
drivers.zip(monitor.nodeSeq).foreach { case (driver, monitorNode) => monitorNode := driver.node }
monitor.nodeSum := adder.node
在这里,我们将驱动程序连接到加法器,将驱动程序连接到监视器,然后将加法器连接到监视器。这些连接基于为每个节点定义的 Bundle 生成创建硬件。
所以我倾向于将 LazyModules
和一般的外交视为创建硬件的两次通过方法。第一步是定义硬件拓扑。这是在 LazyModuleImp
之外完成的。我将描述每一块是如何连接的,并解析宽度、地址等参数。第二遍是实际的硬件生成。在这里,我所有的参数都应该被解析,我定义的硬件现在已经创建了。
外交令人印象深刻,但掌握起来却相当困难。特别是如果来自严格的硬件背景或严格的软件背景。它需要对某些软件范例的工作原理有深刻的理解,才能掌握 parameter/edge 分辨率的架构,然后你就会遇到使用它来实际创建一些真实硬件的障碍。
LazyModule 和 LazyModuleImp 有什么区别?
就像rocket-chip/doc下的外交演示说的那样:The desired hardware for the module must be written inside LazyModuleImp.
但考虑以下代码:
class A(implicit p: Parameters) extends LazyModule {
val b = LazyModule(new Leaf)
val c = LazyModule(new Leaf)
val input = b.input
val output = c.output
val bOutput = b.output.makeSink
val cInput = BundleBridgeSource[Bool](() => Bool())
c.input := cInput
lazy val module = new LazyModuleImp(this) {
cInput.bundle := bOutput.bundle
}
}
:=
是硬件操作,在LazyModuleImp内部和外部都会出现,那么LazyModuleImp应该放哪段代码?
考虑 LazyModule 的最佳方式 (IMO) 是 LazyModule 本质上有两个部分
- 非硬件实现(
LazyModuleImp
之外的所有内容)这是我们定义Nodes
、解析参数、执行任何人们认为是“软件”的地方 - 硬件实现(
LazyModuleImp
中的所有内容)这是我们创建实际硬件的地方。我们一般都是用外面解析出来的参数来搭建一些硬件。
在外交方面,:=
实际上是Node
联系。您在其中连接两个外交节点。执行此连接时,您实际上是在“绘制”从一个节点到另一个节点的路径。在外交演示的情况下,您将把 AdderDriverNode
连接到 AdderNode
。这是在 LazyModuleImp
的 外部 执行的,因为我们需要在 之前定义此节点图 我们可以构建硬件。
例如,如果您查看 AdderTestHarness
,您可以在 LazyModuleImp
// create edges via binding operators between nodes in order to define a complete graph
drivers.foreach{ driver => adder.node := driver.node }
drivers.zip(monitor.nodeSeq).foreach { case (driver, monitorNode) => monitorNode := driver.node }
monitor.nodeSum := adder.node
在这里,我们将驱动程序连接到加法器,将驱动程序连接到监视器,然后将加法器连接到监视器。这些连接基于为每个节点定义的 Bundle 生成创建硬件。
所以我倾向于将 LazyModules
和一般的外交视为创建硬件的两次通过方法。第一步是定义硬件拓扑。这是在 LazyModuleImp
之外完成的。我将描述每一块是如何连接的,并解析宽度、地址等参数。第二遍是实际的硬件生成。在这里,我所有的参数都应该被解析,我定义的硬件现在已经创建了。
外交令人印象深刻,但掌握起来却相当困难。特别是如果来自严格的硬件背景或严格的软件背景。它需要对某些软件范例的工作原理有深刻的理解,才能掌握 parameter/edge 分辨率的架构,然后你就会遇到使用它来实际创建一些真实硬件的障碍。