Skip to content

Commit

Permalink
Merge pull request universal-ctags#260 from vhda/verilog/inheritance
Browse files Browse the repository at this point in the history
Extract class inheritance information from SystemVerilog files
  • Loading branch information
vhda committed Mar 7, 2015
2 parents ee66264 + 051f516 commit 3085a65
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Units/verilog-sv-class.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--extra=+q
--fields=+i
35 changes: 35 additions & 0 deletions Units/verilog-sv-class.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
BASE input.sv /^ type BASE=supertest #(test)$/;" c class:paramtest2
BASE input.sv /^class paramtest #(type BASE=supertest #(test)) extends BASE;$/;" c class:paramtest
DEFINE input.sv /^`define DEFINE$/;" c
DEF_VALUE input.sv /^`define DEF_VALUE 1'd100$/;" c
DEF_WITH_EQ input.sv /^`define DEF_WITH_EQ = 1'd100$/;" c
a input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" p function:test.extern_func
a input.sv /^ function mult (a, input b = 0);$/;" p function:supertest.mult
a input.sv /^ function mult (a, input b = 0);$/;" p function:test.mult
a input.sv /^ reg a;$/;" r class:test
b input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" p function:test.extern_func
b input.sv /^ function mult (a, input b = 0);$/;" p function:supertest.mult
b input.sv /^ function mult (a, input b = 0);$/;" p function:test.mult
b input.sv /^ logic b;$/;" r class:test
c input.sv /^ logic c;$/;" r class:supertest
extern_func input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" f class:test
mult input.sv /^ function mult (a, input b = 0);$/;" f class:supertest
mult input.sv /^ function mult (a, input b = 0);$/;" f class:test
paramtest input.sv /^class paramtest #(type BASE=supertest #(test)) extends BASE;$/;" C inherits:BASE
paramtest.BASE input.sv /^class paramtest #(type BASE=supertest #(test)) extends BASE;$/;" c class:paramtest
paramtest2 input.sv /^class paramtest2 #($/;" C
paramtest2.BASE input.sv /^ type BASE=supertest #(test)$/;" c class:paramtest2
supertest input.sv /^class supertest extends test;$/;" C inherits:test
supertest.c input.sv /^ logic c;$/;" r class:supertest
supertest.mult input.sv /^ function mult (a, input b = 0);$/;" f class:supertest
supertest.mult.a input.sv /^ function mult (a, input b = 0);$/;" p function:supertest.mult
supertest.mult.b input.sv /^ function mult (a, input b = 0);$/;" p function:supertest.mult
test input.sv /^class test;$/;" C
test.a input.sv /^ reg a;$/;" r class:test
test.b input.sv /^ logic b;$/;" r class:test
test.extern_func input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" f class:test
test.extern_func.a input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" p function:test.extern_func
test.extern_func.b input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" p function:test.extern_func
test.mult input.sv /^ function mult (a, input b = 0);$/;" f class:test
test.mult.a input.sv /^ function mult (a, input b = 0);$/;" p function:test.mult
test.mult.b input.sv /^ function mult (a, input b = 0);$/;" p function:test.mult
32 changes: 32 additions & 0 deletions Units/verilog-sv-class.d/input.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Include module declaration in a comment
// module wrong;
// endmodule
`define DEFINE
`define DEF_WITH_EQ = 1'd100
`define DEF_VALUE 1'd100

class test;
reg a;
logic b;
function mult (a, input b = 0);
return a * b;
endfunction : mult

extern virtual function void extern_func (input bit a, input b);

endclass : test

class supertest extends test;
logic c;
function mult (a, input b = 0);
return a * b * 2;
endfunction : mult
endclass : test

class paramtest #(type BASE=supertest #(test)) extends BASE;
endclass : paramtest

