Ctags: VHDL : ajout de processus et de types de composants instanciés

Créé le 26 oct. 2020  ·  42Commentaires  ·  Source: universal-ctags/ctags

Voici les types VHDL analysés dans la dernière implémentation de ctags :

static kindDefinition VhdlKinds[] = {
    {true, 'c', "constant", "constant declarations"},
    {true, 't', "type", "type definitions"},
    {true, 'T', "subtype", "subtype definitions"},
    {true, 'r', "record", "record names"},
    {true, 'e', "entity", "entity declarations"},
    {false, 'C', "component", "component declarations"},
    {false, 'd', "prototype", "prototypes"},
    {true, 'f', "function", "function prototypes and declarations"},
    {true, 'p', "procedure", "procedure prototypes and declarations"},
    {true, 'P', "package", "package definitions"},
    {false, 'l', "local", "local definitions"}
};

https://github.com/universal-ctags/ctags/blob/master/parsers/vhdl.c

Veuillez ajouter trois types supplémentaires :

  • Traiter:
optional_label: process (optional sensitivity list)
    declarations
begin
    sequential statements
end process optional_label;

optional_label est l'étiquette de processus facultative et doit être signalée comme balise (par exemple kind = process ). S'il manque, une chaîne aléatoire (par exemple 4534_process) doit être utilisée comme nom de balise à la place. Les structures anonymes analysées de ctags en C peuvent être considérées comme un exemple.

  • Composant instancié et son nom d'instance :
instance_label: component_name
    generic map (generic_association_list)
    port map (port_association_list);

instance_label est l'étiquette d'instanciation de composant obligatoire et doit être signalée comme balise (par exemple, kind = component instance label ). component_name est le nom du composant instancié et doit également être signalé comme balise (par exemple kind = component instance ), afin que les balises de composant/entité associées puissent être trouvées.

Tous les 42 commentaires

J'ai trouvé un exemple dans nos cas de test :

entity accumulator is port (
  a: in std_logic_vector(3 downto 0);
  clk, reset: in std_logic;
  accum: out std_logic_vector(3 downto 0)
  );
end accumulator;

architecture simple of accumulator is

signal accumL: unsigned(3 downto 0);

