Added support for default subroutine lifetimes (SystemVerilog).
(cherry picked from commit 6e718c2e0c)
This commit is contained in:
parent
4aef636559
commit
7d2eeb0137
3
PScope.h
3
PScope.h
|
|
@ -57,6 +57,9 @@ class LexicalScope {
|
||||||
// A virtual destructor is so that dynamic_cast can work.
|
// A virtual destructor is so that dynamic_cast can work.
|
||||||
virtual ~LexicalScope() { }
|
virtual ~LexicalScope() { }
|
||||||
|
|
||||||
|
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
|
||||||
|
lifetime_t default_lifetime;
|
||||||
|
|
||||||
struct range_t {
|
struct range_t {
|
||||||
// True if this is an exclude
|
// True if this is an exclude
|
||||||
bool exclude_flag;
|
bool exclude_flag;
|
||||||
|
|
|
||||||
91
parse.y
91
parse.y
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
%{
|
%{
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -452,6 +452,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
|
|
||||||
PSpecPath* specpath;
|
PSpecPath* specpath;
|
||||||
list<index_component_t> *dimensions;
|
list<index_component_t> *dimensions;
|
||||||
|
|
||||||
|
LexicalScope::lifetime_t lifetime;
|
||||||
};
|
};
|
||||||
|
|
||||||
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
|
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
|
||||||
|
|
@ -560,7 +562,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
%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> import_export
|
%type <flag> import_export
|
||||||
%type <flag> K_automatic_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt
|
%type <flag> K_packed_opt K_reg_opt K_static_opt K_virtual_opt
|
||||||
%type <flag> udp_reg_opt edge_operator
|
%type <flag> udp_reg_opt edge_operator
|
||||||
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||||
%type <letter> udp_input_sym udp_output_sym
|
%type <letter> udp_input_sym udp_output_sym
|
||||||
|
|
@ -665,6 +667,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
%type <int_val> atom2_type
|
%type <int_val> atom2_type
|
||||||
%type <int_val> module_start module_end
|
%type <int_val> module_start module_end
|
||||||
|
|
||||||
|
%type <lifetime> lifetime_opt
|
||||||
|
|
||||||
%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
|
||||||
%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
|
%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
|
||||||
|
|
@ -724,17 +728,17 @@ block_identifier_opt /* */
|
||||||
;
|
;
|
||||||
|
|
||||||
class_declaration /* IEEE1800-2005: A.1.2 */
|
class_declaration /* IEEE1800-2005: A.1.2 */
|
||||||
: K_virtual_opt K_class class_identifier class_declaration_extends_opt ';'
|
: K_virtual_opt K_class lifetime_opt class_identifier class_declaration_extends_opt ';'
|
||||||
{ pform_start_class_declaration(@2, $3, $4.type, $4.exprs); }
|
{ pform_start_class_declaration(@2, $4, $5.type, $5.exprs, $3); }
|
||||||
class_items_opt K_endclass
|
class_items_opt K_endclass
|
||||||
{ // Process a class.
|
{ // Process a class.
|
||||||
pform_end_class_declaration(@8);
|
pform_end_class_declaration(@9);
|
||||||
}
|
}
|
||||||
class_declaration_endlabel_opt
|
class_declaration_endlabel_opt
|
||||||
{ // Wrap up the class.
|
{ // Wrap up the class.
|
||||||
if ($10 && $3 && $3->name != $10) {
|
if ($11 && $4 && $4->name != $11) {
|
||||||
yyerror(@10, "error: Class end label doesn't match class name.");
|
yyerror(@11, "error: Class end label doesn't match class name.");
|
||||||
delete[]$10;
|
delete[]$11;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
@ -1194,7 +1198,7 @@ for_step /* IEEE1800-2005: A.6.8 */
|
||||||
definitions in the func_body to take on the scope of the function
|
definitions in the func_body to take on the scope of the function
|
||||||
instead of the module. */
|
instead of the module. */
|
||||||
function_declaration /* IEEE1800-2005: A.2.6 */
|
function_declaration /* IEEE1800-2005: A.2.6 */
|
||||||
: K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER ';'
|
: K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER ';'
|
||||||
{ assert(current_function == 0);
|
{ assert(current_function == 0);
|
||||||
current_function = pform_push_function_scope(@1, $4, $2);
|
current_function = pform_push_function_scope(@1, $4, $2);
|
||||||
}
|
}
|
||||||
|
|
@ -1215,7 +1219,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
||||||
"function name");
|
"function name");
|
||||||
}
|
}
|
||||||
if (! gn_system_verilog()) {
|
if (! gn_system_verilog()) {
|
||||||
yyerror(@11, "error: Function end label require "
|
yyerror(@11, "error: Function end labels require "
|
||||||
"SystemVerilog.");
|
"SystemVerilog.");
|
||||||
}
|
}
|
||||||
delete[]$11;
|
delete[]$11;
|
||||||
|
|
@ -1223,7 +1227,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
||||||
delete[]$4;
|
delete[]$4;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER
|
| K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER
|
||||||
{ assert(current_function == 0);
|
{ assert(current_function == 0);
|
||||||
current_function = pform_push_function_scope(@1, $4, $2);
|
current_function = pform_push_function_scope(@1, $4, $2);
|
||||||
}
|
}
|
||||||
|
|
@ -1259,7 +1263,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
||||||
|
|
||||||
/* Detect and recover from some errors. */
|
/* Detect and recover from some errors. */
|
||||||
|
|
||||||
| K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER error K_endfunction
|
| K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER error K_endfunction
|
||||||
{ /* */
|
{ /* */
|
||||||
if (current_function) {
|
if (current_function) {
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
|
|
@ -1365,6 +1369,12 @@ jump_statement /* IEEE1800-2005: A.6.5 */
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
lifetime_opt /* IEEE1800-2005: A.2.1.3 */
|
||||||
|
: K_automatic { $$ = LexicalScope::AUTOMATIC; }
|
||||||
|
| K_static { $$ = LexicalScope::STATIC; }
|
||||||
|
| { $$ = LexicalScope::INHERITED; }
|
||||||
|
;
|
||||||
|
|
||||||
/* Loop statements are kinds of statements. */
|
/* Loop statements are kinds of statements. */
|
||||||
|
|
||||||
loop_statement /* IEEE1800-2005: A.6.8 */
|
loop_statement /* IEEE1800-2005: A.6.8 */
|
||||||
|
|
@ -1704,20 +1714,20 @@ open_range_list /* IEEE1800-2005 A.2.11 */
|
||||||
;
|
;
|
||||||
|
|
||||||
package_declaration /* IEEE1800-2005 A.1.2 */
|
package_declaration /* IEEE1800-2005 A.1.2 */
|
||||||
: K_package IDENTIFIER ';'
|
: K_package lifetime_opt IDENTIFIER ';'
|
||||||
{ pform_start_package_declaration(@1, $2);
|
{ pform_start_package_declaration(@1, $3, $2);
|
||||||
}
|
}
|
||||||
package_item_list_opt
|
package_item_list_opt
|
||||||
K_endpackage endlabel_opt
|
K_endpackage endlabel_opt
|
||||||
{ pform_end_package_declaration(@1);
|
{ pform_end_package_declaration(@1);
|
||||||
// If an end label is present make sure it match the package name.
|
// If an end label is present make sure it match the package name.
|
||||||
if ($7) {
|
if ($8) {
|
||||||
if (strcmp($2,$7) != 0) {
|
if (strcmp($3,$8) != 0) {
|
||||||
yyerror(@7, "error: End label doesn't match package name");
|
yyerror(@8, "error: End label doesn't match package name");
|
||||||
}
|
}
|
||||||
delete[]$7;
|
delete[]$8;
|
||||||
}
|
}
|
||||||
delete[]$2;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -1896,7 +1906,7 @@ streaming_concatenation /* IEEE1800-2005: A.8.1 */
|
||||||
|
|
||||||
task_declaration /* IEEE1800-2005: A.2.7 */
|
task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
|
|
||||||
: K_task K_automatic_opt IDENTIFIER ';'
|
: K_task lifetime_opt IDENTIFIER ';'
|
||||||
{ assert(current_task == 0);
|
{ assert(current_task == 0);
|
||||||
current_task = pform_push_task_scope(@1, $3, $2);
|
current_task = pform_push_task_scope(@1, $3, $2);
|
||||||
}
|
}
|
||||||
|
|
@ -1909,7 +1919,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
current_task = 0;
|
current_task = 0;
|
||||||
if ($7 && $7->size() > 1 && !gn_system_verilog()) {
|
if ($7 && $7->size() > 1 && !gn_system_verilog()) {
|
||||||
yyerror(@7, "error: Task body with multiple statements requres SystemVerilog.");
|
yyerror(@7, "error: Task body with multiple statements requires SystemVerilog.");
|
||||||
}
|
}
|
||||||
delete $7;
|
delete $7;
|
||||||
}
|
}
|
||||||
|
|
@ -1932,7 +1942,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_task K_automatic_opt IDENTIFIER '('
|
| K_task lifetime_opt IDENTIFIER '('
|
||||||
{ assert(current_task == 0);
|
{ assert(current_task == 0);
|
||||||
current_task = pform_push_task_scope(@1, $3, $2);
|
current_task = pform_push_task_scope(@1, $3, $2);
|
||||||
}
|
}
|
||||||
|
|
@ -1966,7 +1976,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_task K_automatic_opt IDENTIFIER '(' ')' ';'
|
| K_task lifetime_opt IDENTIFIER '(' ')' ';'
|
||||||
{ assert(current_task == 0);
|
{ assert(current_task == 0);
|
||||||
current_task = pform_push_task_scope(@1, $3, $2);
|
current_task = pform_push_task_scope(@1, $3, $2);
|
||||||
}
|
}
|
||||||
|
|
@ -1983,7 +1993,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
current_task = 0;
|
current_task = 0;
|
||||||
if ($9->size() > 1 && !gn_system_verilog()) {
|
if ($9->size() > 1 && !gn_system_verilog()) {
|
||||||
yyerror(@9, "error: Task body with multiple statements requres SystemVerilog.");
|
yyerror(@9, "error: Task body with multiple statements requires SystemVerilog.");
|
||||||
}
|
}
|
||||||
delete $9;
|
delete $9;
|
||||||
}
|
}
|
||||||
|
|
@ -2006,7 +2016,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_task K_automatic_opt IDENTIFIER error K_endtask
|
| K_task lifetime_opt IDENTIFIER error K_endtask
|
||||||
{
|
{
|
||||||
assert(current_task == 0);
|
assert(current_task == 0);
|
||||||
}
|
}
|
||||||
|
|
@ -4377,13 +4387,13 @@ local_timeunit_prec_decl2
|
||||||
items, and finally an end marker. */
|
items, and finally an end marker. */
|
||||||
|
|
||||||
module
|
module
|
||||||
: attribute_list_opt module_start IDENTIFIER
|
: attribute_list_opt module_start lifetime_opt IDENTIFIER
|
||||||
{ pform_startmodule(@2, $3, $2==K_program, $2==K_interface, $1); }
|
{ pform_startmodule(@2, $4, $2==K_program, $2==K_interface, $3, $1); }
|
||||||
module_package_import_list_opt
|
module_package_import_list_opt
|
||||||
module_parameter_port_list_opt
|
module_parameter_port_list_opt
|
||||||
module_port_list_opt
|
module_port_list_opt
|
||||||
module_attribute_foreign ';'
|
module_attribute_foreign ';'
|
||||||
{ pform_module_set_ports($7); }
|
{ pform_module_set_ports($8); }
|
||||||
local_timeunit_prec_decl_opt
|
local_timeunit_prec_decl_opt
|
||||||
{ have_timeunit_decl = true; // Every thing past here is
|
{ have_timeunit_decl = true; // Every thing past here is
|
||||||
have_timeprec_decl = true; // a check!
|
have_timeprec_decl = true; // a check!
|
||||||
|
|
@ -4409,22 +4419,22 @@ module
|
||||||
}
|
}
|
||||||
// Check that program/endprogram and module/endmodule
|
// Check that program/endprogram and module/endmodule
|
||||||
// keywords match.
|
// keywords match.
|
||||||
if ($2 != $14) {
|
if ($2 != $15) {
|
||||||
switch ($2) {
|
switch ($2) {
|
||||||
case K_module:
|
case K_module:
|
||||||
yyerror(@14, "error: module not closed by endmodule.");
|
yyerror(@15, "error: module not closed by endmodule.");
|
||||||
break;
|
break;
|
||||||
case K_program:
|
case K_program:
|
||||||
yyerror(@14, "error: program not closed by endprogram.");
|
yyerror(@15, "error: program not closed by endprogram.");
|
||||||
break;
|
break;
|
||||||
case K_interface:
|
case K_interface:
|
||||||
yyerror(@14, "error: interface not closed by endinterface.");
|
yyerror(@15, "error: interface not closed by endinterface.");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pform_endmodule($3, in_celldefine, ucd);
|
pform_endmodule($4, in_celldefine, ucd);
|
||||||
have_timeunit_decl = false; // We will allow decls again.
|
have_timeunit_decl = false; // We will allow decls again.
|
||||||
have_timeprec_decl = false;
|
have_timeprec_decl = false;
|
||||||
}
|
}
|
||||||
|
|
@ -4434,19 +4444,19 @@ module
|
||||||
// endlabel_opt but still have the pform_endmodule() called
|
// endlabel_opt but still have the pform_endmodule() called
|
||||||
// early enough that the lexor can know we are outside the
|
// early enough that the lexor can know we are outside the
|
||||||
// module.
|
// module.
|
||||||
if ($16) {
|
if ($17) {
|
||||||
if (strcmp($3,$16) != 0) {
|
if (strcmp($4,$17) != 0) {
|
||||||
switch ($2) {
|
switch ($2) {
|
||||||
case K_module:
|
case K_module:
|
||||||
yyerror(@16, "error: End label doesn't match "
|
yyerror(@17, "error: End label doesn't match "
|
||||||
"module name.");
|
"module name.");
|
||||||
break;
|
break;
|
||||||
case K_program:
|
case K_program:
|
||||||
yyerror(@16, "error: End label doesn't match "
|
yyerror(@17, "error: End label doesn't match "
|
||||||
"program name.");
|
"program name.");
|
||||||
break;
|
break;
|
||||||
case K_interface:
|
case K_interface:
|
||||||
yyerror(@16, "error: End label doesn't match "
|
yyerror(@17, "error: End label doesn't match "
|
||||||
"interface name.");
|
"interface name.");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -4457,9 +4467,9 @@ module
|
||||||
yyerror(@8, "error: Module end labels require "
|
yyerror(@8, "error: Module end labels require "
|
||||||
"SystemVerilog.");
|
"SystemVerilog.");
|
||||||
}
|
}
|
||||||
delete[]$16;
|
delete[]$17;
|
||||||
}
|
}
|
||||||
delete[]$3;
|
delete[]$4;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -6782,7 +6792,6 @@ udp_primitive
|
||||||
presence is significant. This is a fairly common pattern so
|
presence is significant. This is a fairly common pattern so
|
||||||
collect those rules here. */
|
collect those rules here. */
|
||||||
|
|
||||||
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false; } ;
|
|
||||||
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
|
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
|
||||||
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
||||||
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
|
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
|
||||||
|
|
|
||||||
55
pform.cc
55
pform.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -312,12 +312,29 @@ static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
|
||||||
*/
|
*/
|
||||||
static LexicalScope* lexical_scope = 0;
|
static LexicalScope* lexical_scope = 0;
|
||||||
|
|
||||||
|
LexicalScope* pform_peek_scope(void)
|
||||||
|
{
|
||||||
|
assert(lexical_scope);
|
||||||
|
return lexical_scope;
|
||||||
|
}
|
||||||
|
|
||||||
void pform_pop_scope()
|
void pform_pop_scope()
|
||||||
{
|
{
|
||||||
assert(lexical_scope);
|
assert(lexical_scope);
|
||||||
lexical_scope = lexical_scope->parent_scope();
|
lexical_scope = lexical_scope->parent_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime)
|
||||||
|
{
|
||||||
|
if (lifetime != LexicalScope::INHERITED)
|
||||||
|
return lifetime;
|
||||||
|
|
||||||
|
if (lexical_scope != 0)
|
||||||
|
return lexical_scope->default_lifetime;
|
||||||
|
|
||||||
|
return LexicalScope::STATIC;
|
||||||
|
}
|
||||||
|
|
||||||
static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
|
static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
|
||||||
{
|
{
|
||||||
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
|
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
|
||||||
|
|
@ -328,15 +345,11 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
|
||||||
return scopex;
|
return scopex;
|
||||||
}
|
}
|
||||||
|
|
||||||
LexicalScope* pform_peek_scope(void)
|
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
|
||||||
{
|
LexicalScope::lifetime_t lifetime)
|
||||||
assert(lexical_scope);
|
|
||||||
return lexical_scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
|
|
||||||
{
|
{
|
||||||
PClass*class_scope = new PClass(name, lexical_scope);
|
PClass*class_scope = new PClass(name, lexical_scope);
|
||||||
|
class_scope->default_lifetime = find_lifetime(lifetime);
|
||||||
FILE_NAME(class_scope, loc);
|
FILE_NAME(class_scope, loc);
|
||||||
|
|
||||||
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
||||||
|
|
@ -364,20 +377,27 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
|
||||||
return class_scope;
|
return class_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name)
|
PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name,
|
||||||
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
PPackage*pkg_scope = new PPackage(name, lexical_scope);
|
PPackage*pkg_scope = new PPackage(name, lexical_scope);
|
||||||
|
pkg_scope->default_lifetime = find_lifetime(lifetime);
|
||||||
FILE_NAME(pkg_scope, loc);
|
FILE_NAME(pkg_scope, loc);
|
||||||
|
|
||||||
lexical_scope = pkg_scope;
|
lexical_scope = pkg_scope;
|
||||||
return pkg_scope;
|
return pkg_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
|
PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
|
||||||
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
perm_string task_name = lex_strings.make(name);
|
perm_string task_name = lex_strings.make(name);
|
||||||
|
|
||||||
|
LexicalScope::lifetime_t default_lifetime = find_lifetime(lifetime);
|
||||||
|
bool is_auto = default_lifetime == LexicalScope::AUTOMATIC;
|
||||||
|
|
||||||
PTask*task = new PTask(task_name, lexical_scope, is_auto);
|
PTask*task = new PTask(task_name, lexical_scope, is_auto);
|
||||||
|
task->default_lifetime = default_lifetime;
|
||||||
FILE_NAME(task, loc);
|
FILE_NAME(task, loc);
|
||||||
|
|
||||||
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
||||||
|
|
@ -424,11 +444,15 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
|
||||||
}
|
}
|
||||||
|
|
||||||
PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
|
PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
|
||||||
bool is_auto)
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
perm_string func_name = lex_strings.make(name);
|
perm_string func_name = lex_strings.make(name);
|
||||||
|
|
||||||
|
LexicalScope::lifetime_t default_lifetime = find_lifetime(lifetime);
|
||||||
|
bool is_auto = default_lifetime == LexicalScope::AUTOMATIC;
|
||||||
|
|
||||||
PFunction*func = new PFunction(func_name, lexical_scope, is_auto);
|
PFunction*func = new PFunction(func_name, lexical_scope, is_auto);
|
||||||
|
func->default_lifetime = default_lifetime;
|
||||||
FILE_NAME(func, loc);
|
FILE_NAME(func, loc);
|
||||||
|
|
||||||
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
||||||
|
|
@ -1131,6 +1155,7 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||||
|
|
||||||
void pform_startmodule(const struct vlltype&loc, const char*name,
|
void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
bool program_block, bool is_interface,
|
bool program_block, bool is_interface,
|
||||||
|
LexicalScope::lifetime_t lifetime,
|
||||||
list<named_pexpr_t>*attr)
|
list<named_pexpr_t>*attr)
|
||||||
{
|
{
|
||||||
if (! pform_cur_module.empty() && !gn_system_verilog()) {
|
if (! pform_cur_module.empty() && !gn_system_verilog()) {
|
||||||
|
|
@ -1139,6 +1164,12 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lifetime != LexicalScope::INHERITED && !gn_system_verilog()) {
|
||||||
|
cerr << loc << ": error: Default subroutine lifetimes "
|
||||||
|
"require SystemVerilog." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (gn_system_verilog() && ! pform_cur_module.empty()) {
|
if (gn_system_verilog() && ! pform_cur_module.empty()) {
|
||||||
if (pform_cur_module.front()->program_block) {
|
if (pform_cur_module.front()->program_block) {
|
||||||
cerr << loc << ": error: module, program, or interface "
|
cerr << loc << ": error: module, program, or interface "
|
||||||
|
|
@ -1158,6 +1189,8 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
Module*cur_module = new Module(lexical_scope, lex_name);
|
Module*cur_module = new Module(lexical_scope, lex_name);
|
||||||
cur_module->program_block = program_block;
|
cur_module->program_block = program_block;
|
||||||
cur_module->is_interface = is_interface;
|
cur_module->is_interface = is_interface;
|
||||||
|
cur_module->default_lifetime = find_lifetime(lifetime);
|
||||||
|
|
||||||
/* Set the local time unit/precision to the global value. */
|
/* Set the local time unit/precision to the global value. */
|
||||||
cur_module->time_unit = pform_time_unit;
|
cur_module->time_unit = pform_time_unit;
|
||||||
cur_module->time_precision = pform_time_prec;
|
cur_module->time_precision = pform_time_prec;
|
||||||
|
|
|
||||||
24
pform.h
24
pform.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_pform_H
|
#ifndef IVL_pform_H
|
||||||
#define IVL_pform_H
|
#define IVL_pform_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -163,6 +163,7 @@ extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_ty
|
||||||
*/
|
*/
|
||||||
extern void pform_startmodule(const struct vlltype&loc, const char*name,
|
extern void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
bool program_block, bool is_interface,
|
bool program_block, bool is_interface,
|
||||||
|
LexicalScope::lifetime_t lifetime,
|
||||||
list<named_pexpr_t>*attr);
|
list<named_pexpr_t>*attr);
|
||||||
extern void pform_check_timeunit_prec();
|
extern void pform_check_timeunit_prec();
|
||||||
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
||||||
|
|
@ -186,7 +187,8 @@ extern void pform_endmodule(const char*, bool inside_celldefine,
|
||||||
extern void pform_start_class_declaration(const struct vlltype&loc,
|
extern void pform_start_class_declaration(const struct vlltype&loc,
|
||||||
class_type_t*type,
|
class_type_t*type,
|
||||||
data_type_t*base_type,
|
data_type_t*base_type,
|
||||||
std::list<PExpr*>*base_exprs);
|
std::list<PExpr*>*base_exprs,
|
||||||
|
LexicalScope::lifetime_t lifetime);
|
||||||
extern void pform_class_property(const struct vlltype&loc,
|
extern void pform_class_property(const struct vlltype&loc,
|
||||||
property_qualifier_t pq,
|
property_qualifier_t pq,
|
||||||
data_type_t*data_type,
|
data_type_t*data_type,
|
||||||
|
|
@ -211,7 +213,8 @@ extern void pform_make_udp(perm_string name,
|
||||||
* Package related functions.
|
* Package related functions.
|
||||||
*/
|
*/
|
||||||
extern void pform_start_package_declaration(const struct vlltype&loc,
|
extern void pform_start_package_declaration(const struct vlltype&loc,
|
||||||
const char*type);
|
const char*type,
|
||||||
|
LexicalScope::lifetime_t lifetime);
|
||||||
extern void pform_end_package_declaration(const struct vlltype&loc);
|
extern void pform_end_package_declaration(const struct vlltype&loc);
|
||||||
extern void pform_package_import(const struct vlltype&loc,
|
extern void pform_package_import(const struct vlltype&loc,
|
||||||
PPackage*pkg, const char*ident);
|
PPackage*pkg, const char*ident);
|
||||||
|
|
@ -246,13 +249,20 @@ extern void pform_pop_scope();
|
||||||
*/
|
*/
|
||||||
extern LexicalScope* pform_peek_scope();
|
extern LexicalScope* pform_peek_scope();
|
||||||
|
|
||||||
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name);
|
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
|
||||||
|
LexicalScope::lifetime_t lifetime);
|
||||||
|
|
||||||
extern PFunction*pform_push_constructor_scope(const struct vlltype&loc);
|
extern PFunction*pform_push_constructor_scope(const struct vlltype&loc);
|
||||||
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name);
|
|
||||||
|
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name,
|
||||||
|
LexicalScope::lifetime_t lifetime);
|
||||||
|
|
||||||
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
|
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
|
||||||
bool is_auto);
|
LexicalScope::lifetime_t lifetime);
|
||||||
|
|
||||||
extern PFunction*pform_push_function_scope(const struct vlltype&loc, const char*name,
|
extern PFunction*pform_push_function_scope(const struct vlltype&loc, const char*name,
|
||||||
bool is_auto);
|
LexicalScope::lifetime_t lifetime);
|
||||||
|
|
||||||
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
|
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
|
||||||
|
|
||||||
extern void pform_put_behavior_in_scope(AProcess*proc);
|
extern void pform_put_behavior_in_scope(AProcess*proc);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2013 Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2013 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -35,12 +35,13 @@ map<perm_string,PPackage*> pform_packages;
|
||||||
|
|
||||||
static PPackage*pform_cur_package = 0;
|
static PPackage*pform_cur_package = 0;
|
||||||
|
|
||||||
void pform_start_package_declaration(const struct vlltype&loc, const char*name)
|
void pform_start_package_declaration(const struct vlltype&loc, const char*name,
|
||||||
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
ivl_assert(loc, pform_cur_package == 0);
|
ivl_assert(loc, pform_cur_package == 0);
|
||||||
|
|
||||||
perm_string use_name = lex_strings.make(name);
|
perm_string use_name = lex_strings.make(name);
|
||||||
PPackage*pkg_scope = pform_push_package_scope(loc, use_name);
|
PPackage*pkg_scope = pform_push_package_scope(loc, use_name, lifetime);
|
||||||
FILE_NAME(pkg_scope, loc);
|
FILE_NAME(pkg_scope, loc);
|
||||||
pform_cur_package = pkg_scope;
|
pform_cur_package = pkg_scope;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -36,9 +36,13 @@ static PClass*pform_cur_class = 0;
|
||||||
* if present, are the "exprs" that would be passed to a chained
|
* if present, are the "exprs" that would be passed to a chained
|
||||||
* constructor.
|
* constructor.
|
||||||
*/
|
*/
|
||||||
void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, data_type_t*base_type, list<PExpr*>*base_exprs)
|
void pform_start_class_declaration(const struct vlltype&loc,
|
||||||
|
class_type_t*type,
|
||||||
|
data_type_t*base_type,
|
||||||
|
list<PExpr*>*base_exprs,
|
||||||
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
PClass*class_scope = pform_push_class_scope(loc, type->name);
|
PClass*class_scope = pform_push_class_scope(loc, type->name, lifetime);
|
||||||
class_scope->type = type;
|
class_scope->type = type;
|
||||||
assert(pform_cur_class == 0);
|
assert(pform_cur_class == 0);
|
||||||
pform_cur_class = class_scope;
|
pform_cur_class = class_scope;
|
||||||
|
|
@ -127,7 +131,7 @@ void pform_set_constructor_return(PFunction*net)
|
||||||
PFunction*pform_push_constructor_scope(const struct vlltype&loc)
|
PFunction*pform_push_constructor_scope(const struct vlltype&loc)
|
||||||
{
|
{
|
||||||
assert(pform_cur_class);
|
assert(pform_cur_class);
|
||||||
PFunction*func = pform_push_function_scope(loc, "new", true);
|
PFunction*func = pform_push_function_scope(loc, "new", LexicalScope::AUTOMATIC);
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,7 +142,7 @@ void pform_end_class_declaration(const struct vlltype&loc)
|
||||||
// If there were initializer statements, then collect them
|
// If there were initializer statements, then collect them
|
||||||
// into an implicit constructor function.
|
// into an implicit constructor function.
|
||||||
if (! pform_cur_class->type->initialize.empty()) {
|
if (! pform_cur_class->type->initialize.empty()) {
|
||||||
PFunction*func = pform_push_function_scope(loc, "new@", true);
|
PFunction*func = pform_push_function_scope(loc, "new@", LexicalScope::AUTOMATIC);
|
||||||
func->set_ports(0);
|
func->set_ports(0);
|
||||||
pform_set_constructor_return(func);
|
pform_set_constructor_return(func);
|
||||||
pform_set_this_class(loc, func);
|
pform_set_this_class(loc, func);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue