FPGA開発日記

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

RustでRISC-V命令セットシミュレータを作ろう (6. MMUの実装とテストパタンの実行)

f:id:msyksphinz:20190224185310p:plain

Rustで作るRISC-Vシミュレータ。基本的な形が出来上がった。トレースファイルも出せるようになったので、MMUを実装してテストパタンを実行して確認しよう。 MMUを動かすテストパタンは、rv{32,64}u{imfda}-v-xxxという形で表現されている。-v-というテストパタンが、MMUを使用するテストパタンだ。

MMUの実装自体は、C++で実装したものを流用している。ただし、Rustで実装するにあたりいろいろ修正しなければならない部分が存在した。

  • Rustでdecrementのfor文はどのように記述すればよいのか? MMUアルゴリズムの記述で、levelをderementしなければならない部分がある。とりあえず、あまり綺麗ではないけど以下のように記述した。 もう少し綺麗に書けないものだろうか...
        for level in range(0, init_level).rev() {
            let va_vpn_i: AddrType =
                (vaddr >> vpn_idx[level as usize]) & ((1 << vpn_len[level as usize]) - 1);
...

あとは、MMUのアクセス権限の確認はRead/Write/Execute(Fetch)でケースが異なるのだが、何となくmatchを使っている。この辺ももう少しRustっぽく書けないものだろうか...

        let allowed_access = match acc_type {
            MemAccType::Fetch => (i_type & 0x04) != 0,
            MemAccType::Write => ((i_type & 0x01) != 0) && ((i_type & 0x02) != 0),
            MemAccType::Read => {
                let mstatus: XlenType = self.m_csr.csrrs(CsrAddr::Mstatus, 0);
                let mxr: u8 = Self::extract_bit_field(
                    mstatus,
                    SYSREG_MSTATUS_MXR_MSB,
                    SYSREG_MSTATUS_MXR_LSB,
                ) as u8;
                ((i_type & 0x01) != 0) | ((mxr & (i_type & 0x04)) != 0)
            },
        };

とりあえずパタンをすべて流しなおした。今のところ、全体の9/94パタンがFAILなのでもう少しだ。

2019/03/28追記。ロード命令とストア命令の例外処理が抜けていた。例外処理を追加して無事にすべてのパタンが通過できた。