src/Sim/InorderList/InorderList.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 #include <pch.h>
00033 
00034 #include "Sim/InorderList/InorderList.h"
00035 
00036 
00037 #include "Sim/Dumper/Dumper.h"
00038 
00039 #include "Sim/Foundation/Hook/HookUtil.h"
00040 #include "Sim/Op/Op.h"
00041 #include "Sim/Pipeline/Scheduler/Scheduler.h"
00042 #include "Sim/Core/Core.h"
00043 #include "Sim/Thread/Thread.h"
00044 
00045 #include "Sim/Memory/MemOrderManager/MemOrderManager.h"
00046 #include "Sim/Memory/Cache/CacheSystem.h"
00047 #include "Sim/Predictor/DepPred/RegDepPred/RegDepPredIF.h"
00048 #include "Sim/Predictor/DepPred/MemDepPred/MemDepPredIF.h"
00049 #include "Sim/Op/OpObserver/OpObserver.h"
00050 
00051 #include "Sim/Pipeline/Fetcher/Fetcher.h"
00052 #include "Sim/Pipeline/Renamer/Renamer.h"
00053 #include "Sim/Pipeline/Dispatcher/Dispatcher.h"
00054 #include "Sim/Pipeline/Retirer/Retirer.h"
00055 
00056 #include "Utility/RuntimeError.h"
00057 
00058 namespace Onikiri
00059 {
00060     HookPoint<InorderList> InorderList::s_opFlushHook;
00061 }
00062 
00063 using namespace std;
00064 using namespace Onikiri;
00065 
00066 InorderList::InorderList() :
00067     m_core(0),
00068     m_checkpointMaster(0),
00069     m_thread(0),
00070     m_notifier(0),
00071     m_memOrderManager(0),
00072     m_regDepPred(0),
00073     m_memDepPred(0),
00074     m_fetcher(0),
00075     m_renamer(0),
00076     m_dispatcher(0),
00077     m_retirer(0),
00078     m_cacheSystem(0),
00079     m_inorderList(0),
00080     m_mode( SM_SIMULATION ),
00081     m_capacity(0),
00082     m_removeOpsOnCommit(false),
00083     m_retiredOps(0),
00084     m_retiredInsns(0)
00085 {
00086 
00087 }
00088 
00089 InorderList::~InorderList()
00090 {
00091     ReleaseParam();
00092 }
00093 
00094 void InorderList::Initialize(InitPhase phase)
00095 {
00096     if(phase == INIT_PRE_CONNECTION){
00097         LoadParam();
00098     }
00099     else if(phase == INIT_POST_CONNECTION){
00100         if( m_core == 0 ) {
00101             THROW_RUNTIME_ERROR("core not set.");
00102         }
00103         if( m_checkpointMaster == 0 ) {
00104             THROW_RUNTIME_ERROR("CheckpointMaster not set.");
00105         }
00106         if( m_thread == 0 ) {
00107             THROW_RUNTIME_ERROR("thread not set.");
00108         }
00109 
00110         m_opArray     = m_core->GetOpArray();
00111         m_notifier    = new OpNotifier();
00112         
00113         m_inorderList.resize( *m_opArray );
00114         m_committedList.resize( *m_opArray );
00115 
00116         m_memOrderManager = m_thread->GetMemOrderManager();
00117         m_regDepPred = m_thread->GetRegDepPred();
00118         m_memDepPred = m_thread->GetMemDepPred();
00119 
00120         m_fetcher    = m_core->GetFetcher();
00121         m_dispatcher = m_core->GetDispatcher();
00122         m_renamer    = m_core->GetRenamer();
00123         m_retirer    = m_core->GetRetirer();
00124 
00125         m_cacheSystem = m_core->GetCacheSystem();
00126 
00127         if( m_fetcher->GetFetchWidth() > m_capacity ){
00128             THROW_RUNTIME_ERROR( "The capacity of InOrderList is too small. It must be larger than fetch width." );
00129         }
00130     }
00131 }
00132 
00133 
00134 // --- Op Ej
00135 // Op 
00136 OpIterator InorderList::ConstructOp(const OpInitArgs& args)
00137 {
00138     OpIterator op = m_opArray->CreateOp();
00139     op->Initialize(args);
00140 
00141     return op;
00142 }
00143         
00144 // Op j
00145 void InorderList::DestroyOp(OpIterator op)
00146 {
00147     m_opArray->ReleaseOp(op);
00148 }
00149 
00150 
00151 // --- tFb`W
00152 // opfetch
00153 void InorderList::PushBack(OpIterator op)
00154 {
00155     // Gg
00156     m_inorderList.push_back(op);
00157 }
00158 
00159 // --- Remove a back op from a list.
00160 void InorderList::PopBack()
00161 {
00162     m_inorderList.pop_back();
00163 }
00164 
00165 
00166 // --- /O/
00167 // R~bgCvOI[_
00168 OpIterator InorderList::GetCommittedFrontOp()
00169 {
00170     if( m_committedList.empty() ){
00171         return OpIterator(0);
00172     }
00173     
00174     return m_committedList.front();
00175 }
00176 
00177 OpIterator InorderList::GetFrontOp()
00178 {
00179     if( m_inorderList.empty() ){
00180         return OpIterator(0);
00181     }
00182     
00183     return m_inorderList.front();
00184 }
00185 
00186 // vOI[_
00187 OpIterator InorderList::GetBackOp()
00188 {
00189     if(m_inorderList.empty())
00190         return OpIterator(0);
00191     else
00192         return m_inorderList.back();
00193 }
00194 
00195 // OIndexOp
00196 /*
00197 op1 ( PC = PC0, No = 0 )
00198 op2 ( PC = PC0, No = 1 )
00199 op3 ( PC = PC1, No = 0 )
00200 
00201 GetPrevIndexOp(op3) -> op2
00202 GetPrevIndexOp(op2) -> op1
00203 */
00204 OpIterator InorderList::GetPrevIndexOp(OpIterator op)
00205 {
00206     if( GetFrontOp() == op ){
00207         return OpIterator(0);
00208     }
00209 
00210     return *(--m_inorderList.get_iterator(op));
00211 }
00212 
00213 // IndexOp
00214 /*
00215 op1 ( PC = PC0, No = 0 )
00216 op2 ( PC = PC0, No = 1 )
00217 op3 ( PC = PC1, No = 0 )
00218 
00219 GetNextIndexOp(op1) -> op2
00220 GetNextIndexOp(op2) -> op3
00221 */
00222 OpIterator InorderList::GetNextIndexOp(OpIterator op)
00223 {
00224     if(m_inorderList.back() == op) {
00225         return OpIterator(0);
00226     }
00227 
00228     return *(++m_inorderList.get_iterator(op));
00229 }
00230 
00231 // OPCOp
00232 /*
00233 op1 ( PC = PC0, No = 0 )
00234 op2 ( PC = PC0, No = 1 )
00235 op3 ( PC = PC1, No = 0 )
00236 op4 ( PC = PC1, No = 1 )
00237 
00238 GetPrevPCOp(op3) -> op2
00239 GetPrevPCOp(op4) -> op2
00240 */
00241 OpIterator InorderList::GetPrevPCOp(OpIterator op)
00242 {
00243     int opNo = op->GetNo();
00244     
00245     OpIterator prev = op;
00246 
00247     // opNo + 1  GetPrevIndexOp OPC
00248     //  op3  1Aop4 2
00249     for(int i = 0; i <= opNo; ++i) {
00250         prev = GetPrevIndexOp(prev);
00251         
00252         if( prev.IsNull() ) {
00253             break;
00254         }
00255     }
00256     return prev;
00257 }
00258 
00259 // PCOp
00260 /*
00261 op1 ( PC = PC0, No = 0 )
00262 op2 ( PC = PC0, No = 1 )
00263 op3 ( PC = PC1, No = 0 )
00264 
00265 GetNextPCOp(op1) -> op3
00266 */
00267 OpIterator InorderList::GetNextPCOp(OpIterator op)
00268 {
00269 
00270     OpIterator next = GetNextIndexOp(op);
00271 
00272     //  No == 0 T
00273     while( (!next.IsNull()) && (next->GetNo() != 0) ) {
00274         next = GetNextIndexOp(next);
00275     }
00276 
00277     return next;
00278 }
00279 
00280 // PC Op( MicroOp )
00281 /*
00282 op1 ( PC = PC0, No = 0 )
00283 op2 ( PC = PC0, No = 1 )
00284 op3 ( PC = PC1, No = 0 )
00285 
00286 GetNextPCOp(op2) -> op1
00287 GetNextPCOp(op3) -> op3
00288 */
00289 OpIterator InorderList::GetFrontOpOfSamePC(OpIterator op)
00290 {
00291     OpIterator previousOp = GetPrevPCOp(op);
00292 
00293     if( ! previousOp.IsNull() ) {
00294         return GetNextIndexOp(previousOp);
00295     }else {
00296         return GetFrontOp();
00297     }
00298 }
00299 
00300 // 
00301 bool InorderList::IsEmpty()
00302 {
00303     return m_inorderList.empty() && m_committedList.empty();
00304 }
00305 
00306 // Return whether an inorder list can reserve entries or not.
00307 bool InorderList::CanAllocate( int ops )
00308 {
00309     int current = (int)m_inorderList.size();
00310     if( !m_removeOpsOnCommit ){
00311         current += (int)m_committedList.size();
00312     }
00313     return ops + current <= m_capacity; 
00314 }
00315 
00316 
00317 void InorderList::Commit( OpIterator op )
00318 {
00319     if( m_mode == SM_SIMULATION ){
00320         ASSERT( 
00321             m_inorderList.front() == op, 
00322             "The front of a raw inorder list and the committed op are inconsistent. The committed op:\n%s", 
00323             op->ToString().c_str() 
00324         );
00325 
00326         g_dumper.Dump( DS_COMMIT, op );
00327         NotifyCommit( op );
00328         op->SetStatus( OpStatus::OS_COMITTING );
00329 
00330         // Move to the committed list.
00331         m_inorderList.pop_front();
00332         m_committedList.push_back( op );
00333     }
00334 }
00335 
00336 void InorderList::Retire( OpIterator op )
00337 {
00338     bool headOp = op->GetNo() == 0; // This op is a head of divided micro ops or not.
00339 
00340     if( m_mode == SM_SIMULATION ){
00341         g_dumper.Dump( DS_RETIRE, op );
00342         op->SetStatus( OpStatus::OS_RETIRED );
00343 
00344         for( OpIterator i = m_committedList.front();
00345              i->GetStatus() == OpStatus::OS_RETIRED;
00346         ){
00347             m_committedList.pop_front();
00348             NotifyRetire( i );
00349             DestroyOp( i );
00350             
00351             if( m_committedList.empty() ){
00352                 break;
00353             }
00354 
00355             i = m_committedList.front();
00356         }
00357     }
00358 
00359     if( headOp ){
00360         ++m_retiredInsns;
00361     }
00362     m_retiredOps++;
00363 }
00364 
00365 
00366 // Flush all backward ops from 'startOp'.
00367 // This method flushes ops including 'startOp'.
00368 int InorderList::FlushBackward( OpIterator startOp )
00369 {
00370     // ~XtFb`
00371     if( startOp.IsNull() ){
00372         return 0;
00373     }
00374 
00375     // back()  startOp Flush
00376     int flushedInsns = 0;
00377     while( true ){
00378         OpIterator op = GetBackOp();
00379         Flush( op );
00380         flushedInsns++;
00381         
00382         PopBack();
00383 
00384         bool end = ( op == startOp ) ? true : false;
00385 
00386         // op 
00387         DestroyOp( op );
00388 
00389         if( end ){
00390             break;
00391         }
00392     }
00393 
00394     return flushedInsns;
00395 }
00396 
00397 void InorderList::Flush(OpIterator op)
00398 {
00399     HOOK_SECTION_OP( s_opFlushHook, op )
00400     {
00401         g_dumper.Dump( DS_FLUSH, op );
00402         NotifyFlush( op );
00403         op->SetStatus( OpStatus::OS_FLUSHED );
00404     }
00405 }
00406 
00407 void InorderList::NotifyCommit(OpIterator op)
00408 {
00409     // `FbN|CgR~bg
00410     if( op->GetBeforeCheckpoint() ) {
00411         m_checkpointMaster->Commit(op->GetBeforeCheckpoint());
00412     }
00413     if( op->GetAfterCheckpoint() ) {
00414         m_checkpointMaster->Commit(op->GetAfterCheckpoint());
00415     }
00416 
00417     // CacheSystem must be retired after that of MemOrderManager,
00418     // because CacheSystem uses cache access results of stores 
00419     // set by MemOrderManager.
00420     m_memOrderManager->Commit( op );
00421     m_cacheSystem->Commit( op );    
00422 
00423     m_regDepPred->Commit(op);
00424     m_memDepPred->Commit(op);
00425 
00426     m_fetcher->Commit(op);
00427     m_dispatcher->Commit(op);
00428     m_renamer->Commit(op);
00429     if( op->GetScheduler() != 0 ) {
00430         op->GetScheduler()->Commit(op);
00431     }
00432 
00433     m_notifier->NotifyCommit( op );
00434 }
00435 
00436 
00437 void InorderList::NotifyRetire( OpIterator op )
00438 {
00439     op->ClearEvent();
00440 
00441     if( op->GetScheduler() ){
00442         op->GetScheduler()->Retire( op );
00443     }
00444 
00445     m_cacheSystem->Retire( op );
00446     m_memOrderManager->Retire( op );
00447     m_dispatcher->Retire( op );
00448     m_renamer->Retire( op );
00449     m_fetcher->Retire( op );
00450 
00451     // src  dependency `
00452     op->DissolveSrcReg();
00453     op->DissolveSrcMem();
00454 }
00455 
00456 void InorderList::NotifyFlush( OpIterator op )
00457 {
00458     if( op->GetAfterCheckpoint() ){
00459         m_checkpointMaster->Flush( op->GetAfterCheckpoint() );
00460     }
00461     if( op->GetBeforeCheckpoint() ){
00462         m_checkpointMaster->Flush( op->GetBeforeCheckpoint() );
00463     }
00464 
00465     op->CancelEvent();
00466     op->ClearEvent();
00467     if( op->GetScheduler() ){
00468         op->GetScheduler()->Flush( op );
00469     }
00470 
00471     m_cacheSystem->Flush( op );
00472     m_memOrderManager->Flush( op );
00473     m_retirer->Flush( op );
00474     m_dispatcher->Flush( op );
00475     m_renamer->Flush( op );
00476     m_fetcher->Flush( op );
00477     m_regDepPred->Flush(op);
00478     m_memDepPred->Flush(op);
00479 
00480     op->DissolveSrcReg();   // src  dependency `
00481     op->DissolveSrcMem();
00482 
00483     m_notifier->NotifyFlush( op );
00484 }

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