FPGA開発日記

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

RustでRISC-V命令セットシミュレータを作ろう (3. 乗除算命令の実装とWrapping処理)

f:id:msyksphinz:20190224185310p:plain

Rustで作るRISC-Vシミュレータ。基本的な形が出来上がったので、次に命令を追加してテストパタンをパスさせていく。 次に追加するのは乗除算命令だ。RV32には以下のテストパタンが用意されているので、それぞれ実装していく。

  • rv32um-x-mulhsu
  • rv32um-x-mulh
  • rv32um-x-rem
  • rv32um-x-mulhu
  • rv32um-x-mul
  • rv32um-x-remu
  • rv32um-x-div
  • rv32um-x-divu

github.com

それぞれで実装していくうえで気を付けなければならないのはWrappingだ。いろんな実装を見ていると、Wrappingした演算を実現するためにはもう少しきれいな記法があることが分かった。

             RiscvInst::ADD => {
                 let rs1_data = self.read_reg(rs1);
                 let rs2_data = self.read_reg(rs2);
-                let reg_data:XlenType = (Wrapping(rs1_data) + Wrapping(rs2_data)).0;
+                let reg_data:XlenType = rs1_data.wrapping_add(rs2_data);
                 self.write_reg(rd, reg_data);
             }

これでテストパタンを書き直す。MUL,DIV,REMについてもWrappingした演算が定義されているのでとても便利だ。

  • DIV
                let reg_data: XlenType = rs1_data.wrapping_mul(rs2_data);
  • MUL
                    reg_data = rs1_data.wrapping_div(rs2_data);
  • REM
                    reg_data = rs1_data.wrapping_rem(rs2_data);

これでテストパタンを実行した。無事にPASSすることが確認できたぞ。

PASS : ./riscv-tests/isa/rv32ui-p-sll.bin
PASS : ./riscv-tests/isa/rv32ui-p-jal.bin
PASS : ./riscv-tests/isa/rv32ui-p-lhu.bin
PASS : ./riscv-tests/isa/rv32ui-p-slti.bin
PASS : ./riscv-tests/isa/rv32ui-p-sra.bin
PASS : ./riscv-tests/isa/rv32ui-p-sh.bin
PASS : ./riscv-tests/isa/rv32ui-p-blt.bin
PASS : ./riscv-tests/isa/rv32ui-p-and.bin
PASS : ./riscv-tests/isa/rv32ui-p-andi.bin
PASS : ./riscv-tests/isa/rv32ui-p-xor.bin
PASS : ./riscv-tests/isa/rv32ui-p-sltu.bin
PASS : ./riscv-tests/isa/rv32ui-p-bge.bin
PASS : ./riscv-tests/isa/rv32ui-p-jalr.bin
PASS : ./riscv-tests/isa/rv32ui-p-bne.bin
PASS : ./riscv-tests/isa/rv32ui-p-srai.bin
PASS : ./riscv-tests/isa/rv32ui-p-lw.bin
PASS : ./riscv-tests/isa/rv32ui-p-bltu.bin
PASS : ./riscv-tests/isa/rv32ui-p-lbu.bin
PASS : ./riscv-tests/isa/rv32ui-p-beq.bin
PASS : ./riscv-tests/isa/rv32ui-p-ori.bin
PASS : ./riscv-tests/isa/rv32ui-p-lui.bin
PASS : ./riscv-tests/isa/rv32ui-p-sltiu.bin
PASS : ./riscv-tests/isa/rv32ui-p-srli.bin
PASS : ./riscv-tests/isa/rv32ui-p-add.bin
PASS : ./riscv-tests/isa/rv32ui-p-slt.bin
PASS : ./riscv-tests/isa/rv32ui-p-lh.bin
PASS : ./riscv-tests/isa/rv32ui-p-fence_i.bin
PASS : ./riscv-tests/isa/rv32ui-p-slli.bin
PASS : ./riscv-tests/isa/rv32ui-p-xori.bin
PASS : ./riscv-tests/isa/rv32ui-p-addi.bin
PASS : ./riscv-tests/isa/rv32ui-p-bgeu.bin
PASS : ./riscv-tests/isa/rv32ui-p-srl.bin
PASS : ./riscv-tests/isa/rv32ui-p-sw.bin
PASS : ./riscv-tests/isa/rv32ui-p-simple.bin
PASS : ./riscv-tests/isa/rv32ui-p-auipc.bin
PASS : ./riscv-tests/isa/rv32ui-p-sb.bin
PASS : ./riscv-tests/isa/rv32ui-p-or.bin
PASS : ./riscv-tests/isa/rv32ui-p-lb.bin
PASS : ./riscv-tests/isa/rv32ui-p-sub.bin
PASS : ./riscv-tests/isa/rv32um-p-mulhsu.bin
PASS : ./riscv-tests/isa/rv32um-p-mulh.bin
PASS : ./riscv-tests/isa/rv32um-p-rem.bin
PASS : ./riscv-tests/isa/rv32um-p-mulhu.bin
PASS : ./riscv-tests/isa/rv32um-p-mul.bin
PASS : ./riscv-tests/isa/rv32um-p-remu.bin
PASS : ./riscv-tests/isa/rv32um-p-div.bin
PASS : ./riscv-tests/isa/rv32um-p-divu.bin