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 #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
00135
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
00145 void InorderList::DestroyOp(OpIterator op)
00146 {
00147 m_opArray->ReleaseOp(op);
00148 }
00149
00150
00151
00152
00153 void InorderList::PushBack(OpIterator op)
00154 {
00155
00156 m_inorderList.push_back(op);
00157 }
00158
00159
00160 void InorderList::PopBack()
00161 {
00162 m_inorderList.pop_back();
00163 }
00164
00165
00166
00167
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
00187 OpIterator InorderList::GetBackOp()
00188 {
00189 if(m_inorderList.empty())
00190 return OpIterator(0);
00191 else
00192 return m_inorderList.back();
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202
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
00214
00215
00216
00217
00218
00219
00220
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
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 OpIterator InorderList::GetPrevPCOp(OpIterator op)
00242 {
00243 int opNo = op->GetNo();
00244
00245 OpIterator prev = op;
00246
00247
00248
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
00260
00261
00262
00263
00264
00265
00266
00267 OpIterator InorderList::GetNextPCOp(OpIterator op)
00268 {
00269
00270 OpIterator next = GetNextIndexOp(op);
00271
00272
00273 while( (!next.IsNull()) && (next->GetNo() != 0) ) {
00274 next = GetNextIndexOp(next);
00275 }
00276
00277 return next;
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
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
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
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;
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
00367
00368 int InorderList::FlushBackward( OpIterator startOp )
00369 {
00370
00371 if( startOp.IsNull() ){
00372 return 0;
00373 }
00374
00375
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
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
00410 if( op->GetBeforeCheckpoint() ) {
00411 m_checkpointMaster->Commit(op->GetBeforeCheckpoint());
00412 }
00413 if( op->GetAfterCheckpoint() ) {
00414 m_checkpointMaster->Commit(op->GetAfterCheckpoint());
00415 }
00416
00417
00418
00419
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
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();
00481 op->DissolveSrcMem();
00482
00483 m_notifier->NotifyFlush( op );
00484 }