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/Pipeline/Dispatcher/Dispatcher.h"
00035
00036 #include "Sim/Dumper/Dumper.h"
00037 #include "Sim/Foundation/Hook/HookUtil.h"
00038 #include "Sim/Op/Op.h"
00039 #include "Sim/Pipeline/Scheduler/Scheduler.h"
00040 #include "Sim/Core/Core.h"
00041
00042 using namespace std;
00043 using namespace boost;
00044 using namespace Onikiri;
00045
00046 namespace Onikiri
00047 {
00048 HookPoint<Dispatcher, Dispatcher::DispatchHookParam> Dispatcher::s_dispatchEvaluateHook;
00049 HookPoint<Dispatcher, Dispatcher::DispatchHookParam> Dispatcher::s_dispatchUpdateHook;
00050 };
00051
00052 Dispatcher::SchedulerInfo::SchedulerInfo() :
00053 index(0),
00054 saturateCount(0),
00055 scheduler(0),
00056 numDispatchedOps(0)
00057 {
00058 }
00059
00060
00061 Dispatcher::Dispatcher() :
00062 m_dispatchLatency(0)
00063 {
00064 }
00065
00066 Dispatcher::~Dispatcher()
00067 {
00068 }
00069
00070 void Dispatcher::Initialize( InitPhase phase )
00071 {
00072 PipelineNodeBase::Initialize( phase );
00073
00074 if( phase == INIT_PRE_CONNECTION ){
00075 LoadParam();
00076 }
00077 else if( phase == INIT_POST_CONNECTION ){
00078
00079
00080 m_numScheduler = GetCore()->GetNumScheduler();
00081 if( MAX_SCHEDULER_NUM < m_numScheduler ){
00082 THROW_RUNTIME_ERROR(
00083 "The number of schedulers is greater than MAX_SCHEDULER_NUM."
00084 );
00085 }
00086
00087 ASSERT( m_schedInfo.size() == 0 );
00088 m_schedInfo.resize( m_numScheduler );
00089
00090 for( int i = 0; i < m_numScheduler; ++i ){
00091 Scheduler* sched = GetCore()->GetScheduler(i);
00092 int index = sched->GetIndex();
00093 ASSERT( i == index, "Mismatched scheduler's indeces." );
00094
00095 m_schedInfo[i].index = index;
00096 m_schedInfo[i].scheduler = sched;
00097 m_schedInfo[i].dispatchingOps.resize( *GetCore()->GetOpArray() );
00098 }
00099
00100
00101
00102 LoadParam();
00103
00104
00105 if ( m_dispatchLatency == 0 ) {
00106 THROW_RUNTIME_ERROR( "A dispatch latency must be more than 0." );
00107 }
00108 }
00109 }
00110
00111 void Dispatcher::Finalize()
00112 {
00113 m_stallCylcles.clear();
00114 for( vector< SchedulerInfo >::iterator i = m_schedInfo.begin(); i != m_schedInfo.end(); ++i ){
00115 m_stallCylcles.push_back( i->saturateCount );
00116 m_schedulerName.push_back( i->scheduler->GetName() );
00117 m_numDispatchedOps.push_back( i->numDispatchedOps );
00118 }
00119
00120 ReleaseParam();
00121 }
00122
00123 Dispatcher::SchedulerInfo* Dispatcher::GetSchedulerInfo( OpIterator op )
00124 {
00125 Scheduler* sched = op->GetScheduler();
00126 int index = sched->GetIndex();
00127 return &m_schedInfo[index];
00128 }
00129
00130 void Dispatcher::Evaluate()
00131 {
00132 BaseType::Evaluate();
00133
00134
00135
00136 DispatchingOpNums dispatchingOps;
00137 for( int i = 0; i < m_numScheduler; i++ ){
00138 dispatchingOps.push_back( (int)m_schedInfo[i].dispatchingOps.size() );
00139 }
00140
00141 DispatchHookParam hookParam;
00142 hookParam.dispatchingOps = &dispatchingOps;
00143 for( PipelineLatch::iterator i = m_latch.begin(); i != m_latch.end(); ++i ){
00144
00145 hookParam.dispatch = true;
00146 HOOK_SECTION_OP_PARAM( s_dispatchEvaluateHook, *i, hookParam ){
00147 if( hookParam.dispatch ){
00148 dispatchingOps[ (*i)->GetScheduler()->GetIndex() ]++;
00149 }
00150 }
00151 }
00152
00153
00154 bool stall = false;
00155 for( int i = 0; i < m_numScheduler; i++ ){
00156 if( !m_schedInfo[i].scheduler->CanAllocate( dispatchingOps[i] ) ){
00157 stall = true;
00158 m_schedInfo[i].saturateCount++;
00159 }
00160 }
00161
00162 if( stall ){
00163
00164
00165
00166 StallThisNodeAndUpperThisCycle();
00167 }
00168 }
00169
00170 void Dispatcher::Dispatch( OpIterator op )
00171 {
00172 SchedulerInfo* schd = GetSchedulerInfo(op);
00173 op->SetStatus( OpStatus::OS_DISPATCHING );
00174 schd->dispatchingOps.push_back( op );
00175
00176 GetLowerPipeline()->EnterPipeline(
00177 op, m_dispatchLatency - 1, op->GetScheduler()
00178 );
00179 schd->numDispatchedOps++;
00180 g_dumper.Dump( DS_DISPATCH, op );
00181 }
00182
00183
00184 void Dispatcher::Update()
00185 {
00186
00187 DispatchingOpNums dispatchingOps;
00188 for( int i = 0; i < m_numScheduler; i++ ){
00189 dispatchingOps.push_back( (int)m_schedInfo[i].dispatchingOps.size() );
00190 }
00191 DispatchHookParam hookParam;
00192 hookParam.dispatchingOps = &dispatchingOps;
00193
00194 for( PipelineLatch::iterator i = m_latch.begin();
00195 i != m_latch.end();
00196
00197 ){
00198 OpIterator op = *i;
00199 hookParam.dispatch = true;
00200 HOOK_SECTION_OP_PARAM( s_dispatchUpdateHook, op, hookParam ){
00201 if( hookParam.dispatch ){
00202 Dispatch( op );
00203 }
00204 }
00205 i = m_latch.erase( i );
00206 }
00207 }
00208
00209
00210 void Dispatcher::ExitLowerPipeline( OpIterator op )
00211 {
00212 SchedulerInfo* schd = GetSchedulerInfo( op );
00213 schd->dispatchingOps.find_and_erase( op );
00214 }
00215
00216 void Dispatcher::Retire( OpIterator op )
00217 {
00218 PipelineNodeBase::Retire( op );
00219 Delete( op, false );
00220 }
00221
00222 void Dispatcher::Flush( OpIterator op )
00223 {
00224 PipelineNodeBase::Flush( op );
00225 Delete( op, true );
00226 }
00227
00228 void Dispatcher::Delete( OpIterator op, bool flush )
00229 {
00230
00231 if( op->GetStatus() < OpStatus::OS_DISPATCHING ||
00232 op->GetStatus() > OpStatus::OS_DISPATCHED
00233 ){
00234 return;
00235 }
00236
00237 SchedulerInfo* schd = GetSchedulerInfo( op );
00238 schd->dispatchingOps.find_and_erase( op );
00239 }