在 Chisel 中实现外交 AXI Stream 接口 - BundleMap.cloneType 错误

Implementing a diplomatic AXI Stream interface in Chisel - BundleMap.cloneType error

我正在尝试构建一个最小示例,说明如何使用 Chisel 和外交生成 AXI4Stream 接口。我正在使用 rocket-chip (freechips.rocketchip.amba.axis) 中已有的外交界面。我对 Chisel 有一些经验,但我仍在努力学习外交。

无论如何,我已经使用此处提供的答案成功创建了一个小型 APB 示例:

之后,我尝试创建一个类似的、简单的 AXI Stream 示例,但我不断收到错误。具体来说,我收到以下错误:

[error] (Compile / run) java.lang.Exception: Unable to use BundleMap.cloneType on class freechips.rocketchip.amba.axis.AXISBundleBits, probably because class freechips.rocketchip.amba.axis.AXISBundleBits does not have a constructor accepting BundleFields. Consider overriding cloneType() on class freechips.rocketchip.amba.axis.AXISBundleBits

代码:

package chipyard.example
import chisel3._
import chisel3.internal.sourceinfo.SourceInfo
import chisel3.stage.ChiselStage
import freechips.rocketchip.config.{Config, Parameters}
import freechips.rocketchip.amba.axis._
import freechips.rocketchip.diplomacy.{SimpleNodeImp, ValName, SourceNode, NexusNode, 
                                       SinkNode, LazyModule, LazyModuleImp, TransferSizes,
                                       SimpleDevice, AddressSet}

class MyAxisController(implicit p: Parameters) extends LazyModule {
  val device = new SimpleDevice("my-device", Seq("tutorial,my-device0"))
  val axisParams = AXISSlaveParameters.v1(name = "axisSlave", supportsSizes = TransferSizes(8,8))
  val axisPortParams = AXISSlavePortParameters.v1(slaves = Seq(axisParams))
  val node = AXISSlaveNode(portParams = Seq(axisPortParams))

  lazy val module = new LazyModuleImp(this) {
      val ins = node.in.unzip._1
      val register = RegInit(UInt(8.W), 0.U)
      register := register + ins(0).bits.data
  }
}

class AXISMaster()(implicit p: Parameters) extends LazyModule {
  val axisMasterParams = AXISMasterParameters.v1(
    name = "axisMaster", emitsSizes = TransferSizes(8, 8)
  )

  val axisMasterPortParams = AXISMasterPortParameters.v1(
    masters = Seq(axisMasterParams),
    beatBytes = Option(8)
  )

  val node = AXISMasterNode(
    portParams = Seq(axisMasterPortParams)
  )

  
  lazy val module = new LazyModuleImp(this) {
    //The dontTouch here preserves the interface so logic is generated
    dontTouch(node.out.head._1)
  }
}


class MyAxisWrapper()(implicit p: Parameters) extends LazyModule {
  val master = LazyModule(new AXISMaster)
  val slave  = LazyModule(new MyAxisController()(Parameters.empty))

  slave.node := master.node 

  lazy val module = new LazyModuleImp(this) {
    //nothing???
  }
}

和Main.scala:

package chipyard.example

import chisel3._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._

import java.io.File
import java.io.FileWriter


/**
 * An object extending App to generate the Verilog code.
 */
object Main {
  def main(args: Array[String]): Unit = {
    //(new chisel3.stage.ChiselStage).execute(args, Seq(ChiselGeneratorAnnotation(() => LazyModule(new MyWrapper()(Parameters.empty)).module)))

    val verilog = (new chisel3.stage.ChiselStage).emitVerilog(
                   LazyModule(new MyAxisWrapper()(Parameters.empty)).module
    )
    //println(s"```verilog\n$verilog```")

    val fileWriter = new FileWriter(new File("./gen/gen.v"))
    fileWriter.write(verilog)
    fileWriter.close()

  }
}

该代码也可在 https://github.com/jurevreca12/temp_dspblock_example/tree/axistream2/scala/main 获得。

我的问题是。为什么会出现此错误?或者我一开始就做错了什么,有没有更简单的方法来创建 AXIStream 模块?

感谢任何反馈。

这似乎是 Rocket-Chip 为升级到 Chisel 3.5 所做的更改的问题。在这些更改期间,AXISBundleBits 删除了它的 cloneType,即使它扩展了 BundleMap(因此由于扩展了 Record 而需要 cloneType)。

目前我还不了解 cloneType 的所有细节,但本质上:

  • 记录需要 cloneType
  • Bundle 过去需要 cloneType,但自从编译器插件实现后,从 3.5 开始,它们不再需要 cloneType。
  • BundleMap 是一个令人困惑的情况,因为它是一个直接从 Record 扩展的自定义 Bundle 类型,而不是 Bundle 类型。因此,它不应该在 3.5 Chisel bump 期间删除其 cloneType 方法,并且需要将其添加回 RC 主分支中的 AXIS 才能再次开始工作。

编辑:cloneType 异常问题现已在主分支上针对 3.5 修复:)