"I am a person who works hard and plays hard."

Yuan Wei
Second Year Graduate Student Department of Computer Science
University of Virginia Charlottesville, VA 22903
Email: yw3f@cs.virginia.edu


Source Code Analysis

Main Page   Compound List   File List   Compound Members   File Members  

bpred.h File Reference

#include <stdio.h>
#include "host.h"
#include "misc.h"
#include "machine.h"
#include "stats.h"

Include dependency graph for bpred.h:

Include dependency graph

This graph shows which files directly or indirectly include this file:

Included by dependency graph

Go to the source code of this file.

Compounds

Defines

Enumerations

Functions


Define Documentation

#define dassert      assert(a)
 

Definition at line 106 of file bpred.h.

Referenced by bpred_update().


Enumeration Type Documentation

enum bpred_class
 

Enumeration values:
BPredComb 
BPred2Level 
BPred2bit 
BPredTaken 
BPredNotTaken 
BPred_NUM 

Definition at line 152 of file bpred.h.

00152                  {
00153   BPredComb,                    /* combined predictor (McFarling) */
00154   BPred2Level,                  /* 2-level correlating pred w/2-bit counters */
00155   BPred2bit,                    /* 2-bit saturating cntr pred (dir mapped) */
00156   BPredTaken,                   /* static predict taken */
00157   BPredNotTaken,                /* static predict not taken */
00158   BPred_NUM
00159 };


Function Documentation

void bpred_after_priming struct bpred_t   bpred
 

Definition at line 536 of file bpred.c.

References bpred_t::addr_hits, bpred_t::dir_hits, bpred_t::jr_hits, bpred_t::jr_seen, bpred_t::lookups, bpred_t::misses, bpred_t::ras_hits, bpred_t::retstack_pops, bpred_t::retstack_pushes, bpred_t::used_2lev, bpred_t::used_bimod, and bpred_t::used_ras.

00537 {
00538   if (bpred == NULL)
00539     return;
00540 
00541   bpred->lookups = 0;
00542   bpred->addr_hits = 0;
00543   bpred->dir_hits = 0;
00544   bpred->used_ras = 0;
00545   bpred->used_bimod = 0;
00546   bpred->used_2lev = 0;
00547   bpred->jr_hits = 0;
00548   bpred->jr_seen = 0;
00549   bpred->misses = 0;
00550   bpred->retstack_pops = 0;
00551   bpred->retstack_pushes = 0;
00552   bpred->ras_hits = 0;
00553 }

void bpred_config struct bpred_t   pred,
FILE *    stream
 

Definition at line 370 of file bpred.c.

References BPred2bit, BPred2Level, bpred_dir_config(), BPredComb, BPredNotTaken, BPredTaken, bpred_t::btb, bpred_t::class, bpred_t::dirpred, panic(), and bpred_t::retstack.

00372 {
00373   switch (pred->class) {
00374   case BPredComb:
00375     bpred_dir_config (pred->dirpred.bimod, "bimod", stream);
00376     bpred_dir_config (pred->dirpred.twolev, "2lev", stream);
00377     bpred_dir_config (pred->dirpred.meta, "meta", stream);
00378     fprintf(stream, "btb: %d sets x %d associativity", 
00379             pred->btb.sets, pred->btb.assoc);
00380     fprintf(stream, "ret_stack: %d entries", pred->retstack.size);
00381     break;
00382 
00383   case BPred2Level:
00384     bpred_dir_config (pred->dirpred.twolev, "2lev", stream);
00385     fprintf(stream, "btb: %d sets x %d associativity", 
00386             pred->btb.sets, pred->btb.assoc);
00387     fprintf(stream, "ret_stack: %d entries", pred->retstack.size);
00388     break;
00389 
00390   case BPred2bit:
00391     bpred_dir_config (pred->dirpred.bimod, "bimod", stream);
00392     fprintf(stream, "btb: %d sets x %d associativity", 
00393             pred->btb.sets, pred->btb.assoc);
00394     fprintf(stream, "ret_stack: %d entries", pred->retstack.size);
00395     break;
00396 
00397   case BPredTaken:
00398     bpred_dir_config (pred->dirpred.bimod, "taken", stream);
00399     break;
00400   case BPredNotTaken:
00401     bpred_dir_config (pred->dirpred.bimod, "nottaken", stream);
00402     break;
00403 
00404   default:
00405     panic("bogus branch predictor class");
00406   }
00407 }

