src/Sim/System/SystemManager.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/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     // Set the emulator
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     // Set the external emulator to the resource builder before constructing and connecting.
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     // Construct objects
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     // Get initial contexts
00178     ArchitectureStateList archStateList;
00179     GetInitialContext( &archStateList );
00180 
00181     // Set the initial contexts
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         // PC
00192         PC pc = m_context.emulator->GetEntryPoint(pid);
00193         pc.tid = pid;   // The thread id from the GetEntryPoint() is not set in the emulator
00194         (*archStateList)[pid].pc = pc;
00195     }
00196 
00197     ISAInfoIF* isaInfo = m_context.emulator->GetISAInfo();
00198 
00199     // _WX^l emulator Zbg
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         // fetch index
00219         core->GetFetcher()->SetInitialNumFetchedOp(0);
00220         // retire count
00221         core->GetRetirer()->SetInitialNumRetiredOp(0, 0, m_context.executionInsns );
00222 
00223         // register readiness
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             // fetch pc
00238             PC pc = context.pc;
00239             pc.tid = pid;   // A thread id is not set in the emulator
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             // register value
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             // Deactivate the process
00255             m_context.threads[pid]->Activate( false );
00256         }
00257     }
00258 
00259     // Threads that exceed the number of the processes are deactivated.
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     // Initialize the system.
00316     try{
00317         Initialize();
00318         initialized = true;
00319     }
00320     catch( const std::exception& error ){
00321         errMessage = error.what();
00322         thrown = true;
00323     }
00324 
00325     // Run
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     // Finalize the system.
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         // Run emulation
00381         m_context.executionInsns  = m_skipInsns;
00382         m_context.executionCycles = 0;
00383         RunEmulation( &m_context );
00384         m_skippedInsns = m_context.executedInsns;
00385 
00386         // Run inorder
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         // Run inorder
00397         m_context.executionInsns  = m_skipInsns;
00398         m_context.executionCycles = 0;
00399         RunInorder( &m_context );
00400         m_skippedInsns = m_context.executedInsns;
00401 
00402         // Run simulation
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         // Run emulation
00414         m_context.executionInsns  = m_skipInsns;
00415         m_context.executionCycles = 0;
00416         RunEmulation( &m_context );
00417         m_skippedInsns = m_context.executedInsns;
00418 
00419         // Run simulation
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 // SystemIF
00452  
00453 void SystemManager::NotifyProcessTermination(int pid)
00454 {   
00455     ProcessNotifyParam param = { PNT_TERMINATION, pid, Addr(), 0/*size*/, 0/*totalSize*/ };
00456     HookEntry(
00457         this,
00458         &SystemManager::NotifyProcessTerminationBody,
00459         &s_processNotifyHook,
00460         &param 
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         &param 
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         &param 
00489     );
00490 }
00491 
00492 void SystemManager::NotifyMemoryAllocation(const Addr& addr, u64 size, bool allocate)
00493 {
00494     // Update process memory usage
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         &param 
00518     );
00519 }
00520 
00521 //
00522 // The bodies of notify methods
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 

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