TileLinkプロトコルの続き。
まず、以下のような構成にてどのようにキャッシュブロックが移るのかを見ていく。キャッシュを含めてそれぞれのノードにはブロックのコピーが置かれるわけだが、それぞれについて許可できる操作が異なる。
- None:コピーを持っていない
- Read:読み込み専用
- Read + Write:読み込み書き込み可能
となっている。TileLinkはInclusiveコヒーレントツリーなので、上位のブロックがデータを持っている場合、下位のブロックも常にデータを持っていることになる。保持しているブロックの状態は、以下のような属性でカテゴライズできる。
- Nothing:キャッシュのコピーを保持していない状態。読み込みも書き込みもできない。
- Trunk:TipとRootの間にある状態のブロックのことを指す。読み込みも書き込みもできない状態。例えばコアとL3キャッシュの間にあるL2キャッシュに存在するコピーのことを指す。コアが書き込みを行っている可能性があり、データとしては古いため、読み込みも書き込みもできないことになっている。
- Tip (with no Branches):キャッシュコピーを保持している状態かつ、自分のみがそのコピーを持っている状態。読み込みも書き込みもできる状態。
- Tip (with Branches):キャッシュのコピーを保持している。データを書き込んだ後にパーミッションの移動により読み込み専用となっている。
- Branch:キャッシュコピーを保持しているが、読み込み専用となっている。
次に、マニュアルのサンプルを見ながらTileLinkのフローを見ていこう。TileLinkのマニュアルには以下のようなブロックの移動フローが示されている。
この図は、3つのノードが存在していることに注意する。
- MasterA:マスターその1。CPUコア0だと思えばよい。
- MasterB:マスターその2。CPUコア1だと思えばよい。
- Slave:スレーブ。L2キャッシュだと思えばよい。
これらがどのようにしてブロックを転送しあうかどうかについてチェックする。
- MasterAがSlaveに対してAcquire要求を出す(ここではGet要求でないことに注意。Getはブロックの取得というよりデータの取得で、パーミッションは移動しない)。
- 同時に、1. で取得する予定のブロックを確保するためのL1Dキャッシュの余裕がない場合、Release要求をSlaveに対して送出し、キャッシュブロックを破棄する準備を進める。
- このとき、ReleaseDataでないことに注意。もしL1Dキャッシュ内のデータを書き換えている場合はこれをスピルアウトする必要があるが、そうでない場合はRelease要求により単純にそのブロックを捨てる。
- Slaveは必要に応じてさらに上位のキャッシュにアクセスする(たとえばReleaseDataの場合Slaveに受け入れる容量が無い場合など?)
- Slave、つまりL2キャッシュはRelease要求に対してReleaseAckを返す。これにより当該ブロックの権限はSlave側に移り、MasterAはブロックを持っていないことになる。
- SlaveはMasterBに対してProbe信号を送り、当該ブロックを持っているかどうか確認する。
- MasterBはもし当該データが入っているDirtyなブロックを持っている場合、それをSlaveに対してProbeAckで送り返す。
- Slaveは必要に応じてさらに上位のキャッシュにアクセスする(例えば当該ブロックをだれも持っていなかった場合?)
- SlaveはMasterAに対してGrantを送出し、データを渡す。
- MasterAはデータ受け取り、GrantAckを返す。