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