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