FPGA開発日記

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

命令セットシミュレータにおける命令のデコードと実行

大概の命令セットシミュレータは同様の構成を取っていると思うが、命令セットシミュレータといえど * 命令デコード * 命令実行 というハードウェアと同じことをしているのは変わらない。 自作シミュレータも多分に漏れず、以下のような構成を取っている。

f:id:msyksphinz:20150623020506j:plain

このときに、命令デコーダから一意にデコードキーを受け取り、それを元に命令実行フェーズに移る。 デコードキーを受け取ると、命令実行については、デコードキーにもとづいた関数ポインタ配列を使っている。

class InstEnv {

private:
    RiscvEnv *m_env;

public:
    InstEnv (RiscvEnv *env);

    typedef void (InstEnv::*InstFunc) (Word_t inst_hex);
    static const InstFunc m_inst_exec_func[];


    void RISCV_INST_LUI (Word_t inst_hex);
    void RISCV_INST_AUIPC (Word_t inst_hex);
    void RISCV_INST_JAL (Word_t inst_hex);
...
};

const InstEnv::InstFunc InstEnv::m_inst_exec_func[] = {
    &InstEnv::RISCV_INST_LUI,
    &InstEnv::RISCV_INST_AUIPC,
    &InstEnv::RISCV_INST_JAL,
    &InstEnv::RISCV_INST_JALR,
    &InstEnv::RISCV_INST_BEQ,
    &InstEnv::RISCV_INST_BNE,
    &InstEnv::RISCV_INST_BLT,
    &InstEnv::RISCV_INST_BGE,
    &InstEnv::RISCV_INST_BLTU,
    &InstEnv::RISCV_INST_BGEU,
    &InstEnv::RISCV_INST_LB,
    &InstEnv::RISCV_INST_LH,
    &InstEnv::RISCV_INST_LW,
    &InstEnv::RISCV_INST_LBU,
    &InstEnv::RISCV_INST_LHU,
    &InstEnv::RISCV_INST_SB,
...
};

で、これをC++でどうやって実現しようかというと(C言語ならクラスの改造構造を考えなくてもいいけど、C++だとどう実装するかが問題だ...)、

qiita.com

ロベールのC++入門講座

ロベールのC++入門講座

あたりを参考に実装している。基本的な構造は、

class RiscvEnv {
   CsrEnv  *m_csr_env;    // CSRシステムレジスタの階層
   InstEnv *m_inst_env;   // 命令実行の階層

   ...
};

InstEnv内は上記の命令毎の実装を記述している。1命令実行する度に、命令をメモリからフェッチ、デコード、デコード結果を関数ポインタに引き渡している。 基本的な構成はこれで大丈夫なはずだけど、とりあえず、まだ動かないなあー...