Vengineerの妄想(準備期間)

人生は短いけど、長いです。人生を楽しみましょう!

OVP : Single Cortex-A9デモ、その2


今回は、シミュレータ部のソースコードOVPsim_single_arm_Cortex-A9UP.cです。

まずは、デバッグ有効にするかどうかの処理。デバッグするときは、ポート番号を指定する。
    if(enableDebug) {
        icmInit(icmAttrs,"rsp", portNum);
    } else {
        icmInit(icmAttrs, 0 , 0);
    }
プロセッサのインスタンスを定義する部分です。
    // create a processor instance
    icmProcessorP processor = icmNewProcessor(
        "cpu0",             // CPU name
        "arm",              // CPU type
        0,                  // CPU cpuId
        0,                  // CPU model flags
        32,                 // address bits
        armModel,           // model file
        "modelAttrs",       // morpher attributes
        SIM_ATTRS,          // attributes
        icmAttr,            // user-defined attributes
        armSemihost,        // semi-hosting file
        "modelAttrs"        // semi-hosting attributes
    );

icmNewProcessor関数は、OVPのAPIで"icm/icmCpuManager.h"で定義されています。
icmNewProcessor関数は、上記のように11個の引数を取ります。

第 1引数:CPUの名称、プログラム内ではユニーク
第 2引数:CPUのタイプ、モデル内で定義されたアーキテクチャ
第 3引数:CPU ID、0から始まるID、プログラム内ではユニーク
第 4引数:CPUモデルに対するフラグ、各モデルに対応したフラグを指定できる
第 5引数:アドレス幅
第 6引数:モデルファイル
    ARMモデルを使うときは、下記のコードをお呪いだと思って使えばいいと思う。

    const char *armModel    = icmGetVlnvString(NULL, 
                                               "arm.ovpworld.org", 
                                               "processor", 
                                               "arm", 
                                               "1.0", 
                                               "model");

第 7引数:モデルのアトリビュート

    // enable relaxed scheduling for maximum performance
    #define SIM_ATTRS (ICM_ATTR_RELAXED_SCHED)
第 8引数:ユーザ定義のアトリビュート
    icmAttrListP icmAttr = icmNewAttrList();
    icmAddStringAttr(icmAttr, "endian",        "little");
    icmAddStringAttr(icmAttr, "compatibility", "nopSVC");
    icmAddStringAttr(icmAttr, "variant",       variant);
    icmAddStringAttr(icmAttr, "UAL",           "1");
第 9引数:semi-hostingのファイル名
第10引数:semi-hostingのアトリビュート
    ARMモデルを使うときは、下記のコードをお呪いだと思って使えばいいと思う。

    const char *armSemihost = icmGetVlnvString(NULL, 
                                               "arm.ovpworld.org", 
                                               "semihosting", 
                                               "armNewlib", 
                                               "1.0", 
                                               "model");

CPUでデバッグをするときは、次のようなコードでデバッガと接続する。
デバッグするCPUモデル(proc)に対して、デバッグを有効にする(icmDebugThisProcess関数)
    char  coreName[32] = "cpu0";        // set to core name to debug

    if(enableDebug) {
        icmProcessorP proc = icmFindProcessorByName(coreName);
        if(proc) {
            // If there's a processor of this name, set this for debug
            // This is required for debug using a standard GDB via RSP.
            // It's not required for Imperas MPD
            icmDebugThisProcessor(proc);

            // Reduce the timeslice to minimize multicore scheduling effects
            icmSetSimulationTimeSlice(0.00001);
        }
    }
CPU内部のメモリにアプリケーション(ELFファイル)をロードする。
プログラムは外部ROMではなく、プロセッサの内部ROMにストアされる。
    // load the application executable file into processor memory space
    if(!icmLoadProcessorMemory(processor, application, False, False, True)) {
        return -1;
    }

CPUを起動(icmSimulatePlatfom)し、正常終了か強制終了(CTRL-C)(icmGetStopReason)を待ち、
CPUを終了される(icmTerminate)。
    // simulate the platform
    icmProcessorP final = icmSimulatePlatform();

    // was simulation interrupted or did it complete
    if(final && (icmGetStopReason(final)==ICM_SR_INTERRUPT)) {
        icmPrintf("*** simulation interrupted\n");
    }

    icmTerminate();

と、いたって簡単なコードになっています。

検証、Verification、OVP