Skip to content
11 changes: 5 additions & 6 deletions src/cpu/pred/BranchPredictor.py
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ class MBTB(TimedBaseBTBPredictor):
instShiftAmt = Param.Unsigned(1, "Amount to shift PC to get inst bits")
numThreads = Param.Unsigned(1, "Number of threads")
numWays = Param.Unsigned(4, "Number of ways per set") # for 2 SRAMs, 4 ways per SRAM
numDelay = 2
numDelay = 0
blockSize = 32 # max 64 byte block, 32 byte aligned
# MBTB is always half-aligned - no parameter needed
victimCacheSize = Param.Unsigned(0, "Number of entries in the victim cache")
Expand Down Expand Up @@ -1071,16 +1071,15 @@ class MicroTAGE(TimedBaseBTBPredictor):
updateOnRead = Param.Bool(True,"Enable update on read, no need to save tage meta in FTQ")
# Keep vector parameters consistent with numPredictors to avoid constructor asserts.
numPredictors = Param.Unsigned(4, "Number of TAGE predictors")
tableSizes = VectorParam.Unsigned([512] * 4,"the TAGE T0~Tn length")
TTagBitSizes = VectorParam.Unsigned([16] * 4 ,"the T0~Tn entry's tag bit size")
TTagPcShifts = VectorParam.Unsigned([1] * 4 ,"when the T0~Tn entry's tag generating, PC right shift")
tableSizes = VectorParam.Unsigned([512]*4 ,"the TAGE T0~Tn length")
TTagBitSizes = VectorParam.Unsigned([16]*4 ,"the T0~Tn entry's tag bit size")
TTagPcShifts = VectorParam.Unsigned([1]*4 ,"when the T0~Tn entry's tag generating, PC right shift")
blockSize = Param.Unsigned(32,"tage index function uses 32B aligned block address")

histLengths = VectorParam.Unsigned([5,9,17,27] ,"the BTB TAGE T0~Tn history length")
histLengths = VectorParam.Unsigned([5, 29, 57, 107] ,"the BTB TAGE T0~Tn history length")
maxHistLen = Param.Unsigned(970,"The length of history passed from DBP")
numTablesToAlloc = Param.Unsigned(1,"The number of table to allocated each time")
numWays = Param.Unsigned(1, "Number of ways per set")
baseTableSize = Param.Unsigned(256,"Base table size")
maxBranchPositions = Param.Unsigned(32,"Maximum branch positions per 64-byte block")
useAltOnNaSize = Param.Unsigned(128,"Size of the useAltOnNa table")
useAltOnNaWidth = Param.Unsigned(7,"Width of the useAltOnNa table")
Expand Down
6 changes: 3 additions & 3 deletions src/cpu/pred/btb/decoupled_bpred.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ DecoupledBPUWithBTB::DecoupledBPUWithBTB(const DecoupledBPUWithBTBParams &p)
}
bpType = DecoupledBTBType;
// Only add enabled components to the list
if (ubtb->isEnabled()) components.push_back(ubtb);
if (abtb->isEnabled()) components.push_back(abtb);
if (microtage->isEnabled()) components.push_back(microtage);
// if (ubtb->isEnabled()) components.push_back(ubtb);
// if (abtb->isEnabled()) components.push_back(abtb);
if (mbtb->isEnabled()) components.push_back(mbtb);
if (microtage->isEnabled()) components.push_back(microtage);
Comment on lines +58 to +61
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if ubtb/abtb maintain any speculative history state
# that would need recovery during squashes

# Search for history-related state in UBTB and AheadBTB implementations
rg -n -C5 'specUpdateHist|recoverHist|history' src/cpu/pred/btb/btb_ubtb.cc src/cpu/pred/btb/btb_ubtb.hh src/cpu/pred/btb/abtb.cc src/cpu/pred/btb/abtb.hh 2>/dev/null || echo "Files not found, searching with fd..."

fd -e cc -e hh 'ubtb|abtb' src/cpu/pred/btb --exec rg -l 'history|specUpdate|recover' {} \;

Repository: OpenXiangShan/GEM5

Length of output: 6523


🏁 Script executed:

# Verify aheadReadBtbEntries is used/declared in abtb
rg -n 'aheadReadBtbEntries' src/cpu/pred/btb/abtb.hh src/cpu/pred/btb/abtb.cc

Repository: OpenXiangShan/GEM5

Length of output: 869


🏁 Script executed:

# Check if updateUsingS3Pred in ABTB does anything with the queue
rg -n -A 20 'AheadBTB::updateUsingS3Pred' src/cpu/pred/btb/abtb.cc

# Also check if there's any other recovery mechanism for ABTB
rg -n 'updateUsingS3Pred' src/cpu/pred/btb/decoupled_bpred.cc

Repository: OpenXiangShan/GEM5

Length of output: 1247


🏁 Script executed:

# Check if any code path still calls recoverHist for abtb directly (outside of components iteration)
rg -n 'abtb.*recoverHist|\.recoverHist.*abtb' src/cpu/pred/btb/decoupled_bpred.cc

# Check the actual components iteration to confirm abtb won't have recoverHist called
rg -n -B 5 -A 10 'for.*components' src/cpu/pred/btb/decoupled_bpred.cc | grep -A 10 'recoverHist'

Repository: OpenXiangShan/GEM5

Length of output: 44


🏁 Script executed:

# Check what recoverHist calls look like in decoupled_bpred
rg -n 'recoverHist' src/cpu/pred/btb/decoupled_bpred.cc

# Also check the exact component loop that calls history recovery
rg -n -B 3 -A 3 'for.*components' src/cpu/pred/btb/decoupled_bpred.cc | head -40

Repository: OpenXiangShan/GEM5

Length of output: 316


🏁 Script executed:

# Check the recoverHistoryForSquash function and the components loop
sed -n '977,1020p' src/cpu/pred/btb/decoupled_bpred.cc | cat -n

# Also verify that abtb is no longer in components by checking lines 58-62
sed -n '55,65p' src/cpu/pred/btb/decoupled_bpred.cc | cat -n

Repository: OpenXiangShan/GEM5

Length of output: 2712


ABTB removal from components breaks the history recovery mechanism.

While UBTB can be safely excluded from the components list (its recoverHist is explicitly marked "not used" and empty), ABTB has an active recoverHist() implementation (abtb.cc:330-335) that clears the aheadReadBtbEntries queue.

By commenting out ABTB from line 58-59, its recoverHist will not be called during squash recovery (line 1007 in decoupled_bpred.cc). The aheadReadBtbEntries queue will accumulate stale entries across branch mispredictions, creating inconsistent state. The updateUsingS3Pred() calls do not manage this queue.

Either restore ABTB to the components list or implement explicit queue recovery outside the component iteration.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cpu/pred/btb/decoupled_bpred.cc` around lines 58 - 61, The ABTB instance
was removed from the components vector causing its recoverHist() not to be
invoked during squash recovery, which leaves aheadReadBtbEntries uncleared and
leads to stale state; to fix it either add ABTB (abtb) back into the components
list where mbtb and microtage are pushed, or, if you intentionally omit abtb
from components, call abtb->recoverHist() explicitly during the same recovery
path (the squash recovery routine that currently iterates components and calls
recoverHist), ensuring aheadReadBtbEntries is cleared; updateUsingS3Pred()
should not be relied on for this, so reference the abtb object and its
recoverHist() method (or re-add abtb to the components vector) to restore
correct recovery behavior.

if (tage->isEnabled()) components.push_back(tage);
if (ras->isEnabled()) components.push_back(ras);
if (ittage->isEnabled()) components.push_back(ittage);
Expand Down