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 #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 };
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
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
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
00118 GetLowerPipeline()->EnableDumpStall( false );
00119
00120
00121
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
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
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
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
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
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
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
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
00217
00218 ClearEvaluated();
00219
00220
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();
00232 EvaluateSelect();
00233 BaseType::Evaluate();
00234 }
00235
00236 void Scheduler::Transition()
00237 {
00238 BaseType::Transition();
00239
00240
00241
00242 if( IsStalledThisCycle() ){
00243 ClearEvaluated();
00244 }
00245 }
00246 void Scheduler::Update()
00247 {
00248 UpdateWakeUp();
00249 UpdateSelect();
00250
00251
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
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
00322 }
00323
00324
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
00358 void Scheduler::ExitUpperPipeline( OpIterator op )
00359 {
00360 HookEntry(
00361 this,
00362 &Scheduler::DispatchEnd,
00363 &s_dispatchedHook,
00364 op
00365 );
00366
00367
00368
00369
00370
00371
00372
00373
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
00394
00395
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
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
00412
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
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
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
00474
00475 void Scheduler::Finished( OpIterator op )
00476 {
00477
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
00501 op->AddEvent(
00502 OpWriteBackEvent::Construct( op, this, true ),
00503 GetLowerPipeline(),
00504 1
00505 );
00506 }
00507
00508
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 ),
00516 GetLowerPipeline(),
00517 m_writeBackLatency - 1
00518
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
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
00551
00552 bool clearIssueState = m_loadPipelineModel == LPM_SINGLE_ISSUE;
00553 op->RescheduleSelf( clearIssueState );
00554
00555
00556 Cancel( op );
00557
00558 param.canceled = false;
00559 if( m_issuedOp.find_and_erase(op) ) {
00560
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
00572 if( !op->IsSrcReady(GetIndex()) ) {
00573 m_readyOp.erase(op);
00574 m_notReadyOp.push_back(op);
00575 }
00576 }
00577 else {
00578
00579 }
00580
00581 op->SetStatus(OpStatus::OS_DISPATCHED);
00582 g_dumper.Dump(DS_RESCHEDULE, op);
00583 }
00584 return param.canceled;
00585 }
00586
00587
00588
00589 bool Scheduler::CanAllocate( int ops )
00590 {
00591 return ( GetOpCount() + ops ) <= m_windowCapacity;
00592 }
00593
00594
00595 void Scheduler::ClearEvaluated()
00596 {
00597 m_evaluated.deps.clear();
00598 m_evaluated.selected.clear();
00599 m_evaluated.wokeUp.clear();
00600 }
00601
00602
00603 void Scheduler::DispatchEnd( OpIterator op )
00604 {
00605 if( GetOpCount() >= m_windowCapacity ) {
00606 THROW_RUNTIME_ERROR("scheduler cannot receive");
00607 }
00608
00609
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
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
00670 m_evaluated.wokeUp.push_back( op );
00671 }
00672 }
00673 }
00674 }
00675
00676 void Scheduler::UpdateWakeUp()
00677 {
00678
00679 for( DependencySet::iterator i = m_evaluated.deps.begin(); i != m_evaluated.deps.end(); ++i ){
00680
00681 (*i)->SetReadiness( true, GetIndex() );
00682 }
00683
00684
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
00710
00711 void Scheduler::EvaluateSelect()
00712 {
00713 m_selector->EvaluateSelect( this );
00714 }
00715
00716 void Scheduler::UpdateSelect()
00717 {
00718
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
00729 const LatPredResult& predResult = op->GetLatPredRsult();
00730 IssueState issueState = op->GetIssueState();
00731
00732 if( m_loadPipelineModel == LPM_MULTI_ISSUE ){
00733
00734
00735
00736
00737 issueState.multiIssue = true;
00738
00739 const LatPredResult::Scheduling& sched = predResult.Get( 0 );
00740 if( (!issueState.issued && sched.wakeup) || issueState.issued ){
00741
00742
00743 RegisterWakeUpEvent( op, sched.latency );
00744 }
00745 }
00746 else{
00747
00748
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
00761 EventPtr issueEvent( OpIssueEvent::Construct( op ) );
00762 op->AddEvent(issueEvent, GetLowerPipeline(), 1 );
00763
00764
00765 RegisterExecuteEvent( op, m_issueLatency + 1 );
00766
00767
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
00786
00787 bool Scheduler::CanSelect( OpIterator op )
00788 {
00789 ASSERT( GetCurrentPhase() == PHASE_EVALUATE );
00790
00791
00792 return op->GetExecUnit()->CanReserve( op, m_issueLatency + 1 );
00793 }
00794
00795
00796
00797 void Scheduler::ReserveSelect( OpIterator op )
00798 {
00799 ASSERT( GetCurrentPhase() == PHASE_EVALUATE );
00800 op->GetExecUnit()->Reserve( op, m_issueLatency + 1 );
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
00837
00838 void Scheduler::RegisterExecuteEvent( OpIterator op, int latencyFromNow )
00839 {
00840 op->AddEvent(
00841 OpExecuteEvent::Construct( op ),
00842 GetLowerPipeline(),
00843 latencyFromNow
00844 );
00845 }