diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index 05a31809b..32af037ea 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -69,6 +69,16 @@ ForGenerate::~ForGenerate() { } +IfGenerate::IfGenerate(perm_string gname, Expression*cond, + std::list&s) +: GenerateStatement(gname, s), cond_(cond) +{ +} + +IfGenerate::~IfGenerate() +{ +} + SignalAssignment::SignalAssignment(ExpName*name, list&rv) : lval_(name) { diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 2a40189ef..4e46652ed 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -127,6 +127,19 @@ class ForGenerate : public GenerateStatement { Expression*msb_; }; +class IfGenerate : public GenerateStatement { + + public: + IfGenerate(perm_string gname, Expression*cond, + std::list&s); + ~IfGenerate(); + + int elaborate(Entity*ent, Architecture*arc); + int emit(ostream&out, Entity*entity, Architecture*arc); + + private: + Expression*cond_; +}; /* * The SignalAssignment class represents the diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index b820d3f39..d399c141d 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -117,6 +117,13 @@ int ForGenerate::elaborate(Entity*ent, Architecture*arc) return errors; } +int IfGenerate::elaborate(Entity*ent, Architecture*arc) +{ + int errors = 0; + errors += elaborate_statements(ent, arc); + return errors; +} + /* * This method attempts to rewrite the process content as an * always-@(n-edge ) version of the same statement. This makes diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index c2a855b61..78f3131f8 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -181,7 +181,7 @@ int GenerateStatement::emit_statements(ostream&out, Entity*ent, Architecture*arc int ForGenerate::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0; - out << "generate genvar \\" << genvar_ << " ;" << endl; + out << "genvar \\" << genvar_ << " ;" << endl; out << "for (\\" << genvar_ << " = "; errors += lsb_->emit(out, ent, arc); out << "; \\" << genvar_ << " <= "; @@ -192,7 +192,21 @@ int ForGenerate::emit(ostream&out, Entity*ent, Architecture*arc) errors += emit_statements(out, ent, arc); out << "end" << endl; - out << "endgenerate" << endl; + + return errors; +} + +int IfGenerate::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + out << "if ("; + cond_->emit(out, ent, arc); + out << ") begin : \\" << get_name() << endl; + + errors += emit_statements(out, ent, arc); + + out << "end" << endl; + return errors; } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 844a7c307..81d71db3c 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -283,7 +283,8 @@ static list* record_elements(list*names, %type component_specification %type concurrent_statement component_instantiation_statement concurrent_signal_assignment_statement -%type for_generate_statement process_statement +%type for_generate_statement generate_statement if_generate_statement +%type process_statement %type architecture_statement_part generate_statement_body %type choice @@ -692,7 +693,7 @@ concurrent_signal_assignment_statement concurrent_statement : component_instantiation_statement | concurrent_signal_assignment_statement - | for_generate_statement + | generate_statement | process_statement ; @@ -1068,6 +1069,11 @@ for_generate_statement } ; +generate_statement /* IEEE 1076-2008 P11.8 */ + : if_generate_statement + | for_generate_statement + ; + generate_statement_body : architecture_statement_part { $$ = $1; } ; @@ -1123,6 +1129,29 @@ identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ; identifier_colon_opt : IDENTIFIER ':' { $$ = $1; } | { $$ = 0; }; + /* The if_generate_statement rule describes the if_generate syntax. + + NOTE: This does not yet implement the elsif and else parts of the + syntax. This shouldn't be hard, but is simply not done yet. */ +if_generate_statement /* IEEE 1076-2008 P11.8 */ + : IDENTIFIER ':' K_if expression + K_generate generate_statement_body + K_end K_generate identifier_opt ';' + { perm_string name = lex_strings.make($1); + IfGenerate*tmp = new IfGenerate(name, $4, *$6); + FILE_NAME(tmp, @3); + + if ($9 && name != $9) { + errormsg(@1, "if-generate name %s does not match closing name %s\n", + name.str(), $9); + } + delete[]$1; + delete $6; + delete[]$9; + $$ = tmp; + } + ; + if_statement : K_if expression K_then sequence_of_statements if_statement_elsif_list_opt if_statement_else