1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.ExcitingUtils.{ConnectionType, Debug} 5import chisel3.util._ 6import utils._ 7import xiangshan._ 8import xiangshan.backend._ 9import xiangshan.backend.fu.util._ 10import utils.XSDebug 11 12object hartId extends (() => Int) { 13 var x = 0 14 def apply(): Int = { 15 x = x + 1 16 x-1 17 } 18} 19 20trait HasExceptionNO { 21 def instrAddrMisaligned = 0 22 def instrAccessFault = 1 23 def illegalInstr = 2 24 def breakPoint = 3 25 def loadAddrMisaligned = 4 26 def loadAccessFault = 5 27 def storeAddrMisaligned = 6 28 def storeAccessFault = 7 29 def ecallU = 8 30 def ecallS = 9 31 def ecallM = 11 32 def instrPageFault = 12 33 def loadPageFault = 13 34 def storePageFault = 15 35 36 val ExcPriority = Seq( 37 breakPoint, // TODO: different BP has different priority 38 instrPageFault, 39 instrAccessFault, 40 illegalInstr, 41 instrAddrMisaligned, 42 ecallM, ecallS, ecallU, 43 storePageFault, 44 loadPageFault, 45 storeAccessFault, 46 loadAccessFault, 47 storeAddrMisaligned, 48 loadAddrMisaligned 49 ) 50} 51 52class FpuCsrIO extends XSBundle { 53 val fflags = Output(Valid(UInt(5.W))) 54 val isIllegal = Output(Bool()) 55 val dirty_fs = Output(Bool()) 56 val frm = Input(UInt(3.W)) 57} 58 59 60class PerfCounterIO extends XSBundle { 61 val retiredInstr = Input(UInt(3.W)) 62 val value = Input(UInt(XLEN.W)) 63} 64 65class CSR extends FunctionUnit with HasCSRConst 66{ 67 val csrio = IO(new Bundle { 68 // output (for func === CSROpType.jmp) 69 val redirectOut = ValidIO(UInt(VAddrBits.W)) 70 val perf = new PerfCounterIO 71 val isPerfCnt = Output(Bool()) 72 // to FPU 73 val fpu = Flipped(new FpuCsrIO) 74 // from rob 75 val exception = Flipped(ValidIO(new MicroOp)) 76 val isInterrupt = Input(Bool()) 77 // to ROB 78 val trapTarget = Output(UInt(VAddrBits.W)) 79 val interrupt = Output(Bool()) 80 // from LSQ 81 val memExceptionVAddr = Input(UInt(VAddrBits.W)) 82 // from outside cpu,externalInterrupt 83 val externalInterrupt = new ExternalInterruptIO 84 // TLB 85 val tlb = Output(new TlbCsrBundle) 86 }) 87 88 val cfIn = io.in.bits.uop.cf 89 val cfOut = Wire(new CtrlFlow) 90 cfOut := cfIn 91 val flushPipe = Wire(Bool()) 92 93 val (valid, src1, src2, func) = ( 94 io.in.valid, 95 io.in.bits.src(0), 96 io.in.bits.uop.ctrl.imm, 97 io.in.bits.uop.ctrl.fuOpType 98 ) 99 100 // CSR define 101 102 class Priv extends Bundle { 103 val m = Output(Bool()) 104 val h = Output(Bool()) 105 val s = Output(Bool()) 106 val u = Output(Bool()) 107 } 108 109 val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U) 110 111 class MstatusStruct extends Bundle { 112 val sd = Output(UInt(1.W)) 113 114 val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null 115 val sxl = if (XLEN == 64) Output(UInt(2.W)) else null 116 val uxl = if (XLEN == 64) Output(UInt(2.W)) else null 117 val pad0 = if (XLEN == 64) Output(UInt(9.W)) else Output(UInt(8.W)) 118 119 val tsr = Output(UInt(1.W)) 120 val tw = Output(UInt(1.W)) 121 val tvm = Output(UInt(1.W)) 122 val mxr = Output(UInt(1.W)) 123 val sum = Output(UInt(1.W)) 124 val mprv = Output(UInt(1.W)) 125 val xs = Output(UInt(2.W)) 126 val fs = Output(UInt(2.W)) 127 val mpp = Output(UInt(2.W)) 128 val hpp = Output(UInt(2.W)) 129 val spp = Output(UInt(1.W)) 130 val pie = new Priv 131 val ie = new Priv 132 assert(this.getWidth == XLEN) 133 } 134 135 class SatpStruct extends Bundle { 136 val mode = UInt(4.W) 137 val asid = UInt(16.W) 138 val ppn = UInt(44.W) 139 } 140 141 class Interrupt extends Bundle { 142 val e = new Priv 143 val t = new Priv 144 val s = new Priv 145 } 146 147 // Machine-Level CSRs 148 149 val mtvec = RegInit(UInt(XLEN.W), 0.U) 150 val mcounteren = RegInit(UInt(XLEN.W), 0.U) 151 val mcause = RegInit(UInt(XLEN.W), 0.U) 152 val mtval = RegInit(UInt(XLEN.W), 0.U) 153 val mepc = Reg(UInt(XLEN.W)) 154 155 val mie = RegInit(0.U(XLEN.W)) 156 val mipWire = WireInit(0.U.asTypeOf(new Interrupt)) 157 val mipReg = RegInit(0.U.asTypeOf(new Interrupt).asUInt) 158 val mipFixMask = GenMask(9) | GenMask(5) | GenMask(1) 159 val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt) 160 161 def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}.asUInt() 162 def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}.asUInt() 163 var extList = List('a', 's', 'i', 'u') 164 if (HasMExtension) { extList = extList :+ 'm' } 165 if (HasCExtension) { extList = extList :+ 'c' } 166 if (HasFPU) { extList = extList ++ List('f', 'd') } 167 val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U 168 val misa = RegInit(UInt(XLEN.W), misaInitVal) 169 170 // MXL = 2 | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101 171 // (XLEN-1, XLEN-2) | |(25, 0) ZY XWVU TSRQ PONM LKJI HGFE DCBA 172 173 val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation 174 val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented 175 val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation 176 val mhartNo = hartId() 177 val mhartid = RegInit(UInt(XLEN.W), mhartNo.asUInt) // the hardware thread running the code 178 val mstatus = RegInit(UInt(XLEN.W), "h00001800".U) // another option: "h8000c0100".U 179 180 // mstatus Value Table 181 // | sd | 182 // | pad1 | 183 // | sxl | hardlinked to 10, use 00 to pass xv6 test 184 // | uxl | hardlinked to 00 185 // | pad0 | 186 // | tsr | 187 // | tw | 188 // | tvm | 189 // | mxr | 190 // | sum | 191 // | mprv | 192 // | xs | 00 | 193 // | fs | 00 | 194 // | mpp | 00 | 195 // | hpp | 00 | 196 // | spp | 0 | 197 // | pie | 0000 | pie.h is used as UBE 198 // | ie | 0000 | uie hardlinked to 0, as N ext is not implemented 199 200 val mstatusStruct = mstatus.asTypeOf(new MstatusStruct) 201 def mstatusUpdateSideEffect(mstatus: UInt): UInt = { 202 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 203 val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0)) 204 mstatusNew 205 } 206 207 val mstatusMask = (~ZeroExt(( 208 GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) | 209 GenMask(37) | // MBE 210 GenMask(36) | // SBE 211 GenMask(6) // UBE 212 ), 64)).asUInt() 213 214 val medeleg = RegInit(UInt(XLEN.W), 0.U) 215 val mideleg = RegInit(UInt(XLEN.W), 0.U) 216 val mscratch = RegInit(UInt(XLEN.W), 0.U) 217 218 val pmpcfg0 = RegInit(UInt(XLEN.W), 0.U) 219 val pmpcfg1 = RegInit(UInt(XLEN.W), 0.U) 220 val pmpcfg2 = RegInit(UInt(XLEN.W), 0.U) 221 val pmpcfg3 = RegInit(UInt(XLEN.W), 0.U) 222 val pmpaddr0 = RegInit(UInt(XLEN.W), 0.U) 223 val pmpaddr1 = RegInit(UInt(XLEN.W), 0.U) 224 val pmpaddr2 = RegInit(UInt(XLEN.W), 0.U) 225 val pmpaddr3 = RegInit(UInt(XLEN.W), 0.U) 226 227 // Superviser-Level CSRs 228 229 // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U) 230 val sstatusWmask = "hc6122".U 231 // Sstatus Write Mask 232 // ------------------------------------------------------- 233 // 19 9 5 2 234 // 0 1100 0000 0001 0010 0010 235 // 0 c 0 1 2 2 236 // ------------------------------------------------------- 237 val sstatusRmask = sstatusWmask | "h8000000300018000".U 238 // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32)) 239 val stvec = RegInit(UInt(XLEN.W), 0.U) 240 // val sie = RegInit(0.U(XLEN.W)) 241 val sieMask = "h222".U & mideleg 242 val sipMask = "h222".U & mideleg 243 val satp = RegInit(0.U(XLEN.W)) 244 // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug 245 val satpMask = "h80000fffffffffff".U // disable asid, mode can only be 8 / 0 246 val sepc = RegInit(UInt(XLEN.W), 0.U) 247 val scause = RegInit(UInt(XLEN.W), 0.U) 248 val stval = Reg(UInt(XLEN.W)) 249 val sscratch = RegInit(UInt(XLEN.W), 0.U) 250 val scounteren = RegInit(UInt(XLEN.W), 0.U) 251 252 val tlbBundle = Wire(new TlbCsrBundle) 253 tlbBundle.satp := satp.asTypeOf(new SatpStruct) 254 csrio.tlb := tlbBundle 255 256 // User-Level CSRs 257 val uepc = Reg(UInt(XLEN.W)) 258 259 // fcsr 260 class FcsrStruct extends Bundle { 261 val reserved = UInt((XLEN-3-5).W) 262 val frm = UInt(3.W) 263 val fflags = UInt(5.W) 264 assert(this.getWidth == XLEN) 265 } 266 val fcsr = RegInit(0.U(XLEN.W)) 267 // set mstatus->sd and mstatus->fs when true 268 val csrw_dirty_fp_state = WireInit(false.B) 269 270 def frm_wfn(wdata: UInt): UInt = { 271 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 272 csrw_dirty_fp_state := true.B 273 fcsrOld.frm := wdata(2,0) 274 fcsrOld.asUInt() 275 } 276 def frm_rfn(rdata: UInt): UInt = rdata(7,5) 277 278 def fflags_wfn(update: Boolean)(wdata: UInt): UInt = { 279 val fcsrOld = fcsr.asTypeOf(new FcsrStruct) 280 val fcsrNew = WireInit(fcsrOld) 281 csrw_dirty_fp_state := true.B 282 if (update) { 283 fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags 284 } else { 285 fcsrNew.fflags := wdata(4,0) 286 } 287 fcsrNew.asUInt() 288 } 289 def fflags_rfn(rdata:UInt): UInt = rdata(4,0) 290 291 def fcsr_wfn(wdata: UInt): UInt = { 292 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 293 csrw_dirty_fp_state := true.B 294 Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags) 295 } 296 297 val fcsrMapping = Map( 298 MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn), 299 MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn), 300 MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn) 301 ) 302 303 // Atom LR/SC Control Bits 304 // val setLr = WireInit(Bool(), false.B) 305 // val setLrVal = WireInit(Bool(), false.B) 306 // val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check 307 // val lr = RegInit(Bool(), false.B) 308 // val lrAddr = RegInit(UInt(AddrBits.W), 0.U) 309 // 310 // when (setLr) { 311 // lr := setLrVal 312 // lrAddr := setLrAddr 313 // } 314 315 // Hart Priviledge Mode 316 val priviledgeMode = RegInit(UInt(2.W), ModeM) 317 318 // Emu perfcnt 319 val hasEmuPerfCnt = !env.FPGAPlatform 320 val nrEmuPerfCnts = if (hasEmuPerfCnt) 0x80 else 0x3 321 322 val emuPerfCnts = List.fill(nrEmuPerfCnts)(RegInit(0.U(XLEN.W))) 323 val emuPerfCntCond = List.fill(nrEmuPerfCnts)(WireInit(false.B)) 324 (emuPerfCnts zip emuPerfCntCond).map { case (c, e) => when (e) { c := c + 1.U } } 325 326 val emuPerfCntsLoMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1000 + i, emuPerfCnts(i))) 327 val emuPerfCntsHiMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1080 + i, emuPerfCnts(i)(63, 32))) 328 println(s"CSR: hasEmuPerfCnt:${hasEmuPerfCnt}") 329 330 // Perf Counter 331 val nrPerfCnts = 29 // 3...31 332 val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W))) 333 val perfEvents = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W))) 334 val mcountinhibit = RegInit(0.U(XLEN.W)) 335 val mcycle = RegInit(0.U(XLEN.W)) 336 mcycle := mcycle + 1.U 337 val minstret = RegInit(0.U(XLEN.W)) 338 minstret := minstret + RegNext(csrio.perf.retiredInstr) 339 340 // CSR reg map 341 val basicPrivMapping = Map( 342 343 //--- User Trap Setup --- 344 // MaskedRegMap(Ustatus, ustatus), 345 // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable), 346 // MaskedRegMap(Utvec, utvec), 347 348 //--- User Trap Handling --- 349 // MaskedRegMap(Uscratch, uscratch), 350 // MaskedRegMap(Uepc, uepc), 351 // MaskedRegMap(Ucause, ucause), 352 // MaskedRegMap(Utval, utval), 353 // MaskedRegMap(Uip, uip), 354 355 //--- User Counter/Timers --- 356 // MaskedRegMap(Cycle, cycle), 357 // MaskedRegMap(Time, time), 358 // MaskedRegMap(Instret, instret), 359 360 //--- Supervisor Trap Setup --- 361 MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask), 362 // MaskedRegMap(Sedeleg, Sedeleg), 363 // MaskedRegMap(Sideleg, Sideleg), 364 MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask), 365 MaskedRegMap(Stvec, stvec), 366 MaskedRegMap(Scounteren, scounteren), 367 368 //--- Supervisor Trap Handling --- 369 MaskedRegMap(Sscratch, sscratch), 370 MaskedRegMap(Sepc, sepc), 371 MaskedRegMap(Scause, scause), 372 MaskedRegMap(Stval, stval), 373 MaskedRegMap(Sip, mip.asUInt, sipMask, MaskedRegMap.Unwritable, sipMask), 374 375 //--- Supervisor Protection and Translation --- 376 MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask), 377 378 //--- Machine Information Registers --- 379 MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable), 380 MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable), 381 MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable), 382 MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable), 383 384 //--- Machine Trap Setup --- 385 MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask), 386 MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable 387 MaskedRegMap(Medeleg, medeleg, "hf3ff".U), 388 MaskedRegMap(Mideleg, mideleg, "h222".U), 389 MaskedRegMap(Mie, mie), 390 MaskedRegMap(Mtvec, mtvec), 391 MaskedRegMap(Mcounteren, mcounteren), 392 393 //--- Machine Trap Handling --- 394 MaskedRegMap(Mscratch, mscratch), 395 MaskedRegMap(Mepc, mepc), 396 MaskedRegMap(Mcause, mcause), 397 MaskedRegMap(Mtval, mtval), 398 MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable), 399 ) 400 401 // PMP is unimplemented yet 402 val pmpMapping = Map( 403 MaskedRegMap(Pmpcfg0, pmpcfg0), 404 MaskedRegMap(Pmpcfg1, pmpcfg1), 405 MaskedRegMap(Pmpcfg2, pmpcfg2), 406 MaskedRegMap(Pmpcfg3, pmpcfg3), 407 MaskedRegMap(PmpaddrBase + 0, pmpaddr0), 408 MaskedRegMap(PmpaddrBase + 1, pmpaddr1), 409 MaskedRegMap(PmpaddrBase + 2, pmpaddr2), 410 MaskedRegMap(PmpaddrBase + 3, pmpaddr3) 411 ) 412 413 var perfCntMapping = Map( 414 MaskedRegMap(Mcountinhibit, mcountinhibit), 415 MaskedRegMap(Mcycle, mcycle), 416 MaskedRegMap(Minstret, minstret), 417 ) 418 val MhpmcounterStart = Mhpmcounter3 419 val MhpmeventStart = Mhpmevent3 420 for (i <- 0 until nrPerfCnts) { 421 perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i)) 422 perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i)) 423 } 424 425 val mapping = basicPrivMapping ++ 426 perfCntMapping ++ 427 pmpMapping ++ 428 emuPerfCntsLoMapping ++ 429 (if (XLEN == 32) emuPerfCntsHiMapping else Nil) ++ 430 (if (HasFPU) fcsrMapping else Nil) 431 432 val addr = src2(11, 0) 433 val csri = src2(16, 12) 434 val rdata = Wire(UInt(XLEN.W)) 435 val wdata = LookupTree(func, List( 436 CSROpType.wrt -> src1, 437 CSROpType.set -> (rdata | src1), 438 CSROpType.clr -> (rdata & (~src1).asUInt()), 439 CSROpType.wrti -> csri, 440 CSROpType.seti -> (rdata | csri), 441 CSROpType.clri -> (rdata & (~csri).asUInt()) 442 )) 443 444 csrio.isPerfCnt := (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U) 445 446 // satp wen check 447 val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U) 448 449 // general CSR wen check 450 val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode) 451 val permitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode) 452 // Writeable check is ingored. 453 // Currently, write to illegal csr addr will be ignored 454 MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata) 455 io.out.bits.data := rdata 456 io.out.bits.uop := io.in.bits.uop 457 io.out.bits.uop.cf := cfOut 458 io.out.bits.uop.ctrl.flushPipe := flushPipe 459 460 // Fix Mip/Sip write 461 val fixMapping = Map( 462 MaskedRegMap(Mip, mipReg.asUInt, mipFixMask), 463 MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask) 464 ) 465 val rdataDummy = Wire(UInt(XLEN.W)) 466 MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata) 467 468 when (csrio.fpu.fflags.valid) { 469 fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits) 470 } 471 // set fs and sd in mstatus 472 when (csrw_dirty_fp_state || csrio.fpu.dirty_fs) { 473 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 474 mstatusNew.fs := "b11".U 475 mstatusNew.sd := true.B 476 mstatus := mstatusNew.asUInt() 477 } 478 csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm 479 480 // CSR inst decode 481 val isEbreak = addr === privEbreak && func === CSROpType.jmp 482 val isEcall = addr === privEcall && func === CSROpType.jmp 483 val isMret = addr === privMret && func === CSROpType.jmp 484 val isSret = addr === privSret && func === CSROpType.jmp 485 val isUret = addr === privUret && func === CSROpType.jmp 486 487 XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func) 488 XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode) 489 490 // Illegal priviledged operation list 491 val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool 492 493 // Illegal priviledged instruction check 494 val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr) 495 val isIllegalAccess = !permitted 496 val isIllegalPrivOp = illegalSModeSret 497 498 // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) 499 // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex)) 500 // imem 501 // val imemPtev = true.B 502 // val imemPteu = true.B 503 // val imemPtex = true.B 504 // val imemReq = true.B 505 // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu) 506 // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex) 507 // assert(!hasInstrPageFault) 508 509 // dmem 510 // val dmemPtev = true.B 511 // val dmemPteu = true.B 512 // val dmemReq = true.B 513 // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu) 514 // val dmemIsStore = true.B 515 516 // val hasLoadPageFault = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed) 517 // val hasStorePageFault = dmemReq && dmemIsStore && !(dmemPermissionCheckPassed) 518 // assert(!hasLoadPageFault) 519 // assert(!hasStorePageFault) 520 521 //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet 522 tlbBundle.priv.mxr := mstatusStruct.mxr.asBool 523 tlbBundle.priv.sum := mstatusStruct.sum.asBool 524 tlbBundle.priv.imode := priviledgeMode 525 tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode) 526 527 // Branch control 528 val retTarget = Wire(UInt(VAddrBits.W)) 529 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 530 csrio.redirectOut.valid := valid && func === CSROpType.jmp && !isEcall 531 csrio.redirectOut.bits := retTarget 532 flushPipe := resetSatp 533 XSDebug(csrio.redirectOut.valid, "redirect to %x, pc=%x\n", csrio.redirectOut.bits, cfIn.pc) 534 535 retTarget := DontCare 536 // val illegalEret = TODO 537 538 when (valid && isMret) { 539 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 540 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 541 mstatusNew.ie.m := mstatusOld.pie.m 542 priviledgeMode := mstatusOld.mpp 543 mstatusNew.pie.m := true.B 544 mstatusNew.mpp := ModeU 545 mstatusNew.mprv := 0.U 546 mstatus := mstatusNew.asUInt 547 // lr := false.B 548 retTarget := mepc(VAddrBits-1, 0) 549 } 550 551 when (valid && isSret && !illegalSModeSret) { 552 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 553 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 554 mstatusNew.ie.s := mstatusOld.pie.s 555 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 556 mstatusNew.pie.s := true.B 557 mstatusNew.spp := ModeU 558 mstatus := mstatusNew.asUInt 559 mstatusNew.mprv := 0.U 560 // lr := false.B 561 retTarget := sepc(VAddrBits-1, 0) 562 } 563 564 when (valid && isUret) { 565 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 566 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 567 // mstatusNew.mpp.m := ModeU //TODO: add mode U 568 mstatusNew.ie.u := mstatusOld.pie.u 569 priviledgeMode := ModeU 570 mstatusNew.pie.u := true.B 571 mstatus := mstatusNew.asUInt 572 retTarget := uepc(VAddrBits-1, 0) 573 } 574 575 XSDebug(csrio.redirectOut.valid, 576 "Rediret %x isSret:%d retTarget:%x sepc:%x cfInpc:%x valid:%d\n", 577 csrio.redirectOut.bits, isSret, retTarget, sepc, cfIn.pc, valid 578 ) 579 580 io.in.ready := true.B 581 io.out.valid := valid 582 583 /** 584 * Exception and Intr 585 */ 586 val ideleg = (mideleg & mip.asUInt) 587 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 588 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 589 590 // send interrupt information to ROQ 591 val intrVecEnable = Wire(Vec(12, Bool())) 592 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 593 val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt 594 val intrBitSet = intrVec.orR() 595 csrio.interrupt := intrBitSet 596 mipWire.t.m := csrio.externalInterrupt.mtip 597 mipWire.s.m := csrio.externalInterrupt.msip 598 mipWire.e.m := csrio.externalInterrupt.meip 599 600 // interrupts 601 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 602 val raiseIntr = csrio.exception.valid && csrio.isInterrupt 603 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.cf.pc, intrNO) 604 605 // exceptions 606 val raiseException = csrio.exception.valid && !csrio.isInterrupt 607 val hasInstrPageFault = csrio.exception.bits.cf.exceptionVec(instrPageFault) && raiseException 608 val hasLoadPageFault = csrio.exception.bits.cf.exceptionVec(loadPageFault) && raiseException 609 val hasStorePageFault = csrio.exception.bits.cf.exceptionVec(storePageFault) && raiseException 610 val hasStoreAddrMisaligned = csrio.exception.bits.cf.exceptionVec(storeAddrMisaligned) && raiseException 611 val hasLoadAddrMisaligned = csrio.exception.bits.cf.exceptionVec(loadAddrMisaligned) && raiseException 612 613 val csrExceptionVec = Wire(Vec(16, Bool())) 614 csrExceptionVec.map(_ := false.B) 615 csrExceptionVec(breakPoint) := io.in.valid && isEbreak 616 csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall 617 csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall 618 csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall 619 // Trigger an illegal instr exception when: 620 // * unimplemented csr is being read/written 621 // * csr access is illegal 622 csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen 623 csrExceptionVec(loadPageFault) := hasLoadPageFault 624 csrExceptionVec(storePageFault) := hasStorePageFault 625 val iduExceptionVec = cfIn.exceptionVec 626 val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt() 627 cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) } 628 629 val raiseExceptionVec = csrio.exception.bits.cf.exceptionVec.asUInt() 630 val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum)) 631 val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO) 632 633 val raiseExceptionIntr = csrio.exception.valid 634 XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n", 635 csrio.exception.bits.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt 636 ) 637 XSDebug(raiseExceptionIntr, 638 "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", 639 csrio.exception.bits.cf.pc, 640 mstatus, 641 mideleg, 642 medeleg, 643 priviledgeMode 644 ) 645 646 // mtval write logic 647 val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN) 648 when (hasInstrPageFault || hasLoadPageFault || hasStorePageFault) { 649 val tval = Mux( 650 hasInstrPageFault, 651 Mux( 652 csrio.exception.bits.cf.crossPageIPFFix, 653 SignExt(csrio.exception.bits.cf.pc + 2.U, XLEN), 654 SignExt(csrio.exception.bits.cf.pc, XLEN) 655 ), 656 memExceptionAddr 657 ) 658 when (priviledgeMode === ModeM) { 659 mtval := tval 660 }.otherwise { 661 stval := tval 662 } 663 } 664 665 when (hasLoadAddrMisaligned || hasStoreAddrMisaligned) { 666 mtval := memExceptionAddr 667 } 668 669 val deleg = Mux(raiseIntr, mideleg , medeleg) 670 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 671 val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM) 672 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check 673 csrio.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0) 674 675 when (raiseExceptionIntr) { 676 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 677 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 678 679 when (delegS) { 680 scause := causeNO 681 sepc := SignExt(csrio.exception.bits.cf.pc, XLEN) 682 mstatusNew.spp := priviledgeMode 683 mstatusNew.pie.s := mstatusOld.ie.s 684 mstatusNew.ie.s := false.B 685 priviledgeMode := ModeS 686 when (tvalWen) { stval := 0.U } 687 }.otherwise { 688 mcause := causeNO 689 mepc := SignExt(csrio.exception.bits.cf.pc, XLEN) 690 mstatusNew.mpp := priviledgeMode 691 mstatusNew.pie.m := mstatusOld.ie.m 692 mstatusNew.ie.m := false.B 693 priviledgeMode := ModeM 694 when (tvalWen) { mtval := 0.U } 695 } 696 697 mstatus := mstatusNew.asUInt 698 } 699 700 XSDebug(raiseExceptionIntr && delegS, 701 "Red(%d, %x) raiseExcepIntr:%d isSret:%d sepc:%x delegs:%d deleg:%x\n", 702 csrio.redirectOut.valid, csrio.redirectOut.bits, raiseExceptionIntr, 703 isSret, sepc, delegS, deleg 704 ) 705 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc) 706 707 708 /** 709 * Emu Performance counters 710 */ 711 val emuPerfCntList = Map( 712 // "Mcycle" -> (0x1000, "perfCntCondMcycle" ), 713 // "Minstret" -> (0x1002, "perfCntCondMinstret" ), 714 "BpInstr" -> (0x1003, "perfCntCondBpInstr" ), 715 "BpRight" -> (0x1004, "perfCntCondBpRight" ), 716 "BpWrong" -> (0x1005, "perfCntCondBpWrong" ), 717 "BpBRight" -> (0x1006, "perfCntCondBpBRight"), 718 "BpBWrong" -> (0x1007, "perfCntCondBpBWrong"), 719 "BpJRight" -> (0x1008, "perfCntCondBpJRight"), 720 "BpJWrong" -> (0x1009, "perfCntCondBpJWrong"), 721 "BpIRight" -> (0x100a, "perfCntCondBpIRight"), 722 "BpIWrong" -> (0x100b, "perfCntCondBpIWrong"), 723 "BpRRight" -> (0x100c, "perfCntCondBpRRight"), 724 "BpRWrong" -> (0x100d, "perfCntCondBpRWrong"), 725 "RoqWalk" -> (0x100f, "perfCntCondRoqWalk" ), 726 "DTlbReqCnt0" -> (0x1015, "perfCntDtlbReqCnt0" ), 727 "DTlbReqCnt1" -> (0x1016, "perfCntDtlbReqCnt1" ), 728 "DTlbReqCnt2" -> (0x1017, "perfCntDtlbReqCnt2" ), 729 "DTlbReqCnt3" -> (0x1018, "perfCntDtlbReqCnt3" ), 730 "DTlbMissCnt0"-> (0x1019, "perfCntDtlbMissCnt0" ), 731 "DTlbMissCnt1"-> (0x1020, "perfCntDtlbMissCnt1" ), 732 "DTlbMissCnt2"-> (0x1021, "perfCntDtlbMissCnt2" ), 733 "DTlbMissCnt3"-> (0x1022, "perfCntDtlbMissCnt3" ), 734 "ITlbReqCnt0" -> (0x1023, "perfCntItlbReqCnt0" ), 735 "ITlbMissCnt0"-> (0x1024, "perfCntItlbMissCnt0" ), 736 "PtwReqCnt" -> (0x1025, "perfCntPtwReqCnt" ), 737 "PtwCycleCnt" -> (0x1026, "perfCntPtwCycleCnt" ), 738 "PtwL2TlbHit" -> (0x1027, "perfCntPtwL2TlbHit" ), 739 "ICacheReq" -> (0x1028, "perfCntIcacheReqCnt" ), 740 "ICacheMiss" -> (0x1029, "perfCntIcacheMissCnt") 741 // "FetchFromICache" -> (0x102a, "CntFetchFromICache"), 742 // "FetchFromLoopBuffer" -> (0x102b, "CntFetchFromLoopBuffer"), 743 // "ExitLoop1" -> (0x102c, "CntExitLoop1"), 744 // "ExitLoop2" -> (0x102d, "CntExitLoop2"), 745 // "ExitLoop3" -> (0x102e, "CntExitLoop3") 746 // "L2cacheHit" -> (0x1023, "perfCntCondL2cacheHit") 747 ) ++ ( 748 (0 until dcacheParameters.nMissEntries).map(i => 749 ("DCacheMissQueuePenalty" + Integer.toString(i, 10), (0x102d + i, "perfCntDCacheMissQueuePenaltyEntry" + Integer.toString(i, 10))) 750 ).toMap 751 ) ++ ( 752 (0 until icacheParameters.nMissEntries).map(i => 753 ("ICacheMissQueuePenalty" + Integer.toString(i, 10), (0x102d + dcacheParameters.nMissEntries + i, "perfCntICacheMissQueuePenaltyEntry" + Integer.toString(i, 10))) 754 ).toMap 755 ) ++ ( 756 (0 until l1plusPrefetcherParameters.nEntries).map(i => 757 ("L1+PrefetchPenalty" + Integer.toString(i, 10), (0x102d + dcacheParameters.nMissEntries + icacheParameters.nMissEntries + i, "perfCntL1plusPrefetchPenaltyEntry" + Integer.toString(i, 10))) 758 ).toMap 759 ) ++ ( 760 (0 until l2PrefetcherParameters.nEntries).map(i => 761 ("L2PrefetchPenalty" + Integer.toString(i, 10), (0x102d + dcacheParameters.nMissEntries + icacheParameters.nMissEntries + l1plusPrefetcherParameters.nEntries + i, "perfCntL2PrefetchPenaltyEntry" + Integer.toString(i, 10))) 762 ).toMap 763 ) 764 765 emuPerfCntList.foreach { 766 case (_, (address, boringId)) => 767 if (hasEmuPerfCnt) { 768 ExcitingUtils.addSink(emuPerfCntCond(address & 0x7f), boringId, ConnectionType.Perf) 769 } 770 // if (!hasEmuPerfCnt) { 771 // // do not enable perfcnts except for Mcycle and Minstret 772 // if (address != emuPerfCntList("Mcycle")._1 && address != emuPerfCntList("Minstret")._1) { 773 // perfCntCond(address & 0x7f) := false.B 774 // } 775 // } 776 } 777 778 val xstrap = WireInit(false.B) 779 if (!env.FPGAPlatform && EnableBPU) { 780 ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug) 781 } 782 def readWithScala(addr: Int): UInt = mapping(addr)._1 783 784 if (!env.FPGAPlatform) { 785 786 // display all perfcnt when nooptrap is executed 787 when (xstrap) { 788 printf("======== PerfCnt =========\n") 789 emuPerfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, _)) => 790 printf("%d <- " + str + "\n", readWithScala(address)) 791 } 792 } 793 794 val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U) 795 ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR") 796 ExcitingUtils.addSource(causeNO, "difftestCausefromCSR") 797 ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug) 798 ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug) 799 ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug) 800 ExcitingUtils.addSource(mepc, "difftestMepc", Debug) 801 ExcitingUtils.addSource(sepc, "difftestSepc", Debug) 802 ExcitingUtils.addSource(mtval, "difftestMtval", Debug) 803 ExcitingUtils.addSource(stval, "difftestStval", Debug) 804 ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug) 805 ExcitingUtils.addSource(stvec, "difftestStvec", Debug) 806 ExcitingUtils.addSource(mcause, "difftestMcause", Debug) 807 ExcitingUtils.addSource(scause, "difftestScause", Debug) 808 ExcitingUtils.addSource(satp, "difftestSatp", Debug) 809 ExcitingUtils.addSource(mipReg, "difftestMip", Debug) 810 ExcitingUtils.addSource(mie, "difftestMie", Debug) 811 ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug) 812 ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug) 813 ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug) 814 ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug) 815 } 816} 817