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/Core/Core.h"
00035
00036 #include "Utility/RuntimeError.h"
00037
00038 #include "Sim/Dumper/Dumper.h"
00039
00040 #include "Sim/Foundation/Hook/HookUtil.h"
00041 #include "Sim/Memory/MemOrderManager/MemOrderManager.h"
00042 #include "Sim/Memory/Cache/Cache.h"
00043 #include "Sim/Memory/Cache/CacheSystem.h"
00044 #include "Sim/Thread/Thread.h"
00045 #include "Sim/InorderList/InorderList.h"
00046 #include "Sim/Pipeline/Scheduler/Scheduler.h"
00047
00048 #include "Sim/Pipeline/Dispatcher/Dispatcher.h"
00049 #include "Sim/Pipeline/Retirer/Retirer.h"
00050 #include "Sim/Op/Op.h"
00051
00052 namespace Onikiri
00053 {
00054 HookPoint<Core, Core::CheckpointDecisionHookParam> Core::s_checkpointDecisionHook;
00055 };
00056
00057
00058
00059 using namespace std;
00060 using namespace Onikiri;
00061
00062 Core::Core() :
00063 m_opArrayCapacity(0),
00064 m_timeWheelSize(0),
00065 m_globalClock(0),
00066 m_opArray(0),
00067 m_registerFile(0),
00068 m_fetcher(0),
00069 m_renamer(0),
00070 m_dispatcher(0),
00071 m_scheduler(0),
00072 m_retirer(0),
00073 m_latPred(0),
00074 m_cacheSystem(0),
00075 m_emulator(0),
00076 m_bPred(0),
00077 m_execLatencyInfo(0),
00078 m_loadPipeLineModel(LPM_MULTI_ISSUE),
00079 m_schedulerRemovePolicy(RP_FOLLOW_CORE),
00080 m_checkpointingPolicy(CP_AUTO)
00081 {
00082
00083 }
00084
00085 Core::~Core()
00086 {
00087 if( m_opArray != 0 ) delete m_opArray;
00088 ReleaseParam();
00089 }
00090
00091 void Core::Initialize(InitPhase phase)
00092 {
00093 if(phase == INIT_PRE_CONNECTION){
00094 LoadParam();
00095
00096 m_opArray = new OpArray( m_opArrayCapacity );
00097
00098 m_latencyPredRecv.Validate();
00099 m_addrMatchPredRecv.Validate();
00100 m_valuePredRecv.Validate();
00101 m_partialLoadRecovery.Validate();
00102
00103
00104 }
00105 else if(phase == INIT_POST_CONNECTION){
00106
00107 CheckNodeInitialized( "registerFile", m_registerFile );
00108 CheckNodeInitialized( "fetcher", m_fetcher );
00109 CheckNodeInitialized( "renamer", m_renamer );
00110 CheckNodeInitialized( "dispatcher", m_dispatcher );
00111 CheckNodeInitialized( "retirer", m_retirer );
00112 CheckNodeInitialized( "latPred", m_latPred );
00113 CheckNodeInitialized( "execLatencyInfo", m_execLatencyInfo );
00114 CheckNodeInitialized( "thread", m_thread );
00115 CheckNodeInitialized( "cacheSystem", m_cacheSystem );
00116 CheckNodeInitialized( "emulator", m_emulator );
00117
00118 for( int localTID = 0; localTID < GetThreadCount(); localTID++ ){
00119 m_thread[localTID]->SetLocalThreadID( localTID );
00120 }
00121
00122
00123 for(int i = 0; i < GetNumScheduler(); ++i) {
00124 for(int k = i + 1; k < GetNumScheduler(); ++k) {
00125 if( GetScheduler(i)->GetIndex() == GetScheduler(k)->GetIndex() ) {
00126 THROW_RUNTIME_ERROR("same schduler index %d(%d, %d).",
00127 GetScheduler(k)->GetIndex(), i, k);
00128 }
00129 }
00130 }
00131
00132
00133 int totalInorderListCapacity = 0;
00134 for( int i = 0; i < m_thread.GetSize(); ++i ){
00135 totalInorderListCapacity +=
00136 m_thread[i]->GetInorderList()->GetCapacity();
00137 }
00138 if( m_opArrayCapacity < totalInorderListCapacity ){
00139 THROW_RUNTIME_ERROR(
00140 "The capacity(%d) of 'OpArray' is too small. Make 'Core/@OpArrayCapacity' more larger.",
00141 m_opArrayCapacity
00142 );
00143 }
00144 }
00145 }
00146
00147
00148 int Core::GetCID()
00149 {
00150 return GetRID();
00151 }
00152
00153 int Core::GetTID(const int index)
00154 {
00155 return PhysicalResourceNode::GetTID( index );
00156 }
00157
00158 void Core::AddScheduler( Scheduler* scheduler )
00159 {
00160 m_scheduler.push_back( scheduler );
00161 }
00162
00163 Scheduler* Core::GetScheduler( int index )
00164 {
00165 ASSERT(
00166 index >= 0 && index < static_cast<int>(m_scheduler.size()),
00167 "illegal index: %d", index
00168 );
00169 return m_scheduler[index];
00170 }
00171
00172 int Core::GetNumScheduler() const
00173 {
00174 return static_cast<int>(m_scheduler.size());
00175 }
00176
00177 Thread* Core::GetThread(int tid)
00178 {
00179 return m_thread[tid];
00180 }
00181
00182 int Core::GetThreadCount()
00183 {
00184 return m_thread.GetSize();
00185 }
00186
00187
00188
00189
00190
00191
00192 bool Core::IsRequiredCheckpointBefore( const PC& pc, const OpInfo* const info)
00193 {
00194 CheckpointDecisionHookParam param = { &pc, info, true, false } ;
00195
00196 HOOK_SECTION_PARAM( s_checkpointDecisionHook, param ){
00197 if( m_checkpointingPolicy == CP_ALL ){
00198 param.requried = true;
00199 }
00200 else if ( m_checkpointingPolicy == CP_AUTO ){
00201 const OpClass& opClass = param.info->GetOpClass();
00202 param.requried =
00203 m_latencyPredRecv.IsRequiredBeforeCheckpoint ( opClass ) ||
00204 m_addrMatchPredRecv.IsRequiredBeforeCheckpoint ( opClass ) ||
00205 m_valuePredRecv.IsRequiredBeforeCheckpoint ( opClass ) ||
00206 m_partialLoadRecovery.IsRequiredBeforeCheckpoint( opClass );
00207 }
00208 else{
00209 ASSERT( "Unknown check-pointing policy." );
00210 }
00211 }
00212
00213 return param.requried;
00214 }
00215
00216
00217
00218 bool Core::IsRequiredCheckpointAfter( const PC& pc, const OpInfo* const info)
00219 {
00220 CheckpointDecisionHookParam param = { &pc, info, false, false } ;
00221 HOOK_SECTION_PARAM( s_checkpointDecisionHook, param ){
00222 if( m_checkpointingPolicy == CP_ALL ){
00223 param.requried = true;
00224 }
00225 else if ( m_checkpointingPolicy == CP_AUTO ){
00226 const OpClass& opClass = param.info->GetOpClass();
00227 param.requried =
00228 opClass.IsBranch() ||
00229 m_latencyPredRecv.IsRequiredAfterCheckpoint ( opClass ) ||
00230 m_addrMatchPredRecv.IsRequiredAfterCheckpoint ( opClass ) ||
00231 m_valuePredRecv.IsRequiredAfterCheckpoint ( opClass ) ||
00232 m_partialLoadRecovery.IsRequiredAfterCheckpoint ( opClass );
00233 }
00234 else{
00235 ASSERT( "Unknown check-pointing policy." );
00236 }
00237 }
00238
00239 return param.requried;
00240 }
00241
00242
00243 void Core::Evaluate()
00244 {
00245 ClockedResourceBase::Evaluate();
00246
00247
00248 Cache* lv1ICache = m_cacheSystem->GetFirstLevelInsnCache();
00249 if( lv1ICache->IsStallRequired() ){
00250 m_dispatcher->StallThisCycle();
00251 }
00252
00253 Cache* lv1DCache = m_cacheSystem->GetFirstLevelDataCache();
00254 if( lv1DCache->IsStallRequired() ){
00255
00256 m_retirer->StallThisCycle();
00257 for( size_t i = 0; i < m_scheduler.size(); i++ ){
00258 m_scheduler[i]->StallThisCycle();
00259 }
00260 }
00261
00262 }
00263