Skip to content

Commit c62c7f4

Browse files
happy-lxzybzzz
andauthored
cpu-o3: Add load value prediction framework (#766)
Integrate and resolve code merge conflicts of the load value prediction (LVP) framework from PR #297, keeping training/prediction/recovery/algorithm paths only, remove Ideal Model code paths to simplify maintenance. Add IdealConstantLVP with unbounded table as an ideal constant predictor, to explore the upper bound and parameter space of constant value prediction. Change-Id: I2f11ea1af963e3dcae82f7380a1e3cf016d7007c Co-authored-by: Yibo Zhang <yb_zhang@mail.ustc.edu.cn>
1 parent 1464005 commit c62c7f4

27 files changed

+1407
-3
lines changed

configs/example/idealkmhv3.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
from common.Caches import *
2020
from common.xiangshan import *
2121

22+
from m5.objects.ValuePredictor import *
23+
2224
def setKmhV3IdealParams(args, system):
2325
for cpu in system.cpu:
2426

@@ -63,6 +65,9 @@ def setKmhV3IdealParams(args, system):
6365
cpu.sbufferBankWriteAccurately = True
6466
cpu.DcacheSetDivNum = 2
6567

68+
# value predictor
69+
cpu.valuePred = IdealConstantLVP()
70+
6671
# lsq
6772
cpu.LQEntries = 128
6873
cpu.SQEntries = 64

src/cpu/o3/BaseO3CPU.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
from m5.objects.FuncScheduler import *
4545
#from m5.objects.O3Checker import O3Checker
4646
from m5.objects.BranchPredictor import *
47+
from m5.objects.ValuePredictor import *
4748
from m5.SimObject import *
4849

4950
class SMTFetchPolicy(ScopedEnum):
@@ -254,6 +255,9 @@ def support_take_over(cls):
254255

255256
store_prefetch_train = Param.Bool(True, "Training store prefetcher with store addresses")
256257

258+
# value predictor
259+
valuePred = Param.ValuePredictor(NULL, "valuepred unit")
260+
257261
enable_loadFusion = Param.Bool(False, "Enable load fusion")
258262

259263
enableConstantFolding = Param.Bool(False, "Enable Constant Folding (add-immediate elimination)")

src/cpu/o3/comm.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ struct IEWStruct
157157
bool branchMispredict[MaxThreads];
158158
bool branchTaken[MaxThreads];
159159
bool includeSquashInst[MaxThreads];
160+
161+
bool valuePredictionError[MaxThreads];
160162
};
161163

162164
struct IssueStruct

