
前回のRVVLoadの定義に対して、いくつかデバッグをしていた。ドキュメントが数少ないので調べるのが大変なのだが、GDBで一つ一つコードの動きを読んでいく。
命令の定義には大きく分けて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の実装を読み直してみたいと思う。
