技術共有

NEMU DiffTest の基本原理

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina


この記事は以下のものに属します「RISC-V 命令セット差動テスト (DiffTest) シリーズ チュートリアル」1、他の記事をチェックすることを歓迎します。

1 DiffTest 原理の簡単な説明

DiffTest の核となる考え方: 同じ仕様に基づく 2 つの実装では、同じ定義された入力が与えられ、それらの動作は一貫している必要があります。
プロセッサの設計に戻ります。riscv マニュアルによる 2 つの実装では、同じ正しいプログラムが与えられた場合、その状態変化 (レジスタ、メモリ) は 2 つの実装で一貫している必要があります。

  • そのうちの 1 つは CPU です。
  • あるいは、リファレンス実装としてシミュレーターを選択します。
    ここに画像の説明を挿入します
    両者は命令の実行を終了するたびに、それぞれのレジスタやメモリの状態を確認し、状態が矛盾している場合には直ちにエラーを報告し、クライアントプログラムの実行を停止します(アサート判定を行うのと同じです)。各指示)。
  • DiffTest = オンラインのコマンドレベルの動作検証方法
    • オンライン = プログラムの実行中に検証します
    • 命令レベル = 実行されたすべての命令が検証される
  • あらゆるプログラムを命令レベルのテストに変換し、ステータスをアサートできます
    • OSなどのサポートプログラムは終了しない
  • 事前に手続きの結果を知る必要はありません
    • プログラムのセマンティクスではなく、命令実行の動作を比較しているためです。

DiffTest の最大の用途は次のとおりです。何百、何千もの命令を実行した後にデコードや実行のバグが発生した場合、最初のエラー命令をどのようにして素早く見つけ出すか、これは地獄レベルの困難です。

この記事では、説明する例として次のものを選択します。

  • 参照オブジェクト (REF) としての QEMU
  • 被験者(DUT)としてのNEMU

もちろん、プロセッサのハードウェアをテストする必要がある場合は、プロセッサを DUT として使用することもできます。

2 NEMU によってサポートされる DiffTest

make menuconfig
  • 1

次のように、「テストとデバッグ」→「差動テストを有効にする」→「リファレンス デザイン」に入ります。

ここに画像の説明を挿入します
NEMU を DUT に使用する場合、リファレンス シミュレータ REF として 5 つのシミュレータ モードを選択できます。

  • QEMU、ダイナミック ライブラリ モード、コードは NEMU/tools/qemu-dl-diff/ にあります。
  • QEMU、ソケット モード、コードは NEMU/tools/qemu-socket-diff/ にあります。
  • KVM の場合、コードは NEMU/tools/kvm-diff/ にあります。
  • ネム
  • スパイク

後の 3 つについては、筆者は特に調査を行っていないため、本稿では紹介しない。

3 QEMU は REF (ダイナミック ライブラリ モード) を作成します

NEMU/tools/を変更できます。qemu-dl-diff/、ダイナミック ライブラリ riscv64-qemu-so にコンパイルされます。
NEMU、動的ライブラリ、および QEMU の関係:
ここに画像の説明を挿入します

  • ダイナミック ライブラリ: riscv64-qemu-so、difftest_xx シリーズの関数インターフェイスをエクスポートします。
  • QEMU: qemu-system-riscv64 実行可能ファイルには、cpu_xx、gdb_xx、および qemu_xx シリーズの関数インターフェイスがあります。
  • NEMU: riscv64-nemu-interpreter プログラムは動的ライブラリを呼び出し、その後 QEMU を呼び出します。

具体的なプロセス:

  • NEMU 実行可能プログラム riscv64-nemu-interpreter は、dlopen 関数を呼び出すことによって riscv64-qemu-so をロードし、後続の呼び出しのために difftest_xx シリーズの関数シンボルを解析します。
  • 次に、NEMU は difftest_init 関数を呼び出して初期化します。
  • difftest_init 関数では、dlopen 関数が再度呼び出され、qemu-system-riscv64 実行可能ファイルがロードされ、cpu_xx、gdb_xx、および qemu_xx シリーズの関数シンボルが解析されます。これらの関数シンボルは、実際には、difftest_xx シリーズの関数の基礎となる実装コードです。 。
  • qemu-system-riscv64 ファイルでは、解析された関数が main 関数であり、difftest_init 関数がそれを呼び出して qemu プログラムを開始します。
  • すべてが正常であれば、qemu 関数を呼び出して命令結果を比較できます。

4 REF 用 QEMU (ソケット モード)

NEMU/tools/を変更できます。qemu ソケット diff/、ダイナミック ライブラリ riscv64-qemu-so にコンパイルされます。
NEMU、動的ライブラリ、および QEMU の関係:
ここに画像の説明を挿入します

  • ダイナミック ライブラリ: riscv64-qemu-so、difftest_xx シリーズの関数インターフェイスをエクスポートします。
  • QEMU: qemu-system-riscv64 実行可能ファイルには、cpu_xx および gdb_xx シリーズの関数インターフェイスがあります。
  • NEMU: riscv64-nemu-interpreter プログラムはダイナミック ライブラリを呼び出します。ダイナミック ライブラリはソケット経由でコマンド パケットを送信し、QEMU がパケットを受信して​​解析し、特定のコマンドに基づいて実行する関数を決定します。

具体的なプロセス:

  • NEMU 実行可能プログラム riscv64-nemu-interpreter は、dlopen 関数を呼び出すことによって riscv64-qemu-so をロードし、後続の呼び出しのために difftest_xx シリーズの関数シンボルを解析します。
  • 次に、NEMU は difftest_init 関数を呼び出して初期化します。
  • difftest_init 関数では、子プロセスが fork() アウトし、execlp 関数を呼び出して QEMU を開始します。一方、親プロセスは実行を継続し、ソケット経由で QEMU に接続し、init_isa 関数を呼び出して初期化します。
  • すべてが正常であれば、ソケットを介してコマンドの結果を比較できます。

参考ドキュメント: