00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <pch.h>
00033
00034 #include "Sim/Memory/Prefetcher/StridePrefetcher.h"
00035 #include "Sim/Op/Op.h"
00036
00037 using namespace Onikiri;
00038
00039
00040
00041 String StridePrefetcher::Stream::ToString() const
00042 {
00043 String str;
00044
00045
00046 str += "status: ";
00047 switch( status ){
00048 default:
00049 case SS_INVALID:
00050 str += "INVALID ";
00051 break;
00052 case SS_ALLOCATED:
00053 str += "ALLOCATED ";
00054 break;
00055 }
00056
00057
00058 str += " pc: ";
00059 str += pc.ToString();
00060 str += " addr: ";
00061 str += addr.ToString();
00062 str += " stride: ";
00063 str += String().format( "%llx", stride );
00064
00065
00066 str += " count: ";
00067 str += String().format( "%d", count );
00068 str += " conf: ";
00069 str += String().format( "%d", (int)confidence );
00070 return str;
00071
00072 }
00073
00074
00075 StridePrefetcher::StridePrefetcher()
00076 {
00077 m_distance = 0;
00078 m_degree = 0;
00079 m_streamTableSize = 0;
00080
00081 m_numPrefetchingStream = 0;
00082 m_numAvgPrefetchStreamLength = 0.0;
00083 }
00084
00085
00086 StridePrefetcher::~StridePrefetcher()
00087 {
00088 if( m_numPrefetchingStream ){
00089 m_numAvgPrefetchStreamLength =
00090 (double)m_numPrefetch / (double)m_numPrefetchingStream;
00091 }
00092
00093 ReleaseParam();
00094 }
00095
00096
00097
00098 void StridePrefetcher::Initialize(InitPhase phase)
00099 {
00100 PrefetcherBase::Initialize( phase );
00101
00102 if(phase == INIT_PRE_CONNECTION){
00103
00104 LoadParam();
00105 m_streamTable.construct( m_streamTableSize );
00106 }
00107 else if(phase == INIT_POST_CONNECTION){
00108
00109 }
00110 }
00111
00112
00113
00114 void StridePrefetcher::OnCacheAccess(
00115 Cache* cache,
00116 const CacheAccess& access,
00117 bool hit
00118 ){
00119 if( !m_enabled ){
00120 return;
00121 }
00122
00123 OpIterator op = access.op;
00124 if( op.IsNull() ){
00125 return;
00126 }
00127
00128 Addr pc = op->GetPC();
00129 Addr missAddr = op->GetMemAccess().address;
00130
00131
00132 #ifdef STRIDE_PREFETCHER_DEBUG
00133 g_env.Print(
00134 String( "access\t" ) +
00135 "pc: " + pc.ToString() +
00136 " addr: " + missAddr.ToString() +
00137 ( hit ? " hit" : " miss" ) +
00138 "\n"
00139 );
00140 #endif
00141
00142
00143
00144
00145 for( size_t i = 0; i < m_streamTable.size(); i++ ){
00146 Stream* stream = &m_streamTable[i];
00147 if( stream->status == SS_INVALID )
00148 continue;
00149
00150 if( stream->pc != pc )
00151 continue;
00152
00153 m_streamTable.touch( i );
00154
00155 stream->count++;
00156
00157 #ifdef STRIDE_PREFETCHER_DEBUG
00158 g_env.Print( String( " stream\t" ) + stream->ToString() + "\n" );
00159 #endif
00160
00161 if( stream->addr.address + stream->stride == missAddr.address ){
00162
00163 if( stream->confidence.above_threshold() ){
00164
00165 for( int d = 0; d < m_degree; d++ ){
00166 CacheAccess prefetch;
00167 prefetch.op = op;
00168 prefetch.type = CacheAccess::OT_PREFETCH;
00169
00170
00171 prefetch.address = missAddr;
00172 prefetch.address.address +=
00173 stream->stride * (m_distance + d);
00174
00175 PrefetcherBase::Prefetch( prefetch );
00176
00177
00178 #ifdef STRIDE_PREFETCHER_DEBUG
00179 g_env.Print(
00180 String( " prefetch\t" ) +
00181 prefetch.address.ToString() +
00182 "\n"
00183 );
00184 #endif
00185 }
00186
00187 IncrementPrefetchNum();
00188 if( stream->status != SS_PREFETCHING ){
00189 m_numPrefetchingStream++;
00190 }
00191 stream->status = SS_PREFETCHING;
00192 }
00193
00194 stream->confidence.inc();
00195 stream->streamLength++;
00196 }
00197 else{
00198 stream->confidence.dec();
00199 }
00200
00201 stream->stride =
00202 (s64)missAddr.address - (s64)stream->addr.address;
00203 stream->addr.address = missAddr.address;
00204
00205 if( stream->stride == 0 ){
00206 stream->status = SS_INVALID;
00207 }
00208 return;
00209 }
00210
00211 if( hit )
00212 return;
00213
00214
00215 Stream stream;
00216 stream.Reset();
00217 stream.pc = pc;
00218 stream.addr = missAddr;
00219 stream.orig = missAddr;
00220 stream.stride = m_lineSize;
00221 stream.status = SS_ALLOCATED;
00222
00223 int target = (int)m_streamTable.replacement_target();
00224 m_streamTable[ target ] = stream;
00225 m_streamTable.touch( target );
00226
00227 #ifdef STRIDE_PREFETCHER_DEBUG
00228 g_env.Print(
00229 String( " alloc\t" ) +
00230 missAddr.ToString() + " " +
00231 stream.ToString() + "\n"
00232 );
00233 #endif
00234
00235
00236 }
00237