More rework to canonicalize tf_port_item rules.

This commit is contained in:
Stephen Williams 2012-02-26 10:57:03 -08:00
parent 410350ae5a
commit 481a9dec69
1 changed files with 76 additions and 45 deletions

111
parse.y
View File

@ -447,7 +447,7 @@ static void current_task_set_statement(vector<Statement*>*s)
%type <flag> from_exclude
%type <number> number pos_neg_number
%type <flag> 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_virtual_opt
%type <flag> udp_reg_opt edge_operator
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
@ -670,18 +670,34 @@ data_type /* IEEE1800-2005: A.2.2.1 */
}
;
/* The data_type_or_implicit rule is a little more complex then the
rule documented in the IEEE format syntax in order to allow for
signaling the special case that the data_type is completely
absent. The context may need that information to decide to resort
to left context. */
data_type_or_implicit /* IEEE1800-2005: A.2.2.1 */
: data_type
{ $$ = $1; }
| unsigned_signed_opt range_opt
| signing range_opt
{ vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, $1, $2);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| range
{ vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, false, $1);
FILE_NAME(tmp, @1);
$$ = tmp;
}
|
{ $$ = 0; }
;
/* This implements the [ : INDENTIFIER ] part of the constructure
rule documented in IEEE1800-2005: A.1.8 */
endnew_opt : ':' K_new | ;
for_step /* IEEE1800-2005: A.6.8 */
: lpvalue '=' expression
{ PAssign*tmp = new PAssign($1,$3);
@ -824,12 +840,13 @@ port_direction /* IEEE1800-2005 A.1.3 */
}
;
/* port_direction_opt is used in places where the prot direction is
option, and defaults to input. */
/* port_direction_opt is used in places where the port direction is
optional. The default direction is selected by the context,
which needs to notice the PIMPLICIT direction. */
port_direction_opt
: port_direction { $$ = $1; }
| { $$ = NetNet::PINPUT; }
| { $$ = NetNet::PIMPLICIT; }
;
/* real and realtime are exactly the same so save some code
@ -839,6 +856,11 @@ real_or_realtime
| K_realtime
;
signing /* IEEE1800-2005: A.2.2.1 */
: K_signed { $$ = true; }
| K_unsigned { $$ = false; }
;
/* Many places where statements are allowed can actually take a
statement or a null statement marked with a naked semi-colon. */
@ -992,7 +1014,9 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
: 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;
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
port_declaration_context.port_type = use_port_type;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = true;
delete port_declaration_context.range;
@ -1015,13 +1039,15 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
| 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;
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
port_declaration_context.port_type = use_port_type;
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,
svector<PWire*>*tmp = pform_make_task_ports(@3, use_port_type, IVL_VT_LOGIC,
false, range_stub,
list_from_identifier($3));
$$ = tmp;
if ($4) {
@ -1034,15 +1060,43 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
}
}
| port_direction data_type_or_implicit IDENTIFIER range_opt tf_port_item_expr_opt
{ port_declaration_context.port_type = $1;
| port_direction_opt data_type_or_implicit IDENTIFIER range_opt tf_port_item_expr_opt
{ svector<PWire*>*tmp;
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
list<perm_string>* ilist = list_from_identifier($3);
if (($2 == 0) && ($1==NetNet::PIMPLICIT)) {
// Detect special case this is an undecorated
// identifier and we need to get the declaration from
// left context.
if (port_declaration_context.var_type == IVL_VT_NO_TYPE) {
tmp = pform_make_task_ports(@3, use_port_type,
port_declaration_context.data_type,
ilist);
} else {
tmp = pform_make_task_ports(@3, use_port_type,
port_declaration_context.var_type,
port_declaration_context.sign_flag,
copy_range(port_declaration_context.range),
ilist);
}
} else {
// Otherwise, the decorations for this identifier
// indicate the type. Save the type for any right
// context thta may come later.
port_declaration_context.port_type = use_port_type;
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;
if ($2 == 0) {
$2 = new vector_type_t(IVL_VT_LOGIC, false, 0);
FILE_NAME($2, @3);
}
port_declaration_context.data_type = $2;
svector<PWire*>*tmp = pform_make_task_ports(@3, $1, $2,
list_from_identifier($3));
tmp = pform_make_task_ports(@3, $1, $2, ilist);
}
$$ = tmp;
if ($4) {
yyerror(@4, "sorry: Port variable dimensions not supported yet.");
@ -1067,12 +1121,14 @@ tf_port_list /* IEEE1800-2005: A.2.7 */
: tf_port_list ',' tf_port_item
{ svector<PWire*>*tmp;
if ($3) {
if ($1 && $3) {
tmp = new svector<PWire*>(*$1, *$3);
delete $1;
delete $3;
} else {
} else if ($1) {
tmp = $1;
} else {
tmp = $3;
}
$$ = tmp;
}
@ -1080,31 +1136,6 @@ tf_port_list /* IEEE1800-2005: A.2.7 */
| 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