分析Gem5中的TAGE-SC-L分支预测器工作流程,重点关注预测性历史更新策略的技术实现。
一、指令创建 文件路径:./src/cpu/o3/fetch.cc
instruction在buildInst函数执行后生成,随后会逐步调用函数,调用顺序如下:
1 2 3 4 5 6 7 8 9 10 11 ->lookupAndUpdateNextPC () ->branchPred->predict () ->lookup () ->predict () ->tage->tagePredict () ->loopPredictor->loopPredict () ->statisticalCorrector->scPredict ()
二、TAGE预测 文件路径:./src/cpu/pred/tage_sc_l.cc.cc
在tage_sc_l.cc.cc中,会分别调用TAGE、Loop、SC预测器进行预测,首先讨论TAGE预测器。在调用tage->tagePredict()后,函数调用路径如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ->tage->tagePredict () ->calculateIndicesAndTags () ->calculateIndicesAndTags () ->gindex () index = shifted_pc ^ (shifted_pc >> ((int ) abs (logTagTableSizes[bank] - bank) + 1 )) ^ threadHistory[tid].computeIndices[bank].comp ^ F (threadHistory[tid].pathHist, hlen, bank); ->gtage () Addr shifted_pc = pc >> instShiftAmt; int tag = shifted_pc ^ threadHistory[tid].computeTags[0 ][bank].comp ^ (threadHistory[tid].computeTags[1 ][bank].comp << 1 ); return (tag & ((1ULL << tagTableTagWidths[bank]) - 1 )); ->bindex ()
2.1 threadHistory结构 threadHistory结构体定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 struct ThreadHistory { int pathHist; int nonSpecPathHist; std::vector<uint8_t > globalHist; int ptGhist; FoldedHistory *computeIndices; FoldedHistory *computeTags[2 ]; }; struct FoldedHistory { unsigned comp; int compLength; int origLength; int outpoint; int bufferSize; FoldedHistory () { comp = 0 ; } void init (int original_length, int compressed_length) { origLength = original_length; compLength = compressed_length; outpoint = original_length % compressed_length; } void update (uint8_t * h) { comp = (comp << 1 ) | h[0 ]; comp ^= h[origLength] << outpoint; comp ^= (comp >> compLength); comp &= (1ULL << compLength) - 1 ; } void restore (uint8_t * h) { comp ^= h[origLength] << outpoint; auto tmp = (comp & 1 ) ^ h[0 ]; comp = (tmp << (compLength-1 )) | (comp >> 1 ); } };
其中 pathHist/computeIndices/
三、非预测性路径历史更新 更新函数调用路径:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ->branchPred->update () while (!predHist[tid].empty () && predHist[tid].back ()->seqNum <= done_sn) { commitBranch (tid, *predHist[tid].rbegin ()); delete predHist[tid].back (); predHist[tid].pop_back (); } ->commitBranch () ->update () ->tage->updateHistories () threadHistory[tid].nonSpecPathHist = calcNewPathHist (tid, branch_pc, bi->pathHist, taken, branchTypeExtra (inst), target);
三、预测性历史更新 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ->lookupAndUpdateNextPC () ->branchPred->predict () ->updateHistories () ->updateHistories () ->updateHistories () ->updatePathAndGlobalHistory () ->updatePathAndGlobalHistory () tHist.pathHist = calcNewPathHist (tid, branch_pc, tHist.pathHist, taken, brtype, target); ->updateGHist () ->updateGHist ()
四、预测性历史恢复 1 2 3 4 5 6 7 8 9 10 11 12 ->branchPred->squash () ->squash () ->update () ->squash () ->updateHistories () ->restoreHistState ()