1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* 4* XiangShan is licensed under Mulan PSL v2. 5* You can use this software according to the terms and conditions of the Mulan PSL v2. 6* You may obtain a copy of Mulan PSL v2 at: 7* http://license.coscl.org.cn/MulanPSL2 8* 9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12* 13* See the Mulan PSL v2 for more details. 14***************************************************************************************/ 15 16package xiangshan.backend.fu 17 18import chipsalliance.rocketchip.config.Parameters 19import chisel3._ 20import chisel3.util._ 21import utils._ 22import xiangshan._ 23import xiangshan.backend._ 24import xiangshan.frontend.BPUCtrl 25import xiangshan.backend.fu.util._ 26import difftest._ 27 28trait HasExceptionNO { 29 def instrAddrMisaligned = 0 30 def instrAccessFault = 1 31 def illegalInstr = 2 32 def breakPoint = 3 33 def loadAddrMisaligned = 4 34 def loadAccessFault = 5 35 def storeAddrMisaligned = 6 36 def storeAccessFault = 7 37 def ecallU = 8 38 def ecallS = 9 39 def ecallM = 11 40 def instrPageFault = 12 41 def loadPageFault = 13 42 def storePageFault = 15 43 44 val ExcPriority = Seq( 45 breakPoint, // TODO: different BP has different priority 46 instrPageFault, 47 instrAccessFault, 48 illegalInstr, 49 instrAddrMisaligned, 50 ecallM, ecallS, ecallU, 51 storePageFault, 52 loadPageFault, 53 storeAccessFault, 54 loadAccessFault, 55 storeAddrMisaligned, 56 loadAddrMisaligned 57 ) 58 val frontendSet = List( 59 // instrAddrMisaligned, 60 instrAccessFault, 61 illegalInstr, 62 instrPageFault 63 ) 64 val csrSet = List( 65 illegalInstr, 66 breakPoint, 67 ecallU, 68 ecallS, 69 ecallM 70 ) 71 val loadUnitSet = List( 72 loadAddrMisaligned, 73 loadAccessFault, 74 loadPageFault 75 ) 76 val storeUnitSet = List( 77 storeAddrMisaligned, 78 storeAccessFault, 79 storePageFault 80 ) 81 val atomicsUnitSet = (loadUnitSet ++ storeUnitSet).distinct 82 val allPossibleSet = (frontendSet ++ csrSet ++ loadUnitSet ++ storeUnitSet).distinct 83 val csrWbCount = (0 until 16).map(i => if (csrSet.contains(i)) 1 else 0) 84 val loadWbCount = (0 until 16).map(i => if (loadUnitSet.contains(i)) 1 else 0) 85 val storeWbCount = (0 until 16).map(i => if (storeUnitSet.contains(i)) 1 else 0) 86 val atomicsWbCount = (0 until 16).map(i => if (atomicsUnitSet.contains(i)) 1 else 0) 87 val writebackCount = (0 until 16).map(i => csrWbCount(i) + atomicsWbCount(i) + loadWbCount(i) + 2 * storeWbCount(i)) 88 def partialSelect(vec: Vec[Bool], select: Seq[Int], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = { 89 if (dontCareBits) { 90 val new_vec = Wire(ExceptionVec()) 91 new_vec := DontCare 92 select.map(i => new_vec(i) := vec(i)) 93 return new_vec 94 } 95 else if (falseBits) { 96 val new_vec = Wire(ExceptionVec()) 97 new_vec.map(_ := false.B) 98 select.map(i => new_vec(i) := vec(i)) 99 return new_vec 100 } 101 else { 102 val new_vec = Wire(Vec(select.length, Bool())) 103 select.zipWithIndex.map{ case(s, i) => new_vec(i) := vec(s) } 104 return new_vec 105 } 106 } 107 def selectFrontend(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 108 partialSelect(vec, frontendSet, dontCareBits, falseBits) 109 def selectCSR(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 110 partialSelect(vec, csrSet, dontCareBits, falseBits) 111 def selectLoad(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 112 partialSelect(vec, loadUnitSet, dontCareBits, falseBits) 113 def selectStore(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 114 partialSelect(vec, storeUnitSet, dontCareBits, falseBits) 115 def selectAtomics(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 116 partialSelect(vec, atomicsUnitSet, dontCareBits, falseBits) 117 def selectAll(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = 118 partialSelect(vec, allPossibleSet, dontCareBits, falseBits) 119} 120 121class FpuCsrIO extends Bundle { 122 val fflags = Output(Valid(UInt(5.W))) 123 val isIllegal = Output(Bool()) 124 val dirty_fs = Output(Bool()) 125 val frm = Input(UInt(3.W)) 126} 127 128 129class PerfCounterIO(implicit p: Parameters) extends XSBundle { 130 val retiredInstr = UInt(3.W) 131 val frontendInfo = new Bundle { 132 val ibufFull = Bool() 133 } 134 val ctrlInfo = new Bundle { 135 val roqFull = Bool() 136 val intdqFull = Bool() 137 val fpdqFull = Bool() 138 val lsdqFull = Bool() 139 } 140 val memInfo = new Bundle { 141 val sqFull = Bool() 142 val lqFull = Bool() 143 val dcacheMSHRFull = Bool() 144 } 145 val bpuInfo = new Bundle { 146 val bpRight = UInt(XLEN.W) 147 val bpWrong = UInt(XLEN.W) 148 } 149 val cacheInfo = new Bundle { 150 val l2MSHRFull = Bool() 151 val l3MSHRFull = Bool() 152 val l2nAcquire = UInt(XLEN.W) 153 val l2nAcquireMiss = UInt(XLEN.W) 154 val l3nAcquire = UInt(XLEN.W) 155 val l3nAcquireMiss = UInt(XLEN.W) 156 } 157} 158 159class CSRFileIO(implicit p: Parameters) extends XSBundle { 160 val hartId = Input(UInt(64.W)) 161 // output (for func === CSROpType.jmp) 162 val perf = Input(new PerfCounterIO) 163 val isPerfCnt = Output(Bool()) 164 // to FPU 165 val fpu = Flipped(new FpuCsrIO) 166 // from rob 167 val exception = Flipped(ValidIO(new ExceptionInfo)) 168 // to ROB 169 val isXRet = Output(Bool()) 170 val trapTarget = Output(UInt(VAddrBits.W)) 171 val interrupt = Output(Bool()) 172 // from LSQ 173 val memExceptionVAddr = Input(UInt(VAddrBits.W)) 174 // from outside cpu,externalInterrupt 175 val externalInterrupt = new ExternalInterruptIO 176 // TLB 177 val tlb = Output(new TlbCsrBundle) 178 // Custom microarchiture ctrl signal 179 val customCtrl = Output(new CustomCSRCtrlIO) 180} 181 182class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst 183{ 184 val csrio = IO(new CSRFileIO) 185 186 val cfIn = io.in.bits.uop.cf 187 val cfOut = Wire(new CtrlFlow) 188 cfOut := cfIn 189 val flushPipe = Wire(Bool()) 190 191 val (valid, src1, src2, func) = ( 192 io.in.valid, 193 io.in.bits.src(0), 194 io.in.bits.uop.ctrl.imm, 195 io.in.bits.uop.ctrl.fuOpType 196 ) 197 198 // CSR define 199 200 class Priv extends Bundle { 201 val m = Output(Bool()) 202 val h = Output(Bool()) 203 val s = Output(Bool()) 204 val u = Output(Bool()) 205 } 206 207 val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U) 208 209 class MstatusStruct extends Bundle { 210 val sd = Output(UInt(1.W)) 211 212 val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null 213 val sxl = if (XLEN == 64) Output(UInt(2.W)) else null 214 val uxl = if (XLEN == 64) Output(UInt(2.W)) else null 215 val pad0 = if (XLEN == 64) Output(UInt(9.W)) else Output(UInt(8.W)) 216 217 val tsr = Output(UInt(1.W)) 218 val tw = Output(UInt(1.W)) 219 val tvm = Output(UInt(1.W)) 220 val mxr = Output(UInt(1.W)) 221 val sum = Output(UInt(1.W)) 222 val mprv = Output(UInt(1.W)) 223 val xs = Output(UInt(2.W)) 224 val fs = Output(UInt(2.W)) 225 val mpp = Output(UInt(2.W)) 226 val hpp = Output(UInt(2.W)) 227 val spp = Output(UInt(1.W)) 228 val pie = new Priv 229 val ie = new Priv 230 assert(this.getWidth == XLEN) 231 } 232 233 class SatpStruct extends Bundle { 234 val mode = UInt(4.W) 235 val asid = UInt(16.W) 236 val ppn = UInt(44.W) 237 } 238 239 class Interrupt extends Bundle { 240 val e = new Priv 241 val t = new Priv 242 val s = new Priv 243 } 244 245 // Machine-Level CSRs 246 247 val mtvec = RegInit(UInt(XLEN.W), 0.U) 248 val mcounteren = RegInit(UInt(XLEN.W), 0.U) 249 val mcause = RegInit(UInt(XLEN.W), 0.U) 250 val mtval = RegInit(UInt(XLEN.W), 0.U) 251 val mepc = Reg(UInt(XLEN.W)) 252 253 val mie = RegInit(0.U(XLEN.W)) 254 val mipWire = WireInit(0.U.asTypeOf(new Interrupt)) 255 val mipReg = RegInit(0.U.asTypeOf(new Interrupt).asUInt) 256 val mipFixMask = GenMask(9) | GenMask(5) | GenMask(1) 257 val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt) 258 259 def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}.asUInt() 260 def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}.asUInt() 261 var extList = List('a', 's', 'i', 'u') 262 if (HasMExtension) { extList = extList :+ 'm' } 263 if (HasCExtension) { extList = extList :+ 'c' } 264 if (HasFPU) { extList = extList ++ List('f', 'd') } 265 val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U 266 val misa = RegInit(UInt(XLEN.W), misaInitVal) 267 268 // MXL = 2 | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101 269 // (XLEN-1, XLEN-2) | |(25, 0) ZY XWVU TSRQ PONM LKJI HGFE DCBA 270 271 val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation 272 val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented 273 val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation 274 val mhartid = RegInit(UInt(XLEN.W), csrio.hartId) // the hardware thread running the code 275 val mstatus = RegInit(UInt(XLEN.W), 0.U) 276 277 // mstatus Value Table 278 // | sd | 279 // | pad1 | 280 // | sxl | hardlinked to 10, use 00 to pass xv6 test 281 // | uxl | hardlinked to 00 282 // | pad0 | 283 // | tsr | 284 // | tw | 285 // | tvm | 286 // | mxr | 287 // | sum | 288 // | mprv | 289 // | xs | 00 | 290 // | fs | 00 | 291 // | mpp | 00 | 292 // | hpp | 00 | 293 // | spp | 0 | 294 // | pie | 0000 | pie.h is used as UBE 295 // | ie | 0000 | uie hardlinked to 0, as N ext is not implemented 296 297 val mstatusStruct = mstatus.asTypeOf(new MstatusStruct) 298 def mstatusUpdateSideEffect(mstatus: UInt): UInt = { 299 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 300 val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0)) 301 mstatusNew 302 } 303 304 val mstatusMask = (~ZeroExt(( 305 GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) | 306 GenMask(37) | // MBE 307 GenMask(36) | // SBE 308 GenMask(6) // UBE 309 ), 64)).asUInt() 310 311 val medeleg = RegInit(UInt(XLEN.W), 0.U) 312 val mideleg = RegInit(UInt(XLEN.W), 0.U) 313 val mscratch = RegInit(UInt(XLEN.W), 0.U) 314 315 val pmpcfg0 = RegInit(UInt(XLEN.W), 0.U) 316 val pmpcfg1 = RegInit(UInt(XLEN.W), 0.U) 317 val pmpcfg2 = RegInit(UInt(XLEN.W), 0.U) 318 val pmpcfg3 = RegInit(UInt(XLEN.W), 0.U) 319 val pmpaddr0 = RegInit(UInt(XLEN.W), 0.U) 320 val pmpaddr1 = RegInit(UInt(XLEN.W), 0.U) 321 val pmpaddr2 = RegInit(UInt(XLEN.W), 0.U) 322 val pmpaddr3 = RegInit(UInt(XLEN.W), 0.U) 323 324 // Superviser-Level CSRs 325 326 // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U) 327 val sstatusWmask = "hc6122".U 328 // Sstatus Write Mask 329 // ------------------------------------------------------- 330 // 19 9 5 2 331 // 0 1100 0000 0001 0010 0010 332 // 0 c 0 1 2 2 333 // ------------------------------------------------------- 334 val sstatusRmask = sstatusWmask | "h8000000300018000".U 335 // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32)) 336 val stvec = RegInit(UInt(XLEN.W), 0.U) 337 // val sie = RegInit(0.U(XLEN.W)) 338 val sieMask = "h222".U & mideleg 339 val sipMask = "h222".U & mideleg 340 val satp = if(EnbaleTlbDebug) RegInit(UInt(XLEN.W), "h8000000000087fbe".U) else RegInit(0.U(XLEN.W)) 341 // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug 342 val satpMask = "h80000fffffffffff".U // disable asid, mode can only be 8 / 0 343 val sepc = RegInit(UInt(XLEN.W), 0.U) 344 val scause = RegInit(UInt(XLEN.W), 0.U) 345 val stval = Reg(UInt(XLEN.W)) 346 val sscratch = RegInit(UInt(XLEN.W), 0.U) 347 val scounteren = RegInit(UInt(XLEN.W), 0.U) 348 349 // sbpctl 350 // Bits 0-7: {LOOP, RAS, SC, TAGE, BIM, BTB, uBTB} 351 val sbpctl = RegInit(UInt(XLEN.W), "h7f".U) 352 csrio.customCtrl.bp_ctrl.ubtb_enable := sbpctl(0) 353 csrio.customCtrl.bp_ctrl.btb_enable := sbpctl(1) 354 csrio.customCtrl.bp_ctrl.bim_enable := sbpctl(2) 355 csrio.customCtrl.bp_ctrl.tage_enable := sbpctl(3) 356 csrio.customCtrl.bp_ctrl.sc_enable := sbpctl(4) 357 csrio.customCtrl.bp_ctrl.ras_enable := sbpctl(5) 358 csrio.customCtrl.bp_ctrl.loop_enable := sbpctl(6) 359 360 // spfctl Bit 0: L1plusCache Prefetcher Enable 361 // spfctl Bit 1: L2Cache Prefetcher Enable 362 val spfctl = RegInit(UInt(XLEN.W), "h3".U) 363 csrio.customCtrl.l1plus_pf_enable := spfctl(0) 364 csrio.customCtrl.l2_pf_enable := spfctl(1) 365 366 // sdsid: Differentiated Services ID 367 val sdsid = RegInit(UInt(XLEN.W), 0.U) 368 csrio.customCtrl.dsid := sdsid 369 370 // slvpredctl: load violation predict settings 371 val slvpredctl = RegInit(UInt(XLEN.W), "h70".U) // default reset period: 2^17 372 csrio.customCtrl.lvpred_disable := slvpredctl(0) 373 csrio.customCtrl.no_spec_load := slvpredctl(1) 374 csrio.customCtrl.waittable_timeout := slvpredctl(8, 4) 375 376 // smblockctl: memory block configurations 377 // bits 0-3: store buffer flush threshold (default: 8 entries) 378 val smblockctl = RegInit(UInt(XLEN.W), "hf".U & StoreBufferThreshold.U) 379 csrio.customCtrl.sbuffer_threshold := smblockctl(3, 0) 380 381 val srnctl = RegInit(UInt(XLEN.W), "h1".U) 382 csrio.customCtrl.move_elim_enable := srnctl(0) 383 384 val tlbBundle = Wire(new TlbCsrBundle) 385 tlbBundle.satp := satp.asTypeOf(new SatpStruct) 386 csrio.tlb := tlbBundle 387 388 // User-Level CSRs 389 val uepc = Reg(UInt(XLEN.W)) 390 391 // fcsr 392 class FcsrStruct extends Bundle { 393 val reserved = UInt((XLEN-3-5).W) 394 val frm = UInt(3.W) 395 val fflags = UInt(5.W) 396 assert(this.getWidth == XLEN) 397 } 398 val fcsr = RegInit(0.U(XLEN.W)) 399 // set mstatus->sd and mstatus->fs when true 400 val csrw_dirty_fp_state = WireInit(false.B) 401 402 def frm_wfn(wdata: UInt): UInt = { 403 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 404 csrw_dirty_fp_state := true.B 405 fcsrOld.frm := wdata(2,0) 406 fcsrOld.asUInt() 407 } 408 def frm_rfn(rdata: UInt): UInt = rdata(7,5) 409 410 def fflags_wfn(update: Boolean)(wdata: UInt): UInt = { 411 val fcsrOld = fcsr.asTypeOf(new FcsrStruct) 412 val fcsrNew = WireInit(fcsrOld) 413 csrw_dirty_fp_state := true.B 414 if (update) { 415 fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags 416 } else { 417 fcsrNew.fflags := wdata(4,0) 418 } 419 fcsrNew.asUInt() 420 } 421 def fflags_rfn(rdata:UInt): UInt = rdata(4,0) 422 423 def fcsr_wfn(wdata: UInt): UInt = { 424 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 425 csrw_dirty_fp_state := true.B 426 Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags) 427 } 428 429 val fcsrMapping = Map( 430 MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn), 431 MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn), 432 MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn) 433 ) 434 435 // Atom LR/SC Control Bits 436 // val setLr = WireInit(Bool(), false.B) 437 // val setLrVal = WireInit(Bool(), false.B) 438 // val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check 439 // val lr = RegInit(Bool(), false.B) 440 // val lrAddr = RegInit(UInt(AddrBits.W), 0.U) 441 // 442 // when (setLr) { 443 // lr := setLrVal 444 // lrAddr := setLrAddr 445 // } 446 447 // Hart Priviledge Mode 448 val priviledgeMode = RegInit(UInt(2.W), ModeM) 449 450 // Emu perfcnt 451 val hasEmuPerfCnt = !env.FPGAPlatform 452 val nrEmuPerfCnts = if (hasEmuPerfCnt) 0x80 else 0x3 453 454 val emuPerfCnts = List.fill(nrEmuPerfCnts)(RegInit(0.U(XLEN.W))) 455 val emuPerfCntCond = List.fill(nrEmuPerfCnts)(WireInit(false.B)) 456 (emuPerfCnts zip emuPerfCntCond).map { case (c, e) => when (e) { c := c + 1.U } } 457 458 val emuPerfCntsLoMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1000 + i, emuPerfCnts(i))) 459 val emuPerfCntsHiMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1080 + i, emuPerfCnts(i)(63, 32))) 460 println(s"CSR: hasEmuPerfCnt:${hasEmuPerfCnt}") 461 462 // Perf Counter 463 val nrPerfCnts = 29 // 3...31 464 val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W))) 465 val perfEvents = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W))) 466 val mcountinhibit = RegInit(0.U(XLEN.W)) 467 val mcycle = RegInit(0.U(XLEN.W)) 468 mcycle := mcycle + 1.U 469 val minstret = RegInit(0.U(XLEN.W)) 470 minstret := minstret + RegNext(csrio.perf.retiredInstr) 471 val ibufFull = RegInit(0.U(XLEN.W)) 472 ibufFull := ibufFull + RegNext(csrio.perf.frontendInfo.ibufFull) 473 val roqFull = RegInit(0.U(XLEN.W)) 474 roqFull := roqFull + RegNext(csrio.perf.ctrlInfo.roqFull) 475 val intdqFull = RegInit(0.U(XLEN.W)) 476 intdqFull := intdqFull + RegNext(csrio.perf.ctrlInfo.intdqFull) 477 val fpdqFull = RegInit(0.U(XLEN.W)) 478 fpdqFull := fpdqFull + RegNext(csrio.perf.ctrlInfo.fpdqFull) 479 val lsdqFull = RegInit(0.U(XLEN.W)) 480 lsdqFull := lsdqFull + RegNext(csrio.perf.ctrlInfo.lsdqFull) 481 val sqFull = RegInit(0.U(XLEN.W)) 482 sqFull := sqFull + RegNext(csrio.perf.memInfo.sqFull) 483 val lqFull = RegInit(0.U(XLEN.W)) 484 lqFull := lqFull + RegNext(csrio.perf.memInfo.lqFull) 485 val dcacheMSHRFull = RegInit(0.U(XLEN.W)) 486 dcacheMSHRFull := dcacheMSHRFull + RegNext(csrio.perf.memInfo.dcacheMSHRFull) 487 val bpRight = RegInit(0.U(XLEN.W)) 488 bpRight := bpRight + RegNext(csrio.perf.bpuInfo.bpRight) 489 val bpWrong = RegInit(0.U(XLEN.W)) 490 bpWrong := bpWrong + RegNext(csrio.perf.bpuInfo.bpWrong) 491 492 // CSR reg map 493 val basicPrivMapping = Map( 494 495 //--- User Trap Setup --- 496 // MaskedRegMap(Ustatus, ustatus), 497 // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable), 498 // MaskedRegMap(Utvec, utvec), 499 500 //--- User Trap Handling --- 501 // MaskedRegMap(Uscratch, uscratch), 502 // MaskedRegMap(Uepc, uepc), 503 // MaskedRegMap(Ucause, ucause), 504 // MaskedRegMap(Utval, utval), 505 // MaskedRegMap(Uip, uip), 506 507 //--- User Counter/Timers --- 508 // MaskedRegMap(Cycle, cycle), 509 // MaskedRegMap(Time, time), 510 // MaskedRegMap(Instret, instret), 511 512 //--- Supervisor Trap Setup --- 513 MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask), 514 // MaskedRegMap(Sedeleg, Sedeleg), 515 // MaskedRegMap(Sideleg, Sideleg), 516 MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask), 517 MaskedRegMap(Stvec, stvec), 518 MaskedRegMap(Scounteren, scounteren), 519 520 //--- Supervisor Trap Handling --- 521 MaskedRegMap(Sscratch, sscratch), 522 MaskedRegMap(Sepc, sepc), 523 MaskedRegMap(Scause, scause), 524 MaskedRegMap(Stval, stval), 525 MaskedRegMap(Sip, mip.asUInt, sipMask, MaskedRegMap.Unwritable, sipMask), 526 527 //--- Supervisor Protection and Translation --- 528 MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask), 529 530 //--- Supervisor Custom Read/Write Registers 531 MaskedRegMap(Sbpctl, sbpctl), 532 MaskedRegMap(Spfctl, spfctl), 533 MaskedRegMap(Sdsid, sdsid), 534 MaskedRegMap(Slvpredctl, slvpredctl), 535 MaskedRegMap(Smblockctl, smblockctl), 536 MaskedRegMap(Srnctl, srnctl), 537 538 //--- Machine Information Registers --- 539 MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable), 540 MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable), 541 MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable), 542 MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable), 543 544 //--- Machine Trap Setup --- 545 MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask), 546 MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable 547 MaskedRegMap(Medeleg, medeleg, "hf3ff".U), 548 MaskedRegMap(Mideleg, mideleg, "h222".U), 549 MaskedRegMap(Mie, mie), 550 MaskedRegMap(Mtvec, mtvec), 551 MaskedRegMap(Mcounteren, mcounteren), 552 553 //--- Machine Trap Handling --- 554 MaskedRegMap(Mscratch, mscratch), 555 MaskedRegMap(Mepc, mepc), 556 MaskedRegMap(Mcause, mcause), 557 MaskedRegMap(Mtval, mtval), 558 MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable), 559 ) 560 561 // PMP is unimplemented yet 562 val pmpMapping = Map( 563 MaskedRegMap(Pmpcfg0, pmpcfg0), 564 MaskedRegMap(Pmpcfg1, pmpcfg1), 565 MaskedRegMap(Pmpcfg2, pmpcfg2), 566 MaskedRegMap(Pmpcfg3, pmpcfg3), 567 MaskedRegMap(PmpaddrBase + 0, pmpaddr0), 568 MaskedRegMap(PmpaddrBase + 1, pmpaddr1), 569 MaskedRegMap(PmpaddrBase + 2, pmpaddr2), 570 MaskedRegMap(PmpaddrBase + 3, pmpaddr3) 571 ) 572 573 var perfCntMapping = Map( 574 MaskedRegMap(Mcountinhibit, mcountinhibit), 575 MaskedRegMap(Mcycle, mcycle), 576 MaskedRegMap(Minstret, minstret), 577 MaskedRegMap(Mhpmevent3, ibufFull), 578 MaskedRegMap(Mhpmevent4, roqFull), 579 MaskedRegMap(Mhpmevent5, intdqFull), 580 MaskedRegMap(Mhpmevent6, fpdqFull), 581 MaskedRegMap(Mhpmevent7, lsdqFull), 582 MaskedRegMap(Mhpmevent8, sqFull), 583 MaskedRegMap(Mhpmevent9, lqFull), 584 MaskedRegMap(Mhpmevent10, dcacheMSHRFull), 585 MaskedRegMap(Mhpmevent11, bpRight), 586 MaskedRegMap(Mhpmevent12, bpWrong), 587 ) 588 // TODO: mechanism should be implemented later 589 // val MhpmcounterStart = Mhpmcounter3 590 // val MhpmeventStart = Mhpmevent3 591 // for (i <- 0 until nrPerfCnts) { 592 // perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i)) 593 // perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i)) 594 // } 595 596 val mapping = basicPrivMapping ++ 597 perfCntMapping ++ 598 pmpMapping ++ 599 emuPerfCntsLoMapping ++ 600 (if (XLEN == 32) emuPerfCntsHiMapping else Nil) ++ 601 (if (HasFPU) fcsrMapping else Nil) 602 603 val addr = src2(11, 0) 604 val csri = ZeroExt(src2(16, 12), XLEN) 605 val rdata = Wire(UInt(XLEN.W)) 606 val wdata = LookupTree(func, List( 607 CSROpType.wrt -> src1, 608 CSROpType.set -> (rdata | src1), 609 CSROpType.clr -> (rdata & (~src1).asUInt()), 610 CSROpType.wrti -> csri, 611 CSROpType.seti -> (rdata | csri), 612 CSROpType.clri -> (rdata & (~csri).asUInt()) 613 )) 614 615 val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U) 616 csrio.isPerfCnt := addrInPerfCnt 617 618 // satp wen check 619 val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U) 620 621 // general CSR wen check 622 val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode) 623 val modePermitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode) 624 val perfcntPermitted = perfcntPermissionCheck(addr, priviledgeMode, mcounteren, scounteren) 625 val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) 626 // Writeable check is ingored. 627 // Currently, write to illegal csr addr will be ignored 628 MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata) 629 io.out.bits.data := rdata 630 io.out.bits.uop := io.in.bits.uop 631 io.out.bits.uop.cf := cfOut 632 io.out.bits.uop.ctrl.flushPipe := flushPipe 633 634 // Fix Mip/Sip write 635 val fixMapping = Map( 636 MaskedRegMap(Mip, mipReg.asUInt, mipFixMask), 637 MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask) 638 ) 639 val rdataDummy = Wire(UInt(XLEN.W)) 640 MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata) 641 642 when (csrio.fpu.fflags.valid) { 643 fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits) 644 } 645 // set fs and sd in mstatus 646 when (csrw_dirty_fp_state || csrio.fpu.dirty_fs) { 647 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 648 mstatusNew.fs := "b11".U 649 mstatusNew.sd := true.B 650 mstatus := mstatusNew.asUInt() 651 } 652 csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm 653 654 // CSR inst decode 655 val isEbreak = addr === privEbreak && func === CSROpType.jmp 656 val isEcall = addr === privEcall && func === CSROpType.jmp 657 val isMret = addr === privMret && func === CSROpType.jmp 658 val isSret = addr === privSret && func === CSROpType.jmp 659 val isUret = addr === privUret && func === CSROpType.jmp 660 661 XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func) 662 XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode) 663 664 // Illegal priviledged operation list 665 val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool 666 667 // Illegal priviledged instruction check 668 val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr) 669 val isIllegalAccess = !permitted 670 val isIllegalPrivOp = illegalSModeSret 671 672 // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) 673 // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex)) 674 // imem 675 // val imemPtev = true.B 676 // val imemPteu = true.B 677 // val imemPtex = true.B 678 // val imemReq = true.B 679 // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu) 680 // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex) 681 // assert(!hasInstrPageFault) 682 683 // dmem 684 // val dmemPtev = true.B 685 // val dmemPteu = true.B 686 // val dmemReq = true.B 687 // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu) 688 // val dmemIsStore = true.B 689 690 // val hasLoadPageFault = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed) 691 // val hasStorePageFault = dmemReq && dmemIsStore && !(dmemPermissionCheckPassed) 692 // assert(!hasLoadPageFault) 693 // assert(!hasStorePageFault) 694 695 //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet 696 tlbBundle.priv.mxr := mstatusStruct.mxr.asBool 697 tlbBundle.priv.sum := mstatusStruct.sum.asBool 698 tlbBundle.priv.imode := priviledgeMode 699 tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode) 700 701 // Branch control 702 val retTarget = Wire(UInt(VAddrBits.W)) 703 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 704 flushPipe := resetSatp || (valid && func === CSROpType.jmp && !isEcall) 705 706 retTarget := DontCare 707 // val illegalEret = TODO 708 709 when (valid && isMret) { 710 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 711 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 712 mstatusNew.ie.m := mstatusOld.pie.m 713 priviledgeMode := mstatusOld.mpp 714 mstatusNew.pie.m := true.B 715 mstatusNew.mpp := ModeU 716 mstatusNew.mprv := 0.U 717 mstatus := mstatusNew.asUInt 718 // lr := false.B 719 retTarget := mepc(VAddrBits-1, 0) 720 } 721 722 when (valid && isSret && !illegalSModeSret) { 723 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 724 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 725 mstatusNew.ie.s := mstatusOld.pie.s 726 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 727 mstatusNew.pie.s := true.B 728 mstatusNew.spp := ModeU 729 mstatus := mstatusNew.asUInt 730 mstatusNew.mprv := 0.U 731 // lr := false.B 732 retTarget := sepc(VAddrBits-1, 0) 733 } 734 735 when (valid && isUret) { 736 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 737 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 738 // mstatusNew.mpp.m := ModeU //TODO: add mode U 739 mstatusNew.ie.u := mstatusOld.pie.u 740 priviledgeMode := ModeU 741 mstatusNew.pie.u := true.B 742 mstatus := mstatusNew.asUInt 743 retTarget := uepc(VAddrBits-1, 0) 744 } 745 746 io.in.ready := true.B 747 io.out.valid := valid 748 749 val csrExceptionVec = WireInit(cfIn.exceptionVec) 750 csrExceptionVec(breakPoint) := io.in.valid && isEbreak 751 csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall 752 csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall 753 csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall 754 // Trigger an illegal instr exception when: 755 // * unimplemented csr is being read/written 756 // * csr access is illegal 757 csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen 758 cfOut.exceptionVec := csrExceptionVec 759 760 /** 761 * Exception and Intr 762 */ 763 val ideleg = (mideleg & mip.asUInt) 764 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 765 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 766 767 // send interrupt information to ROQ 768 val intrVecEnable = Wire(Vec(12, Bool())) 769 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 770 val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt 771 val intrBitSet = intrVec.orR() 772 csrio.interrupt := intrBitSet 773 mipWire.t.m := csrio.externalInterrupt.mtip 774 mipWire.s.m := csrio.externalInterrupt.msip 775 mipWire.e.m := csrio.externalInterrupt.meip 776 777 // interrupts 778 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 779 val raiseIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt 780 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.uop.cf.pc, intrNO) 781 782 // exceptions 783 val raiseException = csrio.exception.valid && !csrio.exception.bits.isInterrupt 784 val hasInstrPageFault = csrio.exception.bits.uop.cf.exceptionVec(instrPageFault) && raiseException 785 val hasLoadPageFault = csrio.exception.bits.uop.cf.exceptionVec(loadPageFault) && raiseException 786 val hasStorePageFault = csrio.exception.bits.uop.cf.exceptionVec(storePageFault) && raiseException 787 val hasStoreAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(storeAddrMisaligned) && raiseException 788 val hasLoadAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(loadAddrMisaligned) && raiseException 789 val hasInstrAccessFault = csrio.exception.bits.uop.cf.exceptionVec(instrAccessFault) && raiseException 790 val hasLoadAccessFault = csrio.exception.bits.uop.cf.exceptionVec(loadAccessFault) && raiseException 791 val hasStoreAccessFault = csrio.exception.bits.uop.cf.exceptionVec(storeAccessFault) && raiseException 792 793 val raiseExceptionVec = csrio.exception.bits.uop.cf.exceptionVec 794 val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum)) 795 val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO) 796 797 val raiseExceptionIntr = csrio.exception.valid 798 XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n", 799 csrio.exception.bits.uop.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt 800 ) 801 XSDebug(raiseExceptionIntr, 802 "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", 803 csrio.exception.bits.uop.cf.pc, 804 mstatus, 805 mideleg, 806 medeleg, 807 priviledgeMode 808 ) 809 810 // mtval write logic 811 val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN) 812 when (hasInstrPageFault || hasLoadPageFault || hasStorePageFault) { 813 val tval = Mux( 814 hasInstrPageFault, 815 Mux( 816 csrio.exception.bits.uop.cf.crossPageIPFFix, 817 SignExt(csrio.exception.bits.uop.cf.pc + 2.U, XLEN), 818 SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 819 ), 820 memExceptionAddr 821 ) 822 when (priviledgeMode === ModeM) { 823 mtval := tval 824 }.otherwise { 825 stval := tval 826 } 827 } 828 829 when (hasLoadAddrMisaligned || hasStoreAddrMisaligned) { 830 mtval := memExceptionAddr 831 } 832 833 val deleg = Mux(raiseIntr, mideleg , medeleg) 834 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 835 val delegS = deleg(causeNO(3,0)) && (priviledgeMode < ModeM) 836 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check 837 val isXRet = io.in.valid && func === CSROpType.jmp && !isEcall 838 839 // ctrl block will use theses later for flush 840 val isXRetFlag = RegInit(false.B) 841 val retTargetReg = Reg(retTarget.cloneType) 842 when (io.flushIn) { 843 isXRetFlag := false.B 844 }.elsewhen (isXRet) { 845 isXRetFlag := true.B 846 retTargetReg := retTarget 847 } 848 csrio.isXRet := isXRetFlag 849 csrio.trapTarget := Mux(isXRetFlag, 850 retTargetReg, 851 Mux(delegS, stvec, mtvec)(VAddrBits-1, 0) 852 ) 853 854 when (raiseExceptionIntr) { 855 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 856 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 857 858 when (delegS) { 859 scause := causeNO 860 sepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 861 mstatusNew.spp := priviledgeMode 862 mstatusNew.pie.s := mstatusOld.ie.s 863 mstatusNew.ie.s := false.B 864 priviledgeMode := ModeS 865 when (tvalWen) { stval := 0.U } 866 }.otherwise { 867 mcause := causeNO 868 mepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 869 mstatusNew.mpp := priviledgeMode 870 mstatusNew.pie.m := mstatusOld.ie.m 871 mstatusNew.ie.m := false.B 872 priviledgeMode := ModeM 873 when (tvalWen) { mtval := 0.U } 874 } 875 876 mstatus := mstatusNew.asUInt 877 } 878 879 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc) 880 881 def readWithScala(addr: Int): UInt = mapping(addr)._1 882 883 val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U) 884 885 if (!env.FPGAPlatform) { 886 val difftest = Module(new DifftestArchEvent) 887 difftest.io.clock := clock 888 difftest.io.coreid := hardId.U 889 difftest.io.intrNO := RegNext(difftestIntrNO) 890 difftest.io.cause := RegNext(Mux(csrio.exception.valid, causeNO, 0.U)) 891 difftest.io.exceptionPC := RegNext(SignExt(csrio.exception.bits.uop.cf.pc, XLEN)) 892 } 893 894 if (!env.FPGAPlatform) { 895 val difftest = Module(new DifftestCSRState) 896 difftest.io.clock := clock 897 difftest.io.coreid := hardId.U 898 difftest.io.priviledgeMode := priviledgeMode 899 difftest.io.mstatus := mstatus 900 difftest.io.sstatus := mstatus & sstatusRmask 901 difftest.io.mepc := mepc 902 difftest.io.sepc := sepc 903 difftest.io.mtval:= mtval 904 difftest.io.stval:= stval 905 difftest.io.mtvec := mtvec 906 difftest.io.stvec := stvec 907 difftest.io.mcause := mcause 908 difftest.io.scause := scause 909 difftest.io.satp := satp 910 difftest.io.mip := mipReg 911 difftest.io.mie := mie 912 difftest.io.mscratch := mscratch 913 difftest.io.sscratch := sscratch 914 difftest.io.mideleg := mideleg 915 difftest.io.medeleg := medeleg 916 } 917} 918