begin

  accumulate: process (clk, reset) begin
    if (reset = '1') then
      accumL <= "0000";
    elsif (clk'event and clk= '1') then
      accumL <= accumL + to_unsigned(a);
    end if;
  end process;

  accum <= std_logic_vector(accumL);

end simple;

Avant de parler de processus, j'ai une question. Je pense que "simple" devrait être étiqueté si nous devions créer une étiquette pour accumuler.
Ai-je raison? Dans ce cas, quel "type" devrions-nous utiliser pour "simple" ?

Oui, simple devrait également être tagué. Chaque entité VHDL a une architecture qui définit le comportement de l'entité elle-même.

Ainsi, je proposerais d'ajouter un autre type VHDL : a , pour architecture bodies .

@pidgeon777 , merci.

2687 est une pull request pour baliser les architectures.

entity accumulator is port (
  a: in std_logic_vector(3 downto 0);
  clk, reset: in std_logic;
  accum: out std_logic_vector(3 downto 0)
  );
end accumulator;

Je pense que a, clk, accum, accumL devrait aussi être étiqueté.
Pour taguer accumL, nous devrions introduire le type "signal".
Pour taguer a, clk, accum, ~quel type devrions-nous introduire ?~ Je suppose que nous devrions introduire le type "port".

les champs d'étendue ne sont pas remplis. Vous ne pouvez donc rien faire d'intéressant.

Pour taguer a, clk, accum, quel genre devrions-nous introduire ? Je suppose que nous devrions introduire le type "port".

Oui, ils devraient également être étiquetés, éventuellement comme port declarations :

http://www.vhdl.renerta.com/mobile/source/vhd00051.htm

Pour taguer accumL, nous devrions introduire le type "signal".

signal declarations serait également acceptable :

http://www.vhdl.renerta.com/source/vhd00064.htm

les champs d'étendue ne sont pas remplis. Vous ne pouvez donc rien faire d'intéressant.

Je n'ai pas compris le point ci-dessus.

Cependant, nous ne devons pas non plus oublier les génériques :

http://www.vhdl.renerta.com/source/vhd00034.htm

Celles-ci sont également très importantes en VHDL et doivent donc également être étiquetées.

Merci.

champ de portée représente les relations propriétaire/possédé ou parent/enfant.
Les outils clients peuvent créer une "arborescence" à partir des champs.

Je voudrais montrer un exemple en langage C.

entrée.c :

     1  struct point {
     2      int x, y;
     3  };
     4  int length (point *p0, point *p1)
     5  {
     6     int dx = p1->x - p0->x;
     7     int dy = p1->y - p0->y;
     8     return (int)sqrt((double)(dx*dx + dy*dy));
     9  }

sortie ctags :

% u-ctags --sort=no --fields=+KkZzSe-lf -n --kinds-C=+zl -o - input.c 
point   input.c 1;" kind:struct end:3
x   input.c 2;" kind:member scope:struct:point  typeref:typename:int    end:2
y   input.c 2;" kind:member scope:struct:point  typeref:typename:int    end:2
length  input.c 4;" kind:function   typeref:typename:int    signature:(point * p0,point * p1)   end:9
p0  input.c 4;" kind:parameter  scope:function:length   typeref:typename:point *
p1  input.c 4;" kind:parameter  scope:function:length   typeref:typename:point *
dx  input.c 6;" kind:local  scope:function:length   typeref:typename:int    end:6
dy  input.c 7;" kind:local  scope:function:length   typeref:typename:int    end:7

Voir portée : dans la sortie.

Pensons au VHDL.

entity accumulator is port (
  a: in std_logic_vector(3 downto 0);
  clk, reset: in std_logic;
  accum: out std_logic_vector(3 downto 0)
  );
end accumulator;

La portée de a , clk et accum peut être : " scope:entity :accumulator".
Ceux-ci sont faciles.

architecture simple of accumulator is

signal accumL: unsigned(3 downto 0);

begin
...

Que diriez-vous accumL ?
Une de mes idées est scope:architecture:simple .
Ce sera mieux que scope:entity:accumulator car l'accumulateur peut avoir plusieurs architectures.

VHDL: tag architectures #2687 est fusionné.

Pour taguer a, clk, accum, quel genre devrions-nous introduire ? Je suppose que nous devrions introduire le type "port".

Oui, elles doivent également être étiquetées, éventuellement en tant que déclarations de port :

Voulez-vous dire que "déclaration de port" est préférable à "port" comme nom de genre pour a, clk, accum ?
J'ai fait une pull request (#2695) pour le marquage des ports. J'ai utilisé "port" comme nom de genre. Est-ce que je vais dans le mauvais sens ?

Me revoilà. Je pense que ctags a beaucoup de potentiel pour baliser les langages HDL ( VHDL , Verilog , SystemVerilog ) même à des fins d'analyse de code/de peluchage, donc je ' Je suis plus qu'heureux de vous aider.

Il ne me sera peut-être pas possible de répondre rapidement certains jours, mais j'essaierai de répondre à toutes vos questions dès que possible.

De plus, j'ai quelques idées intéressantes à partager plus tard dans la journée, et je vous fournirai également les réponses que vous avez demandées.

Excellent!

@pidgeon777 ,
Pensez-vous que "port" est un mauvais nom?

$ ./ctags --list-kinds=SystemVerilog
c  constants (define, parameter, specparam, enum values)
e  events
f  functions
m  modules
n  net data types
p  ports

Je ne connais pas bien les langues pour le matériel. Cependant, "port" est utilisé dans SystemVerilog.
Je suppose donc que l'utilisation du même nom en VHDL peut convenir

Salut @masatake , la liste des types VHDL :

c  constant declarations
t  type definitions
T  subtype definitions
r  record names
e  entity declarations
C  component declarations [off]
d  prototypes [off]
f  function prototypes and declarations
p  procedure prototypes and declarations
P  package definitions
l  local definitions [off]

port pourrait convenir, mais si vous souhaitez conserver le même format utilisé dans ces types de VHDL, je pense que l'un des éléments suivants pourrait être plus approprié :

  • port declarations ← meilleur
  • port definitions

Pourtant, je ne suis pas si sûr de la différence entre la définition et la déclaration en VHDL. Un cas C++ :

https://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration

Plus tard dans la soirée, j'essaierai de répondre aux autres questions que vous avez posées, j'ai déjà pris quelques notes il y a quelques jours.

Je vois. Vous parlez de "DESCRIPTION".

$ ./ctags --list-kinds-full=VHDL      
#LETTER NAME         ENABLED REFONLY NROLES MASTER DESCRIPTION
C       component    no      no      0      NONE   component declarations
P       package      yes     no      0      NONE   package definitions
T       subtype      yes     no      0      NONE   subtype definitions
a       architecture yes     no      0      NONE   architectures
c       constant     yes     no      0      NONE   constant declarations
d       prototype    no      no      0      NONE   prototypes
e       entity       yes     no      0      NONE   entity declarations
f       function     yes     no      0      NONE   function prototypes and declarations
l       local        no      no      0      NONE   local definitions
p       procedure    yes     no      0      NONE   procedure prototypes and declarations
r       record       yes     no      0      NONE   record names
t       type         yes     no      0      NONE   type definitions

Nous ne considérons pas DESCRIPTION comme la partie de la CLI ctags dont nous devrions conserver la compatibilité.
La valeur de DESCRIPTION n'apparaît pas dans la sortie des balises.
Ce que je voudrais savoir, c'est NOM. Le NOM fait partie de la CLI.
La valeur de NAME apparaît dans la sortie des balises. Ainsi, un outil lisant un fichier de balises peut dépendre de la valeur de NAME.
Ma question initiale est de savoir si "port" est un NOM de type approprié ou non.
Je pense que "port" comme NAME est correct. Ce que je dois mettre à jour est le champ DESCRIPTION pour le type "port":

diff --git a/parsers/vhdl.c b/parsers/vhdl.c
index 868c02e3..e276d978 100644
--- a/parsers/vhdl.c
+++ b/parsers/vhdl.c
@@ -204,7 +204,7 @@ static kindDefinition VhdlKinds[] = {
    {true, 'P', "package", "package definitions"},
    {false, 'l', "local", "local definitions"},
    {true, 'a', "architecture", "architectures"},
-   {false, 'q', "port", "ports"},
+   {false, 'q', "port", "port declarations"},
 };

Avec ce changement, --list-kinds-full=VHDL rapporte :

...
p       procedure    yes     no      0      NONE   procedure prototypes and declarations
q       port         no      no      0      NONE   port declarations
r       record       yes     no      0      NONE   record names
...

Je pense que "port" comme NAME est correct

Je confirme.

q port no no 0 NONE port declarations

Aussi ce serait parfait.

Mais, parlant d'un port, il serait essentiel à mon avis de le rattacher à un champ d'application. Ou, si vous préférez, étant donné un port appelé PORT_C , cela pourrait être déclaré dans deux ou plusieurs entités différentes, ainsi le nom de l'entité doit être utilisé comme portée pour le port.

Exemple:

entity ENTITY_A is
  generic (
    GENERIC_C : integer := value;
  );
  port (
    PORT_C : in std_logic
  );
end entity;

entity ENTITY_B is
  generic (
    GENERIC_C : integer := value;
  );
  port (
    PORT_C : in std_logic
  );
end entity;

Balises analysées :

 6:PORT_C   scope:entity:ENTITY_A
15:PORT_C   scope:entity:ENTITY_B

On pourrait aussi avoir :

component COMPONENT_A is
  generic (
    GENERIC_C : integer := value;
  );
  port (
    PORT_C : in std_logic
  );
end entity;

component COMPONENT_B is
  generic (
    GENERIC_C : integer := value;
  );
  port (
    PORT_C : in std_logic
  );
end entity;

Balises analysées :

 6:PORT_C   scope:component:COMPONENT_A
15:PORT_C   scope:component:COMPONENT_B

Merci pour la description détaillée.
Dans #2695, j'ai déjà rempli les champs de portée des déclarations de port si elles sont dans des entités.

Je n'ai rien fait pour les déclarations de port dans les composants.
Je vais réviser mon changement.

Avec le changement proposé dans #2695, l'analyseur VHDL peut extraire les ports et les génériques déclarés dans une entité et un composant.

$  u-ctags --list-kinds-full=VHDL 
#LETTER NAME         ENABLED REFONLY NROLES MASTER DESCRIPTION
C       component    no      no      0      NONE   component declarations
P       package      yes     no      0      NONE   package definitions
T       subtype      yes     no      0      NONE   subtype definitions
a       architecture yes     no      0      NONE   architectures
c       constant     yes     no      0      NONE   constant declarations
d       prototype    no      no      0      NONE   prototypes
e       entity       yes     no      0      NONE   entity declarations
f       function     yes     no      0      NONE   function prototypes and declarations
g       generic      no      no      0      NONE   generic declarations
l       local        no      no      0      NONE   local definitions
p       procedure    yes     no      0      NONE   procedure prototypes and declarations
q       port         no      no      0      NONE   port declarations
r       record       yes     no      0      NONE   record names
t       type         yes     no      0      NONE   type definitions
$  cat input.vhd                          
-- https://www.ics.uci.edu/~jmoorkan/vhdlref/Synario%20VHDL%20Manual.pdf
entity logical_ops_1 is
  port (a, b, c, d: in bit;
        m: out bit);
end logical_ops_1;
$  u-ctags --sort=no --kinds-VHDL='*' -o - input.vhd
logical_ops_1   input.vhd   /^entity logical_ops_1 is$/;"   e
a   input.vhd   /^  port (a, b, c, d: in bit;$/;"   q   entity:logical_ops_1
b   input.vhd   /^  port (a, b, c, d: in bit;$/;"   q   entity:logical_ops_1
c   input.vhd   /^  port (a, b, c, d: in bit;$/;"   q   entity:logical_ops_1
d   input.vhd   /^  port (a, b, c, d: in bit;$/;"   q   entity:logical_ops_1
m   input.vhd   /^        m: out bit);$/;"  q   entity:logical_ops_1
$  cat input-0.vhd                                  
-- Taken from https://github.com/universal-ctags/ctags/issues/2678
-- commented by @pidgeon777.
entity ENTITY_A is
  generic (
    GENERIC_C : integer := value;
  );
  port (
    PORT_C : in std_logic
  );
end entity;

entity ENTITY_B is
  generic (
    GENERIC_C : integer := value;
  );
  port (
    PORT_C : in std_logic
  );
end entity;
$  u-ctags --sort=no --kinds-VHDL='*' -o - input-0.vhd
ENTITY_A    input-0.vhd /^entity ENTITY_A is$/;"    e
GENERIC_C   input-0.vhd /^    GENERIC_C : integer := value;$/;" g   entity:ENTITY_A
PORT_C  input-0.vhd /^    PORT_C : in std_logic$/;" q   entity:ENTITY_A
ENTITY_B    input-0.vhd /^entity ENTITY_B is$/;"    e
GENERIC_C   input-0.vhd /^    GENERIC_C : integer := value;$/;" g   entity:ENTITY_B
PORT_C  input-0.vhd /^    PORT_C : in std_logic$/;" q   entity:ENTITY_B
$  cat input-1.vhd                                    
-- Taken from https://github.com/universal-ctags/ctags/issues/2678
-- commented by @pidgeon777.
component COMPONENT_A is
  generic (
    GENERIC_C : integer := value;
  );
  port (
    PORT_C : in std_logic
  );
end entity;

component COMPONENT_B is
  generic (
    GENERIC_C : integer := value;
  );
  port (
    PORT_C : in std_logic
  );
end entity;
$  u-ctags --sort=no --kinds-VHDL='*' -o - input-1.vhd
COMPONENT_A input-1.vhd /^component COMPONENT_A is$/;"  C
GENERIC_C   input-1.vhd /^    GENERIC_C : integer := value;$/;" g   component:COMPONENT_A
PORT_C  input-1.vhd /^    PORT_C : in std_logic$/;" q   component:COMPONENT_A
COMPONENT_B input-1.vhd /^component COMPONENT_B is$/;"  C
GENERIC_C   input-1.vhd /^    GENERIC_C : integer := value;$/;" g   component:COMPONENT_B
PORT_C  input-1.vhd /^    PORT_C : in std_logic$/;" q   component:COMPONENT_B

Le dernier est un signal sur lequel je devrais travailler avant de travailler sur le processus et l'instance.

Si j'ai fait quelque chose de mal, faites-le moi savoir.

@pidgeon777 ,

component COMPONENT_A is
  generic (
    GENERIC_C : integer := value;
  );
  port (
    PORT_C : in std_logic
  );
end entity;

Est la dernière ligne, "end entity ;" correct?
Après avoir lu quelques articles sur VHDL, je suppose que la ligne devrait être "composant de fin ;" ?

Est la dernière ligne, "end entity ;" correct?

Ma faute, quand j'ai copié-collé la déclaration du composant j'ai oublié de changer la dernière ligne. Je ferai plus attention la prochaine fois.

La déclaration de composant correcte est :

component COMPONENT_A is
  generic (
    GENERIC_C : integer := value
  );
  port (
    PORT_C : in std_logic
  );
end component [COMPONENT_A];

Notez que le nom du composant à la fin de end component n'est pas obligatoire dans le code, seulement facultatif. Je l'ai donc mis entre crochets.

Plus généralement, pour la déclaration de composant :

component component_name [ is ] 
  [ generic ( generic_list ); ] 
  [ port ( port_list ); ] 
end component [ component_name ]; 

Je suggère fortement cette référence pour les déclarations et définitions VHDL :

https://www.hdlworks.com/hdl_corner/vhdl_ref/

Avec le changement proposé dans #2695, l'analyseur VHDL peut extraire les ports et les génériques déclarés dans une entité et un composant.

Considérons maintenant la situation suivante. ENTITY_TOP instancie à la fois ENTITY_1 et ENTITY_2 :

entrée.vhd :

library ieee;
use ieee.std_logic_1164.all;

entity ENTITY_TOP is
  generic (
    GEN : integer := 0
  );
  port (
    INP : in std_logic
  );
end entity;

architecture arch of ENTITY_TOP is
  signal sig : std_logic := '0';

  component ENTITY_1
    generic (
      GEN : integer := 0
    );
    port (
      INP : in std_logic
    );
  end component;

  component ENTITY_2
    generic (
      GEN : integer := 0
    );
    port (
      INP : in std_logic
    );
  end component;

begin

  ENTITY_1_i : ENTITY_1
  generic map(
    GEN => 0
  )
  port map(
    INP => '0'
  );

  ENTITY_2_i : ENTITY_2
  generic map(
    GEN => 0
  )
  port map(
    INP => '0'
  );

end architecture;

entrée-0.vhd :

library ieee;
use ieee.std_logic_1164.all;

entity ENTITY_1 is
  generic (
    GEN : integer := 0
  );
  port (
    INP : in std_logic
  );
end entity;

architecture arch of ENTITY_1 is

  signal sig : std_logic := '0';

begin
end architecture;

entrée-1.vhd :

library ieee;
use ieee.std_logic_1164.all;

entity ENTITY_2 is
  generic (
    GEN : integer := 0
  );
  port (
    INP : in std_logic
  );
end entity;

architecture arch of ENTITY_2 is

  signal sig : std_logic := '0';

begin
end architecture;

Nous pouvons noter ce qui suit :

1) GEN générique est le même nom pour les trois entités, ainsi que les deux composants, et enfin les deux instanciations de composants. Le nom de l'entité ou du composant doit-il être utilisé comme étendue pour différencier les différentes balises GEN ? Exemple : GEN:scope:entity:ENTITY_TOP , GEN:scope:entity:ENTITY_1 , GEN:scope:entity:ENTITY_2 , GEN:scope:component:ENTITY_1 , GEN:scope:component:ENTITY_2 , GEN:scope:instance:ENTITY_1 , GEN:scope:instance:ENTITY_2 .
2) INP generic est le même nom pour les trois entités, ainsi que les deux composants, et enfin les deux instanciations de composants. Le nom de l'entité ou du composant doit-il être utilisé comme étendue pour différencier les différentes balises INP ? Exemple : INP:scope:entity:ENTITY_TOP , INP:scope:entity:ENTITY_1 , INP:scope:entity:ENTITY_2 , INP:scope:component:ENTITY_1 , INP:scope:component:ENTITY_2 , INP:scope:instance:ENTITY_1 , INP:scope:instance:ENTITY_2 .
3) arch est le même nom pour l'architecture des trois entités. Le nom de l'entité doit-il être utilisé comme étendue pour différencier les trois balises arch ? Exemple : arch:scope:ENTITY_TOP , arch:scope:ENTITY_1 , arch:scope:ENTITY_2 .
4) sig est le même nom pour le signal des trois architectures. Le nom de l'entité et de l'architecture doit-il être utilisé comme étendue pour différencier les trois balises arch ? Exemple : sig:scope:arch:ENTITY_TOP , sig:scope:arch:ENTITY_1 , sig:scope:arch:ENTITY_2 . À la fois entité et architecture, car une entité peut avoir plusieurs architectures partageant la définition d'un signal avec le même nom, et le même nom de signal peut être utilisé dans l'architecture de différentes entités.


