我正在Chisel中编写一个中断控制器。
以下函数确定最高优先级挂起中断。每个中断源由IRQStatusReg
表示,组合寄存器文件为凿Vec
。为了确定具有最高优先级的中断,使用递归的分治策略。在硬件中,这应该被合成为多路复用器树。返回的元组包含寄存器及其ID。
def select_highest_prio_irq(vec: Vec[IRQStatusReg], start: Int, len: Int) : (IRQStatusReg, UInt) = {
if(len == 1){
return (vec(start), UInt(width=0))
}
else{
val left_len = len / 2
val right_len = len - left_len
val (left, l0) = select_highest_prio_irq(vec, start, left_len)
val (right, r0) = select_highest_prio_irq(vec, start+ left_len, right_len)
val select_left = left.irq_pending && !left.irq_masked && left.irq_prio > right.irq_prio
printf("val: %x\n", select_left)
printf("expr: %x\n", left.irq_pending && !left.irq_masked && left.irq_prio > right.irq_prio)
(Mux(select_left, left, right),
Cat(!select_left, Mux(select_left, l0, r0)))
}
}
val (highest_prio_reg, irq_nr) = select_highest_prio_irq(irq_status_regfile, 0, intSources)
但是,使用某些寄存器配置和4个中断源时,此功能无法确定正确的结果。原因在于对select_left的赋值:右侧表达式的值与赋值后select_left的值不同(见第3/4行):
val:0
expr: 0
val:0
expr: 1
val: 1
expr: 1
怎么可能? val在赋值后如何具有与表达式不同的值?
作为参考,这里是IRQStatusReg Vec的定义:
class IRQStatusReg(priorityLevels: Int) extends Bundle {
val irq_prio = UInt(width = log2Up(priorityLevels))
val irq_masked = Bool()
val irq_pending = Bool()
override def cloneType: this.type =
new IRQStatusReg(priorityLevels).asInstanceOf[this.type]
}
val irq_status_regfile = Reg(init = Vec(intSources, new IRQStatusReg(priorityLevels)))