From 29ddd5208fce6a113e05173cfb838293f4216e0a Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 29 May 2015 10:54:29 +0200 Subject: [PATCH] vhdlpp: 'wait on' and 'wait until' statements. --- vhdlpp/parse.y | 16 +++++++++--- vhdlpp/sequential.cc | 5 ++++ vhdlpp/sequential.h | 20 ++++++++++++-- vhdlpp/sequential_debug.cc | 7 +++++ vhdlpp/sequential_elaborate.cc | 24 +++++++++++++++++ vhdlpp/sequential_emit.cc | 48 ++++++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+), 5 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index b6a877438..f75cd19e2 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -359,7 +359,7 @@ static void touchup_interface_for_functions(std::list*ports) %type sequential_statement if_statement signal_assignment signal_assignment_statement %type case_statement procedure_call procedure_call_statement %type loop_statement variable_assignment variable_assignment_statement -%type assertion_statement report_statement return_statement wait_for_statement +%type assertion_statement report_statement return_statement wait_statement %type range %type range_list index_constraint @@ -2201,7 +2201,7 @@ sequential_statement | return_statement { $$ = $1; } | report_statement { $$ = $1; } | assertion_statement { $$ = $1; } - | wait_for_statement { $$ = $1; } + | wait_statement { $$ = $1; } | K_null ';' { $$ = 0; } | error ';' { errormsg(@1, "Syntax error in sequential statement.\n"); @@ -2632,12 +2632,22 @@ variable_declaration /* IEEE 1076-2008 P6.4.2.4 */ } ; -wait_for_statement +wait_statement : K_wait K_for expression ';' { WaitForStmt*tmp = new WaitForStmt($3); FILE_NAME(tmp, @1); $$ = tmp; } + | K_wait K_on expression ';' + { WaitStmt*tmp = new WaitStmt(WaitStmt::ON, $3); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | K_wait K_until expression ';' + { WaitStmt*tmp = new WaitStmt(WaitStmt::UNTIL, $3); + FILE_NAME(tmp, @1); + $$ = tmp; + } ; waveform diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index b6a4c1079..0f793b713 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -289,3 +289,8 @@ WaitForStmt::WaitForStmt(Expression*delay) : delay_(delay) { } + +WaitStmt::WaitStmt(wait_type_t type, Expression*expr) +: type_(type), expr_(expr) +{ +} diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index ed7bb17a8..eba398cef 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -22,8 +22,7 @@ # include "LineInfo.h" # include "parse_types.h" -# include -# include +# include class ScopeBase; class Entity; @@ -321,4 +320,21 @@ class WaitForStmt : public SequentialStmt { Expression*delay_; }; +class WaitStmt : public SequentialStmt { + public: + typedef enum { ON, UNTIL } wait_type_t; + WaitStmt(wait_type_t type, Expression*expression); + + void dump(ostream&out, int indent) const; + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); + + private: + wait_type_t type_; + Expression*expr_; + // Sensitivity list for 'wait until' statement + std::set sens_list_; +}; + #endif /* IVL_sequential_H */ diff --git a/vhdlpp/sequential_debug.cc b/vhdlpp/sequential_debug.cc index 5c40b5012..149021440 100644 --- a/vhdlpp/sequential_debug.cc +++ b/vhdlpp/sequential_debug.cc @@ -187,3 +187,10 @@ void WaitForStmt::dump(ostream&out, int indent) const out << setw(indent+3) << "" << "delay: "; delay_->dump(out, indent+3); } + +void WaitStmt::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "WaitStmt at file=" << get_fileline() << endl; + out << setw(indent+3) << "" << "expression: "; + expr_->dump(out, indent+3); +} diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index a0cfafe6d..80e7b2584 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -19,6 +19,7 @@ # include "sequential.h" # include "expression.h" +# include "scope.h" int SequentialStmt::elaborate(Entity*, ScopeBase*) { @@ -202,3 +203,26 @@ int WaitForStmt::elaborate(Entity*ent, ScopeBase*scope) { return delay_->elaborate_expr(ent, scope, 0); } + +int WaitStmt::elaborate(Entity*ent, ScopeBase*scope) +{ + if(type_ == UNTIL) { + struct fill_sens_list_t : public ExprVisitor { + fill_sens_list_t(set& sig_list) + : sig_list_(sig_list) {}; + + void operator() (Expression*s) { + if(ExpName*name = dynamic_cast(s)) + sig_list_.insert(name); + } + + private: + set& sig_list_; + } fill_sens_list(sens_list_); + + // Fill the sensitivity list + expr_->visit(fill_sens_list); + } + + return expr_->elaborate_expr(ent, scope, 0); +} diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index f0e6f0b5c..619c0f5e5 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -529,3 +529,51 @@ void WaitForStmt::write_to_stream(std::ostream&fd) fd << "wait for "; delay_->write_to_stream(fd); } + +int WaitStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) +{ + int errors = 0; + + switch(type_) { + case ON: + out << "@("; + break; + + case UNTIL: + if(!sens_list_.empty()) { + out << "@("; + for(std::set::iterator it = sens_list_.begin(); + it != sens_list_.end(); ++it) { + if(it != sens_list_.begin()) + out << ","; + + (*it)->emit(out, ent, scope); + } + + out << ");"; + } + + out << "wait("; + break; + } + + errors += expr_->emit(out, ent, scope); + out << ");" << endl; + + return errors; +} + +void WaitStmt::write_to_stream(std::ostream&fd) +{ + switch(type_) { + case ON: + fd << "wait on "; + break; + + case UNTIL: + fd << "wait until "; + break; + } + + expr_->write_to_stream(fd); +}