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