Skip to content

Commit

Permalink
feat(Ss/Smdbltrp) : Support RISC-V Ss/Smdbltrp Extension (#3789)
Browse files Browse the repository at this point in the history
* NEMU commit: 066cb1f1c61feb21153399c26ca393dfb3a560d7
* NEMU configs:
  * riscv64-xs-ref_defconfig
  * riscv64-dual-xs-ref_defconfig

Including:
  * fix(format): adjust code format and add one config (OpenXiangShan/NEMU#603)
  * fix(vfredusum): set xstatus.fs and xstatus.vs dirty (OpenXiangShan/NEMU#605)
  * fix(vf): do not set dirtyFs for some instructions (OpenXiangShan/NEMU#606)
  * feat(trigger): add trigger support for rva.
  * configs(xs): open Sm/sdbltrp extension and add MDT_INIT config (OpenXiangShan/NEMU#604)

---

* spike commit: c0b18d3913d8ceac83743a053a7dbd2fb8716c83
* spike config: CPU=XIANGSHAN

Including:
* fix(rva, trigger): For rva instr, raise BP from trigger prior to misaligned.
* fix(Makefile): Increase maxdepth for finding .h files.
* fix(tdata1): CPU_XIANGSHAN do not implement hit bit in tdata1.
* fix(icount): place the read before the return of the detect_icount_match.
  • Loading branch information
lewislzh authored Oct 29, 2024
1 parent 189d8d0 commit 6808b80
Show file tree
Hide file tree
Showing 16 changed files with 197 additions and 45 deletions.
2 changes: 1 addition & 1 deletion ready-to-run
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ object CSRBundles {
val STCE = RO( 63) .withReset(0.U) // Sstc Enable
val PBMTE = RO( 62) .withReset(0.U) // Svpbmt Enable
val ADUE = RO( 61) .withReset(0.U) // Svadu extension Enable
val DTE = RO( 59) .withReset(0.U) // Ssdbltrp extension Enable
val PMM = RO(33, 32) .withReset(0.U) // Smnpm extension
val CBZE = RW( 7) .withReset(1.U) // Zicboz extension
val CBCFE = RW( 6) .withReset(1.U) // Zicbom extension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class TrapEntryEventInput(implicit val p: Parameters) extends Bundle with HasXSP
val isFetchMalAddr = Input(Bool())
val isFetchBkpt = Input(Bool())
val trapIsForVSnonLeafPTE = Input(Bool())
val hasDTExcp = Input(Bool())

// always current privilege
val iMode = Input(new PrivState())
Expand All @@ -136,6 +137,9 @@ class TrapEntryEventInput(implicit val p: Parameters) extends Bundle with HasXSP
val hstatus = Input(new HstatusBundle)
val sstatus = Input(new SstatusBundle)
val vsstatus = Input(new SstatusBundle)
// envcfg
val menvcfg = Input(new MEnvCfg)
val henvcfg = Input(new HEnvCfg)

val pcFromXtvec = Input(UInt(XLEN.W))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import xiangshan.AddrTransType

class MNretEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase {
val mnstatus = ValidIO((new MnstatusBundle).addInEvent(_.MNPP, _.MNPV, _.NMIE))
val mstatus = ValidIO((new MstatusBundle).addInEvent(_.MPRV))
val mstatus = ValidIO((new MstatusBundle).addInEvent(_.MPRV, _.MDT, _.SDT))
val vsstatus = ValidIO((new SstatusBundle).addInEvent(_.SDT))
val targetPc = ValidIO(new TargetPCBundle)
}

Expand All @@ -26,6 +27,7 @@ class MNretEventInput extends Bundle {
val satp = Input(new SatpBundle)
val vsatp = Input(new SatpBundle)
val hgatp = Input(new HgatpBundle)
val vsstatus = Input(new SstatusBundle)
}

class MNretEventModule(implicit p: Parameters) extends Module with CSREventBase {
Expand All @@ -49,18 +51,29 @@ class MNretEventModule(implicit p: Parameters) extends Module with CSREventBase
sv48x4 = nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv48x4
)

val outPrivState = Wire(new PrivState)
outPrivState.PRVM := in.mnstatus.MNPP
outPrivState.V := Mux(in.mnstatus.MNPP === PrivMode.M, VirtMode.Off.asUInt, in.mnstatus.MNPV.asUInt)

val mnretToM = outPrivState.isModeM
val mnretToS = outPrivState.isModeHS
val mnretToVU = outPrivState.isModeVU

out := DontCare

out.privState.valid := valid
out.mnstatus .valid := valid
out.targetPc .valid := valid

out.privState.bits.PRVM := in.mnstatus.MNPP
out.privState.bits.V := Mux(in.mnstatus.MNPP === PrivMode.M, VirtMode.Off.asUInt, in.mnstatus.MNPV.asUInt)
out.privState.bits := outPrivState
out.mnstatus.bits.MNPP := PrivMode.U
out.mnstatus.bits.MNPV := VirtMode.Off.asUInt
out.mnstatus.bits.NMIE := 1.U
out.mstatus.bits.MPRV := Mux(in.mnstatus.MNPP =/= PrivMode.M, 0.U, in.mstatus.MPRV.asUInt)
// clear MDT when mnret to below M
out.mstatus.bits.MDT := Mux(mnretToM, in.mstatus.MDT.asBool, 0.U)
out.mstatus.bits.SDT := Mux(mnretToM || mnretToS, in.mstatus.SDT.asBool, 0.U)
out.vsstatus.bits.SDT := Mux(mnretToVU, 0.U, in.vsstatus.SDT.asBool)
out.targetPc.bits.pc := in.mnepc.asUInt
out.targetPc.bits.raiseIPF := instrAddrTransType.checkPageFault(in.mnepc.asUInt)
out.targetPc.bits.raiseIAF := instrAddrTransType.checkAccessFault(in.mnepc.asUInt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import xiangshan.AddrTransType


class MretEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase {
val mstatus = ValidIO((new MstatusBundle).addInEvent(_.MPP, _.MPV, _.MIE, _.MPIE, _.MPRV))
val mstatus = ValidIO((new MstatusBundle).addInEvent(_.MPP, _.MPV, _.MIE, _.MPIE, _.MPRV, _.MDT, _.SDT))
val vsstatus = ValidIO((new SstatusBundle).addInEvent(_.SDT))
val targetPc = ValidIO(new TargetPCBundle)
}

class MretEventInput extends Bundle {
val mstatus = Input(new MstatusBundle)
val vsstatus = Input(new SstatusBundle)
val mepc = Input(new Epc())
val satp = Input(new SatpBundle)
val vsatp = Input(new SatpBundle)
Expand All @@ -46,20 +48,33 @@ class MretEventModule(implicit p: Parameters) extends Module with CSREventBase {
sv39x4 = nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv39x4,
sv48x4 = nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv48x4
)
val outPrivState = Wire(new PrivState)
outPrivState.PRVM := in.mstatus.MPP
outPrivState.V := Mux(in.mstatus.MPP === PrivMode.M, VirtMode.Off.asUInt, in.mstatus.MPV.asUInt)

val mretToM = outPrivState.isModeM
val mretToS = outPrivState.isModeHS
val mretToVu = outPrivState.isModeVU

out := DontCare

out.privState.valid := valid
out.mstatus .valid := valid
out.targetPc .valid := valid

out.privState.bits.PRVM := in.mstatus.MPP
out.privState.bits.V := Mux(in.mstatus.MPP === PrivMode.M, VirtMode.Off.asUInt, in.mstatus.MPV.asUInt)
out.privState.bits := outPrivState
out.mstatus.bits.MPP := PrivMode.U
out.mstatus.bits.MPV := VirtMode.Off.asUInt
out.mstatus.bits.MIE := in.mstatus.MPIE
out.mstatus.bits.MPIE := 1.U
out.mstatus.bits.MPRV := Mux(in.mstatus.MPP =/= PrivMode.M, 0.U, in.mstatus.MPRV.asUInt)
// clear MDT when return mret always execute in M mode
out.mstatus.bits.MDT := 0.U
// clear sstatus.SDT when return mode below M and HS
out.mstatus.bits.SDT := Mux(mretToM || mretToS, in.mstatus.SDT.asBool, 0.U)
// clear vsstatus.SDT when return to VU
out.vsstatus.bits.SDT := Mux(mretToVu, 0.U, in.vsstatus.SDT.asBool)

out.targetPc.bits.pc := in.mepc.asUInt
out.targetPc.bits.raiseIPF := instrAddrTransType.checkPageFault(in.mepc.asUInt)
out.targetPc.bits.raiseIAF := instrAddrTransType.checkAccessFault(in.mepc.asUInt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ import xiangshan.AddrTransType

class SretEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase {
// Todo: write sstatus instead of mstatus
val mstatus = ValidIO((new MstatusBundle).addInEvent(_.SIE, _.SPIE, _.SPP, _.MPRV))
val mstatus = ValidIO((new MstatusBundle).addInEvent(_.SIE, _.SPIE, _.SPP, _.MPRV, _.MDT, _.SDT))
val hstatus = ValidIO((new HstatusBundle).addInEvent(_.SPV))
val vsstatus = ValidIO((new SstatusBundle).addInEvent(_.SIE, _.SPIE, _.SPP))
val vsstatus = ValidIO((new SstatusBundle).addInEvent(_.SIE, _.SPIE, _.SPP, _.SDT))
val targetPc = ValidIO(new TargetPCBundle)
}

class SretEventInput extends Bundle {
val privState = Input(new PrivState)
val sstatus = Input(new SstatusBundle)
val mstatus = Input(new MstatusBundle)
val hstatus = Input(new HstatusBundle)
val vsstatus = Input(new SstatusBundle)
val sepc = Input(new Epc())
Expand Down Expand Up @@ -53,45 +53,62 @@ class SretEventModule(implicit p: Parameters) extends Module with CSREventBase {
sv48x4 = nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv48x4
)

private val sretInHSorM = in.privState.isModeM || in.privState.isModeHS
private val sretInM = in.privState.isModeM
private val sretInHS = in.privState.isModeHS
private val sretInHSorM = sretInM || sretInHS
private val sretInVS = in.privState.isModeVS

private val xepc = Mux1H(Seq(
sretInHSorM -> in.sepc,
sretInVS -> in.vsepc,
)).asUInt

out := DontCare

out.privState.valid := valid
out.targetPc .valid := valid

out.privState.bits.PRVM := Mux1H(Seq(
private val outPrivState = Wire(new PrivState)
outPrivState.PRVM := Mux1H(Seq(
// SPP is not PrivMode enum type, so asUInt
sretInHSorM -> in.sstatus.SPP.asUInt,
sretInHSorM -> in.mstatus.SPP.asUInt,
sretInVS -> in.vsstatus.SPP.asUInt,
))
out.privState.bits.V := Mux1H(Seq(
outPrivState.V := Mux1H(Seq(
sretInHSorM -> in.hstatus.SPV,
sretInVS -> in.privState.V, // keep
))

private val sretToVU = outPrivState.isModeVU
private val sretToVS = outPrivState.isModeVS
private val sretToU = outPrivState.isModeHU

out := DontCare

out.privState.valid := valid
out.targetPc .valid := valid

out.privState.bits := outPrivState

// hstatus
out.hstatus.valid := valid && sretInHSorM
out.hstatus.bits.SPV := VirtMode.Off

// sstatus
out.mstatus.valid := valid && sretInHSorM
out.mstatus.bits.SPP := PrivMode.U.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
out.mstatus.bits.SIE := in.sstatus.SPIE
out.mstatus.bits.SIE := in.mstatus.SPIE
out.mstatus.bits.SPIE := 1.U
out.mstatus.bits.MPRV := 0.U // sret will always leave M mode
out.mstatus.bits.MDT := Mux(sretInM, 0.U, in.mstatus.MDT.asBool) // when execute return in M mode, set MDT 0
out.mstatus.bits.SDT := MuxCase(in.mstatus.SDT.asBool, Seq(
sretInHS -> 0.U, // sret will alway leave M mode
(sretInM && (sretToU || sretToVS || sretToVU)) -> 0.U
))


// vsstatus
out.vsstatus.valid := valid && sretInVS
out.vsstatus.bits.SPP := PrivMode.U.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
out.vsstatus.bits.SIE := in.vsstatus.SPIE
out.vsstatus.bits.SPIE := 1.U
out.vsstatus.bits.SDT := Mux(sretToVU || sretInVS, 0.U, in.vsstatus.SDT.asBool) // clear SDT when return to VU or sret in vs

out.targetPc.bits.pc := xepc
out.targetPc.bits.raiseIPF := instrAddrTransType.checkPageFault(xepc)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import xiangshan.AddrTransType
class TrapEntryHSEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase {

// Todo: use sstatus instead of mstatus
val mstatus = ValidIO((new MstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE))
val mstatus = ValidIO((new MstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE, _.SDT))
val hstatus = ValidIO((new HstatusBundle ).addInEvent(_.SPV, _.SPVP, _.GVA))
val sepc = ValidIO((new Epc ).addInEvent(_.epc))
val scause = ValidIO((new CauseBundle ).addInEvent(_.Interrupt, _.ExceptionCode))
Expand Down Expand Up @@ -124,6 +124,7 @@ class TrapEntryHSEventModule(implicit val p: Parameters) extends Module with CSR
out.mstatus.bits.SPP := current.privState.PRVM.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
out.mstatus.bits.SPIE := current.sstatus.SIE
out.mstatus.bits.SIE := 0.U
out.mstatus.bits.SDT := in.menvcfg.DTE.asBool // when DTE open set SDT to 1, else SDT is readonly 0
// hstatus
out.hstatus.bits.SPV := current.privState.V
// SPVP is not PrivMode enum type, so asUInt and shrink the width
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import xiangshan.AddrTransType

class TrapEntryMEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase {

val mstatus = ValidIO((new MstatusBundle ).addInEvent(_.MPV, _.MPP, _.GVA, _.MPIE, _.MIE))
val mstatus = ValidIO((new MstatusBundle ).addInEvent(_.MPV, _.MPP, _.GVA, _.MPIE, _.MIE, _.MDT))
val mepc = ValidIO((new Epc ).addInEvent(_.epc))
val mcause = ValidIO((new CauseBundle ).addInEvent(_.Interrupt, _.ExceptionCode))
val mtval = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
Expand All @@ -32,6 +32,7 @@ class TrapEntryMEventModule(implicit val p: Parameters) extends Module with CSRE
private val satp = current.satp
private val vsatp = current.vsatp
private val hgatp = current.hgatp
private val isDTExcp = current.hasDTExcp

private val highPrioTrapNO = in.causeNO.ExceptionCode.asUInt
private val isException = !in.causeNO.Interrupt.asBool
Expand Down Expand Up @@ -96,6 +97,8 @@ class TrapEntryMEventModule(implicit val p: Parameters) extends Module with CSRE
(isLSGuestExcp ) -> trapMemGPA,
))

private val precause = Cat(isInterrupt, highPrioTrapNO)

out := DontCare

out.privState.valid := valid
Expand All @@ -113,11 +116,12 @@ class TrapEntryMEventModule(implicit val p: Parameters) extends Module with CSRE
out.mstatus.bits.GVA := tvalFillGVA
out.mstatus.bits.MPIE := current.mstatus.MIE
out.mstatus.bits.MIE := 0.U
out.mstatus.bits.MDT := 1.U
out.mepc.bits.epc := Mux(isFetchMalAddr, in.fetchMalTval(63, 1), trapPC(63, 1))
out.mcause.bits.Interrupt := isInterrupt
out.mcause.bits.ExceptionCode := highPrioTrapNO
out.mcause.bits.ExceptionCode := Mux(isDTExcp, ExceptionNO.EX_DT.U, highPrioTrapNO)
out.mtval.bits.ALL := Mux(isFetchMalAddr, in.fetchMalTval, tval)
out.mtval2.bits.ALL := tval2 >> 2
out.mtval2.bits.ALL := Mux(isDTExcp, precause, tval2 >> 2)
out.mtinst.bits.ALL := Mux(isFetchGuestExcp && in.trapIsForVSnonLeafPTE || isLSGuestExcp && in.memExceptionIsForVSnonLeafPTE, 0x3000.U, 0.U)
out.targetPc.bits.pc := in.pcFromXtvec
out.targetPc.bits.raiseIPF := false.B
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import xiangshan.AddrTransType

class TrapEntryVSEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase {

val vsstatus = ValidIO((new SstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE))
val vsstatus = ValidIO((new SstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE, _.SDT))
val vsepc = ValidIO((new Epc ).addInEvent(_.epc))
val vscause = ValidIO((new CauseBundle ).addInEvent(_.Interrupt, _.ExceptionCode))
val vstval = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
Expand Down Expand Up @@ -122,6 +122,7 @@ class TrapEntryVSEventModule(implicit val p: Parameters) extends Module with CSR
out.vsstatus.bits.SPP := current.privState.PRVM.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
out.vsstatus.bits.SPIE := current.vsstatus.SIE
out.vsstatus.bits.SIE := 0.U
out.vsstatus.bits.SDT := in.henvcfg.DTE.asBool // when DTE open set SDT to 1, else SDT is readonly 0
// SPVP is not PrivMode enum type, so asUInt and shrink the width
out.vsepc.bits.epc := Mux(isFetchMalAddr, in.fetchMalTval(63, 1), trapPC(63, 1))
out.vscause.bits.Interrupt := isInterrupt
Expand Down
15 changes: 11 additions & 4 deletions src/main/scala/xiangshan/backend/fu/NewCSR/HypervisorLevel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,16 @@ trait HypervisorLevel { self: NewCSR =>
.setAddr(CSRs.hvictl)

val henvcfg = Module(new CSRModule("Henvcfg", new HEnvCfg) with HasHypervisorEnvBundle {
when (!menvcfg.STCE.asBool) {
when(!menvcfg.STCE) {
regOut.STCE := 0.U
}
when (!menvcfg.PBMTE) {
when(!menvcfg.PBMTE) {
regOut.PBMTE := 0.U
}
})
.setAddr(CSRs.henvcfg)
when(!menvcfg.DTE) {
regOut.DTE := 0.U
}
}).setAddr(CSRs.henvcfg)

val htval = Module(new CSRModule("Htval", new XtvalBundle) with TrapEntryHSEventSinkBundle)
.setAddr(CSRs.htval)
Expand Down Expand Up @@ -340,6 +342,11 @@ class HEnvCfg extends EnvCfg {
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)
}
}

trait HypervisorBundle { self: CSRModule[_] =>
Expand Down
26 changes: 24 additions & 2 deletions src/main/scala/xiangshan/backend/fu/NewCSR/MachineLevel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -452,12 +452,14 @@ class MstatusBundle extends CSRBundle {
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
)
Expand All @@ -471,6 +473,7 @@ class MstatusModule(implicit override val p: Parameters) extends CSRModule("MSta
with MNretEventSinkBundle
with SretEventSinkBundle
with HasRobCommitBundle
with HasMachineEnvBundle
{
val mstatus = IO(Output(bundle))
val sstatus = IO(Output(new SstatusBundle))
Expand All @@ -496,9 +499,23 @@ class MstatusModule(implicit override val p: Parameters) extends CSRModule("MSta
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 writeSDT = Wire(Bool())
writeSDT := Mux(this.menvcfg.DTE.asBool, (w.wdataFields.SDT && w.wen) || (wAliasSstatus.wdataFields.SDT && wAliasSstatus.wen), 0.U)
when (!this.menvcfg.DTE) {
regOut.SDT := false.B
}
// SDT and SIE is the same as MDT and MIE
when (writeSDT) {
reg.SIE := false.B
}
// read connection
mstatus :|= reg
mstatus :|= regOut
sstatus := mstatus
rdata := mstatus.asUInt
sstatusRdata := sstatus.asUInt
Expand Down Expand Up @@ -628,6 +645,11 @@ class MEnvCfg extends EnvCfg {
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 {
Expand Down
Loading

0 comments on commit 6808b80

Please sign in to comment.