Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

verilog: keep trace with instance in TAGS file #2703

Merged
merged 1 commit into from
Nov 22, 2020
Merged

verilog: keep trace with instance in TAGS file #2703

merged 1 commit into from
Nov 22, 2020

Conversation

my2817
Copy link
Contributor

@my2817 my2817 commented Nov 18, 2020

add a kind named K_INST
update function tagNameList to update kind from K_IDENTIFIER to K_INST

@masatake
Copy link
Member

The way to write test cases is wrong. expected.tags is missing. See https://docs.ctags.io/en/latest/units.html.
You should not use _ as the part of the kind name. The tests on the CI environment may be failed because of the _ in the kind name.

@hirooih
Copy link
Contributor

hirooih commented Nov 18, 2020

Thanks for enhancement.

make units LANGUAGES=SystemVerilog,Verilog
make units LANGUAGES=SystemVerilog,Verilog VG=1
  • Make sure only instance names are tagged.

@hirooih
Copy link
Contributor

hirooih commented Nov 18, 2020

Make sure only instance names are tagged.

And;

  • Make sure all instance names are tagged.

@my2817
Copy link
Contributor Author

my2817 commented Nov 19, 2020

Make sure only instance names are tagged.

And;

  • Make sure all instance names are tagged.

Thanks for your work on this awesome tool and advice.

