天天看點

[GEM5學習]1、GEM5仿真器啟動過程

GEM5簡介

      GEM5是高度面子產品化的仿真器,主要由Python和C++語言編寫,Python用初始化、設定、組織和配置各個子產品,因為C++的高性能,是以真正執行的子產品都由C++語言編寫,GEM5還內建了兩種DSL語言,一種用于描述ISA,一種用來實作Cache的一緻性協定(SLLIC)。

     Swig工具用來封裝和導出C++子產品接口,使C++子產品可以被Python組織和調用。swig的使用方法

GEM5啟動過程

本文使用X86架構為例介紹GEM5中最簡單的SE模式啟動過程。GEM5啟動的指令為:

~/simulators/gem5$ build/X86_MESI_Three_Level_sparse/gem5.opt configs/example/se.py -c test
           

其中gem5.opt為GEM5的主二進制程式,se.py為用Python語言編寫的配置檔案,test為标準Linux下gcc編譯的二進制檔案。

運作結果如下:

[email protected]:~/simulators/gem5$ build/X86_MESI_Three_Level_sparse/gem5.opt configs/example/se.py -c test
gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 compiled Jun 22 2014 15:27:09
gem5 started Jun 22 2014 15:27:28
gem5 executing on atlantis
command line: build/X86_MESI_Three_Level_sparse/gem5.opt configs/example/se.py -c test
Global frequency set at 1000000000000 ticks per second
0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000
**** REAL SIMULATION ****
info: Entering event queue @ 0.  Starting simulation...
info: Increasing stack size by one page.
warn: ignoring syscall access(0, 4893217, ...)
Hello, world!
Exiting @ tick 6979500 because target called exit()
           

    通過GDB調試發現GEM5啟動的過程如下圖:

[GEM5學習]1、GEM5仿真器啟動過程

其中GEM5啟動使用的trigger是标準的C/C++的main函數,main函數主要工作為初始化信号量和初始化Python環境。然後通過調用sim/init.cc中的initM5Python()方法來初始化GEM5使用的子產品。在initM5Python()函數主要調用了兩個方法:

int
initM5Python()
{
    EmbeddedSwig::initAll();
    return EmbeddedPython::initAll();
}
           

EmbeddedSwig::initAll()用來調用每個子產品與swig相關的初始化函數,這些函數都在xxx.i_init.cc中聲明,xxx為子產品名。比如一個param_IsaFake的子產品中的代碼:

#include "sim/init.hh"

extern "C" {
    void init_param_IsaFake();
}

EmbeddedSwig embed_swig_param_IsaFake(init_param_IsaFake); //執行個體化一個EmbeddedSwig對象,并把初始化函數通過構造函數傳給類中的靜态變量list
           
//EmbeddedSwig的構造函數
EmbeddedSwig::EmbeddedSwig(void (*init_func)())
    : initFunc(init_func)
{
    getList().push_back(this);
}
           

在EmbeddedSwig的構造函數中會把每個子產品的初始化函數放到一個list中,InitAll()函數的主要工作就是掉用這些已經定義好的初始化函數。

    EmbeddedPython::initAll()用來整理繼承于SimObject的子產品并把他們映射到m5.objects命名空間下。這些gem5子產品是分布在不同檔案夾下的,理論上Python是通過檔案的路徑來确定Python子產品的命名空間(類似Java),但是通過分析來看下gem5是通過什麼方法把分布在不同檔案下的Python子產品map到m5.objects下。

    在每個gem5的功能子產品下都會有類似,xxxx.py.cc的檔案,這個檔案就是用來描述這個子產品的名字、檔案的絕對路徑等資訊:

EmbeddedPython embedded_m5_objects_AtomicSimpleCPU(
    "m5/objects/AtomicSimpleCPU.py",  //理論上這個檔案該在的位置
    "/home/wgh/simulators/gem5/src/cpu/simple/AtomicSimpleCPU.py", //實際在的位置
    "m5.objects.AtomicSimpleCPU",   //子產品的名字
    data_m5_objects_AtomicSimpleCPU,  //是一個大數組,I don't know what the fuck it is!
    766,   //上面那個大數組的長度
    1610);  //?
}
           

通過實力化EmbeddedPython對象,構造函數會把這些子產品的資訊添加到内部的一個list上,這為gem5未來加載這些子產品提供資訊。InitAll()函數會調用每個子產品自身的AddModule()把自己映射到它理論上該在的位置。

初始化完畢,仿真器調用main.cc的m5Main()函數,在m5Main()函數中使用PyRun_String來啟動Python子產品,PyRun_String()函數為c/c++調用python的接口,其中函數第一個參數為python指令,在這個地方使用了兩個指令:import m5和m5.main(),第二個指令是調用python子產品的main()函數。在m5.main()函數中使用

if options.pdb:    
	......
         pdb.run(filecode, scope) #調試模式下運作se.py,在gem5.opt的運作參數下加上--pdb參數。pdb調試器類似gdb,
    	.....
    else:
        exec filecode in scope   #正常運作
           

來執行se.py檔案。se.py為SE模式的配置檔案。在se.py中會調用Simulation子產品的run()函數,run()函數中調用了m5的simulate(),從圖中可以看出在src/python/m5/simulate.py檔案中的simulate()函數最終調用了被封裝過的C++子產品,子產品已經被映射到m5.internal.event下。到此為止,GEM5的啟動基本結束。下一篇分析simulate()函數的作用和gem5深入的一些機制。