Pass to the targets if an implicit T0 trigger event is needed.

This commit is contained in:
Cary R 2017-11-24 12:35:02 -08:00
parent 585a0232cb
commit 84d0df8a8a
7 changed files with 25 additions and 2 deletions

View File

@ -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) ||

View File

@ -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

View File

@ -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 */

View File

@ -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::vector<NetEvent*>events_;
bool has_t0_trigger_;
};
ostream& operator << (ostream&out, const NetEvWait&obj);

View File

@ -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);

View File

@ -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*)

View File

@ -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;