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