Skip to content

Commit 4b6b1dc

Browse files
authored
Spec vp flush1 (#808)
* mem: update specwakeup for valuepre Changed lvpWakeDependents to use speculative wakeup; replaced full squash in readyToFinish with loadCancel. Introduced specWakeUpFromVP and adjusted the VP-related condition for loadCancel. Change-Id: I44e3c02f31e2a30a2206936bc5041b1761e04030 * mem: enableSelectiveVPFlush Enable partial flush Added a new member enableSelectiveVPFlush and initialized it from params. Change-Id: Ic6577e30061fb483a82698e91a3abd1a843b847a
1 parent fa46f57 commit 4b6b1dc

File tree

7 files changed

+109
-28
lines changed

7 files changed

+109
-28
lines changed

src/cpu/o3/BaseO3CPU.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ def support_take_over(cls):
257257

258258
# value predictor
259259
valuePred = Param.ValuePredictor(NULL, "valuepred unit")
260+
enableSelectiveVPFlush = Param.Bool(False,
261+
"Enable selective rollback for value prediction misprediction")
260262

261263
enable_loadFusion = Param.Bool(False, "Enable load fusion")
262264

src/cpu/o3/iew.cc

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -452,15 +452,18 @@ IEW::setScoreboard(Scoreboard *sb_ptr)
452452
void
453453
IEW::lvpWakeDependents(const DynInstPtr &inst) {
454454
assert(inst->numDestRegs() == 1);
455-
for (int i = 0; i < inst->numDestRegs(); i++) {
456-
auto dest = inst->renamedDestIdx(i);
457-
if (dest->isFixedMapping()) {
458-
continue;
455+
if (enableSelectiveVPFlush) {
456+
scheduler->specWakeUpFromVP(inst);
457+
DPRINTF(IEW,"[sn:%llu] vp specWakeUp dependents\n", inst->seqNum);
458+
} else {
459+
for (int i = 0; i < inst->numDestRegs(); i++) {
460+
auto dest = inst->renamedDestIdx(i);
461+
if (dest->isFixedMapping()) {
462+
continue;
463+
}
464+
scheduler->setAllScoreBoard(dest);
465+
DPRINTF(IEW,"[sn:%llu] vp set scoreboard to true\n", inst->seqNum);
459466
}
460-
461-
scheduler->setAllScoreBoard(dest);
462-
463-
DPRINTF(IEW,"[sn:%llu] vp set scoreboard to true\n", inst->seqNum);
464467
}
465468
}
466469

@@ -723,10 +726,30 @@ IEW::readyToFinish(const DynInstPtr& inst)
723726

724727
ThreadID tid = inst->threadNumber;
725728
if (inst->vpMisprediction) {
726-
if (!fetchRedirect[tid] || !toCommit->squash[tid] || toCommit->squashedSeqNum[tid] > inst->seqNum) {
727-
// deal with value prediction error
728-
fetchRedirect[tid] = true;
729-
squashDueToValuePrediction(inst, tid);
729+
if (!enableSelectiveVPFlush) {
730+
if (!fetchRedirect[tid] || !toCommit->squash[tid] ||
731+
toCommit->squashedSeqNum[tid] > inst->seqNum) {
732+
fetchRedirect[tid] = true;
733+
squashDueToValuePrediction(inst, tid);
734+
}
735+
} else {
736+
// VP selective flush: cancel data-dependent consumers when possible.
737+
// If any dependent consumer is already issued, fallback to squash.
738+
DPRINTF(IEW, "[sn:%llu] VP misprediction detected, "
739+
"selective cancel via loadCancel\n", inst->seqNum);
740+
bool needSquashFallback = scheduler->loadCancel(inst);
741+
if (needSquashFallback) {
742+
DPRINTF(IEW, "[sn:%llu] VP fallback to squash due to issued dependent\n",
743+
inst->seqNum);
744+
if (!fetchRedirect[tid] || !toCommit->squash[tid] ||
745+
toCommit->squashedSeqNum[tid] > inst->seqNum) {
746+
fetchRedirect[tid] = true;
747+
squashDueToValuePrediction(inst, tid);
748+
}
749+
} else {
750+
// Writeback with real value to re-wake consumers
751+
scheduler->writebackWakeup(inst);
752+
}
730753
}
731754
}
732755

src/cpu/o3/iew.hh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,9 @@ class IEW
410410
/** Value predictor */
411411
valuepred::VPUnit *valuePred;
412412

413+
/** Enable selective VP flush path */
414+
bool enableSelectiveVPFlush;
415+
413416
private:
414417
/** CPU pointer. */
415418
CPU *cpu;

src/cpu/o3/issue_queue.cc

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,10 @@ IssueQue::wakeUpDependents(const DynInstPtr& inst, bool speculative)
508508
void
509509
IssueQue::addIfReady(const DynInstPtr& inst)
510510
{
511+
if (inst->isIssued()) {
512+
return;
513+
}
514+
511515
if (inst->readyToIssue()) {
512516
if (inst->readyTick == -1) {
513517
inst->readyTick = curTick();
@@ -1258,6 +1262,32 @@ Scheduler::specWakeUpDependents(const DynInstPtr& inst, IssueQue* from_issue_que
12581262
}
12591263
}
12601264

1265+
void
1266+
Scheduler::specWakeUpFromVP(const DynInstPtr& inst)
1267+
{
1268+
DPRINTF(Schedule, "[sn:%llu] VP speculative wakeup dependents\n", inst->seqNum);
1269+
// Wake consumers already in IQ via speculative wakeup (preserves subDepGraph)
1270+
for (auto to : issueQues) {
1271+
to->wakeUpDependents(inst, true); // speculative=true -> depgraph preserved
1272+
}
1273+
// Set earlyScoreboard + bypassScoreboard (but NOT scoreboard) so that
1274+
// future consumers entering IQ via insert() will:
1275+
// - see scoreboard[src]=false -> enter the else branch
1276+
// - see earlyScoreboard[src]=true -> markSrcRegReady AND added to subDepGraph
1277+
// This ensures loadCancel DFS can find them.
1278+
for (int i = 0; i < inst->numDestRegs(); i++) {
1279+
PhysRegIdPtr dst = inst->renamedDestIdx(i);
1280+
if (dst->isFixedMapping()) [[unlikely]] {
1281+
continue;
1282+
}
1283+
earlyScoreboard[dst->flatIndex()] = true;
1284+
bypassScoreboard[dst->flatIndex()] = true;
1285+
// NOTE: intentionally NOT setting scoreboard[dst] = true
1286+
// so consumers go through the earlyScoreboard path in insert()
1287+
// which adds them to subDepGraph
1288+
}
1289+
}
1290+
12611291
void
12621292
Scheduler::specWakeUpFromLoadPipe(const DynInstPtr& inst)
12631293
{
@@ -1360,7 +1390,7 @@ Scheduler::useRfWrPort(const DynInstPtr& inst, const PhysRegIdPtr& regid, int ty
13601390
t_lat = lat;
13611391
}
13621392

1363-
void
1393+
bool
13641394
Scheduler::loadCancel(const DynInstPtr& inst)
13651395
{
13661396
DPRINTF(Schedule, "[sn:%llu] %s cache miss, cancel consumers\n", inst->seqNum,
@@ -1369,10 +1399,12 @@ Scheduler::loadCancel(const DynInstPtr& inst)
13691399
inst->issueQue->iqstats->loadmiss++;
13701400
}
13711401

1372-
// speculative value prediction load should not be cancel
1373-
// because the dependency issue has been resolved
1374-
if (inst->vpResult.speculative) {
1375-
return;
1402+
bool needSquashFallback = false;
1403+
1404+
// For VP load: if prediction is correct (no misprediction), skip cancel.
1405+
// If VP misprediction detected, allow DFS to cancel dependent consumers.
1406+
if (inst->vpResult.speculative && !inst->vpMisprediction) {
1407+
return false;
13761408
}
13771409

13781410
dfs.push(inst);
@@ -1398,6 +1430,18 @@ Scheduler::loadCancel(const DynInstPtr& inst)
13981430
if (depInst->readySrcIdx(srcIdx)) {
13991431
DPRINTF(Schedule, "cancel [sn:%llu], clear src p%d ready\n", depInst->seqNum,
14001432
depInst->renamedSrcIdx(srcIdx)->flatIndex());
1433+
if (depInst->isIssued()) {
1434+
if (inst->vpMisprediction) {
1435+
// VP misprediction: consumer may already be in-flight.
1436+
// Mark canceled and propagate to its dependents.
1437+
depInst->setCancel();
1438+
depInst->clearSrcRegReady(srcIdx);
1439+
dfs.push(depInst);
1440+
needSquashFallback = true;
1441+
}
1442+
continue;
1443+
}
1444+
14011445
depInst->issueQue->cancel(depInst);
14021446
depInst->clearSrcRegReady(srcIdx);
14031447
dfs.push(depInst);
@@ -1418,6 +1462,8 @@ Scheduler::loadCancel(const DynInstPtr& inst)
14181462
}
14191463
}
14201464
}
1465+
1466+
return needSquashFallback;
14211467
}
14221468

14231469
void
@@ -1456,14 +1502,14 @@ Scheduler::bypassWriteback(const DynInstPtr& inst)
14561502
}
14571503
if (inst->canLVP()) {
14581504
RegVal actualValue = cpu->getReg(inst->extRenamedDestIdx(0));
1459-
// RegVal actualValue_2 = inst->getResult().as<RegVal>();
1460-
// assert(actualValue == actualValue_2);
14611505
inst->actualValue = actualValue;
1462-
if (inst->vpResult.speculative && inst->fault == NoFault) {
1463-
if (actualValue != inst->vpResult.value) {
1464-
// check error
1465-
inst->vpMisprediction = true;
1466-
}
1506+
inst->vpMisprediction = false;
1507+
if (inst->vpResult.speculative && inst->fault == NoFault &&
1508+
actualValue != inst->vpResult.value) {
1509+
DPRINTF(Schedule, "actual value: 0x%lx, predicted value: 0x%lx pc %lx\n", actualValue,
1510+
inst->vpResult.value, inst->pcState().instAddr());
1511+
inst->vpMisprediction = true;
1512+
inst->vpResult.speculative = false;
14671513
}
14681514
}
14691515
}

src/cpu/o3/issue_queue.hh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,9 @@ class Scheduler : public SimObject
346346
void useRfRdPort(const DynInstPtr& inst, const PhysRegIdPtr& regid, int typePortId, int pri);
347347
void useRfWrPort(const DynInstPtr& inst, const PhysRegIdPtr& regid, int typePortId, int pri);
348348

349+
void specWakeUpFromVP(const DynInstPtr& inst);
349350
void specWakeUpFromLoadPipe(const DynInstPtr& inst);
350-
void loadCancel(const DynInstPtr& inst);
351+
bool loadCancel(const DynInstPtr& inst);
351352

352353
void writebackWakeup(const DynInstPtr& inst);
353354
void bypassWriteback(const DynInstPtr& inst);

src/cpu/o3/rename.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ Rename::Rename(CPU *_cpu, const BaseO3CPUParams &params)
6767
releaseWidth(params.phyregReleaseWidth),
6868
numThreads(params.numThreads),
6969
stats(_cpu),
70-
valuePred(params.valuePred)
70+
valuePred(params.valuePred),
71+
enableSelectiveVPFlush(params.enableSelectiveVPFlush)
7172
{
7273
if (renameWidth > MaxWidth)
7374
fatal("renameWidth (%d) is larger than compiled limit (%d),\n"
@@ -943,8 +944,10 @@ Rename::renameDestRegs(const DynInstPtr &inst, ThreadID tid)
943944

944945
inst->vpSupported = true;
945946
if (inst->vpResult.speculative) {
946-
// set the scoreboard, let the back-to-back rename inst mark reg ready
947-
scoreboard->setReg(rename_result.first.PhyReg());
947+
if (!enableSelectiveVPFlush) {
948+
// old behavior: let back-to-back rename consumers see ready
949+
scoreboard->setReg(rename_result.first.PhyReg());
950+
}
948951
inst->setRegOperand(inst->staticInst.get(), 0, inst->vpResult.value);
949952
// must pop result here
950953
inst->popResult();

src/cpu/o3/rename.hh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,9 @@ class Rename
455455

456456
/** Value predictor */
457457
valuepred::VPUnit *valuePred;
458+
459+
/** Enable selective VP flush path */
460+
bool enableSelectiveVPFlush;
458461
};
459462

460463
} // namespace o3

0 commit comments

Comments
 (0)