Skip to content

Commit ca94910

Browse files
committed
bpu: abb BTBMGSC new unit tests (BwTable, ITable, BiasTable)
- Added new test cases to validate the learning of alternating patterns for different tables (BwTable, ITable, BiasTable). Change-Id: I2273e645f276fac9089581631001be0f4b37b5ca
1 parent ad08419 commit ca94910

File tree

2 files changed

+191
-2
lines changed

2 files changed

+191
-2
lines changed

src/cpu/pred/btb/btb_mgsc.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ BTBMGSC::initStorage()
116116
BTBMGSC::BTBMGSC()
117117
: TimedBaseBTBPredictor(),
118118
bwTableNum(1),
119-
bwTableIdxWidth(5),
119+
// Use a slightly larger idx width so foldedLen is not too small (helps pattern-learning tests).
120+
bwTableIdxWidth(6),
120121
bwHistLen({4}),
121122
numEntriesFirstLocalHistories(4),
122123
lTableNum(1),
@@ -126,7 +127,8 @@ BTBMGSC::BTBMGSC()
126127
iTableIdxWidth(5),
127128
// `ImliFoldedHist` requires foldedLen >= histLen. With `numCtrsPerLine=8` and `iTableIdxWidth=5`,
128129
// foldedLen is small (5 - log2(8) = 2), so keep histLen=1 for unit tests.
129-
iHistLen({1}),
130+
// Also keep it >= 2 so we can build loop-trip-count tests on IMLI.
131+
iHistLen({2}),
130132
gTableNum(1),
131133
// Use a slightly larger idx width so foldedLen is not too small (helps pattern-learning tests).
132134
gTableIdxWidth(6),

src/cpu/pred/btb/test/btb_mgsc.test.cc

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,45 @@ struct MgscHarness
152152
BTBMGSC::TestAccess::forceUseSC(mgsc) = true;
153153
}
154154

155+
void
156+
setOnlyBwTable()
157+
{
158+
BTBMGSC::TestAccess::enableBwTable(mgsc) = true;
159+
BTBMGSC::TestAccess::enableLTable(mgsc) = false;
160+
BTBMGSC::TestAccess::enableITable(mgsc) = false;
161+
BTBMGSC::TestAccess::enableGTable(mgsc) = false;
162+
BTBMGSC::TestAccess::enablePTable(mgsc) = false;
163+
BTBMGSC::TestAccess::enableBiasTable(mgsc) = false;
164+
BTBMGSC::TestAccess::enablePCThreshold(mgsc) = false;
165+
BTBMGSC::TestAccess::forceUseSC(mgsc) = true;
166+
}
167+
168+
void
169+
setOnlyITable()
170+
{
171+
BTBMGSC::TestAccess::enableBwTable(mgsc) = false;
172+
BTBMGSC::TestAccess::enableLTable(mgsc) = false;
173+
BTBMGSC::TestAccess::enableITable(mgsc) = true;
174+
BTBMGSC::TestAccess::enableGTable(mgsc) = false;
175+
BTBMGSC::TestAccess::enablePTable(mgsc) = false;
176+
BTBMGSC::TestAccess::enableBiasTable(mgsc) = false;
177+
BTBMGSC::TestAccess::enablePCThreshold(mgsc) = false;
178+
BTBMGSC::TestAccess::forceUseSC(mgsc) = true;
179+
}
180+
181+
void
182+
setOnlyBiasTable()
183+
{
184+
BTBMGSC::TestAccess::enableBwTable(mgsc) = false;
185+
BTBMGSC::TestAccess::enableLTable(mgsc) = false;
186+
BTBMGSC::TestAccess::enableITable(mgsc) = false;
187+
BTBMGSC::TestAccess::enableGTable(mgsc) = false;
188+
BTBMGSC::TestAccess::enablePTable(mgsc) = false;
189+
BTBMGSC::TestAccess::enableBiasTable(mgsc) = true;
190+
BTBMGSC::TestAccess::enablePCThreshold(mgsc) = false;
191+
BTBMGSC::TestAccess::forceUseSC(mgsc) = true;
192+
}
193+
155194
struct StepResult
156195
{
157196
bool predicted_taken{false};
@@ -227,6 +266,9 @@ struct MgscHarness
227266
FetchStream recover_stream;
228267
recover_stream.startPC = start_pc;
229268
recover_stream.predMetas[mgsc.getComponentIdx()] = meta;
269+
recover_stream.resolved = true;
270+
recover_stream.exeBranchInfo = entry;
271+
recover_stream.exeTaken = actual_taken;
230272

231273
mgsc.recoverHist(ghr, recover_stream, shamt, actual_taken);
232274
mgsc.recoverPHist(phr, recover_stream, 2, actual_taken);
@@ -509,6 +551,151 @@ TEST(BTBMGSCTest, GTableLearnsAlternatingPattern)
509551
EXPECT_GE(acc, 0.80) << "Accuracy too low for alternating pattern: " << acc;
510552
}
511553

