Support SystemVerilog size cast.
This commit is contained in:
parent
873a447b5c
commit
557e331ce1
9
PExpr.cc
9
PExpr.cc
|
|
@ -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);
|
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)
|
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
||||||
: PEBinary(op, l, r)
|
: PEBinary(op, l, r)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
23
PExpr.h
23
PExpr.h
|
|
@ -706,6 +706,29 @@ class PECallFunction : public PExpr {
|
||||||
width_mode_t&mode);
|
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
|
* This class is used for error recovery. All methods do nothing and return
|
||||||
* null or default values.
|
* null or default values.
|
||||||
|
|
|
||||||
20
elab_expr.cc
20
elab_expr.cc
|
|
@ -1423,6 +1423,26 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
return 0;
|
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&)
|
unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
|
||||||
{
|
{
|
||||||
expr_width_ = 0;
|
expr_width_ = 0;
|
||||||
|
|
|
||||||
|
|
@ -688,6 +688,8 @@ TU [munpf]
|
||||||
<< endl;
|
<< endl;
|
||||||
error_count += 1; }
|
error_count += 1; }
|
||||||
|
|
||||||
|
. { return yytext[0]; }
|
||||||
|
|
||||||
/* Final catchall. something got lost or mishandled. */
|
/* Final catchall. something got lost or mishandled. */
|
||||||
/* XXX Should we tell the user something about the lexical state? */
|
/* XXX Should we tell the user something about the lexical state? */
|
||||||
|
|
||||||
|
|
|
||||||
113
parse.y
113
parse.y
|
|
@ -1600,29 +1600,29 @@ expression_list_proper
|
||||||
;
|
;
|
||||||
|
|
||||||
expr_primary
|
expr_primary
|
||||||
: number
|
: number
|
||||||
{ assert($1);
|
{ assert($1);
|
||||||
PENumber*tmp = new PENumber($1);
|
PENumber*tmp = new PENumber($1);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| REALTIME
|
| REALTIME
|
||||||
{ PEFNumber*tmp = new PEFNumber($1);
|
{ PEFNumber*tmp = new PEFNumber($1);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| STRING
|
| STRING
|
||||||
{ PEString*tmp = new PEString($1);
|
{ PEString*tmp = new PEString($1);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| SYSTEM_IDENTIFIER
|
| SYSTEM_IDENTIFIER
|
||||||
{ perm_string tn = lex_strings.make($1);
|
{ perm_string tn = lex_strings.make($1);
|
||||||
PECallFunction*tmp = new PECallFunction(tn);
|
PECallFunction*tmp = new PECallFunction(tn);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The hierarchy_identifier rule matches simple identifiers as well as
|
/* The hierarchy_identifier rule matches simple identifiers as well as
|
||||||
indexed arrays and part selects */
|
indexed arrays and part selects */
|
||||||
|
|
@ -1836,35 +1836,50 @@ expr_primary
|
||||||
|
|
||||||
/* Parenthesized expressions are primaries. */
|
/* Parenthesized expressions are primaries. */
|
||||||
|
|
||||||
| '(' expr_mintypmax ')'
|
| '(' expr_mintypmax ')'
|
||||||
{ $$ = $2; }
|
{ $$ = $2; }
|
||||||
|
|
||||||
/* Various kinds of concatenation expressions. */
|
/* Various kinds of concatenation expressions. */
|
||||||
|
|
||||||
| '{' expression_list_proper '}'
|
| '{' expression_list_proper '}'
|
||||||
{ PEConcat*tmp = new PEConcat(*$2);
|
{ PEConcat*tmp = new PEConcat(*$2);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
delete $2;
|
delete $2;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| '{' expression '{' expression_list_proper '}' '}'
|
| '{' expression '{' expression_list_proper '}' '}'
|
||||||
{ PExpr*rep = $2;
|
{ PExpr*rep = $2;
|
||||||
PEConcat*tmp = new PEConcat(*$4, rep);
|
PEConcat*tmp = new PEConcat(*$4, rep);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
delete $4;
|
delete $4;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| '{' expression '{' expression_list_proper '}' error '}'
|
| '{' expression '{' expression_list_proper '}' error '}'
|
||||||
{ PExpr*rep = $2;
|
{ PExpr*rep = $2;
|
||||||
PEConcat*tmp = new PEConcat(*$4, rep);
|
PEConcat*tmp = new PEConcat(*$4, rep);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
delete $4;
|
delete $4;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
yyerror(@5, "error: Syntax error between internal '}' "
|
yyerror(@5, "error: Syntax error between internal '}' "
|
||||||
"and closing '}' of repeat concatenation.");
|
"and closing '}' of repeat concatenation.");
|
||||||
yyerrok;
|
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
|
/* A function_item_list borrows the task_port_item run to match
|
||||||
declarations of ports. We check later to make sure there are no
|
declarations of ports. We check later to make sure there are no
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,13 @@ void PECallFunction::dump(ostream &out) const
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PECastSize::dump(ostream &out) const
|
||||||
|
{
|
||||||
|
out << size_ << "'(";
|
||||||
|
base_->dump(out);
|
||||||
|
out << ")";
|
||||||
|
}
|
||||||
|
|
||||||
void PEEvent::dump(ostream&out) const
|
void PEEvent::dump(ostream&out) const
|
||||||
{
|
{
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue