Handle rising_edge and falling_edge functions.

This commit is contained in:
Stephen Williams 2013-06-05 20:39:04 -07:00
parent 3446455055
commit 0fcd2d9db6
3 changed files with 61 additions and 2 deletions

View File

@ -174,9 +174,54 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*)
return -1;
const Expression*ce_raw = stmt->peek_condition();
// Now we have matched this pattern:
// process(<expr>) begin if <ce_raw>...
// The <ce_raw> is the condition.
// We expect the condition to be <name>'event AND <name>='1'.
// If it's not a logical AND, I give up.
if (const ExpFunc*ce_func = dynamic_cast<const ExpFunc*>(ce_raw)) {
if (ce_func->func_args() != 1)
return -1;
if (ce_func->func_name()!="rising_edge" && ce_func->func_name()!="falling_edge")
return -1;
if (! se->symbolic_compare(ce_func->func_arg(0)))
return -1;
// We've matched this pattern:
// process(<se>) if (rising_edge(<se>)) then ...
// and we can convert it to:
// always @(posedge <se>) ...
ExpEdge::fun_t use_edge;
if (ce_func->func_name()=="rising_edge")
use_edge = ExpEdge::POSEDGE;
else if (ce_func->func_name()=="falling_edge")
use_edge = ExpEdge::NEGEDGE;
else
use_edge = ExpEdge::ANYEDGE;
// Replace the sensitivity expression with an edge
// expression. The ExpEdge expression signals that this
// is an always-@(edge) statement.
ExpEdge*edge = new ExpEdge(use_edge, se);
assert(sensitivity_list_.size() == 1);
sensitivity_list_.pop_front();
sensitivity_list_.push_front(edge);
// Replace the statement with the body of the always
// statement, which is the true clause of the top "if"
// statement. There should be no "else" clause.
assert(statements_list_.size() == 1);
statements_list_.pop_front();
stmt->extract_true(statements_list_);
delete stmt;
return 0;
}
// Here we expect the condition to be
// <name>'event AND <name>='1'.
// So if ce_raw is not a logical AND, I give up.
const ExpLogical*ce = dynamic_cast<const ExpLogical*> (ce_raw);
if (ce == 0)
return -1;

View File

@ -461,6 +461,10 @@ class ExpFunc : public Expression {
ExpFunc(perm_string nn, std::list<Expression*>*args);
~ExpFunc();
inline perm_string func_name() const { return name_; }
inline size_t func_args() const { return argv_.size(); }
inline const Expression*func_arg(size_t idx) const { return argv_[idx]; }
public: // Base methods
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd);

View File

@ -554,6 +554,16 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
errors += argv_[0]->emit(out, ent, arc);
out << ")";
} else if (name_ == "rising_edge" && argv_.size()==1) {
out << "$ivlh_rising_edge(";
errors += argv_[0]->emit(out, ent, arc);
out << ")";
} else if (name_ == "falling_edge" && argv_.size()==1) {
out << "$ivlh_falling_edge(";
errors += argv_[0]->emit(out, ent, arc);
out << ")";
} else {
out << "\\" << name_ << " (";
for (size_t idx = 0; idx < argv_.size() ; idx += 1) {