diff --git a/docs/Gem5_Docs/frontend/mgsc_notes.md b/docs/Gem5_Docs/frontend/mgsc_notes.md new file mode 100644 index 0000000000..0423f8c7a7 --- /dev/null +++ b/docs/Gem5_Docs/frontend/mgsc_notes.md @@ -0,0 +1,54 @@ +# MGSC 预测器备忘 + +面向本仓库 BTB 侧的 MGSC(Multi-Geometric Statistical Corrector)总结:设计特点、关键结构、改进思路、统计计数器、以及便于验证的敏感小测试。 + +## 1. MGSC 设计要点 +- 核心角色:TAGE 做“主判官”,MGSC 做“量化纠错”。MGSC 拿到 TAGE 的预测与置信度后,基于多类独立的历史特征表(几何长度)求和,给出一个带权的分数;只有当分数绝对值高于动态阈值时才覆盖 TAGE,否则保持原判。 +- 特征多样性(降维防冲突): + - **G** 全局方向历史:捕获长程相关; + - **P** 路径历史:区分同一分支的不同来路; + - **L** 局部(per-PC)历史:解决每个分支的重复模式; + - **BW** 后向历史:强化循环/尾递归偏好; + - **I/IMLI** 迭代计数:对“第 N 次迭代取反”类模式敏感; + - **Bias** 静态偏置:兜底偏好。 + 这些表使用折叠历史压缩到较短索引位宽,降低端口和存储压力,同时减少与 TAGE 的直接结构耦合。 +- 决策与门控:各表计数器 percsum 做线性求和,并用简化权重(1x/2x 档)缩放,合成 `total_sum`。阈值由全局+PC 两级组成,并根据 TAGE 置信度动态放宽/收紧(高/中/低置信度对应 |sum| > thres/2, /4, /8)。这样在 TAGE 自信时,需要更强证据才覆盖。 +- 自适应更新:仅在 SC 预测错或低置信时更新,避免破坏已稳定的正确判决;权重只在“该表是否关键到翻转决策”时调整;阈值在 SC 与真实冲突时上调,吻合时下调,使覆盖策略自动收敛到合适激进度。 + +## 2. 关键数据结构(参考 `src/cpu/pred/btb/btb_mgsc.hh/.cc`) +- `MgscPrediction`:一次预测的完整快照,包含: + - 总分 `total_sum`,是否使用 MGSC (`use_mgsc`),最终 taken 判定; + - TAGE 原始预测与置信度(高/中/低); + - 各表索引、raw/scaled percsum、`weight_scale_diff`(权重翻倍/归零是否翻转决策)、组合阈值。 + 这些字段既驱动训练,也被统计模块消费。 +- 折叠历史:`index{G,P,Bw,L,I}FoldedHist`,把长历史折叠成较短索引用;Bias 索引还混入 TAGE 主预测、低置信标志,形成轻量级“条件偏置”。 +- 预测与权重表:六类计数器矩阵 `bw/l/i/g/p/biasTable[table][index][way]`,存储方向倾向;对应的 `*_WeightTable[index]` 只用 PC hash,提供 1x/2x 缩放权重(-32..31,经简化映射)。 +- 阈值:全局 `updateThreshold`(单计数器)+ PC 表 `pUpdateThreshold`(按 PC hash 的多计数器),共同决定覆盖门槛,随误差自适应。 +- 元数据:`MgscMeta` 在 fetch 时缓存预测与折叠历史,用于后续恢复/回滚,保证推测一致性。 + +## 3. 新增统计计数器及含义(已合入) +路径:`system.cpu.branchPred.mgsc.*` +- SC/TAGE 关系:`scCorrectTageWrong`、`scWrongTageCorrect`、`scCorrectTageCorrect`、`scWrongTageWrong`、`scUsed`、`scNotUsed`、`scPredCorrect/Wrong`、`predHit/Miss`。 +- 权重关键性:`*WeightScaleDiff`(bw/l/i/g/p/bias)——该表权重翻倍/去掉会翻转决策的次数。 +- Raw percsum 符号正确率:`*PercsumCorrect/Wrong` —— 该表自身方向是否与真实一致。 +- 阈值方向:`pcThresholdInc/Dec`、`globalThresholdInc/Dec` —— SC 与真实冲突多则递增,反之递减。 +- 按 TAGE 置信度分桶的 SC 使用/绕过:`scHigh/Mid/LowUseCorrect/Wrong`、`scHigh/Mid/LowBypass`。 + +解读小贴士: +- 某表 `WeightScaleDiff` 高且 `PercsumCorrect` 高:表在“起关键作用”。若后者低,则可能误导。 +- `pc/globalThresholdDec` ≫ `Inc`:SC 表现好,门槛在下降;反之说明冲突多。 +- `scCorrectTageWrong` ≫ `scWrongTageCorrect`:SC 对 TAGE 有正纠错价值。 + +## 4. 改进方向(未实现,仅供参考) +1) 权重档位更细(0.5/1/1.5/2 等),提升相关性刻画精度。 +2) 权重表索引加入部分历史哈希(而非仅 PC),降低别名。 +3) 阈值更新考虑 TAGE 置信度(高置信错时更快抬阈,低置信错时慢抬),减少误覆盖。 +4) 更丰富的可观测性:按表/置信度输出热分支热点,或导出 per-PC 纠错热度。 + +## 5. MGSC 敏感小测试(C 版,放在 'nexus-am/tests/frontendtest/mgsc_test/tests/`) +已提供源码,可按现有 Makefile 通配编译: +- `long_period_flip.c`:长周期偶发翻转 + 噪声。期望 I/G/P 纠偏远距稀疏翻转。 +- `xor_dependency.c`:B2 方向 = 上一轮 B0^B1,跨分支相关。期望路径/局部/全局组合纠错。 +- `alias_many_branches.c`:16 个相邻分支,各有不同小周期,制造索引/标签冲突。期望 MGSC 通过局部/路径缓解别名。 + +使用建议:开/关 MGSC 对比 `condMiss`、`mgsc.scCorrectTageWrong/scWrongTageCorrect`、各表 `*PercsumWrong` 与阈值增减,定位是哪类表在纠错或噪声。必要时可缩短 TAGE 历史或减小表尺寸以放大差异。 diff --git a/src/cpu/pred/BranchPredictor.py b/src/cpu/pred/BranchPredictor.py index 297b7a92b0..44e58c7015 100644 --- a/src/cpu/pred/BranchPredictor.py +++ b/src/cpu/pred/BranchPredictor.py @@ -1146,6 +1146,16 @@ class BTBMGSC(TimedBaseBTBPredictor): # How many counters readed per prediction (usually per cycle) numCtrsPerLine = Param.Unsigned(8, "Counters per SRAM line") + # Test switches for SC tables + forceUseSC = Param.Bool(False, "Force use SC prediction, ignore TAGE confidence") + enableBwTable = Param.Bool(True, "Enable BW (backward) table") + enableLTable = Param.Bool(True, "Enable L (local) table") + enableITable = Param.Bool(True, "Enable I (IMLI) table") + enableGTable = Param.Bool(True, "Enable G (global) table") + enablePTable = Param.Bool(True, "Enable P (path) table") + enableBiasTable = Param.Bool(True, "Enable Bias table") + enablePCThreshold = Param.Bool(False, "Enable PC-indexed threshold table") + numDelay = 2 class DecoupledBPUWithBTB(BranchPredictor): diff --git a/src/cpu/pred/btb/btb_mgsc.cc b/src/cpu/pred/btb/btb_mgsc.cc index b0bcc0c5bd..a7d32137a1 100755 --- a/src/cpu/pred/btb/btb_mgsc.cc +++ b/src/cpu/pred/btb/btb_mgsc.cc @@ -52,6 +52,14 @@ BTBMGSC::BTBMGSC(const Params &p) extraWeightsWidth(p.extraWeightsWidth), weightTableIdxWidth(p.weightTableIdxWidth), numCtrsPerLine(p.numCtrsPerLine), + forceUseSC(p.forceUseSC), + enableBwTable(p.enableBwTable), + enableLTable(p.enableLTable), + enableITable(p.enableITable), + enableGTable(p.enableGTable), + enablePTable(p.enablePTable), + enableBiasTable(p.enableBiasTable), + enablePCThreshold(p.enablePCThreshold), mgscStats(this) { DPRINTF(MGSC, "BTBMGSC constructor\n"); @@ -128,14 +136,40 @@ BTBMGSC::BTBMGSC(const Params &p) pUpdateThreshold.resize(std::pow(2, thresholdTablelogSize)); updateThreshold = 35 * 8; -} + hasDB = true; + dbName = std::string("mgsc"); +} BTBMGSC::~BTBMGSC() {} // Set up tracing for debugging void BTBMGSC::setTrace() { +#ifndef UNIT_TEST + if (enableDB) { + std::vector> fields_vec = { + std::make_pair("branchPC", UINT64), + std::make_pair("tagePred", UINT64), + std::make_pair("tageConfHigh", UINT64), + std::make_pair("tageConfMid", UINT64), + std::make_pair("tageConfLow", UINT64), + std::make_pair("bwPercsum", UINT64), + std::make_pair("lPercsum", UINT64), + std::make_pair("iPercsum", UINT64), + std::make_pair("gPercsum", UINT64), + std::make_pair("pPercsum", UINT64), + std::make_pair("biasPercsum", UINT64), + std::make_pair("totalSum", UINT64), + std::make_pair("totalThres", UINT64), + std::make_pair("useSc", UINT64), + std::make_pair("scPred", UINT64), + std::make_pair("actualTaken", UINT64), + }; + mgscMissTrace = _db->addAndGetTrace("MGSCTRACE", fields_vec); + mgscMissTrace->init_table(); + } +#endif } void @@ -151,12 +185,13 @@ BTBMGSC::tickStart() /** * Calculate perceptron sum from a table for a given PC - * perceptron sum is the sum of the (2*counter + 1) of the matching entries + * Counter range: [-2^(w-1), 2^(w-1)-1], e.g., [-32, 31] for w=6 + * Percsum = sum of (2*counter + 1), transforms to odd numbers, e.g., [-63, 63] per entry * @param table The table to search in * @param tableIndices Indices to use for each table component * @param numTables Number of tables to search * @param pc PC to match against - * @return Calculated percsum value + * @return Calculated percsum value (positive=taken bias, negative=not-taken bias) */ int BTBMGSC::calculatePercsum(const std::vector>> &table, @@ -166,7 +201,7 @@ BTBMGSC::calculatePercsum(const std::vector>> & for (unsigned int i = 0; i < numTables; ++i) { auto [idx1, idx2] = posHash(pc, tableIndices[i]); auto &entry = table[i][idx1][idx2]; - percsum += (2 * entry + 1); // align to zero center + percsum += (2 * entry + 1); // transform to odd numbers, avoid zero } return percsum; } @@ -187,17 +222,11 @@ BTBMGSC::findWeight(const std::vector &weightTable, Addr pc) return entry; } -/** - * Calculate scaled percsum using weight - * weight range is [-32, 31], return value range is percsum or 2x percsum - * @param weight Weight value - * @param percsum Original percsum value - * @return Scaled percsum value - */ + int BTBMGSC::calculateScaledPercsum(int weight, int percsum) { - return ((weight + 64) / 32) * percsum; + return percsum; // disable weight scaling for test } /** @@ -273,27 +302,27 @@ BTBMGSC::generateSinglePrediction(const BTBEntry &btb_entry, const Addr &startPC tage_info.tage_pred_conf_low); } - int bw_percsum = calculatePercsum(bwTable, bwIndex, bwTableNum, btb_entry.pc); + int bw_percsum = enableBwTable ? calculatePercsum(bwTable, bwIndex, bwTableNum, btb_entry.pc) : 0; int bw_weight = findWeight(bwWeightTable, btb_entry.pc); int bw_scaled_percsum = calculateScaledPercsum(bw_weight, bw_percsum); - int l_percsum = calculatePercsum(lTable, lIndex, lTableNum, btb_entry.pc); + int l_percsum = enableLTable ? calculatePercsum(lTable, lIndex, lTableNum, btb_entry.pc) : 0; int l_weight = findWeight(lWeightTable, btb_entry.pc); int l_scaled_percsum = calculateScaledPercsum(l_weight, l_percsum); - int i_percsum = calculatePercsum(iTable, iIndex, iTableNum, btb_entry.pc); + int i_percsum = enableITable ? calculatePercsum(iTable, iIndex, iTableNum, btb_entry.pc) : 0; int i_weight = findWeight(iWeightTable, btb_entry.pc); int i_scaled_percsum = calculateScaledPercsum(i_weight, i_percsum); - int g_percsum = calculatePercsum(gTable, gIndex, gTableNum, btb_entry.pc); + int g_percsum = enableGTable ? calculatePercsum(gTable, gIndex, gTableNum, btb_entry.pc) : 0; int g_weight = findWeight(gWeightTable, btb_entry.pc); int g_scaled_percsum = calculateScaledPercsum(g_weight, g_percsum); - int p_percsum = calculatePercsum(pTable, pIndex, pTableNum, btb_entry.pc); + int p_percsum = enablePTable ? calculatePercsum(pTable, pIndex, pTableNum, btb_entry.pc) : 0; int p_weight = findWeight(pWeightTable, btb_entry.pc); int p_scaled_percsum = calculateScaledPercsum(p_weight, p_percsum); - int bias_percsum = calculatePercsum(biasTable, biasIndex, biasTableNum, btb_entry.pc); + int bias_percsum = enableBiasTable ? calculatePercsum(biasTable, biasIndex, biasTableNum, btb_entry.pc) : 0; int bias_weight = findWeight(biasWeightTable, btb_entry.pc); int bias_scaled_percsum = calculateScaledPercsum(bias_weight, bias_percsum); @@ -302,23 +331,25 @@ BTBMGSC::generateSinglePrediction(const BTBEntry &btb_entry, const Addr &startPC bias_scaled_percsum; // Find thresholds - // pc-indexed threshold table - int p_update_thres = findThreshold(pUpdateThreshold, btb_entry.pc); + // pc-indexed threshold table (only if enabled) + int p_update_thres = enablePCThreshold ? findThreshold(pUpdateThreshold, btb_entry.pc) : 0; int total_thres = (updateThreshold / 8) + p_update_thres; - bool use_sc_pred = false; - if (tage_info.tage_pred_conf_high) { - if (abs(total_sum) > total_thres / 2) { - use_sc_pred = true; - } - } else if (tage_info.tage_pred_conf_mid) { - if (abs(total_sum) > total_thres / 4) { - use_sc_pred = true; - } - } else if (tage_info.tage_pred_conf_low) { - if (abs(total_sum) > total_thres / 8) { - use_sc_pred = true; + bool use_sc_pred = forceUseSC; // Force use SC if configured + if (!use_sc_pred) { + if (tage_info.tage_pred_conf_high) { + if (abs(total_sum) > total_thres / 2) { + use_sc_pred = true; + } + } else if (tage_info.tage_pred_conf_mid) { + if (abs(total_sum) > total_thres / 4) { + use_sc_pred = true; + } + } else if (tage_info.tage_pred_conf_low) { + if (abs(total_sum) > total_thres / 8) { + use_sc_pred = true; + } } } // Final prediction, total_sum >= 0 means taken if use_sc_pred @@ -334,10 +365,11 @@ BTBMGSC::generateSinglePrediction(const BTBEntry &btb_entry, const Addr &startPC DPRINTF(MGSC, "sc predict %#lx taken %d\n", btb_entry.pc, taken); - return MgscPrediction(btb_entry.pc, total_sum, use_sc_pred, taken, tage_info.tage_pred_taken, total_thres, bwIndex, - lIndex, iIndex, gIndex, pIndex, biasIndex, bw_weight_scale_diff, l_weight_scale_diff, - i_weight_scale_diff, g_weight_scale_diff, p_weight_scale_diff, bias_weight_scale_diff, - bw_percsum, l_percsum, i_percsum, g_percsum, p_percsum, bias_percsum); + return MgscPrediction(btb_entry.pc, total_sum, use_sc_pred, taken, tage_info.tage_pred_taken, + tage_info.tage_pred_conf_high, tage_info.tage_pred_conf_mid, tage_info.tage_pred_conf_low, + total_thres, bwIndex, lIndex, iIndex, gIndex, pIndex, biasIndex, bw_weight_scale_diff, + l_weight_scale_diff, i_weight_scale_diff, g_weight_scale_diff, p_weight_scale_diff, + bias_weight_scale_diff, bw_percsum, l_percsum, i_percsum, g_percsum, p_percsum, bias_percsum); } /** @@ -544,6 +576,93 @@ BTBMGSC::updateGlobalThreshold(Addr pc, bool update_direction) updateCounter(update_direction, updateThresholdWidth, updateThreshold); } +void +BTBMGSC::recordPredictionStats(const MgscPrediction &pred, bool actual_taken, bool sc_pred_taken, + bool tage_pred_taken) +{ + auto tage_conf_high = pred.tage_conf_high; + auto tage_conf_mid = pred.tage_conf_mid; + auto tage_conf_low = pred.tage_conf_low; + + // SC vs TAGE outcomes + if (pred.use_mgsc) { + mgscStats.scUsed++; + if (sc_pred_taken == actual_taken && tage_pred_taken != actual_taken) { + mgscStats.scCorrectTageWrong++; + } else if (sc_pred_taken != actual_taken && tage_pred_taken == actual_taken) { + mgscStats.scWrongTageCorrect++; + } else if (sc_pred_taken == actual_taken && tage_pred_taken == actual_taken) { + mgscStats.scCorrectTageCorrect++; + } else if (sc_pred_taken != actual_taken && tage_pred_taken != actual_taken) { + mgscStats.scWrongTageWrong++; + } + } else { + mgscStats.scNotUsed++; // sc confidence is low + } + + // Record raw percsum correctness and weight criticality for each table + auto recordPercsum = [&](int percsum, statistics::Scalar &correct, statistics::Scalar &wrong) { + if ((percsum >= 0) == actual_taken) { + correct++; + } else { + wrong++; + } + }; + if (pred.bw_weight_scale_diff) { + mgscStats.bwWeightScaleDiff++; + } + recordPercsum(pred.bw_percsum, mgscStats.bwPercsumCorrect, mgscStats.bwPercsumWrong); + + if (pred.l_weight_scale_diff) { + mgscStats.lWeightScaleDiff++; + } + recordPercsum(pred.l_percsum, mgscStats.lPercsumCorrect, mgscStats.lPercsumWrong); + + if (pred.i_weight_scale_diff) { + mgscStats.iWeightScaleDiff++; + } + recordPercsum(pred.i_percsum, mgscStats.iPercsumCorrect, mgscStats.iPercsumWrong); + + if (pred.g_weight_scale_diff) { + mgscStats.gWeightScaleDiff++; + } + recordPercsum(pred.g_percsum, mgscStats.gPercsumCorrect, mgscStats.gPercsumWrong); + + if (pred.p_weight_scale_diff) { + mgscStats.pWeightScaleDiff++; + } + recordPercsum(pred.p_percsum, mgscStats.pPercsumCorrect, mgscStats.pPercsumWrong); + + if (pred.bias_weight_scale_diff) { + mgscStats.biasWeightScaleDiff++; + } + recordPercsum(pred.bias_percsum, mgscStats.biasPercsumCorrect, mgscStats.biasPercsumWrong); + + // SC usage under TAGE confidence buckets + auto recordConfOutcome = [&](bool conf_high, bool conf_mid, bool conf_low, bool use, bool correct) { + if (conf_high) { + if (use) { + correct ? mgscStats.scHighUseCorrect++ : mgscStats.scHighUseWrong++; + } else { + mgscStats.scHighBypass++; + } + } else if (conf_mid) { + if (use) { + correct ? mgscStats.scMidUseCorrect++ : mgscStats.scMidUseWrong++; + } else { + mgscStats.scMidBypass++; + } + } else if (conf_low) { + if (use) { + correct ? mgscStats.scLowUseCorrect++ : mgscStats.scLowUseWrong++; + } else { + mgscStats.scLowBypass++; + } + } + }; + recordConfOutcome(tage_conf_high, tage_conf_mid, tage_conf_low, pred.use_mgsc, sc_pred_taken == actual_taken); +} + /** * @brief Update predictor for a single entry and allocate new entries if needed * @@ -566,26 +685,34 @@ BTBMGSC::updateSinglePredictor(const BTBEntry &entry, bool actual_taken, const M auto sc_pred_taken = total_sum >= 0; auto tage_pred_taken = pred.taken_before_sc; // tage predictions - // Update statistics - if (use_mgsc) { - mgscStats.scUsed++; - if (sc_pred_taken == actual_taken && tage_pred_taken != actual_taken) { - mgscStats.scCorrectTageWrong++; - } else if (sc_pred_taken != actual_taken && tage_pred_taken == actual_taken) { - mgscStats.scWrongTageCorrect++; - } else if (sc_pred_taken == actual_taken && tage_pred_taken == actual_taken) { - mgscStats.scCorrectTageCorrect++; - } else if (sc_pred_taken != actual_taken && tage_pred_taken != actual_taken) { - mgscStats.scWrongTageWrong++; - } - } else { - mgscStats.scNotUsed++; // sc confidence is low + recordPredictionStats(pred, actual_taken, sc_pred_taken, tage_pred_taken); + +#ifndef UNIT_TEST + // Write trace record + if (enableDB) { + MgscTrace t; + t.set(entry.pc, + tage_pred_taken, pred.tage_conf_high, pred.tage_conf_mid, pred.tage_conf_low, + pred.bw_percsum, pred.l_percsum, pred.i_percsum, + pred.g_percsum, pred.p_percsum, pred.bias_percsum, + total_sum, total_thres, use_mgsc, sc_pred_taken, + actual_taken); + mgscMissTrace->write_record(t); } +#endif // Only update tables if prediction was wrong or confidence was low if (sc_pred_taken != actual_taken || abs(total_sum) < total_thres) { // get weight table index from startPC Addr weightTableIdx = getPcIndex(stream.startPC, weightTableIdxWidth); + bool threshold_inc = (sc_pred_taken != actual_taken); + if (threshold_inc) { + mgscStats.pcThresholdInc++; + mgscStats.globalThresholdInc++; + } else { + mgscStats.pcThresholdDec++; + mgscStats.globalThresholdDec++; + } // Update BW tables updatePredTable(bwTable, pred.bwIndex, bwTableNum, entry.pc, actual_taken); @@ -617,8 +744,10 @@ BTBMGSC::updateSinglePredictor(const BTBEntry &entry, bool actual_taken, const M updateWeightTable(biasWeightTable, weightTableIdx, entry.pc, pred.bias_weight_scale_diff, (pred.bias_percsum >= 0) == actual_taken); - // Update PC-indexed threshold table - updatePCThresholdTable(entry.pc, sc_pred_taken != actual_taken); + // Update PC-indexed threshold table (only if enabled) + if (enablePCThreshold) { + updatePCThresholdTable(entry.pc, sc_pred_taken != actual_taken); + } // Update global threshold table updateGlobalThreshold(entry.pc, sc_pred_taken != actual_taken); @@ -1091,7 +1220,42 @@ BTBMGSC::MgscStats::MgscStats(statistics::Group *parent) ADD_STAT(scPredMissTaken, statistics::units::Count::get(), "number of sc prediction miss taken"), ADD_STAT(scPredMissNotTaken, statistics::units::Count::get(), "number of sc prediction miss not taken"), ADD_STAT(scPredCorrectTageWrong, statistics::units::Count::get(),"number of sc prediction correct and tage wrong"), - ADD_STAT(scPredWrongTageCorrect, statistics::units::Count::get(),"number of sc prediction wrong and tage correct") + ADD_STAT(scPredWrongTageCorrect, statistics::units::Count::get(),"number of sc prediction wrong and tage correct"), + + ADD_STAT(bwWeightScaleDiff, statistics::units::Count::get(), "bw table weight scaling decisive"), + ADD_STAT(lWeightScaleDiff, statistics::units::Count::get(), "l table weight scaling decisive"), + ADD_STAT(iWeightScaleDiff, statistics::units::Count::get(), "i table weight scaling decisive"), + ADD_STAT(gWeightScaleDiff, statistics::units::Count::get(), "g table weight scaling decisive"), + ADD_STAT(pWeightScaleDiff, statistics::units::Count::get(), "p table weight scaling decisive"), + ADD_STAT(biasWeightScaleDiff, statistics::units::Count::get(), "bias table weight scaling decisive"), + + ADD_STAT(bwPercsumCorrect, statistics::units::Count::get(), "bw table raw percsum sign correct"), + ADD_STAT(bwPercsumWrong, statistics::units::Count::get(), "bw table raw percsum sign wrong"), + ADD_STAT(lPercsumCorrect, statistics::units::Count::get(), "l table raw percsum sign correct"), + ADD_STAT(lPercsumWrong, statistics::units::Count::get(), "l table raw percsum sign wrong"), + ADD_STAT(iPercsumCorrect, statistics::units::Count::get(), "i table raw percsum sign correct"), + ADD_STAT(iPercsumWrong, statistics::units::Count::get(), "i table raw percsum sign wrong"), + ADD_STAT(gPercsumCorrect, statistics::units::Count::get(), "g table raw percsum sign correct"), + ADD_STAT(gPercsumWrong, statistics::units::Count::get(), "g table raw percsum sign wrong"), + ADD_STAT(pPercsumCorrect, statistics::units::Count::get(), "p table raw percsum sign correct"), + ADD_STAT(pPercsumWrong, statistics::units::Count::get(), "p table raw percsum sign wrong"), + ADD_STAT(biasPercsumCorrect, statistics::units::Count::get(), "bias table raw percsum sign correct"), + ADD_STAT(biasPercsumWrong, statistics::units::Count::get(), "bias table raw percsum sign wrong"), + + ADD_STAT(pcThresholdInc, statistics::units::Count::get(), "pc threshold increment"), + ADD_STAT(pcThresholdDec, statistics::units::Count::get(), "pc threshold decrement"), + ADD_STAT(globalThresholdInc, statistics::units::Count::get(), "global threshold increment"), + ADD_STAT(globalThresholdDec, statistics::units::Count::get(), "global threshold decrement"), + + ADD_STAT(scHighUseCorrect, statistics::units::Count::get(), "tage high conf, sc used, correct"), + ADD_STAT(scHighUseWrong, statistics::units::Count::get(), "tage high conf, sc used, wrong"), + ADD_STAT(scMidUseCorrect, statistics::units::Count::get(), "tage mid conf, sc used, correct"), + ADD_STAT(scMidUseWrong, statistics::units::Count::get(), "tage mid conf, sc used, wrong"), + ADD_STAT(scLowUseCorrect, statistics::units::Count::get(), "tage low conf, sc used, correct"), + ADD_STAT(scLowUseWrong, statistics::units::Count::get(), "tage low conf, sc used, wrong"), + ADD_STAT(scHighBypass, statistics::units::Count::get(), "tage high conf, sc not used"), + ADD_STAT(scMidBypass, statistics::units::Count::get(), "tage mid conf, sc not used"), + ADD_STAT(scLowBypass, statistics::units::Count::get(), "tage low conf, sc not used") { } diff --git a/src/cpu/pred/btb/btb_mgsc.hh b/src/cpu/pred/btb/btb_mgsc.hh index 1dc3a5d45d..f0e834e735 100755 --- a/src/cpu/pred/btb/btb_mgsc.hh +++ b/src/cpu/pred/btb/btb_mgsc.hh @@ -39,6 +39,9 @@ class BTBMGSC : public TimedBaseBTBPredictor bool use_mgsc; // Whether to use MGSC prediction bool taken; // Final prediction = (use sc pred) ? (total_sum >= 0) : tage prediction bool taken_before_sc; // Tage prediction (before SC) + bool tage_conf_high; + bool tage_conf_mid; + bool tage_conf_low; int16_t total_thres; // Combined threshold std::vector bwIndex; // BW table indices std::vector lIndex; // L table indices @@ -66,6 +69,9 @@ class BTBMGSC : public TimedBaseBTBPredictor use_mgsc(false), taken(false), taken_before_sc(false), + tage_conf_high(false), + tage_conf_mid(false), + tage_conf_low(false), total_thres(0), bwIndex(0), lIndex(0), @@ -89,17 +95,20 @@ class BTBMGSC : public TimedBaseBTBPredictor } MgscPrediction(Addr btb_pc, int total_sum, bool use_mgsc, bool taken, bool taken_before_sc, - int16_t total_thres, std::vector bwIndex, std::vector lIndex, - std::vector iIndex, std::vector gIndex, std::vector pIndex, - std::vector biasIndex, bool bw_weight_scale_diff, bool l_weight_scale_diff, - bool i_weight_scale_diff, bool g_weight_scale_diff, bool p_weight_scale_diff, - bool bias_weight_scale_diff, int bw_percsum, int l_percsum, int i_percsum, int g_percsum, - int p_percsum, int bias_percsum) + bool tage_conf_high, bool tage_conf_mid, bool tage_conf_low, int16_t total_thres, + std::vector bwIndex, std::vector lIndex, std::vector iIndex, + std::vector gIndex, std::vector pIndex, std::vector biasIndex, + bool bw_weight_scale_diff, bool l_weight_scale_diff, bool i_weight_scale_diff, + bool g_weight_scale_diff, bool p_weight_scale_diff, bool bias_weight_scale_diff, int bw_percsum, + int l_percsum, int i_percsum, int g_percsum, int p_percsum, int bias_percsum) : btb_pc(btb_pc), total_sum(total_sum), use_mgsc(use_mgsc), taken(taken), taken_before_sc(taken_before_sc), + tage_conf_high(tage_conf_high), + tage_conf_mid(tage_conf_mid), + tage_conf_low(tage_conf_low), total_thres(total_thres), bwIndex(bwIndex), lIndex(lIndex), @@ -259,6 +268,8 @@ class BTBMGSC : public TimedBaseBTBPredictor void updateSinglePredictor(const BTBEntry &entry, bool actual_taken, const MgscPrediction &pred, const FetchStream &stream); + void recordPredictionStats(const MgscPrediction &pred, bool actual_taken, bool sc_pred_taken, + bool tage_pred_taken); /** global backward branch history indexed tables */ // number of global backward branch history indexed tables @@ -315,6 +326,16 @@ class BTBMGSC : public TimedBaseBTBPredictor unsigned numCtrsPerLine; unsigned numCtrsPerLineBits; + // Test switches for SC tables + bool forceUseSC; + bool enableBwTable; + bool enableLTable; + bool enableITable; + bool enableGTable; + bool enablePTable; + bool enableBiasTable; + bool enablePCThreshold; + // Folded history for index calculation std::vector indexBwFoldedHist; std::vector> indexLFoldedHist; @@ -398,6 +419,45 @@ class BTBMGSC : public TimedBaseBTBPredictor statistics::Scalar scPredCorrectTageWrong; statistics::Scalar scPredWrongTageCorrect; + // Weight scale sensitivity (how often this table is decisive) + statistics::Scalar bwWeightScaleDiff; + statistics::Scalar lWeightScaleDiff; + statistics::Scalar iWeightScaleDiff; + statistics::Scalar gWeightScaleDiff; + statistics::Scalar pWeightScaleDiff; + statistics::Scalar biasWeightScaleDiff; + + // Raw percsum correctness per table + statistics::Scalar bwPercsumCorrect; + statistics::Scalar bwPercsumWrong; + statistics::Scalar lPercsumCorrect; + statistics::Scalar lPercsumWrong; + statistics::Scalar iPercsumCorrect; + statistics::Scalar iPercsumWrong; + statistics::Scalar gPercsumCorrect; + statistics::Scalar gPercsumWrong; + statistics::Scalar pPercsumCorrect; + statistics::Scalar pPercsumWrong; + statistics::Scalar biasPercsumCorrect; + statistics::Scalar biasPercsumWrong; + + // Threshold updates + statistics::Scalar pcThresholdInc; + statistics::Scalar pcThresholdDec; + statistics::Scalar globalThresholdInc; + statistics::Scalar globalThresholdDec; + + // Use/non-use of SC under different TAGE confidences + statistics::Scalar scHighUseCorrect; + statistics::Scalar scHighUseWrong; + statistics::Scalar scMidUseCorrect; + statistics::Scalar scMidUseWrong; + statistics::Scalar scLowUseCorrect; + statistics::Scalar scLowUseWrong; + statistics::Scalar scHighBypass; + statistics::Scalar scMidBypass; + statistics::Scalar scLowBypass; + MgscStats(statistics::Group *parent); }; diff --git a/src/cpu/pred/btb/stream_struct.hh b/src/cpu/pred/btb/stream_struct.hh index 1add6de600..9680359be6 100644 --- a/src/cpu/pred/btb/stream_struct.hh +++ b/src/cpu/pred/btb/stream_struct.hh @@ -798,6 +798,43 @@ struct BTBTrace : public Record { } }; +struct MgscTrace : public Record +{ + void set(uint64_t branchPC, + // TAGE prediction info + uint64_t tagePred, uint64_t tageConfHigh, uint64_t tageConfMid, uint64_t tageConfLow, + // Percsum for each table (signed values stored as int64) + int64_t bwPercsum, int64_t lPercsum, int64_t iPercsum, + int64_t gPercsum, int64_t pPercsum, int64_t biasPercsum, + // SC decision + int64_t totalSum, int64_t totalThres, uint64_t useSc, uint64_t scPred, + // Result + uint64_t actualTaken) + { + _tick = curTick(); + _uint64_data["branchPC"] = branchPC; + // TAGE info + _uint64_data["tagePred"] = tagePred; + _uint64_data["tageConfHigh"] = tageConfHigh; + _uint64_data["tageConfMid"] = tageConfMid; + _uint64_data["tageConfLow"] = tageConfLow; + // Percsum values (cast signed to uint64 for storage) + _uint64_data["bwPercsum"] = static_cast(bwPercsum); + _uint64_data["lPercsum"] = static_cast(lPercsum); + _uint64_data["iPercsum"] = static_cast(iPercsum); + _uint64_data["gPercsum"] = static_cast(gPercsum); + _uint64_data["pPercsum"] = static_cast(pPercsum); + _uint64_data["biasPercsum"] = static_cast(biasPercsum); + // SC decision + _uint64_data["totalSum"] = static_cast(totalSum); + _uint64_data["totalThres"] = static_cast(totalThres); + _uint64_data["useSc"] = useSc; + _uint64_data["scPred"] = scPred; + // Result + _uint64_data["actualTaken"] = actualTaken; + } +}; + } // namespace btb_pred } // namespace branch_prediction