Skip to content

エミュレーション

Ryota Shioya edited this page Mar 24, 2022 · 2 revisions

dst/仕様/シミュレーション/エミュレーション.md

はじめに

  • エミュレータ
    • 実際の演算やメモリ・アクセス,システムコールなどの動作を実現する
  • ここでは投機的/Out-of-orderにエミュレーションを実行するための仕組みについて説明

基本的なエミュレーションの仕組み

  • 鬼斬では,シミュレータ側ドリブンでエミュレーションを実行する
    • シミュレータ側において,エミュレータより命令のOpコードやオペランド番号などの情報を取得し(デコード),
    • それらの情報と,演算に使用する値等のコンテキストを合わせてエミュレータに与える事によって,演算結果を得る

エミュレータ

  • 主な役割
    • PCに対応した命令情報の取得
    • 演算の実行
    • システム・コールの再現
    • メモリ・イメージの管理保持

命令

  • 命令を,動的な情報と静的な情報にわけて処理する
    • 静的な情報(OpInfo)
      • Opコード,オペランドの個数など
    • 動的な情報(OpStateIF)
      • レジスタ値や分岐方向などのコンテキストを格納する
      • エミュレータでは,静的な情報を用いてこれの更新を行う
      • PCもこっちに入る

実行の流れ

鬼斬では,シミュレータ側ドリブンでエミュレーションを実行する

  • 命令の静的な情報の取得(デコード)
    • 命令アドレスに対応するマイクロ命令群を取得
      • Fetcher::Simulate() -> m_emulator->GetOp(pc)
  • Out-of-Order実行
    • 静的な情報(opInfo)を元にして動的な情報(opState)を更新
      • opStateには,ソース・オペランドの値も入っている
      • OpExecuteEvent -> Op::Execute() ->Emulator::Execute( opState, opInfo )
  • リタイア
    • ストアの場合,ストア・バッファからエミュレータ側メモリ・イメージへの反映を行う

投機実行

  • 通常の演算命令(レジスタのみにアクセス)
    • レジスタについてはシミュレータ側でリネーミングや回復が行われるため,Out-of-Order に実行しても構わない
  • メモリ・アクセスについては,シミュレータ側に実装されたストア・バッファによって投機が実現される
    • エミュレータ側が持つメモリ・イメージには確定状態のみが反映される
  • システム・コールは不特定かつ複数のメモリ・ロケーションを操作しうるため,シリアライズして実行

メモリ・アクセスの投機実行

  • 実装としては,エミュレーションの実現コード内からシミュレーション側に制御を戻すことにより実現
    • エミュレーション内からOpStateIF::Write/Read を呼ぶ
      • ストアの場合,エミュレーション側のメモリ・イメージに直接反映を行うのではなく,一旦ストア・バッファにいれる
      • ロードの場合,投機的に行われたストアの内容を考慮した値をシミュレータ側から戻す

ロード

  1. Op::Execute() ->
  2. (エミュレータ内のLoad実現コード) ->
  3. OpStateIF::Read() ->
  4. MemOrderManager::Read() -> # 場合によっては,ここでストアバッファから値を取得
  5. m_emulator->GetMemImage()->Read()

ストア

ストアの動作は命令の実行とリタイアに分けられる

  • 実行時
  1. Op::Execute() ->
  2. (エミュレータ内のStore実現コード) ->
  3. OpStateIF::Write() ->
  4. MemOrderManager::Write() #シミュレータ側のストアバッファに格納
  • リタイア時
  1. MemOrderManager::Commit() ->
  2. m_emulator->GetMemImage()->Write() # ストアバッファから書き込み

システム・コール命令の実行

  • システム・コール呼び出しの1命令によってシステム・コールによる動作を全て行ったかのように扱う
    • 依存元/先のメモリ・アドレスについてはわからないため,投機実行は行わずにシリアライズして実行する
  • シリアライズ
    • システム・コール命令を実行する場合,常にコア内にシステム・コール命令が1つしかない状態に保つ
      • 上流の命令が全てリタイアするまで,システムコール命令をフェッチしない
      • コア内にシステム・コール命令があった場合,命令をフェッチしない
Clone this wiki locally