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
00033
00034
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
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
00078
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
00091
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
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
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
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
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
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
00159 if( foundAccess != m_list.end() && !foundAccess->link ){
00160
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
00192
00193 void CacheMissedAccessList::Remove(
00194 const CacheAccess& access, AccessListIterator target
00195 ){
00196
00197
00198 ASSERT( m_enabled );
00199
00200
00201 CacheAccessNotificationParam notification = target->notification;
00202 NotifieeArray notifiees = target->notifiees;
00203 int notifieesCount = target->notifieesCount;
00204 m_list.erase( target );
00205
00206
00207 for( int i = 0; i < notifieesCount; ++i ){
00208 notifiees[i]->AccessFinished( access, notification );
00209 }
00210 }
00211
00212
00213 size_t CacheMissedAccessList::GetSize() const
00214 {
00215 return m_list.size();
00216 }