vhdlpp: Improved conditional assignments.
Now they handle expressions without the final 'else'.
This commit is contained in:
parent
19a187fa90
commit
daed47eb45
|
|
@ -178,6 +178,21 @@ SignalAssignment::~SignalAssignment()
|
|||
delete lval_;
|
||||
}
|
||||
|
||||
CondSignalAssignment::CondSignalAssignment(ExpName*target, std::list<ExpConditional::case_t*>&options)
|
||||
: lval_(target)
|
||||
{
|
||||
options_.splice(options_.end(), options);
|
||||
}
|
||||
|
||||
CondSignalAssignment::~CondSignalAssignment()
|
||||
{
|
||||
delete lval_;
|
||||
for(list<ExpConditional::case_t*>::iterator it = options_.begin();
|
||||
it != options_.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
ComponentInstantiation::ComponentInstantiation(perm_string i, perm_string c,
|
||||
list<named_expr_t*>*parms,
|
||||
list<named_expr_t*>*ports)
|
||||
|
|
|
|||
|
|
@ -189,6 +189,25 @@ class SignalAssignment : public Architecture::Statement {
|
|||
std::list<Expression*> rval_;
|
||||
};
|
||||
|
||||
class CondSignalAssignment : public Architecture::Statement {
|
||||
|
||||
public:
|
||||
CondSignalAssignment(ExpName*target, std::list<ExpConditional::case_t*>&options);
|
||||
~CondSignalAssignment();
|
||||
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
void dump(ostream&out, int ident =0) const;
|
||||
|
||||
private:
|
||||
ExpName*lval_;
|
||||
std::list<ExpConditional::case_t*> options_;
|
||||
|
||||
// List of signals that should be emitted in the related process
|
||||
// sensitivity list. It is filled during the elaboration step.
|
||||
std::list<const ExpName*>sens_list_;
|
||||
};
|
||||
|
||||
class ComponentInstantiation : public Architecture::Statement {
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -95,6 +95,18 @@ void SignalAssignment::dump(ostream&out, int indent) const
|
|||
}
|
||||
}
|
||||
|
||||
void CondSignalAssignment::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "CondSignalAssignment file=" << get_fileline() << endl;
|
||||
lval_->dump(out, indent+1);
|
||||
out << setw(indent+2) << "" << "<= <expr>..." << endl;
|
||||
|
||||
for(list<ExpConditional::case_t*>::const_iterator it = options_.begin();
|
||||
it != options_.end(); ++it) {
|
||||
(*it)->dump(out, indent+2);
|
||||
}
|
||||
}
|
||||
|
||||
void StatementList::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent+3) << "" << "sequence of statements:" << endl;
|
||||
|
|
|
|||
|
|
@ -353,3 +353,48 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc)
|
|||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int CondSignalAssignment::elaborate(Entity*ent, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
// Visitor to extract signal names occuring in the conditional
|
||||
// statements to create the sensitivity list
|
||||
struct name_extractor_t : public ExprVisitor {
|
||||
name_extractor_t(list<const ExpName*>& name_list)
|
||||
: name_list_(name_list) {}
|
||||
void operator() (Expression*s) {
|
||||
if(const ExpName*name = dynamic_cast<const ExpName*>(s))
|
||||
name_list_.push_back(name);
|
||||
}
|
||||
|
||||
private:
|
||||
list<const ExpName*>& name_list_;
|
||||
} name_extractor(sens_list_);
|
||||
|
||||
// Elaborate the l-value expression.
|
||||
errors += lval_->elaborate_lval(ent, arc, true);
|
||||
|
||||
// The elaborate_lval should have resolved the type of the
|
||||
// l-value expression. We'll use that type to elaborate the
|
||||
// r-value.
|
||||
const VType*lval_type = lval_->peek_type();
|
||||
if (lval_type == 0) {
|
||||
if (errors == 0) {
|
||||
errors += 1;
|
||||
cerr << get_fileline()
|
||||
<< ": error: Unable to calculate type for l-value expression."
|
||||
<< endl;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
for(list<ExpConditional::case_t*>::iterator it = options_.begin();
|
||||
it != options_.end(); ++it) {
|
||||
ExpConditional::case_t*cas = (*it);
|
||||
cas->elaborate_expr(ent, arc, lval_type);
|
||||
cas->visit(name_extractor);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,6 +150,56 @@ int SignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
return errors;
|
||||
}
|
||||
|
||||
int CondSignalAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
out << "// " << get_fileline() << endl;
|
||||
out << "always @(";
|
||||
|
||||
bool first = true;
|
||||
for(list<const ExpName*>::const_iterator it = sens_list_.begin();
|
||||
it != sens_list_.end(); ++it) {
|
||||
if(first)
|
||||
first = false;
|
||||
else
|
||||
out << ",";
|
||||
|
||||
errors += (*it)->emit(out, ent, arc);
|
||||
}
|
||||
|
||||
out << ") begin" << endl;
|
||||
|
||||
first = true;
|
||||
for(list<ExpConditional::case_t*>::iterator it = options_.begin();
|
||||
it != options_.end(); ++it) {
|
||||
ExpConditional::case_t*cas = *it;
|
||||
ivl_assert(*this, cas->true_clause().size() == 1);
|
||||
const Expression*rval = cas->true_clause().front();
|
||||
|
||||
if(first)
|
||||
first = false;
|
||||
else
|
||||
out << "else ";
|
||||
|
||||
if(Expression*cond = cas->condition()) {
|
||||
out << "if(";
|
||||
cond->emit(out, ent, arc);
|
||||
out << ") ";
|
||||
}
|
||||
|
||||
out << endl;
|
||||
lval_->emit(out, ent, arc);
|
||||
out << " = ";
|
||||
rval->emit(out, ent, arc);
|
||||
out << ";" << endl;
|
||||
}
|
||||
|
||||
out << "end" << endl;
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
{
|
||||
const char*comma = "";
|
||||
|
|
|
|||
|
|
@ -509,8 +509,9 @@ class ExpConditional : public Expression {
|
|||
case_t(const case_t&other);
|
||||
~case_t();
|
||||
|
||||
inline Expression*condition() { return cond_; }
|
||||
inline Expression*condition() const { return cond_; }
|
||||
inline void set_condition(Expression*cond) { cond_ = cond; }
|
||||
inline const std::list<Expression*>& true_clause() const { return true_clause_; }
|
||||
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt);
|
||||
int emit_option(ostream&out, Entity*ent, ScopeBase*scope) const;
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
%type <elsif_list> if_statement_elsif_list if_statement_elsif_list_opt
|
||||
|
||||
%type <exp_options> else_when_waveform selected_waveform
|
||||
%type <exp_options_list> else_when_waveforms selected_waveform_list
|
||||
%type <exp_options_list> else_when_waveforms else_when_waveforms_opt selected_waveform_list
|
||||
|
||||
%type <subprogram> function_specification procedure_specification
|
||||
%type <subprogram> subprogram_specification subprogram_body_start
|
||||
|
|
@ -787,18 +787,18 @@ concurrent_assertion_statement
|
|||
create Expression objects for it, but the parser will only
|
||||
recognize it it in specific situations. */
|
||||
concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */
|
||||
: name LEQ waveform K_when expression else_when_waveforms ';'
|
||||
{ ExpConditional*tmp = new ExpConditional($5, $3, $6);
|
||||
FILE_NAME(tmp, @3);
|
||||
delete $3;
|
||||
delete $6;
|
||||
: name LEQ waveform K_when expression else_when_waveforms_opt ';'
|
||||
{ std::list<ExpConditional::case_t*>*options;
|
||||
options = $6 ? $6 : new std::list<ExpConditional::case_t*>;
|
||||
options->push_front(new ExpConditional::case_t($5, $3));
|
||||
|
||||
ExpName*name = dynamic_cast<ExpName*> ($1);
|
||||
assert(name);
|
||||
SignalAssignment*tmpa = new SignalAssignment(name, tmp);
|
||||
FILE_NAME(tmpa, @1);
|
||||
ExpName*name = dynamic_cast<ExpName*>($1);
|
||||
assert(name);
|
||||
CondSignalAssignment*tmp = new CondSignalAssignment(name, *options);
|
||||
|
||||
$$ = tmpa;
|
||||
FILE_NAME(tmp, @1);
|
||||
delete options;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Error recovery rules. */
|
||||
|
|
@ -842,6 +842,12 @@ else_when_waveforms
|
|||
}
|
||||
;
|
||||
|
||||
else_when_waveforms_opt
|
||||
: else_when_waveforms { $$ = $1; }
|
||||
| { $$ = 0; }
|
||||
;
|
||||
|
||||
|
||||
else_when_waveform
|
||||
: K_else waveform K_when expression
|
||||
{ ExpConditional::case_t*tmp = new ExpConditional::case_t($4, $2);
|
||||
|
|
|
|||
Loading…
Reference in New Issue