Skip to content

Commit af0f545

Browse files
committed
Verilog: introduce scope stack
This adds a scope stack to the Verilog parser, to enable entering named scopes using the :: and member operators while parsing.
1 parent 2ccff6c commit af0f545

File tree

4 files changed

+98
-34
lines changed

4 files changed

+98
-34
lines changed

src/verilog/parser.y

+25-18
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Author: Daniel Kroening, [email protected]
2828
#define mts(x, y) stack_expr(x).move_to_sub((irept &)stack_expr(y))
2929
#define swapop(x, y) stack_expr(x).operands().swap(stack_expr(y).operands())
3030
#define addswap(x, y, z) stack_expr(x).add(y).swap(stack_expr(z))
31-
#define push_scope(x, y) PARSER.scopes.push_scope(x, y)
31+
#define push_scope(name, separator, kind) PARSER.scopes.push_scope(name, separator, kind)
3232
#define pop_scope() PARSER.scopes.pop_scope();
3333

3434
int yyveriloglex();
@@ -644,7 +644,7 @@ module_identifier_with_scope:
644644
module_identifier
645645
{
646646
$$ = $1;
647-
push_scope(stack_expr($1).id(), ".");
647+
push_scope(stack_expr($1).id(), ".", verilog_scopet::MODULE);
648648
}
649649
;
650650

@@ -823,7 +823,7 @@ class_declaration:
823823
{
824824
init($$, ID_verilog_class);
825825
stack_expr($$).set(ID_base_name, stack_expr($2).id());
826-
push_scope(stack_expr($2).id(), "::");
826+
push_scope(stack_expr($2).id(), "::", verilog_scopet::CLASS);
827827
}
828828
class_item_brace
829829
TOK_ENDCLASS
@@ -839,7 +839,7 @@ package_declaration:
839839
lifetime_opt
840840
package_identifier ';'
841841
{
842-
push_scope(stack_expr($5).id(), "::");
842+
push_scope(stack_expr($5).id(), "::", verilog_scopet::PACKAGE);
843843
}
844844
timeunits_declaration_opt
845845
package_item_brace
@@ -1442,9 +1442,7 @@ net_declaration:
14421442
type_declaration:
14431443
TOK_TYPEDEF data_type new_identifier ';'
14441444
{ // add to the scope as a type name
1445-
auto &name = PARSER.scopes.add_name(stack_expr($3).get(ID_identifier), "");
1446-
name.is_type = true;
1447-
1445+
PARSER.scopes.add_name(stack_expr($3).get(ID_identifier), "", verilog_scopet::TYPEDEF);
14481446
init($$, ID_decl);
14491447
stack_expr($$).set(ID_class, ID_typedef);
14501448
addswap($$, ID_type, $2);
@@ -1535,7 +1533,7 @@ data_type:
15351533

15361534
// We attach a dummy id to distinguish two syntactically
15371535
// identical enum types.
1538-
auto id = PARSER.scopes.current_scope->prefix + "enum-" + PARSER.get_next_id();
1536+
auto id = PARSER.scopes.current_scope().prefix + "enum-" + PARSER.get_next_id();
15391537
stack_expr($$).set(ID_identifier, id);
15401538
}
15411539
| TOK_STRING
@@ -1569,7 +1567,7 @@ enum_name_declaration:
15691567
TOK_NON_TYPE_IDENTIFIER enum_name_value_opt
15701568
{
15711569
init($$);
1572-
auto &scope = PARSER.scopes.add_name(stack_expr($1).id(), "");
1570+
auto &scope = PARSER.scopes.add_name(stack_expr($1).id(), "", verilog_scopet::ENUM);
15731571
stack_expr($$).set(ID_base_name, scope.base_name());
15741572
stack_expr($$).set(ID_identifier, scope.identifier());
15751573
stack_expr($$).add(ID_value).swap(stack_expr($2));
@@ -2137,7 +2135,7 @@ function_declaration: TOK_FUNCTION lifetime_opt function_body_declaration
21372135
function_body_declaration:
21382136
function_data_type_or_implicit
21392137
function_identifier
2140-
{ push_scope(stack_expr($2).get(ID_identifier), "."); }
2138+
{ push_scope(stack_expr($2).get(ID_identifier), ".", verilog_scopet::FUNCTION); }
21412139
';'
21422140
tf_item_declaration_brace statement
21432141
TOK_ENDFUNCTION
@@ -2152,7 +2150,7 @@ function_body_declaration:
21522150
}
21532151
| function_data_type_or_implicit
21542152
function_identifier
2155-
{ push_scope(stack_expr($2).get(ID_identifier), "."); }
2153+
{ push_scope(stack_expr($2).get(ID_identifier), ".", verilog_scopet::FUNCTION); }
21562154
'(' tf_port_list_opt ')' ';'
21572155
tf_item_declaration_brace statement
21582156
TOK_ENDFUNCTION
@@ -2193,7 +2191,7 @@ function_prototype: TOK_FUNCTION data_type_or_void function_identifier
21932191

