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