@my2817 my2817 closed this Nov 19, 2020
@my2817 my2817 reopened this Nov 19, 2020
{
if(c == '('){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't use this style, putting { at the end of line IN THIS FILE.

if (c == '(')
{
   ...

is expected.

parsers/verilog.c Outdated Show resolved Hide resolved
@codecov
Copy link

codecov bot commented Nov 19, 2020

Codecov Report

Merging #2703 (05f5707) into master (5938fa1) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #2703   +/-   ##
=======================================
  Coverage   86.99%   86.99%           
=======================================
  Files         185      185           
  Lines       39462    39465    +3     
=======================================
+ Hits        34330    34334    +4     
+ Misses       5132     5131    -1     
Impacted Files Coverage Δ
parsers/verilog.c 98.75% <100.00%> (+<0.01%) ⬆️
main/kind.c 98.29% <0.00%> (+0.34%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5938fa1...05f5707. Read the comment docs.

token->kind = K_UNDEFINED;
kind = K_UNDEFINED;
}
else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't use this style, putting { at the end of line IN THIS FILE.

else
{
...

is expected.

kind = K_UNDEFINED;
}
else {
verbose("find instance: %s with kind %d\n", vStringValue (token->name), token->kind);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about printing the kind in a string?

verbose("find instance: %s with kind %s\n", vStringValue (token->name),getNameForKind(token->kind));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I myself didn't test the change that I showed.)

@masatake
Copy link
Member

I would like you to squash the commits into one commit.
The idea behind the squashing is described in #2705 (comment) .

In addition, I would like you to use "SystemVerilog" or "Verilog,SystemVerilog" instead of "[verilog/SystemVerilog]" as the prefix of the commit header like:

cc26cc1d Ruby: fill signature fields for the method kind
65f5bc5b Go: use symbol table for attaching typeref field to members of a structure
bf1206cc SystemVerilog: parse a multi dimensional packed array in typedef correctly

@my2817 my2817 changed the title [verilog/SystemVerilog] keep trace with instance in TAGS file verilog: keep trace with instance in TAGS file Nov 19, 2020
token->kind = K_INSTANCE;
kind = K_INSTANCE;
c = skipPastMatch ("()");
if(c != ';' && c != ',')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can simplify the code a bit like:

if (c == '(')
{
      kind = K_UNDEFINED;
      c = skipPastMatch ("()");
      if (c == ';' || c == ',')
      {
			kind = K_INSTANCE;
            verbose("find instance: %s with kind %s\n", vStringValue (token->name), getNameForKind(kind));        
      }
      token->kind = kind;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will check this code in detail in this week.
Quick comments.

I propose the followings;

if (c == '(')
{
      c = skipPastMatch ("()");
      if (c == ';' || c == ',')
      {
		kind = K_INSTANCE;
        	verbose("find instance: %s with kind %s\n", vStringValue (token->name), getNameForKind(kind));        
      }
      else  // comment why this condition is required
		kind = K_UNDEFINED;

      token->kind = kind;
}

Actually I don't understand why the condition is required.

From LRM 23.3.2 Module instantiation syntax

module_instantiation ::= // from A.4.1.1
	module_identifier [ parameter_value_assignment ] hierarchical_instance { , hierarchical_instance };
...
hierarchical_instance ::= name_of_instance ( [ list_of_port_connections ] )
name_of_instance ::= instance_identifier { unpacked_dimension }
...

Please take care of { unpacked_dimension } part.

Please check interface instantiation syntax, too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the units test, the parser will treat "`add_t" as instance if there isn't a "else" condition

    var `add_t(foo) = '0;

I will check unpacked_dimension and interface syntax later, thanks.

@coveralls
Copy link

coveralls commented Nov 20, 2020

Coverage Status

Coverage increased (+0.003%) to 87.087% when pulling 05f5707 on my2817:verilog_TagInst into 5938fa1 on universal-ctags:master.

Copy link
Contributor

@hirooih hirooih left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your proposal.

Instance name support is very important. I completely missed the issue.
Please see my comments.

There is one issue. If I understand your fix correctly, it tags a void function as a instance.

// LRM 13.4.1 Return values and void functions
myprint(a); // call myprint (defined below) as a statement
function void myprint (int a);  // FIXME
...
endfunction

Void function is not used often. Supporting instance tag is much more important. Leave it as known bug for now.

Please add the test case above, too.

Thanks.

@@ -1577,8 +1580,26 @@ static int tagNameList (tokenInfo* token, int c)
{
c = processType(token, c, &kind); // update token and kind

if (c == '=' || c == ',' || c == ';' || c == ')' || c == '`')
if (c == '=' || c == ',' || c == ';' || c == ')' || c == '`' || c == '(' || c == '[')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instance processing is dependent from variable processing. The following structure is more readable.

		if (c == '=' || c == ',' || c == ';' || c == ')' || c == '`')
		{
		...
		}
		else if (c == '(' ...)
		...

{
while(c == '[')
{
c = skipPastMatch ("[]");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use skipDimension().

}
if(c == '(')
{
c = skipPastMatch ("()");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need c= skipWhite (c); here.

m inst () ; // a space before semicolon fails. (You may want to add a test case for this. )

skipPastMatch() should do the job, but it does not now. I will work on this issue on this weekend.
You may wait for the fix.

@@ -127,7 +128,8 @@ static kindDefinition VerilogKinds [] = {
{ true, 'p', "port", "ports" },
{ true, 'r', "register", "variable data types" },
{ true, 't', "task", "tasks" },
{ true, 'b', "block", "blocks (begin, fork)" }
{ true, 'b', "block", "blocks (begin, fork)" },
{ true, 'i', "instance", "instance(module instance)" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be consistent with the line above. i.e. "instance (module, instance)"

@@ -140,6 +142,7 @@ static kindDefinition SystemVerilogKinds [] = {
{ true, 'r', "register", "variable data types" },
{ true, 't', "task", "tasks" },
{ true, 'b', "block", "blocks (begin, fork)" },
{ true, 'i', "instance" "instance(module or interface instance)"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor

@hirooih hirooih left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for many change requests...

@@ -1577,13 +1580,32 @@ static int tagNameList (tokenInfo* token, int c)
{
c = processType(token, c, &kind); // update token and kind

if (c == '=' || c == ',' || c == ';' || c == ')' || c == '`')
if (c == '=' || c == ',' || c == ';' || c == ')' || c == '`' )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove a space you added.

createTag (token, kind);
}
else
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This else clause is not necessary.

else if (c == '(' || c == '[') // should be instance? TODO: function void foo();
{
c = skipDimension(c);
if(c == '(')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if-clause is not necessary.

/* c= skipWhite (c); */
if(c == ';' || c == ',')
{
kind = K_INSTANCE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable is not necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'm sorry for my poor coding skill 😭

else if (c == '(' || c == '[') // should be instance? TODO: function void foo();
{
c = skipDimension(c);
if(c == '(')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a space after 'if'.

@@ -127,7 +128,8 @@ static kindDefinition VerilogKinds [] = {
{ true, 'p', "port", "ports" },
{ true, 'r', "register", "variable data types" },
{ true, 't', "task", "tasks" },
{ true, 'b', "block", "blocks (begin, fork)" }
{ true, 'b', "block", "blocks (begin, fork)" },
{ true, 'i', "instance", "instances" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you chose "instances of module or interface" below, this should be "instances of module".

@@ -140,6 +142,7 @@ static kindDefinition SystemVerilogKinds [] = {
{ true, 'r', "register", "variable data types" },
{ true, 't', "task", "tasks" },
{ true, 'b', "block", "blocks (begin, fork)" },
{ true, 'i', "instance" "instances of module or interface"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a space before "}".

Copy link
Contributor

@hirooih hirooih left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is getting simpler, isn't it?

c = skipDimension(c);
c = skipPastMatch ("()");
c = skipWhite (c);
if (c == ';' || c == ',')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave a comment here as we discussed.

c = skipWhite (c);
if (c == ';' || c == ',')
{
kind = K_INSTANCE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that you missed my review comment this morning.
This variable is not necessary. You can specify K_INSTANCE directly.

Copy link
Contributor Author

@my2817 my2817 Nov 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get it, thanks!

{
c = skipDimension(c);
c = skipPastMatch ("()");
c = skipWhite (c);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've sent a pull-request #2718 for this. I am waiting for the approval by @masatake.
If it is merged earlier than this pull-request, remove this line.

Again add a test case which fails by this issue. (Add a space in ");" at the end of one of module instantiations.)

Copy link
Contributor

@hirooih hirooih left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment.

Again add a test case which fails by this issue. (Add a space in ");" at the end of one of module instantiations.)

For example;
verilog-instance.d/input.v: L57

             .b                         (b));

Change this line as;

             .b                         (b))   ;  // spaces before semicolon

Remove;

			c = skipWhite (c);

and confirm that the test fails.

And #2718 is merged into universal-ctags:master.
Merge it into your branch and confirm the test passes.

// var `add_t(foo) = '0;
if (c == ';' || c == ',')
{
verbose("find instance: %s with kind %s\n", vStringValue (token->name), getNameForKind(kind));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kind is in this line, too.

@hirooih
Copy link
Contributor

hirooih commented Nov 21, 2020

One more thing.
Have you checked the coverage report? (It is a really awesome tool.)

https://codecov.io/gh/universal-ctags/ctags/compare/4a9f00a1c199133729819043292aedff7c580ed8...2069733b92a881ec74bd5419d186611e7432e870/changes

Your fix made the following lines unnecessary.

1643 | 1660 |   | /* skip port list of module instance: foo bar(xx, yy); */
1644 | 1661 |   | c = skipWhite (c);
1645 | 1662 |   | if (c == '(')
1646 | 1663 |   | {
1647 | 1664 |   | c = skipPastMatch ("()");
1648 | 1665 |   | c = skipWhite (c);
1649 | 1666 |   | }

Please remove them.

Your fix added very small number of lines and gave us great functionality. It sounds great!

SystemVerilog: give K_INSTANCE to createTag directly
SystemVerilog: new test case
Add a space in ");" at the end of one of module instantiationsadd
@hirooih hirooih merged commit bdeb61a into universal-ctags:master Nov 22, 2020
@hirooih
Copy link
Contributor

hirooih commented Nov 22, 2020

Again, thank you for your contribution.

@my2817
Copy link
Contributor Author

my2817 commented Nov 22, 2020

Again, thank you for your contribution.

Thanks for your patience!

@masatake
Copy link
Member

I'm working on VHDL and I have studied some concepts of this technology area.
I got some ideas to improve SystemVerilog parser.

module foo # (parameter
...
endmodule: foo
...

  foo uut7 [1:0][10:0]();

for uut7, ctags with this pull request emits:

uut7   input.v /^   foo uut7 [1:0][10:0]();$/;"        i       module:top

I think we can fill typeref: field for representing the relationship between uut7 and foo.

uut7   input.v /^   foo uut7 [1:0][10:0]();$/;"        i       module:top       typeref:module:foo

I'm taking the same approach in VHDL.

@hirooih
Copy link
Contributor

hirooih commented Nov 23, 2020

Thanks.
I've added the feature on the TODO list #2674 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants