FPGA開発日記

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

FPNewでの1ビット誤差が発生する場合の検証環境での対応

自作CPUのFPUは、外部IPを使用している。FPNewというIPを使っている。

github.com

FPNewは、簡単に浮動小数点演算を実装できるのだが、これをインテグレートした後に問題を見つけた。

Some compliance issues with IEEE 754-2008 are currently known to exist for the PULP DivSqrt unit (Rounding mismatches have been reported in GitHub issues. This can lead to results being off by 1ulp, and the inexact flag not being properly raised in these cases as well)

つまり、いくつかの演算についてはDivSqrtユニットに問題がありミスマッチが発生する可能性があるということだ。 実際この問題に直結するケースがあり、これを今のところ解決する手段はないので、検証環境側を変更する必要がある。

つまり、当該div命令やsqrt命令が実行された場合は、結果に1ビットの誤差があるときはそれを認め、ISS側にRTLの値を伝搬することで検証を継続させることにする。

    int64_t iss_wr_val = p->get_state()->FPR[rtl_wr_gpr_addr].v[0];
    if (!is_equal_flen(iss_wr_val, rtl_wr_val)) {
      fprintf(compare_log_fp, "==========================================\n");
      fprintf(compare_log_fp, "Wrong FPR[%02d](%d): RTL = %0*llx, ISS = %0*lx\n",
              rtl_wr_gpr_addr, rtl_wr_gpr_rnid,
              g_rv_flen / 4, rtl_wr_val,
              g_rv_flen / 4, iss_wr_val);
      if (abs(iss_wr_val - rtl_wr_val) == 1) {
        float128_t f128_rtl_val;
        f128_rtl_val.v[0] = rtl_wr_val;
        f128_rtl_val.v[1] = 0;
        fprintf(compare_log_fp, "Small Approximation error. Backpropagating to ISS\n");
        p->get_state()->FPR.write(rtl_wr_gpr_addr, f128_rtl_val);
        fprintf(compare_log_fp, "==========================================\n");
        return;
      }
      fprintf(compare_log_fp, "==========================================\n");
      fail_count ++;
      if (fail_count >= fail_max) {
        stop_sim(100, rtl_time);
      }
      return;
    } else {
      fprintf(compare_log_fp, "FPR[%02d](%d) <= %0*llx\n", rtl_wr_gpr_addr, rtl_wr_gpr_rnid, g_rv_flen / 4, rtl_wr_val);
    }

こんな感じで、1ビットの誤差があればそれを認めて、SpikeのレジスタにRTLの値を上書きする。

        float128_t f128_rtl_val;
        f128_rtl_val.v[0] = rtl_wr_val;
        f128_rtl_val.v[1] = 0;
        p->get_state()->FPR.write(rtl_wr_gpr_addr, f128_rtl_val);

これで、とりあえず浮動小数点の検証を継続できるようになった。

GPR[10](109) <= 0000000080002f10
336061 : 371660 : PC=[0000000080002f14] (M,41,02) 4b050513 addi    a0, a0, 1200
GPR[10](135) <= 00000000800033c0
336061 : 371661 : PC=[0000000080002f18] (M,41,04) 1aa477d3 fdiv.d  fa5, fs0, fa0
==========================================
Wrong FPR[15](126): RTL = 40a9114a6e7937b4, ISS = 40a9114a6e7937b5
Small Approximation error. Backpropagating to ISS
==========================================
336061 : 371662 : PC=[0000000080002f1c] (M,41,08) e20785d3 fmv.x.d a1, fa5
GPR[11](126) <= 40a9114a6e7937b4
336061 : 371663 : PC=[0000000080002f20] (M,41,16) 9b5ff0ef jal     pc - 0x64c
GPR[01](87) <= 0000000080002f24
336062 : 371664 : PC=[00000000800028d4] (M,42,01) 0000711d c.addi16sp sp, -96
GPR[02](83) <= 0000000080024130
336062 : 371665 : PC=[00000000800028d6] (M,42,02) 02810313 addi    t1, sp, 40
GPR[06](132) <= 0000000080024158