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 src1Type, src2Type, src3Type = SrcType() 255 val lsrc1, lsrc2, lsrc3 = 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(src1Type, src2Type, src3Type, 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 psrc1, psrc2, psrc3, pdest, old_pdest = UInt(PhyRegIdxWidth.W) 308 val src1State, src2State, src3State = SrcState() 309 val roqIdx = new RoqPtr 310 val lqIdx = new LqPtr 311 val sqIdx = new SqPtr 312 val diffTestDebugLrScValid = Bool() 313 val debugInfo = new PerfDebugInfo 314 def needRfRPort(index: Int, rfType: Int, ignoreState: Boolean = true) : Bool = { 315 (index, rfType) match { 316 case (0, 0) => ctrl.src1Type === SrcType.reg && ctrl.lsrc1 =/= 0.U && (src1State === SrcState.rdy || ignoreState.B) 317 case (1, 0) => ctrl.src2Type === SrcType.reg && ctrl.lsrc2 =/= 0.U && (src2State === SrcState.rdy || ignoreState.B) 318 case (0, 1) => ctrl.src1Type === SrcType.fp && (src1State === SrcState.rdy || ignoreState.B) 319 case (1, 1) => ctrl.src2Type === SrcType.fp && (src2State === SrcState.rdy || ignoreState.B) 320 case (2, 1) => ctrl.src3Type === SrcType.fp && (src3State === SrcState.rdy || ignoreState.B) 321 case _ => false.B 322 } 323 } 324} 325 326class Redirect(implicit p: Parameters) extends XSBundle { 327 val roqIdx = new RoqPtr 328 val ftqIdx = new FtqPtr 329 val ftqOffset = UInt(log2Up(PredictWidth).W) 330 val level = RedirectLevel() 331 val interrupt = Bool() 332 val cfiUpdate = new CfiUpdateInfo 333 334 335 // def isUnconditional() = RedirectLevel.isUnconditional(level) 336 def flushItself() = RedirectLevel.flushItself(level) 337 // def isException() = RedirectLevel.isException(level) 338} 339 340class Dp1ToDp2IO(implicit p: Parameters) extends XSBundle { 341 val intDqToDp2 = Vec(dpParams.IntDqDeqWidth, DecoupledIO(new MicroOp)) 342 val fpDqToDp2 = Vec(dpParams.FpDqDeqWidth, DecoupledIO(new MicroOp)) 343 val lsDqToDp2 = Vec(dpParams.LsDqDeqWidth, DecoupledIO(new MicroOp)) 344} 345 346class ReplayPregReq(implicit p: Parameters) extends XSBundle { 347 // NOTE: set isInt and isFp both to 'false' when invalid 348 val isInt = Bool() 349 val isFp = Bool() 350 val preg = UInt(PhyRegIdxWidth.W) 351} 352 353class DebugBundle(implicit p: Parameters) extends XSBundle { 354 val isMMIO = Bool() 355 val isPerfCnt = Bool() 356 val paddr = UInt(PAddrBits.W) 357} 358 359class ExuInput(implicit p: Parameters) extends XSBundle { 360 val uop = new MicroOp 361 val src1, src2, src3 = UInt((XLEN + 1).W) 362} 363 364class ExuOutput(implicit p: Parameters) extends XSBundle { 365 val uop = new MicroOp 366 val data = UInt((XLEN + 1).W) 367 val fflags = UInt(5.W) 368 val redirectValid = Bool() 369 val redirect = new Redirect 370 val debug = new DebugBundle 371} 372 373class ExternalInterruptIO(implicit p: Parameters) extends XSBundle { 374 val mtip = Input(Bool()) 375 val msip = Input(Bool()) 376 val meip = Input(Bool()) 377} 378 379class CSRSpecialIO(implicit p: Parameters) extends XSBundle { 380 val exception = Flipped(ValidIO(new MicroOp)) 381 val isInterrupt = Input(Bool()) 382 val memExceptionVAddr = Input(UInt(VAddrBits.W)) 383 val trapTarget = Output(UInt(VAddrBits.W)) 384 val externalInterrupt = new ExternalInterruptIO 385 val interrupt = Output(Bool()) 386} 387 388class ExceptionInfo(implicit p: Parameters) extends XSBundle { 389 val uop = new MicroOp 390 val isInterrupt = Bool() 391} 392 393class RoqCommitInfo(implicit p: Parameters) extends XSBundle { 394 val ldest = UInt(5.W) 395 val rfWen = Bool() 396 val fpWen = Bool() 397 val wflags = Bool() 398 val commitType = CommitType() 399 val pdest = UInt(PhyRegIdxWidth.W) 400 val old_pdest = UInt(PhyRegIdxWidth.W) 401 val ftqIdx = new FtqPtr 402 val ftqOffset = UInt(log2Up(PredictWidth).W) 403 404 // these should be optimized for synthesis verilog 405 val pc = UInt(VAddrBits.W) 406} 407 408class RoqCommitIO(implicit p: Parameters) extends XSBundle { 409 val isWalk = Output(Bool()) 410 val valid = Vec(CommitWidth, Output(Bool())) 411 val info = Vec(CommitWidth, Output(new RoqCommitInfo)) 412 413 def hasWalkInstr = isWalk && valid.asUInt.orR 414 415 def hasCommitInstr = !isWalk && valid.asUInt.orR 416} 417 418class RSFeedback(implicit p: Parameters) extends XSBundle { 419 val rsIdx = UInt(log2Up(IssQueSize).W) 420 val hit = Bool() 421 val flushState = Bool() 422 val sourceType = RSFeedbackType() 423} 424 425class FrontendToBackendIO(implicit p: Parameters) extends XSBundle { 426 // to backend end 427 val cfVec = Vec(DecodeWidth, DecoupledIO(new CtrlFlow)) 428 val fetchInfo = DecoupledIO(new FtqEntry) 429 // from backend 430 val redirect_cfiUpdate = Flipped(ValidIO(new Redirect)) 431 val commit_cfiUpdate = Flipped(ValidIO(new FtqEntry)) 432 val ftqEnqPtr = Input(new FtqPtr) 433 val ftqLeftOne = Input(Bool()) 434} 435 436class TlbCsrBundle(implicit p: Parameters) extends XSBundle { 437 val satp = new Bundle { 438 val mode = UInt(4.W) // TODO: may change number to parameter 439 val asid = UInt(16.W) 440 val ppn = UInt(44.W) // just use PAddrBits - 3 - vpnnLen 441 } 442 val priv = new Bundle { 443 val mxr = Bool() 444 val sum = Bool() 445 val imode = UInt(2.W) 446 val dmode = UInt(2.W) 447 } 448 449 override def toPrintable: Printable = { 450 p"Satp mode:0x${Hexadecimal(satp.mode)} asid:0x${Hexadecimal(satp.asid)} ppn:0x${Hexadecimal(satp.ppn)} " + 451 p"Priv mxr:${priv.mxr} sum:${priv.sum} imode:${priv.imode} dmode:${priv.dmode}" 452 } 453} 454 455class SfenceBundle(implicit p: Parameters) extends XSBundle { 456 val valid = Bool() 457 val bits = new Bundle { 458 val rs1 = Bool() 459 val rs2 = Bool() 460 val addr = UInt(VAddrBits.W) 461 } 462 463 override def toPrintable: Printable = { 464 p"valid:0x${Hexadecimal(valid)} rs1:${bits.rs1} rs2:${bits.rs2} addr:${Hexadecimal(bits.addr)}" 465 } 466} 467 468class WaitTableUpdateReq(implicit p: Parameters) extends XSBundle with WaitTableParameters { 469 val valid = Bool() 470 val waddr = UInt(WaitTableAddrWidth.W) 471 val wdata = Bool() // true.B by default 472} 473 474class PerfInfoIO extends Bundle { 475 val clean = Input(Bool()) 476 val dump = Input(Bool()) 477} 478 479class CustomCSRCtrlIO(implicit p: Parameters) extends XSBundle { 480 // Prefetcher 481 val l1plus_pf_enable = Output(Bool()) 482 val l2_pf_enable = Output(Bool()) 483 // Labeled XiangShan 484 val dsid = Output(UInt(8.W)) // TODO: DsidWidth as parameter 485 // Load violation predictor 486 val lvpred_disable = Output(Bool()) 487 val no_spec_load = Output(Bool()) 488 val waittable_timeout = Output(UInt(5.W)) 489 // Branch predictor 490 val bp_ctrl = Output(new BPUCtrl) 491 // Memory Block 492 val sbuffer_threshold = Output(UInt(4.W)) 493 // Rename 494 val move_elim_enable = Output(Bool()) 495} 496