FPGA開発日記

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

RustでRISC-V命令セットシミュレータを作ろう (14. リグレッションテストの全確認)

f:id:msyksphinz:20190224185310p:plain:w400

Rustで作る自作命令セットシミュレータの続き。RV32とRV64でテストはある程度動くようになっているので、ここらでリグレッションテストを通して細かいところを修正していこうと思う。

Rust実装の修正

  • RV32とRV64で微妙に動作が異なる部分

例えばシフト命令の即値シフト量はRV32だと5ビットだが、RV64だと64ビットになる。

            RiscvInstId::SRLI => {
                let shamt_mask = if self.m_xlen == 32 { 0x1f } else { 0x3f };
                let shamt: u32 = (Self::extract_shamt_field(inst) & shamt_mask) as u32;
                let rs1_data_64 = self.read_reg(rs1) as UXlen64T;
                let rs1_data = self.uext_xlen(rs1_data_64 as Xlen64T);
                let data = rs1_data.wrapping_shr(shamt) as Xlen64T;
                let reg_data = self.sext_xlen(data);
                self.write_reg(rd, reg_data);
            }
  • 32ビットと64ビットでのアドレス拡張方法

例えばCSRレジスタの値をそのままメモリのフェッチアドレスとして使用するタイプの処理において、RV32では(一応)64ビットで用意されているレジスタを32ビットの切り落としてメモリアドレスとして活用する必要がある。このためにuext_xlen()関数を使用してアドレス値をRV32とRV64で上手くカットしている。

    fn write_bus_hword(&mut self, addr: Addr64T, data: Xlen64T) -> MemResult {
        return match self.convert_virtual_address(addr, MemAccType::Write) {
            Ok(phy_addr) => {
                // ここでいったんRV32とRV64のモードに応じてアドレスの切り落としを行う。
                let uext_phy_addr = self.uext_xlen(phy_addr as Xlen64T);
                let write_mem_trace = TraceInfo::MemWrite { addr: addr,
                                                            value: data,
                                                            memresult: MemResult::NoExcept };
                self.m_trace.m_trace_info.push(write_mem_trace);
                self.write_memory_hword(uext_phy_addr, data);
                MemResult::NoExcept
            },
            Err(result) => result,
        }
    }

リグレッションテストの実行

リグレッションテストを実行した結果以下のテストがFailとなった。

failures:
    rv64ud_p_fclass
    rv64ud_p_fcmp
    rv64ud_p_fcvt
    rv64ud_p_fcvt_w
    rv64ud_p_fdiv
    rv64ud_p_fmin
    rv64ud_p_ldst
    rv64ud_p_move
    rv64ud_p_recoding
    rv64ud_p_structural
    rv64ud_v_fclass
    rv64ud_v_fcmp
    rv64ud_v_fcvt
    rv64ud_v_fcvt_w
    rv64ud_v_fdiv
    rv64ud_v_fmin
    rv64ud_v_ldst
    rv64ud_v_move
    rv64ud_v_recoding
    rv64ud_v_structural
    rv64uf_p_fclass
    rv64uf_p_fcmp
    rv64uf_p_fcvt
    rv64uf_p_fcvt_w
    rv64uf_p_fdiv
    rv64uf_p_fmin
    rv64uf_p_move
    rv64uf_p_recoding
    rv64uf_v_fclass
    rv64uf_v_fcmp
    rv64uf_v_fcvt
    rv64uf_v_fcvt_w
    rv64uf_v_fdiv
    rv64uf_v_fmin
    rv64uf_v_move
    rv64uf_v_recoding

浮動小数点系がやはり多い。これはhardfloatのサポートを追加していかなければならない。