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/System/SystemManager.h"
00035
00036 #include "Sim/Dumper/Dumper.h"
00037 #include "Emu/EmulatorFactory.h"
00038
00039 #include "Sim/Pipeline/Fetcher/Fetcher.h"
00040 #include "Sim/Pipeline/Retirer/Retirer.h"
00041 #include "Sim/Register/RegisterFile.h"
00042 #include "Sim/Predictor/DepPred/RegDepPred/RegDepPredIF.h"
00043 #include "Sim/Dependency/PhyReg/PhyReg.h"
00044
00045 #include "Sim/System/EmulationSystem/EmulationSystem.h"
00046 #include "Sim/System/InorderSystem/InorderSystem.h"
00047 #include "Sim/System/EmulationTraceSystem/EmulationTraceSystem.h"
00048 #include "Sim/System/SimulationSystem/SimulationSystem.h"
00049 #include "Sim/System/EmulationDebugSystem/EmulationDebugSystem.h"
00050 #include "Sim/System/ForwardEmulator.h"
00051
00052 #include "Sim/Foundation/Hook/HookUtil.h"
00053
00054 namespace Onikiri
00055 {
00056 HookPoint<SystemManager, SystemManager::ProcessNotifyParam>
00057 SystemManager::s_processNotifyHook;
00058 }
00059
00060 using namespace Onikiri;
00061
00062 SystemManager::SystemManager()
00063 {
00064 m_system = NULL;
00065
00066 m_simulationCycles = 0;
00067 m_simulationInsns = 0;
00068 m_skipInsns = 0;
00069 }
00070
00071 SystemManager::~SystemManager()
00072 {
00073 }
00074
00075 void SystemManager::Initialize()
00076 {
00077 LoadParam();
00078
00079 m_context.resBuilder = new ResourceBuilder();
00080
00081 InitializeEmulator();
00082 InitializeResources();
00083
00084 GetInitialContext( &m_context.architectureStateList );
00085
00086 }
00087
00088 void SystemManager::Finalize()
00089 {
00090 g_dumper.Finalize();
00091
00092 m_context.emulatorWrapper.ReleaseParam();
00093 ReleaseParam();
00094
00095 if( m_context.emulator ){
00096 delete m_context.emulator;
00097 m_context.emulator = NULL;
00098 }
00099 if( m_context.resBuilder ){
00100 delete m_context.resBuilder;
00101 m_context.resBuilder = NULL;
00102 }
00103 }
00104
00105 void SystemManager::InitializeEmulator()
00106 {
00107 g_env.PrintInternal("Emulator ... ");
00108
00109 int processConfigCount = 0;
00110 if( !g_paramDB.Get( "/Session/Emulator/Processes/#Process", &processConfigCount, false ) ){
00111 THROW_RUNTIME_ERROR(
00112 "'/Session/Emulator/Processes/Process' node is not found. "
00113 "There is no process configuration. "
00114 "This may occur when no configuration XML file is passed. "
00115 "Please check your command line option."
00116 );
00117 }
00118
00119
00120 EmulatorFactory emulatorFactory;
00121 m_context.emulator = emulatorFactory.Create( m_context.targetArchitecture, this );
00122 m_context.emulator->SetExtraOpDecoder( &m_extraOpDecoder );
00123 SimISAInfo::TestISAInfo( m_context.emulator->GetISAInfo() );
00124
00125 g_env.PrintInternal("initialized.\n");
00126 }
00127
00128 void SystemManager::InitializeResources()
00129 {
00130 g_env.PrintInternal("Resources ... ");
00131
00132
00133 PhysicalResourceNodeInfo info;
00134 info.name = "emulator";
00135 info.typeName = "EmulatorIF";
00136 info.paramPath = "/Session/Emulator/";
00137 info.resultPath = "/Session/Result/Resource/Emulator/";
00138 info.resultRootPath = "/Session/Result/Resource/Emulator/";
00139 m_context.emulatorWrapper.SetInfo( info );
00140 m_context.emulatorWrapper.SetEmulator( m_context.emulator );
00141
00142 ResourceBuilder::ResNode node;
00143 node.count = 1;
00144 node.external = true;
00145 node.instances.push_back( &m_context.emulatorWrapper );
00146 node.name = info.name;
00147 node.type = info.typeName;
00148 node.paramPath = info.paramPath;
00149 node.resultPath = info.resultPath;
00150 m_context.resBuilder->SetExternalResource( &node );
00151
00152
00153 m_context.resBuilder->Construct();
00154
00155 m_context.resBuilder->GetResourceByType( "Core", m_context.cores );
00156 m_context.resBuilder->GetResourceByType( "Thread", m_context.threads );
00157 m_context.resBuilder->GetResourceByType( "Cache", m_context.caches );
00158 m_context.resBuilder->GetResourceByType( "GlobalClock", m_context.globalClock );
00159 m_context.resBuilder->GetResourceByType( "ForwardEmulator", m_context.forwardEmulator );
00160
00161 InitializeSimulationContext();
00162
00163 g_dumper.Initialize( m_context.cores, m_context.threads );
00164
00165 g_env.PrintInternal("initialized.\n");
00166 }
00167
00168 void SystemManager::InitializeSimulationContext()
00169 {
00170 int processCount = m_context.emulator->GetProcessCount();
00171 if( processCount > m_context.threads.GetSize() ){
00172 THROW_RUNTIME_ERROR(
00173 "The number of the processes is greater than the number of the threads."
00174 );
00175 }
00176
00177
00178 ArchitectureStateList archStateList;
00179 GetInitialContext( &archStateList );
00180
00181
00182 SetSimulationContext( archStateList );
00183 }
00184
00185 void SystemManager::GetInitialContext( ArchitectureStateList* archStateList )
00186 {
00187
00188 int processCount = m_context.emulator->GetProcessCount();
00189 archStateList->resize( processCount );
00190 for( int pid = 0; pid < processCount; pid++ ){
00191
00192 PC pc = m_context.emulator->GetEntryPoint(pid);
00193 pc.tid = pid;
00194 (*archStateList)[pid].pc = pc;
00195 }
00196
00197 ISAInfoIF* isaInfo = m_context.emulator->GetISAInfo();
00198
00199
00200 int logicalRegCount = isaInfo->GetRegisterCount();
00201 for( int pid = 0; pid < processCount; pid++ ){
00202 (*archStateList)[pid].registerValue.resize( logicalRegCount );
00203 for (int i = 0; i < logicalRegCount; i ++) {
00204 (*archStateList)[pid].registerValue[i] = m_context.emulator->GetInitialRegValue(pid, i);
00205 }
00206 }
00207 }
00208
00209 bool SystemManager::SetSimulationContext( const ArchitectureStateList& archStateList )
00210 {
00211 ISAInfoIF* isaInfo = m_context.emulator->GetISAInfo();
00212 int processCount = m_context.emulator->GetProcessCount();
00213 int logicalRegCount = isaInfo->GetRegisterCount();
00214
00215 for( int i = 0; i < m_context.cores.GetSize(); i++ ){
00216 Core* core = m_context.cores[i];
00217
00218
00219 core->GetFetcher()->SetInitialNumFetchedOp(0);
00220
00221 core->GetRetirer()->SetInitialNumRetiredOp(0, 0, m_context.executionInsns );
00222
00223
00224 RegisterFile* regFile = core->GetRegisterFile();
00225 for(int i = 0; i < regFile->GetTotalCapacity(); ++i) {
00226 PhyReg* reg = regFile->GetPhyReg(i);
00227 reg->Set();
00228 }
00229 }
00230
00231 bool remainingProcess = false;
00232 for( int pid = 0; pid < processCount; pid++ ){
00233 const ArchitectureState& context = archStateList[pid];
00234 if( context.pc.address != 0 ){
00235 remainingProcess = true;
00236
00237
00238 PC pc = context.pc;
00239 pc.tid = pid;
00240 m_context.threads[pid]->InitializeContext( pc );
00241 m_context.threads[pid]->Activate( true );
00242
00243 RegDepPredIF* regDepPred = m_context.threads[pid]->GetRegDepPred();
00244 RegisterFile* regFile = m_context.threads[pid]->GetCore()->GetRegisterFile();
00245
00246
00247 for(int i = 0; i < logicalRegCount; ++i) {
00248 int phyRegNo = regDepPred->PeekReg(i);
00249 PhyReg* reg = regFile->GetPhyReg( phyRegNo );
00250 reg->SetVal( context.registerValue[i] );
00251 }
00252 }
00253 else{
00254
00255 m_context.threads[pid]->Activate( false );
00256 }
00257 }
00258
00259
00260 for( int i = processCount; i < m_context.threads.GetSize(); i++ ){
00261 PC entryPoint( PID_INVALID, i, 0 );
00262 m_context.threads[i]->InitializeContext( entryPoint );
00263 m_context.threads[i]->Activate( false );
00264 }
00265
00266 m_context.forwardEmulator->SetContext( archStateList );
00267 return remainingProcess;
00268 }
00269
00270 void SystemManager::RunSimulation( SystemContext* context )
00271 {
00272 NotifyChangingMode( PhysicalResourceNode::SM_SIMULATION );
00273 SimulationSystem simulationSystem;
00274 simulationSystem.Run( context );
00275 }
00276
00277 void SystemManager::RunEmulation( SystemContext* context )
00278 {
00279 NotifyChangingMode( PhysicalResourceNode::SM_EMULATION );
00280 EmulationSystem emulationSystem;
00281 emulationSystem.Run( context );
00282 }
00283
00284 void SystemManager::RunEmulationTrace( SystemContext* context )
00285 {
00286 NotifyChangingMode( PhysicalResourceNode::SM_EMULATION );
00287 EmulationTraceSystem emulationTraceSystem;
00288 emulationTraceSystem.Run( context );
00289 }
00290
00291 void SystemManager::RunEmulationDebug( SystemContext* context )
00292 {
00293 EmulationDebugSystem emulationDebugSystem;
00294 emulationDebugSystem.Run( context );
00295 }
00296
00297 void SystemManager::RunInorder( SystemContext* context )
00298 {
00299 NotifyChangingMode( PhysicalResourceNode::SM_INORDER );
00300 InorderSystem inorderSystem;
00301 inorderSystem.Run( context );
00302 }
00303
00304 void SystemManager::SetSystem( SystemIF* system )
00305 {
00306 m_system = system;
00307 }
00308
00309 void SystemManager::Main()
00310 {
00311 bool initialized = false;
00312 bool thrown = false;
00313 std::string errMessage;
00314
00315
00316 try{
00317 Initialize();
00318 initialized = true;
00319 }
00320 catch( const std::exception& error ){
00321 errMessage = error.what();
00322 thrown = true;
00323 }
00324
00325
00326 try{
00327 if( initialized ){
00328 Run();
00329 }
00330 }
00331 catch( const std::exception& error ){
00332 if( !thrown ){
00333 errMessage = error.what();
00334 }
00335 thrown = true;
00336 }
00337
00338
00339 try{
00340 Finalize();
00341 }
00342 catch( const std::exception& error ){
00343 if( !thrown ){
00344 errMessage = error.what();
00345 }
00346 thrown = true;
00347 }
00348
00349 if( thrown ){
00350 throw std::runtime_error( errMessage.c_str() );
00351 }
00352 }
00353
00354 void SystemManager::Run()
00355 {
00356 const String& mode = m_context.mode;
00357
00358 m_context.executionInsns = m_simulationInsns;
00359 m_context.executionCycles = m_simulationCycles;
00360
00361 if( mode == "Emulation" ){
00362 if( m_context.executionInsns == 0 ){
00363 RUNTIME_WARNING( "'@SimulationInsns' is 0 and nothing is executed in 'Emulation' mode." );
00364 }
00365 RunEmulation( &m_context );
00366 }
00367 else if( mode == "CreateEmulationTrace" ){
00368 if( m_context.executionInsns == 0 ){
00369 RUNTIME_WARNING( "'@SimulationInsns' is 0 and nothing is executed in 'CreateEmulationTrace' mode." );
00370 }
00371 RunEmulationTrace( &m_context );
00372 }
00373 else if( mode == "EmulationWithDebug" ){
00374 if( m_context.executionInsns == 0 ){
00375 RUNTIME_WARNING( "'@SimulationInsns' is 0 and nothing is executed in 'CreateEmulationTrace' mode." );
00376 }
00377 RunEmulationDebug( &m_context );
00378 }
00379 else if( mode == "Inorder" ) {
00380
00381 m_context.executionInsns = m_skipInsns;
00382 m_context.executionCycles = 0;
00383 RunEmulation( &m_context );
00384 m_skippedInsns = m_context.executedInsns;
00385
00386
00387 m_context.executionInsns = m_simulationInsns;
00388 m_context.executionCycles = m_simulationCycles;
00389 m_context.executedInsns.clear();
00390 m_context.executedCycles = 0;
00391 if( SetSimulationContext( m_context.architectureStateList ) ){
00392 RunInorder( &m_context );
00393 }
00394 }
00395 else if( mode == "SkipByInorder" ) {
00396
00397 m_context.executionInsns = m_skipInsns;
00398 m_context.executionCycles = 0;
00399 RunInorder( &m_context );
00400 m_skippedInsns = m_context.executedInsns;
00401
00402
00403 m_context.executionInsns = m_simulationInsns;
00404 m_context.executionCycles = m_simulationCycles;
00405 m_context.executedInsns.clear();
00406 m_context.executedCycles = 0;
00407 if( SetSimulationContext( m_context.architectureStateList ) ){
00408 RunSimulation( &m_context );
00409 }
00410 }
00411 else if( mode == "Simulation" ){
00412
00413
00414 m_context.executionInsns = m_skipInsns;
00415 m_context.executionCycles = 0;
00416 RunEmulation( &m_context );
00417 m_skippedInsns = m_context.executedInsns;
00418
00419
00420 m_context.executionInsns = m_simulationInsns;
00421 m_context.executionCycles = m_simulationCycles;
00422 m_context.executedInsns.clear();
00423 m_context.executedCycles = 0;
00424 if( SetSimulationContext( m_context.architectureStateList ) ){
00425 RunSimulation( &m_context );
00426 }
00427 }
00428 else{
00429 THROW_RUNTIME_ERROR(
00430 "An unknown simulation mode is specified in the"
00431 "'/Session/System/@Mode'\n"
00432 "This parameter must be one of the following strings : \n"
00433 "[Emulation, Simulation, Inorder, CreateEmulationTrace, SkipByInorder]"
00434 );
00435 }
00436
00437 m_executedInsns = m_context.executedInsns;
00438 m_executedCycles = m_context.executedCycles;
00439 m_ipc.clear();
00440 for( size_t i = 0; i < m_executedInsns.size(); ++i ){
00441 if( m_executedCycles != 0 ){
00442 m_ipc.push_back( (double)m_executedInsns[i] / (double)m_executedCycles );
00443 }
00444 else{
00445 m_ipc.push_back( 1.0 );
00446 }
00447 }
00448
00449 }
00450
00451
00452
00453 void SystemManager::NotifyProcessTermination(int pid)
00454 {
00455 ProcessNotifyParam param = { PNT_TERMINATION, pid, Addr(), 0, 0 };
00456 HookEntry(
00457 this,
00458 &SystemManager::NotifyProcessTerminationBody,
00459 &s_processNotifyHook,
00460 ¶m
00461 );
00462 }
00463
00464 void SystemManager::NotifySyscallReadFileToMemory(const Addr& addr, u64 size)
00465 {
00466 ProcessNotifyParam param =
00467 {
00468 PNT_READ_FILE_TO_MEMORY, addr.pid, addr, size, 0
00469 };
00470 HookEntry(
00471 this,
00472 &SystemManager::NotifySyscallReadFileToMemoryBody,
00473 &s_processNotifyHook,
00474 ¶m
00475 );
00476 }
00477
00478 void SystemManager::NotifySyscallWriteFileFromMemory(const Addr& addr, u64 size)
00479 {
00480 ProcessNotifyParam param =
00481 {
00482 PNT_WRITE_FILE_FROM_MEMORY, addr.pid, addr, size, 0
00483 };
00484 HookEntry(
00485 this,
00486 &SystemManager::NotifySyscallWriteFileFromMemoryBody,
00487 &s_processNotifyHook,
00488 ¶m
00489 );
00490 }
00491
00492 void SystemManager::NotifyMemoryAllocation(const Addr& addr, u64 size, bool allocate)
00493 {
00494
00495 if( m_processMemoryUsage.size() <= (size_t)addr.pid ){
00496 m_processMemoryUsage.resize( addr.pid + 1 );
00497 }
00498 if( allocate ){
00499 m_processMemoryUsage[addr.pid] += size;
00500 }
00501 else{
00502 m_processMemoryUsage[addr.pid] -= size;
00503 }
00504
00505 ProcessNotifyParam param =
00506 {
00507 allocate ? PNT_ALLOCATE_MEMORY : PNT_FREE_MEMORY,
00508 addr.pid,
00509 addr,
00510 size,
00511 m_processMemoryUsage[addr.pid]
00512 };
00513 HookEntry(
00514 this,
00515 &SystemManager::NotifyMemoryAllocationBody,
00516 &s_processNotifyHook,
00517 ¶m
00518 );
00519 }
00520
00521
00522
00523
00524 void SystemManager::NotifyProcessTerminationBody( ProcessNotifyParam* param )
00525 {
00526 if(!m_system)
00527 return;
00528
00529 m_system->NotifyProcessTermination( param->pid );
00530 }
00531
00532 void SystemManager::NotifySyscallReadFileToMemoryBody( ProcessNotifyParam* param )
00533 {
00534 if(!m_system)
00535 return;
00536
00537 m_system->NotifySyscallReadFileToMemory( param->addr, param->size );
00538 }
00539
00540 void SystemManager::NotifySyscallWriteFileFromMemoryBody( ProcessNotifyParam* param )
00541 {
00542 if(!m_system)
00543 return;
00544
00545 m_system->NotifySyscallWriteFileFromMemory( param->addr, param->size );
00546 }
00547
00548 void SystemManager::NotifyMemoryAllocationBody( ProcessNotifyParam* param )
00549 {
00550 if(!m_system)
00551 return;
00552
00553 m_system->NotifyMemoryAllocation(
00554 param->addr,
00555 param->size,
00556 param->type == PNT_ALLOCATE_MEMORY ? true : false
00557 );
00558 }
00559
00560 void SystemManager::NotifyChangingMode( PhysicalResourceNode::SimulationMode mode )
00561 {
00562 ASSERT( m_context.resBuilder != NULL );
00563 std::vector<PhysicalResourceNode*> res =
00564 m_context.resBuilder->GetAllResources();
00565 for( size_t i = 0; i < res.size(); i++ ){
00566 res[i]->ChangeSimulationMode( mode );
00567 }
00568 }
00569