/* Stride Prefetcher */ void stride_prefetcher(struct cache_t *cp, md_addr_t addr) { #if 0 int counter = 0; while (pc) { if (pc & 1) printf("1"); else printf("0"); if (counter == 0 && pc&1 != 0 || counter == 1 && pc&1 != 0 || counter == 2 && pc&1 != 0) assert(0); pc >>= 1; counter++; } printf("\n"); #endif #if 1 md_addr_t pc = get_PC(); // The last three bits do not change unsigned int index = (pc >> 3) & (cp->prefetch_type - 1); unsigned int tag = (pc >> (log_base2(cp->prefetch_type) + 3)); #endif // Scenario 1 if (cp->rpt[index].tag != tag) { cp->rpt[index].tag = tag; cp->rpt[index].prev_addr = addr; cp->rpt[index].stride = 0; cp->rpt[index].state = initial; cp->rpt[index].is_neg = 0; } else { // Scenario 2 md_addr_t prev_addr = cp->rpt[index].prev_addr; md_addr_t new_stride = MAX(addr, prev_addr) - MIN(addr, prev_addr); int new_is_neg = prev_addr > addr ? 1 : 0; int stride_condition = new_stride == cp->rpt[index].stride && new_is_neg == cp->rpt[index].is_neg; assert(stride_condition == 1 || stride_condition == 0); cp->rpt[index].state = update_state(cp->rpt[index].state, stride_condition); if (!stride_condition && (cp->rpt[index].state == transient || cp->rpt[index].state== no_prediction)) { cp->rpt[index].stride = new_stride; cp->rpt[index].is_neg = new_is_neg; } cp->rpt[index].prev_addr = addr; if (cp->rpt[index].state != no_prediction) { if (cp->rpt[index].is_neg) { prefetch(cp, addr - cp->rpt[index].stride); } else { prefetch(cp, addr + cp->rpt[index].stride); } } } }
/* Open Ended Prefetcher */ void open_ended_prefetcher(struct cache_t *cp, md_addr_t addr) { md_addr_t pc = get_PC(); // The last three bits do not change unsigned int index = (pc >> 3) & (DEFAULT_RPT_SIZE - 1); unsigned int tag = (pc >> (log_base2(DEFAULT_RPT_SIZE) + 3)); assert(index >= 0 && index < rdim); //unsigned int hist_index = (cp->prev_hist_addr & (rdim - 1)); //unsigned int hist_tag = cp->prev_hist_addr >> log_base2(rdim); // Scenario 1 if (cp->rpt[index].tag != tag) { cp->rpt[index].tag = tag; cp->rpt[index].prev_addr = addr; cp->rpt[index].stride = 0; cp->rpt[index].state = initial; cp->rpt[index].is_neg = 0; history_push_back(cp, addr, index, tag); return; //if (cp->prev_hist_addr != 0) //history_push_back(cp, addr, hist_index, hist_tag); } else { // Scenario 2 md_addr_t prev_addr = cp->rpt[index].prev_addr; md_addr_t new_stride = MAX(addr, prev_addr) - MIN(addr, prev_addr); int new_is_neg = prev_addr > addr ? 1 : 0; int stride_condition = new_stride == cp->rpt[index].stride && new_is_neg == cp->rpt[index].is_neg; assert(stride_condition == 1 || stride_condition == 0); cp->rpt[index].state = update_state(cp->rpt[index].state, stride_condition); if (!stride_condition && (cp->rpt[index].state == transient || cp->rpt[index].state== no_prediction)) { cp->rpt[index].stride = new_stride; cp->rpt[index].is_neg = new_is_neg; } cp->rpt[index].prev_addr = addr; if (cp->rpt[index].state != no_prediction) { if (cp->rpt[index].is_neg) { prefetch(cp, addr - cp->rpt[index].stride); } else { prefetch(cp, addr + cp->rpt[index].stride); } } else { int i; for (i = cp->idx[index] - 2; i >= 0; i--) { if (cp->ht[index][i] == addr) { prefetch(cp, cp->ht[index][i + 1]); break; } } //if (cp->idx[hist_index] - 1 >= 0) { //prefetch(cp, cp->ht[hist_index][cp->idx[hist_index] - 1]); //} } //if (cp->prev_hist_addr != 0) //history_push_back(cp, addr, hist_index, hist_tag); } history_push_back(cp, addr, index, tag); //cp->prev_hist_addr = addr; }
/* Stride Prefetcher */ void stride_prefetcher(struct cache_t *cp, md_addr_t addr) { int i; md_addr_t pc_tag = get_PC(); assert((7 & pc_tag) == 0); pc_tag = get_PC() >> 3; md_addr_t prefetch_addr = 0; int rpt_set_shift = log2(cp->prefetch_type); int rpt_idx = pc_tag & ((1 << rpt_set_shift) - 1); if (rpt.size() > cp->prefetch_type) fatal("RPT table went over the size limit \n"); if (rpt_idx > cp->prefetch_type) fatal("RPT index went over the size limit \n"); prediction_t * match_entry = NULL; bool match = false; if(rpt[rpt_idx].tag == pc_tag) { match = true; match_entry = &rpt[rpt_idx]; } //no matching PC tag; assign a new entry if (!match) { prediction_t n_entry; n_entry.tag = pc_tag; n_entry.state = INITIAL; n_entry.prev_addr = addr; n_entry.stride = 0; rpt[rpt_idx] = n_entry; } else { int stride = (int)addr - (int)match_entry->prev_addr; switch(match_entry->state) { case INITIAL: if(stride == match_entry->stride) { prefetch_addr = (md_addr_t)((int)addr + (int)match_entry->stride); match_entry->state = STEADY; } else { match_entry->state = TRANSIENT; match_entry->stride= stride; } break; case TRANSIENT: if(stride == match_entry->stride) { match_entry->state = STEADY; prefetch_addr = (md_addr_t)((int)addr + (int)match_entry->stride); } else { match_entry->state = NO_PRED; match_entry->stride= stride; } break; case STEADY: if(stride != match_entry->stride) { match_entry->state = INITIAL; } else { prefetch_addr = (md_addr_t)((int)addr + (int)match_entry->stride); } break; case NO_PRED: if(stride == match_entry->stride) { match_entry->state = TRANSIENT; } else { match_entry->stride= stride; } break; } match_entry->prev_addr = addr; } if (prefetch_addr != 0) fetch_cache_blk(cp, prefetch_addr); }
void process_instruction(){ instruction *inst; int i; // for loop /* pipeline */ CURRENT_STATE.PIPE[0] = CURRENT_STATE.PC; CURRENT_STATE.PIPE[1] = CURRENT_STATE.IF_ID.PC; CURRENT_STATE.PIPE[2] = CURRENT_STATE.ID_EX.PC; CURRENT_STATE.PIPE[3] = CURRENT_STATE.EX_MEM.PC; CURRENT_STATE.PIPE[4] = CURRENT_STATE.MEM_WB.PC; mem_wb_reg MEM_WB; ex_mem_reg EX_MEM; id_ex_reg ID_EX; memset(&MEM_WB, 0, sizeof(mem_wb_reg)); memset(&EX_MEM, 0, sizeof(ex_mem_reg)); memset(&ID_EX, 0, sizeof(id_ex_reg)); if(CURRENT_STATE.PIPE[4]) run_WB(); if(CURRENT_STATE.PIPE[3]) MEM_WB = run_MEM(); if(CURRENT_STATE.MEM_bubble_count) { if(DEBUG) printf("MEM BUBBLE\n"); CURRENT_STATE.MEM_bubble_count--; CURRENT_STATE.pc_hold = 1; } else if(CURRENT_STATE.IF_ID_flush_count) { CURRENT_STATE.MEM_WB = MEM_WB; ex_mem_reg rr; memset(&rr, 0, sizeof(rr)); CURRENT_STATE.EX_MEM = rr; id_ex_reg rrr; memset(&rrr, 0, sizeof(rrr)); CURRENT_STATE.ID_EX = rrr; CURRENT_STATE.IF_ID = run_BUBBLE(); CURRENT_STATE.IF_ID_flush_count = 0; CURRENT_STATE.flushed = 1; } else { if(CURRENT_STATE.PIPE[2]) EX_MEM = run_EX(); // if(CURRENT_STATE.EX_bubble_count) // { // if(DEBUG) printf("EX BUBBLE\n"); // CURRENT_STATE.MEM_WB = MEM_WB; // CURRENT_STATE.EX_bubble_count--; // CURRENT_STATE.pc_hold = 1; // } // 얘가 여기 있으면 안됨. 파이프라인은 다 같이 도는거기 때문에 이번 결과를 적용시켜버리면 안되지. // else if(CURRENT_STATE.IF_ID_flush_count) // { // CURRENT_STATE.MEM_WB = MEM_WB; // CURRENT_STATE.EX_MEM = EX_MEM; // id_ex_reg rrr; // memset(&rrr, 0, sizeof(rrr)); // CURRENT_STATE.ID_EX = rrr; // CURRENT_STATE.IF_ID = run_BUBBLE(); // CURRENT_STATE.IF_ID_flush_count = 0; // CURRENT_STATE.flushed = 1; // } if(CURRENT_STATE.PIPE[1]) { ID_EX = run_ID(); // CURRENT_STATE.PC = ID_EX.NPC; } if_id_reg IF_ID = run_IF(); // 포워드 없을때 기다리는거! EX버블은 아닙니다! if(CURRENT_STATE.EX_bubble_count){ CURRENT_STATE.MEM_WB = MEM_WB; CURRENT_STATE.EX_MEM = EX_MEM; CURRENT_STATE.ID_EX = ID_EX; CURRENT_STATE.pc_hold = 1; CURRENT_STATE.EX_bubble_count--; } else{ // branch가 taken되면 IF_ID에 들어가있는걸 비운다! if(!nobp_set && CURRENT_STATE.branchhuh){ IF_ID = run_BUBBLE(); } if(CURRENT_STATE.bubble_count) { if(DEBUG) printf("bubble1\n"); CURRENT_STATE.pc_hold = 1; IF_ID = run_BUBBLE(); CURRENT_STATE.bubble_count--; } if(ID_EX.cMemRd && (IF_ID.instr.r_t.r_i.rs == ID_EX.rt || IF_ID.instr.r_t.r_i.rt == ID_EX.rt)) // Load-use XXX 포워드 없을땐? // IF에 잡아두면 안되네 밀어줘야하네! { CURRENT_STATE.pc_hold = 1; if(DEBUG) printf("bubble2: load-use\n"); IF_ID = run_BUBBLE(); } if(ID_EX.cALUOp == 7 || ID_EX.cALUOp == -1) // Jump { // CURRENT_STATE.pc_hold = 1; if(DEBUG) printf("bubble3\n"); IF_ID = run_BUBBLE(); } // if(nobp_set && (ID_EX.cALUOp == 3 || ID_EX.cALUOp == 4)) // nobp! if(nobp_set && (ID_EX.cBranch)) { if(DEBUG) printf("bubble4\n"); IF_ID = run_BUBBLE(); CURRENT_STATE.bubble_count = 2; } // bubble + flush..? //TODO: what if branch f****d up? CURRENT_STATE.IF_ID = IF_ID; CURRENT_STATE.ID_EX = ID_EX; CURRENT_STATE.EX_MEM = EX_MEM; CURRENT_STATE.MEM_WB = MEM_WB; } } CURRENT_STATE.PC = get_PC(); // printf("PC : %x, end point : %x\n", CURRENT_STATE.PC, MEM_REGIONS[0].start + (NUM_INST * 4) ); if (CURRENT_STATE.PC < MEM_REGIONS[0].start || ( CURRENT_STATE.PC >= (MEM_REGIONS[0].start + (NUM_INST * 4)) && !CURRENT_STATE.IF_ID.PC&&!CURRENT_STATE.ID_EX.PC&& !CURRENT_STATE.EX_MEM.PC&&!CURRENT_STATE.MEM_WB.PC) || (num_inst_set && !num_inst)) RUN_BIT = FALSE; else { //otherwise, why does it continue? //int ii; //for(ii=0;ii<5;ii++) //{ // //if(CURRENT_STATE.PIPE[ii]) break; // printf("PIPE[%d]: %x\n",ii, CURRENT_STATE.PIPE[ii]); //} //if(1) //{ // printf("it's because: \n"); // printf("CURRENT_STATE.PC < MEM_REGIONS[0].start: %d\n", // CURRENT_STATE.PC < MEM_REGIONS[0].start); // printf("CURRENT_STATE.PC >= (MEM_REGIONS[0].start + (NUM_INST * 4)): %d\n", // CURRENT_STATE.PC >= (MEM_REGIONS[0].start + (NUM_INST * 4))); // printf("!CURRENT_STATE.IF_ID.PC: %d\n", // !CURRENT_STATE.IF_ID.PC); // printf("!CURRENT_STATE.ID_EX.PC: %d\n", // !CURRENT_STATE.ID_EX.PC); // printf("!CURRENT_STATE.EX_MEM.PC: %d\n", // !CURRENT_STATE.EX_MEM.PC); // printf("!CURRENT_STATE.MEM_WB.PC: %d\n", // !CURRENT_STATE.MEM_WB.PC); // printf("num_inst_set: %d\n", // num_inst_set); // printf("!num_inst: %d\n", // !num_inst); //} } }
/* Open Ended Prefetcher */ void open_ended_prefetcher(struct cache_t *cp, md_addr_t addr) { /* ECE552 Assignment 4 - BEGIN CODE */ float accuracy = (float)cp->prefetch_useful_cnt / (float) cp->prefetch_cnt; float polution = (float)cp->prefetch_misses / (float) cp->misses; //High-accuracy if(accuracy > 0.75) { //low polution if (polution < 0.01) { if(cp->prefetch_aggr < 5) { cp->prefetch_aggr += 1; } } else { if(cp->prefetch_aggr > 0) { cp->prefetch_aggr -= 1; } } } //Medium-accuracy else if (accuracy > 0.4) { //poluting if (polution >= 0.01) { if(cp->prefetch_aggr > 0) { cp->prefetch_aggr -= 1; } } } //Low-accuracy else { //poluting if (polution >= 0.01) { if(cp->prefetch_aggr > 0) { cp->prefetch_aggr -= 1; } } } md_addr_t pc_tag = get_PC(); assert((7 & pc_tag) == 0); pc_tag = get_PC() >> 3; md_addr_t prefetch_addr = 0; int set_shift = log2(256); int p_idx = pc_tag & ((1 << set_shift) - 1); if (p_idx >= 256) fatal("open-ended: index went over the size limit \n"); prediction_t * match_entry = NULL; bool match = false; if(p_table[p_idx].tag == pc_tag) { match = true; match_entry = &p_table[p_idx]; } //no matching PC tag; assign a new entry if (!match) { prediction_t n_entry; n_entry.tag = pc_tag; n_entry.state = INITIAL; n_entry.prev_addr = addr; n_entry.stride = 0; p_table[p_idx] = n_entry; } else { int stride = (int)addr - (int)match_entry->prev_addr; switch(match_entry->state) { case INITIAL: if(stride == match_entry->stride) { prefetch_addr = (md_addr_t)((int)addr + (int)match_entry->stride); match_entry->state = STEADY; } else { match_entry->state = TRANSIENT; match_entry->stride= stride; } break; case TRANSIENT: if(stride == match_entry->stride) { match_entry->state = STEADY; prefetch_addr = (md_addr_t)((int)addr + (int)match_entry->stride); } else { match_entry->state = NO_PRED; match_entry->stride= stride; } break; case STEADY: if(stride != match_entry->stride) { match_entry->state = INITIAL; } else { prefetch_addr = (md_addr_t)((int)addr + (int)match_entry->stride); } break; case NO_PRED: if(stride == match_entry->stride) { match_entry->state = TRANSIENT; } else { match_entry->stride= stride; } break; } match_entry->prev_addr = addr; } if (prefetch_addr != 0) fetch_cache_blk(cp, prefetch_addr); if (prefetch_addr != 0) { switch(cp->prefetch_aggr) { case 0: fetch_cache_blk(cp, prefetch_addr); break; case 1: prefetch_addr = (md_addr_t)((int)addr + ((int)match_entry->stride << 1) ); fetch_cache_blk(cp, prefetch_addr); break; case 2: prefetch_addr = (md_addr_t)((int)addr + ((int)match_entry->stride << 2) ); fetch_cache_blk(cp, prefetch_addr); break; case 3: prefetch_addr = (md_addr_t)((int)addr + ((int)match_entry->stride << 3) ); fetch_cache_blk(cp, prefetch_addr); prefetch_addr += match_entry->stride; fetch_cache_blk(cp, prefetch_addr); break; case 4: prefetch_addr = (md_addr_t)((int)addr + ((int)match_entry->stride << 4) ); fetch_cache_blk(cp, prefetch_addr); prefetch_addr += match_entry->stride; fetch_cache_blk(cp, prefetch_addr); prefetch_addr += match_entry->stride; fetch_cache_blk(cp, prefetch_addr); prefetch_addr += match_entry->stride; fetch_cache_blk(cp, prefetch_addr); break; case 5: prefetch_addr = (md_addr_t)((int)addr + ((int)match_entry->stride << 5) ); fetch_cache_blk(cp, prefetch_addr); prefetch_addr += match_entry->stride; fetch_cache_blk(cp, prefetch_addr); prefetch_addr += match_entry->stride; fetch_cache_blk(cp, prefetch_addr); prefetch_addr += match_entry->stride; fetch_cache_blk(cp, prefetch_addr); break; default: fatal("Unsupported Prefetching aggressiveness\n"); break; } } /* ECE552 Assignment 4 - END CODE */ }