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/PrefetcherBase.h"
00035 #include "Sim/Memory/Cache/Cache.h"
00036
00037 using namespace Onikiri;
00038
00039 PrefetcherBase::PrefetcherBase()
00040 {
00041 m_prefetchTarget = NULL;
00042
00043 m_enabled = false;
00044
00045 m_lineSize = 0;
00046 m_lineBitSize = 0;
00047
00048 m_numPrefetch = 0;
00049 m_numReadHitAccess = 0;
00050 m_numReadMissAccess = 0;
00051 m_numWriteHitAccess = 0;
00052 m_numWriteMissAccess = 0;
00053
00054 m_numReplacedLine = 0;
00055 m_numPrefetchedReplacedLine = 0;
00056 m_numEffectivePrefetchedReplacedLine = 0;
00057
00058 m_mode = SM_EMULATION;
00059
00060 }
00061
00062 PrefetcherBase::~PrefetcherBase()
00063 {
00064 }
00065
00066
00067 void PrefetcherBase::Initialize(InitPhase phase)
00068 {
00069 if(phase == INIT_PRE_CONNECTION){
00070
00071 LoadParam();
00072
00073 m_lineSize = 1 << m_lineBitSize;
00074 }
00075 else if(phase == INIT_POST_CONNECTION){
00076 m_exLineState.Resize( m_prefetchTarget );
00077 }
00078 }
00079
00080 void PrefetcherBase::ChangeSimulationMode( SimulationMode mode )
00081 {
00082 m_mode = mode;
00083 }
00084
00085
00086 void PrefetcherBase::UpdateCacheAccessStat( const CacheAccess& access, bool hit )
00087 {
00088 switch( access.type ){
00089 case CacheAccess::OT_READ:
00090 case CacheAccess::OT_PREFETCH:
00091 case CacheAccess::OT_READ_FOR_WRITE_ALLOCATE:
00092 if( hit )
00093 m_numReadHitAccess++;
00094 else
00095 m_numReadMissAccess++;
00096 break;
00097 case CacheAccess::OT_WRITE:
00098 case CacheAccess::OT_WRITE_BACK:
00099 if( hit )
00100 m_numWriteHitAccess++;
00101 else
00102 m_numWriteMissAccess++;
00103 break;
00104 default:
00105 THROW_RUNTIME_ERROR( "Invalid access." );
00106 break;
00107 }
00108 }
00109
00110
00111 void PrefetcherBase::IncrementPrefetchNum()
00112 {
00113 m_numPrefetch++;
00114 }
00115
00116
00117 u64 PrefetcherBase::MaskLineOffset( u64 addr )
00118 {
00119 return addr & ~((1 << m_lineBitSize) - 1);
00120 }
00121
00122
00123 bool PrefetcherBase::IsPrefetch( const CacheAccess& access )
00124 {
00125 return access.type == CacheAccess::OT_PREFETCH;
00126 }
00127
00128
00129
00130 PrefetcherBase::AccessList::iterator
00131 PrefetcherBase::FindPrefetching( const Addr& address )
00132 {
00133 for( pool_list< PrefetchAccess >::iterator i = m_accessList.begin();
00134 i != m_accessList.end();
00135 ++i
00136 ){
00137 if( address == i->address){
00138 return i;
00139 }
00140 }
00141
00142 return m_accessList.end();
00143 }
00144
00145
00146
00147 void PrefetcherBase::OnCacheRead( Cache* cache, CacheHookParam* param )
00148 {
00149 if( !m_enabled )
00150 return;
00151
00152 if( !IsPrefetch( *param->access ) || !IsAccessFromThisPrefetcher( param ) ){
00153 bool hit = param->result.state != CacheAccessResult::ST_MISS;
00154 OnCacheAccess(
00155 cache,
00156 *param->access,
00157 hit
00158 );
00159
00160 if( param->line != param->table->end() ){
00161 ExLineState* state = &m_exLineState[ param->line ];
00162 state->accessed = true;
00163 }
00164
00165 ASSERT( param->access );
00166 AccessList::iterator prefetch = FindPrefetching( param->access->address );
00167 if( prefetch != m_accessList.end() ){
00168 prefetch->accessdCount++;
00169 }
00170
00171
00172 UpdateCacheAccessStat( *param->access, hit );
00173 }
00174 }
00175
00176
00177 void PrefetcherBase::OnCacheWrite( Cache* cache, CacheHookParam* param )
00178 {
00179 if( !m_enabled )
00180 return;
00181
00182 if( !IsPrefetch( *param->access ) || !IsAccessFromThisPrefetcher( param ) ){
00183 bool hit = param->result.state != CacheAccessResult::ST_MISS;
00184 OnCacheAccess(
00185 cache,
00186 *param->access,
00187 hit
00188 );
00189
00190
00191 UpdateCacheAccessStat( *param->access, hit );
00192
00193 if( param->line != param->table->end() ){
00194 ExLineState* state = &m_exLineState[ param->line ];
00195 state->accessed = true;
00196 }
00197 }
00198 }
00199
00200
00201 void PrefetcherBase::OnCacheInvalidation( Cache* cache, CacheHookParam* param )
00202 {
00203 if( !m_enabled )
00204 return;
00205
00206 if( param->line != param->table->end() ){
00207 m_exLineState[ param->line ].valid = false;
00208 }
00209
00210 AccessList::iterator prefetch = FindPrefetching( *param->address );
00211 if( prefetch != m_accessList.end() ){
00212 prefetch->invalidated = true;
00213 }
00214 }
00215
00216
00217 void PrefetcherBase::OnCacheTableUpdate( Cache* cache, CacheHookParam* param )
00218 {
00219 if( !m_enabled )
00220 return;
00221
00222 ExLineState* state = &m_exLineState[ param->line ];
00223
00224 if( param->replaced ){
00225 m_numReplacedLine++;
00226
00227 if( state->valid && state->prefetched ){
00228 m_numPrefetchedReplacedLine++;
00229 if( state->accessed ){
00230 m_numEffectivePrefetchedReplacedLine++;
00231 }
00232 }
00233
00234 }
00235
00236
00237 state->valid = true;
00238 if( IsPrefetch( *param->access ) ){
00239 state->prefetched = true;
00240 state->accessed = false;
00241 ASSERT( param->access );
00242 AccessList::iterator prefetch = FindPrefetching( param->access->address );
00243 if( prefetch != m_accessList.end() && prefetch->accessdCount > 0 ){
00244 state->accessed = true;
00245 }
00246 }
00247 else{
00248 state->prefetched = false;
00249 state->accessed = true;
00250 }
00251 }
00252
00253
00254 void PrefetcherBase::Prefetch( const CacheAccess& access )
00255 {
00256 CacheAccess prefetch = access;
00257 prefetch.type = CacheAccess::OT_PREFETCH;
00258 prefetch.address.address = MaskLineOffset( access.address.address );
00259
00260
00261 AccessList::iterator current;
00262 if( m_mode == SM_SIMULATION ){
00263 current = m_accessList.insert( m_accessList.end(), prefetch );
00264 if( m_accessList.size() >= MAX_INFLIGHT_PREFETCH_ACCESSES ){
00265 THROW_RUNTIME_ERROR( "The size of the prefetch access list exceeds a limit." );
00266 }
00267 }
00268
00269 CacheAccessResult result =
00270 m_prefetchTarget->Read( prefetch, this );
00271
00272 if( m_mode == SM_SIMULATION ){
00273 if( result.state != CacheAccessResult::ST_MISS ){
00274 m_accessList.erase( current );
00275 }
00276 }
00277 }
00278
00279 void PrefetcherBase::AccessFinished(
00280 const CacheAccess& access,
00281 const CacheAccessNotificationParam& param
00282 ){
00283 if( m_mode != SM_SIMULATION ){
00284 return;
00285 }
00286
00287 ASSERT(
00288 param.result.state != CacheAccessResult::ST_NOT_ACCESSED,
00289 "Not initialized notification is reached."
00290 );
00291
00292 switch( param.type ){
00293
00294 case CAET_FILL_FROM_NEXT_CACHE_FINISHED:
00295 case CAET_FILL_FROM_MAL_FINISHED:
00296 case CAET_READ_ACCESS_FINISHED:
00297
00298 if( param.result.state == CacheAccessResult::ST_MISS ){
00299 AccessList::iterator prefetch = FindPrefetching( access.address );
00300 if( prefetch != m_accessList.end() ){
00301 m_accessList.erase( prefetch );
00302 }
00303 else{
00304 ASSERT( 0, "An unknown prefetch access is finished.")
00305 }
00306 }
00307 break;
00308
00309 default:
00310 ASSERT( 0, "A write access must not be notified.." );
00311 break;
00312 }
00313 }
00314
00315
00316 bool PrefetcherBase::IsAccessFromThisPrefetcher( CacheHookParam* param ) const
00317 {
00318 if( !param->notifiee ){
00319 return false;
00320 }
00321
00322 return param->notifiee == static_cast<const CacheAccessNotifieeIF*>(this);
00323 }
00324