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