使用 UInt 在 Seq 中获取一个项目
Get an item in Seq using UInt
我正在尝试写入高速缓存,因此我创建了一个 Seq
类型的 Mem
因为我正在尝试访问一组高速缓存中的所有元素同时.
val metaMem = Seq.fill(nWays) (Mem((nSets), new MetaData))
然后我想要如下所示的索引:
metaMem(way).write(set, MD)
但是,因为我的代码中way是UInt
,而seq只接受Int
进行索引,所以会导致编译错误。
有人对如何解决这个问题有什么建议吗?
非常感谢
通常要使用 UInt
中的动态值访问硬件元素,您必须使用 Vec
。在这种情况下,最简单的方法是使用 VecInit
创建一个 Vec
,给定一个序列,定义 Vec
并连接你的元素。
但是 内存不是数据的子类(正如Vec
/VecInit
所要求的)。
这是一个非常简单的示例,它创建了一个内存库并提供 read/write 对它们的访问。
/** Simulate a VecLike bank of memories
*/
class MemBank(val banks: Int, val bankDepth: Int) extends MultiIOModule {
val bank = IO(Input(UInt(16.W)))
val address = IO(Input(UInt(16.W)))
val isRead = IO(Input(Bool()))
val inputValue = IO(Input(UInt(32.W)))
val outputValue = IO(Output(UInt(32.W)))
val mems = Seq.fill(banks) { Mem(bankDepth, UInt(32.W)) }
outputValue := DontCare
when(isRead) {
(0 until banks).foldLeft(when(false.B) {}) {
case (whenContext, bankIndex) =>
whenContext.elsewhen(bank === bankIndex.U) {
outputValue := mems(bankIndex)(address)
}
}
}.otherwise {
(0 until banks).foldLeft(when(false.B) {}) {
case (whenContext, bankIndex) =>
whenContext.elsewhen(bank === bankIndex.U) {
mems(bankIndex)(address) := inputValue
}
}
}
}
这是一个单元测试,可以演示如何使用这个模块
class MemBankTest extends FreeSpec with ChiselScalatestTester {
"MemBankSimulation should work" in {
test(new MemBank(banks = 3, bankDepth = 3)) { dut =>
// write values into memory
dut.isRead.poke(false.B)
for (bank <- 0 until dut.banks) {
for (address <- 0 until dut.bankDepth) {
dut.clock.step()
dut.bank.poke(bank.U)
dut.address.poke(address.U)
dut.inputValue.poke((bank * 1000 + address).U)
}
}
// read values out of memory banks
dut.isRead.poke(true.B)
for (bank <- 0 until dut.banks) {
for (address <- 0 until dut.bankDepth) {
dut.clock.step()
dut.bank.poke(bank.U)
dut.address.poke(address.U)
println(f"Bank $bank%3d at address $address%3d contains ${dut.outputValue.peek().litValue()}%6d")
}
}
}
}
}
还有很多其他方法可以做到这一点,我鼓励您查看其他 chisel 项目,例如 rocket-chip 以了解如何处理多个内存。
看看这种方法是如何工作的还是很高兴的。它创建了 Mem
的 Seq
,但它使用 foldLeft(一种非常有用的方法)创建了一组 Mux
es,即 select 您感兴趣的银行。有两个并行使用这个来分别控制读写。
我希望这会有所帮助,这是一个很好但很难回答的问题。
我正在尝试写入高速缓存,因此我创建了一个 Seq
类型的 Mem
因为我正在尝试访问一组高速缓存中的所有元素同时.
val metaMem = Seq.fill(nWays) (Mem((nSets), new MetaData))
然后我想要如下所示的索引:
metaMem(way).write(set, MD)
但是,因为我的代码中way是UInt
,而seq只接受Int
进行索引,所以会导致编译错误。
有人对如何解决这个问题有什么建议吗?
非常感谢
通常要使用 UInt
中的动态值访问硬件元素,您必须使用 Vec
。在这种情况下,最简单的方法是使用 VecInit
创建一个 Vec
,给定一个序列,定义 Vec
并连接你的元素。
但是 内存不是数据的子类(正如Vec
/VecInit
所要求的)。
这是一个非常简单的示例,它创建了一个内存库并提供 read/write 对它们的访问。
/** Simulate a VecLike bank of memories
*/
class MemBank(val banks: Int, val bankDepth: Int) extends MultiIOModule {
val bank = IO(Input(UInt(16.W)))
val address = IO(Input(UInt(16.W)))
val isRead = IO(Input(Bool()))
val inputValue = IO(Input(UInt(32.W)))
val outputValue = IO(Output(UInt(32.W)))
val mems = Seq.fill(banks) { Mem(bankDepth, UInt(32.W)) }
outputValue := DontCare
when(isRead) {
(0 until banks).foldLeft(when(false.B) {}) {
case (whenContext, bankIndex) =>
whenContext.elsewhen(bank === bankIndex.U) {
outputValue := mems(bankIndex)(address)
}
}
}.otherwise {
(0 until banks).foldLeft(when(false.B) {}) {
case (whenContext, bankIndex) =>
whenContext.elsewhen(bank === bankIndex.U) {
mems(bankIndex)(address) := inputValue
}
}
}
}
这是一个单元测试,可以演示如何使用这个模块
class MemBankTest extends FreeSpec with ChiselScalatestTester {
"MemBankSimulation should work" in {
test(new MemBank(banks = 3, bankDepth = 3)) { dut =>
// write values into memory
dut.isRead.poke(false.B)
for (bank <- 0 until dut.banks) {
for (address <- 0 until dut.bankDepth) {
dut.clock.step()
dut.bank.poke(bank.U)
dut.address.poke(address.U)
dut.inputValue.poke((bank * 1000 + address).U)
}
}
// read values out of memory banks
dut.isRead.poke(true.B)
for (bank <- 0 until dut.banks) {
for (address <- 0 until dut.bankDepth) {
dut.clock.step()
dut.bank.poke(bank.U)
dut.address.poke(address.U)
println(f"Bank $bank%3d at address $address%3d contains ${dut.outputValue.peek().litValue()}%6d")
}
}
}
}
}
还有很多其他方法可以做到这一点,我鼓励您查看其他 chisel 项目,例如 rocket-chip 以了解如何处理多个内存。
看看这种方法是如何工作的还是很高兴的。它创建了 Mem
的 Seq
,但它使用 foldLeft(一种非常有用的方法)创建了一组 Mux
es,即 select 您感兴趣的银行。有两个并行使用这个来分别控制读写。
我希望这会有所帮助,这是一个很好但很难回答的问题。