@masatake a ajouté des noms de fichiers pour chaque exemple de code.

  1. Oui.
  2. Oui.
  3. non. J'ai décidé d'utiliser entity: field pour représenter la relation entre l'architecture et son entité.
  4. Oui.

Je voudrais que vous lisiez https://docs.ctags.io/en/latest/units.html. J'ai ajouté des cas de test en fonction de votre entrée à ma demande d'extraction.
Je voudrais que vous lisiez args.ctags, input(-[0-9])?.vhd et les balises attendues. Ils expliquent comment fonctionne mon amélioration.

J'expliquerai 3 plus tard.

Vous n'avez pas besoin de voir les modifications apportées aux fichiers sous Units/review-needed.r/test.vhd.t/. Ils sont trop grands.

Après avoir repensé à 3., je devrais utiliser le champ de portée au lieu du champ d'entité pour représenter la relation entre l'architecture et l'entité. Cela rompt les compatibilités.

process a été ajouté dans #2695 .

instance_label: component_name
    generic map (generic_association_list)
    port map (port_association_list);

Je pense que instance_label devrait être étiqueté avec le type "instance".
Le champ typeref peut être utilisé pour attacher "component_name" à la balise.
component_name est étiqueté comme balise de référence avec le type "composant".

instance_label  input.vhd /^...$/;"  kind:instance scope:... typeref:component:component_name roles:def
component_nameinput.vhd /^...$/;"  kind:component roles:instantiated instance:instance_label

instance: est un champ spécifique au VHDL.

Je pense que je dois écrire une page de manuel pour l'analyseur VHDL.

Je voudrais que vous lisiez https://docs.ctags.io/en/latest/units.html. J'ai ajouté des cas de test en fonction de votre entrée à ma demande d'extraction.
Je voudrais que vous lisiez args.ctags, input(-[0-9])?.vhd et les balises attendues. Ils expliquent comment fonctionne mon amélioration.

Ok je vais lire ça.

Après avoir repensé à 3., je devrais utiliser le champ de portée au lieu du champ d'entité pour représenter la relation entre l'architecture et l'entité. Cela rompt les compatibilités.

Le fait est que :

  • Dans une bibliothèque, chaque entité a son nom unique. Aucune entité partageant le même nom n'est autorisée dans une bibliothèque.
  • Une entité peut avoir plusieurs architectures, mais celles-ci doivent avoir des noms uniques.
  • Le même nom d'architecture peut être utilisé dans plusieurs entités.
  • Chaque étiquette à l'intérieur d'une architecture (instanciation de composant, instruction de génération, etc.) doit être unique.
  • Un composant ne peut être associé qu'à une seule entité d'une bibliothèque, mais il est possible de choisir quelle architecture instancier si l'entité comprend plusieurs architectures.

