// 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; }