Mon dossier d'apprentissage System Verilog (11)



 introduction

Cet article présente brièvement d'autres structures de programme de SystemVerilog.

Lien précédent :

Mon dossier d'apprentissage System Verilog (1)

Mon dossier d'apprentissage System Verilog (2)

Mon dossier d'apprentissage System Verilog (3)

Mon dossier d'apprentissage System Verilog (4)

Mon dossier d'apprentissage System Verilog (5)

Dossier d'apprentissage My System Verilog (6)

Mon dossier d'apprentissage System Verilog (7)

Mon dossier d'apprentissage System Verilog (8)

Mon dossier d'apprentissage System Verilog (9)

Mon dossier d'apprentissage System Verilog (10)



bloc de programme

Les modules sont la structure de base utilisée pour créer des conceptions, et chaque module peut contenir une hiérarchie d'autres modules, réseaux, variables et autres blocs de programme pour décrire n'importe quelle fonction matérielle. Un banc d'essai, d'autre part, est un environnement complet pour valider une conception, donc l'accent est mis sur la façon dont il est modélisé pour le rendre plus réutilisable et efficace. Doit être correctement initialisé et synchronisé pour éviter les conditions de concurrence entre la conception et le banc d'essai.

Quelles sont les exigences du bloc de programme ?

Le bloc de programme de SV a été introduit pour les raisons suivantes :

  • Fournit un point d'entrée pour l'exécution du banc de test
  • Créez un conteneur pour contenir toutes les autres données de testbench telles que les tâches, les objets de classe et les fonctions
  • Évitez les conditions de concurrence dans votre conception en exécutant dans la région réactive du cycle de simulation

La zone réactive est l'une des dernières étapes avant que le temps de simulation n'avance, moment auquel toutes les déclarations d'éléments de conception ont été exécutées et le banc d'essai verra les valeurs mises à jour. Il est important d'avoir cette division entre l'exécution de la conception et la déclaration du banc d'essai car elle fournira une sortie plus déterministe entre les simulateurs.

grammaire

exemple

 Les blocs procéduraux peuvent être imbriqués dans des modules et des interfaces, de sorte que plusieurs programmes dans le même module peuvent partager des variables locales à cette portée. Dans l'exemple ci-dessous, schema est une variable locale dans TB, accessible par les programmes p1 et p2.



casting dynamique

Lorsque vous devez affecter une valeur entre deux variables de types de données différents, l'affectation ordinaire peut ne pas fonctionner et une tâche système appelée $cast doit être utilisée à la place.
$cast peut être utilisé en tant que tâche ou en tant que fonction, la différence est que lorsqu'il est utilisé en tant que fonction, il renvoie 1 si le cast est valide. Cela devient utile lorsqu'il s'agit d'affectations invalides.

grammaire

Ici, targ_var est la variable cible et source_exp est l'expression source qui doit être calculée et affectée à la variable cible.

appel avec fonction/tâche

Lorsque $cast est appelé en tant que tâche, il tentera d'assigner l'expression source à la variable cible, et si elle n'est pas valide, une erreur d'exécution se produira, tandis que la variable cible restera inchangée.
Lorsque $cast est appelé en tant que fonction, il tentera d'affecter l'expression source à la variable de destination, renvoyant 1 en cas de succès. S'il échoue et renvoie 0, aucune allocation ne sera effectuée. Notez que dans ce cas, aucune erreur d'exécution ne se produira et la simulation se poursuivra avec la valeur inchangée de la variable cible.

exemple

utiliser $ cast 

 sans $cast

Certains émulateurs donneront des avertissements de compilation, et certains signaleront des erreurs.

Transférer de force des données invalides

 Il n'y a pas d'élément avec une valeur de 75 dans la variable d'énumération, et une erreur sera signalée pendant l'opération.

appeler en tant que fonction



emballer

Un package fournit un mécanisme de stockage et de partage de données, de méthodes, de propriétés et de paramètres qui peuvent être réutilisés dans plusieurs autres modules, interfaces ou programmes. Ils nomment explicitement la portée au même niveau que le module de niveau supérieur. Par conséquent, tous les paramètres et énumérations peuvent être référencés via cette étendue. Mettre de telles définitions et déclarations dans un package évite également d'encombrer le miroir de noms global. Le package peut ensuite être importé dans la portée actuelle où les éléments du package peuvent être utilisés. Notez que les éléments d'un package ne peuvent pas avoir de références hiérarchiques à des identifiants, à l'exception de ceux créés dans le package ou rendus visibles en important un autre package.

exemple

Les packages présentés ci-dessus peuvent être importés dans d'autres modules et portées de classe afin que les éléments qui y sont définis puissent être réutilisés. Cela peut être fait en utilisant le mot-clé import suivi de l'opérateur de résolution de portée :: suivi en spécifiant ce qu'il faut importer. Dans l'exemple ci-dessous, nous importons tout ce qui est défini dans le package, comme indiqué par l'opérateur * ci-dessous, pour pouvoir utiliser n'importe quel élément.

 Notez que le package doit être importé pour que le compilateur reconnaisse où green est défini. Si le package n'est pas importé, une erreur de compilation apparaîtra comme indiqué ci-dessous.

Si vous savez exactement ce qui est utilisé dans votre code, vous pouvez également les importer individuellement au lieu d'importer toutes les définitions du package. Cependant, cela est considéré comme une surcharge, en particulier lorsque plusieurs membres sont accessibles à partir du package.

