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/CacheAccessRequestQueue.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 CacheAccessRequestQueue::CacheAccessRequestQueue(
00047 Pipeline* pipe,
00048 int ports,
00049 int serializedCycles
00050 ) :
00051 m_enabled( false ),
00052 m_currentAccessID( 0 ),
00053 m_pipe( pipe ),
00054 m_ports( ports ),
00055 m_serializedCycles( serializedCycles )
00056 {
00057 }
00058
00059 CacheAccessRequestQueue::~CacheAccessRequestQueue()
00060 {
00061 }
00062
00063 void CacheAccessRequestQueue::SetEnabled( bool enabled )
00064 {
00065 m_enabled = enabled;
00066 }
00067
00068
00069 s64 CacheAccessRequestQueue::GetNextAccessStartableTime()
00070 {
00071 s64 now = m_pipe->GetNow();
00072 if( m_ports == 0 || m_queue.size() == 0 ){
00073 return now;
00074 }
00075
00076 if( (int)m_queue.size() < m_ports ){
00077 return now;
00078 }
00079
00080 AccessQueue::reverse_iterator firstPortAccess = m_queue.rbegin();
00081 for( int i = 0; i < m_ports - 1; i++ )
00082 {
00083 firstPortAccess++;
00084 ASSERT( firstPortAccess != m_queue.rend() );
00085 }
00086
00087 s64 serializingEndTime = firstPortAccess->serializingEndTime;
00088
00089
00090
00091 if( serializingEndTime < now )
00092 return now;
00093 else
00094 return serializingEndTime;
00095 }
00096
00097
00098 void CacheAccessRequestQueue::PushAccess( const CacheAccess& access, const AccessState& state, int latency )
00099 {
00100 m_currentAccessID++;
00101 m_queue.push_back( state );
00102
00103
00104 AccessQueueIterator stateIterator = m_queue.end();
00105 stateIterator--;
00106 EventPtr evnt(
00107 CacheAccessEndEvent::Construct( access, stateIterator, this )
00108 );
00109 m_pipe->AddEvent( evnt, latency );
00110 }
00111
00112
00113
00114
00115
00116 s64 CacheAccessRequestQueue::Push(
00117 const Access& access,
00118 int minLatency,
00119 CacheAccessNotifieeIF* notifiee,
00120 const CacheAccessNotificationParam& notification
00121 ){
00122 if( !m_enabled || m_ports == 0 || m_serializedCycles == 0 ){
00123
00124 if( notifiee ){
00125 notifiee->AccessFinished( access, notification );
00126 }
00127 return minLatency;
00128 }
00129
00130 s64 now = m_pipe->GetNow();
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 ASSERT( minLatency >= m_serializedCycles, "Minimum latency is shorter than serialized cycles." );
00143
00144 s64 serializingStartTime = GetNextAccessStartableTime();
00145 s64 accessEndTime = serializingStartTime + minLatency;
00146
00147 AccessState state =
00148 {
00149 access,
00150 m_currentAccessID,
00151 now,
00152 accessEndTime,
00153 serializingStartTime,
00154 serializingStartTime + m_serializedCycles,
00155 notifiee,
00156 notification
00157 };
00158
00159 int latency = (int)( accessEndTime - now );
00160 PushAccess( access, state, latency );
00161 return latency;
00162 }
00163
00164
00165
00166 void CacheAccessRequestQueue::Pop(
00167 const CacheAccess& access, AccessQueueIterator target
00168 ){
00169
00170 ASSERT( m_enabled );
00171
00172
00173 CacheAccessNotificationParam notification = target->notification;
00174 CacheAccessNotifieeIF* notifiee = target->notifiee;
00175 m_queue.erase( target );
00176
00177
00178 if( notifiee ){
00179 notifiee->AccessFinished( access, notification );
00180 }
00181 }
00182
00183
00184 size_t CacheAccessRequestQueue::GetSize() const
00185 {
00186 return m_queue.size();
00187 }