diff --git a/configs/common/xiangshan.py b/configs/common/xiangshan.py index 6abcd5ea39..295d87c053 100644 --- a/configs/common/xiangshan.py +++ b/configs/common/xiangshan.py @@ -881,6 +881,12 @@ def xiangshan_system_init(): default=False, help="Use BTBTAGEUpperBound in kmhv3 instead of the default BTBTAGE", ) + parser.add_argument( + "--standalone-sc", + action="store_true", + default=False, + help="Disable direction TAGE sources in kmhv3 and force MGSC standalone SC prediction", + ) # Add the ruby specific and protocol specific args if '--ruby' in sys.argv: diff --git a/configs/example/kmhv3.py b/configs/example/kmhv3.py index 48bbe80b75..639b35ce78 100644 --- a/configs/example/kmhv3.py +++ b/configs/example/kmhv3.py @@ -113,6 +113,13 @@ def setKmhV3Params(args, system): cpu.branchPred.mgsc.enabled = True cpu.branchPred.ras.enabled = True + if getattr(args, 'standalone_sc', False): + cpu.branchPred.microtage.enabled = False + cpu.branchPred.tage.enabled = False + + cpu.branchPred.mgsc.forceUseSC = True + cpu.branchPred.mgsc.allowMissingTageInfo = True + # l1 cache per core if args.caches: cpu.icache.size = '64kB' diff --git a/src/base/gtest/serialization_fixture.hh b/src/base/gtest/serialization_fixture.hh index 65269e094c..4af5e44b60 100644 --- a/src/base/gtest/serialization_fixture.hh +++ b/src/base/gtest/serialization_fixture.hh @@ -27,6 +27,7 @@ */ #include +#include #include #include @@ -68,7 +69,8 @@ class SerializationFixture : public ::testing::Test static std::string generateTempDirName() { - return "/tmp/temp_dir_test" + std::to_string(dirNumber++) + "/"; + return "/tmp/temp_dir_test_" + std::to_string(getpid()) + "_" + + std::to_string(dirNumber++) + "/"; } /** Get the name of the directory we have created on SetUp. */ diff --git a/src/cpu/pred/BranchPredictor.py b/src/cpu/pred/BranchPredictor.py index c09b2c16ce..e18d26daf2 100644 --- a/src/cpu/pred/BranchPredictor.py +++ b/src/cpu/pred/BranchPredictor.py @@ -1174,6 +1174,8 @@ class BTBMGSC(TimedBaseBTBPredictor): # Test switches for SC tables forceUseSC = Param.Bool(False, "Force use SC prediction, ignore TAGE confidence") + allowMissingTageInfo = Param.Bool( + False, "Allow MGSC to run with default TAGE metadata when TAGE info is unavailable") enableBwTable = Param.Bool(True, "Enable BW (backward) table") enableLTable = Param.Bool(False, "Enable L (local) table") enableITable = Param.Bool(True, "Enable I (IMLI) table") diff --git a/src/cpu/pred/btb/btb_mgsc.cc b/src/cpu/pred/btb/btb_mgsc.cc index 2fa390bffe..db887be7c2 100755 --- a/src/cpu/pred/btb/btb_mgsc.cc +++ b/src/cpu/pred/btb/btb_mgsc.cc @@ -1,6 +1,7 @@ #include "cpu/pred/btb/btb_mgsc.hh" #include "base/intmath.hh" +#include "base/logging.hh" #ifdef UNIT_TEST #include "cpu/pred/btb/test/test_dprintf.hh" @@ -173,6 +174,7 @@ BTBMGSC::BTBMGSC() // This models "read a whole SRAM line, then pick a lane" behavior in `posHash()`. numCtrsPerLine(8), forceUseSC(false), + allowMissingTageInfo(false), enableBwTable(true), enableLTable(true), enableITable(true), @@ -217,6 +219,7 @@ BTBMGSC::BTBMGSC(const Params &p) weightTableIdxWidth(p.weightTableIdxWidth), numCtrsPerLine(p.numCtrsPerLine), forceUseSC(p.forceUseSC), + allowMissingTageInfo(p.allowMissingTageInfo), enableBwTable(p.enableBwTable), enableLTable(p.enableLTable), enableITable(p.enableITable), @@ -282,14 +285,19 @@ BTBMGSC::setTrace() std::make_pair("totalThres", UINT64), std::make_pair("effectiveGate", UINT64), std::make_pair("margin", UINT64), - std::make_pair("bwIndexSig", UINT64), - std::make_pair("lIndexSig", UINT64), - std::make_pair("iIndexSig", UINT64), - std::make_pair("gIndexSig", UINT64), - std::make_pair("pIndexSig", UINT64), - std::make_pair("biasIndexSig", UINT64), + std::make_pair("bwIndex0", UINT64), + std::make_pair("bwIndex1", UINT64), + std::make_pair("lIndex0", UINT64), + std::make_pair("lIndex1", UINT64), + std::make_pair("iIndex0", UINT64), + std::make_pair("gIndex0", UINT64), + std::make_pair("gIndex1", UINT64), + std::make_pair("pIndex0", UINT64), + std::make_pair("pIndex1", UINT64), + std::make_pair("biasIndex0", UINT64), std::make_pair("useSc", UINT64), std::make_pair("scPred", UINT64), + std::make_pair("scWrong", UINT64), std::make_pair("actualTaken", UINT64), }; mgscMissTrace = _db->addAndGetTrace("MGSCTRACE", fields_vec); @@ -542,15 +550,18 @@ BTBMGSC::lookupHelper(const Addr &startPC, const std::vector &btbEntri // Only predict for valid conditional branches if (btb_entry.isCond && btb_entry.valid) { auto tage_info = tageInfoForMgscs.find(btb_entry.pc); - if (tage_info != tageInfoForMgscs.end()) { - auto pred = generateSinglePrediction(btb_entry, startPC, - tage_info->second, tid, - asidHash); - threadMeta[tid]->preds[btb_entry.pc] = pred; - results.push_back({btb_entry.pc, pred.taken || btb_entry.alwaysTaken}); - } else { - assert(false); - } + panic_if(tage_info == tageInfoForMgscs.end() && !allowMissingTageInfo, + "MGSC missing TAGE info for conditional branch pc %#lx " + "startPC %#lx tid %u asidHash %#x", + btb_entry.pc, startPC, static_cast(tid), + static_cast(asidHash)); + + const TageInfoForMGSC missing_tage_info; + const auto &info = + tage_info != tageInfoForMgscs.end() ? tage_info->second : missing_tage_info; + auto pred = generateSinglePrediction(btb_entry, startPC, info, tid, asidHash); + threadMeta[tid]->preds[btb_entry.pc] = pred; + results.push_back({btb_entry.pc, pred.taken || btb_entry.alwaysTaken}); } } } @@ -861,12 +872,8 @@ BTBMGSC::updateSinglePredictor(const BTBEntry &entry, bool actual_taken, const M auto effective_gate = pred.tage_conf_high ? (total_thres / 2) : (pred.tage_conf_mid ? (total_thres / 4) : (total_thres / 8)); auto margin = std::abs(total_sum) - effective_gate; - auto foldIndexSig = [](const std::vector &indices) -> uint64_t { - uint64_t sig = 0xcbf29ce484222325ULL; - for (auto idx : indices) { - sig ^= static_cast(idx) + 0x9e3779b97f4a7c15ULL + (sig << 6) + (sig >> 2); - } - return sig; + auto indexAt = [](const std::vector &indices, size_t idx) -> uint64_t { + return idx < indices.size() ? indices[idx] : 0; }; MgscTrace t; t.set(entry.pc, @@ -875,9 +882,13 @@ BTBMGSC::updateSinglePredictor(const BTBEntry &entry, bool actual_taken, const M pred.bw_percsum, pred.l_percsum, pred.i_percsum, pred.g_percsum, pred.p_percsum, pred.bias_percsum, total_sum, total_thres, effective_gate, margin, - foldIndexSig(pred.bwIndex), foldIndexSig(pred.lIndex), foldIndexSig(pred.iIndex), - foldIndexSig(pred.gIndex), foldIndexSig(pred.pIndex), foldIndexSig(pred.biasIndex), - use_mgsc, sc_pred_taken, + indexAt(pred.bwIndex, 0), indexAt(pred.bwIndex, 1), + indexAt(pred.lIndex, 0), indexAt(pred.lIndex, 1), + indexAt(pred.iIndex, 0), + indexAt(pred.gIndex, 0), indexAt(pred.gIndex, 1), + indexAt(pred.pIndex, 0), indexAt(pred.pIndex, 1), + indexAt(pred.biasIndex, 0), + use_mgsc, sc_pred_taken, sc_pred_taken != actual_taken, actual_taken); mgscMissTrace->write_record(t); } diff --git a/src/cpu/pred/btb/btb_mgsc.hh b/src/cpu/pred/btb/btb_mgsc.hh index 0bd0bb387f..d07319e928 100755 --- a/src/cpu/pred/btb/btb_mgsc.hh +++ b/src/cpu/pred/btb/btb_mgsc.hh @@ -361,6 +361,7 @@ class BTBMGSC : public TimedBaseBTBPredictor // Test switches for SC tables bool forceUseSC; + bool allowMissingTageInfo; bool enableBwTable; bool enableLTable; bool enableITable; @@ -537,6 +538,7 @@ class BTBMGSC : public TimedBaseBTBPredictor static unsigned biasTableIdxWidth(const BTBMGSC &mgsc) { return mgsc.biasTableIdxWidth; } static bool &forceUseSC(BTBMGSC &mgsc) { return mgsc.forceUseSC; } + static bool &allowMissingTageInfo(BTBMGSC &mgsc) { return mgsc.allowMissingTageInfo; } static bool &enableBwTable(BTBMGSC &mgsc) { return mgsc.enableBwTable; } static bool &enableLTable(BTBMGSC &mgsc) { return mgsc.enableLTable; } static bool &enableITable(BTBMGSC &mgsc) { return mgsc.enableITable; } diff --git a/src/cpu/pred/btb/common.hh b/src/cpu/pred/btb/common.hh index 2a25540bd9..b05a07fd84 100644 --- a/src/cpu/pred/btb/common.hh +++ b/src/cpu/pred/btb/common.hh @@ -813,9 +813,13 @@ struct MgscTrace : public Record int64_t gPercsum, int64_t pPercsum, int64_t biasPercsum, // SC decision int64_t totalSum, int64_t totalThres, int64_t effectiveGate, int64_t margin, - uint64_t bwIndexSig, uint64_t lIndexSig, uint64_t iIndexSig, - uint64_t gIndexSig, uint64_t pIndexSig, uint64_t biasIndexSig, - uint64_t useSc, uint64_t scPred, + uint64_t bwIndex0, uint64_t bwIndex1, + uint64_t lIndex0, uint64_t lIndex1, + uint64_t iIndex0, + uint64_t gIndex0, uint64_t gIndex1, + uint64_t pIndex0, uint64_t pIndex1, + uint64_t biasIndex0, + uint64_t useSc, uint64_t scPred, uint64_t scWrong, // Result uint64_t actualTaken) { @@ -840,14 +844,19 @@ struct MgscTrace : public Record _uint64_data["totalThres"] = static_cast(totalThres); _uint64_data["effectiveGate"] = static_cast(effectiveGate); _uint64_data["margin"] = static_cast(margin); - _uint64_data["bwIndexSig"] = bwIndexSig; - _uint64_data["lIndexSig"] = lIndexSig; - _uint64_data["iIndexSig"] = iIndexSig; - _uint64_data["gIndexSig"] = gIndexSig; - _uint64_data["pIndexSig"] = pIndexSig; - _uint64_data["biasIndexSig"] = biasIndexSig; + _uint64_data["bwIndex0"] = bwIndex0; + _uint64_data["bwIndex1"] = bwIndex1; + _uint64_data["lIndex0"] = lIndex0; + _uint64_data["lIndex1"] = lIndex1; + _uint64_data["iIndex0"] = iIndex0; + _uint64_data["gIndex0"] = gIndex0; + _uint64_data["gIndex1"] = gIndex1; + _uint64_data["pIndex0"] = pIndex0; + _uint64_data["pIndex1"] = pIndex1; + _uint64_data["biasIndex0"] = biasIndex0; _uint64_data["useSc"] = useSc; _uint64_data["scPred"] = scPred; + _uint64_data["scWrong"] = scWrong; // Result _uint64_data["actualTaken"] = actualTaken; } diff --git a/src/cpu/pred/btb/test/btb_mgsc.test.cc b/src/cpu/pred/btb/test/btb_mgsc.test.cc index 34d5142625..05901cff82 100644 --- a/src/cpu/pred/btb/test/btb_mgsc.test.cc +++ b/src/cpu/pred/btb/test/btb_mgsc.test.cc @@ -730,6 +730,51 @@ TEST(BTBMGSCTest, BiasTableLearnsTwoTageContexts) EXPECT_GE(acc, 0.90) << "Accuracy too low for two-context bias learning: " << acc; } +TEST(BTBMGSCTest, MissingTageInfoUsesDefaultFallbackContext) +{ + MgscHarness h; + h.setOnlyBiasTable(); + BTBMGSC::TestAccess::allowMissingTageInfo(h.mgsc) = true; + + const TageInfoForMGSC fallback_ctx; + + const Addr start_pc = 0x1000; + const Addr branch_pc = 0x1000; + auto entry = makeCondBTBEntry(branch_pc); + + setAllTableCountersForPc(h.mgsc, start_pc, branch_pc, fallback_ctx, + /*bw=*/0, /*l=*/0, /*i=*/0, /*g=*/0, /*p=*/0, + /*bias=*/4); + + boost::dynamic_bitset<> history(64, 0); + std::vector stage_preds(2); + for (auto &pred : stage_preds) { + pred.bbStart = start_pc; + pred.btbEntries = {entry}; + pred.tageInfoForMgscs.clear(); + } + + h.mgsc.putPCHistory(start_pc, history, stage_preds); + + auto [found, taken] = findCondTaken(stage_preds[1].condTakens, branch_pc); + ASSERT_TRUE(found); + EXPECT_TRUE(taken); + + const auto &preds = BTBMGSC::TestAccess::preds(h.mgsc); + auto it = preds.find(branch_pc); + ASSERT_NE(it, preds.end()); + EXPECT_TRUE(it->second.use_mgsc); + EXPECT_FALSE(it->second.taken_before_sc); + EXPECT_FALSE(it->second.tage_conf_low); + + const auto [expected_bias_idx, _] = + lineLaneForBiasIndex(h.mgsc, start_pc, branch_pc, + BTBMGSC::TestAccess::biasTableIdxWidth(h.mgsc), + fallback_ctx); + ASSERT_FALSE(it->second.biasIndex.empty()); + EXPECT_EQ(it->second.biasIndex[0], expected_bias_idx); +} + TEST(BTBMGSCTest, LTableLearnsTwoIndependentLocalHistories) { MgscHarness h;