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