554+
TEST(BTBMGSCTest, BwTableLearnsAlternatingPatternOnBackwardBranches)
555+
{
556+
MgscHarness h;
557+
h.setOnlyBwTable();
558+
559+
const Addr start_pc = 0x1000;
560+
const Addr branch_pc = 0x1000;
561+
auto entry = makeCondBTBEntry(branch_pc);
562+
entry.target = branch_pc - 4; // backward branch so bw_taken == taken
563+
564+
const TageInfoForMGSC tage_info(
565+
/*tage_pred_taken=*/false,
566+
/*tage_main_taken=*/false,
567+
/*tage_pred_conf_high=*/true,
568+
/*tage_pred_conf_mid=*/false,
569+
/*tage_pred_conf_low=*/false,
570+
/*tage_pred_alt_diff=*/false);
571+
572+
const int iters = 200;
573+
const int warmup = 100;
574+
int correct_after_warmup = 0;
575+
int total_after_warmup = 0;
576+
std::set<unsigned> seen_bw_indices;
577+
578+
for (int i = 0; i < iters; ++i) {
579+
bool actual_taken = (i % 2) == 0;
580+
auto step = h.step(start_pc, entry, tage_info, actual_taken);
581+
582+
if (!step.mgsc_pred.bwIndex.empty()) {
583+
seen_bw_indices.insert(step.mgsc_pred.bwIndex[0]);
584+
}
585+
586+
if (i >= warmup) {
587+
total_after_warmup++;
588+
if (step.predicted_taken == actual_taken) {
589+
correct_after_warmup++;
590+
}
591+
}
592+
}
593+
594+
EXPECT_GE(seen_bw_indices.size(), 2u);
595+
double acc = static_cast<double>(correct_after_warmup) / static_cast<double>(total_after_warmup);
596+
EXPECT_GE(acc, 0.80) << "Accuracy too low for alternating backward branches: " << acc;
597+
}
598+
599+
TEST(BTBMGSCTest, ITableLearnsFixedTripCountLoop)
600+
{
601+
MgscHarness h;
602+
h.setOnlyITable();
603+
604+
const Addr start_pc = 0x1000;
605+
const Addr branch_pc = 0x1000;
606+
auto entry = makeCondBTBEntry(branch_pc);
607+
entry.target = branch_pc - 4; // backward loop branch
608+
609+
const TageInfoForMGSC tage_info(
610+
/*tage_pred_taken=*/false,
611+
/*tage_main_taken=*/false,
612+
/*tage_pred_conf_high=*/true,
613+
/*tage_pred_conf_mid=*/false,
614+
/*tage_pred_conf_low=*/false,
615+
/*tage_pred_alt_diff=*/false);
616+
617+
// Loop pattern: T, T, T, N, repeat. IMLI counter (consecutive backward-taken count) should separate phases.
618+
const int iters = 400;
619+
const int warmup = 200;
620+
int correct_after_warmup = 0;
621+
int total_after_warmup = 0;
622+
std::set<unsigned> seen_i_indices;
623+
624+
for (int i = 0; i < iters; ++i) {
625+
bool actual_taken = (i % 4) != 3;
626+
auto step = h.step(start_pc, entry, tage_info, actual_taken);
627+
628+
if (!step.mgsc_pred.iIndex.empty()) {
629+
seen_i_indices.insert(step.mgsc_pred.iIndex[0]);
630+
}
631+
632+
if (i >= warmup) {
633+
total_after_warmup++;
634+
if (step.predicted_taken == actual_taken) {
635+
correct_after_warmup++;
636+
}
637+
}
638+
}
639+
640+
EXPECT_GE(seen_i_indices.size(), 3u);
641+
double acc = static_cast<double>(correct_after_warmup) / static_cast<double>(total_after_warmup);
642+
EXPECT_GE(acc, 0.85) << "Accuracy too low for fixed-trip loop: " << acc;
643+
}
644+
645+
TEST(BTBMGSCTest, BiasTableLearnsTwoTageContexts)
646+
{
647+
MgscHarness h;
648+
h.setOnlyBiasTable();
649+
650+
const Addr start_pc = 0x1000;
651+
const Addr branch_pc = 0x1000;
652+
auto entry = makeCondBTBEntry(branch_pc);
653+
654+
// Two contexts keyed by (tage_main_taken, tage_pred_conf_low). Bias table should learn separate counters.
655+
const TageInfoForMGSC ctx_a(
656+
/*tage_pred_taken=*/false,
657+
/*tage_main_taken=*/false,
658+
/*tage_pred_conf_high=*/false,
659+
/*tage_pred_conf_mid=*/false,
660+
/*tage_pred_conf_low=*/false,
661+
/*tage_pred_alt_diff=*/false);
662+
const TageInfoForMGSC ctx_b(
663+
/*tage_pred_taken=*/false,
664+
/*tage_main_taken=*/true,
665+
/*tage_pred_conf_high=*/false,
666+
/*tage_pred_conf_mid=*/false,
667+
/*tage_pred_conf_low=*/true,
668+
/*tage_pred_alt_diff=*/false);
669+
670+
const int iters = 200;
671+
const int warmup = 100;
672+
int correct_after_warmup = 0;
673+
int total_after_warmup = 0;
674+
std::set<unsigned> seen_bias_indices;
675+
676+
for (int i = 0; i < iters; ++i) {
677+
bool use_a = (i % 2) == 0;
678+
const auto &tage_info = use_a ? ctx_a : ctx_b;
679+
bool actual_taken = use_a; // ctx_a => taken, ctx_b => not taken
680+
681+
auto step = h.step(start_pc, entry, tage_info, actual_taken);
682+
if (!step.mgsc_pred.biasIndex.empty()) {
683+
seen_bias_indices.insert(step.mgsc_pred.biasIndex[0]);
684+
}
685+
686+
if (i >= warmup) {
687+
total_after_warmup++;
688+
if (step.predicted_taken == actual_taken) {
689+
correct_after_warmup++;
690+
}
691+
}
692+
}
693+
694+
EXPECT_GE(seen_bias_indices.size(), 2u);
695+
double acc = static_cast<double>(correct_after_warmup) / static_cast<double>(total_after_warmup);
696+
EXPECT_GE(acc, 0.90) << "Accuracy too low for two-context bias learning: " << acc;
697+
}
698+
512699
} // namespace test
513700
} // namespace btb_pred
514701
} // namespace branch_prediction

0 commit comments

Comments
 (0)