自作CPUにベクトル実行エンジンを追加する試行をしている。
vl/vtypeレジスタはリネームをしないとなかなか性能的に厳しい。これを実現するための方法についていろいろ考えている。
ベクトル拡張命令で使用されるvlレジスタとvtypeレジスタは、プロセッサ内でリネームされる。
このため、vl/vtypeレジスタを複数用意し、リネーム・ステージにおいてどのレジスタを使うかを割り当てる。
割り当てられたvl/vtypeレジスタのインデックスを、vlvtype_ren_idx
と呼ぶ。
まず、リネーム・ステージにおいてvsetvl系命令が検出されると、vl/vtypeレジスタ群のうち、1つのエントリが割り当てられる。
このvl/vtypeレジスタは基本的にシーケンシャルにアップデートされるので、vlvtype_ren_idx
もシーケンシャルに割り当てられる。
以降のベクトル命令は、ディスパッチ時に現在のvlvtype_ren_idx
の最も最近割り当てられたエントリのインデックスが返される。
vsetvl命令は、リネーム・ステージを通過するたびにに固有のvlvtype_ren_idx
が割り当てられる。
後続のベクトル命令は直近で割り当てられたvlvtype_ren_idx
を渡され、そのインデックスのvlvtype_ren_idxがreadyになるまで待つ。
つまり、そのvlvtype_ren_idx
を持つvsetvl命令が計算を完了するまで、当該インデックスを持つベクトル命令はスケジューラ内で待機する。
CSUパイプラインによってvsetvl命令が処理され、vlとvtypeが算出されると、vlvtype_upd_ifインタフェースを通じて、ベクトル命令発行ユニットに通知される。
また、vsetvl命令が計算を完了すると、そのvlvtype_ren_idxに相当するエントリのreadyが1に設定され、以降のベクトル命令で同一vlvtype_ren_idxを参照するときはready=1で、vsetvlの完了を待つ必要がない(すでに計算済み)。
また、vsetvlによるvlvtypeアップデート時に、1つ前のvlvtype_ren_idxは無効化される。
ここまでを少し例でまとめる。
下記のようなベクトル命令のアセンブリがあるとする。
vsetvli x10, x20, e32, m1 vadd.vv v10, v11, v12 vsub.vv v10, v12, v13 vsetvli x10, x20, e64, m2 vle32.v v30(x10) vle32.v v14(x11)
vlvtype_ren_idx
は以下のように割り当てられる。
(0) vsetvli x10, x20, e32, m1 (0) vadd.vv v10, v11, v12 (0) vsub.vv v10, v12, v13 (1) vsetvli x10, x20, e64, m2 (1) vle32.v v30(x10) (1) vle32.v v14(x11)