2010-12-13 05:02:18 +01:00
|
|
|
|
|
|
|
|
%{
|
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
|
|
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "vhdlpp_config.h"
|
2011-02-04 17:51:51 +01:00
|
|
|
# include "vhdlint.h"
|
2011-01-31 18:25:29 +01:00
|
|
|
# include "vhdlreal.h"
|
2011-01-03 07:30:09 +01:00
|
|
|
# include "compiler.h"
|
2010-12-13 05:02:18 +01:00
|
|
|
# include "parse_api.h"
|
2011-01-24 05:26:27 +01:00
|
|
|
# include "parse_misc.h"
|
|
|
|
|
# include "architec.h"
|
2011-01-30 02:27:30 +01:00
|
|
|
# include "expression.h"
|
2011-03-22 17:16:20 +01:00
|
|
|
# include "vsignal.h"
|
2011-02-14 01:37:10 +01:00
|
|
|
# include "vtype.h"
|
2010-12-15 06:36:47 +01:00
|
|
|
# include <cstdarg>
|
2011-03-29 10:33:09 +02:00
|
|
|
# include <cstring>
|
2011-01-03 07:30:09 +01:00
|
|
|
# include <list>
|
2011-03-22 17:16:20 +01:00
|
|
|
# include <map>
|
2011-03-29 10:33:09 +02:00
|
|
|
# include <vector>
|
2011-04-01 03:50:48 +02:00
|
|
|
# include "parse_types.h"
|
2011-03-27 21:01:58 +02:00
|
|
|
# include <assert.h>
|
2010-12-13 05:02:18 +01:00
|
|
|
|
2011-01-06 18:27:30 +01:00
|
|
|
inline void FILE_NAME(LineInfo*tmp, const struct yyltype&where)
|
|
|
|
|
{
|
|
|
|
|
tmp->set_lineno(where.first_line);
|
|
|
|
|
tmp->set_file(filename_strings.make(where.text));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-03-19 19:15:47 +01:00
|
|
|
/* Recent version of bison expect that the user supply a
|
|
|
|
|
YYLLOC_DEFAULT macro that makes up a yylloc value from existing
|
|
|
|
|
values. I need to supply an explicit version to account for the
|
|
|
|
|
text field, that otherwise won't be copied. */
|
|
|
|
|
# define YYLLOC_DEFAULT(Current, Rhs, N) do { \
|
|
|
|
|
(Current).first_line = (Rhs)[1].first_line; \
|
|
|
|
|
(Current).first_column = (Rhs)[1].first_column; \
|
|
|
|
|
(Current).last_line = (Rhs)[N].last_line; \
|
|
|
|
|
(Current).last_column = (Rhs)[N].last_column; \
|
|
|
|
|
(Current).text = (Rhs)[1].text; } while (0)
|
|
|
|
|
|
2010-12-13 05:02:18 +01:00
|
|
|
static void yyerror(const char*msg);
|
|
|
|
|
|
2010-12-15 06:36:47 +01:00
|
|
|
int parse_errors = 0;
|
2011-03-20 02:26:43 +01:00
|
|
|
int parse_sorrys = 0;
|
2011-03-22 17:16:20 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This map accumulates signals that are matched in the declarations
|
|
|
|
|
* section of a block. When the declarations are over, these are
|
|
|
|
|
* transferred to a map for the block proper.
|
|
|
|
|
*/
|
|
|
|
|
static map<perm_string, Signal*> block_signals;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This map accumulates component declarations.
|
|
|
|
|
*/
|
|
|
|
|
static map<perm_string, ComponentBase*> block_components;
|
2010-12-13 05:02:18 +01:00
|
|
|
%}
|
|
|
|
|
|
2011-01-31 18:25:29 +01:00
|
|
|
|
2011-01-03 07:30:09 +01:00
|
|
|
%union {
|
|
|
|
|
port_mode_t port_mode;
|
2011-02-19 20:39:00 +01:00
|
|
|
|
2011-01-03 07:30:09 +01:00
|
|
|
char*text;
|
2011-03-15 01:34:57 +01:00
|
|
|
|
2011-02-19 20:39:00 +01:00
|
|
|
std::list<perm_string>* name_list;
|
2011-03-29 10:33:09 +02:00
|
|
|
std::vector<perm_string>* compound_name;
|
|
|
|
|
std::list<std::vector<perm_string>* >* compound_name_list;
|
2011-01-30 02:27:30 +01:00
|
|
|
|
2011-02-14 04:01:21 +01:00
|
|
|
bool flag;
|
|
|
|
|
int64_t uni_integer;
|
|
|
|
|
double uni_real;
|
2011-03-29 10:33:09 +02:00
|
|
|
|
2011-01-30 02:27:30 +01:00
|
|
|
Expression*expr;
|
|
|
|
|
std::list<Expression*>* expr_list;
|
|
|
|
|
|
2011-04-01 03:50:48 +02:00
|
|
|
named_expr_t*named_expr;
|
|
|
|
|
std::list<named_expr_t*>*named_expr_list;
|
2011-03-31 15:19:42 +02:00
|
|
|
entity_aspect_t* entity_aspect;
|
2011-03-31 17:02:44 +02:00
|
|
|
instant_list_t* instantiation_list;
|
2011-04-01 09:50:04 +02:00
|
|
|
std::pair<instant_list_t*, ExpName*>* component_specification;
|
2011-04-01 03:50:48 +02:00
|
|
|
|
2011-02-14 01:37:10 +01:00
|
|
|
const VType* vtype;
|
|
|
|
|
|
2011-01-03 07:30:09 +01:00
|
|
|
std::list<InterfacePort*>* interface_list;
|
2011-01-27 05:38:20 +01:00
|
|
|
|
|
|
|
|
Architecture::Statement* arch_statement;
|
|
|
|
|
std::list<Architecture::Statement*>* arch_statement_list;
|
2011-01-03 07:30:09 +01:00
|
|
|
};
|
|
|
|
|
|
2010-12-13 05:02:18 +01:00
|
|
|
/* The keywords are all tokens. */
|
|
|
|
|
%token K_abs K_access K_after K_alias K_all K_and K_architecture
|
|
|
|
|
%token K_array K_assert K_assume K_assume_guarantee K_attribute
|
|
|
|
|
%token K_begin K_block K_body K_buffer K_bus
|
|
|
|
|
%token K_case K_component K_configuration K_constant K_context K_cover
|
2011-01-27 15:13:38 +01:00
|
|
|
%token K_default K_disconnect K_downto
|
2010-12-13 05:02:18 +01:00
|
|
|
%token K_else K_elsif K_end K_entity K_exit
|
|
|
|
|
%token K_fairness K_file K_for K_force K_function
|
|
|
|
|
%token K_generate K_generic K_group K_guarded
|
2011-01-27 15:13:38 +01:00
|
|
|
%token K_if K_impure K_in K_inertial K_inout K_is
|
2010-12-13 05:02:18 +01:00
|
|
|
%token K_label K_library K_linkage K_literal K_loop
|
|
|
|
|
%token K_map K_mod
|
|
|
|
|
%token K_nand K_new K_next K_nor K_not K_null
|
|
|
|
|
%token K_of K_on K_open K_or K_others K_out
|
|
|
|
|
%token K_package K_parameter K_port K_postponed K_procedure K_process
|
|
|
|
|
%token K_property K_protected K_pure
|
|
|
|
|
%token K_range K_record K_register K_reject K_release K_rem K_report
|
|
|
|
|
%token K_restrict K_restrict_guarantee K_return K_rol K_ror
|
2011-01-27 15:13:38 +01:00
|
|
|
%token K_select K_sequence K_severity K_signal K_shared
|
2011-01-28 10:40:38 +01:00
|
|
|
%token K_sla K_sll K_sra K_srl K_strong K_subtype
|
2010-12-13 05:02:18 +01:00
|
|
|
%token K_then K_to K_transport K_type
|
|
|
|
|
%token K_unaffected K_units K_until K_use
|
|
|
|
|
%token K_variable K_vmode K_vprop K_vunit
|
|
|
|
|
%token K_wait K_when K_while K_with
|
|
|
|
|
%token K_xnor K_xor
|
|
|
|
|
/* Identifiers that are not keywords are identifiers. */
|
2011-01-03 07:30:09 +01:00
|
|
|
%token <text> IDENTIFIER
|
2011-02-14 04:01:21 +01:00
|
|
|
%token <uni_integer> INT_LITERAL
|
|
|
|
|
%token <uni_real> REAL_LITERAL
|
2011-01-31 18:25:29 +01:00
|
|
|
%token <text> STRING_LITERAL CHARACTER_LITERAL
|
2010-12-15 06:36:47 +01:00
|
|
|
/* compound symbols */
|
2011-01-31 18:25:29 +01:00
|
|
|
%token LEQ GEQ VASSIGN NE BOX EXP ARROW DLT DGT
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2011-01-03 07:30:09 +01:00
|
|
|
/* The rules may have types. */
|
2011-01-27 05:38:20 +01:00
|
|
|
|
2011-02-14 04:01:21 +01:00
|
|
|
%type <flag> direction
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
%type <interface_list> interface_element interface_list entity_header
|
|
|
|
|
%type <interface_list> port_clause port_clause_opt
|
2011-01-03 07:30:09 +01:00
|
|
|
%type <port_mode> mode
|
|
|
|
|
|
2011-03-31 17:02:44 +02:00
|
|
|
%type <entity_aspect> entity_aspect entity_aspect_opt binding_indication binding_indication_semicolon_opt
|
|
|
|
|
%type <instantiation_list> instantiation_list
|
2011-04-01 09:50:04 +02:00
|
|
|
%type <component_specification> component_specification
|
2011-03-31 15:19:42 +02:00
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
%type <arch_statement> concurrent_statement component_instantiation_statement concurrent_signal_assignment_statement
|
2011-01-27 05:38:20 +01:00
|
|
|
%type <arch_statement_list> architecture_statement_part
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
%type <expr> expression factor primary relation
|
|
|
|
|
%type <expr> expression_logical expression_logical_and expression_logical_or
|
|
|
|
|
%type <expr> expression_logical_xnor expression_logical_xor
|
2011-03-27 21:01:58 +02:00
|
|
|
%type <expr> name
|
2011-01-30 02:27:30 +01:00
|
|
|
%type <expr> shift_expression simple_expression term waveform_element
|
|
|
|
|
|
|
|
|
|
%type <expr_list> waveform waveform_elements
|
2011-02-03 05:14:27 +01:00
|
|
|
|
2011-04-01 03:50:48 +02:00
|
|
|
%type <named_expr> association_element
|
|
|
|
|
%type <named_expr_list> association_list port_map_aspect port_map_aspect_opt
|
|
|
|
|
|
2011-02-14 01:37:10 +01:00
|
|
|
%type <vtype> subtype_indication
|
|
|
|
|
|
2011-03-29 10:33:09 +02:00
|
|
|
%type <text> identifier_opt logical_name suffix
|
2011-03-19 19:15:47 +01:00
|
|
|
%type <name_list> logical_name_list identifier_list
|
2011-03-29 10:33:09 +02:00
|
|
|
%type <compound_name> prefix selected_name
|
|
|
|
|
%type <compound_name_list> selected_names use_clause
|
2011-02-03 05:14:27 +01:00
|
|
|
|
2010-12-13 05:02:18 +01:00
|
|
|
%%
|
|
|
|
|
|
2010-12-15 06:36:47 +01:00
|
|
|
/* The design_file is the root for the VHDL parse. */
|
|
|
|
|
design_file : design_units ;
|
|
|
|
|
|
|
|
|
|
architecture_body
|
|
|
|
|
: K_architecture IDENTIFIER
|
|
|
|
|
K_of IDENTIFIER
|
2011-03-20 02:26:43 +01:00
|
|
|
K_is block_declarative_items_opt
|
2011-02-03 05:14:27 +01:00
|
|
|
K_begin architecture_statement_part K_end K_architecture_opt identifier_opt ';'
|
2011-03-22 17:16:20 +01:00
|
|
|
{ Architecture*tmp = new Architecture(lex_strings.make($2),
|
|
|
|
|
block_signals,
|
|
|
|
|
block_components, *$8);
|
2011-01-24 05:26:27 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
bind_architecture_to_entity($4, tmp);
|
2011-03-20 02:26:43 +01:00
|
|
|
if ($11 && tmp->get_name() != $11)
|
2011-03-28 18:59:04 +02:00
|
|
|
errormsg(@2, "Architecture name doesn't match closing name.\n");
|
2011-01-24 05:26:27 +01:00
|
|
|
delete[]$2;
|
|
|
|
|
delete[]$4;
|
2011-03-20 02:26:43 +01:00
|
|
|
delete $8;
|
2011-03-22 17:16:20 +01:00
|
|
|
block_signals.clear();
|
|
|
|
|
block_components.clear();
|
2011-03-20 02:26:43 +01:00
|
|
|
if ($11) delete[]$11;
|
2011-01-24 05:26:27 +01:00
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
| K_architecture IDENTIFIER
|
|
|
|
|
K_of IDENTIFIER
|
2011-03-20 02:26:43 +01:00
|
|
|
K_is block_declarative_items_opt
|
2011-03-19 19:15:47 +01:00
|
|
|
K_begin error K_end K_architecture_opt identifier_opt ';'
|
2011-03-20 02:26:43 +01:00
|
|
|
{ errormsg(@8, "Errors in architecture statements.\n"); yyerrok; }
|
2010-12-15 06:36:47 +01:00
|
|
|
| K_architecture error ';'
|
2011-03-20 02:26:43 +01:00
|
|
|
{ errormsg(@2, "Errors in architecture body.\n"); yyerrok; }
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
/*
|
|
|
|
|
* The architecture_statement_part is a list of concurrent
|
|
|
|
|
* statements.
|
|
|
|
|
*/
|
2010-12-15 06:36:47 +01:00
|
|
|
architecture_statement_part
|
|
|
|
|
: architecture_statement_part concurrent_statement
|
2011-01-27 05:38:20 +01:00
|
|
|
{ std::list<Architecture::Statement*>*tmp = $1;
|
2011-03-19 19:15:47 +01:00
|
|
|
if ($2) tmp->push_back($2);
|
2011-01-27 05:38:20 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
| concurrent_statement
|
2011-01-27 05:38:20 +01:00
|
|
|
{ std::list<Architecture::Statement*>*tmp = new std::list<Architecture::Statement*>;
|
2011-03-19 19:15:47 +01:00
|
|
|
if ($1) tmp->push_back($1);
|
2011-01-27 05:38:20 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
|
|
|
|
|
| error ';'
|
|
|
|
|
{ $$ = 0;
|
|
|
|
|
errormsg(@1, "Syntax error in architecture statement.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
association_element
|
2011-04-01 03:50:48 +02:00
|
|
|
: IDENTIFIER ARROW name
|
|
|
|
|
{ named_expr_t*tmp = new named_expr_t(lex_strings.make($1), $3);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
association_list
|
|
|
|
|
: association_list ',' association_element
|
2011-04-01 03:50:48 +02:00
|
|
|
{ std::list<named_expr_t*>*tmp = $1;
|
|
|
|
|
tmp->push_back($3);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
| association_element
|
2011-04-01 03:50:48 +02:00
|
|
|
{ std::list<named_expr_t*>*tmp = new std::list<named_expr_t*>;
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
binding_indication
|
|
|
|
|
: K_use entity_aspect_opt
|
|
|
|
|
port_map_aspect_opt
|
|
|
|
|
generic_map_aspect_opt
|
2011-03-31 17:02:44 +02:00
|
|
|
{ //TODO: do sth with generic map aspect
|
|
|
|
|
$$ = $2;
|
|
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
binding_indication_semicolon_opt
|
2011-03-31 17:02:44 +02:00
|
|
|
: binding_indication ';' { $$ = $1; }
|
|
|
|
|
| { $$ = 0; }
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
block_configuration
|
|
|
|
|
: K_for IDENTIFIER
|
|
|
|
|
use_clauses_opt
|
|
|
|
|
configuration_items_opt
|
|
|
|
|
K_end K_for ';'
|
|
|
|
|
{ delete[] $2; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
block_configuration_opt
|
|
|
|
|
: block_configuration
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
block_declarative_item
|
|
|
|
|
: K_signal identifier_list ':' subtype_indication ';'
|
2011-03-22 17:16:20 +01:00
|
|
|
{ /* Save the signal declaration in the block_signals map. */
|
|
|
|
|
for (std::list<perm_string>::iterator cur = $2->begin()
|
|
|
|
|
; cur != $2->end() ; ++cur) {
|
|
|
|
|
Signal*sig = new Signal(*cur, $4);
|
|
|
|
|
FILE_NAME(sig, @1);
|
|
|
|
|
block_signals[*cur] = sig;
|
|
|
|
|
}
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
|
|
|
|
|
| K_component IDENTIFIER K_is_opt
|
|
|
|
|
port_clause_opt
|
|
|
|
|
K_end K_component identifier_opt ';'
|
|
|
|
|
{ perm_string name = lex_strings.make($2);
|
2011-03-28 18:59:04 +02:00
|
|
|
if($7) {
|
|
|
|
|
if (name != $7)
|
|
|
|
|
errormsg(@7, "Identifier %s doesn't match component name %s.\n",
|
2011-03-20 02:26:43 +01:00
|
|
|
$7, name.str());
|
2011-03-28 18:59:04 +02:00
|
|
|
delete[] $7;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
|
2011-03-22 17:16:20 +01:00
|
|
|
ComponentBase*comp = new ComponentBase(name);
|
|
|
|
|
if ($4) comp->set_interface($4);
|
|
|
|
|
block_components[name] = comp;
|
2011-03-20 02:26:43 +01:00
|
|
|
delete[]$2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Various error handling rules for block_declarative_item... */
|
|
|
|
|
|
|
|
|
|
| K_signal error ';'
|
|
|
|
|
{ errormsg(@2, "Syntax error declaring signals.\n"); yyerrok; }
|
|
|
|
|
| error ';'
|
|
|
|
|
{ errormsg(@1, "Syntax error in block declarations.\n"); yyerrok; }
|
|
|
|
|
|
|
|
|
|
| K_component IDENTIFIER K_is_opt error K_end K_component identifier_opt ';'
|
2011-03-28 18:59:04 +02:00
|
|
|
{ errormsg(@4, "Syntax error in component declaration.\n");
|
|
|
|
|
delete[] $2;
|
|
|
|
|
if($7) {
|
|
|
|
|
delete[] $7;
|
|
|
|
|
}
|
|
|
|
|
yyerrok; }
|
2011-03-20 02:26:43 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The block_declarative_items rule matches "{ block_declarative_item }"
|
|
|
|
|
* which is a synonym for "architecture_declarative_part" and
|
|
|
|
|
* "block_declarative_part".
|
|
|
|
|
*/
|
|
|
|
|
block_declarative_items
|
|
|
|
|
: block_declarative_items block_declarative_item
|
|
|
|
|
| block_declarative_item
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
block_declarative_items_opt
|
|
|
|
|
: block_declarative_items
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
component_configuration
|
|
|
|
|
: K_for component_specification
|
|
|
|
|
binding_indication_semicolon_opt
|
|
|
|
|
block_configuration_opt
|
|
|
|
|
K_end K_for ';'
|
2011-04-01 09:50:04 +02:00
|
|
|
| K_for component_specification error K_end K_for
|
|
|
|
|
{
|
|
|
|
|
errormsg(@1, "Error in component configuration statement.\n");
|
|
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
component_instantiation_statement
|
2011-04-01 03:50:48 +02:00
|
|
|
: IDENTIFIER ':' K_component_opt IDENTIFIER port_map_aspect_opt ';'
|
|
|
|
|
{ perm_string iname = lex_strings.make($1);
|
|
|
|
|
perm_string cname = lex_strings.make($4);
|
|
|
|
|
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $5);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
2011-03-20 02:26:43 +01:00
|
|
|
delete[]$1;
|
2011-04-01 03:50:48 +02:00
|
|
|
delete[]$4;
|
|
|
|
|
$$ = tmp;
|
2011-03-20 02:26:43 +01:00
|
|
|
}
|
2011-04-01 03:50:48 +02:00
|
|
|
| IDENTIFIER ':' K_component_opt IDENTIFIER error ';'
|
2011-03-20 02:26:43 +01:00
|
|
|
{ errormsg(@4, "Errors in component instantiation.\n");
|
|
|
|
|
delete[]$1;
|
2011-04-01 03:50:48 +02:00
|
|
|
delete[]$4;
|
2011-03-20 02:26:43 +01:00
|
|
|
$$ = 0;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
component_specification
|
2011-04-01 09:50:04 +02:00
|
|
|
: instantiation_list ':' name
|
|
|
|
|
{
|
|
|
|
|
ExpName* name = dynamic_cast<ExpName*>($3);
|
|
|
|
|
std::pair<instant_list_t*, ExpName*>* tmp = new std::pair<instant_list_t*, ExpName*>($1, name);
|
|
|
|
|
$$ = tmp;
|
2011-03-28 18:59:04 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2010-12-15 06:36:47 +01:00
|
|
|
concurrent_signal_assignment_statement
|
2011-03-20 02:26:43 +01:00
|
|
|
: name LEQ waveform ';'
|
2011-03-27 21:01:58 +02:00
|
|
|
{ ExpName*name = dynamic_cast<ExpName*> ($1);
|
|
|
|
|
assert(name);
|
|
|
|
|
SignalAssignment*tmp = new SignalAssignment(name, *$3);
|
2011-01-27 05:38:20 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
|
|
|
|
|
$$ = tmp;
|
2011-01-30 02:27:30 +01:00
|
|
|
delete $3;
|
2011-01-27 05:38:20 +01:00
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
| name LEQ error ';'
|
2011-03-19 19:15:47 +01:00
|
|
|
{ errormsg(@2, "Syntax error in signal assignment waveform.\n");
|
2011-03-27 21:01:58 +02:00
|
|
|
delete $1;
|
2011-03-19 19:15:47 +01:00
|
|
|
$$ = 0;
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
concurrent_statement
|
2011-03-20 02:26:43 +01:00
|
|
|
: component_instantiation_statement
|
|
|
|
|
| concurrent_signal_assignment_statement
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
2011-03-31 15:22:55 +02:00
|
|
|
|
|
|
|
|
configuration_declaration
|
|
|
|
|
: K_configuration IDENTIFIER K_of IDENTIFIER K_is
|
|
|
|
|
configuration_declarative_part
|
|
|
|
|
block_configuration
|
|
|
|
|
K_end K_configuration_opt identifier_opt ';'
|
|
|
|
|
{
|
|
|
|
|
if(design_entities.find(lex_strings.make($4)) == design_entities.end())
|
|
|
|
|
errormsg(@4, "Couldn't find entity %s used in configuration declaration", $4);
|
|
|
|
|
//choose_architecture_for_entity();
|
|
|
|
|
sorrymsg(@1, "Configuration declaration is not yet supported.\n");
|
|
|
|
|
}
|
|
|
|
|
| K_configuration error K_end K_configuration_opt identifier_opt ';'
|
|
|
|
|
{ errormsg(@2, "Too many errors, giving up on configuration declaration.\n");
|
|
|
|
|
if($5) delete $5;
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
;
|
2011-03-28 18:59:04 +02:00
|
|
|
//TODO: this list is only a sketch. It must be filled out later
|
|
|
|
|
configuration_declarative_item
|
|
|
|
|
: use_clause
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
configuration_declarative_items
|
|
|
|
|
: configuration_declarative_items configuration_declarative_item
|
|
|
|
|
| configuration_declarative_item
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
configuration_declarative_part
|
|
|
|
|
: configuration_declarative_items
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
configuration_item
|
|
|
|
|
: block_configuration
|
|
|
|
|
| component_configuration
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
configuration_items
|
|
|
|
|
: configuration_items configuration_item
|
|
|
|
|
| configuration_item
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
configuration_items_opt
|
|
|
|
|
: configuration_items
|
|
|
|
|
|
|
|
|
|
|
;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
|
|
|
|
context_clause : context_items | ;
|
|
|
|
|
|
|
|
|
|
context_item
|
|
|
|
|
: library_clause
|
2011-03-29 10:33:09 +02:00
|
|
|
| use_clause_lib
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
context_items
|
|
|
|
|
: context_items context_item
|
|
|
|
|
| context_item
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
design_unit
|
|
|
|
|
: context_clause library_unit
|
|
|
|
|
| error { errormsg(@1, "Invalid design_unit\n"); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
design_units
|
2011-03-03 05:23:02 +01:00
|
|
|
: design_units design_unit
|
2010-12-15 06:36:47 +01:00
|
|
|
| design_unit
|
|
|
|
|
;
|
|
|
|
|
|
2011-02-14 04:01:21 +01:00
|
|
|
/* Indicate the direction as a flag, with "downto" being TRUE. */
|
|
|
|
|
direction : K_to { $$ = false; } | K_downto { $$ = true; } ;
|
2011-02-14 01:37:10 +01:00
|
|
|
|
2011-01-03 07:30:09 +01:00
|
|
|
/* As an entity is declared, add it to the map of design entities. */
|
2011-03-28 18:59:04 +02:00
|
|
|
entity_aspect
|
2011-03-31 15:19:42 +02:00
|
|
|
: K_entity name
|
|
|
|
|
{
|
|
|
|
|
ExpName* name = dynamic_cast<ExpName*>($2);
|
|
|
|
|
entity_aspect_t* tmp = new entity_aspect_t(entity_aspect_t::ENTITY, name);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_configuration name
|
|
|
|
|
{
|
|
|
|
|
ExpName* name = dynamic_cast<ExpName*>($2);
|
|
|
|
|
entity_aspect_t* tmp = new entity_aspect_t(entity_aspect_t::CONFIGURATION, name);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
| K_open
|
2011-03-31 15:19:42 +02:00
|
|
|
{
|
|
|
|
|
entity_aspect_t* tmp = new entity_aspect_t(entity_aspect_t::OPEN, 0);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
entity_aspect_opt
|
2011-03-31 15:19:42 +02:00
|
|
|
: entity_aspect { $$ = $1; }
|
|
|
|
|
| { $$ = 0; }
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
2010-12-15 06:36:47 +01:00
|
|
|
entity_declaration
|
2011-03-23 16:17:18 +01:00
|
|
|
: K_entity IDENTIFIER K_is entity_header K_end K_entity_opt identifier_opt';'
|
2011-01-24 05:26:27 +01:00
|
|
|
{ Entity*tmp = new Entity(lex_strings.make($2));
|
2011-01-06 18:27:30 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2011-01-03 07:30:09 +01:00
|
|
|
// Transfer the ports
|
|
|
|
|
std::list<InterfacePort*>*ports = $4;
|
2011-02-03 04:59:20 +01:00
|
|
|
tmp->set_interface(ports);
|
2011-01-03 07:30:09 +01:00
|
|
|
delete ports;
|
|
|
|
|
// Save the entity in the entity map.
|
2011-01-24 05:26:27 +01:00
|
|
|
design_entities[tmp->get_name()] = tmp;
|
|
|
|
|
delete[]$2;
|
2011-03-23 16:17:18 +01:00
|
|
|
if($7) {
|
|
|
|
|
if(tmp->get_name() != $7) {
|
|
|
|
|
errormsg(@1, "Syntax error in entity clause. Closing name doesn't match.\n");
|
2011-03-28 18:59:04 +02:00
|
|
|
yyerrok;
|
2011-03-23 16:17:18 +01:00
|
|
|
}
|
|
|
|
|
delete $7;
|
|
|
|
|
}
|
2011-01-27 02:44:58 +01:00
|
|
|
}
|
2011-02-14 01:37:10 +01:00
|
|
|
| K_entity error K_end K_entity_opt identifier_opt ';'
|
|
|
|
|
{ errormsg(@1, "Too many errors, giving up on entity declaration.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
if ($5) delete[]$5;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
entity_header
|
|
|
|
|
: port_clause
|
2011-01-03 07:30:09 +01:00
|
|
|
{ $$ = $1; }
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
expression
|
|
|
|
|
: expression_logical
|
2011-01-30 02:27:30 +01:00
|
|
|
{ $$ = $1; }
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
/*
|
|
|
|
|
* The expression_logical matches the logical_expression from the
|
|
|
|
|
* standard. Note that this is a little more tricky then usual because
|
|
|
|
|
* of the strange VHDL rules for logical expressions. We have to
|
|
|
|
|
* account for things like this:
|
|
|
|
|
*
|
|
|
|
|
* <exp> and <exp> and <exp>...
|
|
|
|
|
*
|
|
|
|
|
* which is matched by the standard rule:
|
|
|
|
|
*
|
|
|
|
|
* logical_expression ::=
|
|
|
|
|
* ...
|
|
|
|
|
* relation { and relation }
|
|
|
|
|
*
|
|
|
|
|
* The {} is important, and implies that "and" can be strung together
|
|
|
|
|
* with other "and" operators without parentheses. This is true for
|
|
|
|
|
* "and", "or", "xor", and "xnor". The tricky part is that these
|
|
|
|
|
* cannot be mixed. For example, this is not OK:
|
|
|
|
|
*
|
|
|
|
|
* <exp> and <exp> or <exp>
|
|
|
|
|
*
|
|
|
|
|
* Also note that "nand" and "nor" can not be chained in this manner.
|
|
|
|
|
*/
|
2010-12-15 06:36:47 +01:00
|
|
|
expression_logical
|
2011-02-20 02:47:30 +01:00
|
|
|
: relation { $$ = $1; }
|
2011-03-20 02:26:43 +01:00
|
|
|
| relation K_and expression_logical_and
|
2011-01-30 02:27:30 +01:00
|
|
|
{ ExpLogical*tmp = new ExpLogical(ExpLogical::AND, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
| relation K_or expression_logical_or
|
2011-01-30 02:27:30 +01:00
|
|
|
{ ExpLogical*tmp = new ExpLogical(ExpLogical::OR, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
| relation K_xor expression_logical_xor
|
2011-01-30 02:27:30 +01:00
|
|
|
{ ExpLogical*tmp = new ExpLogical(ExpLogical::XOR, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| relation K_nand relation
|
|
|
|
|
{ ExpLogical*tmp = new ExpLogical(ExpLogical::NAND, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| relation K_nor relation
|
|
|
|
|
{ ExpLogical*tmp = new ExpLogical(ExpLogical::NOR, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
| relation K_xnor expression_logical_xnor
|
|
|
|
|
{ ExpLogical*tmp = new ExpLogical(ExpLogical::XNOR, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
expression_logical_and
|
|
|
|
|
: relation
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| expression_logical_and K_and relation
|
|
|
|
|
{ ExpLogical*tmp = new ExpLogical(ExpLogical::AND, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
expression_logical_or
|
|
|
|
|
: relation
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| expression_logical_or K_or relation
|
|
|
|
|
{ ExpLogical*tmp = new ExpLogical(ExpLogical::OR, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
expression_logical_xnor
|
|
|
|
|
: relation
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| expression_logical_xnor K_xnor relation
|
2011-01-30 02:27:30 +01:00
|
|
|
{ ExpLogical*tmp = new ExpLogical(ExpLogical::XNOR, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
expression_logical_xor
|
|
|
|
|
: relation
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| expression_logical_xor K_xor relation
|
|
|
|
|
{ ExpLogical*tmp = new ExpLogical(ExpLogical::XOR, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-02-20 02:47:30 +01:00
|
|
|
factor
|
|
|
|
|
: primary
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| primary EXP primary
|
|
|
|
|
{ ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::POW, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-02-21 02:03:46 +01:00
|
|
|
| K_abs primary
|
|
|
|
|
{ ExpUAbs*tmp = new ExpUAbs($2);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_not primary
|
|
|
|
|
{ ExpUNot*tmp = new ExpUNot($2);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-02-20 02:47:30 +01:00
|
|
|
;
|
2011-03-28 18:59:04 +02:00
|
|
|
generic_map_aspect_opt
|
|
|
|
|
: generic_map_aspect
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
generic_map_aspect
|
|
|
|
|
: K_generic K_map '(' association_list ')'
|
|
|
|
|
;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2011-03-19 19:15:47 +01:00
|
|
|
identifier_list
|
|
|
|
|
: identifier_list ',' IDENTIFIER
|
|
|
|
|
{ std::list<perm_string>* tmp = $1;
|
|
|
|
|
tmp->push_back(lex_strings.make($3));
|
|
|
|
|
delete[]$3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| IDENTIFIER
|
|
|
|
|
{ std::list<perm_string>*tmp = new std::list<perm_string>;
|
|
|
|
|
tmp->push_back(lex_strings.make($1));
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-02-03 05:14:27 +01:00
|
|
|
identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
|
|
|
|
|
instantiation_list
|
|
|
|
|
: identifier_list
|
2011-03-31 17:02:44 +02:00
|
|
|
{
|
|
|
|
|
instant_list_t* tmp = new instant_list_t(instant_list_t::NONE, $1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
| K_others
|
2011-03-31 17:02:44 +02:00
|
|
|
{
|
|
|
|
|
instant_list_t* tmp = new instant_list_t(instant_list_t::OTHERS, 0);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
| K_all
|
|
|
|
|
{
|
2011-03-31 17:02:44 +02:00
|
|
|
instant_list_t* tmp = new instant_list_t(instant_list_t::ALL, 0);
|
|
|
|
|
$$ = tmp;
|
2011-03-28 18:59:04 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2010-12-15 06:36:47 +01:00
|
|
|
/* The interface_element is also an interface_declaration */
|
|
|
|
|
interface_element
|
2011-03-19 19:15:47 +01:00
|
|
|
: identifier_list ':' mode subtype_indication
|
|
|
|
|
{ std::list<InterfacePort*>*tmp = new std::list<InterfacePort*>;
|
|
|
|
|
for (std::list<perm_string>::iterator cur = $1->begin()
|
|
|
|
|
; cur != $1->end() ; ++cur) {
|
|
|
|
|
InterfacePort*port = new InterfacePort;
|
|
|
|
|
FILE_NAME(port, @1);
|
|
|
|
|
port->mode = $3;
|
|
|
|
|
port->name = *(cur);
|
|
|
|
|
port->type = $4;
|
|
|
|
|
tmp->push_back(port);
|
|
|
|
|
}
|
|
|
|
|
delete $1;
|
2011-01-03 07:30:09 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
interface_list
|
|
|
|
|
: interface_list ';' interface_element
|
2011-01-06 17:12:55 +01:00
|
|
|
{ std::list<InterfacePort*>*tmp = $1;
|
2011-03-19 19:15:47 +01:00
|
|
|
tmp->splice(tmp->end(), *$3);
|
|
|
|
|
delete $3;
|
2011-01-03 07:30:09 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
| interface_element
|
2011-03-19 19:15:47 +01:00
|
|
|
{ std::list<InterfacePort*>*tmp = $1;
|
2011-01-03 07:30:09 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
library_clause
|
|
|
|
|
: K_library logical_name_list ';'
|
2011-02-19 20:39:00 +01:00
|
|
|
{ library_import(@1, $2);
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
| K_library error ';'
|
|
|
|
|
{ errormsg(@1, "Syntax error in library clause.\n"); yyerrok; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Collapse the primary_unit and secondary_unit of the library_unit
|
|
|
|
|
into this single set of rules. */
|
|
|
|
|
library_unit
|
2011-03-28 18:59:04 +02:00
|
|
|
: primary_unit
|
|
|
|
|
| secondary_unit
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-02-19 20:39:00 +01:00
|
|
|
logical_name : IDENTIFIER { $$ = $1; } ;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
|
|
|
|
logical_name_list
|
|
|
|
|
: logical_name_list ',' logical_name
|
2011-02-19 20:39:00 +01:00
|
|
|
{ std::list<perm_string>*tmp = $1;
|
|
|
|
|
tmp->push_back(lex_strings.make($3));
|
|
|
|
|
delete[]$3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
| logical_name
|
2011-02-19 20:39:00 +01:00
|
|
|
{ std::list<perm_string>*tmp = new std::list<perm_string>;
|
|
|
|
|
tmp->push_back(lex_strings.make($1));
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-01-03 07:30:09 +01:00
|
|
|
mode
|
|
|
|
|
: K_in { $$ = PORT_IN; }
|
|
|
|
|
| K_out { $$ = PORT_OUT; }
|
|
|
|
|
;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
name
|
|
|
|
|
: IDENTIFIER
|
2011-03-27 21:01:58 +02:00
|
|
|
{ ExpName*tmp = new ExpName(lex_strings.make($1));
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
| IDENTIFIER '(' expression ')'
|
2011-03-27 21:01:58 +02:00
|
|
|
{ ExpName*tmp = new ExpName(lex_strings.make($1), $3);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
2011-03-20 02:26:43 +01:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
package_declaration
|
|
|
|
|
: K_package IDENTIFIER K_is
|
|
|
|
|
package_declarative_part_opt
|
|
|
|
|
K_end K_package_opt identifier_opt ';'
|
|
|
|
|
{ sorrymsg(@4, "Package declaration not supported yet.\n");
|
|
|
|
|
if($7) {
|
|
|
|
|
if($2 != $7) {
|
|
|
|
|
errormsg(@1, "Syntax error in package clause. Closing name doesn't match.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
delete $7;
|
|
|
|
|
}
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
|
|
|
|
| K_package error K_end K_package_opt identifier_opt ';'
|
|
|
|
|
{ errormsg(@2, "Syntax error in package clause.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* TODO: this list must be extended in the future
|
|
|
|
|
presently it is only a sketch */
|
|
|
|
|
package_body_declarative_item
|
|
|
|
|
: use_clause
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
package_body_declarative_items
|
|
|
|
|
: package_body_declarative_items package_body_declarative_item
|
|
|
|
|
| package_body_declarative_item
|
|
|
|
|
;
|
|
|
|
|
package_body_declarative_part_opt
|
|
|
|
|
: package_body_declarative_items
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* TODO: this list is only a sketch
|
|
|
|
|
it must be extended in the future */
|
|
|
|
|
package_declarative_item
|
|
|
|
|
: use_clause
|
|
|
|
|
;
|
|
|
|
|
package_declarative_items
|
|
|
|
|
: package_declarative_items package_declarative_item
|
|
|
|
|
| package_declarative_item
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
package_declarative_part_opt
|
|
|
|
|
: package_declarative_items
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
package_body
|
|
|
|
|
: K_package K_body IDENTIFIER K_is
|
|
|
|
|
package_body_declarative_part_opt
|
|
|
|
|
K_end K_package_opt identifier_opt ';'
|
|
|
|
|
{
|
|
|
|
|
delete[] $3;
|
|
|
|
|
if($8) delete[] $8;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-01-03 07:30:09 +01:00
|
|
|
port_clause
|
|
|
|
|
: K_port '(' interface_list ')' ';'
|
|
|
|
|
{ $$ = $3; }
|
2011-02-14 01:37:10 +01:00
|
|
|
| K_port '(' error ')' ';'
|
2011-03-28 18:59:04 +02:00
|
|
|
{ errormsg(@1, "Syntax error in port list.\n");
|
2011-02-14 01:37:10 +01:00
|
|
|
yyerrok;
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
2011-01-03 07:30:09 +01:00
|
|
|
;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
port_clause_opt : port_clause {$$ = $1;} | {$$ = 0;} ;
|
|
|
|
|
|
|
|
|
|
port_map_aspect
|
|
|
|
|
: K_port K_map '(' association_list ')'
|
2011-04-01 03:50:48 +02:00
|
|
|
{ $$ = $4; }
|
2011-03-20 02:26:43 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
port_map_aspect_opt
|
2011-04-01 03:50:48 +02:00
|
|
|
: port_map_aspect { $$ = $1; }
|
|
|
|
|
| { $$ = 0; }
|
2011-03-20 02:26:43 +01:00
|
|
|
;
|
|
|
|
|
|
2011-03-29 10:33:09 +02:00
|
|
|
prefix
|
|
|
|
|
: IDENTIFIER
|
|
|
|
|
{
|
|
|
|
|
std::vector<perm_string>* tmp = new std::vector<perm_string>();
|
|
|
|
|
tmp->push_back(lex_strings.make($1));
|
|
|
|
|
delete[] $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| STRING_LITERAL
|
|
|
|
|
{
|
|
|
|
|
std::vector<perm_string>* tmp = new std::vector<perm_string>();
|
|
|
|
|
tmp->push_back(lex_strings.make($1));
|
|
|
|
|
delete[] $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| selected_name
|
|
|
|
|
{
|
|
|
|
|
$$ = $1;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2010-12-15 06:36:47 +01:00
|
|
|
primary
|
2011-03-20 02:26:43 +01:00
|
|
|
: name
|
2011-03-27 21:01:58 +02:00
|
|
|
{ $$ = $1; }
|
2011-02-14 04:01:21 +01:00
|
|
|
| INT_LITERAL
|
|
|
|
|
{ ExpInteger*tmp = new ExpInteger($1);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-02-21 02:03:46 +01:00
|
|
|
| '(' expression ')'
|
|
|
|
|
{ $$ = $2; }
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
primary_unit
|
|
|
|
|
: entity_declaration
|
|
|
|
|
| configuration_declaration
|
|
|
|
|
| package_declaration
|
|
|
|
|
;
|
|
|
|
|
|
2011-01-30 02:27:30 +01:00
|
|
|
relation : shift_expression { $$ = $1; } ;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
secondary_unit
|
|
|
|
|
: architecture_body
|
|
|
|
|
| package_body
|
|
|
|
|
;
|
2011-03-29 10:33:09 +02:00
|
|
|
|
|
|
|
|
selected_name
|
|
|
|
|
: prefix '.' suffix
|
|
|
|
|
{
|
|
|
|
|
std::vector<perm_string>* tmp = $1;
|
|
|
|
|
tmp->push_back(lex_strings.make($3));
|
|
|
|
|
delete[] $3;
|
|
|
|
|
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
selected_names
|
|
|
|
|
: selected_names ',' selected_name
|
|
|
|
|
{
|
|
|
|
|
std::list<std::vector<perm_string>* >* tmp = $1;
|
|
|
|
|
tmp->push_back($3);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| selected_name
|
|
|
|
|
{
|
|
|
|
|
std::list<std::vector<perm_string>* >* tmp = new std::list<std::vector<perm_string>* >();
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
2011-02-19 22:08:26 +01:00
|
|
|
/* The *_use variant of selected_name is used by the "use"
|
|
|
|
|
clause. It is syntactically identical to other selected_name
|
|
|
|
|
rules, but is a convenient place to attach use_clause actions. */
|
|
|
|
|
selected_name_use
|
2010-12-15 06:36:47 +01:00
|
|
|
: IDENTIFIER '.' K_all
|
2011-02-19 22:08:26 +01:00
|
|
|
{ library_use(@1, 0, $1, 0);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
| IDENTIFIER '.' IDENTIFIER '.' K_all
|
2011-02-19 22:08:26 +01:00
|
|
|
{ library_use(@1, $1, $3, 0);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
delete[]$3;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-02-19 22:08:26 +01:00
|
|
|
selected_names_use
|
|
|
|
|
: selected_names_use ',' selected_name_use
|
|
|
|
|
| selected_name_use
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-01-30 02:27:30 +01:00
|
|
|
shift_expression : simple_expression { $$ = $1; } ;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2011-02-20 02:47:30 +01:00
|
|
|
simple_expression
|
|
|
|
|
: term
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| term '+' term
|
|
|
|
|
{ ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::PLUS, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| term '-' term
|
|
|
|
|
{ ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::MINUS, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2011-02-14 01:37:10 +01:00
|
|
|
subtype_indication
|
|
|
|
|
: IDENTIFIER
|
|
|
|
|
{ const VType*tmp = global_types[lex_strings.make($1)];
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-02-14 04:01:21 +01:00
|
|
|
| IDENTIFIER '(' simple_expression direction simple_expression ')'
|
|
|
|
|
{ const VType*tmp = calculate_subtype($1, $3, $4, $5);
|
2011-02-14 01:37:10 +01:00
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-29 10:33:09 +02:00
|
|
|
suffix
|
|
|
|
|
: IDENTIFIER
|
|
|
|
|
{
|
|
|
|
|
$$ = $1;
|
|
|
|
|
}
|
|
|
|
|
| CHARACTER_LITERAL
|
|
|
|
|
{
|
|
|
|
|
$$ = $1;
|
|
|
|
|
}
|
|
|
|
|
| K_all
|
|
|
|
|
{
|
|
|
|
|
//do not have now better idea than using char constant
|
|
|
|
|
$$ = strcpy(new char[strlen("all"+1)], "all");
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-02-20 02:47:30 +01:00
|
|
|
term
|
|
|
|
|
: factor
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| factor '*' factor
|
|
|
|
|
{ ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::MULT, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| factor '/' factor
|
|
|
|
|
{ ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::DIV, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| factor K_mod factor
|
|
|
|
|
{ ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::MOD, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| factor K_rem factor
|
|
|
|
|
{ ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::REM, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
|
|
|
|
use_clause
|
2011-03-29 10:33:09 +02:00
|
|
|
: K_use selected_names ';'
|
|
|
|
|
{
|
|
|
|
|
$$ = $2;
|
|
|
|
|
}
|
|
|
|
|
| K_use error ';'
|
|
|
|
|
{ errormsg(@1, "Syntax error in use clause.\n"); yyerrok; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
use_clause_lib
|
2011-02-19 22:08:26 +01:00
|
|
|
: K_use selected_names_use ';'
|
2010-12-15 06:36:47 +01:00
|
|
|
| K_use error ';'
|
|
|
|
|
{ errormsg(@1, "Syntax error in use clause.\n"); yyerrok; }
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
use_clauses
|
|
|
|
|
: use_clauses use_clause
|
|
|
|
|
| use_clause
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
use_clauses_opt
|
|
|
|
|
: use_clauses
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
2010-12-15 06:36:47 +01:00
|
|
|
waveform
|
|
|
|
|
: waveform_elements
|
2011-01-30 02:27:30 +01:00
|
|
|
{ $$ = $1; }
|
2010-12-15 06:36:47 +01:00
|
|
|
| K_unaffected
|
2011-01-30 02:27:30 +01:00
|
|
|
{ $$ = 0; }
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
waveform_elements
|
|
|
|
|
: waveform_elements ',' waveform_element
|
2011-01-30 02:27:30 +01:00
|
|
|
{ std::list<Expression*>*tmp = $1;
|
|
|
|
|
tmp->push_back($3);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
| waveform_element
|
2011-01-30 02:27:30 +01:00
|
|
|
{ std::list<Expression*>*tmp = new std::list<Expression*>;
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
waveform_element
|
|
|
|
|
: expression
|
2011-01-30 02:27:30 +01:00
|
|
|
{ $$ = $1; }
|
2010-12-15 06:36:47 +01:00
|
|
|
| K_null
|
2011-01-30 02:27:30 +01:00
|
|
|
{ $$ = 0; }
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* Some keywords are optional in some contexts. In all such cases, a
|
|
|
|
|
similar rule is used, as described here. */
|
|
|
|
|
K_architecture_opt : K_architecture | ;
|
2011-04-01 03:50:48 +02:00
|
|
|
K_component_opt : K_component | ;
|
2011-03-28 18:59:04 +02:00
|
|
|
K_configuration_opt: K_configuration| ;
|
2011-03-20 02:26:43 +01:00
|
|
|
K_entity_opt : K_entity | ;
|
2011-03-28 18:59:04 +02:00
|
|
|
K_package_opt : K_package | ;
|
2011-03-20 02:26:43 +01:00
|
|
|
K_is_opt : K_is | ;
|
2010-12-13 05:02:18 +01:00
|
|
|
%%
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
static void yyerror(const char* /*msg*/)
|
2010-12-13 05:02:18 +01:00
|
|
|
{
|
2011-03-20 02:26:43 +01:00
|
|
|
//fprintf(stderr, "%s\n", msg);
|
2010-12-15 06:36:47 +01:00
|
|
|
parse_errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char*file_path = "";
|
|
|
|
|
|
2011-02-19 20:39:00 +01:00
|
|
|
void errormsg(const YYLTYPE&loc, const char*fmt, ...)
|
2010-12-15 06:36:47 +01:00
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
fprintf(stderr, "%s:%d: error: ", file_path, loc.first_line);
|
2010-12-15 06:36:47 +01:00
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
parse_errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
void sorrymsg(const YYLTYPE&loc, const char*fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "%s:%d: sorry: ", file_path, loc.first_line);
|
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
parse_sorrys += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-15 06:36:47 +01:00
|
|
|
/*
|
|
|
|
|
* This is used only by the lexor, to set the file path used in error
|
|
|
|
|
* messages.
|
|
|
|
|
*/
|
|
|
|
|
void yyparse_set_filepath(const char*path)
|
|
|
|
|
{
|
|
|
|
|
file_path = path;
|
2010-12-13 05:02:18 +01:00
|
|
|
}
|