L'omission de l'une de ces trois instructions d'importation entraînera une erreur du compilateur car il ne sait pas où elles sont définies à moins qu'elles ne soient importées.

conflit d'espace de noms

Prenons l'exemple suivant, où des définitions identiques existent, l'une au niveau supérieur et l'autre via un package importé.

Notez que même si my_pkg est importé, la valeur Read de la variable e_rd_wr OPC2 est 1, ce qui signifie que la valeur d'énumération dans le package n'est pas prise en compte.

 Pour que l'émulateur applique la valeur du package, le nom du package doit être mentionné explicitement à l'aide de l'opérateur :: comme indiqué ci-dessous.



entrée de ligne de commande

Parfois, vous devez éviter de recompiler testbench et être en mesure d'accepter les valeurs de la ligne de commande comme n'importe quel langage de script comme bash ou perl. Dans SystemVerilog, ces informations sont fournies à la simulation sous la forme d'un argument facultatif qui commence toujours par un caractère. Ces arguments transmis depuis la ligne de commande sont accessibles dans le code SV via la fonction système suivante appelée plusargs.

grammaire

$test$plusargs

La fonction $test$plusargs est généralement utilisée lorsque la valeur de l'argument n'est pas requise. Il recherche une liste de signes plus pour une chaîne spécifiée par l'utilisateur. Les variables peuvent également être utilisées pour spécifier des chaînes, tous les caractères nuls seront ignorés. La fonction renvoie un entier différent de zéro si un préfixe de l'un des signes plus fournis correspond à tous les caractères de la chaîne fournie, et zéro dans le cas contraire.

exemple

Lors de la compilation et de la simulation du code illustré ci-dessus avec l'argument d'exécution +STANDBY, où STANDBY est la chaîne plusarg fournie à l'outil de simulation, nous obtenons la sortie indiquée ci-dessous. Notez que plusarg est sensible à la casse, il correspond à "S" et "STAND" même si la chaîne fournie est "STANDBY".

$value$plusargs

La fonction système $value$plusargs recherche également la liste des plusargs, comme $test$plusargs, mais elle a la capacité d'obtenir la valeur d'une chaîne utilisateur spécifiée. Si un préfixe plusarg fourni correspond à tous les caractères de la chaîne utilisateur donnée, la fonction renverra une valeur différente de zéro et stockera la valeur résultante dans la variable fournie. Si aucune chaîne utilisateur n'est trouvée, la fonction renverra une valeur différente de zéro et la variable ne sera pas modifiée.
La chaîne utilisateur doit être "plusarg_string format_string", où la chaîne de format est la même que la tâche $display. Ces identifiants de format permettent de convertir une valeur fournie via la ligne de commande dans un format donné et de la stocker dans une variable.

 Exemple:

Pour différents paramètres d'entrée, nous obtiendrons une sortie différente. Notez également qu'il ne doit y avoir aucun espace entre les chaînes utilisateur, = et les valeurs dans les expressions de ligne de commande.

Exemple concret :

Arguments de ligne de commande SystemVerilog



opération de fichier

ouvrir/fermer le fichier

Les fichiers peuvent être ouverts en lecture ou en écriture à l'aide de la tâche système $fopen(). Cette tâche renverra un descripteur d'entier 32 bits appelé descripteur de fichier. Cette poignée doit être utilisée pour lire et écrire dans le fichier jusqu'à ce qu'il soit fermé. Les descripteurs de fichiers peuvent être fermés à l'aide de la tâche système $flose(). Une fois fermé, aucune autre lecture ou écriture dans le descripteur de fichier n'est autorisée.

exemple

 Comment ouvrir en mode lecture et ajout ?

exemple

Comment lire et écrire des fichiers ?

Lors de l'écriture d'un fichier, la méthode d'ouverture du fichier est w (w+) ou a (a+) ; pour écrire du texte, utilisez $fdisplay() ou $fwrite();

Lors de la lecture d'un fichier, ouvrez le fichier en mode r ou r+, $fgets() lit une ligne à chaque fois qu'il est appelé ;

exemple

Comment savoir si vous avez atteint la fin du fichier ?

Utilisez $feof(); tâche système. Si la fin du fichier est lue, retourne 1 ;

exemple

 Comment analyser les données en ligne ?

Utilisez la tâche système $fscanf(). Les exemples sont les suivants :



Spécificateur de portée SV

L'opérateur de portée :: est utilisé pour faire référence à des identificateurs dans la portée d'une classe.
Le côté gauche de l'opérateur de résolution de portée :: doit être un nom de type de classe, un nom de package, un nom de type de groupe de couverture, un nom de point de couverture ou d'intersection, un nom de définition de type (typedef). Le côté droit de l'opérateur doit être un identifiant comme un nom de variable ou de méthode.

Quel est l'intérêt des spécificateurs de portée ?

Les classes et autres étendues peuvent avoir le même nom d'identifiant, créant potentiellement un conflit d'espace de noms si l'étendue n'est pas spécifiée.
L'opérateur de résolution de portée identifie de manière unique un membre ou un paramètre d'une classe donnée.
Ils sont également utilisés pour accéder aux variables et méthodes statiques, aux paramètres et aux paramètres locaux des classes en dehors de la classe. Il permet également l'accès aux membres publics de la classe de base et aux membres protégés des sous-classes.

exemple

définir des fonctions externes

Accès aux méthodes/fonctions statiques

utiliser le paquet

Éviter les conflits d'espace de noms

 

Je suppose que tu aimes

Origine blog.csdn.net/qq_43045275/article/details/129664250
conseillé
Classement