struct bpred_t* bpred_create enum bpred_class    class,
unsigned int    bimod_size,
unsigned int    l1size,
unsigned int    l2size,
unsigned int    meta_size,
unsigned int    shift_width,
unsigned int    xor,
unsigned int    btb_sets,
unsigned int    btb_assoc,
unsigned int    retstack_size
 

Definition at line 136 of file bpred.c.

References BPred2bit, BPred2Level, bpred_dir_create(), BPredComb, BPredNotTaken, BPredTaken, bpred_t::btb, bpred_t::class, bpred_t::dirpred, fatal(), panic(), and bpred_t::retstack.

Referenced by sim_check_options().

00146 {
00147   struct bpred_t *pred;
00148 
00149   if (!(pred = calloc(1, sizeof(struct bpred_t))))
00150     fatal("out of virtual memory");
00151 
00152   pred->class = class;
00153 
00154   switch (class) {
00155   case BPredComb:
00156     /* bimodal component */
00157     pred->dirpred.bimod = 
00158       bpred_dir_create(BPred2bit, bimod_size, 0, 0, 0);
00159 
00160     /* 2-level component */
00161     pred->dirpred.twolev = 
00162       bpred_dir_create(BPred2Level, l1size, l2size, shift_width, xor);
00163 
00164     /* metapredictor component */
00165     pred->dirpred.meta = 
00166       bpred_dir_create(BPred2bit, meta_size, 0, 0, 0);
00167 
00168     break;
00169 
00170   case BPred2Level:
00171     pred->dirpred.twolev = 
00172       bpred_dir_create(class, l1size, l2size, shift_width, xor);
00173 
00174     break;
00175 
00176   case BPred2bit:
00177     pred->dirpred.bimod = 
00178       bpred_dir_create(class, bimod_size, 0, 0, 0);
00179 
00180   case BPredTaken:
00181   case BPredNotTaken:
00182     /* no other state */
00183     break;
00184 
00185   default:
00186     panic("bogus predictor class");
00187   }
00188 
00189   /* allocate ret-addr stack */
00190   switch (class) {
00191   case BPredComb:
00192   case BPred2Level:
00193   case BPred2bit:
00194     {
00195       int i;
00196 
00197       /* allocate BTB */
00198       if (!btb_sets || (btb_sets & (btb_sets-1)) != 0)
00199         fatal("number of BTB sets must be non-zero and a power of two");
00200       if (!btb_assoc || (btb_assoc & (btb_assoc-1)) != 0)
00201         fatal("BTB associativity must be non-zero and a power of two");
00202 
00203       if (!(pred->btb.btb_data = calloc(btb_sets * btb_assoc,
00204                                         sizeof(struct bpred_btb_ent_t))))
00205         fatal("cannot allocate BTB");
00206 
00207       pred->btb.sets = btb_sets;
00208       pred->btb.assoc = btb_assoc;
00209 
00210       if (pred->btb.assoc > 1)
00211         for (i=0; i < (pred->btb.assoc*pred->btb.sets); i++)
00212           {
00213             if (i % pred->btb.assoc != pred->btb.assoc - 1)
00214               pred->btb.btb_data[i].next = &pred->btb.btb_data[i+1];
00215             else
00216               pred->btb.btb_data[i].next = NULL;
00217             
00218             if (i % pred->btb.assoc != pred->btb.assoc - 1)
00219               pred->btb.btb_data[i+1].prev = &pred->btb.btb_data[i];
00220           }
00221 
00222       /* allocate retstack */
00223       if ((retstack_size & (retstack_size-1)) != 0)
00224         fatal("Return-address-stack size must be zero or a power of two");
00225       
00226       pred->retstack.size = retstack_size;
00227       if (retstack_size)
00228         if (!(pred->retstack.stack = calloc(retstack_size, 
00229                                             sizeof(struct bpred_btb_ent_t))))
00230           fatal("cannot allocate return-address-stack");
00231       pred->retstack.tos = retstack_size - 1;
00232       
00233       break;
00234     }
00235 
00236   case BPredTaken:
00237   case BPredNotTaken:
00238     /* no other state */
00239     break;
00240 
00241   default:
00242     panic("bogus predictor class");
00243   }
00244 
00245   return pred;
00246 }

struct bpred_dir_t* bpred_dir_create enum bpred_class    class,
unsigned int    l1size,
unsigned int    l2size,
unsigned int    shift_width,
unsigned int    xor
 

Definition at line 250 of file bpred.c.

References BPred2bit, BPred2Level, BPredNotTaken, BPredTaken, bpred_dir_t::class, bpred_dir_t::config, fatal(), and panic().

Referenced by bpred_create().

