Add support for wait fork to the compiler and code generators

This commit is contained in:
Cary R 2013-10-22 09:39:25 -07:00
parent 61fbfb562e
commit 97d06b107f
10 changed files with 134 additions and 5 deletions

View File

@ -391,6 +391,7 @@ class PEventStatement : public Statement {
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
NetProc* elaborate_wait(Design*des, NetScope*scope, NetProc*st) const;
NetProc* elaborate_wait_fork(Design*des, NetScope*scope) const;
private:
svector<PEEvent*>expr_;

View File

@ -1077,7 +1077,15 @@ void NetEvTrig::dump(ostream&o, unsigned ind) const
void NetEvWait::dump(ostream&o, unsigned ind) const
{
o << setw(ind) <<"" << "@(";
o << setw(ind) << "";
/* Check for a wait fork. */
if ((nevents() == 1) && (event(0) == 0)) {
o << "wait fork;";
return;
}
o << "@(";
if (nevents() > 0)
o << event(0)->name();
@ -1101,6 +1109,12 @@ ostream& operator << (ostream&out, const NetEvWait&obj)
void NetEvWait::dump_inline(ostream&o) const
{
/* Check for a wait fork. */
if ((nevents() == 1) && (event(0) == 0)) {
o << "wait fork;";
return;
}
o << "@(";
if (nevents() > 0)

View File

@ -4232,9 +4232,57 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
return block;
}
/*
* This is a special case of the event statement, the wait fork
* statement. This is elaborated into a simplified statement.
*
* wait fork;
*
* becomes
*
* @(0) <noop>;
*/
NetProc* PEventStatement::elaborate_wait_fork(Design*des, NetScope*scope) const
{
assert(scope);
assert(expr_.count() == 1);
assert(expr_[0] == 0);
assert(! statement_);
if (scope->in_func()) {
cerr << get_fileline() << ": error: functions cannot have "
"wait fork statements." << endl;
des->errors += 1;
return 0;
}
if (scope->in_final()) {
cerr << get_fileline() << ": error: final procedures cannot "
"have wait fork statements." << endl;
des->errors += 1;
return 0;
}
if (gn_system_verilog()) {
NetEvWait*wait = new NetEvWait(0 /* noop */);
wait->add_event(0);
wait->set_line(*this);
return wait;
} else {
cerr << get_fileline()
<< ": error: 'wait fork' requires SystemVerilog." << endl;
des->errors += 1;
return 0;
}
}
NetProc* PEventStatement::elaborate(Design*des, NetScope*scope) const
{
/* Check to see if this is a wait fork statement. */
if ((expr_.count() == 1) && (expr_[0] == 0))
return elaborate_wait_fork(des, scope);
NetProc*enet = 0;
if (statement_) {
enet = statement_->elaborate(des, scope);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-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
@ -372,11 +372,20 @@ NetEvWait::~NetEvWait()
void NetEvWait::add_event(NetEvent*tgt)
{
assert(tgt);
/* A wait fork is an empty event. */
if (! tgt) {
assert(nevents_ == 0);
nevents_ = 1;
events_ = new NetEvent*[1];
events_[0] = 0;
return;
}
if (nevents_ == 0) {
events_ = new NetEvent*[1];
} else {
assert(events_[0]);
NetEvent**tmp = new NetEvent*[nevents_+1];
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
tmp[idx] = events_[idx];

View File

@ -5784,6 +5784,11 @@ statement_item /* This is roughly statement_item in the LRM */
tmp->set_statement($5);
$$ = tmp;
}
| K_wait K_fork ';'
{ PEventStatement*tmp = new PEventStatement(0);
FILE_NAME(tmp,@1);
$$ = tmp;
}
| SYSTEM_IDENTIFIER '(' expression_list_with_nuls ')' ';'
{ PCallTask*tmp = new PCallTask(lex_strings.make($1), *$3);
FILE_NAME(tmp,@1);

View File

@ -874,6 +874,9 @@ void PEventStatement::dump(ostream&out, unsigned ind) const
if (expr_.count() == 0) {
out << setw(ind) << "" << "@* ";
} else if ((expr_.count() == 1) && (expr_[0] == 0)) {
out << setw(ind) << "" << "wait fork ";
} else {
out << setw(ind) << "" << "@(" << *(expr_[0]);
if (expr_.count() > 1)

View File

@ -805,8 +805,17 @@ bool dll_target::proc_wait(const NetEvWait*net)
stmt_cur_->u_.wait_.stmt_ = (struct ivl_statement_s*)
calloc(1, sizeof(struct ivl_statement_s));
// This event processing code is also in the NB assign above.
stmt_cur_->u_.wait_.nevent = net->nevents();
/* This is a wait fork statement. */
if ((net->nevents() == 1) && (net->event(0) == 0)) {
stmt_cur_->u_.wait_.event = 0;
stmt_cur_->type_ = IVL_ST_WAIT;
stmt_cur_->u_.wait_.stmt_->type_ = IVL_ST_NOOP;
return true;
}
// This event processing code is also in the NB assign above.
if (net->nevents() > 1) {
stmt_cur_->u_.wait_.events = (ivl_event_t*)
calloc(net->nevents(), sizeof(ivl_event_t*));

View File

@ -231,7 +231,16 @@ void show_stmt_wait(ivl_statement_t net, unsigned ind)
{
unsigned idx;
const char*comma = "";
fprintf(out, "%*s@(", ind, "");
fprintf(out, "%*s", ind, "");
/* Emit a SystemVerilog wait fork. */
if ((ivl_stmt_nevent(net) == 1) && (ivl_stmt_events(net, 0) == 0)) {
assert(ivl_statement_type(ivl_stmt_sub_stmt(net)) == IVL_ST_NOOP);
fprintf(out, "wait fork;\n");
return;
}
fprintf(out, "@(");
for (idx = 0 ; idx < ivl_stmt_nevent(net) ; idx += 1) {
ivl_event_t evnt = ivl_stmt_events(net, idx);

View File

@ -1408,6 +1408,23 @@ static void emit_stmt_utask(ivl_scope_t scope, ivl_statement_t stmt)
fprintf(vlog_out, "\n");
}
/* Look to see if this is a SystemVerilog wait fork statement. */
static unsigned is_wait_fork(ivl_scope_t scope, ivl_statement_t stmt)
{
if (ivl_stmt_nevent(stmt) != 1) return 0;
if (ivl_stmt_events(stmt, 0) != 0) return 0;
assert(ivl_statement_type(ivl_stmt_sub_stmt(stmt)) == IVL_ST_NOOP);
fprintf(vlog_out, "%*cwait fork;", get_indent(), ' ');
emit_stmt_file_line(stmt);
fprintf(vlog_out, "\n");
fprintf(stderr, "%s:%u: vlog95 sorry: wait fork is not currently "
"translated.\n",
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt));
vlog_errors += 1;
return 1;
}
static void emit_stmt_wait(ivl_scope_t scope, ivl_statement_t stmt)
{
fprintf(vlog_out, "%*c@(", get_indent(), ' ');
@ -1540,6 +1557,7 @@ void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt)
emit_stmt_utask(scope, stmt);
break;
case IVL_ST_WAIT:
if (is_wait_fork(scope, stmt)) break;
emit_stmt_wait(scope, stmt);
break;
case IVL_ST_WHILE:

View File

@ -1724,6 +1724,19 @@ static int show_stmt_utask(ivl_statement_t net)
static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope)
{
/* Look to see if this is a SystemVerilog wait fork. */
if ((ivl_stmt_nevent(net) == 1) && (ivl_stmt_events(net, 0) == 0)) {
assert(ivl_statement_type(ivl_stmt_sub_stmt(net)) == IVL_ST_NOOP);
show_stmt_file_line(net, "Wait fork statement.");
fprintf(vvp_out, " %%wait_fork;\n");
fprintf(stderr, "%s:%u: vvp.tgt sorry: wait fork is not currently "
"supported.\n",
ivl_stmt_file(net), ivl_stmt_lineno(net));
vvp_errors += 1;
return 0;
}
show_stmt_file_line(net, "Event wait (@) statement.");
if (ivl_stmt_nevent(net) == 1) {