src/Sim/ExecUnit/ExecUnitBase.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 #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     // ExecutionBegin() G~[Vs
00104     // タss--タsXe[WiKC
00105     // \[XEIyhm--
00106     // execution stages G~[VsD
00107 
00108     // When a multi-issue mode is enabled, Execute() need to be called more than once,
00109     // because access order violation is detected from 'executed' load ops.
00110     // Re-scheduling changes the status of load ops to 'un-executed' and
00111     // cannot detect those load ops.
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     // Record a cycle time when execution is kicked initially. 
00123     // 'executionKicked' is cleared when op is canceled by the other ops.
00124     if( !issueState.executionKicked ){
00125         issueState.executionKickedTime =
00126             op->GetScheduler()->GetLowerPipeline()->GetNow();
00127         issueState.executionLatency = latency;
00128     }
00129 
00130     if( issueState.multiIssue ){
00131         // Multi issue mode
00132         const LatPredResult::Scheduling& schd = op->GetLatPredRsult().Get(0);
00133         if( schd.latency == latency ){
00134             RegisterFinishEvent( op, latency ); // タsICxgo^
00135         }
00136         else{
00137             RegisterRescheduleEvent( op, latency, &issueState );
00138         }
00139     }
00140     else{
00141         // Single issue mode
00142         if( issueState.executionKicked ){
00143             THROW_RUNTIME_ERROR( "An op is executed more than once." );
00144         }
00145         else{
00146             RegisterFinishEvent( op, latency ); // タsICxgo^
00147             RegisterDetectEvent( op, latency ); // \~XoCxgo^
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     // finish Cxgo^
00160     EventPtr finishEvent(
00161         OpFinishEvent::Construct( op ));
00162     // RegisterFinishEvent タsJn(OpExecuteEvent)
00163     //  Finish タsCeV-1 TCN
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     // Detect events
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     // Search next speculatively rescheduling timing.
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     // There is no speculative rescheduling timing, wait for the latency.
00219     if( !speculative ){
00220         rsLatency = latency - latencyOffset;
00221     }
00222 
00223     if( rsLatency < 1 ){
00224         rsLatency = 1;
00225     }
00226 
00227     // When ops are speculatively waken-up, detection events need to be registered.
00228     if( (!issueState->executionKicked && schd.wakeup) || 
00229         issueState->executionKicked
00230     ){
00231         // Detection events need to occur before re-scheduling events occur,
00232         // because re-scheduling events cancel all the other events.
00233         if( rsLatency < minLatency ){
00234             rsLatency = minLatency;
00235         }
00236 
00237         // An op is issued when the op is finished for 'minLatency' except the first time,
00238         // so detection events are registered after 'minLatency'.
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     // Re-scheduling events need to be registered after detection events.
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 // OpClass CeV
00262 int ExecUnitBase::GetLatencyCount(const OpClass& opClass)
00263 {
00264     // ZCeV
00265     return 1;
00266 }
00267 
00268 // OpClass CfNXCeV
00269 int ExecUnitBase::GetLatency(const OpClass& opClass, int index)
00270 {
00271     // PExecLatencyInfo
00272     return m_execLatencyInfo->GetLatency(opClass.GetCode());
00273 }
00274 
00275 // TCN
00276 void ExecUnitBase::Begin()
00277 {
00278     m_reserver.Begin();
00279 }
00280 
00281 // Called in Update phase.
00282 void ExecUnitBase::Update()
00283 {
00284     m_reserver.Update();
00285 }
00286 

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