FPGA開発日記

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

L1データキャッシュの実装設計(LSUとの接続部の検討)

L1データキャッシュは、L1命令キャッシュと違って書き込みにも対応する必要がある。もちろん、LSUもReadとWriteを同様に対応しなければならないのだが、いくつかの問題にぶち当たった。

一般的なLSUの構成

一般的なLSUの構成は、Hisa Ando氏の本にあるように、以下のような構成を取るものが一般的である。

高性能コンピュータ技術の基礎

高性能コンピュータ技術の基礎

f:id:msyksphinz:20161116013833p:plain

LSUは、データの一貫性を保つために、ロードとストアの順番について制限がある。 - (基本的に)ストアは順番に実行する。 - (命令的に)ロードの前にストアを実行する。

このようにしないと、同じアドレスにおいてストア命令がロード命令に追い抜かされてしまう場合が発生し、データがメモリに書き込まれる前にロードをしてしまい、誤ったデータをロードしてしまう可能性がある。

上記のロードキューとストアキューを別々にした場合にも当該の問題が発生する可能性がある。 つまり、ロード側のキューが掃けるのが先の場合、ストア命令よりもロード命令が先に実行される可能性があり、その結果データが正しく読み込まれない場合が発生する。

この場合に備えて、ストア側のキューからロード側のキューへフォワーディングする機構が存在する(メモリディスアンビギュエーション)。

しかし、そもそもこの上記の図は、メモリに対してロードとストアが同時に発行できることが前提だ。では、L1キャッシュがロードとストアを1つのポートから実行しなければならない場合、どのように実装すべきか?

L1キャッシュの口がロードとストアで共通の場合

この場合、そもそも上記のようにロードキューとストアキューを別々に分けるのはナンセンスということになる。 どちらのキューからリクエストを出すのか選別しなければならなないし、それを実現しながらメモリの一貫性を保つ必要がある。

そうすると、一つのメモリキューからリクエストを出すのだが、これがやっかいだ。

下記はそのようなロードストアキューを表現してみた。この場合、インデックスは昇順で進んでいき、Index=2のストア命令を実行中。ただしコミットはIndex=3まで確定。 それより先の命令はまだコミット未確定ということになる。

f:id:msyksphinz:20161116015817p:plain:w400

ストア命令は、メモリ(まずはL1キャッシュ)にリクエストを出すのは、その命令が確定するまで、つまりコミットが発生しないと進めることができない。 一方でロード命令は、メモリにリクエストを出すのはコミットを待つ必要がない。このため、自由にメモリへのリクエストを出しつつ、フラッシュで破棄される場合はリオーダバッファをクリアするだけで良い、という訳だ。

そうすると、パイプラインフラッシュが発生した場合に、どこまで命令キューを元に戻すかという問題がある。

  1. ストア命令が完了して、ストア処理を実行中の場合→ストアロードキューの先頭ポインタを元に戻す必要はない。ストアは命令コミット確定後の操作のため、そのまま実行し続ける
  2. ロード命令が実行されている場合→当該ロード命令は破棄すべき。確定したコミット位置まで戻す必要あり。

そうすると、結局上記のExeIndexをどこまで戻せば良いのか?ということになる。きちんと定式化できたとしても、実装するのはかなり複雑になるのではないか。

一つの解決策

そもそもロード命令とストア命令の実行が確定するタイミングが上記の1.と2.で異なる。 これが問題なのであって、ロード命令であっても、ロードオペランドが確定した時点で(メモリアクセスを実行する前でも)、仮のコミットを発生してしまう。

このコミットが発生すると、ロード命令が確定され、フラッシュ対象から外れる。 このフラッシュ対象から外れたロード命令はかならず実行されるため、実行タイミングとしてはストア命令と同一になり、キューの管理が楽になる。

f:id:msyksphinz:20161116020446p:plain:w400

二つめの解決策

最初からロードとストアのキューを分け、メモリディスアンビギュエーションを実装する。 さらに、L1キャッシュの制御ステートマシンを複製し、メモリのリード用ポートとライト用ポートを分離する。 これによりL1キャッシュはロードとストアを別々のステートマシンで同時に処理できるようになる。

問題は、タグメモリとデータメモリを、デュアルポート化して、ロードとストアを同時に処理できるようにならなければならない。 f:id:msyksphinz:20161116020814p:plain

追記: 二つめの解決策はダメだ。もし同時にミスを検出した場合、やはりどこかで外部のインタフェースのためにリクエストを一本に統一する必要がある。 結局どこで一本に統一するかの違いだけであって、一つめの解決策が実装のし易さについても有 利な気がする。