SV: Add support for var decls in unnamed begin/end blocks.

SystemVerilog allows variables to be declared in unnamed begin/end
blocks. This patch adds support for this functionality.
This commit is contained in:
Cary R 2014-07-22 18:55:24 -07:00
parent cc9d5f90e0
commit 588409389e
2 changed files with 54 additions and 8 deletions

46
parse.y
View File

@ -535,7 +535,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
/* Support some meta-comments as pragmas. */ /* Support some meta-comments as pragmas. */
%token K_MC_TRANSLATE_ON K_MC_TRANSLATE_OFF %token K_MC_TRANSLATE_ON K_MC_TRANSLATE_OFF
%type <flag> from_exclude %type <flag> from_exclude block_item_decls_opt
%type <number> number pos_neg_number %type <number> number pos_neg_number
%type <flag> signing unsigned_signed_opt signed_unsigned_opt %type <flag> signing unsigned_signed_opt signed_unsigned_opt
%type <flag> K_automatic_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt %type <flag> K_automatic_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt
@ -2170,8 +2170,8 @@ block_item_decls
; ;
block_item_decls_opt block_item_decls_opt
: block_item_decls : block_item_decls { $$ = true; }
| | { $$ = false; }
; ;
/* Type declarations are parsed here. The rule actions call pform /* Type declarations are parsed here. The rule actions call pform
@ -5629,11 +5629,40 @@ statement_item /* This is roughly statement_item in the LRM */
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
$$ = tmp; $$ = tmp;
} }
| K_begin statement_or_null_list K_end /* In SystemVerilog an unnamed block can contain variable declarations. */
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ); | K_begin
{ PBlock*tmp = pform_push_block_scope(0, PBlock::BL_SEQ);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
tmp->set_statement(*$2); current_block_stack.push(tmp);
delete $2; }
block_item_decls_opt
{ if ($3) {
if (! gn_system_verilog()) {
yyerror("error: Variable declaration in unnamed block "
"requires SystemVerilog.");
}
} else {
/* If there are no declarations in the scope then just delete it. */
pform_pop_scope();
assert(! current_block_stack.empty());
PBlock*tmp = current_block_stack.top();
current_block_stack.pop();
delete tmp;
}
}
statement_or_null_list K_end
{ PBlock*tmp;
if ($3) {
pform_pop_scope();
assert(! current_block_stack.empty());
tmp = current_block_stack.top();
current_block_stack.pop();
} else {
tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, @1);
}
if ($5) tmp->set_statement(*$5);
delete $5;
$$ = tmp; $$ = tmp;
} }
| K_begin ':' IDENTIFIER | K_begin ':' IDENTIFIER
@ -5674,6 +5703,9 @@ statement_item /* This is roughly statement_item in the LRM */
$$ = tmp; $$ = tmp;
} }
| K_fork statement_or_null_list join_keyword | K_fork statement_or_null_list join_keyword
// HERE
// Create an anonymous scope and if no definitions are found then delete
// the scope and use a simple block.
{ PBlock*tmp = new PBlock($3); { PBlock*tmp = new PBlock($3);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
tmp->set_statement(*$2); tmp->set_statement(*$2);

View File

@ -242,6 +242,11 @@ static list<Module*>pform_cur_module;
bool pform_library_flag = false; bool pform_library_flag = false;
/*
* Give each unnamed block that has a variable declaration a unique name.
*/
static unsigned scope_unnamed_block_with_decl = 1;
/* increment this for generate schemes within a module, and set it /* increment this for generate schemes within a module, and set it
to zero when a new module starts. */ to zero when a new module starts. */
static unsigned scope_generate_counter = 1; static unsigned scope_generate_counter = 1;
@ -439,7 +444,16 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt) PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
{ {
perm_string block_name = lex_strings.make(name); perm_string block_name;
if (name) block_name = lex_strings.make(name);
else {
// Create a unique name for this unnamed block.
char tmp[32];
snprintf(tmp, sizeof tmp, "$unm_blk_%u",
scope_unnamed_block_with_decl);
block_name = lex_strings.make(tmp);
scope_unnamed_block_with_decl += 1;
}
PBlock*block = new PBlock(block_name, lexical_scope, bt); PBlock*block = new PBlock(block_name, lexical_scope, bt);
lexical_scope = block; lexical_scope = block;