⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bpred.phalanx_history.c

📁 uploading the file , the system will delete the file when time expires
💻 C
📖 第 1 页 / 共 3 页
字号:
  /* record pre-pop TOS; if this branch is executed speculatively   * and is squashed, we'll restore the TOS and hope the data   * wasn't corrupted in the meantime. */  if (pred->retstack.size)    *stack_recover_idx = pred->retstack.tos;  else    *stack_recover_idx = 0;  /* if this is a return, pop return-address stack */  if (is_return && pred->retstack.size)    {      md_addr_t target = pred->retstack.stack[pred->retstack.tos].target;      pred->retstack.tos = (pred->retstack.tos + pred->retstack.size - 1)	                   % pred->retstack.size;      pred->retstack_pops++;      dir_update_ptr->dir.ras = TRUE; /* using RAS here */      return target;    }#ifndef RAS_BUG_COMPATIBLE  /* if function call, push return-address onto return-address stack */  if (is_call && pred->retstack.size)    {      pred->retstack.tos = (pred->retstack.tos + 1)% pred->retstack.size;      pred->retstack.stack[pred->retstack.tos].target = 	baddr + sizeof(md_inst_t);      pred->retstack_pushes++;    }#endif /* !RAS_BUG_COMPATIBLE */    /* not a return. Get a pointer into the Branch table buffer */  index = (baddr >> MD_BR_SHIFT) & (pred->btb.sets - 1);  if (pred->btb.assoc > 1)    {      index *= pred->btb.assoc;      // note, at this point, pbtb==NULL      /* Now we know the set; look for a PC match */      for (i = index; i < (index+pred->btb.assoc) ; i++)	if (pred->btb.btb_data[i].addr == baddr)	  {	    /* match */	    pbtb = &pred->btb.btb_data[i];	    break;	  }    }	  else    {      // no need to do an associative search...just index directly      pbtb = &pred->btb.btb_data[index];      if (pbtb->addr != baddr)	// pbtb==NULL => a BTB miss has occurred	pbtb = NULL;    }  /*   * We now also have a pointer into the BTB for a hit, or NULL otherwise   */  /* if this is a jump, ignore predicted direction; we know it's taken. */  if ((MD_OP_FLAGS(op) & (F_CTRL|F_UNCOND)) == (F_CTRL|F_UNCOND))    {      return (pbtb ? pbtb->target : 1);    }  /* otherwise we have a conditional branch */  if (pbtb == NULL)    {      /* BTB miss -- just return a predicted direction */      return ((*(dir_update_ptr->pdir1) >= 2)	      ? /* taken */     1	      : /* not taken */ 0);    }  else    {      /* BTB hit, so return target if it's a predicted-taken branch */      return ((*(dir_update_ptr->pdir1) >= 2)	      ? /* taken */     pbtb->target	      : /* not taken */ 0);    }}/* Speculative execution can corrupt the ret-addr stack.  So for each * lookup we return the top-of-stack (TOS) at that point; a mispredicted * branch, as part of its recovery, restores the TOS using this value -- * hopefully this uncorrupts the stack. */voidbpred_recover(struct bpred_t *pred,	/* branch predictor instance */	      md_addr_t baddr,		/* branch address */	      int stack_recover_idx)	/* Non-speculative top-of-stack;					 * used on mispredict recovery */{  if (pred == NULL)    return;  if(pred->class==BPredPhalanx) {    // each of the child predictors must recover    if(GAG_ENABLE) bpred_recover(pred->phalanx.gag,baddr,stack_recover_idx);    if(PAG_ENABLE) bpred_recover(pred->phalanx.pag,baddr,stack_recover_idx);    if(PAP_ENABLE) bpred_recover(pred->phalanx.pap,baddr,stack_recover_idx);    if(GSHARE_ENABLE) bpred_recover(pred->phalanx.gshare,baddr,stack_recover_idx);    if(BIMOD_ENABLE) bpred_recover(pred->phalanx.bimod, baddr,stack_recover_idx);  }  pred->retstack.tos = stack_recover_idx;}/* update the branch predictor, only useful for stateful predictors; updates   entry for instruction type OP at address BADDR.  BTB only gets updated   for branches which are taken.  Inst was determined to jump to   address BTARGET and was taken if TAKEN is non-zero.  Predictor    statistics are updated with result of prediction, indicated by CORRECT and    PRED_TAKEN, predictor state to be updated is indicated by *DIR_UPDATE_PTR    (may be NULL for jumps, which shouldn't modify state bits).  Note if   bpred_update is done speculatively, branch-prediction may get polluted. */voidbpred_update(struct bpred_t *pred,	/* branch predictor instance */	     md_addr_t baddr,		/* branch address */	     md_addr_t btarget,		/* resolved branch target */	     int taken,			/* non-zero if branch was taken */	     int pred_taken,		/* non-zero if branch was pred taken */	     int correct,		/* was earlier addr prediction ok? */	     enum md_opcode op,		/* opcode of instruction */	     struct bpred_update_t *dir_update_ptr)/* pred state pointer */{  struct bpred_btb_ent_t *pbtb = NULL;  struct bpred_btb_ent_t *lruhead = NULL, *lruitem = NULL;  int index, i;  /* don't change bpred state or statistic for non-branch instructions or if this   * is a stateless predictor*/  if (!(MD_OP_FLAGS(op) & F_CTRL))    return;  /* Have a branch here */  if(PRINT_RESOL==0) {    fprintf(outfile,"PREDICTION OF BRANCH AT %i ",(int) baddr);    fprintf(outfile,(pred_taken==0) ? "NOTTAKEN ":"TAKEN ");    if(!correct) fprintf(outfile,"WAS INCORRECT, TRUE PATH WAS %i\n",(int) btarget);    else fprintf(outfile,"WAS CORRECT\n");    fflush(outfile);  }  if (correct)    pred->addr_hits++;  if (!!pred_taken == !!taken)    pred->dir_hits++;  else    pred->misses++;  if (dir_update_ptr->dir.ras)    {      pred->used_ras++;      if (correct)	pred->ras_hits++;    }  else if ((MD_OP_FLAGS(op) & (F_CTRL|F_COND)) == (F_CTRL|F_COND))    {      if (dir_update_ptr->dir.meta)	pred->used_2lev++;      else	pred->used_bimod++;    }  /* keep stats about JR's; also, but don't change any bpred state for JR's   * which are returns unless there's no retstack */  if (MD_IS_INDIR(op))    {      pred->jr_seen++;      if (correct)	pred->jr_hits++;            if (!dir_update_ptr->dir.ras)	{	  pred->jr_non_ras_seen++;	  if (correct)	    pred->jr_non_ras_hits++;	}      else	{	  /* return that used the ret-addr stack; no further work to do */	  return;	}    }  // now that stats are recorded, if this is a phalanx combination predictor,  // ignore the rest of this function   if(pred->class==BPredPhalanx) {    // update all child predictors -- "correct" is not correct for all predictors    int sri;    struct bpred_update_t dup;    int prediction;    int predNum = 0;    if(GAG_ENABLE) {    prediction = bpred_lookup(pred->phalanx.gag,baddr,btarget,op,MD_IS_CALL(op),MD_IS_RETURN(op),&dup,&sri);    pred_taken = ( prediction == btarget ) ? 1 : 0;    correct = (!!pred_taken == !! taken);     bpred_update(pred->phalanx.gag,baddr,btarget,taken,pred_taken,correct,                 op,dir_update_ptr);    updatePhalanxMember(pred,predNum,correct);    predNum++;    }    if(PAG_ENABLE) {    prediction = bpred_lookup(pred->phalanx.pag,baddr,btarget,op,MD_IS_CALL(op),MD_IS_RETURN(op),&dup,&sri);    pred_taken = ( prediction == btarget ) ? 1 : 0;    correct = (!!pred_taken == !! taken);     bpred_update(pred->phalanx.pag,baddr,btarget,taken,pred_taken,correct,                 op,dir_update_ptr);    updatePhalanxMember(pred,predNum,correct);    predNum++;    }    if(PAP_ENABLE) {    prediction = bpred_lookup(pred->phalanx.pap,baddr,btarget,op,MD_IS_CALL(op),MD_IS_RETURN(op),&dup,&sri);    pred_taken = ( prediction == btarget ) ? 1 : 0;    correct = (!!pred_taken == !! taken);     bpred_update(pred->phalanx.pap,baddr,btarget,taken,pred_taken,correct,                 op,dir_update_ptr);    updatePhalanxMember(pred,predNum,correct);    predNum++;    }    if(GSHARE_ENABLE) {    prediction = bpred_lookup(pred->phalanx.gshare,baddr,btarget,op,MD_IS_CALL(op),MD_IS_RETURN(op),&dup,&sri);    pred_taken = ( prediction == btarget ) ? 1 : 0;    correct = (!!pred_taken == !! taken);     bpred_update(pred->phalanx.gshare,baddr,btarget,taken,pred_taken,correct,                 op,dir_update_ptr);    updatePhalanxMember(pred,predNum,correct);    predNum++;    }    if(BIMOD_ENABLE) {    prediction = bpred_lookup(pred->phalanx.bimod,baddr,btarget,op,MD_IS_CALL(op),MD_IS_RETURN(op),&dup,&sri);    pred_taken = ( prediction == btarget ) ? 1 : 0;    correct = (!!pred_taken == !! taken);      bpred_update(pred->phalanx.bimod ,baddr,btarget,taken,pred_taken,correct,                 op,dir_update_ptr);    updatePhalanxMember(pred,predNum,correct);    predNum++;    }    // after all children have been updated, return    return;  }  // MAKE SURE TO INCLUDE ALL STATELESS PREDICTORS HERE  /* Can exit now if this is a stateless predictor */  if (pred->class == BPredNotTaken || pred->class == BPredTaken)    return;  /*    * Now we know the branch didn't use the ret-addr stack, and that this   * is a stateful predictor    */#ifdef RAS_BUG_COMPATIBLE  /* if function call, push return-address onto return-address stack */  if (MD_IS_CALL(op) && pred->retstack.size)    {      pred->retstack.tos = (pred->retstack.tos + 1)% pred->retstack.size;      pred->retstack.stack[pred->retstack.tos].target = 	baddr + sizeof(md_inst_t);      pred->retstack_pushes++;    }#endif /* RAS_BUG_COMPATIBLE */  /* update L1 table if appropriate */  /* L1 table is updated unconditionally for combining predictor too */  if ((MD_OP_FLAGS(op) & (F_CTRL|F_UNCOND)) != (F_CTRL|F_UNCOND) &&      (pred->class == BPred2Level || pred->class == BPredComb))    // if this is a conditional branch AND    // if this predictor contains a 2level component    {      int l1index, shift_reg;            /* also update appropriate L1 history register */      l1index =	(baddr >> MD_BR_SHIFT) & (pred->dirpred.twolev->config.two.l1size - 1);      shift_reg =	(pred->dirpred.twolev->config.two.shiftregs[l1index] << 1) | (!!taken);      pred->dirpred.twolev->config.two.shiftregs[l1index] =	shift_reg & ((1 << pred->dirpred.twolev->config.two.shift_width) - 1);    }  /* find BTB entry if it's a taken branch (don't allocate for non-taken) */  if (taken)    {      index = (baddr >> MD_BR_SHIFT) & (pred->btb.sets - 1);            if (pred->btb.assoc > 1)	{	  index *= pred->btb.assoc;	  	  /* Now we know the set; look for a PC match; also identify	   * MRU and LRU items */	  for (i = index; i < (index+pred->btb.assoc) ; i++)	    {	      if (pred->btb.btb_data[i].addr == baddr)		{		  /* match */		  assert(!pbtb);		  pbtb = &pred->btb.btb_data[i];		}	      	      dassert(pred->btb.btb_data[i].prev 		      != pred->btb.btb_data[i].next);	      if (pred->btb.btb_data[i].prev == NULL)		{		  /* this is the head of the lru list, ie current MRU item */		  dassert(lruhead == NULL);		  lruhead = &pred->btb.btb_data[i];		}	      if (pred->btb.btb_data[i].next == NULL)		{		  /* this is the tail of the lru list, ie the LRU item */		  dassert(lruitem == NULL);		  lruitem = &pred->btb.btb_data[i];		}	    }	  dassert(lruhead && lruitem);	  	  if (!pbtb)	    /* missed in BTB; choose the LRU item in this set as the victim */	    pbtb = lruitem;		  /* else hit, and pbtb points to matching BTB entry */	  	  /* Update LRU state: selected item, whether selected because it	   * matched or because it was LRU and selected as a victim, becomes 	   * MRU */	  if (pbtb != lruhead)	    {	      /* this splices out the matched entry... */	      if (pbtb->prev)		pbtb->prev->next = pbtb->next;	      if (pbtb->next)		pbtb->next->prev = pbtb->prev;	      /* ...and this puts the matched entry at the head of the list */	      pbtb->next = lruhead;	      pbtb->prev = NULL;	      lruhead->prev = pbtb;	      dassert(pbtb->prev || pbtb->next);	      dassert(pbtb->prev != pbtb->next);	    }	  /* else pbtb is already MRU item; do nothing */	}      else	pbtb = &pred->btb.btb_data[index];    }        /*    * Now 'p' is a possibly null pointer into the direction prediction table,    * and 'pbtb' is a possibly null pointer into the BTB (either to a    * matched-on entry or a victim which was LRU in its set)   */  /* update state (but not for jumps) */  if (dir_update_ptr->pdir1)    {      if (taken)	{	  if (*dir_update_ptr->pdir1 < 3)	    ++*dir_update_ptr->pdir1;	}      else	{ /* not taken */	  if (*dir_update_ptr->pdir1 > 0)	    --*dir_update_ptr->pdir1;	}    }  /* combining predictor also updates second predictor and meta predictor */  /* second direction predictor */  if (dir_update_ptr->pdir2)    {      if (taken)	{	  if (*dir_update_ptr->pdir2 < 3)	    ++*dir_update_ptr->pdir2;	}      else	{ /* not taken */	  if (*dir_update_ptr->pdir2 > 0)	    --*dir_update_ptr->pdir2;	}    }  /* meta predictor */  if (dir_update_ptr->pmeta)    {      if (dir_update_ptr->dir.bimod != dir_update_ptr->dir.twolev)	{	  /* we only update meta predictor if directions were different */	  if (dir_update_ptr->dir.twolev == (unsigned int)taken)	    {	      /* 2-level predictor was correct */	      if (*dir_update_ptr->pmeta < 3)		++*dir_update_ptr->pmeta;	    }	  else	    {	      /* bimodal predictor was correct */	      if (*dir_update_ptr->pmeta > 0)		--*dir_update_ptr->pmeta;	    }	}    }  /* update BTB (but only for taken branches) */  if (pbtb)    {      /* update current information */      dassert(taken);      if (pbtb->addr == baddr)	{	  if (!correct)	    pbtb->target = btarget;	}      else	{	  /* enter a new branch in the table */	  pbtb->addr = baddr;	  pbtb->op = op;	  pbtb->target = btarget;	}    }} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -