未验证 提交 7ed96bee 编写于 作者: Y Yinan Xu 提交者: GitHub

scheduler: allow multiple-dequeue RS for load and store (#895)

This commit adds support for multiple enqueue for load and store RS.
Also update the parameters in XSCore to avoid explicitly setting wakeup ports.
上级 ba25aadb
......@@ -28,7 +28,7 @@ import chipsalliance.rocketchip.config
import chipsalliance.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
import freechips.rocketchip.tile.HasFPUParameters
import system.{HasSoCParameter, L1CacheErrorInfo}
import system.{HasSoCParameter, L1CacheErrorInfo, SoCParamsKey}
import utils._
abstract class XSModule(implicit val p: Parameters) extends MultiIOModule
......@@ -67,7 +67,7 @@ abstract class XSCoreBase()(implicit p: config.Parameters) extends LazyModule
val frontend = LazyModule(new Frontend())
val l1pluscache = LazyModule(new L1plusCacheWrapper())
val ptw = LazyModule(new PTWWrapper())
val memBlock = LazyModule(new MemBlock)
// TODO: better RS organization
// generate rs according to number of function units
......@@ -78,15 +78,13 @@ abstract class XSCoreBase()(implicit p: config.Parameters) extends LazyModule
// one RS every 2 MDUs
val schedulePorts = Seq(
// exuCfg, numDeq, intFastWakeupTarget, fpFastWakeupTarget
(AluExeUnitCfg, exuParameters.AluCnt, Seq(0, 1, 2, 5, 6, 7, 8), Seq()),
(MulDivExeUnitCfg, exuParameters.MduCnt, Seq(0, 1, 2, 5, 6, 7, 8), Seq()),
(AluExeUnitCfg, exuParameters.AluCnt, Seq(AluExeUnitCfg, MulDivExeUnitCfg, JumpExeUnitCfg, LdExeUnitCfg, StExeUnitCfg), Seq()),
(MulDivExeUnitCfg, exuParameters.MduCnt, Seq(AluExeUnitCfg, MulDivExeUnitCfg, JumpExeUnitCfg, LdExeUnitCfg, StExeUnitCfg), Seq()),
(JumpExeUnitCfg, 1, Seq(), Seq()),
(FmacExeUnitCfg, exuParameters.FmacCnt, Seq(), Seq(3, 4)),
(FmiscExeUnitCfg, exuParameters.FmiscCnt, Seq(), Seq(3, 4)),
(LdExeUnitCfg, 1, Seq(0, 5, 6), Seq()),
(LdExeUnitCfg, 1, Seq(0, 5, 6), Seq()),
(StExeUnitCfg, 1, Seq(), Seq()),
(StExeUnitCfg, 1, Seq(), Seq())
(FmacExeUnitCfg, exuParameters.FmacCnt, Seq(), Seq(FmacExeUnitCfg, FmiscExeUnitCfg)),
(FmiscExeUnitCfg, exuParameters.FmiscCnt, Seq(), Seq(FmacExeUnitCfg, FmiscExeUnitCfg)),
(LdExeUnitCfg, exuParameters.LduCnt, Seq(AluExeUnitCfg, LdExeUnitCfg), Seq()),
(StExeUnitCfg, exuParameters.StuCnt, Seq(), Seq())
)
// allow mdu and fmisc to have 2*numDeq enqueue ports
val intDpPorts = (0 until exuParameters.AluCnt).map(i => {
......@@ -100,14 +98,25 @@ abstract class XSCoreBase()(implicit p: config.Parameters) extends LazyModule
})
val lsDpPorts = Seq(
Seq((5, 0)),
Seq((5, 1)),
Seq((6, 0)),
Seq((7, 0)),
Seq((8, 0))
Seq((6, 1))
)
val dispatchPorts = intDpPorts ++ fpDpPorts ++ lsDpPorts
val scheduler = LazyModule(new Scheduler(schedulePorts, dispatchPorts))
val mappedSchedulePorts = schedulePorts.map(port => {
val intWakeup = port._3.flatMap(cfg => schedulePorts.zipWithIndex.filter(_._1._1 == cfg).map(_._2))
val fpWakeup = port._4.flatMap(cfg => schedulePorts.zipWithIndex.filter(_._1._1 == cfg).map(_._2))
(port._1, port._2, intWakeup, fpWakeup)
})
val scheduler = LazyModule(new Scheduler(mappedSchedulePorts, dispatchPorts))
val memBlock = LazyModule(new MemBlock()(p.alter((site, here, up) => {
case XSCoreParamsKey => up(XSCoreParamsKey).copy(
IssQueSize = scheduler.memRsEntries.max
)
})))
}
class XSCore()(implicit p: config.Parameters) extends XSCoreBase
......@@ -192,18 +201,18 @@ class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer)
ctrlBlock.io.stOut <> memBlock.io.stOut
ctrlBlock.io.memoryViolation <> memBlock.io.memoryViolation
ctrlBlock.io.enqLsq <> memBlock.io.enqLsq
// TODO
ctrlBlock.io.writeback <> VecInit(intArbiter.io.out ++ fpArbiter.io.out)
scheduler.io.redirect <> ctrlBlock.io.redirect
scheduler.io.flush <> ctrlBlock.io.flush
scheduler.io.allocate <> ctrlBlock.io.enqIQ
scheduler.io.issue <> integerBlock.io.issue ++ floatBlock.io.issue ++ memBlock.io.issue
// TODO arbiter
scheduler.io.writeback <> VecInit(intArbiter.io.out ++ fpArbiter.io.out)
scheduler.io.replay <> memBlock.io.replay
scheduler.io.rsIdx <> memBlock.io.rsIdx
println(s"${scheduler.io.rsIdx(0).getWidth}, ${memBlock.io.rsIdx(0).getWidth}")
require(scheduler.io.rsIdx(0).getWidth == memBlock.io.rsIdx(0).getWidth)
scheduler.io.isFirstIssue <> memBlock.io.isFirstIssue
scheduler.io.stData <> memBlock.io.stData
scheduler.io.otherFastWakeup <> memBlock.io.otherFastWakeup
......
......@@ -114,9 +114,12 @@ class Scheduler(
println("Scheduler: ")
val numIssuePorts = configs.map(_._2).sum
println(s" number of issue ports: ${numIssuePorts}")
val numReplayPorts = reservationStations.count(_.params.hasFeedback == true)
val numReplayPorts = reservationStations.filter(_.params.hasFeedback == true).map(_.params.numDeq).sum
println(s" number of replay ports: ${numReplayPorts}")
val numSTDPorts = reservationStations.count(_.params.isStore == true)
val memRsEntries = reservationStations.filter(_.params.hasFeedback == true).map(_.params.numEntries)
require(memRsEntries.max == memRsEntries.min, "different indexes not supported")
println(s" size of load and store RSes: ${memRsEntries.max}")
val numSTDPorts = reservationStations.filter(_.params.isStore == true).map(_.params.numDeq).sum
println(s" number of std ports: ${numSTDPorts}")
val numOutsideWakeup = reservationStations.map(_.numExtFastWakeupPort).sum
println(s" number of outside fast wakeup ports: ${numOutsideWakeup}")
......@@ -125,6 +128,13 @@ class Scheduler(
}
class SchedulerImp(outer: Scheduler) extends LazyModuleImp(outer) with HasXSParameter {
val memRsEntries = outer.memRsEntries.max
val updatedP = p.alter((site, here, up) => {
case XSCoreParamsKey => up(XSCoreParamsKey).copy(
IssQueSize = memRsEntries
)
})
val io = IO(new Bundle {
// global control
val redirect = Flipped(ValidIO(new Redirect))
......@@ -136,8 +146,8 @@ class SchedulerImp(outer: Scheduler) extends LazyModuleImp(outer) with HasXSPara
val readFpRf = Vec(outer.fpRfReadPorts, Input(UInt(PhyRegIdxWidth.W)))
val issue = Vec(outer.numIssuePorts, DecoupledIO(new ExuInput))
val writeback = Vec(outer.intRfWritePorts + outer.fpRfWritePorts, Flipped(ValidIO(new ExuOutput)))
val replay = Vec(outer.numReplayPorts, Flipped(ValidIO(new RSFeedback)))
val rsIdx = Vec(outer.numReplayPorts, Output(UInt(log2Up(IssQueSize).W)))
val replay = Vec(outer.numReplayPorts, Flipped(ValidIO(new RSFeedback()(updatedP))))
val rsIdx = Vec(outer.numReplayPorts, Output(UInt(log2Up(memRsEntries).W)))
val isFirstIssue = Vec(outer.numReplayPorts, Output(Bool()))
val stData = Vec(outer.numSTDPorts, ValidIO(new StoreDataBundle))
// 2LOAD, data is selected from writeback ports
......@@ -190,14 +200,17 @@ class SchedulerImp(outer: Scheduler) extends LazyModuleImp(outer) with HasXSPara
rs.module.io_checkwait.get.stIssuePtr <> io.stIssuePtr
}
if (rs.module.io_feedback.isDefined) {
rs.module.io_feedback.get.memfeedback <> io.replay(feedbackIdx)
rs.module.io_feedback.get.rsIdx <> io.rsIdx(feedbackIdx)
rs.module.io_feedback.get.isFirstIssue <> io.isFirstIssue(feedbackIdx)
feedbackIdx += 1
require(io.rsIdx(0).getWidth == rs.module.io_feedback.get.rsIdx(0).getWidth)
val width = rs.module.io_feedback.get.memfeedback.length
rs.module.io_feedback.get.memfeedback <> io.replay.slice(feedbackIdx, feedbackIdx + width)
rs.module.io_feedback.get.rsIdx <> io.rsIdx.slice(feedbackIdx, feedbackIdx + width)
rs.module.io_feedback.get.isFirstIssue <> io.isFirstIssue.slice(feedbackIdx, feedbackIdx + width)
feedbackIdx += width
}
if (rs.module.io_store.isDefined) {
rs.module.io_store.get.stData <> io.stData(stDataIdx)
stDataIdx += 1
val width = rs.module.io_store.get.stData.length
rs.module.io_store.get.stData <> io.stData.slice(stDataIdx, stDataIdx + width)
stDataIdx += width
}
(rs.intSrcCnt > 0, rs.fpSrcCnt > 0) match {
......@@ -263,6 +276,7 @@ class SchedulerImp(outer: Scheduler) extends LazyModuleImp(outer) with HasXSPara
}
intReadPort += numIntRfPorts
}
val numFpRfPorts = dp.map(_._1).map(rs_all(_).fpSrcCnt).max
if (numFpRfPorts > 0) {
val fpRfPorts = VecInit(fpRf.io.readPorts.slice(fpReadPort, fpReadPort + numFpRfPorts).map(_.data))
......@@ -273,7 +287,7 @@ class SchedulerImp(outer: Scheduler) extends LazyModuleImp(outer) with HasXSPara
if (numIntRfPorts > 0) {
require(numFpRfPorts == 1)
require(numIntRfPorts == 2)
when(RegNext(mod.io.fromDispatch(0).bits.ctrl.srcType(1) === SrcType.fp)) {
when(RegNext(mod.io.fromDispatch(idx).bits.ctrl.srcType(1) === SrcType.fp)) {
target(1) := fpRfPorts(0)
}
}
......
......@@ -136,7 +136,15 @@ class ReservationStation(implicit p: Parameters) extends LazyModule with HasXSPa
override def toString: String = params.toString
def indexWidth = log2Up(params.numEntries)
lazy val module = new LazyModuleImp(this) {
val updatedP = p.alter((site, here, up) => {
case XSCoreParamsKey => up(XSCoreParamsKey).copy(
IssQueSize = params.numEntries
)
})
val io = IO(new Bundle {
val redirect = Flipped(ValidIO(new Redirect))
val flush = Input(Bool())
......@@ -158,15 +166,15 @@ class ReservationStation(implicit p: Parameters) extends LazyModule with HasXSPa
val jalr_target = Input(UInt(VAddrBits.W))
})) else None
val io_feedback = if (params.hasFeedback) Some(IO(new Bundle {
val memfeedback = Flipped(ValidIO(new RSFeedback))
val rsIdx = Output(UInt(log2Up(params.numEntries).W))
val isFirstIssue = Output(Bool()) // NOTE: just use for tlb perf cnt
val memfeedback = Vec(params.numDeq, Flipped(ValidIO(new RSFeedback()(updatedP))))
val rsIdx = Vec(params.numDeq, Output(UInt(indexWidth.W)))
val isFirstIssue = Vec(params.numDeq, Output(Bool())) // NOTE: just use for tlb perf cnt
})) else None
val io_checkwait = if (params.checkWaitBit) Some(IO(new Bundle {
val stIssuePtr = Input(new SqPtr())
})) else None
val io_store = if (params.isStore) Some(IO(new Bundle {
val stData = ValidIO(new StoreDataBundle)
val stData = Vec(params.numDeq, ValidIO(new StoreDataBundle))
})) else None
val statusArray = Module(new StatusArray(params))
......@@ -226,20 +234,15 @@ class ReservationStation(implicit p: Parameters) extends LazyModule with HasXSPa
select.io.request := statusArray.io.canIssue
for (i <- 0 until params.numDeq) {
select.io.grant(i).ready := io.deq(i).ready
statusArray.io.issueGranted(i).valid := select.io.grant(i).fire
statusArray.io.issueGranted(i).bits := select.io.grant(i).bits
statusArray.io.deqResp(i).valid := select.io.grant(i).fire
statusArray.io.deqResp(i).bits.rsMask := select.io.grant(i).bits
statusArray.io.deqResp(i).bits.success := io.deq(i).ready
if (io_feedback.isDefined) {
require(params.numDeq == 1)
statusArray.io.issueGranted(0).valid := select.io.grant(0).fire
statusArray.io.issueGranted(0).bits := select.io.grant(0).bits
statusArray.io.deqResp(0).valid := io_feedback.get.memfeedback.valid
statusArray.io.deqResp(0).bits.rsMask := UIntToOH(io_feedback.get.memfeedback.bits.rsIdx)
statusArray.io.deqResp(0).bits.success := io_feedback.get.memfeedback.bits.hit
}
else {
statusArray.io.issueGranted(i).valid := select.io.grant(i).fire
statusArray.io.issueGranted(i).bits := select.io.grant(i).bits
statusArray.io.deqResp(i).valid := select.io.grant(i).fire
statusArray.io.deqResp(i).bits.rsMask := select.io.grant(i).bits
statusArray.io.deqResp(i).bits.success := io.deq(i).ready
statusArray.io.deqResp(i).valid := io_feedback.get.memfeedback(i).valid
statusArray.io.deqResp(i).bits.rsMask := UIntToOH(io_feedback.get.memfeedback(i).bits.rsIdx)
statusArray.io.deqResp(i).bits.success := io_feedback.get.memfeedback(i).bits.hit
}
payloadArray.io.read(i).addr := select.io.grant(i).bits
if (io_fastWakeup.isDefined) {
......@@ -370,8 +373,8 @@ class ReservationStation(implicit p: Parameters) extends LazyModule with HasXSPa
PipelineConnect(s1_out(i), io.deq(i), io.deq(i).ready || io.deq(i).bits.uop.roqIdx.needFlush(io.redirect, io.flush), false.B)
val pipeline_fire = s1_out(i).valid && io.deq(i).ready
if (params.hasFeedback) {
io_feedback.get.rsIdx := RegEnable(OHToUInt(select.io.grant(i).bits), pipeline_fire)
io_feedback.get.isFirstIssue := RegEnable(statusArray.io.isFirstIssue.head, pipeline_fire)
io_feedback.get.rsIdx(i) := RegEnable(OHToUInt(select.io.grant(i).bits), pipeline_fire)
io_feedback.get.isFirstIssue(i) := RegEnable(statusArray.io.isFirstIssue(i), pipeline_fire)
}
for (j <- 0 until params.numSrc) {
......@@ -379,9 +382,9 @@ class ReservationStation(implicit p: Parameters) extends LazyModule with HasXSPa
}
if (io_store.isDefined) {
io_store.get.stData.valid := io.deq(i).valid
io_store.get.stData.bits.data := io.deq(i).bits.src(1)
io_store.get.stData.bits.uop := io.deq(i).bits.uop
io_store.get.stData(i).valid := io.deq(i).valid
io_store.get.stData(i).bits.data := io.deq(i).bits.src(1)
io_store.get.stData(i).bits.uop := io.deq(i).bits.uop
}
}
......
......@@ -132,13 +132,13 @@ class StatusArray(params: RSParams)(implicit p: Parameters) extends XSModule
if (params.checkWaitBit) {
statusNext.blocked := updateStatus.blocked && isAfter(updateStatus.sqIdx, io.stIssuePtr)
}
XSError(status.valid, p"should not update a valid entry\n")
XSError(status.valid, p"should not update a valid entry $i\n")
}.otherwise {
val hasIssued = VecInit(io.issueGranted.map(iss => iss.valid && iss.bits(i))).asUInt.orR
val (deqResp, deqGrant) = deqRespSel(i)
XSError(deqResp && !status.valid, "should not deq an invalid entry\n")
XSError(deqResp && !status.valid, p"should not deq an invalid entry $i\n")
if (params.hasFeedback) {
XSError(deqResp && !status.scheduled, "should not deq an un-scheduled entry\n")
XSError(deqResp && !status.scheduled, p"should not deq an un-scheduled entry $i\n")
}
val wakeupEnVec = VecInit(status.psrc.zip(status.srcType).map{ case (p, t) => wakeupMatch(p, t) })
val wakeupEn = wakeupEnVec.map(_.orR)
......@@ -146,7 +146,7 @@ class StatusArray(params: RSParams)(implicit p: Parameters) extends XSModule
statusNext.valid := Mux(deqResp && deqGrant, false.B, status.valid && !status.roqIdx.needFlush(io.redirect, io.flush))
// (1) when deq is not granted, unset its scheduled bit; (2) set scheduled if issued
statusNext.scheduled := Mux(deqResp && !deqGrant || status.credit === 1.U, false.B, status.scheduled || hasIssued)
XSError(hasIssued && !status.valid, "should not issue an invalid entry\n")
XSError(hasIssued && !status.valid, p"should not issue an invalid entry $i\n")
statusNext.blocked := false.B
if (params.checkWaitBit) {
statusNext.blocked := status.blocked && isAfter(status.sqIdx, io.stIssuePtr)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册