/* LSU EE 7700-1, Computer Architecture Research Methods
Spring 2006
Live classroom example of writing a local history branch predictor
analyzer for Shade.
*/
#define TR_REGS
#include <stdio.h>
#include <stdlib.h>
#include <IHASH.h>
#include <ITYPES.h>
#include <trace.h>
#include <stdtr.h>
#include <trctl.h>
static void sim_init(int argc, char **argv);
static void sim_analyzer();
static void sim_results_write();
static void bp_init(int argc, char **argv);
static void bp_predict(int pc, int outcome);
static void bp_results_write();
int shade_main(int argc, char **argv)
{
sim_init(argc, argv);
bp_init(argc, argv);
shade_trctl_trsize( sizeof(Trace) ); /* Initialize. */
shade_trctl_it(IT_ANY, 1, 0,
TC_TAKEN | TC_PC | TC_IH ); /* Tell shade what to collect. */
shade_shell(sim_analyzer); /* Start. (Returns after analyzer done.) */
sim_results_write();
bp_results_write();
return 0;
}
struct Sim_Info_s
{
int icount; /* Number of instructions. */
int ibranch; /* Number of integer branches. */
};
typedef struct Sim_Info_s Sim_Info;
Sim_Info sim_info;
void
sim_init(int argc, char **argv)
{
sim_info.icount = 0;
sim_info.ibranch = 0;
}
void
sim_analyzer()
{
/* /data4/koppel/shadekit/shade.v9.elf/src/include/trace.h */
Trace *trace_entry;
while( ( trace_entry = shade_step() ) )
{
/* One iteration per (traced) instruction. */
int ih = trace_entry->tr_ih; /* Information about instruction. */
int prediction;
int *elt;
sim_info.icount++;
if( !ih_isbicc(ih) ) continue;
sim_info.ibranch++;
bp_predict(trace_entry->tr_pc,trace_entry->tr_taken);
}
}
void
sim_results_write()
{
printf("Found %d instructions of which %d were branches.\n",
sim_info.icount, sim_info.ibranch);
}
/* ************************************************************************ */
struct Branch_Predictor_s
{
int bht_sizelg, bht_size, bht_mask;
int *bht;
char *pht;
int pht_size,pht_mask;
int history_len;
int correct, wrong;
};
typedef struct Branch_Predictor_s Branch_Predictor;
Branch_Predictor bp;
void
bp_init(int argv, char **argc)
{
int i;
bp.wrong = bp.correct = 0;
bp.bht_sizelg = atoi(argc[1]);
bp.bht_size = 1 << bp.bht_sizelg;
bp.bht_mask = bp.bht_size - 1;
bp.bht = (int*) malloc( bp.bht_size * sizeof(bp.bht[0]) );
bp.history_len = atoi(argc[2]);
bp.pht_size = 1 << bp.history_len;
bp.pht_mask = bp.pht_size -1;
bp.pht = (char*) malloc( bp.pht_size * sizeof(bp.pht[0]) );
/* Note: The line below does not make sense for the local history
predictor, it did serve a purpose in the bimodal predictor which
is what this code simulated before being modified. */
for(i=0; i<bp.bht_size; i++) bp.bht[i] = 1;
}
void
bp_predict(int pc, int outcome)
{
int *local_history = &bp.bht[ ( pc >> 2 ) & bp.bht_mask ];
char *elt = &bp.pht[ *local_history ];
int prediction = *elt > 1;
*local_history = ( ( *local_history << 1 ) + outcome ) & bp.pht_mask;
if( prediction == outcome ) bp.correct++; else bp.wrong++;
if( outcome && *elt < 3 ) elt[0]++;
if( !outcome && *elt > 0 ) elt[0]--;
}
void
bp_results_write()
{
printf("For table size lg %d\n",bp.bht_sizelg);
printf("Accuracy %.3f\n", ((double)bp.correct)/(bp.correct+bp.wrong));
}