punk@1: import RegFile::*;
punk@1: import ProcTypes::*;
punk@1: import FIFO::*;
punk@1: 
punk@1: typedef Maybe#(Addr) BrPred;
punk@1: typedef Bit#(4) BPindx;
punk@1: 
punk@1: typedef struct {Addr brpc; Addr nextpc;} BrPair deriving (Bits,Eq);
punk@1: 
punk@1: typedef union tagged
punk@1: {
punk@1:   BrPair Valid;
punk@1:   void Invalid;
punk@1: } CBranchPath deriving(Bits, Eq);	// have the cache start out invalid and add valid values.
punk@1: 
punk@1: interface BranchPred;
punk@1:    method BrPred get(Addr pres);  //returns a maybe type that is invalid if no predition
punk@1:    method Action upd(Addr pres, Addr next);
punk@1: endinterface
punk@1: 
punk@1: module mkBranchPred(BranchPred);
punk@1: 
punk@1:    //state variables
punk@1:    RegFile#(BPindx, CBranchPath)  bcache <- mkRegFileFull(); // cache to hold 16 (based on BPindx)
punk@1: 
punk@1:    method Action upd(Addr pres, Addr next);
punk@1:       BrPair brp;
punk@1:       brp = BrPair {brpc:pres, nextpc:next};
punk@1:       bcache.upd(pres[5:2], tagged Valid brp);
punk@1:    endmethod
punk@1: 
punk@1:    method BrPred get(Addr prespc);
punk@1:       BPindx rd = prespc[5:2];
punk@1:       let cbp = bcache.sub(rd);
punk@1:       if (cbp matches tagged Valid .bp &&& bp.brpc == prespc)  //make sure that the read value was actually put there and the full address matches
punk@1: 	 return tagged Valid bp.nextpc;
punk@1:       else return Invalid;
punk@1:    endmethod
punk@1:    
punk@1: endmodule
punk@1: