src/Sim/Memory/Cache/CacheMissedAccessList.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 // This class handles missed accesses.
00034 // It corresponds to Miss Status Handling Register(MSHR)
00035 //
00036 
00037 #include <pch.h>
00038 
00039 #include "Sim/Memory/Cache/CacheMissedAccessList.h"
00040 #include "Sim/Memory/Cache/MemoryAccessEndEvent.h"
00041 #include "Sim/Pipeline/Pipeline.h"
00042 
00043 using namespace Onikiri;
00044 using namespace std;
00045 
00046 CacheMissedAccessList::CacheMissedAccessList(
00047     Pipeline* pipe,
00048     int offsetBitSize
00049 ) :
00050     m_enabled( false ),
00051     m_currentAccessID( 0 ),
00052     m_pipe( pipe ),
00053     m_offsetBitSize( offsetBitSize )
00054 {
00055 }
00056 
00057 CacheMissedAccessList::~CacheMissedAccessList()
00058 {
00059 }
00060 
00061 void CacheMissedAccessList::SetEnabled( bool enabled )
00062 {
00063     m_enabled = enabled;
00064 }
00065 
00066 // Mask the line offset part of 'addr'.
00067 Addr CacheMissedAccessList::MaskLineOffset( Addr addr )
00068 {
00069     addr.address &= 
00070         shttl::mask( 
00071             m_offsetBitSize, 
00072             64 - m_offsetBitSize 
00073         );
00074     return addr;
00075 }
00076 
00077 // Find an access corresponding to 'addr' from the list.
00078 // This method returns an iterator of a found access.
00079 CacheMissedAccessList::AccessListIterator 
00080 CacheMissedAccessList::FindAccess( const Addr& addr )
00081 {
00082     AccessListIterator i = m_list.begin();
00083     Addr maskedAddr = MaskLineOffset( addr );
00084     while( i != m_list.end() && i->access.address != maskedAddr ){
00085         ++i;
00086     }
00087     return i;
00088 }
00089 
00090 // Find an access corresponding to 'addr' from the list.
00091 // This method returns remaining cycles of a found access.
00092 CacheMissedAccessList::Result CacheMissedAccessList::Find( const Addr& addr )
00093 {
00094     if( !m_enabled ){
00095         return Result( 0, Result::ST_MISS );
00096     }
00097 
00098     AccessListIterator e = FindAccess( addr );
00099     if( e == m_list.end() ){
00100         return Result( 0, Result::ST_MISS );
00101     }
00102 
00103     // hit
00104     int leftCycles = (int)e->endTime - (int)m_pipe->GetNow();
00105     if( leftCycles < 0 ){
00106         THROW_RUNTIME_ERROR( "Invalid Pending Access." );
00107     }
00108 
00109     return Result( leftCycles, Result::ST_HIT );
00110 }
00111 
00112 // Add an access state to the list.
00113 void CacheMissedAccessList::AddList( 
00114     const CacheAccess& access, const AccessState& state, int latency 
00115 ){
00116     m_currentAccessID++;
00117     m_list.push_back( state );
00118 
00119     if( m_list.size() >= MAX_MISSED_ACCESS_LIST_LIMIT ){
00120         THROW_RUNTIME_ERROR( "The size of the missed access list exceeds a limit." );
00121     }
00122 
00123     // An event of memory access end time.
00124     AccessListIterator stateIterator = m_list.end(); 
00125     stateIterator--;
00126     EventPtr evnt(
00127         MissedAccessRearchEvent::Construct( access, stateIterator, this )
00128     );
00129     m_pipe->AddEvent( evnt, latency ); 
00130 }
00131 
00132 
00133 // Add a missed access to the list.
00134 void CacheMissedAccessList::Add( 
00135     const Access& access, 
00136     const Result& result, 
00137     CacheAccessNotifieeIF* notifiees[],
00138     int notifieesCount,
00139     const CacheAccessNotificationParam& notification
00140 ){
00141     ASSERT( !access.IsWirte(), "A write access is pushed to CacheMissedAccessList." );
00142 
00143     if( !m_enabled ){
00144         // Notify access finish.
00145         for( int i = 0; i < notifieesCount; i++ ){
00146             notifiees[i]->AccessFinished( access, notification );
00147         }
00148         return;
00149     }
00150 
00151     Addr addr = access.address;
00152     int  latency = result.latency;
00153     s64  now = m_pipe->GetNow();
00154         
00155     CacheMissedAccessList::AccessListIterator 
00156         foundAccess = FindAccess( addr );
00157 
00158     // A link of a link is forbidden.
00159     if( foundAccess != m_list.end() && !foundAccess->link ){
00160         // Add a link to the found predecessor access.
00161         AccessState state = *foundAccess;
00162         state.notification = notification;
00163         state.notifieesCount = notifieesCount;
00164         for( int i = 0; i < notifieesCount; i++ ){
00165             state.notifiees[i] = notifiees[i];
00166         }
00167         state.link = true;
00168         state.id = m_currentAccessID;
00169         int latency = (int)(state.endTime - now);
00170         AddList( access, state, latency );
00171         
00172     }
00173     else{
00174         AccessState state;
00175         state.access    = access;
00176         state.id        = m_currentAccessID;
00177         state.startTime = now;
00178         state.endTime   = now + latency;
00179         state.link      = false;
00180         state.notifieesCount = notifieesCount;
00181         for( int i = 0; i < notifieesCount; i++ ){
00182             state.notifiees[i] = notifiees[i];
00183         }
00184         state.notification = notification;
00185         state.access.address = MaskLineOffset( state.access.address );
00186         AddList( access, state, latency );
00187     } 
00188 
00189 }
00190 
00191 // When missed accesses are reached to this cache, removing the accesses
00192 // from the list and notify this to the cache.
00193 void CacheMissedAccessList::Remove( 
00194     const CacheAccess& access, AccessListIterator target 
00195 ){
00196     
00197 
00198     ASSERT( m_enabled );
00199 
00200     // Remove from the list.
00201     CacheAccessNotificationParam notification = target->notification;
00202     NotifieeArray notifiees = target->notifiees;
00203     int notifieesCount = target->notifieesCount;
00204     m_list.erase( target );
00205     
00206     // Notify access finish.
00207     for( int i = 0; i < notifieesCount; ++i ){
00208         notifiees[i]->AccessFinished( access, notification );
00209     }
00210 }
00211 
00212 // Returns the size of the access list.
00213 size_t CacheMissedAccessList::GetSize() const
00214 {
00215     return m_list.size();
00216 }

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