package xiangshan.backend.fu.NewCSR import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import top.{ArgParser, Generator} import xiangshan.{HasXSParameter, XSCoreParamsKey, XSTileKey} import xiangshan.backend.fu.NewCSR.CSRDefines.{PrivMode, VirtMode} import xiangshan.backend.fu.NewCSR.CSREvents.{CSREvents, EventUpdatePrivStateOutput, MretEventSinkBundle, SretEventSinkBundle, TrapEntryEventInput, TrapEntryHSEventSinkBundle, TrapEntryMEventSinkBundle, TrapEntryVSEventSinkBundle} 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 = 41 // only Sv39 and Sv39x4 final val XLEN = 64 // Todo: use XSParams } 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 HasInstCommitBundle with SupervisorMachineAliasConnect with CSREvents { import CSRConfig._ val io = IO(new Bundle { val w = Flipped(ValidIO(new Bundle { val addr = UInt(12.W) val data = UInt(64.W) })) val rAddr = Input(UInt(12.W)) val rData = Output(UInt(64.W)) val trap = Flipped(ValidIO(new Bundle { val toPRVM = PrivMode() val toV = VirtMode() val tpc = UInt(VaddrMaxWidth.W) val isInterrupt = Bool() val trapVec = UInt(64.W) val isCrossPageIPF = Bool() })) val fromMem = Input(new Bundle { val excpVA = UInt(VaddrMaxWidth.W) val excpGPA = UInt(VaddrMaxWidth.W) // Todo: use guest physical address width }) val tret = Flipped(ValidIO(new Bundle { val toPRVM = PrivMode() val toV = VirtMode() })) val out = new Bundle { val targetPc = UInt(VaddrMaxWidth.W) } }) val toAIA = IO(Output(new CSRToAIABundle)) val fromAIA = IO(Flipped(Output(new AIAToCSRBundle))) dontTouch(toAIA) dontTouch(fromAIA) toAIA := DontCare val addr = io.w.bits.addr val data = io.w.bits.data val wen = io.w.valid val PRVM = RegInit(PrivMode(0), PrivMode.M) val V = RegInit(VirtMode(0), VirtMode.Off) val trap = io.trap.valid val trapToPRVM = io.trap.bits.toPRVM val trapToV = io.trap.bits.toV val trapToM = trapToPRVM === PrivMode.M val trapToHS = trapToPRVM === PrivMode.S && trapToV === VirtMode.Off val trapToHU = trapToPRVM === PrivMode.U && trapToV === VirtMode.Off val trapToVS = trapToPRVM === PrivMode.S && trapToV === VirtMode.On val trapToVU = trapToPRVM === PrivMode.U && trapToV === VirtMode.On val tret = io.tret.valid val tretPRVM = io.tret.bits.toPRVM val tretV = io.tret.bits.toV val isSret = tret && tretPRVM === PrivMode.S val isMret = tret && tretPRVM === PrivMode.M var csrRwMap = machineLevelCSRMap ++ supervisorLevelCSRMap ++ hypervisorCSRMap ++ virtualSupervisorCSRMap ++ unprivilegedCSRMap ++ aiaCSRMap val csrMods = machineLevelCSRMods ++ supervisorLevelCSRMods ++ hypervisorCSRMods ++ virtualSupervisorCSRMods ++ unprivilegedCSRMods ++ aiaCSRMods for ((id, (wBundle, _)) <- csrRwMap) { wBundle.wen := wen && addr === id.U wBundle.wdata := data } io.rData := Mux1H(csrRwMap.map { case (id, (_, rBundle)) => (io.rAddr === id.U) -> rBundle.asUInt }) csrMods.foreach { mod => mod match { case m: HypervisorBundle => m.hstatus := hstatus.regOut m.hvip := hvip.regOut m.hideleg := hideleg.regOut m.hedeleg := hedeleg.regOut m.hgeip := hgeip.regOut m.hgeie := hgeie.regOut m.hip := hip.regOut m.hie := hie.regOut case _ => } mod match { case m: HasMachineInterruptBundle => m.mvien := mvien.regOut m.mvip := mvip.regOut m.mip := mip.regOut m.mie := mie.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 case _ => } mod match { case m: HasInstCommitBundle => m.commitValid := this.commitValid m.commitInstNum := this.commitInstNum case _ => } mod match { case m: TrapEntryMEventSinkBundle => m.trapToM := trapEntryMEvent.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: SretEventSinkBundle => m.retFromS := sretEvent.out case _ => } } csrMods.foreach { mod => mod.commonIn.status := mstatus.mstatus mod.commonIn.prvm := PRVM mod.commonIn.v := V mod.commonIn.hstatus := hstatus.rdata println(s"${mod.modName}: ") println(mod.dumpFields) } trapEntryMEvent.valid := trapToM trapEntryHSEvent.valid := trapToHS trapEntryVSEvent.valid := trapToVS Seq(trapEntryMEvent, trapEntryHSEvent, trapEntryVSEvent).foreach { mod => mod.in match { case in: TrapEntryEventInput => in.causeNO := DontCare in.trapPc := io.trap.bits.tpc in.isCrossPageIPF := io.trap.bits.isCrossPageIPF in.iMode.PRVM := PRVM in.iMode.V := V in.dMode.PRVM := Mux(mstatus.rdata.MPRV.asBool, mstatus.rdata.MPP, PRVM) in.dMode.V := Mux(mstatus.rdata.MPRV.asBool, mstatus.rdata.MPV, V) in.privState.PRVM := PRVM in.privState.V := V in.mstatus := mstatus.regOut in.hstatus := hstatus.regOut in.sstatus := mstatus.sstatus in.vsstatus := vsstatus.regOut in.satp := satp.rdata in.vsatp := vsatp.rdata in.memExceptionVAddr := io.fromMem.excpVA in.memExceptionGPAddr := io.fromMem.excpGPA } } mretEvent.valid := isMret mretEvent.in match { case in => in.mstatus := mstatus.regOut in.mepc := mepc.regOut } sretEvent.valid := isSret sretEvent.in match { case in => in.privState.PRVM := PRVM in.privState.V := V in.sstatus := mstatus.sstatus in.hstatus := hstatus.regOut in.vsstatus := vsstatus.regOut in.sepc := sepc.regOut in.vsepc := vsepc.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) } } ) io.out.targetPc := Mux1H(Seq( mretEvent.out.targetPc.valid -> mretEvent.out.targetPc.bits.asUInt )) } trait SupervisorMachineAliasConnect { self: NewCSR with MachineLevel with SupervisorLevel => mip.fromMvip := mvip.toMip mip.fromSip := sip.toMip mie.fromSie := sie.toMie } 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") }