Simplify edge detector code

Now generates a `wait until' statement rather than a
sensitivity list.
This commit is contained in:
Nick Gasson 2008-07-14 20:29:49 +01:00
parent d22c9a8b05
commit 99ef8ec4f1
3 changed files with 44 additions and 79 deletions

View File

@ -161,7 +161,7 @@ static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container,
&& container == proc->get_container() // Top-level container
&& !isvar) {
decl->set_initial(rhs);
// decl->set_initial(new vhdl_expr(*rhs));
/*if (blocking && proc->get_scope()->allow_signal_assignment()) {
// This signal may be used e.g. in a loop test so we need
@ -183,9 +183,8 @@ static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container,
return a;
}
else*/
return NULL; // No statement need be emitted
}
else {
/*if (blocking && proc->get_scope()->allow_signal_assignment()) {
// Remember we need to write the variable back to the
// original signal
@ -205,7 +204,6 @@ static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container,
container->add_stmt(a);
return a;
}
}
/*
@ -280,11 +278,8 @@ static int draw_nbassign(vhdl_procedural *proc, stmt_container *container,
vhdl_nbassign_stmt *a =
make_assignment<vhdl_nbassign_stmt>(proc, container, stmt, false);
if (a != NULL) {
// Assignment is a statement and not moved into the initialisation
if (after != NULL)
a->set_after(after);
}
if (after != NULL)
a->set_after(after);
return 0;
}
@ -298,14 +293,12 @@ static int draw_assign(vhdl_procedural *proc, stmt_container *container,
vhdl_nbassign_stmt *a =
make_assignment<vhdl_nbassign_stmt>(proc, container, stmt, false);
if (a != NULL) {
// Assignment is a statement and not moved into the initialisation
//if (after != NULL)
// a->set_after(after);
// Assignment is a statement and not moved into the initialisation
//if (after != NULL)
// a->set_after(after);
container->add_stmt
(new vhdl_wait_stmt(VHDL_WAIT_FOR, new vhdl_const_time(0)));
}
container->add_stmt
(new vhdl_wait_stmt(VHDL_WAIT_FOR, new vhdl_const_time(0)));
}
else
make_assignment<vhdl_assign_stmt>(proc, container, stmt, true);
@ -404,83 +397,48 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
vhdl_process *proc = dynamic_cast<vhdl_process*>(_proc);
assert(proc); // Catch not process
ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt);
vhdl_binop_expr *test =
new vhdl_binop_expr(VHDL_BINOP_OR, vhdl_type::boolean());
// TODO: This should really be merged with the
// nexus_to_XXX code
int nevents = ivl_stmt_nevent(stmt);
for (int i = 0; i < nevents; i++) {
ivl_event_t event = ivl_stmt_events(stmt, i);
// A list of the non-edge triggered signals to they can
// be added to the edge-detecting `if' statement later
string_list_t non_edges;
int nany = ivl_event_nany(event);
for (int i = 0; i < nany; i++) {
ivl_nexus_t nexus = ivl_event_any(event, i);
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
int nptrs = ivl_nexus_ptrs(nexus);
for (int j = 0; j < nptrs; j++) {
ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, j);
ivl_signal_t sig;
if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) {
if (!seen_signal_before(sig))
continue;
std::string signame(get_renamed_signal(sig));
// Only add this signal to the sensitivity if it's part
// of the containing architecture (i.e. it has already
// been declared)
if (proc->get_scope()->get_parent()->have_declared(signame)) {
proc->add_sensitivity(signame.c_str());
non_edges.push_back(signame);
break;
}
}
else {
// Ignore all other types of nexus pointer
}
}
ref->set_name(ref->get_name() + "'Event");
test->add_expr(ref);
}
int nneg = ivl_event_nneg(event);
int npos = ivl_event_npos(event);
if (nneg + npos > 0) {
vhdl_binop_expr *test =
new vhdl_binop_expr(VHDL_BINOP_OR, vhdl_type::boolean());
for (int i = 0; i < nneg; i++) {
ivl_nexus_t nexus = ivl_event_neg(event, i);
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
vhdl_fcall *detect =
new vhdl_fcall("falling_edge", vhdl_type::boolean());
detect->add_expr(ref);
// Generate falling_edge(..) calls for each negedge event
for (int i = 0; i < nneg; i++)
edge_detector(ivl_event_neg(event, i), proc, test, "falling_edge");
// Generate rising_edge(..) calls for each posedge event
for (int i = 0; i < npos; i++)
edge_detector(ivl_event_pos(event, i), proc, test, "rising_edge");
// Add Name'Event terms for each non-edge-triggered signal
string_list_t::iterator it;
for (it = non_edges.begin(); it != non_edges.end(); ++it) {
test->add_expr
(new vhdl_var_ref((*it + "'Event").c_str(),
vhdl_type::boolean()));
}
vhdl_if_stmt *edge_det = new vhdl_if_stmt(test);
container->add_stmt(edge_det);
draw_stmt(proc, edge_det->get_then_container(), sub_stmt);
test->add_expr(detect);
}
else {
// Don't bother generating an edge detector if there
// are no edge-triggered events
draw_stmt(proc, container, sub_stmt);
int npos = ivl_event_npos(event);
for (int i = 0; i < npos; i++) {
ivl_nexus_t nexus = ivl_event_pos(event, i);
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
vhdl_fcall *detect =
new vhdl_fcall("rising_edge", vhdl_type::boolean());
detect->add_expr(ref);
test->add_expr(detect);
}
}
draw_stmt(proc, container, ivl_stmt_sub_stmt(stmt));
container->add_stmt(new vhdl_wait_stmt(VHDL_WAIT_UNTIL, test));
return 0;
}

View File

@ -293,6 +293,11 @@ void vhdl_wait_stmt::emit(std::ostream &of, int level) const
of << " for ";
expr_->emit(of, level);
break;
case VHDL_WAIT_UNTIL:
assert(expr_);
of << " until ";
expr_->emit(of, level);
break;
}
of << ";";

View File

@ -56,6 +56,7 @@ public:
void emit(std::ostream &of, int level) const;
const std::string &get_name() const { return name_; }
void set_name(const std::string &name) { name_ = name; }
void set_slice(vhdl_expr *s, int w=0);
private:
std::string name_;
@ -303,6 +304,7 @@ public:
enum vhdl_wait_type_t {
VHDL_WAIT_INDEF, // Suspend indefinitely
VHDL_WAIT_FOR, // Wait for a constant amount of time
VHDL_WAIT_UNTIL, // Wait on a sensitivity list
};
/*