#include "ooo_cpu.h"

#define IPREF_DEGREE 2	// Next how many lines

uint64_t last_ip_block;

void O3_CPU::l1i_prefetcher_initialize() 
{
   last_ip_block = 0;
}

void O3_CPU::l1i_prefetcher_branch_operate(uint64_t ip, uint8_t branch_type, uint64_t branch_target)
{
   if (branch_target) {
      // Predicted taken
      prefetch_code_line(branch_target);	// Prefetch block containing branch target
      for (uint8_t i=0; i<IPREF_DEGREE; i++) {	// Next n line prefetch
         prefetch_code_line(branch_target+((i+1) << LOG2_BLOCK_SIZE));
      }
   }
   if (last_ip_block != (ip >> LOG2_BLOCK_SIZE)) {	// A new code block
      prefetch_code_line(ip);	// Prefetch this code block
      if (!branch_target) {
         for (uint8_t i=0; i<IPREF_DEGREE; i++) {	// Next n line prefetch
            prefetch_code_line(ip+((i+1) << LOG2_BLOCK_SIZE));
         }
      }
   }

   last_ip_block = ip >> LOG2_BLOCK_SIZE;
}

void O3_CPU::l1i_prefetcher_cache_operate(uint64_t v_addr, uint8_t cache_hit, uint8_t prefetch_hit)
{

}

void O3_CPU::l1i_prefetcher_cycle_operate()
{

}

void O3_CPU::l1i_prefetcher_cache_fill(uint64_t v_addr, uint32_t set, uint32_t way, uint8_t prefetch, uint64_t evicted_v_addr)
{

}

void O3_CPU::l1i_prefetcher_final_stats()
{

}
