Simplify edge detector code
Now generates a `wait until' statement rather than a sensitivity list.
This commit is contained in:
parent
d22c9a8b05
commit
99ef8ec4f1
|
|
@ -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
|
||||
|
|
@ -206,7 +205,6 @@ static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container,
|
|||
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate an assignment of type T for the Verilog statement stmt.
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -298,7 +293,6 @@ 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);
|
||||
|
|
@ -306,7 +300,6 @@ static int draw_assign(vhdl_procedural *proc, stmt_container *container,
|
|||
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);
|
||||
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);
|
||||
|
||||
test->add_expr(detect);
|
||||
}
|
||||
|
||||
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 < 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
else {
|
||||
// Don't bother generating an edge detector if there
|
||||
// are no edge-triggered events
|
||||
draw_stmt(proc, container, sub_stmt);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 << ";";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue