Skip to content
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
62 changes: 23 additions & 39 deletions src/cpu/pred/btb/common.hh
Original file line number Diff line number Diff line change
Expand Up @@ -516,24 +516,29 @@ struct FullBTBPrediction
return (bbStart + predictWidth) & ~mask(floorLog2(predictWidth) - 1);
}

Addr getEntryTarget(const BTBEntry &entry) {
Addr target = entry.target;
// indirect target should come from ipred or ras,
// or btb itself when ipred miss
if (entry.isIndirect) {
if (!entry.isReturn) { // normal indirect, see ittage
auto& pc = entry.pc;
auto it = IndirectTakens_find(indirectTargets, pc);
if (it != indirectTargets.end()) { // found in ittage, use it
target = it->second;
}
} else { // indirect return, use RAS target
target = returnTarget;
}
} // else: normal taken, use btb target
return target;
}

Addr getTarget(Addr predictWidth) {
Addr target;
const auto &entry = getTakenEntry();
if (entry.valid) { // found a taken entry
target = entry.target;
// indirect target should come from ipred or ras,
// or btb itself when ipred miss
if (entry.isIndirect) {
if (!entry.isReturn) { // normal indirect, see ittage
auto& pc = entry.pc;
auto it = IndirectTakens_find(indirectTargets, pc);
if (it != indirectTargets.end()) { // found in ittage, use it
target = it->second;
}
} else { // indirect return, use RAS target
target = returnTarget;
}
} // else: normal taken, use btb target
target = getEntryTarget(entry);
} else {
target = getFallThrough(predictWidth);
}
Expand Down Expand Up @@ -631,32 +636,11 @@ struct FullBTBPrediction

std::tuple<Addr, Addr, bool> getPHistInfo() //path
{
bool taken = false;
Addr pc = 0;
Addr target = 0;
for (auto &entry : btbEntries) {
if (entry.valid) {
if (entry.isCond) {
auto& _pc = entry.pc;
auto it = CondTakens_find(condTakens, _pc);
if (it != condTakens.end()) {
if (it->second) {
taken = true;
pc = entry.pc; // get the pc of the cond branch
target = entry.target;
break;
}
}
} else {
// uncond
taken = true;
pc = entry.pc; // get the pc of the cond branch
target = entry.target;
break;
}
}
const auto &entry = getTakenEntry();
if (entry.valid) {
return std::make_tuple(entry.pc, getEntryTarget(entry), true);
}
return std::make_tuple(pc, target, taken);
return std::make_tuple(0, 0, false);
}

};
Expand Down
49 changes: 49 additions & 0 deletions src/cpu/pred/btb/test/btb_mgsc.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,55 @@ TEST(BTBMGSCTest, PTableLearnsOutcomeFromPreviousTakenBranchTarget)
EXPECT_GE(acc, 0.80) << "Accuracy too low for PTable path-target learning: " << acc;
}

TEST(BTBMGSCTest, SpecUpdatePHistUsesIndirectTargetOverride)
{
MgscHarness h;

BTBEntry entry = makeCondBTBEntry(0x1000);
entry.isIndirect = true;
entry.target = 0x2000;
const Addr indirectTarget = 0x3000;

ASSERT_NE(pathHash(entry.pc, entry.target), pathHash(entry.pc, indirectTarget));

FullBTBPrediction pred;
pred.btbEntries = {entry};
pred.condTakens.push_back({entry.pc, true});
pred.indirectTargets.push_back({entry.pc, indirectTarget});

boost::dynamic_bitset<> expected_phr = h.phr;
pHistShiftIn(2, true, expected_phr, entry.pc, indirectTarget);

h.mgsc.specUpdatePHist(h.phr, pred);
h.mgsc.checkFoldedHist(h.ghr, expected_phr, h.lhr,
"indirect target override");
}

TEST(BTBMGSCTest, SpecUpdatePHistUsesReturnTargetOverride)
{
MgscHarness h;

BTBEntry entry = makeCondBTBEntry(0x1000);
entry.isIndirect = true;
entry.isReturn = true;
entry.target = 0x2000;
const Addr returnTarget = 0x3400;

ASSERT_NE(pathHash(entry.pc, entry.target), pathHash(entry.pc, returnTarget));

FullBTBPrediction pred;
pred.btbEntries = {entry};
pred.condTakens.push_back({entry.pc, true});
pred.returnTarget = returnTarget;

boost::dynamic_bitset<> expected_phr = h.phr;
pHistShiftIn(2, true, expected_phr, entry.pc, returnTarget);

h.mgsc.specUpdatePHist(h.phr, pred);
h.mgsc.checkFoldedHist(h.ghr, expected_phr, h.lhr,
"return target override");
}

} // namespace test
} // namespace btb_pred
} // namespace branch_prediction
Expand Down
53 changes: 53 additions & 0 deletions src/cpu/pred/btb/test/btb_tage.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,59 @@ TEST_F(BTBTAGEUpperBoundPathHashTest, PredictionUsesPathHashHistorySnapshot) {
EXPECT_TRUE(predicted);
}

TEST_F(BTBTAGEUpperBoundPathHashTest, PredictionUsesIndirectOverridePathHashSnapshot) {
BTBEntry entry = createBTBEntry(0x1000, true, true, false, -1, 0x2000);
entry.isIndirect = true;
const Addr indirectTarget = 0x3000;

ASSERT_NE(pathHash(entry.pc, entry.target), pathHash(entry.pc, indirectTarget));

boost::dynamic_bitset<> pathHistoryA(128, 0);
boost::dynamic_bitset<> pathHistoryB(128, 0);
applyPathHistoryTaken(pathHistoryB, entry.pc, indirectTarget);

ASSERT_TRUE(tage->insertExactEntry(2, entry.pc, pathHistoryB, 2));

FullBTBPrediction pred;
pred.btbEntries.push_back(entry);
pred.condTakens.push_back({entry.pc, true});
pred.indirectTargets.push_back({entry.pc, indirectTarget});

tage->specUpdatePHist(pathHistoryA, pred);
tage->checkFoldedHist(pathHistoryB, "indirect target override");

bool predicted = predictTAGE(tage, 0x1000, {entry}, outcomeHistory, stagePreds);

EXPECT_TRUE(predicted);
}

TEST_F(BTBTAGEUpperBoundPathHashTest, PredictionUsesReturnOverridePathHashSnapshot) {
BTBEntry entry = createBTBEntry(0x1000, true, true, false, -1, 0x2000);
entry.isIndirect = true;
entry.isReturn = true;
const Addr returnTarget = 0x3400;

ASSERT_NE(pathHash(entry.pc, entry.target), pathHash(entry.pc, returnTarget));

boost::dynamic_bitset<> pathHistoryA(128, 0);
boost::dynamic_bitset<> pathHistoryB(128, 0);
applyPathHistoryTaken(pathHistoryB, entry.pc, returnTarget);

ASSERT_TRUE(tage->insertExactEntry(2, entry.pc, pathHistoryB, 2));

FullBTBPrediction pred;
pred.btbEntries.push_back(entry);
pred.condTakens.push_back({entry.pc, true});
pred.returnTarget = returnTarget;

tage->specUpdatePHist(pathHistoryA, pred);
tage->checkFoldedHist(pathHistoryB, "return target override");

bool predicted = predictTAGE(tage, 0x1000, {entry}, outcomeHistory, stagePreds);

EXPECT_TRUE(predicted);
}


} // namespace test

Expand Down
Loading