00256 {
00257   struct bpred_dir_t *pred_dir;
00258   unsigned int cnt;
00259   int flipflop;
00260 
00261   if (!(pred_dir = calloc(1, sizeof(struct bpred_dir_t))))
00262     fatal("out of virtual memory");
00263 
00264   pred_dir->class = class;
00265 
00266   cnt = -1;
00267   switch (class) {
00268   case BPred2Level:
00269     {
00270       if (!l1size || (l1size & (l1size-1)) != 0)
00271         fatal("level-1 size, `%d', must be non-zero and a power of two", 
00272               l1size);
00273       pred_dir->config.two.l1size = l1size;
00274       
00275       if (!l2size || (l2size & (l2size-1)) != 0)
00276         fatal("level-2 size, `%d', must be non-zero and a power of two", 
00277               l2size);
00278       pred_dir->config.two.l2size = l2size;
00279       
00280       if (!shift_width || shift_width > 30)
00281         fatal("shift register width, `%d', must be non-zero and positive",
00282               shift_width);
00283       pred_dir->config.two.shift_width = shift_width;
00284       
00285       pred_dir->config.two.xor = xor;
00286       pred_dir->config.two.shiftregs = calloc(l1size, sizeof(int));
00287       if (!pred_dir->config.two.shiftregs)
00288         fatal("cannot allocate shift register table");
00289       
00290       pred_dir->config.two.l2table = calloc(l2size, sizeof(unsigned char));
00291       if (!pred_dir->config.two.l2table)
00292         fatal("cannot allocate second level table");
00293 
00294       /* initialize counters to weakly this-or-that */
00295       flipflop = 1;
00296       for (cnt = 0; cnt < l2size; cnt++)
00297         {
00298           pred_dir->config.two.l2table[cnt] = flipflop;
00299           flipflop = 3 - flipflop;
00300         }
00301 
00302       break;
00303     }
00304 
00305   case BPred2bit:
00306     if (!l1size || (l1size & (l1size-1)) != 0)
00307       fatal("2bit table size, `%d', must be non-zero and a power of two", 
00308             l1size);
00309     pred_dir->config.bimod.size = l1size;
00310     if (!(pred_dir->config.bimod.table =
00311           calloc(l1size, sizeof(unsigned char))))
00312       fatal("cannot allocate 2bit storage");
00313     /* initialize counters to weakly this-or-that */
00314     flipflop = 1;
00315     for (cnt = 0; cnt < l1size; cnt++)
00316       {
00317         pred_dir->config.bimod.table[cnt] = flipflop;
00318         flipflop = 3 - flipflop;
00319       }
00320 
00321     break;
00322 
00323   case BPredTaken:
00324   case BPredNotTaken:
00325     /* no other state */
00326     break;
00327 
00328   default:
00329     panic("bogus branch direction predictor class");
00330   }
00331 
00332   return pred_dir;
00333 }

md_addr_t bpred_lookup struct bpred_t   pred,
md_addr_t    baddr,
md_addr_t    btarget,
enum md_opcode    op,
int    is_call,
int    is_return,
struct bpred_update_t   dir_update_ptr,
int *    stack_recover_idx
 

Definition at line 623 of file bpred.c.

References bpred_btb_ent_t::addr, BPred2bit, BPred2Level, bpred_dir_lookup(), BPredComb, BPredNotTaken, BPredTaken, bpred_t::btb, bpred_t::class, bpred_update_t::dir, bpred_t::dirpred, FALSE, bpred_t::lookups, MD_OP_FLAGS, panic(), bpred_update_t::pdir1, bpred_update_t::pdir2, bpred_update_t::pmeta, bpred_t::retstack, bpred_t::retstack_pops, bpred_t::retstack_pushes, bpred_btb_ent_t::target, and TRUE.

Referenced by sim_main().

