diff --git a/elaborate.cc b/elaborate.cc index 0fb01c6b4..15f3d9602 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -4208,6 +4208,9 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, if (synthesis || search_funcs_) { rem_out = true; } + // If this is an always_comp/latch then we need an implicit T0 + // trigger of the event expression. + if (search_funcs_) wa->set_t0_trigger(); NexusSet*nset = enet->nex_input(rem_out, search_funcs_); if (nset == 0) { cerr << get_fileline() << ": error: Unable to elaborate:" @@ -6111,7 +6114,7 @@ bool Design::check_proc_delay() const for (const NetProcTop*pr = procs_ ; pr ; pr = pr->next_) { /* If this is an always block and we have no or zero delay then - * a runtime infinite loop will happen. If we possible have some + * a runtime infinite loop will happen. If we possibly have some * delay then print a warning that an infinite loop is possible. */ if ((pr->type() == IVL_PR_ALWAYS) || diff --git a/ivl.def b/ivl.def index 5fee414ef..39682eaf5 100644 --- a/ivl.def +++ b/ivl.def @@ -294,6 +294,7 @@ ivl_stmt_lval ivl_stmt_lvals ivl_stmt_lwidth ivl_stmt_name +ivl_stmt_needs_t0_trigger ivl_stmt_nevent ivl_stmt_opcode ivl_stmt_parm diff --git a/ivl_target.h b/ivl_target.h index 22342affb..f3fed5669 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -2105,6 +2105,7 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net); * handle disable statements. * * ivl_stmt_events + * ivl_stmt_needs_t0_trigger * ivl_stmt_nevent * Statements that have event arguments (TRIGGER and WAIT) make * those event objects available through these methods. @@ -2232,6 +2233,7 @@ extern ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net); /* IVL_ST_DELAY */ extern uint64_t ivl_stmt_delay_val(ivl_statement_t net); /* IVL_ST_WAIT IVL_ST_TRIGGER */ +extern unsigned ivl_stmt_needs_t0_trigger(ivl_statement_t net); extern unsigned ivl_stmt_nevent(ivl_statement_t net); extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx); /* IVL_ST_CONTRIB */ diff --git a/netlist.h b/netlist.h index 18abc161b..ad8a78f9f 100644 --- a/netlist.h +++ b/netlist.h @@ -3398,10 +3398,12 @@ class NetEvWait : public NetProc { void add_event(NetEvent*tgt); void replace_event(NetEvent*orig, NetEvent*repl); + inline void set_t0_trigger() { has_t0_trigger_ = true; }; inline unsigned nevents() const { return events_.size(); } inline const NetEvent*event(unsigned idx) const { return events_[idx]; } inline NetEvent*event(unsigned idx) { return events_[idx]; } + inline bool has_t0_trigger() const { return has_t0_trigger_; }; NetProc*statement(); @@ -3442,6 +3444,7 @@ class NetEvWait : public NetProc { NetProc*statement_; // Events that I might wait for. std::vectorevents_; + bool has_t0_trigger_; }; ostream& operator << (ostream&out, const NetEvWait&obj); diff --git a/t-dll-api.cc b/t-dll-api.cc index 9c8283ab3..a32950437 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -2815,6 +2815,16 @@ extern "C" uint64_t ivl_stmt_delay_val(ivl_statement_t net) return net->u_.delay_.value; } +extern "C" unsigned ivl_stmt_needs_t0_trigger(ivl_statement_t net) +{ + assert(net); + if (net->type_ == IVL_ST_WAIT) { + return net->u_.wait_.needs_t0_trigger; + } else { + return 0; + } +} + extern "C" unsigned ivl_stmt_nevent(ivl_statement_t net) { assert(net); diff --git a/t-dll-proc.cc b/t-dll-proc.cc index e668919eb..ba0d4b1a0 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 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 @@ -847,12 +847,15 @@ bool dll_target::proc_wait(const NetEvWait*net) /* This is a wait fork statement. */ if ((net->nevents() == 1) && (net->event(0) == 0)) { + stmt_cur_->u_.wait_.needs_t0_trigger = 0; stmt_cur_->u_.wait_.event = 0; stmt_cur_->type_ = IVL_ST_WAIT; stmt_cur_->u_.wait_.stmt_->type_ = IVL_ST_NOOP; return true; } + stmt_cur_->u_.wait_.needs_t0_trigger = net->has_t0_trigger(); + // This event processing code is also in the NB assign above. if (net->nevents() > 1) { stmt_cur_->u_.wait_.events = (ivl_event_t*) diff --git a/t-dll.h b/t-dll.h index 31b2106a1..879a5c966 100644 --- a/t-dll.h +++ b/t-dll.h @@ -862,6 +862,7 @@ struct ivl_statement_s { } utask_; struct { /* IVL_ST_TRIGGER IVL_ST_WAIT */ + unsigned needs_t0_trigger; unsigned nevent; union { ivl_event_t event;