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