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