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 168class PerfCounterIO extends XSBundle { 169 val value = Input(UInt(XLEN.W)) 170} 171 172class CSRIO extends FunctionUnitIO { 173 val cfIn = Input(new CtrlFlow) 174 val redirect = Output(new Redirect) 175 val redirectValid = Output(Bool()) 176 val fpu_csr = Flipped(new FpuCsrIO) 177 val cfOut = Output(new CtrlFlow) 178 // from rob 179 val exception = Flipped(ValidIO(new MicroOp)) 180 // for exception check 181 val instrValid = Input(Bool()) 182 val flushPipe = Output(Bool()) 183 // for differential testing 184// val intrNO = Output(UInt(XLEN.W)) 185 val wenFix = Output(Bool()) 186 val perf = Vec(NumPerfCounters, new PerfCounterIO) 187 val memExceptionVAddr = Input(UInt(VAddrBits.W)) 188 val trapTarget = Output(UInt(VAddrBits.W)) 189 val mtip = Input(Bool()) 190 val msip = Input(Bool()) 191 val meip = Input(Bool()) 192 val interrupt = Output(Bool()) 193} 194 195class CSR extends FunctionUnit(csrCfg) with HasCSRConst{ 196 val io = IO(new CSRIO) 197 198 io.cfOut := io.cfIn 199 200 val (valid, src1, src2, func) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.func) 201 def access(valid: Bool, src1: UInt, src2: UInt, func: UInt): UInt = { 202 this.valid := valid 203 this.src1 := src1 204 this.src2 := src2 205 this.func := func 206 io.out.bits 207 } 208 209 // CSR define 210 211 class Priv extends Bundle { 212 val m = Output(Bool()) 213 val h = Output(Bool()) 214 val s = Output(Bool()) 215 val u = Output(Bool()) 216 } 217 218 val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U) 219 220 class MstatusStruct extends Bundle { 221 val sd = Output(UInt(1.W)) 222 223 val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null 224 val sxl = if (XLEN == 64) Output(UInt(2.W)) else null 225 val uxl = if (XLEN == 64) Output(UInt(2.W)) else null 226 val pad0 = if (XLEN == 64) Output(UInt(9.W)) else Output(UInt(8.W)) 227 228 val tsr = Output(UInt(1.W)) 229 val tw = Output(UInt(1.W)) 230 val tvm = Output(UInt(1.W)) 231 val mxr = Output(UInt(1.W)) 232 val sum = Output(UInt(1.W)) 233 val mprv = Output(UInt(1.W)) 234 val xs = Output(UInt(2.W)) 235 val fs = Output(UInt(2.W)) 236 val mpp = Output(UInt(2.W)) 237 val hpp = Output(UInt(2.W)) 238 val spp = Output(UInt(1.W)) 239 val pie = new Priv 240 val ie = new Priv 241 assert(this.getWidth == XLEN) 242 } 243 244 class SatpStruct extends Bundle { 245 val mode = UInt(4.W) 246 val asid = UInt(16.W) 247 val ppn = UInt(44.W) 248 } 249 250 class Interrupt extends Bundle { 251 val e = new Priv 252 val t = new Priv 253 val s = new Priv 254 } 255 256 // Machine-Level CSRs 257 258 val mtvec = RegInit(UInt(XLEN.W), 0.U) 259 val mcounteren = RegInit(UInt(XLEN.W), 0.U) 260 val mcause = RegInit(UInt(XLEN.W), 0.U) 261 val mtval = RegInit(UInt(XLEN.W), 0.U) 262 val mepc = Reg(UInt(XLEN.W)) 263 264 val mie = RegInit(0.U(XLEN.W)) 265 val mipWire = WireInit(0.U.asTypeOf(new Interrupt)) 266 val mipReg = RegInit(0.U.asTypeOf(new Interrupt).asUInt) 267 val mipFixMask = GenMask(9) | GenMask(5) | GenMask(1) 268 val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt) 269 270 def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)} 271 def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)} 272 var extList = List('a', 's', 'i', 'u') 273 if(HasMExtension){ extList = extList :+ 'm'} 274 if(HasCExtension){ extList = extList :+ 'c'} 275 if(HasFPU){ extList = extList ++ List('f', 'd')} 276 val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U 277 val misa = RegInit(UInt(XLEN.W), misaInitVal) 278 // MXL = 2 | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101 279 // (XLEN-1, XLEN-2) | |(25, 0) ZY XWVU TSRQ PONM LKJI HGFE DCBA 280 281 val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation 282 val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented 283 val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation 284 val mhartid = RegInit(UInt(XLEN.W), 0.U) // the hardware thread running the code 285 val mstatus = RegInit(UInt(XLEN.W), "h00001800".U) 286 // val mstatus = RegInit(UInt(XLEN.W), "h8000c0100".U) 287 // mstatus Value Table 288 // | sd | 289 // | pad1 | 290 // | sxl | hardlinked to 10, use 00 to pass xv6 test 291 // | uxl | hardlinked to 00 292 // | pad0 | 293 // | tsr | 294 // | tw | 295 // | tvm | 296 // | mxr | 297 // | sum | 298 // | mprv | 299 // | xs | 00 | 300 // | fs | 00 | 301 // | mpp | 00 | 302 // | hpp | 00 | 303 // | spp | 0 | 304 // | pie | 0000 | pie.h is used as UBE 305 // | ie | 0000 | uie hardlinked to 0, as N ext is not implemented 306 val mstatusStruct = mstatus.asTypeOf(new MstatusStruct) 307 def mstatusUpdateSideEffect(mstatus: UInt): UInt = { 308 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 309 val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0)) 310 mstatusNew 311 } 312 313 val mstatusMask = ~ZeroExt(( 314 GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) | 315 GenMask(37) | // MBE 316 GenMask(36) | // SBE 317 GenMask(6) // UBE 318 ), 64) 319 320 val medeleg = RegInit(UInt(XLEN.W), 0.U) 321 val mideleg = RegInit(UInt(XLEN.W), 0.U) 322 val mscratch = RegInit(UInt(XLEN.W), 0.U) 323 324 val pmpcfg0 = RegInit(UInt(XLEN.W), 0.U) 325 val pmpcfg1 = RegInit(UInt(XLEN.W), 0.U) 326 val pmpcfg2 = RegInit(UInt(XLEN.W), 0.U) 327 val pmpcfg3 = RegInit(UInt(XLEN.W), 0.U) 328 val pmpaddr0 = RegInit(UInt(XLEN.W), 0.U) 329 val pmpaddr1 = RegInit(UInt(XLEN.W), 0.U) 330 val pmpaddr2 = RegInit(UInt(XLEN.W), 0.U) 331 val pmpaddr3 = RegInit(UInt(XLEN.W), 0.U) 332 333 // Superviser-Level CSRs 334 335 // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U) 336 val sstatusWmask = "hc6122".U 337 // Sstatus Write Mask 338 // ------------------------------------------------------- 339 // 19 9 5 2 340 // 0 1100 0000 0001 0010 0010 341 // 0 c 0 1 2 2 342 // ------------------------------------------------------- 343 val sstatusRmask = sstatusWmask | "h8000000300018000".U 344 // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32)) 345 val stvec = RegInit(UInt(XLEN.W), 0.U) 346 // val sie = RegInit(0.U(XLEN.W)) 347 val sieMask = "h222".U & mideleg 348 val sipMask = "h222".U & mideleg 349 val satp = RegInit(0.U(XLEN.W)) 350 // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug 351 val satpMask = "h80000fffffffffff".U // disable asid, mode can only be 8 / 0 352 // val satp = RegInit(UInt(XLEN.W), 0.U) 353 val sepc = RegInit(UInt(XLEN.W), 0.U) 354 val scause = RegInit(UInt(XLEN.W), 0.U) 355 val stval = Reg(UInt(XLEN.W)) 356 val sscratch = RegInit(UInt(XLEN.W), 0.U) 357 val scounteren = RegInit(UInt(XLEN.W), 0.U) 358 359 val tlbBundle = Wire(new TlbCsrBundle) 360 // val sfence = Wire(new SfenceBundle) 361 tlbBundle.satp := satp.asTypeOf(new SatpStruct) 362 // sfence := 0.U.asTypeOf(new SfenceBundle) 363 BoringUtils.addSource(tlbBundle, "TLBCSRIO") 364 // BoringUtils.addSource(sfence, "SfenceBundle") // FIXME: move to MOU 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 := rdata 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.redirect := DontCare 681 io.redirectValid := valid && func === CSROpType.jmp && !isEcall 682 io.redirect.target := retTarget 683 io.flushPipe := resetSatp 684 685 XSDebug(io.redirectValid, "redirect to %x, pc=%x\n", io.redirect.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.redirectValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n", 770 io.redirect.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.redirectValid, io.redirect.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