21942192
task_declaration:
21952193
TOK_TASK task_identifier
2196-
{ push_scope(stack_expr($2).get(ID_identifier), "."); }
2194+
{ push_scope(stack_expr($2).get(ID_identifier), ".", verilog_scopet::TASK); }
21972195
';'
21982196
tf_item_declaration_brace
21992197
statement_or_null TOK_ENDTASK
@@ -2205,7 +2203,7 @@ task_declaration:
22052203
pop_scope();
22062204
}
22072205
| TOK_TASK task_identifier
2208-
{ push_scope(stack_expr($2).get(ID_identifier), "."); }
2206+
{ push_scope(stack_expr($2).get(ID_identifier), ".", verilog_scopet::TASK); }
22092207
'(' tf_port_list_opt ')' ';'
22102208
tf_item_declaration_brace
22112209
statement_or_null TOK_ENDTASK
@@ -3385,7 +3383,7 @@ seq_block:
33853383
TOK_END
33863384
{ init($$, ID_block); swapop($$, $2); }
33873385
| TOK_BEGIN TOK_COLON block_identifier
3388-
{ push_scope(stack_expr($3).id(), "."); }
3386+
{ push_scope(stack_expr($3).id(), ".", verilog_scopet::BLOCK); }
33893387
block_item_declaration_or_statement_or_null_brace
33903388
TOK_END
33913389
{ init($$, ID_block);
@@ -4222,10 +4220,19 @@ part_select_range:
42224220

42234221
primary: primary_literal
42244222
| hierarchical_identifier_select
4225-
| package_scope hierarchical_identifier_select
4226-
{ init($$, ID_verilog_package_scope);
4223+
| package_scope
4224+
{
4225+
init($$, ID_verilog_package_scope);
4226+
// enter that scope
4227+
PARSER.scopes.enter_package_scope(stack_expr($1).id());
42274228
mto($$, $1);
4228-
mto($$, $2); }
4229+
}
4230+
hierarchical_identifier_select
4231+
{ $$ = $2;
4232+
mto($$, $3);
4233+
// exit the scope
4234+
pop_scope();
4235+
}
42294236
| concatenation
42304237
| multiple_concatenation
42314238
| function_subroutine_call
@@ -4426,7 +4433,7 @@ type_identifier: TOK_TYPE_IDENTIFIER
44264433
init($$, ID_typedef_type);
44274434
auto base_name = stack_expr($1).id();
44284435
stack_expr($$).set(ID_base_name, base_name);
4429-
stack_expr($$).set(ID_identifier, PARSER.scopes.current_scope->prefix+id2string(base_name));
4436+
stack_expr($$).set(ID_identifier, PARSER.scopes.current_scope().prefix+id2string(base_name));
44304437
}
44314438
;
44324439

src/verilog/scanner.l

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static void preprocessor()
6767
stack_expr(yyveriloglval).id(irep_id); \
6868
auto name = PARSER.scopes.lookup(irep_id); \
6969
return name == nullptr ? TOK_NON_TYPE_IDENTIFIER : \
70-
name->is_type ? TOK_TYPE_IDENTIFIER : \
70+
name->is_type() ? TOK_TYPE_IDENTIFIER : \
7171
TOK_NON_TYPE_IDENTIFIER; \
7272
}
7373
#define KEYWORD(s, x) \