class paramtest2 #(
type BASE=supertest #(test)
) extends BASE;
endclass : paramtest2
1 change: 1 addition & 0 deletions Units/verilog-sv-qualifiers.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--extra=+q
70 changes: 70 additions & 0 deletions Units/verilog-sv-qualifiers.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
ext_func input.sv /^extern function ext_func (x, y);$/;" f
ext_func.x input.sv /^extern function ext_func (x, y);$/;" p function:ext_func
ext_func.y input.sv /^extern function ext_func (x, y);$/;" p function:ext_func
ext_local_func input.sv /^extern local function ext_local_func (x, y);$/;" f
ext_local_func.x input.sv /^extern local function ext_local_func (x, y);$/;" p function:ext_local_func
ext_local_func.y input.sv /^extern local function ext_local_func (x, y);$/;" p function:ext_local_func
ext_local_task input.sv /^extern local task ext_local_task (x, y);$/;" t
ext_local_task.x input.sv /^extern local task ext_local_task (x, y);$/;" p task:ext_local_task
ext_local_task.y input.sv /^extern local task ext_local_task (x, y);$/;" p task:ext_local_task
ext_protected_func input.sv /^extern protected function ext_protected_func (x, y);$/;" f
ext_protected_func.x input.sv /^extern protected function ext_protected_func (x, y);$/;" p function:ext_protected_func
ext_protected_func.y input.sv /^extern protected function ext_protected_func (x, y);$/;" p function:ext_protected_func
ext_protected_task input.sv /^extern protected task ext_protected_task (x, y);$/;" t
ext_protected_task.x input.sv /^extern protected task ext_protected_task (x, y);$/;" p task:ext_protected_task
ext_protected_task.y input.sv /^extern protected task ext_protected_task (x, y);$/;" p task:ext_protected_task
ext_pure_virt_func input.sv /^extern pure virtual function ext_pure_virt_func (x);$/;" f
ext_pure_virt_func.x input.sv /^extern pure virtual function ext_pure_virt_func (x);$/;" p function:ext_pure_virt_func
ext_pure_virt_task input.sv /^extern pure virtual task ext_pure_virt_task (x);$/;" t
ext_pure_virt_task.x input.sv /^extern pure virtual task ext_pure_virt_task (x);$/;" p task:ext_pure_virt_task
ext_static_func input.sv /^extern static function ext_static_func (x, y);$/;" f
ext_static_func.x input.sv /^extern static function ext_static_func (x, y);$/;" p function:ext_static_func
ext_static_func.y input.sv /^extern static function ext_static_func (x, y);$/;" p function:ext_static_func
ext_static_task input.sv /^extern static task ext_static_task (x, y);$/;" t
ext_static_task.x input.sv /^extern static task ext_static_task (x, y);$/;" p task:ext_static_task
ext_static_task.y input.sv /^extern static task ext_static_task (x, y);$/;" p task:ext_static_task
ext_task input.sv /^extern task ext_task (x, y);$/;" t
ext_task.x input.sv /^extern task ext_task (x, y);$/;" p task:ext_task
ext_task.y input.sv /^extern task ext_task (x, y);$/;" p task:ext_task
pure_virt_func input.sv /^pure virtual function pure_virt_func (x);$/;" f
pure_virt_func.x input.sv /^pure virtual function pure_virt_func (x);$/;" p function:pure_virt_func
pure_virt_local_func input.sv /^pure virtual local function pure_virt_local_func (x);$/;" f
pure_virt_local_func.x input.sv /^pure virtual local function pure_virt_local_func (x);$/;" p function:pure_virt_local_func
pure_virt_local_task input.sv /^pure virtual local task pure_virt_local_task (x);$/;" t
pure_virt_local_task.x input.sv /^pure virtual local task pure_virt_local_task (x);$/;" p task:pure_virt_local_task
pure_virt_protected_func input.sv /^pure virtual protected function pure_virt_protected_func (x);$/;" f
pure_virt_protected_func.x input.sv /^pure virtual protected function pure_virt_protected_func (x);$/;" p function:pure_virt_protected_func
pure_virt_protected_task input.sv /^pure virtual protected task pure_virt_protected_task (x);$/;" t
pure_virt_protected_task.x input.sv /^pure virtual protected task pure_virt_protected_task (x);$/;" p task:pure_virt_protected_task
pure_virt_static_func input.sv /^pure virtual static function pure_virt_static_func (x);$/;" f
pure_virt_static_func.x input.sv /^pure virtual static function pure_virt_static_func (x);$/;" p function:pure_virt_static_func
pure_virt_static_task input.sv /^pure virtual static task pure_virt_static_task (x);$/;" t
pure_virt_static_task.x input.sv /^pure virtual static task pure_virt_static_task (x);$/;" p task:pure_virt_static_task
pure_virt_task input.sv /^pure virtual task pure_virt_task (x);$/;" t
pure_virt_task.x input.sv /^pure virtual task pure_virt_task (x);$/;" p task:pure_virt_task
x input.sv /^extern function ext_func (x, y);$/;" p function:ext_func
x input.sv /^extern local function ext_local_func (x, y);$/;" p function:ext_local_func
x input.sv /^extern local task ext_local_task (x, y);$/;" p task:ext_local_task
x input.sv /^extern protected function ext_protected_func (x, y);$/;" p function:ext_protected_func
x input.sv /^extern protected task ext_protected_task (x, y);$/;" p task:ext_protected_task
x input.sv /^extern pure virtual function ext_pure_virt_func (x);$/;" p function:ext_pure_virt_func
x input.sv /^extern pure virtual task ext_pure_virt_task (x);$/;" p task:ext_pure_virt_task
x input.sv /^extern static function ext_static_func (x, y);$/;" p function:ext_static_func
x input.sv /^extern static task ext_static_task (x, y);$/;" p task:ext_static_task
x input.sv /^extern task ext_task (x, y);$/;" p task:ext_task
x input.sv /^pure virtual function pure_virt_func (x);$/;" p function:pure_virt_func
x input.sv /^pure virtual local function pure_virt_local_func (x);$/;" p function:pure_virt_local_func
x input.sv /^pure virtual local task pure_virt_local_task (x);$/;" p task:pure_virt_local_task
x input.sv /^pure virtual protected function pure_virt_protected_func (x);$/;" p function:pure_virt_protected_func
x input.sv /^pure virtual protected task pure_virt_protected_task (x);$/;" p task:pure_virt_protected_task
x input.sv /^pure virtual static function pure_virt_static_func (x);$/;" p function:pure_virt_static_func
x input.sv /^pure virtual static task pure_virt_static_task (x);$/;" p task:pure_virt_static_task
x input.sv /^pure virtual task pure_virt_task (x);$/;" p task:pure_virt_task
y input.sv /^extern function ext_func (x, y);$/;" p function:ext_func
y input.sv /^extern local function ext_local_func (x, y);$/;" p function:ext_local_func
y input.sv /^extern local task ext_local_task (x, y);$/;" p task:ext_local_task
y input.sv /^extern protected function ext_protected_func (x, y);$/;" p function:ext_protected_func
y input.sv /^extern protected task ext_protected_task (x, y);$/;" p task:ext_protected_task
y input.sv /^extern static function ext_static_func (x, y);$/;" p function:ext_static_func
y input.sv /^extern static task ext_static_task (x, y);$/;" p task:ext_static_task
y input.sv /^extern task ext_task (x, y);$/;" p task:ext_task
36 changes: 36 additions & 0 deletions Units/verilog-sv-qualifiers.d/input.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
extern function ext_func (x, y);

