Ryuz's tech blog

FPGAなどの技術ブログ

ストールしないテクスチャキャッシュ

はじめに

Verilator を試すのに昔書いたRTLソースを発掘していたら、かなり昔書いたGPU用のテクスチャサンプラーとテクスチャキャッシュが出てきました。

こんなことやってたころに作ったやつだと思いますが、記事にしたことが無かったと思いますので、少し書いてみようと思います。

ストールさせたくない

例えば、グラフィックス描画の帯域の 1/10 しか DDR-SDRAM の帯域が無かったとしてもキャッシュヒット率が90%以上であれば、後段の回路を休ませることなくスループット1/1で途切れることなく毎クロックデータを出力してほしくなります。

その時に一般的なメモリキャッシュだとキャッシュミスが起こると、そこからアクセスが発生してキャッシュフィルまでストールしてしまいパイプラインにバブルが発生してしまいます。

最近のCPU等であれば、キャッシュミスをしてもその間に後続の依存の無い命令がどんどん実行されていったり、そもそもミスする前に予測して先読みしたり、いろんな複雑な仕組みでCPU停止時間を極力抑える工夫があったりするわけですが、あまり難しいことをせずに安直に効率を上げたいなと思ってトライしたのが当時のRTLです。

何をやったのか

キャッシュメモリには、キャッシュメモリの各ラインにどのアドレスのデータをキャッシュしているか(あるいはしていないか)を保持する為のtagRAMがあります。これはキャッシュ本体に比べるととても小さいサイズで、分散メモリでの実装が適していたと記憶しております。 tagRAM内に目的のアドレスが含まれているかどうかで、キャッシュのヒット/ミスヒットが判定されます。ミスヒットの時にはキャッシュをリフィルする為、tagRAMには新しいアドレスが格納されます。とにもかくにもtagRAMさえ操作すればヒット/ミスヒットの判断とその後格納されるべきデータのアドレスを確定することができます。

このtagRAMを2つ用意して、下記のようにFIFOを挟んで1個に先行してアドレスを入力する事にしました。そうすると時間だけずれて全く同じ動きをするtagRAMが2つ出来上がります。

ここで1個目のtagRAMでキャッシュミスが予測された段階でAXI4バスのアドレスチャネルにアクセス要求を投げ込みます。そうするとFIFOで遅延された後に実際にキャッシュにアクセスすると同じようにミスするわけですが、その時にはもうリード済みのデータがそこまで来ているのでストール時間ゼロで読み出せるわけです。

もちろんやり方はこのほかにもいろいろあるとは思うのですが、とても安直な方法のわりに、そこそこ効果的に動いてくれましたのでネタ程度に記事しておければと思います。

テクスチャキャッシュにはWriteはなくReadOnlyだからできることですね。

なおソースコードこのへんに転がっています(長らくメンテしてなかったので、合成や動作も非常に怪しいですが)。

Verilator の出力

もともと回転時のアクセス効率アップのためにこんなことをしていたのもあって、回転アクセスについてテストベンチ作っていたのですが、Verilator でもちゃんと動き始めました。

が、トレース等のオプション付けないとうまく動いてくれておらず、あまり速くなっていなかったり(汗) まだまだ怪しいバグがRTLに残っていそうですね。