// my_predictor.h
// This file contains a sample my_predictor class.
// It is a simple 512-entry perceptrons with a history length of 16.

class my_update : public branch_update {
public:
	unsigned int index;
};

class my_predictor : public branch_predictor {
public:
#define HISTORY_LENGTH	16
#define ENTRY	        512  
#define THRESHOLD       45
	my_update u;
	branch_info bi;
        int y;  
	unsigned long history,history_reg;
	signed char tab [ENTRY][HISTORY_LENGTH+1];

	my_predictor (void) : history(0) { 
		memset (tab, 0, sizeof (tab));
	}

	branch_update *predict (branch_info & b) {
		bi = b;
		if (b.br_flags & BR_CONDITIONAL) {
			u.index = (b.address) % ENTRY ; //hash PC to obtain entry.
                        y= tab [u.index][0];// y=W0
                        history_reg=history;
                        for (int j=1; j<=HISTORY_LENGTH; j++) 
			   {
                             	if (history_reg & 1){
                              		 y+=tab [u.index][j];//if history bit taken, 
                             	}                        //y=y+Wi
				else {                                   //otherwise, y=y-Wi
                               		y-=tab [u.index][j];
				}
					history_reg >>= 1;
                            }
                              if (y >= 0) {
                            	     u.direction_prediction (true);
                               }
                              else {
                             	    u.direction_prediction (false);
                                 }
		} 
		else {
			u.direction_prediction (true);
		     }
		u.target_prediction (0);
			return &u;
	    }

	void update (branch_update *u, bool taken, unsigned int target) {
		       bool t,ht;
                       long int k=1;
                       history_reg=history;
                       signed char *c;  
              if (bi.br_flags & BR_CONDITIONAL) {
			 if (y >= 0) {
                                 t=true;
                               }
                              else {
                                 t=false;
                               }  
                   if ((taken!=t)|| (y<=THRESHOLD && y>=-THRESHOLD)) {    //judge the update condition     
                              c=&tab [((my_update*)u)->index][0]; //update W0
                                if (taken) {
                                 (*c)++;
                            } else {
                                (*c)--;
                             }       
                          for (int j=1; j<=HISTORY_LENGTH; j++) {
                           if (history_reg & 1){
                               ht=true;
                             } else{ 
                               ht=false;
				}
			  history_reg >>= 1;
                           c = &tab [((my_update*)u)->index][j];
	                     if (ht==taken) {           //compare the outcome with 
                               (*c)++;              //global history bit
			   } else {                             //if same ,Wi inc. 
				(*c)--;                             //if different,Wi dec.
			   }
                        }
                     }
			history <<= 1;
			history |= taken;
			history &= (k<<HISTORY_LENGTH)-1;
		}
	}
};

