src/Sim/Memory/Prefetcher/PrefetcherBase.cpp

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
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 // --- PhysicalResourceNode
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 // Update cache access statistics.
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 // Increment the number of prefetch.
00111 void PrefetcherBase::IncrementPrefetchNum()
00112 {
00113     m_numPrefetch++;
00114 }
00115 
00116 // Masks offset bits of the cache line in the 'addr'.
00117 u64 PrefetcherBase::MaskLineOffset( u64 addr )
00118 {
00119     return addr & ~((1 << m_lineBitSize) - 1);
00120 }
00121 
00122 // Returns whether an access is prefetch or not.
00123 bool PrefetcherBase::IsPrefetch( const CacheAccess& access )
00124 {
00125     return access.type == CacheAccess::OT_PREFETCH;
00126 }
00127 
00128 
00129 // Find a prefetching access with same the access's address. 
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 // Cache read
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         // Update statistics about cache accesses.
00172         UpdateCacheAccessStat( *param->access, hit );
00173     }
00174 }
00175 
00176 // Cache write
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         // Update statistics about cache accesses.
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 // Invalidate line
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 // Write an access to the cache table.
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 // Invoke a prefetch access.
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 // Returns whether this access is from this prefetcher or not.
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 

Onikiri2に対してTue Jun 18 14:34:24 2013に生成されました。  doxygen 1.4.7