00632 {
00633   struct bpred_btb_ent_t *pbtb = NULL;
00634   int index, i;
00635 
00636   if (!dir_update_ptr)
00637     panic("no bpred update record");
00638 
00639   /* if this is not a branch, return not-taken */
00640   if (!(MD_OP_FLAGS(op) & F_CTRL))
00641     return 0;
00642 
00643   pred->lookups++;
00644 
00645   dir_update_ptr->dir.ras = FALSE;
00646   dir_update_ptr->pdir1 = NULL;
00647   dir_update_ptr->pdir2 = NULL;
00648   dir_update_ptr->pmeta = NULL;
00649   /* Except for jumps, get a pointer to direction-prediction bits */
00650   switch (pred->class) {
00651     case BPredComb:
00652       if ((MD_OP_FLAGS(op) & (F_CTRL|F_UNCOND)) != (F_CTRL|F_UNCOND))
00653         {
00654           char *bimod, *twolev, *meta;
00655           bimod = bpred_dir_lookup (pred->dirpred.bimod, baddr);
00656           twolev = bpred_dir_lookup (pred->dirpred.twolev, baddr);
00657           meta = bpred_dir_lookup (pred->dirpred.meta, baddr);
00658           dir_update_ptr->pmeta = meta;
00659           dir_update_ptr->dir.meta  = (*meta >= 2);
00660           dir_update_ptr->dir.bimod = (*bimod >= 2);
00661           dir_update_ptr->dir.twolev  = (*twolev >= 2);
00662           if (*meta >= 2)
00663             {
00664               dir_update_ptr->pdir1 = twolev;
00665               dir_update_ptr->pdir2 = bimod;
00666             }
00667           else
00668             {
00669               dir_update_ptr->pdir1 = bimod;
00670               dir_update_ptr->pdir2 = twolev;
00671             }
00672         }
00673       break;
00674     case BPred2Level:
00675       if ((MD_OP_FLAGS(op) & (F_CTRL|F_UNCOND)) != (F_CTRL|F_UNCOND))
00676         {
00677           dir_update_ptr->pdir1 =
00678             bpred_dir_lookup (pred->dirpred.twolev, baddr);
00679         }
00680       break;
00681     case BPred2bit:
00682       if ((MD_OP_FLAGS(op) & (F_CTRL|F_UNCOND)) != (F_CTRL|F_UNCOND))
00683         {
00684           dir_update_ptr->pdir1 =
00685             bpred_dir_lookup (pred->dirpred.bimod, baddr);
00686         }
00687       break;
00688     case BPredTaken:
00689       return btarget;
00690     case BPredNotTaken:
00691       if ((MD_OP_FLAGS(op) & (F_CTRL|F_UNCOND)) != (F_CTRL|F_UNCOND))
00692         {
00693           return baddr + sizeof(md_inst_t);
00694         }
00695       else
00696         {
00697           return btarget;
00698         }
00699     default:
00700       panic("bogus predictor class");
00701   }
00702 
00703   /*
00704    * We have a stateful predictor, and have gotten a pointer into the
00705    * direction predictor (except for jumps, for which the ptr is null)
00706    */
00707 
00708   /* record pre-pop TOS; if this branch is executed speculatively
00709    * and is squashed, we'll restore the TOS and hope the data
00710    * wasn't corrupted in the meantime. */
00711   if (pred->retstack.size)
00712     *stack_recover_idx = pred->retstack.tos;
00713   else
00714     *stack_recover_idx = 0;
00715 
00716   /* if this is a return, pop return-address stack */
00717   if (is_return && pred->retstack.size)
00718     {
00719       md_addr_t target = pred->retstack.stack[pred->retstack.tos].target;
00720       pred->retstack.tos = (pred->retstack.tos + pred->retstack.size - 1)
00721                            % pred->retstack.size;
00722       pred->retstack_pops++;
00723       dir_update_ptr->dir.ras = TRUE; /* using RAS here */
00724       return target;
00725     }
00726 
00727 #ifndef RAS_BUG_COMPATIBLE
00728   /* if function call, push return-address onto return-address stack */
00729   if (is_call && pred->retstack.size)
00730     {
00731       pred->retstack.tos = (pred->retstack.tos + 1)% pred->retstack.size;
00732       pred->retstack.stack[pred->retstack.tos].target = 
00733         baddr + sizeof(md_inst_t);
00734       pred->retstack_pushes++;
00735     }
00736 #endif /* !RAS_BUG_COMPATIBLE */
00737   
00738   /* not a return. Get a pointer into the BTB */
00739   index = (baddr >> MD_BR_SHIFT) & (pred->btb.sets - 1);
00740 
00741   if (pred->btb.assoc > 1)
00742     {
00743       index *= pred->btb.assoc;
00744 
00745       /* Now we know the set; look for a PC match */
00746       for (i = index; i < (index+pred->btb.assoc) ; i++)
00747         if (pred->btb.btb_data[i].addr == baddr)
00748           {
00749             /* match */
00750             pbtb = &pred->btb.btb_data[i];
00751             break;
00752           }
00753     }   
00754   else
00755     {
00756       pbtb = &pred->btb.btb_data[index];
00757       if (pbtb->addr != baddr)
00758         pbtb = NULL;
00759     }
00760 
00761   /*
00762    * We now also have a pointer into the BTB for a hit, or NULL otherwise
00763    */
00764 
00765   /* if this is a jump, ignore predicted direction; we know it's taken. */
00766   if ((MD_OP_FLAGS(op) & (F_CTRL|F_UNCOND)) == (F_CTRL|F_UNCOND))
00767     {
00768       return (pbtb ? pbtb->target : 1);
00769     }
00770 
00771   /* otherwise we have a conditional branch */
00772   if (pbtb == NULL)
00773     {
00774       /* BTB miss -- just return a predicted direction */
00775       return ((*(dir_update_ptr->pdir1) >= 2)
00776               ? /* taken */ 1
00777               : /* not taken */ 0);
00778     }
00779   else
00780     {
00781       /* BTB hit, so return target if it's a predicted-taken branch */
00782       return ((*(dir_update_ptr->pdir1) >= 2)
00783               ? /* taken */ pbtb->target
00784               : /* not taken */ 0);
00785     }
00786 }

