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/ExecUnit/ExecUnitBase.h"
00035
00036 #include "Sim/Op/Op.h"
00037 #include "Sim/Foundation/Hook/Hook.h"
00038 #include "Sim/Pipeline/Scheduler/Scheduler.h"
00039 #include "Sim/Pipeline/Scheduler/FinishEvent.h"
00040 #include "Sim/Pipeline/Scheduler/DetectLatPredMissEvent.h"
00041 #include "Sim/Pipeline/Pipeline.h"
00042 #include "Sim/ExecUnit/ExecLatencyInfo.h"
00043 #include "Sim/Dumper/Dumper.h"
00044 #include "Sim/Pipeline/Scheduler/RescheduleEvent.h"
00045 #include "Sim/Core/Core.h"
00046 #include "Sim/Predictor/LatPred/LatPred.h"
00047 #include "Sim/System/GlobalClock.h"
00048
00049 using namespace Onikiri;
00050 using namespace std;
00051
00052 ExecUnitBase::ExecUnitBase()
00053 {
00054 m_execLatencyInfo = 0;
00055 m_core = 0;
00056 m_numPorts = 0;
00057 m_numUsed = 0;
00058 m_numUsable = 0;
00059 }
00060
00061 ExecUnitBase::~ExecUnitBase()
00062 {
00063 }
00064
00065 void ExecUnitBase::Initialize( InitPhase phase )
00066 {
00067 if(phase == INIT_PRE_CONNECTION){
00068 LoadParam();
00069 for(size_t i = 0; i < m_codeStr.size(); i++){
00070 m_code.push_back( OpClassCode::FromString( m_codeStr[i] ) );
00071 }
00072 }
00073 else if(phase == INIT_POST_CONNECTION){
00074 CheckNodeInitialized( "execLatencyInfo", m_execLatencyInfo );
00075 CheckNodeInitialized( "core", m_core );
00076
00077 m_reserver.Initialize( m_numPorts, m_core->GetTimeWheelSize() );
00078 }
00079 }
00080
00081 void ExecUnitBase::Finalize()
00082 {
00083 if( m_core ){
00084 m_numUsable = m_core->GetGlobalClock()->GetTick() * m_numPorts;
00085 }
00086 ReleaseParam();
00087 }
00088
00089 int ExecUnitBase::GetMappedCode(int i)
00090 {
00091 if((int)m_code.size() <= i)
00092 THROW_RUNTIME_ERROR("invalid mapped code.");
00093 return m_code[i];
00094 }
00095
00096 int ExecUnitBase::GetMappedCodeCount()
00097 {
00098 return (int)m_code.size();
00099 }
00100
00101 void ExecUnitBase::Execute( OpIterator op )
00102 {
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 op->ExecutionBegin();
00113 g_dumper.Dump( DS_EXECUTE, op );
00114 op->SetStatus( OpStatus::OS_EXECUTING );
00115 }
00116
00117
00118 void ExecUnitBase::RegisterEvents( OpIterator op, const int latency )
00119 {
00120 IssueState issueState = op->GetIssueState();
00121
00122
00123
00124 if( !issueState.executionKicked ){
00125 issueState.executionKickedTime =
00126 op->GetScheduler()->GetLowerPipeline()->GetNow();
00127 issueState.executionLatency = latency;
00128 }
00129
00130 if( issueState.multiIssue ){
00131
00132 const LatPredResult::Scheduling& schd = op->GetLatPredRsult().Get(0);
00133 if( schd.latency == latency ){
00134 RegisterFinishEvent( op, latency );
00135 }
00136 else{
00137 RegisterRescheduleEvent( op, latency, &issueState );
00138 }
00139 }
00140 else{
00141
00142 if( issueState.executionKicked ){
00143 THROW_RUNTIME_ERROR( "An op is executed more than once." );
00144 }
00145 else{
00146 RegisterFinishEvent( op, latency );
00147 RegisterDetectEvent( op, latency );
00148 }
00149 }
00150
00151 issueState.executionKicked = true;
00152 op->SetIssueState( issueState );
00153
00154 }
00155
00156
00157 void ExecUnitBase::RegisterFinishEvent( OpIterator op, const int latency )
00158 {
00159
00160 EventPtr finishEvent(
00161 OpFinishEvent::Construct( op ));
00162
00163
00164 op->AddEvent(
00165 finishEvent,
00166 op->GetScheduler()->GetLowerPipeline(),
00167 latency - 1
00168 );
00169 }
00170
00171 void ExecUnitBase::RegisterDetectEvent( OpIterator op, const int latency )
00172 {
00173 const LatPredResult& predResult = op->GetLatPredRsult();
00174
00175
00176 Scheduler* scheduler = op->GetScheduler();
00177 int wakeups = predResult.GetCount();
00178 for( int i = 0; i < wakeups - 1; i++ ){
00179 const LatPredResult::Scheduling& sched = predResult.Get( i );
00180 if( sched.wakeup ){
00181
00182 EventPtr detectLatPredMiss(
00183 OpDetectLatPredMissEvent::Construct( op, 0, sched.latency, latency )
00184 );
00185 op->AddEvent(
00186 detectLatPredMiss,
00187 scheduler->GetLowerPipeline(),
00188 sched.latency - 1
00189 );
00190 }
00191 }
00192 }
00193
00194 void ExecUnitBase::RegisterRescheduleEvent( OpIterator op, const int latency, IssueState* issueState )
00195 {
00196 const LatPredResult::Scheduling& schd = op->GetLatPredRsult().Get(0);
00197 int minLatency = schd.latency;
00198
00199
00200 int elpasedTime = (int)( op->GetScheduler()->GetLowerPipeline()->GetNow() - issueState->executionKickedTime );
00201 int latencyOffset = op->GetScheduler()->GetIssueLatency() + 1 + minLatency;
00202
00203
00204 const LatPredResult& predResult = op->GetLatPredRsult();
00205 int wakeups = predResult.GetCount();
00206 int rsLatency = 0;
00207 bool speculative = false;
00208 for( int i = issueState->currentPredIndex + 1; i < wakeups; i++ ){
00209 const LatPredResult::Scheduling& sched = predResult.Get( i );
00210 if( sched.wakeup ){
00211 issueState->currentPredIndex = i;
00212 rsLatency = predResult.Get(i).latency - latencyOffset - elpasedTime;
00213 speculative = true;
00214 break;
00215 }
00216 }
00217
00218
00219 if( !speculative ){
00220 rsLatency = latency - latencyOffset;
00221 }
00222
00223 if( rsLatency < 1 ){
00224 rsLatency = 1;
00225 }
00226
00227
00228 if( (!issueState->executionKicked && schd.wakeup) ||
00229 issueState->executionKicked
00230 ){
00231
00232
00233 if( rsLatency < minLatency ){
00234 rsLatency = minLatency;
00235 }
00236
00237
00238
00239 EventPtr detectLatPredMiss(
00240 OpDetectLatPredMissEvent::Construct( op, 0, minLatency, latency )
00241 );
00242 op->AddEvent(
00243 detectLatPredMiss,
00244 op->GetScheduler()->GetLowerPipeline(),
00245 minLatency - 1
00246 );
00247 }
00248
00249
00250 EventPtr evnt(
00251 OpRescheduleEvent::Construct(op)
00252 );
00253 op->AddEvent( evnt, op->GetScheduler()->GetLowerPipeline(), rsLatency, Op::EVENT_MASK_WAKEUP_RELATED );
00254
00255
00256
00257
00258
00259 }
00260
00261
00262 int ExecUnitBase::GetLatencyCount(const OpClass& opClass)
00263 {
00264
00265 return 1;
00266 }
00267
00268
00269 int ExecUnitBase::GetLatency(const OpClass& opClass, int index)
00270 {
00271
00272 return m_execLatencyInfo->GetLatency(opClass.GetCode());
00273 }
00274
00275
00276 void ExecUnitBase::Begin()
00277 {
00278 m_reserver.Begin();
00279 }
00280
00281
00282 void ExecUnitBase::Update()
00283 {
00284 m_reserver.Update();
00285 }
00286