Support SystemVerilog size cast.

This commit is contained in:
Stephen Williams 2011-09-18 19:21:46 -07:00
parent 873a447b5c
commit 557e331ce1
6 changed files with 125 additions and 49 deletions

View File

@ -98,6 +98,15 @@ bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
}
PECastSize::PECastSize(unsigned si, PExpr*b)
: size_(si), base_(b)
{
}
PECastSize::~PECastSize()
{
}
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{

23
PExpr.h
View File

@ -706,6 +706,29 @@ class PECallFunction : public PExpr {
width_mode_t&mode);
};
/*
* Support the SystemVerilog cast to size.
*/
class PECastSize : public PExpr {
public:
explicit PECastSize(unsigned expr_wid, PExpr*base);
~PECastSize();
void dump(ostream &out) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
private:
unsigned size_;
PExpr* base_;
};
/*
* This class is used for error recovery. All methods do nothing and return
* null or default values.

View File

@ -1423,6 +1423,26 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return 0;
}
unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&)
{
expr_width_ = size_;
width_mode_t tmp_mode = PExpr::SIZED;
base_->test_width(des, scope, tmp_mode);
return size_;
}
NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope,
unsigned, unsigned) const
{
NetExpr*sub = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS);
NetESelect*sel = new NetESelect(sub, 0, size_);
sel->set_line(*this);
return sel;
}
unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
{
expr_width_ = 0;

View File

@ -688,6 +688,8 @@ TU [munpf]
<< endl;
error_count += 1; }
. { return yytext[0]; }
/* Final catchall. something got lost or mishandled. */
/* XXX Should we tell the user something about the lexical state? */

113
parse.y
View File

@ -1600,29 +1600,29 @@ expression_list_proper
;
expr_primary
: number
{ assert($1);
PENumber*tmp = new PENumber($1);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| REALTIME
{ PEFNumber*tmp = new PEFNumber($1);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| STRING
{ PEString*tmp = new PEString($1);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| SYSTEM_IDENTIFIER
{ perm_string tn = lex_strings.make($1);
PECallFunction*tmp = new PECallFunction(tn);
FILE_NAME(tmp, @1);
$$ = tmp;
delete[]$1;
}
: number
{ assert($1);
PENumber*tmp = new PENumber($1);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| REALTIME
{ PEFNumber*tmp = new PEFNumber($1);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| STRING
{ PEString*tmp = new PEString($1);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| SYSTEM_IDENTIFIER
{ perm_string tn = lex_strings.make($1);
PECallFunction*tmp = new PECallFunction(tn);
FILE_NAME(tmp, @1);
$$ = tmp;
delete[]$1;
}
/* The hierarchy_identifier rule matches simple identifiers as well as
indexed arrays and part selects */
@ -1836,35 +1836,50 @@ expr_primary
/* Parenthesized expressions are primaries. */
| '(' expr_mintypmax ')'
{ $$ = $2; }
| '(' expr_mintypmax ')'
{ $$ = $2; }
/* Various kinds of concatenation expressions. */
| '{' expression_list_proper '}'
{ PEConcat*tmp = new PEConcat(*$2);
FILE_NAME(tmp, @1);
delete $2;
$$ = tmp;
}
| '{' expression '{' expression_list_proper '}' '}'
{ PExpr*rep = $2;
PEConcat*tmp = new PEConcat(*$4, rep);
FILE_NAME(tmp, @1);
delete $4;
$$ = tmp;
}
| '{' expression '{' expression_list_proper '}' error '}'
{ PExpr*rep = $2;
PEConcat*tmp = new PEConcat(*$4, rep);
FILE_NAME(tmp, @1);
delete $4;
$$ = tmp;
yyerror(@5, "error: Syntax error between internal '}' "
"and closing '}' of repeat concatenation.");
yyerrok;
}
;
| '{' expression_list_proper '}'
{ PEConcat*tmp = new PEConcat(*$2);
FILE_NAME(tmp, @1);
delete $2;
$$ = tmp;
}
| '{' expression '{' expression_list_proper '}' '}'
{ PExpr*rep = $2;
PEConcat*tmp = new PEConcat(*$4, rep);
FILE_NAME(tmp, @1);
delete $4;
$$ = tmp;
}
| '{' expression '{' expression_list_proper '}' error '}'
{ PExpr*rep = $2;
PEConcat*tmp = new PEConcat(*$4, rep);
FILE_NAME(tmp, @1);
delete $4;
$$ = tmp;
yyerror(@5, "error: Syntax error between internal '}' "
"and closing '}' of repeat concatenation.");
yyerrok;
}
/* Cast expressions are primaries */
| DEC_NUMBER '\'' '(' expression ')'
{ PExpr*base = $4;
if (gn_system_verilog()) {
PECastSize*tmp = new PECastSize($1->as_ulong(), base);
FILE_NAME(tmp, @1);
delete $1;
$$ = tmp;
} else {
yyerror(@1, "error: Size cast requires SystemVerilog.");
$$ = base;
}
}
;
/* A function_item_list borrows the task_port_item run to match
declarations of ports. We check later to make sure there are no

View File

@ -197,6 +197,13 @@ void PECallFunction::dump(ostream &out) const
out << ")";
}
void PECastSize::dump(ostream &out) const
{
out << size_ << "'(";
base_->dump(out);
out << ")";
}
void PEEvent::dump(ostream&out) const
{
switch (type_) {