@@ -48,6 +48,7 @@ DecoupledBPUWithBTB::DecoupledBPUWithBTB(const DecoupledBPUWithBTBParams &p)
4848 numStages(p.numStages),
4949 historyManager(16 ), // TODO: fix this
5050 resolveBlockThreshold(p.resolveBlockThreshold),
51+ enable2Taken(p.enable2Taken),
5152 enable2Fetch(p.enable2Fetch),
5253 maxFetchBytesPerCycle(p.maxFetchBytesPerCycle),
5354 dbpBtbStats(this , p.numStages, p.fsq_size, maxInstsNum)
@@ -131,54 +132,48 @@ DecoupledBPUWithBTB::tick()
131132 tage->dryRunCycle (s0PC);
132133 DPRINTF (Override, " Squashing, BPU state updated.\n " );
133134 squashing = false ;
135+ predDFF.reset ();
134136 return ;
135137 }
136138
137- int predsRemainsToBeMade = enableTwoTaken ? 2 : 1 ;
138- unsigned tempNumOverrideBubbles = 0 ;
139+ if (bpuState == BpuState::IDLE && !targetQueueFull ()) {
140+ if (blockPredictionPending) {
141+ DPRINTF (Override, " Prediction blocked to prioritize resolve update\n " );
142+ dbpBtbStats.predictionBlockedForUpdate ++;
143+ blockPredictionPending = false ;
144+ } else {
145+ requestNewPrediction ();
146+ trainUbtbFor2Taken ();
147+ predDFF.storePrediction (predsOfEachStage[numStages - 1 ], ubtbHitIndex);
139148
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- }
151- }
152-
153- // 2. Handle pending prediction if available
154- if (bpuState == BpuState::PREDICTOR_DONE ) {
155149 DPRINTF (Override, " Generating final prediction for PC %#lx\n " , s0PC);
156150 numOverrideBubbles = generateFinalPredAndCreateBubbles ();
157- bpuState = BpuState::PREDICTION_OUTSTANDING ;
151+ clearPreds ();
152+ validateSecondFBPrediction ();
158153
159- // Clear each predictor's output
160- for (int i = 0 ; i < numStages; i++) {
161- predsOfEachStage[i].btbEntries .clear ();
154+ if (hasSecondPrediction) {
155+ dbpBtbStats.predProduce2Taken ++;
156+ } else {
157+ dbpBtbStats.predProduce1Taken ++;
162158 }
159+ bpuState = BpuState::PREDS_READY ;
163160 }
161+ }
164162
165- if (bpuState == BpuState::PREDICTION_OUTSTANDING && numOverrideBubbles > 0 ) {
166- tage->dryRunCycle (s0PC);
167- }
168-
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 ();
176-
177- DPRINTF (Override, " FSQ entry enqueued, prediction state reset\n " );
163+ if (bpuState == BpuState::PREDS_READY && validateFSQEnqueue ()) {
164+ processNewPrediction (false );
165+ if (hasSecondPrediction) {
166+ finalPred = secondPrediction;
167+ hasSecondPrediction = false ;
168+ bpuState = BpuState::WAITING_FOR_SECOND_ENQ ;
169+ } else {
178170 bpuState = BpuState::IDLE ;
179171 }
172+ }
180173
181- predsRemainsToBeMade--;
174+ if (bpuState == BpuState::WAITING_FOR_SECOND_ENQ && validateFSQEnqueue ()) {
175+ processNewPrediction (true );
176+ bpuState = BpuState::IDLE ;
182177 }
183178
184179 // Decrement override bubbles counter
@@ -201,19 +196,59 @@ DecoupledBPUWithBTB::tick()
201196void
202197DecoupledBPUWithBTB::requestNewPrediction ()
203198{
199+ DPRINTF (Override, " Requesting new prediction for PC %#lx\n " , s0PC);
204200
205- DPRINTF (Override, " Requesting new prediction for PC %#lx\n " , s0PC);
201+ for (int i = 0 ; i < numStages; i++) {
202+ predsOfEachStage[i].bbStart = s0PC;
203+ }
206204
207- // Initialize prediction state for each stage
208- for (int i = 0 ; i < numStages; i++) {
209- predsOfEachStage[i].bbStart = s0PC;
210- }
205+ hasSecondPrediction = false ;
206+ ubtbHitIndex = -1 ;
207+ secondPrediction = FullBTBPrediction ();
208+ secondPrediction.predSource = 0 ;
209+ secondPrediction.overrideReason = OverrideReason::NO_OVERRIDE ;
211210
212- // Query each predictor component with current PC and history
213- for (int i = 0 ; i < numComponents; i++) {
214- components[i]->putPCHistory (s0PC, s0History, predsOfEachStage); // s0History not used
211+ for (int i = 0 ; i < numComponents; i++) {
212+ if (components[i] == ubtb && enable2Taken) {
213+ auto [hitIndex, secondAvailable] = ubtb->putPCHistory2Taken (
214+ s0PC, s0History, predsOfEachStage, secondPrediction);
215+ ubtbHitIndex = hitIndex;
216+ hasSecondPrediction = secondAvailable;
217+ if (secondAvailable) {
218+ dbpBtbStats.twoTakenHit ++;
219+ } else {
220+ dbpBtbStats.twoTakenMiss ++;
221+ }
222+ } else {
223+ components[i]->putPCHistory (s0PC, s0History, predsOfEachStage);
215224 }
225+ }
226+ }
227+
228+ void
229+ DecoupledBPUWithBTB::trainUbtbFor2Taken ()
230+ {
231+ auto &s3_pred = predsOfEachStage[numStages - 1 ];
232+ if (enable2Taken && predDFF.valid ) {
233+ ubtb->train2Taken (predDFF.prevS3Pred , s3_pred, predDFF.prevUbtbHitIndex );
234+ } else {
235+ ubtb->train1Taken (s3_pred);
236+ }
237+ predDFF.reset ();
238+ }
216239
240+ void
241+ DecoupledBPUWithBTB::validateSecondFBPrediction ()
242+ {
243+ if (!hasSecondPrediction) {
244+ return ;
245+ }
246+ if (finalPred.predSource != 0 ) {
247+ hasSecondPrediction = false ;
248+ dbpBtbStats.twoTakenDiscardedByOverride ++;
249+ } else {
250+ dbpBtbStats.twoTakenRemainsAfterOverride ++;
251+ }
217252}
218253
219254// this function collects predictions from all stages and generate bubbles
@@ -308,9 +343,6 @@ DecoupledBPUWithBTB::generateFinalPredAndCreateBubbles()
308343
309344 // update ubtb/abtb using final S3 prediction
310345 if (predsOfEachStage[numStages - 1 ].btbEntries .size () > 0 ) {
311- if (ubtb->isEnabled ()) {
312- ubtb->updateUsingS3Pred (predsOfEachStage[numStages - 1 ]);
313- }
314346 if (abtb->isEnabled () && hasTarget (ftqId - 1 )) {
315347 auto previous_block_startpc = getTarget (ftqId - 1 ).startPC ;
316348 abtb->updateUsingS3Pred (predsOfEachStage[numStages - 1 ], previous_block_startpc);
@@ -672,7 +704,8 @@ DecoupledBPUWithBTB::validateFSQEnqueue()
672704 }
673705
674706 // 1. Check if a prediction is available to enqueue
675- if (bpuState != BpuState::PREDICTION_OUTSTANDING ) {
707+ if (bpuState != BpuState::PREDS_READY &&
708+ bpuState != BpuState::WAITING_FOR_SECOND_ENQ ) {
676709 DPRINTF (Override, " No prediction available to enqueue into FSQ\n " );
677710 return false ;
678711 }
@@ -730,7 +763,7 @@ DecoupledBPUWithBTB::pHistShiftIn(int shamt, bool taken, boost::dynamic_bitset<>
730763 * @return FetchTarget The created fetch target
731764 */
732765FetchTarget
733- DecoupledBPUWithBTB::createFetchTargetEntry ()
766+ DecoupledBPUWithBTB::createFetchTargetEntry (bool is_second_pred )
734767{
735768 // Create a new fetch target entry
736769 FetchTarget entry;
@@ -765,10 +798,16 @@ DecoupledBPUWithBTB::createFetchTargetEntry()
765798
766799 entry.s1Source = finalPred.s1Source ;
767800 entry.s3Source = finalPred.s3Source ;
801+ entry.isSecondFBPred = is_second_pred;
768802
769803 // Save predictors' metadata
770804 for (int i = 0 ; i < numComponents; i++) {
771- entry.predMetas [i] = components[i]->getPredictionMeta ();
805+ if (is_second_pred) {
806+ auto second_meta = components[i]->getSecondPredictionMeta ();
807+ entry.predMetas [i] = second_meta ? second_meta : components[i]->getPredictionMeta ();
808+ } else {
809+ entry.predMetas [i] = components[i]->getPredictionMeta ();
810+ }
772811 }
773812
774813 // Initialize default resolution state
@@ -803,12 +842,12 @@ DecoupledBPUWithBTB::fillAheadPipeline(FetchTarget &entry)
803842
804843// this function enqueues fsq and update s0PC and s0History
805844void
806- DecoupledBPUWithBTB::processNewPrediction ()
845+ DecoupledBPUWithBTB::processNewPrediction (bool is_second_pred )
807846{
808847 DPRINTF (DecoupleBP, " Creating new prediction for PC %#lx\n " , s0PC);
809848
810849 // 1. Create a new fetch target entry with prediction information
811- FetchTarget entry = createFetchTargetEntry ();
850+ FetchTarget entry = createFetchTargetEntry (is_second_pred );
812851
813852 // 2. Update global PC state to target or fall-through
814853 s0PC = finalPred.getTarget (predictWidth);;
0 commit comments