


// replace get_op function in sim.cpp 


int get_op(Op *op)
{
  static UINT64 unique_count = 0; 
  static UINT64 fetch_arbiter; 
  
  Trace_op trace_op; 
  bool success = FALSE; 
  int fetch_id = -1; 
  bool br_stall_fail = false; 
  // read trace 
  // fill out op info 
  // return FALSE if the end of trace 
  for (int jj =0; jj < KNOB_MAX_THREAD_NUM.Value(); jj++){
    fetch_id = (fetch_arbiter++%KNOB_MAX_THREAD_NUM.Value());


    if (br_stall[fetch_id]) {
    br_stall_fail = true; 
    continue; 
    }

    success = (gzread(stream[fetch_id], &trace_op, sizeof(Trace_op)) > 0 );

    /* copy trace structure to op */ 
    if (success) { 

	if (KNOB_PRINT_INST.Value()) dprint_trace(&trace_op); 
	
	if ((KNOB_MAX_THREAD_NUM.Value()> 1)  && (KNOB_PRINT_INST.Value() >0 ))
	{
	    std::cout <<"thread_id: " << fetch_id << endl; 
	}
	    
	copy_trace_op(&trace_op, op); 

	op->inst_id  = unique_count++;
	op->valid    = TRUE; 
	op->thread_id = fetch_id; 
	    return success;  // get op so return 
    }
    
	// if not success and go to another trace. 
}
if (br_stall_fail) return -1; 
return success; 
}




// sim.h 


#define MAX_THREAD 4   // add this line 
extern gzFile stream[MAX_THREAD];    // replace extern gzFile stream; 
extern uint64_t inst_count[MAX_THREAD];  // replace extern uint64_t inst_count[MAX_THREAD]; 



// ad thread_id into Op_struct. 

typedef struct Op_struct : public Trace_op{
  uint64_t inst_id; 
  Op_struct *op_pool_next; 
  uint32_t  op_pool_id; 
  bool valid; 
  int thread_id;  // new data structure 
  /* when you add new element, you must change the init_op function also */ 
} Op; 





UINT64 dcache_hit_count; 

UINT64 bp_miss_thread[MAX_THREAD];
UINT64 bp_corr_predict_thread[MAX_THREAD]; 
UINT64 retired_instruction_thread[MAX_THREAD];
UINT64 dcache_miss_count_thread[MAX_THREAD]; 
UINT64 dcache_hit_count_thread[MAX_THREAD]; 
bool br_stall[MAX_THREAD];  


/* you must replace this function in your source code */
void print_stats() {
   std::ofstream out(KNOB_OUTPUT_FILE.Value().c_str());
 /* Do not modify this function. This messages will be used for grading */  
 out << "Total instruction: " << retired_instruction << endl; 
 out << "Total cycles: " << cycle_count << endl;  
 float ipc = (cycle_count ? ((float)retired_instruction/(float)cycle_count): 0 );
 out << "IPC: " << ipc << endl;
 out << "Total I-cache miss: " << icache_miss_count << endl;  
 out << "Total D-cache miss: " << dcache_miss_count << endl;  
 out << "Total L2-cache miss: " << l2_cache_miss_count << endl; 
 out << "Total data hazard: " << data_hazard_count << endl;
 out << "Total BR_mispred: " << bp_miss << endl; 
 out << "Total BR_corrpred: " << bp_corr_predict << endl; 
 out << "Total control hazard : " << control_hazard_count << endl;   

 out << "\n\n\n" << endl; 
 for ( int ii = 0; ii < KNOB_MAX_THREAD_NUM.Value(); ii++) { 
      float thread_ipc = (cycle_count ? ((float)retired_instruction_thread[ii]/(float)cycle_count): 0 );
  out << "THREAD_IPC : " << thread_ipc << " Thread id: " << ii << endl; 
  out << "THREAD_D-cache miss: " << dcache_miss_count_thread[ii] << " Thread id: " << ii << endl;  
  out << "THREAD_D-cache hit:  " << dcache_hit_count_thread[ii] << " Thread id: " << ii << endl;  
  out << "THREAD_BR_mispred: " << bp_miss_thread[ii] << " Thread id: " << ii << endl;  
  out << "THREAD_BR_corrpred: " << bp_corr_predict_thread[ii] << " Thread id: " << ii << endl;  
  
}
out.close();
}



Add thread_id field into the following two debug statements. 


if (KNOB_DEBUG_PRINT.Value()) {
        cout << "ID_STAGE OP " << op->inst_id <<  " is scheduled at cycle " << cycle_count <<  " thread_id " << op->thread_id <<  endl; }


if (KNOB_DEBUG_PRINT.Value()) {
        cout << "WB_STAGE OP " << op->inst_id <<  " is retired at cycle " << cycle_count << " thread_id " << op->thread_id << endl; }




void print_heartbeat()
{
  static uint64_t last_cycle ;
  static uint64_t last_inst_count[MAX_THREAD]; 

for (int ii = 0; ii < KNOB_MAX_THREAD_NUM.Value(); ii++) { 
  float temp_ipc = float(retired_instruction_thread[ii] - last_inst_count[ii]) /(float)(cycle_count-last_cycle) ;
  float ipc = float(retired_instruction) /(float)(cycle_count) ;
  /* Do not modify this function. This messages will be used for grading */ 
  cout <<"**Heartbeat** cycle_count: " << cycle_count << " inst:" << retired_instruction_thread[ii] << " IPC: " << temp_ipc << " Overall IPC: " << ipc << " thread_id " << ii << endl; 

  last_inst_count[ii] = retired_instruction_thread[ii]; 
  }
  last_cycle = cycle_count;
}
