提交 2aa3b6d8 编写于 作者: Y Yinan Xu

Merge remote-tracking branches 'origin' and 'origin/issueQueue-fixSrcType' into improve-dp2

......@@ -62,6 +62,15 @@ class Redirect extends XSBundle {
val freelistAllocPtr = new FreeListPtr
}
class RedirectInfo extends XSBundle {
val valid = Bool() // a valid commit form brq/roq
val misPred = Bool() // a branch miss prediction ?
val redirect = new Redirect
def flush():Bool = valid && (redirect.isException || misPred)
}
class Dp1ToDp2IO extends XSBundle {
val intDqToDp2 = Vec(IntDqDeqWidth, DecoupledIO(new MicroOp))
val fpDqToDp2 = Vec(FpDqDeqWidth, DecoupledIO(new MicroOp))
......@@ -104,6 +113,6 @@ class FrontendToBackendIO extends XSBundle {
// to backend end
val cfVec = Vec(DecodeWidth, DecoupledIO(new CtrlFlow))
// from backend
val redirect = Flipped(ValidIO(new Redirect))
val redirectInfo = Input(new RedirectInfo)
val commits = Vec(CommitWidth, Flipped(ValidIO(new RoqCommit))) // update branch pred
}
......@@ -31,6 +31,7 @@ trait HasXSParameter {
val RenameWidth = 6
val CommitWidth = 6
val BrqSize = 16
val IssQueSize = 8
val BrTagWidth = log2Up(BrqSize)
val NRPhyRegs = 128
val PhyRegIdxWidth = log2Up(NRPhyRegs)
......
......@@ -46,7 +46,16 @@ class Backend(implicit val p: XSConfig) extends XSModule
numWirtePorts = NRWritePorts,
hasZero = false
))
// backend redirect, flush pipeline
val redirect = Mux(roq.io.redirect.valid, roq.io.redirect, brq.io.redirect)
val redirectInfo = Wire(new RedirectInfo)
// exception or misprediction
redirectInfo.valid := roq.io.redirect.valid || brq.io.out.valid
redirectInfo.misPred := !roq.io.redirect.valid && brq.io.redirect.valid
redirectInfo.redirect := redirect.bits
val issueQueues = exeUnits.zipWithIndex.map({ case(eu, i) =>
def needBypass(x: Exu): Boolean = eu.enableBypass
val bypassCnt = exeUnits.count(needBypass)//if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0
......@@ -86,7 +95,7 @@ class Backend(implicit val p: XSConfig) extends XSModule
lsuExeUnits.foreach(_.io.dmem <> io.dmem)
lsuExeUnits.foreach(_.io.scommit <> roq.io.scommit)
io.frontend.redirect <> redirect
io.frontend.redirectInfo <> redirectInfo
io.frontend.commits <> roq.io.commits
decode.io.in <> io.frontend.cfVec
......
......@@ -3,7 +3,7 @@ package xiangshan.backend.brq
import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.utils.XSInfo
import xiangshan.utils._
class BrqPtr extends XSBundle {
......@@ -22,25 +22,17 @@ class BrqPtr extends XSBundle {
(this.value===that.value) && (this.flag===that.flag)
}
// this.age <= that.age
final def <= (that: BrqPtr): Bool = {
// this.age < that.age
final def < (that: BrqPtr): Bool = {
Mux(this.flag === that.flag,
this.value > that.value,
this.value < that.value
)
}
def needBrFlush(redirectTag: BrqPtr): Bool = this <= redirectTag
def needBrFlush(redirectTag: BrqPtr): Bool = this < redirectTag
def needFlush(redirect: Valid[Redirect]): Bool = {
val redirectTag = redirect.bits.brTag
// assert(!(
// redirect.valid &&
// !redirect.bits.isException &&
// (flag=/=redirectTag.flag) &&
// (this.value===redirectTag.value)
// )
// )
redirect.valid && (redirect.bits.isException || needBrFlush(redirect.bits.brTag))
}
......@@ -57,30 +49,45 @@ object BrqPtr {
}
}
class BrqIO extends XSBundle{
// interrupt/exception happen, flush Brq
val roqRedirect = Input(Valid(new Redirect))
// receive branch/jump calculated target
val exuRedirect = Vec(exuConfig.AluCnt + exuConfig.BruCnt, Flipped(ValidIO(new ExuOutput)))
// from decode, branch insts enq
val enqReqs = Vec(DecodeWidth, Flipped(DecoupledIO(new CfCtrl)))
// to decode
val brTags = Output(Vec(DecodeWidth, new BrqPtr))
// to roq
val out = ValidIO(new ExuOutput)
// misprediction, flush pipeline
val redirect = Output(Valid(new Redirect))
}
class Brq extends XSModule {
val io = IO(new Bundle() {
// interrupt/exception happen, flush Brq
val roqRedirect = Input(Valid(new Redirect))
// receive branch/jump calculated target
val exuRedirect = Vec(exuConfig.AluCnt + exuConfig.BruCnt, Flipped(ValidIO(new ExuOutput)))
// from decode, branch insts enq
val enqReqs = Vec(DecodeWidth, Flipped(DecoupledIO(new CfCtrl)))
// to decode
val brTags = Output(Vec(DecodeWidth, new BrqPtr))
// to roq
val out = ValidIO(new ExuOutput)
// misprediction, flush pipeline
val redirect = Output(Valid(new Redirect))
})
val io = IO(new BrqIO)
def redirctWindowSize: Int = BrqSize/2
require(redirctWindowSize <= BrqSize && redirctWindowSize > 0)
class BrqEntry extends Bundle {
val ptrFlag = Bool()
val npc = UInt(VAddrBits.W)
val misPred = Bool()
val exuOut = new ExuOutput
}
val s_idle :: s_wb :: s_commited :: Nil =
List.tabulate(3)(i => (1 << i).U(3.W).asTypeOf(new StateQueueEntry))
class StateQueueEntry extends Bundle{
val isCommit = Bool()
val isWb = Bool()
val isIdle = Bool()
}
val brQueue = Reg(Vec(BrqSize, new BrqEntry))
val wbFlags = RegInit(VecInit(Seq.fill(BrqSize)(false.B)))
val stateQueue = RegInit(VecInit(Seq.fill(BrqSize)(s_idle)))
val headPtr, tailPtr = RegInit(BrqPtr(false.B, 0.U))
......@@ -90,18 +97,57 @@ class Brq extends XSModule {
// dequeue
val headIdx = headPtr.value
val deqValid = wbFlags(headIdx)
val deqEntry = brQueue(headIdx)
var commitIdx = WireInit(headIdx)
val headPtrNext = WireInit(headPtr + deqValid)
when(deqValid){
wbFlags(headIdx) := false.B
def needCheckNext(idx: UInt): Bool = {
(stateQueue(idx).isWb && !brQueue(idx).misPred) || stateQueue(idx).isCommit
}
var checkNext = WireInit(needCheckNext(headIdx))
for(i <- 1 until redirctWindowSize){
val idx = commitIdx + i.U
val commitThis = checkNext && stateQueue(idx).isWb && brQueue(idx).misPred
commitIdx = Mux(commitThis,
idx,
commitIdx
)
checkNext = checkNext && needCheckNext(idx)
}
val commitIsHead = commitIdx===headIdx
val deqValid = !stateQueue(headIdx).isIdle && commitIsHead
val commitValid = stateQueue(commitIdx).isWb
val commitEntry = brQueue(commitIdx)
XSDebug(p"headIdx:$headIdx commitIdx:$commitIdx\n")
XSDebug(p"headPtr:$headPtr tailPtr:$tailPtr\n")
XSDebug("")
stateQueue.map(s =>{
XSDebug(false, s.isIdle, "-")
XSDebug(false, s.isWb, "w")
XSDebug(false, s.isCommit, "c")
})
XSDebug(false, true.B, "\n")
val headPtrNext = WireInit(headPtr + deqValid)
stateQueue(commitIdx):= Mux(deqValid,
s_idle,
Mux(commitValid,
s_commited,
stateQueue(commitIdx)
)
)
headPtr := headPtrNext
io.redirect.valid := deqValid && (deqEntry.npc =/= deqEntry.exuOut.redirect.target)
io.redirect.bits := deqEntry.exuOut.redirect
io.out.valid := deqValid
io.out.bits := deqEntry.exuOut
io.redirect.valid := commitValid && commitEntry.misPred
io.redirect.bits := commitEntry.exuOut.redirect
io.out.valid := commitValid
io.out.bits := commitEntry.exuOut
XSInfo(io.out.valid,
p"commit branch to roq, mispred:${io.redirect.valid} pc=${Hexadecimal(io.out.bits.uop.cf.pc)}\n"
)
// branch insts enq
var full = WireInit(isFull(headPtrNext, tailPtr))
......@@ -110,7 +156,10 @@ class Brq extends XSModule {
enq.ready := !full
brTag := tailPtrNext
// TODO: check rvc and use predict npc
when(enq.fire()){ brQueue(tailPtrNext.value).npc := enq.bits.cf.pc + 4.U }
when(enq.fire()){
brQueue(tailPtrNext.value).npc := enq.bits.cf.pc + 4.U
brQueue(tailPtrNext.value).ptrFlag := tailPtrNext.flag
}
tailPtrNext = tailPtrNext + enq.fire()
full = isFull(tailPtrNext, headPtrNext)
}
......@@ -119,17 +168,31 @@ class Brq extends XSModule {
// exu write back
for(exuWb <- io.exuRedirect){
when(exuWb.valid){
wbFlags(exuWb.bits.uop.brTag.value) := true.B
brQueue(exuWb.bits.uop.brTag.value).exuOut := exuWb.bits
val wbIdx = exuWb.bits.redirect.brTag.value
XSInfo(
p"exu write back: brTag:${exuWb.bits.redirect.brTag}" +
p" pc=${Hexadecimal(exuWb.bits.uop.cf.pc)}\n"
)
stateQueue(wbIdx) := s_wb
brQueue(wbIdx).exuOut := exuWb.bits
brQueue(wbIdx).misPred := brQueue(wbIdx).npc =/= exuWb.bits.redirect.target
}
}
// when redirect, reset all regs
when(io.roqRedirect.valid || io.redirect.valid){
wbFlags.foreach(_ := false.B)
val resetPtr = io.redirect.bits.brTag + true.B
headPtr := resetPtr
tailPtr := resetPtr
when(io.roqRedirect.valid){
// exception
stateQueue.foreach(_ := s_idle)
headPtr := BrqPtr(false.B, 0.U)
tailPtr := BrqPtr(false.B, 0.U)
}.elsewhen(io.redirect.valid){
// misprediction
stateQueue.zipWithIndex.foreach({case(s, i) =>
val ptr = BrqPtr(brQueue(i).ptrFlag, i.U)
when(ptr.needBrFlush(io.redirect.bits.brTag)){
s := s_idle
}
})
tailPtr := io.redirect.bits.brTag + true.B
}
......@@ -141,7 +204,7 @@ class Brq extends XSModule {
val debug_normal_mode = !(debug_roq_redirect || debug_brq_redirect)
for(i <- 0 until DecodeWidth){
XSInfo(
XSDebug(
debug_normal_mode,
p"enq v:${io.enqReqs(i).valid} rdy:${io.enqReqs(i).ready} pc:${Hexadecimal(io.enqReqs(i).bits.cf.pc)}" +
p" brTag:${io.brTags(i)}\n"
......
......@@ -2,8 +2,8 @@ package xiangshan.backend.decode
import chisel3._
import chisel3.util._
import noop.{ALUOpType, NOOPTrap}
import xiangshan.{FuType, HasXSParameter}
import xiangshan.backend._
import xiangshan.backend.decode.isa._
trait HasInstrType {
......@@ -36,7 +36,7 @@ object FuOpType {
object Instructions extends HasInstrType with HasXSParameter {
def NOP = 0x00000013.U
val DecodeDefault = List(InstrN, FuType.alu, ALUOpType.sll)
def DecodeTable = RVIInstr.table ++ NOOPTrap.table ++
def DecodeTable = RVIInstr.table ++ XSTrap.table ++
(if (HasMExtension) RVMInstr.table else Nil) // ++
// (if (HasCExtension) RVCInstr.table else Nil) ++
// (if (HasFPU) RVFInstr.table ++ RVDInstr.table else Nil) ++
......
......@@ -3,7 +3,6 @@ package xiangshan.backend.decode
import chisel3._
import chisel3.util._
import chisel3.util.experimental.BoringUtils
import noop.NOOPTrap
import xiangshan._
import utils.{LookupTree, SignExt, ZeroExt}
import xiangshan.backend._
......@@ -141,7 +140,6 @@ class Decoder extends XSModule with HasInstrType {
val BlockList = Seq(
)
io.out.ctrl.isXSTrap := (instr(31,0) === NOOPTrap.TRAP)
io.out.ctrl.noSpecExec := NoSpecList.map(j => io.out.ctrl.fuType === j).foldRight(false.B)((sum, i) => sum | i)
io.out.ctrl.isBlocked := DontCare
// (
......@@ -169,7 +167,10 @@ class Decoder extends XSModule with HasInstrType {
io.out.cf.exceptionVec(instrPageFault) := io.in.exceptionVec(instrPageFault)
io.out.cf.exceptionVec(instrAccessFault) := io.in.pc(VAddrBits - 1, PAddrBits).orR && !vmEnable
io.out.ctrl.isXSTrap := (instr === NOOPTrap.TRAP)
io.out.ctrl.isXSTrap := (instr === XSTrap.TRAP)
when(io.out.ctrl.isXSTrap){
io.out.ctrl.lsrc1 := 10.U // a0
}
// io.isWFI := (instr === Priviledged.WFI) && io.in.valid
}
package xiangshan.backend.decode
import chisel3._
import chisel3.util._
import xiangshan.FuType
import xiangshan.backend.ALUOpType
object XSTrap extends HasInstrType {
def StateGoodTrap = 0.U
def StateBadTrap = 1.U
def StateInvOpcode = 2.U
def StateRunning = 3.U
/*
calculate as ADDI => addi zero, a0, 0
replace rs '?????' with '01010'(a0) in decode stage
*/
def TRAP = BitPat("b000000000000_?????_000_00000_1101011")
val table = Array(TRAP -> List(InstrI, FuType.alu, ALUOpType.add))
}
......@@ -5,50 +5,7 @@ import chisel3.util._
import xiangshan._
import xiangshan.FuType._
import xiangshan.utils._
import xiangshan.backend.regfile.RfWritePort
object ALUOpType {
def add = "b000000".U
def sll = "b000001".U
def slt = "b000010".U
def sltu = "b000011".U
def xor = "b000100".U
def srl = "b000101".U
def or = "b000110".U
def and = "b000111".U
def sub = "b001000".U
def sra = "b001101".U
def addw = "b100000".U
def subw = "b101000".U
def sllw = "b100001".U
def srlw = "b100101".U
def sraw = "b101101".U
def isWordOp(func: UInt) = func(5)
// TODO: move jal/jalr/call/ret from ALU to BRU&CSR
def jal = "b011000".U
def jalr = "b011010".U
// def cjalr= "b111010".U // pc + 2 instead of 4
def beq = "b010000".U
def bne = "b010001".U
def blt = "b010100".U
def bge = "b010101".U
def bltu = "b010110".U
def bgeu = "b010111".U
// for RAS
def call = "b011100".U
def ret = "b011110".U
// def pcPlus2(func: UInt) = func(5)//[important]
def isBranch(func: UInt) = func(4,3)===2.U
def isBru(func: UInt) = func(4)
def isJump(func: UInt) = func(4,3)===3.U//isBru(func) && !isBranch(func)
def getBranchType(func: UInt) = func(2, 1)
def isBranchInvert(func: UInt) = func(0)
}
import xiangshan.backend._
class Alu extends Exu(alu.litValue(), hasRedirect = true) {
override def toString: String = "Alu"
......
......@@ -6,8 +6,8 @@ import xiangshan._
import xiangshan.backend.rename.FreeListPtr
import xiangshan.utils._
trait IQConst{
val iqSize = 8
trait IQConst extends HasXSParameter{
val iqSize = IssQueSize
val iqIdxWidth = log2Up(iqSize)
}
......@@ -43,6 +43,9 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
// use bypass uops to speculative wake-up
val bypassUops = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new MicroOp))) else null
val bypassData = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new ExuOutput))) else null
// to Dispatch
val numExist = Output(UInt((iqIdxWidth+1).W))
})
val srcAllNum = 3
......@@ -92,7 +95,9 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
val popOne = Wire(Bool())
io.enqCtrl.ready := !full || popOne
val enqSelIq = Wire(UInt(iqIdxWidth.W))
val enqSrcRdy = List(Mux(SrcType.isPcImm(io.enqCtrl.bits.src1State), true.B, io.enqCtrl.bits.src1State === SrcState.rdy), Mux(SrcType.isPcImm(io.enqCtrl.bits.src2State), true.B, io.enqCtrl.bits.src2State === SrcState.rdy), Mux(SrcType.isPcImm(io.enqCtrl.bits.src3State), true.B, io.enqCtrl.bits.src3State === SrcState.rdy))
val enqSrcRdy = List(Mux(SrcType.isPcImm(io.enqCtrl.bits.ctrl.src1Type), true.B, io.enqCtrl.bits.src1State === SrcState.rdy),
Mux(SrcType.isPcImm(io.enqCtrl.bits.ctrl.src2Type), true.B, io.enqCtrl.bits.src2State === SrcState.rdy),
Mux(SrcType.isPcImm(io.enqCtrl.bits.ctrl.src3Type), true.B, io.enqCtrl.bits.src3State === SrcState.rdy))
// state enq
when (enqFire) {
......@@ -184,7 +189,7 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
// redirect issQue
val redHitVec = List.tabulate(iqSize)(i => issQue(i).uop.brTag.needFlush(io.redirect))
for (i <- 0 until iqSize) {
for (i <- validQue.indices) {
when (redHitVec(i) && validQue(i)) {
validQue(i) := false.B
}
......@@ -229,19 +234,22 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
idQue(tail)
) // Note: direct by IQue's idx, different from deqSel
io.numExist := tailAll
assert(tailAll < 9.U)
//-----------------------------------------
// Wakeup and Bypass
//-----------------------------------------
if (wakeupCnt > 0) {
val cdbValid = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).valid)
val cdbData = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.data)
val cdbPdest = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.pdest)
val cdbrfWen = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.ctrl.rfWen)
val cdbfpWen = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.ctrl.fpWen)
val cdbValid = io.wakeUpPorts.map(_.valid)
val cdbData = io.wakeUpPorts.map(_.bits.data)
val cdbPdest = io.wakeUpPorts.map(_.bits.uop.pdest)
val cdbrfWen = io.wakeUpPorts.map(_.bits.uop.ctrl.rfWen)
val cdbfpWen = io.wakeUpPorts.map(_.bits.uop.ctrl.fpWen)
for(i <- 0 until iqSize) {
for(i <- idQue.indices) { // Should be IssQue.indices but Mem() does not support
for(j <- 0 until srcListenNum) {
val hitVec = List.tabulate(wakeupCnt)(k => psrc(i)(j) === cdbPdest(k) && cdbValid(k) && (srcType(i)(j)===SrcType.reg && cdbrfWen(k) || srcType(i)(j)===SrcType.fp && cdbfpWen(k)))
val hitVec = cdbValid.indices.map(k => psrc(i)(j) === cdbPdest(k) && cdbValid(k) && (srcType(i)(j)===SrcType.reg && cdbrfWen(k) || srcType(i)(j)===SrcType.fp && cdbfpWen(k)))
val hit = ParallelOR(hitVec).asBool
val data = ParallelMux(hitVec zip cdbData)
when (validQue(i) && !srcRdyVec(i)(j) && hit) {
......@@ -249,36 +257,36 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
srcRdyVec(i)(j) := true.B
}
// XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit, "WakeUp: Sel:%d Src:(%d|%d) Rdy:%d Hit:%d HitVec:%b Data:%x\n", i.U, j.U, psrc(i)(j), srcRdyVec(i)(j), hit, VecInit(hitVec).asUInt, data)
for (k <- 0 until wakeupCnt) {
for (k <- cdbValid.indices) {
XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit && hitVec(k), "WakeUpHit: IQIdx:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n", i.U, j.U, psrc(i)(j), k.U, cdbData(k), io.wakeUpPorts(k).bits.uop.cf.pc, io.wakeUpPorts(k).bits.uop.roqIdx)
}
}
}
}
if (useBypass) {
val bpPdest = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.pdest)
val bpValid = List.tabulate(bypassCnt)(i => io.bypassUops(i).valid)
val bpData = List.tabulate(bypassCnt)(i => io.bypassData(i).bits.data)
val bprfWen = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.ctrl.rfWen)
val bpfpWen = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.ctrl.fpWen)
val bpPdest = io.bypassUops.map(_.bits.pdest)
val bpValid = io.bypassUops.map(_.valid)
val bpData = io.bypassData.map(_.bits.data)
val bprfWen = io.bypassUops.map(_.bits.ctrl.rfWen)
val bpfpWen = io.bypassUops.map(_.bits.ctrl.fpWen)
for (i <- 0 until iqSize) {
for (i <- idQue.indices) { // Should be IssQue.indices but Mem() does not support
for (j <- 0 until srcListenNum) {
val hitVec = List.tabulate(bypassCnt)(k => psrc(i)(j) === bpPdest(k) && bpValid(k) && (srcType(i)(j)===SrcType.reg && bprfWen(k) || srcType(i)(j)===SrcType.fp && bpfpWen(k)))
val hitVec = bpValid.indices.map(k => psrc(i)(j) === bpPdest(k) && bpValid(k) && (srcType(i)(j)===SrcType.reg && bprfWen(k) || srcType(i)(j)===SrcType.fp && bpfpWen(k)))
val hitVecNext = hitVec.map(RegNext(_))
val hit = ParallelOR(hitVec).asBool
when (validQue(i) && !srcRdyVec(i)(j) && hit) {
srcRdyVec(i)(j) := true.B // FIXME: if uncomment the up comment, will cause combiantional loop, but it is Mem type??
srcRdyVec(i)(j) := true.B
}
when (RegNext(validQue(i) && !srcRdyVec(i)(j) && hit)) {
srcDataWire(i)(j) := PriorityMux(hitVecNext zip bpData)
}
// XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit, "BypassCtrl: Sel:%d Src:(%d|%d) Rdy:%d Hit:%d HitVec:%b\n", i.U, j.U, psrc(i)(j), srcRdyVec(i)(j), hit, VecInit(hitVec).asUInt)
for (k <- 0 until bypassCnt) {
for (k <- bpValid.indices) {
XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit && hitVec(k), "BypassCtrlHit: IQIdx:%d Src%d:%d Ports:%d Pc:%x RoqIdx:%x\n", i.U, j.U, psrc(i)(j), k.U, io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx)
}
// XSDebug(RegNext(validQue(i) && !srcRdyVec(i)(j) && hit), "BypassData: Sel:%d Src:(%d|%d) HitVecNext:%b Data:%x (for last cycle's Ctrl)\n", i.U, j.U, psrc(i)(j), VecInit(hitVecNext).asUInt, ParallelMux(hitVecNext zip bpData))
for (k <- 0 until bypassCnt) {
for (k <- bpValid.indices) {
XSDebug(RegNext(validQue(i) && !srcRdyVec(i)(j) && hit && hitVec(k)), "BypassDataHit: IQIdx:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n", i.U, j.U, psrc(i)(j), k.U, bpData(k), io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx)
}
}
......@@ -289,7 +297,7 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
val enqPsrc = List(enqCtrl.bits.psrc1, enqCtrl.bits.psrc2, enqCtrl.bits.psrc3)
val enqSrcType = List(enqCtrl.bits.ctrl.src1Type, enqCtrl.bits.ctrl.src2Type, enqCtrl.bits.ctrl.src3Type)
for (i <- 0 until srcListenNum) {
val hitVec = List.tabulate(bypassCnt)(j => enqPsrc(i)===bpPdest(j) && bpValid(j) && (enqSrcType(i)===SrcType.reg && bprfWen(j) || enqSrcType(i)===SrcType.fp && bpfpWen(j)))
val hitVec = bpValid.indices.map(j => enqPsrc(i)===bpPdest(j) && bpValid(j) && (enqSrcType(i)===SrcType.reg && bprfWen(j) || enqSrcType(i)===SrcType.fp && bpfpWen(j)))
val hitVecNext = hitVec.map(RegNext(_))
val hit = ParallelOR(hitVec).asBool
when (enqFire && hit && !enqSrcRdy(i)) {
......@@ -299,17 +307,17 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
srcDataWire(enqSelIqNext)(i) := ParallelMux(hitVecNext zip bpData)
}
// XSDebug(enqFire && hit, "EnqBypassCtrl: enqSelIq:%d Src:(%d|%d) Hit:%d HitVec:%b \n", enqSelIq, i.U, enqPsrc(i), hit, VecInit(hitVec).asUInt)
for (k <- 0 until bypassCnt) {
for (k <- bpValid.indices) {
XSDebug(enqFire && hit && !enqSrcRdy(i) && hitVec(k), "EnqBypassCtrlHit: enqSelIq:%d Src%d:%d Ports:%d Pc:%x RoqIdx:%x\n", enqSelIq, i.U, enqPsrc(i), k.U, io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx)
}
// XSDebug(RegNext(enqFire && hit), "EnqBypassData: enqSelIqNext:%d Src:(%d|%d) HitVecNext:%b Data:%x (for last cycle's Ctrl)\n", enqSelIqNext, i.U, enqPsrc(i), VecInit(hitVecNext).asUInt, ParallelMux(hitVecNext zip bpData))
for (k <- 0 until bypassCnt) {
for (k <- bpValid.indices) {
XSDebug(RegNext(enqFire && hit && !enqSrcRdy(i) && hitVec(k)), "EnqBypassDataHit: enqSelIq:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n", enqSelIq, i.U, enqPsrc(i), k.U, bpData(k), io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx)
}
}
// send out bypass
assert(fixedDelay==1) // only support fixedDelay is 1 now
require(fixedDelay==1) // only support fixedDelay is 1 now
val sel = io.selectedUop
sel.valid := toIssFire
sel.bits := DontCare
......
......@@ -5,6 +5,7 @@ import chisel3.util._
import xiangshan._
import xiangshan.utils._
import chisel3.util.experimental.BoringUtils
import xiangshan.backend.decode.XSTrap
// A "just-enough" Roq
class Roq(implicit val p: XSConfig) extends XSModule {
......@@ -216,14 +217,23 @@ class Roq(implicit val p: XSConfig) extends XSModule {
val wdata = Wire(Vec(CommitWidth, UInt(XLEN.W)))
val wdst = Wire(Vec(CommitWidth, UInt(32.W)))
val wpc = Wire(Vec(CommitWidth, UInt(VAddrBits.W)))
val trapVec = Wire(Vec(CommitWidth, Bool()))
for(i <- 0 until CommitWidth){
// io.commits(i).valid
skip(i) := exuDebug(ringBufferTail+i.U).isMMIO && io.commits(i).valid
wen(i) := io.commits(i).valid && microOp(ringBufferTail+i.U).ctrl.rfWen && microOp(ringBufferTail+i.U).ctrl.ldest =/= 0.U
wdata(i) := exuData(ringBufferTail+i.U)
wdst(i) := microOp(ringBufferTail+i.U).ctrl.ldest
wpc(i) := microOp(ringBufferTail+i.U).cf.pc
// io.commits(i).valid
val idx = ringBufferTail+i.U
val uop = microOp(idx)
skip(i) := exuDebug(idx).isMMIO && io.commits(i).valid
wen(i) := io.commits(i).valid && uop.ctrl.rfWen && uop.ctrl.ldest =/= 0.U
wdata(i) := exuData(idx)
wdst(i) := uop.ctrl.ldest
wpc(i) := uop.cf.pc
trapVec(i) := io.commits(i).valid && (state===s_idle) && uop.ctrl.isXSTrap
}
val instrCnt = RegInit(0.U(64.W))
instrCnt := instrCnt + retireCounter
val hitTrap = trapVec.reduce(_||_)
val trapCode = PriorityMux(wdata.zip(trapVec).map(x => x._2 -> x._1))
val trapPC = PriorityMux(wpc.zip(trapVec).map(x => x._2 ->x._1))
if(!p.FPGAPlatform){
BoringUtils.addSource(RegNext(retireCounter), "difftestCommit")
......@@ -247,5 +257,26 @@ class Roq(implicit val p: XSConfig) extends XSModule {
BoringUtils.addSource(emptyCsr, "difftestSepc")
BoringUtils.addSource(emptyCsr, "difftestMcause")
BoringUtils.addSource(emptyCsr, "difftestScause")
class Monitor extends BlackBox {
val io = IO(new Bundle {
val clk = Input(Clock())
val reset = Input(Reset())
val isNoopTrap = Input(Bool())
val trapCode = Input(UInt(32.W))
val trapPC = Input(UInt(64.W))
val cycleCnt = Input(UInt(64.W))
val instrCnt = Input(UInt(64.W))
})
}
val debugMonitor = Module(new Monitor)
debugMonitor.io.clk := this.clock
debugMonitor.io.reset := this.reset
debugMonitor.io.isNoopTrap := hitTrap
debugMonitor.io.trapCode := trapCode
debugMonitor.io.trapPC := trapPC
debugMonitor.io.cycleCnt := GTimer()
debugMonitor.io.instrCnt := instrCnt
}
}
......@@ -14,10 +14,13 @@ class Frontend extends XSModule {
val fakeIFU = Module(new FakeIFU)
val ibuffer= Module(new Ibuffer)
fakeIFU.io.redirect := io.backend.redirect
val needFlush = io.backend.redirectInfo.flush()
fakeIFU.io.redirect.valid := needFlush
fakeIFU.io.redirect.bits := io.backend.redirectInfo.redirect
ibuffer.io.in <> fakeIFU.io.fetchPacket
ibuffer.io.flush := io.backend.redirect.valid
ibuffer.io.flush := needFlush
io.backend.cfVec <> ibuffer.io.out
......
package xiangshan.utils
import chisel3._
object PriorityMuxDefault {
def apply[T <: Data](in: Seq[(Bool, T)], default: T): T = {
in.size match {
case 1=>
Mux(in.head._1, in.head._2, default)
case _ =>
Mux(in.head._1, in.head._2, PriorityMuxDefault(in.tail, default))
}
}
}
object PriorityEncoderDefault {
def apply(in: Seq[Bool], default: UInt): UInt = {
PriorityMuxDefault(in.zipWithIndex.map(x => x._1 -> x._2.U), default)
}
}
\ No newline at end of file
......@@ -149,10 +149,12 @@ class Emulator {
tfp->open("vlt_dump.vcd"); // Open the dump file
#endif
while (!is_finish() && n > 0) {
while (n > 0) {
single_cycle();
n --;
if(is_finish()) return;
if (lastcommit - n > stuck_limit && hascommit) {
eprintf("No instruction commits for %d cycles, maybe get stuck\n"
"(please also check whether a fence.i instruction requires more than %d cycles to flush the icache)\n",
......
......@@ -39,6 +39,8 @@ int display_trapinfo(uint64_t max_cycles) {
case STATE_RUNNING:
eprintf(ANSI_COLOR_RED "Timeout after %" PRIx64 " cycles\n" ANSI_COLOR_RESET, max_cycles);
break;
default:
eprintf(ANSI_COLOR_RED "Unknown trap code: %d\n", g_trapCode);
}
double ipc = (double)g_instrCnt / g_cycleCnt;
......
......@@ -9,16 +9,16 @@ import chisel3.stage.ChiselGeneratorAnnotation
import device.AXI4RAM
import xiangshan._
class DiffTestIO extends Bundle {
val r = Output(Vec(64, UInt(64.W)))
class DiffTestIO extends XSBundle {
val r = Output(Vec(64, UInt(XLEN.W)))
val commit = Output(UInt(32.W))
val thisPC = Output(UInt(64.W))
val thisPC = Output(UInt(VAddrBits.W))
val thisINST = Output(UInt(32.W))
val skip = Output(UInt(32.W))
val wen = Output(UInt(32.W))
val wdata = Output(Vec(6, UInt(64.W))) // set difftest width to 6
val wdst = Output(Vec(6, UInt(32.W))) // set difftest width to 6
val wpc = Output(Vec(6, UInt(39.W))) // set difftest width to 6
val wdata = Output(Vec(CommitWidth, UInt(XLEN.W))) // set difftest width to 6
val wdst = Output(Vec(CommitWidth, UInt(32.W))) // set difftest width to 6
val wpc = Output(Vec(CommitWidth, UInt(VAddrBits.W))) // set difftest width to 6
val isRVC = Output(Bool())
val intrNO = Output(UInt(64.W))
......
package xiangshan.backend.brq
import org.scalatest._
import chiseltest._
import chisel3._
import chisel3.experimental.BundleLiterals._
import chisel3.util._
import chiseltest.experimental.TestOptionBuilder._
import chiseltest.internal.VerilatorBackendAnnotation
import xiangshan._
import xiangshan.testutils._
import xiangshan.testutils.TestCaseGenerator._
import scala.util.Random
class BrqTest extends FlatSpec
with ChiselScalatestTester
with Matchers
with ParallelTestExecution
with HasPartialDecoupledDriver {
it should "" in {
test(new Brq {
AddSinks()
}).withAnnotations(Seq(VerilatorBackendAnnotation)) { c =>
def genEnqReq(x: => DecoupledIO[CfCtrl], pc: Long) = {
chiselTypeOf(x.bits).Lit(
_.cf.pc -> pc.U
)
}
def genExuWb(exuRedirect: => Valid[ExuOutput], tagIdx: Int, tagFlag: Boolean, target: Long) = {
chiselTypeOf(exuRedirect.bits).Lit(
_.redirect.brTag.value -> tagIdx.U,
_.redirect.brTag.flag -> tagFlag.B,
_.redirect.target -> target.U
)
}
c.io.enqReqs.head.initSource().setSourceClock(c.clock)
var brqPtrSeq = Seq[(BigInt, Boolean)]()
for (i <- 0 until 10) {
val enqPort = c.io.enqReqs.head
enqPort.enqueuePartial(genEnqReq(enqPort, i * 0x1000))
}
var enqTags = List.tabulate(10)(i => i)
val misPred = Random.nextInt(10)
println(s"enqTags:$enqTags misPredTag:$misPred")
enqTags = enqTags.take(misPred + 1)
var deqTags = List[Int]()
def checkDeq = {
if (c.io.out.valid.peek().litToBoolean) {
deqTags = deqTags :+ c.io.redirect.bits.brTag.value.peek().litValue().toInt
println(s"====deq tags:$deqTags====")
}
}
println("====Start random write back====")
val wbPort = c.io.exuRedirect.head
//-----------------write back-----------------//
while (enqTags.nonEmpty) {
val idx = Random.nextInt(enqTags.size)
val tag = enqTags(idx)
println(s"====write tag:$tag back to Brq====")
enqTags = enqTags.filter(x => x != tag)
wbPort.valid.poke(true.B)
wbPort.bits.pokePartial(
genExuWb(wbPort, tag, tagFlag = false, if (tag == misPred) 0xffff else tag * 0x1000 + 4)
)
checkDeq
c.clock.step(1)
wbPort.valid.poke(false.B)
for (i <- 0 until Random.nextInt(3)) {
checkDeq
c.clock.step(1)
}
}
while (deqTags.size != misPred+1) {
checkDeq
c.clock.step(1)
}
c.clock.step(10)
val left = deqTags.takeWhile(x => x!=misPred)
val right = deqTags.dropWhile(x => x!=misPred).drop(1)
println(s"deq before mispred: $left")
println(s"deq after mispred: $right")
def isValidDeqSeq(in: Seq[Int]): Boolean = {
for(i <- 1 until in.size){
if(in(i) == in(i-1)) return false
}
true
}
assert(isValidDeqSeq(left) && isValidDeqSeq(right))
}
}
}
......@@ -6,7 +6,7 @@ import chisel3.experimental.BundleLiterals._
import chiseltest._
import noop.MDUOpType
import xiangshan._
import xiangshan.backend.exu.{ALUOpType, LSUOpType}
import xiangshan.backend._
object TestCaseGenerator {
......@@ -61,15 +61,15 @@ object TestCaseGenerator {
}
def genLsuLd(x: => ExuInput, base: Long, offset: Long) =
genLsuInput(LSUOpType.ld)(x, base, offset, 0)
genLsuInput(LDUOpType.ld)(x, base, offset, 0)
def genLsuLw(x: => ExuInput, base: Long, offset: Long) =
genLsuInput(LSUOpType.lw)(x, base, offset, 0)
genLsuInput(LDUOpType.lw)(x, base, offset, 0)
def genLsuSd(x: => ExuInput, base: Long, offset: Long, stData: Long) =
genLsuInput(LSUOpType.sd)(x, base, offset, stData)
genLsuInput(STUOpType.sd)(x, base, offset, stData)
def genLsuSw(x: => ExuInput, base: Long, offset: Long, stData: Long) =
genLsuInput(LSUOpType.sw)(x, base, offset, stData)
genLsuInput(STUOpType.sw)(x, base, offset, stData)
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册