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

📄 bpred.c

📁 RISC处理器仿真分析程序。可以用于研究通用RISC处理器的指令和架构设计。在linux下编译
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * bpred.c - branch predictor routines * * This file is a part of the SimpleScalar tool suite written by * Todd M. Austin as a part of the Multiscalar Research Project. *   * The tool suite is currently maintained by Doug Burger and Todd M. Austin. *  * Copyright (C) 1994, 1995, 1996, 1997 by Todd M. Austin * * This source file is distributed "as is" in the hope that it will be * useful.  The tool set comes with no warranty, and no author or * distributor accepts any responsibility for the consequences of its * use.  *  * Everyone is granted permission to copy, modify and redistribute * this tool set under the following conditions: *  *    This source code is distributed for non-commercial use only.  *    Please contact the maintainer for restrictions applying to  *    commercial use. * *    Permission is granted to anyone to make or distribute copies *    of this source code, either as received or modified, in any *    medium, provided that all copyright notices, permission and *    nonwarranty notices are preserved, and that the distributor *    grants the recipient permission for further redistribution as *    permitted by this document. * *    Permission is granted to distribute this file in compiled *    or executable form under the same conditions that apply for *    source code, provided that either: * *    A. it is accompanied by the corresponding machine-readable *       source code, *    B. it is accompanied by a written offer, with no time limit, *       to give anyone a machine-readable copy of the corresponding *       source code in return for reimbursement of the cost of *       distribution.  This written offer must permit verbatim *       duplication by anyone, or *    C. it is distributed by someone who received only the *       executable form, and is accompanied by a copy of the *       written offer of source code that they received concurrently. * * In other words, you are welcome to use, share and improve this * source file.  You are forbidden to forbid anyone else to use, share * and improve what you give them. * * INTERNET: dburger@cs.wisc.edu * US Mail:  1210 W. Dayton Street, Madison, WI 53706 * * $Id: bpred.c,v 1.1.1.1 1997/05/22 00:33:18 aklauser Exp $ * * $Log: bpred.c,v $ * Revision 1.1.1.1  1997/05/22 00:33:18  aklauser * * Revision 1.11  1997/05/01 20:23:00  skadron * BTB bug fixes; jumps no longer update direction state; non-taken *    branches non longer update BTB * * Revision 1.10  1997/05/01 00:05:42  skadron * Separated BTB from direction-predictor * * Revision 1.9  1997/04/30  01:42:42  skadron * 1. Not aggressively returning the BTB target regardless of hit on jump's, *    but instead returning just "taken" when it's a BTB miss yields an *    apparent epsilon performance improvement for cc1 and perl. * 2. Bug fix: if no retstack, treat return's as any other jump * * Revision 1.8  1997/04/29  23:50:33  skadron * Added r31 info to distinguish between return-JRs and other JRs for bpred * * Revision 1.7  1997/04/29  22:53:04  skadron * Hopefully bpred is now right: bpred now allocates entries only for *    branches; on a BTB miss it still returns a direction; and it uses a *    return-address stack.  Returns are not yet distinguished among JR's * * Revision 1.6  1997/04/28  17:37:02  skadron * Bpred now allocates entries for any instruction instead of only *    branches; also added return-address stack * * Revision 1.5  1997/04/24  16:57:21  skadron * Bpred used to return no prediction if the indexing branch didn't match *    in the BTB.  Now it can predict a direction even on a BTB address *    conflict * * Revision 1.4  1997/03/27  16:31:52  skadron * Fixed bug: sim-outorder calls bpred_after_priming(), even if no bpred *    exists.  Now we check for a null ptr. * * Revision 1.3  1997/03/25  16:16:33  skadron * Statistics now take account of priming: statistics report only *    post-prime info. * * Revision 1.2  1997/02/24  18:02:41  skadron * Fixed output format of a formula stat * * Revision 1.1  1997/02/16  22:23:54  skadron * Initial revision * * */#include <stdio.h>#include <stdlib.h>#include <math.h>#include <assert.h>#include "misc.h"#include "ss.h"#include "bpred.h"/* create a branch predictor */struct bpred *				/* branch predictory instance */bpred_create(enum bpred_class class,	/* type of predictor to create */	     unsigned int bimod_size,	/* bimod table size */	     unsigned int l1size,	/* 2lev l1 table size */	     unsigned int l2size,	/* 2lev l2 table size */	     unsigned int meta_size,	/* meta table size */	     unsigned int shift_width,	/* history register width */	     unsigned int xor,  	/* history xor address flag */	     unsigned int btb_sets,	/* number of sets in BTB */ 	     unsigned int btb_assoc,	/* BTB associativity */	     unsigned int retstack_size) /* num entries in ret-addr stack */{  struct bpred *pred;  if (!(pred = calloc(1, sizeof(struct bpred))))    fatal("out of virtual memory");  pred->class = class;  switch (class) {  case BPredComb:    /* bimodal component */    pred->dirpred.bimod =       bpred_dir_create(BPred2bit, bimod_size, 0, 0, 0);    /* 2-level component */    pred->dirpred.twolev =       bpred_dir_create(BPred2Level, l1size, l2size, shift_width, xor);    /* metapredictor component */    pred->dirpred.meta =       bpred_dir_create(BPred2bit, meta_size, 0, 0, 0);    break;  case BPred2Level:    pred->dirpred.twolev =       bpred_dir_create(class, l1size, l2size, shift_width, xor);    break;  case BPred2bit:    pred->dirpred.bimod =       bpred_dir_create(class, bimod_size, 0, 0, 0);  case BPredTaken:  case BPredNotTaken:    /* no other state */    break;  default:    panic("bogus predictor class");  }  /* allocate ret-addr stack */  switch (class) {  case BPredComb:  case BPred2Level:  case BPred2bit:    {      int i;      /* allocate BTB */      if (!btb_sets || (btb_sets & (btb_sets-1)) != 0)	fatal("number of BTB sets must be non-zero and a power of two");      if (!btb_assoc || (btb_assoc & (btb_assoc-1)) != 0)	fatal("BTB associativity must be non-zero and a power of two");      if (!(pred->btb.btb_data = calloc(btb_sets * btb_assoc,					sizeof(struct bpred_btb_ent))))	fatal("cannot allocate BTB");      pred->btb.sets = btb_sets;      pred->btb.assoc = btb_assoc;      if (pred->btb.assoc > 1)	for (i=0; i < (pred->btb.assoc*pred->btb.sets); i++)	  {	    if (i % pred->btb.assoc != pred->btb.assoc - 1)	      pred->btb.btb_data[i].next = &pred->btb.btb_data[i+1];	    else	      pred->btb.btb_data[i].next = NULL;	    	    if (i % pred->btb.assoc != pred->btb.assoc - 1)	      pred->btb.btb_data[i+1].prev = &pred->btb.btb_data[i];	  }      /* allocate retstack */      if ((retstack_size & (retstack_size-1)) != 0)	fatal("Return-address-stack size must be zero or a power of two");            pred->retstack.size = retstack_size;      if (retstack_size)	if (!(pred->retstack.stack = calloc(retstack_size, 					    sizeof(struct bpred_btb_ent))))	  fatal("cannot allocate return-address-stack");      pred->retstack.tos = retstack_size - 1;            break;    }  case BPredTaken:  case BPredNotTaken:    /* no other state */    break;  default:    panic("bogus predictor class");  }  return pred;}/* create a branch direction predictor */struct bpred_dir *		/* branch direction predictor instance */bpred_dir_create (  enum bpred_class class,	/* type of predictor to create */  unsigned int l1size,	 	/* level-1 table size */  unsigned int l2size,	 	/* level-2 table size (if relevant) */  unsigned int shift_width,	/* history register width */  unsigned int  xor)    	/* history xor address flag */{  struct bpred_dir *pred_dir;  unsigned int cnt;  int flipflop;  if (!(pred_dir = calloc(1, sizeof(struct bpred_dir))))    fatal("out of virtual memory");  pred_dir->class = class;  cnt = -1;  switch (class) {  case BPred2Level:    {      if (!l1size || (l1size & (l1size-1)) != 0)	fatal("level-1 size, `%d', must be non-zero and a power of two", 	      l1size);      pred_dir->config.two.l1size = l1size;            if (!l2size || (l2size & (l2size-1)) != 0)	fatal("level-2 size, `%d', must be non-zero and a power of two", 	      l2size);      pred_dir->config.two.l2size = l2size;            if (!shift_width || shift_width > 30)	fatal("shift register width, `%d', must be non-zero and positive",	      shift_width);      pred_dir->config.two.shift_width = shift_width;            pred_dir->config.two.xor = xor;      pred_dir->config.two.shiftregs = calloc(l1size, sizeof(int));      if (!pred_dir->config.two.shiftregs)	fatal("cannot allocate shift register table");            pred_dir->config.two.l2table = calloc(l2size, sizeof(unsigned char));      if (!pred_dir->config.two.l2table)	fatal("cannot allocate second level table");      /* initialize counters to weakly this-or-that */      flipflop = 1;      for (cnt = 0; cnt < l2size; cnt++)	{	  pred_dir->config.two.l2table[cnt] = flipflop;	  flipflop = 3 - flipflop;	}      break;    }  case BPred2bit:    if (!l1size || (l1size & (l1size-1)) != 0)      fatal("2bit table size, `%d', must be non-zero and a power of two", 	    l1size);    pred_dir->config.bimod.size = l1size;    if (!(pred_dir->config.bimod.table =	  calloc(l1size, sizeof(unsigned char))))      fatal("cannot allocate 2bit storage");    /* initialize counters to weakly this-or-that */    flipflop = 1;    for (cnt = 0; cnt < l1size; cnt++)      {	pred_dir->config.bimod.table[cnt] = flipflop;	flipflop = 3 - flipflop;      }    break;  case BPredTaken:  case BPredNotTaken:    /* no other state */    break;  default:    panic("bogus branch direction predictor class");  }  return pred_dir;}/* print branch direction predictor configuration */voidbpred_dir_config(  struct bpred_dir *pred_dir,   /* branch direction predictor instance */  char name[],                  /* predictor name */  FILE *stream)	        	/* output stream */{  switch (pred_dir->class) {  case BPred2Level:    fprintf(stream,      "pred_dir: %s: 2-lvl: %d l1-sz, %d bits/ent, %s xor, %d l2-sz, direct-mapped\n",      name, pred_dir->config.two.l1size, pred_dir->config.two.shift_width,      pred_dir->config.two.xor ? "" : "no", pred_dir->config.two.l2size);    break;  case BPred2bit:    fprintf(stream, "pred_dir: %s: 2-bit: %d entries, direct-mapped\n",      name, pred_dir->config.bimod.size);    break;  case BPredTaken:    fprintf(stream, "pred_dir: %s: predict taken\n", name);    break;  case BPredNotTaken:    fprintf(stream, "pred_dir: %s: predict not taken\n", name);    break;  default:    panic("bogus branch direction predictor class");  }}/* print branch predictor configuration */voidbpred_config(struct bpred *pred,	/* branch predictor instance */	     FILE *stream)		/* output stream */{  switch (pred->class) {  case BPredComb:    bpred_dir_config (pred->dirpred.bimod, "bimod", stream);    bpred_dir_config (pred->dirpred.twolev, "2lev", stream);    bpred_dir_config (pred->dirpred.meta, "meta", stream);    fprintf(stream, "btb: %d sets x %d associativity", 	    pred->btb.sets, pred->btb.assoc);    fprintf(stream, "ret_stack: %d entries", pred->retstack.size);    break;  case BPred2Level:    bpred_dir_config (pred->dirpred.twolev, "2lev", stream);    fprintf(stream, "btb: %d sets x %d associativity", 	    pred->btb.sets, pred->btb.assoc);    fprintf(stream, "ret_stack: %d entries", pred->retstack.size);    break;  case BPred2bit:    bpred_dir_config (pred->dirpred.bimod, "bimod", stream);    fprintf(stream, "btb: %d sets x %d associativity", 	    pred->btb.sets, pred->btb.assoc);    fprintf(stream, "ret_stack: %d entries", pred->retstack.size);    break;  case BPredTaken:    bpred_dir_config (pred->dirpred.bimod, "taken", stream);    break;  case BPredNotTaken:    bpred_dir_config (pred->dirpred.bimod, "nottaken", stream);    break;  default:    panic("bogus branch predictor class");  }}/* print predictor stats */voidbpred_stats(struct bpred *pred,		/* branch predictor instance */	    FILE *stream)		/* output stream */{  fprintf(stream, "pred: addr-prediction rate = %f\n",	  (double)pred->addr_hits/(double)(pred->addr_hits+pred->misses));  fprintf(stream, "pred: dir-prediction rate = %f\n",	  (double)pred->dir_hits/(double)(pred->dir_hits+pred->misses));}/* register branch predictor stats */voidbpred_reg_stats(struct bpred *pred,	/* branch predictor instance */		struct stat_sdb_t *sdb)	/* stats database */{  char buf[512], buf1[512], *name;  /* get a name for this predictor */  switch (pred->class)    {    case BPredComb:      name = "bpred_comb";      break;    case BPred2Level:      name = "bpred_2lev";      break;    case BPred2bit:      name = "bpred_bimod";      break;    case BPredTaken:      name = "bpred_taken";      break;    case BPredNotTaken:      name = "bpred_nottaken";      break;    default:      panic("bogus branch predictor class");    }  sprintf(buf, "%s.lookups", name);  stat_reg_counter(sdb, buf, "total number of bpred lookups",		   &pred->lookups, 0, NULL);  sprintf(buf, "%s.updates", name);  sprintf(buf1, "%s.dir_hits + %s.misses", name, name);  stat_reg_formula(sdb, buf, "total number of updates", buf1, "%11.0f");  sprintf(buf, "%s.addr_hits", name);  stat_reg_counter(sdb, buf, "total number of address-predicted hits", 		   &pred->addr_hits, 0, NULL);  sprintf(buf, "%s.dir_hits", name);  stat_reg_counter(sdb, buf, 		   "total number of direction-predicted hits "		   "(includes addr-hits)", 		   &pred->dir_hits, 0, NULL);  if (pred->class == BPredComb)    {      sprintf(buf, "%s.used_bimod", name);      stat_reg_counter(sdb, buf, 		       "total number of bimodal predictions used", 		       &pred->used_bimod, 0, NULL);      sprintf(buf, "%s.used_2lev", name);      stat_reg_counter(sdb, buf, 		       "total number of 2-level predictions used", 		       &pred->used_2lev, 0, NULL);    }  sprintf(buf, "%s.misses", name);  stat_reg_counter(sdb, buf, "total number of misses", &pred->misses, 0, NULL);  sprintf(buf, "%s.jr_hits", name);  stat_reg_counter(sdb, buf,		   "total number of address-predicted hits for JR's",		   &pred->jr_hits, 0, NULL);  sprintf(buf, "%s.jr_seen", name);  stat_reg_counter(sdb, buf,		   "total number of JR's seen",		   &pred->jr_seen, 0, NULL);  sprintf(buf, "%s.bpred_addr_rate", name);  sprintf(buf1, "%s.addr_hits / %s.updates", name, name);  stat_reg_formula(sdb, buf,		   "branch address-prediction rate (i.e., addr-hits/updates)",		   buf1, "%9.4f");  sprintf(buf, "%s.bpred_dir_rate", name);  sprintf(buf1, "%s.dir_hits / %s.updates", name, name);  stat_reg_formula(sdb, buf,		  "branch direction-prediction rate (i.e., all-hits/updates)",		  buf1, "%9.4f");  sprintf(buf, "%s.bpred_jr_rate", name);  sprintf(buf1, "%s.jr_hits / %s.jr_seen", name, name);  stat_reg_formula(sdb, buf,		  "JR address-prediction rate (i.e., JR addr-hits/JRs seen)",		  buf1, "%9.4f");  sprintf(buf, "%s.retstack_pushes", name);  stat_reg_counter(sdb, buf,		   "total number of address pushed onto ret-addr stack",		   &pred->retstack_pushes, 0, NULL);  sprintf(buf, "%s.retstack_pops", name);

⌨️ 快捷键说明

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