src/Sim/Memory/Cache/CacheAccessRequestQueue.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 queue of cache access requests.
00034 // This queue is for band width simulation of caches/memories.
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 // Get a time when new memory access can start.
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     //printf( "%I64d - %I64d\n", now, serializingEndTime );
00090 
00091     if( serializingEndTime < now )
00092         return now;
00093     else
00094         return serializingEndTime;
00095 }
00096 
00097 // Add an access state to the list.
00098 void CacheAccessRequestQueue::PushAccess( const CacheAccess& access, const AccessState& state, int latency )
00099 {
00100     m_currentAccessID++;
00101     m_queue.push_back( state );
00102 
00103     // An event of memory access end time.
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 // Push an access to a queue.
00114 // This method returns the latency of an access.
00115 // See more detailed comments in the method definition.
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         // Notify access finish.
00124         if( notifiee ){
00125             notifiee->AccessFinished( access, notification );
00126         }
00127         return minLatency;
00128     }
00129 
00130     s64 now = m_pipe->GetNow();
00131 
00132     // Each access exclusively use one cache port for S cycles.
00133     // After S cycles, a next access can start.
00134     //   L: latency (Cache/@Latency)
00135     //   S: serialized cycles ()
00136     //   *: wait for serializing
00137     //
00138     //   A0: <--S--><------(L-S)------>
00139     //   A1:   *****<--S--><------(L-S)------>
00140     //   A2:    ***********<--S--><------(L-S)------>
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,                                     // addr
00150         m_currentAccessID,                          // ID
00151         now,                                        // start
00152         accessEndTime,                              // end
00153         serializingStartTime,                       // serializingStart
00154         serializingStartTime + m_serializedCycles,  // serializingEnd
00155         notifiee,                                   // notifiee
00156         notification                                // type
00157     };
00158     
00159     int latency = (int)( accessEndTime - now );
00160     PushAccess( access, state, latency );
00161     return latency;
00162 }
00163 
00164 // Remove an access from the queue and notify this to a connected cache
00165 // when a memory access finishes. 
00166 void CacheAccessRequestQueue::Pop( 
00167     const CacheAccess& access, AccessQueueIterator target 
00168 ){
00169 
00170     ASSERT( m_enabled );
00171 
00172     // Remove an access request from the queue.
00173     CacheAccessNotificationParam notification = target->notification;
00174     CacheAccessNotifieeIF* notifiee = target->notifiee;
00175     m_queue.erase( target );
00176     
00177     // Notify access finish.
00178     if( notifiee ){
00179         notifiee->AccessFinished( access, notification );
00180     }
00181 }
00182 
00183 // Returns the size of the access queue.
00184 size_t CacheAccessRequestQueue::GetSize() const
00185 {
00186     return m_queue.size();
00187 }

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