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