L'idée centrale de DiffTest : pour deux implémentations basées sur la même spécification, étant donné la même entrée définie, leur comportement doit être cohérent. De retour à la conception du processeur, pour les deux implémentations selon le manuel riscv, étant donné le même programme correct, leurs changements d'état (registres, mémoire) doivent être cohérents pour les deux implémentations :
L’un d’eux est notre processeur ;
Vous pouvez également choisir un simulateur comme implémentation de référence. Chaque fois que les deux parties terminent l'exécution d'une instruction, elles vérifient l'état de leurs registres et de leur mémoire respectifs. S'ils constatent que l'état est incohérent, ils signalent immédiatement une erreur et arrêtent l'exécution du programme client (ce qui équivaut à un jugement d'assertion pour). chaque instruction).
DiffTest = méthode de vérification comportementale au niveau des commandes en ligne
En ligne = Vérifier lors de l'exécution du programme
Niveau d'instruction = chaque instruction exécutée est vérifiée
Peut convertir n'importe quel programme en tests de niveau instruction et affirmer son statut
Programmes de support qui ne s'arrêteront pas, tels que le système d'exploitation
Pas besoin de connaître l’issue de la procédure à l’avance
Parce que nous comparons le comportement de l'exécution des instructions, pas la sémantique du programme
Les principales utilisations de DiffTest sont :Lorsque des bugs de décodage ou d'exécution surviennent après l'exécution de centaines ou de milliers d'instructions, comment trouver rapidement la première instruction d'erreur. C'est une difficulté infernale ?
Dans cet article, nous choisissons l’exemple suivant pour illustrer :
QEMU comme objet de référence (REF)
NEMU comme sujet de test (DUT)
Bien entendu, si vous devez tester le matériel du processeur, celui-ci peut également être utilisé comme objet sous test.
2 DiffTest pris en charge par NEMU
make menuconfig
1
Entrez Tests et débogage -> Activer les tests différentiels -> Conception de référence, comme suit :
Lorsque NEMU est utilisé pour un DUT, vous pouvez choisir 5 modes de simulateur comme simulateur de référence REF.
QEMU, mode bibliothèque dynamique, le code se trouve dans NEMU/tools/qemu-dl-diff/
QEMU, mode Socket, le code se trouve dans NEMU/tools/qemu-socket-diff/
KVM, le code se trouve dans NEMU/tools/kvm-diff/
NÉMU
POINTE
Pour ces trois derniers, l’auteur n’a pas fait de recherche spécifique, cet article ne les présentera donc pas.
3 QEMU crée REF (mode bibliothèque dynamique)
Vous pouvez changer NEMU/tools/qemu-dl-diff/, compilé dans la bibliothèque dynamique riscv64-qemu-so. La relation entre NEMU, les bibliothèques dynamiques et QEMU :
Bibliothèque dynamique : riscv64-qemu-so, qui exporte la série difftest_xx d'interfaces de fonctions.
QEMU : dans le fichier exécutable qemu-system-riscv64, il existe des interfaces de fonctions des séries cpu_xx, gdb_xx et qemu_xx.
NEMU : Le programme riscv64-nemu-interpreter appelle la bibliothèque dynamique, qui appelle ensuite QEMU.
processus spécifique :
Le programme exécutable NEMU riscv64-nemu-interpreter charge riscv64-qemu-so en appelant la fonction dlopen et analyse les symboles de fonction de la série difftest_xx pour les appels ultérieurs.
Ensuite, NEMU appelle la fonction difftest_init pour s'initialiser.
Dans la fonction difftest_init, la fonction dlopen sera à nouveau appelée pour charger le fichier exécutable qemu-system-riscv64 et analyser les séries de symboles de fonction cpu_xx, gdb_xx et qemu_xx. Ces symboles de fonction sont en fait le code d'implémentation sous-jacent de la série de fonctions difftest_xx. .
À partir du fichier qemu-system-riscv64, la fonction analysée est la fonction principale, puis la fonction difftest_init l'appellera pour démarrer le programme qemu.
Ensuite, si tout est normal, vous pouvez appeler la fonction qemu pour comparer les résultats des instructions.
4 QEMU pour REF (mode Socket)
Vous pouvez changer NEMU/tools/différence de socket qemu/, compilé dans la bibliothèque dynamique riscv64-qemu-so. La relation entre NEMU, les bibliothèques dynamiques et QEMU :
Bibliothèque dynamique : riscv64-qemu-so, qui exporte la série difftest_xx d'interfaces de fonctions.
QEMU : le fichier exécutable qemu-system-riscv64 possède des interfaces de fonctions des séries cpu_xx et gdb_xx.
NEMU : le programme riscv64-nemu-interpreter appelle la bibliothèque dynamique. La bibliothèque dynamique envoie un paquet de commande via le socket, reçoit le paquet, l'analyse et décide quelle fonction appeler pour l'exécution en fonction de la commande spécifique.
processus spécifique :
Le programme exécutable NEMU riscv64-nemu-interpreter charge riscv64-qemu-so en appelant la fonction dlopen et analyse les symboles de fonction de la série difftest_xx pour les appels ultérieurs.
Ensuite, NEMU appelle la fonction difftest_init pour s'initialiser.
Dans la fonction difftest_init, un processus enfant fork() et démarrera QEMU en appelant la fonction execlp ; pendant que le processus parent continue de s'exécuter, se connecte à QEMU via le socket et appelle la fonction init_isa pour s'initialiser.
Ensuite, si tout est normal, vous pouvez comparer les résultats de la commande via le socket.