1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.backend.fu 18 19import chipsalliance.rocketchip.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import freechips.rocketchip.util._ 23import utils.MaskedRegMap.WritableMask 24import utils._ 25import xiangshan._ 26import xiangshan.backend._ 27import xiangshan.cache._ 28import xiangshan.frontend.BPUCtrl 29import xiangshan.backend.fu.util._ 30import difftest._ 31 32trait HasExceptionNO { 33 def instrAddrMisaligned = 0 34 def instrAccessFault = 1 35 def illegalInstr = 2 36 def breakPoint = 3 37 def loadAddrMisaligned = 4 38 def loadAccessFault = 5 39 def storeAddrMisaligned = 6 40 def storeAccessFault = 7 41 def ecallU = 8 42 def ecallS = 9 43 def ecallM = 11 44 def instrPageFault = 12 45 def loadPageFault = 13 46 def storePageFault = 15 47 48// def singleStep = 14 49 50 val ExcPriority = Seq( 51 breakPoint, // TODO: different BP has different priority 52 instrPageFault, 53 instrAccessFault, 54 illegalInstr, 55 instrAddrMisaligned, 56 ecallM, ecallS, ecallU, 57 storePageFault, 58 loadPageFault, 59 storeAccessFault, 60 loadAccessFault, 61 storeAddrMisaligned, 62 loadAddrMisaligned 63 ) 64 val frontendSet = List( 65 // instrAddrMisaligned, 66 instrAccessFault, 67 illegalInstr, 68 instrPageFault 69 ) 70 val csrSet = List( 71 illegalInstr, 72 breakPoint, 73 ecallU, 74 ecallS, 75 ecallM 76 ) 77 val loadUnitSet = List( 78 loadAddrMisaligned, 79 loadAccessFault, 80 loadPageFault 81 ) 82 val storeUnitSet = List( 83 storeAddrMisaligned, 84 storeAccessFault, 85 storePageFault 86 ) 87 val atomicsUnitSet = (loadUnitSet ++ storeUnitSet).distinct 88 val allPossibleSet = (frontendSet ++ csrSet ++ loadUnitSet ++ storeUnitSet).distinct 89 val csrWbCount = (0 until 16).map(i => if (csrSet.contains(i)) 1 else 0) 90 val loadWbCount = (0 until 16).map(i => if (loadUnitSet.contains(i)) 1 else 0) 91 val storeWbCount = (0 until 16).map(i => if (storeUnitSet.contains(i)) 1 else 0) 92 val atomicsWbCount = (0 until 16).map(i => if (atomicsUnitSet.contains(i)) 1 else 0) 93 val writebackCount = (0 until 16).map(i => csrWbCount(i) + atomicsWbCount(i) + loadWbCount(i) + 2 * storeWbCount(i)) 94 def partialSelect(vec: Vec[Bool], select: Seq[Int], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = { 95 if (dontCareBits) { 96 val new_vec = Wire(ExceptionVec()) 97 new_vec := DontCare 98 select.map(i => new_vec(i) := vec(i)) 99 return new_vec 100 } 101 else if (falseBits) { 102 val new_vec = Wire(ExceptionVec()) 103 new_vec.map(_ := false.B) 104 select.map(i => new_vec(i) := vec(i)) 105 return new_vec 106 } 107 else { 108 val new_vec = Wire(Vec(select.length, Bool())) 109 select.zipWithIndex.map{ case(s, i) => new_vec(i) := vec(s) } 110 return new_vec 111 } 112 } 113 def selectFrontend(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 114 partialSelect(vec, frontendSet, dontCareBits, falseBits) 115 def selectCSR(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 116 partialSelect(vec, csrSet, dontCareBits, falseBits) 117 def selectLoad(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 118 partialSelect(vec, loadUnitSet, dontCareBits, falseBits) 119 def selectStore(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 120 partialSelect(vec, storeUnitSet, dontCareBits, falseBits) 121 def selectAtomics(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 122 partialSelect(vec, atomicsUnitSet, dontCareBits, falseBits) 123 def selectAll(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 124 partialSelect(vec, allPossibleSet, dontCareBits, falseBits) 125} 126 127// Trigger Tdata1 bundles 128trait HasTriggerConst { 129 def I_Trigger = 0.U 130 def S_Trigger = 1.U 131 def L_Trigger = 2.U 132 def GenESL(triggerType: UInt) = Cat((triggerType === I_Trigger), (triggerType === I_Trigger), (triggerType === I_Trigger)) 133} 134 135class TdataBundle extends Bundle { 136 val hit = Bool() 137 val select = Bool() 138 val timing = Bool() 139// val size = UInt(4.W) // hardwire to 0 140 val action = Bool() 141 val chain = Bool() 142 val matchType = UInt(2.W) 143 val m = Bool() 144 val s = Bool() 145 val u = Bool() 146 val data = UInt(64.W) // tdata2 147} 148 149class FpuCsrIO extends Bundle { 150 val fflags = Output(Valid(UInt(5.W))) 151 val isIllegal = Output(Bool()) 152 val dirty_fs = Output(Bool()) 153 val frm = Input(UInt(3.W)) 154} 155 156 157class PerfCounterIO(implicit p: Parameters) extends XSBundle { 158 val perfEventsFrontend = (new PerfEventsBundle(numCSRPCntFrontend )) 159 val perfEventsCtrl = (new PerfEventsBundle(numCSRPCntCtrl )) 160 val perfEventsLsu = (new PerfEventsBundle(numCSRPCntLsu )) 161 val perfEventsHc = Vec(numPCntHc * coreParams.L2NBanks,(UInt(6.W))) 162 val retiredInstr = UInt(3.W) 163 val frontendInfo = new Bundle { 164 val ibufFull = Bool() 165 val bpuInfo = new Bundle { 166 val bpRight = UInt(XLEN.W) 167 val bpWrong = UInt(XLEN.W) 168 } 169 } 170 val ctrlInfo = new Bundle { 171 val robFull = Bool() 172 val intdqFull = Bool() 173 val fpdqFull = Bool() 174 val lsdqFull = Bool() 175 } 176 val memInfo = new Bundle { 177 val sqFull = Bool() 178 val lqFull = Bool() 179 val dcacheMSHRFull = Bool() 180 } 181 182 val cacheInfo = new Bundle { 183 val l2MSHRFull = Bool() 184 val l3MSHRFull = Bool() 185 val l2nAcquire = UInt(XLEN.W) 186 val l2nAcquireMiss = UInt(XLEN.W) 187 val l3nAcquire = UInt(XLEN.W) 188 val l3nAcquireMiss = UInt(XLEN.W) 189 } 190} 191 192class CSRFileIO(implicit p: Parameters) extends XSBundle { 193 val hartId = Input(UInt(8.W)) 194 // output (for func === CSROpType.jmp) 195 val perf = Input(new PerfCounterIO) 196 val isPerfCnt = Output(Bool()) 197 // to FPU 198 val fpu = Flipped(new FpuCsrIO) 199 // from rob 200 val exception = Flipped(ValidIO(new ExceptionInfo)) 201 // to ROB 202 val isXRet = Output(Bool()) 203 val trapTarget = Output(UInt(VAddrBits.W)) 204 val interrupt = Output(Bool()) 205 // from LSQ 206 val memExceptionVAddr = Input(UInt(VAddrBits.W)) 207 // from outside cpu,externalInterrupt 208 val externalInterrupt = new ExternalInterruptIO 209 // TLB 210 val tlb = Output(new TlbCsrBundle) 211 // Debug Mode 212 val singleStep = Output(Bool()) 213 val debugMode = Output(Bool()) 214 // to Fence to disable sfence 215 val disableSfence = Output(Bool()) 216 // Custom microarchiture ctrl signal 217 val customCtrl = Output(new CustomCSRCtrlIO) 218 // distributed csr write 219 val distributedUpdate = Flipped(new DistributedCSRUpdateReq) 220} 221 222class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMPMethod with PMAMethod with HasTriggerConst 223{ 224 val csrio = IO(new CSRFileIO) 225 226 val cfIn = io.in.bits.uop.cf 227 val cfOut = Wire(new CtrlFlow) 228 cfOut := cfIn 229 val flushPipe = Wire(Bool()) 230 231 val (valid, src1, src2, func) = ( 232 io.in.valid, 233 io.in.bits.src(0), 234 io.in.bits.uop.ctrl.imm, 235 io.in.bits.uop.ctrl.fuOpType 236 ) 237 238 // CSR define 239 240 class Priv extends Bundle { 241 val m = Output(Bool()) 242 val h = Output(Bool()) 243 val s = Output(Bool()) 244 val u = Output(Bool()) 245 } 246 247 val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U) 248 249 class DcsrStruct extends Bundle { 250 val xdebugver = Output(UInt(2.W)) 251 val zero4 = Output(UInt(2.W)) 252 val zero3 = Output(UInt(12.W)) 253 val ebreakm = Output(Bool()) 254 val ebreakh = Output(Bool()) 255 val ebreaks = Output(Bool()) 256 val ebreaku = Output(Bool()) 257 val zero2 = Output(Bool()) 258 val stopcycle = Output(Bool()) 259 val stoptime = Output(Bool()) 260 val cause = Output(UInt(3.W)) 261 val zero1 = Output(UInt(3.W)) 262 val step = Output(Bool()) 263 val prv = Output(UInt(2.W)) 264 } 265 266 class MstatusStruct extends Bundle { 267 val sd = Output(UInt(1.W)) 268 269 val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null 270 val sxl = if (XLEN == 64) Output(UInt(2.W)) else null 271 val uxl = if (XLEN == 64) Output(UInt(2.W)) else null 272 val pad0 = if (XLEN == 64) Output(UInt(9.W)) else Output(UInt(8.W)) 273 274 val tsr = Output(UInt(1.W)) 275 val tw = Output(UInt(1.W)) 276 val tvm = Output(UInt(1.W)) 277 val mxr = Output(UInt(1.W)) 278 val sum = Output(UInt(1.W)) 279 val mprv = Output(UInt(1.W)) 280 val xs = Output(UInt(2.W)) 281 val fs = Output(UInt(2.W)) 282 val mpp = Output(UInt(2.W)) 283 val hpp = Output(UInt(2.W)) 284 val spp = Output(UInt(1.W)) 285 val pie = new Priv 286 val ie = new Priv 287 assert(this.getWidth == XLEN) 288 } 289 290 class Interrupt extends Bundle { 291// val d = Output(Bool()) // Debug 292 val e = new Priv 293 val t = new Priv 294 val s = new Priv 295 } 296 297 // Debug CSRs 298 val dcsr = RegInit(UInt(32.W), 0x4000b010.U) 299 val dpc = Reg(UInt(64.W)) 300 val dscratch = Reg(UInt(64.W)) 301 val dscratch1 = Reg(UInt(64.W)) 302 val debugMode = RegInit(false.B) 303 val debugIntrEnable = RegInit(true.B) 304 csrio.debugMode := debugMode 305 306 val dpcPrev = RegNext(dpc) 307 XSDebug(dpcPrev =/= dpc, "Debug Mode: dpc is altered! Current is %x, previous is %x.", dpc, dpcPrev) 308 309 // dcsr value table 310 // | debugver | 0100 311 // | zero | 10 bits of 0 312 // | ebreakvs | 0 313 // | ebreakvu | 0 314 // | ebreakm | 1 if ebreak enters debug 315 // | zero | 0 316 // | ebreaks | 317 // | ebreaku | 318 // | stepie | 0 disable interrupts in singlestep 319 // | stopcount| stop counter, 0 320 // | stoptime | stop time, 0 321 // | cause | 3 bits read only 322 // | v | 0 323 // | mprven | 1 324 // | nmip | read only 325 // | step | 326 // | prv | 2 bits 327 328 val dcsrData = Wire(new DcsrStruct) 329 dcsrData := dcsr.asTypeOf(new DcsrStruct) 330 val dcsrMask = ZeroExt(GenMask(15) | GenMask(13, 11) | GenMask(2, 0), XLEN)// Dcsr write mask 331 def dcsrUpdateSideEffect(dcsr: UInt): UInt = { 332 val dcsrOld = WireInit(dcsr.asTypeOf(new DcsrStruct)) 333 val dcsrNew = dcsr | (dcsrOld.prv(0) | dcsrOld.prv(1)).asUInt // turn 10 priv into 11 334 dcsrNew 335 } 336 csrio.singleStep := dcsrData.step 337 338 // Trigger CSRs 339 340 val tdata1_function = Map( 341 0.U -> (true, I_Trigger), 1.U -> (false, I_Trigger), 342 2.U -> (true, S_Trigger), 3.U -> (false, S_Trigger), 343 4.U -> (true, L_Trigger), 5.U -> (false, L_Trigger), 344 6.U -> (true, I_Trigger), 7.U -> (false, S_Trigger), 345 8.U -> (true, I_Trigger), 9.U -> (false, L_Trigger) 346 ).withDefaultValue((false, I_Trigger)) 347 val tdata1Phy = RegInit(VecInit(List.fill(10) {0.U(64.W).asTypeOf(new TdataBundle)})) 348 val tdata2Phy = Reg(Vec(10, UInt(64.W))) 349 val tselectPhy = RegInit(0.U(4.W)) 350 val tDummy = WireInit(0.U(64.W)) 351 val tControlPhy = RegInit(0.U(64.W)) 352 def ReadTdata1(rdata: UInt) = { 353 val tdata1 = tdata1Phy(tselectPhy) 354 Cat( 355 2.U(4.W), // type, hardwired 356 0.U(1.W), // dmode, hardwired 357 0.U(6.W), // maskmax, hardwired to 0 because we don not support 358 1.U(2.W), // sizehi, hardwired 359 tdata1.hit, 360 tdata1.select, // select 361 tdata1.timing, 362 0.U(2.W), // sizelo 363 0.U(3.W), tdata1.action, // action, 0 is breakpoint 1 is enter debug 364 tdata1.chain, 365 0.U(2.W), tdata1.matchType, 366 tdata1.m, false.B, tdata1.s, tdata1.u, 367 GenESL(tdata1_function(tselectPhy)._2) 368 ) 369 } 370 def WriteTdata1(wdata: UInt) = { 371 val tdata1_new = WireInit(tdata1Phy(tselectPhy)) 372 tdata1_new.hit := wdata(20) 373 tdata1_new.select := wdata(19) 374 tdata1_new.timing := wdata(18) 375 tdata1_new.action := wdata(12) 376 tdata1_new.chain := tdata1_function(tselectPhy)._1.B && wdata(11) 377 when(wdata(10, 7) === 0.U || wdata(10, 7) === 2.U || wdata(10, 7) === 3.U) {tdata1_new.matchType := wdata(8, 7)} 378 tdata1_new.m := wdata(6) 379 tdata1_new.s := wdata(4) 380 tdata1_new.u := wdata(3) 381 tdata1Phy(tselectPhy) := tdata1_new 382 0.U 383 } 384 385 def ReadTselect(rdata: UInt) = Cat(0.U(60.W), tselectPhy) 386 def WriteTselect(wdata: UInt) = { 387 when (wdata <= 10.U){ 388 tselectPhy := wdata(3, 0) 389 } 390 0.U 391 } 392 393 def ReadTdata2(tdata: UInt) = tdata2Phy(tselectPhy) 394 def WriteTdata2(wdata: UInt) = { 395 tdata2Phy(tselectPhy) := wdata 396 0.U 397 } 398 399 def ReadTinfo(tdata: UInt) = 2.U(XLEN.W) 400 401 val tcontrolWriteMask = ZeroExt(GenMask(3) | GenMask(7), XLEN) 402 403 404 def GenTdataDistribute(tdata1: TdataBundle, tdata2: UInt): MatchTriggerIO = { 405 val res = Wire(new MatchTriggerIO) 406 res.matchType := tdata1.matchType 407 res.select := tdata1.select 408 res.timing := tdata1.timing 409 res.action := tdata1.action 410 res.chain := tdata1.chain 411 res.tdata2 := tdata2 412 res 413 } 414 415 csrio.customCtrl.frontend_trigger.t.bits.addr := MuxLookup(tselectPhy, 0.U, Seq( 416 0.U -> 0.U, 417 1.U -> 1.U, 418 6.U -> 2.U, 419 8.U -> 3.U 420 )) 421 csrio.customCtrl.mem_trigger.t.bits.addr := MuxLookup(tselectPhy, 0.U, Seq( 422 2.U -> 0.U, 423 3.U -> 1.U, 424 4.U -> 2.U, 425 5.U -> 3.U, 426 7.U -> 4.U, 427 9.U -> 5.U 428 )) 429 csrio.customCtrl.frontend_trigger.t.bits.tdata := GenTdataDistribute(tdata1Phy(tselectPhy), tdata2Phy(tselectPhy)) 430 csrio.customCtrl.mem_trigger.t.bits.tdata := GenTdataDistribute(tdata1Phy(tselectPhy), tdata2Phy(tselectPhy)) 431 432 // Machine-Level CSRs 433 434 val mtvec = RegInit(UInt(XLEN.W), 0.U) 435 val mcounteren = RegInit(UInt(XLEN.W), 0.U) 436 val mcause = RegInit(UInt(XLEN.W), 0.U) 437 val mtval = RegInit(UInt(XLEN.W), 0.U) 438 val mepc = Reg(UInt(XLEN.W)) 439 // Page 36 in riscv-priv: The low bit of mepc (mepc[0]) is always zero. 440 val mepcMask = ~(0x1.U(XLEN.W)) 441 442 val mie = RegInit(0.U(XLEN.W)) 443 val mipWire = WireInit(0.U.asTypeOf(new Interrupt)) 444 val mipReg = RegInit(0.U(XLEN.W)) 445 val mipFixMask = ZeroExt(GenMask(9) | GenMask(5) | GenMask(1), XLEN) 446 val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt) 447 448 def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}.asUInt() 449 def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}.asUInt() 450 var extList = List('a', 's', 'i', 'u') 451 if (HasMExtension) { extList = extList :+ 'm' } 452 if (HasCExtension) { extList = extList :+ 'c' } 453 if (HasFPU) { extList = extList ++ List('f', 'd') } 454 val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U 455 val misa = RegInit(UInt(XLEN.W), misaInitVal) 456 457 // MXL = 2 | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101 458 // (XLEN-1, XLEN-2) | |(25, 0) ZY XWVU TSRQ PONM LKJI HGFE DCBA 459 460 val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation 461 val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented 462 val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation 463 val mhartid = RegInit(UInt(XLEN.W), csrio.hartId) // the hardware thread running the code 464 val mstatus = RegInit("ha00000000".U(XLEN.W)) 465 466 // mstatus Value Table 467 // | sd | 468 // | pad1 | 469 // | sxl | hardlinked to 10, use 00 to pass xv6 test 470 // | uxl | hardlinked to 10 471 // | pad0 | 472 // | tsr | 473 // | tw | 474 // | tvm | 475 // | mxr | 476 // | sum | 477 // | mprv | 478 // | xs | 00 | 479 // | fs | 00 | 480 // | mpp | 00 | 481 // | hpp | 00 | 482 // | spp | 0 | 483 // | pie | 0000 | pie.h is used as UBE 484 // | ie | 0000 | uie hardlinked to 0, as N ext is not implemented 485 486 val mstatusStruct = mstatus.asTypeOf(new MstatusStruct) 487 def mstatusUpdateSideEffect(mstatus: UInt): UInt = { 488 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 489 val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0)) 490 mstatusNew 491 } 492 493 val mstatusWMask = (~ZeroExt(( 494 GenMask(XLEN - 2, 36) | // WPRI 495 GenMask(35, 32) | // SXL and UXL cannot be changed 496 GenMask(31, 23) | // WPRI 497 GenMask(10, 9) | // WPRI 498 GenMask(6) | // WPRI 499 GenMask(2) // WPRI 500 ), 64)).asUInt() 501 val mstatusMask = (~ZeroExt(( 502 GenMask(XLEN - 2, 36) | // WPRI 503 GenMask(31, 23) | // WPRI 504 GenMask(10, 9) | // WPRI 505 GenMask(6) | // WPRI 506 GenMask(2) // WPRI 507 ), 64)).asUInt() 508 509 val medeleg = RegInit(UInt(XLEN.W), 0.U) 510 val mideleg = RegInit(UInt(XLEN.W), 0.U) 511 val mscratch = RegInit(UInt(XLEN.W), 0.U) 512 513 // PMP Mapping 514 val pmp = Wire(Vec(NumPMP, new PMPEntry())) // just used for method parameter 515 val pma = Wire(Vec(NumPMA, new PMPEntry())) // just used for method parameter 516 val pmpMapping = pmp_gen_mapping(pmp_init, NumPMP, PmpcfgBase, PmpaddrBase, pmp) 517 val pmaMapping = pmp_gen_mapping(pma_init, NumPMA, PmacfgBase, PmaaddrBase, pma) 518 519 // Superviser-Level CSRs 520 521 // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U) 522 val sstatusWmask = "hc6122".U(XLEN.W) 523 // Sstatus Write Mask 524 // ------------------------------------------------------- 525 // 19 9 5 2 526 // 0 1100 0000 0001 0010 0010 527 // 0 c 0 1 2 2 528 // ------------------------------------------------------- 529 val sstatusRmask = sstatusWmask | "h8000000300018000".U 530 // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32)) 531 val stvec = RegInit(UInt(XLEN.W), 0.U) 532 // val sie = RegInit(0.U(XLEN.W)) 533 val sieMask = "h222".U & mideleg 534 val sipMask = "h222".U & mideleg 535 val sipWMask = "h2".U(XLEN.W) // ssip is writeable in smode 536 val satp = if(EnbaleTlbDebug) RegInit(UInt(XLEN.W), "h8000000000087fbe".U) else RegInit(0.U(XLEN.W)) 537 // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug 538 // val satpMask = "h80000fffffffffff".U(XLEN.W) // disable asid, mode can only be 8 / 0 539 // TODO: use config to control the length of asid 540 // val satpMask = "h8fffffffffffffff".U(XLEN.W) // enable asid, mode can only be 8 / 0 541 val satpMask = Cat("h8".U(4.W),Asid_true_mask(AsidLength),"hfffffffffff".U((XLEN - 4 - 16).W)) 542 val sepc = RegInit(UInt(XLEN.W), 0.U) 543 // Page 60 in riscv-priv: The low bit of sepc (sepc[0]) is always zero. 544 val sepcMask = ~(0x1.U(XLEN.W)) 545 val scause = RegInit(UInt(XLEN.W), 0.U) 546 val stval = Reg(UInt(XLEN.W)) 547 val sscratch = RegInit(UInt(XLEN.W), 0.U) 548 val scounteren = RegInit(UInt(XLEN.W), 0.U) 549 550 // sbpctl 551 // Bits 0-7: {LOOP, RAS, SC, TAGE, BIM, BTB, uBTB} 552 val sbpctl = RegInit(UInt(XLEN.W), "h7f".U) 553 csrio.customCtrl.bp_ctrl.ubtb_enable := sbpctl(0) 554 csrio.customCtrl.bp_ctrl.btb_enable := sbpctl(1) 555 csrio.customCtrl.bp_ctrl.bim_enable := sbpctl(2) 556 csrio.customCtrl.bp_ctrl.tage_enable := sbpctl(3) 557 csrio.customCtrl.bp_ctrl.sc_enable := sbpctl(4) 558 csrio.customCtrl.bp_ctrl.ras_enable := sbpctl(5) 559 csrio.customCtrl.bp_ctrl.loop_enable := sbpctl(6) 560 561 // spfctl Bit 0: L1plusCache Prefetcher Enable 562 // spfctl Bit 1: L2Cache Prefetcher Enable 563 val spfctl = RegInit(UInt(XLEN.W), "h3".U) 564 csrio.customCtrl.l1plus_pf_enable := spfctl(0) 565 csrio.customCtrl.l2_pf_enable := spfctl(1) 566 567 // sdsid: Differentiated Services ID 568 val sdsid = RegInit(UInt(XLEN.W), 0.U) 569 csrio.customCtrl.dsid := sdsid 570 571 // slvpredctl: load violation predict settings 572 val slvpredctl = RegInit(UInt(XLEN.W), "h70".U) // default reset period: 2^17 573 csrio.customCtrl.lvpred_disable := slvpredctl(0) 574 csrio.customCtrl.no_spec_load := slvpredctl(1) 575 csrio.customCtrl.storeset_wait_store := slvpredctl(2) 576 csrio.customCtrl.storeset_no_fast_wakeup := slvpredctl(3) 577 csrio.customCtrl.lvpred_timeout := slvpredctl(8, 4) 578 579 // smblockctl: memory block configurations 580 // bits 0-3: store buffer flush threshold (default: 8 entries) 581 val smblockctl_init_val = 582 ("hf".U & StoreBufferThreshold.U) | 583 (EnableLdVioCheckAfterReset.B.asUInt << 4) 584 val smblockctl = RegInit(UInt(XLEN.W), smblockctl_init_val) 585 csrio.customCtrl.sbuffer_threshold := smblockctl(3, 0) 586 // bits 4: enable load load violation check 587 csrio.customCtrl.ldld_vio_check := smblockctl(4) 588 589 val srnctl = RegInit(UInt(XLEN.W), "h3".U) 590 csrio.customCtrl.move_elim_enable := srnctl(0) 591 csrio.customCtrl.svinval_enable := srnctl(1) 592 593 val tlbBundle = Wire(new TlbCsrBundle) 594 tlbBundle.satp.apply(satp) 595 596 csrio.tlb := tlbBundle 597 598 // User-Level CSRs 599 val uepc = Reg(UInt(XLEN.W)) 600 601 // fcsr 602 class FcsrStruct extends Bundle { 603 val reserved = UInt((XLEN-3-5).W) 604 val frm = UInt(3.W) 605 val fflags = UInt(5.W) 606 assert(this.getWidth == XLEN) 607 } 608 val fcsr = RegInit(0.U(XLEN.W)) 609 // set mstatus->sd and mstatus->fs when true 610 val csrw_dirty_fp_state = WireInit(false.B) 611 612 def frm_wfn(wdata: UInt): UInt = { 613 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 614 csrw_dirty_fp_state := true.B 615 fcsrOld.frm := wdata(2,0) 616 fcsrOld.asUInt() 617 } 618 def frm_rfn(rdata: UInt): UInt = rdata(7,5) 619 620 def fflags_wfn(update: Boolean)(wdata: UInt): UInt = { 621 val fcsrOld = fcsr.asTypeOf(new FcsrStruct) 622 val fcsrNew = WireInit(fcsrOld) 623 csrw_dirty_fp_state := true.B 624 if (update) { 625 fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags 626 } else { 627 fcsrNew.fflags := wdata(4,0) 628 } 629 fcsrNew.asUInt() 630 } 631 def fflags_rfn(rdata:UInt): UInt = rdata(4,0) 632 633 def fcsr_wfn(wdata: UInt): UInt = { 634 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 635 csrw_dirty_fp_state := true.B 636 Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags) 637 } 638 639 val fcsrMapping = Map( 640 MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn), 641 MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn), 642 MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn) 643 ) 644 645 // Hart Priviledge Mode 646 val priviledgeMode = RegInit(UInt(2.W), ModeM) 647 648 //val perfEventscounten = List.fill(nrPerfCnts)(RegInit(false(Bool()))) 649 // Perf Counter 650 val nrPerfCnts = 29 // 3...31 651 val priviledgeModeOH = UIntToOH(priviledgeMode) 652 val perfEventscounten = RegInit(0.U.asTypeOf(Vec(nrPerfCnts, Bool()))) 653 val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W))) 654 val perfEvents = List.fill(8)(RegInit("h0000000000".U(XLEN.W))) ++ 655 List.fill(8)(RegInit("h4010040100".U(XLEN.W))) ++ 656 List.fill(8)(RegInit("h8020080200".U(XLEN.W))) ++ 657 List.fill(5)(RegInit("hc0300c0300".U(XLEN.W))) 658 for (i <-0 until nrPerfCnts) { 659 perfEventscounten(i) := (Cat(perfEvents(i)(62),perfEvents(i)(61),(perfEvents(i)(61,60))) & priviledgeModeOH).orR 660 } 661 662 val hpmEvents = Wire(new PerfEventsBundle(numPCntHc * coreParams.L2NBanks)) 663 for(i <- 0 until numPCntHc * coreParams.L2NBanks) { 664 hpmEvents.perf_events(i).incr_step := csrio.perf.perfEventsHc(i) 665 } 666 667 val hpm_hc = Module(new HPerfmonitor(numPCntHc * coreParams.L2NBanks,numCSRPCntHc)) 668 val csrevents = perfEvents.slice(24,29) 669 hpm_hc.io.hpm_event := csrevents 670 hpm_hc.io.events_sets := hpmEvents 671 val mcountinhibit = RegInit(0.U(XLEN.W)) 672 val mcycle = RegInit(0.U(XLEN.W)) 673 mcycle := mcycle + 1.U 674 val minstret = RegInit(0.U(XLEN.W)) 675 val perf_events = csrio.perf.perfEventsFrontend.perf_events ++ 676 csrio.perf.perfEventsCtrl.perf_events ++ 677 csrio.perf.perfEventsLsu.perf_events ++ 678 hpm_hc.io.events_selected.perf_events 679 minstret := minstret + RegNext(csrio.perf.retiredInstr) 680 for(i <- 0 until 29){ 681 perfCnts(i) := Mux((mcountinhibit(i+3) | !perfEventscounten(i)), perfCnts(i), (perfCnts(i) + perf_events(i).incr_step)) 682 } 683 684 // CSR reg map 685 val basicPrivMapping = Map( 686 687 //--- User Trap Setup --- 688 // MaskedRegMap(Ustatus, ustatus), 689 // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable), 690 // MaskedRegMap(Utvec, utvec), 691 692 //--- User Trap Handling --- 693 // MaskedRegMap(Uscratch, uscratch), 694 // MaskedRegMap(Uepc, uepc), 695 // MaskedRegMap(Ucause, ucause), 696 // MaskedRegMap(Utval, utval), 697 // MaskedRegMap(Uip, uip), 698 699 //--- User Counter/Timers --- 700 // MaskedRegMap(Cycle, cycle), 701 // MaskedRegMap(Time, time), 702 // MaskedRegMap(Instret, instret), 703 704 //--- Supervisor Trap Setup --- 705 MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask), 706 // MaskedRegMap(Sedeleg, Sedeleg), 707 // MaskedRegMap(Sideleg, Sideleg), 708 MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask), 709 MaskedRegMap(Stvec, stvec), 710 MaskedRegMap(Scounteren, scounteren), 711 712 //--- Supervisor Trap Handling --- 713 MaskedRegMap(Sscratch, sscratch), 714 MaskedRegMap(Sepc, sepc, sepcMask, MaskedRegMap.NoSideEffect, sepcMask), 715 MaskedRegMap(Scause, scause), 716 MaskedRegMap(Stval, stval), 717 MaskedRegMap(Sip, mip.asUInt, sipWMask, MaskedRegMap.Unwritable, sipMask), 718 719 //--- Supervisor Protection and Translation --- 720 MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask), 721 722 //--- Supervisor Custom Read/Write Registers 723 MaskedRegMap(Sbpctl, sbpctl), 724 MaskedRegMap(Spfctl, spfctl), 725 MaskedRegMap(Sdsid, sdsid), 726 MaskedRegMap(Slvpredctl, slvpredctl), 727 MaskedRegMap(Smblockctl, smblockctl), 728 MaskedRegMap(Srnctl, srnctl), 729 730 //--- Machine Information Registers --- 731 MaskedRegMap(Mvendorid, mvendorid, 0.U(XLEN.W), MaskedRegMap.Unwritable), 732 MaskedRegMap(Marchid, marchid, 0.U(XLEN.W), MaskedRegMap.Unwritable), 733 MaskedRegMap(Mimpid, mimpid, 0.U(XLEN.W), MaskedRegMap.Unwritable), 734 MaskedRegMap(Mhartid, mhartid, 0.U(XLEN.W), MaskedRegMap.Unwritable), 735 736 //--- Machine Trap Setup --- 737 MaskedRegMap(Mstatus, mstatus, mstatusWMask, mstatusUpdateSideEffect, mstatusMask), 738 MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable 739 MaskedRegMap(Medeleg, medeleg, "hf3ff".U(XLEN.W)), 740 MaskedRegMap(Mideleg, mideleg, "h222".U(XLEN.W)), 741 MaskedRegMap(Mie, mie), 742 MaskedRegMap(Mtvec, mtvec), 743 MaskedRegMap(Mcounteren, mcounteren), 744 745 //--- Machine Trap Handling --- 746 MaskedRegMap(Mscratch, mscratch), 747 MaskedRegMap(Mepc, mepc, mepcMask, MaskedRegMap.NoSideEffect, mepcMask), 748 MaskedRegMap(Mcause, mcause), 749 MaskedRegMap(Mtval, mtval), 750 MaskedRegMap(Mip, mip.asUInt, 0.U(XLEN.W), MaskedRegMap.Unwritable), 751 752 //--- Trigger --- 753 MaskedRegMap(Tselect, tDummy, WritableMask, WriteTselect, WritableMask, ReadTselect), 754 MaskedRegMap(Tdata1, tDummy, WritableMask, WriteTdata1, WritableMask, ReadTdata1), 755 MaskedRegMap(Tdata2, tDummy, WritableMask, WriteTdata2, WritableMask, ReadTdata2), 756 MaskedRegMap(Tinfo, tDummy, 0.U(XLEN.W), MaskedRegMap.Unwritable, WritableMask, ReadTinfo), 757 MaskedRegMap(Tcontrol, tControlPhy, tcontrolWriteMask), 758 759 //--- Debug Mode --- 760 MaskedRegMap(Dcsr, dcsr, dcsrMask, dcsrUpdateSideEffect), 761 MaskedRegMap(Dpc, dpc), 762 MaskedRegMap(Dscratch, dscratch), 763 MaskedRegMap(Dscratch1, dscratch1), 764 MaskedRegMap(Mcountinhibit, mcountinhibit), 765 MaskedRegMap(Mcycle, mcycle), 766 MaskedRegMap(Minstret, minstret), 767 ) 768 769 val perfCntMapping = (0 until 29).map(i => {Map( 770 MaskedRegMap(addr = Mhpmevent3 +i, 771 reg = perfEvents(i), 772 wmask = "hf87fff3fcff3fcff".U(XLEN.W)), 773 MaskedRegMap(addr = Mhpmcounter3 +i, 774 reg = perfCnts(i)) 775 )}).fold(Map())((a,b) => a ++ b) 776 // TODO: mechanism should be implemented later 777 // val MhpmcounterStart = Mhpmcounter3 778 // val MhpmeventStart = Mhpmevent3 779 // for (i <- 0 until nrPerfCnts) { 780 // perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i)) 781 // perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i)) 782 // } 783 784 val cacheopRegs = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => { 785 name -> RegInit(0.U(attribute("width").toInt.W)) 786 }} 787 val cacheopMapping = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => { 788 MaskedRegMap( 789 Scachebase + attribute("offset").toInt, 790 cacheopRegs(name) 791 ) 792 }} 793 794 val mapping = basicPrivMapping ++ 795 perfCntMapping ++ 796 pmpMapping ++ 797 pmaMapping ++ 798 (if (HasFPU) fcsrMapping else Nil) ++ 799 (if (HasCustomCSRCacheOp) cacheopMapping else Nil) 800 801 val addr = src2(11, 0) 802 val csri = ZeroExt(src2(16, 12), XLEN) 803 val rdata = Wire(UInt(XLEN.W)) 804 val wdata = LookupTree(func, List( 805 CSROpType.wrt -> src1, 806 CSROpType.set -> (rdata | src1), 807 CSROpType.clr -> (rdata & (~src1).asUInt()), 808 CSROpType.wrti -> csri, 809 CSROpType.seti -> (rdata | csri), 810 CSROpType.clri -> (rdata & (~csri).asUInt()) 811 )) 812 813 val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U) || 814 (addr >= Mcountinhibit.U) && (addr <= Mhpmevent31.U) 815 csrio.isPerfCnt := addrInPerfCnt && valid && func =/= CSROpType.jmp 816 817 // satp wen check 818 val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U) 819 820 // csr access check, special case 821 val tvmNotPermit = (priviledgeMode === ModeS && mstatusStruct.tvm.asBool) 822 val accessPermitted = !(addr === Satp.U && tvmNotPermit) 823 csrio.disableSfence := tvmNotPermit 824 825 // general CSR wen check 826 val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode) 827 val dcsrPermitted = dcsrPermissionCheck(addr, false.B, debugMode) 828 val triggerPermitted = triggerPermissionCheck(addr, true.B, debugMode) // todo dmode 829 val modePermitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode) && dcsrPermitted && triggerPermitted 830 val perfcntPermitted = perfcntPermissionCheck(addr, priviledgeMode, mcounteren, scounteren) 831 val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) && accessPermitted 832 833 MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata) 834 io.out.bits.data := rdata 835 io.out.bits.uop := io.in.bits.uop 836 io.out.bits.uop.cf := cfOut 837 io.out.bits.uop.ctrl.flushPipe := flushPipe 838 839 // send distribute csr a w signal 840 csrio.customCtrl.distribute_csr.w.valid := wen && permitted 841 csrio.customCtrl.distribute_csr.w.bits.data := wdata 842 csrio.customCtrl.distribute_csr.w.bits.addr := addr 843 844 // Fix Mip/Sip write 845 val fixMapping = Map( 846 MaskedRegMap(Mip, mipReg.asUInt, mipFixMask), 847 MaskedRegMap(Sip, mipReg.asUInt, sipWMask, MaskedRegMap.NoSideEffect, sipMask) 848 ) 849 val rdataFix = Wire(UInt(XLEN.W)) 850 val wdataFix = LookupTree(func, List( 851 CSROpType.wrt -> src1, 852 CSROpType.set -> (rdataFix | src1), 853 CSROpType.clr -> (rdataFix & (~src1).asUInt()), 854 CSROpType.wrti -> csri, 855 CSROpType.seti -> (rdataFix | csri), 856 CSROpType.clri -> (rdataFix & (~csri).asUInt()) 857 )) 858 MaskedRegMap.generate(fixMapping, addr, rdataFix, wen && permitted, wdataFix) 859 860 when (csrio.fpu.fflags.valid) { 861 fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits) 862 } 863 // set fs and sd in mstatus 864 when (csrw_dirty_fp_state || csrio.fpu.dirty_fs) { 865 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 866 mstatusNew.fs := "b11".U 867 mstatusNew.sd := true.B 868 mstatus := mstatusNew.asUInt() 869 } 870 csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm 871 872 873 // Trigger Ctrl 874 csrio.customCtrl.trigger_enable := tdata1Phy.map{tdata1 => tdata1.m && priviledgeMode === ModeM || 875 tdata1.s && priviledgeMode === ModeS || tdata1.u && priviledgeMode === ModeU 876 } 877 csrio.customCtrl.frontend_trigger.t.valid := RegNext(wen && addr === Tdata1.U && tdata1_function(tselectPhy)._2 === I_Trigger) 878 csrio.customCtrl.mem_trigger.t.valid := RegNext(wen && addr === Tdata1.U && tdata1_function(tselectPhy)._2 =/= I_Trigger) 879 880 881 // CSR inst decode 882 val isEbreak = addr === privEbreak && func === CSROpType.jmp 883 val isEcall = addr === privEcall && func === CSROpType.jmp 884 val isMret = addr === privMret && func === CSROpType.jmp 885 val isSret = addr === privSret && func === CSROpType.jmp 886 val isUret = addr === privUret && func === CSROpType.jmp 887 val isDret = addr === privDret && func === CSROpType.jmp 888 889 XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func) 890 XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode) 891 892 // Illegal priviledged operation list 893 val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool 894 895 // Illegal priviledged instruction check 896 val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr) 897 val isIllegalAccess = !permitted 898 val isIllegalPrivOp = illegalSModeSret 899 900 // expose several csr bits for tlb 901 tlbBundle.priv.mxr := mstatusStruct.mxr.asBool 902 tlbBundle.priv.sum := mstatusStruct.sum.asBool 903 tlbBundle.priv.imode := priviledgeMode 904 tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode) 905 906 // Branch control 907 val retTarget = Wire(UInt(VAddrBits.W)) 908 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 909 flushPipe := resetSatp || (valid && func === CSROpType.jmp && !isEcall) 910 911 retTarget := DontCare 912 // val illegalEret = TODO 913 914 when (valid && isDret) { 915 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 916 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 917 val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct)) 918 val debugModeNew = WireInit(debugMode) 919 when (dcsr.asTypeOf(new DcsrStruct).prv =/= ModeM) {mstatusNew.mprv := 0.U} //If the new privilege mode is less privileged than M-mode, MPRV in mstatus is cleared. 920 mstatus := mstatusNew.asUInt 921 priviledgeMode := dcsrNew.prv 922 retTarget := dpc(VAddrBits-1, 0) 923 debugModeNew := false.B 924 debugIntrEnable := true.B 925 debugMode := debugModeNew 926 XSDebug("Debug Mode: Dret executed, returning to %x.", retTarget) 927 } 928 929 when (valid && isMret) { 930 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 931 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 932 mstatusNew.ie.m := mstatusOld.pie.m 933 priviledgeMode := mstatusOld.mpp 934 mstatusNew.pie.m := true.B 935 mstatusNew.mpp := ModeU 936 when (mstatusOld.mpp =/= ModeM) { mstatusNew.mprv := 0.U } 937 mstatus := mstatusNew.asUInt 938 // lr := false.B 939 retTarget := mepc(VAddrBits-1, 0) 940 } 941 942 when (valid && isSret && !illegalSModeSret) { 943 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 944 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 945 mstatusNew.ie.s := mstatusOld.pie.s 946 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 947 mstatusNew.pie.s := true.B 948 mstatusNew.spp := ModeU 949 mstatus := mstatusNew.asUInt 950 mstatusNew.mprv := 0.U 951 // lr := false.B 952 retTarget := sepc(VAddrBits-1, 0) 953 } 954 955 when (valid && isUret) { 956 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 957 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 958 // mstatusNew.mpp.m := ModeU //TODO: add mode U 959 mstatusNew.ie.u := mstatusOld.pie.u 960 priviledgeMode := ModeU 961 mstatusNew.pie.u := true.B 962 mstatus := mstatusNew.asUInt 963 retTarget := uepc(VAddrBits-1, 0) 964 } 965 966 io.in.ready := true.B 967 io.out.valid := valid 968 969 val ebreakCauseException = (priviledgeMode === ModeM && dcsrData.ebreakm) || (priviledgeMode === ModeS && dcsrData.ebreaks) || (priviledgeMode === ModeU && dcsrData.ebreaku) 970 971 val csrExceptionVec = WireInit(cfIn.exceptionVec) 972 csrExceptionVec(breakPoint) := io.in.valid && isEbreak && ebreakCauseException 973 csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall 974 csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall 975 csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall 976 // Trigger an illegal instr exception when: 977 // * unimplemented csr is being read/written 978 // * csr access is illegal 979 csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen 980 cfOut.exceptionVec := csrExceptionVec 981 982 /** 983 * Exception and Intr 984 */ 985 val ideleg = (mideleg & mip.asUInt) 986 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 987 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 988 989 val debugIntr = csrio.externalInterrupt.debug & debugIntrEnable 990 XSDebug(debugIntr, "Debug Mode: debug interrupt is asserted and valid!") 991 // send interrupt information to ROB 992 val intrVecEnable = Wire(Vec(12, Bool())) 993 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 994 val intrVec = Cat(debugIntr, (mie(11,0) & mip.asUInt & intrVecEnable.asUInt)) 995 val intrBitSet = intrVec.orR() 996 csrio.interrupt := intrBitSet 997 mipWire.t.m := csrio.externalInterrupt.mtip 998 mipWire.s.m := csrio.externalInterrupt.msip 999 mipWire.e.m := csrio.externalInterrupt.meip 1000 mipWire.e.s := csrio.externalInterrupt.seip 1001 1002 // interrupts 1003 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 1004 val raiseIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt 1005 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.uop.cf.pc, intrNO) 1006 val raiseDebugIntr = intrNO === IRQ_DEBUG.U && raiseIntr 1007 1008 // exceptions 1009 val raiseException = csrio.exception.valid && !csrio.exception.bits.isInterrupt 1010 val hasInstrPageFault = csrio.exception.bits.uop.cf.exceptionVec(instrPageFault) && raiseException 1011 val hasLoadPageFault = csrio.exception.bits.uop.cf.exceptionVec(loadPageFault) && raiseException 1012 val hasStorePageFault = csrio.exception.bits.uop.cf.exceptionVec(storePageFault) && raiseException 1013 val hasStoreAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(storeAddrMisaligned) && raiseException 1014 val hasLoadAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(loadAddrMisaligned) && raiseException 1015 val hasInstrAccessFault = csrio.exception.bits.uop.cf.exceptionVec(instrAccessFault) && raiseException 1016 val hasLoadAccessFault = csrio.exception.bits.uop.cf.exceptionVec(loadAccessFault) && raiseException 1017 val hasStoreAccessFault = csrio.exception.bits.uop.cf.exceptionVec(storeAccessFault) && raiseException 1018 val hasbreakPoint = csrio.exception.bits.uop.cf.exceptionVec(breakPoint) && raiseException 1019 val hasSingleStep = csrio.exception.bits.uop.ctrl.singleStep && raiseException 1020 val hasTriggerHit = csrio.exception.bits.uop.cf.trigger.triggerHitVec.orR && raiseException 1021 1022 val raiseExceptionVec = csrio.exception.bits.uop.cf.exceptionVec 1023 val regularExceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum)) 1024 val exceptionNO = Mux(hasSingleStep || hasTriggerHit, 3.U, regularExceptionNO) 1025 val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO) 1026 1027 val raiseExceptionIntr = csrio.exception.valid 1028 1029 val raiseDebugExceptionIntr = !debugMode && hasbreakPoint || raiseDebugIntr || hasSingleStep || hasTriggerHit // todo 1030 val ebreakEnterParkLoop = debugMode && raiseExceptionIntr // exception in debug mode (except ebrk) changes cmderr. how ??? 1031 1032 XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n", 1033 csrio.exception.bits.uop.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt 1034 ) 1035 XSDebug(raiseExceptionIntr, 1036 "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", 1037 csrio.exception.bits.uop.cf.pc, 1038 mstatus, 1039 mideleg, 1040 medeleg, 1041 priviledgeMode 1042 ) 1043 1044 // mtval write logic 1045 // Due to timing reasons of memExceptionVAddr, we delay the write of mtval and stval 1046 val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN) 1047 when (RegNext(RegNext(hasInstrPageFault || hasLoadPageFault || hasStorePageFault))) { 1048 val tval = RegNext(Mux( 1049 RegNext(hasInstrPageFault), 1050 RegNext(Mux( 1051 csrio.exception.bits.uop.cf.crossPageIPFFix, 1052 SignExt(csrio.exception.bits.uop.cf.pc + 2.U, XLEN), 1053 SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 1054 )), 1055 memExceptionAddr 1056 )) 1057 when (RegNext(RegNext(priviledgeMode === ModeM))) { 1058 mtval := tval 1059 }.otherwise { 1060 stval := tval 1061 } 1062 } 1063 1064 when (RegNext(RegNext(hasLoadAddrMisaligned || hasStoreAddrMisaligned))) { 1065 mtval := RegNext(memExceptionAddr) 1066 } 1067 1068 val debugTrapTarget = Mux(!isEbreak && debugMode, 0x38020808.U, 0x38020800.U) // 0x808 is when an exception occurs in debug mode prog buf exec 1069 val deleg = Mux(raiseIntr, mideleg , medeleg) 1070 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 1071 val delegS = deleg(causeNO(3,0)) && (priviledgeMode < ModeM) 1072 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check 1073 val isXRet = io.in.valid && func === CSROpType.jmp && !isEcall && !isEbreak 1074 1075 // ctrl block will use theses later for flush 1076 val isXRetFlag = RegInit(false.B) 1077 val retTargetReg = Reg(retTarget.cloneType) 1078 when (io.redirectIn.valid) { 1079 isXRetFlag := false.B 1080 }.elsewhen (isXRet) { 1081 isXRetFlag := true.B 1082 retTargetReg := retTarget 1083 } 1084 csrio.isXRet := isXRetFlag 1085 csrio.trapTarget := Mux(isXRetFlag, 1086 retTargetReg, 1087 Mux(raiseDebugExceptionIntr || ebreakEnterParkLoop, debugTrapTarget, 1088 Mux(delegS, stvec, mtvec))(VAddrBits-1, 0) 1089 ) 1090 1091 when (raiseExceptionIntr) { 1092 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 1093 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 1094 val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct)) 1095 val debugModeNew = WireInit(debugMode) 1096 1097 when (raiseDebugExceptionIntr) { 1098 when (raiseDebugIntr) { 1099 debugModeNew := true.B 1100 mstatusNew.mprv := false.B 1101 dpc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 1102 dcsrNew.cause := 1.U 1103 dcsrNew.prv := priviledgeMode 1104 priviledgeMode := ModeM 1105 XSDebug(raiseDebugIntr, "Debug Mode: Trap to %x at pc %x\n", debugTrapTarget, dpc) 1106 }.elsewhen ((hasbreakPoint || hasSingleStep) && !debugMode) { 1107 // ebreak or ss in running hart 1108 debugModeNew := true.B 1109 dpc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 1110 dcsrNew.cause := Mux(hasbreakPoint, 3.U, 0.U) 1111 dcsrNew.prv := priviledgeMode // TODO 1112 priviledgeMode := ModeM 1113 mstatusNew.mprv := false.B 1114 } 1115 dcsr := dcsrNew.asUInt 1116 debugIntrEnable := false.B 1117 }.elsewhen (delegS) { 1118 scause := causeNO 1119 sepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 1120 mstatusNew.spp := priviledgeMode 1121 mstatusNew.pie.s := mstatusOld.ie.s 1122 mstatusNew.ie.s := false.B 1123 priviledgeMode := ModeS 1124 when (tvalWen) { stval := 0.U } 1125 }.otherwise { 1126 mcause := causeNO 1127 mepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 1128 mstatusNew.mpp := priviledgeMode 1129 mstatusNew.pie.m := mstatusOld.ie.m 1130 mstatusNew.ie.m := false.B 1131 priviledgeMode := ModeM 1132 when (tvalWen) { mtval := 0.U } 1133 } 1134 mstatus := mstatusNew.asUInt 1135 debugMode := debugModeNew 1136 } 1137 1138 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc) 1139 1140 // Distributed CSR update req 1141 // 1142 // For now we use it to implement customized cache op 1143 1144 when(csrio.distributedUpdate.w.valid){ 1145 // cacheopRegs can be distributed updated 1146 CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => { 1147 when((Scachebase + attribute("offset").toInt).U === csrio.distributedUpdate.w.bits.addr){ 1148 cacheopRegs(name) := csrio.distributedUpdate.w.bits.data 1149 } 1150 }} 1151 } 1152 1153 // Implicit add reset values for mepc[0] and sepc[0] 1154 // TODO: rewrite mepc and sepc using a struct-like style with the LSB always being 0 1155 when (reset.asBool) { 1156 mepc := Cat(mepc(XLEN - 1, 1), 0.U(1.W)) 1157 sepc := Cat(sepc(XLEN - 1, 1), 0.U(1.W)) 1158 } 1159 1160 def readWithScala(addr: Int): UInt = mapping(addr)._1 1161 1162 val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U) 1163 1164 // Always instantiate basic difftest modules. 1165 if (env.AlwaysBasicDiff || env.EnableDifftest) { 1166 val difftest = Module(new DifftestArchEvent) 1167 difftest.io.clock := clock 1168 difftest.io.coreid := csrio.hartId 1169 difftest.io.intrNO := RegNext(RegNext(RegNext(difftestIntrNO))) 1170 difftest.io.cause := RegNext(RegNext(RegNext(Mux(csrio.exception.valid, causeNO, 0.U)))) 1171 difftest.io.exceptionPC := RegNext(RegNext(RegNext(SignExt(csrio.exception.bits.uop.cf.pc, XLEN)))) 1172 } 1173 1174 // Always instantiate basic difftest modules. 1175 if (env.AlwaysBasicDiff || env.EnableDifftest) { 1176 val difftest = Module(new DifftestCSRState) 1177 difftest.io.clock := clock 1178 difftest.io.coreid := csrio.hartId 1179 difftest.io.priviledgeMode := priviledgeMode 1180 difftest.io.mstatus := mstatus 1181 difftest.io.sstatus := mstatus & sstatusRmask 1182 difftest.io.mepc := mepc 1183 difftest.io.sepc := sepc 1184 difftest.io.mtval:= mtval 1185 difftest.io.stval:= stval 1186 difftest.io.mtvec := mtvec 1187 difftest.io.stvec := stvec 1188 difftest.io.mcause := mcause 1189 difftest.io.scause := scause 1190 difftest.io.satp := satp 1191 difftest.io.mip := mipReg 1192 difftest.io.mie := mie 1193 difftest.io.mscratch := mscratch 1194 difftest.io.sscratch := sscratch 1195 difftest.io.mideleg := mideleg 1196 difftest.io.medeleg := medeleg 1197 } 1198} 1199 1200class PFEvent(implicit p: Parameters) extends XSModule with HasCSRConst { 1201 val io = IO(new Bundle { 1202 val distribute_csr = Flipped(new DistributedCSRIO()) 1203 val hpmevent = Output(Vec(29, UInt(XLEN.W))) 1204 }) 1205 1206 val w = io.distribute_csr.w 1207 1208 val perfEvents = List.fill(8)(RegInit("h0000000000".U(XLEN.W))) ++ 1209 List.fill(8)(RegInit("h4010040100".U(XLEN.W))) ++ 1210 List.fill(8)(RegInit("h8020080200".U(XLEN.W))) ++ 1211 List.fill(5)(RegInit("hc0300c0300".U(XLEN.W))) 1212 1213 val perfEventMapping = (0 until 29).map(i => {Map( 1214 MaskedRegMap(addr = Mhpmevent3 +i, 1215 reg = perfEvents(i), 1216 wmask = "hf87fff3fcff3fcff".U(XLEN.W)) 1217 )}).fold(Map())((a,b) => a ++ b) 1218 1219 val rdata = Wire(UInt(XLEN.W)) 1220 MaskedRegMap.generate(perfEventMapping, w.bits.addr, rdata, w.valid, w.bits.data) 1221 for(i <- 0 until 29){ 1222 io.hpmevent(i) := perfEvents(i) 1223 } 1224} 1225 1226