插槽(Slots)
简介
假设您有一些硬件必须跟踪多个相似的正在进行的活动,您可能需要实现一组“插槽”来执行此操作。此示例展示如何使用 Area 、 OHMasking.first 、 onMask 和 reader 来完成此操作。
实现
此实现不使用Vec,相反,它使用Area,从而允许在每个插槽中混合定义信号、寄存器和逻辑。
请注意, reader API 适用于1.9.1之后推出的SpinalHDL版本
package spinaldoc.examples.advanced
import spinal.core._
import spinal.lib._
import scala.language.postfixOps
case class SlotsDemo(slotsCount : Int) extends Component {
// ...
// Create the hardware for each slot.
// Note each slot is an Area, not a Bundle.
val slots = for(i <- 0 until slotsCount) yield new Area {
// Because the slot is an Area, we can define mix signals, registers,
// logic definitions.
// Here are the registers for each slots:
val valid = RegInit(False)
val address = Reg(UInt(8 bits))
val age = Reg(UInt(16 bits)) // Will count since how many cycles the slot is valid
// Here is some hardware behavior for each slots.
// Implement the age logic.
when(valid) {
age := age + 1
}
// removeIt will be used as a slot interface later on.
val removeIt = False
when(removeIt) {
valid := False
}
}
// Logic to allocate a new slot.
val insert = new Area {
val cmd = Stream(UInt(8 bits)) // Interface to issue requests.
val free = slots.map(!_.valid)
val freeOh = OHMasking.first(free) // Get the first free slot (on hot mask).
cmd.ready := free.orR // Only allow cmd when there is a free slot.
when(cmd.fire) {
// slots.onMask(freeOh)(code) will execute the code for each slot where
// the corresponding freeOh bit is set
slots.onMask(freeOh){slot =>
slot.valid := True
slot.address := cmd.payload
slot.age := 0
}
}
}
// Logic to remove the slots which match a given address (assuming
// there is not more than one match).
val remove = new Area {
val cmd = Flow(UInt(8 bits)) // Interface to issue requests.
// oh meaning "one hot"
val oh = slots.map(s => s.valid && s.address === cmd.payload)
when(cmd.fire) {
slots.onMask(oh){ slot =>
slot.removeIt := True
}
}
// Create a facility to read the slots using "oh" as index
val reader = slots.reader(oh)
val age = reader(_.age) // Age of the slot which is selected by "oh"
}
// ...
}
object SlotsDemo extends App {
SpinalVerilog(SlotsDemo(4))
}
应用
例如,在Tilelink一致性中心中,这类槽位模式被用于追踪所有正在进行的传输中内存探针,详见 SpinalHDL代码.
以及在 DRAM / SDR / DDR 内存控制器中实现并发处理多个内存事务(同时进行预充电/激活/读/写以提高性能):详见 此处.
以及在NaxRiscv(乱序 CPU)的加载存储单元中处理存储队列/读取队列的硬件(难度有些可怕,不宜在文档中展示XD)