Parse program blocks / Fix module end-name syntax.
This commit is contained in:
parent
0aefcf9b48
commit
5880a3ad8f
112
parse.y
112
parse.y
|
|
@ -460,7 +460,7 @@ static void current_task_set_statement(vector<Statement*>*s)
|
||||||
%type <statement> udp_initial udp_init_opt
|
%type <statement> udp_initial udp_init_opt
|
||||||
%type <expr> udp_initial_expr_opt
|
%type <expr> udp_initial_expr_opt
|
||||||
|
|
||||||
%type <text> register_variable net_variable real_variable
|
%type <text> register_variable net_variable real_variable endname_opt
|
||||||
%type <perm_strings> register_variable_list net_variable_list
|
%type <perm_strings> register_variable_list net_variable_list
|
||||||
%type <perm_strings> real_variable_list list_of_identifiers
|
%type <perm_strings> real_variable_list list_of_identifiers
|
||||||
%type <port_list> list_of_port_identifiers
|
%type <port_list> list_of_port_identifiers
|
||||||
|
|
@ -535,6 +535,7 @@ static void current_task_set_statement(vector<Statement*>*s)
|
||||||
%type <specpath> specify_edge_path specify_edge_path_decl
|
%type <specpath> specify_edge_path specify_edge_path_decl
|
||||||
|
|
||||||
%type <int_val> atom2_type
|
%type <int_val> atom2_type
|
||||||
|
%type <int_val> module_start module_end
|
||||||
|
|
||||||
%token K_TAND
|
%token K_TAND
|
||||||
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
||||||
|
|
@ -2680,40 +2681,83 @@ local_timeunit_prec_decl
|
||||||
section, with optional ports, then an optional list of module
|
section, with optional ports, then an optional list of module
|
||||||
items, and finally an end marker. */
|
items, and finally an end marker. */
|
||||||
|
|
||||||
module : attribute_list_opt module_start IDENTIFIER
|
module
|
||||||
{ pform_startmodule($3, @2.text, @2.first_line, $1); }
|
: attribute_list_opt module_start IDENTIFIER
|
||||||
module_parameter_port_list_opt
|
{ pform_startmodule($3, @2.text, @2.first_line, $1); }
|
||||||
module_port_list_opt
|
module_parameter_port_list_opt
|
||||||
module_attribute_foreign ';'
|
module_port_list_opt
|
||||||
{ pform_module_set_ports($6); }
|
module_attribute_foreign ';'
|
||||||
local_timeunit_prec_decl_opt
|
{ pform_module_set_ports($6); }
|
||||||
{ have_timeunit_decl = true; // Every thing past here is
|
local_timeunit_prec_decl_opt
|
||||||
have_timeprec_decl = true; // a check!
|
{ have_timeunit_decl = true; // Every thing past here is
|
||||||
pform_check_timeunit_prec();
|
have_timeprec_decl = true; // a check!
|
||||||
}
|
pform_check_timeunit_prec();
|
||||||
module_item_list_opt
|
}
|
||||||
K_endmodule
|
module_item_list_opt
|
||||||
{ Module::UCDriveType ucd;
|
module_end endname_opt
|
||||||
switch (uc_drive) {
|
{ Module::UCDriveType ucd;
|
||||||
case UCD_NONE:
|
// The lexor detected `unconnected_drive directives and
|
||||||
default:
|
// marked what it found in the uc_drive variable. Use that
|
||||||
ucd = Module::UCD_NONE;
|
// to generate a UCD flag for the module.
|
||||||
break;
|
switch (uc_drive) {
|
||||||
case UCD_PULL0:
|
case UCD_NONE:
|
||||||
ucd = Module::UCD_PULL0;
|
default:
|
||||||
break;
|
ucd = Module::UCD_NONE;
|
||||||
case UCD_PULL1:
|
break;
|
||||||
ucd = Module::UCD_PULL1;
|
case UCD_PULL0:
|
||||||
break;
|
ucd = Module::UCD_PULL0;
|
||||||
}
|
break;
|
||||||
pform_endmodule($3, in_celldefine, ucd);
|
case UCD_PULL1:
|
||||||
delete[]$3;
|
ucd = Module::UCD_PULL1;
|
||||||
have_timeunit_decl = false; // We will allow decls again.
|
break;
|
||||||
have_timeprec_decl = false;
|
}
|
||||||
}
|
// Check that program/endprogram and module/endmodule
|
||||||
;
|
// keywords match.
|
||||||
|
if ($2 != $13) {
|
||||||
|
switch ($2) {
|
||||||
|
case K_module:
|
||||||
|
yyerror(@13, "error: module not closed by endmodule.");
|
||||||
|
break;
|
||||||
|
case K_program:
|
||||||
|
yyerror(@13, "error: program not closed by endprogram.");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($14 && (strcmp($3,$14) != 0)) {
|
||||||
|
yyerror(@14, "error: End name doesn't match module/program name");
|
||||||
|
}
|
||||||
|
if ($2 == K_program) {
|
||||||
|
yyerror(@2, "sorry: Program blocks not supported yet.");
|
||||||
|
}
|
||||||
|
pform_endmodule($3, in_celldefine, ucd);
|
||||||
|
delete[]$3;
|
||||||
|
if ($14) delete[]$14;
|
||||||
|
have_timeunit_decl = false; // We will allow decls again.
|
||||||
|
have_timeprec_decl = false;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
module_start : K_module | K_macromodule ;
|
/* Modules start with module/macromodule or program keyword, and end
|
||||||
|
with the endmodule or endprogram keyword. The syntax for modules
|
||||||
|
and programs is almost identical, so let semantics sort out the
|
||||||
|
differences. */
|
||||||
|
module_start
|
||||||
|
: K_module { $$ = K_module; }
|
||||||
|
| K_macromodule { $$ = K_module; }
|
||||||
|
| K_program { $$ = K_program; }
|
||||||
|
;
|
||||||
|
|
||||||
|
module_end
|
||||||
|
: K_endmodule { $$ = K_module; }
|
||||||
|
| K_endprogram { $$ = K_program; }
|
||||||
|
;
|
||||||
|
|
||||||
|
endname_opt
|
||||||
|
: ':' IDENTIFIER { $$ = $2; }
|
||||||
|
| { $$ = 0; }
|
||||||
|
;
|
||||||
|
|
||||||
module_attribute_foreign
|
module_attribute_foreign
|
||||||
: K_PSTAR IDENTIFIER K_integer IDENTIFIER '=' STRING ';' K_STARP { $$ = 0; }
|
: K_PSTAR IDENTIFIER K_integer IDENTIFIER '=' STRING ';' K_STARP { $$ = 0; }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue