FPGA開発日記

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

RISC-VのCore Local Interrupt (CLINT)の仕様について調査 (3. CLINTのテストケースデバッグ)

自作CPUでのCLINTの実装をやりたくて、仕様を調査している。

とりえあずテストケースが完成したのでRTLシミュレーションで動かしてみているのだが、いくつか考えなければならないことがある。

まず、mtimeレジスタやメモリマップされた領域をアクセスしたときに、RTLとSpikeでどうしても誤差が発生する。これを埋めるために、CLINTのmtimeレジスタにアクセスしたときにその誤差を埋めるためにDPIをコールしてSpikeの設定を上書きする。

  for (auto &iss_rd: p->get_state()->log_mem_read) {
    int64_t iss_wr_val = p->get_state()->XPR[rtl_wr_gpr_addr];
    uint64_t iss_lsu_addr = std::get<0>(iss_rd);
    fprintf(compare_log_fp, "MR%d(0x%0*lx)=>%0*lx\n", std::get<2>(iss_rd),
            g_rv_xlen / 4, iss_lsu_addr,
            g_rv_xlen / 4, iss_wr_val /* std::get<1>(iss_rd) */);
    if (iss_lsu_addr == 0x200bff8) {
      fprintf(compare_log_fp, "==========================================\n");
      fprintf(compare_log_fp, "RTL MTIME (0x2000_bff8) Backporting to ISS.\n");
      fprintf(compare_log_fp, "ISS MTIME is updated by RTL = %0*llx\n", g_rv_xlen / 4, rtl_wr_val);
      fprintf(compare_log_fp, "==========================================\n");
      p->get_mmu()->store_uint64 (0x200bff8, rtl_wr_val);
      p->get_state()->XPR.write(rtl_wr_gpr_addr, rtl_wr_val);
      return;
    }
  }

このようにして、CLINTのmtimeレジスタ (0x200bff8)にアクセスしたときにSpikeのモデルを上書きする。実際に適用されたときはこのようなログが表示される。

4294 : 539 : PC=[0000000080002b54] (M,13,01) 0200c7b7 lui     a5, 0x200c
GPR[15](47) <= 000000000200c000
4294 : 540 : PC=[0000000080002b58] (M,13,02) ff87b703 ld      a4, -8(a5)
MR8(0x000000000200bff8)=>0000000000000042
==========================================
RTL MTIME (0x2000_bff8) Backporting to ISS.
ISS MTIME is updated by RTL = 0000000000000042
==========================================
4300 : RTL(14,1) Exception Cause = CSR Update Flush(27) PC=000080002b5c, Inst=f14027f3, csrr    a5, mhartid
4300 : 541 : PC=[0000000080002b5c] (M,14,01) f14027f3 csrr    a5, mhartid
GPR[15](37) <= 0000000000000000

もう一つの課題は、実際にタイマ割込みが発生したとき、Spikeとの動作を合わせる必要があるということだ。

割込みがMTIPに設定された瞬間にSpikeで割り込みを発生させてしまうと、パイプライン中に存在している命令がコミットを起こしたときに誤差が発生してしまう。 考え方としては、MTIP&MTIEが有効化されたときにフェッチが先が切り替わったとき、それを信号として記憶しておき、コミットが発生したときに同様にSpikeにも割り込みを挿入するという方式だ。

どちらにしろRTLに情報を追加して、コミット時に、割込みが発生したことを示さなければならないだろう。