The following function determines the highest priority pending interrupt. Each interrupt source is represented by a IRQStatusReg and the combined register file is a Chisel Vec. To determine the interrupt with the highest priority, a recursive divide and conquer strategy is used. In hardware, this should be synthesized as a tree of multiplexers. The returned tuple contains the register and its ID.
However, this function fails to determine the correct result when using certain register configurations and 4 interrupt sources. The reason lies in the assignment to select_left: The value of the expression on the right hand side differs from the value select_left has after the assignment (see line 3/4):
val:0
expr: 0
val:0
expr: 1
val: 1
expr: 1
How is that possible? How can a val have a different value than an expression after an assignment?
For reference, here is the definition of the 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)))
Curiously enough, the code behaves as expected when I rewrite the function like this:
def select_highest_prio_irq(vec: Vec[IRQStatusReg], start: Int, len: Int) : (IRQStatusReg, UInt) = {
if(len == 1){
return (vec(start), UInt(start))
}
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))
val mux_reg = Mux(select_left, left, right)
val mux_nr = Mux(select_left, l0, r0)
(mux_reg, mux_nr)
}
}
I am writing an interrupt controller in Chisel.
The following function determines the highest priority pending interrupt. Each interrupt source is represented by a IRQStatusReg and the combined register file is a Chisel Vec. To determine the interrupt with the highest priority, a recursive divide and conquer strategy is used. In hardware, this should be synthesized as a tree of multiplexers. The returned tuple contains the register and its ID.
However, this function fails to determine the correct result when using certain register configurations and 4 interrupt sources. The reason lies in the assignment to select_left: The value of the expression on the right hand side differs from the value select_left has after the assignment (see line 3/4):
How is that possible? How can a val have a different value than an expression after an assignment?
For reference, here is the definition of the IRQStatusReg Vec:
Curiously enough, the code behaves as expected when I rewrite the function like this: