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 sipWMask = "h2".U // ssip is writeable in smode 341 val satp = if(EnbaleTlbDebug) RegInit(UInt(XLEN.W), "h8000000000087fbe".U) else RegInit(0.U(XLEN.W)) 342 // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug 343 val satpMask = "h80000fffffffffff".U // disable asid, mode can only be 8 / 0 344 val sepc = RegInit(UInt(XLEN.W), 0.U) 345 val scause = RegInit(UInt(XLEN.W), 0.U) 346 val stval = Reg(UInt(XLEN.W)) 347 val sscratch = RegInit(UInt(XLEN.W), 0.U) 348 val scounteren = RegInit(UInt(XLEN.W), 0.U) 349 350 // sbpctl 351 // Bits 0-7: {LOOP, RAS, SC, TAGE, BIM, BTB, uBTB} 352 val sbpctl = RegInit(UInt(XLEN.W), "h7f".U) 353 csrio.customCtrl.bp_ctrl.ubtb_enable := sbpctl(0) 354 csrio.customCtrl.bp_ctrl.btb_enable := sbpctl(1) 355 csrio.customCtrl.bp_ctrl.bim_enable := sbpctl(2) 356 csrio.customCtrl.bp_ctrl.tage_enable := sbpctl(3) 357 csrio.customCtrl.bp_ctrl.sc_enable := sbpctl(4) 358 csrio.customCtrl.bp_ctrl.ras_enable := sbpctl(5) 359 csrio.customCtrl.bp_ctrl.loop_enable := sbpctl(6) 360 361 // spfctl Bit 0: L1plusCache Prefetcher Enable 362 // spfctl Bit 1: L2Cache Prefetcher Enable 363 val spfctl = RegInit(UInt(XLEN.W), "h3".U) 364 csrio.customCtrl.l1plus_pf_enable := spfctl(0) 365 csrio.customCtrl.l2_pf_enable := spfctl(1) 366 367 // sdsid: Differentiated Services ID 368 val sdsid = RegInit(UInt(XLEN.W), 0.U) 369 csrio.customCtrl.dsid := sdsid 370 371 // slvpredctl: load violation predict settings 372 val slvpredctl = RegInit(UInt(XLEN.W), "h70".U) // default reset period: 2^17 373 csrio.customCtrl.lvpred_disable := slvpredctl(0) 374 csrio.customCtrl.no_spec_load := slvpredctl(1) 375 csrio.customCtrl.waittable_timeout := slvpredctl(8, 4) 376 377 // smblockctl: memory block configurations 378 // bits 0-3: store buffer flush threshold (default: 8 entries) 379 val smblockctl = RegInit(UInt(XLEN.W), "hf".U & StoreBufferThreshold.U) 380 csrio.customCtrl.sbuffer_threshold := smblockctl(3, 0) 381 382 val srnctl = RegInit(UInt(XLEN.W), "h1".U) 383 csrio.customCtrl.move_elim_enable := srnctl(0) 384 385 val tlbBundle = Wire(new TlbCsrBundle) 386 tlbBundle.satp := satp.asTypeOf(new SatpStruct) 387 csrio.tlb := tlbBundle 388 389 // User-Level CSRs 390 val uepc = Reg(UInt(XLEN.W)) 391 392 // fcsr 393 class FcsrStruct extends Bundle { 394 val reserved = UInt((XLEN-3-5).W) 395 val frm = UInt(3.W) 396 val fflags = UInt(5.W) 397 assert(this.getWidth == XLEN) 398 } 399 val fcsr = RegInit(0.U(XLEN.W)) 400 // set mstatus->sd and mstatus->fs when true 401 val csrw_dirty_fp_state = WireInit(false.B) 402 403 def frm_wfn(wdata: UInt): UInt = { 404 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 405 csrw_dirty_fp_state := true.B 406 fcsrOld.frm := wdata(2,0) 407 fcsrOld.asUInt() 408 } 409 def frm_rfn(rdata: UInt): UInt = rdata(7,5) 410 411 def fflags_wfn(update: Boolean)(wdata: UInt): UInt = { 412 val fcsrOld = fcsr.asTypeOf(new FcsrStruct) 413 val fcsrNew = WireInit(fcsrOld) 414 csrw_dirty_fp_state := true.B 415 if (update) { 416 fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags 417 } else { 418 fcsrNew.fflags := wdata(4,0) 419 } 420 fcsrNew.asUInt() 421 } 422 def fflags_rfn(rdata:UInt): UInt = rdata(4,0) 423 424 def fcsr_wfn(wdata: UInt): UInt = { 425 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 426 csrw_dirty_fp_state := true.B 427 Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags) 428 } 429 430 val fcsrMapping = Map( 431 MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn), 432 MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn), 433 MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn) 434 ) 435 436 // Atom LR/SC Control Bits 437 // val setLr = WireInit(Bool(), false.B) 438 // val setLrVal = WireInit(Bool(), false.B) 439 // val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check 440 // val lr = RegInit(Bool(), false.B) 441 // val lrAddr = RegInit(UInt(AddrBits.W), 0.U) 442 // 443 // when (setLr) { 444 // lr := setLrVal 445 // lrAddr := setLrAddr 446 // } 447 448 // Hart Priviledge Mode 449 val priviledgeMode = RegInit(UInt(2.W), ModeM) 450 451 // Emu perfcnt 452 val hasEmuPerfCnt = !env.FPGAPlatform 453 val nrEmuPerfCnts = if (hasEmuPerfCnt) 0x80 else 0x3 454 455 val emuPerfCnts = List.fill(nrEmuPerfCnts)(RegInit(0.U(XLEN.W))) 456 val emuPerfCntCond = List.fill(nrEmuPerfCnts)(WireInit(false.B)) 457 (emuPerfCnts zip emuPerfCntCond).map { case (c, e) => when (e) { c := c + 1.U } } 458 459 val emuPerfCntsLoMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1000 + i, emuPerfCnts(i))) 460 val emuPerfCntsHiMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1080 + i, emuPerfCnts(i)(63, 32))) 461 println(s"CSR: hasEmuPerfCnt:${hasEmuPerfCnt}") 462 463 // Perf Counter 464 val nrPerfCnts = 29 // 3...31 465 val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W))) 466 val perfEvents = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W))) 467 val mcountinhibit = RegInit(0.U(XLEN.W)) 468 val mcycle = RegInit(0.U(XLEN.W)) 469 mcycle := mcycle + 1.U 470 val minstret = RegInit(0.U(XLEN.W)) 471 minstret := minstret + RegNext(csrio.perf.retiredInstr) 472 val ibufFull = RegInit(0.U(XLEN.W)) 473 ibufFull := ibufFull + RegNext(csrio.perf.frontendInfo.ibufFull) 474 val roqFull = RegInit(0.U(XLEN.W)) 475 roqFull := roqFull + RegNext(csrio.perf.ctrlInfo.roqFull) 476 val intdqFull = RegInit(0.U(XLEN.W)) 477 intdqFull := intdqFull + RegNext(csrio.perf.ctrlInfo.intdqFull) 478 val fpdqFull = RegInit(0.U(XLEN.W)) 479 fpdqFull := fpdqFull + RegNext(csrio.perf.ctrlInfo.fpdqFull) 480 val lsdqFull = RegInit(0.U(XLEN.W)) 481 lsdqFull := lsdqFull + RegNext(csrio.perf.ctrlInfo.lsdqFull) 482 val sqFull = RegInit(0.U(XLEN.W)) 483 sqFull := sqFull + RegNext(csrio.perf.memInfo.sqFull) 484 val lqFull = RegInit(0.U(XLEN.W)) 485 lqFull := lqFull + RegNext(csrio.perf.memInfo.lqFull) 486 val dcacheMSHRFull = RegInit(0.U(XLEN.W)) 487 dcacheMSHRFull := dcacheMSHRFull + RegNext(csrio.perf.memInfo.dcacheMSHRFull) 488 val bpRight = RegInit(0.U(XLEN.W)) 489 bpRight := bpRight + RegNext(csrio.perf.bpuInfo.bpRight) 490 val bpWrong = RegInit(0.U(XLEN.W)) 491 bpWrong := bpWrong + RegNext(csrio.perf.bpuInfo.bpWrong) 492 493 // CSR reg map 494 val basicPrivMapping = Map( 495 496 //--- User Trap Setup --- 497 // MaskedRegMap(Ustatus, ustatus), 498 // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable), 499 // MaskedRegMap(Utvec, utvec), 500 501 //--- User Trap Handling --- 502 // MaskedRegMap(Uscratch, uscratch), 503 // MaskedRegMap(Uepc, uepc), 504 // MaskedRegMap(Ucause, ucause), 505 // MaskedRegMap(Utval, utval), 506 // MaskedRegMap(Uip, uip), 507 508 //--- User Counter/Timers --- 509 // MaskedRegMap(Cycle, cycle), 510 // MaskedRegMap(Time, time), 511 // MaskedRegMap(Instret, instret), 512 513 //--- Supervisor Trap Setup --- 514 MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask), 515 // MaskedRegMap(Sedeleg, Sedeleg), 516 // MaskedRegMap(Sideleg, Sideleg), 517 MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask), 518 MaskedRegMap(Stvec, stvec), 519 MaskedRegMap(Scounteren, scounteren), 520 521 //--- Supervisor Trap Handling --- 522 MaskedRegMap(Sscratch, sscratch), 523 MaskedRegMap(Sepc, sepc), 524 MaskedRegMap(Scause, scause), 525 MaskedRegMap(Stval, stval), 526 MaskedRegMap(Sip, mip.asUInt, sipWMask, MaskedRegMap.Unwritable, sipMask), 527 528 //--- Supervisor Protection and Translation --- 529 MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask), 530 531 //--- Supervisor Custom Read/Write Registers 532 MaskedRegMap(Sbpctl, sbpctl), 533 MaskedRegMap(Spfctl, spfctl), 534 MaskedRegMap(Sdsid, sdsid), 535 MaskedRegMap(Slvpredctl, slvpredctl), 536 MaskedRegMap(Smblockctl, smblockctl), 537 MaskedRegMap(Srnctl, srnctl), 538 539 //--- Machine Information Registers --- 540 MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable), 541 MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable), 542 MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable), 543 MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable), 544 545 //--- Machine Trap Setup --- 546 MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask), 547 MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable 548 MaskedRegMap(Medeleg, medeleg, "hf3ff".U), 549 MaskedRegMap(Mideleg, mideleg, "h222".U), 550 MaskedRegMap(Mie, mie), 551 MaskedRegMap(Mtvec, mtvec), 552 MaskedRegMap(Mcounteren, mcounteren), 553 554 //--- Machine Trap Handling --- 555 MaskedRegMap(Mscratch, mscratch), 556 MaskedRegMap(Mepc, mepc), 557 MaskedRegMap(Mcause, mcause), 558 MaskedRegMap(Mtval, mtval), 559 MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable), 560 ) 561 562 // PMP is unimplemented yet 563 val pmpMapping = Map( 564 MaskedRegMap(Pmpcfg0, pmpcfg0), 565 MaskedRegMap(Pmpcfg1, pmpcfg1), 566 MaskedRegMap(Pmpcfg2, pmpcfg2), 567 MaskedRegMap(Pmpcfg3, pmpcfg3), 568 MaskedRegMap(PmpaddrBase + 0, pmpaddr0), 569 MaskedRegMap(PmpaddrBase + 1, pmpaddr1), 570 MaskedRegMap(PmpaddrBase + 2, pmpaddr2), 571 MaskedRegMap(PmpaddrBase + 3, pmpaddr3) 572 ) 573 574 var perfCntMapping = Map( 575 MaskedRegMap(Mcountinhibit, mcountinhibit), 576 MaskedRegMap(Mcycle, mcycle), 577 MaskedRegMap(Minstret, minstret), 578 MaskedRegMap(Mhpmevent3, ibufFull), 579 MaskedRegMap(Mhpmevent4, roqFull), 580 MaskedRegMap(Mhpmevent5, intdqFull), 581 MaskedRegMap(Mhpmevent6, fpdqFull), 582 MaskedRegMap(Mhpmevent7, lsdqFull), 583 MaskedRegMap(Mhpmevent8, sqFull), 584 MaskedRegMap(Mhpmevent9, lqFull), 585 MaskedRegMap(Mhpmevent10, dcacheMSHRFull), 586 MaskedRegMap(Mhpmevent11, bpRight), 587 MaskedRegMap(Mhpmevent12, bpWrong), 588 ) 589 // TODO: mechanism should be implemented later 590 // val MhpmcounterStart = Mhpmcounter3 591 // val MhpmeventStart = Mhpmevent3 592 // for (i <- 0 until nrPerfCnts) { 593 // perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i)) 594 // perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i)) 595 // } 596 597 val mapping = basicPrivMapping ++ 598 perfCntMapping ++ 599 pmpMapping ++ 600 emuPerfCntsLoMapping ++ 601 (if (XLEN == 32) emuPerfCntsHiMapping else Nil) ++ 602 (if (HasFPU) fcsrMapping else Nil) 603 604 val addr = src2(11, 0) 605 val csri = ZeroExt(src2(16, 12), XLEN) 606 val rdata = Wire(UInt(XLEN.W)) 607 val wdata = LookupTree(func, List( 608 CSROpType.wrt -> src1, 609 CSROpType.set -> (rdata | src1), 610 CSROpType.clr -> (rdata & (~src1).asUInt()), 611 CSROpType.wrti -> csri, 612 CSROpType.seti -> (rdata | csri), 613 CSROpType.clri -> (rdata & (~csri).asUInt()) 614 )) 615 616 val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U) 617 csrio.isPerfCnt := addrInPerfCnt 618 619 // satp wen check 620 val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U) 621 622 // general CSR wen check 623 val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode) 624 val modePermitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode) 625 val perfcntPermitted = perfcntPermissionCheck(addr, priviledgeMode, mcounteren, scounteren) 626 val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) 627 // Writeable check is ingored. 628 // Currently, write to illegal csr addr will be ignored 629 MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata) 630 io.out.bits.data := rdata 631 io.out.bits.uop := io.in.bits.uop 632 io.out.bits.uop.cf := cfOut 633 io.out.bits.uop.ctrl.flushPipe := flushPipe 634 635 // Fix Mip/Sip write 636 val fixMapping = Map( 637 MaskedRegMap(Mip, mipReg.asUInt, mipFixMask), 638 MaskedRegMap(Sip, mipReg.asUInt, sipWMask, MaskedRegMap.NoSideEffect, sipMask) 639 ) 640 val rdataFix = Wire(UInt(XLEN.W)) 641 val wdataFix = LookupTree(func, List( 642 CSROpType.wrt -> src1, 643 CSROpType.set -> (rdataFix | src1), 644 CSROpType.clr -> (rdataFix & (~src1).asUInt()), 645 CSROpType.wrti -> csri, 646 CSROpType.seti -> (rdataFix | csri), 647 CSROpType.clri -> (rdataFix & (~csri).asUInt()) 648 )) 649 MaskedRegMap.generate(fixMapping, addr, rdataFix, wen && permitted, wdataFix) 650 651 when (csrio.fpu.fflags.valid) { 652 fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits) 653 } 654 // set fs and sd in mstatus 655 when (csrw_dirty_fp_state || csrio.fpu.dirty_fs) { 656 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 657 mstatusNew.fs := "b11".U 658 mstatusNew.sd := true.B 659 mstatus := mstatusNew.asUInt() 660 } 661 csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm 662 663 // CSR inst decode 664 val isEbreak = addr === privEbreak && func === CSROpType.jmp 665 val isEcall = addr === privEcall && func === CSROpType.jmp 666 val isMret = addr === privMret && func === CSROpType.jmp 667 val isSret = addr === privSret && func === CSROpType.jmp 668 val isUret = addr === privUret && func === CSROpType.jmp 669 670 XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func) 671 XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode) 672 673 // Illegal priviledged operation list 674 val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool 675 676 // Illegal priviledged instruction check 677 val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr) 678 val isIllegalAccess = !permitted 679 val isIllegalPrivOp = illegalSModeSret 680 681 // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) 682 // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex)) 683 // imem 684 // val imemPtev = true.B 685 // val imemPteu = true.B 686 // val imemPtex = true.B 687 // val imemReq = true.B 688 // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu) 689 // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex) 690 // assert(!hasInstrPageFault) 691 692 // dmem 693 // val dmemPtev = true.B 694 // val dmemPteu = true.B 695 // val dmemReq = true.B 696 // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu) 697 // val dmemIsStore = true.B 698 699 // val hasLoadPageFault = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed) 700 // val hasStorePageFault = dmemReq && dmemIsStore && !(dmemPermissionCheckPassed) 701 // assert(!hasLoadPageFault) 702 // assert(!hasStorePageFault) 703 704 //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet 705 tlbBundle.priv.mxr := mstatusStruct.mxr.asBool 706 tlbBundle.priv.sum := mstatusStruct.sum.asBool 707 tlbBundle.priv.imode := priviledgeMode 708 tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode) 709 710 // Branch control 711 val retTarget = Wire(UInt(VAddrBits.W)) 712 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 713 flushPipe := resetSatp || (valid && func === CSROpType.jmp && !isEcall) 714 715 retTarget := DontCare 716 // val illegalEret = TODO 717 718 when (valid && isMret) { 719 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 720 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 721 mstatusNew.ie.m := mstatusOld.pie.m 722 priviledgeMode := mstatusOld.mpp 723 mstatusNew.pie.m := true.B 724 mstatusNew.mpp := ModeU 725 mstatusNew.mprv := 0.U 726 mstatus := mstatusNew.asUInt 727 // lr := false.B 728 retTarget := mepc(VAddrBits-1, 0) 729 } 730 731 when (valid && isSret && !illegalSModeSret) { 732 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 733 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 734 mstatusNew.ie.s := mstatusOld.pie.s 735 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 736 mstatusNew.pie.s := true.B 737 mstatusNew.spp := ModeU 738 mstatus := mstatusNew.asUInt 739 mstatusNew.mprv := 0.U 740 // lr := false.B 741 retTarget := sepc(VAddrBits-1, 0) 742 } 743 744 when (valid && isUret) { 745 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 746 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 747 // mstatusNew.mpp.m := ModeU //TODO: add mode U 748 mstatusNew.ie.u := mstatusOld.pie.u 749 priviledgeMode := ModeU 750 mstatusNew.pie.u := true.B 751 mstatus := mstatusNew.asUInt 752 retTarget := uepc(VAddrBits-1, 0) 753 } 754 755 io.in.ready := true.B 756 io.out.valid := valid 757 758 val csrExceptionVec = WireInit(cfIn.exceptionVec) 759 csrExceptionVec(breakPoint) := io.in.valid && isEbreak 760 csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall 761 csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall 762 csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall 763 // Trigger an illegal instr exception when: 764 // * unimplemented csr is being read/written 765 // * csr access is illegal 766 csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen 767 cfOut.exceptionVec := csrExceptionVec 768 769 /** 770 * Exception and Intr 771 */ 772 val ideleg = (mideleg & mip.asUInt) 773 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 774 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 775 776 // send interrupt information to ROQ 777 val intrVecEnable = Wire(Vec(12, Bool())) 778 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 779 val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt 780 val intrBitSet = intrVec.orR() 781 csrio.interrupt := intrBitSet 782 mipWire.t.m := csrio.externalInterrupt.mtip 783 mipWire.s.m := csrio.externalInterrupt.msip 784 mipWire.e.m := csrio.externalInterrupt.meip 785 mipWire.e.s := csrio.externalInterrupt.meip 786 787 // interrupts 788 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 789 val raiseIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt 790 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.uop.cf.pc, intrNO) 791 792 // exceptions 793 val raiseException = csrio.exception.valid && !csrio.exception.bits.isInterrupt 794 val hasInstrPageFault = csrio.exception.bits.uop.cf.exceptionVec(instrPageFault) && raiseException 795 val hasLoadPageFault = csrio.exception.bits.uop.cf.exceptionVec(loadPageFault) && raiseException 796 val hasStorePageFault = csrio.exception.bits.uop.cf.exceptionVec(storePageFault) && raiseException 797 val hasStoreAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(storeAddrMisaligned) && raiseException 798 val hasLoadAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(loadAddrMisaligned) && raiseException 799 val hasInstrAccessFault = csrio.exception.bits.uop.cf.exceptionVec(instrAccessFault) && raiseException 800 val hasLoadAccessFault = csrio.exception.bits.uop.cf.exceptionVec(loadAccessFault) && raiseException 801 val hasStoreAccessFault = csrio.exception.bits.uop.cf.exceptionVec(storeAccessFault) && raiseException 802 803 val raiseExceptionVec = csrio.exception.bits.uop.cf.exceptionVec 804 val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum)) 805 val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO) 806 807 val raiseExceptionIntr = csrio.exception.valid 808 XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n", 809 csrio.exception.bits.uop.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt 810 ) 811 XSDebug(raiseExceptionIntr, 812 "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", 813 csrio.exception.bits.uop.cf.pc, 814 mstatus, 815 mideleg, 816 medeleg, 817 priviledgeMode 818 ) 819 820 // mtval write logic 821 val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN) 822 when (hasInstrPageFault || hasLoadPageFault || hasStorePageFault) { 823 val tval = Mux( 824 hasInstrPageFault, 825 Mux( 826 csrio.exception.bits.uop.cf.crossPageIPFFix, 827 SignExt(csrio.exception.bits.uop.cf.pc + 2.U, XLEN), 828 SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 829 ), 830 memExceptionAddr 831 ) 832 when (priviledgeMode === ModeM) { 833 mtval := tval 834 }.otherwise { 835 stval := tval 836 } 837 } 838 839 when (hasLoadAddrMisaligned || hasStoreAddrMisaligned) { 840 mtval := memExceptionAddr 841 } 842 843 val deleg = Mux(raiseIntr, mideleg , medeleg) 844 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 845 val delegS = deleg(causeNO(3,0)) && (priviledgeMode < ModeM) 846 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check 847 val isXRet = io.in.valid && func === CSROpType.jmp && !isEcall 848 849 // ctrl block will use theses later for flush 850 val isXRetFlag = RegInit(false.B) 851 val retTargetReg = Reg(retTarget.cloneType) 852 when (io.flushIn) { 853 isXRetFlag := false.B 854 }.elsewhen (isXRet) { 855 isXRetFlag := true.B 856 retTargetReg := retTarget 857 } 858 csrio.isXRet := isXRetFlag 859 csrio.trapTarget := Mux(isXRetFlag, 860 retTargetReg, 861 Mux(delegS, stvec, mtvec)(VAddrBits-1, 0) 862 ) 863 864 when (raiseExceptionIntr) { 865 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 866 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 867 868 when (delegS) { 869 scause := causeNO 870 sepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 871 mstatusNew.spp := priviledgeMode 872 mstatusNew.pie.s := mstatusOld.ie.s 873 mstatusNew.ie.s := false.B 874 priviledgeMode := ModeS 875 when (tvalWen) { stval := 0.U } 876 }.otherwise { 877 mcause := causeNO 878 mepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN) 879 mstatusNew.mpp := priviledgeMode 880 mstatusNew.pie.m := mstatusOld.ie.m 881 mstatusNew.ie.m := false.B 882 priviledgeMode := ModeM 883 when (tvalWen) { mtval := 0.U } 884 } 885 886 mstatus := mstatusNew.asUInt 887 } 888 889 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc) 890 891 def readWithScala(addr: Int): UInt = mapping(addr)._1 892 893 val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U) 894 895 if (!env.FPGAPlatform) { 896 val difftest = Module(new DifftestArchEvent) 897 difftest.io.clock := clock 898 difftest.io.coreid := hardId.U 899 difftest.io.intrNO := RegNext(difftestIntrNO) 900 difftest.io.cause := RegNext(Mux(csrio.exception.valid, causeNO, 0.U)) 901 difftest.io.exceptionPC := RegNext(SignExt(csrio.exception.bits.uop.cf.pc, XLEN)) 902 } 903 904 if (!env.FPGAPlatform) { 905 val difftest = Module(new DifftestCSRState) 906 difftest.io.clock := clock 907 difftest.io.coreid := hardId.U 908 difftest.io.priviledgeMode := priviledgeMode 909 difftest.io.mstatus := mstatus 910 difftest.io.sstatus := mstatus & sstatusRmask 911 difftest.io.mepc := mepc 912 difftest.io.sepc := sepc 913 difftest.io.mtval:= mtval 914 difftest.io.stval:= stval 915 difftest.io.mtvec := mtvec 916 difftest.io.stvec := stvec 917 difftest.io.mcause := mcause 918 difftest.io.scause := scause 919 difftest.io.satp := satp 920 difftest.io.mip := mipReg 921 difftest.io.mie := mie 922 difftest.io.mscratch := mscratch 923 difftest.io.sscratch := sscratch 924 difftest.io.mideleg := mideleg 925 difftest.io.medeleg := medeleg 926 } 927} 928