Add support for wait fork to the compiler and code generators
This commit is contained in:
parent
61fbfb562e
commit
97d06b107f
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
48
elaborate.cc
48
elaborate.cc
|
|
@ -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);
|
||||
|
|
|
|||
13
net_event.cc
13
net_event.cc
|
|
@ -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];
|
||||
|
|
|
|||
5
parse.y
5
parse.y
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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*));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue