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