FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

RISC-Vのbenchmarkパタンセットを動作させる(2)

引き続きRISC-VのISSをメンテナンスして、OSのポーティングと調整を行っているのだが、そういえばベンチマークセットの動作確認をやっている途中で忘れていた。

ISSの調整ついでに、失敗したパタンについて何が起きているのかを見ていこう。

msyksphinz.hatenablog.com

Dhrystoneベンチマークを動作させる

dhrystoneは、riscv-testsリポジトリ内に格納されている。

github.com

これをそのまま実行すると、パタンが正常に終了してくれないという問題があった。通常のテストパタンセットでは、mtohostシステムレジスタに1を書き込むと成功、それ以外を書き込むと失敗となっている。 mtohostには、よくわからない値が格納されていて終了していた。

    151988:M:MBar:[00000cf0] 00e7b023 : sd         tp,sp,0x00|zero      tp=>0000000000024ac0 sp=>0000000000000040 (0000000000024ac0)<=00000040
    151989:M:MBar:[00000cf4] 06063703 : ld         sp,s10,0x060         s10=>0000000000024b50 (0000000000024bb0)=>0000002e sp<=000000000000002e
    151990:M:MBar:[00000cf8] 00a7b423 : sd         tp,s8,0x00|s6        tp=>0000000000024ac0 s8=>0000000000000001 (0000000000024ac8)<=00000001
    151991:M:MBar:[00000cfc] 00d7b823 : sd         tp,s11,0x00|v0       tp=>0000000000024ac0 s11=>0000000000005280 (0000000000024ad0)<=00000080
    151992:M:MBar:[00000d00] 00e7bc23 : sd         tp,sp,0x00|a6        tp=>0000000000024ac0 sp=>000000000000002e (0000000000024ad8)<=0000002e
    151993:M:MBar:[00000d04] 0330000f : fence
    151994:M:MBar:[00000d08] 78079073 : csrrw      zero,0x780,tp        mtohost=>0000000000000000 tp=>0000000000024ac0 mtohost<=0000000000024ac0

これ、ルーチンを追いかけていくと、printfなどを利用するとプログラム内でmtohostにアクセスするらしい。なのでこのmtohostへの書き込みは終了コードを出しているわけではなく、普通にprintfをしているようだった。 ちょっとわかりにくいが、とりあえずmtohostで0か1が出力される以外は終了しないようにしておこう。

その中で、プログラムを追いかけていたのだが、ちゃんとeretでユーザモードに戻ってくれない場所がある。

RISC-Vのeret命令について

eret命令は、スーパバイザコードや割り込みによって割り込みコードに分岐した場合、ユーザコードに戻るために利用される命令だ。eret命令は、mstatusのbitを読み取り、PRV,IEのモード情報をmstatus内からポップする。 より具体的には、mstatusには複数割り込みに備えてPRV,IEビットがスタックできるようになっており、eretはそのスタックをポップしてユーザモードに戻るわけだ。

あれ、よく考えると、eretの逆、つまり特権モードに移るための命令であるecallには、mstatusにpushする操作を追加していたかな?

f:id:msyksphinz:20160410175955p:plain

確認すると追加されていなかったので、ecallのルーチンにmstatusを操作するコードを追加した。 これで、ecallでモード情報をmstatusにpush、eretでモード情報をmstatusからpop、という操作が実現される。

  UDWord_t curr_mstatus;
  m_env->CSRRead (SYSREG_ADDR_MSTATUS, &curr_mstatus);
  UDWord_t next_mstatus = (curr_mstatus << 3) | (static_cast<UDWord_t>(curr_priv) << 1);
  m_env->CSRWrite (SYSREG_ADDR_MSTATUS, next_mstatus);

Dhrystoneベンチマークの修正

上記の修正を行って改めてdhrystoneを走らせていたのだが、どうやら終了しない。調べてみると実機のタイマー情報を利用して終了判定をしているようだ。

    /**************/
    /* Stop timer */
    /**************/

    Stop_Timer();
    setStats(0);

    User_Time = End_Time - Begin_Time;

    if (User_Time < Too_Small_Time)
    {
      printf("Measured time too small to obtain meaningful results\n");
      Number_Of_Runs = Number_Of_Runs * 10;
      printf("\n");
    } else Done = true;
  }

タイマー情報を使われるとシミュレーションにもかなりの長い時間が使われてしまうため、ここはベンチマークを書き換えて終了するようにした。

    /**************/
    /* Stop timer */
    /**************/

    Stop_Timer();
    setStats(0);

    User_Time = End_Time - Begin_Time;

    // if (User_Time < Too_Small_Time)
    // {
    //   printf("Measured time too small to obtain meaningful results\n");
    //   Number_Of_Runs = Number_Of_Runs * 10;
    //   printf("\n");
    // } else Done = true;
    Done = true;
  }

とりあえずこれで良し。

と思ったらSupervisorのアドレッシングモードがまじめに動き出したのでユーザモードを使うパタンが落ちだしたなあ。。。修正しないと。