FPGA開発日記

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

Gem5のインストール試行とベンチマーク実行 (RISC-V命令にベクトル新規命令を追加する3)

前回のRVVLoadの定義に対して、いくつかデバッグをしていた。ドキュメントが数少ないので調べるのが大変なのだが、GDBで一つ一つコードの動きを読んでいく。

seanzw.github.io

命令の定義には大きく分けて3ステップが必要そうだ。

        Fault execute(ExecContext *, Trace::InstRecord *) const override;
        Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override;
        Fault completeAcc(PacketPtr, ExecContext *,
                          Trace::InstRecord *) const override;

execute()は主に算術演算命令に使用される。Load/Store命令ではあまり使用されないようだ。実際、ロード命令でexecute()Invokeするとエラーを出力して終了した。

Execute (IEW::executeInsts()) Here we invoke the execute() function of the compute instruction and send them to commit. Notice execute() will write results to the destiniation register.

initiateAcc()は、メモリアクセスを起動する操作らしい。メモリアクセスリクエストを発行するイメージでよい。

LSQUnit::executeLoad() will initiate the access by invoking the instruction’s initiateAcc(). Through the execution context interface, initiateAcc() will call initiateMemRead() and eventually be directed to LSQ::pushRequest().

つまり、LSQに対してリクエストが挿入されるイメージだ。

completeAcc()は、メモリアクセスが完了してレジスタにデータが書き込まれるイメージだ。

LSQUnit::writeback() will invoke StaticInst::completeAcc(), which will eventually write loaded value to destination register. Then the instruction is pushed to commit queue, so that IEW::writebackInsts() will mark it done and wake up its dependents. Starting from here it shares same path with compute instructions.

これに基づいて、VLE8ベクトルロード命令を考えてみる。

まず、initiateAcc()だが、initiateMemRead()の方法がよくわからない。これはLSQを起動するとしたら、ベクトルアクセス要素数分だけ呼び出さないといけないのかなあ?この辺がよくわからない。

def template RVVLoadInitiateAcc {{
    Fault
    %(class_name)s::initiateAcc(ExecContext *xc,
        Trace::InstRecord *traceData) const
    {
        Addr EA;

        %(op_src_decl)s;
        %(op_rd)s;

        MemElemType memData = 0;

        EA = Rs1;

        return initiateMemRead(xc, traceData, EA, memData, memAccessFlags);
    }
}};

completeAcc()のほうは、一応要素の数だけ書き込みを起こすようにしてみたが、それでも正しく動作しているのかよくわからない。

def template RVVLoadCompleteAcc {{
    Fault
    %(class_name)s::completeAcc(PacketPtr pkt, ExecContext *xc,
        Trace::InstRecord *traceData) const
    {
        Addr EA;

        %(op_decl)s;
        %(op_rd)s;

        EA = Rs1;

        MemElemType memData = 0;

        {
           for (int i = 0; i < 16; i++) {
               getMemLE(pkt, memData, traceData);
           }
        }

        %(memacc_code)s;
        %(op_wb)s;

        return NoFault;
    }
}};

なんか違うなあ。そもそもロード命令としてVLE8を定義するのが間違ってるのかなあ。もう一度SVEの実装を読み直してみたいと思う。