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