void bpred_recover struct bpred_t   pred,
md_addr_t    baddr,
int    stack_recover_idx
 

Definition at line 793 of file bpred.c.

References bpred_t::retstack.

Referenced by ruu_writeback().

00797 {
00798   if (pred == NULL)
00799     return;
00800 
00801   pred->retstack.tos = stack_recover_idx;
00802 }

void bpred_reg_stats struct bpred_t   pred,
struct stat_sdb_t   sdb
 

Definition at line 422 of file bpred.c.

References bpred_t::addr_hits, BPred2bit, BPred2Level, BPredComb, BPredNotTaken, BPredTaken, bpred_t::class, bpred_t::dir_hits, bpred_t::jr_hits, bpred_t::jr_non_ras_hits, bpred_t::jr_non_ras_seen, bpred_t::jr_seen, bpred_t::lookups, bpred_t::misses, panic(), bpred_t::ras_hits, bpred_t::retstack_pops, bpred_t::retstack_pushes, stat_reg_counter, stat_reg_formula(), bpred_t::used_2lev, bpred_t::used_bimod, and bpred_t::used_ras.

Referenced by sim_reg_stats().

00424 {
00425   char buf[512], buf1[512], *name;
00426 
00427   /* get a name for this predictor */
00428   switch (pred->class)
00429     {
00430     case BPredComb:
00431       name = "bpred_comb";
00432       break;
00433     case BPred2Level:
00434       name = "bpred_2lev";
00435       break;
00436     case BPred2bit:
00437       name = "bpred_bimod";
00438       break;
00439     case BPredTaken:
00440       name = "bpred_taken";
00441       break;
00442     case BPredNotTaken:
00443       name = "bpred_nottaken";
00444       break;
00445     default:
00446       panic("bogus branch predictor class");
00447     }
00448 
00449   sprintf(buf, "%s.lookups", name);
00450   stat_reg_counter(sdb, buf, "total number of bpred lookups",
00451                    &pred->lookups, 0, NULL);
00452   sprintf(buf, "%s.updates", name);
00453   sprintf(buf1, "%s.dir_hits + %s.misses", name, name);
00454   stat_reg_formula(sdb, buf, "total number of updates", buf1, "%12.0f");
00455   sprintf(buf, "%s.addr_hits", name);
00456   stat_reg_counter(sdb, buf, "total number of address-predicted hits", 
00457                    &pred->addr_hits, 0, NULL);
00458   sprintf(buf, "%s.dir_hits", name);
00459   stat_reg_counter(sdb, buf, 
00460                    "total number of direction-predicted hits "
00461                    "(includes addr-hits)", 
00462                    &pred->dir_hits, 0, NULL);
00463   if (pred->class == BPredComb)
00464     {
00465       sprintf(buf, "%s.used_bimod", name);
00466       stat_reg_counter(sdb, buf, 
00467                        "total number of bimodal predictions used", 
00468                        &pred->used_bimod, 0, NULL);
00469       sprintf(buf, "%s.used_2lev", name);
00470       stat_reg_counter(sdb, buf, 
00471                        "total number of 2-level predictions used", 
00472                        &pred->used_2lev, 0, NULL);
00473     }
00474   sprintf(buf, "%s.misses", name);
00475   stat_reg_counter(sdb, buf, "total number of misses", &pred->misses, 0, NULL);
00476   sprintf(buf, "%s.jr_hits", name);
00477   stat_reg_counter(sdb, buf,
00478                    "total number of address-predicted hits for JR's",
00479                    &pred->jr_hits, 0, NULL);
00480   sprintf(buf, "%s.jr_seen", name);
00481   stat_reg_counter(sdb, buf,
00482                    "total number of JR's seen",
00483                    &pred->jr_seen, 0, NULL);
00484   sprintf(buf, "%s.jr_non_ras_hits.PP", name);
00485   stat_reg_counter(sdb, buf,
00486                    "total number of address-predicted hits for non-RAS JR's",
00487                    &pred->jr_non_ras_hits, 0, NULL);
00488   sprintf(buf, "%s.jr_non_ras_seen.PP", name);
00489   stat_reg_counter(sdb, buf,
00490                    "total number of non-RAS JR's seen",
00491                    &pred->jr_non_ras_seen, 0, NULL);
00492   sprintf(buf, "%s.bpred_addr_rate", name);
00493   sprintf(buf1, "%s.addr_hits / %s.updates", name, name);
00494   stat_reg_formula(sdb, buf,
00495                    "branch address-prediction rate (i.e., addr-hits/updates)",
00496                    buf1, "%9.4f");
00497   sprintf(buf, "%s.bpred_dir_rate", name);
00498   sprintf(buf1, "%s.dir_hits / %s.updates", name, name);
00499   stat_reg_formula(sdb, buf,
00500                   "branch direction-prediction rate (i.e., all-hits/updates)",
00501                   buf1, "%9.4f");
00502   sprintf(buf, "%s.bpred_jr_rate", name);
00503   sprintf(buf1, "%s.jr_hits / %s.jr_seen", name, name);
00504   stat_reg_formula(sdb, buf,
00505                   "JR address-prediction rate (i.e., JR addr-hits/JRs seen)",
00506                   buf1, "%9.4f");
00507   sprintf(buf, "%s.bpred_jr_non_ras_rate.PP", name);
00508   sprintf(buf1, "%s.jr_non_ras_hits.PP / %s.jr_non_ras_seen.PP", name, name);
00509   stat_reg_formula(sdb, buf,
00510                    "non-RAS JR addr-pred rate (ie, non-RAS JR hits/JRs seen)",
00511                    buf1, "%9.4f");
00512   sprintf(buf, "%s.retstack_pushes", name);
00513   stat_reg_counter(sdb, buf,
00514                    "total number of address pushed onto ret-addr stack",
00515                    &pred->retstack_pushes, 0, NULL);
00516   sprintf(buf, "%s.retstack_pops", name);
00517   stat_reg_counter(sdb, buf,
00518                    "total number of address popped off of ret-addr stack",
00519                    &pred->retstack_pops, 0, NULL);
00520   sprintf(buf, "%s.used_ras.PP", name);
00521   stat_reg_counter(sdb, buf,
00522                    "total number of RAS predictions used",
00523                    &pred->used_ras, 0, NULL);
00524   sprintf(buf, "%s.ras_hits.PP", name);
00525   stat_reg_counter(sdb, buf,
00526                    "total number of RAS hits",
00527                    &pred->ras_hits, 0, NULL);
00528   sprintf(buf, "%s.ras_rate.PP", name);
00529   sprintf(buf1, "%s.ras_hits.PP / %s.used_ras.PP", name, name);
00530   stat_reg_formula(sdb, buf,
00531                    "RAS prediction rate (i.e., RAS hits/used RAS)",
00532                    buf1, "%9.4f");
00533 }

