vhdlpp: Support for selected assignments.

This commit is contained in:
Maciej Suminski 2015-05-22 10:33:30 +02:00
parent 5a0d967682
commit c28000c55f
3 changed files with 100 additions and 6 deletions

View File

@ -367,6 +367,38 @@ ExpConditional::case_t::~case_t()
}
}
ExpSelected::ExpSelected(Expression*selector, std::list<case_t*>*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<case_t*>::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<case_t*>*new_options = NULL;
if(!options_.empty()) {
new_options = new std::list<case_t*>();
for(std::list<case_t*>::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)
{

View File

@ -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<Expression*>*tru,
std::list<case_t*>*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<case_t*> options_;
};
/*
* Expression to handle selected assignments (with .. select target <= value when ..)
*/
class ExpSelected : public ExpConditional {
public:
ExpSelected(Expression*selector, std::list<case_t*>*options);
~ExpSelected();
Expression*clone() const;
private:
Expression*selector_;
};
/*
* This is a special expression type that represents posedge/negedge
* expressions in sensitivity lists.

View File

@ -318,7 +318,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <arch_statement> concurrent_conditional_signal_assignment
%type <arch_statement> concurrent_signal_assignment_statement concurrent_simple_signal_assignment
%type <arch_statement> for_generate_statement generate_statement if_generate_statement
%type <arch_statement> process_statement
%type <arch_statement> process_statement selected_signal_assignment
%type <arch_statement_list> architecture_statement_part generate_statement_body
%type <choice> choice
@ -370,8 +370,8 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%type <elsif> if_statement_elsif
%type <elsif_list> if_statement_elsif_list if_statement_elsif_list_opt
%type <exp_options> else_when_waveform
%type <exp_options_list> else_when_waveforms
%type <exp_options> else_when_waveform selected_waveform
%type <exp_options_list> else_when_waveforms selected_waveform_list
%type <subprogram> function_specification subprogram_specification subprogram_body_start
%type <severity> 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<ExpName*>($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<ExpConditional::case_t*>*tmp = $1;
tmp->push_back($3);
$$ = tmp;
}
| selected_waveform
{ list<ExpConditional::case_t*>*tmp = new list<ExpConditional::case_t*>;
tmp->push_back($1);
$$ = tmp;
}
;
sequence_of_statements
: sequence_of_statements sequential_statement