From c28000c55f6574dbc3eba0170046808cd4e4d312 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 May 2015 10:33:30 +0200 Subject: [PATCH] vhdlpp: Support for selected assignments. --- vhdlpp/expression.cc | 32 +++++++++++++++++++++++++++ vhdlpp/expression.h | 23 +++++++++++++++++--- vhdlpp/parse.y | 51 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 9caed2296..3cd8c5606 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -367,6 +367,38 @@ ExpConditional::case_t::~case_t() } } +ExpSelected::ExpSelected(Expression*selector, std::list*options) +: ExpConditional(NULL, NULL, options), selector_(selector) +{ + // Currently condition field contains only value, + // so substitute it with a comparison to create a valid condition + for(std::list::iterator it = options_.begin(); + it != options_.end(); ++it) { + Expression*cond = (*it)->condition(); + + if(cond) + (*it)->set_condition(new ExpRelation(ExpRelation::EQ, selector_->clone(), cond)); + } +} + +ExpSelected::~ExpSelected() +{ +} + +Expression*ExpSelected::clone() const +{ + std::list*new_options = NULL; + if(!options_.empty()) { + new_options = new std::list(); + + for(std::list::const_iterator it = options_.begin(); + it != options_.end(); ++it) { + new_options->push_back(new case_t(**it)); + } + } + + return new ExpSelected(selector_->clone(), new_options); +} void ExpConditional::case_t::visit(ExprVisitor& func) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index e98ee86e4..0847244b5 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -466,6 +466,9 @@ class ExpConditional : public Expression { case_t(const case_t&other); ~case_t(); + inline Expression*condition() { return cond_; } + inline void set_condition(Expression*cond) { cond_ = cond; } + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt); int emit_option(ostream&out, Entity*ent, ScopeBase*scope); int emit_default(ostream&out, Entity*ent, ScopeBase*scope); @@ -481,9 +484,9 @@ class ExpConditional : public Expression { public: ExpConditional(Expression*cond, std::list*tru, std::list*options); - ~ExpConditional(); + virtual ~ExpConditional(); - Expression*clone() const; + virtual Expression*clone() const; const VType*probe_type(Entity*ent, ScopeBase*scope) const; int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); @@ -492,10 +495,24 @@ class ExpConditional : public Expression { void dump(ostream&out, int indent = 0) const; void visit(ExprVisitor& func); - private: + protected: std::list options_; }; +/* + * Expression to handle selected assignments (with .. select target <= value when ..) + */ +class ExpSelected : public ExpConditional { + public: + ExpSelected(Expression*selector, std::list*options); + ~ExpSelected(); + + Expression*clone() const; + + private: + Expression*selector_; +}; + /* * This is a special expression type that represents posedge/negedge * expressions in sensitivity lists. diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 670304aac..39061ffbb 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -318,7 +318,7 @@ static void touchup_interface_for_functions(std::list*ports) %type concurrent_conditional_signal_assignment %type concurrent_signal_assignment_statement concurrent_simple_signal_assignment %type for_generate_statement generate_statement if_generate_statement -%type process_statement +%type process_statement selected_signal_assignment %type architecture_statement_part generate_statement_body %type choice @@ -370,8 +370,8 @@ static void touchup_interface_for_functions(std::list*ports) %type if_statement_elsif %type if_statement_elsif_list if_statement_elsif_list_opt -%type else_when_waveform -%type else_when_waveforms +%type else_when_waveform selected_waveform +%type else_when_waveforms selected_waveform_list %type function_specification subprogram_specification subprogram_body_start %type severity severity_opt @@ -833,6 +833,10 @@ concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */ | IDENTIFIER ':' concurrent_conditional_signal_assignment { $$ = $3; } + | selected_signal_assignment + + | IDENTIFIER ':' selected_signal_assignment { $$ = $3; } + | name LEQ error ';' { errormsg(@2, "Syntax error in signal assignment waveform.\n"); delete $1; @@ -2175,6 +2179,47 @@ selected_names_lib | selected_name_lib ; +selected_signal_assignment + : K_with expression K_select name LEQ selected_waveform_list ';' + { ExpSelected*tmp = new ExpSelected($2, $6); + FILE_NAME(tmp, @3); + delete $2; + delete $6; + + ExpName*name = dynamic_cast($4); + assert(name); + SignalAssignment*tmpa = new SignalAssignment(name, tmp); + FILE_NAME(tmpa, @1); + + $$ = tmpa; + } + ; + +selected_waveform + : waveform K_when expression + { ExpConditional::case_t*tmp = new ExpConditional::case_t($3, $1); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | waveform K_when K_others + { ExpConditional::case_t*tmp = new ExpConditional::case_t(0, $1); + FILE_NAME(tmp, @1); + $$ = tmp; + } + ; + +selected_waveform_list + : selected_waveform_list ',' selected_waveform + { list*tmp = $1; + tmp->push_back($3); + $$ = tmp; + } + | selected_waveform + { list*tmp = new list; + tmp->push_back($1); + $$ = tmp; + } + ; sequence_of_statements : sequence_of_statements sequential_statement