package xiangshan.backend.fu.NewCSR import chisel3._ import chisel3.experimental.SourceInfo import chisel3.util._ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.rocket.CSRs import utility.{SignExt, PerfEvent} import xiangshan.backend.fu.NewCSR.CSRBundles._ import xiangshan.backend.fu.NewCSR.CSRDefines._ import xiangshan.backend.fu.NewCSR.CSRDefines.{CSRROField => RO, CSRRWField => RW, _} import xiangshan.backend.fu.NewCSR.CSREvents._ import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._ import xiangshan.backend.fu.NewCSR.ChiselRecordForField._ import xiangshan.backend.fu.PerfCounterIO import xiangshan.backend.fu.NewCSR.CSRConfig._ import xiangshan.backend.fu.NewCSR.CSRFunc._ import xiangshan.backend.fu.util.CSRConst._ import scala.collection.immutable.SeqMap trait MachineLevel { self: NewCSR => // Machine level Custom Read/Write val mbmc = if (HasBitmapCheck) Some(Module(new CSRModule("Mbmc", new MbmcBundle) { val mbmc_lock = reg.BME.asBool if (!HasBitmapCheckDefault) { reg.BME := Mux(wen && !mbmc_lock, wdata.BME, reg.BME) reg.CMODE := Mux(wen, wdata.CMODE, reg.CMODE) reg.BMA := Mux(wen && !mbmc_lock, wdata.BMA, reg.BMA) } else { reg.BME := 1.U reg.CMODE := 0.U reg.BMA := BMAField.TestBMA } reg.BCLEAR := Mux(reg.BCLEAR.asBool, 0.U, Mux(wen && wdata.BCLEAR.asBool, 1.U, 0.U)) }) .setAddr(Mbmc)) else None val mstatus = Module(new MstatusModule) .setAddr(CSRs.mstatus) val misa = Module(new CSRModule("Misa", new MisaBundle)) .setAddr(CSRs.misa) println(s"[CSR] supported isa ext: ${misa.bundle.getISAString}") val medeleg = Module(new CSRModule("Medeleg", new MedelegBundle)) .setAddr(CSRs.medeleg) val mideleg = Module(new CSRModule("Mideleg", new MidelegBundle)) .setAddr(CSRs.mideleg) val mie = Module(new CSRModule("Mie", new MieBundle) with HasIpIeBundle { val fromHie = IO(Flipped(new HieToMie)) val fromSie = IO(Flipped(new SieToMie)) val fromVSie = IO(Flipped(new VSieToMie)) // bit 1 SSIE when (fromSie.SSIE.valid) { reg.SSIE := fromSie.SSIE.bits } // bit 2 VSSIE when (fromHie.VSSIE.valid || fromVSie.VSSIE.valid) { reg.VSSIE := Mux1H(Seq( fromHie .VSSIE.valid -> fromHie .VSSIE.bits, fromVSie.VSSIE.valid -> fromVSie.VSSIE.bits, )) } // bit 5 STIE when(fromSie.STIE.valid) { reg.STIE := fromSie.STIE.bits } // bit 6 VSTIE when(fromHie.VSTIE.valid || fromVSie.VSTIE.valid) { reg.VSTIE := Mux1H(Seq( fromHie .VSTIE.valid -> fromHie .VSTIE.bits, fromVSie.VSTIE.valid -> fromVSie.VSTIE.bits, )) } // bit 9 SEIE when(fromSie.SEIE.valid) { reg.SEIE := fromSie.SEIE.bits } // bit 10 VSEIE when(fromHie.VSEIE.valid || fromVSie.VSEIE.valid) { reg.VSEIE := Mux1H(Seq( fromHie .VSEIE.valid -> fromHie .VSEIE.bits, fromVSie.VSEIE.valid -> fromVSie.VSEIE.bits, )) } // bit 12 SGEIE when(fromHie.SGEIE.valid) { reg.SGEIE := fromHie.SGEIE.bits } // bit 13~63 LCIP reg.getLocal lazyZip fromSie.getLocal lazyZip fromVSie.getLocal foreach { case (rLCIE, sieLCIE, vsieLCIE) => when (sieLCIE.valid || vsieLCIE.valid) { rLCIE := Mux1H(Seq( sieLCIE .valid -> sieLCIE .bits, vsieLCIE.valid -> vsieLCIE.bits, )) } } // 14~63 read only 0 regOut.getLocal.filterNot(_.lsb == InterruptNO.COI).foreach(_ := 0.U) }).setAddr(CSRs.mie) val mtvec = Module(new CSRModule("Mtvec", new XtvecBundle)) .setAddr(CSRs.mtvec) // Todo: support "Stimecmp/Vstimecmp" Extension, Version 1.0.0 // Todo: support Sscounterenw Extension val mcounteren = Module(new CSRModule("Mcounteren", new Counteren)) .setAddr(CSRs.mcounteren) val mvien = Module(new CSRModule("Mvien", new MvienBundle)) .setAddr(CSRs.mvien) val mvip = Module(new CSRModule("Mvip", new MvipBundle) with HasIpIeBundle with HasMachineEnvBundle { val toMip = IO(new MvipToMip).connectZeroNonRW val fromMip = IO(Flipped(new MipToMvip)) val fromSip = IO(Flipped(new SipToMvip)) val fromVSip = IO(Flipped(new VSipToMvip)) // When bit 1 of mvien is zero, bit 1(SSIP) of mvip is an alias of the same bit (SSIP) of mip. // But when bit 1 of mvien is one, bit 1(SSIP) of mvip is a separate writable bit independent of mip.SSIP. // When the value of bit 1 of mvien is changed from zero to one, the value of bit 1 of mvip becomes UNSPECIFIED. // XiangShan will keep the value in mvip.SSIP when mvien.SSIE is changed from zero to one reg.SSIP := Mux(wen && this.mvien.SSIE.asBool, wdata.SSIP, reg.SSIP) regOut.SSIP := Mux(this.mvien.SSIE.asBool, reg.SSIP, this.mip.SSIP) toMip.SSIP.valid := wen && !this.mvien.SSIE.asBool toMip.SSIP.bits := wdata.SSIP // Bit 5 of mvip is an alias of the same bit (STIP) in mip when that bit is writable in mip. // When STIP is not writable in mip (such as when menvcfg.STCE = 1), bit 5 of mvip is read-only zero. // Todo: check mip writable when menvcfg.STCE = 1 regOut.STIP := Mux(this.menvcfg.STCE.asBool, 0.U, this.mip.STIP.asBool) // Don't update mip.STIP when menvcfg.STCE is 1 toMip.STIP.valid := wen && !this.menvcfg.STCE.asBool toMip.STIP.bits := wdata.STIP // When bit 9 of mvien is zero, bit 9 of mvip is an alias of the software-writable bit 9 of mip (SEIP). // But when bit 9 of mvien is one, bit 9 of mvip is a writable bit independent of mip.SEIP. // Unlike for bit 1, changing the value of bit 9 of mvien does not affect the value of bit 9 of mvip. toMip.SEIP.valid := wen && !this.mvien.SEIE.asUInt.asBool toMip.SEIP.bits := wdata.SEIP when (fromMip.SEIP.valid) { reg.SEIP := fromMip.SEIP.bits } // write from sip when (fromSip.SSIP.valid) { reg.SSIP := fromSip.SSIP.bits } reg.getLocal lazyZip fromSip.getLocal lazyZip fromVSip.getLocal foreach { case (rLCIP, sipLCIP, vsipLCIP) => // sip should assert valid when mideleg=0 && mvien=1 when (sipLCIP.valid || vsipLCIP.valid) { rLCIP := Mux1H(Seq( sipLCIP .valid -> sipLCIP .bits, vsipLCIP.valid -> vsipLCIP.bits, )) } } }).setAddr(CSRs.mvip) val menvcfg = Module(new CSRModule("Menvcfg", new MEnvCfg)) .setAddr(CSRs.menvcfg) val mcountinhibit = Module(new CSRModule("Mcountinhibit", new McountinhibitBundle)) .setAddr(CSRs.mcountinhibit) val mhpmevents: Seq[CSRModule[_]] = (3 to 0x1F).map(num => Module(new CSRModule(s"Mhpmevent", new MhpmeventBundle) with HasOfFromPerfCntBundle { when(wen){ reg.OF := wdata.OF }.elsewhen(ofFromPerfCnt) { reg.OF := ofFromPerfCnt } }) .setAddr(CSRs.mhpmevent3 - 3 + num).suggestName(s"Mhpmevent$num") ) val mscratch = Module(new CSRModule("Mscratch")) .setAddr(CSRs.mscratch) val mepc = Module(new CSRModule("Mepc", new Epc) with TrapEntryMEventSinkBundle) .setAddr(CSRs.mepc) val mcause = Module(new CSRModule("Mcause", new CauseBundle) with TrapEntryMEventSinkBundle) .setAddr(CSRs.mcause) val mtval = Module(new CSRModule("Mtval", new XtvalBundle) with TrapEntryMEventSinkBundle) .setAddr(CSRs.mtval) val mip = Module(new CSRModule("Mip", new MipBundle) with HasIpIeBundle with HasExternalInterruptBundle with HasMachineEnvBundle with HasLocalInterruptReqBundle with HasAIABundle { // Alias write in val fromMvip = IO(Flipped(new MvipToMip)) val fromSip = IO(Flipped(new SipToMip)) val fromVSip = IO(Flipped(new VSipToMip)) // Alias write out val toMvip = IO(new MipToMvip).connectZeroNonRW val toHvip = IO(new MipToHvip).connectZeroNonRW // bit 1 SSIP when (fromMvip.SSIP.valid || fromSip.SSIP.valid) { reg.SSIP := Mux1H(Seq( fromMvip.SSIP.valid -> fromMvip.SSIP.bits, fromSip .SSIP.valid -> fromSip .SSIP.bits, )) } // bit 2 VSSIP reg in hvip // alias of hvip.VSSIP toHvip.VSSIP.valid := wen toHvip.VSSIP.bits := wdata.VSSIP regOut.VSSIP := hvip.VSSIP // bit 3 MSIP is read-only in mip, and is written by accesses to memory-mapped control registers, // which are used by remote harts to provide machine-level interprocessor interrupts. regOut.MSIP := platformIRP.MSIP // bit 5 STIP // If the stimecmp (supervisor-mode timer compare) register is implemented(menvcfg.STCE=1), STIP is read-only in mip. regOut.STIP := Mux(this.menvcfg.STCE.asBool, platformIRP.STIP, reg.STIP.asBool) when ((wen || fromMvip.STIP.valid) && !this.menvcfg.STCE) { reg.STIP := Mux1H(Seq( wen -> wdata.STIP, fromMvip.STIP.valid -> fromMvip.STIP.bits, )) }.otherwise { reg.STIP := reg.STIP } // bit 6 VSTIP regOut.VSTIP := hvip.VSTIP || platformIRP.VSTIP // bit 7 MTIP is read-only in mip, and is cleared by writing to the memory-mapped machine-mode timer compare register regOut.MTIP := platformIRP.MTIP // bit 9 SEIP // When bit 9 of mvien is zero, the value of bit 9 of mvip is logically ORed into the readable value of mip.SEIP. // when bit 9 of mvien is one, bit SEIP in mip is read-only and does not include the value of bit 9 of mvip. // // As explained in this issue(https://github.com/riscv/riscv-aia/issues/64), // when mvien[9]=0, mip.SEIP is a software-writable bit and is special in its read value, which is the logical-OR of // mip.SEIP reg and other source from the interrupt controller. // mvip.SEIP is alias of mip.SEIP's reg part, and is independent of the other source from the interrupt controller. // // mip.SEIP is implemented as the alias of mvip.SEIP when mvien=0 // the read valid of SEIP is ORed by mvip.SEIP and the other source from the interrupt controller. toMvip.SEIP.valid := wen && !this.mvien.SEIE toMvip.SEIP.bits := wdata.SEIP // When mvien.SEIE = 0, mip.SEIP is alias of mvip.SEIP. // Otherwise, mip.SEIP is read only 0 regOut.SEIP := Mux(!this.mvien.SEIE, this.mvip.SEIP.asUInt, 0.U) rdataFields.SEIP := regOut.SEIP || platformIRP.SEIP || aiaToCSR.seip // bit 10 VSEIP regOut.VSEIP := hvip.VSEIP || platformIRP.VSEIP || hgeip.asUInt(hstatusVGEIN.asUInt) // bit 11 MEIP is read-only in mip, and is set and cleared by a platform-specific interrupt controller. // MEIP can from PLIC and IMSIC regOut.MEIP := platformIRP.MEIP || aiaToCSR.meip // bit 12 SGEIP regOut.SGEIP := Cat(hgeip.asUInt & hgeie.asUInt).orR // bit 13 LCOFIP when (fromSip.LCOFIP.valid || fromVSip.LCOFIP.valid || wen) { reg.LCOFIP := Mux1H(Seq( fromSip.LCOFIP.valid -> fromSip.LCOFIP.bits, fromVSip.LCOFIP.valid -> fromVSip.LCOFIP.bits, wen -> wdata.LCOFIP, )) }.elsewhen(lcofiReq) { reg.LCOFIP := lcofiReq }.otherwise { reg.LCOFIP := reg.LCOFIP } }).setAddr(CSRs.mip) val mtinst = Module(new CSRModule("Mtinst", new XtinstBundle) with TrapEntryMEventSinkBundle) .setAddr(CSRs.mtinst) val mtval2 = Module(new CSRModule("Mtval2", new Mtval2Bundle) with TrapEntryMEventSinkBundle) .setAddr(CSRs.mtval2) val mseccfg = Module(new CSRModule("Mseccfg", new CSRBundle { val PMM = EnvPMM(33, 32, wNoEffect).withReset(EnvPMM.Disable) // Smmpm extension val MLPE = RO(10) // Landing pand, Zicfilp extension val SSEED = RO( 9) // Zkr extension val USEED = RO( 8) // Zkr extension val RLB = RO( 2) // Smepmp val MMWP = RO( 1) // Smepmp val MML = RO( 0) // Smepmp })).setAddr(CSRs.mseccfg) val mcycle = Module(new CSRModule("Mcycle") with HasMachineCounterControlBundle { when(w.wen) { reg := w.wdata }.elsewhen(!this.mcountinhibit.CY.asUInt.asBool) { reg := reg.ALL.asUInt + 1.U }.otherwise { reg := reg } }).setAddr(CSRs.mcycle) val minstret = Module(new CSRModule("Minstret") with HasMachineCounterControlBundle with HasRobCommitBundle { when(w.wen) { reg := w.wdata }.elsewhen(!this.mcountinhibit.IR && robCommit.instNum.valid) { reg := reg.ALL.asUInt + robCommit.instNum.bits }.otherwise { reg := reg } }).setAddr(CSRs.minstret) val mhpmcounters: Seq[CSRModule[_]] = (3 to 0x1F).map(num => Module(new CSRModule(s"Mhpmcounter$num", new MhpmcounterBundle) with HasMachineCounterControlBundle with HasPerfCounterBundle { val countingInhibit = this.mcountinhibit.asUInt(num) | !countingEn val counterAdd = reg.ALL.asUInt +& perf.value when (w.wen) { reg := w.wdata }.elsewhen (perf.value =/= 0.U && !countingInhibit) { reg := counterAdd.tail(1) }.otherwise { reg := reg } // Count overflow never results from writes to the mhpmcountern or mhpmeventn registers, only from // hardware increments of counter registers. toMhpmeventOF := !countingInhibit & counterAdd.head(1) }).setAddr(CSRs.mhpmcounter3 - 3 + num) ) val mvendorid = Module(new CSRModule("Mvendorid", new CSRBundle { val ALL = RO(63, 0) })) .setAddr(CSRs.mvendorid) // architecture id for XiangShan is 25 // see https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md val marchid = Module(new CSRModule("Marchid", new CSRBundle { val ALL = MarchidField(63, 0).withReset(MarchidField.XSArchid) })).setAddr(CSRs.marchid) val mimpid = Module(new CSRModule("Mimpid", new CSRBundle { val ALL = RO(0).withReset(0.U) })) .setAddr(CSRs.mimpid) val mhartid = Module(new CSRModule("Mhartid", new CSRBundle { val ALL = RO(hartIdLen - 1, 0) }) { val hartid = IO(Input(UInt(hartIdLen.W))) this.regOut.ALL := hartid }) .setAddr(CSRs.mhartid) val mconfigptr = Module(new CSRModule("Mconfigptr", new CSRBundle { val ALL = RO(63, 0) })) .setAddr(CSRs.mconfigptr) val mstateen0 = Module(new CSRModule("Mstateen", new MstateenBundle0)).setAddr(CSRs.mstateen0) // smrnmi extension val mnepc = Module(new CSRModule("Mnepc", new Epc) with TrapEntryMNEventSinkBundle { rdata := SignExt(Cat(reg.epc.asUInt, 0.U(1.W)), XLEN) }) .setAddr(CSRs.mnepc) val mncause = Module(new CSRModule("Mncause", new CauseBundle) with TrapEntryMNEventSinkBundle) .setAddr(CSRs.mncause) val mnstatus = Module(new CSRModule("Mnstatus", new MnstatusBundle) with TrapEntryMNEventSinkBundle with MNretEventSinkBundle{ // NMIE write 0 with no effect // as opensbi not support smrnmi, we init nmie with 1,and allow software to set nmie close for testing // Attension, when set nmie to zero ,do not cause double trap when nmi interrupt has triggered // when(!wdata.NMIE.asBool) { // reg.NMIE := reg.NMIE // } }).setAddr(CSRs.mnstatus) val mnscratch = Module(new CSRModule("Mnscratch")) .setAddr(CSRs.mnscratch) val machineLevelCSRMods: Seq[CSRModule[_]] = Seq( mstatus, misa, medeleg, mideleg, mie, mtvec, mcounteren, mvien, mvip, menvcfg, mcountinhibit, mscratch, mepc, mcause, mtval, mip, mtinst, mtval2, mseccfg, mcycle, minstret, mvendorid, marchid, mimpid, mhartid, mconfigptr, mstateen0, mnepc, mncause, mnstatus, mnscratch, ) ++ mhpmevents ++ mhpmcounters ++ (if (HasBitmapCheck) Seq(mbmc.get) else Seq()) val machineLevelCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap.from( machineLevelCSRMods.map(csr => (csr.addr -> (csr.w -> csr.rdata))).iterator ) val machineLevelCSROutMap: SeqMap[Int, UInt] = SeqMap.from( machineLevelCSRMods.map(csr => (csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt)).iterator ) } class MbmcBundle extends CSRBundle { val BMA = BMAField(63,6,null).withReset(BMAField.ResetBMA) val BME = RW(2).withReset(0.U) val BCLEAR = RW(1).withReset(0.U) val CMODE = RW(0).withReset(0.U) } class MstatusBundle extends CSRBundle { val SIE = CSRRWField (1).withReset(0.U) val MIE = CSRRWField (3).withReset(0.U) val SPIE = CSRRWField (5).withReset(0.U) val UBE = CSRROField (6).withReset(0.U) val MPIE = CSRRWField (7).withReset(0.U) val SPP = CSRRWField (8).withReset(0.U) val VS = ContextStatus (10, 9).withReset(ContextStatus.Off) val MPP = PrivMode (12, 11).withReset(PrivMode.U) val FS = ContextStatus (14, 13).withReset(ContextStatus.Off) val XS = ContextStatusRO(16, 15).withReset(0.U) val MPRV = CSRRWField (17).withReset(0.U) val SUM = CSRRWField (18).withReset(0.U) val MXR = CSRRWField (19).withReset(0.U) val TVM = CSRRWField (20).withReset(0.U) val TW = CSRRWField (21).withReset(0.U) val TSR = CSRRWField (22).withReset(0.U) val SDT = CSRRWField (24).withReset(0.U) val UXL = XLENField (33, 32).withReset(XLENField.XLEN64) val SXL = XLENField (35, 34).withReset(XLENField.XLEN64) val SBE = CSRROField (36).withReset(0.U) val MBE = CSRROField (37).withReset(0.U) val GVA = CSRRWField (38).withReset(0.U) val MPV = VirtMode (39).withReset(0.U) val MDT = CSRRWField (42).withReset(mdtInit.U) val SD = CSRROField (63, (_, _) => FS === ContextStatus.Dirty || VS === ContextStatus.Dirty ) } class MstatusModule(implicit override val p: Parameters) extends CSRModule("MStatus", new MstatusBundle) with TrapEntryMEventSinkBundle with TrapEntryHSEventSinkBundle with DretEventSinkBundle with MretEventSinkBundle with MNretEventSinkBundle with SretEventSinkBundle with HasRobCommitBundle with HasMachineEnvBundle { val mstatus = IO(Output(bundle)) val sstatus = IO(Output(new SstatusBundle)) val sstatusRdata = IO(Output(UInt(64.W))) val wAliasSstatus = IO(Input(new CSRAddrWriteBundle(new SstatusBundle))) for ((name, field) <- wAliasSstatus.wdataFields.elements) { reg.elements(name).asInstanceOf[CSREnumType].addOtherUpdate( wAliasSstatus.wen && field.asInstanceOf[CSREnumType].isLegal, field.asInstanceOf[CSREnumType] ) } // write connection reconnectReg() when (robCommit.fsDirty || writeFCSR) { assert(reg.FS =/= ContextStatus.Off, "The [m|s]status.FS should not be Off when set dirty, please check decode") reg.FS := ContextStatus.Dirty } when (robCommit.vsDirty || writeVCSR) { assert(reg.VS =/= ContextStatus.Off, "The [m|s]status.VS should not be Off when set dirty, please check decode") reg.VS := ContextStatus.Dirty } // when MDT is explicitly written by 1, clear MIE // only when reg.MDT is zero or wdata.MDT is zero , MIE can be explicitly written by 1 when (w.wdataFields.MDT && w.wen) { reg.MIE := false.B } // when DTE is zero, SDT field is read-only zero(write any, read zero, side effect of write 1 is block) val writeSstatusSDT = Wire(Bool()) val writeMstatusSDT = Wire(Bool()) val writeSDT = Wire(Bool()) writeMstatusSDT := w.wdataFields.SDT.asBool writeSstatusSDT := Mux(this.menvcfg.DTE.asBool, wAliasSstatus.wdataFields.SDT.asBool, reg.SDT.asBool) writeSDT := Mux(w.wen, writeMstatusSDT, wAliasSstatus.wen && writeSstatusSDT) // menvcfg.DTE only control Smode dbltrp. Thus mstatus.sdt will not control by DTE. // as sstatus is alias of mstatus, when menvcfg.DTE close write, // sstatus.sdt cannot lead to shadow write of mstatus.sdt. \ // As a result, we add wmask of sdt, when write source is from alias write. when (!this.menvcfg.DTE.asBool && wAliasSstatus.wen) { reg.SDT := reg.SDT } // SDT and SIE is the same as MDT and MIE when (writeSDT) { reg.SIE := false.B } // read connection mstatus :|= regOut sstatus := mstatus sstatus.SDT := regOut.SDT && menvcfg.DTE rdata := mstatus.asUInt sstatusRdata := sstatus.asUInt } class MnstatusBundle extends CSRBundle { val NMIE = CSRRWField (3).withReset(1.U) // as opensbi not support smrnmi, we init nmie open val MNPV = VirtMode (7).withReset(0.U) val MNPELP = RO (9).withReset(0.U) val MNPP = PrivMode (12, 11).withReset(PrivMode.U) } class MisaBundle extends CSRBundle { // Todo: reset with ISA string val A = RO( 0).withReset(1.U) // Atomic extension val B = RO( 1).withReset(1.U) // B extension val C = RO( 2).withReset(1.U) // Compressed extension val D = RO( 3).withReset(1.U) // Double-precision floating-point extension val E = RO( 4).withReset(0.U) // RV32E/64E base ISA val F = RO( 5).withReset(1.U) // Single-precision floating-point extension val G = RO( 6).withReset(0.U) // Reserved val H = RO( 7).withReset(1.U) // Hypervisor extension val I = RO( 8).withReset(1.U) // RV32I/64I/128I base ISA val J = RO( 9).withReset(0.U) // Reserved val K = RO(10).withReset(0.U) // Reserved val L = RO(11).withReset(0.U) // Reserved val M = RO(12).withReset(1.U) // Integer Multiply/Divide extensi val N = RO(13).withReset(0.U) // Tentatively reserved for User-Level Interrupts extension val O = RO(14).withReset(0.U) // Reserved val P = RO(15).withReset(0.U) // Tentatively reserved for Packed-SIMD extension val Q = RO(16).withReset(0.U) // Quad-precision floating-point extension val R = RO(17).withReset(0.U) // Reserved val S = RO(18).withReset(1.U) // Supervisor mode implemented val T = RO(19).withReset(0.U) // Reserved val U = RO(20).withReset(1.U) // User mode implemented val V = RO(21).withReset(1.U) // Vector extension val W = RO(22).withReset(0.U) // Reserved val X = RO(23).withReset(0.U) // Non-standard extensions present val Y = RO(24).withReset(0.U) // Reserved val Z = RO(25).withReset(0.U) // Reserved val MXL = XLENField(63, 62).withReset(XLENField.XLEN64) def getISAString = this.getFields.filter(x => x != MXL && x.init.litValue == 1).sortBy(_.lsb).map(x => ('A' + x.msb).toChar).mkString } class MedelegBundle extends ExceptionBundle { this.getALL.foreach(_.setRW().withReset(0.U)) this.EX_MCALL.setRO().withReset(0.U) // never delegate machine level ecall this.EX_DBLTRP.setRO().withReset(0.U)// double trap is not delegatable } class MidelegBundle extends InterruptBundle { this.getALL.foreach(_.setRW().withReset(0.U)) // Don't delegate Machine level interrupts this.getM.foreach(_.setRO().withReset(0.U)) // Ref: 13.4.2. Machine Interrupt Delegation Register (mideleg) // When the hypervisor extension is implemented, bits 10, 6, and 2 of mideleg (corresponding to the standard VS-level // interrupts) are each read-only one. this.getVS.foreach(_.setRO().withReset(1.U)) // bit 12 of mideleg (corresponding to supervisor-level guest external interrupts) is also read-only one. // VS-level interrupts and guest external interrupts are always delegated past M-mode to HS-mode. this.SGEI.setRO().withReset(1.U) this.getLocal.foreach(_.setRO().withReset(0.U)) this.LCOFI.setRW().withReset(0.U) } class MieBundle extends InterruptEnableBundle { this.getNonLocal.foreach(_.setRW().withReset(0.U)) this.LCOFIE.setRW().withReset(0.U) } class MipBundle extends InterruptPendingBundle { // Ref: riscv privileged spec - 18.4.3. Machine Interrupt (mip and mie) Registers // Bits SGEIP, VSEIP, VSTIP, and VSSIP in mip are aliases for the same bits in hypervisor CSR hip // // We implement SGEIP, VSEIP, VSTIP, and VSSIP in mip are registers, // while these bits in hip are aliases for the same bits in mip. // // Ref: riscv interrupt spec - 2.1 Machine-level CSRs // Existing CSRs mie, mip, and mideleg are widended to 64 bits to support a total of 64 interrupt causes. this.getHS.foreach(_.setRW().withReset(0.U)) this.getVS.foreach(_.setRW().withReset(0.U)) this.LCOFIP.setRW().withReset(0.U) } class MvienBundle extends InterruptEnableBundle { // Ref: riscv interrupt spec - 5.3 Interrupt filtering and virtual interrupts for supervisor level // It is strongly recommended that bit 9 of mvien be writable. // It is strongly recommended that bit 1 of mvien also be writable. // A bit in mvien can be set to 1 only for major interrupts 1, 9, and 13–63. this.SSIE.setRW().withReset(0.U) this.SEIE.setRW().withReset(0.U) this.getLocal.foreach(_.setRW().withReset(0.U)) } class MvipBundle extends InterruptPendingBundle { this.getHS.foreach(_.setRW().withReset(0.U)) this.getLocal.foreach(_.setRW().withReset(0.U)) } class Epc extends CSRBundle { val epc = RW(63, 1).withReset(0.U) } class McountinhibitBundle extends CSRBundle { val CY = RW(0).withReset(0.U) val IR = RW(2).withReset(0.U) val HPM3 = RW(31, 3).withReset(0.U) } class Mtval2Bundle extends FieldInitBundle class MhpmcounterBundle extends FieldInitBundle class MEnvCfg extends EnvCfg { if (CSRConfig.EXT_SSTC) { this.STCE.setRW().withReset(1.U) } this.PBMTE.setRW().withReset(0.U) if (CSRConfig.EXT_DBLTRP) { // software write envcfg to open ssdbltrp if need // set 0 to pass ci this.DTE.setRW().withReset(0.U) } } object MarchidField extends CSREnum with ROApply { val XSArchid = Value(25.U) } class MieToHie extends Bundle { val VSSIE = ValidIO(RW(0)) val VSTIE = ValidIO(RW(0)) val VSEIE = ValidIO(RW(0)) val SGEIE = ValidIO(RW(0)) } class MvipToMip extends IpValidBundle { this.getHS.foreach(_.bits.setRW()) } class HipToMip extends IpValidBundle { // Only hip.VSSIP is writable this.VSSIP.bits.setRW() } class VSipToMip extends IpValidBundle { this.LCOFIP.bits.setRW() } class MipToHvip extends IpValidBundle { this.VSSIP.bits.setRW() } class MipToMvip extends IpValidBundle { this.SEIP.bits.setRW() } class MhpmeventBundle extends CSRBundle { val OF = RW(63).withReset(0.U) val MINH = RW(62).withReset(0.U) val SINH = RW(61).withReset(0.U) val UINH = RW(60).withReset(0.U) val VSINH = RW(59).withReset(0.U) val VUINH = RW(58).withReset(0.U) val OPTYPE2 = OPTYPE(54, 50, wNoFilter).withReset(OPTYPE.OR) val OPTYPE1 = OPTYPE(49, 45, wNoFilter).withReset(OPTYPE.OR) val OPTYPE0 = OPTYPE(44, 40, wNoFilter).withReset(OPTYPE.OR) val EVENT3 = RW(39, 30).withReset(0.U) val EVENT2 = RW(29, 20).withReset(0.U) val EVENT1 = RW(19, 10).withReset(0.U) val EVENT0 = RW(9, 0).withReset(0.U) } object OPTYPE extends CSREnum with WARLApply { val OR = Value(0.U) val AND = Value(1.U) val XOR = Value(2.U) val ADD = Value(4.U) override def isLegal(enumeration: CSREnumType): Bool = enumeration.isOneOf(OR, AND, XOR, ADD) } trait HasOfFromPerfCntBundle { self: CSRModule[_] => val ofFromPerfCnt = IO(Input(Bool())) } trait HasMipToAlias { self: CSRModule[_] => val mipAlias = Output(new MipBundle) } trait HasMachineDelegBundle { self: CSRModule[_] => val mideleg = IO(Input(new MidelegBundle)) val medeleg = IO(Input(new MedelegBundle)) } trait HasExternalInterruptBundle { val platformIRP = IO(new Bundle { val MEIP = Input(Bool()) val MTIP = Input(Bool()) val MSIP = Input(Bool()) val SEIP = Input(Bool()) val STIP = Input(Bool()) val VSEIP = Input(Bool()) val VSTIP = Input(Bool()) // debug interrupt from debug module val debugIP = Input(Bool()) }) } trait HasNonMaskableIRPBundle { val nonMaskableIRP = IO(new Bundle { val NMI_43 = Input(Bool()) val NMI_31 = Input(Bool()) }) } trait HasMachineCounterControlBundle { self: CSRModule[_] => val mcountinhibit = IO(Input(new McountinhibitBundle)) } trait HasRobCommitBundle { self: CSRModule[_] => val robCommit = IO(Input(new RobCommitCSR)) val writeFCSR = IO(Input(Bool())) val writeVCSR = IO(Input(Bool())) val isVirtMode = IO(Input(Bool())) } trait HasMachineEnvBundle { self: CSRModule[_] => val menvcfg = IO(Input(new MEnvCfg)) } trait HasPerfCounterBundle { self: CSRModule[_] => val countingEn = IO(Input(Bool())) val perf = IO(Input(new PerfEvent)) val toMhpmeventOF = IO(Output(Bool())) } trait HasPerfEventBundle { self: CSRModule[_] => val perfEvents = IO(Input(Vec(perfCntNum, UInt(XLEN.W)))) } trait HasLocalInterruptReqBundle { self: CSRModule[_] => val lcofiReq = IO(Input(Bool())) } trait HasMachineFlushL2Bundle { self: CSRModule[_] => val l2FlushDone = IO(Input(Bool())) }