Cette page est un complément à une autre page qu’il convient de lire avant celle-ci. Les deux pages font partie d’une série de pages qui expliquent la théorie derrière les calculs de timing, montrent comment écrire plusieurs contraintes temporelles et abordent les principes de la convergence temporelle.
N’utilisez les motifs de recherche simples que s’il le faut
Cette page explique comment utiliser les caractères génériques pour écrire des contraintes temporelles au format SDC. Même si les caractères génériques peuvent être utilisés avec plusieurs commandes Tcl, cette page se concentre sur les commandes qui prennent en charge l’option « -hierarchical » : get_cells, get_pins et get_nets. Ces commandes Tcl sont expliquées sur une autre page. Notez toutefois que certains outils FPGA ne prennent pas en charge « -hierarchical » avec ces trois commandes.
Malheureusement, la capacité de recherche de ces trois commandes est assez limitée et parfois déroutante : si l’on ne comprend pas exactement comment fonctionne le caractère générique, les résultats peuvent être inattendus. En particulier, lorsque « -hierarchical » est utilisé, les résultats peuvent surprendre, comme le montrent les exemples ci-dessous.
Pour cette raison, il est toujours préférable d’utiliser l’option « -filter » lorsque l’outil FPGA concerné la prend en charge pour la commande utilisée. En l’absence d’un tel support, on n’a pas d’autre choix que d’utiliser les caractères génériques simples.
Tous les exemples de cette page sont fondés sur le même code Verilog que celui de cette autre page connexe.
Motifs de recherche simples
Les commandes qui recherchent des éléments logiques et d’autres objets peuvent être utilisées avec ou sans motif de recherche. Sans motif, tous les objets pertinents sont trouvés. Par exemple, pour trouver toutes les broches (pins) au niveau supérieur de la hiérarchie :
get_pins
Et la commande qui trouve toutes les broches de l’ensemble du design FPGA est :
get_pins -hierarchical
Si un motif de recherche est utilisé, les résultats sont limités à ce motif. Par exemple, pour trouver une broche précise dont on connaît le nom et la position dans la hiérarchie :
> get_pins foo_reg_reg/Q foo_reg_reg/Q > get_pins pll_i/clk_in1 pll_i/clk_in1 > get_pins pll_i/inst/clk_in1 pll_i/inst/clk_in1
Le motif peut aussi contenir des caractères génériques, par exemple :
> get_pins foo_reg_reg/* foo_reg_reg/Q foo_reg_reg/C foo_reg_reg/CE foo_reg_reg/D foo_reg_reg/R > get_pins pll_i/* pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2 > get_pins pll_i/inst/* pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2 > get_pins pll_i/*/* pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2 > get_pins pll_i/*/clk* pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2
Le comportement du caractère générique
Il existe deux caractères génériques courants :
- L’astérisque (« * »), qui remplace n’importe quelle suite de caractères.
- Le point d’interrogation (« ? »), qui remplace un seul caractère.
Toutefois, ces deux caractères génériques ne s’appliquent jamais au séparateur de hiérarchie. Autrement dit, « * » et « ? » ne remplacent pas un « / » (ni un « | » avec Quartus). Cela vaut toujours avec les caractères génériques, que l’option « -hierarchical » soit utilisée ou non (mais notez qu’avec « -filter » ou « -regexp », c’est une autre histoire).
Il faut donc écrire explicitement la position exacte de l’objet dans la hiérarchie :
> get_pins */clk_* pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2 > get_pins */*/clk_* pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2
Notez que différents outils peuvent utiliser des caractères différents pour le séparateur de hiérarchie. Comme on vient de le mentionner, Quartus utilise le caractère barre verticale (« | »), et non « / », à cette fin.
L’option « -hierarchical » permet de trouver des éléments logiques où qu’ils se trouvent dans la hiérarchie du design. Elle évite d’avoir à préciser la position exacte dans la hiérarchie et permet aussi de trouver des éléments logiques dans tout le design FPGA avec une seule commande.
Répétons donc les mêmes expressions avec « -hierarchical » :
> get_pins -hierarchical */clk_* pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2 pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2 > get_pins -hierarchical */*/clk_* WARNING: [Vivado 12-508] No pins matched '*/*/clk_*'.
Avec « -hierarchical », le motif de recherche est appliqué à toutes les positions de la hiérarchie du design. Dans l’exemple ci-dessus, « */clk_* » a d’abord été appliqué au niveau supérieur de la hiérarchie — d’où, par exemple, « pll_i/clk_in1 » — puis le même motif a été appliqué à l’intérieur de « pll_i/ », d’où « pll_i/inst/clk_in1 ».
Mais pourquoi « */*/clk_* » n’a-t-il rien donné avec « -hierarchical » ? Le même motif donnait des résultats sans cette option. N’y a-t-il pas toujours plus de résultats avec « -hierarchical » ?
Avec -hierarchical, le motif de recherche est restreint
Curieusement, l’option « -hierarchical » ne change pas seulement l’endroit où le motif est appliqué : elle limite aussi les motifs autorisés. Malheureusement, les outils ne répondent pas par une erreur lorsqu’un motif illégal est utilisé. Ils répondent simplement qu’aucun objet n’est trouvé.
Chacune des trois commandes Tcl (get_cells, get_pins et get_nets) a sa propre règle qui restreint le motif de recherche. Pour connaître les limitations exactes, reportez-vous à la documentation de votre outil FPGA. L’interprétation standard (telle que détaillée dans la documentation de Synopsys) est présentée ci-dessous.
Notez que l’abréviation « -hier » est souvent utilisée à la place de « -hierarchical ». La signification est exactement la même.
get_cells -hierarchical
Lorsque get_cells est utilisé avec -hierarchical, le motif ne correspond qu’au nom de l’objet. Si le motif contient un séparateur de hiérarchie, le résultat est toujours vide. Par exemple :
> get_cells -hierarchical *_buf pll_i/inst/clkf_buf pll_i/inst/clkout1_buf pll_i/inst/clkout2_buf > get_cells -hierarchical inst/*_buf WARNING: [Vivado 12-180] No cells matched 'inst/*_buf'.
Notez qu’il s’agit d’une erreur si le motif contient un « / », car un tel motif ne donne jamais rien. Les outils ne répondent toutefois pas par une erreur : la commande ne retourne simplement aucun résultat.
Comme le séparateur de hiérarchie n’est pas autorisé dans le motif, get_cells se limite aux possibilités suivantes :
- Une recherche de cellules à une position précise de la hiérarchie (lorsque -hierarchical n’est pas utilisé).
- Une recherche de cellules dans l’ensemble du design FPGA à l’aide de -hierarchical.
- Utilisez plutôt -filter ou -regexp, si ces options sont prises en charge. Elles ne comportent pas cette limitation.
Cet exemple montre comment déclarer des chemins faux (false paths) pour toutes les cellules dont le nom suit un format particulier :
set_false_path -to [get_cells -hierarchical *metaguard*]
Avec une contrainte de ce genre, il suffit que tous les registres utilisés comme gardes de métastabilité (metastability guards) portent un nom contenant « metaguard ». Le risque, cependant, est que l’expression corresponde involontairement à un élément logique sans rapport, quelque part dans le design FPGA. Il est donc préférable de choisir un mot moins courant que « metaguard ».
get_nets -hierarchical
get_nets suit la même règle que get_cells : sans -hierarchical, get_nets trouve tous les fils (nets) du niveau supérieur de la hiérarchie qui correspondent au motif. Avec -hierarchical, le motif ne correspond qu’au nom de l’objet. Si le motif contient un séparateur de hiérarchie, le résultat est toujours vide.
> get_nets pll_i/clk_i* pll_i/clk_in1 > get_nets clk_i* WARNING: [Vivado 12-507] No nets matched 'clk_i*'. > get_nets -hierarchical clk_i* pll_i/clk_in1 pll_i/inst/clk_in1 > get_nets -hierarchical pll_i/clk_i* WARNING: [Vivado 12-507] No nets matched 'pll_i/clk_i*'.
get_pins -hierarchical
Lorsque get_pins est utilisé avec -hierarchical, le motif correspond au nom complet de la broche, par exemple baz_reg/Q, clkout1_buf/I, etc. Le « / » est alors considéré comme faisant partie du nom, et non comme un séparateur de hiérarchie. Autrement dit, le caractère situé entre le nom de la cellule et l’identifiant de la broche peut être remplacé par un caractère générique. Cela vaut uniquement pour le dernier séparateur de hiérarchie, et seulement lorsque -hierarchical est utilisé.
Ainsi, par exemple :
> get_pins -hierarchical clkout1_buf/* pll_i/inst/clkout1_buf/O pll_i/inst/clkout1_buf/CE pll_i/inst/clkout1_buf/I > get_pins -hierarchical clkout1_bu* pll_i/inst/clkout1_buf/O pll_i/inst/clkout1_buf/CE pll_i/inst/clkout1_buf/I > get_pins -hierarchical clkout1_buf WARNING: [Vivado 12-508] No pins matched 'clkout1_buf'.
Notez que clkout1_bu* correspond à clkout1_buf/O (entre autres). Le « * » peut être remplacé par « /O » uniquement grâce à -hierarchical.
Comme avec get_cells, si le motif contient un séparateur de hiérarchie, le résultat est toujours vide. Cela ne contredit pas l’exemple ci-dessus : comme mentionné, le dernier « / » est considéré comme faisant partie du nom de la broche.
> get_pins pll_i/inst/clkout1*/I pll_i/inst/clkout1_buf/I > get_pins -hierarchical pll_i/inst/clkout1*/I WARNING: [Vivado 12-508] No pins matched 'pll_i/inst/clkout1*/I'. > get_pins -hierarchical pll_i/inst/*/* WARNING: [Vivado 12-508] No pins matched 'pll_i/inst/*/*'. > get_pins -hierarchical pll_i/*/*/* WARNING: [Vivado 12-508] No pins matched 'pll_i/*/*/*'. > get_pins -hierarchical pll_i/*/* WARNING: [Vivado 12-508] No pins matched 'pll_i/*/*'. > get_pins -hierarchical pll_i/* pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2 > get_pins pll_i/* pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2
Notez que lorsque -hierarchical n’est pas utilisé, un caractère générique ne correspond jamais à un séparateur de hiérarchie, pas même au dernier :
> get_pins pll_i/inst/clkout1_buf/I pll_i/inst/clkout1_buf/I > get_pins pll_i/inst/clkout1_buf/* pll_i/inst/clkout1_buf/O pll_i/inst/clkout1_buf/CE pll_i/inst/clkout1_buf/I > get_pins pll_i/inst/clkout1_bu* WARNING: [Vivado 12-508] No pins matched 'pll_i/inst/clkout1_bu*'. > get_pins pll_i/inst/clkout1_bu*/* pll_i/inst/clkout1_buf/O pll_i/inst/clkout1_buf/CE pll_i/inst/clkout1_buf/I
Ces exemples montrent clairement à quel point get_pins peut prêter à confusion. Comme précédemment, utilisez plutôt -filter ou -regexp si ces options sont prises en charge.
Résumé
Même si les caractères génériques constituent une méthode disponible pour trouver des éléments logiques, les résultats ne sont pas toujours ceux que l’on attend naturellement. De même, l’option -hierarchical peut être utile dans certains scénarios, mais elle s’accompagne d’une restriction sur le motif de recherche et d’un comportement encore plus déroutant.
Il est donc recommandé d’utiliser d’autres méthodes pour sélectionner les éléments logiques : si -filter, -regexp ou -of_objects sont pris en charge par les outils FPGA, l’une de ces options est probablement une meilleure solution. L’utilisation de caractères génériques simples ne se justifie que si aucune de ces autres options n’est disponible, ou si aucune n’est utile dans le scénario concerné. Dans ce cas, il importe d’être particulièrement vigilant quant à la signification du motif de recherche.