void bpred_stats struct bpred_t   pred,
FILE *    stream
 

Definition at line 411 of file bpred.c.

References bpred_t::addr_hits, bpred_t::dir_hits, and bpred_t::misses.

00413 {
00414   fprintf(stream, "pred: addr-prediction rate = %f\n",
00415           (double)pred->addr_hits/(double)(pred->addr_hits+pred->misses));
00416   fprintf(stream, "pred: dir-prediction rate = %f\n",
00417           (double)pred->dir_hits/(double)(pred->dir_hits+pred->misses));
00418 }

void bpred_update struct bpred_t   pred,
md_addr_t    baddr,
md_addr_t    btarget,
int    taken,
int    pred_taken,
int    correct,
enum md_opcode    op,
struct bpred_update_t   dir_update_ptr
 

Definition at line 813 of file bpred.c.

References bpred_btb_ent_t::addr, bpred_t::addr_hits, BPred2Level, BPredComb, BPredNotTaken, BPredTaken, bpred_t::btb, bpred_t::class, dassert, bpred_update_t::dir, bpred_t::dir_hits, bpred_t::dirpred, bpred_t::jr_hits, bpred_t::jr_non_ras_hits, bpred_t::jr_non_ras_seen, bpred_t::jr_seen, MD_IS_CALL, MD_IS_INDIR, MD_OP_FLAGS, bpred_t::misses, bpred_btb_ent_t::next, bpred_btb_ent_t::op, bpred_update_t::pdir1, bpred_update_t::pdir2, bpred_update_t::pmeta, bpred_btb_ent_t::prev, bpred_t::ras_hits, bpred_t::retstack, bpred_t::retstack_pushes, bpred_btb_ent_t::target, bpred_t::used_2lev, bpred_t::used_bimod, and bpred_t::used_ras.

