1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.util._ 5import chisel3.util.experimental.BoringUtils 6import fpu.Fflags 7import noop.MMUIO 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, NOOP 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 privMret = 0x302.U 95 def privSret = 0x102.U 96 def privUret = 0x002.U 97 98 def ModeM = 0x3.U 99 def ModeH = 0x2.U 100 def ModeS = 0x1.U 101 def ModeU = 0x0.U 102 103 def IRQ_UEIP = 0 104 def IRQ_SEIP = 1 105 def IRQ_MEIP = 3 106 107 def IRQ_UTIP = 4 108 def IRQ_STIP = 5 109 def IRQ_MTIP = 7 110 111 def IRQ_USIP = 8 112 def IRQ_SSIP = 9 113 def IRQ_MSIP = 11 114 115 val IntPriority = Seq( 116 IRQ_MEIP, IRQ_MSIP, IRQ_MTIP, 117 IRQ_SEIP, IRQ_SSIP, IRQ_STIP, 118 IRQ_UEIP, IRQ_USIP, IRQ_UTIP 119 ) 120} 121 122trait HasExceptionNO { 123 def instrAddrMisaligned = 0 124 def instrAccessFault = 1 125 def illegalInstr = 2 126 def breakPoint = 3 127 def loadAddrMisaligned = 4 128 def loadAccessFault = 5 129 def storeAddrMisaligned = 6 130 def storeAccessFault = 7 131 def ecallU = 8 132 def ecallS = 9 133 def ecallM = 11 134 def instrPageFault = 12 135 def loadPageFault = 13 136 def storePageFault = 15 137 138 val ExcPriority = Seq( 139 breakPoint, // TODO: different BP has different priority 140 instrPageFault, 141 instrAccessFault, 142 illegalInstr, 143 instrAddrMisaligned, 144 ecallM, ecallS, ecallU, 145 storeAddrMisaligned, 146 loadAddrMisaligned, 147 storePageFault, 148 loadPageFault, 149 storeAccessFault, 150 loadAccessFault 151 ) 152} 153 154class FpuCsrIO extends XSBundle { 155 val fflags = Output(new Fflags) 156 val isIllegal = Output(Bool()) 157 val dirty_fs = Output(Bool()) 158 val frm = Input(UInt(3.W)) 159} 160 161class CSRIO extends FunctionUnitIO { 162 val cfIn = Input(new CtrlFlow) 163 val redirect = Output(new Redirect) 164 val redirectValid = Output(Bool()) 165 val fpu_csr = Flipped(new FpuCsrIO) 166 val cfOut = Output(new CtrlFlow) 167 // from rob 168 val exception = Flipped(ValidIO(new MicroOp)) 169 // for exception check 170 val instrValid = Input(Bool()) 171 // for differential testing 172// val intrNO = Output(UInt(XLEN.W)) 173 val imemMMU = Flipped(new MMUIO) 174 val dmemMMU = Flipped(new MMUIO) 175 val wenFix = Output(Bool()) 176} 177 178class CSR(implicit val p: XSConfig) extends FunctionUnit(csrCfg) with HasCSRConst{ 179 val io = IO(new CSRIO) 180 181 io.cfOut := io.cfIn 182 183 val (valid, src1, src2, func) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.func) 184 def access(valid: Bool, src1: UInt, src2: UInt, func: UInt): UInt = { 185 this.valid := valid 186 this.src1 := src1 187 this.src2 := src2 188 this.func := func 189 io.out.bits 190 } 191 192 // CSR define 193 194 class Priv extends Bundle { 195 val m = Output(Bool()) 196 val h = Output(Bool()) 197 val s = Output(Bool()) 198 val u = Output(Bool()) 199 } 200 201 val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U) 202 203 class MstatusStruct extends Bundle { 204 val sd = Output(UInt(1.W)) 205 val pad1 = Output(UInt((XLEN-37).W)) 206 val sxl = Output(UInt(2.W)) 207 val uxl = Output(UInt(2.W)) 208 val pad0 = Output(UInt(9.W)) 209 val tsr = Output(UInt(1.W)) 210 val tw = Output(UInt(1.W)) 211 val tvm = Output(UInt(1.W)) 212 val mxr = Output(UInt(1.W)) 213 val sum = Output(UInt(1.W)) 214 val mprv = Output(UInt(1.W)) 215 val xs = Output(UInt(2.W)) 216 val fs = Output(UInt(2.W)) 217 val mpp = Output(UInt(2.W)) 218 val hpp = Output(UInt(2.W)) 219 val spp = Output(UInt(1.W)) 220 val pie = new Priv 221 val ie = new Priv 222 assert(this.getWidth == XLEN) 223 } 224 225 class Interrupt extends Bundle { 226 val e = new Priv 227 val t = new Priv 228 val s = new Priv 229 } 230 231 // Machine-Level CSRs 232 233 val mtvec = RegInit(UInt(XLEN.W), 0.U) 234 val mcounteren = RegInit(UInt(XLEN.W), 0.U) 235 val mcause = RegInit(UInt(XLEN.W), 0.U) 236 val mtval = RegInit(UInt(XLEN.W), 0.U) 237 val mepc = Reg(UInt(XLEN.W)) 238 239 val mie = RegInit(0.U(XLEN.W)) 240 val mipWire = WireInit(0.U.asTypeOf(new Interrupt)) 241 val mipReg = RegInit(0.U.asTypeOf(new Interrupt).asUInt) 242 val mipFixMask = "h777".U 243 val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt) 244 245 def getMisaMxl(mxl: Int): UInt = (mxl.U << (XLEN-2)).asUInt() 246 def getMisaExt(ext: Char): UInt = (1.U << (ext.toInt - 'a'.toInt)).asUInt() 247 var extList = List('a', 's', 'i', 'u') 248 if(HasMExtension){ extList = extList :+ 'm'} 249 if(HasCExtension){ extList = extList :+ 'c'} 250 if(HasFPU){ extList = extList ++ List('f', 'd')} 251 val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U 252 val misa = RegInit(UInt(XLEN.W), misaInitVal) 253 // MXL = 2 | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101 254 // (XLEN-1, XLEN-2) | |(25, 0) ZY XWVU TSRQ PONM LKJI HGFE DCBA 255 256 val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation 257 val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented 258 val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation 259 val mhartid = RegInit(UInt(XLEN.W), 0.U) // the hardware thread running the code 260 val mstatus = RegInit(UInt(XLEN.W), "h00001800".U) 261 // val mstatus = RegInit(UInt(XLEN.W), "h8000c0100".U) 262 // mstatus Value Table 263 // | sd | 264 // | pad1 | 265 // | sxl | hardlinked to 10, use 00 to pass xv6 test 266 // | uxl | hardlinked to 00 267 // | pad0 | 268 // | tsr | 269 // | tw | 270 // | tvm | 271 // | mxr | 272 // | sum | 273 // | mprv | 274 // | xs | 00 | 275 // | fs | 276 // | mpp | 00 | 277 // | hpp | 00 | 278 // | spp | 0 | 279 // | pie | 0000 | 280 // | ie | 0000 | uie hardlinked to 0, as N ext is not implemented 281 val mstatusStruct = mstatus.asTypeOf(new MstatusStruct) 282 def mstatusUpdateSideEffect(mstatus: UInt): UInt = { 283 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 284 val mstatusNew = Cat(mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0)) 285 mstatusNew 286 } 287 288 val medeleg = RegInit(UInt(XLEN.W), 0.U) 289 val mideleg = RegInit(UInt(XLEN.W), 0.U) 290 val mscratch = RegInit(UInt(XLEN.W), 0.U) 291 292 val pmpcfg0 = RegInit(UInt(XLEN.W), 0.U) 293 val pmpcfg1 = RegInit(UInt(XLEN.W), 0.U) 294 val pmpcfg2 = RegInit(UInt(XLEN.W), 0.U) 295 val pmpcfg3 = RegInit(UInt(XLEN.W), 0.U) 296 val pmpaddr0 = RegInit(UInt(XLEN.W), 0.U) 297 val pmpaddr1 = RegInit(UInt(XLEN.W), 0.U) 298 val pmpaddr2 = RegInit(UInt(XLEN.W), 0.U) 299 val pmpaddr3 = RegInit(UInt(XLEN.W), 0.U) 300 301 // Superviser-Level CSRs 302 303 // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U) 304 val sstatusWmask = "hc6122".U 305 // Sstatus Write Mask 306 // ------------------------------------------------------- 307 // 19 9 5 2 308 // 0 1100 0000 0001 0010 0010 309 // 0 c 0 1 2 2 310 // ------------------------------------------------------- 311 val sstatusRmask = sstatusWmask | "h8000000300018000".U 312 // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32)) 313 val stvec = RegInit(UInt(XLEN.W), 0.U) 314 // val sie = RegInit(0.U(XLEN.W)) 315 val sieMask = "h222".U & mideleg 316 val sipMask = "h222".U & mideleg 317 //val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) 318 val satp = RegInit(UInt(XLEN.W), 0.U) 319 val sepc = RegInit(UInt(XLEN.W), 0.U) 320 val scause = RegInit(UInt(XLEN.W), 0.U) 321 val stval = Reg(UInt(XLEN.W)) 322 val sscratch = RegInit(UInt(XLEN.W), 0.U) 323 val scounteren = RegInit(UInt(XLEN.W), 0.U) 324 BoringUtils.addSource(satp, "CSRSATP") 325 326 // User-Level CSRs 327 val uepc = Reg(UInt(XLEN.W)) 328 329 // fcsr 330 class FcsrStruct extends Bundle{ 331 val reserved = UInt((XLEN-3-5).W) 332 val frm = UInt(3.W) 333 val fflags = UInt(5.W) 334 assert(this.getWidth == XLEN) 335 } 336 val fcsr = RegInit(0.U(XLEN.W)) 337 // set mstatus->sd and mstatus->fs when true 338 val csrw_dirty_fp_state = WireInit(false.B) 339 340 def frm_wfn(wdata: UInt): UInt = { 341 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 342 csrw_dirty_fp_state := true.B 343 fcsrOld.frm := wdata(2,0) 344 fcsrOld.asUInt() 345 } 346 def frm_rfn(rdata: UInt): UInt = rdata(7,5) 347 348 def fflags_wfn(wdata: UInt): UInt = { 349 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 350 csrw_dirty_fp_state := true.B 351 fcsrOld.fflags := wdata(4,0) 352 fcsrOld.asUInt() 353 } 354 def fflags_rfn(rdata:UInt): UInt = rdata(4,0) 355 356 def fcsr_wfn(wdata: UInt): UInt = { 357 val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct)) 358 csrw_dirty_fp_state := true.B 359 Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags) 360 } 361 362 val fcsrMapping = Map( 363 MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn, rfn = fflags_rfn), 364 MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn), 365 MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn) 366 ) 367 368 // Atom LR/SC Control Bits 369// val setLr = WireInit(Bool(), false.B) 370// val setLrVal = WireInit(Bool(), false.B) 371// val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check 372// val lr = RegInit(Bool(), false.B) 373// val lrAddr = RegInit(UInt(AddrBits.W), 0.U) 374// BoringUtils.addSink(setLr, "set_lr") 375// BoringUtils.addSink(setLrVal, "set_lr_val") 376// BoringUtils.addSink(setLrAddr, "set_lr_addr") 377// BoringUtils.addSource(lr, "lr") 378// BoringUtils.addSource(lrAddr, "lr_addr") 379// 380// when(setLr){ 381// lr := setLrVal 382// lrAddr := setLrAddr 383// } 384 385 // Hart Priviledge Mode 386 val priviledgeMode = RegInit(UInt(2.W), ModeM) 387 388 // perfcnt 389 // TODO: deal with perfCnt 390 val hasPerfCnt = false 391 val nrPerfCnts = if (hasPerfCnt) 0x80 else 0x3 392 val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W))) 393 val perfCntsLoMapping = (0 until nrPerfCnts).map { case i => MaskedRegMap(0xb00 + i, perfCnts(i)) } 394 val perfCntsHiMapping = (0 until nrPerfCnts).map { case i => MaskedRegMap(0xb80 + i, perfCnts(i)(63, 32)) } 395 396 // CSR reg map 397 val mapping = Map( 398 399 // User Trap Setup 400 // MaskedRegMap(Ustatus, ustatus), 401 // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable), 402 // MaskedRegMap(Utvec, utvec), 403 404 // User Trap Handling 405 // MaskedRegMap(Uscratch, uscratch), 406 // MaskedRegMap(Uepc, uepc), 407 // MaskedRegMap(Ucause, ucause), 408 // MaskedRegMap(Utval, utval), 409 // MaskedRegMap(Uip, uip), 410 411 // User Counter/Timers 412 // MaskedRegMap(Cycle, cycle), 413 // MaskedRegMap(Time, time), 414 // MaskedRegMap(Instret, instret), 415 416 // Supervisor Trap Setup 417 MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask), 418 419 // MaskedRegMap(Sedeleg, Sedeleg), 420 // MaskedRegMap(Sideleg, Sideleg), 421 MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask), 422 MaskedRegMap(Stvec, stvec), 423 MaskedRegMap(Scounteren, scounteren), 424 425 // Supervisor Trap Handling 426 MaskedRegMap(Sscratch, sscratch), 427 MaskedRegMap(Sepc, sepc), 428 MaskedRegMap(Scause, scause), 429 MaskedRegMap(Stval, stval), 430 MaskedRegMap(Sip, mip.asUInt, sipMask, MaskedRegMap.Unwritable, sipMask), 431 432 // Supervisor Protection and Translation 433 MaskedRegMap(Satp, satp), 434 435 // Machine Information Registers 436 MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable), 437 MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable), 438 MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable), 439 MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable), 440 441 // Machine Trap Setup 442 // MaskedRegMap(Mstatus, mstatus, "hffffffffffffffee".U, (x=>{printf("mstatus write: %x time: %d\n", x, GTimer()); x})), 443 MaskedRegMap(Mstatus, mstatus, "hffffffffffffffff".U, mstatusUpdateSideEffect), 444 MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable 445 MaskedRegMap(Medeleg, medeleg, "hbbff".U), 446 MaskedRegMap(Mideleg, mideleg, "h222".U), 447 MaskedRegMap(Mie, mie), 448 MaskedRegMap(Mtvec, mtvec), 449 MaskedRegMap(Mcounteren, mcounteren), 450 451 // Machine Trap Handling 452 MaskedRegMap(Mscratch, mscratch), 453 MaskedRegMap(Mepc, mepc), 454 MaskedRegMap(Mcause, mcause), 455 MaskedRegMap(Mtval, mtval), 456 MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable), 457 458 // Machine Memory Protection 459 MaskedRegMap(Pmpcfg0, pmpcfg0), 460 MaskedRegMap(Pmpcfg1, pmpcfg1), 461 MaskedRegMap(Pmpcfg2, pmpcfg2), 462 MaskedRegMap(Pmpcfg3, pmpcfg3), 463 MaskedRegMap(PmpaddrBase + 0, pmpaddr0), 464 MaskedRegMap(PmpaddrBase + 1, pmpaddr1), 465 MaskedRegMap(PmpaddrBase + 2, pmpaddr2), 466 MaskedRegMap(PmpaddrBase + 3, pmpaddr3) 467 468 ) ++ 469 perfCntsLoMapping ++ (if (XLEN == 32) perfCntsHiMapping else Nil) ++ 470 (if(HasFPU) fcsrMapping else Nil) 471 472 val addr = src2(11, 0) 473 val rdata = Wire(UInt(XLEN.W)) 474 val csri = ZeroExt(io.cfIn.instr(19,15), XLEN) //unsigned imm for csri. [TODO] 475 val wdata = LookupTree(func, List( 476 CSROpType.wrt -> src1, 477 CSROpType.set -> (rdata | src1), 478 CSROpType.clr -> (rdata & (~src1).asUInt()), 479 CSROpType.wrti -> csri,//TODO: csri --> src2 480 CSROpType.seti -> (rdata | csri), 481 CSROpType.clri -> (rdata & (~csri).asUInt()) 482 )) 483 484 val wen = valid && func =/= CSROpType.jmp 485 // Debug(){when(wen){printf("[CSR] addr %x wdata %x func %x rdata %x\n", addr, wdata, func, rdata)}} 486 MaskedRegMap.generate(mapping, addr, rdata, wen, wdata) 487 val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr) 488 val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed 489 io.out.bits := rdata 490 491 // Fix Mip/Sip write 492 val fixMapping = Map( 493 MaskedRegMap(Mip, mipReg.asUInt, mipFixMask), 494 MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask) 495 ) 496 val rdataDummy = Wire(UInt(XLEN.W)) 497 MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata) 498 499 when(io.fpu_csr.fflags.asUInt() =/= 0.U){ 500 fcsr := fflags_wfn(io.fpu_csr.fflags.asUInt()) 501 } 502 // set fs and sd in mstatus 503 when(csrw_dirty_fp_state || io.fpu_csr.dirty_fs){ 504 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 505 mstatusNew.fs := "b11".U 506 mstatusNew.sd := true.B 507 mstatus := mstatusNew.asUInt() 508 } 509 io.fpu_csr.frm := fcsr.asTypeOf(new FcsrStruct).frm 510 511 // CSR inst decode 512 val ret = Wire(Bool()) 513 val isEcall = addr === privEcall && func === CSROpType.jmp 514 val isMret = addr === privMret && func === CSROpType.jmp 515 val isSret = addr === privSret && func === CSROpType.jmp 516 val isUret = addr === privUret && func === CSROpType.jmp 517 518 XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", io.cfIn.pc, addr, rdata, wdata, func) 519 XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode) 520 521 522 // MMU Permission Check 523 524 // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) 525 // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex)) 526 // imem 527 // val imemPtev = true.B 528 // val imemPteu = true.B 529 // val imemPtex = true.B 530 // val imemReq = true.B 531 // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu) 532 // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex) 533 // assert(!hasInstrPageFault) 534 535 // dmem 536 // val dmemPtev = true.B 537 // val dmemPteu = true.B 538 // val dmemReq = true.B 539 // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu) 540 // val dmemIsStore = true.B 541 542 // val hasLoadPageFault = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed) 543 // val hasStorePageFault = dmemReq && dmemIsStore && !(dmemPermissionCheckPassed) 544 // assert(!hasLoadPageFault) 545 // assert(!hasStorePageFault) 546 547 //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet 548 io.imemMMU.priviledgeMode := priviledgeMode 549 io.dmemMMU.priviledgeMode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode) 550 io.imemMMU.status_sum := mstatusStruct.sum.asBool 551 io.dmemMMU.status_sum := mstatusStruct.sum.asBool 552 io.imemMMU.status_mxr := DontCare 553 io.dmemMMU.status_mxr := mstatusStruct.mxr.asBool 554 555 val hasInstrPageFault = io.exception.bits.cf.exceptionVec(instrPageFault) && io.exception.valid 556 val hasLoadPageFault = io.dmemMMU.loadPF 557 val hasStorePageFault = io.dmemMMU.storePF 558 val hasStoreAddrMisaligned = io.exception.bits.cf.exceptionVec(storeAddrMisaligned) 559 val hasLoadAddrMisaligned = io.exception.bits.cf.exceptionVec(loadAddrMisaligned) 560 561 when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){ 562 val tval = Mux( 563 hasInstrPageFault, 564 Mux( 565 io.exception.bits.cf.crossPageIPFFix, 566 SignExt(io.exception.bits.cf.pc + 2.U, XLEN), 567 SignExt(io.exception.bits.cf.pc, XLEN) 568 ), 569 SignExt(io.dmemMMU.addr, XLEN) 570 ) 571 when(priviledgeMode === ModeM){ 572 mtval := tval 573 }.otherwise{ 574 stval := tval 575 } 576 } 577 578 val lsuAddr = WireInit(0.U(64.W)) 579 BoringUtils.addSink(lsuAddr, "LSUADDR") 580 when(hasLoadAddrMisaligned || hasStoreAddrMisaligned) 581 { 582 mtval := SignExt(lsuAddr, XLEN) 583 } 584 585 // Exception and Intr 586 587 // interrupts 588 589 val ideleg = (mideleg & mip.asUInt) 590 def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS), 591 ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM)) 592 593 val intrVecEnable = Wire(Vec(12, Bool())) 594 intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)} 595 val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt 596 ExcitingUtils.addSource(intrVec, "intrVecIDU") 597 // val intrNO = PriorityEncoder(intrVec) 598 599 val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum)) 600 // val intrNO = PriorityEncoder(io.cfIn.intrVec) 601// val raiseIntr = io.cfIn.intrVec.asUInt.orR 602 val raiseIntr = intrVec.asUInt.orR && io.exception.valid 603 XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", io.exception.bits.cf.pc, intrNO) 604 605 val mtip = WireInit(false.B) 606 val meip = WireInit(false.B) 607 BoringUtils.addSink(mtip, "mtip") 608 BoringUtils.addSink(meip, "meip") 609 mipWire.t.m := mtip 610 mipWire.e.m := meip 611 612 // exceptions 613 614 // TODO: merge iduExceptionVec, csrExceptionVec as raiseExceptionVec 615 val csrExceptionVec = Wire(Vec(16, Bool())) 616 csrExceptionVec.map(_ := false.B) 617 csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall 618 csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall 619 csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall 620 // csrExceptionVec(instrPageFault) := hasInstrPageFault 621 csrExceptionVec(illegalInstr) := isIllegalAddr && wen // Trigger an illegal instr exception when unimplemented csr is being read/written 622 csrExceptionVec(loadPageFault) := hasLoadPageFault 623 csrExceptionVec(storePageFault) := hasStorePageFault 624 val iduExceptionVec = io.cfIn.exceptionVec 625 val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt() 626 io.cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) } 627// val raiseException = raiseExceptionVec.orR 628// val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum)) 629 io.wenFix := DontCare 630// val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO) 631 632 val raiseExceptionVec = io.exception.bits.cf.exceptionVec.asUInt() 633 val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum)) 634 val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO) 635 val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U) 636 ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR") 637 638 val raiseExceptionIntr = io.exception.valid 639// val raiseExceptionIntr = (raiseException || raiseIntr) && io.instrValid 640 val retTarget = Wire(UInt(VAddrBits.W)) 641 val trapTarget = Wire(UInt(VAddrBits.W)) 642 ExcitingUtils.addSource(trapTarget, "trapTarget") 643 io.redirect := DontCare 644 io.redirectValid := (valid && func === CSROpType.jmp) || resetSatp 645 //TODO: use pred pc instead pc+4 646 io.redirect.target := Mux( 647 resetSatp, 648 io.cfIn.pc+4.U, 649// Mux( 650// raiseExceptionIntr, 651// trapTarget, 652 retTarget 653// ) 654 ) 655 656 XSDebug( 657 io.redirectValid, 658 "redirect to %x, pc=%x\n", 659 io.redirect.target, 660 io.cfIn.pc 661 ) 662 663 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) 664 XSDebug(raiseExceptionIntr, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.exception.bits.cf.pc, mstatus, mideleg, medeleg, priviledgeMode) 665 666 XSDebug(io.redirectValid, "redirect to %x\n", io.redirect.target) 667 668 XSDebug(valid && isMret, "Mret to %x!\n[CSR] int/exc: pc %x int (%d):%x exc: (%d):%x\n",retTarget, io.cfIn.pc, intrNO, io.cfIn.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt) 669 XSDebug(valid && isMret, "[MST] pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode) 670 671 XSDebug(valid && isSret, "Sret to %x!\n[CSR] int/exc: pc %x int (%d):%x exc: (%d):%x\n",retTarget, io.cfIn.pc, intrNO, io.cfIn.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt) 672 XSDebug(valid && isSret, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode) 673 XSDebug(io.redirectValid, "Redirect %x raiseExcepIntr:%d valid:%d instrValid:%x \n", io.redirect.target, raiseExceptionIntr, valid, io.instrValid) 674 675 // Branch control 676 677 val deleg = Mux(raiseIntr, mideleg , medeleg) 678 // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM); 679 val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM) 680 val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // in noop-riscv64, no exception will come together with PF 681 682 ret := isMret || isSret || isUret 683 trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0) 684 retTarget := DontCare 685 // val illegalEret = TODO 686 687 when (valid && isMret) { 688 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 689 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 690 // mstatusNew.mpp.m := ModeU //TODO: add mode U 691 mstatusNew.ie.m := mstatusOld.pie.m 692 priviledgeMode := mstatusOld.mpp 693 mstatusNew.pie.m := true.B 694 mstatusNew.mpp := ModeU 695 mstatus := mstatusNew.asUInt 696// lr := false.B 697 retTarget := mepc(VAddrBits-1, 0) 698 } 699 700 when (valid && isSret) { 701 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 702 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 703 // mstatusNew.mpp.m := ModeU //TODO: add mode U 704 mstatusNew.ie.s := mstatusOld.pie.s 705 priviledgeMode := Cat(0.U(1.W), mstatusOld.spp) 706 mstatusNew.pie.s := true.B 707 mstatusNew.spp := ModeU 708 mstatus := mstatusNew.asUInt 709// lr := false.B 710 retTarget := sepc(VAddrBits-1, 0) 711 } 712 713 when (valid && isUret) { 714 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 715 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 716 // mstatusNew.mpp.m := ModeU //TODO: add mode U 717 mstatusNew.ie.u := mstatusOld.pie.u 718 priviledgeMode := ModeU 719 mstatusNew.pie.u := true.B 720 mstatus := mstatusNew.asUInt 721 retTarget := uepc(VAddrBits-1, 0) 722 } 723 724 when (raiseExceptionIntr) { 725 val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct)) 726 val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct)) 727 728 when (delegS) { 729 scause := causeNO 730 sepc := SignExt(io.exception.bits.cf.pc, XLEN) 731 mstatusNew.spp := priviledgeMode 732 mstatusNew.pie.s := mstatusOld.ie.s 733 mstatusNew.ie.s := false.B 734 priviledgeMode := ModeS 735 when(tvalWen){stval := 0.U} // TODO: should not use =/= 736 // printf("[*] mstatusNew.spp %x\n", mstatusNew.spp) 737 // trapTarget := stvec(VAddrBits-1. 0) 738 }.otherwise { 739 mcause := causeNO 740 mepc := SignExt(io.exception.bits.cf.pc, XLEN) 741 mstatusNew.mpp := priviledgeMode 742 mstatusNew.pie.m := mstatusOld.ie.m 743 mstatusNew.ie.m := false.B 744 priviledgeMode := ModeM 745 when(tvalWen){mtval := 0.U} // TODO: should not use =/= 746 // trapTarget := mtvec(VAddrBits-1. 0) 747 } 748 // mstatusNew.pie.m := LookupTree(priviledgeMode, List( 749 // ModeM -> mstatusOld.ie.m, 750 // ModeH -> mstatusOld.ie.h, //ERROR 751 // ModeS -> mstatusOld.ie.s, 752 // ModeU -> mstatusOld.ie.u 753 // )) 754 755 mstatus := mstatusNew.asUInt 756 } 757 758 io.in.ready := true.B 759 io.out.valid := valid 760 761 762 XSDebug(io.redirectValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n", 763 io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid) 764 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", 765 io.redirectValid, io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid) 766 XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", io.cfIn.pc) 767 768 769 // perfcnt 770 771 val perfCntList = Map( 772 "Mcycle" -> (0xb00, "perfCntCondMcycle" ), 773 "Minstret" -> (0xb02, "perfCntCondMinstret" ), 774 "MimemStall" -> (0xb03, "perfCntCondMimemStall" ), 775 "MaluInstr" -> (0xb04, "perfCntCondMaluInstr" ), 776 "MbruInstr" -> (0xb05, "perfCntCondMbruInstr" ), 777 "MlsuInstr" -> (0xb06, "perfCntCondMlsuInstr" ), 778 "MmduInstr" -> (0xb07, "perfCntCondMmduInstr" ), 779 "McsrInstr" -> (0xb08, "perfCntCondMcsrInstr" ), 780 "MloadInstr" -> (0xb09, "perfCntCondMloadInstr" ), 781 "MloadStall" -> (0xb0a, "perfCntCondMloadStall" ), 782 "MstoreStall" -> (0xb0b, "perfCntCondMstoreStall"), 783 "MmmioInstr" -> (0xb0c, "perfCntCondMmmioInstr" ), 784 "MicacheHit" -> (0xb0d, "perfCntCondMicacheHit" ), 785 "MdcacheHit" -> (0xb0e, "perfCntCondMdcacheHit" ), 786 "MmulInstr" -> (0xb0f, "perfCntCondMmulInstr" ), 787 "MifuFlush" -> (0xb10, "perfCntCondMifuFlush" ), 788 "MrawStall" -> (0xb11, "perfCntCondMrawStall" ), 789 "MexuBusy" -> (0xb12, "perfCntCondMexuBusy" ), 790 "MbpBRight" -> (0xb13, "MbpBRight" ), 791 "MbpBWrong" -> (0xb14, "MbpBWrong" ), 792 "MbpJRight" -> (0xb15, "MbpJRight" ), 793 "MbpJWrong" -> (0xb16, "MbpJWrong" ), 794 "MbpIRight" -> (0xb17, "MbpIRight" ), 795 "MbpIWrong" -> (0xb18, "MbpIWrong" ), 796 "MbpRRight" -> (0xb19, "MbpRRight" ), 797 "MbpRWrong" -> (0xb1a, "MbpRWrong" ), 798 "Custom1" -> (0xb1b, "Custom1" ), 799 "Custom2" -> (0xb1c, "Custom2" ), 800 "Custom3" -> (0xb1d, "Custom3" ), 801 "Custom4" -> (0xb1e, "Custom4" ), 802 "Custom5" -> (0xb1f, "Custom5" ), 803 "Custom6" -> (0xb20, "Custom6" ), 804 "Custom7" -> (0xb21, "Custom7" ), 805 "Custom8" -> (0xb22, "Custom8" ), 806 "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit") 807 ) 808 val perfCntCond = List.fill(0x80)(WireInit(false.B)) 809 (perfCnts zip perfCntCond).map { case (c, e) => { when (e) { c := c + 1.U } } } 810 811 BoringUtils.addSource(WireInit(true.B), "perfCntCondMcycle") 812 perfCntList.map { case (name, (addr, boringId)) => { 813 BoringUtils.addSink(perfCntCond(addr & 0x7f), boringId) 814 if (!hasPerfCnt) { 815 // do not enable perfcnts except for Mcycle and Minstret 816 if (addr != perfCntList("Mcycle")._1 && addr != perfCntList("Minstret")._1) { 817 perfCntCond(addr & 0x7f) := false.B 818 } 819 } 820 }} 821 822 val nooptrap = WireInit(false.B) 823 BoringUtils.addSink(nooptrap, "nooptrap") 824 def readWithScala(addr: Int): UInt = mapping(addr)._1 825 826 if (!p.FPGAPlatform) { 827 828 // display all perfcnt when nooptrap is executed 829// when (nooptrap) { 830// printf("======== PerfCnt =========\n") 831// perfCntList.toSeq.sortBy(_._2._1).map { case (name, (addr, boringId)) => 832// printf("%d <- " + name + "\n", readWithScala(addr)) } 833// } 834 835 // for differential testing 836// BoringUtils.addSource(RegNext(priviledgeMode), "difftestMode") 837// BoringUtils.addSource(RegNext(mstatus), "difftestMstatus") 838// BoringUtils.addSource(RegNext(mstatus & sstatusRmask), "difftestSstatus") 839// BoringUtils.addSource(RegNext(mepc), "difftestMepc") 840// BoringUtils.addSource(RegNext(sepc), "difftestSepc") 841// BoringUtils.addSource(RegNext(mcause), "difftestMcause") 842// BoringUtils.addSource(RegNext(scause), "difftestScause") 843 BoringUtils.addSource(priviledgeMode, "difftestMode") 844 BoringUtils.addSource(mstatus, "difftestMstatus") 845 BoringUtils.addSource(mstatus & sstatusRmask, "difftestSstatus") 846 BoringUtils.addSource(mepc, "difftestMepc") 847 BoringUtils.addSource(sepc, "difftestSepc") 848 BoringUtils.addSource(mcause, "difftestMcause") 849 BoringUtils.addSource(scause, "difftestScause") 850 } else { 851// BoringUtils.addSource(readWithScala(perfCntList("Minstret")._1), "ilaInstrCnt") 852 } 853} 854