NaxRiscvのドキュメントを、改めて位置から読んでみることにしたいと思う。
分岐予測
現在、分岐予測はパイプライン内の二か所で実装されている:
- フェッチ予測 :BTBとGShare予測器で構成されている
- デコード予測 :RAS予測を使用することができ、BTB予測がない場合は静的ジャンプとgshare分岐予測を行うことができる
以下は分岐予測パイプラインの図示である:
フェッチ予測
フェッチステージでは、BTBは与えられたフェッチワードについていくつかの予測を行う。 - ターゲットPC - 命令の性質(分岐かどうか) - 命令の最後の部分がワードのどのスライスであるか(スライスはRVCなしで4バイト、RVCありで2バイト)
この予測を使用し、最終的にはGShare予測を使用して、予測を適用する。
デコード予測
命令がフェッチされると、その段階での予測を改善するために使用できる情報がかなり多く得られる。
フェッチBTB予測がジャンプ/分岐を行わなかった場合、デコード予測は以下のいずれかを行う可能性がある。
- 何も行わない
- 静的ジャンプ(call,j)を適用する
- GShare予測があった場合、その分岐を適用する
- 命令がリターン(ret)の場合、RAS予測を適用する
フェッチBTBがジャンプ/分岐を行った場合、デコード予測は以下を行う可能性がある。
- 命令がジャンプ/分岐でなかった場合、ジャンプ/分岐を元に戻す
- RASが別の値を提供した場合、予測を修正する
- 予測対象が正しかったと仮定する(分岐ターゲットを計算し、それを予測されたPCと比較するのは、組み合わせパスが多すぎる)
その後、予測結果はジャンプ/分岐の循環バッファに格納され、実行ユニットの分岐ロジックによって最終的な修正のために使用される。
RASは再スケジュール時にポインタを修復するが、投機的に更新された値は修復しない。
ジャンプ/分岐用循環バッファ
- Push : デコード予測中
- Read: 実行ユニットが分岐実行中に、最終的に誤った予測分岐を修正する
- Pop: 命令確定後、分岐予測器の学習もトリガーする