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