1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* 4* XiangShan is licensed under Mulan PSL v2. 5* You can use this software according to the terms and conditions of the Mulan PSL v2. 6* You may obtain a copy of Mulan PSL v2 at: 7* http://license.coscl.org.cn/MulanPSL2 8* 9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12* 13* See the Mulan PSL v2 for more details. 14***************************************************************************************/ 15 16package xiangshan 17 18import chisel3._ 19import chisel3.util._ 20import xiangshan.backend.roq.RoqPtr 21import xiangshan.backend.decode.{ImmUnion, XDecode} 22import xiangshan.mem.{LqPtr, SqPtr} 23import xiangshan.frontend.PreDecodeInfoForDebug 24import xiangshan.frontend.PreDecodeInfo 25import xiangshan.frontend.HasBPUParameter 26import xiangshan.frontend.PreDecodeInfo 27import xiangshan.frontend.HasTageParameter 28import xiangshan.frontend.HasSCParameter 29import xiangshan.frontend.HasIFUConst 30import xiangshan.frontend.GlobalHistory 31import xiangshan.frontend.RASEntry 32import xiangshan.frontend.BPUCtrl 33import utils._ 34 35import scala.math.max 36import Chisel.experimental.chiselName 37import chipsalliance.rocketchip.config.Parameters 38import xiangshan.backend.ftq.FtqPtr 39 40// Fetch FetchWidth x 32-bit insts from Icache 41class FetchPacket(implicit p: Parameters) extends XSBundle { 42 val instrs = Vec(PredictWidth, UInt(32.W)) 43 val mask = UInt(PredictWidth.W) 44 val pdmask = UInt(PredictWidth.W) 45 // val pc = UInt(VAddrBits.W) 46 val pc = Vec(PredictWidth, UInt(VAddrBits.W)) 47 val foldpc = Vec(PredictWidth, UInt(MemPredPCWidth.W)) 48 val pd = Vec(PredictWidth, new PreDecodeInfo) 49 val ipf = Bool() 50 val acf = Bool() 51 val crossPageIPFFix = Bool() 52 val pred_taken = UInt(PredictWidth.W) 53 val ftqPtr = new FtqPtr 54} 55 56class ValidUndirectioned[T <: Data](gen: T) extends Bundle { 57 val valid = Bool() 58 val bits = gen.cloneType.asInstanceOf[T] 59 60 override def cloneType = new ValidUndirectioned(gen).asInstanceOf[this.type] 61} 62 63object ValidUndirectioned { 64 def apply[T <: Data](gen: T) = { 65 new ValidUndirectioned[T](gen) 66 } 67} 68 69object RSFeedbackType { 70 val tlbMiss = 0.U(2.W) 71 val mshrFull = 1.U(2.W) 72 val dataInvalid = 2.U(2.W) 73 74 def apply() = UInt(2.W) 75} 76 77class SCMeta(val useSC: Boolean)(implicit p: Parameters) extends XSBundle with HasSCParameter { 78 val tageTaken = if (useSC) Bool() else UInt(0.W) 79 val scUsed = if (useSC) Bool() else UInt(0.W) 80 val scPred = if (useSC) Bool() else UInt(0.W) 81 // Suppose ctrbits of all tables are identical 82 val ctrs = if (useSC) Vec(SCNTables, SInt(SCCtrBits.W)) else Vec(SCNTables, SInt(0.W)) 83} 84 85class TageMeta(implicit p: Parameters) extends XSBundle with HasTageParameter { 86 val provider = ValidUndirectioned(UInt(log2Ceil(TageNTables).W)) 87 val altDiffers = Bool() 88 val providerU = UInt(2.W) 89 val providerCtr = UInt(3.W) 90 val allocate = ValidUndirectioned(UInt(log2Ceil(TageNTables).W)) 91 val taken = Bool() 92 val scMeta = new SCMeta(EnableSC) 93} 94 95@chiselName 96class BranchPrediction(implicit p: Parameters) extends XSBundle with HasIFUConst { 97 // val redirect = Bool() 98 val takens = UInt(PredictWidth.W) 99 // val jmpIdx = UInt(log2Up(PredictWidth).W) 100 val brMask = UInt(PredictWidth.W) 101 val jalMask = UInt(PredictWidth.W) 102 val targets = Vec(PredictWidth, UInt(VAddrBits.W)) 103 104 // half RVI could only start at the end of a packet 105 val hasHalfRVI = Bool() 106 107 def brNotTakens = (~takens & brMask) 108 109 def sawNotTakenBr = VecInit((0 until PredictWidth).map(i => 110 (if (i == 0) false.B else ParallelORR(brNotTakens(i - 1, 0))))) 111 112 // if not taken before the half RVI inst 113 def saveHalfRVI = hasHalfRVI && !(ParallelORR(takens(PredictWidth - 2, 0))) 114 115 // could get PredictWidth-1 when only the first bank is valid 116 def jmpIdx = ParallelPriorityEncoder(takens) 117 118 // only used when taken 119 def target = { 120 val generator = new PriorityMuxGenerator[UInt] 121 generator.register(takens.asBools, targets, List.fill(PredictWidth)(None)) 122 generator() 123 } 124 125 def taken = ParallelORR(takens) 126 127 def takenOnBr = taken && ParallelPriorityMux(takens, brMask.asBools) 128 129 def hasNotTakenBrs = Mux(taken, ParallelPriorityMux(takens, sawNotTakenBr), ParallelORR(brNotTakens)) 130} 131 132class PredictorAnswer(implicit p: Parameters) extends XSBundle { 133 val hit = if (!env.FPGAPlatform) Bool() else UInt(0.W) 134 val taken = if (!env.FPGAPlatform) Bool() else UInt(0.W) 135 val target = if (!env.FPGAPlatform) UInt(VAddrBits.W) else UInt(0.W) 136} 137 138class BpuMeta(implicit p: Parameters) extends XSBundle with HasBPUParameter { 139 val btbWriteWay = UInt(log2Up(BtbWays).W) 140 val btbHit = Bool() 141 val bimCtr = UInt(2.W) 142 val tageMeta = new TageMeta 143 // for global history 144 145 val debug_ubtb_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W) 146 val debug_btb_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W) 147 val debug_tage_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W) 148 149 val predictor = if (BPUDebug) UInt(log2Up(4).W) else UInt(0.W) // Mark which component this prediction comes from {ubtb, btb, tage, loopPredictor} 150 151 val ubtbHit = if (BPUDebug) UInt(1.W) else UInt(0.W) 152 153 val ubtbAns = new PredictorAnswer 154 val btbAns = new PredictorAnswer 155 val tageAns = new PredictorAnswer 156 val rasAns = new PredictorAnswer 157 val loopAns = new PredictorAnswer 158 159 // def apply(histPtr: UInt, tageMeta: TageMeta, rasSp: UInt, rasTopCtr: UInt) = { 160 // this.histPtr := histPtr 161 // this.tageMeta := tageMeta 162 // this.rasSp := rasSp 163 // this.rasTopCtr := rasTopCtr 164 // this.asUInt 165 // } 166 def size = 0.U.asTypeOf(this).getWidth 167 168 def fromUInt(x: UInt) = x.asTypeOf(this) 169} 170 171class Predecode(implicit p: Parameters) extends XSBundle with HasIFUConst { 172 val hasLastHalfRVI = Bool() 173 val mask = UInt(PredictWidth.W) 174 val lastHalf = Bool() 175 val pd = Vec(PredictWidth, (new PreDecodeInfo)) 176} 177 178class CfiUpdateInfo(implicit p: Parameters) extends XSBundle with HasBPUParameter { 179 // from backend 180 val pc = UInt(VAddrBits.W) 181 // frontend -> backend -> frontend 182 val pd = new PreDecodeInfo 183 val rasSp = UInt(log2Up(RasSize).W) 184 val rasEntry = new RASEntry 185 val hist = new GlobalHistory 186 val predHist = new GlobalHistory 187 val specCnt = Vec(PredictWidth, UInt(10.W)) 188 // need pipeline update 189 val sawNotTakenBranch = Bool() 190 val predTaken = Bool() 191 val target = UInt(VAddrBits.W) 192 val taken = Bool() 193 val isMisPred = Bool() 194} 195 196// Dequeue DecodeWidth insts from Ibuffer 197class CtrlFlow(implicit p: Parameters) extends XSBundle { 198 val instr = UInt(32.W) 199 val pc = UInt(VAddrBits.W) 200 val foldpc = UInt(MemPredPCWidth.W) 201 val exceptionVec = ExceptionVec() 202 val intrVec = Vec(12, Bool()) 203 val pd = new PreDecodeInfo 204 val pred_taken = Bool() 205 val crossPageIPFFix = Bool() 206 val storeSetHit = Bool() // inst has been allocated an store set 207 val loadWaitBit = Bool() // load inst should not be executed until all former store addr calcuated 208 val ssid = UInt(SSIDWidth.W) 209 val ftqPtr = new FtqPtr 210 val ftqOffset = UInt(log2Up(PredictWidth).W) 211} 212 213class FtqEntry(implicit p: Parameters) extends XSBundle { 214 // fetch pc, pc of each inst could be generated by concatenation 215 val ftqPC = UInt(VAddrBits.W) 216 val lastPacketPC = ValidUndirectioned(UInt(VAddrBits.W)) 217 // prediction metas 218 val hist = new GlobalHistory 219 val predHist = new GlobalHistory 220 val rasSp = UInt(log2Ceil(RasSize).W) 221 val rasTop = new RASEntry() 222 val specCnt = Vec(PredictWidth, UInt(10.W)) 223 val metas = Vec(PredictWidth, new BpuMeta) 224 225 val cfiIsCall, cfiIsRet, cfiIsJalr, cfiIsRVC = Bool() 226 val rvc_mask = Vec(PredictWidth, Bool()) 227 val br_mask = Vec(PredictWidth, Bool()) 228 val cfiIndex = ValidUndirectioned(UInt(log2Up(PredictWidth).W)) 229 val valids = Vec(PredictWidth, Bool()) 230 231 // backend update 232 val mispred = Vec(PredictWidth, Bool()) 233 val target = UInt(VAddrBits.W) 234 235 // For perf counters 236 val pd = Vec(PredictWidth, new PreDecodeInfoForDebug(!env.FPGAPlatform)) 237 238 def takens = VecInit((0 until PredictWidth).map(i => cfiIndex.valid && cfiIndex.bits === i.U)) 239 def hasLastPrev = lastPacketPC.valid 240 241 override def toPrintable: Printable = { 242 p"ftqPC: ${Hexadecimal(ftqPC)} lastPacketPC: ${Hexadecimal(lastPacketPC.bits)} hasLastPrev:$hasLastPrev " + 243 p"rasSp:$rasSp specCnt:$specCnt brmask:${Binary(Cat(br_mask))} rvcmask:${Binary(Cat(rvc_mask))} " + 244 p"valids:${Binary(valids.asUInt())} cfi valid: ${cfiIndex.valid} " + 245 p"cfi index: ${cfiIndex.bits} isCall:$cfiIsCall isRet:$cfiIsRet isJalr:$cfiIsJalr, isRvc:$cfiIsRVC " + 246 p"mispred:${Binary(Cat(mispred))} target:${Hexadecimal(target)}\n" 247 } 248 249} 250 251 252class FPUCtrlSignals(implicit p: Parameters) extends XSBundle { 253 val isAddSub = Bool() // swap23 254 val typeTagIn = UInt(2.W) 255 val typeTagOut = UInt(2.W) 256 val fromInt = Bool() 257 val wflags = Bool() 258 val fpWen = Bool() 259 val fmaCmd = UInt(2.W) 260 val div = Bool() 261 val sqrt = Bool() 262 val fcvt = Bool() 263 val typ = UInt(2.W) 264 val fmt = UInt(2.W) 265 val ren3 = Bool() //TODO: remove SrcType.fp 266 val rm = UInt(3.W) 267} 268 269// Decode DecodeWidth insts at Decode Stage 270class CtrlSignals(implicit p: Parameters) extends XSBundle { 271 val srcType = Vec(3, SrcType()) 272 val lsrc = Vec(3, UInt(5.W)) 273 val ldest = UInt(5.W) 274 val fuType = FuType() 275 val fuOpType = FuOpType() 276 val rfWen = Bool() 277 val fpWen = Bool() 278 val isXSTrap = Bool() 279 val noSpecExec = Bool() // wait forward 280 val blockBackward = Bool() // block backward 281 val flushPipe = Bool() // This inst will flush all the pipe when commit, like exception but can commit 282 val isRVF = Bool() 283 val selImm = SelImm() 284 val imm = UInt(ImmUnion.maxLen.W) 285 val commitType = CommitType() 286 val fpu = new FPUCtrlSignals 287 val isMove = Bool() 288 289 def decode(inst: UInt, table: Iterable[(BitPat, List[BitPat])]) = { 290 val decoder = freechips.rocketchip.rocket.DecodeLogic(inst, XDecode.decodeDefault, table) 291 val signals = 292 Seq(srcType(0), srcType(1), srcType(2), fuType, fuOpType, rfWen, fpWen, 293 isXSTrap, noSpecExec, blockBackward, flushPipe, isRVF, selImm) 294 signals zip decoder map { case (s, d) => s := d } 295 commitType := DontCare 296 this 297 } 298} 299 300class CfCtrl(implicit p: Parameters) extends XSBundle { 301 val cf = new CtrlFlow 302 val ctrl = new CtrlSignals 303} 304 305class PerfDebugInfo(implicit p: Parameters) extends XSBundle { 306 val src1MoveElim = Bool() 307 val src2MoveElim = Bool() 308 // val fetchTime = UInt(64.W) 309 val renameTime = UInt(64.W) 310 val dispatchTime = UInt(64.W) 311 val issueTime = UInt(64.W) 312 val writebackTime = UInt(64.W) 313 // val commitTime = UInt(64.W) 314} 315 316// Separate LSQ 317class LSIdx(implicit p: Parameters) extends XSBundle { 318 val lqIdx = new LqPtr 319 val sqIdx = new SqPtr 320} 321 322// CfCtrl -> MicroOp at Rename Stage 323class MicroOp(implicit p: Parameters) extends CfCtrl { 324 val srcState = Vec(3, SrcState()) 325 val psrc = Vec(3, UInt(PhyRegIdxWidth.W)) 326 val pdest = UInt(PhyRegIdxWidth.W) 327 val old_pdest = UInt(PhyRegIdxWidth.W) 328 val roqIdx = new RoqPtr 329 val lqIdx = new LqPtr 330 val sqIdx = new SqPtr 331 val diffTestDebugLrScValid = Bool() 332 val debugInfo = new PerfDebugInfo 333 def needRfRPort(index: Int, rfType: Int, ignoreState: Boolean = true) : Bool = { 334 (index, rfType) match { 335 case (0, 0) => ctrl.srcType(0) === SrcType.reg && ctrl.lsrc(0) =/= 0.U && (srcState(0) === SrcState.rdy || ignoreState.B) 336 case (1, 0) => ctrl.srcType(1) === SrcType.reg && ctrl.lsrc(1) =/= 0.U && (srcState(1) === SrcState.rdy || ignoreState.B) 337 case (0, 1) => ctrl.srcType(0) === SrcType.fp && (srcState(0) === SrcState.rdy || ignoreState.B) 338 case (1, 1) => ctrl.srcType(1) === SrcType.fp && (srcState(1) === SrcState.rdy || ignoreState.B) 339 case (2, 1) => ctrl.srcType(2) === SrcType.fp && (srcState(2) === SrcState.rdy || ignoreState.B) 340 case _ => false.B 341 } 342 } 343 def srcIsReady: Vec[Bool] = { 344 VecInit(ctrl.srcType.zip(srcState).map{ case (t, s) => SrcType.isPcImm(t) || s === SrcState.rdy }) 345 } 346 def doWriteIntRf: Bool = ctrl.rfWen && ctrl.ldest =/= 0.U 347 def doWriteFpRf: Bool = ctrl.fpWen 348} 349 350class MicroOpRbExt(implicit p: Parameters) extends XSBundle { 351 val uop = new MicroOp 352 val flag = UInt(1.W) 353} 354 355class Redirect(implicit p: Parameters) extends XSBundle { 356 val roqIdx = new RoqPtr 357 val ftqIdx = new FtqPtr 358 val ftqOffset = UInt(log2Up(PredictWidth).W) 359 val level = RedirectLevel() 360 val interrupt = Bool() 361 val cfiUpdate = new CfiUpdateInfo 362 363 val stFtqIdx = new FtqPtr // for load violation predict 364 val stFtqOffset = UInt(log2Up(PredictWidth).W) 365 366 // def isUnconditional() = RedirectLevel.isUnconditional(level) 367 def flushItself() = RedirectLevel.flushItself(level) 368 // def isException() = RedirectLevel.isException(level) 369} 370 371class Dp1ToDp2IO(implicit p: Parameters) extends XSBundle { 372 val intDqToDp2 = Vec(dpParams.IntDqDeqWidth, DecoupledIO(new MicroOp)) 373 val fpDqToDp2 = Vec(dpParams.FpDqDeqWidth, DecoupledIO(new MicroOp)) 374 val lsDqToDp2 = Vec(dpParams.LsDqDeqWidth, DecoupledIO(new MicroOp)) 375} 376 377class ReplayPregReq(implicit p: Parameters) extends XSBundle { 378 // NOTE: set isInt and isFp both to 'false' when invalid 379 val isInt = Bool() 380 val isFp = Bool() 381 val preg = UInt(PhyRegIdxWidth.W) 382} 383 384class DebugBundle(implicit p: Parameters) extends XSBundle { 385 val isMMIO = Bool() 386 val isPerfCnt = Bool() 387 val paddr = UInt(PAddrBits.W) 388} 389 390class ExuInput(implicit p: Parameters) extends XSBundle { 391 val uop = new MicroOp 392 val src = Vec(3, UInt((XLEN + 1).W)) 393} 394 395class ExuOutput(implicit p: Parameters) extends XSBundle { 396 val uop = new MicroOp 397 val data = UInt((XLEN + 1).W) 398 val fflags = UInt(5.W) 399 val redirectValid = Bool() 400 val redirect = new Redirect 401 val debug = new DebugBundle 402} 403 404class ExternalInterruptIO(implicit p: Parameters) extends XSBundle { 405 val mtip = Input(Bool()) 406 val msip = Input(Bool()) 407 val meip = Input(Bool()) 408} 409 410class CSRSpecialIO(implicit p: Parameters) extends XSBundle { 411 val exception = Flipped(ValidIO(new MicroOp)) 412 val isInterrupt = Input(Bool()) 413 val memExceptionVAddr = Input(UInt(VAddrBits.W)) 414 val trapTarget = Output(UInt(VAddrBits.W)) 415 val externalInterrupt = new ExternalInterruptIO 416 val interrupt = Output(Bool()) 417} 418 419class ExceptionInfo(implicit p: Parameters) extends XSBundle { 420 val uop = new MicroOp 421 val isInterrupt = Bool() 422} 423 424class RoqCommitInfo(implicit p: Parameters) extends XSBundle { 425 val ldest = UInt(5.W) 426 val rfWen = Bool() 427 val fpWen = Bool() 428 val wflags = Bool() 429 val commitType = CommitType() 430 val pdest = UInt(PhyRegIdxWidth.W) 431 val old_pdest = UInt(PhyRegIdxWidth.W) 432 val ftqIdx = new FtqPtr 433 val ftqOffset = UInt(log2Up(PredictWidth).W) 434 435 // these should be optimized for synthesis verilog 436 val pc = UInt(VAddrBits.W) 437} 438 439class RoqCommitIO(implicit p: Parameters) extends XSBundle { 440 val isWalk = Output(Bool()) 441 val valid = Vec(CommitWidth, Output(Bool())) 442 val info = Vec(CommitWidth, Output(new RoqCommitInfo)) 443 444 def hasWalkInstr = isWalk && valid.asUInt.orR 445 446 def hasCommitInstr = !isWalk && valid.asUInt.orR 447} 448 449class RSFeedback(implicit p: Parameters) extends XSBundle { 450 val rsIdx = UInt(log2Up(IssQueSize).W) 451 val hit = Bool() 452 val flushState = Bool() 453 val sourceType = RSFeedbackType() 454} 455 456class FrontendToBackendIO(implicit p: Parameters) extends XSBundle { 457 // to backend end 458 val cfVec = Vec(DecodeWidth, DecoupledIO(new CtrlFlow)) 459 val fetchInfo = DecoupledIO(new FtqEntry) 460 // from backend 461 val redirect_cfiUpdate = Flipped(ValidIO(new Redirect)) 462 val commit_cfiUpdate = Flipped(ValidIO(new FtqEntry)) 463 val ftqEnqPtr = Input(new FtqPtr) 464 val ftqLeftOne = Input(Bool()) 465} 466 467class TlbCsrBundle(implicit p: Parameters) extends XSBundle { 468 val satp = new Bundle { 469 val mode = UInt(4.W) // TODO: may change number to parameter 470 val asid = UInt(16.W) 471 val ppn = UInt(44.W) // just use PAddrBits - 3 - vpnnLen 472 } 473 val priv = new Bundle { 474 val mxr = Bool() 475 val sum = Bool() 476 val imode = UInt(2.W) 477 val dmode = UInt(2.W) 478 } 479 480 override def toPrintable: Printable = { 481 p"Satp mode:0x${Hexadecimal(satp.mode)} asid:0x${Hexadecimal(satp.asid)} ppn:0x${Hexadecimal(satp.ppn)} " + 482 p"Priv mxr:${priv.mxr} sum:${priv.sum} imode:${priv.imode} dmode:${priv.dmode}" 483 } 484} 485 486class SfenceBundle(implicit p: Parameters) extends XSBundle { 487 val valid = Bool() 488 val bits = new Bundle { 489 val rs1 = Bool() 490 val rs2 = Bool() 491 val addr = UInt(VAddrBits.W) 492 } 493 494 override def toPrintable: Printable = { 495 p"valid:0x${Hexadecimal(valid)} rs1:${bits.rs1} rs2:${bits.rs2} addr:${Hexadecimal(bits.addr)}" 496 } 497} 498 499// Bundle for load violation predictor updating 500class MemPredUpdateReq(implicit p: Parameters) extends XSBundle { 501 val valid = Bool() 502 503 // wait table update 504 val waddr = UInt(MemPredPCWidth.W) 505 val wdata = Bool() // true.B by default 506 507 // store set update 508 // by default, ldpc/stpc should be xor folded 509 val ldpc = UInt(MemPredPCWidth.W) 510 val stpc = UInt(MemPredPCWidth.W) 511} 512 513class PerfInfoIO extends Bundle { 514 val clean = Input(Bool()) 515 val dump = Input(Bool()) 516} 517 518class CustomCSRCtrlIO(implicit p: Parameters) extends XSBundle { 519 // Prefetcher 520 val l1plus_pf_enable = Output(Bool()) 521 val l2_pf_enable = Output(Bool()) 522 // Labeled XiangShan 523 val dsid = Output(UInt(8.W)) // TODO: DsidWidth as parameter 524 // Load violation predictor 525 val lvpred_disable = Output(Bool()) 526 val no_spec_load = Output(Bool()) 527 val waittable_timeout = Output(UInt(5.W)) 528 // Branch predictor 529 val bp_ctrl = Output(new BPUCtrl) 530 // Memory Block 531 val sbuffer_threshold = Output(UInt(4.W)) 532 // Rename 533 val move_elim_enable = Output(Bool()) 534} 535