1package xiangshan 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan.backend.SelImm 6import xiangshan.backend.brq.BrqPtr 7import xiangshan.backend.rename.FreeListPtr 8import xiangshan.backend.roq.RoqPtr 9import xiangshan.backend.decode.{ImmUnion, XDecode} 10import xiangshan.mem.{LqPtr, SqPtr} 11import xiangshan.frontend.PreDecodeInfo 12import xiangshan.frontend.HasBPUParameter 13import xiangshan.frontend.HasTageParameter 14import xiangshan.frontend.HasIFUConst 15import xiangshan.frontend.GlobalHistory 16import xiangshan.frontend.RASEntry 17import utils._ 18 19import scala.math.max 20import Chisel.experimental.chiselName 21 22// Fetch FetchWidth x 32-bit insts from Icache 23class FetchPacket extends XSBundle { 24 val instrs = Vec(PredictWidth, UInt(32.W)) 25 val mask = UInt(PredictWidth.W) 26 val pdmask = UInt(PredictWidth.W) 27 // val pc = UInt(VAddrBits.W) 28 val pc = Vec(PredictWidth, UInt(VAddrBits.W)) 29 val pnpc = Vec(PredictWidth, UInt(VAddrBits.W)) 30 val bpuMeta = Vec(PredictWidth, new BpuMeta) 31 val pd = Vec(PredictWidth, new PreDecodeInfo) 32 val ipf = Bool() 33 val acf = Bool() 34 val crossPageIPFFix = Bool() 35 val predTaken = Bool() 36} 37 38class ValidUndirectioned[T <: Data](gen: T) extends Bundle { 39 val valid = Bool() 40 val bits = gen.cloneType.asInstanceOf[T] 41 override def cloneType = new ValidUndirectioned(gen).asInstanceOf[this.type] 42} 43 44object ValidUndirectioned { 45 def apply[T <: Data](gen: T) = { 46 new ValidUndirectioned[T](gen) 47 } 48} 49 50class SCMeta(val useSC: Boolean) extends XSBundle with HasTageParameter { 51 def maxVal = 8 * ((1 << TageCtrBits) - 1) + SCTableInfo.map{case (_,cb,_) => (1 << cb) - 1}.reduce(_+_) 52 def minVal = -(8 * (1 << TageCtrBits) + SCTableInfo.map{case (_,cb,_) => 1 << cb}.reduce(_+_)) 53 def sumCtrBits = max(log2Ceil(-minVal), log2Ceil(maxVal+1)) + 1 54 val tageTaken = if (useSC) Bool() else UInt(0.W) 55 val scUsed = if (useSC) Bool() else UInt(0.W) 56 val scPred = if (useSC) Bool() else UInt(0.W) 57 // Suppose ctrbits of all tables are identical 58 val ctrs = if (useSC) Vec(SCNTables, SInt(SCCtrBits.W)) else Vec(SCNTables, SInt(0.W)) 59 val sumAbs = if (useSC) UInt(sumCtrBits.W) else UInt(0.W) 60} 61 62class TageMeta extends XSBundle with HasTageParameter { 63 val provider = ValidUndirectioned(UInt(log2Ceil(TageNTables).W)) 64 val altDiffers = Bool() 65 val providerU = UInt(2.W) 66 val providerCtr = UInt(3.W) 67 val allocate = ValidUndirectioned(UInt(log2Ceil(TageNTables).W)) 68 val taken = Bool() 69 val scMeta = new SCMeta(EnableSC) 70} 71 72@chiselName 73class BranchPrediction extends XSBundle with HasIFUConst { 74 // val redirect = Bool() 75 val takens = UInt(PredictWidth.W) 76 // val jmpIdx = UInt(log2Up(PredictWidth).W) 77 val brMask = UInt(PredictWidth.W) 78 val jalMask = UInt(PredictWidth.W) 79 val targets = Vec(PredictWidth, UInt(VAddrBits.W)) 80 81 // marks the last 2 bytes of this fetch packet 82 // val endsAtTheEndOfFirstBank = Bool() 83 // val endsAtTheEndOfLastBank = Bool() 84 85 // half RVI could only start at the end of a packet 86 val hasHalfRVI = Bool() 87 88 89 // assumes that only one of the two conditions could be true 90 def lastHalfRVIMask = Cat(hasHalfRVI.asUInt, 0.U((PredictWidth-1).W)) 91 92 def lastHalfRVIClearMask = ~lastHalfRVIMask 93 // is taken from half RVI 94 def lastHalfRVITaken = takens(PredictWidth-1) && hasHalfRVI 95 96 def lastHalfRVIIdx = (PredictWidth-1).U 97 // should not be used if not lastHalfRVITaken 98 def lastHalfRVITarget = targets(PredictWidth-1) 99 100 def realTakens = takens & lastHalfRVIClearMask 101 def realBrMask = brMask & lastHalfRVIClearMask 102 def realJalMask = jalMask & lastHalfRVIClearMask 103 104 def brNotTakens = (~takens & realBrMask) 105 def sawNotTakenBr = VecInit((0 until PredictWidth).map(i => 106 (if (i == 0) false.B else ParallelORR(brNotTakens(i-1,0))))) 107 // def hasNotTakenBrs = (brNotTakens & LowerMaskFromLowest(realTakens)).orR 108 def unmaskedJmpIdx = ParallelPriorityEncoder(takens) 109 // if not taken before the half RVI inst 110 def saveHalfRVI = hasHalfRVI && !(ParallelORR(takens(PredictWidth-2,0))) 111 // could get PredictWidth-1 when only the first bank is valid 112 def jmpIdx = ParallelPriorityEncoder(realTakens) 113 // only used when taken 114 def target = { 115 val generator = new PriorityMuxGenerator[UInt] 116 generator.register(realTakens.asBools, targets, List.fill(PredictWidth)(None)) 117 generator() 118 } 119 def taken = ParallelORR(realTakens) 120 def takenOnBr = taken && ParallelPriorityMux(realTakens, realBrMask.asBools) 121 def hasNotTakenBrs = Mux(taken, ParallelPriorityMux(realTakens, sawNotTakenBr), ParallelORR(brNotTakens)) 122} 123 124class BpuMeta extends XSBundle with HasBPUParameter { 125 val ubtbWriteWay = UInt(log2Up(UBtbWays).W) 126 val ubtbHits = Bool() 127 val btbWriteWay = UInt(log2Up(BtbWays).W) 128 val btbHitJal = Bool() 129 val bimCtr = UInt(2.W) 130 val tageMeta = new TageMeta 131 val rasSp = UInt(log2Up(RasSize).W) 132 val rasTopCtr = UInt(8.W) 133 val rasToqAddr = UInt(VAddrBits.W) 134 val fetchIdx = UInt(log2Up(PredictWidth).W) 135 val specCnt = UInt(10.W) 136 // for global history 137 val predTaken = Bool() 138 val hist = new GlobalHistory 139 val predHist = new GlobalHistory 140 val sawNotTakenBranch = Bool() 141 142 val debug_ubtb_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W) 143 val debug_btb_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W) 144 val debug_tage_cycle = if (EnableBPUTimeRecord) UInt(64.W) else UInt(0.W) 145 146 val predictor = if (BPUDebug) UInt(log2Up(4).W) else UInt(0.W) // Mark which component this prediction comes from {ubtb, btb, tage, loopPredictor} 147 148 // def apply(histPtr: UInt, tageMeta: TageMeta, rasSp: UInt, rasTopCtr: UInt) = { 149 // this.histPtr := histPtr 150 // this.tageMeta := tageMeta 151 // this.rasSp := rasSp 152 // this.rasTopCtr := rasTopCtr 153 // this.asUInt 154 // } 155 def size = 0.U.asTypeOf(this).getWidth 156 def fromUInt(x: UInt) = x.asTypeOf(this) 157} 158 159class Predecode extends XSBundle with HasIFUConst { 160 val hasLastHalfRVI = Bool() 161 val mask = UInt(PredictWidth.W) 162 val lastHalf = Bool() 163 val pd = Vec(PredictWidth, (new PreDecodeInfo)) 164} 165 166class CfiUpdateInfo extends XSBundle with HasBPUParameter { 167 // from backend 168 val pc = UInt(VAddrBits.W) 169 val pnpc = UInt(VAddrBits.W) 170 val fetchIdx = UInt(log2Up(PredictWidth).W) 171 // frontend -> backend -> frontend 172 val pd = new PreDecodeInfo 173 val bpuMeta = new BpuMeta 174 175 // need pipeline update 176 val target = UInt(VAddrBits.W) 177 val brTarget = UInt(VAddrBits.W) 178 val taken = Bool() 179 val isMisPred = Bool() 180 val brTag = new BrqPtr 181 val isReplay = Bool() 182} 183 184// Dequeue DecodeWidth insts from Ibuffer 185class CtrlFlow extends XSBundle { 186 val instr = UInt(32.W) 187 val pc = UInt(VAddrBits.W) 188 val exceptionVec = ExceptionVec() 189 val intrVec = Vec(12, Bool()) 190 val brUpdate = new CfiUpdateInfo 191 val crossPageIPFFix = Bool() 192} 193 194class OfqEntry extends XSBundle { 195 // fetch pc, pc of each inst could be generated by concatenation 196 val pc = UInt(VAddrBits.W) 197 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 metas = Vec(PredictWidth, new BpuMeta) 204 205 val brMask = UInt(PredictWidth.W) 206 val jalMask = UInt(PredictWidth.W) 207 208 val mispred = UInt(PredictWidth.W) 209} 210 211 212 213class FPUCtrlSignals extends XSBundle { 214 val isAddSub = Bool() // swap23 215 val typeTagIn = UInt(2.W) 216 val typeTagOut = UInt(2.W) 217 val fromInt = Bool() 218 val wflags = Bool() 219 val fpWen = Bool() 220 val fmaCmd = UInt(2.W) 221 val div = Bool() 222 val sqrt = Bool() 223 val fcvt = Bool() 224 val typ = UInt(2.W) 225 val fmt = UInt(2.W) 226 val ren3 = Bool() //TODO: remove SrcType.fp 227} 228 229// Decode DecodeWidth insts at Decode Stage 230class CtrlSignals extends XSBundle { 231 val src1Type, src2Type, src3Type = SrcType() 232 val lsrc1, lsrc2, lsrc3 = UInt(5.W) 233 val ldest = UInt(5.W) 234 val fuType = FuType() 235 val fuOpType = FuOpType() 236 val rfWen = Bool() 237 val fpWen = Bool() 238 val isXSTrap = Bool() 239 val noSpecExec = Bool() // wait forward 240 val blockBackward = Bool() // block backward 241 val flushPipe = Bool() // This inst will flush all the pipe when commit, like exception but can commit 242 val isRVF = Bool() 243 val selImm = SelImm() 244 val imm = UInt(ImmUnion.maxLen.W) 245 val commitType = CommitType() 246 val fpu = new FPUCtrlSignals 247 248 def decode(inst: UInt, table: Iterable[(BitPat, List[BitPat])]) = { 249 val decoder = freechips.rocketchip.rocket.DecodeLogic(inst, XDecode.decodeDefault, table) 250 val signals = 251 Seq(src1Type, src2Type, src3Type, fuType, fuOpType, rfWen, fpWen, 252 isXSTrap, noSpecExec, blockBackward, flushPipe, isRVF, selImm) 253 signals zip decoder map { case(s, d) => s := d } 254 commitType := DontCare 255 this 256 } 257} 258 259class CfCtrl extends XSBundle { 260 val cf = new CtrlFlow 261 val ctrl = new CtrlSignals 262 val brTag = new BrqPtr 263} 264 265class PerfDebugInfo extends XSBundle { 266 // val fetchTime = UInt(64.W) 267 val renameTime = UInt(64.W) 268 val dispatchTime = UInt(64.W) 269 val issueTime = UInt(64.W) 270 val writebackTime = UInt(64.W) 271 // val commitTime = UInt(64.W) 272} 273 274// Separate LSQ 275class LSIdx extends XSBundle { 276 val lqIdx = new LqPtr 277 val sqIdx = new SqPtr 278} 279 280// CfCtrl -> MicroOp at Rename Stage 281class MicroOp extends CfCtrl { 282 val psrc1, psrc2, psrc3, pdest, old_pdest = UInt(PhyRegIdxWidth.W) 283 val src1State, src2State, src3State = SrcState() 284 val roqIdx = new RoqPtr 285 val lqIdx = new LqPtr 286 val sqIdx = new SqPtr 287 val diffTestDebugLrScValid = Bool() 288 val debugInfo = new PerfDebugInfo 289} 290 291class Redirect extends XSBundle { 292 val roqIdx = new RoqPtr 293 val level = RedirectLevel() 294 val interrupt = Bool() 295 val pc = UInt(VAddrBits.W) 296 val target = UInt(VAddrBits.W) 297 val brTag = new BrqPtr 298 299 def isUnconditional() = RedirectLevel.isUnconditional(level) 300 def flushItself() = RedirectLevel.flushItself(level) 301 def isException() = RedirectLevel.isException(level) 302} 303 304class Dp1ToDp2IO extends XSBundle { 305 val intDqToDp2 = Vec(dpParams.IntDqDeqWidth, DecoupledIO(new MicroOp)) 306 val fpDqToDp2 = Vec(dpParams.FpDqDeqWidth, DecoupledIO(new MicroOp)) 307 val lsDqToDp2 = Vec(dpParams.LsDqDeqWidth, DecoupledIO(new MicroOp)) 308} 309 310class ReplayPregReq extends XSBundle { 311 // NOTE: set isInt and isFp both to 'false' when invalid 312 val isInt = Bool() 313 val isFp = Bool() 314 val preg = UInt(PhyRegIdxWidth.W) 315} 316 317class DebugBundle extends XSBundle{ 318 val isMMIO = Bool() 319 val isPerfCnt = Bool() 320} 321 322class ExuInput extends XSBundle { 323 val uop = new MicroOp 324 val src1, src2, src3 = UInt((XLEN+1).W) 325} 326 327class ExuOutput extends XSBundle { 328 val uop = new MicroOp 329 val data = UInt((XLEN+1).W) 330 val fflags = UInt(5.W) 331 val redirectValid = Bool() 332 val redirect = new Redirect 333 val brUpdate = new CfiUpdateInfo 334 val debug = new DebugBundle 335} 336 337class ExternalInterruptIO extends XSBundle { 338 val mtip = Input(Bool()) 339 val msip = Input(Bool()) 340 val meip = Input(Bool()) 341} 342 343class CSRSpecialIO extends XSBundle { 344 val exception = Flipped(ValidIO(new MicroOp)) 345 val isInterrupt = Input(Bool()) 346 val memExceptionVAddr = Input(UInt(VAddrBits.W)) 347 val trapTarget = Output(UInt(VAddrBits.W)) 348 val externalInterrupt = new ExternalInterruptIO 349 val interrupt = Output(Bool()) 350} 351 352class RoqCommitInfo extends XSBundle { 353 val ldest = UInt(5.W) 354 val rfWen = Bool() 355 val fpWen = Bool() 356 val wflags = Bool() 357 val commitType = CommitType() 358 val pdest = UInt(PhyRegIdxWidth.W) 359 val old_pdest = UInt(PhyRegIdxWidth.W) 360 val lqIdx = new LqPtr 361 val sqIdx = new SqPtr 362 363 // these should be optimized for synthesis verilog 364 val pc = UInt(VAddrBits.W) 365} 366 367class RoqCommitIO extends XSBundle { 368 val isWalk = Output(Bool()) 369 val valid = Vec(CommitWidth, Output(Bool())) 370 val info = Vec(CommitWidth, Output(new RoqCommitInfo)) 371 372 def hasWalkInstr = isWalk && valid.asUInt.orR 373 def hasCommitInstr = !isWalk && valid.asUInt.orR 374} 375 376class TlbFeedback extends XSBundle { 377 val roqIdx = new RoqPtr 378 val hit = Bool() 379} 380 381class FrontendToBackendIO extends XSBundle { 382 // to backend end 383 val cfVec = Vec(DecodeWidth, DecoupledIO(new CtrlFlow)) 384 // from backend 385 val redirect = Flipped(ValidIO(UInt(VAddrBits.W))) 386 // val cfiUpdateInfo = Flipped(ValidIO(new CfiUpdateInfo)) 387 val cfiUpdateInfo = Flipped(ValidIO(new CfiUpdateInfo)) 388} 389 390class TlbCsrBundle extends XSBundle { 391 val satp = new Bundle { 392 val mode = UInt(4.W) // TODO: may change number to parameter 393 val asid = UInt(16.W) 394 val ppn = UInt(44.W) // just use PAddrBits - 3 - vpnnLen 395 } 396 val priv = new Bundle { 397 val mxr = Bool() 398 val sum = Bool() 399 val imode = UInt(2.W) 400 val dmode = UInt(2.W) 401 } 402 403 override def toPrintable: Printable = { 404 p"Satp mode:0x${Hexadecimal(satp.mode)} asid:0x${Hexadecimal(satp.asid)} ppn:0x${Hexadecimal(satp.ppn)} " + 405 p"Priv mxr:${priv.mxr} sum:${priv.sum} imode:${priv.imode} dmode:${priv.dmode}" 406 } 407} 408 409class SfenceBundle extends XSBundle { 410 val valid = Bool() 411 val bits = new Bundle { 412 val rs1 = Bool() 413 val rs2 = Bool() 414 val addr = UInt(VAddrBits.W) 415 } 416 417 override def toPrintable: Printable = { 418 p"valid:0x${Hexadecimal(valid)} rs1:${bits.rs1} rs2:${bits.rs2} addr:${Hexadecimal(bits.addr)}" 419 } 420} 421