makeSink 方法为外围制作 IOs 的目的是什么

What is the purpose of the makeSink method in making IOs for a periphery

我正在关注一些向火箭芯片添加外围设备的示例。 我用了sifive-blocks作为参考。

下面是他们的 I2C 示例中的一个示例(我希望在这里 post 它没问题)

case object PeripheryI2CKey extends Field[Seq[I2CParams]]

trait HasPeripheryI2C { this: BaseSubsystem =>
  val i2cNodes =  p(PeripheryI2CKey).map { ps =>
    I2C.attach(I2CAttachParams(ps, pbus, ibus.fromAsync)).ioNode.makeSink()
  }
}

trait HasPeripheryI2CBundle {
  val i2c: Seq[I2CPort]
}

trait HasPeripheryI2CModuleImp extends LazyModuleImp with HasPeripheryI2CBundle {
  val outer: HasPeripheryI2C
  val i2c  = outer.i2cNodes.zipWithIndex.map  { case(n,i) => n.makeIO()(ValName(s"i2c_$i")) }
}

我了解 makeIO 步骤,即获取一个包并在其上应用 IO,但不了解 makeSink 步骤。 他们为什么要做这一步,makeIO 还不够吗?

我不是 rocket-chip 外交方面的专家,但从代码来看,我认为 makeIOmakeSink 做了根本不同的事情。

makeIO 采用 BundleBridgeSource 并具体化 Chisel 模块实现中的端口以驱动该源。 BundleBrigeSink上也有同样的方法。我相信这种方法是您采用 Bundle 桥的任一侧并在生成器的实际 Chisel 部分(与外交部分相对)与之交互的方式。

makeSinkBundleBridgeSource 变成 BundleBridgeSink。它不会具体化 Chisel 港口并且它停留在外交世界而不是 Chisel 世界。

在您包含的 I2C 的示例中,请注意带有 makeSink 的部分是如何混合到扩展 BaseSubsystem 的内容中的特征,它是外交的。另一方面,具有 makeIOHasPeripheryI2CModuleImp 扩展了 LazyModuleImp,这是 Chisel 部分。一种思考方式是同一事物的两个不同 "views"。凿子和外交使用不同的对象,因此 i2cNodes(外交)与 i2c(凿子)。