extern static function ext_static_func (x, y);

extern protected function ext_protected_func (x, y);

extern local function ext_local_func (x, y);

extern pure virtual function ext_pure_virt_func (x);

pure virtual function pure_virt_func (x);

pure virtual static function pure_virt_static_func (x);

pure virtual protected function pure_virt_protected_func (x);

pure virtual local function pure_virt_local_func (x);


extern task ext_task (x, y);

extern static task ext_static_task (x, y);

extern protected task ext_protected_task (x, y);

extern local task ext_local_task (x, y);

extern pure virtual task ext_pure_virt_task (x);

pure virtual task pure_virt_task (x);

pure virtual static task pure_virt_static_task (x);

pure virtual protected task pure_virt_protected_task (x);

pure virtual local task pure_virt_local_task (x);
93 changes: 92 additions & 1 deletion verilog.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ typedef struct sTokenInfo {
int nestLevel; /* Current nest level */
verilogKind lastKind; /* Kind of last found tag */
vString* blockName; /* Current block name */
vString* inheritance; /* Class inheritance */
boolean singleStat; /* Single statement (ends at next semi-colon) */
} tokenInfo;

Expand Down Expand Up @@ -179,6 +180,7 @@ static const keywordAssoc KeywordTable [] = {
{ "shortreal", K_REGISTER, { 1, 0 } },
{ "static", K_IGNORE, { 1, 0 } },
{ "string", K_REGISTER, { 1, 0 } },
{ "type", K_IGNORE, { 1, 0 } },
{ "typedef", K_TYPEDEF, { 1, 0 } },
{ "unsigned", K_IGNORE, { 1, 0 } },
{ "virtual", K_IGNORE, { 1, 0 } },
Expand Down Expand Up @@ -244,7 +246,8 @@ static short hasSimplePortList (tokenInfo const* token)

static short isSingleStatement (tokenInfo const* token)
{
if (strcmp (vStringValue (token->name), "extern") == 0 )
if (strcmp (vStringValue (token->name), "extern") == 0 ||
strcmp (vStringValue (token->name), "virtual") == 0 )
{
return TRUE;
} else {
Expand All @@ -263,6 +266,7 @@ static tokenInfo *newToken (void)
token->nestLevel = 0;
token->lastKind = K_UNDEFINED;
token->blockName = vStringNew ();
token->inheritance = vStringNew ();
token->singleStat = FALSE;
return token;
}
Expand All @@ -273,6 +277,7 @@ static void deleteToken (tokenInfo * const token)
{
vStringDelete (token->name);
vStringDelete (token->blockName);
vStringDelete (token->inheritance);
eFree (token);
}
}
Expand Down Expand Up @@ -601,6 +606,11 @@ static void createTag (tokenInfo *const token)
tag.extensionFields.scope [1] = vStringValue (currentContext->name);
}
verbose ("\n");
if (vStringLength (token->inheritance) > 0)
{
tag.extensionFields.inheritance = vStringValue (token->inheritance);
verbose ("Class %s extends %s\n", vStringValue (token->name), tag.extensionFields.inheritance);
}
makeTagEntry (&tag);
if (Option.include.qualifiedTags && currentContext->kind != K_UNDEFINED)
{
Expand All @@ -615,6 +625,8 @@ static void createTag (tokenInfo *const token)

vStringDelete (scopedName);
}

