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;
}
void ComponentBase::set_interface(std::list<InterfacePort*>*ports)
void ComponentBase::set_interface(std::list<InterfacePort*>*parms,
std::list<InterfacePort*>*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

View File

@ -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<InterfacePort*>*ports);
void set_interface(std::list<InterfacePort*>*parms,
std::list<InterfacePort*>*ports);
void write_to_stream(std::ostream&fd) const;
@ -77,6 +81,7 @@ class ComponentBase : public LineInfo {
private:
perm_string name_;
std::vector<InterfacePort*> parms_;
std::vector<InterfacePort*> ports_;
};

View File

@ -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);
}

View File

@ -224,9 +224,10 @@ const VType*parse_type_by_name(perm_string name)
%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 <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 <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> name
%type <expr> shift_expression simple_expression term waveform_element
%type <expr> interface_element_expression
%type <expr_list> waveform waveform_elements
%type <expr_list> 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<InterfacePort*>*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<perm_string>*tmp = new list<perm_string>;
@ -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<InterfacePort*>*tmp = new std::list<InterfacePort*>;
for (std::list<perm_string>::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<InterfacePort*>*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));