Implement increment/decrement statements.
During parse/pform processing, convert increment statements to the equivalent compressed assignment statement. This is less weird for elaboration processing and better expresses what is going on.
This commit is contained in:
parent
6b4251626b
commit
f8e346f108
4
PExpr.h
4
PExpr.h
|
|
@ -509,6 +509,10 @@ class PEUnary : public PExpr {
|
||||||
unsigned flags) const;
|
unsigned flags) const;
|
||||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline char get_op() const { return op_; }
|
||||||
|
inline PExpr*get_expr() const { return expr_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetExpr* elaborate_expr_bits_(NetExpr*operand, unsigned expr_wid) const;
|
NetExpr* elaborate_expr_bits_(NetExpr*operand, unsigned expr_wid) const;
|
||||||
|
|
||||||
|
|
|
||||||
97
parse.y
97
parse.y
|
|
@ -496,7 +496,7 @@ static void current_task_set_statement(vector<Statement*>*s)
|
||||||
|
|
||||||
%type <pform_name> hierarchy_identifier
|
%type <pform_name> hierarchy_identifier
|
||||||
%type <expr> assignment_pattern expression expr_primary expr_mintypmax
|
%type <expr> assignment_pattern expression expr_primary expr_mintypmax
|
||||||
%type <expr> lpvalue
|
%type <expr> inc_or_dec_expression lpvalue
|
||||||
%type <expr> branch_probe_expression
|
%type <expr> branch_probe_expression
|
||||||
%type <expr> delay_value delay_value_simple
|
%type <expr> delay_value delay_value_simple
|
||||||
%type <exprs> delay1 delay3 delay3_opt delay_value_list
|
%type <exprs> delay1 delay3 delay3_opt delay_value_list
|
||||||
|
|
@ -665,6 +665,35 @@ implicit_class_handle /* IEEE1800-2005: A.8.4 */
|
||||||
| K_super
|
| K_super
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* SystemVerilog adds support for the increment/decrement
|
||||||
|
expressions, which look like a++, --a, etc. These are primaries
|
||||||
|
but are in their own rules because they can also be
|
||||||
|
statements. Note that the operator can only take l-value
|
||||||
|
expressions. */
|
||||||
|
|
||||||
|
inc_or_dec_expression /* IEEE1800-2005: A.4.3 */
|
||||||
|
: K_INCR lpvalue %prec UNARY_PREC
|
||||||
|
{ PEUnary*tmp = new PEUnary('I', $2);
|
||||||
|
FILE_NAME(tmp, @2);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| lpvalue K_INCR %prec UNARY_PREC
|
||||||
|
{ PEUnary*tmp = new PEUnary('i', $1);
|
||||||
|
FILE_NAME(tmp, @1);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| K_DECR lpvalue %prec UNARY_PREC
|
||||||
|
{ PEUnary*tmp = new PEUnary('D', $2);
|
||||||
|
FILE_NAME(tmp, @2);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| lpvalue K_DECR %prec UNARY_PREC
|
||||||
|
{ PEUnary*tmp = new PEUnary('d', $1);
|
||||||
|
FILE_NAME(tmp, @1);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
number : BASED_NUMBER
|
number : BASED_NUMBER
|
||||||
{ $$ = $1; based_size = 0;}
|
{ $$ = $1; based_size = 0;}
|
||||||
| DEC_NUMBER
|
| DEC_NUMBER
|
||||||
|
|
@ -1790,32 +1819,10 @@ branch_probe_expression
|
||||||
expression
|
expression
|
||||||
: expr_primary
|
: expr_primary
|
||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
|
| inc_or_dec_expression
|
||||||
|
{ $$ = $1; }
|
||||||
| '+' expr_primary %prec UNARY_PREC
|
| '+' expr_primary %prec UNARY_PREC
|
||||||
{ $$ = $2; }
|
{ $$ = $2; }
|
||||||
| K_INCR expr_primary %prec UNARY_PREC
|
|
||||||
{
|
|
||||||
PEUnary*tmp = new PEUnary('I', $2);
|
|
||||||
FILE_NAME(tmp, @2);
|
|
||||||
$$ = tmp;
|
|
||||||
}
|
|
||||||
| expr_primary K_INCR %prec UNARY_PREC
|
|
||||||
{
|
|
||||||
PEUnary*tmp = new PEUnary('i', $1);
|
|
||||||
FILE_NAME(tmp, @1);
|
|
||||||
$$ = tmp;
|
|
||||||
}
|
|
||||||
| K_DECR expr_primary %prec UNARY_PREC
|
|
||||||
{
|
|
||||||
PEUnary*tmp = new PEUnary('D', $2);
|
|
||||||
FILE_NAME(tmp, @2);
|
|
||||||
$$ = tmp;
|
|
||||||
}
|
|
||||||
| expr_primary K_DECR %prec UNARY_PREC
|
|
||||||
{
|
|
||||||
PEUnary*tmp = new PEUnary('d', $1);
|
|
||||||
FILE_NAME(tmp, @1);
|
|
||||||
$$ = tmp;
|
|
||||||
}
|
|
||||||
| '-' expr_primary %prec UNARY_PREC
|
| '-' expr_primary %prec UNARY_PREC
|
||||||
{ PEUnary*tmp = new PEUnary('-', $2);
|
{ PEUnary*tmp = new PEUnary('-', $2);
|
||||||
FILE_NAME(tmp, @2);
|
FILE_NAME(tmp, @2);
|
||||||
|
|
@ -4897,7 +4904,7 @@ spec_notifier
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
statement
|
statement /* This is roughly statement_item in the LRM */
|
||||||
|
|
||||||
/* assign and deassign statements are procedural code to do
|
/* assign and deassign statements are procedural code to do
|
||||||
structural assignments, and to turn that structural assignment
|
structural assignments, and to turn that structural assignment
|
||||||
|
|
@ -5094,16 +5101,29 @@ statement
|
||||||
{ $$ = 0;
|
{ $$ = 0;
|
||||||
yyerror(@1, "error: Error in while loop condition.");
|
yyerror(@1, "error: Error in while loop condition.");
|
||||||
}
|
}
|
||||||
| compressed_statement ';'
|
|
||||||
{ $$ = $1; }
|
/* SytemVerilog adds the compressed_statement */
|
||||||
| delay1 statement_or_null
|
|
||||||
{ PExpr*del = $1->front();
|
| compressed_statement ';'
|
||||||
assert($1->size() == 1);
|
{ $$ = $1; }
|
||||||
delete $1;
|
|
||||||
PDelayStatement*tmp = new PDelayStatement(del, $2);
|
/* increment/decrement expressions can also be statements. When used
|
||||||
FILE_NAME(tmp, @1);
|
as statements, we can rewrite a++ as a += 1, and so on. */
|
||||||
$$ = tmp;
|
|
||||||
}
|
| inc_or_dec_expression ';'
|
||||||
|
{ $$ = pform_compressed_assign_from_inc_dec(@1, $1); }
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
| delay1 statement_or_null
|
||||||
|
{ PExpr*del = $1->front();
|
||||||
|
assert($1->size() == 1);
|
||||||
|
delete $1;
|
||||||
|
PDelayStatement*tmp = new PDelayStatement(del, $2);
|
||||||
|
FILE_NAME(tmp, @1);
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
| event_control attribute_list_opt statement_or_null
|
| event_control attribute_list_opt statement_or_null
|
||||||
{ PEventStatement*tmp = $1;
|
{ PEventStatement*tmp = $1;
|
||||||
if (tmp == 0) {
|
if (tmp == 0) {
|
||||||
|
|
@ -5129,6 +5149,9 @@ statement
|
||||||
tmp->set_statement($6);
|
tmp->set_statement($6);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Various assignment statements */
|
||||||
|
|
||||||
| lpvalue '=' expression ';'
|
| lpvalue '=' expression ';'
|
||||||
{ PAssign*tmp = new PAssign($1,$3);
|
{ PAssign*tmp = new PAssign($1,$3);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
|
|
@ -5184,6 +5207,8 @@ statement
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
| K_wait '(' expression ')' statement_or_null
|
| K_wait '(' expression ')' statement_or_null
|
||||||
{ PEventStatement*tmp;
|
{ PEventStatement*tmp;
|
||||||
PEEvent*etmp = new PEEvent(PEEvent::POSITIVE, $3);
|
PEEvent*etmp = new PEEvent(PEEvent::POSITIVE, $3);
|
||||||
|
|
|
||||||
37
pform.cc
37
pform.cc
|
|
@ -2208,6 +2208,43 @@ svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||||
range_tmp, names);
|
range_tmp, names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The parser calls this in the rule that matches increment/decrement
|
||||||
|
* statements. The rule that does the matching creates a PEUnary with
|
||||||
|
* all the information we need, but here we convert that expression to
|
||||||
|
* a compressed assignment statement.
|
||||||
|
*/
|
||||||
|
PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc, PExpr*exp)
|
||||||
|
{
|
||||||
|
PEUnary*expu = dynamic_cast<PEUnary*> (exp);
|
||||||
|
ivl_assert(*exp, expu != 0);
|
||||||
|
|
||||||
|
char use_op = 0;
|
||||||
|
switch (expu->get_op()) {
|
||||||
|
case 'i':
|
||||||
|
case 'I':
|
||||||
|
use_op = '+';
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
use_op = '-';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ivl_assert(*exp, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PExpr*lval = expu->get_expr();
|
||||||
|
PExpr*rval = new PENumber(new verinum((uint64_t)1, 1));
|
||||||
|
FILE_NAME(rval, loc);
|
||||||
|
|
||||||
|
PAssign*tmp = new PAssign(lval, use_op, rval);
|
||||||
|
FILE_NAME(tmp, loc);
|
||||||
|
|
||||||
|
delete exp;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
void pform_set_attrib(perm_string name, perm_string key, char*value)
|
void pform_set_attrib(perm_string name, perm_string key, char*value)
|
||||||
{
|
{
|
||||||
if (PWire*cur = lexical_scope->wires_find(name)) {
|
if (PWire*cur = lexical_scope->wires_find(name)) {
|
||||||
|
|
|
||||||
7
pform.h
7
pform.h
|
|
@ -398,6 +398,13 @@ extern svector<PWire*>*pform_make_task_ports(const struct vlltype&loc,
|
||||||
data_type_t*vtype,
|
data_type_t*vtype,
|
||||||
list<perm_string>*names);
|
list<perm_string>*names);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The parser uses this function to convert a unary
|
||||||
|
* increment/decrement expression to the equivilent compressed
|
||||||
|
* assignment statement.
|
||||||
|
*/
|
||||||
|
extern PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc,
|
||||||
|
PExpr*exp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are functions that the outside-the-parser code uses the do
|
* These are functions that the outside-the-parser code uses the do
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue