Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vtype: fix x-propagation and vtype walk value when using snapshot #3001

Merged
merged 4 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/main/scala/xiangshan/backend/Backend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,8 @@ class BackendImp(override val wrapper: Backend)(implicit p: Parameters) extends
csrio.fpu.dirty_fs := ctrlBlock.io.robio.csr.dirty_fs
csrio.vpu <> 0.U.asTypeOf(csrio.vpu) // Todo

val vsetvlVType = intExuBlock.io.vtype.getOrElse(0.U.asTypeOf(new VType))
val fromVsetVType = intExuBlock.io.vtype.getOrElse(0.U.asTypeOf((Valid(new VType))))
val vsetvlVType = RegEnable(fromVsetVType.bits, 0.U.asTypeOf(new VType), fromVsetVType.valid)
ctrlBlock.io.robio.vsetvlVType := vsetvlVType

val debugVconfig = dataPath.io.debugVconfig match {
Expand Down
5 changes: 5 additions & 0 deletions src/main/scala/xiangshan/backend/CtrlBlock.scala
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,12 @@ class CtrlBlockImp(
decode.io.commitVType := rob.io.toDecode.commitVType
decode.io.walkVType := rob.io.toDecode.walkVType

// spec vtype, from vtypegen to vtpebuffer
rob.io.fromDecode.lastSpecVType := decode.io.lastSpecVType
rob.io.fromDecode.specVtype := decode.io.specVtype

decode.io.redirect := s1_s3_redirect.valid || s2_s4_pendingRedirectValid
decode.io.vtypeRedirect := s1_s3_redirect.valid

decode.io.in.zip(io.frontend.cfVec).foreach { case (decodeIn, frontendCf) =>
decodeIn.valid := frontendCf.valid
Expand Down
7 changes: 6 additions & 1 deletion src/main/scala/xiangshan/backend/decode/DecodeStage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class DecodeStage(implicit p: Parameters) extends XSModule
val io = IO(new Bundle() {
val redirect = Input(Bool())
val canAccept = Output(Bool())
val vtypeRedirect = Input(Bool())
// from Ibuffer
val in = Vec(DecodeWidth, Flipped(DecoupledIO(new StaticInst)))
// to Rename
Expand All @@ -64,6 +65,8 @@ class DecodeStage(implicit p: Parameters) extends XSModule
val out = new StallReasonIO(DecodeWidth)
}
val vsetvlVType = Input(VType())
val lastSpecVType = (Valid(new VType))
val specVtype = Output(new VType)
})

// io alias
Expand Down Expand Up @@ -104,10 +107,12 @@ class DecodeStage(implicit p: Parameters) extends XSModule
inst.bits := io.in(i).bits.instr
}
vtypeGen.io.canUpdateVType := decoderComp.io.in.fire && decoderComp.io.in.bits.simpleDecodedInst.isVset
vtypeGen.io.redirect := io.redirect
vtypeGen.io.redirect := io.vtypeRedirect
vtypeGen.io.commitVType := io.commitVType
vtypeGen.io.walkVType := io.walkVType
vtypeGen.io.vsetvlVType := io.vsetvlVType
io.specVtype := vtypeGen.io.specVtype
io.lastSpecVType := vtypeGen.io.lastSpecVType

//Comp 1
decoderComp.io.redirect := io.redirect
Expand Down
19 changes: 18 additions & 1 deletion src/main/scala/xiangshan/backend/decode/VTypeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class VTypeGen(implicit p: Parameters) extends XSModule{
val vtype = Flipped(Valid(new VType))
val hasVsetvl = Input(Bool())
}
val lastSpecVType = (Valid(new VType))
val specVtype = Output(new VType)
})
private val instValidVec = io.insts.map(_.valid)
private val instFieldVec = io.insts.map(_.bits.asTypeOf(new XSInstBitFields))
Expand All @@ -37,12 +39,15 @@ class VTypeGen(implicit p: Parameters) extends XSModule{

private val vtypeArch = RegInit(0.U.asTypeOf(new VType))
private val vtypeSpec = RegInit(0.U.asTypeOf(new VType))
private val lastSpecVType = RegInit(0.U.asTypeOf(new ValidIO(VType())))

private val vtypeArchNext = WireInit(vtypeArch)
private val vtypeSpecNext = WireInit(vtypeSpec)
private val lastSpecVTypeNext = WireInit(lastSpecVType)

vtypeArch := vtypeArchNext
vtypeSpec := vtypeSpecNext
lastSpecVType := lastSpecVTypeNext

private val instVType: InstVType = firstVsetInstField.ZIMM_VTYPE.asTypeOf(new InstVType)
private val vtypei: VType = VType.fromInstVType(instVType)
Expand All @@ -54,24 +59,36 @@ class VTypeGen(implicit p: Parameters) extends XSModule{

private val vtypeNew = vsetModule.io.out.vconfig.vtype

when(io.commitVType.vtype.valid) {
when(io.commitVType.hasVsetvl) {
vtypeArchNext := io.vsetvlVType
}.elsewhen(io.commitVType.vtype.valid) {
vtypeArchNext := io.commitVType.vtype.bits
}

private val inHasVset = isVsetVec.asUInt.orR

when(io.commitVType.hasVsetvl) {
// when vsetvl instruction commit, also update vtypeSpec, because vsetvl flush pipe
lastSpecVTypeNext.valid := true.B
lastSpecVTypeNext.bits := vtypeSpec
vtypeSpecNext := io.vsetvlVType
}.elsewhen(io.walkVType.valid) {
lastSpecVTypeNext.valid := false.B
vtypeSpecNext := io.walkVType.bits
}.elsewhen(io.redirect) {
lastSpecVTypeNext.valid := false.B
vtypeSpecNext := vtypeArch
}.elsewhen(inHasVset && io.canUpdateVType) {
lastSpecVTypeNext.valid := true.B
lastSpecVTypeNext.bits := vtypeSpec
vtypeSpecNext := vtypeNew
}.otherwise {
lastSpecVTypeNext.valid := false.B
}

io.vtype := vtypeSpec
io.specVtype := vtypeSpec
io.lastSpecVType := lastSpecVType

// just make verilog more readable
dontTouch(isVsetVec)
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/xiangshan/backend/exu/ExeUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class ExeUnitIO(params: ExeUnitParams)(implicit p: Parameters) extends XSBundle
val fenceio = OptionWrapper(params.hasFence, new FenceIO)
val frm = OptionWrapper(params.needSrcFrm, Input(Frm()))
val vxrm = OptionWrapper(params.needSrcVxrm, Input(Vxrm()))
val vtype = OptionWrapper(params.writeVConfig, new VType)
val vtype = OptionWrapper(params.writeVConfig, (Valid(new VType)))
val vlIsZero = OptionWrapper(params.writeVConfig, Output(Bool()))
val vlIsVlmax = OptionWrapper(params.writeVConfig, Output(Bool()))
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/xiangshan/backend/exu/ExuBlock.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class ExuBlockIO(implicit p: Parameters, params: SchdBlockParams) extends XSBund
val fenceio = OptionWrapper(params.hasFence, new FenceIO)
val frm = OptionWrapper(params.needSrcFrm, Input(Frm()))
val vxrm = OptionWrapper(params.needSrcVxrm, Input(Vxrm()))
val vtype = OptionWrapper(params.writeVConfig, new VType)
val vtype = OptionWrapper(params.writeVConfig, (Valid(new VType)))
val vlIsZero = OptionWrapper(params.writeVConfig, Output(Bool()))
val vlIsVlmax = OptionWrapper(params.writeVConfig, Output(Bool()))
}
2 changes: 1 addition & 1 deletion src/main/scala/xiangshan/backend/fu/FuncUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class FuncUnitIO(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
val fenceio = OptionWrapper(cfg.isFence, new FenceIO)
val frm = OptionWrapper(cfg.needSrcFrm, Input(UInt(3.W)))
val vxrm = OptionWrapper(cfg.needSrcVxrm, Input(UInt(2.W)))
val vtype = OptionWrapper(cfg.writeVConfig, new VType)
val vtype = OptionWrapper(cfg.writeVConfig, (Valid(new VType)))
val vlIsZero = OptionWrapper(cfg.writeVConfig, Output(Bool()))
val vlIsVlmax = OptionWrapper(cfg.writeVConfig, Output(Bool()))
}
Expand Down
6 changes: 4 additions & 2 deletions src/main/scala/xiangshan/backend/fu/wrapper/VSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ class VSetRiWvf(cfg: FuConfig)(implicit p: Parameters) extends VSetBase(cfg) {

out.res.data := vsetModule.io.out.vconfig.vl

if (cfg.writeVConfig) io.vtype.get := vsetModule.io.out.vconfig.vtype
if (cfg.writeVConfig) io.vtype.get.bits := vsetModule.io.out.vconfig.vtype
if (cfg.writeVConfig) io.vtype.get.valid := io.out.valid
if (cfg.writeVConfig) io.vlIsZero.get := vl === 0.U
if (cfg.writeVConfig) io.vlIsVlmax.get := vl === vlmax

Expand Down Expand Up @@ -106,7 +107,8 @@ class VSetRvfWvf(cfg: FuConfig)(implicit p: Parameters) extends VSetBase(cfg) {
out.res.data := Mux(vsetModule.io.out.vconfig.vtype.illegal, 0.U,
Mux(VSETOpType.isKeepVl(in.ctrl.fuOpType), oldVL, vsetModule.io.out.vconfig.vl))

if (cfg.writeVConfig) io.vtype.get := vsetModule.io.out.vconfig.vtype
if (cfg.writeVConfig) io.vtype.get.bits := vsetModule.io.out.vconfig.vtype
if (cfg.writeVConfig) io.vtype.get.valid := io.out.valid
if (cfg.writeVConfig) io.vlIsZero.get := res.vl === 0.U
if (cfg.writeVConfig) io.vlIsVlmax.get := res.vl === vlmax

Expand Down
7 changes: 6 additions & 1 deletion src/main/scala/xiangshan/backend/rob/Rob.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ class RobImp(override val wrapper: Rob)(implicit p: Parameters, params: BackendP
val hasVsetvl = Output(Bool())
}
}
val fromDecode = new Bundle {
val lastSpecVType = Flipped(Valid(new VType))
val specVtype = Input(new VType)
}
val readGPAMemAddr = ValidIO(new Bundle {
val ftqPtr = new FtqPtr()
val ftqOffset = UInt(log2Up(PredictWidth).W)
Expand Down Expand Up @@ -284,7 +288,8 @@ class RobImp(override val wrapper: Rob)(implicit p: Parameters, params: BackendP
io.toDecode.isResumeVType := vtypeBuffer.io.toDecode.isResumeVType
io.toDecode.commitVType := vtypeBuffer.io.toDecode.commitVType
io.toDecode.walkVType := vtypeBuffer.io.toDecode.walkVType

vtypeBuffer.io.fromDecode.lastSpecVType := io.fromDecode.lastSpecVType
vtypeBuffer.io.fromDecode.specVtype := io.fromDecode.specVtype

// When blockBackward instruction leaves Rob (commit or walk), hasBlockBackward should be set to false.B
// To reduce registers usage, for hasBlockBackward cases, we allow enqueue after ROB is empty.
Expand Down
30 changes: 23 additions & 7 deletions src/main/scala/xiangshan/backend/rob/VTypeBuffer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ class VTypeBufferIO(size: Int)(implicit p: Parameters) extends XSBundle {
}
})

val fromDecode = new Bundle {
val lastSpecVType = Flipped(Valid(new VType))
val specVtype = Input(new VType)
}

val status = Output(new Bundle {
val walkEnd = Bool()
})
Expand Down Expand Up @@ -103,7 +108,15 @@ class VTypeBuffer(size: Int)(implicit p: Parameters) extends XSModule with HasCi
private val walkPtrNext = Wire(new VTypeBufferPtr)
private val walkPtrVecNext = VecInit((0 until CommitWidth).map(x => walkPtrNext + x.U))

private val enqVType = WireInit(0.U.asTypeOf(new (VType)))
when(io.fromDecode.lastSpecVType.valid) {
enqVType := io.fromDecode.lastSpecVType.bits
}.otherwise {
enqVType := io.fromDecode.specVtype
}

private val walkPtrSnapshots = SnapshotGenerator(enqPtr, io.snpt.snptEnq, io.snpt.snptDeq, io.redirect.valid, io.snpt.flushVec)
private val walkVtypeSnapshots = SnapshotGenerator(enqVType, io.snpt.snptEnq, io.snpt.snptDeq, io.redirect.valid, io.snpt.flushVec)

private val robWalkEndReg = RegInit(false.B)
private val robWalkEnd = io.fromRob.walkEnd || robWalkEndReg
Expand Down Expand Up @@ -141,7 +154,7 @@ class VTypeBuffer(size: Int)(implicit p: Parameters) extends XSModule with HasCi

commitSize := Mux(io.redirect.valid && !io.snpt.useSnpt, 0.U, commitSizeNext)
spclWalkSize := spclWalkSizeNext
walkSize := Mux(io.redirect.valid && !io.snpt.useSnpt, 0.U, walkSizeNext)
walkSize := Mux(io.redirect.valid, 0.U, walkSizeNext)

walkPtrNext := MuxCase(walkPtr, Seq(
(state === s_idle && stateNext === s_walk) -> walkPtrSnapshots(snptSelect),
Expand All @@ -152,6 +165,8 @@ class VTypeBuffer(size: Int)(implicit p: Parameters) extends XSModule with HasCi

walkPtr := walkPtrNext

private val useSnapshot = (state === s_idle && stateNext === s_walk) || (state === s_walk && io.snpt.useSnpt && io.redirect.valid)

// update enq ptr
private val enqPtrNext = Mux(
state === s_walk && stateNext === s_idle,
Expand Down Expand Up @@ -204,9 +219,6 @@ class VTypeBuffer(size: Int)(implicit p: Parameters) extends XSModule with HasCi
private val infoVec = Wire(Vec(CommitWidth, VType()))
private val hasVsetvlVec = Wire(Vec(CommitWidth, Bool()))

private val isCommit = state === s_idle || state === s_spcl_walk
private val isWalk = state === s_walk || state === s_spcl_walk

for (i <- 0 until CommitWidth) {
commitValidVec(i) := state === s_idle && i.U < commitSize || state === s_spcl_walk && i.U < spclWalkSize
walkValidVec(i) := state === s_walk && i.U < walkSize || state === s_spcl_walk && i.U < spclWalkSize
Expand Down Expand Up @@ -254,7 +266,7 @@ class VTypeBuffer(size: Int)(implicit p: Parameters) extends XSModule with HasCi
true.B
)

private val decodeResumeVType = Reg(ValidIO(VType()))
private val decodeResumeVType = WireInit(0.U.asTypeOf(new ValidIO(VType())))
private val newestVType = PriorityMux(walkValidVec.zip(infoVec).map { case(walkValid, info) => walkValid -> info }.reverse)
private val newestArchVType = PriorityMux(commitValidVec.zip(infoVec).map { case(commitValid, info) => commitValid -> info }.reverse)
private val commitVTypeValid = commitValidVec.asUInt.orR
Expand All @@ -265,6 +277,10 @@ class VTypeBuffer(size: Int)(implicit p: Parameters) extends XSModule with HasCi
// special walk use commit vtype
decodeResumeVType.valid := commitVTypeValid
decodeResumeVType.bits := newestArchVType
}.elsewhen (useSnapshot) {
// use snapshot vtype
decodeResumeVType.valid := true.B
decodeResumeVType.bits := walkVtypeSnapshots(snptSelect)
}.elsewhen (state === s_walk && walkCount =/= 0.U) {
decodeResumeVType.valid := true.B
decodeResumeVType.bits := newestVType
Expand All @@ -277,10 +293,10 @@ class VTypeBuffer(size: Int)(implicit p: Parameters) extends XSModule with HasCi
// update vtype in decode when VTypeBuffer resumes from walk state
// note that VTypeBuffer can still send resuming request in the first cycle of s_idle
io.toDecode.isResumeVType := state =/= s_idle || decodeResumeVType.valid
io.toDecode.walkVType.valid := isWalk && decodeResumeVType.valid
io.toDecode.walkVType.valid := decodeResumeVType.valid
io.toDecode.walkVType.bits := Mux(io.toDecode.walkVType.valid, decodeResumeVType.bits, 0.U.asTypeOf(VType()))

io.toDecode.commitVType.vtype.valid := isCommit && commitVTypeValid
io.toDecode.commitVType.vtype.valid := commitVTypeValid
io.toDecode.commitVType.vtype.bits := newestArchVType

// because vsetvl flush pipe, there is only one vset instruction when vsetvl is committed
Expand Down
Loading