FPGA開発日記

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

Gem5のチュートリアル "Learning Gem5"をやってみる(17. gem5が提供するキャッシュ・コヒーレンス・プロトコル・プラットフォームrubyについて)

gem5を構成するSimObjectを追加するためのチュートリアルをやってみる。

www.gem5.org

  • gem5記事一覧インデックス

msyksphinz.hatenablog.com


Rubyは、詳細なキャッシュメモリとキャッシュコヒーレンスモデル、および詳細なネットワークモデル(Garnet)を提供するものである。

  • Rubyは、キャッシュの一部分を詳細に記憶し、データの一貫性とネットワークモデルを保つためのソフトウェアである。
  • Rubyは、多種多様なデータ一貫性の実装をモデル化できる柔軟性を持つ。
  • Rubyは基本的に既存のメモリシステムに対する代替品で、完全な互換性はない。
  • 本書では、プロトコルの作成からデバッグ、実行までの手順を説明する。
  • Rubyアーキテクチャは、コントローラという重要な構造で構成され、これはSLICC状態マシンファイルを用いて実装される。
  • SLICC(Specification Language including Cache Coherence)は、コヒーレンスプロトコルを定義するための特定の言語で、".sm"という拡張子を持つ状態マシンファイルである。
  • コヒーレンスプロトコルは複数のSLICC状態マシンファイルで構成され、それらはPythonで書かれたSLICCコンパイラーでコンパイルされる。そして、これらは一連のC++ファイルに変換され、その他のgem5のファイルとともにコンパイルされる。
  • gem5は、一度に一つのコヒーレンスプロトコルのみをコンパイルできる。異なるプロトコルを使用するためには、gem5の再コンパイルが必要である。

MSIキャッシュ・プロトコルの例

  • キャッシュコヒーレンスについての確固たる理解が必要で、これについては指定された参考書を参照することが推奨される。
  • 本章では、MSIプロトコルの実装を行い、その詳細は指定された参考書の特定のセクションに記述されている。

プロトコルの作成の初歩

Import('*')

main.Append(ALL_PROTOCOLS=['MSI'])

main.Append(PROTOCOL_DIRS=[Dir('.')])

ステート・マシンファイルの作成

  • パラメータ
    • SLICCコードから生成されるSimObjectのパラメータ
  • 必要な構造体と関数の宣言
    • 状態、イベント、およびその他多くの状態マシンに必要な構造体を宣言する
  • In portコードブロック
    • (in_port)メッセージバッファからの入力メッセージを見て、どのイベントをトリガするかを決定するコードを含む
  • アクション
    • これらはシンプルな1エフェクトのコードブロック(例えば、メッセージを送る)で、トランジションを通る際に実行される
  • トランジション
    • 開始状態とイベントが与えられた場合に実行するアクションと最終状態を指定する。これが状態マシン定義の肉心の部分である。

まずはステート・マシンを作成する。MSI-cache.smというファイルを作成する。

machine(MachineType:L1Cache, "MSI cache")
    : <parameters>
{
    <All state machine code>
}

MachineType:L1Cacheで、このステート・マシンをL1Cacheと名付けている。SLICCは、その名前を使ってステート・マシンから多くの異なるオブジェクトを生成する。例えば、このファイルがコンパイルされると、キャッシュコントローラーである新しいSimObject: L1Cache_Controllerが出来上がります。また、この宣言にはこのステート・マシンの説明、「MSI cache」も含まれている。

ステート・マシン・パラメータ

ステート・マシンの宣言後に、パラメータを記述している。

machine(MachineType:L1Cache, "MSI cache")
: Sequencer *sequencer;
  CacheMemory *cacheMemory;
  bool send_evictions;

  <Message buffer declarations>

  {

  }

最初に、Sequencerという特別なクラスがある。これはRubyで実装され、gem5とのインターフェースを提供する。Sequencerは、他のオブジェクトからメモリリクエストを受け入れることができるgem5のMemObjectである。SequencerはCPU(または他のマスターポート)からのリクエストを受け付け、gem5のパケットをRubyRequestに変換する。最後に、RubyRequestは状態マシンのmandatoryQueueにプッシュされる。mandatoryQueueについては、in-portセクションで説明する。

次に、CacheMemoryオブジェクトがある。これはキャッシュデータ(つまり、キャッシュエントリ)を保持する。具体的な実装、サイズなどはランタイムで設定可能である。

他の任意のパラメータを指定できます。この場合、bool変数send_evictionsがある。これは、投機的なロードである場合に、ロードをsquashするためにアドレスが追い出されたことをロードストアキューに通知するためのものである。

次に、パラメータブロック(つまり、最初のブラケットの前)に、このステート・マシンが使用するすべてのメッセージバッファを宣言する必要がある。メッセージバッファはステート・マシンとRubyネットワークのインターフェースである。メッセージはメッセージ・バッファを介して送受信される。したがって、プロトコルの各仮想チャネルに対して別々のメッセージ・バッファが必要である。