Open pidgeon777 opened 3 years ago
I found an example in our test cases:
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;
Before talking about process, I have a question. I think "simple" should be tagged if we should make a tag for accumulate. Am I correct? In this case what "kind" should we use for "simple"?
Yes, simple
should be tagged, too. Each VHDL entity has an architecture which defines the behaviour of the entity itself.
Thus, I would propose to add one more VHDL kind: a
, for architecture bodies
.
@pidgeon777, thank you.
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;
I think a, clk, accum, accumL should be tagged, too. For tagging accumL, we should introduce "signal" kind. For tagging a, clk, accum, ~what kind we should introduce?~ I guess we should introduce "port" kind.
scope fields are not filled. So you cannot do any interesting things.
For tagging a, clk, accum, what kind we should introduce? I guess we should introduce "port" kind.
Yes, they should be tagged as well, eventually as port declarations
:
http://www.vhdl.renerta.com/mobile/source/vhd00051.htm
For tagging accumL, we should introduce "signal" kind.
signal declarations
would also be ok:
http://www.vhdl.renerta.com/source/vhd00064.htm
scope fields are not filled. So you cannot do any interesting things.
I didn't understand the above point.
However, we should not forget about generics, too:
http://www.vhdl.renerta.com/source/vhd00034.htm
Those are also really important in VHDL, and should thus be tagged, too.
Thank you.
scope field represents owner/owned or parent/child relationships. Client tools can make a "tree" from the fields.
I would like to show an example in C language.
input.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 }
ctags output:
% 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
See scope: in the output.
Let's think about 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;
The scope of a
, clk
, and accum
may be: "scope:entity:accumulator".
These ones are easy.
architecture simple of accumulator is
signal accumL: unsigned(3 downto 0);
begin
...
How about accumL
?
One of my ideas is scope:architecture:simple
.
This will be better than scope:entity:accumulator
because accumulator may have multiple architectures.
VHDL: tag architectures #2687
is merged.
Ports are tagged: https://github.com/universal-ctags/ctags/pull/2695 .
For tagging a, clk, accum, what kind we should introduce? I guess we should introduce "port" kind.
Yes, they should be tagged as well, eventually as port declarations:
Do you mean "port declaration" is better than "port" as the kind name for a, clk, accum? I made a pull request (#2695) for tagging ports. I used "port" as the name of kind. Am I going to wrong way?
Here I am again. I think ctags
has a lot of potential for tagging HDL languages (VHDL
, Verilog
, SystemVerilog
) even for code analysis/linting purposes, thus I'm more than happy to help.
Maybe it won't be possible for me to quickly reply on certain days, but I'll try to answer all of your questions as soon as I can.
Moreover, I have some interesting ideas to share later today, and I will also provide you with the answers you asked for.
Excellent!
@pidgeon777, Do you think "port" is bad kind name?
$ ./ctags --list-kinds=SystemVerilog
c constants (define, parameter, specparam, enum values)
e events
f functions
m modules
n net data types
p ports
I don't know well about languages for hardware. However, "port" is used in SystemVerilog. So I assume using the same name in VHDL may be o.k.
Hi @masatake, the list of VHDL kinds:
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
could be ok, but if you want to maintain the same format used in those VHDL kinds, then I think one of the following could be more appropriate:
port declarations
← bestport definitions
Still, I'm not so sure about the difference between definition and declaration in VHDL. A C++ case:
Later this evening I'll try to answer the remaining questions you asked for, I already took some notes a few days ago.
I see. You are talking about "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
We don't regard DESCRIPTION as the part of ctags CLI that we should keep the compatibility. The value for DESCRIPTION does not appear in tags output. What I would like to know is NAME. The NAME is part of the CLI. The value for NAME appears in tags output. So a tool reading a tags file may depend on the value of NAME. My original question is whether "port" is a proper kind NAME or not. I think "port" as NAME is o.k. What I have to update is the DESCRIPTION field for "port" kind:
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"},
};
With this change, --list-kinds-full=VHDL
reports:
...
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
...
I think "port" as NAME is o.k.
I confirm.
q port no no 0 NONE port declarations
Also this would be perfect.
But, speaking of a port, it would be essential in my opinion to attach it to a scope. Or, if you prefer, given a port called PORT_C
, this could be declared in two or more different entities, thus the name of the entity should be used as scope for the port.
Example:
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;
Parsed tags:
6:PORT_C scope:entity:ENTITY_A
15:PORT_C scope:entity:ENTITY_B
Also we could have:
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;
Parsed tags:
6:PORT_C scope:component:COMPONENT_A
15:PORT_C scope:component:COMPONENT_B
Thank you for the detailed description. In #2695, I already filled the scope fields of port declarations if they are in entities.
I did nothing for port declarations in components. I will revise my change.
With the change proposed in #2695, the VHDL parser can extract ports and generics declared in an entity and component.
$ 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
The last one is signal that I should work on before working on process and instance.
If I did something wrong, let me know.
@pidgeon777,
component COMPONENT_A is
generic (
GENERIC_C : integer := value;
);
port (
PORT_C : in std_logic
);
end entity;
Is the last line, "end entity;" correct? After reading some articles about VHDL, I guess the line should be "end component;" ?
Is the last line, "end entity;" correct?
My fault, when I copied-pasted the component declaration I forgot to change the last line. I will pay more attention the next time.
Correct component declaration is:
component COMPONENT_A is
generic (
GENERIC_C : integer := value
);
port (
PORT_C : in std_logic
);
end component [COMPONENT_A];
Note that the component name at the end of end component
is not mandatory in code, only optional. Thus I included it into the square brackets.
More in general, for the component declaration:
component component_name [ is ]
[ generic ( generic_list ); ]
[ port ( port_list ); ]
end component [ component_name ];
I highly suggest this reference for VHDL declarations and definitions:
https://www.hdlworks.com/hdl_corner/vhdl_ref/
With the change proposed in #2695, the VHDL parser can extract ports and generics declared in an entity and component.
Let's now consider the following situation. ENTITY_TOP
instantiate both ENTITY_1
and ENTITY_2
:
input.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;
input-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;
input-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;
We can note the following:
1) GEN
generic is the same name for all of the three entities, and also the two components, and finally the two component instantiations. Should the entity or component name be used as a scope to differentiate the various GEN
tags? Example: 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 is the same name for all of the three entities, and also the two components, and finally the two component instantiations. Should the entity or component name be used as a scope to differentiate the various INP
tags? Example: 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
is the same name for the architecture of the three entities. Should the entity name be used as a scope to differentiate the three arch
tags? Example: arch:scope:ENTITY_TOP
, arch:scope:ENTITY_1
, arch:scope:ENTITY_2
.
4) sig
is the same name for the signal of the three architectures. Should the entity and architecture name be used as a scope to differentiate the three arch
tags? Example: sig:scope:arch:ENTITY_TOP
, sig:scope:arch:ENTITY_1
, sig:scope:arch:ENTITY_2
. Both entity and architecture because an entity can have multiple architectures sharing the definition of a signal with the same name, and the same signal name could be used in the architecture of different entities.
@masatake added file names for each example code.
I would like you to read https://docs.ctags.io/en/latest/units.html. I added test cases based on your input to my pull request. I would like you to read args.ctags, input(-[0-9])?.vhd, and expected tags. They explain how my improvement works.
I will explain 3 later.
You don't need to see changes for files under Units/review-needed.r/test.vhd.t/. They are too large.
After rethinking about 3., I should use the scope field instead of the entity field for representing the relationship between architecture and entity. This breaks compatibilities.
process
was added in #2695 .
instance_label: component_name
generic map (generic_association_list)
port map (port_association_list);
I think instance_label
should be tagged with "instance" kind.
typeref field can be used to attach "component_name" to the tag.
component_name
is tagged as a reference tag with "component" kind.
instance_label input.vhd /^...$/;" kind:instance scope:... typeref:component:component_name roles:def
component_nameinput.vhd /^...$/;" kind:component roles:instantiated instance:instance_label
instance:
is a VHDL specific field.
I think I have to write a man page for the VHDL parser.
I would like you to read https://docs.ctags.io/en/latest/units.html. I added test cases based on your input to my pull request. I would like you to read args.ctags, input(-[0-9])?.vhd, and expected tags. They explain how my improvement works.
Ok I will read that.
After rethinking about 3., I should use the scope field instead of the entity field for representing the relationship between architecture and entity. This breaks compatibilities.
The fact is that:
So, for example:
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
ENTITY_1:entity ENTITY_1:component:entity:ENTITY_TOP ENTITY_1:component instance:entity:ENTITY_TOP
ENTITY_2:entity ENTITY_2:component:entity:ENTITY_TOP ENTITY_2:component instance:entity:ENTITY_TOP
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: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: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:architecture:entity:ENTITY_TOP
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:architecture:entity:ENTITY_1 arch2:architecture:entity:ENTITY_2
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: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:
component ENTITY_1
generic (
GEN : integer := 0
);
port (
INP : in std_logic
);
end component;
Basic tagging: component ENTITY_1
. But we don't know if ENTITY_1
will be really instantiated or not, by only judging from this component statement.
And
ENTITY_1_i : entity work.ENTITY_1(arch1)
generic map(
GEN => 0
)
port map(
INP => '0'
);
Complete tagging: ENTITY_1_i : entity work.ENTITY_1(arch1)
. Now we know that ENTITY_1
will be instantiated.
Why this is vital information? Because it would make it possible to build a hierarchy of components. This would be of extreme help with:
Thank you. I found it will take more time to tag instantiations. So I would like to merge #2695 before working on instantiations.
Could you try #2695? With the change in the pull request, you can tag processes.
The following command line activates all the features I implemented in #2695.
$ ./ctags --options=NONE -o - --sort=no '--fields=+Kpre' '--extras=+r' '--kinds-VHDL=+{local}{prototype}{component}' --fields=+e INPUT.vhd
Hi, unfortunately, I am not a Github expert. I would like to deeply test your latest changes, but I don't know how I could do that. Is there an executable available somewhere for download? Or it is something which I should compile with the proper tools? In the latter case, would you suggest me the proper documentation to follow?
Which OS do you use?
Windows 10 x64 Pro and Windows 7 x64.
Before trying the VHDL branch, you must find a way to build ctags taken from the master branch. What you must know about git is very simple; type "git clone https://github.com/universal-ctags/ctags.git". Building it requires preparations and knowledge. In this area, I cannot help you because I don't use Windows. See https://docs.ctags.io/en/latest/windows.html. If you can build a ctags executable successfully, let me know it. I will explain the way to build the code at the branch for VHDL.
Unfortunately, I think I won't be able to run those tests soon, I got this critical issue:
https://github.com/universal-ctags/ctags/issues/2725
This happens when I try to run the Ctags versions released during the latest few months. Do you know if a way to solve this problem exists?
There is no pre-built binary for #2695. To try #2695, you must build a ctags executable by yourself.
This is now clear, thank you. I'll try to build a ctags executable following your instructions, then.
Here I am again. I've successfully cloned the main ctags
repository, also fetching your pull request, finally obtaining the new ctags
executable with all of your new improvements.
I did some tests generating tags for the following input files:
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;
Your recent changes improved a lot the VHDL parser, increasing its potential.
Now, here are some findings after having conducted some 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
Regarding the missing tags, we have:
instance label
. Let consider this snippet of code, used to instantiate a component inside an architecture:
instance_label : entity library_name.entity_name(arch_name)
generic map(
GEN => GEN
)
port map(
PORT => PORT
);
instance_label
identifies the particular instance of entity_name
component, whose entity is compiled in the library_name
library, also specifying its arch_name
architecture as the one to enable. Thus, supposing it is instanced inside the top_arch
architecture of top_entity
entity, its scope should theoretically be something like:
architecture:top_entity.top_arch.library_name.entity_name.arch_name
.
But now an important consideration has to be made. First of all, let's describe what a library in VHDL is. A library is a container into which entities and their respective architectures, must be compiled. Multiple entities with the same name cannot be compiled into the same library, but an entity could be compiled into multiple libraries, without changing its name at each compilation. The current, working library in VHDL is named work
.
By specifying the library_name
library in this case, we are supposing that the component to instantiate is thus associated with an entity compiled into that library. But, by just parsing the file containing the definition of that entity, in no way we could retrieve in advance the name of the library into which it will be compiled.
This is because the library_name
element strictly depends on the parameters passed during the compilation of that entity (for example, a compilation argument is used to indicate the library into which the selected component has to be compiled).
Also, this is the reason for which no library_name
element is currently used as scope for the currently available VHDL kinds in ctags
. Because, in short, this element is generally known only on two occasions:
So, until a proper solution or usage is found for the library_name
element, the following could be considered as a good scope for the instance label
tag instead:
architecture:top_entity.top_arch.entity_name.arch_name
.
With omitting the library_name
element, the assumption here is that no multiple entities sharing the same name will be parsed and tagged in the current working project and that the parsed entity will exactly be the one which would be compiled into that library_name
library.
instance label generic/port
. Also doing the same considerations as above, we should tag the generic/port mapping of the instanced component too (the mappings described in the instance_label
instanced component label). Scope for both generic and port should be, for the reasons previously described:
instance label:top_entity.top_arch.entity_name.arch_name.instance_label
.
There won't be any case of anonymous instance_label
tags, because a label has to be specified for each instanced component.
Now, here are some findings after having conducted some 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`
Thank you for trying.
I will update #2695 after trying to fix the above items. Then I will merge #2695. The pull requests contain so many commits. I will work on the rest of the items you put in the comments after merging #2695.
I was thinking of another critical thing. Let's consider this snippet again:
instance_label : entity library_name.entity_name(arch_name)
generic map(
GEN => GEN
)
port map(
PORT => PORT
);
As I observed in my previous post, a tag for instance_label
(named e.g. instance label) should be added too, and I proposed this scope:
architecture:top_entity.top_arch.entity_name.arch_name
Eventually, that scope could be reduced to the following:
architecture:top_entity.top_arch
because instance label names are unique within an architecture. But option 1, albeit somewhat redundant, would give more information about the instance label tag, thus could be highly preferable during tag browsing.
But the critical missing thing, which I forgot about, would be a tag for the instanced component itself (entity_name
in the above snippet). This tag could be called component instance (being its label, instance label) and its scope should then be:
instance label:top_entity.top_arch.instance_label
This would be vital for tags browsing. For example, starting from a given tag of an entity, it will then be possible to find:
instance_label
tag.A final observation, for the instance label generic/port
tagging discussed in my previous post. As scope I suggested:
instance label:top_entity.top_arch.entity_name.arch_name.instance_label
but this could be reduced to:
instance label:top_entity.top_arch.instance_label
again because instance label names are unique within an architecture.
but variant 1 is the highly recommended one because it provides information about the entity and architecture couple related to the instance label.
@pidgeon777, do you think we can merge #2695? I think I solved the following items you pointed out:
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
@pidgeon777, do you think we can merge #2695?
I'm doing more tests for https://github.com/universal-ctags/ctags/pull/2695 before confirmation.
I think I solved the following items you pointed out
Are those included in the aforementioned https://github.com/universal-ctags/ctags/pull/2695?
Are those included in the aforementioned #2695?
Yes. https://github.com/universal-ctags/ctags/pull/2695/commits/cf9a5d2eebc884e992aeaa2edcc4627452d12c78 in #2695 is the change for the items.
Are those included in the aforementioned #2695?
Yes. cf9a5d2 in #2695 is the change for the items.
The new additions in https://github.com/universal-ctags/ctags/pull/2695 seem to be OK.
I merged #2695. Thank you for testing.
@pidgeon777, can I ask you to summarize the rest items? (opening a new issue is an alternative way.)
I have one request. When showing an example of scope field, could you add scope:
prefix?
ctags can emit the prefix when you give --fields=+Z
option.
$ 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
I would like you to show the examples in the above forms.
These are the VHDL kinds parsed in the latest implementation of ctags:
https://github.com/universal-ctags/ctags/blob/master/parsers/vhdl.c
Please add three more kinds:
optional_label
is the optional process label and should be reported as tag (e.g. kind =process
). If missing, a random string (e.g. 4534_process) should be used as tag name instead. ctags' parsed anonymous structs in C can be considered as an example.instance_label
is the mandatory component instantiation label and should be reported as tag (e.g. kind =component instance label
).component_name
is the instantiated component name and should be reported as tag as well (e.g. kind =component instance
), so that the associated component/entity tags could be found.