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 val isInterrupt = Input(Bool()) 181 // for exception check 182 val instrValid = Input(Bool()) 183 val flushPipe = Output(Bool()) 184 // for differential testing 185// val intrNO = Output(UInt(XLEN.W)) 186 val wenFix = Output(Bool()) 187 188 override def cloneType: CSRIO.this.type = 189 new CSRIO().asInstanceOf[this.type] 190 191 val perf = Vec(NumPerfCounters, new PerfCounterIO) 192 val memExceptionVAddr = Input(UInt(VAddrBits.W)) 193 val trapTarget = Output(UInt(VAddrBits.W)) 194 val mtip = Input(Bool()) 195 val msip = Input(Bool()) 196 val meip = Input(Bool()) 197 val interrupt = Output(Bool()) 198 val tlbCsrIO = Output(new TlbCsrBundle) 199} 200 201class CSR extends XSModule 202 with HasCSRConst 203{ 204 205 val io = IO(new CSRIO) 206 207 io.cfOut := io.cfIn 208 209 val (valid, src1, src2, func) = 210 (io.in.valid, io.in.bits.src(0), io.in.bits.uop.ctrl.imm, io.in.bits.ext.get) 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 io.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(io.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 530 // Fix Mip/Sip write 531 val fixMapping = Map( 532 MaskedRegMap(Mip, mipReg.asUInt, mipFixMask), 533 MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask) 534 ) 535 val rdataDummy = Wire(UInt(XLEN.W)) 536 MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata) 537 538 when(io.fpu_csr.fflags.asUInt() =/= 0.U){ 539 fcsr := fflags_wfn(io.fpu_csr.fflags.asUInt()) 540 } 541 // set fs and sd in mstatus 542 when(csrw_dirty_fp_state || io.fpu_csr.dirty_fs){ 543 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 544 mstatusNew.fs := "b11".U 545 mstatusNew.sd := true.B 546 mstatus := mstatusNew.asUInt() 547 } 548 io.fpu_csr.frm := fcsr.asTypeOf(new FcsrStruct).frm 549 550 // CSR inst decode 551 val isEbreak = addr === privEbreak && func === CSROpType.jmp 552 val isEcall = addr === privEcall && func === CSROpType.jmp 553 val isMret = addr === privMret && func === CSROpType.jmp 554 val isSret = addr === privSret && func === CSROpType.jmp 555 val isUret = addr === privUret && func === CSROpType.jmp 556 557 XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", io.cfIn.pc, addr, rdata, wdata, func) 558 XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode) 559 560 // Illegal priviledged operation list 561 val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool 562 563 // Illegal priviledged instruction check 564 val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr) 565 val isIllegalAccess = !permitted 566 val isIllegalPrivOp = illegalSModeSret 567 568 // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) 569 // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex)) 570 // imem 571 // val imemPtev = true.B 572 // val imemPteu = true.B 573 // val imemPtex = true.B 574 // val imemReq = true.B 575 // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu) 576 // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex) 577 // assert(!hasInstrPageFault) 578 579 // dmem 580 // val dmemPtev = true.B 581 // val dmemPteu = true.B 582 // val dmemReq = true.B 583 // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu) 584 // val dmemIsStore = true.B 585 586 // val hasLoadPageFault = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed) 587 // val hasStorePageFault = dmemReq && dmemIsStore && !(dmemPermissionCheckPassed) 588 // assert(!hasLoadPageFault) 589 // assert(!hasStorePageFault) 590 591 //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet 592 tlbBundle.priv.mxr := mstatusStruct.mxr.asBool 593 tlbBundle.priv.sum := mstatusStruct.sum.asBool 594 tlbBundle.priv.imode := priviledgeMode 595 tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode) 596 597 val hasInstrPageFault = io.exception.bits.cf.exceptionVec(instrPageFault) && io.exception.valid 598 val hasLoadPageFault = io.exception.bits.cf.exceptionVec(loadPageFault) && io.exception.valid 599 val hasStorePageFault = io.exception.bits.cf.exceptionVec(storePageFault) && io.exception.valid 600 val hasStoreAddrMisaligned = io.exception.bits.cf.exceptionVec(storeAddrMisaligned) && io.exception.valid 601 val hasLoadAddrMisaligned = io.exception.bits.cf.exceptionVec(loadAddrMisaligned) && io.exception.valid 602 603 // mtval write logic 604 val memExceptionAddr = SignExt(io.memExceptionVAddr, XLEN) 605 when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){ 606 val tval = Mux( 607 hasInstrPageFault, 608 Mux( 609 io.exception.bits.cf.crossPageIPFFix, 610 SignExt(io.exception.bits.cf.pc + 2.U, XLEN), 611 SignExt(io.exception.bits.cf.pc, XLEN) 612 ), 613 memExceptionAddr 614 ) 615 when(priviledgeMode === ModeM){ 616 mtval := tval 617 }.otherwise{ 618 stval := tval 619 } 620 } 621 622 when(hasLoadAddrMisaligned || hasStoreAddrMisaligned) 623 { 624 mtval := memExceptionAddr 625 } 626 627 // Exception and Intr 628 629 // interrupts 630 631 val ideleg = (mideleg & mip.asUInt) 632 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 633 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 634 635 val intrVecEnable = Wire(Vec(12, Bool())) 636 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 637 val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt 638 val intrBitSet = intrVec.orR() 639 io.interrupt := intrBitSet 640 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 641 val raiseIntr = intrBitSet && io.exception.valid && io.isInterrupt 642 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", io.exception.bits.cf.pc, intrNO) 643 644 mipWire.t.m := io.mtip 645 mipWire.s.m := io.msip 646 mipWire.e.m := io.meip 647 648 // exceptions 649 val csrExceptionVec = Wire(Vec(16, Bool())) 650 csrExceptionVec.map(_ := false.B) 651 csrExceptionVec(breakPoint) := io.in.valid && isEbreak 652 csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall 653 csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall 654 csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall 655 // Trigger an illegal instr exception when: 656 // * unimplemented csr is being read/written 657 // * csr access is illegal 658 csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen 659 csrExceptionVec(loadPageFault) := hasLoadPageFault 660 csrExceptionVec(storePageFault) := hasStorePageFault 661 val iduExceptionVec = io.cfIn.exceptionVec 662 val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt() 663 io.cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) } 664 io.wenFix := DontCare 665 666 val raiseExceptionVec = io.exception.bits.cf.exceptionVec.asUInt() 667 val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum)) 668 val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO) 669 val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U) 670 ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR") 671 ExcitingUtils.addSource(causeNO, "difftestCausefromCSR") 672 673 val raiseExceptionIntr = io.exception.valid 674 val retTarget = Wire(UInt(VAddrBits.W)) 675 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 676 io.redirectOut := DontCare 677 io.redirectOutValid := valid && func === CSROpType.jmp && !isEcall 678 io.redirectOut.target := retTarget 679 io.flushPipe := resetSatp 680 681 XSDebug(io.redirectOutValid, "redirect to %x, pc=%x\n", io.redirectOut.target, io.cfIn.pc) 682 683 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) 684 XSDebug(raiseExceptionIntr, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.exception.bits.cf.pc, mstatus, mideleg, medeleg, priviledgeMode) 685 686 // Branch control 687 688 val deleg = Mux(raiseIntr, mideleg , medeleg) 689 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 690 val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM) 691 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check 692 693 io.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0) 694 retTarget := DontCare 695 // val illegalEret = TODO 696 697 when (valid && isMret) { 698 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 699 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 700 mstatusNew.ie.m := mstatusOld.pie.m 701 priviledgeMode := mstatusOld.mpp 702 mstatusNew.pie.m := true.B 703 mstatusNew.mpp := ModeU 704 mstatusNew.mprv := 0.U 705 mstatus := mstatusNew.asUInt 706// lr := false.B 707 retTarget := mepc(VAddrBits-1, 0) 708 } 709 710 when (valid && isSret && !illegalSModeSret) { 711 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 712 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 713 mstatusNew.ie.s := mstatusOld.pie.s 714 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 715 mstatusNew.pie.s := true.B 716 mstatusNew.spp := ModeU 717 mstatus := mstatusNew.asUInt 718 mstatusNew.mprv := 0.U 719 // lr := false.B 720 retTarget := sepc(VAddrBits-1, 0) 721 } 722 723 when (valid && isUret) { 724 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 725 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 726 // mstatusNew.mpp.m := ModeU //TODO: add mode U 727 mstatusNew.ie.u := mstatusOld.pie.u 728 priviledgeMode := ModeU 729 mstatusNew.pie.u := true.B 730 mstatus := mstatusNew.asUInt 731 retTarget := uepc(VAddrBits-1, 0) 732 } 733 734 when (raiseExceptionIntr) { 735 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 736 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 737 738 when (delegS) { 739 scause := causeNO 740 sepc := SignExt(io.exception.bits.cf.pc, XLEN) 741 mstatusNew.spp := priviledgeMode 742 mstatusNew.pie.s := mstatusOld.ie.s 743 mstatusNew.ie.s := false.B 744 priviledgeMode := ModeS 745 when(tvalWen){stval := 0.U} 746 // trapTarget := stvec(VAddrBits-1. 0) 747 }.otherwise { 748 mcause := causeNO 749 mepc := SignExt(io.exception.bits.cf.pc, XLEN) 750 mstatusNew.mpp := priviledgeMode 751 mstatusNew.pie.m := mstatusOld.ie.m 752 mstatusNew.ie.m := false.B 753 priviledgeMode := ModeM 754 when(tvalWen){mtval := 0.U} 755 // trapTarget := mtvec(VAddrBits-1. 0) 756 } 757 758 mstatus := mstatusNew.asUInt 759 } 760 761 io.in.ready := true.B 762 io.out.valid := valid 763 764 765 XSDebug(io.redirectOutValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n", 766 io.redirectOut.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid) 767 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", 768 io.redirectOutValid, io.redirectOut.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid) 769 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", io.cfIn.pc) 770 771 772 // perfcnt 773 774 val perfCntList = Map( 775// "Mcycle" -> (0xb00, "perfCntCondMcycle" ), 776// "Minstret" -> (0xb02, "perfCntCondMinstret" ), 777 "MbpInstr" -> (0xb03, "perfCntCondMbpInstr" ), 778 "MbpRight" -> (0xb04, "perfCntCondMbpRight" ), 779 "MbpWrong" -> (0xb05, "perfCntCondMbpWrong" ), 780 "MbpBRight" -> (0xb06, "perfCntCondMbpBRight" ), 781 "MbpBWrong" -> (0xb07, "perfCntCondMbpBWrong" ), 782 "MbpJRight" -> (0xb08, "perfCntCondMbpJRight" ), 783 "MbpJWrong" -> (0xb09, "perfCntCondMbpJWrong" ), 784 "MbpIRight" -> (0xb0a, "perfCntCondMbpIRight" ), 785 "MbpIWrong" -> (0xb0b, "perfCntCondMbpIWrong" ), 786 "MbpRRight" -> (0xb0c, "perfCntCondMbpRRight" ), 787 "MbpRWrong" -> (0xb0d, "perfCntCondMbpRWrong" ), 788 "DpqReplay" -> (0xb0e, "perfCntCondDpqReplay" ), 789 "RoqWalk" -> (0xb0f, "perfCntCondRoqWalk" ), 790 "RoqWaitInt" -> (0xb10, "perfCntCondRoqWaitInt" ), 791 "RoqWaitFp" -> (0xb11, "perfCntCondRoqWaitFp" ), 792 "RoqWaitLoad" -> (0xb12, "perfCntCondRoqWaitLoad" ), 793 "RoqWaitStore"-> (0xb13, "perfCntCondRoqWaitStore"), 794 "Dp1Empty" -> (0xb14, "perfCntCondDp1Empty" ), 795 "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0" ), 796 "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1" ), 797 "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2" ), 798 "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3" ), 799 "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0" ), 800 "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1" ), 801 "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2" ), 802 "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3" ), 803 "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0" ), 804 "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0" ), 805 "PtwReqCnt" -> (0xb25, "perfCntPtwReqCnt" ), 806 "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt" ), 807 "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit" ), 808 "ICacheReq" -> (0xb28, "perfCntIcacheReqCnt" ), 809 "ICacheMiss" -> (0xb29, "perfCntIcacheMissCnt" ) 810// "Custom1" -> (0xb1b, "Custom1" ), 811// "Custom2" -> (0xb1c, "Custom2" ), 812// "Custom3" -> (0xb1d, "Custom3" ), 813// "Custom4" -> (0xb1e, "Custom4" ), 814// "Custom5" -> (0xb1f, "Custom5" ), 815// "Custom6" -> (0xb20, "Custom6" ), 816// "Custom7" -> (0xb21, "Custom7" ), 817// "Custom8" -> (0xb22, "Custom8" ), 818// "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit") 819 ) 820 val perfCntCond = List.fill(0x80)(WireInit(false.B)) 821 (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } } 822 823// ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf) 824 perfCntList.foreach { 825 case (_, (address, boringId)) => 826 if(hasPerfCnt){ 827 ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf) 828 } 829// if (!hasPerfCnt) { 830// // do not enable perfcnts except for Mcycle and Minstret 831// if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) { 832// perfCntCond(address & 0x7f) := false.B 833// } 834// } 835 } 836 837 val xstrap = WireInit(false.B) 838 if(!env.FPGAPlatform && EnableBPU){ 839 ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug) 840 } 841 def readWithScala(addr: Int): UInt = mapping(addr)._1 842 843 if (!env.FPGAPlatform) { 844 845 // display all perfcnt when nooptrap is executed 846 when (xstrap) { 847 printf("======== PerfCnt =========\n") 848 perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) => 849 printf("%d <- " + str + "\n", readWithScala(address)) 850 } 851 } 852 853 ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug) 854 ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug) 855 ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug) 856 ExcitingUtils.addSource(mepc, "difftestMepc", Debug) 857 ExcitingUtils.addSource(sepc, "difftestSepc", Debug) 858 ExcitingUtils.addSource(mtval, "difftestMtval", Debug) 859 ExcitingUtils.addSource(stval, "difftestStval", Debug) 860 ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug) 861 ExcitingUtils.addSource(stvec, "difftestStvec", Debug) 862 ExcitingUtils.addSource(mcause, "difftestMcause", Debug) 863 ExcitingUtils.addSource(scause, "difftestScause", Debug) 864 ExcitingUtils.addSource(satp, "difftestSatp", Debug) 865 ExcitingUtils.addSource(mipReg, "difftestMip", Debug) 866 ExcitingUtils.addSource(mie, "difftestMie", Debug) 867 ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug) 868 ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug) 869 ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug) 870 ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug) 871 } else { 872 } 873} 874