1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.ExcitingUtils.{ConnectionType, Debug} 5import chisel3.util._ 6import fpu.Fflags 7import utils._ 8import xiangshan._ 9import xiangshan.backend._ 10import utils.XSDebug 11 12trait HasCSRConst { 13 // User Trap Setup 14 val Ustatus = 0x000 15 val Uie = 0x004 16 val Utvec = 0x005 17 18 // User Trap Handling 19 val Uscratch = 0x040 20 val Uepc = 0x041 21 val Ucause = 0x042 22 val Utval = 0x043 23 val Uip = 0x044 24 25 // User Floating-Point CSRs (not implemented) 26 val Fflags = 0x001 27 val Frm = 0x002 28 val Fcsr = 0x003 29 30 // User Counter/Timers 31 val Cycle = 0xC00 32 val Time = 0xC01 33 val Instret = 0xC02 34 35 // Supervisor Trap Setup 36 val Sstatus = 0x100 37 val Sedeleg = 0x102 38 val Sideleg = 0x103 39 val Sie = 0x104 40 val Stvec = 0x105 41 val Scounteren = 0x106 42 43 // Supervisor Trap Handling 44 val Sscratch = 0x140 45 val Sepc = 0x141 46 val Scause = 0x142 47 val Stval = 0x143 48 val Sip = 0x144 49 50 // Supervisor Protection and Translation 51 val Satp = 0x180 52 53 // Machine Information Registers 54 val Mvendorid = 0xF11 55 val Marchid = 0xF12 56 val Mimpid = 0xF13 57 val Mhartid = 0xF14 58 59 // Machine Trap Setup 60 val Mstatus = 0x300 61 val Misa = 0x301 62 val Medeleg = 0x302 63 val Mideleg = 0x303 64 val Mie = 0x304 65 val Mtvec = 0x305 66 val Mcounteren = 0x306 67 68 // Machine Trap Handling 69 val Mscratch = 0x340 70 val Mepc = 0x341 71 val Mcause = 0x342 72 val Mtval = 0x343 73 val Mip = 0x344 74 75 // Machine Memory Protection 76 // TBD 77 val Pmpcfg0 = 0x3A0 78 val Pmpcfg1 = 0x3A1 79 val Pmpcfg2 = 0x3A2 80 val Pmpcfg3 = 0x3A3 81 val PmpaddrBase = 0x3B0 82 83 // Machine Counter/Timers 84 // Currently, we uses perfcnt csr set instead of standard Machine Counter/Timers 85 // 0xB80 - 0x89F are also used as perfcnt csr 86 87 // Machine Counter Setup (not implemented) 88 // Debug/Trace Registers (shared with Debug Mode) (not implemented) 89 // Debug Mode Registers (not implemented) 90 91 def privEcall = 0x000.U 92 def privEbreak = 0x001.U 93 def privMret = 0x302.U 94 def privSret = 0x102.U 95 def privUret = 0x002.U 96 97 def ModeM = 0x3.U 98 def ModeH = 0x2.U 99 def ModeS = 0x1.U 100 def ModeU = 0x0.U 101 102 def IRQ_UEIP = 0 103 def IRQ_SEIP = 1 104 def IRQ_MEIP = 3 105 106 def IRQ_UTIP = 4 107 def IRQ_STIP = 5 108 def IRQ_MTIP = 7 109 110 def IRQ_USIP = 8 111 def IRQ_SSIP = 9 112 def IRQ_MSIP = 11 113 114 val IntPriority = Seq( 115 IRQ_MEIP, IRQ_MSIP, IRQ_MTIP, 116 IRQ_SEIP, IRQ_SSIP, IRQ_STIP, 117 IRQ_UEIP, IRQ_USIP, IRQ_UTIP 118 ) 119 120 def csrAccessPermissionCheck(addr: UInt, wen: Bool, mode: UInt): Bool = { 121 val readOnly = addr(11,10) === "b11".U 122 val lowestAccessPrivilegeLevel = addr(9,8) 123 mode >= lowestAccessPrivilegeLevel && !(wen && readOnly) 124 } 125} 126 127trait HasExceptionNO { 128 def instrAddrMisaligned = 0 129 def instrAccessFault = 1 130 def illegalInstr = 2 131 def breakPoint = 3 132 def loadAddrMisaligned = 4 133 def loadAccessFault = 5 134 def storeAddrMisaligned = 6 135 def storeAccessFault = 7 136 def ecallU = 8 137 def ecallS = 9 138 def ecallM = 11 139 def instrPageFault = 12 140 def loadPageFault = 13 141 def storePageFault = 15 142 143 val ExcPriority = Seq( 144 breakPoint, // TODO: different BP has different priority 145 instrPageFault, 146 instrAccessFault, 147 illegalInstr, 148 instrAddrMisaligned, 149 ecallM, ecallS, ecallU, 150 storePageFault, 151 loadPageFault, 152 storeAccessFault, 153 loadAccessFault, 154 storeAddrMisaligned, 155 loadAddrMisaligned 156 ) 157} 158 159class FpuCsrIO extends XSBundle { 160 val fflags = Output(new Fflags) 161 val isIllegal = Output(Bool()) 162 val dirty_fs = Output(Bool()) 163 val frm = Input(UInt(3.W)) 164} 165 166 167class PerfCounterIO extends XSBundle { 168 val value = Input(UInt(XLEN.W)) 169} 170 171class CSR extends FunctionUnit(FuConfig( 172 fuType = FuType.csr, 173 numIntSrc = 1, 174 numFpSrc = 0, 175 writeIntRf = true, 176 writeFpRf = false, 177 hasRedirect = false 178)) with HasCSRConst 179{ 180 181 val redirectOut = IO(Output(new Redirect)) 182 val redirectOutValid = IO(Output(Bool())) 183 val fpu_csr = IO(Flipped(new FpuCsrIO)) 184 // from rob 185 val exception = IO(Flipped(ValidIO(new MicroOp))) 186 val isInterrupt = IO(Input(Bool())) 187 // for exception check 188 // for differential testing 189 // val intrNO = Output(UInt(XLEN.W)) 190 val wenFix = IO(Output(Bool())) 191 val perf = IO(Vec(NumPerfCounters, new PerfCounterIO)) 192 val memExceptionVAddr = IO(Input(UInt(VAddrBits.W))) 193 val trapTarget = IO(Output(UInt(VAddrBits.W))) 194 val mtip = IO(Input(Bool())) 195 val msip = IO(Input(Bool())) 196 val meip = IO(Input(Bool())) 197 val interrupt = IO(Output(Bool())) 198 val tlbCsrIO = IO(Output(new TlbCsrBundle)) 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 tlbCsrIO := 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 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(fpu_csr.fflags.asUInt() =/= 0.U){ 541 fcsr := fflags_wfn(fpu_csr.fflags.asUInt()) 542 } 543 // set fs and sd in mstatus 544 when(csrw_dirty_fp_state || fpu_csr.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 fpu_csr.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 val hasInstrPageFault = exception.bits.cf.exceptionVec(instrPageFault) && exception.valid 600 val hasLoadPageFault = exception.bits.cf.exceptionVec(loadPageFault) && exception.valid 601 val hasStorePageFault = exception.bits.cf.exceptionVec(storePageFault) && exception.valid 602 val hasStoreAddrMisaligned = exception.bits.cf.exceptionVec(storeAddrMisaligned) && exception.valid 603 val hasLoadAddrMisaligned = exception.bits.cf.exceptionVec(loadAddrMisaligned) && exception.valid 604 605 // mtval write logic 606 val memExceptionAddr = SignExt(memExceptionVAddr, XLEN) 607 when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){ 608 val tval = Mux( 609 hasInstrPageFault, 610 Mux( 611 exception.bits.cf.crossPageIPFFix, 612 SignExt(exception.bits.cf.pc + 2.U, XLEN), 613 SignExt(exception.bits.cf.pc, XLEN) 614 ), 615 memExceptionAddr 616 ) 617 when(priviledgeMode === ModeM){ 618 mtval := tval 619 }.otherwise{ 620 stval := tval 621 } 622 } 623 624 when(hasLoadAddrMisaligned || hasStoreAddrMisaligned) 625 { 626 mtval := memExceptionAddr 627 } 628 629 // Exception and Intr 630 631 // interrupts 632 633 val ideleg = (mideleg & mip.asUInt) 634 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 635 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 636 637 val intrVecEnable = Wire(Vec(12, Bool())) 638 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 639 val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt 640 val intrBitSet = intrVec.orR() 641 interrupt := intrBitSet 642 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 643 val raiseIntr = intrBitSet && exception.valid && isInterrupt 644 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", exception.bits.cf.pc, intrNO) 645 646 mipWire.t.m := mtip 647 mipWire.s.m := msip 648 mipWire.e.m := meip 649 650 // exceptions 651 val csrExceptionVec = Wire(Vec(16, Bool())) 652 csrExceptionVec.map(_ := false.B) 653 csrExceptionVec(breakPoint) := io.in.valid && isEbreak 654 csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall 655 csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall 656 csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall 657 // Trigger an illegal instr exception when: 658 // * unimplemented csr is being read/written 659 // * csr access is illegal 660 csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen 661 csrExceptionVec(loadPageFault) := hasLoadPageFault 662 csrExceptionVec(storePageFault) := hasStorePageFault 663 val iduExceptionVec = cfIn.exceptionVec 664 val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt() 665 cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) } 666 wenFix := DontCare 667 668 val raiseExceptionVec = exception.bits.cf.exceptionVec.asUInt() 669 val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum)) 670 val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO) 671 val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U) 672 ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR") 673 ExcitingUtils.addSource(causeNO, "difftestCausefromCSR") 674 675 val raiseExceptionIntr = exception.valid 676 val retTarget = Wire(UInt(VAddrBits.W)) 677 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 678 redirectOut := DontCare 679 redirectOutValid := valid && func === CSROpType.jmp && !isEcall 680 redirectOut.target := retTarget 681 flushPipe := resetSatp 682 683 XSDebug(redirectOutValid, "redirect to %x, pc=%x\n", redirectOut.target, cfIn.pc) 684 685 XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n", 686 exception.bits.cf.pc, 687 intrNO, 688 exception.bits.cf.intrVec.asUInt, 689 exceptionNO, 690 raiseExceptionVec.asUInt 691 ) 692 XSDebug(raiseExceptionIntr, 693 "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", 694 exception.bits.cf.pc, 695 mstatus, 696 mideleg, 697 medeleg, 698 priviledgeMode 699 ) 700 701 // Branch control 702 703 val deleg = Mux(raiseIntr, mideleg , medeleg) 704 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 705 val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM) 706 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check 707 708 trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0) 709 retTarget := DontCare 710 // val illegalEret = TODO 711 712 when (valid && isMret) { 713 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 714 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 715 mstatusNew.ie.m := mstatusOld.pie.m 716 priviledgeMode := mstatusOld.mpp 717 mstatusNew.pie.m := true.B 718 mstatusNew.mpp := ModeU 719 mstatusNew.mprv := 0.U 720 mstatus := mstatusNew.asUInt 721// lr := false.B 722 retTarget := mepc(VAddrBits-1, 0) 723 } 724 725 when (valid && isSret && !illegalSModeSret) { 726 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 727 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 728 mstatusNew.ie.s := mstatusOld.pie.s 729 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 730 mstatusNew.pie.s := true.B 731 mstatusNew.spp := ModeU 732 mstatus := mstatusNew.asUInt 733 mstatusNew.mprv := 0.U 734 // lr := false.B 735 retTarget := sepc(VAddrBits-1, 0) 736 } 737 738 when (valid && isUret) { 739 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 740 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 741 // mstatusNew.mpp.m := ModeU //TODO: add mode U 742 mstatusNew.ie.u := mstatusOld.pie.u 743 priviledgeMode := ModeU 744 mstatusNew.pie.u := true.B 745 mstatus := mstatusNew.asUInt 746 retTarget := uepc(VAddrBits-1, 0) 747 } 748 749 when (raiseExceptionIntr) { 750 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 751 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 752 753 when (delegS) { 754 scause := causeNO 755 sepc := SignExt(exception.bits.cf.pc, XLEN) 756 mstatusNew.spp := priviledgeMode 757 mstatusNew.pie.s := mstatusOld.ie.s 758 mstatusNew.ie.s := false.B 759 priviledgeMode := ModeS 760 when(tvalWen){stval := 0.U} 761 // trapTarget := stvec(VAddrBits-1. 0) 762 }.otherwise { 763 mcause := causeNO 764 mepc := SignExt(exception.bits.cf.pc, XLEN) 765 mstatusNew.mpp := priviledgeMode 766 mstatusNew.pie.m := mstatusOld.ie.m 767 mstatusNew.ie.m := false.B 768 priviledgeMode := ModeM 769 when(tvalWen){mtval := 0.U} 770 // trapTarget := mtvec(VAddrBits-1. 0) 771 } 772 773 mstatus := mstatusNew.asUInt 774 } 775 776 io.in.ready := true.B 777 io.out.valid := valid 778 779 780 XSDebug(redirectOutValid, 781 "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d\n", 782 redirectOut.target, 783 raiseExceptionIntr, 784 isSret, 785 retTarget, 786 sepc, 787 delegS, 788 deleg, 789 cfIn.pc, 790 valid 791 ) 792 XSDebug(raiseExceptionIntr && delegS, 793 "Red(%d, %x) raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d\n", 794 redirectOutValid, 795 redirectOut.target, 796 raiseExceptionIntr, 797 isSret, 798 retTarget, 799 sepc, 800 delegS, 801 deleg, 802 cfIn.pc, 803 valid 804 ) 805 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc) 806 807 808 // perfcnt 809 810 val perfCntList = Map( 811// "Mcycle" -> (0xb00, "perfCntCondMcycle" ), 812// "Minstret" -> (0xb02, "perfCntCondMinstret" ), 813 "MbpInstr" -> (0xb03, "perfCntCondMbpInstr" ), 814 "MbpRight" -> (0xb04, "perfCntCondMbpRight" ), 815 "MbpWrong" -> (0xb05, "perfCntCondMbpWrong" ), 816 "MbpBRight" -> (0xb06, "perfCntCondMbpBRight" ), 817 "MbpBWrong" -> (0xb07, "perfCntCondMbpBWrong" ), 818 "MbpJRight" -> (0xb08, "perfCntCondMbpJRight" ), 819 "MbpJWrong" -> (0xb09, "perfCntCondMbpJWrong" ), 820 "MbpIRight" -> (0xb0a, "perfCntCondMbpIRight" ), 821 "MbpIWrong" -> (0xb0b, "perfCntCondMbpIWrong" ), 822 "MbpRRight" -> (0xb0c, "perfCntCondMbpRRight" ), 823 "MbpRWrong" -> (0xb0d, "perfCntCondMbpRWrong" ), 824 "DpqReplay" -> (0xb0e, "perfCntCondDpqReplay" ), 825 "RoqWalk" -> (0xb0f, "perfCntCondRoqWalk" ), 826 "RoqWaitInt" -> (0xb10, "perfCntCondRoqWaitInt" ), 827 "RoqWaitFp" -> (0xb11, "perfCntCondRoqWaitFp" ), 828 "RoqWaitLoad" -> (0xb12, "perfCntCondRoqWaitLoad" ), 829 "RoqWaitStore"-> (0xb13, "perfCntCondRoqWaitStore"), 830 "Dp1Empty" -> (0xb14, "perfCntCondDp1Empty" ), 831 "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0" ), 832 "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1" ), 833 "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2" ), 834 "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3" ), 835 "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0" ), 836 "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1" ), 837 "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2" ), 838 "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3" ), 839 "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0" ), 840 "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0" ), 841 "PtwReqCnt" -> (0xb25, "perfCntPtwReqCnt" ), 842 "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt" ), 843 "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit" ), 844 "ICacheReq" -> (0xb28, "perfCntIcacheReqCnt" ), 845 "ICacheMiss" -> (0xb29, "perfCntIcacheMissCnt" )//, 846 // "FetchFromICache" -> (0xb2a, "CntFetchFromICache"), 847 // "FetchFromLoopBuffer" -> (0xb2b, "CntFetchFromLoopBuffer"), 848 // "ExitLoop1" -> (0xb2c, "CntExitLoop1"), 849 // "ExitLoop2" -> (0xb2d, "CntExitLoop2"), 850 // "ExitLoop3" -> (0xb2e, "CntExitLoop3") 851// "Custom1" -> (0xb1b, "Custom1" ), 852// "Custom2" -> (0xb1c, "Custom2" ), 853// "Custom3" -> (0xb1d, "Custom3" ), 854// "Custom4" -> (0xb1e, "Custom4" ), 855// "Custom5" -> (0xb1f, "Custom5" ), 856// "Custom6" -> (0xb20, "Custom6" ), 857// "Custom7" -> (0xb21, "Custom7" ), 858// "Custom8" -> (0xb22, "Custom8" ), 859// "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit") 860 ) 861 val perfCntCond = List.fill(0x80)(WireInit(false.B)) 862 (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } } 863 864// ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf) 865 perfCntList.foreach { 866 case (_, (address, boringId)) => 867 if(hasPerfCnt){ 868 ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf) 869 } 870// if (!hasPerfCnt) { 871// // do not enable perfcnts except for Mcycle and Minstret 872// if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) { 873// perfCntCond(address & 0x7f) := false.B 874// } 875// } 876 } 877 878 val xstrap = WireInit(false.B) 879 if(!env.FPGAPlatform && EnableBPU){ 880 ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug) 881 } 882 def readWithScala(addr: Int): UInt = mapping(addr)._1 883 884 if (!env.FPGAPlatform) { 885 886 // display all perfcnt when nooptrap is executed 887 when (xstrap) { 888 printf("======== PerfCnt =========\n") 889 perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) => 890 printf("%d <- " + str + "\n", readWithScala(address)) 891 } 892 } 893 894 ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug) 895 ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug) 896 ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug) 897 ExcitingUtils.addSource(mepc, "difftestMepc", Debug) 898 ExcitingUtils.addSource(sepc, "difftestSepc", Debug) 899 ExcitingUtils.addSource(mtval, "difftestMtval", Debug) 900 ExcitingUtils.addSource(stval, "difftestStval", Debug) 901 ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug) 902 ExcitingUtils.addSource(stvec, "difftestStvec", Debug) 903 ExcitingUtils.addSource(mcause, "difftestMcause", Debug) 904 ExcitingUtils.addSource(scause, "difftestScause", Debug) 905 ExcitingUtils.addSource(satp, "difftestSatp", Debug) 906 ExcitingUtils.addSource(mipReg, "difftestMip", Debug) 907 ExcitingUtils.addSource(mie, "difftestMie", Debug) 908 ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug) 909 ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug) 910 ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug) 911 ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug) 912 } else { 913 } 914} 915