FPGA開発日記

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

自作CPUにベクトル命令を追加する実装検討 (22. vsetvl命令の投機実行の見直し)

vsetvli命令を投機的に実行する場合を考える。

デフォルト状態: - head_ptr : 現在のvlvtypeレジスタが、投機的にどこまでエントリを確保しているかを意味する。デフォルト値は0。 - tail_ptr : 現在のvlvtypeレジスタの投機実行が、どこまでコミットされているのかを示す。デフォルト値は0。

vsetvli命令がディスパッチされるたびにhead_ptrをインクリメントし、現在処理を行っているvsetvliを取得する。 例えばhead_ptr=0でvsetvliがディスパッチされると、vsetvli命令以降のベクトル命令はインデックス=0のvlvtypeレジスタの情報を参照するものとする。この時、vlvtype_valid[index=0]=1とし、現在このインデックスは使用中であることを示す。

  • vlvtype_validのassert条件:新たにvsetvli命令がディスパッチされる
  • vlvtype_validのdeassert条件:次に新しいvsetvli命令がコミットされる

vsetvli命令がCSU内で実行されてVL値が確定するたびに、そのインデックスの情報テーブルがアップデートされ、そのテーブルはすでに取得可能であることを示す。これは、vlvtype_ready[index=0]=1とし、このvlvtype情報はすでに確定済みであることを命令に知らせる。

  • vlvtype_readyのassert条件:当該vsetvli命令の実行が完了し、vl/vtype値が確定する
  • vlvtype_readyのdeassert条件:vlvtype_validのdeassert条件と同じ

  • vlvtype投機実行エントリがFull状態の場合:つまり、vsetvli命令が非常に投機的に実行されており、どのvsetvli命令も確定状態ではない場合は、それ以降のvsetvli命令の発行を中止する。これはvlvtype_valid[*]=1である状態を示している。

このとき、投機実行ミスや例外が発生するとどうなるか。

vsetvli (0)
vadd.vv (0)
bne
vsetvli (1)
vadd.vv (1)

ここで、最初のvsetvli(0)がディスパッチされて、直近のvadd.vvがvlvtype[0]の情報をもとに動作するものとし、vsetvli(1)は投機的にディスパッチされて直近のvadd.vvはvlvtype[1]の情報をもとに動作するものとする。

この時点で、上記のhead_ptrは2まで進んでいるものする。

bneが投機実行ミスを発生させた場合:vsetvli(0)およびvadd.vv(0)に動作の影響を及ぼすものではない。したがって、通常通りvsetvli(0)は動作しコミットにより確定する。 一方で、vsetvli(1)は一応動作し確定し、vadd.vvも確定するが、これは動作に影響を与えるものではなく、ROBから削除されるのと同じタイミングポインタは進んでいく。

この時、bneによりやり直しが始まった新たなvsetvli(2)は、head_ptr=2から新たにエントリを確保してもよい。 tail_ptrはROBから削除される際に必ず進むので、矛盾が発生することはない。

ということは、この順番を守っている限りは、命令の投機実行ミスなどをあまり考える必要はないというとか。

以下の問題も同様で、ldにより例外が発生したとしても、ROBから正しく抜けてポインタを進めることができるのであれば、特に矛盾は発生しないということか。

vsetvli (0)
vadd.vv (0)
ld
vsetvli (1)
vadd.vv (1)