Add support for SystemVerilog return statements.
This commit is contained in:
parent
dca6171f5f
commit
1b178d56b7
12
Statement.cc
12
Statement.cc
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
13
Statement.h
13
Statement.h
|
|
@ -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.
|
||||
|
|
|
|||
63
elaborate.cc
63
elaborate.cc
|
|
@ -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
10
parse.y
|
|
@ -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;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue