src/Sim/Memory/Cache/Cache.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 //
00033 // A cache class.
00034 //
00035 // ARQ: AccessRequestQueue
00036 //   This is used for simulation of band width limit.
00037 //
00038 // MAL: MissedAccessList
00039 //   This is used for missed access handling including 
00040 //   write allocate and refill. 
00041 //   MAL corresponds to a Miss Status Handling Register (MSHR).
00042 //  
00043 //   Upper caches
00044 //--------|--------
00045 //    ---------
00046 //    |  ARQ  |
00047 //    ---------
00048 //        |
00049 //    ---------
00050 //    | Cache |
00051 //    ---------
00052 //        |
00053 //    ---------
00054 //    |  MAL  |
00055 //    ---------
00056 //--------|--------
00057 //   Lower caches
00058 //
00059 
00060 #include <pch.h>
00061 
00062 #include "Sim/Memory/Cache/Cache.h"
00063 #include "Sim/Op/Op.h"
00064 #include "Sim/Foundation/Hook/HookUtil.h"
00065 #include "Sim/Memory/Cache/CacheMissedAccessList.h"
00066 #include "Sim/Memory/Prefetcher/PrefetcherIF.h"
00067 #include "Sim/Memory/Cache/CacheExtraStateTable.h"
00068 #include "Sim/Memory/Cache/CacheAccessRequestQueue.h"
00069 
00070 //
00071 // --- Hooks
00072 //
00073 namespace Onikiri
00074 {
00075     HookPoint<Cache, CacheHookParam> Cache::s_readHook;
00076     HookPoint<Cache, CacheHookParam> Cache::s_writeHook;
00077     HookPoint<Cache, CacheHookParam> Cache::s_invalidateHook;
00078     HookPoint<Cache, CacheHookParam> Cache::s_tableUpdateHook;
00079 };
00080 
00081 using namespace Onikiri;
00082 
00083 Cache::Cache() :
00084     m_latency           (0),
00085     m_nextLevelCache    (0),
00086     m_prefetcher        (0),
00087     m_perfect           (0),
00088     m_writePolicy       (WP_INVALID),
00089     m_missedAccessList  (0),
00090     m_accessQueue       (0),
00091     m_level             (0),
00092     m_indexBitSize      (0),
00093     m_offsetBitSize     (0),
00094     m_numWays           (0),
00095     m_numPorts          (0),
00096     m_reqQueueSize      (0),
00097     m_missedAccessListSize(0),
00098     m_numReadHit        (0),
00099     m_numReadMiss       (0),
00100     m_numReadAccess     (0),
00101     m_numReadPendingHit (0),
00102     m_numPrefetchHit    (0),
00103     m_numPrefetchMiss   (0),
00104     m_numPrefetchPendingHit(0),
00105     m_numPrefetchAccess (0),
00106     m_numWriteHit       (0),
00107     m_numWriteMiss      (0),
00108     m_numWriteAccess    (0),
00109     m_numWritePendingHit(0),
00110     m_numInvalidated    (0),
00111     m_capacityKB        (0)
00112 {
00113     m_lineBitSize = 0;
00114     m_capacityKB = 0;
00115     m_cacheTable = 0;
00116     m_lineState = new ExtraStateTableType();
00117 }
00118 
00119 Cache::~Cache()
00120 {
00121     ReleaseParam();
00122 
00123     if( m_lineState != NULL ){
00124         delete m_lineState;
00125         m_lineState = NULL;
00126     }
00127 
00128     if( m_missedAccessList != NULL ){
00129         delete m_missedAccessList;
00130         m_missedAccessList = NULL;
00131     }
00132 
00133     if( m_accessQueue != NULL ){
00134         delete m_accessQueue;
00135         m_accessQueue = NULL;
00136     }
00137 }
00138 
00139 void Cache::Initialize( InitPhase phase )
00140 {
00141     PipelineNodeBase::Initialize( phase );
00142 
00143     if(phase == INIT_PRE_CONNECTION){
00144 
00145         LoadParam();
00146         m_lineBitSize = m_offsetBitSize;
00147         int lineSize = (1 << m_lineBitSize);
00148 
00149         m_capacityKB = 
00150             m_numWays * 
00151             (1 << m_indexBitSize) *
00152             lineSize /
00153             1024;
00154 
00155         // This cache can transfer one line for 'm_exclusiveAccessCycles' cycles.
00156         if( m_exclusiveAccessCycles == 0 || m_numPorts == 0 ){
00157             m_maxThroughputBytesPerCycle = "Infinite";
00158         }
00159         else{
00160             m_maxThroughputBytesPerCycle.format( 
00161                 "%f", 
00162                 (double)lineSize / (double)m_exclusiveAccessCycles * m_numPorts
00163             );
00164         }
00165 
00166 
00167         if( m_latency < m_exclusiveAccessCycles ){
00168             THROW_RUNTIME_ERROR(
00169                 "The latency is less than the exclusive access cycles. "
00170                 "This means that the cache/memory cannot transfer whole "
00171                 "line data within the latency because the bandwidth "
00172                 "is too narow."
00173             );
00174         };
00175 
00176         if( m_numPorts != 0 ){
00177             if( m_exclusiveAccessCycles*m_reqQueueSize/m_numPorts + m_latency >
00178                 GetLowerPipeline()->GetWheelSize()
00179             ){
00180                 RUNTIME_WARNING( 
00181                     "The size of the time wheel may not be enough. " 
00182                     "Inclease the time wheel size or decrease @ExclusiveAccessCycles/@NumRequestListSize "
00183                 );
00184             }
00185         }
00186 
00187         m_cacheTable =
00188             new Cache::TableType( 
00189                 HasherType( m_indexBitSize, m_offsetBitSize ), 
00190                 m_numWays 
00191             );
00192 
00193     }
00194     else if( phase == INIT_POST_CONNECTION ){
00195         
00196         int offset = m_offsetBitSize;
00197 
00198         m_missedAccessList = 
00199             new CacheMissedAccessList( GetLowerPipeline(), offset );
00200 
00201         m_accessQueue = 
00202             new CacheAccessRequestQueue( GetLowerPipeline(), m_numPorts, m_exclusiveAccessCycles );
00203 
00204         if( m_prevLevelCaches.GetSize() == 0 && 
00205             ( m_exclusiveAccessCycles != 0 || m_numPorts != 0)
00206         ){
00207             // Scheduler assumes that a top level cache(L1) has enough band width.
00208             // If an user enable band width limit option of a top level cache, 
00209             // the system will be dead locked...
00210             THROW_RUNTIME_ERROR( "Band width limit of a top level cache is not support." );
00211         }
00212 
00213         if( !m_perfect && !m_nextLevelCache ){
00214             THROW_RUNTIME_ERROR( "The last level of a memory hierarchy must be 'perfect'." );
00215         }
00216 
00217         LineState initState;
00218         initState.dirty = false;
00219         m_lineState->Resize( this, initState );
00220 
00221         DisableLatch();
00222     }
00223 }
00224 
00225 // This method is called when a simulation mode is changed.
00226 void Cache::ChangeSimulationMode( PhysicalResourceNode::SimulationMode mode )
00227 {
00228     ASSERT( m_missedAccessList );
00229     ASSERT( m_accessQueue );
00230 
00231     bool isSimulation = ( mode == PhysicalResourceNode::SM_SIMULATION );
00232 
00233     // Disable access queues if the 'mode' is not 'Simulation' because 
00234     // Access queues use event mechanisms, which can run only under 'Simulation' mode.
00235     // In disabled queues, pushed accesses are reflected to caches immediately.
00236     m_missedAccessList->SetEnabled( isSimulation );
00237     m_accessQueue->SetEnabled(  isSimulation );
00238 }
00239 
00240 
00241 // Update statistics.
00242 void Cache::UpdateStatistics( const Access& access, Result::State state )
00243 {
00244     switch( access.type ){
00245 
00246     case AOT_READ:
00247     case AOT_READ_FOR_WRITE_ALLOCATE:
00248         m_numReadAccess++;
00249         switch( state ){
00250         case Result::ST_HIT:            m_numReadHit++;         break;
00251         case Result::ST_PENDING_HIT:    m_numReadPendingHit++;  break;
00252         case Result::ST_MISS:           m_numReadMiss++;        break;
00253         case Result::ST_NOT_ACCESSED:   ASSERT(0);              break;
00254         }
00255         break;
00256 
00257     case AOT_WRITE:
00258     case AOT_WRITE_BACK:
00259         m_numWriteAccess++;
00260         switch( state ){
00261         case Result::ST_HIT:            m_numWriteHit++;        break;
00262         case Result::ST_PENDING_HIT:    m_numWritePendingHit++; break;
00263         case Result::ST_MISS:           m_numWriteMiss++;       break;
00264         case Result::ST_NOT_ACCESSED:   ASSERT(0);              break;
00265         }
00266         break;
00267     
00268     case AOT_PREFETCH:
00269         m_numPrefetchAccess++;
00270         switch( state ){
00271         case Result::ST_HIT:            m_numPrefetchHit++;         break;
00272         case Result::ST_PENDING_HIT:    m_numPrefetchPendingHit++;  break;
00273         case Result::ST_MISS:           m_numPrefetchMiss++;        break;
00274         case Result::ST_NOT_ACCESSED:   ASSERT(0);                  break;
00275         }
00276         break;
00277 
00278     }
00279 }
00280 
00281 
00282 // Chech whether the access is valid or not
00283 void Cache::CheckValidAddress( const Addr& addr )
00284 {
00285     ASSERT(
00286         addr.pid != PID_INVALID && addr.tid != TID_INVALID,
00287         "The address has an invalid id (PID:%d, TID:%d).",
00288         addr.pid, addr.tid
00289     );
00290 }
00291 
00292 
00293 // Add accesses to a missed access list.
00294 void Cache::AddToMissedAccessList( 
00295     const Access& access,
00296     const Result& result,
00297     CacheAccessNotifieeIF* notifee,
00298     const NotifyParam& param
00299 ){
00300     CacheAccessNotifieeIF* notifeeList[2] = { this, notifee };
00301     int notifieeCount = notifee != NULL ? 2 : 1;
00302 
00303     // Add the missed access to the list.
00304     m_missedAccessList->Add( 
00305         access, 
00306         result, 
00307         notifeeList,    // Notifiees
00308         notifieeCount,  // The number of notifiees
00309         param   
00310     );
00311 }
00312 
00313 // Get the access latency of a hit access.
00314 Cache::Result Cache::OnReadHit( const Access& access)
00315 {
00316     // Update cache replacement information.
00317     if( !m_perfect ){
00318         m_cacheTable->read( access.address );
00319     }
00320 
00321     Result result( (int)m_latency, Result::ST_HIT, this );
00322 
00323     // Push the access to the queue.
00324     result.latency = 
00325         (int)m_accessQueue->Push( 
00326             access, 
00327             m_latency,
00328             NULL,
00329             NotifyParam()
00330         );
00331     
00332     return result;
00333 }
00334 
00335 
00336 // Process accesses that hit in the missed access list.
00337 Cache::Result Cache::OnReadPendingHit( 
00338     const Access& access, 
00339     const Result& phResult,
00340     CacheAccessNotifieeIF* notifee
00341 ){
00342     ASSERT( !m_perfect );
00343 
00344     Result result ( phResult.latency, Result::ST_PENDING_HIT, this );
00345     if( result.latency < m_latency ){
00346         result.latency = m_latency;
00347     }
00348 
00349     NotifyParam notification( CAET_FILL_FROM_MAL_FINISHED, result );
00350     AddToMissedAccessList( access, result, notifee, notification );
00351 
00352     return result;
00353 }
00354 
00355 
00356 // Processes on cache misses.
00357 Cache::Result Cache::OnReadMiss( 
00358     const Access& access,
00359     CacheAccessNotifieeIF* notifee
00360 ){
00361     // xLbVCeV
00362     Result nextResult = m_nextLevelCache->Read( access, NULL );
00363     int nextLatency = nextResult.latency;
00364 
00365     Result result( m_latency + nextLatency, Result::ST_MISS, nextResult.cache );
00366 
00367     NotifyParam notification( CAET_FILL_FROM_NEXT_CACHE_FINISHED, result );
00368     AddToMissedAccessList( access, result, notifee, notification );
00369 
00370     return result;
00371 }
00372 
00373 
00374 // [hCeV
00375 // A implementation body of Read/ReadInorder.
00376 void Cache::ReadBody( CacheHookParam* param )
00377 {
00378     const Access& access = *param->access;
00379 
00380     Addr addr = access.address;
00381     CheckValidAddress( addr );
00382 
00383     Result result;
00384 
00385     if( m_perfect ){
00386         // Perfect
00387         result = OnReadHit( access );
00388     } 
00389     else{
00390         CacheTableIterator line = m_cacheTable->find( addr );
00391         if( line != m_cacheTable->end() ){
00392             // Perfect or Hit
00393             result = OnReadHit( access );
00394             param->line = line;
00395         } 
00396         else{
00397 
00398             Result phResult = m_missedAccessList->Find( addr );
00399             CacheAccessNotifieeIF* notifee = param->notifiee;
00400             if( phResult.state == Result::ST_HIT ){ 
00401                 // Hit in the missed access list.
00402                 result = OnReadPendingHit( access, phResult, notifee );
00403             }
00404             else{
00405                 // Miss
00406                 result = OnReadMiss( access, notifee );
00407             }
00408         }
00409     }
00410 
00411     // Update statistics
00412     UpdateStatistics( access, result.state );
00413     param->result = result;
00414 }
00415 
00416 Cache::Result Cache::Read( const Access& access, NotifieeIF* notifiee )
00417 {
00418     CacheHookParam param;
00419     param.access = &access;
00420     param.table  = m_cacheTable;
00421     param.address   = &access.address;
00422     param.notifiee = notifiee;
00423     param.line = m_cacheTable->end();
00424 
00425     HookEntry( this, &Cache::ReadBody, &s_readHook, &param );
00426 
00427     if( m_prefetcher ){
00428         m_prefetcher->OnCacheRead( this, &param );
00429     }
00430 
00431     return param.result;
00432 }
00433 
00434 
00435 // Processes on a cache hit.
00436 Cache::Result Cache::OnWriteHit( const Access& access )
00437 {
00438     Result result( (int)m_latency, Result::ST_HIT, this );
00439     NotifyParam notification( CAET_WRITE_ACCESS_FINISHED, result );
00440 
00441     // Push the access to the queue.
00442     result.latency = 
00443     (int)m_accessQueue->Push( 
00444         access, 
00445         m_latency,
00446         this,
00447         notification
00448     );
00449 
00450     return result;  
00451 }
00452 
00453 // Processes on a cache partial hit (hits in PendingAccess).
00454 Cache::Result Cache::OnWritePendingHit( 
00455     const Access& access, 
00456     const Result& phResult,
00457     CacheAccessNotifieeIF* notifee
00458 ){
00459     Access writeAllocate = access;
00460     writeAllocate.type = Access::OT_READ_FOR_WRITE_ALLOCATE;
00461 
00462     // Add the access to the missed accessed list.
00463     NotifyParam notification( CAET_WRITE_ALLOCATE_FINISHED, phResult );
00464     AddToMissedAccessList( writeAllocate, phResult, notifee, notification );
00465 
00466     return Result( 
00467         m_latency + phResult.latency, 
00468         Result::ST_MISS,
00469         this
00470     );
00471 }
00472 
00473 // Processes on a cache miss
00474 Cache::Result Cache::OnWriteMiss( 
00475     const Access& access,
00476     CacheAccessNotifieeIF* notifee
00477 ){
00478     // Write allocate
00479     Access writeAllocate = access;
00480     writeAllocate.type = Access::OT_READ_FOR_WRITE_ALLOCATE;
00481     Result nextResult = 
00482         m_nextLevelCache->Read( writeAllocate, NULL );
00483 
00484     int nextLatency = nextResult.latency;
00485     
00486     NotifyParam notification( CAET_WRITE_ALLOCATE_FINISHED, nextResult );
00487     AddToMissedAccessList( writeAllocate, nextResult, notifee, notification );
00488 
00489     return Result( 
00490         m_latency + nextLatency, 
00491         Result::ST_MISS,
00492         nextResult.cache
00493     );
00494 }
00495 
00496 
00497 // StoreRetirem_cacheWrite
00498 // CeVCCg~XCgAP[g
00499 Cache::Result Cache::Write( const Access& access, NotifieeIF* notifiee )
00500 {
00501     CacheHookParam param;
00502     param.access = &access;
00503     param.address   = &access.address;
00504     param.table  = m_cacheTable;
00505     param.notifiee = notifiee;
00506     param.line = m_cacheTable->end();
00507 
00508     HookEntry( this, &Cache::WriteBody, &s_writeHook, &param );
00509 
00510     if( m_prefetcher ){
00511         m_prefetcher->OnCacheWrite( this, &param );
00512     }
00513 
00514     return param.result;
00515 }
00516 
00517 void Cache::WriteBody( CacheHookParam* param )
00518 {
00519     const Access& access = *param->access;
00520 
00521     Addr addr = access.address;
00522     CheckValidAddress( addr );
00523 
00524     Result result;
00525 
00526     if( m_perfect ){
00527         // Perfect
00528         result = OnWriteHit( access );
00529     }
00530     else{
00531 
00532         CacheTableIterator line = m_cacheTable->find( addr );
00533         if( line != m_cacheTable->end() ){
00534             // Hit
00535             result = OnWriteHit( access );
00536             param->line = line;
00537         }
00538         else{
00539             CacheAccessNotifieeIF* notifee = param->notifiee;
00540             Result phResult = m_missedAccessList->Find( addr );
00541             if( phResult.state == Result::ST_HIT ){ 
00542                 // Write allocate request hits in the missed access list.
00543                 result = OnWritePendingHit( access, phResult, notifee );
00544             }
00545             else{   
00546                 // Miss
00547                 result = OnWriteMiss( access, notifee );
00548             }
00549         }
00550     }
00551 
00552     // Update statistics
00553     UpdateStatistics( access, result.state );
00554 
00555     param->result = result;
00556 }
00557 
00558 // Write an access to the cache table on re-fill, write, write-back and write-allocate.
00559 void Cache::UpdateTableBody( CacheHookParam* param )
00560 {
00561     const CacheAccess& access = *param->access;
00562     bool dirty = access.IsWirte();
00563 
00564     bool replaced;
00565     CacheLine replacedLine;
00566     Addr replacedAddr;
00567     TableType::iterator line =
00568         m_cacheTable->write( access.address, Value(), &replaced, &replacedAddr, &replacedLine );
00569     param->line = line;
00570     param->replaced = replaced;
00571 
00572     if( replaced ){
00573     
00574         // Invalidate replaced lines in previous level caches for keep inclusion.
00575         for( int i = 0; i < m_prevLevelCaches.GetSize(); i++ ){
00576             m_prevLevelCaches[i]->Invalidate( replacedAddr );
00577         }
00578         
00579         // Write back replaced lines to the next level cache.
00580         if( m_writePolicy == WP_WRITE_BACK && !m_perfect ){
00581             if( (*m_lineState)[ line ].dirty ){
00582                 Access writeBack  = access;
00583                 writeBack.address = replacedAddr;
00584                 writeBack.value       = 0;
00585                 writeBack.lineValue   = replacedLine.value;
00586                 writeBack.type    = AOT_WRITE_BACK;
00587                 m_nextLevelCache->Write( writeBack, NULL );
00588             }
00589         }
00590     }
00591 
00592     // Set a dirty flag.
00593     (*m_lineState)[ line ].dirty = dirty;
00594 }
00595 
00596 
00597 void Cache::UpdateTable( const Access& access )
00598 {
00599     CacheHookParam param;
00600     param.access = &access;
00601     param.table  = m_cacheTable;
00602     param.line = m_cacheTable->end();
00603 
00604     HookEntry( this, &Cache::UpdateTableBody, &s_tableUpdateHook, &param );
00605 
00606     if( m_prefetcher ){
00607         m_prefetcher->OnCacheTableUpdate( this, &param );
00608     }
00609 }
00610 
00611 
00612 // Invalidate line
00613 void Cache::Invalidate( const Addr& addr )
00614 {
00615     CacheHookParam param;
00616     param.address = &addr;
00617     param.table  = m_cacheTable;
00618     param.line = m_cacheTable->end();
00619 
00620     HookEntry( this, &Cache::InvalidateBody, &s_invalidateHook, &param );
00621 
00622     if( m_prefetcher ){
00623         m_prefetcher->OnCacheInvalidation( this, &param );
00624     }
00625 }
00626 
00627 void Cache::InvalidateBody( CacheHookParam* param )
00628 {
00629     CacheTableIterator line = m_cacheTable->invalidate( *param->address );
00630     if( line != m_cacheTable->end() ){
00631         m_numInvalidated++;
00632     }
00633     param->line = line;
00634 }
00635 
00636 // PendingAccess eANZXIm
00637 void Cache::AccessFinished( const Access& access, const NotifyParam& param ) 
00638 {
00639     CheckValidAddress( access.address );
00640 
00641     switch( param.type ){
00642     case CAET_FILL_FROM_MAL_FINISHED:
00643         ASSERT( !access.IsWirte() );
00644         break;
00645 
00646     case CAET_FILL_FROM_NEXT_CACHE_FINISHED:
00647         ASSERT( !access.IsWirte() );
00648         UpdateTable( access );
00649         break;
00650     
00651     case CAET_WRITE_ALLOCATE_FINISHED:
00652     {
00653         ASSERT( !access.IsWirte() );
00654         Access writeAccess = access;
00655         writeAccess.type = Access::OT_WRITE;
00656         OnWriteHit( writeAccess );
00657         break;
00658     }
00659 
00660     case CAET_WRITE_ACCESS_FINISHED:
00661         ASSERT( access.IsWirte() );
00662         UpdateTable( access );
00663         if( m_writePolicy == WP_WRITE_THROUGH && !m_perfect ){
00664             m_nextLevelCache->Write( access, NULL );
00665         }
00666         break;
00667 
00668     default:
00669         ASSERT(0);
00670         break;
00671     }
00672     
00673 }
00674 
00675 
00676 Cache* Cache::GetNextCache()
00677 {
00678     if( m_nextLevelCache != 0 ){
00679         return m_nextLevelCache;
00680     } 
00681     else{
00682         return 0;
00683     }
00684 }
00685 
00686 void Cache::SetNextCache( PhysicalResourceArray<Cache>& next )
00687 {
00688     m_nextLevelCache = next[0];
00689     m_nextLevelCache->AddPreviousLevelCache( this );
00690 }
00691 
00692 // Add previous level cache
00693 void Cache::AddPreviousLevelCache( Cache* prev )
00694 {
00695     for( int i = 0; i < m_prevLevelCaches.GetSize(); i++ ){
00696         if( m_prevLevelCaches[i] == prev ){
00697             THROW_RUNTIME_ERROR( "A same previous level cache is added more than once." );
00698         }
00699     }
00700 
00701     m_prevLevelCaches.Add( prev );
00702 }
00703 
00704 int Cache::GetOffsetBitSize() const
00705 {
00706     return m_offsetBitSize;
00707 }
00708 
00709 // Returns true when resources (a request queue etc) are full and stall is required.
00710 bool Cache::IsStallRequired()
00711 {
00712 
00713     if( m_nextLevelCache && m_nextLevelCache->IsStallRequired() ){
00714         return true;
00715     }
00716 
00717     if( m_reqQueueSize != 0 && 
00718         (int)m_accessQueue->GetSize() >= m_reqQueueSize 
00719     ){
00720         return true;
00721     }
00722 
00723     if( m_missedAccessListSize != 0 && 
00724         (int)m_missedAccessList->GetSize() >= m_missedAccessListSize 
00725     ){
00726         return true;
00727     }
00728 
00729     return false;
00730 }
00731 
00732 // This is called on every cycle except stall time.
00733 void Cache::Update()
00734 {
00735 }

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