Add support for SystemVerilog return statements.

This commit is contained in:
Stephen Williams 2013-05-23 19:59:57 -07:00
parent dca6171f5f
commit 1b178d56b7
6 changed files with 112 additions and 7 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2008,2010,2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008,2010,2012-2013 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -329,6 +329,16 @@ PRepeat::~PRepeat()
delete statement_;
}
PReturn::PReturn(PExpr*e)
: expr_(e)
{
}
PReturn::~PReturn()
{
delete expr_;
}
PTrigger::PTrigger(const pform_name_t&e)
: event_(e)
{

View File

@ -462,6 +462,19 @@ class PRelease : public Statement {
PExpr*lval_;
};
class PReturn : public Statement {
public:
explicit PReturn(PExpr*e);
~PReturn();
NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
private:
PExpr*expr_;
};
/*
* The PTrigger statement sends a trigger to a named event. Take the
* name here.

View File

@ -4443,6 +4443,69 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
return proc;
}
NetProc* PReturn::elaborate(Design*des, NetScope*scope) const
{
NetScope*target = scope;
for (;;) {
if (target == 0) {
cerr << get_fileline() << ": error: "
<< "Return statement is not in a function." << endl;
des->errors += 1;
return 0;
}
if (target->type() == NetScope::FUNC)
break;
if (target->type() == NetScope::TASK) {
cerr << get_fileline() << ": error: "
<< "Cannot \"return\" from tasks." << endl;
des->errors += 1;
return 0;
}
if (target->type()==NetScope::BEGIN_END) {
target = target->parent();
continue;
}
cerr << get_fileline() << ": error: "
<< "Cannot \"return\" from this scope: " << scope_path(target) << endl;
des->errors += 1;
return 0;
}
// We don't yet support void functions, so require an
// expression for the return statement.
if (expr_ == 0) {
cerr << get_fileline() << ": error: "
<< "Return from " << scope_path(target)
<< " requires a return value expression." << endl;
des->errors += 1;
return 0;
}
NetNet*res = target->find_signal(target->basename());
ivl_variable_type_t lv_type = res->data_type();
unsigned long wid = res->vector_width();
NetAssign_*lv = new NetAssign_(res);
NetExpr*val = elaborate_rval_expr(des, scope, lv_type, wid, expr_);
NetBlock*proc = new NetBlock(NetBlock::SEQU, 0);
proc->set_line( *this );
NetAssign*assn = new NetAssign(lv, val);
assn->set_line( *this );
proc->append(assn);
NetDisable*disa = new NetDisable(target);
disa->set_line( *this );
proc->append( disa );
return proc;
}
/*
* A task definition is elaborated by elaborating the statement that
* it contains, and connecting its ports to NetNet objects. The

10
parse.y
View File

@ -1229,12 +1229,14 @@ jump_statement /* IEEE1800-2005: A.6.5 */
$$ = 0;
}
| K_return ';'
{ yyerror(@1, "sorry: return statements not supported.");
$$ = 0;
{ PReturn*tmp = new PReturn(0);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_return expression ';'
{ yyerror(@1, "sorry: return statements not supported.");
$$ = 0;
{ PReturn*tmp = new PReturn($2);
FILE_NAME(tmp, @1);
$$ = tmp;
}
;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -928,6 +928,13 @@ void PRepeat::dump(ostream&out, unsigned ind) const
statement_->dump(out, ind+3);
}
void PReturn::dump(ostream&fd, unsigned ind) const
{
fd << setw(ind) << "" << "return (";
if (expr_) fd << *expr_;
fd << ")" << endl;
}
void PTask::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "task ";

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-2013 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -153,6 +153,12 @@ static void show_stmt_delayx(ivl_statement_t net, unsigned ind)
show_statement(ivl_stmt_sub_stmt(net), ind+2);
}
static void show_stmt_disable(ivl_statement_t net, unsigned ind)
{
ivl_scope_t scope = ivl_stmt_call(net);
fprintf(out, "%*sdisable %s\n", ind, "", ivl_scope_basename(scope));
}
static void show_stmt_force(ivl_statement_t net, unsigned ind)
{
unsigned idx;
@ -378,6 +384,10 @@ void show_statement(ivl_statement_t net, unsigned ind)
show_stmt_delayx(net, ind);
break;
case IVL_ST_DISABLE:
show_stmt_disable(net, ind);
break;
case IVL_ST_FORCE:
show_stmt_force(net, ind);
break;