@@ -134,51 +134,67 @@ DecoupledBPUWithBTB::tick()
134134 return ;
135135 }
136136
137- int predsRemainsToBeMade = enableTwoTaken ? 2 : 1 ;
138- unsigned tempNumOverrideBubbles = 0 ;
139-
140- while (predsRemainsToBeMade > 0 ) {
141- // 1. Request new prediction if FSQ not full and we are idle
142- if (bpuState == BpuState::IDLE && !targetQueueFull ()) {
143- if (blockPredictionPending) {
144- DPRINTF (Override, " Prediction blocked to prioritize resolve update\n " );
145- dbpBtbStats.predictionBlockedForUpdate ++;
146- blockPredictionPending = false ;
147- } else {
148- requestNewPrediction ();
149- bpuState = BpuState::PREDICTOR_DONE ;
150- }
137+ bool firstPredEnqueued = false ;
138+ bool firstPredTaken = false ;
139+
140+ // 1. First block: keep full multi-stage prediction flow.
141+ if (bpuState == BpuState::IDLE && !targetQueueFull ()) {
142+ if (blockPredictionPending) {
143+ DPRINTF (Override, " Prediction blocked to prioritize resolve update\n " );
144+ dbpBtbStats.predictionBlockedForUpdate ++;
145+ blockPredictionPending = false ;
146+ } else {
147+ requestNewPrediction ();
148+ bpuState = BpuState::PREDICTOR_DONE ;
151149 }
150+ }
152151
153- // 2. Handle pending prediction if available
154- if (bpuState == BpuState::PREDICTOR_DONE ) {
155- DPRINTF (Override, " Generating final prediction for PC %#lx\n " , s0PC);
156- numOverrideBubbles = generateFinalPredAndCreateBubbles ();
157- bpuState = BpuState::PREDICTION_OUTSTANDING ;
152+ if (bpuState == BpuState::PREDICTOR_DONE ) {
153+ DPRINTF (Override, " Generating final prediction for PC %#lx\n " , s0PC);
154+ numOverrideBubbles = generateFinalPredAndCreateBubbles ();
155+ bpuState = BpuState::PREDICTION_OUTSTANDING ;
158156
159- // Clear each predictor's output
160- for (int i = 0 ; i < numStages; i++) {
161- predsOfEachStage[i].btbEntries .clear ();
162- }
157+ for (int i = 0 ; i < numStages; i++) {
158+ predsOfEachStage[i].btbEntries .clear ();
163159 }
160+ }
164161
165- if (bpuState == BpuState::PREDICTION_OUTSTANDING && numOverrideBubbles > 0 ) {
166- tage->dryRunCycle (s0PC);
167- }
162+ if (bpuState == BpuState::PREDICTION_OUTSTANDING && numOverrideBubbles > 0 ) {
163+ tage->dryRunCycle (s0PC);
164+ }
165+
166+ if (validateFSQEnqueue ()) {
167+ firstPredTaken = finalPred.isTaken ();
168+ processNewPrediction ();
169+ firstPredEnqueued = true ;
170+
171+ DPRINTF (Override, " FSQ entry enqueued, prediction state reset\n " );
172+ bpuState = BpuState::IDLE ;
173+ }
174+
175+ // 2. Second block: use target PC and only trust uBTB result.
176+ if (enableTwoTaken && firstPredEnqueued && firstPredTaken &&
177+ bpuState == BpuState::IDLE && !targetQueueFull ()) {
178+ requestNewPrediction ();
168179
169- // check if:
170- // 1. FSQ has space
171- // 2. there's no bubble
172- // 3. PREDICTION_OUTSTANDING
173- if (validateFSQEnqueue ()) {
174- // Create new FSQ entry with the current prediction
175- processNewPrediction ();
180+ const auto &ubtbPred = predsOfEachStage[0 ];
181+ if (shouldGenerateSecondFromUBTB (ubtbPred)) {
182+ finalPred = buildSecondPredFromUBTB (ubtbPred);
183+ numOverrideBubbles = 0 ;
184+ bpuState = BpuState::PREDICTION_OUTSTANDING ;
176185
177- DPRINTF (Override, " FSQ entry enqueued, prediction state reset\n " );
186+ if (validateFSQEnqueue ()) {
187+ processNewPrediction ();
188+ DPRINTF (Override,
189+ " Second FSQ entry enqueued with uBTB-only prediction\n " );
190+ }
178191 bpuState = BpuState::IDLE ;
192+ } else {
193+ DPRINTF (Override,
194+ " Skip second prediction due to conditional/invalid uBTB result\n " );
179195 }
180196
181- predsRemainsToBeMade-- ;
197+ clearPreds () ;
182198 }
183199
184200 // Decrement override bubbles counter
@@ -192,6 +208,45 @@ DecoupledBPUWithBTB::tick()
192208
193209}
194210
211+ bool
212+ DecoupledBPUWithBTB::shouldGenerateSecondFromUBTB (
213+ const FullBTBPrediction &ubtbPred) const
214+ {
215+ auto pred = ubtbPred;
216+ const auto takenEntry = pred.getTakenEntry ();
217+ if (!takenEntry.valid || takenEntry.isCond ) {
218+ return false ;
219+ }
220+
221+ // Guard against history pollution: no conditional branch is allowed
222+ // before the terminating taken branch in the second block.
223+ for (const auto &entry : ubtbPred.btbEntries ) {
224+ if (!entry.valid ) {
225+ continue ;
226+ }
227+ if (entry.pc == takenEntry.pc ) {
228+ break ;
229+ }
230+ if (entry.isCond ) {
231+ return false ;
232+ }
233+ }
234+ return true ;
235+ }
236+
237+ FullBTBPrediction
238+ DecoupledBPUWithBTB::buildSecondPredFromUBTB (
239+ const FullBTBPrediction &ubtbPred) const
240+ {
241+ FullBTBPrediction pred = ubtbPred;
242+ pred.predSource = 0 ;
243+ pred.overrideReason = OverrideReason::NO_OVERRIDE ;
244+ pred.predTick = curTick ();
245+ pred.s1Source = ubtb->getComponentIdx ();
246+ pred.s3Source = ubtb->getComponentIdx ();
247+ return pred;
248+ }
249+
195250/* *
196251 * @brief Requests new predictions from predictor components
197252 *
0 commit comments