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