Ainsi, par exemple :

ENTITY_1.vhd :

library ieee;
use ieee.std_logic_1164.all;

entity ENTITY_1 is
  generic (
    GEN : integer := 0
  );
  port (
    INP : in std_logic
  );
end entity;

architecture arch1 of ENTITY_1 is

  signal sig : std_logic := '0';

begin
end architecture;

architecture arch2 of ENTITY_1 is

  signal sig : std_logic := '0';

begin
end architecture;

ENTITY_2.vhd :

library ieee;
use ieee.std_logic_1164.all;

entity ENTITY_2 is
  generic (
    GEN : integer := 0
  );
  port (
    INP : in std_logic
  );
end entity;

architecture arch1 of ENTITY_2 is

  signal sig : std_logic := '0';

begin
end architecture;

architecture arch2 of ENTITY_2 is

  signal sig : std_logic := '0';

begin
end architecture;

ENTITY_TOP.vhd :

library ieee;
use ieee.std_logic_1164.all;

entity ENTITY_TOP is
  generic (
    GEN : integer := 0
  );
  port (
    INP : in std_logic
  );
end entity;

architecture arch of ENTITY_TOP is
  signal sig : std_logic := '0';

  component ENTITY_1
    generic (
      GEN : integer := 0
    );
    port (
      INP : in std_logic
    );
  end component;

  component ENTITY_2
    generic (
      GEN : integer := 0
    );
    port (
      INP : in std_logic
    );
  end component;

begin

  ENTITY_1_i : entity work.ENTITY_1(arch1)
  generic map(
    GEN => 0
  )
  port map(
    INP => '0'
  );

  ENTITY_2_i : entity work.ENTITY_2(arch2)
  generic map(
    GEN => 0
  )
  port map(
    INP => '0'
  );

end architecture;
````

Some examples of expected tags:

- ENTITY_TOP

ENTITY_TOP:entity

- ENTITY_1

ENTITY_1:entity
ENTITY_1:component:entity:ENTITY_TOP
ENTITY_1:component instance:entity:ENTITY_TOP

- ENTITY_2

ENTITY_2:entity
ENTITY_2:component:entity:ENTITY_TOP
ENTITY_2:component instance:entity:ENTITY_TOP

- GEN

GEN:generic:entity:ENTITY_TOP
GEN:generic:entity:ENTITY_1
GEN:generic:entity:ENTITY_2
GEN:generic:component:ENTITY_1:entity:ENTITY_TOP → Tag of the generic `GEN` of the component `ENTITY_1` in `ENTITY_TOP`
GEN:generic:component:ENTITY_2:entity:ENTITY_TOP → Tag of the generic `GEN` of the component `ENTITY_2` in `ENTITY_TOP`
GEN:generic:instance label:ENTITY_1_i:(component:ENTITY_1):entity:ENTITY_TOP ? Tag of the generic map `GEN` of the instance `ENTITY_1_i` of the component `ENTITY_1` in `ENTITY_TOP` (`instance label:ENTITY_1_i` has to be associated to `component:ENTITY_1`, so the latter may be redundant for this particular tag of `GEN`, thus reported between parenthesis)
GEN:generic:instance label:ENTITY_2_i:(component:ENTITY_2):entity:ENTITY_TOP ? Tag of the generic map `GEN` of the instance `ENTITY_2_i` of the component `ENTITY_2` in `ENTITY_TOP` (`instance label:ENTITY_2_i` has to be associated to `component:ENTITY_2`, so the latter may be redundant for this particular tag of `GEN`, thus reported between parenthesis)

- INP

INP:port:entity:ENTITY_TOP
INP:port:entity:ENTITY_1
INP:port:entity:ENTITY_2
INP:port:component:ENTITY_1:entity:ENTITY_TOP → Tag of the port `INP` of the component `ENTITY_1` in `ENTITY_TOP`
INP:port:component:ENTITY_2:entity:ENTITY_TOP → Tag of the port `INP` of the component `ENTITY_2` in `ENTITY_TOP`
INP:port:instance label:ENTITY_1_i:(component:ENTITY_1):entity:ENTITY_TOP → Tag of the port map `INP` of the instance `ENTITY_1_i` of the component `ENTITY_1` in `ENTITY_TOP` (`instance label:ENTITY_1_i` has to be associated to `component:ENTITY_1`, so the latter may be redundant for this particular tag of `INP`, thus reported between parenthesis)
INP:port:instance label:ENTITY_2_i:(component:ENTITY_2):entity:ENTITY_TOP → Tag of the port map `INP` of the instance `ENTITY_2_i` of the component `ENTITY_2` in `ENTITY_TOP` (`instance label:ENTITY_2_i` has to be associated to `component:ENTITY_2`, so the latter may be redundant for this particular tag of `INP`, thus reported between parenthesis)

- sig

sig:signal:architecture:arch1:entity:ENTITY_TOP
sig:signal:architecture:arch1:entity:ENTITY_1
sig:signal:architecture:arch2:entity:ENTITY_1
sig:signal:architecture:arch1:entity:ENTITY_2
sig:signal:architecture:arch2:entity:ENTITY_2

- arch

arch:architecture:entity:ENTITY_TOP

- arch1

arch1:architecture:entity:ENTITY_1
arch1:architecture:entity:ENTITY_2
(arch1:architecture:instance label:ENTITY_1_i) ? Should enabled architecture of instanced component be tagged too? See `ENTITY_1_i : entity work.ENTITY_1(arch1)`
(arch1:architecture:instance label:ENTITY_2_i) ? Should enabled architecture of instanced component be tagged too? See `ENTITY_2_i : entity work.ENTITY_2(arch1)`

- arch2

arch2:architecture:entity:ENTITY_1
arch2:architecture:entity:ENTITY_2

- ENTITY_1_i

