Remove some uneccessary zero-time waits from VHDL outputs

This patch optimises away straight line sequences like:

wait for 0 ns;
wait for X ns;

to:

wait for X ns;

This tidies up the output a bit.

It also has the effect of removing all code from initial
processes where the assignments have been extracted as
VHDL signal intialisers. (c.f. pr2391337)
This commit is contained in:
Nick Gasson 2008-12-07 19:01:18 +00:00 committed by Stephen Williams
parent 712e08ebe8
commit 651d208451
5 changed files with 43 additions and 7 deletions

View File

@ -56,10 +56,15 @@ static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc)
// However, if no statements were added to the container
// by draw_stmt, don't bother adding a wait as `emit'
// will optimise the process out of the output
if (ivl_process_type(proc) == IVL_PR_INITIAL
&& !vhdl_proc->get_container()->empty()) {
vhdl_wait_stmt *wait = new vhdl_wait_stmt();
vhdl_proc->get_container()->add_stmt(wait);
if (ivl_process_type(proc) == IVL_PR_INITIAL) {
// Get rid of any useless `wait for 0 ns's at the end of the process
prune_wait_for_0(vhdl_proc->get_container());
// The above pruning might have removed all logic from the process
if (!vhdl_proc->get_container()->empty()) {
vhdl_wait_stmt *wait = new vhdl_wait_stmt();
vhdl_proc->get_container()->add_stmt(wait);
}
}
// Add a comment indicating where it came from

View File

@ -396,7 +396,7 @@ static int draw_assign(vhdl_procedural *proc, stmt_container *container,
// the process
if (!is_last)
container->add_stmt
(new vhdl_wait_stmt(VHDL_WAIT_FOR, new vhdl_const_time(0)));
(new vhdl_wait_stmt(VHDL_WAIT_FOR0));
}
else
make_assignment(proc, container, stmt, true);
@ -404,6 +404,27 @@ static int draw_assign(vhdl_procedural *proc, stmt_container *container,
return 0;
}
/*
* The VHDL code generator inserts `wait for 0 ns' after each
* not-last-in-block blocking assignment.
* If this is immediately followed by another `wait for ...' then
* we might as well not emit the first zero-time wait.
*/
void prune_wait_for_0(stmt_container *container)
{
vhdl_wait_stmt *wait0;
stmt_container::stmt_list_t &stmts = container->get_stmts();
while (stmts.size() > 0
&& (wait0 = dynamic_cast<vhdl_wait_stmt*>(stmts.back()))) {
if (wait0->get_type() == VHDL_WAIT_FOR0) {
delete wait0;
stmts.pop_back();
}
else
break;
}
}
/*
* Delay statements are equivalent to the `wait for' form of the
* VHDL wait statement.
@ -429,6 +450,8 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container,
return 1;
}
prune_wait_for_0(container);
ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt);
vhdl_wait_stmt *wait =
new vhdl_wait_stmt(VHDL_WAIT_FOR, time);

View File

@ -316,6 +316,9 @@ void vhdl_wait_stmt::emit(std::ostream &of, int level) const
of << " for ";
expr_->emit(of, level);
break;
case VHDL_WAIT_FOR0:
of << " for 0 ns";
break;
case VHDL_WAIT_UNTIL:
assert(expr_);
of << " until ";

View File

@ -335,8 +335,11 @@ public:
void add_stmt(vhdl_seq_stmt *stmt);
void emit(std::ostream &of, int level, bool newline=true) const;
bool empty() const { return stmts_.empty(); }
typedef std::list<vhdl_seq_stmt*> stmt_list_t;
stmt_list_t &get_stmts() { return stmts_; }
private:
std::list<vhdl_seq_stmt*> stmts_;
stmt_list_t stmts_;
};
@ -381,6 +384,7 @@ public:
enum vhdl_wait_type_t {
VHDL_WAIT_INDEF, // Suspend indefinitely
VHDL_WAIT_FOR, // Wait for a constant amount of time
VHDL_WAIT_FOR0, // Special wait for zero time
VHDL_WAIT_UNTIL, // Wait on an expression
VHDL_WAIT_ON, // Wait on a sensitivity list
};
@ -398,6 +402,7 @@ public:
void emit(std::ostream &of, int level) const;
void add_sensitivity(const std::string &s) { sensitivity_.push_back(s); }
vhdl_wait_type_t get_type() const { return type_; }
private:
vhdl_wait_type_t type_;
vhdl_expr *expr_;

View File

@ -44,7 +44,7 @@ ivl_signal_t find_signal_named(const string &name, const vhdl_scope *scope);
int draw_stask_display(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, bool newline = true);
void prune_wait_for_0(stmt_container *container);
void require_support_function(support_function_t f);
#endif /* #ifndef INC_VHDL_TARGET_H */