Referenced by ruu_commit(), ruu_dispatch(), ruu_writeback(), and sim_main().

00821 {
00822   struct bpred_btb_ent_t *pbtb = NULL;
00823   struct bpred_btb_ent_t *lruhead = NULL, *lruitem = NULL;
00824   int index, i;
00825 
00826   /* don't change bpred state for non-branch instructions or if this
00827    * is a stateless predictor*/
00828   if (!(MD_OP_FLAGS(op) & F_CTRL))
00829     return;
00830 
00831   /* Have a branch here */
00832 
00833   if (correct)
00834     pred->addr_hits++;
00835 
00836   if (!!pred_taken == !!taken)
00837     pred->dir_hits++;
00838   else
00839     pred->misses++;
00840 
00841   if (dir_update_ptr->dir.ras)
00842     {
00843       pred->used_ras++;
00844       if (correct)
00845         pred->ras_hits++;
00846     }
00847   else if ((MD_OP_FLAGS(op) & (F_CTRL|F_COND)) == (F_CTRL|F_COND))
00848     {
00849       if (dir_update_ptr->dir.meta)
00850         pred->used_2lev++;
00851       else
00852         pred->used_bimod++;
00853     }
00854 
00855   /* keep stats about JR's; also, but don't change any bpred state for JR's
00856    * which are returns unless there's no retstack */
00857   if (MD_IS_INDIR(op))
00858     {
00859       pred->jr_seen++;
00860       if (correct)
00861         pred->jr_hits++;
00862       
00863       if (!dir_update_ptr->dir.ras)
00864         {
00865           pred->jr_non_ras_seen++;
00866           if (correct)
00867             pred->jr_non_ras_hits++;
00868         }
00869       else
00870         {
00871           /* return that used the ret-addr stack; no further work to do */
00872           return;
00873         }
00874     }
00875 
00876   /* Can exit now if this is a stateless predictor */
00877   if (pred->class == BPredNotTaken || pred->class == BPredTaken)
00878     return;
00879 
00880   /* 
00881    * Now we know the branch didn't use the ret-addr stack, and that this
00882    * is a stateful predictor 
00883    */
00884 
00885 #ifdef RAS_BUG_COMPATIBLE
00886   /* if function call, push return-address onto return-address stack */
00887   if (MD_IS_CALL(op) && pred->retstack.size)
00888     {
00889       pred->retstack.tos = (pred->retstack.tos + 1)% pred->retstack.size;
00890       pred->retstack.stack[pred->retstack.tos].target = 
00891         baddr + sizeof(md_inst_t);
00892       pred->retstack_pushes++;
00893     }
00894 #endif /* RAS_BUG_COMPATIBLE */
00895 
00896   /* update L1 table if appropriate */
00897   /* L1 table is updated unconditionally for combining predictor too */
00898   if ((MD_OP_FLAGS(op) & (F_CTRL|F_UNCOND)) != (F_CTRL|F_UNCOND) &&
00899       (pred->class == BPred2Level || pred->class == BPredComb))
00900     {
00901       int l1index, shift_reg;
00902       
00903       /* also update appropriate L1 history register */
00904       l1index =
00905         (baddr >> MD_BR_SHIFT) & (pred->dirpred.twolev->config.two.l1size - 1);
00906       shift_reg =
00907         (pred->dirpred.twolev->config.two.shiftregs[l1index] << 1) | (!!taken);
00908       pred->dirpred.twolev->config.two.shiftregs[l1index] =
00909         shift_reg & ((1 << pred->dirpred.twolev->config.two.shift_width) - 1);
00910     }
00911 
00912   /* find BTB entry if it's a taken branch (don't allocate for non-taken) */
00913   if (taken)
00914     {
00915       index = (baddr >> MD_BR_SHIFT) & (pred->btb.sets - 1);
00916       
00917       if (pred->btb.assoc > 1)
00918         {
00919           index *= pred->btb.assoc;
00920           
00921           /* Now we know the set; look for a PC match; also identify
00922            * MRU and LRU items */
00923           for (i = index; i < (index+pred->btb.assoc) ; i++)
00924             {
00925               if (pred->btb.btb_data[i].addr == baddr)
00926                 {
00927                   /* match */
00928                   assert(!pbtb);
00929                   pbtb = &pred->btb.btb_data[i];
00930                 }
00931               
00932               dassert(pred->btb.btb_data[i].prev 
00933                       != pred->btb.btb_data[i].next);
00934               if (pred->btb.btb_data[i].prev == NULL)
00935                 {
00936                   /* this is the head of the lru list, ie current MRU item */
00937                   dassert(lruhead == NULL);
00938                   lruhead = &pred->btb.btb_data[i];
00939                 }
00940               if (pred->btb.btb_data[i].next == NULL)
00941                 {
00942                   /* this is the tail of the lru list, ie the LRU item */
00943                   dassert(lruitem == NULL);
00944                   lruitem = &pred->btb.btb_data[i];
00945                 }
00946             }
00947           dassert(lruhead && lruitem);
00948           
00949           if (!pbtb)
00950             /* missed in BTB; choose the LRU item in this set as the victim */
00951             pbtb = lruitem;     
00952           /* else hit, and pbtb points to matching BTB entry */
00953           
00954           /* Update LRU state: selected item, whether selected because it
00955            * matched or because it was LRU and selected as a victim, becomes 
00956            * MRU */
00957           if (pbtb != lruhead)
00958             {
00959               /* this splices out the matched entry... */
00960               if (pbtb->prev)
00961                 pbtb->prev->next = pbtb->next;
00962               if (pbtb->next)
00963                 pbtb->next->prev = pbtb->prev;
00964               /* ...and this puts the matched entry at the head of the list */
00965               pbtb->next = lruhead;
00966               pbtb->prev = NULL;
00967               lruhead->prev = pbtb;
00968               dassert(pbtb->prev || pbtb->next);
00969               dassert(pbtb->prev != pbtb->next);
00970             }
00971           /* else pbtb is already MRU item; do nothing */
00972         }
00973       else
00974         pbtb = &pred->btb.btb_data[index];
00975     }
00976       
00977   /* 
00978    * Now 'p' is a possibly null pointer into the direction prediction table, 
00979    * and 'pbtb' is a possibly null pointer into the BTB (either to a 
00980    * matched-on entry or a victim which was LRU in its set)
00981    */
00982 
00983   /* update state (but not for jumps) */
00984   if (dir_update_ptr->pdir1)
00985     {
00986       if (taken)
00987         {
00988           if (*dir_update_ptr->pdir1 < 3)
00989             ++*dir_update_ptr->pdir1;
00990         }
00991       else
00992         { /* not taken */
00993           if (*dir_update_ptr->pdir1 > 0)
00994             --*dir_update_ptr->pdir1;
00995         }
00996     }
00997 
00998   /* combining predictor also updates second predictor and meta predictor */
00999   /* second direction predictor */
01000   if (dir_update_ptr->pdir2)
01001     {
01002       if (taken)
01003         {
01004           if (*dir_update_ptr->pdir2 < 3)
01005             ++*dir_update_ptr->pdir2;
01006         }
01007       else
01008         { /* not taken */
01009           if (*dir_update_ptr->pdir2 > 0)
01010             --*dir_update_ptr->pdir2;
01011         }
01012     }
01013 
01014   /* meta predictor */
01015   if (dir_update_ptr->pmeta)
01016     {
01017       if (dir_update_ptr->dir.bimod != dir_update_ptr->dir.twolev)
01018         {
01019           /* we only update meta predictor if directions were different */
01020           if (dir_update_ptr->dir.twolev == (unsigned int)taken)
01021             {
01022               /* 2-level predictor was correct */
01023               if (*dir_update_ptr->pmeta < 3)
01024                 ++*dir_update_ptr->pmeta;
01025             }
01026           else
01027             {
01028               /* bimodal predictor was correct */
01029               if (*dir_update_ptr->pmeta > 0)
01030                 --*dir_update_ptr->pmeta;
01031             }
01032         }
01033     }
01034 
01035   /* update BTB (but only for taken branches) */
01036   if (pbtb)
01037     {
01038       /* update current information */
01039       dassert(taken);
01040 
01041       if (pbtb->addr == baddr)
01042         {
01043           if (!correct)
01044             pbtb->target = btarget;
01045         }
01046       else
01047         {
01048           /* enter a new branch in the table */
01049           pbtb->addr = baddr;
01050           pbtb->op = op;
01051           pbtb->target = btarget;
01052         }
01053     }
01054 }



UVa CS Department of Computer Science
School of Engineering, University of Virginia
151 Engineer's Way, P.O. Box 400740
Charlottesville, Virginia 22904-4740

(434) 982-2200  Fax: (434) 982-2214