Simplify edge detector code
Now generates a `wait until' statement rather than a sensitivity list.
This commit is contained in:
parent
d22c9a8b05
commit
99ef8ec4f1
116
tgt-vhdl/stmt.cc
116
tgt-vhdl/stmt.cc
|
|
@ -161,7 +161,7 @@ static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
&& container == proc->get_container() // Top-level container
|
&& container == proc->get_container() // Top-level container
|
||||||
&& !isvar) {
|
&& !isvar) {
|
||||||
|
|
||||||
decl->set_initial(rhs);
|
// decl->set_initial(new vhdl_expr(*rhs));
|
||||||
|
|
||||||
/*if (blocking && proc->get_scope()->allow_signal_assignment()) {
|
/*if (blocking && proc->get_scope()->allow_signal_assignment()) {
|
||||||
// This signal may be used e.g. in a loop test so we need
|
// 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;
|
return a;
|
||||||
}
|
}
|
||||||
else*/
|
else*/
|
||||||
return NULL; // No statement need be emitted
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
/*if (blocking && proc->get_scope()->allow_signal_assignment()) {
|
/*if (blocking && proc->get_scope()->allow_signal_assignment()) {
|
||||||
// Remember we need to write the variable back to the
|
// Remember we need to write the variable back to the
|
||||||
// original signal
|
// original signal
|
||||||
|
|
@ -205,7 +204,6 @@ static T *make_vhdl_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
container->add_stmt(a);
|
container->add_stmt(a);
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -279,12 +277,9 @@ static int draw_nbassign(vhdl_procedural *proc, stmt_container *container,
|
||||||
|
|
||||||
vhdl_nbassign_stmt *a =
|
vhdl_nbassign_stmt *a =
|
||||||
make_assignment<vhdl_nbassign_stmt>(proc, container, stmt, false);
|
make_assignment<vhdl_nbassign_stmt>(proc, container, stmt, false);
|
||||||
|
|
||||||
if (a != NULL) {
|
if (after != NULL)
|
||||||
// Assignment is a statement and not moved into the initialisation
|
a->set_after(after);
|
||||||
if (after != NULL)
|
|
||||||
a->set_after(after);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -298,14 +293,12 @@ static int draw_assign(vhdl_procedural *proc, stmt_container *container,
|
||||||
vhdl_nbassign_stmt *a =
|
vhdl_nbassign_stmt *a =
|
||||||
make_assignment<vhdl_nbassign_stmt>(proc, container, stmt, false);
|
make_assignment<vhdl_nbassign_stmt>(proc, container, stmt, false);
|
||||||
|
|
||||||
if (a != NULL) {
|
// Assignment is a statement and not moved into the initialisation
|
||||||
// Assignment is a statement and not moved into the initialisation
|
//if (after != NULL)
|
||||||
//if (after != NULL)
|
// a->set_after(after);
|
||||||
// a->set_after(after);
|
|
||||||
|
container->add_stmt
|
||||||
container->add_stmt
|
(new vhdl_wait_stmt(VHDL_WAIT_FOR, new vhdl_const_time(0)));
|
||||||
(new vhdl_wait_stmt(VHDL_WAIT_FOR, new vhdl_const_time(0)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
make_assignment<vhdl_assign_stmt>(proc, container, stmt, true);
|
make_assignment<vhdl_assign_stmt>(proc, container, stmt, true);
|
||||||
|
|
@ -403,83 +396,48 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
|
||||||
// Wait statements only occur in processes
|
// Wait statements only occur in processes
|
||||||
vhdl_process *proc = dynamic_cast<vhdl_process*>(_proc);
|
vhdl_process *proc = dynamic_cast<vhdl_process*>(_proc);
|
||||||
assert(proc); // Catch not process
|
assert(proc); // Catch not process
|
||||||
|
|
||||||
ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt);
|
|
||||||
|
|
||||||
|
vhdl_binop_expr *test =
|
||||||
// TODO: This should really be merged with the
|
new vhdl_binop_expr(VHDL_BINOP_OR, vhdl_type::boolean());
|
||||||
// nexus_to_XXX code
|
|
||||||
int nevents = ivl_stmt_nevent(stmt);
|
int nevents = ivl_stmt_nevent(stmt);
|
||||||
for (int i = 0; i < nevents; i++) {
|
for (int i = 0; i < nevents; i++) {
|
||||||
ivl_event_t event = ivl_stmt_events(stmt, 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);
|
int nany = ivl_event_nany(event);
|
||||||
for (int i = 0; i < nany; i++) {
|
for (int i = 0; i < nany; i++) {
|
||||||
ivl_nexus_t nexus = ivl_event_any(event, 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);
|
ref->set_name(ref->get_name() + "'Event");
|
||||||
for (int j = 0; j < nptrs; j++) {
|
test->add_expr(ref);
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nneg = ivl_event_nneg(event);
|
int nneg = ivl_event_nneg(event);
|
||||||
int npos = ivl_event_npos(event);
|
for (int i = 0; i < nneg; i++) {
|
||||||
if (nneg + npos > 0) {
|
ivl_nexus_t nexus = ivl_event_neg(event, i);
|
||||||
vhdl_binop_expr *test =
|
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
||||||
new vhdl_binop_expr(VHDL_BINOP_OR, vhdl_type::boolean());
|
vhdl_fcall *detect =
|
||||||
|
new vhdl_fcall("falling_edge", vhdl_type::boolean());
|
||||||
// Generate falling_edge(..) calls for each negedge event
|
detect->add_expr(ref);
|
||||||
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
|
int npos = ivl_event_npos(event);
|
||||||
// are no edge-triggered events
|
for (int i = 0; i < npos; i++) {
|
||||||
draw_stmt(proc, container, sub_stmt);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,11 @@ void vhdl_wait_stmt::emit(std::ostream &of, int level) const
|
||||||
of << " for ";
|
of << " for ";
|
||||||
expr_->emit(of, level);
|
expr_->emit(of, level);
|
||||||
break;
|
break;
|
||||||
|
case VHDL_WAIT_UNTIL:
|
||||||
|
assert(expr_);
|
||||||
|
of << " until ";
|
||||||
|
expr_->emit(of, level);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
of << ";";
|
of << ";";
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ public:
|
||||||
|
|
||||||
void emit(std::ostream &of, int level) const;
|
void emit(std::ostream &of, int level) const;
|
||||||
const std::string &get_name() const { return name_; }
|
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);
|
void set_slice(vhdl_expr *s, int w=0);
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
|
@ -303,6 +304,7 @@ public:
|
||||||
enum vhdl_wait_type_t {
|
enum vhdl_wait_type_t {
|
||||||
VHDL_WAIT_INDEF, // Suspend indefinitely
|
VHDL_WAIT_INDEF, // Suspend indefinitely
|
||||||
VHDL_WAIT_FOR, // Wait for a constant amount of time
|
VHDL_WAIT_FOR, // Wait for a constant amount of time
|
||||||
|
VHDL_WAIT_UNTIL, // Wait on a sensitivity list
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue