FPGA開発日記

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

自作CPUの現状のフロントエンド構成をまとめる

これは、GShareを久しぶりに実装しようとするといろんな事を忘れており忘れてしまっているので思い出すためのメモ。

ちなみに、以下でまとめる現状のフロントエンド構成は非常に良くないと思う。 実デザインではやってはいけない古めかしい構成だと思うので、真似しないように。 あわよくば、知っている人がちゃんとした構成を教えてくれると嬉しい。

基本的にフロントエンドはs0からs2までの3ステージでフェッチと分岐予測が終わるようになっている。 命令フェッチにおいては、

  • s0ステージ: 命令フェッチリクエストを発行する。TLBにアクセスする。命令キャッシュにアクセスする
  • s1ステージ: 命令フェッチ途中
  • s2ステージ: 命令が返される。それとともに命令バッファに格納する

問題は分岐予測の方で、以下のステージ構成となっている。

  • s0ステージ: BTBやBIMへアクセスする
  • s1ステージ: BTBの結果を返す。ヒット・ミスを判定する
  • s2ステージ: 命令バッファに結果を格納する

で、RASの方はCALL/RETの判定をしないといけないので、現在は命令キャッシュから命令の取得可能なs2ステージを全部把握してRASを操作している。 しかし、図を見て分かる通りs2ステージの仕事が多すぎてタイミングをうまくMETできないと思う。だからこのやり方はおそらく間違っている。

考えられるのは、s0ステージでのBTBでCALL/RETの情報を取得してそれを活用することだが、これはつまりs2ステージの実際の命令フェッチ情報を予測する、ということになるのか。 で、ココまで書いておいて気がついたのは、別にs0のBTBの情報自体は命令自体の書き換えが発生しない限りは(まあこの場合は命令キャッシュごとフラッシュしなければならないのだけれども)、通常の場合はBTBにCALL/RETの情報を格納しておいてこれを活用して良い、ということだと思う。

で、この場合s2ステージで命令キャッシュの情報を用いてCALL/RETを検出するかどうか、という話で、

  • する場合: ステージの負荷が大きすぎるのは変わらない。もう1ステージ増やすか?
  • しない場合: s0で検出できないCALL/RET命令についてはRASを更新できない。ストラテジを考え直す必要がある。

現状では「する場合」で行っておりしたがってAssertionでRASの状態更新を完全にチェックできるようにしている。「しない場合」にすると回路の負荷は減るがRASが正しく動作するかどうかの検証が面倒だ。

と、ココまで考えて、次にGShareの話に戻す。 GShareは最初にPC仮想アドレスに基づいてBHRとのXOR演算を行い、BIMのインデックスとして予測器を読み出す。 で、実際にBIMの値と、BTB内にConditional Branchの情報を仕込んでおいて、これが本当に一致するかを確認しないといけない。 これのあとに分岐予測を行うということだ(これを書いていると、意外とできるのでは、と楽観的な気持ちになってきた)。