我一直在研究利用外交的火箭芯片,我对外交如何运作的整体结构有一个不错的掌握。(我不完全理解它,但足以自己创建一些示例)。我想开发一些 IP,其主要目标是regmap
通过使用*RegisterRouter
.
如果我使用/修改 Rocket-chip 中的 RegisterNodeExamples 之一,我会得到以下信息:
class MyDeviceController(implicit p: Parameters) extends LazyModule {
val device = new SimpleDevice("my-device", Seq("tutorial,my-device0"))
val node = APBRegisterNode(
//address = Seq(AddressSet(0x10028000, 0xfff)), (Modified since not in APBRegisterNode)
address = AddressSet(0x002000, 0xfff),
//device = device, (Removed since not in APBRegisterNode)
beatBytes = 8)
lazy val module = new LazyModuleImp(this) {
val bigReg = RegInit(0.U(64.W))
val mediumReg = RegInit(0.U(32.W))
val smallReg = RegInit(0.U(16.W))
val tinyReg0 = RegInit(0.U(4.W))
val tinyReg1 = RegInit(0.U(4.W))
node.regmap(
0x00 -> Seq(RegField(64, bigReg)),
0x08 -> Seq(RegField(32, mediumReg)),
0x0C -> Seq(RegField(16, smallReg)),
0x0E -> Seq(
RegField(4, tinyReg0),
RegField(4, tinyReg1)))
}
}
我目前正在使用 APB,因为我非常熟悉 AMBA 协议,并且它具有diplomacy
包下最小的代码库。我可以这样做,以便以后使用 AMBA 或 TL 协议。
我的问题
有没有办法仅MyDeviceController
作为独立组件生成verilog?
我无法弄清楚是否存在。显然,如果我只是尝试实例化,我将收到未连接MyDeviceController
的内部参数的错误。node
我不确定您是否可以提供“虚拟”节点连接?或者,如果有一些方法可以处理。
为什么我想这样做
最好在没有完整 SoC 的情况下在其自己的测试环境中独立测试 IP。
我当前的解决方法/解决方案
为了解决这个问题,我基本上创建了一个“包装器”,它创建APBMasterNode
并连接到APBRegisterNode
in MyDeviceController
。
class APBMaster()(implicit p: Parameters) extends LazyModule {
val apbMasterParameters = APBMasterParameters(
name = "apbMaster"
)
val apbMasterPortParameters = APBMasterPortParameters(
masters = Seq(apbMasterParameters)
)
val node = APBMasterNode(
portParams = Seq(apbMasterPortParameters)
)
lazy val module = new LazyModuleImp(this) {
val io = IO(new Bundle {
val wtf = Output(Bool())
val start = Input(Bool())
})
val myreg = RegInit(0.U(16.W))
myreg := myreg + 1.U
val prdata = Wire(UInt(64.W))
prdata := node.out.head._1.prdata
//seems to need these things to generate the logic
io.wtf := node.out.head._1.pready && !(node.out.head._1.prdata === 0.U)
node.out.head._1.pstrb := 63.U
node.out.head._1.pprot := 0.U
when(myreg(3,0) === 8.U && io.start) {
node.out.head._1.paddr := myreg
node.out.head._1.psel := true.B
node.out.head._1.penable := false.B
node.out.head._1.pwrite := true.B
node.out.head._1.pwdata := myreg + 1.U
} .elsewhen(myreg(3,0) === 9.U) {
node.out.head._1.paddr := myreg
node.out.head._1.psel := true.B
node.out.head._1.penable := true.B
node.out.head._1.pwrite := true.B
node.out.head._1.pwdata := myreg
} otherwise {
node.out.head._1.paddr := 0.U
node.out.head._1.psel := false.B
node.out.head._1.penable := false.B
node.out.head._1.pwrite := false.B
node.out.head._1.pwdata := 0.U
}
}
}
一个问题是我必须为每个 APB 信号创建一些控件。如果我不这样做,Chisel/FIRRTL 编译器/生成器将不会为MyDeviceController
. 这就是您在上面看到的myreg
用于执行一些基本 APB 事务的计数器。
包装器如下所示:
class APBTop()(implicit p: Parameters) extends LazyModule {
val master = LazyModule(new APBMaster)
val slave = LazyModule(new MyDeviceController()(Parameters.empty))
slave.node := master.node
lazy val module = new LazyModuleImp(this) {
val io = IO(new Bundle {
val busy = Output(Bool())
val wtf = Output(Bool())
val start = Input(Bool())
})
io.busy := true.B
io.wtf := master.module.io.wtf
master.module.io.start := io.start
}
}
我可以将此包装器/主控器创建为典型的测试组件,然后在我的 testenv 中将MyDeviceController
RTL 实例化,但是我想知道是否还有其他解决方案。外交似乎是相当全面的(我理解为什么),但正在寻找有关如何为外交基础设施流程处理 IP 级别开发的建议。
谢谢