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.
This commit is contained in:
Stephen Williams 2011-10-15 09:49:24 -07:00
parent 6268db6e68
commit a6f63b8a54
4 changed files with 61 additions and 29 deletions

View File

@ -38,12 +38,19 @@ ComponentBase::~ComponentBase()
delete *it; delete *it;
} }
void ComponentBase::set_interface(std::list<InterfacePort*>*ports) void ComponentBase::set_interface(std::list<InterfacePort*>*parms,
std::list<InterfacePort*>*ports)
{ {
while (! ports->empty()) { if (parms) {
ports_.push_back(ports->front()); while (! parms->empty()) {
ports->pop_front(); 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 const InterfacePort* ComponentBase::find_port(perm_string my_name) const

View File

@ -30,10 +30,11 @@
typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t; typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t;
class Architecture; class Architecture;
class Expression;
class InterfacePort : public LineInfo { class InterfacePort : public LineInfo {
public: public:
InterfacePort() { mode = PORT_NONE; type=0; } InterfacePort() { mode = PORT_NONE; type=0; expr=0; }
// Port direction from the source code. // Port direction from the source code.
port_mode_t mode; port_mode_t mode;
@ -41,6 +42,8 @@ class InterfacePort : public LineInfo {
perm_string name; perm_string name;
// Name of interface type as given in the source code. // Name of interface type as given in the source code.
const VType*type; 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 // method with a list of interface elements that were parsed
// for the entity. This method collects those entities, and // for the entity. This method collects those entities, and
// empties the list in the process. // empties the list in the process.
void set_interface(std::list<InterfacePort*>*ports); void set_interface(std::list<InterfacePort*>*parms,
std::list<InterfacePort*>*ports);
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
@ -77,6 +81,7 @@ class ComponentBase : public LineInfo {
private: private:
perm_string name_; perm_string name_;
std::vector<InterfacePort*> parms_;
std::vector<InterfacePort*> ports_; std::vector<InterfacePort*> ports_;
}; };

View File

@ -408,10 +408,8 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const
Expression*exp; Expression*exp;
bool rc = scope->find_constant(name_, type, exp); bool rc = scope->find_constant(name_, type, exp);
if (rc == false) { if (rc == false)
cerr << "XXXX Unable to evaluate name " << name_ << "." << endl;
return false; return false;
}
return exp->evaluate(scope, val); return exp->evaluate(scope, val);
} }

View File

@ -224,9 +224,10 @@ const VType*parse_type_by_name(perm_string name)
%type <flag> direction %type <flag> direction
%type <interface_list> interface_element interface_list entity_header %type <interface_list> interface_element interface_list
%type <interface_list> port_clause port_clause_opt %type <interface_list> port_clause port_clause_opt
%type <port_mode> mode %type <interface_list> generic_clause generic_clause_opt
%type <port_mode> mode mode_opt
%type <entity_aspect> entity_aspect entity_aspect_opt binding_indication binding_indication_semicolon_opt %type <entity_aspect> entity_aspect entity_aspect_opt binding_indication binding_indication_semicolon_opt
%type <instantiation_list> instantiation_list %type <instantiation_list> instantiation_list
@ -246,6 +247,7 @@ const VType*parse_type_by_name(perm_string name)
%type <expr> expression_logical_xnor expression_logical_xor %type <expr> expression_logical_xnor expression_logical_xor
%type <expr> name %type <expr> name
%type <expr> shift_expression simple_expression term waveform_element %type <expr> shift_expression simple_expression term waveform_element
%type <expr> interface_element_expression
%type <expr_list> waveform waveform_elements %type <expr_list> waveform waveform_elements
%type <expr_list> name_list expression_list %type <expr_list> name_list expression_list
@ -531,7 +533,7 @@ component_declaration
ComponentBase*comp = new ComponentBase(name); ComponentBase*comp = new ComponentBase(name);
if ($4) { if ($4) {
comp->set_interface($4); comp->set_interface(0, $4);
delete $4; delete $4;
} }
active_scope->bind_name(name, comp); active_scope->bind_name(name, comp);
@ -753,23 +755,22 @@ entity_aspect_opt
; ;
entity_declaration 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)); { Entity*tmp = new Entity(lex_strings.make($2));
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
// Transfer the ports // Transfer the ports
std::list<InterfacePort*>*ports = $4; tmp->set_interface($4, $5);
tmp->set_interface(ports); delete $4;
delete ports; delete $5;
// Save the entity in the entity map. // Save the entity in the entity map.
design_entities[tmp->get_name()] = tmp; design_entities[tmp->get_name()] = tmp;
delete[]$2; delete[]$2;
if($7) { if($8 && tmp->get_name() != $8) {
if(tmp->get_name() != $7) { errormsg(@1, "Syntax error in entity clause. Closing name doesn't match.\n");
errormsg(@1, "Syntax error in entity clause. Closing name doesn't match.\n");
yyerrok;
} }
delete[]$7; delete[]$8;
}
} }
| K_entity error K_end K_entity_opt identifier_opt ';' | K_entity error K_end K_entity_opt identifier_opt ';'
{ errormsg(@1, "Too many errors, giving up on entity declaration.\n"); { errormsg(@1, "Too many errors, giving up on entity declaration.\n");
@ -778,11 +779,6 @@ entity_declaration
} }
; ;
entity_header
: port_clause
{ $$ = $1; }
;
enumeration_literal enumeration_literal
: IDENTIFIER : IDENTIFIER
{ list<perm_string>*tmp = new list<perm_string>; { list<perm_string>*tmp = new list<perm_string>;
@ -942,6 +938,24 @@ factor
$$ = tmp; $$ = 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_opt
: generic_map_aspect : generic_map_aspect
| |
@ -1071,7 +1085,7 @@ instantiation_list
/* The interface_element is also an interface_declaration */ /* The interface_element is also an interface_declaration */
interface_element interface_element
: identifier_list ':' mode subtype_indication : identifier_list ':' mode_opt subtype_indication interface_element_expression
{ std::list<InterfacePort*>*tmp = new std::list<InterfacePort*>; { std::list<InterfacePort*>*tmp = new std::list<InterfacePort*>;
for (std::list<perm_string>::iterator cur = $1->begin() for (std::list<perm_string>::iterator cur = $1->begin()
; cur != $1->end() ; ++cur) { ; cur != $1->end() ; ++cur) {
@ -1080,6 +1094,7 @@ interface_element
port->mode = $3; port->mode = $3;
port->name = *(cur); port->name = *(cur);
port->type = $4; port->type = $4;
port->expr = $5;
tmp->push_back(port); tmp->push_back(port);
} }
delete $1; delete $1;
@ -1087,6 +1102,11 @@ interface_element
} }
; ;
interface_element_expression
: VASSIGN expression { $$ = $2; }
| { $$ = 0; }
;
interface_list interface_list
: interface_list ';' interface_element : interface_list ';' interface_element
{ std::list<InterfacePort*>*tmp = $1; { std::list<InterfacePort*>*tmp = $1;
@ -1200,6 +1220,8 @@ mode
| K_out { $$ = PORT_OUT; } | K_out { $$ = PORT_OUT; }
; ;
mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ;
name name
: IDENTIFIER : IDENTIFIER
{ ExpName*tmp = new ExpName(lex_strings.make($1)); { ExpName*tmp = new ExpName(lex_strings.make($1));