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