From c55ebe48ce54630723ece5c5d800fad27b8cb5c6 Mon Sep 17 00:00:00 2001 From: Vitor Antunes Date: Mon, 26 Oct 2015 19:57:39 +0000 Subject: [PATCH 1/3] units: Improve SystemVerilog qualifiers test unit Include function definitions with lifetime qualifiers "automatic" and "static". --- .../systemverilog-qualifiers.d/expected.tags | 6 ++++++ Units/parser-verilog.r/systemverilog-qualifiers.d/input.sv | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/Units/parser-verilog.r/systemverilog-qualifiers.d/expected.tags b/Units/parser-verilog.r/systemverilog-qualifiers.d/expected.tags index 63b56cfec5..84223b1ed1 100644 --- a/Units/parser-verilog.r/systemverilog-qualifiers.d/expected.tags +++ b/Units/parser-verilog.r/systemverilog-qualifiers.d/expected.tags @@ -1,3 +1,7 @@ +auto_function input.sv /^function automatic auto_function (x);$/;" f +auto_function.x input.sv /^function automatic auto_function (x);$/;" p function:auto_function +auto_static input.sv /^function static auto_static (x);$/;" f +auto_static.x input.sv /^function static auto_static (x);$/;" p function:auto_static ext_func input.sv /^extern function ext_func (x, y);$/;" Q ext_func.x input.sv /^extern function ext_func (x, y);$/;" p prototype:ext_func ext_func.y input.sv /^extern function ext_func (x, y);$/;" p prototype:ext_func @@ -52,6 +56,8 @@ x input.sv /^extern pure virtual task ext_pure_virt_task (x);$/;" p prototype:ex x input.sv /^extern static function ext_static_func (x, y);$/;" p prototype:ext_static_func x input.sv /^extern static task ext_static_task (x, y);$/;" p prototype:ext_static_task x input.sv /^extern task ext_task (x, y);$/;" p prototype:ext_task +x input.sv /^function automatic auto_function (x);$/;" p function:auto_function +x input.sv /^function static auto_static (x);$/;" p function:auto_static x input.sv /^pure virtual function pure_virt_func (x);$/;" p prototype:pure_virt_func x input.sv /^pure virtual local function pure_virt_local_func (x);$/;" p prototype:pure_virt_local_func x input.sv /^pure virtual local task pure_virt_local_task (x);$/;" p prototype:pure_virt_local_task diff --git a/Units/parser-verilog.r/systemverilog-qualifiers.d/input.sv b/Units/parser-verilog.r/systemverilog-qualifiers.d/input.sv index c008f3e06a..f19f99e1ec 100644 --- a/Units/parser-verilog.r/systemverilog-qualifiers.d/input.sv +++ b/Units/parser-verilog.r/systemverilog-qualifiers.d/input.sv @@ -34,3 +34,9 @@ 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); + +function automatic auto_function (x); +endfunction : auto_function + +function static auto_static (x); +endfunction : auto_static From 7f6ca9bea88f4828d64a438fbcacc1e7b1c99dc6 Mon Sep 17 00:00:00 2001 From: Vitor Antunes Date: Wed, 28 Oct 2015 14:30:50 +0000 Subject: [PATCH 2/3] units: Add SystemVerilog qualified attributes test --- .../systemverilog-class.d/expected.tags | 19 +++++++++++++++++++ .../systemverilog-class.d/input.sv | 12 ++++++++++++ 2 files changed, 31 insertions(+) diff --git a/Units/parser-verilog.r/systemverilog-class.d/expected.tags b/Units/parser-verilog.r/systemverilog-class.d/expected.tags index 783ab86ff6..695d1bae2c 100644 --- a/Units/parser-verilog.r/systemverilog-class.d/expected.tags +++ b/Units/parser-verilog.r/systemverilog-class.d/expected.tags @@ -18,12 +18,17 @@ b input.sv /^virtual function myfunc (a, b);$/;" p function:paramtest3.myfunc c input.sv /^ logic c;$/;" r class:supertest c input.sv /^extern virtual function test ext_func (c, d);$/;" p prototype:paramtest3.ext_func c input.sv /^function test paramtest3::ext_func (c, d);$/;" p function:paramtest3.ext_func +const_local_logic input.sv /^ const local logic const_local_logic;$/;" r class:test_attributes +const_logic input.sv /^ const logic const_logic;$/;" r class:test_attributes +const_protected_logic input.sv /^ const protected logic const_protected_logic;$/;" r class:test_attributes +const_static_logic input.sv /^ const static logic const_static_logic;$/;" r class:test_attributes d input.sv /^extern virtual function test ext_func (c, d);$/;" p prototype:paramtest3.ext_func d input.sv /^function test paramtest3::ext_func (c, d);$/;" p function:paramtest3.ext_func ext_func input.sv /^extern virtual function test ext_func (c, d);$/;" Q class:paramtest3 ext_func input.sv /^function test paramtest3::ext_func (c, d);$/;" f class:paramtest3 extern_func input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" Q class:test fwrd_ref input.sv /^ extern virtual function bit fwrd_ref;$/;" Q class:supertest +local_logic input.sv /^ local logic local_logic;$/;" r class:test_attributes mult input.sv /^ function mult (a, input b = 0);$/;" f class:supertest mult input.sv /^ function mult (a, input b = 0);$/;" f class:test myfunc input.sv /^virtual function myfunc (a, b);$/;" f class:paramtest3 @@ -43,6 +48,10 @@ paramtest3.ext_func.d input.sv /^function test paramtest3::ext_func (c, d);$/;" paramtest3.myfunc input.sv /^virtual function myfunc (a, b);$/;" f class:paramtest3 paramtest3.myfunc.a input.sv /^virtual function myfunc (a, b);$/;" p function:paramtest3.myfunc paramtest3.myfunc.b input.sv /^virtual function myfunc (a, b);$/;" p function:paramtest3.myfunc +protected_logic input.sv /^ protected logic protected_logic;$/;" r class:test_attributes +rand_logic input.sv /^ rand logic rand_logic;$/;" r class:test_attributes +randc_logic input.sv /^ randc logic randc_logic;$/;" r class:test_attributes +static_logic input.sv /^ static logic static_logic;$/;" r class:test_attributes supertest input.sv /^class supertest extends test;$/;" C inherits:test supertest.c input.sv /^ logic c;$/;" r class:supertest supertest.fwrd_ref input.sv /^ extern virtual function bit fwrd_ref;$/;" Q class:supertest @@ -58,3 +67,13 @@ test.extern_func.b input.sv /^ extern virtual function void extern_func (inpu 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 +test_attributes input.sv /^class test_attributes;$/;" C +test_attributes.const_local_logic input.sv /^ const local logic const_local_logic;$/;" r class:test_attributes +test_attributes.const_logic input.sv /^ const logic const_logic;$/;" r class:test_attributes +test_attributes.const_protected_logic input.sv /^ const protected logic const_protected_logic;$/;" r class:test_attributes +test_attributes.const_static_logic input.sv /^ const static logic const_static_logic;$/;" r class:test_attributes +test_attributes.local_logic input.sv /^ local logic local_logic;$/;" r class:test_attributes +test_attributes.protected_logic input.sv /^ protected logic protected_logic;$/;" r class:test_attributes +test_attributes.rand_logic input.sv /^ rand logic rand_logic;$/;" r class:test_attributes +test_attributes.randc_logic input.sv /^ randc logic randc_logic;$/;" r class:test_attributes +test_attributes.static_logic input.sv /^ static logic static_logic;$/;" r class:test_attributes diff --git a/Units/parser-verilog.r/systemverilog-class.d/input.sv b/Units/parser-verilog.r/systemverilog-class.d/input.sv index e503aec5f4..b1728419b4 100644 --- a/Units/parser-verilog.r/systemverilog-class.d/input.sv +++ b/Units/parser-verilog.r/systemverilog-class.d/input.sv @@ -43,3 +43,15 @@ endclass : paramtest3 function test paramtest3::ext_func (c, d); endfunction + +class test_attributes; + static logic static_logic; + protected logic protected_logic; + local logic local_logic; + const static logic const_static_logic; + const protected logic const_protected_logic; + const local logic const_local_logic; + rand logic rand_logic; + randc logic randc_logic; + const logic const_logic; +endclass : test_attributes From 9a4331764b7572adb7b11bb99defdef69cfb96a3 Mon Sep 17 00:00:00 2001 From: Vitor Antunes Date: Mon, 10 Jul 2017 01:36:46 +0100 Subject: [PATCH 3/3] verilog: Improve support for enumerators and typedefs --- .../systemverilog-class.d/expected.tags | 30 +++ .../systemverilog-class.d/input.sv | 9 + .../systemverilog-typedef.d/expected.tags | 54 ++++- .../systemverilog-typedef.d/input.sv | 58 ++++- parsers/verilog.c | 227 ++++++++++++++++-- 5 files changed, 338 insertions(+), 40 deletions(-) diff --git a/Units/parser-verilog.r/systemverilog-class.d/expected.tags b/Units/parser-verilog.r/systemverilog-class.d/expected.tags index 695d1bae2c..e855f58dd6 100644 --- a/Units/parser-verilog.r/systemverilog-class.d/expected.tags +++ b/Units/parser-verilog.r/systemverilog-class.d/expected.tags @@ -24,6 +24,21 @@ const_protected_logic input.sv /^ const protected logic const_protected_logic;$ const_static_logic input.sv /^ const static logic const_static_logic;$/;" r class:test_attributes d input.sv /^extern virtual function test ext_func (c, d);$/;" p prototype:paramtest3.ext_func d input.sv /^function test paramtest3::ext_func (c, d);$/;" p function:paramtest3.ext_func +enum_bit1 input.sv /^ enum_bit1,$/;" c enum:test.enum_complex +enum_bit2 input.sv /^ enum_bit2='x,$/;" c enum:test.enum_complex +enum_bit3 input.sv /^ enum_bit3=2'b01,$/;" c enum:test.enum_complex +enum_bit4 input.sv /^ enum_bit4[0:10]=2'b10,$/;" c enum:test.enum_complex +enum_bit5 input.sv /^ enum_bit5 [9:0] = 2'b10 ,$/;" c enum:test.enum_complex +enum_complex input.sv /^ } enum_complex;$/;" E class:test +enum_const1 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" c enum:test.enum_var1 +enum_const1 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" c enum:test.enum_var2 +enum_const2 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" c enum:test.enum_var1 +enum_const2 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" c enum:test.enum_var2 +enum_simple input.sv /^ enum {enum_simple1, enum_simple2} enum_simple;$/;" E class:test +enum_simple1 input.sv /^ enum {enum_simple1, enum_simple2} enum_simple;$/;" c enum:test.enum_simple +enum_simple2 input.sv /^ enum {enum_simple1, enum_simple2} enum_simple;$/;" c enum:test.enum_simple +enum_var1 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" E class:test +enum_var2 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" E class:test ext_func input.sv /^extern virtual function test ext_func (c, d);$/;" Q class:paramtest3 ext_func input.sv /^function test paramtest3::ext_func (c, d);$/;" f class:paramtest3 extern_func input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" Q class:test @@ -61,6 +76,21 @@ supertest.mult.b input.sv /^ function mult (a, input b = 0);$/;" p function:s 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.enum_complex input.sv /^ } enum_complex;$/;" E class:test +test.enum_complex.enum_bit1 input.sv /^ enum_bit1,$/;" c enum:test.enum_complex +test.enum_complex.enum_bit2 input.sv /^ enum_bit2='x,$/;" c enum:test.enum_complex +test.enum_complex.enum_bit3 input.sv /^ enum_bit3=2'b01,$/;" c enum:test.enum_complex +test.enum_complex.enum_bit4 input.sv /^ enum_bit4[0:10]=2'b10,$/;" c enum:test.enum_complex +test.enum_complex.enum_bit5 input.sv /^ enum_bit5 [9:0] = 2'b10 ,$/;" c enum:test.enum_complex +test.enum_simple input.sv /^ enum {enum_simple1, enum_simple2} enum_simple;$/;" E class:test +test.enum_simple.enum_simple1 input.sv /^ enum {enum_simple1, enum_simple2} enum_simple;$/;" c enum:test.enum_simple +test.enum_simple.enum_simple2 input.sv /^ enum {enum_simple1, enum_simple2} enum_simple;$/;" c enum:test.enum_simple +test.enum_var1 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" E class:test +test.enum_var1.enum_const1 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" c enum:test.enum_var1 +test.enum_var1.enum_const2 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" c enum:test.enum_var1 +test.enum_var2 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" E class:test +test.enum_var2.enum_const1 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" c enum:test.enum_var2 +test.enum_var2.enum_const2 input.sv /^ enum {enum_const1, enum_const2} enum_var1, enum_var2;$/;" c enum:test.enum_var2 test.extern_func input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" Q class:test test.extern_func.a input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" p prototype:test.extern_func test.extern_func.b input.sv /^ extern virtual function void extern_func (input bit a, input b);$/;" p prototype:test.extern_func diff --git a/Units/parser-verilog.r/systemverilog-class.d/input.sv b/Units/parser-verilog.r/systemverilog-class.d/input.sv index b1728419b4..0139a4ce4c 100644 --- a/Units/parser-verilog.r/systemverilog-class.d/input.sv +++ b/Units/parser-verilog.r/systemverilog-class.d/input.sv @@ -8,6 +8,15 @@ class test; reg a; logic b; + enum {enum_simple1, enum_simple2} enum_simple; + enum {enum_const1, enum_const2} enum_var1, enum_var2; + enum bit [1:0] { + enum_bit1, + enum_bit2='x, + enum_bit3=2'b01, + enum_bit4[0:10]=2'b10, + enum_bit5 [9:0] = 2'b10 , + } enum_complex; function mult (a, input b = 0); return a * b; endfunction : mult diff --git a/Units/parser-verilog.r/systemverilog-typedef.d/expected.tags b/Units/parser-verilog.r/systemverilog-typedef.d/expected.tags index 89bd746d73..dfcb6b8e70 100644 --- a/Units/parser-verilog.r/systemverilog-typedef.d/expected.tags +++ b/Units/parser-verilog.r/systemverilog-typedef.d/expected.tags @@ -1,8 +1,46 @@ -myType input.sv /^} myType;$/;" T -myType2 input.sv /^typedef classname#(paramvalue) myType2;$/;" T -type_class input.sv /^typedef class type_class;$/;" Q -type_enum input.sv /^typedef enum type_enum;$/;" T -type_interface_class input.sv /^typedef interface class type_interface_class;$/;" T -type_struct input.sv /^typedef struct type_struct;$/;" T -type_union input.sv /^typedef union type_union;$/;" T -type_unnamed input.sv /^typedef type_unnamed;$/;" T +A input.sv /^ A = 2'b00,$/;" c typedef:type_enum_bit_bus_defined_values +B input.sv /^ B = 2'b01,$/;" c typedef:type_enum_bit_bus_defined_values +C input.sv /^ C = 2'b10,$/;" c typedef:type_enum_bit_bus_defined_values +D input.sv /^ D = {1'b1, 1'b1}$/;" c typedef:type_enum_bit_bus_defined_values +W input.sv /^typedef enum bit {W, X} type_enum_bit;$/;" c typedef:type_enum_bit +X input.sv /^typedef enum bit {W, X} type_enum_bit;$/;" c typedef:type_enum_bit +Y input.sv /^typedef enum bit [1:0] {Y, Z} type_enum_bit2;$/;" c typedef:type_enum_bit2 +Z input.sv /^typedef enum bit [1:0] {Y, Z} type_enum_bit2;$/;" c typedef:type_enum_bit2 +cond0 input.sv /^ cond0 = 0, cond1 = 1, cond2 = 2$/;" c typedef:type_int_unsigned +cond1 input.sv /^ cond0 = 0, cond1 = 1, cond2 = 2$/;" c typedef:type_int_unsigned +cond2 input.sv /^ cond0 = 0, cond1 = 1, cond2 = 2$/;" c typedef:type_int_unsigned +fwd_type input.sv /^typedef fwd_type;$/;" Q +fwd_type_class input.sv /^typedef class fwd_type_class;$/;" Q +fwd_type_enum input.sv /^typedef enum fwd_type_enum;$/;" Q +fwd_type_interface_class input.sv /^typedef interface class fwd_type_interface_class;$/;" Q +fwd_type_struct input.sv /^typedef struct fwd_type_struct;$/;" Q +fwd_type_union input.sv /^typedef union fwd_type_union;$/;" Q +no input.sv /^typedef enum {no, yes} type_enum;$/;" c typedef:type_enum +type_bit input.sv /^typedef bit type_bit;$/;" T +type_bit_bus input.sv /^typedef bit [1:0] type_bit_bus;$/;" T +type_bit_bus_array input.sv /^typedef bit [1:0] type_bit_bus_array [2:0];$/;" T +type_class input.sv /^typedef classname#(paramvalue) type_class;$/;" T +type_enum input.sv /^typedef enum {no, yes} type_enum;$/;" T +type_enum.no input.sv /^typedef enum {no, yes} type_enum;$/;" c typedef:type_enum +type_enum.yes input.sv /^typedef enum {no, yes} type_enum;$/;" c typedef:type_enum +type_enum_bit input.sv /^typedef enum bit {W, X} type_enum_bit;$/;" T +type_enum_bit.W input.sv /^typedef enum bit {W, X} type_enum_bit;$/;" c typedef:type_enum_bit +type_enum_bit.X input.sv /^typedef enum bit {W, X} type_enum_bit;$/;" c typedef:type_enum_bit +type_enum_bit2 input.sv /^typedef enum bit [1:0] {Y, Z} type_enum_bit2;$/;" T +type_enum_bit2.Y input.sv /^typedef enum bit [1:0] {Y, Z} type_enum_bit2;$/;" c typedef:type_enum_bit2 +type_enum_bit2.Z input.sv /^typedef enum bit [1:0] {Y, Z} type_enum_bit2;$/;" c typedef:type_enum_bit2 +type_enum_bit_bus_defined_values input.sv /^} type_enum_bit_bus_defined_values;$/;" T +type_enum_bit_bus_defined_values.A input.sv /^ A = 2'b00,$/;" c typedef:type_enum_bit_bus_defined_values +type_enum_bit_bus_defined_values.B input.sv /^ B = 2'b01,$/;" c typedef:type_enum_bit_bus_defined_values +type_enum_bit_bus_defined_values.C input.sv /^ C = 2'b10,$/;" c typedef:type_enum_bit_bus_defined_values +type_enum_bit_bus_defined_values.D input.sv /^ D = {1'b1, 1'b1}$/;" c typedef:type_enum_bit_bus_defined_values +type_int_unsigned input.sv /^ } type_int_unsigned;$/;" T +type_int_unsigned.cond0 input.sv /^ cond0 = 0, cond1 = 1, cond2 = 2$/;" c typedef:type_int_unsigned +type_int_unsigned.cond1 input.sv /^ cond0 = 0, cond1 = 1, cond2 = 2$/;" c typedef:type_int_unsigned +type_int_unsigned.cond2 input.sv /^ cond0 = 0, cond1 = 1, cond2 = 2$/;" c typedef:type_int_unsigned +type_struct input.sv /^ } type_struct;$/;" T +type_struct_union input.sv /^ } type_struct_union;$/;" T +type_union input.sv /^ } type_union;$/;" T +type_union_packed input.sv /^ } type_union_packed;$/;" T +type_union_tagged input.sv /^ } type_union_tagged;$/;" T +yes input.sv /^typedef enum {no, yes} type_enum;$/;" c typedef:type_enum diff --git a/Units/parser-verilog.r/systemverilog-typedef.d/input.sv b/Units/parser-verilog.r/systemverilog-typedef.d/input.sv index c451f7d30d..2f43108346 100644 --- a/Units/parser-verilog.r/systemverilog-typedef.d/input.sv +++ b/Units/parser-verilog.r/systemverilog-typedef.d/input.sv @@ -1,15 +1,55 @@ -typedef enum type_enum; -typedef struct type_struct; -typedef union type_union; -typedef class type_class; -typedef interface class type_interface_class; -typedef type_unnamed; +typedef enum fwd_type_enum; +typedef struct fwd_type_struct; +typedef union fwd_type_union; +typedef class fwd_type_class; +typedef interface class fwd_type_interface_class; +typedef fwd_type; + +typedef enum {no, yes} type_enum; +typedef enum bit {W, X} type_enum_bit; +typedef enum bit [1:0] {Y, Z} type_enum_bit2; + +typedef struct { + real struct_real; + bit [1:0] struct_bit; + } type_struct; + +typedef union { + real union_real; + bit [1:0] union_bit; + } type_union; + +typedef union packed { + bit [1:0] union_bit1; + bit [1:0] union_bit2; + } type_union_packed; + +typedef union tagged { + void Invalid; + int Valid; + } type_union_tagged; + +typedef struct { + real struct_real; + union { + int i; + bit b; + } struct_union; + } type_struct_union; + +typedef bit type_bit; +typedef bit [1:0] type_bit_bus; +typedef bit [1:0] type_bit_bus_array [2:0]; + +typedef enum int unsigned{ + cond0 = 0, cond1 = 1, cond2 = 2 + } type_int_unsigned; typedef enum bit [1:0] { A = 2'b00, B = 2'b01, C = 2'b10, - D = 2'b11 -} myType; + D = {1'b1, 1'b1} +} type_enum_bit_bus_defined_values; -typedef classname#(paramvalue) myType2; +typedef classname#(paramvalue) type_class; diff --git a/parsers/verilog.c b/parsers/verilog.c index 4ae90820ff..17587d8ded 100644 --- a/parsers/verilog.c +++ b/parsers/verilog.c @@ -55,12 +55,14 @@ typedef enum { K_ASSERTION, K_CLASS, K_COVERGROUP, + K_ENUM, K_INTERFACE, K_MODPORT, K_PACKAGE, K_PROGRAM, K_PROTOTYPE, K_PROPERTY, + K_STRUCT, K_TYPEDEF } verilogKind; @@ -80,8 +82,8 @@ typedef struct sTokenInfo { verilogKind lastKind; /* Kind of last found tag */ vString* blockName; /* Current block name */ vString* inheritance; /* Class inheritance */ - bool prototype; /* Is only a prototype */ - bool classScope; /* Context is local to the current sub-context */ + bool prototype; /* Is only a prototype */ + bool classScope; /* Context is local to the current sub-context */ } tokenInfo; /* @@ -104,7 +106,7 @@ static kindDefinition VerilogKinds [] = { }; static kindDefinition SystemVerilogKinds [] = { - { true, 'c', "constant", "constants (define, parameter, specparam)" }, + { true, 'c', "constant", "constants (define, parameter, specparam, enum values)" }, { true, 'e', "event", "events" }, { true, 'f', "function", "functions" }, { true, 'm', "module", "modules" }, @@ -116,12 +118,14 @@ static kindDefinition SystemVerilogKinds [] = { { true, 'A', "assert", "assertions" }, { true, 'C', "class", "classes" }, { true, 'V', "covergroup","covergroups" }, + { true, 'E', "enum", "enumerators" }, { true, 'I', "interface", "interfaces" }, { true, 'M', "modport", "modports" }, { true, 'K', "package", "packages" }, { true, 'P', "program", "programs" }, { false,'Q', "prototype", "prototypes" }, { true, 'R', "property", "properties" }, + { true, 'S', "struct", "structs and unions" }, { true, 'T', "typedef", "type declarations" } }; @@ -169,6 +173,7 @@ static const keywordAssoc KeywordTable [] = { { "class", K_CLASS, { 1, 0 } }, { "cover", K_ASSERTION, { 1, 0 } }, { "covergroup",K_COVERGROUP,{ 1, 0 } }, + { "enum", K_ENUM, { 1, 0 } }, { "extern", K_IGNORE, { 1, 0 } }, { "int", K_REGISTER, { 1, 0 } }, { "interface", K_INTERFACE, { 1, 0 } }, @@ -185,14 +190,17 @@ static const keywordAssoc KeywordTable [] = { { "shortreal", K_REGISTER, { 1, 0 } }, { "static", K_IGNORE, { 1, 0 } }, { "string", K_REGISTER, { 1, 0 } }, + { "struct", K_STRUCT, { 1, 0 } }, { "type", K_IGNORE, { 1, 0 } }, { "typedef", K_TYPEDEF, { 1, 0 } }, + { "union", K_STRUCT, { 1, 0 } }, { "unsigned", K_IGNORE, { 1, 0 } }, { "virtual", K_IGNORE, { 1, 0 } }, { "void", K_IGNORE, { 1, 0 } } }; static tokenInfo *currentContext = NULL; +static tokenInfo *tagContents = NULL; /* * FUNCTION DEFINITIONS @@ -212,6 +220,20 @@ static short isContainer (tokenInfo const* token) case K_PACKAGE: case K_PROGRAM: case K_PROPERTY: + case K_TYPEDEF: + case K_ENUM: + return true; + default: + return false; + } +} + +static short isTempContext (tokenInfo const* token) +{ + switch (token->kind) + { + case K_TYPEDEF: + case K_ENUM: return true; default: return false; @@ -521,7 +543,7 @@ static void createContext (tokenInfo *const scope) } } -static void dropContext (tokenInfo *const token) +static void dropEndContext (tokenInfo *const token) { verbose ("current context %s; context kind %0d; nest level %0d\n", vStringValue (currentContext->name), currentContext->kind, currentContext->nestLevel); vString *endTokenName = vStringNewInit("end"); @@ -568,6 +590,7 @@ static void createTag (tokenInfo *const token) /* Do nothing it tag name is empty or tag kind is disabled */ if (vStringLength (token->name) == 0 || ! kindEnabled (kind)) { + verbose ("Unexpected empty token or kind disabled\n"); return; } @@ -616,6 +639,26 @@ static void createTag (tokenInfo *const token) vStringCopy (newScope->name, token->name); newScope->kind = kind; createContext (newScope); + + /* Include found contents in context */ + if (tagContents != NULL) + { + tokenInfo* content = tagContents; + + verbose ("Including tagContents\n"); + do + { + createTag (content); + content = content->scope; + } while (content); + } + + /* Drop temporary contexts */ + if (isTempContext (currentContext)) + { + verbose ("Dropping context %s\n", vStringValue (currentContext->name)); + currentContext = popToken (currentContext); + } } /* Clear no longer required inheritance information */ @@ -786,43 +829,165 @@ static void processFunction (tokenInfo *const token) } } -static void processTypedef (tokenInfo *const token) +static void tagNameList (tokenInfo* token, int c); + +static void processEnum (tokenInfo *const token) { - /*Note: At the moment, only identifies typedef name and not its contents */ int c; - /* Get typedef type */ + /* Read enum type */ c = skipWhite (vGetc ()); if (isIdentifierCharacter (c)) { - readIdentifier (token, c); - /* A typedef class is just a prototype */ - if (strcmp (vStringValue (token->name), "class") == 0) + tokenInfo* typeQueue = NULL; + tokenInfo* type; + + do { - currentContext->prototype = true; + type = newToken (); + + readIdentifier (type, c); + updateKind (type); + typeQueue = pushToken (typeQueue, type); + verbose ("Enum type %s\n", vStringValue (type->name)); + c = skipWhite (vGetc ()); + } while (isIdentifierCharacter (c)); + + /* Undefined kind means that we've reached the end of the + * declaration without having any contents defined, which + * indicates that this is in fact a forward declaration */ + if (type->kind == K_UNDEFINED && (typeQueue->scope == NULL || typeQueue->scope->kind != K_UNDEFINED)) + { + verbose ("Prototype enum found \"%s\"\n", vStringValue (type->name)); + type->kind = K_PROTOTYPE; + createTag (type); + pruneTokens (typeQueue); + return; } + + /* Cleanup type queue */ + pruneTokens (typeQueue); } - /* Skip remaining identifiers */ + /* Skip bus width definition */ + if (c == '[') + { + c = skipWhite (skipPastMatch ("[]")); + } + + /* Search enum elements */ + if (c == '{') + { + c = skipWhite (vGetc ()); + while (isIdentifierCharacter (c)) + { + tokenInfo *content = newToken (); + + readIdentifier (content, c); + content->kind = K_CONSTANT; + tagContents = pushToken (tagContents, content); + verbose ("Pushed enum element \"%s\"\n", vStringValue (content->name)); + + c = skipWhite (vGetc ()); + /* Skip element ranges */ + /* TODO Implement element ranges */ + if (c == '[') + { + c = skipWhite (skipPastMatch ("[]")); + } + /* Skip value assignments */ + if (c == '=') + { + while (c != '}' && c != ',' && c != EOF) + { + c = skipWhite (vGetc ()); + + /* Skip enum value concatenations */ + if (c == '{') + { + c = skipWhite (skipPastMatch ("{}")); + } + } + } + /* Skip comma */ + if (c == ',') + { + c = skipWhite (vGetc ()); + } + /* End of enum elements list */ + if (c == '}') + { + c = skipWhite (vGetc ()); + break; + } + } + } + + /* Following identifiers are tag names */ + verbose ("Find enum tags. Token %s kind %d\n", vStringValue (token->name), token->kind); + tagNameList (token, c); +} + +static void processTypedef (tokenInfo *const token) +{ + int c; + + /* Get typedef type */ c = skipWhite (vGetc ()); - while (isIdentifierCharacter (c)) + if (isIdentifierCharacter (c)) { readIdentifier (token, c); + updateKind (token); + + switch (token->kind) + { + case K_INTERFACE: + /* Expecting `typedef interface class` */ + c = skipWhite (vGetc ()); + readIdentifier (token, c); + updateKind (token); + case K_CLASS: + /* A typedef class is just a prototype */ + currentContext->prototype = true; + break; + case K_ENUM: + /* Call enum processing function */ + token->kind = K_TYPEDEF; + processEnum (token); + return; + default : + break; + } + c = skipWhite (vGetc ()); } /* Skip bus width definition */ if (c == '[') { - skipPastMatch ("[]"); + c = skipWhite (skipPastMatch ("[]")); + } + + /* Skip remaining identifiers */ + while (isIdentifierCharacter (c)) + { + readIdentifier (token, c); c = skipWhite (vGetc ()); } /* Skip typedef contents */ if (c == '{') { - skipPastMatch ("{}"); - c = skipWhite (vGetc ()); + c = skipWhite (skipPastMatch ("{}")); + } + else + { + /* Typedefs of struct/union that have no contents are forward + * declarations and are considered prototypes */ + if (token->kind == K_STRUCT) + { + currentContext->prototype = true; + } } /* Skip past class parameter override */ @@ -831,8 +996,7 @@ static void processTypedef (tokenInfo *const token) c = skipWhite (vGetc ()); if (c == '(') { - skipPastMatch ("()"); - c = skipWhite (vGetc ()); + c = skipWhite (skipPastMatch ("()")); } } @@ -844,8 +1008,17 @@ static void processTypedef (tokenInfo *const token) else { vUngetc (c); + + /* Empty typedefs are forward declarations and are considered + * prototypes */ + if (token->kind == K_UNDEFINED) + { + currentContext->prototype = true; + } } - /* Use last identifier to create tag */ + + /* Use last identifier to create tag, but always with kind typedef */ + token->kind = K_TYPEDEF; createTag (token); } @@ -1013,7 +1186,7 @@ static void findTag (tokenInfo *const token) if (currentContext->kind != K_UNDEFINED) { /* Drop context, but only if an end token is found */ - dropContext (token); + dropEndContext (token); } if (token->kind == K_CONSTANT && vStringItem (token->name, 0) == '`') @@ -1054,6 +1227,10 @@ static void findTag (tokenInfo *const token) { processTypedef (token); } + else if (token->kind == K_ENUM) + { + processEnum (token); + } else if (token->kind == K_CLASS) { processClass (token); @@ -1121,9 +1298,9 @@ static void findVerilogTags (void) skipPastMatch ("()"); } break; - /* Drop context on prototypes because they don't have an end - * statement */ case ';': + /* Drop context on prototypes because they don't have an + * end statement */ if (currentContext->scope && currentContext->scope->prototype) { verbose ("Dropping context %s\n", vStringValue (currentContext->name)); @@ -1135,7 +1312,11 @@ static void findVerilogTags (void) { currentContext->prototype = false; } - break; + /* Cleanup tag contents list at end of declaration */ + while (tagContents) + { + tagContents = popToken (tagContents); + } default : if (isIdentifierCharacter (c)) {