// ******************************************************************************* // Multi-level Adaptive Sequential Tagged Prefetching // based on Performance Gradient Tracking // Ramos, Briz, Ibanez, Vinals // ******************************************************************************* #include "interface.h" // Do NOT edit interface .h #include "sample_prefetcher.h" // // Function to initialize the prefetchers. DO NOT change the prototype of this // function. You can change the body of the function by calling your necessary // initialization functions. // void InitPrefetchers() // DO NOT CHANGE THE PROTOTYPE { // INSERT YOUR CHANGES IN HERE MSHR_ini(); } // // Function that is called every cycle to issue prefetches should the // prefetcher want to. The arguments to the function are the current cycle, // the demand requests to L1 and L2 cache. Again, DO NOT change the prototype of this // function. You can change the body of the function by calling your necessary // routines to invoke your prefetcher. // // DO NOT CHANGE THE PROTOTYPE void IssuePrefetches( COUNTER cycle, PrefetchData_t *L1Data, PrefetchData_t * L2Data ) { // INSERT YOUR CHANGES IN HERE MSHR_cycle(cycle); AD_cycle(cycle, L1Data); SEQTL1_cycle(cycle, L1Data); SEQT_cycle(cycle, L2Data); } // ******************************************************************************* // SEQT (L2 Prefetcher) // ******************************************************************************* void SEQT_cycle(COUNTER cycle, PrefetchData_t *L2Data){ // miss or "1st use" in L2? (considering demand and prefetch references) if (cycle == L2Data->LastRequestCycle && ((L2Data->hit == 0 && !MSHR_lookup(MSHRD2, cycle, L2Data->DataAddr)) || GetPrefetchBit(1, L2Data->DataAddr)==1) ){ if (L2Data->hit == 0) MSHR_insert(MSHRD2, cycle, L2Data->DataAddr); else UnSetPrefetchBit(1, L2Data->DataAddr); if (AD_degree){ // program SDA SDA_last_addr=L2Data->DataAddr; SDA_degree=AD_degree; } } // the SDA generates 1 prefetch per cycle if (SDA_degree){ ADDRINT predicted_address= SDA_last_addr+0x40; // issue prefetch (if not filtered) if (GetPrefetchBit(1, predicted_address)==-1){ if (!MSHR_lookup(PMAF2, cycle,predicted_address & 0xffff) && !MSHR_lookup(MSHRD2, cycle,predicted_address)){ IssueL2Prefetch(cycle,predicted_address); MSHR_insert(PMAF2, cycle,predicted_address & 0xffff); } } // program SDA SDA_last_addr=predicted_address; SDA_degree--; } } // ******************************************************************************* // SEQTL1 (L1 Prefetcher) // ******************************************************************************* void SEQTL1_cycle(COUNTER cycle, PrefetchData_t *L1Data){ int i; for (i=0; i<4; i++){ // miss or "1st use" in L1? if (cycle == L1Data[i].LastRequestCycle && (L1Data[i].hit == 0 || GetPrefetchBit(0, L1Data[i].DataAddr)==1) ){ if (L1Data[i].hit == 1){ UnSetPrefetchBit(0, L1Data[i].DataAddr); } // program SDA1 SDA1_last_addr=L1Data[i].DataAddr; SDA1_degree=(L1Data[i].hit == 0 ? 1 : 4 ); } //end if } //end for // the SDA1 generates 1 prefetch per cycle if (SDA1_degree){ ADDRINT predicted_address= SDA1_last_addr+0x40; // issue prefetch (if not filtered) if (GetPrefetchBit(0, predicted_address)==-1){ if (!MSHR_lookup(PMAF1, cycle,predicted_address & 0xffff)){ if (IssueL1Prefetch(cycle,predicted_address)==0){; MSHR_insert(PMAF1, cycle,predicted_address & 0xffff); } } } // program next prefetch for the next cycle SDA1_last_addr=predicted_address; SDA1_degree--; } } // ******************************************************************************* // MSHR // ******************************************************************************* void MSHR_ini (void){ PMAF1=(MSHR *) calloc(1, sizeof(MSHR)); PMAF1->size=32; MSHRD2=(MSHR *) calloc(1, sizeof(MSHR)); MSHRD2->size=16; PMAF2=(MSHR *) calloc(1, sizeof(MSHR)); PMAF2->size=32; } int MSHR_lookup (MSHR * MSHR, COUNTER cycle, ADDRINT addr){ int i; ADDRINT MASK = 0x3f; if (!MSHR->size || !MSHR->num) return 0; for (i=0; i < MSHR->size; i++){ if (MSHR->entry[i].valid && (MSHR->entry[i].addr == (addr & ~MASK)) ){ return 1; } } return 0; } void MSHR_insert (MSHR * MSHR, COUNTER cycle, ADDRINT addr){ ADDRINT MASK = 0x3f; if (!MSHR->size || !addr) return; MSHR->entry[MSHR->tail].valid=1; MSHR->entry[MSHR->tail].addr= (addr & ~MASK); MSHR->tail=(MSHR->tail+1)%MSHR->size; if (MSHR->numsize) MSHR->num++; else MSHR->head=MSHR->tail; } void MSHR_cycle (COUNTER cycle){ if (PMAF1->num && (GetPrefetchBit(0, PMAF1->entry[PMAF1->head].addr)!= -1) ){ PMAF1->num--; PMAF1->entry[PMAF1->head].valid=0; PMAF1->head=(PMAF1->head+1)%PMAF1->size; } if (MSHRD2->num && (GetPrefetchBit(1, MSHRD2->entry[MSHRD2->head].addr)!= -1) ){ MSHRD2->num--; MSHRD2->entry[MSHRD2->head].valid=0; MSHRD2->head=(MSHRD2->head+1)%MSHRD2->size; } if (PMAF2->num && (GetPrefetchBit(0, PMAF2->entry[PMAF2->head].addr)!= -1) ){ PMAF2->num--; PMAF2->entry[PMAF2->head].valid=0; PMAF2->head=(PMAF2->head+1)%PMAF2->size; } } // ******************************************************************************* // ADAPTIVE DEGREE (L2) // ******************************************************************************* void AD_cycle(COUNTER cycle, PrefetchData_t *L1Data){ int i; AD_cycles++; for(i = 0; i < 4; i++) { if(cycle == L1Data[i].LastRequestCycle) AD_L1_accesses++; } if (AD_cycles>AD_interval){ AD_cycles=0; if (AD_L1_accesses0) AD_deg_index--; } AD_degree=AD_degs[AD_deg_index]; AD_last_L1_accesses=AD_L1_accesses; AD_L1_accesses=0; } }