src/cpu/o3/commit.cc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ Commit::Commit(CPU *_cpu, branch_prediction::BPredUnit *_bp, const BaseO3CPUPara
135135
}, "CommitStuckCheckEvent"),
136136
cpu(_cpu),
137137
bp(_bp),
138+
valuePred(params.valuePred),
138139
iewToCommitDelay(params.iewToCommitDelay),
139140
commitToIEWDelay(params.commitToIEWDelay),
140141
renameToROBDelay(params.renameToROBDelay),
@@ -294,6 +295,8 @@ Commit::CommitStats::CommitStats(CPU *cpu, Commit *commit)
294295
"Number of squash due to branch"),
295296
ADD_STAT(squashDueToOrderViolation, statistics::units::Count::get(),
296297
"Number of squash due to order violation"),
298+
ADD_STAT(squashDueToValuePrediction, statistics::units::Count::get(),
299+
"Number of squash due to value prediction"),
297300
ADD_STAT(squashDueToTrap, statistics::units::Count::get(),
298301
"Number of squash due to trap"),
299302
ADD_STAT(squashDueToTC, statistics::units::Count::get(),
@@ -691,6 +694,9 @@ Commit::squashAll(ThreadID tid)
691694
rob->squash(squashed_inst, tid);
692695
changedROBNumEntries[tid] = true;
693696

697+
if (valuePred)
698+
valuePred->squash(squashed_inst);
699+
694700
// Send back the sequence number of the squashed instruction.
695701
toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
696702
toIEW->commitInfo[tid].doneMemSeqNum = squashed_inst;
@@ -1034,6 +1040,11 @@ Commit::commit()
10341040
fromIEW->mispredictInst[tid]->pcState().instAddr(),
10351041
fromIEW->squashedSeqNum[tid]);
10361042
stats.squashDueToBranch++;
1043+
} else if (fromIEW->valuePredictionError[tid]) {
1044+
DPRINTF(Commit,
1045+
"[tid:%i] Squashing due to value prediction error [sn:%llu]\n",
1046+
tid, fromIEW->squashedSeqNum[tid]);
1047+
stats.squashDueToValuePrediction++;
10371048
} else {
10381049
DPRINTF(Commit,
10391050
"[tid:%i] Squashing due to order violation [sn:%llu]\n",
@@ -1061,6 +1072,9 @@ Commit::commit()
10611072
rob->squash(squashed_inst, tid);
10621073
changedROBNumEntries[tid] = true;
10631074

1075+
if (valuePred)
1076+
valuePred->squash(squashed_inst);
1077+
10641078
toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
10651079
toIEW->commitInfo[tid].doneMemSeqNum = squashed_inst;
10661080

@@ -1815,6 +1829,25 @@ Commit::commitHead(const DynInstPtr &head_inst, unsigned inst_num)
18151829
if (head_inst->isHtmStart())
18161830
iewStage->setLastRetiredHtmUid(tid, head_inst->getHtmTransactionUid());
18171831

1832+
if (valuePred && head_inst->canLVP() && (inst_fault == NoFault)) {
1833+
valuepred::VPUpdateMetaData *updateMetaData = valuepred::
1834+
VPDataStructFactory::buildUpdateMetaData(valuePred->getValuePredictorType());
1835+
updateMetaData->pc = head_inst->getPC();
1836+
updateMetaData->seq_no = head_inst->seqNum;
1837+
updateMetaData->actualValue = head_inst->actualValue;
1838+
updateMetaData->isMisprediction = head_inst->vpMisprediction;
1839+
valuePred->updateValuePredictor(updateMetaData);
1840+
valuePred->stats.VPsupported++;
1841+
if (head_inst->vpResult.speculative) {
1842+
valuePred->stats.VPpredicted++;
1843+
if (!head_inst->vpMisprediction) {
1844+
valuePred->stats.VPcorrected++;
1845+
}
1846+
}
1847+
1848+
delete updateMetaData;
1849+
}
1850+
18181851
// Finally clear the head ROB entry.
18191852
rob->retireHead(tid);
18201853

src/cpu/o3/commit.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "cpu/pred/general_arch_db.hh"
6565
#include "cpu/pred/stream/decoupled_bpred.hh"
6666
#include "cpu/timebuf.hh"
67+
#include "cpu/valuepred/valuepred_unit.hh"
6768
#include "enums/CommitPolicy.hh"
6869
#include "sim/arch_db.hh"
6970
#include "sim/probe/probe.hh"
@@ -441,6 +442,9 @@ class Commit
441442

442443
branch_prediction::BPredUnit *bp;
443444

445+
/** Value predictor */
446+
valuepred::VPUnit *valuePred;
447+
444448
/** Vector of all of the threads. */
445449
std::vector<ThreadState *> thread;
446450

@@ -633,6 +637,7 @@ class Commit
633637

634638
statistics::Scalar squashDueToBranch;
635639
statistics::Scalar squashDueToOrderViolation;
640+
statistics::Scalar squashDueToValuePrediction;
636641
statistics::Scalar squashDueToTrap;
637642
statistics::Scalar squashDueToTC;
638643
statistics::Scalar squashDueToSquashAfter;

src/cpu/o3/cpu.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ CPU::CPU(const BaseO3CPUParams &params)
131131
issueWidth(params.decodeWidth),
132132
enableConstantFolding(params.enableConstantFolding),
133133
enableMovImmElimination(params.enableMovImmElimination),
134-
cpuStats(this)
134+
cpuStats(this),
135+
valuePred(params.valuePred)
135136
{
136137
fatal_if(FullSystem && params.numThreads > 1,
137138
"SMT is not supported in O3 in full system mode currently.");

src/cpu/o3/cpu.hh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
#include "cpu/o3/thread_state.hh"
7272
#include "cpu/simple_thread.hh"
7373
#include "cpu/timebuf.hh"
74+
#include "cpu/valuepred/valuepred_unit.hh"
7475
#include "mem/cache/prefetch/base.hh"
7576
#include "params/BaseO3CPU.hh"
7677
#include "sim/process.hh"
@@ -739,6 +740,15 @@ class CPU : public BaseCPU
739740

740741
//difftest virtual function
741742
void readGem5Regs() override;
743+
744+
private:
745+
/** Value predictor */
746+
valuepred::VPUnit *valuePred;
747+
748+
public:
749+
bool isValuePredictorEnabled() const { return valuePred != nullptr; }
750+
751+
valuepred::VPUnit *getValuePredictor() const { return valuePred; }
742752
};
743753

744754
} // namespace o3

src/cpu/o3/dyn_inst.hh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#include "cpu/reg_class.hh"
6969
#include "cpu/static_inst.hh"
7070
#include "cpu/translation.hh"
71+
#include "cpu/valuepred/valuepred_metadata.hh"
7172
#include "debug/CommitTrace.hh"
7273
#include "debug/DecoupleBP.hh"
7374
#include "debug/HtmCpu.hh"
@@ -744,6 +745,7 @@ class DynInst : public ExecContext, public RefCounted
744745
bool isHInst() const { return staticInst->isHInst(); }
745746
bool isStore() const { return staticInst->isStore(); }
746747
bool isAtomic() const { return staticInst->isAtomic(); }
748+
bool isLoadReserved() const { return staticInst->isLoadReserved(); }
747749
bool isStoreConditional() const
748750
{ return staticInst->isStoreConditional(); }
749751
bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
@@ -1649,6 +1651,17 @@ class DynInst : public ExecContext, public RefCounted
16491651

16501652
/** get golden */
16511653
uint8_t *getGolden() { return goldenData; }
1654+
1655+
/** value prediction */
1656+
valuepred::VPResult vpResult = {false, 0xdeadbeefULL};
1657+
1658+
RegVal actualValue = 0xdeadbeefULL;
1659+
bool vpMisprediction = false;
1660+
bool vpSupported = false;
1661+
1662+
bool canLVP(){
1663+
return isLoad() && !isVector() && !isLoadReserved();
1664+
}
16521665
};
16531666

