src/Sim/Pipeline/Scheduler/Scheduler.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 // Scheduler
00033 // This class schedules ops on processor back-end stages.
00034 // (from wakeup/select to write back).
00035 
00036 #include <pch.h>
00037 
00038 #include "Sim/Pipeline/Scheduler/Scheduler.h"
00039 
00040 #include "Env/Env.h"
00041 #include "Sim/Dumper/Dumper.h"
00042 
00043 #include "Sim/Pipeline/Scheduler/IssueEvent.h"
00044 #include "Sim/Pipeline/Scheduler/WakeUpEvent.h"
00045 #include "Sim/Pipeline/Scheduler/ExecuteEvent.h"
00046 #include "Sim/Pipeline/Scheduler/RescheduleEvent.h"
00047 #include "Sim/Pipeline/Scheduler/WriteBackEvent.h"
00048 #include "Sim/Pipeline/Scheduler/IssueState.h"
00049 #include "Sim/Pipeline/Scheduler/DumpCommittableEvent.h"
00050 #include "Sim/Pipeline/Scheduler/DumpSchedulingEvent.h"
00051 #include "Sim/Pipeline/Scheduler/IssueSelector/IssueSelectorIF.h"
00052 
00053 #include "Sim/Core/Core.h"
00054 #include "Sim/Predictor/LatPred/LatPredResult.h"
00055 #include "Sim/ExecUnit/ExecUnitIF.h"
00056 
00057 #include "Sim/ExecUnit/ExecLatencyInfo.h"
00058 #include "Sim/Register/RegisterFile.h"
00059 #include "Sim/Op/Op.h"
00060 #include "Sim/Core/DataPredTypes.h"
00061 
00062 #include "Sim/Foundation/Hook/HookUtil.h"
00063 
00064 using namespace std;
00065 using namespace boost;
00066 using namespace Onikiri;
00067 
00068 namespace Onikiri 
00069 {
00070     HookPoint<Scheduler> Scheduler::s_dispatchedHook;
00071     HookPoint<Scheduler> Scheduler::s_readySigHook;
00072     HookPoint<Scheduler> Scheduler::s_wakeUpHook;
00073     HookPoint<Scheduler> Scheduler::s_selectHook;
00074     HookPoint<Scheduler> Scheduler::s_issueHook;
00075     HookPoint<Scheduler, Scheduler::RescheduleHookParam> Scheduler::s_rescheduleHook;
00076 };  // namespace Onikiri
00077 
00078 
00079 Scheduler::Scheduler() :
00080     m_index(0),
00081     m_issueWidth(0),
00082     m_issueLatency(0),
00083     m_communicationLatency(0),
00084     m_windowCapacity(0),
00085     m_loadPipelineModel( LPM_INVALID ),
00086     m_removePolicyParam( RP_FOLLOW_CORE ),
00087     m_removePolicy( RP_FOLLOW_CORE ),
00088     m_selector( NULL )
00089 {
00090 }
00091 
00092 Scheduler::~Scheduler()
00093 {
00094     ReleaseParam();
00095 }
00096 
00097 void Scheduler::Initialize(InitPhase phase)
00098 {
00099     // NX
00100     BaseType::Initialize(phase);
00101 
00102     if(phase == INIT_PRE_CONNECTION){
00103         LoadParam();
00104     }
00105     else if(phase == INIT_POST_CONNECTION){
00106 
00107         CheckNodeInitialized( "selector", m_selector );
00108 
00109         // OpList 
00110         OpArray* opArray = GetCore()->GetOpArray();
00111         m_notReadyOp.resize( *opArray );
00112         m_readyOp.resize( *opArray );
00113         m_issuedOp.resize( *opArray );
00114 
00115         AddChild( &m_issuedOp );
00116 
00117         // Dumping stall is done on buffers.
00118         GetLowerPipeline()->EnableDumpStall( false );
00119         //m_latch.EnableDumpStall( false );
00120 
00121         // Initialize code map
00122         for( size_t i = 0; i < m_execUnit.size(); i++){
00123             int codeCount = m_execUnit[i]->GetMappedCodeCount();
00124 
00125             for(int j = 0; j < codeCount; j++){
00126                 int code = m_execUnit[i]->GetMappedCode( j );
00127             
00128                 // code CfbNXg
00129                 if((int)m_execUnitCodeMap.size() <= code)
00130                     m_execUnitCodeMap.resize(code + 1);
00131 
00132                 ASSERT( m_execUnitCodeMap[code] == 0, "execUnit set twice(code:%d).", code);
00133                 m_execUnitCodeMap[code] = m_execUnit[i];
00134             }
00135         }
00136 
00137         // Initialize scheduler cluster
00138         int numScheduler = GetCore()->GetNumScheduler();
00139         m_clusters.resize( numScheduler );
00140         for( int i = 0; i < numScheduler; i++ ){
00141             Cluster* cluster = &m_clusters[i];
00142             cluster->communicationLatency = m_communicationLatency[i];
00143             cluster->scheduler      = GetCore()->GetScheduler(i);
00144             cluster->issueLatency   = cluster->scheduler->GetIssueLatency();
00145         }
00146 
00147         m_loadPipelineModel = GetCore()->GetLoadPipelineModel();
00148         
00149         if( m_removePolicyParam == RP_FOLLOW_CORE ){
00150             m_removePolicy = GetCore()->GetSchedulerRemovePolicy();
00151         }
00152         else{
00153             m_removePolicy = m_removePolicyParam;
00154         }
00155 
00156         // Push all data prediction policies.
00157         typedef vector< const DataPredMissRecovery * > Preds;
00158         Preds preds;
00159         preds.push_back( &GetCore()->GetAddrPredMissRecovery() );
00160         preds.push_back( &GetCore()->GetLatPredMissRecovery() );
00161         preds.push_back( &GetCore()->GetValuePredMissRecovery() );
00162         preds.push_back( &GetCore()->GetPartialLoadRecovery() );
00163 
00164         // Check data prediction policies.
00165         if( m_removePolicy == RP_REMOVE ) {
00166             for( Preds::iterator i = preds.begin(); i != preds.end(); ++i ){
00167                 if( !(*i)->IsRefetch() ){
00168                     THROW_RUNTIME_ERROR( "'Remove' scheduler only supports 'Refetch'." );
00169                 }
00170             }
00171         }
00172         if( m_removePolicy == RP_REMOVE_AFTER_FINISH ) {
00173             for( Preds::iterator i = preds.begin(); i != preds.end(); ++i ){
00174                 if( !( (*i)->IsRefetch() || (*i)->IsReissueNotFinished() || (*i)->IsReissueSelective() ) ){
00175                     THROW_RUNTIME_ERROR(
00176                         "'RemoveAfterFinish' scheduler only supports"
00177                         "'Refetch' or 'ReissueNotFinished' or 'ReissueSelective'." 
00178                     );
00179                 }
00180             }
00181         }
00182 
00183         // communication latency `FbN
00184         if( static_cast<int>(m_communicationLatency.size()) != GetCore()->GetNumScheduler() ) {
00185             THROW_RUNTIME_ERROR("communication latency count != scheduler count");
00186         }
00187     }
00188 
00189 }
00190 
00191 void Scheduler::SetExecUnit( PhysicalResourceArray<ExecUnitIF>& execUnit )
00192 {
00193     // o^
00194     if( find(m_execUnit.begin(), m_execUnit.end(), execUnit[0]) != m_execUnit.end() ){
00195         THROW_RUNTIME_ERROR("Same exec unit is set twice");
00196     }
00197     m_execUnit.push_back( execUnit[0] );
00198 }
00199 
00200 // code ExecUnit
00201 ExecUnitIF* Scheduler::GetExecUnit(int code)
00202 {
00203     ASSERT(code >= 0 && code < static_cast<int>(m_execUnitCodeMap.size()),
00204         "unknown code %d.", code);
00205 
00206     ASSERT(m_execUnitCodeMap[code] != 0, "no unit (code = %d).", code);
00207 
00208     return m_execUnitCodeMap[code];
00209 }
00210 
00211 
00212 void Scheduler::Begin()
00213 {
00214     ASSERT( m_latch.size() == 0, "The latch is received ops from dispatcher." );
00215 
00216     // WakeupEvent::Evaluate() is triggered before Scheduler::Evaluate(),
00217     // thus clearing evaluated context is done before an evaluation phase.
00218     ClearEvaluated();
00219 
00220     // Call Begin() handlers of execution units.
00221     typedef std::vector<ExecUnitIF*>::iterator iterator;
00222     for( iterator i = m_execUnit.begin(); i != m_execUnit.end(); ++i ){
00223         (*i)->Begin();
00224     }
00225 
00226     BaseType::Begin();
00227 }
00228 
00229 void Scheduler::Evaluate()
00230 {
00231     EvaluateWakeUp();   // Wake up
00232     EvaluateSelect();   // Select
00233     BaseType::Evaluate();
00234 }
00235 
00236 void Scheduler::Transition()
00237 {
00238     BaseType::Transition();
00239 
00240     // On a stalled cycle, evaluated results must be cleared, because
00241     // the evaluated results may incorrectly set dispatched ops ready.
00242     if( IsStalledThisCycle() ){
00243         ClearEvaluated();
00244     }
00245 }
00246 void Scheduler::Update()
00247 {
00248     UpdateWakeUp();     // Wake up
00249     UpdateSelect();     // Select
00250 
00251     // Call Update() handlers of execution units.
00252     typedef std::vector<ExecUnitIF*>::iterator iterator;
00253     for( iterator i = m_execUnit.begin(); i != m_execUnit.end(); ++i ){
00254         (*i)->Update();
00255     }
00256 }
00257 
00258 
00259 void Scheduler::Commit( OpIterator op )
00260 {
00261     if( !op->IsDispatched() ){
00262         return;
00263     }
00264 
00265 #ifdef ONIKIRI_DEBUG
00266     ASSERT(
00267         op->GetScheduler() == this,
00268         "The op does not belong to this scheduler" 
00269     );
00270 
00271     if( m_loadPipelineModel == LPM_SINGLE_ISSUE ){
00272         ASSERT(
00273             m_issuedOp.count(op) > 0,
00274             "Attempted to commit a not issued op. %s", op->ToString(5).c_str()
00275         );
00276     }
00277     else{
00278         ASSERT(
00279             op->GetStatus() > OpStatus::OS_ISSUING,
00280             "Attempted to commit a not issued op. %s", op->ToString(5).c_str()
00281         );
00282     }
00283 #endif
00284 }
00285 
00286 void Scheduler::Flush( OpIterator op )
00287 {
00288     BaseType::Flush( op );
00289     Delete( op );
00290 }
00291 
00292 void Scheduler::Retire( OpIterator op )
00293 {
00294     BaseType::Retire( op );
00295     Delete( op );
00296 }
00297 
00298 void Scheduler::Delete( OpIterator op )
00299 {
00300     OpStatus status = op->GetStatus();
00301     if( status < OpStatus::OS_DISPATCHING ){
00302         // The status of ops in m_dispatchedOp is OS_DISPATCHING.
00303         return;
00304     }
00305 
00306     ASSERT(
00307         op->GetScheduler() == this,
00308         "The op does not belong to this scheduler" 
00309     );
00310 
00311     if( m_issuedOp.find_and_erase(op) ){
00312         return;
00313     }
00314     else if( m_readyOp.find_and_erase(op) ) {
00315         return;
00316     }
00317     else if( m_notReadyOp.find_and_erase(op) ) {
00318         return;
00319     }
00320 
00321     //THROW_RUNTIME_ERROR("The op not found in this scheduler");
00322 }
00323 
00324 // Cancel
00325 void Scheduler::Cancel( OpIterator op )
00326 {
00327     int dstDepNum = op->GetDstDepNum();
00328     for( int i = 0; i < dstDepNum; ++i ){
00329         Dependency* dep = op->GetDstDep( i );
00330         for( DependencySet::iterator d = m_evaluated.deps.begin(); d != m_evaluated.deps.end();  ){
00331             if( *d == dep ){
00332                 d = m_evaluated.deps.erase( d );
00333             }
00334             else{
00335                 ++d;
00336             }
00337         }
00338     }
00339     for( SchedulingOps::iterator i = m_evaluated.selected.begin(); i != m_evaluated.selected.end();  ){
00340         if( *i == op ){
00341             i = m_evaluated.selected.erase( i );
00342         }
00343         else{
00344             ++i;
00345         }
00346     }
00347     for( SchedulingOps::iterator i = m_evaluated.wokeUp.begin(); i != m_evaluated.wokeUp.end();  ){
00348         if( *i == op ){
00349             i = m_evaluated.wokeUp.erase( i );
00350         }
00351         else{
00352             ++i;
00353         }
00354     }
00355 }
00356 
00357 // dispatch op 
00358 void Scheduler::ExitUpperPipeline( OpIterator op )
00359 {
00360     HookEntry(
00361         this,
00362         &Scheduler::DispatchEnd,
00363         &s_dispatchedHook,
00364         op
00365     );
00366 
00367     // Do not call the PipelineNodeBase::ExitUpperPipeline becasue
00368     // the op is pushed to a latch in the ExitUpperPipeline.
00369     //
00370     // Dispatchers dispatch ops to schedulers not depending on the 
00371     // stall of the schedulers, but the free space of those.
00372     // When a scheduler is stalled, its latch cannot receive ops 
00373     // and assertion fails. Thus a scheduler receives ops to m_dispatchedOp.
00374 }
00375 
00376 void Scheduler::EvaluateDependency( OpIterator producer )
00377 {
00378     ASSERT( GetCurrentPhase() == PHASE_EVALUATE );
00379 
00380     int dstDepNum = producer->GetDstDepNum();
00381 
00382     for( int i = 0; i < dstDepNum; ++i ){
00383         Dependency* dep = producer->GetDstDep( i );
00384         const Dependency::ConsumerListType& consumers = dep->GetConsumers();
00385         typedef Dependency::ConsumerListType::const_iterator ConsumerListIterator;
00386         for( ConsumerListIterator c = consumers.begin(); c != consumers.end(); ++c ){
00387             g_dumper.DumpOpDependency( producer, *c );
00388         }
00389         m_evaluated.deps.push_back( dep );
00390     }
00391 }
00392 
00393 // Register wakeup events for waking up consumers of 'op'
00394 // Note: 'latencyFromOp' does not specifies latency from now but
00395 // latency between a producer and consumers.
00396 void Scheduler::RegisterWakeUpEvent( OpIterator op, int latencyFromOp )
00397 {
00398     int numScheduler = (int)m_clusters.size();
00399     for(int i = 0; i < numScheduler; ++i) {
00400         Cluster* cluster = &m_clusters[i];
00401         
00402         // communication latency  -1  wakeup 
00403         int comLatency = cluster->communicationLatency;
00404         if (comLatency == -1) 
00405             continue;
00406 
00407         Scheduler* targetScheduler = cluster->scheduler;
00408         Pipeline* targetPipeline   = targetScheduler->GetLowerPipeline();
00409         int targetIssueLatency     = cluster->issueLatency;
00410 
00411         // back to back タsAScheduler  issue latency l
00412         // Awakeup  communication latency 
00413         int wakeupLatency = latencyFromOp + m_issueLatency - targetIssueLatency;
00414         if( wakeupLatency < comLatency ){
00415             wakeupLatency = comLatency;
00416         }
00417 
00418         op->AddEvent(
00419             OpWakeUpEvent::Construct(
00420                 targetScheduler,
00421                 op
00422             ), 
00423             targetPipeline,
00424             wakeupLatency,
00425             Op::EVENT_MASK_WAKEUP_RELATED
00426         );
00427     }
00428 }
00429 
00430 
00431 //
00432 // Issue
00433 //
00434 void Scheduler::IssueBody(OpIterator op)
00435 {
00436     IssueState state = op->GetIssueState();
00437     if( op->GetStatus() >= OpStatus::OS_ISSUING && state.multiIssue ){
00438     }
00439     else{
00440         // status  ISSUED 
00441         op->SetStatus( OpStatus::OS_ISSUING );
00442     }
00443 
00444 #ifdef ONIKIRI_DEBUG
00445     if(op->GetScheduler() != this) {
00446         THROW_RUNTIME_ERROR("issued an unknown op.");
00447     }
00448     if( !m_issuedOp.count(op) ) {
00449         if( m_notReadyOp.count(op) ) {
00450             THROW_RUNTIME_ERROR("issued not ready op\t%s\n", op->ToString().c_str());
00451         }else if( m_readyOp.count(op) ) {
00452             THROW_RUNTIME_ERROR("issued already not selected op\t%s\n", op->ToString().c_str());
00453         }else {
00454             THROW_RUNTIME_ERROR("issued ? op.");
00455         }
00456     }
00457 #endif
00458 
00459     g_dumper.Dump(DS_ISSUE, op);
00460 }
00461 
00462 void Scheduler::Issue(OpIterator op)
00463 {
00464     HookEntry(
00465         this,
00466         &Scheduler::IssueBody,
00467         &s_issueHook,
00468         op
00469     );
00470 }
00471 
00472 //
00473 // Finish
00474 //
00475 void Scheduler::Finished( OpIterator op )
00476 {
00477     // Cancel all wake up related events and wake up consumers immediately.
00478     op->CancelEvent( Op::EVENT_MASK_WAKEUP_RELATED );
00479 
00480 #if 0
00481     RegisterWakeUpEvent( op, 1 );
00482 #else
00483 
00484     bool needWakeup = false;
00485 
00486     int dstDepNum = op->GetDstDepNum();
00487     for( int i = 0; i < dstDepNum; ++i ){
00488         if( !op->GetDstDep(i)->IsFullyReady() ){
00489             needWakeup = true;
00490             break;
00491         }
00492     }
00493 
00494     if( needWakeup ){
00495         RegisterWakeUpEvent( op, 1 );
00496     }
00497 
00498 #endif
00499     
00500     // Register a register write back event.
00501     op->AddEvent( 
00502         OpWriteBackEvent::Construct( op, this, true /*wbBegin*/ ),
00503         GetLowerPipeline(), 
00504         1   // latency
00505     );
00506 }
00507 
00508 // Write Back
00509 void Scheduler::WriteBackBegin( OpIterator op )
00510 {
00511     op->SetStatus( OpStatus::OS_WRITING_BACK );
00512     g_dumper.Dump( DS_WRITEBACK, op );
00513 
00514     op->AddEvent( 
00515         OpWriteBackEvent::Construct( op, this, false    /*wbBegin*/ ),
00516         GetLowerPipeline(), 
00517         m_writeBackLatency - 1      // latency
00518                                     // -1 corresponds this cycle.
00519     );
00520 }
00521 
00522 void Scheduler::WriteBackEnd( OpIterator op )
00523 {
00524     op->SetStatus( OpStatus::OS_WRITTEN_BACK );
00525     if( g_dumper.IsEnabled() ){
00526         op->AddEvent( OpDumpCommittableEvent::Construct( op ), GetLowerPipeline(), 1 );
00527     }
00528 }
00529 
00530 //
00531 // Reschedule
00532 //
00533 bool Scheduler::Reschedule( OpIterator op )
00534 {
00535     if( !op->IsDispatched() ){
00536         return false;
00537     }
00538 
00539 
00540     RescheduleHookParam param;
00541     param.canceled = false;
00542 
00543     ASSERT(
00544         op->GetScheduler() == this,
00545         "rescheduled an unknown op."
00546     );
00547 
00548     HOOK_SECTION_OP_PARAM( s_rescheduleHook, op, param )
00549     {
00550         // XPW[O|V[
00551 
00552         bool clearIssueState = m_loadPipelineModel == LPM_SINGLE_ISSUE;
00553         op->RescheduleSelf( clearIssueState );
00554 
00555         // Cancel 
00556         Cancel( op );
00557 
00558         param.canceled = false;
00559         if( m_issuedOp.find_and_erase(op) ) {
00560             // sXPW[O
00561 
00562             if(op->IsSrcReady(GetIndex())) {
00563                 m_readyOp.push_inorder(op);
00564             }
00565             else {
00566                 m_notReadyOp.push_back(op);
00567             }
00568             param.canceled = true;
00569         }
00570         else if (m_readyOp.count(op)) {
00571             // sOreadyXPW[O
00572             if( !op->IsSrcReady(GetIndex()) ) {
00573                 m_readyOp.erase(op);
00574                 m_notReadyOp.push_back(op);
00575             }
00576         }
00577         else {
00578             // not ready XPW[O 
00579         }
00580 
00581         op->SetStatus(OpStatus::OS_DISPATCHED);
00582         g_dumper.Dump(DS_RESCHEDULE, op);
00583     }
00584     return param.canceled;
00585 }
00586 
00587 
00588 // Return whether a scheduler can dispatch 'ops' or not.
00589 bool Scheduler::CanAllocate( int ops )
00590 {
00591     return ( GetOpCount() + ops ) <= m_windowCapacity;
00592 }
00593 
00594 // Clear evaluated conctext.
00595 void Scheduler::ClearEvaluated()
00596 {
00597     m_evaluated.deps.clear();
00598     m_evaluated.selected.clear();
00599     m_evaluated.wokeUp.clear();
00600 }
00601 
00602 // dispatch  op 
00603 void Scheduler::DispatchEnd( OpIterator op )
00604 {
00605     if( GetOpCount() >= m_windowCapacity ) {
00606         THROW_RUNTIME_ERROR("scheduler cannot receive");
00607     }
00608 
00609     //  ready 
00610     if( op->IsSrcReady( GetIndex(), &m_evaluated.deps ) ) {
00611         m_readyOp.push_inorder(op);
00612     }
00613     else {
00614         m_notReadyOp.push_back(op);
00615     }
00616 
00617     op->SetStatus( OpStatus::OS_DISPATCHED );
00618     if( g_dumper.IsEnabled() ){
00619         op->AddEvent( OpDumpSchedulingEvent::Construct( op ), GetLowerPipeline(), 1 );
00620     }
00621 }
00622 
00623 
00624 //
00625 // --- wake up
00626 // 
00627 
00628 void Scheduler::CheckOnWakeUp(OpIterator op)
00629 {
00630 #ifdef ONIKIRI_DEBUG
00631     if(!op->IsDispatched()){
00632         THROW_RUNTIME_ERROR("woke up an op that is not dipatched.");
00633     }
00634     if(op->GetScheduler() != this) {
00635         THROW_RUNTIME_ERROR("woke up an unknown op.");
00636     }
00637     
00638     if (m_readyOp.count(op)) {
00639         THROW_RUNTIME_ERROR("woke up a ready op\t%s\n", op->ToString().c_str());
00640     }
00641     else if (m_issuedOp.count(op)) {
00642         THROW_RUNTIME_ERROR("woke up an issued op\t%s\n", op->ToString().c_str());
00643     }
00644     else if (!m_notReadyOp.count(op)) {
00645         THROW_RUNTIME_ERROR("woke up an unknown op.");
00646     }
00647 
00648 #endif
00649 
00650 }
00651 
00652 void Scheduler::EvaluateWakeUp()
00653 {
00654     DependencySet depSet;
00655     int index = GetIndex();
00656     for( DependencySet::iterator d = m_evaluated.deps.begin(); d != m_evaluated.deps.end(); ++d ){
00657         depSet.push_back( *d );
00658 
00659         const Dependency::ConsumerListType& consumers = (*d)->GetConsumers();
00660         typedef Dependency::ConsumerListType::const_iterator ConsumerListIterator;
00661 
00662         ConsumerListIterator end = consumers.end();
00663         for( ConsumerListIterator c = consumers.begin(); c != end; ++c ){
00664             OpIterator op = *c;
00665             if( op->IsDispatched() && 
00666                 op->GetScheduler()->GetIndex() == index &&
00667                 op->IsSrcReady( index, &depSet ) 
00668             ){
00669                 // A woke up op is determined.
00670                 m_evaluated.wokeUp.push_back( op );
00671             }
00672         }
00673     }
00674 }
00675 
00676 void Scheduler::UpdateWakeUp()
00677 {
00678     // Set a ready signal.
00679     for( DependencySet::iterator i = m_evaluated.deps.begin(); i != m_evaluated.deps.end(); ++i ){
00680         // Destination of a producer is set to ready.
00681         (*i)->SetReadiness( true, GetIndex() );
00682     }
00683 
00684     // Wakeup consumers.
00685     for( SchedulingOps::iterator i = m_evaluated.wokeUp.begin(); i != m_evaluated.wokeUp.end(); ++i ){
00686         WakeUp( *i );
00687     }
00688 }
00689 
00690 void Scheduler::WakeUp(OpIterator op)
00691 {
00692     CheckOnWakeUp( op );
00693 
00694     HOOK_SECTION_OP( s_readySigHook, op ){
00695         g_dumper.Dump(DS_READY_SIG, op);
00696     }
00697 
00698     if( op->IsSrcReady(GetIndex()) ){
00699         HOOK_SECTION_OP( s_wakeUpHook, op ){
00700             g_dumper.Dump(DS_WAKEUP, op);
00701             m_notReadyOp.erase(op);
00702             m_readyOp.push_inorder(op);
00703         }
00704     }
00705 }
00706 
00707 
00708 //
00709 // --- Select
00710 //
00711 void Scheduler::EvaluateSelect()
00712 {
00713     m_selector->EvaluateSelect( this );
00714 }
00715 
00716 void Scheduler::UpdateSelect()
00717 {
00718     // Select and issue ops.
00719     for( SchedulingOps::iterator i = m_evaluated.selected.begin(); i != m_evaluated.selected.end(); ++i ){
00720         m_readyOp.erase( *i );
00721         m_issuedOp.push_back( *i );
00722         Select( *i );
00723     }
00724 }
00725 
00726 void Scheduler::SelectBody(OpIterator op)
00727 {
00728     // Reserve an execution unit.
00729     const LatPredResult& predResult = op->GetLatPredRsult();
00730     IssueState issueState = op->GetIssueState();
00731 
00732     if( m_loadPipelineModel == LPM_MULTI_ISSUE ){
00733         // Multi issue mode:
00734         // In a multi issue mode, ops are re-scheduled and issued 
00735         // when their consumers need to be waken-up, 
00736         // so always wakeup its consumer when an op is selected.
00737         issueState.multiIssue = true;
00738 
00739         const LatPredResult::Scheduling& sched = predResult.Get( 0 );
00740         if( (!issueState.issued && sched.wakeup) || issueState.issued ){
00741             // In case of second or later issue,
00742             // wakeup is always done at the earliest timing.
00743             RegisterWakeUpEvent( op, sched.latency );
00744         }
00745     }
00746     else{
00747         // Single issue mode:
00748         // In a single issue mode, register wakeup-events at all possible timings.
00749         issueState.multiIssue = false;
00750 
00751         int wakeups = predResult.GetCount();
00752         for( int i = 0; i < wakeups; i++ ){
00753             const LatPredResult::Scheduling& sched = predResult.Get( i );
00754             if( sched.wakeup ){
00755                 RegisterWakeUpEvent( op, sched.latency );
00756             }
00757         }
00758     }
00759     
00760     // Register an issue event at the next cycle.
00761     EventPtr issueEvent( OpIssueEvent::Construct( op ) );
00762     op->AddEvent(issueEvent, GetLowerPipeline(), 1 );
00763 
00764     // Register an execution event after an issue latency + 1(for select<>issue time).
00765     RegisterExecuteEvent( op, m_issueLatency + 1 );
00766 
00767     // Update issue state.
00768     issueState.issued = true;
00769     op->SetIssueState( issueState );
00770 
00771     g_dumper.Dump( DS_SELECT, op );
00772 
00773 }
00774 
00775 void Scheduler::Select(OpIterator op)
00776 {
00777     HookEntry(
00778         this,
00779         &Scheduler::SelectBody,
00780         &s_selectHook,
00781         op
00782     );
00783 }
00784 
00785 // Returns whether 'op' can be selected in this cycle.
00786 // This method must be called only in a 'Evaluate' phase.
00787 bool Scheduler::CanSelect( OpIterator op )
00788 {
00789     ASSERT( GetCurrentPhase() == PHASE_EVALUATE );
00790     // Check whether execution units can be reserved or not after the latency of issue.
00791     // +1 is for the first execution stage.
00792     return op->GetExecUnit()->CanReserve( op, m_issueLatency + 1 );
00793 }
00794 
00795 // Reserves 'op' to select in this cycle.
00796 // This method must be called only in a 'Evaluate' phase.
00797 void Scheduler::ReserveSelect( OpIterator op )
00798 {
00799     ASSERT( GetCurrentPhase() == PHASE_EVALUATE );
00800     op->GetExecUnit()->Reserve( op, m_issueLatency + 1 );   // +1 is for the first execution stage.
00801     m_evaluated.selected.push_back( op );
00802 }
00803 
00804 
00805 int Scheduler::GetOpCount()
00806 {
00807     int size = static_cast<int>( m_notReadyOp.size() + m_readyOp.size() );
00808     if( m_removePolicy == RP_RETAIN ) {
00809         size += static_cast<int>( m_issuedOp.size() );
00810     }
00811     else if( m_removePolicy == RP_REMOVE_AFTER_FINISH ){
00812         for( OpBuffer::iterator i = m_issuedOp.begin(); i != m_issuedOp.end(); ++i ){
00813             OpIterator op = *i;
00814             if( op->GetStatus() <= OpStatus::OS_EXECUTING ){
00815                 size++;
00816             }
00817         }
00818     }
00819     return size;
00820 }
00821 
00822 bool Scheduler::IsInScheduler( OpIterator op )
00823 {
00824     bool isInSched = (m_notReadyOp.count(op) || m_readyOp.count(op));
00825     if( m_removePolicy == RP_RETAIN ) {
00826         isInSched = (isInSched || m_issuedOp.count(op));
00827     }
00828     else if( m_removePolicy == RP_REMOVE_AFTER_FINISH ){
00829         if( op->GetStatus() <= OpStatus::OS_EXECUTING ){
00830             isInSched = (isInSched || m_issuedOp.count(op));
00831         }
00832     }
00833     return isInSched;
00834 }
00835 
00836 // Register execute events for 'op'.
00837 // Note: 'latencyFromNow' specifies latency from now.
00838 void Scheduler::RegisterExecuteEvent( OpIterator op, int latencyFromNow )
00839 {
00840     op->AddEvent(
00841         OpExecuteEvent::Construct( op ),
00842         GetLowerPipeline(), 
00843         latencyFromNow
00844     );
00845 }

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