src/verilog/verilog_scope.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Author: Daniel Kroening, [email protected]
1111
const verilog_scopet *verilog_scopest::lookup(irep_idt name) const
1212
{
1313
// we start from the current scope, and walk upwards to the root
14-
auto scope = current_scope;
14+
auto scope = &current_scope();
1515
while(scope != nullptr)
1616
{
1717
auto name_it = scope->scope_map.find(name);
@@ -24,3 +24,13 @@ const verilog_scopet *verilog_scopest::lookup(irep_idt name) const
2424
// not found, give up
2525
return nullptr;
2626
}
27+
28+
void verilog_scopest::enter_package_scope(irep_idt name)
29+
{
30+
// look in the global scope
31+
auto name_it = top_scope.scope_map.find(name);
32+
if(name_it == top_scope.scope_map.end())
33+
enter_scope(current_scope());
34+
else
35+
enter_scope(name_it->second); // found it
36+
}

src/verilog/verilog_scope.h

+61-14
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,40 @@ Author: Daniel Kroening, [email protected]
1616
// parser scopes and identifiers
1717
struct verilog_scopet
1818
{
19-
verilog_scopet() : parent(nullptr), prefix("Verilog::")
19+
using kindt = enum {
20+
GLOBAL,
21+
FILE,
22+
PACKAGE,
23+
MODULE,
24+
CLASS,
25+
ENUM,
26+
TASK,
27+
FUNCTION,
28+
BLOCK,
29+
TYPEDEF,
30+
OTHER
31+
};
32+
33+
verilog_scopet() : parent(nullptr), prefix("Verilog::"), kind(GLOBAL)
2034
{
2135
}
2236

2337
verilog_scopet(
2438
irep_idt _base_name,
2539
const std::string &separator,
26-
verilog_scopet *_parent)
40+
verilog_scopet *_parent,
41+
kindt _kind)
2742
: parent(_parent),
2843
__base_name(_base_name),
29-
prefix(id2string(_parent->prefix) + id2string(_base_name) + separator)
44+
prefix(id2string(_parent->prefix) + id2string(_base_name) + separator),
45+
kind(_kind)
3046
{
3147
}
3248

3349
verilog_scopet *parent = nullptr;
34-
bool is_type = false;
3550
irep_idt __base_name;
3651
std::string prefix;
52+
kindt kind;
3753

3854
irep_idt identifier() const
3955
{
@@ -46,6 +62,11 @@ struct verilog_scopet
4662
return __base_name;
4763
}
4864

65+
bool is_type() const
66+
{
67+
return kind == TYPEDEF;
68+
}
69+
4970
// sub-scopes
5071
using scope_mapt = std::map<irep_idt, verilog_scopet>;
5172
scope_mapt scope_map;
@@ -56,25 +77,51 @@ class verilog_scopest
5677
public:
5778
using scopet = verilog_scopet;
5879

59-
scopet top_scope, *current_scope = &top_scope;
80+
scopet top_scope;
6081

61-
scopet &add_name(irep_idt _base_name, const std::string &separator)
82+
scopet &add_name(
83+
irep_idt _base_name,
84+
const std::string &separator,
85+
scopet::kindt kind)
6286
{
63-
auto result = current_scope->scope_map.emplace(
64-
_base_name, scopet{_base_name, separator, current_scope});
87+
auto &current = current_scope();
88+
auto result = current.scope_map.emplace(
89+
_base_name, scopet{_base_name, separator, &current, kind});
6590
return result.first->second;
6691
}
6792

68-
// Create the given sub-scope of the current scope.
69-
void push_scope(irep_idt _base_name, const std::string &separator)
93+
// Scope stack
94+
std::vector<scopet *> scope_stack = {&top_scope};
95+
96+
scopet &current_scope() const
97+
{
98+
// We never pop the top scope
99+
PRECONDITION(!scope_stack.empty());
100+
return *scope_stack.back();
101+
}
102+
103+
// find the package scope with given base name, and enter it
104+
void enter_package_scope(irep_idt base_name);
105+
106+
void enter_scope(scopet &scope)
107+
{
108+
scope_stack.push_back(&scope);
109+
}
110+
111+
// Create the given sub-scope of the current scope, and enter it.
112+
void push_scope(
113+
irep_idt _base_name,
114+
const std::string &separator,
115+
scopet::kindt kind)
70116
{
71-
current_scope = &add_name(_base_name, separator);
117+
enter_scope(add_name(_base_name, separator, kind));
72118
}
73119

74120
void pop_scope()
75121
{
76-
PRECONDITION(current_scope->parent != nullptr);
77-
current_scope = current_scope->parent;
122+
// We never pop the top scope
123+
PRECONDITION(scope_stack.size() >= 2);
124+
scope_stack.pop_back();
78125
}
79126

80127
// Look up an identifier, starting from the current scope,
@@ -84,7 +131,7 @@ class verilog_scopest
84131
bool is_type(irep_idt base_name) const
85132
{
86133
auto scope_ptr = lookup(base_name);
87-
return scope_ptr == nullptr ? false : scope_ptr->is_type;
134+
return scope_ptr == nullptr ? false : scope_ptr->is_type();
88135
}
89136
};
90137

0 commit comments

Comments
 (0)