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