16541667
} // namespace o3

src/cpu/o3/fetch.cc

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ Fetch::Fetch(CPU *_cpu, const BaseO3CPUParams &params)
110110
numThreads(params.numThreads),
111111
numFetchingThreads(params.smtNumFetchingThreads),
112112
icachePort(this, _cpu),
113-
finishTranslationEvent(this), fetchStats(_cpu, this)
113+
finishTranslationEvent(this), fetchStats(_cpu, this),
114+
valuePred(params.valuePred)
114115
{
115116
if (numThreads > MaxThreads)
116117
fatal("numThreads (%d) is larger than compiled limit (%d),\n"
@@ -1921,6 +1922,17 @@ Fetch::processSingleInstruction(ThreadID tid, PCStateBase &pc,
19211922
// Update the main PC state for the next instruction.
19221923
set(pc, *next_pc);
19231924

1925+
// Do the value prediction
1926+
if (valuePred && instruction->canLVP()) {
1927+
valuepred::VPPredMetaData* vpPredMetaData = valuepred::VPDataStructFactory::
1928+
buildPredMetaData(valuePred->getValuePredictorType());
1929+
1930+
vpPredMetaData->pc = instruction->getPC();
1931+
vpPredMetaData->seq_no = instruction->seqNum;
1932+
instruction->vpResult = valuePred->valuePredict(vpPredMetaData);
1933+
delete vpPredMetaData;
1934+
}
1935+
19241936
return predictedBranch;
19251937
}
19261938

src/cpu/o3/fetch.hh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#include "cpu/pred/btb/decoupled_bpred.hh"
6060
#include "cpu/timebuf.hh"
6161
#include "cpu/translation.hh"
62+
#include "cpu/valuepred/valuepred_unit.hh"
6263
#include "enums/SMTFetchPolicy.hh"
6364
#include "mem/packet.hh"
6465
#include "mem/port.hh"
@@ -1116,6 +1117,9 @@ public:
11161117
private:
11171118

11181119
bool waitForVsetvl = false;
1120+
1121+
/** Value predictor */
1122+
valuepred::VPUnit *valuePred;
11191123
};
11201124

11211125
} // namespace o3

0 commit comments

Comments
 (0)