/* Push token as context if it is a container */
if (isContainer (token))
{
tokenInfo *newScope = newToken ();
Expand All @@ -623,6 +635,9 @@ static void createTag (tokenInfo *const token)
newScope->kind = token->kind;
createContext (newScope);
}

/* Clear no longer required inheritance information */
vStringClear (token->inheritance);
}

static boolean findBlockName (tokenInfo *const token)
Expand Down Expand Up @@ -814,6 +829,78 @@ static void processTypedef (tokenInfo *const token)
createTag (token);
}

static void processClass (tokenInfo *const token)
{
/*Note: At the moment, only identifies typedef name and not its contents */
int c;
tokenInfo *extra;
tokenInfo *parameters = NULL;

/* Get identifiers */
c = skipWhite (vGetc ());
if (isIdentifierCharacter (c))
{
readIdentifier (token, c);
c = skipWhite (vGetc ());
}

/* Find class parameters list */
if (c == '#')
{
c = skipWhite (vGetc ());
if (c == '(')
{
parameters = newToken ();
do
{
c = skipWhite (vGetc ());
readIdentifier (parameters, c);
updateKind (parameters);
verbose ("Found class parameter %s\n", vStringValue (parameters->name));
if (parameters->kind == K_UNDEFINED)
{
parameters->kind = K_CONSTANT;
parameters = pushToken (parameters, newToken ());
c = vGetc();
while (c != ',' && c != ')' && c != EOF)
{
c = vGetc();
}
}
} while (c != ')' && c != EOF);
c = vGetc ();
parameters = popToken (parameters);
}
c = skipWhite (vGetc ());
}

/* Search for inheritance information */
if (isIdentifierCharacter (c))
{
extra = newToken ();

readIdentifier (extra, c);
c = skipWhite (vGetc ());
if (strcmp (vStringValue (extra->name), "extends") == 0)
{
readIdentifier (extra, c);
vStringCopy (token->inheritance, extra->name);
verbose ("Inheritance %s\n", vStringValue (token->inheritance));
}
deleteToken (extra);
}

/* Use last identifier to create tag */
createTag (token);

/* Add parameter list */
while (parameters)
{
createTag (parameters);
parameters = popToken (parameters);
}
}

static void tagNameList (tokenInfo* token, int c)
{
verilogKind localKind;
Expand Down Expand Up @@ -941,6 +1028,10 @@ static void findTag (tokenInfo *const token)
{
processTypedef (token);
}
else if (token->kind == K_CLASS)
{
processClass (token);
}
else if (token->kind == K_IGNORE && isSingleStatement (token))
{
currentContext->singleStat = TRUE;
Expand Down

0 comments on commit 3085a65

Please sign in to comment.