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 if(EnableUnifiedLSQ){ 603 ExcitingUtils.addSource(io.exception.bits.lsroqIdx, "EXECPTION_LSROQIDX") 604 ExcitingUtils.addSink(lsroqExceptionAddr, "EXECPTION_VADDR") 605 } else { 606 val lsIdx = WireInit(0.U.asTypeOf(new LSIdx())) 607 lsIdx.lqIdx := io.exception.bits.lqIdx 608 lsIdx.sqIdx := io.exception.bits.sqIdx 609 ExcitingUtils.addSource(lsIdx, "EXECPTION_LSROQIDX") 610 val lqExceptionAddr = WireInit(0.U(VAddrBits.W)) 611 val sqExceptionAddr = WireInit(0.U(VAddrBits.W)) 612 ExcitingUtils.addSink(lqExceptionAddr, "EXECPTION_LOAD_VADDR") 613 ExcitingUtils.addSink(sqExceptionAddr, "EXECPTION_STORE_VADDR") 614 lsroqExceptionAddr := Mux(CommitType.lsInstIsStore(io.exception.bits.ctrl.commitType), sqExceptionAddr, lqExceptionAddr) 615 } 616 617 val atomExceptionAddr = WireInit(0.U(VAddrBits.W)) 618 val atomOverrideXtval = WireInit(false.B) 619 ExcitingUtils.addSink(atomExceptionAddr, "ATOM_EXECPTION_VADDR") 620 ExcitingUtils.addSink(atomOverrideXtval, "ATOM_OVERRIDE_XTVAL") 621 val memExceptionAddr = Mux(atomOverrideXtval, atomExceptionAddr, lsroqExceptionAddr) 622 when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){ 623 val tval = Mux( 624 hasInstrPageFault, 625 Mux( 626 io.exception.bits.cf.crossPageIPFFix, 627 SignExt(io.exception.bits.cf.pc + 2.U, XLEN), 628 SignExt(io.exception.bits.cf.pc, XLEN) 629 ), 630 SignExt(memExceptionAddr, XLEN) 631 ) 632 when(priviledgeMode === ModeM){ 633 mtval := tval 634 }.otherwise{ 635 stval := tval 636 } 637 } 638 639 when(hasLoadAddrMisaligned || hasStoreAddrMisaligned) 640 { 641 mtval := SignExt(memExceptionAddr, XLEN) 642 } 643 644 // Exception and Intr 645 646 // interrupts 647 648 val ideleg = (mideleg & mip.asUInt) 649 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 650 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 651 652 val intrVecEnable = Wire(Vec(12, Bool())) 653 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 654 val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt 655 val intrBitSet = intrVec.orR() 656 ExcitingUtils.addSource(intrBitSet, "intrBitSetIDU") 657 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 658 val raiseIntr = intrBitSet && io.exception.valid 659 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", io.exception.bits.cf.pc, intrNO) 660 661 val mtip = WireInit(false.B) 662 val msip = WireInit(false.B) 663 val meip = WireInit(false.B) 664 ExcitingUtils.addSink(mtip, "mtip") 665 ExcitingUtils.addSink(msip, "msip") 666 ExcitingUtils.addSink(meip, "meip") 667 mipWire.t.m := mtip 668 mipWire.s.m := msip 669 mipWire.e.m := meip 670 671 // exceptions 672 val csrExceptionVec = Wire(Vec(16, Bool())) 673 csrExceptionVec.map(_ := false.B) 674 csrExceptionVec(breakPoint) := io.in.valid && isEbreak 675 csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall 676 csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall 677 csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall 678 // Trigger an illegal instr exception when: 679 // * unimplemented csr is being read/written 680 // * csr access is illegal 681 csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen 682 csrExceptionVec(loadPageFault) := hasLoadPageFault 683 csrExceptionVec(storePageFault) := hasStorePageFault 684 val iduExceptionVec = io.cfIn.exceptionVec 685 val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt() 686 io.cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) } 687 io.wenFix := DontCare 688 689 val raiseExceptionVec = io.exception.bits.cf.exceptionVec.asUInt() 690 val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum)) 691 val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO) 692 val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U) 693 ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR") 694 ExcitingUtils.addSource(causeNO, "difftestCausefromCSR") 695 696 val raiseExceptionIntr = io.exception.valid 697 val retTarget = Wire(UInt(VAddrBits.W)) 698 val trapTarget = Wire(UInt(VAddrBits.W)) 699 ExcitingUtils.addSource(trapTarget, "trapTarget") 700 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 701 io.redirectOut := DontCare 702 io.redirectOutValid := valid && func === CSROpType.jmp && !isEcall 703 io.redirectOut.target := retTarget 704 io.flushPipe := resetSatp 705 706 XSDebug(io.redirectOutValid, "redirect to %x, pc=%x\n", io.redirectOut.target, io.cfIn.pc) 707 708 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) 709 XSDebug(raiseExceptionIntr, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.exception.bits.cf.pc, mstatus, mideleg, medeleg, priviledgeMode) 710 711 // Branch control 712 713 val deleg = Mux(raiseIntr, mideleg , medeleg) 714 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 715 val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM) 716 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check 717 718 trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0) 719 retTarget := DontCare 720 // val illegalEret = TODO 721 722 when (valid && isMret) { 723 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 724 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 725 mstatusNew.ie.m := mstatusOld.pie.m 726 priviledgeMode := mstatusOld.mpp 727 mstatusNew.pie.m := true.B 728 mstatusNew.mpp := ModeU 729 mstatusNew.mprv := 0.U 730 mstatus := mstatusNew.asUInt 731// lr := false.B 732 retTarget := mepc(VAddrBits-1, 0) 733 } 734 735 when (valid && isSret && !illegalSModeSret) { 736 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 737 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 738 mstatusNew.ie.s := mstatusOld.pie.s 739 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 740 mstatusNew.pie.s := true.B 741 mstatusNew.spp := ModeU 742 mstatus := mstatusNew.asUInt 743 mstatusNew.mprv := 0.U 744 // lr := false.B 745 retTarget := sepc(VAddrBits-1, 0) 746 } 747 748 when (valid && isUret) { 749 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 750 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 751 // mstatusNew.mpp.m := ModeU //TODO: add mode U 752 mstatusNew.ie.u := mstatusOld.pie.u 753 priviledgeMode := ModeU 754 mstatusNew.pie.u := true.B 755 mstatus := mstatusNew.asUInt 756 retTarget := uepc(VAddrBits-1, 0) 757 } 758 759 when (raiseExceptionIntr) { 760 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 761 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 762 763 when (delegS) { 764 scause := causeNO 765 sepc := SignExt(io.exception.bits.cf.pc, XLEN) 766 mstatusNew.spp := priviledgeMode 767 mstatusNew.pie.s := mstatusOld.ie.s 768 mstatusNew.ie.s := false.B 769 priviledgeMode := ModeS 770 when(tvalWen){stval := 0.U} 771 // trapTarget := stvec(VAddrBits-1. 0) 772 }.otherwise { 773 mcause := causeNO 774 mepc := SignExt(io.exception.bits.cf.pc, XLEN) 775 mstatusNew.mpp := priviledgeMode 776 mstatusNew.pie.m := mstatusOld.ie.m 777 mstatusNew.ie.m := false.B 778 priviledgeMode := ModeM 779 when(tvalWen){mtval := 0.U} 780 // trapTarget := mtvec(VAddrBits-1. 0) 781 } 782 783 mstatus := mstatusNew.asUInt 784 } 785 786 io.in.ready := true.B 787 io.out.valid := valid 788 789 790 XSDebug(io.redirectOutValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n", 791 io.redirectOut.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid) 792 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", 793 io.redirectOutValid, io.redirectOut.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid) 794 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", io.cfIn.pc) 795 796 797 // perfcnt 798 799 val perfCntList = Map( 800// "Mcycle" -> (0xb00, "perfCntCondMcycle" ), 801// "Minstret" -> (0xb02, "perfCntCondMinstret" ), 802 "MbpInstr" -> (0xb03, "perfCntCondMbpInstr" ), 803 "MbpRight" -> (0xb04, "perfCntCondMbpRight" ), 804 "MbpWrong" -> (0xb05, "perfCntCondMbpWrong" ), 805 "MbpBRight" -> (0xb06, "perfCntCondMbpBRight" ), 806 "MbpBWrong" -> (0xb07, "perfCntCondMbpBWrong" ), 807 "MbpJRight" -> (0xb08, "perfCntCondMbpJRight" ), 808 "MbpJWrong" -> (0xb09, "perfCntCondMbpJWrong" ), 809 "MbpIRight" -> (0xb0a, "perfCntCondMbpIRight" ), 810 "MbpIWrong" -> (0xb0b, "perfCntCondMbpIWrong" ), 811 "MbpRRight" -> (0xb0c, "perfCntCondMbpRRight" ), 812 "MbpRWrong" -> (0xb0d, "perfCntCondMbpRWrong" ), 813 "DpqReplay" -> (0xb0e, "perfCntCondDpqReplay" ), 814 "RoqWalk" -> (0xb0f, "perfCntCondRoqWalk" ), 815 "RoqWaitInt" -> (0xb10, "perfCntCondRoqWaitInt" ), 816 "RoqWaitFp" -> (0xb11, "perfCntCondRoqWaitFp" ), 817 "RoqWaitLoad" -> (0xb12, "perfCntCondRoqWaitLoad" ), 818 "RoqWaitStore"-> (0xb13, "perfCntCondRoqWaitStore"), 819 "Dp1Empty" -> (0xb14, "perfCntCondDp1Empty" ), 820 "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0" ), 821 "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1" ), 822 "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2" ), 823 "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3" ), 824 "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0" ), 825 "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1" ), 826 "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2" ), 827 "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3" ), 828 "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0" ), 829 "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0" ), 830 "PtwReqCnt" -> (0xb25, "perfCntPtwReqCnt" ), 831 "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt" ), 832 "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit" ), 833 "ICacheReq" -> (0xb28, "perfCntIcacheReqCnt" ), 834 "ICacheMiss" -> (0xb29, "perfCntIcacheMissCnt" ) 835// "Custom1" -> (0xb1b, "Custom1" ), 836// "Custom2" -> (0xb1c, "Custom2" ), 837// "Custom3" -> (0xb1d, "Custom3" ), 838// "Custom4" -> (0xb1e, "Custom4" ), 839// "Custom5" -> (0xb1f, "Custom5" ), 840// "Custom6" -> (0xb20, "Custom6" ), 841// "Custom7" -> (0xb21, "Custom7" ), 842// "Custom8" -> (0xb22, "Custom8" ), 843// "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit") 844 ) 845 val perfCntCond = List.fill(0x80)(WireInit(false.B)) 846 (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } } 847 848// ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf) 849 perfCntList.foreach { 850 case (_, (address, boringId)) => 851 if(hasPerfCnt){ 852 ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf) 853 } 854// if (!hasPerfCnt) { 855// // do not enable perfcnts except for Mcycle and Minstret 856// if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) { 857// perfCntCond(address & 0x7f) := false.B 858// } 859// } 860 } 861 862 val xstrap = WireInit(false.B) 863 if(!env.FPGAPlatform && EnableBPU){ 864 ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug) 865 } 866 def readWithScala(addr: Int): UInt = mapping(addr)._1 867 868 if (!env.FPGAPlatform) { 869 870 // display all perfcnt when nooptrap is executed 871 when (xstrap) { 872 printf("======== PerfCnt =========\n") 873 perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) => 874 printf("%d <- " + str + "\n", readWithScala(address)) 875 } 876 } 877 878 // for differential testing 879// BoringUtils.addSource(RegNext(priviledgeMode), "difftestMode") 880// BoringUtils.addSource(RegNext(mstatus), "difftestMstatus") 881// BoringUtils.addSource(RegNext(mstatus & sstatusRmask), "difftestSstatus") 882// BoringUtils.addSource(RegNext(mepc), "difftestMepc") 883// BoringUtils.addSource(RegNext(sepc), "difftestSepc") 884// BoringUtils.addSource(RegNext(mcause), "difftestMcause") 885// BoringUtils.addSource(RegNext(scause), "difftestScause") 886 BoringUtils.addSource(priviledgeMode, "difftestMode") 887 BoringUtils.addSource(mstatus, "difftestMstatus") 888 BoringUtils.addSource(mstatus & sstatusRmask, "difftestSstatus") 889 BoringUtils.addSource(mepc, "difftestMepc") 890 BoringUtils.addSource(sepc, "difftestSepc") 891 BoringUtils.addSource(mtval, "difftestMtval") 892 BoringUtils.addSource(stval, "difftestStval") 893 BoringUtils.addSource(mtvec, "difftestMtvec") 894 BoringUtils.addSource(stvec, "difftestStvec") 895 BoringUtils.addSource(mcause, "difftestMcause") 896 BoringUtils.addSource(scause, "difftestScause") 897 BoringUtils.addSource(satp, "difftestSatp") 898 BoringUtils.addSource(mipReg, "difftestMip") 899 BoringUtils.addSource(mie, "difftestMie") 900 BoringUtils.addSource(mscratch, "difftestMscratch") 901 BoringUtils.addSource(sscratch, "difftestSscratch") 902 BoringUtils.addSource(mideleg, "difftestMideleg") 903 BoringUtils.addSource(medeleg, "difftestMedeleg") 904 } else { 905// BoringUtils.addSource(readWithScala(perfCntList("Minstret")._1), "ilaInstrCnt") 906 } 907} 908