Ide inti DiffTest: Untuk dua implementasi berdasarkan spesifikasi yang sama, dengan masukan yang ditentukan sama, perilakunya harus konsisten. Kembali ke desain prosesor, untuk dua implementasi menurut manual riscv, dengan program yang sama dan benar, perubahan statusnya (register, memori) harus konsisten untuk kedua implementasi:
Salah satunya adalah CPU kita;
Alternatifnya, pilih simulator sebagai referensi implementasi. Setiap kali kedua belah pihak selesai menjalankan instruksi, mereka memeriksa status register dan memori masing-masing. Jika mereka menemukan bahwa statusnya tidak konsisten, mereka segera melaporkan kesalahan dan menghentikan eksekusi program klien (setara dengan membuat penilaian tegas untuk program klien). setiap instruksi).
DiffTest = Metode verifikasi perilaku tingkat perintah online
Online = Verifikasi saat menjalankan program
Level instruksi = setiap instruksi yang dijalankan diverifikasi
Dapat mengubah program apa pun menjadi pengujian tingkat instruksi dan menegaskan status
Mendukung program yang tidak akan ada habisnya, seperti OS
Tidak perlu mengetahui hasil dari prosedur ini terlebih dahulu
Karena kita membandingkan perilaku eksekusi instruksi, bukan semantik program
Kegunaan terbesar DiffTest adalah:Ketika bug decoding atau eksekusi terjadi setelah menjalankan ratusan atau ribuan instruksi, bagaimana kita dengan cepat menemukan instruksi kesalahan pertama? Ini adalah tingkat kesulitan yang sangat tinggi.
Dalam artikel ini, kami memilih yang berikut ini sebagai contoh untuk diilustrasikan:
QEMU sebagai objek referensi (REF)
NEMU sebagai subjek tes (DUT)
Tentu saja, jika Anda perlu menguji perangkat keras prosesor, prosesor tersebut juga dapat digunakan sebagai DUT.
2 DiffTest didukung oleh NEMU
make menuconfig
1
Masuk ke Pengujian dan Debugging -> Aktifkan pengujian diferensial -> Desain referensi, sebagai berikut:
Saat NEMU digunakan untuk DUT, Anda dapat memilih 5 mode simulator sebagai referensi simulator REF.
QEMU, mode perpustakaan dinamis, kode terletak di NEMU/tools/qemu-dl-diff/
QEMU, Mode soket, kode terletak di NEMU/tools/qemu-socket-diff/
KVM, kodenya terletak di NEMU/tools/kvm-diff/
NEMU
PAKU
Untuk tiga yang terakhir, penulis belum melakukan penelitian khusus sehingga artikel ini tidak akan memperkenalkannya.
3 QEMU membuat REF (mode perpustakaan dinamis)
Anda dapat mengubah NEMU/alat/qemu-dl-diff/, dikompilasi ke dalam perpustakaan dinamis riscv64-qemu-so. Hubungan antara NEMU, perpustakaan dinamis, dan QEMU:
Pustaka dinamis: riscv64-qemu-so, yang mengekspor rangkaian antarmuka fungsi difftest_xx.
QEMU: Dalam file yang dapat dieksekusi qemu-system-riscv64, terdapat antarmuka fungsi seri cpu_xx, gdb_xx dan qemu_xx.
NEMU: Program juru bahasa riscv64-nemu memanggil perpustakaan dinamis, yang kemudian memanggil QEMU.
proses spesifik:
Program NEMU yang dapat dieksekusi riscv64-nemu-interpreter memuat riscv64-qemu-so dengan memanggil fungsi dlopen, dan menguraikan simbol fungsi seri difftest_xx untuk panggilan berikutnya.
Kemudian, NEMU memanggil fungsi difftest_init untuk menginisialisasi.
Dalam fungsi difftest_init, fungsi dlopen akan dipanggil lagi untuk memuat file eksekusi qemu-system-riscv64 dan mengurai rangkaian simbol fungsi cpu_xx, gdb_xx dan qemu_xx. Simbol fungsi ini sebenarnya adalah kode implementasi yang mendasari rangkaian fungsi difftest_xx .
Dari file qemu-system-riscv64, fungsi yang diurai adalah fungsi utama, kemudian fungsi difftest_init akan memanggilnya untuk memulai program qemu.
Kemudian jika semuanya normal, Anda dapat memanggil fungsi qemu untuk membandingkan hasil instruksi.
4 QEMU untuk REF (Mode soket)
Anda dapat mengubah NEMU/alat/soket qemu-diff/, dikompilasi ke dalam perpustakaan dinamis riscv64-qemu-so. Hubungan antara NEMU, perpustakaan dinamis, dan QEMU:
Pustaka dinamis: riscv64-qemu-so, yang mengekspor rangkaian antarmuka fungsi difftest_xx.
QEMU: File yang dapat dieksekusi qemu-system-riscv64 memiliki antarmuka fungsi seri cpu_xx dan gdb_xx.
NEMU: Program penerjemah riscv64-nemu memanggil perpustakaan dinamis. Perpustakaan dinamis mengirimkan paket perintah melalui soket. QEMU menerima paket dan menguraikannya, dan memutuskan fungsi mana yang akan dipanggil untuk dieksekusi berdasarkan perintah tertentu.
proses spesifik:
Program NEMU yang dapat dieksekusi riscv64-nemu-interpreter memuat riscv64-qemu-so dengan memanggil fungsi dlopen, dan menguraikan simbol fungsi seri difftest_xx untuk panggilan berikutnya.
Kemudian, NEMU memanggil fungsi difftest_init untuk menginisialisasi.
Dalam fungsi difftest_init, proses anak akan fork() keluar dan memulai QEMU dengan memanggil fungsi execlp; sementara proses induk terus dijalankan, terhubung ke QEMU melalui soket, dan memanggil fungsi init_isa untuk menginisialisasi.
Kemudian jika semuanya normal, Anda dapat membandingkan hasil perintah melalui soket.