From 6ca44b48ccec723d790b08f06e346e0dd9285301 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 20 Jul 2011 19:03:24 -0700 Subject: [PATCH] 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 Signed-off-by: Prasad Joshi --- lexor.lex | 27 +++++++++++++++++ parse.y | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/lexor.lex b/lexor.lex index ce3916746..d4788e9da 100644 --- a/lexor.lex +++ b/lexor.lex @@ -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 diff --git a/parse.y b/parse.y index 117684044..9d213602e 100644 --- a/parse.y +++ b/parse.y @@ -296,6 +296,7 @@ static list* make_named_number(perm_string name, PExpr*val =0) %token PATHPULSE_IDENTIFIER %token BASED_NUMBER DEC_NUMBER %token 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* make_named_number(perm_string name, PExpr*val =0) %type event_expression_list %type event_expression %type event_control -%type statement statement_or_null +%type statement statement_or_null compressed_statement %type statement_list %type analog_statement @@ -469,6 +470,8 @@ static list* make_named_number(perm_string name, PExpr*val =0) %type 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*tmp = new svector(*$1, $2);