Handle rising_edge and falling_edge functions.
This commit is contained in:
parent
3446455055
commit
0fcd2d9db6
|
|
@ -174,9 +174,54 @@ int ProcessStatement::rewrite_as_always_edge_(Entity*, Architecture*)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
const Expression*ce_raw = stmt->peek_condition();
|
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 (const ExpFunc*ce_func = dynamic_cast<const ExpFunc*>(ce_raw)) {
|
||||||
// If it's not a logical AND, I give up.
|
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);
|
const ExpLogical*ce = dynamic_cast<const ExpLogical*> (ce_raw);
|
||||||
if (ce == 0)
|
if (ce == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -461,6 +461,10 @@ class ExpFunc : public Expression {
|
||||||
ExpFunc(perm_string nn, std::list<Expression*>*args);
|
ExpFunc(perm_string nn, std::list<Expression*>*args);
|
||||||
~ExpFunc();
|
~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
|
public: // Base methods
|
||||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||||
void write_to_stream(std::ostream&fd);
|
void write_to_stream(std::ostream&fd);
|
||||||
|
|
|
||||||
|
|
@ -554,6 +554,16 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
errors += argv_[0]->emit(out, ent, arc);
|
errors += argv_[0]->emit(out, ent, arc);
|
||||||
out << ")";
|
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 {
|
} else {
|
||||||
out << "\\" << name_ << " (";
|
out << "\\" << name_ << " (";
|
||||||
for (size_t idx = 0; idx < argv_.size() ; idx += 1) {
|
for (size_t idx = 0; idx < argv_.size() ; idx += 1) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue