package xiangshan.backend.fu.NewCSR import chisel3._ import chisel3.util._ import difftest._ import freechips.rocketchip.rocket.CSRs import org.chipsalliance.cde.config.Parameters import top.{ArgParser, Generator} import utility.{DataHoldBypass, DelayN, GatedValidRegNext, RegNextWithEnable, SignExt, ZeroExt} import utils.{HPerfMonitor, OptionWrapper, PerfEvent} import xiangshan.backend.fu.NewCSR.CSRBundles.{CSRCustomState, PrivState, RobCommitCSR} import xiangshan.backend.fu.NewCSR.CSRDefines.{ContextStatus, HgatpMode, PrivMode, SatpMode, VirtMode} import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._ import xiangshan.backend.fu.NewCSR.CSREvents.{CSREvents, DretEventSinkBundle, EventUpdatePrivStateOutput, MNretEventSinkBundle, MretEventSinkBundle, SretEventSinkBundle, TargetPCBundle, TrapEntryDEventSinkBundle, TrapEntryEventInput, TrapEntryHSEventSinkBundle, TrapEntryMEventSinkBundle, TrapEntryMNEventSinkBundle, TrapEntryVSEventSinkBundle} import xiangshan.backend.fu.fpu.Bundles.Frm import xiangshan.backend.fu.util.CSRConst import xiangshan.backend.fu.vector.Bundles.{Vl, Vstart, Vxrm, Vxsat} import xiangshan.backend.fu.wrapper.CSRToDecode import xiangshan.backend.rob.RobPtr import xiangshan._ import xiangshan.backend.fu.PerfCounterIO import xiangshan.ExceptionNO._ import scala.collection.immutable.SeqMap object CSRConfig { final val GEILEN = 63 final val ASIDLEN = 16 // the length of ASID of XS implementation final val ASIDMAX = 16 // the max value of ASIDLEN defined by spec final val HIIDWidth = 12 // support Hvictl[27:16](IID) final val VMIDLEN = 14 // the length of VMID of XS implementation final val VMIDMAX = 14 // the max value of VMIDLEN defined by spec // the width of VGEIN final val VGEINWidth = 6 final val VaddrMaxWidth = 48 + 2 // support Sv39/Sv48/Sv39x4/Sv48x4 final val InstWidth = 32 final val XLEN = 64 // Todo: use XSParams final val VLEN = 128 // Since we need macro to compute the width of CSR field, the input of macro should be the value that can be computed // at compile time. The log2Up function cannot be used as meta-programming function, so we use litral value here // log2Up(128 + 1), hold 0~128 final val VlWidth = 8 final val PAddrWidth = 48 final val AddrWidthInPage = 12 final val PMPAddrWidth = 48 final val PMPOffBits = 2 final val PMPAddrBits = PMPAddrWidth - PMPOffBits // perf final val perfCntNum = 29 // in Spec final val EXT_SSTC = true final val PPNLength = 44 } class NewCSR(implicit val p: Parameters) extends Module with HasXSParameter with MachineLevel with SupervisorLevel with HypervisorLevel with VirtualSupervisorLevel with Unprivileged with CSRAIA with HasExternalInterruptBundle with HasNonMaskableIRPBundle with CSREvents with DebugLevel with CSRCustom with CSRPMP with IpIeAliasConnect { import CSRConfig._ val io = IO(new Bundle { val fromTop = Input(new Bundle { val hartId = UInt(hartIdLen.W) val clintTime = Input(ValidIO(UInt(64.W))) }) val in = Input(ValidIO(new Bundle { val wen = Bool() val ren = Bool() val op = UInt(2.W) val addr = UInt(12.W) val src = UInt(64.W) val wdata = UInt(64.W) val mnret = Input(Bool()) val mret = Input(Bool()) val sret = Input(Bool()) val dret = Input(Bool()) })) val trapInst = Input(ValidIO(UInt(InstWidth.W))) val fromMem = Input(new Bundle { val excpVA = UInt(VaddrMaxWidth.W) val excpGPA = UInt(VaddrMaxWidth.W) // Todo: use guest physical address width }) val fromRob = Input(new Bundle { val trap = ValidIO(new Bundle { val pc = UInt(VaddrMaxWidth.W) val pcGPA = UInt(VaddrMaxWidth.W) val instr = UInt(InstWidth.W) val trapVec = UInt(64.W) val singleStep = Bool() val trigger = TriggerAction() val crossPageIPFFix = Bool() val isInterrupt = Bool() val isHls = Bool() val isFetchMalAddr = Bool() }) val commit = Input(new RobCommitCSR) val robDeqPtr = Input(new RobPtr) }) val perf = Input(new PerfCounterIO) val out = Output(ValidIO(new Bundle { val EX_II = Bool() val EX_VI = Bool() val flushPipe = Bool() val rData = UInt(64.W) val targetPcUpdate = Bool() val targetPc = new TargetPCBundle val regOut = UInt(64.W) // perf val isPerfCnt = Bool() })) val status = Output(new Bundle { val privState = new PrivState val interrupt = Bool() val wfiEvent = Bool() // fp val fpState = new Bundle { val off = Bool() val frm = Frm() } // vec val vecState = new Bundle { val vstart = Vstart() val vxsat = Vxsat() val vxrm = Vxrm() val vcsr = UInt(XLEN.W) val vl = Vl() val vtype = UInt(XLEN.W) val vlenb = UInt(XLEN.W) val off = Bool() } // debug val debugMode = Bool() val singleStepFlag = Bool() // trigger val frontendTrigger = new FrontendTdataDistributeIO() val memTrigger = new MemTdataDistributeIO() // Instruction fetch address translation type val instrAddrTransType = new AddrTransType // custom val custom = new CSRCustomState }) // tlb val tlb = Output(new Bundle { val satpASIDChanged = Bool() val vsatpASIDChanged = Bool() val hgatpVMIDChanged = Bool() val satp = new SatpBundle val vsatp = new SatpBundle val hgatp = new HgatpBundle val mxr = Bool() val sum = Bool() val vmxr = Bool() val vsum = Bool() val spvp = Bool() val imode = UInt(2.W) val dmode = UInt(2.W) val dvirt = Bool() val mPBMTE = Bool() val hPBMTE = Bool() }) val toDecode = new CSRToDecode val fetchMalTval = Input(UInt(XLEN.W)) }) val toAIA = IO(Output(new CSRToAIABundle)) val fromAIA = IO(Flipped(Output(new AIAToCSRBundle))) dontTouch(toAIA) dontTouch(fromAIA) dontTouch(io.fromTop.clintTime) val valid = io.in.valid val wen = io.in.bits.wen && valid val addr = io.in.bits.addr val wdata = io.in.bits.wdata val ren = io.in.bits.ren && valid val raddr = io.in.bits.addr val hasTrap = io.fromRob.trap.valid val trapVec = io.fromRob.trap.bits.trapVec val trapPC = io.fromRob.trap.bits.pc val trapPCGPA = io.fromRob.trap.bits.pcGPA val trapIsInterrupt = io.fromRob.trap.bits.isInterrupt val trapIsCrossPageIPF = io.fromRob.trap.bits.crossPageIPFFix val trigger = io.fromRob.trap.bits.trigger val singleStep = io.fromRob.trap.bits.singleStep val trapIsHls = io.fromRob.trap.bits.isHls val trapIsFetchMalAddr = io.fromRob.trap.bits.isFetchMalAddr // debug_intrrupt val debugIntrEnable = RegInit(true.B) // debug interrupt will be handle only when debugIntrEnable val debugIntr = platformIRP.debugIP && debugIntrEnable // CSR Privilege State val PRVM = RegInit(PrivMode(1, 0), PrivMode.M) val V = RegInit(VirtMode(0), VirtMode.Off) val debugMode = RegInit(false.B) private val privState = Wire(new PrivState) privState.PRVM := PRVM privState.V := V private val isModeM = privState.isModeM private val (isModeHS, isModeHU) = (privState.isModeHS, privState.isModeHU) private val (isModeVS, isModeVU) = (privState.isModeVS, privState.isModeVU) val permitMod = Module(new CSRPermitModule) val sstcIRGen = Module(new SstcInterruptGen) private val wenLegal = permitMod.io.out.hasLegalWen val legalSret = permitMod.io.out.hasLegalSret val legalMret = permitMod.io.out.hasLegalMret val legalMNret = permitMod.io.out.hasLegalMNret val legalDret = permitMod.io.out.hasLegalDret var csrRwMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = machineLevelCSRMap ++ supervisorLevelCSRMap ++ hypervisorCSRMap ++ virtualSupervisorCSRMap ++ unprivilegedCSRMap ++ debugCSRMap ++ aiaCSRMap ++ customCSRMap ++ pmpCSRMap val csrMods: Seq[CSRModule[_]] = machineLevelCSRMods ++ supervisorLevelCSRMods ++ hypervisorCSRMods ++ virtualSupervisorCSRMods ++ unprivilegedCSRMods ++ debugCSRMods ++ aiaCSRMods ++ customCSRMods ++ pmpCSRMods var csrOutMap: SeqMap[Int, UInt] = machineLevelCSROutMap ++ supervisorLevelCSROutMap ++ hypervisorCSROutMap ++ virtualSupervisorCSROutMap ++ unprivilegedCSROutMap ++ debugCSROutMap ++ aiaCSROutMap ++ customCSROutMap ++ pmpCSROutMap // interrupt val intrMod = Module(new InterruptFilter) intrMod.io.in.privState := privState intrMod.io.in.mstatusMIE := mstatus.regOut.MIE.asBool intrMod.io.in.sstatusSIE := mstatus.regOut.SIE.asBool intrMod.io.in.vsstatusSIE := vsstatus.regOut.SIE.asBool intrMod.io.in.mip := mip.rdata.asUInt intrMod.io.in.mie := mie.rdata.asUInt intrMod.io.in.mideleg := mideleg.rdata.asUInt intrMod.io.in.sip := sip.rdata.asUInt intrMod.io.in.sie := sie.rdata.asUInt intrMod.io.in.hip := hip.rdata.asUInt intrMod.io.in.hie := hie.rdata.asUInt intrMod.io.in.hideleg := hideleg.rdata.asUInt intrMod.io.in.vsip := vsip.rdata.asUInt intrMod.io.in.vsie := vsie.rdata.asUInt intrMod.io.in.hvictl := hvictl.rdata.asUInt intrMod.io.in.hstatus := hstatus.rdata.asUInt intrMod.io.in.mtopei := mtopei.rdata.asUInt intrMod.io.in.stopei := stopei.rdata.asUInt intrMod.io.in.vstopei := vstopei.rdata.asUInt intrMod.io.in.hviprio1 := hviprio1.rdata.asUInt intrMod.io.in.hviprio2 := hviprio2.rdata.asUInt intrMod.io.in.miprios := Cat(miregiprios.map(_.rdata).reverse) intrMod.io.in.hsiprios := Cat(siregiprios.map(_.rdata).reverse) intrMod.io.in.mnstatusNMIE := mnstatus.regOut.NMIE.asBool val nmip = RegInit(new NonMaskableIRPendingBundle, (new NonMaskableIRPendingBundle).init) when(nonMaskableIRP.NMI) { nmip.NMI := true.B } intrMod.io.in.nmi := nmip.asUInt.orR intrMod.io.in.nmiVec := nmip.asUInt when(intrMod.io.out.nmi && intrMod.io.out.interruptVec.valid) { nmip.NMI := false.B } val intrVec = RegEnable(intrMod.io.out.interruptVec.bits, 0.U, intrMod.io.out.interruptVec.valid) val nmi = RegEnable(intrMod.io.out.nmi, false.B, intrMod.io.out.interruptVec.valid) val virtualInterruptIsHvictlInject = RegEnable(intrMod.io.out.virtualInterruptIsHvictlInject, false.B, intrMod.io.out.interruptVec.valid) val trapHandleMod = Module(new TrapHandleModule) trapHandleMod.io.in.trapInfo.valid := hasTrap trapHandleMod.io.in.trapInfo.bits.trapVec := trapVec.asUInt trapHandleMod.io.in.trapInfo.bits.nmi := nmi trapHandleMod.io.in.trapInfo.bits.intrVec := intrVec trapHandleMod.io.in.trapInfo.bits.isInterrupt := trapIsInterrupt trapHandleMod.io.in.privState := privState trapHandleMod.io.in.mideleg := mideleg.regOut trapHandleMod.io.in.medeleg := medeleg.regOut trapHandleMod.io.in.hideleg := hideleg.regOut trapHandleMod.io.in.hedeleg := hedeleg.regOut trapHandleMod.io.in.mvien := mvien.regOut trapHandleMod.io.in.hvien := hvien.regOut trapHandleMod.io.in.mtvec := mtvec.regOut trapHandleMod.io.in.stvec := stvec.regOut trapHandleMod.io.in.vstvec := vstvec.regOut trapHandleMod.io.in.virtualInterruptIsHvictlInject := virtualInterruptIsHvictlInject val entryPrivState = trapHandleMod.io.out.entryPrivState val entryDebugMode = WireInit(false.B) // PMP val pmpEntryMod = Module(new PMPEntryHandleModule) pmpEntryMod.io.in.pmpCfg := cfgs.map(_.regOut.asInstanceOf[PMPCfgBundle]) pmpEntryMod.io.in.pmpAddr := pmpaddr.map(_.regOut.asInstanceOf[PMPAddrBundle]) pmpEntryMod.io.in.ren := ren pmpEntryMod.io.in.wen := wen pmpEntryMod.io.in.addr := addr pmpEntryMod.io.in.wdata := wdata for ((id, (wBundle, _)) <- csrRwMap) { if (vsMapS.contains(id)) { // VS access CSR by S: privState.isModeVS && addrMappedToVS === sMapVS(id).U wBundle.wen := wenLegal && ((isModeVS && addr === vsMapS(id).U) || (!isModeVS && addr === id.U)) wBundle.wdata := wdata } else if (sMapVS.contains(id)) { wBundle.wen := wenLegal && !isModeVS && addr === id.U wBundle.wdata := wdata } else { wBundle.wen := wenLegal && addr === id.U wBundle.wdata := wdata } } private val writeFpLegal = permitMod.io.out.hasLegalWriteFcsr private val writeVecLegal = permitMod.io.out.hasLegalWriteVcsr permitMod.io.in.csrAccess.ren := ren && valid permitMod.io.in.csrAccess.wen := wen permitMod.io.in.csrAccess.addr := addr permitMod.io.in.privState := privState permitMod.io.in.debugMode := debugMode permitMod.io.in.mnret := io.in.bits.mnret && valid permitMod.io.in.mret := io.in.bits.mret && valid permitMod.io.in.sret := io.in.bits.sret && valid permitMod.io.in.dret := io.in.bits.dret && valid permitMod.io.in.csrIsCustom := customCSRMods.map(_.addr.U === addr).reduce(_ || _).orR permitMod.io.in.status.tsr := mstatus.regOut.TSR.asBool permitMod.io.in.status.vtsr := hstatus.regOut.VTSR.asBool permitMod.io.in.status.tvm := mstatus.regOut.TVM.asBool permitMod.io.in.status.vtvm := hstatus.regOut.VTVM.asBool permitMod.io.in.status.mcounteren := mcounteren.rdata permitMod.io.in.status.hcounteren := hcounteren.rdata permitMod.io.in.status.scounteren := scounteren.rdata permitMod.io.in.status.mstateen0 := mstateen0.rdata permitMod.io.in.status.hstateen0 := hstateen0.rdata permitMod.io.in.status.sstateen0 := sstateen0.rdata permitMod.io.in.status.menvcfg := menvcfg.rdata permitMod.io.in.status.henvcfg := henvcfg.rdata permitMod.io.in.status.mstatusFSOff := mstatus.regOut.FS === ContextStatus.Off permitMod.io.in.status.mstatusVSOff := mstatus.regOut.VS === ContextStatus.Off permitMod.io.in.status.vsstatusFSOff := vsstatus.regOut.FS === ContextStatus.Off permitMod.io.in.status.vsstatusVSOff := vsstatus.regOut.VS === ContextStatus.Off permitMod.io.in.aia.miselectIsIllegal := miselect.isIllegal permitMod.io.in.aia.siselectIsIllegal := siselect.isIllegal permitMod.io.in.aia.vsiselectIsIllegal := vsiselect.isIllegal permitMod.io.in.aia.siselect := siselect.rdata permitMod.io.in.aia.vsiselect := vsiselect.rdata permitMod.io.in.aia.mvienSEIE := mvien.regOut.SEIE.asBool permitMod.io.in.aia.hvictlVTI := hvictl.regOut.VTI.asBool sstcIRGen.i.stime.valid := time.updated sstcIRGen.i.stime.bits := time.stime sstcIRGen.i.vstime.valid := time.updated sstcIRGen.i.vstime.bits := time.vstime sstcIRGen.i.stimecmp := stimecmp.rdata sstcIRGen.i.vstimecmp := vstimecmp.rdata sstcIRGen.i.menvcfgSTCE := menvcfg.regOut.STCE.asBool sstcIRGen.i.henvcfgSTCE := henvcfg.regOut.STCE.asBool miregiprios.foreach { mod => mod.w.wen := (addr === mireg.addr.U) && (miselect.regOut.ALL.asUInt === mod.addr.U) mod.w.wdata := wdata } siregiprios.foreach { mod => mod.w.wen := (addr === sireg.addr.U) && (siselect.regOut.ALL.asUInt === mod.addr.U) mod.w.wdata := wdata } mhartid.hartid := this.io.fromTop.hartId cfgs.zipWithIndex.foreach { case (mod, i) => mod.w.wen := wen && (addr === (0x3A0 + i / 8 * 2).U) mod.w.wdata := pmpEntryMod.io.out.pmpCfgWData(8*((i%8)+1)-1,8*(i%8)) } pmpaddr.zipWithIndex.foreach{ case(mod, i) => mod.w.wen := wen && (addr === (0x3B0 + i).U) mod.w.wdata := pmpEntryMod.io.out.pmpAddrWData(i) } csrMods.foreach { mod => mod match { case m: HypervisorBundle => m.hstatus := hstatus.regOut case _ => } mod match { case m: VirtualSupervisorBundle => m.v := V.asUInt.asBool m.hgatp := hgatp.regOut case _ => } mod match { case m: HasMachineDelegBundle => m.mideleg := mideleg.regOut m.medeleg := medeleg.regOut case _ => } mod match { case m: HasMachineCounterControlBundle => m.mcountinhibit := mcountinhibit.regOut case _ => } mod match { case m: HasExternalInterruptBundle => m.platformIRP := this.platformIRP m.platformIRP.STIP := sstcIRGen.o.STIP m.platformIRP.VSTIP := sstcIRGen.o.VSTIP case _ => } mod match { case m: HasRobCommitBundle => // Todo: move RegNext from ROB to CSR m.robCommit.instNum := io.fromRob.commit.instNum m.robCommit.fflags := RegNextWithEnable(io.fromRob.commit.fflags) m.robCommit.fsDirty := GatedValidRegNext(io.fromRob.commit.fsDirty) m.robCommit.vsDirty := GatedValidRegNext(io.fromRob.commit.vsDirty) m.robCommit.vxsat := RegNextWithEnable(io.fromRob.commit.vxsat) m.robCommit.vtype := RegNextWithEnable(io.fromRob.commit.vtype) m.robCommit.vl := RegNext (io.fromRob.commit.vl) m.robCommit.vstart := RegNextWithEnable(io.fromRob.commit.vstart) m.writeFCSR := writeFpLegal m.writeVCSR := writeVecLegal m.isVirtMode := V.asUInt.asBool case _ => } mod match { case m: TrapEntryDEventSinkBundle => m.trapToD := trapEntryDEvent.out case _ => } mod match { case m: TrapEntryMEventSinkBundle => m.trapToM := trapEntryMEvent.out case _ => } mod match { case m: TrapEntryMNEventSinkBundle => m.trapToMN := trapEntryMNEvent.out case _ => } mod match { case m: TrapEntryHSEventSinkBundle => m.trapToHS := trapEntryHSEvent.out case _ => } mod match { case m: TrapEntryVSEventSinkBundle => m.trapToVS := trapEntryVSEvent.out case _ => } mod match { case m: MretEventSinkBundle => m.retFromM := mretEvent.out case _ => } mod match { case m: MNretEventSinkBundle => m.retFromMN := mnretEvent.out case _ => } mod match { case m: SretEventSinkBundle => m.retFromS := sretEvent.out case _ => } mod match { case m: DretEventSinkBundle => m.retFromD := dretEvent.out case _ => } mod match { case m: HasAIABundle => m.aiaToCSR.rdata.valid := fromAIA.rdata.valid m.aiaToCSR.rdata.bits.data := fromAIA.rdata.bits.data m.aiaToCSR.rdata.bits.illegal := fromAIA.rdata.bits.illegal m.aiaToCSR.meip := fromAIA.meip m.aiaToCSR.seip := fromAIA.seip m.aiaToCSR.vseip := fromAIA.vseip m.aiaToCSR.mtopei := fromAIA.mtopei m.aiaToCSR.stopei := fromAIA.stopei m.aiaToCSR.vstopei := fromAIA.vstopei case _ => } mod match { case m: HasInterruptFilterSink => m.topIR.mtopi := intrMod.io.out.mtopi m.topIR.stopi := intrMod.io.out.stopi m.topIR.vstopi := intrMod.io.out.vstopi case _ => } mod match { case m: HasPMPAddrSink => m.addrRData := pmpEntryMod.io.out.pmpAddrRData case _ => } mod match { case m: HasMHPMSink => // cycle from mcycle m.mHPM.cycle := mcycle.rdata // time from clint m.mHPM.time := io.fromTop.clintTime // instret from minstret m.mHPM.instret := minstret.rdata // VS-Mode or VU-Mode m.v := privState.isVirtual m.htimedelta := htimedelta.rdata m.mHPM.hpmcounters.zip(mhpmcounters).map{ case(counter, mcounter) => counter := mcounter.rdata } case _ => } mod match { case m: HasMachineEnvBundle => m.menvcfg := menvcfg.regOut case _ => } mod match { case m: HasHypervisorEnvBundle => m.menvcfg := menvcfg.regOut m.privState := privState m.accessStimecmp := (ren || wen) && (addr === CSRs.stimecmp.U || addr === CSRs.vstimecmp.U) case _ => } mod match { case m: HasIpIeBundle => m.mideleg := mideleg.regOut m.mip := mip.rdata m.mie := mie.regOut m.mvip := mvip.regOut m.mvien := mvien.regOut m.hideleg := hideleg.regOut m.hip := hip.regOut m.hie := hie.regOut m.hvien := hvien.regOut m.hvip := hvip.regOut m.sip := sip.regOut m.sie := sie.regOut m.vsip := vsip.regOut m.vsie := vsie.regOut m.hgeip := hgeip.regOut m.hgeie := hgeie.regOut m.hstatusVGEIN := hstatus.regOut.VGEIN case _ => } mod match { case m: HasMhpmeventOfBundle => m.ofVec := VecInit(mhpmevents.map(event => event.rdata.head(1).asBool)).asUInt //todo:fix m.privState := privState m.mcounteren := mcounteren.rdata m.hcounteren := hcounteren.rdata case _ => } mod match { case m: HasStateen0Bundle => m.fromMstateen0 := mstateen0.regOut m.fromHstateen0 := hstateen0.regOut m.privState := privState case _ => } } csrMods.foreach { mod => println(s"${mod.modName}: ") println(mod.dumpFields) } trapEntryMEvent.valid := hasTrap && entryPrivState.isModeM && !entryDebugMode && !debugMode && !nmi trapEntryMNEvent.valid := hasTrap && nmi && !debugMode trapEntryHSEvent.valid := hasTrap && entryPrivState.isModeHS && !entryDebugMode && !debugMode trapEntryVSEvent.valid := hasTrap && entryPrivState.isModeVS && !entryDebugMode && !debugMode Seq(trapEntryMEvent, trapEntryMNEvent, trapEntryHSEvent, trapEntryVSEvent, trapEntryDEvent).foreach { eMod => eMod.in match { case in: TrapEntryEventInput => in.causeNO := trapHandleMod.io.out.causeNO in.trapPc := trapPC in.trapPcGPA := trapPCGPA // only used by trapEntryMEvent & trapEntryHSEvent in.trapInst := io.trapInst in.fetchMalTval := io.fetchMalTval in.isCrossPageIPF := trapIsCrossPageIPF in.isHls := trapIsHls in.isFetchMalAddr := trapIsFetchMalAddr in.iMode.PRVM := PRVM in.iMode.V := V // when NMIE is zero, force to behave as MPRV is zero in.dMode.PRVM := Mux(mstatus.regOut.MPRV.asBool && mnstatus.regOut.NMIE.asBool, mstatus.regOut.MPP, PRVM) in.dMode.V := V.asUInt.asBool || mstatus.regOut.MPRV && mnstatus.regOut.NMIE.asBool && (mstatus.regOut.MPP =/= PrivMode.M) && mstatus.regOut.MPV in.privState := privState in.mstatus := mstatus.regOut in.hstatus := hstatus.regOut in.sstatus := mstatus.sstatus in.vsstatus := vsstatus.regOut in.pcFromXtvec := trapHandleMod.io.out.pcFromXtvec in.tcontrol := tcontrol.regOut in.satp := satp.regOut in.vsatp := vsatp.regOut in.hgatp := hgatp.regOut in.memExceptionVAddr := io.fromMem.excpVA in.memExceptionGPAddr := io.fromMem.excpGPA in.virtualInterruptIsHvictlInject := virtualInterruptIsHvictlInject in.hvictlIID := hvictl.regOut.IID.asUInt } } mnretEvent.valid := legalMNret mnretEvent.in match { case in => in.mstatus := mstatus.regOut in.mnepc := mnepc.regOut in.mnstatus:= mnstatus.regOut in.satp := satp.regOut in.vsatp := vsatp.regOut in.hgatp := hgatp.regOut } mretEvent.valid := legalMret mretEvent.in match { case in => in.mstatus := mstatus.regOut in.mepc := mepc.regOut in.tcontrol := tcontrol.regOut in.satp := satp.regOut in.vsatp := vsatp.regOut in.hgatp := hgatp.regOut } sretEvent.valid := legalSret sretEvent.in match { case in => in.privState := privState in.sstatus := mstatus.sstatus in.hstatus := hstatus.regOut in.vsstatus := vsstatus.regOut in.sepc := sepc.regOut in.vsepc := vsepc.regOut in.satp := satp.regOut in.vsatp := vsatp.regOut in.hgatp := hgatp.regOut } dretEvent.valid := legalDret dretEvent.in match { case in => in.dcsr := dcsr.regOut in.dpc := dpc.regOut in.mstatus := mstatus.regOut in.satp := satp.regOut in.vsatp := vsatp.regOut in.hgatp := hgatp.regOut } PRVM := MuxCase( PRVM, events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map { x => x.out match { case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.PRVM) } } ) V := MuxCase( V, events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map { x => x.out match { case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.V) } } ) debugMode := MuxCase( debugMode, Seq( dretEvent.out.debugMode.valid -> dretEvent.out.debugMode.bits, trapEntryDEvent.out.debugMode.valid -> trapEntryDEvent.out.debugMode.bits ) ) debugIntrEnable := MuxCase( debugIntrEnable, Seq( dretEvent.out.debugIntrEnable.valid -> dretEvent.out.debugIntrEnable.bits, trapEntryDEvent.out.debugIntrEnable.valid -> trapEntryDEvent.out.debugIntrEnable.bits ) ) // perf val addrInPerfCnt = (wen || ren) && ( (addr >= CSRs.mcycle.U) && (addr <= CSRs.mhpmcounter31.U) || (addr === mcountinhibit.addr.U) || (addr >= CSRs.cycle.U) && (addr <= CSRs.hpmcounter31.U) || (addr === CSRs.mip.U) || (addr === CSRs.sip.U) || (addr === CSRs.vsip.U) || (addr === CSRs.hip.U) || (addr === CSRs.mvip.U) || (addr === CSRs.hvip.U) || Cat(aiaSkipCSRs.map(_.addr.U === addr)).orR || (addr === CSRs.menvcfg.U) || (addr === CSRs.henvcfg.U) || (addr === CSRs.stimecmp.U) ) // flush val resetSatp = Cat(Seq(satp, vsatp, hgatp).map(_.addr.U === addr)).orR && wenLegal // write to satp will cause the pipeline be flushed val floatStatusOnOff = mstatus.w.wen && ( mstatus.w.wdataFields.FS === ContextStatus.Off && mstatus.regOut.FS =/= ContextStatus.Off || mstatus.w.wdataFields.FS =/= ContextStatus.Off && mstatus.regOut.FS === ContextStatus.Off ) || mstatus.wAliasSstatus.wen && ( mstatus.wAliasSstatus.wdataFields.FS === ContextStatus.Off && mstatus.regOut.FS =/= ContextStatus.Off || mstatus.wAliasSstatus.wdataFields.FS =/= ContextStatus.Off && mstatus.regOut.FS === ContextStatus.Off ) || vsstatus.w.wen && ( vsstatus.w.wdataFields.FS === ContextStatus.Off && vsstatus.regOut.FS =/= ContextStatus.Off || vsstatus.w.wdataFields.FS =/= ContextStatus.Off && vsstatus.regOut.FS === ContextStatus.Off ) val vectorStatusOnOff = mstatus.w.wen && ( mstatus.w.wdataFields.VS === ContextStatus.Off && mstatus.regOut.VS =/= ContextStatus.Off || mstatus.w.wdataFields.VS =/= ContextStatus.Off && mstatus.regOut.VS === ContextStatus.Off ) || mstatus.wAliasSstatus.wen && ( mstatus.wAliasSstatus.wdataFields.VS === ContextStatus.Off && mstatus.regOut.VS =/= ContextStatus.Off || mstatus.wAliasSstatus.wdataFields.VS =/= ContextStatus.Off && mstatus.regOut.VS === ContextStatus.Off ) || vsstatus.w.wen && ( vsstatus.w.wdataFields.VS === ContextStatus.Off && vsstatus.regOut.VS =/= ContextStatus.Off || vsstatus.w.wdataFields.VS =/= ContextStatus.Off && vsstatus.regOut.VS === ContextStatus.Off ) val triggerFrontendChange = Wire(Bool()) val vstartChange = vstart.w.wen && ( vstart.w.wdata === 0.U && vstart.regOut.vstart.asUInt =/= 0.U || vstart.w.wdata =/= 0.U && vstart.regOut.vstart.asUInt === 0.U ) // flush pipe when write frm and data > 4 or write fcsr and data[7:5] > 4 or write frm/fcsr and frm is reserved val frmIsReserved = fcsr.frm(2) && fcsr.frm(1, 0).orR val frmWdataReserved = fcsr.wAliasFfm.wdata(2) && fcsr.wAliasFfm.wdata(1, 0).orR val fcsrWdataReserved = fcsr.w.wdata(7) && fcsr.w.wdata(6, 5).orR val frmChange = fcsr.wAliasFfm.wen && (!frmIsReserved && frmWdataReserved || frmIsReserved && !frmWdataReserved) || fcsr.w.wen && (!frmIsReserved && fcsrWdataReserved || frmIsReserved && !fcsrWdataReserved) val flushPipe = resetSatp || triggerFrontendChange || floatStatusOnOff || vectorStatusOnOff || vstartChange || frmChange private val rdata = Mux1H(csrRwMap.map { case (id, (_, rdata)) => if (vsMapS.contains(id)) { ((isModeVS && addr === vsMapS(id).U) || !isModeVS && addr === id.U) -> rdata } else if (sMapVS.contains(id)) { (!isModeVS && addr === id.U) -> rdata } else { (raddr === id.U) -> rdata } }) private val regOut = Mux1H(csrOutMap.map { case (id, regOut) => if (vsMapS.contains(id)) { ((isModeVS && addr === vsMapS(id).U) || !isModeVS && addr === id.U) -> regOut } else if (sMapVS.contains(id)) { (!isModeVS && addr === id.U) -> regOut } else { (raddr === id.U) -> regOut } }) private val needTargetUpdate = mnretEvent.out.targetPc.valid || mretEvent.out.targetPc.valid || sretEvent.out.targetPc.valid || dretEvent.out.targetPc.valid || trapEntryMEvent.out.targetPc.valid || trapEntryMNEvent.out.targetPc.valid || trapEntryHSEvent.out.targetPc.valid || trapEntryVSEvent.out.targetPc.valid || trapEntryDEvent.out.targetPc.valid private val noCSRIllegal = (ren || wen) && Cat(csrRwMap.keys.toSeq.sorted.map(csrAddr => !(addr === csrAddr.U))).andR private val s_idle :: s_waitIMSIC :: Nil = Enum(2) private val state = RegInit(s_idle) private val stateNext = WireInit(state) state := stateNext private val asyncRead = ren && ( mireg.addr.U === addr && miselect.inIMSICRange || sireg.addr.U === addr && siselect.inIMSICRange || vsireg.addr.U === addr && vsiselect.inIMSICRange ) switch(state) { is(s_idle) { when(asyncRead) { stateNext := s_waitIMSIC } } is(s_waitIMSIC) { when(fromAIA.rdata.valid) { stateNext := s_idle } } } // Todo: check IMSIC EX_II and EX_VI private val imsicIllegal = fromAIA.rdata.valid && fromAIA.rdata.bits.illegal private val imsic_EX_II = imsicIllegal && !V.asUInt.asBool private val imsic_EX_VI = imsicIllegal && V.asUInt.asBool io.out.valid := io.in.valid && stateNext === s_idle || state === s_waitIMSIC && stateNext === s_idle io.out.bits.EX_II := permitMod.io.out.EX_II || imsic_EX_II || noCSRIllegal io.out.bits.EX_VI := permitMod.io.out.EX_VI || imsic_EX_VI io.out.bits.flushPipe := flushPipe io.out.bits.rData := MuxCase(0.U, Seq( (state === s_waitIMSIC && stateNext === s_idle) -> fromAIA.rdata.bits.data, ren -> rdata, )) io.out.bits.regOut := regOut io.out.bits.targetPc := DataHoldBypass( Mux(trapEntryDEvent.out.targetPc.valid, trapEntryDEvent.out.targetPc.bits, Mux1H(Seq( mnretEvent.out.targetPc.valid -> mnretEvent.out.targetPc.bits, mretEvent.out.targetPc.valid -> mretEvent.out.targetPc.bits, sretEvent.out.targetPc.valid -> sretEvent.out.targetPc.bits, dretEvent.out.targetPc.valid -> dretEvent.out.targetPc.bits, trapEntryMEvent.out.targetPc.valid -> trapEntryMEvent.out.targetPc.bits, trapEntryMNEvent.out.targetPc.valid -> trapEntryMNEvent.out.targetPc.bits, trapEntryHSEvent.out.targetPc.valid -> trapEntryHSEvent.out.targetPc.bits, trapEntryVSEvent.out.targetPc.valid -> trapEntryVSEvent.out.targetPc.bits) ) ), needTargetUpdate) io.out.bits.targetPcUpdate := needTargetUpdate io.out.bits.isPerfCnt := addrInPerfCnt io.status.privState := privState io.status.fpState.frm := fcsr.frm io.status.fpState.off := mstatus.regOut.FS === ContextStatus.Off io.status.vecState.vstart := vstart.rdata.asUInt io.status.vecState.vxsat := vcsr.vxsat io.status.vecState.vxrm := vcsr.vxrm io.status.vecState.vcsr := vcsr.rdata.asUInt io.status.vecState.vl := vl.rdata.asUInt io.status.vecState.vtype := vtype.rdata.asUInt // Todo: check correct io.status.vecState.vlenb := vlenb.rdata.asUInt io.status.vecState.off := mstatus.regOut.VS === ContextStatus.Off io.status.interrupt := intrMod.io.out.interruptVec.valid io.status.wfiEvent := debugIntr || (mie.rdata.asUInt & mip.rdata.asUInt).orR io.status.debugMode := debugMode io.status.singleStepFlag := !debugMode && dcsr.regOut.STEP /** * debug_begin */ val tdata1Selected = Wire(new Tdata1Bundle) tdata1Selected := tdata1.rdata val dmodeInSelectedTrigger = tdata1Selected.DMODE.asBool val triggerCanWrite = dmodeInSelectedTrigger && debugMode || !dmodeInSelectedTrigger val tdata1Update = tdata1.w.wen && triggerCanWrite val tdata2Update = tdata2.w.wen && triggerCanWrite val tdata1Vec = tdata1RegVec.map{ mod => { val tdata1Wire = Wire(new Tdata1Bundle) tdata1Wire := mod.rdata tdata1Wire }} val debugMod = Module(new Debug) debugMod.io.in.trapInfo.valid := hasTrap debugMod.io.in.trapInfo.bits.trapVec := trapVec.asUInt debugMod.io.in.trapInfo.bits.intrVec := intrVec debugMod.io.in.trapInfo.bits.isInterrupt := trapIsInterrupt debugMod.io.in.trapInfo.bits.trigger := trigger debugMod.io.in.trapInfo.bits.singleStep := singleStep debugMod.io.in.privState := privState debugMod.io.in.debugMode := debugMode debugMod.io.in.dcsr := dcsr.regOut debugMod.io.in.tcontrol := tcontrol.regOut debugMod.io.in.tselect := tselect.regOut debugMod.io.in.tdata1Vec := tdata1Vec debugMod.io.in.tdata1Selected := tdata1.rdata debugMod.io.in.tdata2Selected := tdata2.rdata debugMod.io.in.tdata1Update := tdata1Update debugMod.io.in.tdata2Update := tdata2Update debugMod.io.in.tdata1Wdata := wdata entryDebugMode := debugMod.io.out.hasDebugTrap && !debugMode trapEntryDEvent.valid := entryDebugMode trapEntryDEvent.in.hasDebugIntr := debugMod.io.out.hasDebugIntr trapEntryDEvent.in.debugMode := debugMode trapEntryDEvent.in.hasTrap := hasTrap trapEntryDEvent.in.hasSingleStep := debugMod.io.out.hasSingleStep trapEntryDEvent.in.triggerEnterDebugMode := debugMod.io.out.triggerEnterDebugMode trapEntryDEvent.in.hasDebugEbreakException := debugMod.io.out.hasDebugEbreakException trapEntryDEvent.in.breakPoint := debugMod.io.out.breakPoint trapHandleMod.io.in.trapInfo.bits.singleStep := debugMod.io.out.hasSingleStep intrMod.io.in.debugMode := debugMode intrMod.io.in.debugIntr := debugIntr intrMod.io.in.dcsr := dcsr.regOut tdata1RegVec.foreach { mod => mod match { case m: HasdebugModeBundle => m.debugMode := debugMode m.chainable := debugMod.io.out.newTriggerChainIsLegal case _ => } } tdata1RegVec.zip(tdata2RegVec).zipWithIndex.map { case ((mod1, mod2), idx) => { mod1.w.wen := tdata1Update && (tselect.rdata === idx.U) mod1.w.wdata := wdata mod2.w.wen := tdata2Update && (tselect.rdata === idx.U) mod2.w.wdata := wdata }} triggerFrontendChange := debugMod.io.out.triggerFrontendChange io.status.frontendTrigger := debugMod.io.out.frontendTrigger io.status.memTrigger := debugMod.io.out.memTrigger /** * debug_end */ /** * perf_begin * perf number: 29 (frontend 8, ctrlblock 8, memblock 8, huancun 5) */ // tmp: mhpmevents is wrapper of perfEvents, read/write/update mhpmevents -> read/write/update perfEvents val csrevents = perfEvents.slice(24, 29) val hcEvents = Wire(Vec(numPCntHc * coreParams.L2NBanks, new PerfEvent)) for (i <- 0 until numPCntHc * coreParams.L2NBanks) { hcEvents(i) := io.perf.perfEventsHc(i) } val allHcPerfEvents = hcEvents.map(x => (s"Hc", x.value)) if (printEventCoding) { for (((name, inc), i) <- allHcPerfEvents.zipWithIndex) { println("HuanCun perfEvents Set", name, inc, i) } } val hpmHc = HPerfMonitor(csrevents, hcEvents) val privState1H = Cat(privState.isModeM, privState.isModeHS, privState.isModeHU, privState.isModeVS, privState.isModeVU) val countingEn = RegInit(0.U.asTypeOf(Vec(perfCntNum, Bool()))) for (i <-0 until perfCntNum) { countingEn(i) := ((~mhpmevents(i).rdata(62, 58)).asUInt & privState1H).orR } val allPerfEvents = io.perf.perfEventsFrontend ++ io.perf.perfEventsBackend ++ io.perf.perfEventsLsu ++ hpmHc.getPerf val ofFromPerfCntVec = Wire(Vec(perfCntNum, Bool())) val lcofiReqVec = Wire(Vec(perfCntNum, Bool())) for(i <- 0 until perfCntNum) { mhpmcounters(i) match { case m: HasPerfCounterBundle => m.countingEn := countingEn(i) m.perf := allPerfEvents(i) ofFromPerfCntVec(i) := m.toMhpmeventOF case _ => } perfEvents(i) := Mux(mhpmevents(i).w.wen, wdata, (perfEvents(i).head(1).asBool || ofFromPerfCntVec(i)) ## perfEvents(i).tail(1)) lcofiReqVec(i) := ofFromPerfCntVec(i) && !mhpmevents(i).rdata.head(1) } val lcofiReq = lcofiReqVec.asUInt.orR mip match { case m: HasLocalInterruptReqBundle => m.lcofiReq := lcofiReq case _ => } /** * perf_end */ /** * [[io.status.custom]] connection */ io.status.custom.l1I_pf_enable := spfctl.regOut.L1I_PF_ENABLE.asBool io.status.custom.l2_pf_enable := spfctl.regOut.L2_PF_ENABLE.asBool io.status.custom.l1D_pf_enable := spfctl.regOut.L1D_PF_ENABLE.asBool io.status.custom.l1D_pf_train_on_hit := spfctl.regOut.L1D_PF_TRAIN_ON_HIT.asBool io.status.custom.l1D_pf_enable_agt := spfctl.regOut.L1D_PF_ENABLE_AGT.asBool io.status.custom.l1D_pf_enable_pht := spfctl.regOut.L1D_PF_ENABLE_PHT.asBool io.status.custom.l1D_pf_active_threshold := spfctl.regOut.L1D_PF_ACTIVE_THRESHOLD.asUInt io.status.custom.l1D_pf_active_stride := spfctl.regOut.L1D_PF_ACTIVE_STRIDE.asUInt io.status.custom.l1D_pf_enable_stride := spfctl.regOut.L1D_PF_ENABLE_STRIDE.asBool io.status.custom.l2_pf_store_only := spfctl.regOut.L2_PF_STORE_ONLY.asBool io.status.custom.icache_parity_enable := sfetchctl.regOut.ICACHE_PARITY_ENABLE.asBool io.status.custom.lvpred_disable := slvpredctl.regOut.LVPRED_DISABLE.asBool io.status.custom.no_spec_load := slvpredctl.regOut.NO_SPEC_LOAD.asBool io.status.custom.storeset_wait_store := slvpredctl.regOut.STORESET_WAIT_STORE.asBool io.status.custom.storeset_no_fast_wakeup := slvpredctl.regOut.STORESET_NO_FAST_WAKEUP.asBool io.status.custom.lvpred_timeout := slvpredctl.regOut.LVPRED_TIMEOUT.asUInt io.status.custom.bp_ctrl.ubtb_enable := sbpctl.regOut.UBTB_ENABLE .asBool io.status.custom.bp_ctrl.btb_enable := sbpctl.regOut.BTB_ENABLE .asBool io.status.custom.bp_ctrl.bim_enable := sbpctl.regOut.BIM_ENABLE .asBool io.status.custom.bp_ctrl.tage_enable := sbpctl.regOut.TAGE_ENABLE .asBool io.status.custom.bp_ctrl.sc_enable := sbpctl.regOut.SC_ENABLE .asBool io.status.custom.bp_ctrl.ras_enable := sbpctl.regOut.RAS_ENABLE .asBool io.status.custom.bp_ctrl.loop_enable := sbpctl.regOut.LOOP_ENABLE .asBool io.status.custom.sbuffer_threshold := smblockctl.regOut.SBUFFER_THRESHOLD.asUInt io.status.custom.ldld_vio_check_enable := smblockctl.regOut.LDLD_VIO_CHECK_ENABLE.asBool io.status.custom.soft_prefetch_enable := smblockctl.regOut.SOFT_PREFETCH_ENABLE.asBool io.status.custom.cache_error_enable := smblockctl.regOut.CACHE_ERROR_ENABLE.asBool io.status.custom.uncache_write_outstanding_enable := smblockctl.regOut.UNCACHE_WRITE_OUTSTANDING_ENABLE.asBool io.status.custom.hd_misalign_st_enable := smblockctl.regOut.HD_MISALIGN_ST_ENABLE.asBool io.status.custom.hd_misalign_ld_enable := smblockctl.regOut.HD_MISALIGN_LD_ENABLE.asBool io.status.custom.fusion_enable := srnctl.regOut.FUSION_ENABLE.asBool io.status.custom.wfi_enable := srnctl.regOut.WFI_ENABLE.asBool io.status.instrAddrTransType.bare := privState.isModeM || (!privState.isVirtual && satp.regOut.MODE === SatpMode.Bare) || (privState.isVirtual && vsatp.regOut.MODE === SatpMode.Bare && hgatp.regOut.MODE === HgatpMode.Bare) io.status.instrAddrTransType.sv39 := !privState.isModeM && !privState.isVirtual && satp.regOut.MODE === SatpMode.Sv39 || privState.isVirtual && vsatp.regOut.MODE === SatpMode.Sv39 io.status.instrAddrTransType.sv48 := !privState.isModeM && !privState.isVirtual && satp.regOut.MODE === SatpMode.Sv48 || privState.isVirtual && vsatp.regOut.MODE === SatpMode.Sv48 io.status.instrAddrTransType.sv39x4 := privState.isVirtual && vsatp.regOut.MODE === SatpMode.Bare && hgatp.regOut.MODE === HgatpMode.Sv39x4 io.status.instrAddrTransType.sv48x4 := privState.isVirtual && vsatp.regOut.MODE === SatpMode.Bare && hgatp.regOut.MODE === HgatpMode.Sv48x4 assert(PopCount(io.status.instrAddrTransType.asUInt) === 1.U, "Exactly one inst trans type should be asserted") private val csrAccess = wen || ren private val imsicAddrValid = csrAccess && addr === CSRs.mireg.U && miselect.inIMSICRange || csrAccess && addr === CSRs.sireg.U && !isModeVS && siselect.inIMSICRange || csrAccess && (addr === CSRs.sireg.U && isModeVS || addr === CSRs.vsireg.U) && vsiselect.inIMSICRange private val imsicAddr = Mux1H(Seq( (csrAccess && addr === CSRs.mireg.U) -> miselect.rdata, (csrAccess && addr === CSRs.sireg.U && !isModeVS) -> siselect.rdata, (csrAccess && (addr === CSRs.sireg.U && isModeVS || addr === CSRs.vsireg.U)) -> vsiselect.rdata, )) private val imsicAddrPrivState = Mux1H(Seq( (csrAccess && addr === CSRs.mireg.U) -> PrivState.ModeM, (csrAccess && addr === CSRs.sireg.U && !isModeVS) -> PrivState.ModeHS, (csrAccess && (addr === CSRs.sireg.U && isModeVS || addr === CSRs.vsireg.U)) -> PrivState.ModeVS, )) private val imsicWdataValid = mireg.w.wen && miselect.inIMSICRange || sireg.w.wen && siselect.inIMSICRange || vsireg.w.wen && vsiselect.inIMSICRange toAIA.addr.valid := imsicAddrValid toAIA.addr.bits.addr := imsicAddr toAIA.addr.bits.prvm := imsicAddrPrivState.PRVM toAIA.addr.bits.v := imsicAddrPrivState.V toAIA.wdata.valid := imsicWdataValid toAIA.wdata.bits.op := io.in.bits.op toAIA.wdata.bits.data := io.in.bits.src toAIA.vgein := hstatus.regOut.VGEIN.asUInt toAIA.mClaim := mtopei.w.wen toAIA.sClaim := stopei.w.wen toAIA.vsClaim := vstopei.w.wen // tlb io.tlb.satpASIDChanged := GatedValidRegNext(wenLegal && addr === CSRs. satp.U && satp .regOut.ASID =/= satp.w.wdataFields.ASID) io.tlb.vsatpASIDChanged := GatedValidRegNext(wenLegal && addr === CSRs.vsatp.U && vsatp.regOut.ASID =/= vsatp.w.wdataFields.ASID) io.tlb.hgatpVMIDChanged := GatedValidRegNext(wenLegal && addr === CSRs.hgatp.U && hgatp.regOut.VMID =/= hgatp.w.wdataFields.VMID) io.tlb.satp := satp.rdata io.tlb.vsatp := vsatp.rdata io.tlb.hgatp := hgatp.rdata io.tlb.mxr := mstatus.regOut.MXR.asBool io.tlb.sum := mstatus.regOut.SUM.asBool io.tlb.vmxr := vsstatus.regOut.MXR.asBool io.tlb.vsum := vsstatus.regOut.SUM.asBool io.tlb.spvp := hstatus.regOut.SPVP.asBool io.tlb.imode := PRVM.asUInt // when NMIE is zero, force to behave as MPRV is zero io.tlb.dmode := Mux( (debugMode && dcsr.regOut.MPRVEN || !debugMode) && mstatus.regOut.MPRV && mnstatus.regOut.NMIE, mstatus.regOut.MPP.asUInt, PRVM.asUInt ) io.tlb.dvirt := Mux( (debugMode && dcsr.regOut.MPRVEN || !debugMode) && mstatus.regOut.MPRV && mnstatus.regOut.NMIE && mstatus.regOut.MPP =/= PrivMode.M, mstatus.regOut.MPV.asUInt, V.asUInt ) io.tlb.mPBMTE := menvcfg.regOut.PBMTE.asBool io.tlb.hPBMTE := henvcfg.regOut.PBMTE.asBool io.toDecode.illegalInst.sfenceVMA := isModeHS && mstatus.regOut.TVM || isModeHU io.toDecode.virtualInst.sfenceVMA := isModeVS && hstatus.regOut.VTVM || isModeVU io.toDecode.illegalInst.sfencePart := isModeHU io.toDecode.virtualInst.sfencePart := isModeVU io.toDecode.illegalInst.hfenceGVMA := isModeHS && mstatus.regOut.TVM || isModeHU io.toDecode.illegalInst.hfenceVVMA := isModeHU io.toDecode.virtualInst.hfence := isModeVS || isModeVU io.toDecode.illegalInst.hlsv := isModeHU && !hstatus.regOut.HU io.toDecode.virtualInst.hlsv := isModeVS || isModeVU io.toDecode.illegalInst.fsIsOff := mstatus.regOut.FS === ContextStatus.Off || (isModeVS || isModeVU) && vsstatus.regOut.FS === ContextStatus.Off io.toDecode.illegalInst.vsIsOff := mstatus.regOut.VS === ContextStatus.Off || (isModeVS || isModeVU) && vsstatus.regOut.VS === ContextStatus.Off io.toDecode.illegalInst.wfi := isModeHU || !isModeM && mstatus.regOut.TW io.toDecode.virtualInst.wfi := isModeVS && !mstatus.regOut.TW && hstatus.regOut.VTW || isModeVU && !mstatus.regOut.TW io.toDecode.illegalInst.frm := frmIsReserved // Always instantiate basic difftest modules. if (env.AlwaysBasicDiff || env.EnableDifftest) { val hartId = io.fromTop.hartId val trapValid = io.fromRob.trap.valid val trapNO = Mux(virtualInterruptIsHvictlInject && hasTrap, hvictl.regOut.IID.asUInt, trapHandleMod.io.out.causeNO.ExceptionCode.asUInt) val interrupt = trapHandleMod.io.out.causeNO.Interrupt.asBool val hasNMI = nmi && hasTrap val interruptNO = Mux(interrupt, trapNO, 0.U) val exceptionNO = Mux(!interrupt, trapNO, 0.U) val isSv39: Bool = (isModeHS || isModeHU) && satp.regOut.MODE === SatpMode.Sv39 || (isModeVS || isModeVU) && vsatp.regOut.MODE === SatpMode.Sv39 val isSv48: Bool = (isModeHS || isModeHU) && satp.regOut.MODE === SatpMode.Sv48 || (isModeVS || isModeVU) && vsatp.regOut.MODE === SatpMode.Sv48 val isBare = !isSv39 && !isSv48 val sv39PC = SignExt(trapPC.take(39), XLEN) val sv48PC = SignExt(trapPC.take(48), XLEN) val barePC = ZeroExt(trapPC.take(PAddrBits), XLEN) // When enable virtual memory, the higher bit should fill with the msb of address of Sv39/Sv48/Sv57 val exceptionPC = Mux1H(Seq( isSv39 -> sv39PC, isSv48 -> sv48PC, isBare -> barePC, )) val diffArchEvent = DifftestModule(new DiffArchEvent, delay = 3, dontCare = true) diffArchEvent.coreid := hartId diffArchEvent.valid := trapValid diffArchEvent.interrupt := interruptNO diffArchEvent.exception := exceptionNO diffArchEvent.exceptionPC := exceptionPC diffArchEvent.hasNMI := hasNMI diffArchEvent.virtualInterruptIsHvictlInject := virtualInterruptIsHvictlInject && hasTrap if (env.EnableDifftest) { diffArchEvent.exceptionInst := io.fromRob.trap.bits.instr } val diffCSRState = DifftestModule(new DiffCSRState) diffCSRState.coreid := hartId diffCSRState.privilegeMode := privState.PRVM.asUInt diffCSRState.mstatus := mstatus.rdata.asUInt diffCSRState.sstatus := mstatus.sstatus.asUInt diffCSRState.mepc := mepc.rdata.asUInt diffCSRState.sepc := sepc.rdata.asUInt diffCSRState.mtval := mtval.rdata.asUInt diffCSRState.stval := stval.rdata.asUInt diffCSRState.mtvec := mtvec.rdata.asUInt diffCSRState.stvec := stvec.rdata.asUInt diffCSRState.mcause := mcause.rdata.asUInt diffCSRState.scause := scause.rdata.asUInt diffCSRState.satp := satp.rdata.asUInt diffCSRState.mip := mip.regOut.asUInt diffCSRState.mie := mie.rdata.asUInt diffCSRState.mscratch := mscratch.rdata.asUInt diffCSRState.sscratch := sscratch.rdata.asUInt diffCSRState.mideleg := mideleg.rdata.asUInt diffCSRState.medeleg := medeleg.rdata.asUInt val diffDebugMode = DifftestModule(new DiffDebugMode) diffDebugMode.coreid := hartId diffDebugMode.debugMode := debugMode diffDebugMode.dcsr := dcsr.rdata.asUInt diffDebugMode.dpc := dpc.rdata.asUInt diffDebugMode.dscratch0 := dscratch0.rdata.asUInt diffDebugMode.dscratch1 := dscratch1.rdata.asUInt val diffTriggerCSRState = DifftestModule(new DiffTriggerCSRState) diffTriggerCSRState.coreid := hartId diffTriggerCSRState.tselect := tselect.rdata diffTriggerCSRState.tdata1 := tdata1.rdata diffTriggerCSRState.tinfo := tinfo.rdata diffTriggerCSRState.tcontrol := tcontrol.rdata val diffVecCSRState = DifftestModule(new DiffVecCSRState) diffVecCSRState.coreid := hartId diffVecCSRState.vstart := vstart.rdata.asUInt diffVecCSRState.vxsat := vcsr.vxsat.asUInt diffVecCSRState.vxrm := vcsr.vxrm.asUInt diffVecCSRState.vcsr := vcsr.rdata.asUInt diffVecCSRState.vl := RegNext(io.fromRob.commit.vl) diffVecCSRState.vtype := vtype.rdata.asUInt diffVecCSRState.vlenb := vlenb.rdata.asUInt val diffFpCSRState = DifftestModule(new DiffFpCSRState) diffFpCSRState.coreid := hartId diffFpCSRState.fcsr := fcsr.rdata.asUInt val diffHCSRState = DifftestModule(new DiffHCSRState) diffHCSRState.coreid := hartId diffHCSRState.virtMode := privState.V.asBool diffHCSRState.mtval2 := mtval2.rdata.asUInt diffHCSRState.mtinst := mtinst.rdata.asUInt diffHCSRState.hstatus := hstatus.rdata.asUInt diffHCSRState.hideleg := hideleg.rdata.asUInt diffHCSRState.hedeleg := hedeleg.rdata.asUInt diffHCSRState.hcounteren := hcounteren.rdata.asUInt diffHCSRState.htval := htval.rdata.asUInt diffHCSRState.htinst := htinst.rdata.asUInt diffHCSRState.hgatp := hgatp.rdata.asUInt diffHCSRState.vsstatus := vsstatus.rdata.asUInt diffHCSRState.vstvec := vstvec.rdata.asUInt diffHCSRState.vsepc := vsepc.rdata.asUInt diffHCSRState.vscause := vscause.rdata.asUInt diffHCSRState.vstval := vstval.rdata.asUInt diffHCSRState.vsatp := vsatp.rdata.asUInt diffHCSRState.vsscratch := vsscratch.rdata.asUInt } } trait IpIeAliasConnect { self: NewCSR with MachineLevel with SupervisorLevel with VirtualSupervisorLevel with HypervisorLevel => mip.fromMvip := mvip.toMip mip.fromSip := sip.toMip mip.fromVSip := vsip.toMip mvip.fromMip := mip.toMvip mvip.fromSip := sip.toMvip mvip.fromVSip := vsip.toMvip hvip.fromMip := mip.toHvip hvip.fromHip := hip.toHvip hvip.fromVSip := vsip.toHvip mie.fromHie := hie.toMie mie.fromSie := sie.toMie mie.fromVSie := vsie.toMie sie.fromVSie := vsie.toSie } object NewCSRMain extends App { val (config, firrtlOpts, firtoolOpts) = ArgParser.parse( args :+ "--disable-always-basic-diff" :+ "--dump-fir" :+ "--fpga-platform" :+ "--target" :+ "verilog") val defaultConfig = config.alterPartial({ // Get XSCoreParams and pass it to the "small module" case XSCoreParamsKey => config(XSTileKey).head }) Generator.execute( firrtlOpts :+ "--full-stacktrace" :+ "--target-dir" :+ "backend", new NewCSR()(defaultConfig), firtoolOpts ) println("done") }