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