You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在Chipyard中以文件夹形式添加NoC作为BlackBox?

在Chipyard中批量导入整个文件夹的SystemVerilog作为BlackBox MMIO外设

核心结论

可以批量导入整个文件夹的SystemVerilog文件,无需逐个调用addResource(),以下提供两种可行实现方式:

方法一:Scala遍历目录批量添加资源

在NoC_top.scala的BlackBox类中,通过Scala文件API遍历目标目录下所有.sv文件,自动调用addResource()添加。这种方式可控性强,能精准选择需要的文件。

示例代码:

import chisel3._
import chisel3.experimental.{BlackBox, HasBlackBoxResource}
import java.io.File

class NoCTopBlackBox extends BlackBox with HasBlackBoxResource {
  // 定义BlackBox的IO接口,需与NoC_Top.sv的接口匹配
  val io = IO(new Bundle {
    val clk = Input(Clock())
    val rst_n = Input(Bool())
    // 添加MMIO相关信号,如地址、数据、读写使能等
    val mmio_addr = Input(UInt(32.W))
    val mmio_wdata = Input(UInt(64.W))
    val mmio_rdata = Output(UInt(64.W))
    val mmio_we = Input(Bool())
  })

  // 设置SystemVerilog模块名(若与类名不一致时需配置)
  setModuleName("NoC_Top")

  // 遍历指定目录下所有.sv文件的工具方法
  private def addSvFilesFromDir(dirPath: String): Unit = {
    val dir = new File(getClass.getResource(dirPath).getPath)
    if (dir.isDirectory) {
      // 递归遍历所有子目录和文件
      def traverse(currentDir: File): Unit = {
        currentDir.listFiles().foreach { file =>
          if (file.isFile && file.getName.endsWith(".sv")) {
            // 构造相对于resources目录的路径,添加为资源
            val relativePath = s"${dirPath}/${file.getName}"
            addResource(relativePath)
          } else if (file.isDirectory) {
            traverse(file)
          }
        }
      }
      traverse(dir)
    }
  }

  // 添加顶层文件
  addResource("/vsrc/NoC_Top.sv")
  // 批量添加子目录下的所有.sv文件
  addSvFilesFromDir("/vsrc/small_core")
  addSvFilesFromDir("/vsrc/another_NoC_System")
}

方法二:通过sbt配置自动包含资源目录

Chipyard基于sbt构建,可在chipyard/generators/NoC/build.sbt中配置,让sbt自动将整个vsrc目录(或子目录)下的文件作为资源包含,无需在Scala代码中手动遍历。

示例build.sbt配置:

// 将vsrc目录及其子目录下的所有文件加入编译资源
unmanagedResourceDirectories in Compile += baseDirectory.value / "src" / "main" / "resources" / "vsrc"

// 或仅包含特定子目录
unmanagedResourceDirectories in Compile ++= Seq(
  baseDirectory.value / "src" / "main" / "resources" / "vsrc" / "small_core",
  baseDirectory.value / "src" / "main" / "resources" / "vsrc" / "another_NoC_System"
)

配置后,sbt会自动把这些目录下的文件打包到资源中,只需在BlackBox中添加顶层文件addResource("/vsrc/NoC_Top.sv"),工具链会自动找到依赖的子模块文件。

将NoC集成到Chipyard作为MMIO外设

完成BlackBox的文件导入后,需将其封装为LazyModule并连接到系统MMIO总线:

  1. 封装外设模块:
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._

class NoCMMIOPeripheral(implicit p: Parameters) extends LazyModule {
  // 定义TileLink从节点,用于连接到系统MMIO总线
  val node = TLSlaveNode(Seq(TLSlavePortParameters(
    slaves = Seq(TLSlaveParameters(
      address = AddressSet(0x20000000L, 0x00FFFFFFL), // 分配MMIO地址空间
      resources = new SimpleDevice("noc-mmio", Seq("chipyard,noc-1.0")).reg,
      regionType = RegionType.IDEMPOTENT,
      executable = false,
      supportsGet = TransferSizes(1, 8),
      supportsPutFull = TransferSizes(1, 8),
      supportsPutPartial = TransferSizes(1, 8)
    )),
    beatBytes = 8
  )))

  lazy val module = new LazyModuleImp(this) {
    val noC = Module(new NoCTopBlackBox)
    // 连接时钟复位
    noC.io.clk := clock
    noC.io.rst_n := !reset.asBool

    // 连接TileLink信号到BlackBox的MMIO接口
    val tlIn = node.in(0)
    noC.io.mmio_addr := tlIn.a.bits.address(31, 0)
    noC.io.mmio_wdata := tlIn.a.bits.data
    noC.io.mmio_we := tlIn.a.bits.opcode === TLPutFullData || tlIn.a.bits.opcode === TLPutPartialData

    // 处理读响应
    tlIn.d.bits.data := noC.io.mmio_rdata
    tlIn.d.bits.opcode := TLAccessAckData
    tlIn.d.bits.param := 0.U
    tlIn.d.bits.size := tlIn.a.bits.size
    tlIn.d.bits.source := tlIn.a.bits.source
    tlIn.d.bits.sink := tlIn.a.bits.sink
    tlIn.d.bits.error := false.B

    // 控制TileLink握手信号
    tlIn.a.ready := true.B
    tlIn.d.valid := tlIn.a.valid && tlIn.a.bits.opcode === TLGet
  }
}
  1. 在Chipyard配置中启用该外设:
import freechips.rocketchip.config.Config
import chipyard.{BuildTop, DefaultConfig}

class WithNoCMMIOPeripheral extends Config((site, here, up) => {
  case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => {
    val top = up(BuildTop)(clock, reset, p)
    val noCPeriph = LazyModule(new NoCMMIOPeripheral()(p))
    // 将外设连接到系统的MMIO总线(此处假设使用系统的TLXbar)
    top.tlXbar.node := noCPeriph.node
    top
  }
})

// 组合配置:默认配置 + NoC外设
class NoCConfig extends Config(
  new WithNoCMMIOPeripheral ++
  new DefaultConfig
)

注意事项

  • 确保SystemVerilog文件中的模块名与BlackBox中setModuleName()指定的名称一致,否则工具链会找不到模块。
  • 递归遍历目录时,注意过滤非.sv文件,避免引入无关资源。
  • MMIO地址空间的分配需避免与其他外设冲突,可参考Chipyard默认外设地址布局调整。
  • 使用sbt自动包含资源时,需确保目录路径配置正确,否则会出现文件找不到的错误。

内容的提问来源于stack exchange,提问作者asamorning

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 09:34:56