Cours #7 Vérification d’un modèle VHDL
Plan pour aujourd’hui Introduction: retour sur la vérification avec un banc d’essai: sections 7.1 à 7.10 Élaboration d’un plan de test: section 7.11 Composition d’un ensemble de vecteurs de test: section 7.12 tests de boîte noire tests de boîte blanche Concepts avancés: section 7.13 + Des parenthèses sur VHDL, des précisions sur les notes de cours, des trucs pour utiliser Active-HDL, et des exemples!
Flot de conception de circuits numériques (notes, section 4.2) Flot de conception de circuits numériques
Vérification: concepts fondamentaux (notes, section 7.1) Vérification: concepts fondamentaux La vérification est un processus par lequel on vérifie qu’un design rencontre bien ses spécifications. La vérification complète d’un circuit est normalement un problème très difficile. Dans l’industrie de la conception numérique, on considère en général que le processus de vérification nécessite autant d’efforts que le processus de conception lui-même. La vérification d’un circuit est un art qui repose sur la maîtrise de trois principes: la compréhension de la spécification; le contrôle des entrées et de signaux internes du circuit à vérifier; et, l’observation des sorties, des signaux internes et de l’état du circuit à vérifier.
Vérification par banc d’essai (notes, section 7.2 et 7.10) Vérification par banc d’essai Un banc d’essai permet d’appliquer des vecteurs de test à un circuit et d’observer sa sortie dans le but de vérifier qu’il rencontre ses spécifications. Un banc d’essai doit effectuer les tâches suivantes : instancier le circuit à vérifier; générer des vecteurs de test et les appliquer aux ports d’entrée du circuit; [utile]: générer automatiquement des réponses attendues aux vecteurs de test; [utile]: comparer les réponses du circuit aux réponses attendues, et indiquer toute différence entre les deux par une condition d’erreur. (pour circuit séquentiel): générer un signal d’horloge et un signal de réinitialisation
Vecteurs de test encodés dans un tableau de constantes (notes, section 7.4) Vecteurs de test encodés dans un tableau de constantes architecture arch2 of add3bitsTB is component add3bits -- déclaration du module à vérifier port (Cin, X, Y : in std_logic; Cout, S : out std_logic); end component; -- signaux pour les vecteurs de tests signal Cin, X, Y : std_logic; -- signaux pour les réponses signal Cout, S : std_logic; type tableauSLV3 is array (natural range <>) of std_logic_vector(2 downto 0); constant vecteurs : tableauSLV3 := ("000", "001", "010", "011", "100", "101", "110", "111"); begin -- instanciation du module à vérifier UUT : add3bits port map (Cin, X, Y, Cout, S); process -- application des vecteurs de test emmagasinés dans le tableau for k in vecteurs'low to vecteurs'high loop (Cin, Y, X) <= vecteurs(k); wait for 10 ns; end loop; end process; end arch2; nouveau type: tableau de std_logic_vector de 3 éléments déclaration d’une constante contenant les vecteurs de test application de tous les vecteurs Ici on peut faire un test exhaustif, mais quelles valeurs placer dans le tableau des constantes en général?
Vérification exhaustive à l’aide d’une boucle (notes, section 7.5.1) Vérification exhaustive à l’aide d’une boucle Pour un circuit combinatoire, il est parfois possible de faire une vérification exhaustive. Au lieu d’un tableau, on peut utiliser une boucle. library ieee; use ieee.numeric_std.all; architecture arch3 of add3bitsTB is component add3bits -- déclaration du module à vérifier port (Cin, X, Y : in std_logic; Cout, S : out std_logic); end component; -- signaux pour les vecteurs de tests signal Cin, X, Y : std_logic; -- signaux pour les réponses signal Cout, S : std_logic; begin -- instanciation du module à vérifier UUT : add3bits port map (Cin, X, Y, Cout, S); process -- application exhaustive des vecteurs de test for k in 0 to 7 loop (Cin, Y, X) <= to_unsigned(k, 3); wait for 10 ns; end loop; end process; end arch3; La vérification exhaustive n’est pas toujours possible.
Vérification pseudo-aléatoire (notes, section 7.5.2) Vérification pseudo-aléatoire Un test pseudo-aléatoire peut venir compléter un test plus dirigé. library ieee; use ieee.numeric_std.all; use ieee.math_real.all; architecture arch4 of add3bitstb is … -- comme précédemment begin -- instanciation du module à vérifier UUT : add3bits port map (Cin, X, Y, Cout, S); process -- génération aléatoire de vecteurs de test variable seed1 : positive := 1; variable seed2 : positive := 2; variable aleatoire : real; variable t : integer := -1; uniform(seed1, seed2, aleatoire); -- 0.0 < aleatoire < 1.0 aleatoire := floor(aleatoire * 8.0); -- 0.0 <= aleatoire <= 7.0 t := integer(aleatoire); -- 0 <= t <= 7 (Cin, Y, X) <= to_unsigned(t, 3); wait for 10 ns; end process; end arch4; Un test pseudo-aélatoire peut être intéressant, mais il ne permet pas par lui-même de savoir à quel point le circuit a été vérifié.
Vérification d’un circuit séquentiel (notes, section 7.10) Vérification d’un circuit séquentiel library ieee; use ieee.std_logic_1164.all; use std.textio.all; entity cctsequentielex1TB is end cctsequentielex1TB; architecture arch1a of cctsequentielex1TB is signal reset : std_logic := '0'; signal clk : std_logic := '0'; signal X : std_logic := 'X'; signal Z : std_logic := 'X'; constant periode : time := 10 ns; begin clk <= not clk after periode / 2; reset <= '0' after 0 ns, '1' after periode / 4; UUT : entity cctsequentielex1(arch2) port map (reset, clk, X, Z); process (clk) constant vecteurX : std_logic_vector := "00001010010011000111"; variable compte : natural range 0 to vecteurX'length := 0; variable tampon : line; -- pointeur vers objet de type string if (falling_edge(clk)) then -- *** front différent de l'UUT *** write(tampon, "temps: "); write(tampon, now, unit => ns); write(tampon, ", x: " & std_logic'image(x)); write(tampon, ", z: " & std_logic'image(z)); write(tampon, ", compte: " & integer'image(compte)); writeline(output, tampon); -- écriture à la console if compte = vecteurX'length then report "simulation terminée" severity failure; else X <= vecteurX(compte); compte := compte + 1; end if; end process; end arch1a; A B Comment savoir si le circuit a été adéquatement vérifié? Toutes les transitions possibles entre les états ont-elles été testées au moins une fois? Y a-t-il d’autres critères à vérifier? Pour un circuit séquentiel, « vérification exhaustive » veut dire: pour chaque état, appliquer chaque entrée possible.
Plan pour aujourd’hui Introduction: retour sur la vérification avec un banc d’essai: sections 7.1 à 7.10 Élaboration d’un plan de test: section 7.11 Composition d’un ensemble de vecteurs de test: section 7.12 tests de boîte noire tests de boîte blanche Concepts avancés: section 7.13 + Des parenthèses sur VHDL, des précisions sur les notes de cours, des trucs pour utiliser Active-HDL, et des exemples!
Élaboration d’un plan de test (notes, section 7.11) Élaboration d’un plan de test Un plan de test est un document qui détaille la stratégie employée pour effectuer la vérification d’un système. La complexité et le niveau de détail d’un plan de test dépendent de la taille du module, circuit, sous-système ou système à vérifier. Un plan de test complet pourrait entre autres détailler: la couverture du test: quels requis de la spécification doivent être vérifiés par le test? les méthodes de test: comment le système sera-t-il vérifié? quelles sont les conditions de réussite et d’échec des cas de test? les responsabilités de test: qui est responsable de quels tests? Un plan de test sommaire peut être élaboré en trois étapes : Extraire les fonctionnalités requises du système à partir de ses spécifications; Prioriser les fonctionnalités à vérifier; et, Créer des vecteurs de test.
(notes, section 7.11) Élaboration d’un plan de test 1. Extraire les fonctionnalités requises du système La spécification architecturale décrit l’interface du système avec le monde extérieur et ses relations d’entrées et sortie. La spécification architecturale ne spécifie pas comment le comportement interne du système doit être réalisé. Il est difficile d’extraire toutes les fonctionnalités requises à partir de la spécification. Il est encore plus difficile d’automatiser cette extraction. Certaines fonctionnalités sont implicites. D’autres fonctionnalités ou comportements ne doivent pas être présents. Concevoir et décrire une file d'attente en VHDL. Le nombre maximum d'éléments dans la file et la largeur des données en bits doivent être paramétrables. Un signal d'horloge synchronise toutes les activités de la file. Le signal reset permet de vider la file. Les ports din et dout sont respectivement l'entrée et la sortie de la file. Les ports empty et full indiquent respectivement que la file est vide ou bien qu'elle est pleine. Quand le signal wr_en (write enable) est activé, la valeur placée sur le port din sera insérée dans la file lors de la prochaine transition active du signal d'horloge clk. Quand le signal rd_en (read enable) est activé, la valeur qui est dans la file depuis le plus longtemps sera placée sur le port dout lors de la prochaine transition active du signal d'horloge clk. Il doit être possible d'écrire une nouvelle valeur dans la file et de lire la valeur la plus ancienne simultanément. Quand la file est pleine, le signal wr_en n'a aucun effet - il n'est pas possible d'écrire par dessus le contenu présent de la file. Quand la file est vide, le signal rd_en n'a aucun effet. Il doit être possible d'écrire une nouvelle valeur dans la file et de lire la valeur la plus ancienne simultanément.
(notes, section 7.11) Élaboration d’un plan de test 1. Extraire les fonctionnalités requises du système Exemple pour une unité de file d’attente (FIFO). Quatre catégories de fonctionnalités à vérifier Exemple de fonctionnalité Il est possible de placer le système dans son état de départ valide à partir de n’importe quel état. Retour à l’état de départ quand le signal reset est activé. À partir d’un état valide et étant donnée une entrée valide, le système doit se placer dans le bon état valide. Écriture dans la file (quand la file n’est pas pleine). À partir d’un état valide et étant donnée une entrée valide, le système ne doit pas se placer dans un état non valide ou un état incorrect. À partir d’un état valide et étant donnée une entrée non valide, le système ne doit pas se placer dans un état non valide ou un état incorrect. Écriture dans la file (quand la file est pleine).
(notes, section 7.11) Élaboration d’un plan de test 2. Prioriser les fonctionnalités à vérifier Il y a souvent une très grande quantité de fonctionnalités à vérifier. Il peut être utile de les placer en ordre de priorité. Les fonctionnalités qui correspondent à des contraintes de sécurité devraient être considérées en premier. Les fonctionnalités qui correspondent à des besoins fondamentaux du système identifiés dans les spécifications devraient être vérifiées de façon prioritaire. Les fonctionnalités qui faciliteraient l’utilisation du système peuvent avoir une priorité plus faible. Enfin, les fonctionnalités facultatives ou futures du système peuvent avoir une priorité encore plus faible.
Élaboration d’un plan de test 3. Créer un ensemble de vecteurs de test (notes, section 7.11) Élaboration d’un plan de test 3. Créer un ensemble de vecteurs de test On crée un ensemble de vecteurs de test pour chaque fonctionnalité à vérifier. Il faut établir comment vérifier la fonctionnalité et comment établir qu’elle est satisfaite ou non à partir des signaux du système. On détermine les vecteurs de test spécifiques qui permettent de stimuler la fonctionnalité désirée. Pour aider au processus de création des vecteurs de test, il est nécessaire de bien documenter chaque étape.
Élaboration d’un plan de test 3. Créer un ensemble de vecteurs de test (notes, section 7.11) Élaboration d’un plan de test 3. Créer un ensemble de vecteurs de test Par exemple, le plan de test peut comporter un tableau dans lequel on identifie les fonctionnalités à vérifier ainsi que leur priorité, assigner une personne responsable et suivre leur statut dans le temps : en développement, débutée, écrite, appliquée, révisée, etc. Fonctionnalité Priorité Responsable Statut de la tâche 1. Réinitialisation 1 Armand Assignée 2. Écrire dans la pile 2 Écrite 3. Lire de la pile Asma 4. Écriture et lecture simultanées Alexis En dév. 5. Pile pleine Fonctionnement du signal ‘full’ Écriture impossible 6. Pile vide Fonctionnement du signal ‘empty’ Lecture impossible 7. Signaux ‘overflow’ et ‘underflow’ 4
Plan pour aujourd’hui Introduction: retour sur la vérification avec un banc d’essai: sections 7.1 à 7.10 Élaboration d’un plan de test: section 7.11 Composition d’un ensemble de vecteurs de test: section 7.12 tests de boîte noire tests de boîte blanche Concepts avancés: section 7.13 + Des parenthèses sur VHDL, des précisions sur les notes de cours, des trucs pour utiliser Active-HDL, et des exemples!
Cinq qualités d’un bon ensemble de vecteurs de test (notes, section 7.12.2) Cinq qualités d’un bon ensemble de vecteurs de test Le problème de la création d’un ensemble de vecteurs de test n’est pas simple. Les vecteurs de test choisis doivent permettre de vérifier que le circuit rencontre ses spécifications. Les cinq qualités principales d’un bon ensemble de vecteurs de test sont: Efficace pour découvrir des bogues, c’est-à-dire que chaque vecteur de test vérifie plusieurs fonctionnalités en même temps, et donc que peu de vecteurs de tests sont nécessaires. Identifie la source des bogues, pour aider à leur éradication. Reproductible, donc il est facile de recréer le bogue. Automatisé à l’aide d’un banc d’essai. Exécutable dans un temps raisonnable. dépend de la taille et de la complexité du circuit et de l’ampleur du projet Laboratoire de 3 heures: quelques minutes Projet intégrateur: de plusieurs minutes à quelques heures Système de grande envergure: de plusieurs heures à quelques jours
(notes, section 7.12.1) Le test exhaustif Les tests exhaustifs permettent d’observer le comportement du circuit pour toutes les conditions possibles d’entrée. En pratique il est impossible d’effectuer un test exhaustif dans un temps raisonnable. Pour un circuit combinatoire avec M entrées, il faut 2M vecteurs de test. Pour un circuit combinatoire avec: N bascules, S = 2N états, et M entrées, R = 2M transitions possibles à partir de chaque état, il faudrait prévoir 2N + M vecteurs de test différents juste pour effectuer toutes les transitions possibles du système au moins une fois.
Exemple: conversion de secondes library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity convSecondes is port ( secondesIn : in unsigned(7 downto 0); minutesOut : out unsigned(2 downto 0); secondesOut : out unsigned(5 downto 0) ); end convSecondes; Combien de vecteurs de test sont nécessaires pour un test exhaustif?
Exemple: conversion de couleurs de RGB à CMYK Les images sont habituellement encodées dans l’espace à trois dimensions RGB. Une imprimante utilise plutôt l’espace CMY: cyan (C), magenta (M) et jaune (Y), les couleurs complémentaires de rouge, vert et bleu. Les équations de conversion, pour des valeurs exprimées sur 8 bits, sont: C = 255 – R; M = 255 – G; Y = 255 – B A. Stodghill, Tip o’day: ask for a a refill, Green Options, 2007/06/18. Consulté le 4 septembre 2009, tiré de http://greenoptions.com/tag/ink-cartridge
Exemple: conversion de couleurs de RGB à CMYK library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity convRGB2CMYK is port ( rouge, vert, bleu : in unsigned(7 downto 0); cyan, magenta, jaune, noir : out unsigned(7 downto 0) ); end convRGB2CMYK; Combien de vecteurs de test sont nécessaires pour un test exhaustif?
Exemple: machine à états library IEEE; use IEEE.std_logic_1164.all; entity machineAEtats is port ( reset, CLK : in STD_LOGIC; x : in STD_LOGIC_VECTOR(1 downto 0); sortie : out STD_LOGIC ); end machineAEtats; architecture arch of machineAEtats is type type_etat is (S1, S2, S3, S4); signal etat : type_etat := S1; begin … Combien de vecteurs de test sont nécessaires pour un test exhaustif? Quelles informations sont nécessaires pour déterminer le nombre de vecteurs de tests?
Exemple: joueur de blackjack Description du jeu de base (notes, section 6.7) Exemple: joueur de blackjack Description du jeu de base Le jeu oppose des joueurs à un croupier qui joue pour le compte de la banque. Le but du jeu est d’accumuler plus de points que la banque sans dépasser 21. Les cartes ont les valeurs suivantes : les cartes numérotées ont leur propre valeur (2 à 10); les figures valent 10; et, l’as peut valoir 1 ou 11, selon ce qui est le plus avantageux – une main contenant un as qui peut prendre une des deux valeurs est dite ‘facile’. Le croupier distribue deux cartes visibles à chaque joueur, puis se donne une carte visible et une carte cachée. Chaque joueur peut alors tirer une carte ou arrêter, de façon à obtenir la meilleure main possible. Finalement, le croupier révèle sa carte cachée et tire sur un total de 16 ou moins. Un joueur gagne sa mise si sa main est meilleure que celle du croupier. Il récupère sa mise si sa main est égale à celle du croupier. Il perd sa mise si son total est supérieur à 21 ou inférieur au total du croupier.
Exemple: joueur de blackjack (notes, section 6.7) Exemple: joueur de blackjack library IEEE; use IEEE.std_logic_1164.all; entity blackjack is port ( clk: in std_logic; reset: in std_logic; carteValide : in std_logic; valeurCarte: in integer range 2 to 11; tirer: out std_logic; depasse: out std_logic; total: out integer range 0 to 31 ); end blackjack; architecture arch2 of blackjack is signal somme : integer range 0 to 31; signal calculeSomme : std_logic; signal initSomme : std_logic; signal moinsDix : std_logic; type type_etat is (depart, tire, ajoute, verifie, corrige, fini); signal etat : type_etat; … Combien de vecteurs de test sont nécessaires pour un test exhaustif? Quelles informations sont nécessaires pour déterminer le nombre de vecteurs de tests?
Exemple: microprocesseur Combien de vecteurs de test sont nécessaires pour vérifier un microprocesseur de façon exhaustive? Énoncez vos suppositions Donnez un ordre de grandeur de la réponse Estimez le temps nécessaire en supposant que vous pouvez appliquer un vecteur de test à chaque milliseconde.
Plan pour aujourd’hui Introduction: retour sur la vérification avec un banc d’essai: sections 7.1 à 7.10 Élaboration d’un plan de test: section 7.11 Composition d’un ensemble de vecteurs de test: section 7.12 tests de boîte noire tests de boîte blanche Concepts avancés: section 7.13 + Des parenthèses sur VHDL, des précisions sur les notes de cours, des trucs pour utiliser Active-HDL, et des exemples!
Tests de boîte noire (ou tests fonctionnels) (notes, section 7.12.3) Tests de boîte noire (ou tests fonctionnels) Le terme « test de boîte noire » fait référence à un test qui ne suppose aucune connaissance de l’implémentation du système. En anglais: black box, opaque box, closed box, functional test. Les tests de boîte noire s’appuient uniquement sur les spécifications du système. Plus le système est complexe, et plus il faut utiliser ce genre de test. Il est difficile de déterminer à quel point le système a été vérifié par ce genre de test. Les tests de boîte noire ne permettent pas en général de découvrir des comportements non spécifiés du système.
(notes, section 7.12.4) Vecteurs de test choisis par partitionnement en classes (test de boîte noire)
(notes, section 7.12.4) Vecteurs de test choisis par partitionnement en classes (test de boîte noire) L’ensemble des valeurs d’entrée du système est partitionné en classes séparées. Le principe du partitionnement en classes s’appuie sur la supposition suivante: deux données d’une même classe sont similaires et le comportement du système est semblable pour elles On doit choisir des données qui appartiennent à chacune des classes. Un test faible consiste en un ensemble de vecteurs de tests où au moins un élément de chacune des classes serait présent au moins une fois. Un test fort consiste en un ensemble de vecteurs de test où toutes les interactions entre les classes seraient présentes au moins une fois. Le nombre de vecteurs de test est alors égal au produit du nombre de classes pour chacune des entrées du système.
(notes, section 7.12.4) Vecteurs de test choisis par partitionnement en classes (test de boîte noire) - exemple Un module d’un chronomètre doit calculer la date du lendemain à la fin de la journée. On peut identifier les classes de données d’entrée suivantes. Pour les années : {année divisible par 4}, {année centenaire}, {autres années}. Pour les mois : {mois de 30 jours}, {mois de 31 jours}, {mois de février}. Pour les jours : {jour est entre 1 et 28}, {jour est 29}, {jour est 30}, {jour est 31}. Pour un test fort, on devrait choisir au moins un vecteur de test pour chacune des combinaisons de classes. cas du mois de 31 jours avec les quatre classes de jour et les trois classes d’années. cas du mois de février, le jour 31, l’année centenaire (pas valide). etc. Il n’est pas facile en général d’énumérer toutes les classes de données possibles. La combinaison de vecteurs de test couvrant toutes les combinaisons de classes peut être très grande.
(notes, section 7.12.4) Vecteurs de test choisis par partitionnement en classes (test de boîte noire) Test faible - quatre vecteurs, un exemple: {{classe 1-1}, {classe 2-1}, {classe 3-1}}, {{classe 1-2}, {classe 2-2}, {classe 3-2}}, {{classe 1-3}, {classe 2-1}, {classe 3-3}}, {{classe 1-1}, {classe 2-1}, {classe 3-4}} Test fort - 24 vecteurs: {{classe 1-1}, {classe 2-1}, {classe 3-2}}, {{classe 1-1}, {classe 2-1}, {classe 3-3}}, {{classe 1-1}, {classe 2-1}, {classe 3-4}}, {{classe 1-1}, {classe 2-2}, {classe 3-1}}, {{classe 1-1}, {classe 2-2}, {classe 3-2}}, {{classe 1-1}, {classe 2-2}, {classe 3-3}}, {{classe 1-1}, {classe 2-2}, {classe 3-4}}, etc. {classe i-j} : un élément de la classe i-j par exemple: {classe année-divisible par 4}: 1904 {classe mois-mois de 30 jours}: 4 (avril)
(notes, section 7.12.5) Vecteurs de test choisis par analyse des valeurs limites (test de boîte noire) Cette approche découle de l’observation que les erreurs se produisent souvent aux valeurs limites des données (exemple: débordement d’une addition). On devrait inclure dans les vecteurs de test, pour chaque donnée, jusqu’à sept valeurs différentes: Valeur Exemple pour le jour, mois de janvier Une valeur juste inférieure à la valeur minimale La valeur minimale 1 Une valeur juste supérieure à la valeur minimale 2 Une valeur nominale 15 Une valeur juste inférieure à la valeur maximale 30 La valeur maximale 31 Une valeur juste supérieure à la valeur maximale 32
(notes, section 7.12.5) Vecteurs de test choisis par analyse des valeurs limites (test de boîte noire) Vérifier toutes les combinaisons possibles des valeurs limites de chacune des variables: 7n cas différents pour n variables. Si le nombre de variables est trop grand, on peut éliminer les valeurs interdites (sous le minimum et en haut du maximum) et on obtient alors 5n cas différents. On peut encore réduire le nombre de combinaisons en fixant toutes les variables à leur valeur nominale, sauf une ou deux à la fois qui passent à travers leurs valeurs limites. Exemple pour deux variables x et y. Espace des entrées possibles x y
Exemple: conversion de couleurs de RGB à CMYK library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity convRGB2CMYK is port ( rouge, vert, bleu : in unsigned(7 downto 0); cyan, magenta, jaune, noir : out unsigned(7 downto 0) ); end convRGB2CMYK; Quels vecteurs de test choisir selon l’analyse des valeurs limites? - en version complète - en version réduite Comment ces ensembles se comparent-ils au test exhaustif?
Vecteurs de test pseudo-aléatoires (test de boîte noire) (notes, section 7.12.6) Vecteurs de test pseudo-aléatoires (test de boîte noire) Les vecteurs de test pseudo-aléatoires ont l’avantage d’être simples à générer. Ils peuvent compléter de façon intéressante un ensemble de vecteurs de tests composé avec une autre méthode. Quelques principes doivent être respectés pour les tests pseudo-aléatoires : Il est utile de distinguer entre des valeurs valides et non valides appliquées au système, et s’assurer de générer surtout des valeurs de test valides. Le test doit être reproductible, donc il faut choisir des valeurs de graines connues (et non la valeur de l’horloge) pour lancer la génération des nombres pseudo-aléatoires. Le test devrait avoir un objectif précis en restreignant les valeurs aléatoires générées à une seule classe. La distribution des valeurs aléatoires devrait être connue et contrôlable pour correspondre aux conditions d’opération du système.
Plan pour aujourd’hui Introduction: retour sur la vérification avec un banc d’essai: sections 7.1 à 7.10 Élaboration d’un plan de test: section 7.11 Composition d’un ensemble de vecteurs de test: section 7.12 tests de boîte noire tests de boîte blanche Concepts avancés: section 7.13 + Des parenthèses sur VHDL, des précisions sur les notes de cours, des trucs pour utiliser Active-HDL, et des exemples!
Tests de boîte blanche (ou tests structurels) (notes, section 7.12.3) Tests de boîte blanche (ou tests structurels) Le terme « test de boîte blanche » fait référence à un test qui nécessite de connaître le fonctionnement interne du système. En anglais: white box, glass box, clear box, structural test. En s’appuyant sur des principes de couverture, on peut calculer des métriques permettant de déterminer à quel point le test a vérifié le système. Les tests de boîte blanche ne permettent pas en général de découvrir les fonctionnalités manquantes du système.
Couverture de code (test de boîte blanche) (notes, section 7.12.7) Couverture de code (test de boîte blanche) Dans la couverture de code, on choisit des vecteurs de test pour exercer un élément particulier du design ou de sa description. Il y en a plusieurs : Couverture d’énoncés : pourcentage des énoncés du code exécutés. Couverture de blocs : pourcentage de blocs d’énoncés délimités par des structures de contrôle qui ont été exécutés. Cette métrique a l’avantage d’être plus représentative que la couverture d’énoncés, parce que les blocs comportant plusieurs énoncés n’ont pas un poids plus important que les autres. Couverture de branchements : pourcentage des choix de branchement exécutés. Couverture d’expressions : pourcentage des composantes des expressions booléennes qui ont affecté la valeur de ces expressions. Couverture d’états : pourcentage du nombre d’états visités. Couverture de transitions : pourcentage des transitions de chaque état ayant été prises. Couverture de changements de signaux : pourcentage de signaux binaires ayant passé de 0 à 1 et de 1 à 0.
Couverture de code (test de boîte blanche) (notes, section 7.12.7) Couverture de code (test de boîte blanche) Pour chacune des couvertures possibles, on peut calculer une métrique qui exprime: le nombre de fois où chaque situation se produit; ou, le pourcentage des situations qui se sont produites. Par exemple, on voudrait atteindre 100% de couverture des énoncés. Si on n’est qu’à 90%, cela signifie qu’il faut stimuler le circuit avec d’autres vecteurs de test. Le code doit être instrumenté pour obtenir les métriques (par un outil). Un outil peur présenter l’information obtenue de façon conviviale pour faciliter la sélection de vecteurs de test. Les différents éléments de couverture ne sont pas tous indépendants. Par exemple, la couverture d’états et la couverture de transitions sont effectivement des sous-ensembles de la couverture d’énoncés et de branchements. Démonstration avec Active-HDL.
Parenthèse: outils d’Active-HDL pour la couverture de code (pas dans les notes) Parenthèse: outils d’Active-HDL pour la couverture de code Configuration de l’environnement: Design > Settings > Compilation > VHDL > Enable Debug Design > Settings > Coverage/Profiler> Coverage : Code, Expression, Path Design > Settings > Coverage/Profiler> Code Coverage > Collect data per instance Procédure: Choisir le banc d’essai comme entité à simuler Initialiser la simulation Simulation > Toggle Coverage > Toggle On, OK Lancer la simulation Arrêter la simulation (essentiel pour que les rapports soient écrits sur le disque)
Parenthèse: outils d’Active-HDL pour la couverture de code (pas dans les notes) Parenthèse: outils d’Active-HDL pour la couverture de code Tools > Code Coverage Viewer File > Open: Ouvrir le fichier ‘coverage/results.ccl’ Inspecter les rapports de couverture Count: nombre d’exécutions de la ligne BC: branch coverage, nombre d’exécutions vraies et fausses de chaque branchement EC: expression coverage Tools > Toggle Coverage Viewer File > Open: Ouvrir le fichier ‘toggle.xml’ Inspecter le rapport de couverture
Création de vecteurs de test selon la couverture de code (notes, section 7.12.8) Création de vecteurs de test selon la couverture de code Un bon ensemble de vecteurs de tests produit une couverture de code de 100%. Mais … des métriques de couverture de 100% pour un ensemble de vecteurs de test ne garantissent pas que le circuit rencontre toutes ses spécifications. Les métriques de couverture de code complètent les autres types de tests et donnent une certaine assurance au concepteur que le circuit est bien vérifié. Il peut y avoir des exceptions, comme par exemple: des énoncés qui sont en place pour protéger le système lors d’entrées non valides des énoncés pour ramener le système dans un état valide à partir d’un état non valide Ces deux cas nécessitent des vecteurs de test spéciaux.
Couverture de paramètres d’opération (test de boîte blanche) (notes, section 7.12.9) Couverture de paramètres d’opération (test de boîte blanche) La couverture de code n’indique que si certaines situations ont été exercées ou non, sans égard à la fonctionnalité du système. Un test plus puissant consiste à identifier les paramètres d’opération du système et à vérifier la couverture des valeurs possibles de ceux-ci. Par exemple, pour une file d’attente, un paramètre serait le nombre d’éléments dans la file. Il est important de vérifier l’opération de la file quand celle-ci est vide, presque vide, pleine et presque pleine, ainsi qu’en situations mitoyennes. Pour obtenir la couverture des paramètres d’opération, les étapes suivantes peuvent être suivies : Énumérer les paramètres d’opération du module; Pour chaque paramètre, déterminer la gamme des valeurs possibles et identifier les valeurs qui doivent absolument être vérifiées et dans quelles circonstances; Instrumenter le code afin de noter les valeurs de paramètre utilisées; Simuler le système; et, Calculer le rapport des valeurs utilisées sur le nombre de valeurs totales; Établir si les valeurs à vérifier l’ont été.
Couverture fonctionnelle (test de boîte blanche) (notes, section 7.12.10) Couverture fonctionnelle (test de boîte blanche) Dans ce genre de couverture, on énumère toutes les fonctions que le système doit pouvoir effectuer. Par exemple, dans un processeur, il doit être possible de transférer la valeur d’un registre vers un autre. On doit donc choisir des vecteurs de test qui exercent chacune des fonctions de la spécification.
Plan pour aujourd’hui Introduction: retour sur la vérification avec un banc d’essai: sections 7.1 à 7.10 Élaboration d’un plan de test: section 7.11 Composition d’un ensemble de vecteurs de test: section 7.12 tests de boîte noire tests de boîte blanche Concepts avancés: section 7.13 + Des parenthèses sur VHDL, des précisions sur les notes de cours, des trucs pour utiliser Active-HDL, et des exemples!
Concepts avancés de vérification Analyse statique du code (notes, section 7.13.1) Concepts avancés de vérification Analyse statique du code La meilleure façon de réduire le nombre de bogues dans un design est de réduire les chances de leur introduction dans celui-ci. En adoptant des pratiques de codage favorisant la vérification, on augmente les chances d’atteindre ce but. Guides de codage: développés avec le temps en se basant sur l’expérience des concepteurs; restreignent l’utilisation d’un langage à un sous-ensemble robuste et sécuritaire. Il existe des outils de vérification du respect des guides de codage qui effectuent une analyse statique du code. Le premier programme de la sorte s’appelait ‘lint’, et ce terme est souvent appliqué aux outils comme au processus.
Parenthèse: outils pour l’analyse statique du code (pas dans les notes) Parenthèse: outils pour l’analyse statique du code Outils ALINT d’Aldec – voir le site web
Concepts avancés de vérification Analyse statique du code (notes, section 7.13.1) Concepts avancés de vérification Analyse statique du code En VHDL et dans les autres HDL, une analyse statique peut détecter des erreurs potentielles et augmenter la qualité du code. Ces erreurs potentielles peuvent se situer à plusieurs niveaux, et la liste suivante donne quelques exemples : Opérandes de largeurs différentes dans une expression; Énoncés conditionnels dont tous les cas ne sont pas couverts et qui créent des états implicites; Énoncés conditionnels qui se recoupent; Nom d’entité différent du nom du fichier; Insertion de signaux de contrôle dans le chemin d’une horloge; Signaux ou variables qui ne sont pas initialisés avant d’être utilisés; Signaux ou variables auxquels on n’assigne jamais de valeur ou qui ne sont jamais utilisés; et, Expression constante dans une structure de condition.
Concepts avancés de vérification Vérification hiérarchique (notes, section 7.13.2) Concepts avancés de vérification Vérification hiérarchique Une approche hiérarchique simplifie l’effort de vérification. Cette approche devrait correspondre à la hiérarchie naturelle du système. Trois niveaux: Modules (p. ex. additionneur ou décodeur): comportement simple, pleine visibilité, test exhaustif {génie logiciel: test unitaire} Unités (p. ex. une UAL): choisir des vecteurs de test à partir des spécifications, bonne bonne visibilité de l’interface entre les modules, vérification des interactions entre les modules {génie logiciel: test d’intégration} Système: vérifier les fonctionnalités de haut niveau, vérifier que les interconnections entre les unités sont correctes {génie logiciel: test de système}
(notes, section 7.13.3) Concepts avancés de vérification Détection, identification et suivi des bogues Le but de la sélection des vecteurs de test et leur application au circuit en simulation est de découvrir les bogues du circuit. Quand un bogue survient: Identifier les conditions où le bogue est devenu apparent: version du code, suite de vecteurs de tests qui a mené à la défaillance, paramètres de simulation. Déterminer la source du bogue: une stratégie consiste à réduire la portée du circuit ou de l’ensemble de vecteurs de test. Documenter le bogue dans un système de suivi: enregistrer le bogue, les conditions pour le produire, son statut, sa priorité, les actions prises pour le résoudre. Un graphique de la fréquence d’apparence de nouveaux bogues dans un système donne une indication générale de la fiabilité de celui-ci.
Banc d’essai et entrées et sorties par fichiers en VHDL (notes, section 7.7) Banc d’essai et entrées et sorties par fichiers en VHDL On s’est concentrés à date sur la génération algorithmique de vecteurs de test à l’intérieur d’un banc d’essai codé en VHDL. Dans le processus de conception d’un système numérique, on passe souvent par une modélisation de haut niveau, par exemple avec Matlab. Lors de cette modélisation, on génère souvent une grande quantité de cas de test et de réponses attendues qui sont entreposés dans un fichier. Le banc d’essai peut lire ces cas de test et les réponses associées. Le banc d’essai peut aussi écrire ses résultats dans un fichier. Utilités: si la simulation dure plusieurs heures; si on désire obtenir des résultats progressifs; si on doit effectuer un traitement plus complexe des résultats dans un autre environnement que le simulateur VHDL. Par exemple, on pourrait vouloir afficher une image générée sous la forme d’un flux de pixels par un module.
Banc d’essai et entrées et sorties par fichiers en VHDL (notes, section 7.7) Banc d’essai et entrées et sorties par fichiers en VHDL Les entrées et sorties de fichier en VHDL se font à l’aide d’objets de la catégorie file. Comme on traite du texte lors de ces opérations, on utilise aussi les types et les fonctions définis dans le package textio qui fait partie du langage.
Banc d’essai et entrées et sorties par fichiers en VHDL Exemple (notes, section 7.7) Banc d’essai et entrées et sorties par fichiers en VHDL Exemple Module à vérifier et fichier de stimuli et réponses library ieee; use ieee.std_logic_1164.ALL; use ieee.numeric_std.all; entity detecteurPremier is port ( I : in unsigned(5 downto 0); F : out std_logic ); end detecteurPremier; architecture flotdonnees of detecteurPremier is begin with to_integer(I) select F <= '1' when 2 | 3 | 5 | 7 | 11 | 13 | 17 | 19 | 23 | 29 | 31 | 37 | 41 | 43 | 47 | 53 | 59 | 61 | 63, -- erreur! '0' when others; end flotdonnees; -- colonne1: entiers de 0 à 63 -- colonne2: P pour premier, N pour pas premier 0 N 1 N 2 P 3 P 4 N 5 P ...
Banc d’essai et entrées et sorties par fichiers en VHDL Exemple (notes, section 7.7) Banc d’essai et entrées et sorties par fichiers en VHDL Exemple Banc d’essai library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use std.textio.all; entity detecteurPremierTB is end detecteurPremierTB; architecture arch2 of detecteurPremierTB is component detecteurPremier -- déclaration du module à vérifier port (I : in unsigned(5 downto 0); F : out std_logic); end component; signal I : unsigned(5 downto 0); -- signal pour les vecteurs de tests signal F : std_logic; -- signal pour les réponses constant filename : string := "premiers.txt"; file vecteurs : text open read_mode is filename; -- format du fichier: -- colonne1: entier, colonne2: 'P' pour premier, 'N' pour pas premier begin -- instanciation du module à vérifier UUT : detecteurPremier port map (I, F);
Banc d’essai et entrées et sorties par fichiers en VHDL Exemple (notes, section 7.7) Banc d’essai et entrées et sorties par fichiers en VHDL Exemple Banc d’essai process variable tampon : line; -- pointeur vers un objet de type string variable n : integer; variable c : character; begin while not endfile(vecteurs) loop readline(vecteurs, tampon); if tampon(1 to 2) /= "--" then -- passer les lignes de commentaires read(tampon, n); -- lecture de l'entier read(tampon, c); -- lecture du séparateur read(tampon, c); -- lecture de l'indication: premier ('P') ou non ('N') I <= to_unsigned(n, 6); wait for 10 ns; assert ((c = 'P') = (F = '1') and (c = 'N') = (F = '0')) report "erreur pour l'entrée " & integer'image(n) severity error; end if; end loop; deallocate(tampon); -- relâcher la mémoire du tampon report "simulation terminée" severity failure; end process; end arch2;
(notes, section 7.7) Banc d’essai et entrées et sorties par fichiers en VHDL Exemple: écriture dans un fichier Banc d’essai process variable tampon : line; -- pointeur vers objet de type string variable tampon2 : line; begin -- La procédure writeline libère le pointeur quand elle a fini, -- donc il faut construire une copie de l'objet si on veut l'afficher 2 fois. -- À partir d'un pointeur, on va chercher le contenu avec '.all'. write(tampon, string'(" ** sortie de simulation, detecteurPremierTB.vhd ** ")); write(tampon2, tampon.all); -- copier la chaîne de caractères writeline(resultats, tampon); -- écriture dans le fichier writeline(output, tampon2); -- écriture à la console for k in 0 to 63 loop -- application exhaustive des vecteurs de test I <= to_unsigned(k, 6); wait for 10 ns; write(tampon, string'("temps: ")); write(tampon, now, unit => ns); write(tampon, string'(", entier: ") & integer'image(k)); write(tampon, string'(", sortie: ") & std_logic'image(F)); write(tampon2, tampon.all); -- copie la chaîne de caractères end loop; report "simulation terminée" severity failure; end process;
Résumé: vérification Notions à retenir et maîtriser Importance relative 1. Le plan de test: nommer, expliquer et appliquer les trois étapes à suivre 10 2. Évaluer la complexité d’un test exhaustif pour des circuits combinatoires et séquentiels 3. Énumérer les cinq qualités d’un bon ensemble de vecteurs de test 4. Tests de boîte noire Décrire le principe général Le partitionnement en classe: décrire et utiliser Analyse des valeurs limites: décrire et utiliser Tests pseudo-aléatoire: décrire les principes à respecter, utiliser ce test 30 5. Tests de boîte blanche La couverture de code: décrire et utiliser Couverture de paramètres d’opération et couverture fonctionnelle: décrire 10. Analyse statique du code, vérification hiérarchique, et suivi des bogues: décrire 5 11. Banc d’essai et entrées-sorties par fichier: analyser, comprendre et expliquer le code Total 100