From a6f63b8a54e7e5be820ed3f011c9904c355cd227 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 15 Oct 2011 09:49:24 -0700 Subject: [PATCH] Parse generic clause in entity headers The generic clause can create named generics in entities. This patch gets the parser support for them working, even though they cannot yet evaluate. --- vhdlpp/entity.cc | 17 +++++++++---- vhdlpp/entity.h | 9 +++++-- vhdlpp/expression.cc | 4 +-- vhdlpp/parse.y | 60 ++++++++++++++++++++++++++++++-------------- 4 files changed, 61 insertions(+), 29 deletions(-) diff --git a/vhdlpp/entity.cc b/vhdlpp/entity.cc index 27033f489..411596178 100644 --- a/vhdlpp/entity.cc +++ b/vhdlpp/entity.cc @@ -38,12 +38,19 @@ ComponentBase::~ComponentBase() delete *it; } -void ComponentBase::set_interface(std::list*ports) +void ComponentBase::set_interface(std::list*parms, + std::list*ports) { - while (! ports->empty()) { - ports_.push_back(ports->front()); - ports->pop_front(); - } + if (parms) { + while (! parms->empty()) { + parms_.push_back(parms->front()); + parms->pop_front(); + } + } + while (! ports->empty()) { + ports_.push_back(ports->front()); + ports->pop_front(); + } } const InterfacePort* ComponentBase::find_port(perm_string my_name) const diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index 88846a076..05e24f4c4 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -30,10 +30,11 @@ typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t; class Architecture; +class Expression; class InterfacePort : public LineInfo { public: - InterfacePort() { mode = PORT_NONE; type=0; } + InterfacePort() { mode = PORT_NONE; type=0; expr=0; } // Port direction from the source code. port_mode_t mode; @@ -41,6 +42,8 @@ class InterfacePort : public LineInfo { perm_string name; // Name of interface type as given in the source code. const VType*type; + // Default value expression (or nil) + Expression*expr; }; /* @@ -63,7 +66,8 @@ class ComponentBase : public LineInfo { // method with a list of interface elements that were parsed // for the entity. This method collects those entities, and // empties the list in the process. - void set_interface(std::list*ports); + void set_interface(std::list*parms, + std::list*ports); void write_to_stream(std::ostream&fd) const; @@ -77,6 +81,7 @@ class ComponentBase : public LineInfo { private: perm_string name_; + std::vector parms_; std::vector ports_; }; diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index be69247ac..cd8e71469 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -408,10 +408,8 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const Expression*exp; bool rc = scope->find_constant(name_, type, exp); - if (rc == false) { - cerr << "XXXX Unable to evaluate name " << name_ << "." << endl; + if (rc == false) return false; - } return exp->evaluate(scope, val); } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index c419e1878..fdbc55a62 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -224,9 +224,10 @@ const VType*parse_type_by_name(perm_string name) %type direction -%type interface_element interface_list entity_header +%type interface_element interface_list %type port_clause port_clause_opt -%type mode +%type generic_clause generic_clause_opt +%type mode mode_opt %type entity_aspect entity_aspect_opt binding_indication binding_indication_semicolon_opt %type instantiation_list @@ -246,6 +247,7 @@ const VType*parse_type_by_name(perm_string name) %type expression_logical_xnor expression_logical_xor %type name %type shift_expression simple_expression term waveform_element +%type interface_element_expression %type waveform waveform_elements %type name_list expression_list @@ -531,7 +533,7 @@ component_declaration ComponentBase*comp = new ComponentBase(name); if ($4) { - comp->set_interface($4); + comp->set_interface(0, $4); delete $4; } active_scope->bind_name(name, comp); @@ -753,23 +755,22 @@ entity_aspect_opt ; entity_declaration - : K_entity IDENTIFIER K_is entity_header K_end K_entity_opt identifier_opt';' + : K_entity IDENTIFIER + K_is generic_clause_opt port_clause_opt + K_end K_entity_opt identifier_opt';' { Entity*tmp = new Entity(lex_strings.make($2)); FILE_NAME(tmp, @1); // Transfer the ports - std::list*ports = $4; - tmp->set_interface(ports); - delete ports; + tmp->set_interface($4, $5); + delete $4; + delete $5; // Save the entity in the entity map. design_entities[tmp->get_name()] = tmp; delete[]$2; - if($7) { - if(tmp->get_name() != $7) { - errormsg(@1, "Syntax error in entity clause. Closing name doesn't match.\n"); - yyerrok; + if($8 && tmp->get_name() != $8) { + errormsg(@1, "Syntax error in entity clause. Closing name doesn't match.\n"); } - delete[]$7; - } + delete[]$8; } | K_entity error K_end K_entity_opt identifier_opt ';' { errormsg(@1, "Too many errors, giving up on entity declaration.\n"); @@ -778,11 +779,6 @@ entity_declaration } ; -entity_header - : port_clause - { $$ = $1; } - ; - enumeration_literal : IDENTIFIER { list*tmp = new list; @@ -942,6 +938,24 @@ factor $$ = tmp; } ; + +generic_clause_opt + : generic_clause + { $$ = $1;} + | + { $$ = 0; } + ; + +generic_clause + : K_generic '(' interface_list ')' ';' + { $$ = $3; } + | K_generic '(' error ')' ';' + { errormsg(@3, "Error in interface list for generic.\n"); + yyerrok; + $$ = 0; + } + ; + generic_map_aspect_opt : generic_map_aspect | @@ -1071,7 +1085,7 @@ instantiation_list /* The interface_element is also an interface_declaration */ interface_element - : identifier_list ':' mode subtype_indication + : identifier_list ':' mode_opt subtype_indication interface_element_expression { std::list*tmp = new std::list; for (std::list::iterator cur = $1->begin() ; cur != $1->end() ; ++cur) { @@ -1080,6 +1094,7 @@ interface_element port->mode = $3; port->name = *(cur); port->type = $4; + port->expr = $5; tmp->push_back(port); } delete $1; @@ -1087,6 +1102,11 @@ interface_element } ; +interface_element_expression + : VASSIGN expression { $$ = $2; } + | { $$ = 0; } + ; + interface_list : interface_list ';' interface_element { std::list*tmp = $1; @@ -1200,6 +1220,8 @@ mode | K_out { $$ = PORT_OUT; } ; +mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ; + name : IDENTIFIER { ExpName*tmp = new ExpName(lex_strings.make($1));