Randomisation contrainte et reproductibilité
Générer des transactions variées tout en respectant le protocole, puis reproduire exactement un échec.
Aléatoire, mais valide
La randomisation contrainte génère des combinaisons de valeurs dans un espace défini. L'objectif n'est pas de remplacer le plan de vérification, mais d'explorer davantage d'interactions qu'une petite liste de tests dirigés.
class dma_request;
rand bit [31:0] address;
rand int unsigned length;
rand bit write;
constraint legal_length {
length inside {[1:256]};
}
constraint aligned_address {
address[1:0] == 2'b00;
}
constraint boundary {
address[11:0] + length <= 4096;
}
endclassLes contraintes décrivent ici ce qui constitue une commande valide : longueur bornée, adresse alignée et transfert qui ne franchit pas une page de 4 Kio.
Toujours contrôler le résultat
randomize() renvoie 1 si une solution a été trouvée et 0 si les contraintes sont incompatibles.
dma_request req = new();
assert (req.randomize() with {
write == 1'b1;
length inside {16, 32, 64};
}) else $fatal(1, "Request constraints have no solution");Ignorer cette valeur de retour peut envoyer une ancienne valeur ou une valeur par défaut au driver. Un échec de randomisation est une erreur de testbench à diagnostiquer.
Distribution et cas intéressants
dist permet de donner plus de poids à certaines valeurs sans les rendre obligatoires.
constraint length_distribution {
length dist {
1 := 5,
[2:63] := 1,
64 := 5,
256 := 5
};
}Les bornes reçoivent ici plus de poids. La distribution doit venir du plan de vérification et de la couverture observée, pas d'un choix arbitraire.
randc parcourt les valeurs d'un petit domaine avant de les répéter. Il ne convient pas à de grands vecteurs où le cycle complet serait irréaliste.
Reproduire un bug
Un générateur pseudo-aléatoire est déterministe pour une graine donnée, tant que l'environnement, l'ordre des appels et l'outil restent comparables. Le journal de test doit enregistrer :
- la graine globale ou locale ;
- le nom et la configuration du test ;
- les paramètres du DUT ;
- la transaction fautive et son numéro ;
- la version du code et du simulateur.
Relancer avec la même graine est la première étape. Réduire ensuite le scénario à quelques transactions accélère le diagnostic.
À retenir
- Les contraintes décrivent l'espace valide ou volontairement invalide à explorer.
- Le retour de
randomize()doit toujours être contrôlé. - Les distributions ciblent les cas importants et les trous de couverture.
randcest adapté aux petits domaines.- Une graine, la configuration et la transaction fautive doivent être enregistrées.
📝 Tester mes connaissances - Quiz du chapitre