【发布时间】:2020-09-15 20:19:15
【问题描述】:
我一直在研究利用外交的火箭芯片,我对外交如何运作的整体结构有相当的了解。 (我不完全理解它,但足以自己创建一些示例)。我想开发一些 IP,主要目标是通过使用 *RegisterRouter 来获得 regmap。
如果我使用/修改来自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 并连接到MyDeviceController 中的APBRegisterNode。
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 创建任何 Verilog。这就是您在上面看到的,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 级别开发的建议。
谢谢
【问题讨论】:
-
我认为您的“解决方法/解决方案”与最先进的技术相距不远。完全独立是不可能的,因为正如您所提到的,您需要节点的参数。话虽如此,您可以做出的一项重大改进是使用
dontTouch,而不必在APBMasterLazyModuleImp中创建实际逻辑。试试dontTouch(node.out.head._1)。我明白你关于这是一堆样板的意思,尽管如果你还想测试 IP,因为你希望能够测试大量参数化,这很有用。 -
我没想过
dontTouch,它会很好地工作。我不得不问,因为我对那些很容易被我从未找到的简单东西取代的解决方法感到很糟糕:)。感谢您的回复。 -
我认为一些辅助构造只是“获取 Verilog”,参数的合理默认值会很有用。我一直在考虑它,主要问题是它似乎仅对简单的 Verilog 检查有用,并且不能用于编写单元测试或集成到您基本上的实际系统中需要您最终编写的所有样板。也许我缺少一个抽象。
-
我倾向于同意。我相信难题还在于,那些想要包装纸只是为了获得 verilog 的人并不了解外交,以至于它对他们有很大帮助。
标签: chisel rocket-chip