From 0fcd2d9db69433f71b9d5855b50cec6e5b43600e Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 5 Jun 2013 20:39:04 -0700 Subject: [PATCH] Handle rising_edge and falling_edge functions. --- vhdlpp/architec_elaborate.cc | 49 ++++++++++++++++++++++++++++++++++-- vhdlpp/expression.h | 4 +++ vhdlpp/expression_emit.cc | 10 ++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index e7308f96e..3ffc8c6da 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -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() begin if ... + // The is the condition. - // We expect the condition to be 'event AND ='1'. - // If it's not a logical AND, I give up. + if (const ExpFunc*ce_func = dynamic_cast(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() if (rising_edge()) then ... + // and we can convert it to: + // always @(posedge ) ... + + 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 + // 'event AND ='1'. + // So if ce_raw is not a logical AND, I give up. const ExpLogical*ce = dynamic_cast (ce_raw); if (ce == 0) return -1; diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 6d24335f0..d779e484a 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -461,6 +461,10 @@ class ExpFunc : public Expression { ExpFunc(perm_string nn, std::list*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); diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index d4fa884e1..63c1f6eb5 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -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) {