1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.ExcitingUtils.{ConnectionType, Debug} 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 val tlbCsrIO = Output(new TlbCsrBundle) 199} 200 201class CSR extends XSModule 202 with HasCSRConst 203{ 204 205 val io = IO(new CSRIO) 206 207 io.cfOut := io.cfIn 208 209 val (valid, src1, src2, func) = 210 (io.in.valid, io.in.bits.src(0), io.in.bits.uop.ctrl.imm, io.in.bits.ext.get) 211 212 // CSR define 213 214 class Priv extends Bundle { 215 val m = Output(Bool()) 216 val h = Output(Bool()) 217 val s = Output(Bool()) 218 val u = Output(Bool()) 219 } 220 221 val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U) 222 223 class MstatusStruct extends Bundle { 224 val sd = Output(UInt(1.W)) 225 226 val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null 227 val sxl = if (XLEN == 64) Output(UInt(2.W)) else null 228 val uxl = if (XLEN == 64) Output(UInt(2.W)) else null 229 val pad0 = if (XLEN == 64) Output(UInt(9.W)) else Output(UInt(8.W)) 230 231 val tsr = Output(UInt(1.W)) 232 val tw = Output(UInt(1.W)) 233 val tvm = Output(UInt(1.W)) 234 val mxr = Output(UInt(1.W)) 235 val sum = Output(UInt(1.W)) 236 val mprv = Output(UInt(1.W)) 237 val xs = Output(UInt(2.W)) 238 val fs = Output(UInt(2.W)) 239 val mpp = Output(UInt(2.W)) 240 val hpp = Output(UInt(2.W)) 241 val spp = Output(UInt(1.W)) 242 val pie = new Priv 243 val ie = new Priv 244 assert(this.getWidth == XLEN) 245 } 246 247 class SatpStruct extends Bundle { 248 val mode = UInt(4.W) 249 val asid = UInt(16.W) 250 val ppn = UInt(44.W) 251 } 252 253 class Interrupt extends Bundle { 254 val e = new Priv 255 val t = new Priv 256 val s = new Priv 257 } 258 259 // Machine-Level CSRs 260 261 val mtvec = RegInit(UInt(XLEN.W), 0.U) 262 val mcounteren = RegInit(UInt(XLEN.W), 0.U) 263 val mcause = RegInit(UInt(XLEN.W), 0.U) 264 val mtval = RegInit(UInt(XLEN.W), 0.U) 265 val mepc = Reg(UInt(XLEN.W)) 266 267 val mie = RegInit(0.U(XLEN.W)) 268 val mipWire = WireInit(0.U.asTypeOf(new Interrupt)) 269 val mipReg = RegInit(0.U.asTypeOf(new Interrupt).asUInt) 270 val mipFixMask = GenMask(9) | GenMask(5) | GenMask(1) 271 val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt) 272 273 def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}.asUInt() 274 def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}.asUInt() 275 var extList = List('a', 's', 'i', 'u') 276 if(HasMExtension){ extList = extList :+ 'm'} 277 if(HasCExtension){ extList = extList :+ 'c'} 278 if(HasFPU){ extList = extList ++ List('f', 'd')} 279 val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U 280 val misa = RegInit(UInt(XLEN.W), misaInitVal) 281 // MXL = 2 | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101 282 // (XLEN-1, XLEN-2) | |(25, 0) ZY XWVU TSRQ PONM LKJI HGFE DCBA 283 284 val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation 285 val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented 286 val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation 287 val mhartid = RegInit(UInt(XLEN.W), 0.U) // the hardware thread running the code 288 val mstatus = RegInit(UInt(XLEN.W), "h00001800".U) 289 // val mstatus = RegInit(UInt(XLEN.W), "h8000c0100".U) 290 // mstatus Value Table 291 // | sd | 292 // | pad1 | 293 // | sxl | hardlinked to 10, use 00 to pass xv6 test 294 // | uxl | hardlinked to 00 295 // | pad0 | 296 // | tsr | 297 // | tw | 298 // | tvm | 299 // | mxr | 300 // | sum | 301 // | mprv | 302 // | xs | 00 | 303 // | fs | 00 | 304 // | mpp | 00 | 305 // | hpp | 00 | 306 // | spp | 0 | 307 // | pie | 0000 | pie.h is used as UBE 308 // | ie | 0000 | uie hardlinked to 0, as N ext is not implemented 309 val mstatusStruct = mstatus.asTypeOf(new MstatusStruct) 310 def mstatusUpdateSideEffect(mstatus: UInt): UInt = { 311 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 312 val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0)) 313 mstatusNew 314 } 315 316 val mstatusMask = (~ZeroExt(( 317 GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) | 318 GenMask(37) | // MBE 319 GenMask(36) | // SBE 320 GenMask(6) // UBE 321 ), 64)).asUInt() 322 323 val medeleg = RegInit(UInt(XLEN.W), 0.U) 324 val mideleg = RegInit(UInt(XLEN.W), 0.U) 325 val mscratch = RegInit(UInt(XLEN.W), 0.U) 326 327 val pmpcfg0 = RegInit(UInt(XLEN.W), 0.U) 328 val pmpcfg1 = RegInit(UInt(XLEN.W), 0.U) 329 val pmpcfg2 = RegInit(UInt(XLEN.W), 0.U) 330 val pmpcfg3 = RegInit(UInt(XLEN.W), 0.U) 331 val pmpaddr0 = RegInit(UInt(XLEN.W), 0.U) 332 val pmpaddr1 = RegInit(UInt(XLEN.W), 0.U) 333 val pmpaddr2 = RegInit(UInt(XLEN.W), 0.U) 334 val pmpaddr3 = RegInit(UInt(XLEN.W), 0.U) 335 336 // Superviser-Level CSRs 337 338 // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U) 339 val sstatusWmask = "hc6122".U 340 // Sstatus Write Mask 341 // ------------------------------------------------------- 342 // 19 9 5 2 343 // 0 1100 0000 0001 0010 0010 344 // 0 c 0 1 2 2 345 // ------------------------------------------------------- 346 val sstatusRmask = sstatusWmask | "h8000000300018000".U 347 // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32)) 348 val stvec = RegInit(UInt(XLEN.W), 0.U) 349 // val sie = RegInit(0.U(XLEN.W)) 350 val sieMask = "h222".U & mideleg 351 val sipMask = "h222".U & mideleg 352 val satp = RegInit(0.U(XLEN.W)) 353 // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug 354 val satpMask = "h80000fffffffffff".U // disable asid, mode can only be 8 / 0 355 // val satp = RegInit(UInt(XLEN.W), 0.U) 356 val sepc = RegInit(UInt(XLEN.W), 0.U) 357 val scause = RegInit(UInt(XLEN.W), 0.U) 358 val stval = Reg(UInt(XLEN.W)) 359 val sscratch = RegInit(UInt(XLEN.W), 0.U) 360 val scounteren = RegInit(UInt(XLEN.W), 0.U) 361 362 val tlbBundle = Wire(new TlbCsrBundle) 363 tlbBundle.satp := satp.asTypeOf(new SatpStruct) 364 io.tlbCsrIO := tlbBundle 365 366 // User-Level CSRs 367 val uepc = Reg(UInt(XLEN.W)) 368 369 // fcsr 370 class FcsrStruct extends Bundle{ 371 val reserved = UInt((XLEN-3-5).W) 372 val frm = UInt(3.W) 373 val fflags = UInt(5.W) 374 assert(this.getWidth == XLEN) 375 } 376 val fcsr = RegInit(0.U(XLEN.W)) 377 // set mstatus->sd and mstatus->fs when true 378 val csrw_dirty_fp_state = WireInit(false.B) 379 380 def frm_wfn(wdata: UInt): UInt = { 381 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 382 csrw_dirty_fp_state := true.B 383 fcsrOld.frm := wdata(2,0) 384 fcsrOld.asUInt() 385 } 386 def frm_rfn(rdata: UInt): UInt = rdata(7,5) 387 388 def fflags_wfn(wdata: UInt): UInt = { 389 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 390 csrw_dirty_fp_state := true.B 391 fcsrOld.fflags := wdata(4,0) 392 fcsrOld.asUInt() 393 } 394 def fflags_rfn(rdata:UInt): UInt = rdata(4,0) 395 396 def fcsr_wfn(wdata: UInt): UInt = { 397 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 398 csrw_dirty_fp_state := true.B 399 Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags) 400 } 401 402 val fcsrMapping = Map( 403 MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn, rfn = fflags_rfn), 404 MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn), 405 MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn) 406 ) 407 408 // Atom LR/SC Control Bits 409// val setLr = WireInit(Bool(), false.B) 410// val setLrVal = WireInit(Bool(), false.B) 411// val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check 412// val lr = RegInit(Bool(), false.B) 413// val lrAddr = RegInit(UInt(AddrBits.W), 0.U) 414// BoringUtils.addSink(setLr, "set_lr") 415// BoringUtils.addSink(setLrVal, "set_lr_val") 416// BoringUtils.addSink(setLrAddr, "set_lr_addr") 417// BoringUtils.addSource(lr, "lr") 418// BoringUtils.addSource(lrAddr, "lr_addr") 419// 420// when(setLr){ 421// lr := setLrVal 422// lrAddr := setLrAddr 423// } 424 425 // Hart Priviledge Mode 426 val priviledgeMode = RegInit(UInt(2.W), ModeM) 427 428 // perfcnt 429 val hasPerfCnt = !env.FPGAPlatform 430 val nrPerfCnts = if (hasPerfCnt) 0x80 else 0x3 431 val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W))) 432 val perfCntsLoMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb00 + i, perfCnts(i))) 433 val perfCntsHiMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb80 + i, perfCnts(i)(63, 32))) 434 435 // CSR reg map 436 val mapping = Map( 437 438 // User Trap Setup 439 // MaskedRegMap(Ustatus, ustatus), 440 // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable), 441 // MaskedRegMap(Utvec, utvec), 442 443 // User Trap Handling 444 // MaskedRegMap(Uscratch, uscratch), 445 // MaskedRegMap(Uepc, uepc), 446 // MaskedRegMap(Ucause, ucause), 447 // MaskedRegMap(Utval, utval), 448 // MaskedRegMap(Uip, uip), 449 450 // User Counter/Timers 451 // MaskedRegMap(Cycle, cycle), 452 // MaskedRegMap(Time, time), 453 // MaskedRegMap(Instret, instret), 454 455 // Supervisor Trap Setup 456 MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask), 457 458 // MaskedRegMap(Sedeleg, Sedeleg), 459 // MaskedRegMap(Sideleg, Sideleg), 460 MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask), 461 MaskedRegMap(Stvec, stvec), 462 MaskedRegMap(Scounteren, scounteren), 463 464 // Supervisor Trap Handling 465 MaskedRegMap(Sscratch, sscratch), 466 MaskedRegMap(Sepc, sepc), 467 MaskedRegMap(Scause, scause), 468 MaskedRegMap(Stval, stval), 469 MaskedRegMap(Sip, mip.asUInt, sipMask, MaskedRegMap.Unwritable, sipMask), 470 471 // Supervisor Protection and Translation 472 MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask), 473 474 // Machine Information Registers 475 MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable), 476 MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable), 477 MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable), 478 MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable), 479 480 // Machine Trap Setup 481 // MaskedRegMap(Mstatus, mstatus, "hffffffffffffffee".U, (x=>{printf("mstatus write: %x time: %d\n", x, GTimer()); x})), 482 MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask), 483 MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable 484 MaskedRegMap(Medeleg, medeleg, "hf3ff".U), 485 MaskedRegMap(Mideleg, mideleg, "h222".U), 486 MaskedRegMap(Mie, mie), 487 MaskedRegMap(Mtvec, mtvec), 488 MaskedRegMap(Mcounteren, mcounteren), 489 490 // Machine Trap Handling 491 MaskedRegMap(Mscratch, mscratch), 492 MaskedRegMap(Mepc, mepc), 493 MaskedRegMap(Mcause, mcause), 494 MaskedRegMap(Mtval, mtval), 495 MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable), 496 497 // Machine Memory Protection 498 MaskedRegMap(Pmpcfg0, pmpcfg0), 499 MaskedRegMap(Pmpcfg1, pmpcfg1), 500 MaskedRegMap(Pmpcfg2, pmpcfg2), 501 MaskedRegMap(Pmpcfg3, pmpcfg3), 502 MaskedRegMap(PmpaddrBase + 0, pmpaddr0), 503 MaskedRegMap(PmpaddrBase + 1, pmpaddr1), 504 MaskedRegMap(PmpaddrBase + 2, pmpaddr2), 505 MaskedRegMap(PmpaddrBase + 3, pmpaddr3) 506 507 ) ++ 508 perfCntsLoMapping ++ (if (XLEN == 32) perfCntsHiMapping else Nil) ++ 509 (if(HasFPU) fcsrMapping else Nil) 510 511 val addr = src2(11, 0) 512 val rdata = Wire(UInt(XLEN.W)) 513 val csri = ZeroExt(io.cfIn.instr(19,15), XLEN) //unsigned imm for csri. [TODO] 514 val wdata = LookupTree(func, List( 515 CSROpType.wrt -> src1, 516 CSROpType.set -> (rdata | src1), 517 CSROpType.clr -> (rdata & (~src1).asUInt()), 518 CSROpType.wrti -> csri,//TODO: csri --> src2 519 CSROpType.seti -> (rdata | csri), 520 CSROpType.clri -> (rdata & (~csri).asUInt()) 521 )) 522 523 // satp wen check 524 val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U) 525 526 // general CSR wen check 527 val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode) 528 val permitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode) 529 // Writeable check is ingored. 530 // Currently, write to illegal csr addr will be ignored 531 MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata) 532 io.out.bits.data := rdata 533 io.out.bits.uop := io.in.bits.uop 534 535 // Fix Mip/Sip write 536 val fixMapping = Map( 537 MaskedRegMap(Mip, mipReg.asUInt, mipFixMask), 538 MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask) 539 ) 540 val rdataDummy = Wire(UInt(XLEN.W)) 541 MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata) 542 543 when(io.fpu_csr.fflags.asUInt() =/= 0.U){ 544 fcsr := fflags_wfn(io.fpu_csr.fflags.asUInt()) 545 } 546 // set fs and sd in mstatus 547 when(csrw_dirty_fp_state || io.fpu_csr.dirty_fs){ 548 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 549 mstatusNew.fs := "b11".U 550 mstatusNew.sd := true.B 551 mstatus := mstatusNew.asUInt() 552 } 553 io.fpu_csr.frm := fcsr.asTypeOf(new FcsrStruct).frm 554 555 // CSR inst decode 556 val isEbreak = addr === privEbreak && func === CSROpType.jmp 557 val isEcall = addr === privEcall && func === CSROpType.jmp 558 val isMret = addr === privMret && func === CSROpType.jmp 559 val isSret = addr === privSret && func === CSROpType.jmp 560 val isUret = addr === privUret && func === CSROpType.jmp 561 562 XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", io.cfIn.pc, addr, rdata, wdata, func) 563 XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode) 564 565 // Illegal priviledged operation list 566 val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool 567 568 // Illegal priviledged instruction check 569 val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr) 570 val isIllegalAccess = !permitted 571 val isIllegalPrivOp = illegalSModeSret 572 573 // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) 574 // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex)) 575 // imem 576 // val imemPtev = true.B 577 // val imemPteu = true.B 578 // val imemPtex = true.B 579 // val imemReq = true.B 580 // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu) 581 // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex) 582 // assert(!hasInstrPageFault) 583 584 // dmem 585 // val dmemPtev = true.B 586 // val dmemPteu = true.B 587 // val dmemReq = true.B 588 // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu) 589 // val dmemIsStore = true.B 590 591 // val hasLoadPageFault = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed) 592 // val hasStorePageFault = dmemReq && dmemIsStore && !(dmemPermissionCheckPassed) 593 // assert(!hasLoadPageFault) 594 // assert(!hasStorePageFault) 595 596 //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet 597 tlbBundle.priv.mxr := mstatusStruct.mxr.asBool 598 tlbBundle.priv.sum := mstatusStruct.sum.asBool 599 tlbBundle.priv.imode := priviledgeMode 600 tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode) 601 602 val hasInstrPageFault = io.exception.bits.cf.exceptionVec(instrPageFault) && io.exception.valid 603 val hasLoadPageFault = io.exception.bits.cf.exceptionVec(loadPageFault) && io.exception.valid 604 val hasStorePageFault = io.exception.bits.cf.exceptionVec(storePageFault) && io.exception.valid 605 val hasStoreAddrMisaligned = io.exception.bits.cf.exceptionVec(storeAddrMisaligned) && io.exception.valid 606 val hasLoadAddrMisaligned = io.exception.bits.cf.exceptionVec(loadAddrMisaligned) && io.exception.valid 607 608 // mtval write logic 609 val memExceptionAddr = SignExt(io.memExceptionVAddr, XLEN) 610 when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){ 611 val tval = Mux( 612 hasInstrPageFault, 613 Mux( 614 io.exception.bits.cf.crossPageIPFFix, 615 SignExt(io.exception.bits.cf.pc + 2.U, XLEN), 616 SignExt(io.exception.bits.cf.pc, XLEN) 617 ), 618 memExceptionAddr 619 ) 620 when(priviledgeMode === ModeM){ 621 mtval := tval 622 }.otherwise{ 623 stval := tval 624 } 625 } 626 627 when(hasLoadAddrMisaligned || hasStoreAddrMisaligned) 628 { 629 mtval := memExceptionAddr 630 } 631 632 // Exception and Intr 633 634 // interrupts 635 636 val ideleg = (mideleg & mip.asUInt) 637 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 638 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 639 640 val intrVecEnable = Wire(Vec(12, Bool())) 641 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 642 val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt 643 val intrBitSet = intrVec.orR() 644 io.interrupt := intrBitSet 645 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 646 val raiseIntr = intrBitSet && io.exception.valid 647 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", io.exception.bits.cf.pc, intrNO) 648 649 mipWire.t.m := io.mtip 650 mipWire.s.m := io.msip 651 mipWire.e.m := io.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 ExcitingUtils.addSource(causeNO, "difftestCausefromCSR") 677 678 val raiseExceptionIntr = io.exception.valid 679 val retTarget = Wire(UInt(VAddrBits.W)) 680 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 681 io.redirectOut := DontCare 682 io.redirectOutValid := valid && func === CSROpType.jmp && !isEcall 683 io.redirectOut.target := retTarget 684 io.flushPipe := resetSatp 685 686 XSDebug(io.redirectOutValid, "redirect to %x, pc=%x\n", io.redirectOut.target, io.cfIn.pc) 687 688 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) 689 XSDebug(raiseExceptionIntr, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.exception.bits.cf.pc, mstatus, mideleg, medeleg, priviledgeMode) 690 691 // Branch control 692 693 val deleg = Mux(raiseIntr, mideleg , medeleg) 694 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 695 val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM) 696 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check 697 698 io.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0) 699 retTarget := DontCare 700 // val illegalEret = TODO 701 702 when (valid && isMret) { 703 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 704 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 705 mstatusNew.ie.m := mstatusOld.pie.m 706 priviledgeMode := mstatusOld.mpp 707 mstatusNew.pie.m := true.B 708 mstatusNew.mpp := ModeU 709 mstatusNew.mprv := 0.U 710 mstatus := mstatusNew.asUInt 711// lr := false.B 712 retTarget := mepc(VAddrBits-1, 0) 713 } 714 715 when (valid && isSret && !illegalSModeSret) { 716 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 717 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 718 mstatusNew.ie.s := mstatusOld.pie.s 719 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 720 mstatusNew.pie.s := true.B 721 mstatusNew.spp := ModeU 722 mstatus := mstatusNew.asUInt 723 mstatusNew.mprv := 0.U 724 // lr := false.B 725 retTarget := sepc(VAddrBits-1, 0) 726 } 727 728 when (valid && isUret) { 729 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 730 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 731 // mstatusNew.mpp.m := ModeU //TODO: add mode U 732 mstatusNew.ie.u := mstatusOld.pie.u 733 priviledgeMode := ModeU 734 mstatusNew.pie.u := true.B 735 mstatus := mstatusNew.asUInt 736 retTarget := uepc(VAddrBits-1, 0) 737 } 738 739 when (raiseExceptionIntr) { 740 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 741 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 742 743 when (delegS) { 744 scause := causeNO 745 sepc := SignExt(io.exception.bits.cf.pc, XLEN) 746 mstatusNew.spp := priviledgeMode 747 mstatusNew.pie.s := mstatusOld.ie.s 748 mstatusNew.ie.s := false.B 749 priviledgeMode := ModeS 750 when(tvalWen){stval := 0.U} 751 // trapTarget := stvec(VAddrBits-1. 0) 752 }.otherwise { 753 mcause := causeNO 754 mepc := SignExt(io.exception.bits.cf.pc, XLEN) 755 mstatusNew.mpp := priviledgeMode 756 mstatusNew.pie.m := mstatusOld.ie.m 757 mstatusNew.ie.m := false.B 758 priviledgeMode := ModeM 759 when(tvalWen){mtval := 0.U} 760 // trapTarget := mtvec(VAddrBits-1. 0) 761 } 762 763 mstatus := mstatusNew.asUInt 764 } 765 766 io.in.ready := true.B 767 io.out.valid := valid 768 769 770 XSDebug(io.redirectOutValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n", 771 io.redirectOut.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid) 772 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", 773 io.redirectOutValid, io.redirectOut.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid) 774 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", io.cfIn.pc) 775 776 777 // perfcnt 778 779 val perfCntList = Map( 780// "Mcycle" -> (0xb00, "perfCntCondMcycle" ), 781// "Minstret" -> (0xb02, "perfCntCondMinstret" ), 782 "MbpInstr" -> (0xb03, "perfCntCondMbpInstr" ), 783 "MbpRight" -> (0xb04, "perfCntCondMbpRight" ), 784 "MbpWrong" -> (0xb05, "perfCntCondMbpWrong" ), 785 "MbpBRight" -> (0xb06, "perfCntCondMbpBRight" ), 786 "MbpBWrong" -> (0xb07, "perfCntCondMbpBWrong" ), 787 "MbpJRight" -> (0xb08, "perfCntCondMbpJRight" ), 788 "MbpJWrong" -> (0xb09, "perfCntCondMbpJWrong" ), 789 "MbpIRight" -> (0xb0a, "perfCntCondMbpIRight" ), 790 "MbpIWrong" -> (0xb0b, "perfCntCondMbpIWrong" ), 791 "MbpRRight" -> (0xb0c, "perfCntCondMbpRRight" ), 792 "MbpRWrong" -> (0xb0d, "perfCntCondMbpRWrong" ), 793 "DpqReplay" -> (0xb0e, "perfCntCondDpqReplay" ), 794 "RoqWalk" -> (0xb0f, "perfCntCondRoqWalk" ), 795 "RoqWaitInt" -> (0xb10, "perfCntCondRoqWaitInt" ), 796 "RoqWaitFp" -> (0xb11, "perfCntCondRoqWaitFp" ), 797 "RoqWaitLoad" -> (0xb12, "perfCntCondRoqWaitLoad" ), 798 "RoqWaitStore"-> (0xb13, "perfCntCondRoqWaitStore"), 799 "Dp1Empty" -> (0xb14, "perfCntCondDp1Empty" ), 800 "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0" ), 801 "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1" ), 802 "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2" ), 803 "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3" ), 804 "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0" ), 805 "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1" ), 806 "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2" ), 807 "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3" ), 808 "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0" ), 809 "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0" ), 810 "PtwReqCnt" -> (0xb25, "perfCntPtwReqCnt" ), 811 "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt" ), 812 "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit" ), 813 "ICacheReq" -> (0xb28, "perfCntIcacheReqCnt" ), 814 "ICacheMiss" -> (0xb29, "perfCntIcacheMissCnt" ) 815// "Custom1" -> (0xb1b, "Custom1" ), 816// "Custom2" -> (0xb1c, "Custom2" ), 817// "Custom3" -> (0xb1d, "Custom3" ), 818// "Custom4" -> (0xb1e, "Custom4" ), 819// "Custom5" -> (0xb1f, "Custom5" ), 820// "Custom6" -> (0xb20, "Custom6" ), 821// "Custom7" -> (0xb21, "Custom7" ), 822// "Custom8" -> (0xb22, "Custom8" ), 823// "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit") 824 ) 825 val perfCntCond = List.fill(0x80)(WireInit(false.B)) 826 (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } } 827 828// ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf) 829 perfCntList.foreach { 830 case (_, (address, boringId)) => 831 if(hasPerfCnt){ 832 ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf) 833 } 834// if (!hasPerfCnt) { 835// // do not enable perfcnts except for Mcycle and Minstret 836// if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) { 837// perfCntCond(address & 0x7f) := false.B 838// } 839// } 840 } 841 842 val xstrap = WireInit(false.B) 843 if(!env.FPGAPlatform && EnableBPU){ 844 ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug) 845 } 846 def readWithScala(addr: Int): UInt = mapping(addr)._1 847 848 if (!env.FPGAPlatform) { 849 850 // display all perfcnt when nooptrap is executed 851 when (xstrap) { 852 printf("======== PerfCnt =========\n") 853 perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) => 854 printf("%d <- " + str + "\n", readWithScala(address)) 855 } 856 } 857 858 // for differential testing 859// BoringUtils.addSource(RegNext(priviledgeMode), "difftestMode") 860// BoringUtils.addSource(RegNext(mstatus), "difftestMstatus") 861// BoringUtils.addSource(RegNext(mstatus & sstatusRmask), "difftestSstatus") 862// BoringUtils.addSource(RegNext(mepc), "difftestMepc") 863// BoringUtils.addSource(RegNext(sepc), "difftestSepc") 864// BoringUtils.addSource(RegNext(mcause), "difftestMcause") 865// BoringUtils.addSource(RegNext(scause), "difftestScause") 866 ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug) 867 ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug) 868 ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug) 869 ExcitingUtils.addSource(mepc, "difftestMepc", Debug) 870 ExcitingUtils.addSource(sepc, "difftestSepc", Debug) 871 ExcitingUtils.addSource(mtval, "difftestMtval", Debug) 872 ExcitingUtils.addSource(stval, "difftestStval", Debug) 873 ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug) 874 ExcitingUtils.addSource(stvec, "difftestStvec", Debug) 875 ExcitingUtils.addSource(mcause, "difftestMcause", Debug) 876 ExcitingUtils.addSource(scause, "difftestScause", Debug) 877 ExcitingUtils.addSource(satp, "difftestSatp", Debug) 878 ExcitingUtils.addSource(mipReg, "difftestMip", Debug) 879 ExcitingUtils.addSource(mie, "difftestMie", Debug) 880 ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug) 881 ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug) 882 ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug) 883 ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug) 884 } else { 885// BoringUtils.addSource(readWithScala(perfCntList("Minstret")._1), "ilaInstrCnt") 886 } 887} 888