Parse array literals / rearrange task declaration rules.
This commit is contained in:
parent
8456252c0c
commit
6b4251626b
|
|
@ -191,7 +191,7 @@ TU [munpf]
|
|||
">>>=" { return K_RSS_EQ; }
|
||||
"++" { return K_INCR; }
|
||||
"--" {return K_DECR; }
|
||||
|
||||
"'{" { return K_LP; }
|
||||
|
||||
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
|
||||
and ")", but since I know that this is really ( * ), replace it
|
||||
|
|
|
|||
573
parse.y
573
parse.y
|
|
@ -355,7 +355,7 @@ static void current_task_set_statement(vector<Statement*>*s)
|
|||
%token <number> BASED_NUMBER DEC_NUMBER
|
||||
%token <realtime> REALTIME
|
||||
%token K_PLUS_EQ K_MINUS_EQ K_INCR K_DECR
|
||||
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_RSS K_SG
|
||||
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LP K_LS K_RS K_RSS K_SG
|
||||
/* K_CONTRIBUTE is <+, the contribution assign. */
|
||||
%token K_CONTRIBUTE
|
||||
%token K_PO_POS K_PO_NEG K_POW
|
||||
|
|
@ -473,13 +473,13 @@ static void current_task_set_statement(vector<Statement*>*s)
|
|||
%type <mports> list_of_ports module_port_list_opt list_of_port_declarations module_attribute_foreign
|
||||
%type <value_range> parameter_value_range parameter_value_ranges
|
||||
%type <value_range> parameter_value_ranges_opt
|
||||
%type <expr> task_port_decl_expr_opt value_range_expression
|
||||
%type <expr> tf_port_item_expr_opt value_range_expression
|
||||
|
||||
%type <named_pexprs> enum_name_list enum_name
|
||||
%type <enum_type> enum_data_type
|
||||
|
||||
%type <wires> task_item task_item_list task_item_list_opt
|
||||
%type <wires> task_port_item task_port_decl task_port_decl_list task_port_decl_list_opt
|
||||
%type <wires> task_port_item tf_port_item tf_port_list tf_port_list_opt
|
||||
%type <wires> function_item function_item_list
|
||||
|
||||
%type <named_pexpr> port_name parameter_value_byname
|
||||
|
|
@ -495,7 +495,7 @@ static void current_task_set_statement(vector<Statement*>*s)
|
|||
%type <gates> gate_instance_list
|
||||
|
||||
%type <pform_name> hierarchy_identifier
|
||||
%type <expr> expression expr_primary expr_mintypmax
|
||||
%type <expr> assignment_pattern expression expr_primary expr_mintypmax
|
||||
%type <expr> lpvalue
|
||||
%type <expr> branch_probe_expression
|
||||
%type <expr> delay_value delay_value_simple
|
||||
|
|
@ -511,7 +511,7 @@ static void current_task_set_statement(vector<Statement*>*s)
|
|||
%type <struct_members> struct_union_member_list
|
||||
%type <struct_type> struct_data_type
|
||||
|
||||
%type <exprs> range range_opt
|
||||
%type <exprs> range range_opt variable_dimension
|
||||
%type <dimensions> dimensions_opt dimensions
|
||||
%type <nettype> net_type var_type net_type_opt
|
||||
%type <gatetype> gatetype switchtype
|
||||
|
|
@ -574,6 +574,21 @@ source_file
|
|||
| source_file description
|
||||
;
|
||||
|
||||
assignment_pattern /* IEEE1800-2005: A.6.7.1 */
|
||||
: K_LP expression_list_proper '}'
|
||||
{ PEVoid*tmp = new PEVoid;
|
||||
FILE_NAME(tmp, @1);
|
||||
yyerror(@1, "sorry: Assignment patterns (array literals) not supported.");
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_LP '}'
|
||||
{ PEVoid*tmp = new PEVoid;
|
||||
FILE_NAME(tmp, @1);
|
||||
yyerror(@1, "sorry: Assignment patterns (array literals) not supported.");
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
class_declaration /* IEEE1800-2005: A.1.2 */
|
||||
: K_virtual_opt K_class IDENTIFIER ';'
|
||||
class_items_opt K_endclass endname_opt
|
||||
|
|
@ -599,13 +614,22 @@ class_items
|
|||
class_item /* IEEE1800-2005: A.1.8 */
|
||||
|
||||
/* class_constructor_declaration */
|
||||
: K_function K_new '(' task_port_decl_list_opt ')' ';'
|
||||
: K_function K_new '(' tf_port_list_opt ')' ';'
|
||||
statement_list_or_null
|
||||
K_endfunction endnew_opt
|
||||
{ yyerror(@1, "sorry: Class constructors not supported yet.");
|
||||
yyerrok;
|
||||
}
|
||||
|
||||
/* Class properties... */
|
||||
|
||||
| data_type list_of_variable_decl_assignments ';'
|
||||
|
||||
|
||||
/* Class methods... */
|
||||
|
||||
| task_declaration
|
||||
|
||||
/* Here are some error matching rules to help recover from various
|
||||
syntax errors within a class declaration. */
|
||||
|
||||
|
|
@ -657,6 +681,297 @@ real_or_realtime
|
|||
| K_realtime
|
||||
;
|
||||
|
||||
/* The task declaration rule matches the task declaration
|
||||
header, then pushes the function scope. This causes the
|
||||
definitions in the task_body to take on the scope of the task
|
||||
instead of the module. */
|
||||
|
||||
task_declaration /* IEEE1800-2005: A.2.7 */
|
||||
|
||||
: K_task K_automatic_opt IDENTIFIER ';'
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
task_item_list_opt
|
||||
statement_or_null_list
|
||||
K_endtask
|
||||
{ current_task->set_ports($6);
|
||||
current_task_set_statement($7);
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
delete[]$3;
|
||||
if ($7->size() > 1 && !gn_system_verilog()) {
|
||||
yyerror(@7, "error: Task body with multiple statements requres SystemVerilog.");
|
||||
}
|
||||
delete $7;
|
||||
}
|
||||
|
||||
| K_task K_automatic_opt IDENTIFIER '('
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
tf_port_list ')' ';'
|
||||
block_item_decls_opt
|
||||
statement_or_null_list
|
||||
K_endtask
|
||||
{ current_task->set_ports($6);
|
||||
current_task_set_statement($10);
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
delete[]$3;
|
||||
if ($10->size() > 1 && !gn_system_verilog()) {
|
||||
yyerror(@10, "error: Task body with multiple statements requres SystemVerilog.");
|
||||
}
|
||||
delete $10;
|
||||
}
|
||||
|
||||
| K_task K_automatic_opt IDENTIFIER '(' ')' ';'
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
block_item_decls_opt
|
||||
statement_or_null_list
|
||||
K_endtask
|
||||
{ current_task->set_ports(0);
|
||||
current_task_set_statement($9);
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
cerr << @3 << ": warning: task definition for \"" << $3
|
||||
<< "\" has an empty port declaration list!" << endl;
|
||||
delete[]$3;
|
||||
if ($9->size() > 1 && !gn_system_verilog()) {
|
||||
yyerror(@9, "error: Task body with multiple statements requres SystemVerilog.");
|
||||
}
|
||||
delete $9;
|
||||
}
|
||||
|
||||
| K_task K_automatic_opt IDENTIFIER error K_endtask
|
||||
{
|
||||
assert(current_task == 0);
|
||||
delete[]$3;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
|
||||
/* These rules for tf_port_item are slightly expanded from the
|
||||
strict rules in the LRM to help with LALR parsing.
|
||||
|
||||
NOTE: Some of these rules should be folded into the "data_type"
|
||||
variant which uses the data_type rule to match data type
|
||||
declarations. That some rules do not use the data_type production
|
||||
is a consequence of legacy. */
|
||||
|
||||
tf_port_item /* IEEE1800-2005: A.2.7 */
|
||||
|
||||
: port_direction K_reg_opt unsigned_signed_opt range_opt IDENTIFIER range_opt tf_port_item_expr_opt
|
||||
{ port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range($4);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(@5, $1, IVL_VT_LOGIC, $3,
|
||||
$4, list_from_identifier($5));
|
||||
$$ = tmp;
|
||||
if ($6) {
|
||||
yyerror(@6, "sorry: Port variable dimensions not supported yet.");
|
||||
delete $6;
|
||||
}
|
||||
if ($7) {
|
||||
yyerror(@7, "sorry: Port default expressions not supported yet.");
|
||||
delete $7;
|
||||
}
|
||||
}
|
||||
|
||||
| port_direction_opt bit_logic unsigned_signed_opt range_opt IDENTIFIER range_opt tf_port_item_expr_opt
|
||||
{ port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = $2;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range($4);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(@5, $1, $2, $3,
|
||||
$4, list_from_identifier($5));
|
||||
$$ = tmp;
|
||||
if ($6) {
|
||||
yyerror(@6, "sorry: Port variable dimensions not supported yet.");
|
||||
delete $6;
|
||||
}
|
||||
if ($7) {
|
||||
yyerror(@7, "sorry: Port default expressions not supported yet.");
|
||||
delete $7;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ports can be integer with a width of [31:0]. */
|
||||
|
||||
| port_direction_opt K_integer IDENTIFIER range_opt tf_port_item_expr_opt
|
||||
{ list<PExpr*>*range_stub = make_range_from_width(integer_width);
|
||||
port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = true;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(@3, $1, IVL_VT_LOGIC, true,
|
||||
range_stub,
|
||||
list_from_identifier($3), true);
|
||||
$$ = tmp;
|
||||
if ($4) {
|
||||
yyerror(@4, "sorry: Port variable dimensions not supported yet.");
|
||||
delete $4;
|
||||
}
|
||||
if ($5) {
|
||||
yyerror(@5, "sorry: Port default expressions not supported yet.");
|
||||
delete $5;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ports can be time with a width of [63:0] (unsigned). */
|
||||
|
||||
| port_direction_opt K_time IDENTIFIER range_opt tf_port_item_expr_opt
|
||||
{ list<PExpr*>*range_stub = make_range_from_width(64);
|
||||
port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(@3, $1, IVL_VT_LOGIC, false,
|
||||
range_stub,
|
||||
list_from_identifier($3));
|
||||
$$ = tmp;
|
||||
if ($4) {
|
||||
yyerror(@4, "sorry: Port variable dimensions not supported yet.");
|
||||
delete $4;
|
||||
}
|
||||
if ($5) {
|
||||
yyerror(@5, "sorry: Port default expressions not supported yet.");
|
||||
delete $5;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ports can be real or realtime. */
|
||||
|
||||
| port_direction_opt real_or_realtime IDENTIFIER range_opt tf_port_item_expr_opt
|
||||
{ port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = IVL_VT_REAL;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = 0;
|
||||
svector<PWire*>*tmp = pform_make_task_ports(@3, $1, IVL_VT_REAL, false,
|
||||
0, list_from_identifier($3));
|
||||
$$ = tmp;
|
||||
if ($4) {
|
||||
yyerror(@4, "sorry: Port variable dimensions not supported yet.");
|
||||
delete $4;
|
||||
}
|
||||
if ($5) {
|
||||
yyerror(@5, "sorry: Port default expressions not supported yet.");
|
||||
delete $5;
|
||||
}
|
||||
}
|
||||
|
||||
| port_direction_opt data_type IDENTIFIER range_opt tf_port_item_expr_opt
|
||||
{ port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = IVL_VT_NO_TYPE;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = 0;
|
||||
port_declaration_context.data_type = $2;
|
||||
svector<PWire*>*tmp = pform_make_task_ports(@3, $1, $2,
|
||||
list_from_identifier($3));
|
||||
$$ = tmp;
|
||||
if ($4) {
|
||||
yyerror(@4, "sorry: Port variable dimensions not supported yet.");
|
||||
delete $4;
|
||||
}
|
||||
if ($5) {
|
||||
yyerror(@5, "sorry: Port default expressions not supported yet.");
|
||||
delete $5;
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/* This rule matches the [ = <expression> ] part of the tf_port_item rules. */
|
||||
|
||||
tf_port_item_expr_opt
|
||||
: '=' expression { $$ = $2; }
|
||||
| { $$ = 0; }
|
||||
;
|
||||
|
||||
tf_port_list /* IEEE1800-2005: A.2.7 */
|
||||
|
||||
: tf_port_list ',' tf_port_item
|
||||
{ svector<PWire*>*tmp;
|
||||
if ($3) {
|
||||
tmp = new svector<PWire*>(*$1, *$3);
|
||||
delete $1;
|
||||
delete $3;
|
||||
} else {
|
||||
tmp = $1;
|
||||
}
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| tf_port_item
|
||||
{ $$ = $1; }
|
||||
|
||||
/* This rule handles the special case of a set of port items leading
|
||||
an undecorated identifier. Undeconated identifiers in this case
|
||||
pick up the details from the list to its lift. */
|
||||
|
||||
| tf_port_list ',' IDENTIFIER
|
||||
{ // The declaration is already parsed, apply it to IDENTIFIER
|
||||
svector<PWire*>*new_decl;
|
||||
if (port_declaration_context.var_type == IVL_VT_NO_TYPE) {
|
||||
assert(port_declaration_context.data_type);
|
||||
new_decl = pform_make_task_ports(@3, port_declaration_context.port_type,
|
||||
port_declaration_context.data_type,
|
||||
list_from_identifier($3));
|
||||
} else {
|
||||
new_decl = pform_make_task_ports(@3, port_declaration_context.port_type,
|
||||
port_declaration_context.var_type,
|
||||
port_declaration_context.sign_flag,
|
||||
copy_range(port_declaration_context.range),
|
||||
list_from_identifier($3));
|
||||
}
|
||||
svector<PWire*>*tmp = new svector<PWire*>(*$1, *new_decl);
|
||||
delete $1;
|
||||
delete new_decl;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Rules to handle some errors in tf_port_list items. */
|
||||
|
||||
| error ',' tf_port_item
|
||||
{ yyerror(@2, "error: Syntax error in task/function port declaration.");
|
||||
$$ = $3;
|
||||
}
|
||||
| tf_port_list ','
|
||||
{ yyerror(@2, "error: NULL port declarations are not allowed.");
|
||||
$$ = $1;
|
||||
}
|
||||
| tf_port_list ';'
|
||||
{ yyerror(@2, "error: ';' is an invalid port declaration separator.");
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
variable_dimension /* IEEE1800-2005: A.2.5 */
|
||||
: '[' expression ':' expression ']'
|
||||
{ list<PExpr*>*tmp = new list<PExpr*>;
|
||||
tmp->push_back($2);
|
||||
tmp->push_back($4);
|
||||
$$ = tmp;
|
||||
}
|
||||
| '[' ']'
|
||||
{ list<PExpr*>*tmp = new list<PExpr*>;
|
||||
tmp->push_back(0);
|
||||
tmp->push_back(0);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
/* Verilog-2001 supports attribute lists, which can be attached to a
|
||||
variety of different objects. The syntax inside the (* *) is a
|
||||
comma separated list of names or names with assigned values. */
|
||||
|
|
@ -2079,6 +2394,12 @@ expr_primary
|
|||
$$ = base;
|
||||
}
|
||||
}
|
||||
|
||||
/* Aggregate literals are primaries. */
|
||||
|
||||
| assignment_pattern
|
||||
{ $$ = $1; }
|
||||
|
||||
;
|
||||
|
||||
/* A function_item_list borrows the task_port_item run to match
|
||||
|
|
@ -3159,76 +3480,7 @@ module_item
|
|||
|
||||
| class_declaration
|
||||
|
||||
/* The task declaration rule matches the task declaration
|
||||
header, then pushes the function scope. This causes the
|
||||
definitions in the task_body to take on the scope of the task
|
||||
instead of the module. Note that these runs accept for the task
|
||||
body statement_or_null, although the standard does not allow null
|
||||
statements in the task body. But we continue to accept it as an
|
||||
extension. */
|
||||
|
||||
| K_task K_automatic_opt IDENTIFIER ';'
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
task_item_list_opt
|
||||
statement_or_null_list
|
||||
K_endtask
|
||||
{ current_task->set_ports($6);
|
||||
current_task_set_statement($7);
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
delete[]$3;
|
||||
if ($7->size() > 1 && !gn_system_verilog()) {
|
||||
yyerror(@7, "error: Task body with multiple statements requres SystemVerilog.");
|
||||
}
|
||||
delete $7;
|
||||
}
|
||||
|
||||
| K_task K_automatic_opt IDENTIFIER '('
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
task_port_decl_list ')' ';'
|
||||
block_item_decls_opt
|
||||
statement_or_null_list
|
||||
K_endtask
|
||||
{ current_task->set_ports($6);
|
||||
current_task_set_statement($10);
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
delete[]$3;
|
||||
if ($10->size() > 1 && !gn_system_verilog()) {
|
||||
yyerror(@10, "error: Task body with multiple statements requres SystemVerilog.");
|
||||
}
|
||||
delete $10;
|
||||
}
|
||||
|
||||
| K_task K_automatic_opt IDENTIFIER '(' ')' ';'
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
block_item_decls_opt
|
||||
statement_or_null_list
|
||||
K_endtask
|
||||
{ current_task->set_ports(0);
|
||||
current_task_set_statement($9);
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
cerr << @3 << ": warning: task definition for \"" << $3
|
||||
<< "\" has an empty port declaration list!" << endl;
|
||||
delete[]$3;
|
||||
if ($9->size() > 1 && !gn_system_verilog()) {
|
||||
yyerror(@9, "error: Task body with multiple statements requres SystemVerilog.");
|
||||
}
|
||||
delete $9;
|
||||
}
|
||||
|
||||
| K_task K_automatic_opt IDENTIFIER error K_endtask
|
||||
{
|
||||
assert(current_task == 0);
|
||||
delete[]$3;
|
||||
}
|
||||
| task_declaration
|
||||
|
||||
/* The function declaration rule matches the function declaration
|
||||
header, then pushes the function scope. This causes the
|
||||
|
|
@ -3266,7 +3518,7 @@ module_item
|
|||
{ assert(current_function == 0);
|
||||
current_function = pform_push_function_scope(@1, $4, $2);
|
||||
}
|
||||
'(' task_port_decl_list_opt ')' ';'
|
||||
'(' tf_port_list_opt ')' ';'
|
||||
block_item_decls_opt
|
||||
statement_list
|
||||
K_endfunction
|
||||
|
|
@ -4055,17 +4307,12 @@ port_direction_opt
|
|||
| { $$ = NetNet::PINPUT; }
|
||||
;
|
||||
|
||||
/* The range is a list of variable dimensions. */
|
||||
range
|
||||
: '[' expression ':' expression ']'
|
||||
{ list<PExpr*>*tmp = new list<PExpr*>;
|
||||
tmp->push_back($2);
|
||||
tmp->push_back($4);
|
||||
$$ = tmp;
|
||||
}
|
||||
| range '[' expression ':' expression ']'
|
||||
: variable_dimension
|
||||
| range variable_dimension
|
||||
{ list<PExpr*>*tmp = $1;
|
||||
tmp->push_back($3);
|
||||
tmp->push_back($5);
|
||||
if ($2) tmp->splice(tmp->end(), *$2);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
|
@ -5112,11 +5359,10 @@ task_item
|
|||
|
||||
task_port_item
|
||||
: port_direction K_reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp = pform_make_task_ports($1,
|
||||
{ svector<PWire*>*tmp = pform_make_task_ports(@1, $1,
|
||||
$2 ? IVL_VT_LOGIC :
|
||||
IVL_VT_NO_TYPE,
|
||||
$3, $4, $5,
|
||||
@1.text, @1.first_line);
|
||||
$3, $4, $5);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
|
|
@ -5125,9 +5371,8 @@ task_port_item
|
|||
|
||||
| port_direction K_integer list_of_identifiers ';'
|
||||
{ list<PExpr*>*range_stub = make_range_from_width(integer_width);
|
||||
svector<PWire*>*tmp = pform_make_task_ports($1, IVL_VT_LOGIC, true,
|
||||
range_stub, $3,
|
||||
@1.text, @1.first_line, true);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, true,
|
||||
range_stub, $3, true);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
|
|
@ -5135,17 +5380,16 @@ task_port_item
|
|||
|
||||
| port_direction K_time list_of_identifiers ';'
|
||||
{ list<PExpr*>*range_stub = make_range_from_width(64);
|
||||
svector<PWire*>*tmp = pform_make_task_ports($1, IVL_VT_LOGIC, false,
|
||||
range_stub, $3,
|
||||
@1.text, @1.first_line);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, false,
|
||||
range_stub, $3);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Ports can be real or realtime. */
|
||||
|
||||
| port_direction real_or_realtime list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp = pform_make_task_ports($1, IVL_VT_REAL, false,
|
||||
0, $3, @1.text, @1.first_line);
|
||||
{ svector<PWire*>*tmp = pform_make_task_ports(@1, $1, IVL_VT_REAL, false,
|
||||
0, $3);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
|
|
@ -5169,142 +5413,11 @@ task_item_list_opt
|
|||
{ $$ = 0; }
|
||||
;
|
||||
|
||||
task_port_decl
|
||||
|
||||
: port_direction K_reg_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||
{ port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range($4);
|
||||
svector<PWire*>*tmp = pform_make_task_ports($1, IVL_VT_LOGIC, $3,
|
||||
$4, list_from_identifier($5),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| port_direction_opt bit_logic unsigned_signed_opt range_opt IDENTIFIER
|
||||
{ port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = $2;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range($4);
|
||||
svector<PWire*>*tmp = pform_make_task_ports($1, $2, $3,
|
||||
$4, list_from_identifier($5),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Ports can be integer with a width of [31:0]. */
|
||||
|
||||
| port_direction_opt K_integer IDENTIFIER
|
||||
{ list<PExpr*>*range_stub = make_range_from_width(integer_width);
|
||||
port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = true;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports($1, IVL_VT_LOGIC, true,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line, true);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Ports can be time with a width of [63:0] (unsigned). */
|
||||
|
||||
| port_direction_opt K_time IDENTIFIER
|
||||
{ list<PExpr*>*range_stub = make_range_from_width(64);
|
||||
port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports($1, IVL_VT_LOGIC, false,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Ports can be real or realtime. */
|
||||
|
||||
| port_direction_opt real_or_realtime IDENTIFIER
|
||||
{ port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = IVL_VT_REAL;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = 0;
|
||||
svector<PWire*>*tmp = pform_make_task_ports($1, IVL_VT_REAL, false,
|
||||
0, list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| port_direction_opt data_type IDENTIFIER task_port_decl_expr_opt
|
||||
{ port_declaration_context.port_type = $1;
|
||||
port_declaration_context.var_type = IVL_VT_NO_TYPE;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = 0;
|
||||
port_declaration_context.data_type = $2;
|
||||
svector<PWire*>*tmp = pform_make_task_ports(@1, $1, $2,
|
||||
list_from_identifier($3));
|
||||
$$ = tmp;
|
||||
if ($4) {
|
||||
yyerror(@4, "sorry: Port default expressions not supported yet.");
|
||||
delete $4;
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
task_port_decl_expr_opt
|
||||
: '=' expression { $$ = $2; }
|
||||
| { $$ = 0; }
|
||||
;
|
||||
|
||||
task_port_decl_list_opt
|
||||
: task_port_decl_list { $$ = $1; }
|
||||
tf_port_list_opt
|
||||
: tf_port_list { $$ = $1; }
|
||||
| { $$ = 0; }
|
||||
;
|
||||
|
||||
task_port_decl_list
|
||||
: task_port_decl_list ',' task_port_decl
|
||||
{ svector<PWire*>*tmp = new svector<PWire*>(*$1, *$3);
|
||||
delete $1;
|
||||
delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| task_port_decl
|
||||
{ $$ = $1; }
|
||||
| task_port_decl_list ',' IDENTIFIER
|
||||
{ // The declaration is already parsed, apply it to IDENTIFIER
|
||||
svector<PWire*>*new_decl;
|
||||
if (port_declaration_context.var_type == IVL_VT_NO_TYPE) {
|
||||
assert(port_declaration_context.data_type);
|
||||
new_decl = pform_make_task_ports(@3, port_declaration_context.port_type,
|
||||
port_declaration_context.data_type,
|
||||
list_from_identifier($3));
|
||||
} else {
|
||||
new_decl = pform_make_task_ports(port_declaration_context.port_type,
|
||||
port_declaration_context.var_type,
|
||||
port_declaration_context.sign_flag,
|
||||
copy_range(port_declaration_context.range),
|
||||
list_from_identifier($3),
|
||||
@3.text, @3.first_line);
|
||||
}
|
||||
svector<PWire*>*tmp = new svector<PWire*>(*$1, *new_decl);
|
||||
delete $1;
|
||||
delete new_decl;
|
||||
$$ = tmp;
|
||||
}
|
||||
| task_port_decl_list ','
|
||||
{ yyerror(@2, "error: NULL port declarations are not allowed."); }
|
||||
| task_port_decl_list ';'
|
||||
{ yyerror(@2, "error: ';' is an invalid port declaration separator."); }
|
||||
;
|
||||
|
||||
udp_body
|
||||
: K_table { lex_start_table(); }
|
||||
udp_entry_list
|
||||
|
|
|
|||
11
pform.cc
11
pform.cc
|
|
@ -2145,13 +2145,12 @@ void pform_set_port_type(perm_string name, NetNet::PortType pt,
|
|||
* constraints as those of tasks, so this works fine. Functions have
|
||||
* no output or inout ports.
|
||||
*/
|
||||
svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<perm_string>*names,
|
||||
const char* file,
|
||||
unsigned lineno,
|
||||
bool isint)
|
||||
{
|
||||
assert(names);
|
||||
|
|
@ -2168,7 +2167,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
|||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
|
||||
FILE_NAME(curw, file, lineno);
|
||||
FILE_NAME(curw, loc);
|
||||
pform_put_wire_in_scope(name, curw);
|
||||
}
|
||||
|
||||
|
|
@ -2205,8 +2204,8 @@ svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
|||
}
|
||||
|
||||
list<PExpr*>*range_tmp = make_range_from_width(atype->type_code);
|
||||
return pform_make_task_ports(pt, IVL_VT_BOOL, atype->signed_flag,
|
||||
range_tmp, names, loc.text, loc.first_line);
|
||||
return pform_make_task_ports(loc, pt, IVL_VT_BOOL, atype->signed_flag,
|
||||
range_tmp, names);
|
||||
}
|
||||
|
||||
void pform_set_attrib(perm_string name, perm_string key, char*value)
|
||||
|
|
|
|||
5
pform.h
5
pform.h
|
|
@ -385,13 +385,12 @@ extern void pform_make_pgassign_list(list<PExpr*>*alist,
|
|||
|
||||
/* Given a port type and a list of names, make a list of wires that
|
||||
can be used as task port information. */
|
||||
extern svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
extern svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
list<PExpr*>*range,
|
||||
list<perm_string>*names,
|
||||
const char* file,
|
||||
unsigned lineno,
|
||||
bool isint = false);
|
||||
|
||||
extern svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||
|
|
|
|||
|
|
@ -860,6 +860,10 @@ void PTask::dump(ostream&out, unsigned ind) const
|
|||
out << pscope_name() << ";" << endl;
|
||||
if (ports_)
|
||||
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
|
||||
if ((*ports_)[idx] == 0) {
|
||||
out << setw(ind) << "" << "ERROR PORT" << endl;
|
||||
continue;
|
||||
}
|
||||
out << setw(ind) << "";
|
||||
switch ((*ports_)[idx]->get_port_type()) {
|
||||
case NetNet::PINPUT:
|
||||
|
|
@ -871,6 +875,12 @@ void PTask::dump(ostream&out, unsigned ind) const
|
|||
case NetNet::PINOUT:
|
||||
out << "inout ";
|
||||
break;
|
||||
case NetNet::PIMPLICIT:
|
||||
out << "PIMPLICIT";
|
||||
break;
|
||||
case NetNet::NOT_A_PORT:
|
||||
out << "NOT_A_PORT";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue