Add support for C-like assignments operators

SystemVerilog extended the assignments operator support to C-like
assignment operators and special bitwise assignment operators.

For example:
        a += 1;
        a -= 1;

The list of these operators can be found in SV LRM (1800-2009)
section 11.4.1.

NOTE: I fixed a few parts of this. In particular, the PEBShift
class is used for shift operators.

Acked-and-Tested-by: Oswaldo Cadenas <oswaldo.cadenas@gmail.com>
Signed-off-by: Prasad Joshi <prasadjoshi124@gmail.com>
This commit is contained in:
Stephen Williams 2011-07-20 19:03:24 -07:00
parent 4989555646
commit 6ca44b48cc
2 changed files with 113 additions and 1 deletions

View File

@ -145,6 +145,20 @@ TU [munpf]
"<=" { return K_LE; }
">=" { return K_GE; }
"=>" { return K_EG; }
"+=>"|"-=>" {
/*
* Resolve the ambiguity between the += assignment
* operator and +=> polarity edge path operator
*
* +=> should be treated as two separate tokens '+' and
* '=>' (K_EG), therefore we only consume the first
* character of the matched pattern i.e. either + or -
* and push back the rest of the matches text (=>) in
* the input stream.
*/
yyless(1);
return yytext[0];
}
"*>" { return K_SG; }
"==" { return K_EQ; }
"!=" { return K_NE; }
@ -161,6 +175,19 @@ TU [munpf]
"+:" { return K_PO_POS; }
"-:" { return K_PO_NEG; }
"<+" { return K_CONTRIBUTE; }
"+=" { return K_PLUS_EQ; }
"-=" { return K_MINUS_EQ; }
"*=" { return K_MUL_EQ; }
"/=" { return K_DIV_EQ; }
"%=" { return K_MOD_EQ; }
"&=" { return K_AND_EQ; }
"|=" { return K_OR_EQ; }
"^=" { return K_XOR_EQ; }
"<<=" { return K_LS_EQ; }
">>=" { return K_RS_EQ; }
"<<<=" { return K_LS_EQ; }
">>>=" { return K_RSS_EQ; }
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
and ")", but since I know that this is really ( * ), replace it

87
parse.y
View File

@ -296,6 +296,7 @@ static list<named_pexpr_t>* make_named_number(perm_string name, PExpr*val =0)
%token <text> PATHPULSE_IDENTIFIER
%token <number> BASED_NUMBER DEC_NUMBER
%token <realtime> REALTIME
%token K_PLUS_EQ K_MINUS_EQ
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_RSS K_SG
/* K_CONTRIBUTE is <+, the contribution assign. */
%token K_CONTRIBUTE
@ -455,7 +456,7 @@ static list<named_pexpr_t>* make_named_number(perm_string name, PExpr*val =0)
%type <event_expr> event_expression_list
%type <event_expr> event_expression
%type <event_statement> event_control
%type <statement> statement statement_or_null
%type <statement> statement statement_or_null compressed_statement
%type <statement_list> statement_list
%type <statement> analog_statement
@ -469,6 +470,8 @@ static list<named_pexpr_t>* make_named_number(perm_string name, PExpr*val =0)
%type <int_val> atom2_type
%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_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
%right '?' ':'
%left K_LOR
%left K_LAND
@ -4278,6 +4281,8 @@ statement
{ $$ = 0;
yyerror(@1, "error: Error in while loop condition.");
}
| compressed_statement ';'
{ $$ = $1; }
| delay1 statement_or_null
{ PExpr*del = $1->front();
assert($1->size() == 1);
@ -4421,6 +4426,86 @@ statement
}
;
compressed_statement
: lpvalue K_PLUS_EQ expression
{
PEBinary *t = new PEBinary('+', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MINUS_EQ expression
{
PEBinary *t = new PEBinary('-', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MUL_EQ expression
{
PEBinary *t = new PEBinary('*', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_DIV_EQ expression
{
PEBinary *t = new PEBinary('/', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MOD_EQ expression
{
PEBinary *t = new PEBinary('%', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_AND_EQ expression
{
PEBinary *t = new PEBinary('&', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_OR_EQ expression
{
PEBinary *t = new PEBinary('|', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_XOR_EQ expression
{
PEBinary *t = new PEBinary('^', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_LS_EQ expression
{
PEBShift *t = new PEBShift('l', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_RS_EQ expression
{
PEBShift *t = new PEBShift('r', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_RSS_EQ expression
{
PEBShift *t = new PEBShift('R', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
;
statement_list
: statement_list statement
{ svector<Statement*>*tmp = new svector<Statement*>(*$1, $2);