未验证 提交 e8009193 编写于 作者: Y Yinan Xu 提交者: GitHub

rob: add an interrupt safe flag (#1309)

This commit adds an interrupt_safe flag that tracks whether an
instruction is safe for interrupts.

For example, any MMIO instruction is not safe because it changes
the external devices before write-back.
上级 d6477c69
......@@ -88,7 +88,7 @@ class RobDeqPtrWrapper(implicit p: Parameters) extends XSModule with HasCircular
// for flush: when exception occurs, reset deqPtrs to range(0, CommitWidth)
val intrBitSetReg = Input(Bool())
val hasNoSpecExec = Input(Bool())
val commitType = Input(CommitType())
val interrupt_safe = Input(Bool())
val misPredBlock = Input(Bool())
val isReplaying = Input(Bool())
// output: the CommitWidth deqPtr
......@@ -100,7 +100,7 @@ class RobDeqPtrWrapper(implicit p: Parameters) extends XSModule with HasCircular
// for exceptions (flushPipe included) and interrupts:
// only consider the first instruction
val intrEnable = io.intrBitSetReg && !io.hasNoSpecExec && !CommitType.isLoadStore(io.commitType)
val intrEnable = io.intrBitSetReg && !io.hasNoSpecExec && io.interrupt_safe
val exceptionEnable = io.deq_w(0) && io.exception_state.valid && !io.exception_state.bits.flushPipe && io.exception_state.bits.robIdx === deqPtrVec(0)
val redirectOutValid = io.state === 0.U && io.deq_v(0) && (intrEnable || exceptionEnable)
......@@ -283,15 +283,15 @@ class Rob(numWbPorts: Int)(implicit p: Parameters) extends XSModule with HasCirc
println("Rob: size:" + RobSize + " wbports:" + numWbPorts + " commitwidth:" + CommitWidth)
// instvalid field
// val valid = RegInit(VecInit(List.fill(RobSize)(false.B)))
val valid = Mem(RobSize, Bool())
// writeback status
// val writebacked = Reg(Vec(RobSize, Bool()))
val writebacked = Mem(RobSize, Bool())
val store_data_writebacked = Mem(RobSize, Bool())
// data for redirect, exception, etc.
// val flagBkup = RegInit(VecInit(List.fill(RobSize)(false.B)))
val flagBkup = Mem(RobSize, Bool())
// some instructions are not allowed to trigger interrupts
// They have side effects on the states of the processor before they write back
val interrupt_safe = Mem(RobSize, Bool())
// data for debug
// Warn: debug_* prefix should not exist in generated verilog.
......@@ -431,11 +431,8 @@ class Rob(numWbPorts: Int)(implicit p: Parameters) extends XSModule with HasCirc
val deqDispatchData = dispatchDataRead(0)
val debug_deqUop = debug_microOp(deqPtr.value)
// For MMIO instructions, they should not trigger interrupts since they may be sent to lower level before it writes back.
// However, we cannot determine whether a load/store instruction is MMIO.
// Thus, we don't allow load/store instructions to trigger an interrupt.
val intrBitSetReg = RegNext(io.csr.intrBitSet)
val intrEnable = intrBitSetReg && !hasNoSpecExec && !CommitType.isLoadStore(deqDispatchData.commitType)
val intrEnable = intrBitSetReg && !hasNoSpecExec && interrupt_safe(deqPtr.value)
val deqHasExceptionOrFlush = exceptionDataRead.valid && exceptionDataRead.bits.robIdx === deqPtr
val triggerBefore = deqHasExceptionOrFlush && exceptionDataRead.bits.trigger_before
val triggerAfter = deqHasExceptionOrFlush && exceptionDataRead.bits.trigger_after && !exceptionDataRead.bits.trigger_before
......@@ -611,7 +608,7 @@ class Rob(numWbPorts: Int)(implicit p: Parameters) extends XSModule with HasCirc
deqPtrGenModule.io.exception_state := exceptionDataRead
deqPtrGenModule.io.intrBitSetReg := intrBitSetReg
deqPtrGenModule.io.hasNoSpecExec := hasNoSpecExec
deqPtrGenModule.io.commitType := deqDispatchData.commitType
deqPtrGenModule.io.interrupt_safe := interrupt_safe(deqPtr.value)
deqPtrGenModule.io.misPredBlock := misPredBlock
deqPtrGenModule.io.isReplaying := isReplaying
......@@ -740,6 +737,21 @@ class Rob(numWbPorts: Int)(implicit p: Parameters) extends XSModule with HasCirc
}
}
// interrupt_safe
for (i <- 0 until RenameWidth) {
// We RegNext the updates for better timing.
// Note that instructions won't change the system's states in this cycle.
when (RegNext(canEnqueue(i))) {
// For now, we allow non-load-store instructions to trigger interrupts
// For MMIO instructions, they should not trigger interrupts since they may
// be sent to lower level before it writes back.
// However, we cannot determine whether a load/store instruction is MMIO.
// Thus, we don't allow load/store instructions to trigger an interrupt.
// TODO: support non-MMIO load-store instructions to trigger interrupts
val allow_interrupts = !CommitType.isLoadStore(io.enq.req(i).bits.ctrl.commitType)
interrupt_safe(RegNext(enqPtrVec(i).value)) := RegNext(allow_interrupts)
}
}
/**
* read and write of data modules
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册