ENTITY_1_i:instance label:component:ENTITY_1:entity:ENTITY_TOP → It is important to note that an instance label might not be associated to an instanced component (could be used for a generated statement instead, for example), so it could be a good idea to also use the component itself as a scope?

- ENTITY_2_i

ENTITY_2_i:instance label:component:ENTITY_2:entity:ENTITY_TOP → It is important to note that an instance label might not be associated to an instanced component (could be used for a generated statement instead, for example), so it could be a good idea to also use the component itself as a scope?

The most vital things of all, which is really missing and would be extremely useful, is a way to recognize the tags of the components instantiated inside an entity. It should thus include the following:

```vhdl
component ENTITY_1
generic (
  GEN : integer := 0
);
port (
  INP : in std_logic
);
end component;

Balisage de base : component ENTITY_1 . Mais nous ne savons pas si ENTITY_1 sera réellement instancié ou non, à en juger uniquement par cette instruction de composant.

Et

ENTITY_1_i : entity work.ENTITY_1(arch1)
generic map(
  GEN => 0
)
port map(
  INP => '0'
);

Balisage complet : ENTITY_1_i : entity work.ENTITY_1(arch1) . Nous savons maintenant que ENTITY_1 sera instancié.

Pourquoi est-ce une information vitale ? Car cela permettrait de construire une hiérarchie des composants. Ce serait d'une aide extrême avec:

  • Deviner quel est le composant de niveau supérieur étant donné un ensemble d'entrées source.
  • Construire l'arborescence des dépendances des composants → Super utile pour compiler les unités avec le bon ordre. Les unités qui sont "indépendantes" sont compilées en premier, jusqu'à l'entité de niveau supérieur.

Merci. J'ai trouvé qu'il faudrait plus de temps pour baliser les instanciations.
J'aimerais donc fusionner #2695 avant de travailler sur les instanciations.

Pourriez-vous essayer #2695 ? Avec la modification de la demande d'extraction, vous pouvez baliser les processus.

La ligne de commande suivante active toutes les fonctionnalités que j'ai implémentées dans #2695.

$  ./ctags --options=NONE -o - --sort=no '--fields=+Kpre' '--extras=+r' '--kinds-VHDL=+{local}{prototype}{component}' --fields=+e INPUT.vhd

Salut, malheureusement, je ne suis pas un expert Github. J'aimerais tester en profondeur vos dernières modifications, mais je ne sais pas comment je pourrais faire cela. Existe-t-il un exécutable disponible quelque part en téléchargement ? Ou est-ce quelque chose que je devrais compiler avec les outils appropriés ? Dans ce dernier cas, pourriez-vous me suggérer la documentation appropriée à suivre ?

Quel système d'exploitation utilisez-vous ?

Windows 10 x64 Pro et Windows 7 x64.

Avant d'essayer la branche VHDL, vous devez trouver un moyen de construire des ctags tirés de la branche master.
Ce que vous devez savoir sur git est très simple ; tapez "git clone https://github.com/universal-ctags/ctags.git ".
Le construire nécessite des préparations et des connaissances. Dans ce domaine, je ne peux pas vous aider car je n'utilise pas Windows.
Voir https://docs.ctags.io/en/latest/windows.html. Si vous pouvez créer un exécutable ctags avec succès, faites-le moi savoir.
Je vais vous expliquer la façon de construire le code à la branche pour VHDL.

Malheureusement, je pense que je ne pourrai pas exécuter ces tests bientôt, j'ai ce problème critique:

https://github.com/universal-ctags/ctags/issues/2725

Cela se produit lorsque j'essaie d'exécuter les versions de Ctags publiées au cours des derniers mois. Savez-vous s'il existe un moyen de résoudre ce problème ?

2725 n'a rien à voir avec la possibilité ou non d'essayer le code proposé dans #2695.

2725 concerne un binaire pré-construit.

Il n'y a pas de binaire pré-construit pour #2695.
Pour essayer #2695, vous devez créer vous-même un exécutable ctags.

C'est maintenant clair, merci. Je vais essayer de construire un exécutable ctags en suivant vos instructions, alors.

Me revoilà. J'ai réussi à cloner le référentiel principal ctags , en récupérant également votre demande d'extraction, en obtenant enfin le nouvel exécutable ctags avec toutes vos nouvelles améliorations.

J'ai fait quelques tests en générant des balises pour les fichiers d'entrée suivants :

ENTITY_1.vhd :

library ieee;
use ieee.std_logic_1164.all;

entity ENTITY_1 is
  generic (
    GEN : integer := 0
  );
  port (
    INP : in std_logic
  );
end entity;

architecture arch1 of ENTITY_1 is

  signal sig : std_logic := '0';

begin
  PROC_p: process(INP)
  -----------------------------
  variable var_v : integer := 0;
  -----------------------------
  begin
      -----------------------------
      var_v := 0;
      -----------------------------
      if (INP = '1') then
        sig <= '1';
      else
        sig <= '0';
      end if;
      -----------------------------
  end process;
  -----------------------------

  process
  -----------------------------
  variable var_v : integer := 0;
  -----------------------------
  begin
      -----------------------------
      var_v := 0;
      -----------------------------
      if (INP = '1') then
        sig <= '1';
      else
        sig <= '0';
      end if;
      -----------------------------
  end process;
  -----------------------------
end architecture;

architecture arch2 of ENTITY_1 is

  signal sig : std_logic := '0';

begin
  PROC_p: process(INP)
  -----------------------------
  variable var_v : integer := 0;
  -----------------------------
  begin
      -----------------------------
      var_v := 0;
      -----------------------------
      if (INP = '1') then
        sig <= '1';
      else
        sig <= '0';
      end if;
      -----------------------------
  end process;
  -----------------------------

  process
  -----------------------------
  variable var_v : integer := 0;
  -----------------------------
  begin
      -----------------------------
      var_v := 0;
      -----------------------------
      if (INP = '1') then
        sig <= '1';
      else
        sig <= '0';
      end if;
      -----------------------------
  end process;
  -----------------------------
end architecture;

ENTITY_2.vhd :

library ieee;
use ieee.std_logic_1164.all;

entity ENTITY_2 is
  generic (
    GEN : integer := 0
  );
  port (
    INP : in std_logic
  );
end entity;

architecture arch1 of ENTITY_2 is

  signal sig : std_logic := '0';

begin
  PROC_p: process(INP)
  -----------------------------
  variable var_v : integer := 0;
  -----------------------------
  begin
      -----------------------------
      var_v := 0;
      -----------------------------
      if (INP = '1') then
        sig <= '1';
      else
        sig <= '0';
      end if;
      -----------------------------
  end process;
  -----------------------------

  process
  -----------------------------
  variable var_v : integer := 0;
  -----------------------------
  begin
      -----------------------------
      var_v := 0;
      -----------------------------
      if (INP = '1') then
        sig <= '1';
      else
        sig <= '0';
      end if;
      -----------------------------
  end process;
  -----------------------------
end architecture;

architecture arch2 of ENTITY_2 is

  signal sig : std_logic := '0';

begin
  PROC_p: process(INP)
  -----------------------------
  variable var_v : integer := 0;
  -----------------------------
  begin
      -----------------------------
      var_v := 0;
      -----------------------------
      if (INP = '1') then
        sig <= '1';
      else
        sig <= '0';
      end if;
      -----------------------------
  end process;
  -----------------------------

  process
  -----------------------------
  variable var_v : integer := 0;
  -----------------------------
  begin
      -----------------------------
      var_v := 0;
      -----------------------------
      if (INP = '1') then
        sig <= '1';
      else
        sig <= '0';
      end if;
      -----------------------------
  end process;
  -----------------------------
end architecture;

ENTITY_TOP.vhd :

library ieee;
use ieee.std_logic_1164.all;

entity ENTITY_TOP is
  generic (
    GEN : integer := 0
  );
  port (
    INP : in std_logic
  );
end entity;

architecture arch of ENTITY_TOP is
  signal sig : std_logic := '0';

  component ENTITY_1
    generic (
      GEN : integer := 0
    );
    port (
      INP : in std_logic
    );
  end component;

  component ENTITY_2
    generic (
      GEN : integer := 0
    );
    port (
      INP : in std_logic
    );
  end component;

begin

  ENTITY_1_1 : entity work.ENTITY_1(arch1)
  generic map(
    GEN => GEN
  )
  port map(
    INP => INP
  );

  ENTITY_1_2 : entity work.ENTITY_1(arch2)
  generic map(
    GEN => GEN
  )
  port map(
    INP => INP
  );

  ENTITY_2_1 : entity work.ENTITY_2(arch1)
  generic map(
    GEN => GEN
  )
  port map(
    INP => INP
  );

  ENTITY_2_2 : entity work.ENTITY_2(arch2)
  generic map(
    GEN => GEN
  )
  port map(
    INP => INP
  );

  PROC_p: process(INP)
  -----------------------------
  variable var_v : integer := 0;
  -----------------------------
  begin
      -----------------------------
      var_v := 0;
      -----------------------------
      if (INP = '1') then
        sig <= '1';
      else
        sig <= '0';
      end if;
      -----------------------------
  end process;
  -----------------------------

  process
  -----------------------------
  variable var_v : integer := 0;
  -----------------------------
  begin
      -----------------------------
      var_v := 0;
      -----------------------------
      if (INP = '1') then
        sig <= '1';
      else
        sig <= '0';
      end if;
      -----------------------------
  end process;
  -----------------------------
end architecture;

Vos modifications récentes ont beaucoup amélioré l'analyseur VHDL, augmentant son potentiel.

Maintenant, voici quelques résultats après avoir effectué quelques tests :

  • La balise process n'a pas de portée. Ça devrait être:

    architecture:entity_name.arch_name

  • La portée de la balise variable est actuellement :

    process:proc_name

    Ça devrait être:

    process:entity_name.arch_name.proc_name

Concernant les balises manquantes, nous avons :

  • instance label . Considérons cet extrait de code, utilisé pour instancier un composant à l'intérieur d'une architecture :

    instance_label : entity library_name.entity_name(arch_name)
    generic map(
    GEN => GEN
    )
    port map(
    PORT => PORT
    );
    

    instance_label identifie l'instance particulière du composant entity_name , dont l'entité est compilée dans la bibliothèque library_name , en spécifiant également son architecture arch_name comme celle à activer. Ainsi, en supposant qu'il soit instancié à l'intérieur de l'architecture $# top_arch top_entity l'entité top_entity, sa portée devrait théoriquement ressembler à :

    architecture:top_entity.top_arch.library_name.entity_name.arch_name .

    Mais maintenant, une considération importante doit être faite. Tout d'abord, décrivons ce qu'est une bibliothèque en VHDL. Une bibliothèque est un conteneur dans lequel des entités et leurs architectures respectives doivent être compilées. Plusieurs entités portant le même nom ne peuvent pas être compilées dans la même bibliothèque, mais une entité peut être compilée dans plusieurs bibliothèques, sans changer son nom à chaque compilation. La bibliothèque de travail actuelle en VHDL est nommée work .

    En spécifiant la bibliothèque library_name dans ce cas, nous supposons que le composant à instancier est donc associé à une entité compilée dans cette bibliothèque. Mais, en parsant simplement le fichier contenant la définition de cette entité, nous ne pourrions en aucun cas récupérer à l'avance le nom de la bibliothèque dans laquelle elle sera compilée.

    En effet, l'élément library_name dépend strictement des paramètres passés lors de la compilation de cette entité (par exemple, un argument de compilation est utilisé pour indiquer la bibliothèque dans laquelle le composant sélectionné doit être compilé).

    C'est aussi la raison pour laquelle aucun élément library_name n'est actuellement utilisé comme portée pour les types VHDL actuellement disponibles dans ctags . Car, en somme, cet élément n'est généralement connu qu'à deux reprises :

    • L'entité à instancier est disponible dans une bibliothèque pré-compilée, vraisemblablement sans sources disponibles.
    • L'entité à instancier va être compilée dans une bibliothèque spécifique, donc avec les sources disponibles.

    Ainsi, jusqu'à ce qu'une solution ou une utilisation appropriée soit trouvée pour l'élément library_name , ce qui suit pourrait être considéré comme une bonne portée pour la balise instance label la place :

    architecture:top_entity.top_arch.entity_name.arch_name .

    En omettant l'élément library_name , l'hypothèse ici est qu'aucune entité multiple partageant le même nom ne sera analysée et étiquetée dans le projet de travail en cours et que l'entité analysée sera exactement celle qui serait compilée dans ce library_name bibliothèque.

  • instance label generic/port . En faisant également les mêmes considérations que ci-dessus, nous devrions également baliser le mappage générique/port du composant instancié (les mappages décrits dans l'étiquette du composant instancié instance_label ). La portée à la fois pour le générique et le port devrait être, pour les raisons décrites précédemment :

    instance label:top_entity.top_arch.entity_name.arch_name.instance_label .

    Il n'y aura pas de cas de balises anonymes instance_label , car une étiquette doit être spécifiée pour chaque composant instancié.


Maintenant, voici quelques résultats après avoir effectué quelques tests :

* `process` tag is missing a scope.  It should be:
  `architecture:entity_name.arch_name`

* `variable` tag scope is currently:
  `process:proc_name`
  It should be:
  `process:entity_name.arch_name.proc_name`

Merci d'avoir essayé.

Je mettrai à jour #2695 après avoir essayé de corriger les éléments ci-dessus.
Ensuite, je fusionnerai #2695. Les pull requests contiennent tellement de commits.
Je vais travailler sur le reste des éléments que vous avez mis dans les commentaires après avoir fusionné #2695.

Je pensais à une autre chose critique. Reprenons cet extrait :

instance_label : entity library_name.entity_name(arch_name)
generic map(
  GEN => GEN
)
port map(
  PORT => PORT
);

Comme je l'ai observé dans mon post précédent, une balise pour instance_label (nommée par exemple instance label ) devrait également être ajoutée, et j'ai proposé cette portée :

  1. architecture:top_entity.top_arch.entity_name.arch_name

A terme, ce périmètre pourrait être réduit aux éléments suivants :

  1. architecture:top_entity.top_arch

car les noms d' étiquettes d'instance sont uniques au sein d'une architecture. Mais l'option 1 , bien que quelque peu redondante, donnerait plus d'informations sur la balise d' étiquette d'instance , et pourrait donc être hautement préférable lors de la navigation des balises.

Mais la chose manquante critique, que j'ai oubliée, serait une balise pour le composant instancié lui-même ( entity_name dans l'extrait ci-dessus). Cette balise pourrait être appelée instance de composant (étant son étiquette, étiquette d'instance ) et sa portée devrait alors être :

instance label:top_entity.top_arch.instance_label

Ce serait vital pour la navigation des balises. Par exemple, à partir d'un tag donné d'une entité, il sera alors possible de retrouver :

  • Définition de l'entité
  • Définition du composant
  • Instance de composant → il ne serait pas possible de les rechercher efficacement en recherchant uniquement la balise instance_label .

Une dernière observation, pour le balisage instance label generic/port dont j'ai parlé dans mon post précédent. Comme portée, j'ai suggéré:

  1. instance label:top_entity.top_arch.entity_name.arch_name.instance_label

mais cela pourrait être réduit à:

  1. instance label:top_entity.top_arch.instance_label

encore une fois parce que les noms d' étiquettes d'instance sont uniques au sein d'une architecture.

mais la variante 1 est la plus recommandée car elle fournit des informations sur le couple entité et architecture lié au label d'instance.

@pidgeon777 , pensez-vous que nous pouvons fusionner #2695 ?
Je pense avoir résolu les problèmes suivants que vous avez signalés :

  • La balise process n'a pas de portée. Ça devrait être:
    architecture:entity_name.arch_name

  • La portée de la balise variable est actuellement :
    process:proc_name
    Ça devrait être:
    process:entity_name.arch_name.proc_name

@pidgeon777 , pensez-vous que nous pouvons fusionner #2695 ?

Je fais plus de tests pour https://github.com/universal-ctags/ctags/pull/2695 avant confirmation.

Je pense avoir résolu les éléments suivants que vous avez soulignés

Sont-ils inclus dans le https://github.com/universal-ctags/ctags/pull/2695 susmentionné ?

Sont-ils inclus dans le # 2695 susmentionné ?

Oui. https://github.com/universal-ctags/ctags/pull/2695/commits/cf9a5d2eebc884e992aeaa2edcc4627452d12c78 dans # 2695 est le changement pour les éléments.

Sont-ils inclus dans le # 2695 susmentionné ?

Oui. cf9a5d2 dans #2695 est le changement pour les éléments.

Les nouveaux ajouts dans https://github.com/universal-ctags/ctags/pull/2695 semblent être OK.

J'ai fusionné #2695. Merci pour le test.

@pidgeon777 , puis-je vous demander de résumer les autres éléments ? (l'ouverture d'un nouveau problème est un moyen alternatif.)

J'ai une demande. Lors de l'affichage d'un exemple de champ d'étendue, pourriez-vous ajouter le préfixe scope: ?
ctags peut émettre le préfixe lorsque vous donnez l'option --fields=+Z .

$ cat f.h
struct point {
    int x, y;
};
$ ./ctags -o - --fields=+Z f.h
point   f.h /^struct point {$/;"    s
x   f.h /^  int x, y;$/;"   m   scope:struct:point  typeref:typename:int
y   f.h /^  int x, y;$/;"   m   scope:struct:point  typeref:typename:int

Je voudrais que vous montriez les exemples dans les formulaires ci-dessus.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

liuchengxu picture liuchengxu  ·  8Commentaires

cweagans picture cweagans  ·  13Commentaires

jagjordi picture jagjordi  ·  9Commentaires

JulienPivard picture JulienPivard  ·  16Commentaires

cweagans picture cweagans  ·  8Commentaires