FPGA開発日記

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

A64FXのロード・ストア命令の処理について読み解く

いろいろあってA64FXのロード・ストア命令、Gather/Scatter命令がどのように動作するのかを調査している。

github.com

ちょっと予想で書いていることが多い。

ロード命令とストア命令で使用されるキュー(ポート)

A64FXでは、キューのことをポートと呼んでいる部分がある。

まず、Virtual Fetch Port(FP)は「ロード・ストア命令の順序のみを管理するためのキュー」とある。 どうも動作フローを眺めているとVFP自体にアクセス・アドレスを管理する能力はなく、「インオーダ割り当て・インオーダ解放」とあるので、ある種のリオーダ・バッファのような役割で、命令の解放する順序を管理しているのではないかと予想する。

もう一つ、アクセス順序を管理するReal Fetch Port(RFP)は、ロード・ストアのオペレーションフローが発行されるときにアウト・オブ・オーダで割り当てられるとあるので、これは動的に割り当てられるみたいだ。

RFPはメモリアクセスの順序を管理するとあり、「EAGA / EAGB から投入された LD フローは、調停スケジューラにて選択されるとペナル ティなく 0 / 1 番パイプラインに投入される。同時に RFP のエントリに実効アドレスを書き込む。」とあるので、アドレスが決定次第動的に割り当てられてアドレスが書き込まれるのではないかと予想する。

RFPは発行能力自体を持っており、EAGA/EAGBからのメモリアクセスリクエストがパイプラインで選択されない場合は再発行の役割を持っているみたいなので、ある種Replay QueueとLDQの両方の役割を持っているようなイメージを持っている。

解放の手順は、先行のロードが完了していれば解放されるとある。先行のロード、というよりは、当該ロード命令がUncommitted Oldestになると解放されるのではないかと予想する。 理由としては、後述するストア命令からのパイプラインフラッシュに対応するためには、古いストア命令の実行が完了するまで解放してはならないからだ。

ストア命令の処理でも同様に、VSP(Virtual Store Port)とRSP(Real Store Port)が用意されており、その役割は同じのようだ。 ただし、ストア命令はVSPとVFPの両方に割り当てが行われるようだ。 なんでVFPのみで順序を管理せず、VSPにも割り当てを行うのかについてはよくわからない。 予想ではあるが、コミット後のWriteBack Bufferへのデータ移送の際、ロード命令も混じっているVFPを使うとポインタのアップデートが遅くなるので、ストア命令のみを持つバッファを持っているのでは?

リオーダリングのための構成

リオーダリングのために、以下の2つの構造を持っている

  • Store Fetch Interlock (SFI)

要するに、先行ストア命令の物理アドレスが確定している場合、後続のロード命令がパイプラインに投入された際にそれをチェックし、アドレスが一致すると実行をキャンセルする。 ただしこれではアドレスが一致した場合当該ロード命令が完全に停止するので、そうしないためにStore Fetch Bypass、要するにストア・ロード・フォワーディングが実装されているようだ(これにもフォワーディングできるペアに制約はあるが)。

  • パイプライン・フラッシュ

先行するストアが未確定である場合、後続のロード命令は投機的に動作する。 その代わり、ストア命令は実行時にロード命令の実行アドレス(要するにRFPの中身?)をチェックし、順序違反を検出すれば当該ロード命令を含めてフラッシュする。

Gather Scatter命令の実装

Gather Scatterは複数のアドレスを管理するため大変である。 これらの命令は複数のFP/SPを使って管理されているようで、FP(おそらくこの文脈ではRFP)は1命令で最大16個消費される。 RFPのエントリ数は40エントリなので、1命令でかなりの量のエントリを消費することになる。 Scatter命令に至っては最大でFP/SPを16エントリずつ消費し、RSPのエントリ数は24エントリなので、簡単にリソースを使い切ってしまうだろう。

まず、Gather/Scatterのアドレス計算はベクトル演算器を使って行われる。計算結果の実行アドレスはFP/SPに保存され、スカラ命令と同様にメモリ・アクセス・パイプラインを流れる。

さらに、Gather命令は個別のアドレスの分解を行っているのだが、フロー数を削減するために2段階での分解を行っている。 隣り合わせの要素が128バイトの境界に入っているならばそれを1ペアとして扱っているようだが、この判定をどこでやっているのかは不明だ。 1ペアとして扱うことが分かれば、そもそもFP/SPを1エントリしか確保しないのか、後でマージ操作をするのかはよくわからない。とにかく、2つのアドレスを1回のフローで処理できるように工夫がしてある。

ただし、2つのアドレスを1つのFPで管理しているので、上記のパイプライン・フラッシュの判定単位はかなり広くなる。

また、Gatherとは直接関係ないがベクトルロード命令の場合もパイプライン・フラッシュの判定範囲は4バイト単位となり、例えば4バイト未満の境界でベクトル命令によるメモリコピーとかをすると、頻繁にフラッシュが発生するのではないかと予想する。

とにかく、Gatherを動かすためにはかなりの量のフローが動作し、さらに多くのリソースを消費するということだ。