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:
parent
cc9d5f90e0
commit
588409389e
46
parse.y
46
parse.y
|
|
@ -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);
|
||||||
|
|
|
||||||
16
pform.cc
16
pform.cc
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue