未验证 提交 c3ece97f 编写于 作者: S Steve Gou 提交者: GitHub

Merge pull request #329 from RISCVERS/ifu-timing

Ifu timing
......@@ -4,7 +4,7 @@ import chisel3._
import chisel3.util._
object ParallelOperation {
def apply[T <: Data](xs: Seq[T], func: (T, T) => T): T = {
def apply[T](xs: Seq[T], func: (T, T) => T): T = {
require(xs.nonEmpty)
xs match {
case Seq(a) => a
......@@ -21,12 +21,22 @@ object ParallelOR {
}
}
object ParallelORR {
def apply(in: Seq[Bool]): Bool = ParallelOR(in)
def apply(in: Bits): Bool = apply(in.asBools)
}
object ParallelAND {
def apply[T <: Data](xs: Seq[T]): T = {
ParallelOperation(xs, (a: T, b:T) => (a.asUInt() & b.asUInt()).asTypeOf(xs.head))
}
}
object ParallelANDR {
def apply(in: Seq[Bool]): Bool = ParallelAND(in)
def apply(in: Bits): Bool = apply(in.asBools)
}
object ParallelMux {
def apply[T<:Data](in: Seq[(Bool, T)]): T = {
val xs = in map { case (cond, x) => (Fill(x.getWidth, cond) & x.asUInt()).asTypeOf(in.head._2) }
......@@ -50,4 +60,17 @@ object ParallelMin {
def apply[T <: Data](xs: Seq[T]): T = {
ParallelOperation(xs, (a: T, b:T) => Mux(a.asUInt() < b.asUInt(),a, b).asTypeOf(xs.head))
}
}
\ No newline at end of file
}
object ParallelPriorityMux {
def apply[T <: Data](in: Seq[(Bool, T)]): T = {
ParallelOperation(in, (a: (Bool, T), b: (Bool, T)) => (a._1 || b._1, Mux(a._1, a._2, b._2)))._2
}
def apply[T <: Data](sel: Bits, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in)
def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel zip in)
}
object ParallelPriorityEncoder {
def apply(in: Seq[Bool]): UInt = ParallelPriorityMux(in, (0 until in.size).map(_.asUInt))
def apply(in: Bits): UInt = apply(in.asBools)
}
package utils
import chisel3._
import chisel3.util._
// this could be used to handle the situation
// in which we have mux sources at multiple
// locations, and this is same to multiple
// when clauses as below, but collect them
// and put them into a ParallelPrioriyMux
// when (sel1) { x := in1 }
// when (sel2) { x := in2 }
class PriorityMuxGenerator[T <: Data] {
var src: List[(Bool, T)] = List()
def register(sel: Bool, in: T) = src = (sel, in) :: src
def register(in: Seq[(Bool, T)]) = src = in.toList ::: src
def register(sel: Seq[Bool], in: Seq[T]) = src = (sel zip in).toList ::: src
def apply(): T = ParallelPriorityMux(src)
}
\ No newline at end of file
......@@ -90,7 +90,7 @@ class BranchPrediction extends XSBundle with HasIFUConst {
def lastHalfRVIClearMask = ~lastHalfRVIMask
// is taken from half RVI
def lastHalfRVITaken = (takens & lastHalfRVIMask).orR
def lastHalfRVITaken = ParallelORR(takens & lastHalfRVIMask)
def lastHalfRVIIdx = Mux(firstBankHasHalfRVI, (bankWidth-1).U, (PredictWidth-1).U)
// should not be used if not lastHalfRVITaken
......@@ -102,18 +102,18 @@ class BranchPrediction extends XSBundle with HasIFUConst {
def brNotTakens = ~realTakens & realBrMask
def sawNotTakenBr = VecInit((0 until PredictWidth).map(i =>
(if (i == 0) false.B else brNotTakens(i-1,0).orR)))
(if (i == 0) false.B else ParallelORR(brNotTakens(i-1,0)))))
// def hasNotTakenBrs = (brNotTakens & LowerMaskFromLowest(realTakens)).orR
def unmaskedJmpIdx = PriorityEncoder(takens)
def saveHalfRVI = (firstBankHasHalfRVI && (unmaskedJmpIdx === (bankWidth-1).U || !(takens.orR))) ||
def unmaskedJmpIdx = ParallelPriorityEncoder(takens)
def saveHalfRVI = (firstBankHasHalfRVI && (unmaskedJmpIdx === (bankWidth-1).U || !(ParallelORR(takens)))) ||
(lastBankHasHalfRVI && unmaskedJmpIdx === (PredictWidth-1).U)
// could get PredictWidth-1 when only the first bank is valid
def jmpIdx = PriorityEncoder(realTakens)
def jmpIdx = ParallelPriorityEncoder(realTakens)
// only used when taken
def target = targets(jmpIdx)
def taken = realTakens.orR
def takenOnBr = taken && realBrMask(jmpIdx)
def hasNotTakenBrs = Mux(taken, sawNotTakenBr(jmpIdx), brNotTakens.orR)
def target = ParallelPriorityMux(realTakens, targets)
def taken = ParallelORR(realTakens)
def takenOnBr = taken && ParallelPriorityMux(realTakens, realBrMask.asBools)
def hasNotTakenBrs = Mux(taken, ParallelPriorityMux(realTakens, sawNotTakenBr), ParallelORR(brNotTakens))
}
class BranchInfo extends XSBundle with HasBPUParameter {
......
......@@ -140,23 +140,15 @@ class IFU extends XSModule with HasIFUConst
.elsewhen (if2_flush) { if2_valid := false.B }
.elsewhen (if2_fire) { if2_valid := false.B }
when (RegNext(reset.asBool) && !reset.asBool) {
if1_npc := resetVector.U(VAddrBits.W)
}.elsewhen (if2_fire) {
if1_npc := if2_snpc
}.otherwise {
if1_npc := RegNext(if1_npc)
}
val npcGen = new PriorityMuxGenerator[UInt]
npcGen.register(true.B, RegNext(if1_npc))
npcGen.register(if2_fire, if2_snpc)
val if2_bp = bpu.io.out(0)
// val if2_GHInfo = wrapGHInfo(if2_bp, if2_predHist)
// if taken, bp_redirect should be true
// when taken on half RVI, we suppress this redirect signal
if2_redirect := if2_fire && if2_bp.taken
when (if2_redirect) {
if1_npc := if2_bp.target
}
npcGen.register(if2_redirect, if2_bp.target)
if2_predicted_gh := if2_gh.update(if2_bp.hasNotTakenBrs, if2_bp.takenOnBr)
......@@ -166,7 +158,6 @@ class IFU extends XSModule with HasIFUConst
val if3_fire = if3_valid && if4_ready && (inLoop || io.icacheResp.valid) && !if3_flush
val if3_pc = RegEnable(if2_pc, if2_fire)
val if3_predHist = RegEnable(if2_predHist, enable=if2_fire)
// val if3_nextValidPC = Mux(if2_valid)
if3_ready := if3_fire || !if3_valid || if3_flush
when (if3_flush) { if3_valid := false.B }
.elsewhen (if2_fire) { if3_valid := true.B }
......@@ -181,7 +172,7 @@ class IFU extends XSModule with HasIFUConst
val hasPrevHalfInstrReq = prevHalfInstrReq.valid
val if3_prevHalfInstr = RegInit(0.U.asTypeOf(new PrevHalfInstr))
// val if4_prevHalfInstr = Wire(new PrevHalfInstr)
// 32-bit instr crosses 2 pages, and the higher 16-bit triggers page fault
val crossPageIPF = WireInit(false.B)
......@@ -238,10 +229,11 @@ class IFU extends XSModule with HasIFUConst
// }.elsewhen (if3_ghInfoNotIdenticalRedirect) {
// if3_target := Mux(if3_bp.taken, if3_bp.target, snpc(if3_pc))
// }
npcGen.register(if3_redirect, if3_target)
when (if3_redirect) {
if1_npc := if3_target
}
// when (if3_redirect) {
// if1_npc := if3_target
// }
//********************** IF4 ****************************//
val if4_pd = RegEnable(pd.io.out, if3_fire)
......@@ -350,9 +342,7 @@ class IFU extends XSModule with HasIFUConst
// }.elsewhen (if4_ghInfoNotIdenticalRedirect) {
// if4_target := Mux(if4_bp.taken, if4_bp.target, if4_snpc)
// }
when (if4_redirect) {
if1_npc := if4_target
}
npcGen.register(if4_redirect, if4_target)
when (if4_fire) {
final_gh := if4_predicted_gh
......@@ -378,13 +368,11 @@ class IFU extends XSModule with HasIFUConst
flush_final_gh := true.B
}
when (loopBufPar.LBredirect.valid) {
if1_npc := loopBufPar.LBredirect.bits
}
npcGen.register(loopBufPar.LBredirect.valid, loopBufPar.LBredirect.bits)
npcGen.register(io.redirect.valid, io.redirect.bits)
npcGen.register(RegNext(reset.asBool) && !reset.asBool, resetVector.U(VAddrBits.W))
when (io.redirect.valid) {
if1_npc := io.redirect.bits
}
if1_npc := npcGen()
when(inLoop) {
io.icacheReq.valid := if4_flush
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册