2010-12-13 05:02:18 +01:00
|
|
|
|
2011-07-23 05:49:57 +02:00
|
|
|
%pure-parser
|
|
|
|
|
%lex-param { yyscan_t yyscanner }
|
2011-07-23 19:07:20 +02:00
|
|
|
%parse-param {yyscan_t yyscanner }
|
2011-07-23 05:49:57 +02:00
|
|
|
%parse-param {const char*file_path}
|
2011-07-31 00:04:07 +02:00
|
|
|
%parse-param {perm_string parse_library_name}
|
2010-12-13 05:02:18 +01:00
|
|
|
%{
|
|
|
|
|
/*
|
2013-06-11 01:39:53 +02:00
|
|
|
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
|
2014-08-06 15:00:35 +02:00
|
|
|
* Copyright CERN 2012-2014 / Stephen Williams (steve@icarus.com),
|
2015-03-27 15:23:48 +01:00
|
|
|
* @author Maciej Suminski (maciej.suminski@cern.ch)
|
2010-12-13 05:02:18 +01:00
|
|
|
*
|
|
|
|
|
* 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
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2010-12-13 05:02:18 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# 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-05-09 01:40:35 +02:00
|
|
|
# include "sequential.h"
|
2013-05-06 04:05:46 +02:00
|
|
|
# include "subprogram.h"
|
|
|
|
|
# include "package.h"
|
2011-03-22 17:16:20 +01:00
|
|
|
# include "vsignal.h"
|
2011-02-14 01:37:10 +01:00
|
|
|
# include "vtype.h"
|
2015-06-10 18:41:51 +02:00
|
|
|
# include "std_funcs.h"
|
2015-06-11 22:01:22 +02:00
|
|
|
# include "std_types.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-07-20 14:44:25 +02:00
|
|
|
# include <stack>
|
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-10-16 02:41:48 +02:00
|
|
|
# include <ivl_assert.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; \
|
2011-07-23 05:49:57 +02:00
|
|
|
(Current).text = file_path; /*(Rhs)[1].text;*/ } while (0)
|
2011-03-19 19:15:47 +01:00
|
|
|
|
2011-07-23 19:07:20 +02:00
|
|
|
static void yyerror(YYLTYPE*yyllocp,yyscan_t yyscanner,const char*file_path,bool, const char*msg);
|
2010-12-13 05:02:18 +01:00
|
|
|
|
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
|
|
|
|
2011-07-23 05:49:57 +02:00
|
|
|
/*
|
|
|
|
|
* The parser calls yylex to get the next lexical token. It is only
|
|
|
|
|
* called by the bison-generated parser.
|
|
|
|
|
*/
|
|
|
|
|
extern int yylex(union YYSTYPE*yylvalp,YYLTYPE*yyllocp,yyscan_t yyscanner);
|
|
|
|
|
|
2011-03-22 17:16:20 +01:00
|
|
|
|
|
|
|
|
/*
|
2011-04-18 02:19:09 +02:00
|
|
|
* Create an initial scope that collects all the global
|
|
|
|
|
* declarations. Also save a stack of previous scopes, as a way to
|
|
|
|
|
* manage lexical scopes.
|
2011-03-22 17:16:20 +01:00
|
|
|
*/
|
2011-04-18 02:19:09 +02:00
|
|
|
static ActiveScope*active_scope = new ActiveScope;
|
2011-07-20 14:44:25 +02:00
|
|
|
static stack<ActiveScope*> scope_stack;
|
2015-06-10 11:29:37 +02:00
|
|
|
static SubprogramHeader*active_sub = NULL;
|
2011-04-14 03:30:00 +02:00
|
|
|
|
2014-10-08 11:18:06 +02:00
|
|
|
// perm_strings for attributes
|
|
|
|
|
const static perm_string left_attr = perm_string::literal("left");
|
|
|
|
|
const static perm_string right_attr = perm_string::literal("right");
|
|
|
|
|
|
2011-04-14 03:30:00 +02:00
|
|
|
/*
|
2011-04-18 02:19:09 +02:00
|
|
|
* When a scope boundary starts, call the push_scope function to push
|
|
|
|
|
* a scope context. Preload this scope context with the contents of
|
|
|
|
|
* the parent scope, then make this the current scope. When the scope
|
|
|
|
|
* is done, the pop_scope function pops the scope off the stack and
|
|
|
|
|
* resumes the scope that was the parent.
|
2011-04-14 03:30:00 +02:00
|
|
|
*/
|
2011-04-18 02:19:09 +02:00
|
|
|
static void push_scope(void)
|
2011-04-14 03:30:00 +02:00
|
|
|
{
|
2011-04-18 02:19:09 +02:00
|
|
|
assert(active_scope);
|
2011-07-20 14:44:25 +02:00
|
|
|
scope_stack.push(active_scope);
|
2011-04-18 02:19:09 +02:00
|
|
|
active_scope = new ActiveScope (active_scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void pop_scope(void)
|
|
|
|
|
{
|
|
|
|
|
delete active_scope;
|
2011-07-29 02:07:49 +02:00
|
|
|
assert(! scope_stack.empty());
|
2011-07-20 14:44:25 +02:00
|
|
|
active_scope = scope_stack.top();
|
|
|
|
|
scope_stack.pop();
|
2011-04-18 02:19:09 +02:00
|
|
|
}
|
|
|
|
|
|
2014-09-30 11:24:43 +02:00
|
|
|
static bool is_subprogram_param(perm_string name)
|
|
|
|
|
{
|
|
|
|
|
if(!active_sub)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return (active_sub->find_param(name) != NULL);
|
|
|
|
|
}
|
2011-04-18 02:19:09 +02:00
|
|
|
|
|
|
|
|
void preload_global_types(void)
|
|
|
|
|
{
|
|
|
|
|
generate_global_types(active_scope);
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-20 18:19:48 +02:00
|
|
|
//Remove the scope created at the beginning of parser's work.
|
|
|
|
|
//After the parsing active_scope should keep it's address
|
|
|
|
|
|
|
|
|
|
static void delete_global_scope(void)
|
|
|
|
|
{
|
|
|
|
|
active_scope->destroy_global_scope();
|
|
|
|
|
delete active_scope;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-29 01:40:15 +02:00
|
|
|
//delete global entities that were gathered over the parsing process
|
2011-07-20 18:19:48 +02:00
|
|
|
static void delete_design_entities(void)
|
|
|
|
|
{
|
|
|
|
|
for(map<perm_string,Entity*>::iterator cur = design_entities.begin()
|
|
|
|
|
; cur != design_entities.end(); ++cur)
|
|
|
|
|
delete cur->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//clean the mess caused by the parser
|
|
|
|
|
void parser_cleanup(void)
|
|
|
|
|
{
|
|
|
|
|
delete_design_entities();
|
|
|
|
|
delete_global_scope();
|
2015-06-10 18:41:51 +02:00
|
|
|
delete_std_funcs();
|
2011-07-20 18:19:48 +02:00
|
|
|
lex_strings.cleanup();
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
const VType*parse_type_by_name(perm_string name)
|
|
|
|
|
{
|
|
|
|
|
return active_scope->find_type(name);
|
2011-04-14 03:30:00 +02:00
|
|
|
}
|
|
|
|
|
|
2012-07-11 00:36:33 +02:00
|
|
|
// This function is called when an aggregate expression is detected by
|
2012-03-17 23:03:19 +01:00
|
|
|
// the parser. It makes the ExpAggregate. It also tries to detect the
|
|
|
|
|
// special case that the aggregate is really a primary. The problem is
|
|
|
|
|
// that this:
|
|
|
|
|
// ( <expression> )
|
|
|
|
|
// also matches the pattern:
|
|
|
|
|
// ( [ choices => ] <expression> ... )
|
|
|
|
|
// so try to assume that a single expression in parentheses is a
|
|
|
|
|
// primary and fix the parse by returning an Expression instead of an
|
|
|
|
|
// ExpAggregate.
|
|
|
|
|
static Expression*aggregate_or_primary(const YYLTYPE&loc, std::list<ExpAggregate::element_t*>*el)
|
|
|
|
|
{
|
|
|
|
|
if (el->size() != 1) {
|
|
|
|
|
ExpAggregate*tmp = new ExpAggregate(el);
|
|
|
|
|
FILE_NAME(tmp,loc);
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExpAggregate::element_t*el1 = el->front();
|
|
|
|
|
if (el1->count_choices() > 0) {
|
|
|
|
|
ExpAggregate*tmp = new ExpAggregate(el);
|
|
|
|
|
FILE_NAME(tmp,loc);
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return el1->extract_expression();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names,
|
|
|
|
|
const VType*type)
|
|
|
|
|
{
|
|
|
|
|
list<VTypeRecord::element_t*>*res = new list<VTypeRecord::element_t*>;
|
|
|
|
|
|
|
|
|
|
for (list<perm_string>::iterator cur = names->begin()
|
|
|
|
|
; cur != names->end() ; ++cur) {
|
|
|
|
|
res->push_back(new VTypeRecord::element_t(*cur, type));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-20 03:36:29 +02:00
|
|
|
static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|
|
|
|
{
|
|
|
|
|
for (list<InterfacePort*>::iterator cur = ports->begin()
|
|
|
|
|
; cur != ports->end() ; ++cur) {
|
|
|
|
|
InterfacePort*curp = *cur;
|
|
|
|
|
if (curp->mode == PORT_NONE)
|
|
|
|
|
curp->mode = PORT_IN;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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-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-05-09 01:40:35 +02:00
|
|
|
SequentialStmt* sequ;
|
|
|
|
|
std::list<SequentialStmt*>*sequ_list;
|
|
|
|
|
|
2011-06-12 19:51:31 +02:00
|
|
|
IfSequential::Elsif*elsif;
|
|
|
|
|
std::list<IfSequential::Elsif*>*elsif_list;
|
2011-07-29 01:40:15 +02:00
|
|
|
|
2015-05-22 10:10:37 +02:00
|
|
|
ExpConditional::case_t*exp_options;
|
|
|
|
|
std::list<ExpConditional::case_t*>*exp_options_list;
|
2012-03-24 18:23:50 +01:00
|
|
|
|
2011-06-29 11:33:46 +02:00
|
|
|
CaseSeqStmt::CaseStmtAlternative* case_alt;
|
|
|
|
|
std::list<CaseSeqStmt::CaseStmtAlternative*>* case_alt_list;
|
2011-06-12 19:51:31 +02:00
|
|
|
|
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-11-05 23:55:17 +01:00
|
|
|
prange_t* range;
|
|
|
|
|
std::list<prange_t*>*range_list;
|
2011-07-05 18:31:54 +02:00
|
|
|
|
2011-10-24 02:31:58 +02:00
|
|
|
ExpArithmetic::fun_t arithmetic_op;
|
2013-06-12 23:01:43 +02:00
|
|
|
std::list<struct adding_term>*adding_terms;
|
2011-10-24 02:31:58 +02:00
|
|
|
|
2011-09-04 02:11:55 +02:00
|
|
|
ExpAggregate::choice_t*choice;
|
|
|
|
|
std::list<ExpAggregate::choice_t*>*choice_list;
|
|
|
|
|
ExpAggregate::element_t*element;
|
|
|
|
|
std::list<ExpAggregate::element_t*>*element_list;
|
|
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
std::list<VTypeRecord::element_t*>*record_elements;
|
|
|
|
|
|
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;
|
2013-05-06 04:05:46 +02:00
|
|
|
|
2015-04-22 18:02:53 +02:00
|
|
|
ReportStmt::severity_t severity;
|
|
|
|
|
|
2015-06-10 11:29:37 +02:00
|
|
|
SubprogramHeader*subprogram;
|
2015-11-30 17:13:06 +01:00
|
|
|
|
|
|
|
|
file_open_info_t*file_info;
|
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
|
2015-04-24 12:04:41 +02:00
|
|
|
%token K_else K_elsif K_end K_entity K_exit
|
2015-04-24 13:37:04 +02:00
|
|
|
%token K_fairness K_file K_for K_force K_function
|
2010-12-13 05:02:18 +01:00
|
|
|
%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
|
2015-04-24 12:04:41 +02:00
|
|
|
%token K_nand K_new K_next K_nor K_not K_null
|
2010-12-13 05:02:18 +01:00
|
|
|
%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
|
2014-10-08 11:18:06 +02:00
|
|
|
%token K_restrict K_restrict_guarantee K_return K_reverse_range 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
|
2015-04-24 13:37:04 +02:00
|
|
|
%token K_then K_to K_transport K_type
|
2010-12-13 05:02:18 +01:00
|
|
|
%token K_unaffected K_units K_until K_use
|
|
|
|
|
%token K_variable K_vmode K_vprop K_vunit
|
2015-04-24 12:04:41 +02:00
|
|
|
%token K_wait K_when K_while K_with
|
2010-12-13 05:02:18 +01:00
|
|
|
%token K_xnor K_xor
|
|
|
|
|
/* Identifiers that are not keywords are identifiers. */
|
2011-01-03 07:30:09 +01:00
|
|
|
%token <text> IDENTIFIER
|
2011-04-15 23:44:05 +02:00
|
|
|
%token <uni_integer> INT_LITERAL
|
2011-02-14 04:01:21 +01:00
|
|
|
%token <uni_real> REAL_LITERAL
|
2011-06-05 22:58:54 +02:00
|
|
|
%token <text> STRING_LITERAL CHARACTER_LITERAL BITSTRING_LITERAL
|
2010-12-15 06:36:47 +01:00
|
|
|
/* compound symbols */
|
2011-06-27 12:32:58 +02:00
|
|
|
%token LEQ GEQ VASSIGN NE BOX EXP ARROW DLT DGT CC M_EQ M_NE M_LT M_LEQ M_GT M_GEQ
|
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-10-24 02:31:58 +02:00
|
|
|
%type <arithmetic_op> adding_operator
|
2013-06-12 23:01:43 +02:00
|
|
|
%type <adding_terms> simple_expression_terms
|
2011-10-24 02:31:58 +02:00
|
|
|
|
2011-10-15 18:49:24 +02:00
|
|
|
%type <interface_list> interface_element interface_list
|
2011-03-20 02:26:43 +01:00
|
|
|
%type <interface_list> port_clause port_clause_opt
|
2011-10-15 18:49:24 +02:00
|
|
|
%type <interface_list> generic_clause generic_clause_opt
|
2015-06-12 10:06:56 +02:00
|
|
|
%type <interface_list> parameter_list parameter_list_opt
|
2011-10-15 18:49:24 +02:00
|
|
|
%type <port_mode> mode mode_opt
|
2011-01-03 07:30:09 +01:00
|
|
|
|
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
|
|
|
|
2012-03-24 18:23:50 +01:00
|
|
|
%type <arch_statement> concurrent_statement component_instantiation_statement
|
|
|
|
|
%type <arch_statement> concurrent_conditional_signal_assignment
|
2015-02-09 15:36:40 +01:00
|
|
|
%type <arch_statement> concurrent_signal_assignment_statement concurrent_simple_signal_assignment
|
2012-03-19 01:37:19 +01:00
|
|
|
%type <arch_statement> for_generate_statement generate_statement if_generate_statement
|
2015-05-22 10:33:30 +02:00
|
|
|
%type <arch_statement> process_statement selected_signal_assignment
|
2011-10-31 01:10:19 +01:00
|
|
|
%type <arch_statement_list> architecture_statement_part generate_statement_body
|
2011-01-27 05:38:20 +01:00
|
|
|
|
2011-09-04 02:11:55 +02:00
|
|
|
%type <choice> choice
|
|
|
|
|
%type <choice_list> choices
|
|
|
|
|
%type <element> element_association
|
|
|
|
|
%type <element_list> element_association_list
|
|
|
|
|
|
|
|
|
|
%type <expr> expression factor primary relation
|
2011-03-20 02:26:43 +01:00
|
|
|
%type <expr> expression_logical expression_logical_and expression_logical_or
|
|
|
|
|
%type <expr> expression_logical_xnor expression_logical_xor
|
2012-09-01 21:05:40 +02:00
|
|
|
%type <expr> name prefix selected_name
|
2011-10-30 02:06:40 +02:00
|
|
|
%type <expr> shift_expression signal_declaration_assign_opt
|
2015-06-09 10:59:33 +02:00
|
|
|
%type <expr> simple_expression simple_expression_2 term
|
|
|
|
|
%type <expr> variable_declaration_assign_opt waveform_element interface_element_expression
|
2011-01-30 02:27:30 +01:00
|
|
|
|
|
|
|
|
%type <expr_list> waveform waveform_elements
|
2011-09-19 04:31:28 +02:00
|
|
|
%type <expr_list> name_list expression_list
|
2011-05-15 20:07:42 +02:00
|
|
|
%type <expr_list> process_sensitivity_list process_sensitivity_list_opt
|
2012-09-01 21:05:40 +02:00
|
|
|
%type <expr_list> selected_names use_clause
|
2011-02-03 05:14:27 +01:00
|
|
|
|
2015-11-30 17:13:06 +01:00
|
|
|
%type <file_info> file_open_information file_open_information_opt
|
|
|
|
|
|
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-10-24 02:08:48 +02:00
|
|
|
%type <named_expr_list> generic_map_aspect generic_map_aspect_opt
|
2011-04-01 03:50:48 +02:00
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
%type <vtype> composite_type_definition record_type_definition
|
2011-10-02 02:04:04 +02:00
|
|
|
%type <vtype> subtype_indication type_definition
|
2011-02-14 01:37:10 +01:00
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
%type <record_elements> element_declaration element_declaration_list
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
%type <text> architecture_body_start package_declaration_start
|
2013-05-19 02:36:29 +02:00
|
|
|
%type <text> package_body_start
|
2015-02-09 15:36:40 +01:00
|
|
|
%type <text> identifier_opt identifier_colon_opt logical_name suffix instantiated_unit
|
2015-04-22 18:02:53 +02:00
|
|
|
|
2011-03-19 19:15:47 +01:00
|
|
|
%type <name_list> logical_name_list identifier_list
|
2011-10-02 02:04:04 +02:00
|
|
|
%type <name_list> enumeration_literal_list enumeration_literal
|
2011-02-03 05:14:27 +01:00
|
|
|
|
2015-08-12 20:37:42 +02:00
|
|
|
%type <sequ_list> if_statement_else list_of_statements
|
|
|
|
|
%type <sequ_list> sequence_of_statements subprogram_statement_part
|
2015-02-09 15:36:40 +01:00
|
|
|
%type <sequ> sequential_statement if_statement signal_assignment signal_assignment_statement
|
2011-07-05 15:46:21 +02:00
|
|
|
%type <sequ> case_statement procedure_call procedure_call_statement
|
2015-02-09 15:36:40 +01:00
|
|
|
%type <sequ> loop_statement variable_assignment variable_assignment_statement
|
2015-05-29 10:54:29 +02:00
|
|
|
%type <sequ> assertion_statement report_statement return_statement wait_statement
|
2011-07-05 18:31:54 +02:00
|
|
|
|
|
|
|
|
%type <range> range
|
2011-11-05 23:55:17 +01:00
|
|
|
%type <range_list> range_list index_constraint
|
2011-06-29 11:33:46 +02:00
|
|
|
|
|
|
|
|
%type <case_alt> case_statement_alternative
|
|
|
|
|
%type <case_alt_list> case_statement_alternative_list
|
2011-05-09 01:40:35 +02:00
|
|
|
|
2011-06-12 19:51:31 +02:00
|
|
|
%type <elsif> if_statement_elsif
|
|
|
|
|
%type <elsif_list> if_statement_elsif_list if_statement_elsif_list_opt
|
|
|
|
|
|
2015-05-22 10:33:30 +02:00
|
|
|
%type <exp_options> else_when_waveform selected_waveform
|
|
|
|
|
%type <exp_options_list> else_when_waveforms selected_waveform_list
|
2012-03-24 18:23:50 +01:00
|
|
|
|
2015-06-12 10:06:56 +02:00
|
|
|
%type <subprogram> function_specification procedure_specification
|
|
|
|
|
%type <subprogram> subprogram_specification subprogram_body_start
|
2015-06-10 11:29:37 +02:00
|
|
|
|
2015-04-22 18:02:53 +02:00
|
|
|
%type <severity> severity severity_opt
|
2013-05-06 04:05:46 +02:00
|
|
|
|
2010-12-13 05:02:18 +01:00
|
|
|
%%
|
|
|
|
|
|
2011-07-23 05:49:57 +02:00
|
|
|
/* The design_file is the root for the VHDL parse. This rule is also
|
|
|
|
|
where I put some run-time initializations. */
|
|
|
|
|
design_file : { yylloc.text = file_path; } design_units ;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2011-10-24 02:31:58 +02:00
|
|
|
adding_operator
|
|
|
|
|
: '+' { $$ = ExpArithmetic::PLUS; }
|
|
|
|
|
| '-' { $$ = ExpArithmetic::MINUS; }
|
2012-04-22 20:42:16 +02:00
|
|
|
| '&' { $$ = ExpArithmetic::xCONCAT; }
|
2011-10-24 02:31:58 +02:00
|
|
|
;
|
|
|
|
|
|
2010-12-15 06:36:47 +01:00
|
|
|
architecture_body
|
2011-04-18 02:19:09 +02:00
|
|
|
: architecture_body_start
|
2010-12-15 06:36:47 +01:00
|
|
|
K_of IDENTIFIER
|
2012-08-07 00:47:35 +02:00
|
|
|
{ bind_entity_to_active_scope($3, active_scope); }
|
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-04-18 02:19:09 +02:00
|
|
|
{ Architecture*tmp = new Architecture(lex_strings.make($1),
|
2011-09-12 00:28:58 +02:00
|
|
|
*active_scope, *$8);
|
2011-01-24 05:26:27 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2011-04-18 02:19:09 +02:00
|
|
|
bind_architecture_to_entity($3, tmp);
|
2011-09-12 00:28:58 +02:00
|
|
|
if ($11 && tmp->get_name() != $11)
|
2011-04-18 02:19:09 +02:00
|
|
|
errormsg(@1, "Architecture name doesn't match closing name.\n");
|
|
|
|
|
delete[]$1;
|
|
|
|
|
delete[]$3;
|
2011-09-12 00:28:58 +02:00
|
|
|
delete $8;
|
2011-04-18 02:19:09 +02:00
|
|
|
pop_scope();
|
2011-09-12 00:28:58 +02:00
|
|
|
if ($11) delete[]$11;
|
2011-04-18 02:19:09 +02:00
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
architecture_body_start
|
|
|
|
|
: K_architecture IDENTIFIER
|
|
|
|
|
{ $$ = $2;
|
|
|
|
|
push_scope();
|
|
|
|
|
}
|
|
|
|
|
;
|
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;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2015-04-22 18:02:53 +02:00
|
|
|
assertion_statement
|
|
|
|
|
: K_assert expression report_statement
|
|
|
|
|
{ ReportStmt*report = dynamic_cast<ReportStmt*>($3);
|
|
|
|
|
assert(report);
|
2015-12-04 17:44:35 +01:00
|
|
|
AssertStmt*tmp = new AssertStmt($2, report->message(), report->severity());
|
2015-04-22 18:02:53 +02:00
|
|
|
delete report;
|
|
|
|
|
FILE_NAME(tmp,@2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_assert expression severity_opt ';'
|
|
|
|
|
{ AssertStmt*tmp = new AssertStmt($2, NULL, $3);
|
|
|
|
|
FILE_NAME(tmp,@2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
association_element
|
2011-06-05 22:58:54 +02:00
|
|
|
: IDENTIFIER ARROW expression
|
2011-04-01 03:50:48 +02:00
|
|
|
{ named_expr_t*tmp = new named_expr_t(lex_strings.make($1), $3);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
2011-06-05 22:58:54 +02:00
|
|
|
}
|
|
|
|
|
| IDENTIFIER ARROW K_open
|
2011-06-13 01:59:07 +02:00
|
|
|
{ named_expr_t*tmp = new named_expr_t(lex_strings.make($1), 0);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
2011-06-05 22:58:54 +02:00
|
|
|
}
|
|
|
|
|
| IDENTIFIER ARROW error
|
|
|
|
|
{ errormsg(@3, "Invalid target for port map association.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
$$ = 0;
|
2011-04-01 03:50:48 +02:00
|
|
|
}
|
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
|
2011-10-24 02:08:48 +02:00
|
|
|
: K_use entity_aspect_opt port_map_aspect_opt generic_map_aspect_opt
|
|
|
|
|
{ $$ = $2;
|
|
|
|
|
if ($3) sorrymsg(@3, "Port map aspect not supported here. (binding_indication)\n");
|
|
|
|
|
if ($4) sorrymsg(@4, "Generic map aspect not supported here. (binding_indication)\n");
|
|
|
|
|
delete $3;
|
|
|
|
|
delete $4;
|
2011-03-31 17:02:44 +02:00
|
|
|
}
|
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
|
2011-10-30 02:06:40 +02:00
|
|
|
: K_signal identifier_list ':' subtype_indication
|
|
|
|
|
signal_declaration_assign_opt ';'
|
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) {
|
2011-10-30 02:06:40 +02:00
|
|
|
Signal*sig = new Signal(*cur, $4, $5);
|
2011-03-22 17:16:20 +01:00
|
|
|
FILE_NAME(sig, @1);
|
2011-04-18 02:19:09 +02:00
|
|
|
active_scope->bind_name(*cur, sig);
|
2011-03-22 17:16:20 +01:00
|
|
|
}
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
|
2011-04-10 18:42:22 +02:00
|
|
|
| component_declaration
|
2011-03-20 02:26:43 +01:00
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
| constant_declaration
|
2011-06-12 19:51:31 +02:00
|
|
|
|
2013-12-11 23:59:20 +01:00
|
|
|
| subprogram_declaration
|
|
|
|
|
|
|
|
|
|
| subprogram_body
|
|
|
|
|
|
2011-10-02 02:04:04 +02:00
|
|
|
| type_declaration
|
|
|
|
|
|
2011-04-14 03:30:00 +02:00
|
|
|
| use_clause_lib
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
/* 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; }
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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-10-01 20:45:28 +02:00
|
|
|
|
2011-06-29 11:33:46 +02:00
|
|
|
case_statement
|
|
|
|
|
: K_case expression K_is
|
|
|
|
|
case_statement_alternative_list
|
2011-07-05 11:57:25 +02:00
|
|
|
K_end K_case ';'
|
2011-10-01 20:45:28 +02:00
|
|
|
{ CaseSeqStmt* tmp = new CaseSeqStmt($2, $4);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
delete $4;
|
|
|
|
|
$$ = tmp;
|
2011-06-29 11:33:46 +02:00
|
|
|
}
|
|
|
|
|
;
|
2011-10-01 20:45:28 +02:00
|
|
|
|
2011-06-29 11:33:46 +02:00
|
|
|
case_statement_alternative_list
|
|
|
|
|
: case_statement_alternative_list case_statement_alternative
|
|
|
|
|
{ std::list<CaseSeqStmt::CaseStmtAlternative*>* tmp = $1;
|
2011-10-01 20:45:28 +02:00
|
|
|
tmp->push_back($2);
|
|
|
|
|
$$ = tmp;
|
2011-06-29 11:33:46 +02:00
|
|
|
}
|
|
|
|
|
| case_statement_alternative
|
2011-10-01 20:45:28 +02:00
|
|
|
{ std::list<CaseSeqStmt::CaseStmtAlternative*>*tmp
|
|
|
|
|
= new std::list<CaseSeqStmt::CaseStmtAlternative*>();
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
2011-06-29 11:33:46 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-09-04 02:11:55 +02:00
|
|
|
/*
|
|
|
|
|
* The case_statement_alternative uses the "choice" rule to select the
|
|
|
|
|
* reference expression, but that rule is shared with the aggregate
|
|
|
|
|
* expression. So convert the ExpAggregate::choice_t to a case
|
|
|
|
|
* statement alternative and pass that up instead.
|
|
|
|
|
*/
|
2011-06-29 11:33:46 +02:00
|
|
|
case_statement_alternative
|
2015-02-03 16:52:19 +01:00
|
|
|
: K_when choices ARROW sequence_of_statements
|
2011-09-04 02:11:55 +02:00
|
|
|
{ CaseSeqStmt::CaseStmtAlternative* tmp;
|
2015-02-03 16:52:19 +01:00
|
|
|
std::list<ExpAggregate::choice_t*>*choices = $2;
|
|
|
|
|
std::list<Expression*>*exp_list = new std::list<Expression*>;
|
|
|
|
|
bool others = false;
|
|
|
|
|
|
|
|
|
|
for(std::list<ExpAggregate::choice_t*>::iterator it = choices->begin();
|
|
|
|
|
it != choices->end(); ++it) {
|
|
|
|
|
if((*it)->others() || others)
|
|
|
|
|
// If there is one "others", then it also covers all other alternatives
|
|
|
|
|
// Continue the loop to delete every choice_t, but do not
|
|
|
|
|
// bother to add the expressions to the exp_list (we are going to
|
|
|
|
|
// delete them very soon)
|
|
|
|
|
others = true;
|
|
|
|
|
else
|
|
|
|
|
exp_list->push_back((*it)->simple_expression());
|
|
|
|
|
|
|
|
|
|
delete (*it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(others) {
|
|
|
|
|
tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4);
|
|
|
|
|
for(std::list<Expression*>::iterator it = exp_list->begin();
|
|
|
|
|
it != exp_list->end(); ++it) {
|
|
|
|
|
delete (*it);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
tmp = new CaseSeqStmt::CaseStmtAlternative(exp_list, $4);
|
|
|
|
|
}
|
|
|
|
|
if (tmp) FILE_NAME(tmp, @1);
|
|
|
|
|
|
|
|
|
|
delete choices;
|
|
|
|
|
delete $4;
|
|
|
|
|
$$ = tmp;
|
2011-06-29 11:33:46 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
choice
|
2011-07-05 11:57:25 +02:00
|
|
|
: simple_expression
|
2011-09-04 02:11:55 +02:00
|
|
|
{ $$ = new ExpAggregate::choice_t($1);}
|
2011-06-29 11:33:46 +02:00
|
|
|
| K_others
|
2011-09-04 02:11:55 +02:00
|
|
|
{ $$ = new ExpAggregate::choice_t; }
|
2012-04-01 01:29:40 +02:00
|
|
|
| range /* discrete_range: range */
|
|
|
|
|
{ $$ = new ExpAggregate::choice_t($1); }
|
2011-06-29 11:33:46 +02:00
|
|
|
;
|
2011-03-20 02:26:43 +01:00
|
|
|
|
2011-08-22 01:52:18 +02:00
|
|
|
choices
|
|
|
|
|
: choices '|' choice
|
2011-09-04 02:11:55 +02:00
|
|
|
{ std::list<ExpAggregate::choice_t*>*tmp = $1;
|
|
|
|
|
tmp->push_back($3);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-08-22 01:52:18 +02:00
|
|
|
| choice
|
2011-09-04 02:11:55 +02:00
|
|
|
{ std::list<ExpAggregate::choice_t*>*tmp = new std::list<ExpAggregate::choice_t*>;
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-08-22 01:52:18 +02:00
|
|
|
;
|
|
|
|
|
|
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 16:29:47 +02:00
|
|
|
{
|
2015-12-19 19:48:00 +01:00
|
|
|
sorrymsg(@1, "Component configuration in not yet supported\n");
|
2011-04-01 16:29:47 +02:00
|
|
|
if($3) delete $3;
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
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-04-01 16:29:47 +02:00
|
|
|
delete $2;
|
2011-04-01 09:50:04 +02:00
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
2011-04-10 18:42:22 +02:00
|
|
|
component_declaration
|
|
|
|
|
: K_component IDENTIFIER K_is_opt
|
2011-10-24 02:08:48 +02:00
|
|
|
generic_clause_opt port_clause_opt
|
2011-04-10 18:42:22 +02:00
|
|
|
K_end K_component identifier_opt ';'
|
|
|
|
|
{ perm_string name = lex_strings.make($2);
|
2011-10-24 02:08:48 +02:00
|
|
|
if($8 && name != $8) {
|
|
|
|
|
errormsg(@8, "Identifier %s doesn't match component name %s.\n",
|
|
|
|
|
$8, name.str());
|
2011-04-10 18:42:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ComponentBase*comp = new ComponentBase(name);
|
2011-10-24 02:08:48 +02:00
|
|
|
comp->set_interface($4, $5);
|
|
|
|
|
if ($4) delete $4;
|
|
|
|
|
if ($5) delete $5;
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
active_scope->bind_name(name, comp);
|
2011-04-10 18:42:22 +02:00
|
|
|
delete[]$2;
|
2011-10-24 02:08:48 +02:00
|
|
|
if ($8) delete[] $8;
|
2011-04-10 18:42:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| K_component IDENTIFIER K_is_opt error K_end K_component identifier_opt ';'
|
|
|
|
|
{ errormsg(@4, "Syntax error in component declaration.\n");
|
|
|
|
|
delete[] $2;
|
|
|
|
|
if($7) delete[] $7;
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2015-02-09 15:36:40 +01:00
|
|
|
instantiated_unit
|
|
|
|
|
: IDENTIFIER
|
|
|
|
|
| K_component IDENTIFIER { $$ = $2; }
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-20 02:26:43 +01:00
|
|
|
component_instantiation_statement
|
2015-02-09 15:36:40 +01:00
|
|
|
: IDENTIFIER ':' instantiated_unit generic_map_aspect_opt port_map_aspect_opt ';'
|
2011-04-01 03:50:48 +02:00
|
|
|
{ perm_string iname = lex_strings.make($1);
|
2015-02-09 15:36:40 +01:00
|
|
|
perm_string cname = lex_strings.make($3);
|
|
|
|
|
ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $4, $5);
|
|
|
|
|
delete $4;
|
2011-10-24 02:08:48 +02:00
|
|
|
delete $5;
|
2011-04-01 03:50:48 +02:00
|
|
|
FILE_NAME(tmp, @1);
|
2011-03-20 02:26:43 +01:00
|
|
|
delete[]$1;
|
2015-02-09 15:36:40 +01:00
|
|
|
delete[]$3;
|
2011-04-01 03:50:48 +02:00
|
|
|
$$ = tmp;
|
2011-03-20 02:26:43 +01:00
|
|
|
}
|
2015-02-09 15:36:40 +01:00
|
|
|
| IDENTIFIER ':' instantiated_unit error ';'
|
2011-03-20 02:26:43 +01:00
|
|
|
{ errormsg(@4, "Errors in component instantiation.\n");
|
|
|
|
|
delete[]$1;
|
2015-02-09 15:36:40 +01:00
|
|
|
delete[]$3;
|
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
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
composite_type_definition
|
|
|
|
|
/* constrained_array_definition */
|
|
|
|
|
: K_array index_constraint K_of subtype_indication
|
|
|
|
|
{ VTypeArray*tmp = new VTypeArray($4, $2);
|
|
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2013-06-11 01:39:53 +02:00
|
|
|
|
|
|
|
|
/* unbounded_array_definition IEEE 1076-2008 P5.3.2.1 */
|
|
|
|
|
| K_array '(' index_subtype_definition_list ')' K_of subtype_indication
|
2014-08-08 17:17:47 +02:00
|
|
|
{ std::list<prange_t*> r;
|
2014-09-10 14:32:02 +02:00
|
|
|
r.push_back(new prange_t(NULL, NULL, true)); // NULL boundaries indicate unbounded array type
|
2013-06-11 01:39:53 +02:00
|
|
|
VTypeArray*tmp = new VTypeArray($6, &r);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
| record_type_definition
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
;
|
|
|
|
|
|
2012-03-24 18:23:50 +01:00
|
|
|
/* The when...else..when...else syntax is not a general expression
|
|
|
|
|
in VHDL but a specific sort of assignment statement model. We
|
2015-06-02 19:40:24 +02:00
|
|
|
create Expression objects for it, but the parser will only
|
2012-03-24 18:23:50 +01:00
|
|
|
recognize it it in specific situations. */
|
|
|
|
|
concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */
|
|
|
|
|
: name LEQ waveform K_when expression else_when_waveforms ';'
|
|
|
|
|
{ ExpConditional*tmp = new ExpConditional($5, $3, $6);
|
2011-06-12 19:51:31 +02:00
|
|
|
FILE_NAME(tmp, @3);
|
|
|
|
|
delete $3;
|
2012-03-24 18:23:50 +01:00
|
|
|
delete $6;
|
2011-06-12 19:51:31 +02:00
|
|
|
|
|
|
|
|
ExpName*name = dynamic_cast<ExpName*> ($1);
|
2011-06-05 22:58:54 +02:00
|
|
|
assert(name);
|
2011-06-12 19:51:31 +02:00
|
|
|
SignalAssignment*tmpa = new SignalAssignment(name, tmp);
|
|
|
|
|
FILE_NAME(tmpa, @1);
|
2011-06-05 22:58:54 +02:00
|
|
|
|
2012-04-01 01:29:40 +02:00
|
|
|
$$ = tmpa;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Error recovery rules. */
|
|
|
|
|
|
|
|
|
|
| name LEQ error K_when expression else_when_waveforms ';'
|
|
|
|
|
{ errormsg(@3, "Syntax error in waveform of conditional signal assignment.\n");
|
|
|
|
|
ExpConditional*tmp = new ExpConditional($5, 0, $6);
|
|
|
|
|
FILE_NAME(tmp, @3);
|
|
|
|
|
delete $6;
|
|
|
|
|
|
|
|
|
|
ExpName*name = dynamic_cast<ExpName*> ($1);
|
|
|
|
|
assert(name);
|
|
|
|
|
SignalAssignment*tmpa = new SignalAssignment(name, tmp);
|
|
|
|
|
FILE_NAME(tmpa, @1);
|
|
|
|
|
|
2011-06-12 19:51:31 +02:00
|
|
|
$$ = tmpa;
|
2011-06-05 22:58:54 +02:00
|
|
|
}
|
2012-03-24 18:23:50 +01:00
|
|
|
;
|
|
|
|
|
|
2015-02-09 15:36:40 +01:00
|
|
|
concurrent_simple_signal_assignment
|
|
|
|
|
: name LEQ waveform ';'
|
|
|
|
|
{ ExpName*name = dynamic_cast<ExpName*> ($1);
|
|
|
|
|
assert(name);
|
|
|
|
|
SignalAssignment*tmp = new SignalAssignment(name, *$3);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
delete $3;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-24 18:23:50 +01:00
|
|
|
else_when_waveforms
|
|
|
|
|
: else_when_waveforms else_when_waveform
|
2015-05-22 10:10:37 +02:00
|
|
|
{ list<ExpConditional::case_t*>*tmp = $1;
|
2012-03-24 18:23:50 +01:00
|
|
|
tmp ->push_back($2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| else_when_waveform
|
2015-05-22 10:10:37 +02:00
|
|
|
{ list<ExpConditional::case_t*>*tmp = new list<ExpConditional::case_t*>;
|
2012-03-24 18:23:50 +01:00
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
else_when_waveform
|
|
|
|
|
: K_else waveform K_when expression
|
2015-05-22 10:10:37 +02:00
|
|
|
{ ExpConditional::case_t*tmp = new ExpConditional::case_t($4, $2);
|
2012-03-24 18:23:50 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_else waveform
|
2015-05-22 10:10:37 +02:00
|
|
|
{ ExpConditional::case_t*tmp = new ExpConditional::case_t(0, $2);
|
2012-03-24 18:23:50 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */
|
2015-02-09 15:36:40 +01:00
|
|
|
: concurrent_simple_signal_assignment
|
2012-03-24 18:23:50 +01:00
|
|
|
|
2015-08-17 03:29:05 +02:00
|
|
|
| IDENTIFIER ':' concurrent_simple_signal_assignment
|
2015-06-11 17:16:16 +02:00
|
|
|
{ delete[] $1;
|
|
|
|
|
$$ = $3;
|
|
|
|
|
}
|
2012-03-24 18:23:50 +01:00
|
|
|
|
|
|
|
|
| concurrent_conditional_signal_assignment
|
|
|
|
|
|
2015-08-17 03:29:05 +02:00
|
|
|
| IDENTIFIER ':' concurrent_conditional_signal_assignment
|
2015-06-11 17:16:16 +02:00
|
|
|
{ delete[] $1;
|
|
|
|
|
$$ = $3;
|
|
|
|
|
}
|
2015-02-09 15:36:40 +01:00
|
|
|
|
2015-05-22 10:33:30 +02:00
|
|
|
| selected_signal_assignment
|
|
|
|
|
|
|
|
|
|
| IDENTIFIER ':' selected_signal_assignment { $$ = $3; }
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2011-08-22 01:52:18 +02:00
|
|
|
| error LEQ waveform ';'
|
|
|
|
|
{ errormsg(@1, "Syntax error in l-value of signal assignment.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
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
|
2012-03-19 01:37:19 +01:00
|
|
|
| generate_statement
|
2011-05-08 22:51:21 +02:00
|
|
|
| process_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())
|
2015-12-19 19:48:00 +01:00
|
|
|
errormsg(@4, "Couldn't find entity %s used in configuration declaration\n", $4);
|
2011-03-31 15:22:55 +02:00
|
|
|
//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
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
constant_declaration
|
|
|
|
|
: K_constant identifier_list ':' subtype_indication VASSIGN expression ';'
|
2015-06-05 18:11:10 +02:00
|
|
|
{ // The syntax allows multiple names to have the same type/value.
|
2011-04-18 02:19:09 +02:00
|
|
|
for (std::list<perm_string>::iterator cur = $2->begin()
|
|
|
|
|
; cur != $2->end() ; ++cur) {
|
|
|
|
|
active_scope->bind_name(*cur, $4, $6);
|
|
|
|
|
}
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
|
|
|
|
| K_constant identifier_list ':' subtype_indication ';'
|
|
|
|
|
{ sorrymsg(@1, "Deferred constant declarations not supported\n");
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
2012-03-17 23:03:19 +01:00
|
|
|
|
|
|
|
|
/* Some error handling... */
|
|
|
|
|
|
|
|
|
|
| K_constant identifier_list ':' subtype_indication VASSIGN error ';'
|
2015-06-05 18:11:10 +02:00
|
|
|
{ // The syntax allows multiple names to have the same type/value.
|
2012-03-17 23:03:19 +01:00
|
|
|
errormsg(@6, "Error in value expression for constants.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
for (std::list<perm_string>::iterator cur = $2->begin()
|
|
|
|
|
; cur != $2->end() ; ++cur) {
|
|
|
|
|
active_scope->bind_name(*cur, $4, 0);
|
|
|
|
|
}
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
2012-04-06 05:20:34 +02:00
|
|
|
| K_constant identifier_list ':' error ';'
|
|
|
|
|
{ errormsg(@4, "Syntax error in constant declaration type.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
|
|
|
|
| K_constant error ';'
|
|
|
|
|
{ errormsg(@2, "Syntax error in constant declaration.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
;
|
|
|
|
|
|
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-08-22 01:52:18 +02:00
|
|
|
element_association
|
|
|
|
|
: choices ARROW expression
|
2011-09-04 02:11:55 +02:00
|
|
|
{ ExpAggregate::element_t*tmp = new ExpAggregate::element_t($1, $3);
|
2015-06-11 17:16:16 +02:00
|
|
|
delete $1;
|
2011-09-04 02:11:55 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2012-03-17 23:03:19 +01:00
|
|
|
| expression
|
|
|
|
|
{ ExpAggregate::element_t*tmp = new ExpAggregate::element_t(0, $1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-08-22 01:52:18 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
element_association_list
|
|
|
|
|
: element_association_list ',' element_association
|
2011-09-04 02:11:55 +02:00
|
|
|
{ std::list<ExpAggregate::element_t*>*tmp = $1;
|
|
|
|
|
tmp->push_back($3);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-08-22 01:52:18 +02:00
|
|
|
| element_association
|
2011-09-04 02:11:55 +02:00
|
|
|
{ std::list<ExpAggregate::element_t*>*tmp = new std::list<ExpAggregate::element_t*>;
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-08-22 01:52:18 +02:00
|
|
|
;
|
|
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
element_declaration
|
|
|
|
|
: identifier_list ':' subtype_indication ';'
|
2015-06-11 17:16:16 +02:00
|
|
|
{ $$ = record_elements($1, $3);
|
|
|
|
|
delete $1;
|
|
|
|
|
}
|
2012-03-17 23:03:19 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
element_declaration_list
|
|
|
|
|
: element_declaration_list element_declaration
|
|
|
|
|
{ $$ = $1;
|
|
|
|
|
$$->splice($$->end(), *$2);
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
|
|
|
|
| element_declaration
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
;
|
|
|
|
|
|
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-10-15 18:49:24 +02:00
|
|
|
: K_entity IDENTIFIER
|
|
|
|
|
K_is generic_clause_opt port_clause_opt
|
|
|
|
|
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
|
2011-10-15 18:49:24 +02:00
|
|
|
tmp->set_interface($4, $5);
|
|
|
|
|
delete $4;
|
|
|
|
|
delete $5;
|
2011-01-03 07:30:09 +01:00
|
|
|
// Save the entity in the entity map.
|
2011-01-24 05:26:27 +01:00
|
|
|
design_entities[tmp->get_name()] = tmp;
|
|
|
|
|
delete[]$2;
|
2011-10-15 18:49:24 +02:00
|
|
|
if($8 && tmp->get_name() != $8) {
|
|
|
|
|
errormsg(@1, "Syntax error in entity clause. Closing name doesn't match.\n");
|
2011-03-23 16:17:18 +01:00
|
|
|
}
|
2011-10-15 18:49:24 +02:00
|
|
|
delete[]$8;
|
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
|
|
|
;
|
|
|
|
|
|
2011-10-02 02:04:04 +02:00
|
|
|
enumeration_literal
|
|
|
|
|
: IDENTIFIER
|
|
|
|
|
{ list<perm_string>*tmp = new list<perm_string>;
|
|
|
|
|
tmp->push_back(lex_strings.make($1));
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
enumeration_literal_list
|
|
|
|
|
: enumeration_literal_list ',' enumeration_literal
|
|
|
|
|
{ list<perm_string>*tmp = $1;
|
|
|
|
|
list<perm_string>*tmp3 = $3;
|
|
|
|
|
if (tmp3) {
|
|
|
|
|
tmp->splice(tmp->end(), *tmp3);
|
|
|
|
|
delete tmp3;
|
|
|
|
|
}
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| enumeration_literal
|
|
|
|
|
{ list<perm_string>*tmp = $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-09-19 04:31:28 +02:00
|
|
|
expression_list
|
|
|
|
|
: expression_list ',' expression
|
|
|
|
|
{ list<Expression*>*tmp = $1;
|
|
|
|
|
tmp->push_back($3);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| expression
|
|
|
|
|
{ list<Expression*>*tmp = new list<Expression*>;
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
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-10-15 18:49:24 +02:00
|
|
|
|
2015-09-23 16:25:35 +02:00
|
|
|
file_declaration
|
2015-11-30 17:13:06 +01:00
|
|
|
: K_file identifier_list ':' IDENTIFIER file_open_information_opt ';'
|
2015-09-23 16:25:35 +02:00
|
|
|
{
|
|
|
|
|
if (strcasecmp($4, "TEXT"))
|
2015-11-24 15:29:18 +01:00
|
|
|
sorrymsg(@1, "file declaration currently handles only TEXT type.\n");
|
2015-09-23 16:25:35 +02:00
|
|
|
|
|
|
|
|
for (std::list<perm_string>::iterator cur = $2->begin()
|
|
|
|
|
; cur != $2->end() ; ++cur) {
|
|
|
|
|
Variable*var = new Variable(*cur, &primitive_INTEGER);
|
|
|
|
|
FILE_NAME(var, @1);
|
|
|
|
|
active_scope->bind_name(*cur, var);
|
2015-11-30 17:13:06 +01:00
|
|
|
|
|
|
|
|
// there was a file name specified, so it needs an implicit call
|
|
|
|
|
// to open it at the beginning of simulation and close it at the end
|
|
|
|
|
if($5) {
|
|
|
|
|
std::list<Expression*> params;
|
|
|
|
|
|
|
|
|
|
// add file_open() call in 'initial' block
|
|
|
|
|
params.push_back(new ExpName(*cur));
|
|
|
|
|
params.push_back($5->filename());
|
|
|
|
|
params.push_back($5->kind());
|
|
|
|
|
ProcedureCall*fopen_call = new ProcedureCall(perm_string::literal("file_open"), ¶ms);
|
|
|
|
|
active_scope->add_initializer(fopen_call);
|
|
|
|
|
|
|
|
|
|
// add file_close() call in 'final' block
|
|
|
|
|
params.clear();
|
|
|
|
|
params.push_back(new ExpName(*cur));
|
|
|
|
|
ProcedureCall*fclose_call = new ProcedureCall(perm_string::literal("file_close"), ¶ms);
|
|
|
|
|
active_scope->add_finalizer(fclose_call);
|
|
|
|
|
}
|
2015-09-23 16:25:35 +02:00
|
|
|
}
|
2015-11-30 17:13:06 +01:00
|
|
|
|
2015-09-23 16:25:35 +02:00
|
|
|
delete $2;
|
|
|
|
|
}
|
|
|
|
|
| K_file error ';'
|
|
|
|
|
{ errormsg(@2, "Syntax error in file declaration.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2015-11-30 17:13:06 +01:00
|
|
|
file_open_information
|
|
|
|
|
: K_open IDENTIFIER K_is STRING_LITERAL
|
|
|
|
|
{
|
|
|
|
|
ExpName*mode = new ExpName(lex_strings.make($2));
|
|
|
|
|
delete[]$2;
|
|
|
|
|
$$ = new file_open_info_t(new ExpString($4), mode);
|
|
|
|
|
}
|
|
|
|
|
| K_is STRING_LITERAL
|
|
|
|
|
{
|
|
|
|
|
$$ = new file_open_info_t(new ExpString($2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file_open_information_opt
|
|
|
|
|
: file_open_information { $$ = $1; }
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
2011-10-31 01:10:19 +01:00
|
|
|
for_generate_statement
|
|
|
|
|
: IDENTIFIER ':' K_for IDENTIFIER K_in range
|
|
|
|
|
K_generate generate_statement_body
|
|
|
|
|
K_end K_generate identifier_opt ';'
|
|
|
|
|
{ perm_string name = lex_strings.make($1);
|
|
|
|
|
perm_string gvar = lex_strings.make($4);
|
|
|
|
|
ForGenerate*tmp = new ForGenerate(name, gvar, $6, *$8);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
|
|
|
|
|
if ($11 && name != $11) {
|
|
|
|
|
errormsg(@1, "for-generate name %s does not match closing name %s\n",
|
|
|
|
|
name.str(), $11);
|
|
|
|
|
}
|
2011-12-19 01:42:36 +01:00
|
|
|
delete[]$1;
|
|
|
|
|
delete[]$4;
|
2011-10-31 01:10:19 +01:00
|
|
|
delete $8;
|
2011-12-19 01:42:36 +01:00
|
|
|
delete[]$11;
|
2011-10-31 01:10:19 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2012-11-03 03:30:12 +01:00
|
|
|
function_specification /* IEEE 1076-2008 P4.2.1 */
|
2015-06-12 10:06:56 +02:00
|
|
|
: K_function IDENTIFIER parameter_list K_return IDENTIFIER
|
|
|
|
|
{ perm_string type_name = lex_strings.make($5);
|
2013-05-06 04:05:46 +02:00
|
|
|
perm_string name = lex_strings.make($2);
|
|
|
|
|
const VType*type_mark = active_scope->find_type(type_name);
|
2015-06-12 10:06:56 +02:00
|
|
|
touchup_interface_for_functions($3);
|
|
|
|
|
SubprogramHeader*tmp = new SubprogramHeader(name, $3, type_mark);
|
2015-06-10 11:29:37 +02:00
|
|
|
FILE_NAME(tmp, @1);
|
2013-05-06 04:05:46 +02:00
|
|
|
delete[]$2;
|
2015-06-12 10:06:56 +02:00
|
|
|
delete[]$5;
|
2013-05-06 04:05:46 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2012-11-03 03:30:12 +01:00
|
|
|
;
|
|
|
|
|
|
2012-03-19 01:37:19 +01:00
|
|
|
generate_statement /* IEEE 1076-2008 P11.8 */
|
|
|
|
|
: if_generate_statement
|
|
|
|
|
| for_generate_statement
|
|
|
|
|
;
|
|
|
|
|
|
2011-10-31 01:10:19 +01:00
|
|
|
generate_statement_body
|
|
|
|
|
: architecture_statement_part { $$ = $1; }
|
|
|
|
|
;
|
|
|
|
|
|
2011-10-15 18:49:24 +02:00
|
|
|
generic_clause_opt
|
|
|
|
|
: generic_clause
|
|
|
|
|
{ $$ = $1;}
|
|
|
|
|
|
|
|
|
|
|
{ $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
generic_clause
|
2015-06-12 10:06:56 +02:00
|
|
|
: K_generic parameter_list ';'
|
|
|
|
|
{ $$ = $2; }
|
2011-10-15 18:49:24 +02:00
|
|
|
| K_generic '(' error ')' ';'
|
|
|
|
|
{ errormsg(@3, "Error in interface list for generic.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
generic_map_aspect_opt
|
2011-10-24 02:08:48 +02:00
|
|
|
: generic_map_aspect { $$ = $1; }
|
|
|
|
|
| { $$ = 0; }
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
generic_map_aspect
|
|
|
|
|
: K_generic K_map '(' association_list ')'
|
2011-10-24 02:08:48 +02:00
|
|
|
{ $$ = $4; }
|
|
|
|
|
| K_generic K_map '(' error ')'
|
|
|
|
|
{ errormsg(@4, "Error in association list for generic map.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
$$ = 0;
|
2011-04-01 16:29:47 +02:00
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
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;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2015-06-11 17:16:16 +02:00
|
|
|
identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ;
|
2011-02-03 05:14:27 +01:00
|
|
|
|
2011-07-05 18:31:54 +02:00
|
|
|
identifier_colon_opt : IDENTIFIER ':' { $$ = $1; } | { $$ = 0; };
|
2011-03-28 18:59:04 +02:00
|
|
|
|
2012-03-19 01:37:19 +01:00
|
|
|
/* 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;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-05-08 22:51:21 +02:00
|
|
|
if_statement
|
|
|
|
|
: K_if expression K_then sequence_of_statements
|
2011-06-05 22:58:54 +02:00
|
|
|
if_statement_elsif_list_opt if_statement_else
|
2011-05-08 22:51:21 +02:00
|
|
|
K_end K_if ';'
|
2011-06-12 19:51:31 +02:00
|
|
|
{ IfSequential*tmp = new IfSequential($2, $4, $5, $6);
|
2011-05-09 01:40:35 +02:00
|
|
|
FILE_NAME(tmp, @1);
|
2011-06-12 19:51:31 +02:00
|
|
|
delete $4;
|
|
|
|
|
delete $5;
|
|
|
|
|
delete $6;
|
2011-05-09 01:40:35 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-05-08 22:51:21 +02:00
|
|
|
|
|
|
|
|
| K_if error K_then sequence_of_statements
|
2011-06-05 22:58:54 +02:00
|
|
|
if_statement_elsif_list_opt if_statement_else
|
2011-05-08 22:51:21 +02:00
|
|
|
K_end K_if ';'
|
|
|
|
|
{ errormsg(@2, "Error in if_statement condition expression.\n");
|
|
|
|
|
yyerrok;
|
2011-05-09 01:40:35 +02:00
|
|
|
$$ = 0;
|
|
|
|
|
delete $4;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| K_if expression K_then error K_end K_if ';'
|
2011-06-05 22:58:54 +02:00
|
|
|
{ errormsg(@4, "Too many errors in sequence within if_statement.\n");
|
2011-05-08 22:51:21 +02:00
|
|
|
yyerrok;
|
2011-05-09 01:40:35 +02:00
|
|
|
$$ = 0;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| K_if error K_end K_if ';'
|
|
|
|
|
{ errormsg(@2, "Too many errors in if_statement.\n");
|
|
|
|
|
yyerrok;
|
2011-05-09 01:40:35 +02:00
|
|
|
$$ = 0;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-06-05 22:58:54 +02:00
|
|
|
if_statement_elsif_list_opt
|
2011-06-12 19:51:31 +02:00
|
|
|
: if_statement_elsif_list { $$ = $1; }
|
|
|
|
|
| { $$ = 0; }
|
2011-06-05 22:58:54 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
if_statement_elsif_list
|
|
|
|
|
: if_statement_elsif_list if_statement_elsif
|
2011-06-12 19:51:31 +02:00
|
|
|
{ list<IfSequential::Elsif*>*tmp = $1;
|
|
|
|
|
tmp->push_back($2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-06-05 22:58:54 +02:00
|
|
|
| if_statement_elsif
|
2011-06-12 19:51:31 +02:00
|
|
|
{ list<IfSequential::Elsif*>*tmp = new list<IfSequential::Elsif*>;
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-06-05 22:58:54 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
if_statement_elsif
|
|
|
|
|
: K_elsif expression K_then sequence_of_statements
|
2011-06-12 19:51:31 +02:00
|
|
|
{ IfSequential::Elsif*tmp = new IfSequential::Elsif($2, $4);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
delete $4;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-06-05 22:58:54 +02:00
|
|
|
| K_elsif expression K_then error
|
|
|
|
|
{ errormsg(@4, "Too many errors in elsif sub-statements.\n");
|
|
|
|
|
yyerrok;
|
2011-06-12 19:51:31 +02:00
|
|
|
$$ = 0;
|
2011-06-05 22:58:54 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-05-08 22:51:21 +02:00
|
|
|
if_statement_else
|
|
|
|
|
: K_else sequence_of_statements
|
2011-05-09 01:40:35 +02:00
|
|
|
{ $$ = $2; }
|
2011-06-05 22:58:54 +02:00
|
|
|
| K_else error
|
|
|
|
|
{ errormsg(@2, "Too many errors in else sub-statements.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
2011-05-08 22:51:21 +02:00
|
|
|
|
|
2011-05-09 01:40:35 +02:00
|
|
|
{ $$ = 0; }
|
2011-05-08 22:51:21 +02:00
|
|
|
;
|
|
|
|
|
|
2011-11-05 23:55:17 +01:00
|
|
|
index_constraint
|
|
|
|
|
: '(' range_list ')'
|
|
|
|
|
{ $$ = $2; }
|
2012-11-03 03:30:12 +01:00
|
|
|
| '(' error ')'
|
|
|
|
|
{ errormsg(@2, "Errors in the index constraint.\n");
|
2012-11-03 17:54:07 +01:00
|
|
|
yyerrok;
|
2012-11-03 03:30:12 +01:00
|
|
|
$$ = new list<prange_t*>;
|
|
|
|
|
}
|
2011-11-05 23:55:17 +01:00
|
|
|
;
|
|
|
|
|
|
2013-06-11 01:39:53 +02:00
|
|
|
/* The identifier should be a type name */
|
|
|
|
|
index_subtype_definition /* IEEE 1076-2008 P5.3.2.1 */
|
|
|
|
|
: IDENTIFIER K_range BOX
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
index_subtype_definition_list
|
|
|
|
|
: index_subtype_definition_list ',' index_subtype_definition
|
|
|
|
|
| index_subtype_definition
|
|
|
|
|
;
|
|
|
|
|
|
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-10-15 18:49:24 +02:00
|
|
|
: identifier_list ':' mode_opt subtype_indication interface_element_expression
|
2011-03-19 19:15:47 +01:00
|
|
|
{ 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;
|
2011-10-15 18:49:24 +02:00
|
|
|
port->expr = $5;
|
2011-03-19 19:15:47 +01:00
|
|
|
tmp->push_back(port);
|
|
|
|
|
}
|
|
|
|
|
delete $1;
|
2011-01-03 07:30:09 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2011-10-15 18:49:24 +02:00
|
|
|
interface_element_expression
|
|
|
|
|
: VASSIGN expression { $$ = $2; }
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
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-07-05 18:31:54 +02:00
|
|
|
loop_statement
|
|
|
|
|
: identifier_colon_opt
|
|
|
|
|
K_while expression_logical K_loop
|
|
|
|
|
sequence_of_statements
|
|
|
|
|
K_end K_loop identifier_opt ';'
|
2011-09-19 00:51:31 +02:00
|
|
|
{ perm_string loop_name = $1? lex_strings.make($1) : perm_string() ;
|
|
|
|
|
if ($8 && !$1) {
|
|
|
|
|
errormsg(@8, "Loop statement closing name %s for un-named statement\n", $8);
|
|
|
|
|
} else if($8 && loop_name != $8) {
|
|
|
|
|
errormsg(@1, "Loop statement name %s doesn't match closing name %s.\n", loop_name.str(), $8);
|
|
|
|
|
}
|
|
|
|
|
if($1) delete[]$1;
|
|
|
|
|
if($8) delete[]$8;
|
2011-07-05 18:31:54 +02:00
|
|
|
|
2015-12-03 17:53:13 +01:00
|
|
|
WhileLoopStatement* tmp = new WhileLoopStatement(loop_name, $3, $5);
|
2011-09-19 00:51:31 +02:00
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
2011-07-05 18:31:54 +02:00
|
|
|
}
|
|
|
|
|
|
2011-09-19 00:51:31 +02:00
|
|
|
| identifier_colon_opt
|
|
|
|
|
K_for IDENTIFIER K_in range
|
|
|
|
|
K_loop sequence_of_statements K_end K_loop identifier_opt ';'
|
|
|
|
|
{ perm_string loop_name = $1? lex_strings.make($1) : perm_string() ;
|
|
|
|
|
perm_string index_name = lex_strings.make($3);
|
|
|
|
|
if ($10 && !$1) {
|
|
|
|
|
errormsg(@10, "Loop statement closing name %s for un-named statement\n", $10);
|
|
|
|
|
} else if($10 && loop_name != $10) {
|
|
|
|
|
errormsg(@1, "Loop statement name %s doesn't match closing name %s.\n", loop_name.str(), $10);
|
|
|
|
|
}
|
|
|
|
|
if($1) delete[] $1;
|
|
|
|
|
delete[] $3;
|
|
|
|
|
if($10) delete[] $10;
|
2011-07-05 18:31:54 +02:00
|
|
|
|
2011-09-19 00:51:31 +02:00
|
|
|
ForLoopStatement* tmp = new ForLoopStatement(loop_name, index_name, $5, $7);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
2011-07-05 18:31:54 +02:00
|
|
|
}
|
|
|
|
|
|
2011-09-19 00:51:31 +02:00
|
|
|
| identifier_colon_opt
|
|
|
|
|
K_loop sequence_of_statements K_end K_loop identifier_opt ';'
|
|
|
|
|
{ perm_string loop_name = $1? lex_strings.make($1) : perm_string() ;
|
|
|
|
|
if ($6 && !$1) {
|
|
|
|
|
errormsg(@6, "Loop statement closing name %s for un-named statement\n", $6);
|
|
|
|
|
} else if($6 && loop_name != $6) {
|
|
|
|
|
errormsg(@1, "Loop statement name %s doesn't match closing name %s.\n", loop_name.str(), $6);
|
|
|
|
|
}
|
|
|
|
|
if($1) delete[]$1;
|
|
|
|
|
if($6) delete[]$6;
|
2011-07-05 18:31:54 +02:00
|
|
|
|
2011-09-19 00:51:31 +02:00
|
|
|
BasicLoopStatement* tmp = new BasicLoopStatement(loop_name, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
|
|
|
|
|
sorrymsg(@1, "Loop statements are not supported.\n");
|
|
|
|
|
$$ = tmp;
|
2011-07-05 18:31:54 +02:00
|
|
|
};
|
2011-07-29 01:40:15 +02:00
|
|
|
|
2011-01-03 07:30:09 +01:00
|
|
|
mode
|
|
|
|
|
: K_in { $$ = PORT_IN; }
|
|
|
|
|
| K_out { $$ = PORT_OUT; }
|
2015-05-08 15:55:26 +02:00
|
|
|
| K_inout { $$ = PORT_INOUT; }
|
2011-01-03 07:30:09 +01:00
|
|
|
;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2011-10-15 18:49:24 +02:00
|
|
|
mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ;
|
|
|
|
|
|
2012-09-01 21:05:40 +02:00
|
|
|
name /* IEEE 1076-2008 P8.1 */
|
|
|
|
|
: IDENTIFIER /* simple_name (IEEE 1076-2008 P8.2) */
|
2015-06-11 22:01:22 +02:00
|
|
|
{ Expression*tmp = new ExpName(lex_strings.make($1));
|
2015-04-24 13:37:04 +02:00
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
2011-03-27 21:01:58 +02:00
|
|
|
}
|
2012-04-01 01:29:40 +02:00
|
|
|
|
|
|
|
|
| selected_name
|
2012-09-01 21:05:40 +02:00
|
|
|
{ $$ = $1; }
|
2012-04-01 01:29:40 +02:00
|
|
|
|
2011-08-22 01:52:18 +02:00
|
|
|
/* Note that this rule can match array element selects and various
|
|
|
|
|
function calls. The only way we can tell the difference is from
|
|
|
|
|
left context, namely whether the name is a type name or function
|
|
|
|
|
name. If none of the above, treat it as a array element select. */
|
2012-09-01 21:05:40 +02:00
|
|
|
| IDENTIFIER '(' expression_list ')'
|
2011-08-22 01:52:18 +02:00
|
|
|
{ perm_string name = lex_strings.make($1);
|
|
|
|
|
delete[]$1;
|
2014-09-30 11:24:43 +02:00
|
|
|
if (active_scope->is_vector_name(name) || is_subprogram_param(name)) {
|
2011-08-29 00:30:45 +02:00
|
|
|
ExpName*tmp = new ExpName(name, $3);
|
2011-08-22 01:52:18 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
} else {
|
2011-08-29 00:30:45 +02:00
|
|
|
ExpFunc*tmp = new ExpFunc(name, $3);
|
2011-08-22 01:52:18 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
FILE_NAME($$, @1);
|
|
|
|
|
}
|
2012-09-01 21:05:40 +02:00
|
|
|
| IDENTIFIER '(' range ')'
|
2011-08-22 01:52:18 +02:00
|
|
|
{ ExpName*tmp = new ExpName(lex_strings.make($1), $3->msb(), $3->lsb());
|
2011-03-27 21:01:58 +02:00
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
2011-03-20 02:26:43 +01:00
|
|
|
}
|
2015-02-24 16:06:55 +01:00
|
|
|
| selected_name '(' range ')'
|
2012-09-01 21:05:40 +02:00
|
|
|
{ ExpName*tmp = dynamic_cast<ExpName*> ($1);
|
|
|
|
|
tmp->set_range($3->msb(), $3->lsb());
|
2012-04-01 01:29:40 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2015-02-24 16:06:55 +01:00
|
|
|
| selected_name '(' expression ')'
|
|
|
|
|
{ ExpName*tmp = dynamic_cast<ExpName*> ($1);
|
|
|
|
|
tmp->set_range($3, NULL);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-03-20 02:26:43 +01:00
|
|
|
;
|
|
|
|
|
|
2011-05-08 22:51:21 +02:00
|
|
|
/* Handle name lists as lists of expressions. */
|
|
|
|
|
name_list
|
|
|
|
|
: name_list ',' name
|
2011-05-15 20:07:42 +02:00
|
|
|
{ std::list<Expression*>*tmp = $1;
|
|
|
|
|
tmp->push_back($3);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-05-08 22:51:21 +02:00
|
|
|
| name
|
2011-05-15 20:07:42 +02:00
|
|
|
{ std::list<Expression*>*tmp = new std::list<Expression*>;
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-05-08 22:51:21 +02:00
|
|
|
;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
package_declaration
|
2011-04-18 02:19:09 +02:00
|
|
|
: package_declaration_start K_is
|
2011-03-28 18:59:04 +02:00
|
|
|
package_declarative_part_opt
|
|
|
|
|
K_end K_package_opt identifier_opt ';'
|
2011-04-18 02:19:09 +02:00
|
|
|
{ perm_string name = lex_strings.make($1);
|
|
|
|
|
if($6 && name != $6) {
|
2011-04-10 18:42:22 +02:00
|
|
|
errormsg(@1, "Identifier %s doesn't match package name %s.\n",
|
2011-04-18 02:19:09 +02:00
|
|
|
$6, name.str());
|
2011-03-28 18:59:04 +02:00
|
|
|
}
|
2011-04-18 02:19:09 +02:00
|
|
|
Package*tmp = new Package(name, *active_scope);
|
2011-04-14 03:30:00 +02:00
|
|
|
FILE_NAME(tmp, @1);
|
2011-04-18 02:19:09 +02:00
|
|
|
delete[]$1;
|
|
|
|
|
if ($6) delete[]$6;
|
|
|
|
|
pop_scope();
|
2011-07-31 00:04:07 +02:00
|
|
|
/* Put this package into the work library, or the currently
|
|
|
|
|
parsed library. Note that parse_library_name is an
|
|
|
|
|
argument to the parser. */
|
|
|
|
|
library_save_package(parse_library_name, tmp);
|
2011-03-28 18:59:04 +02:00
|
|
|
}
|
2011-04-18 02:19:09 +02:00
|
|
|
| package_declaration_start K_is error K_end K_package_opt identifier_opt ';'
|
|
|
|
|
{ errormsg(@3, "Syntax error in package clause.\n");
|
2011-04-10 18:42:22 +02:00
|
|
|
yyerrok;
|
2011-04-18 02:19:09 +02:00
|
|
|
pop_scope();
|
2011-04-10 18:42:22 +02:00
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
package_declaration_start
|
|
|
|
|
: K_package IDENTIFIER
|
|
|
|
|
{ push_scope();
|
|
|
|
|
$$ = $2;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
/* TODO: this list must be extended in the future
|
|
|
|
|
presently it is only a sketch */
|
2012-11-03 17:54:07 +01:00
|
|
|
package_body_declarative_item /* IEEE1076-2008 P4.8 */
|
2011-03-28 18:59:04 +02:00
|
|
|
: use_clause
|
2012-11-03 17:54:07 +01:00
|
|
|
| subprogram_body
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
package_declarative_item
|
2011-04-10 18:42:22 +02:00
|
|
|
: component_declaration
|
2011-04-18 02:19:09 +02:00
|
|
|
| constant_declaration
|
2012-11-03 03:30:12 +01:00
|
|
|
| subprogram_declaration
|
2011-04-18 02:19:09 +02:00
|
|
|
| subtype_declaration
|
2012-03-17 23:03:19 +01:00
|
|
|
| type_declaration
|
2011-04-10 18:42:22 +02:00
|
|
|
| use_clause
|
2012-03-17 23:03:19 +01:00
|
|
|
| error ';'
|
|
|
|
|
{ errormsg(@1, "Syntax error in package declarative item.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
2011-04-10 18:42:22 +02:00
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
package_declarative_items
|
|
|
|
|
: package_declarative_items package_declarative_item
|
|
|
|
|
| package_declarative_item
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
package_declarative_part_opt
|
|
|
|
|
: package_declarative_items
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
2013-05-19 02:36:29 +02:00
|
|
|
package_body /* IEEE 1076-2008 P4.8 */
|
|
|
|
|
: package_body_start K_is
|
2011-03-28 18:59:04 +02:00
|
|
|
package_body_declarative_part_opt
|
|
|
|
|
K_end K_package_opt identifier_opt ';'
|
2013-05-19 02:36:29 +02:00
|
|
|
{ perm_string name = lex_strings.make($1);
|
|
|
|
|
if ($6 && name != $6)
|
|
|
|
|
errormsg(@6, "Package name (%s) doesn't match closing name (%s).\n", $1, $6);
|
|
|
|
|
delete[] $1;
|
|
|
|
|
if($6) delete[]$6;
|
|
|
|
|
pop_scope();
|
2011-03-28 18:59:04 +02:00
|
|
|
}
|
2011-04-01 16:29:47 +02:00
|
|
|
|
2013-05-19 02:36:29 +02:00
|
|
|
| package_body_start K_is error K_end K_package_opt identifier_opt ';'
|
|
|
|
|
{ errormsg(@1, "Errors in package %s body.\n", $1);
|
2012-11-03 17:54:07 +01:00
|
|
|
yyerrok;
|
2013-05-19 02:36:29 +02:00
|
|
|
pop_scope();
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is a portion of the package_body rule that we factor out so
|
|
|
|
|
* that we can use this rule to start the scope.
|
|
|
|
|
*/
|
|
|
|
|
package_body_start
|
|
|
|
|
: K_package K_body IDENTIFIER
|
|
|
|
|
{ perm_string name = lex_strings.make($3);
|
|
|
|
|
push_scope();
|
|
|
|
|
Package*pkg = library_recall_package(parse_library_name, name);
|
|
|
|
|
if (pkg != 0) {
|
|
|
|
|
active_scope->set_package_header(pkg);
|
|
|
|
|
} else {
|
|
|
|
|
errormsg(@1, "Package body for %s has no matching header.\n", $3);
|
|
|
|
|
}
|
|
|
|
|
$$ = $3;
|
2011-04-01 16:29:47 +02:00
|
|
|
}
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
2015-06-12 10:06:56 +02:00
|
|
|
parameter_list
|
|
|
|
|
: '(' interface_list ')' { $$ = $2; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
parameter_list_opt
|
|
|
|
|
: parameter_list { $$ = $1; }
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
2011-01-03 07:30:09 +01:00
|
|
|
port_clause
|
2015-06-12 10:06:56 +02:00
|
|
|
: K_port parameter_list ';'
|
|
|
|
|
{ $$ = $2; }
|
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-04-01 16:29:47 +02:00
|
|
|
| K_port K_map '(' error ')'
|
2011-06-05 22:58:54 +02:00
|
|
|
{ errormsg(@1, "Syntax error in port map aspect.\n");
|
2012-11-03 17:54:07 +01:00
|
|
|
yyerrok;
|
2011-04-01 16:29:47 +02:00
|
|
|
}
|
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
|
|
|
;
|
|
|
|
|
|
2012-09-01 21:05:40 +02:00
|
|
|
|
|
|
|
|
prefix /* IEEE 1076-2008 P8.1 */
|
|
|
|
|
: name
|
2011-05-08 22:51:21 +02:00
|
|
|
{ $$ = $1; }
|
2011-03-29 10:33:09 +02:00
|
|
|
;
|
|
|
|
|
|
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-05-08 22:51:21 +02:00
|
|
|
| name '\'' IDENTIFIER
|
2011-05-09 01:40:35 +02:00
|
|
|
{ perm_string name = lex_strings.make($3);
|
|
|
|
|
ExpName*base = dynamic_cast<ExpName*> ($1);
|
|
|
|
|
ExpAttribute*tmp = new ExpAttribute(base, name);
|
2011-05-15 20:07:42 +02:00
|
|
|
FILE_NAME(tmp, @3);
|
2011-05-08 22:51:21 +02:00
|
|
|
delete[]$3;
|
2011-05-09 01:40:35 +02:00
|
|
|
$$ = tmp;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
| CHARACTER_LITERAL
|
2011-05-09 01:40:35 +02:00
|
|
|
{ ExpCharacter*tmp = new ExpCharacter($1[0]);
|
2011-05-08 22:51:21 +02:00
|
|
|
FILE_NAME(tmp,@1);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-02-14 04:01:21 +01:00
|
|
|
| INT_LITERAL
|
|
|
|
|
{ ExpInteger*tmp = new ExpInteger($1);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2014-08-06 15:00:35 +02:00
|
|
|
| REAL_LITERAL
|
|
|
|
|
{ ExpReal*tmp = new ExpReal($1);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-07-05 12:03:30 +02:00
|
|
|
| STRING_LITERAL
|
|
|
|
|
{ ExpString*tmp = new ExpString($1);
|
2011-08-22 01:52:18 +02:00
|
|
|
FILE_NAME(tmp,@1);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
2011-07-05 12:03:30 +02:00
|
|
|
}
|
2011-06-05 22:58:54 +02:00
|
|
|
| BITSTRING_LITERAL
|
|
|
|
|
{ ExpBitstring*tmp = new ExpBitstring($1);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2015-05-20 18:53:29 +02:00
|
|
|
| INT_LITERAL IDENTIFIER
|
|
|
|
|
{ ExpTime::timeunit_t unit = ExpTime::FS;
|
|
|
|
|
|
|
|
|
|
if(!strcasecmp($2, "us"))
|
|
|
|
|
unit = ExpTime::US;
|
|
|
|
|
else if(!strcasecmp($2, "ms"))
|
|
|
|
|
unit = ExpTime::MS;
|
|
|
|
|
else if(!strcasecmp($2, "ns"))
|
|
|
|
|
unit = ExpTime::NS;
|
|
|
|
|
else if(!strcasecmp($2, "s"))
|
|
|
|
|
unit = ExpTime::S;
|
|
|
|
|
else if(!strcasecmp($2, "ps"))
|
|
|
|
|
unit = ExpTime::PS;
|
|
|
|
|
else if(!strcasecmp($2, "fs"))
|
|
|
|
|
unit = ExpTime::FS;
|
|
|
|
|
else
|
2015-11-24 15:29:18 +01:00
|
|
|
errormsg(@2, "Invalid time unit (accepted are fs, ps, ns, us, ms, s).\n");
|
2015-05-20 18:53:29 +02:00
|
|
|
|
|
|
|
|
if($1 < 0)
|
2015-11-24 15:29:18 +01:00
|
|
|
errormsg(@1, "Time cannot be negative.\n");
|
2015-05-20 18:53:29 +02:00
|
|
|
|
|
|
|
|
ExpTime*tmp = new ExpTime($1, unit);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
delete[] $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2015-04-22 18:03:35 +02:00
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
/*XXXX Caught up in element_association_list?
|
|
|
|
|
| '(' expression ')'
|
|
|
|
|
{ $$ = $2; }
|
|
|
|
|
*/
|
2011-08-22 01:52:18 +02:00
|
|
|
/* This catches function calls that use association lists for the
|
|
|
|
|
argument list. The position argument list is discovered elsewhere
|
|
|
|
|
and must be discovered by elaboration (thanks to the ambiguity of
|
|
|
|
|
VHDL syntax). */
|
|
|
|
|
| IDENTIFIER '(' association_list ')'
|
|
|
|
|
{ sorrymsg(@1, "Function calls not supported\n");
|
2015-06-11 17:16:16 +02:00
|
|
|
delete[] $1;
|
2011-08-22 01:52:18 +02:00
|
|
|
$$ = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
/* Aggregates */
|
|
|
|
|
|
2011-08-22 01:52:18 +02:00
|
|
|
| '(' element_association_list ')'
|
2012-03-17 23:03:19 +01:00
|
|
|
{ Expression*tmp = aggregate_or_primary(@1, $2);
|
2011-09-04 02:11:55 +02:00
|
|
|
$$ = tmp;
|
2011-08-22 01:52:18 +02:00
|
|
|
}
|
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-07-05 15:46:21 +02:00
|
|
|
procedure_call
|
2015-06-12 10:06:56 +02:00
|
|
|
: IDENTIFIER ';'
|
2011-07-05 15:46:21 +02:00
|
|
|
{
|
|
|
|
|
ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1));
|
2015-06-11 17:16:16 +02:00
|
|
|
delete[] $1;
|
2011-07-05 15:46:21 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2015-06-12 10:06:56 +02:00
|
|
|
| IDENTIFIER '(' association_list ')' ';'
|
2011-07-05 15:46:21 +02:00
|
|
|
{
|
|
|
|
|
ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1), $3);
|
2015-06-11 17:16:16 +02:00
|
|
|
delete[] $1;
|
2011-07-05 15:46:21 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2015-06-12 10:06:56 +02:00
|
|
|
| IDENTIFIER '(' expression_list ')' ';'
|
|
|
|
|
{
|
|
|
|
|
ProcedureCall* tmp = new ProcedureCall(lex_strings.make($1), $3);
|
|
|
|
|
delete[] $1;
|
|
|
|
|
delete $3; // parameters are copied in this variant
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| IDENTIFIER '(' error ')' ';'
|
2013-06-12 23:01:43 +02:00
|
|
|
{ errormsg(@1, "Errors in procedure call.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
delete[]$1;
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
|
|
|
|
;
|
2011-07-05 15:46:21 +02:00
|
|
|
|
|
|
|
|
procedure_call_statement
|
2015-06-11 17:16:16 +02:00
|
|
|
: IDENTIFIER ':' procedure_call
|
|
|
|
|
{ delete[] $1;
|
|
|
|
|
$$ = $3;
|
|
|
|
|
}
|
2011-07-05 15:46:21 +02:00
|
|
|
| procedure_call { $$ = $1; }
|
|
|
|
|
;
|
|
|
|
|
|
2015-06-12 10:06:56 +02:00
|
|
|
procedure_specification /* IEEE 1076-2008 P4.2.1 */
|
|
|
|
|
: K_procedure IDENTIFIER parameter_list_opt
|
|
|
|
|
{ perm_string name = lex_strings.make($2);
|
|
|
|
|
touchup_interface_for_functions($3);
|
|
|
|
|
SubprogramHeader*tmp = new SubprogramHeader(name, $3, NULL);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
delete[]$2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-08-18 05:19:15 +02:00
|
|
|
process_declarative_item
|
2014-09-29 11:41:16 +02:00
|
|
|
: variable_declaration
|
2015-09-23 16:25:35 +02:00
|
|
|
| file_declaration
|
2011-08-18 05:19:15 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
process_declarative_part
|
|
|
|
|
: process_declarative_part process_declarative_item
|
|
|
|
|
| process_declarative_item
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
process_declarative_part_opt
|
|
|
|
|
: process_declarative_part
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
2011-05-08 22:51:21 +02:00
|
|
|
process_statement
|
2011-09-18 18:37:11 +02:00
|
|
|
: identifier_colon_opt K_postponed_opt K_process
|
2011-05-08 22:51:21 +02:00
|
|
|
process_sensitivity_list_opt K_is_opt
|
2011-08-18 05:19:15 +02:00
|
|
|
process_declarative_part_opt
|
2011-05-09 01:40:35 +02:00
|
|
|
K_begin sequence_of_statements
|
2011-05-08 22:51:21 +02:00
|
|
|
K_end K_postponed_opt K_process identifier_opt ';'
|
2011-09-18 18:37:11 +02:00
|
|
|
{ perm_string iname = $1? lex_strings.make($1) : perm_string();
|
|
|
|
|
if ($1) delete[]$1;
|
|
|
|
|
if ($12) {
|
|
|
|
|
if (iname.nil()) {
|
|
|
|
|
errormsg(@12, "Process end name %s for un-named processes.\n", $12);
|
|
|
|
|
} else if (iname != $12) {
|
|
|
|
|
errormsg(@12, "Process name %s does not match opening name %s.\n",
|
|
|
|
|
$12, $1);
|
|
|
|
|
}
|
|
|
|
|
delete[]$12;
|
2011-05-09 01:40:35 +02:00
|
|
|
}
|
|
|
|
|
|
2011-09-18 18:37:11 +02:00
|
|
|
ProcessStatement*tmp = new ProcessStatement(iname, $4, $8);
|
|
|
|
|
FILE_NAME(tmp, @3);
|
|
|
|
|
delete $4;
|
|
|
|
|
delete $8;
|
2011-05-09 01:40:35 +02:00
|
|
|
$$ = tmp;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
|
2011-09-18 18:37:11 +02:00
|
|
|
| identifier_colon_opt K_postponed_opt K_process
|
2011-05-08 22:51:21 +02:00
|
|
|
process_sensitivity_list_opt K_is_opt
|
2011-08-18 05:19:15 +02:00
|
|
|
process_declarative_part_opt
|
2011-05-08 22:51:21 +02:00
|
|
|
K_begin error
|
|
|
|
|
K_end K_postponed_opt K_process identifier_opt ';'
|
2011-09-18 18:37:11 +02:00
|
|
|
{ errormsg(@7, "Too many errors in process sequential statements.\n");
|
2011-05-08 22:51:21 +02:00
|
|
|
yyerrok;
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-05-15 20:07:42 +02:00
|
|
|
/*
|
2015-06-05 18:11:10 +02:00
|
|
|
* A process_sensitivity_list is:
|
2011-05-15 20:07:42 +02:00
|
|
|
* <nil> if the list is not present, or
|
|
|
|
|
* or a non-empty list of actual expressions.
|
|
|
|
|
*/
|
2011-05-08 22:51:21 +02:00
|
|
|
process_sensitivity_list_opt
|
|
|
|
|
: '(' process_sensitivity_list ')'
|
2011-05-15 20:07:42 +02:00
|
|
|
{ $$ = $2; }
|
2011-05-08 22:51:21 +02:00
|
|
|
| '(' error ')'
|
2011-05-15 20:07:42 +02:00
|
|
|
{ errormsg(@2, "Error in process sensitivity list\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
2011-05-08 22:51:21 +02:00
|
|
|
|
|
2011-05-15 20:07:42 +02:00
|
|
|
{ $$ = 0; }
|
2011-05-08 22:51:21 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
process_sensitivity_list
|
|
|
|
|
: K_all
|
2011-05-15 20:07:42 +02:00
|
|
|
{ std::list<Expression*>*tmp = new std::list<Expression*>;
|
|
|
|
|
ExpName*all = new ExpNameALL;
|
|
|
|
|
FILE_NAME(all, @1);
|
|
|
|
|
tmp->push_back(all);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-05-08 22:51:21 +02:00
|
|
|
| name_list
|
2011-05-15 20:07:42 +02:00
|
|
|
{ $$ = $1; }
|
2011-05-08 22:51:21 +02:00
|
|
|
;
|
2011-08-22 01:52:18 +02:00
|
|
|
|
2011-07-05 18:31:54 +02:00
|
|
|
range
|
|
|
|
|
: simple_expression direction simple_expression
|
2011-11-05 23:55:17 +01:00
|
|
|
{ prange_t* tmp = new prange_t($1, $3, $2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2014-10-08 11:18:06 +02:00
|
|
|
| name '\'' K_range
|
|
|
|
|
{
|
|
|
|
|
prange_t*tmp = NULL;
|
|
|
|
|
ExpName*name = NULL;
|
|
|
|
|
if((name = dynamic_cast<ExpName*>($1))) {
|
|
|
|
|
ExpAttribute*left = new ExpAttribute(name, left_attr);
|
|
|
|
|
ExpAttribute*right = new ExpAttribute(name, right_attr);
|
|
|
|
|
tmp = new prange_t(left, right, true);
|
2014-10-10 18:39:14 +02:00
|
|
|
tmp->set_auto_dir();
|
2014-10-08 11:18:06 +02:00
|
|
|
} else {
|
|
|
|
|
errormsg(@1, "'range attribute can be used with named expressions only");
|
|
|
|
|
}
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| name '\'' K_reverse_range
|
|
|
|
|
{
|
|
|
|
|
prange_t*tmp = NULL;
|
|
|
|
|
ExpName*name = NULL;
|
|
|
|
|
if((name = dynamic_cast<ExpName*>($1))) {
|
|
|
|
|
ExpAttribute*left = new ExpAttribute(name, left_attr);
|
|
|
|
|
ExpAttribute*right = new ExpAttribute(name, right_attr);
|
|
|
|
|
tmp = new prange_t(left, right, false);
|
2014-10-10 18:39:14 +02:00
|
|
|
tmp->set_auto_dir();
|
2014-10-08 11:18:06 +02:00
|
|
|
} else {
|
|
|
|
|
errormsg(@1, "'reverse_range attribute can be used with named expressions only");
|
|
|
|
|
}
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-11-05 23:55:17 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
range_list
|
|
|
|
|
: range
|
|
|
|
|
{ list<prange_t*>*tmp = new list<prange_t*>;
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| range_list ',' range
|
|
|
|
|
{ list<prange_t*>*tmp = $1;
|
|
|
|
|
tmp->push_back($3);
|
2011-08-22 01:52:18 +02:00
|
|
|
$$ = tmp;
|
2011-07-05 18:31:54 +02:00
|
|
|
}
|
|
|
|
|
;
|
2011-05-08 22:51:21 +02:00
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
record_type_definition
|
|
|
|
|
: K_record element_declaration_list K_end K_record
|
|
|
|
|
{ VTypeRecord*tmp = new VTypeRecord($2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-05-08 22:51:21 +02:00
|
|
|
relation
|
|
|
|
|
: shift_expression
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| shift_expression '=' shift_expression
|
2011-05-09 01:40:35 +02:00
|
|
|
{ ExpRelation*tmp = new ExpRelation(ExpRelation::EQ, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
| shift_expression '<' shift_expression
|
2011-05-09 01:40:35 +02:00
|
|
|
{ ExpRelation*tmp = new ExpRelation(ExpRelation::LT, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
| shift_expression '>' shift_expression
|
2011-05-09 01:40:35 +02:00
|
|
|
{ ExpRelation*tmp = new ExpRelation(ExpRelation::GT, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
| shift_expression LEQ shift_expression
|
2011-05-09 01:40:35 +02:00
|
|
|
{ ExpRelation*tmp = new ExpRelation(ExpRelation::LE, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
| shift_expression GEQ shift_expression
|
2011-05-09 01:40:35 +02:00
|
|
|
{ ExpRelation*tmp = new ExpRelation(ExpRelation::GE, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
| shift_expression NE shift_expression
|
2011-05-09 01:40:35 +02:00
|
|
|
{ ExpRelation*tmp = new ExpRelation(ExpRelation::NEQ, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
2011-05-08 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2015-04-22 18:02:53 +02:00
|
|
|
report_statement
|
2015-12-04 17:44:35 +01:00
|
|
|
: K_report expression severity_opt ';'
|
2015-04-22 18:02:53 +02:00
|
|
|
{ ReportStmt*tmp = new ReportStmt($2, $3);
|
|
|
|
|
FILE_NAME(tmp,@2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-03 17:54:07 +01:00
|
|
|
return_statement
|
|
|
|
|
: K_return expression ';'
|
|
|
|
|
{ ReturnStmt*tmp = new ReturnStmt($2);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_return ';'
|
|
|
|
|
{ ReturnStmt*tmp = new ReturnStmt(0);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_return error ';'
|
|
|
|
|
{ ReturnStmt*tmp = new ReturnStmt(0);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
errormsg(@2, "Error in expression in return statement.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-28 18:59:04 +02:00
|
|
|
secondary_unit
|
|
|
|
|
: architecture_body
|
|
|
|
|
| package_body
|
|
|
|
|
;
|
2011-03-29 10:33:09 +02:00
|
|
|
|
2012-09-01 21:05:40 +02:00
|
|
|
selected_name /* IEEE 1076-2008 P8.3 */
|
2011-03-29 10:33:09 +02:00
|
|
|
: prefix '.' suffix
|
2012-09-01 21:05:40 +02:00
|
|
|
{ Expression*pfx = $1;
|
|
|
|
|
ExpName*pfx1 = dynamic_cast<ExpName*>(pfx);
|
|
|
|
|
assert(pfx1);
|
|
|
|
|
perm_string tmp = lex_strings.make($3);
|
|
|
|
|
$$ = new ExpName(pfx1, tmp);
|
|
|
|
|
FILE_NAME($$, @3);
|
|
|
|
|
delete[]$3;
|
|
|
|
|
}
|
|
|
|
|
| error '.' suffix
|
|
|
|
|
{ errormsg(@1, "Syntax error in prefix in front of \"%s\".\n", $3);
|
|
|
|
|
yyerrok;
|
|
|
|
|
$$ = new ExpName(lex_strings.make($3));
|
|
|
|
|
FILE_NAME($$, @3);
|
|
|
|
|
delete[]$3;
|
2011-03-29 10:33:09 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
selected_names
|
|
|
|
|
: selected_names ',' selected_name
|
2012-09-01 21:05:40 +02:00
|
|
|
{ std::list<Expression*>* tmp = $1;
|
|
|
|
|
tmp->push_back($3);
|
|
|
|
|
$$ = tmp;
|
2011-03-29 10:33:09 +02:00
|
|
|
}
|
|
|
|
|
| selected_name
|
2012-09-01 21:05:40 +02:00
|
|
|
{ std::list<Expression*>* tmp = new std::list<Expression*>();
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
2011-03-29 10:33:09 +02:00
|
|
|
}
|
|
|
|
|
;
|
2011-04-14 03:30:00 +02:00
|
|
|
|
2012-09-01 21:05:40 +02:00
|
|
|
/* The *_lib variant of selected_name is used by the "use"
|
2011-02-19 22:08:26 +01:00
|
|
|
clause. It is syntactically identical to other selected_name
|
|
|
|
|
rules, but is a convenient place to attach use_clause actions. */
|
2012-09-01 21:05:40 +02:00
|
|
|
selected_name_lib
|
2010-12-15 06:36:47 +01:00
|
|
|
: IDENTIFIER '.' K_all
|
2011-04-18 02:19:09 +02:00
|
|
|
{ library_use(@1, active_scope, 0, $1, 0);
|
2011-02-19 22:08:26 +01:00
|
|
|
delete[]$1;
|
|
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
| IDENTIFIER '.' IDENTIFIER '.' K_all
|
2011-04-18 02:19:09 +02:00
|
|
|
{ library_use(@1, active_scope, $1, $3, 0);
|
2011-04-14 03:30:00 +02:00
|
|
|
delete[]$1;
|
|
|
|
|
delete[]$3;
|
|
|
|
|
}
|
|
|
|
|
| IDENTIFIER '.' IDENTIFIER '.' IDENTIFIER
|
2011-04-18 02:19:09 +02:00
|
|
|
{ library_use(@1, active_scope, $1, $3, $5);
|
2011-02-19 22:08:26 +01:00
|
|
|
delete[]$1;
|
|
|
|
|
delete[]$3;
|
2011-04-14 03:30:00 +02:00
|
|
|
delete[]$5;
|
2011-02-19 22:08:26 +01:00
|
|
|
}
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2012-09-01 21:05:40 +02:00
|
|
|
selected_names_lib
|
|
|
|
|
: selected_names_lib ',' selected_name_lib
|
|
|
|
|
| selected_name_lib
|
2010-12-15 06:36:47 +01:00
|
|
|
;
|
|
|
|
|
|
2015-05-22 10:33:30 +02:00
|
|
|
selected_signal_assignment
|
|
|
|
|
: K_with expression K_select name LEQ selected_waveform_list ';'
|
|
|
|
|
{ ExpSelected*tmp = new ExpSelected($2, $6);
|
|
|
|
|
FILE_NAME(tmp, @3);
|
|
|
|
|
delete $2;
|
|
|
|
|
delete $6;
|
|
|
|
|
|
|
|
|
|
ExpName*name = dynamic_cast<ExpName*>($4);
|
|
|
|
|
assert(name);
|
|
|
|
|
SignalAssignment*tmpa = new SignalAssignment(name, tmp);
|
|
|
|
|
FILE_NAME(tmpa, @1);
|
|
|
|
|
|
|
|
|
|
$$ = tmpa;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
selected_waveform
|
|
|
|
|
: waveform K_when expression
|
|
|
|
|
{ ExpConditional::case_t*tmp = new ExpConditional::case_t($3, $1);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| waveform K_when K_others
|
|
|
|
|
{ ExpConditional::case_t*tmp = new ExpConditional::case_t(0, $1);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
selected_waveform_list
|
|
|
|
|
: selected_waveform_list ',' selected_waveform
|
|
|
|
|
{ list<ExpConditional::case_t*>*tmp = $1;
|
|
|
|
|
tmp->push_back($3);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| selected_waveform
|
|
|
|
|
{ list<ExpConditional::case_t*>*tmp = new list<ExpConditional::case_t*>;
|
|
|
|
|
tmp->push_back($1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
2011-05-08 22:51:21 +02:00
|
|
|
|
2015-08-12 20:37:42 +02:00
|
|
|
list_of_statements
|
|
|
|
|
: list_of_statements sequential_statement
|
2011-05-09 01:40:35 +02:00
|
|
|
{ std::list<SequentialStmt*>*tmp = $1;
|
2011-07-05 15:58:26 +02:00
|
|
|
if($2)
|
|
|
|
|
tmp->push_back($2);
|
2011-05-09 01:40:35 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-05-08 22:51:21 +02:00
|
|
|
| sequential_statement
|
2011-05-09 01:40:35 +02:00
|
|
|
{ std::list<SequentialStmt*>*tmp = new std::list<SequentialStmt*>;
|
2011-07-05 15:58:26 +02:00
|
|
|
if($1)
|
|
|
|
|
tmp->push_back($1);
|
2011-05-09 01:40:35 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2015-08-12 20:37:42 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
sequence_of_statements
|
|
|
|
|
: list_of_statements { $1 = $$; }
|
2015-08-09 18:44:59 +02:00
|
|
|
| { $$ = NULL; }
|
2011-05-08 22:51:21 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
sequential_statement
|
2011-05-09 01:40:35 +02:00
|
|
|
: if_statement { $$ = $1; }
|
|
|
|
|
| signal_assignment_statement { $$ = $1; }
|
2011-08-18 05:19:15 +02:00
|
|
|
| variable_assignment_statement { $$ = $1; }
|
2011-06-29 11:33:46 +02:00
|
|
|
| case_statement { $$ = $1; }
|
2011-07-05 15:46:21 +02:00
|
|
|
| procedure_call_statement { $$ = $1; }
|
2011-07-05 18:31:54 +02:00
|
|
|
| loop_statement { $$ = $1; }
|
2012-11-03 17:54:07 +01:00
|
|
|
| return_statement { $$ = $1; }
|
2015-04-22 18:02:53 +02:00
|
|
|
| report_statement { $$ = $1; }
|
|
|
|
|
| assertion_statement { $$ = $1; }
|
2015-05-29 10:54:29 +02:00
|
|
|
| wait_statement { $$ = $1; }
|
2011-07-05 15:58:26 +02:00
|
|
|
| K_null ';' { $$ = 0; }
|
2011-08-18 05:19:15 +02:00
|
|
|
| error ';'
|
|
|
|
|
{ errormsg(@1, "Syntax error in sequential statement.\n");
|
|
|
|
|
$$ = 0;
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
2011-05-08 22:51:21 +02:00
|
|
|
;
|
|
|
|
|
|
2015-04-22 18:02:53 +02:00
|
|
|
severity
|
2015-04-24 12:04:41 +02:00
|
|
|
: K_severity IDENTIFIER
|
|
|
|
|
{ if(!strcasecmp($2, "NOTE"))
|
|
|
|
|
$$ = ReportStmt::NOTE;
|
|
|
|
|
else if(!strcasecmp($2, "WARNING"))
|
|
|
|
|
$$ = ReportStmt::WARNING;
|
|
|
|
|
else if(!strcasecmp($2, "ERROR"))
|
|
|
|
|
$$ = ReportStmt::ERROR;
|
|
|
|
|
else if(!strcasecmp($2, "FAILURE"))
|
|
|
|
|
$$ = ReportStmt::FAILURE;
|
|
|
|
|
else {
|
|
|
|
|
errormsg(@1, "Invalid severity level (possible values: NOTE, WARNING, ERROR, FAILURE).\n");
|
|
|
|
|
$$ = ReportStmt::UNSPECIFIED;
|
|
|
|
|
}
|
2015-06-11 17:16:16 +02:00
|
|
|
delete[] $2;
|
2015-04-24 12:04:41 +02:00
|
|
|
}
|
2015-04-22 18:02:53 +02:00
|
|
|
|
|
|
|
|
severity_opt
|
|
|
|
|
: severity { $$ = $1; }
|
|
|
|
|
| { $$ = ReportStmt::UNSPECIFIED; }
|
|
|
|
|
|
2015-02-10 14:11:56 +01:00
|
|
|
shift_expression
|
|
|
|
|
: simple_expression
|
|
|
|
|
| simple_expression K_srl simple_expression
|
|
|
|
|
{ ExpShift*tmp = new ExpShift(ExpShift::SRL, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| simple_expression K_sll simple_expression
|
|
|
|
|
{ ExpShift*tmp = new ExpShift(ExpShift::SLL, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| simple_expression K_sra simple_expression
|
|
|
|
|
{ ExpShift*tmp = new ExpShift(ExpShift::SRA, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| simple_expression K_sla simple_expression
|
|
|
|
|
{ ExpShift*tmp = new ExpShift(ExpShift::SLA, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| simple_expression K_ror simple_expression
|
|
|
|
|
{ sorrymsg(@2, "ROR is not supported.\n");
|
|
|
|
|
ExpShift*tmp = new ExpShift(ExpShift::ROR, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| simple_expression K_rol simple_expression
|
|
|
|
|
{ sorrymsg(@2, "ROL is not supported.\n");
|
|
|
|
|
ExpShift*tmp = new ExpShift(ExpShift::ROL, $1, $3);
|
|
|
|
|
FILE_NAME(tmp, @2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2013-06-12 23:01:43 +02:00
|
|
|
sign
|
|
|
|
|
: '+'
|
|
|
|
|
| '-'
|
|
|
|
|
;
|
|
|
|
|
|
2011-10-30 02:06:40 +02:00
|
|
|
signal_declaration_assign_opt
|
|
|
|
|
: VASSIGN expression { $$ = $2; }
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
2011-10-24 02:31:58 +02:00
|
|
|
/*
|
|
|
|
|
* The LRM rule for simple_expression is:
|
|
|
|
|
* simple_expression ::= [sign] term { adding_operator term }
|
|
|
|
|
*
|
|
|
|
|
* This is functionally a list of terms, with the adding_operator used
|
|
|
|
|
* as a list element separator instead of a ','. The LRM rule,
|
2015-06-05 18:11:10 +02:00
|
|
|
* however, is right-recursive, which is not too nice in real LALR
|
2011-10-24 02:31:58 +02:00
|
|
|
* parsers. The solution is to rewrite it as below, to make it
|
2015-06-05 18:11:10 +02:00
|
|
|
* left-recursive. This is much more efficient use of the parse stack.
|
2012-04-22 20:42:16 +02:00
|
|
|
*
|
|
|
|
|
* Note that although the concatenation operator '&' is syntactically
|
|
|
|
|
* an addition operator, it is handled differently during elaboration
|
|
|
|
|
* so detect it and create a different expression type.
|
2013-06-12 23:01:43 +02:00
|
|
|
*
|
|
|
|
|
* Note too that I'm using *right* recursion to implement the {...}
|
|
|
|
|
* part of the rule. This is normally bad, but expression lists aren't
|
|
|
|
|
* normally that long, and the while loop going through the formed
|
|
|
|
|
* list fixes up the associations.
|
2011-10-24 02:31:58 +02:00
|
|
|
*/
|
2011-02-20 02:47:30 +01:00
|
|
|
simple_expression
|
2013-06-12 23:01:43 +02:00
|
|
|
: sign simple_expression_2
|
|
|
|
|
{ sorrymsg(@1, "Unary expression +- not supported.\n");
|
|
|
|
|
$$ = $2;
|
|
|
|
|
}
|
|
|
|
|
| simple_expression_2
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
simple_expression_2
|
2011-02-20 02:47:30 +01:00
|
|
|
: term
|
|
|
|
|
{ $$ = $1; }
|
2013-06-12 23:01:43 +02:00
|
|
|
| term simple_expression_terms
|
|
|
|
|
{ Expression*tmp = $1;
|
|
|
|
|
list<struct adding_term>*lst = $2;
|
|
|
|
|
while (! lst->empty()) {
|
|
|
|
|
struct adding_term item = lst->front();
|
|
|
|
|
lst->pop_front();
|
|
|
|
|
if (item.op == ExpArithmetic::xCONCAT)
|
|
|
|
|
tmp = new ExpConcat(tmp, item.term);
|
|
|
|
|
else
|
|
|
|
|
tmp = new ExpArithmetic(item.op, tmp, item.term);
|
2012-04-22 20:42:16 +02:00
|
|
|
}
|
2013-06-12 23:01:43 +02:00
|
|
|
delete lst;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
simple_expression_terms
|
|
|
|
|
: adding_operator term
|
|
|
|
|
{ struct adding_term item;
|
|
|
|
|
item.op = $1;
|
|
|
|
|
item.term = $2;
|
|
|
|
|
list<adding_term>*tmp = new list<adding_term>;
|
|
|
|
|
tmp->push_back(item);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| simple_expression_terms adding_operator term
|
|
|
|
|
{ list<adding_term>*tmp = $1;
|
|
|
|
|
struct adding_term item;
|
|
|
|
|
item.op = $2;
|
|
|
|
|
item.term = $3;
|
|
|
|
|
tmp->push_back(item);
|
2011-06-05 22:58:54 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-02-20 02:47:30 +01:00
|
|
|
;
|
2010-12-15 06:36:47 +01:00
|
|
|
|
2015-02-09 15:36:40 +01:00
|
|
|
signal_assignment
|
2011-05-08 22:51:21 +02:00
|
|
|
: name LEQ waveform ';'
|
2011-05-09 01:40:35 +02:00
|
|
|
{ SignalSeqAssignment*tmp = new SignalSeqAssignment($1, $3);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-06-05 22:58:54 +02:00
|
|
|
| name LEQ waveform K_when expression K_else waveform ';'
|
|
|
|
|
{ SignalSeqAssignment*tmp = new SignalSeqAssignment($1, $3);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
sorrymsg(@4, "Conditional signal assignment not supported.\n");
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-05-08 22:51:21 +02:00
|
|
|
;
|
|
|
|
|
|
2015-02-09 15:36:40 +01:00
|
|
|
signal_assignment_statement
|
|
|
|
|
: signal_assignment
|
2015-06-11 17:16:16 +02:00
|
|
|
| IDENTIFIER ':' signal_assignment
|
|
|
|
|
{ delete[] $1;
|
|
|
|
|
$$ = $3;
|
|
|
|
|
}
|
2015-02-09 15:36:40 +01:00
|
|
|
|
2014-10-14 18:02:33 +02:00
|
|
|
subprogram_body_start
|
|
|
|
|
: subprogram_specification K_is
|
|
|
|
|
{ assert(!active_sub);
|
|
|
|
|
active_sub = $1;
|
|
|
|
|
$$ = $1; }
|
|
|
|
|
;
|
|
|
|
|
|
2013-05-19 02:36:29 +02:00
|
|
|
/* This is a function/task body. This may have a matching subprogram
|
|
|
|
|
declaration, and if so it will be in the active scope. */
|
|
|
|
|
|
2012-11-03 17:54:07 +01:00
|
|
|
subprogram_body /* IEEE 1076-2008 P4.3 */
|
2014-10-14 18:02:33 +02:00
|
|
|
: subprogram_body_start subprogram_declarative_part
|
2012-11-03 17:54:07 +01:00
|
|
|
K_begin subprogram_statement_part K_end
|
|
|
|
|
subprogram_kind_opt identifier_opt ';'
|
2015-06-10 11:29:37 +02:00
|
|
|
{ SubprogramHeader*prog = $1;
|
|
|
|
|
SubprogramHeader*tmp = active_scope->recall_subprogram(prog->name());
|
2013-05-19 02:36:29 +02:00
|
|
|
if (tmp && prog->compare_specification(tmp)) {
|
|
|
|
|
delete prog;
|
|
|
|
|
prog = tmp;
|
|
|
|
|
} else if (tmp) {
|
|
|
|
|
errormsg(@1, "Subprogram specification for %s doesn't match specification in package header.\n", prog->name().str());
|
|
|
|
|
}
|
2015-06-10 11:29:37 +02:00
|
|
|
|
|
|
|
|
SubprogramBody*body = new SubprogramBody();
|
|
|
|
|
body->transfer_from(*active_scope, ScopeBase::VARIABLES);
|
|
|
|
|
body->set_statements($4);
|
|
|
|
|
|
|
|
|
|
prog->set_body(body);
|
2013-05-19 02:36:29 +02:00
|
|
|
active_scope->bind_name(prog->name(), prog);
|
2014-09-30 11:24:43 +02:00
|
|
|
active_sub = NULL;
|
2012-11-03 17:54:07 +01:00
|
|
|
}
|
|
|
|
|
|
2014-10-14 18:02:33 +02:00
|
|
|
| subprogram_body_start
|
2012-11-03 17:54:07 +01:00
|
|
|
subprogram_declarative_part
|
|
|
|
|
K_begin error K_end
|
|
|
|
|
subprogram_kind_opt identifier_opt ';'
|
|
|
|
|
{ errormsg(@2, "Syntax errors in subprogram body.\n");
|
|
|
|
|
yyerrok;
|
2014-10-14 18:02:33 +02:00
|
|
|
active_sub = NULL;
|
2013-05-06 04:05:46 +02:00
|
|
|
if ($1) delete $1;
|
2014-10-14 18:02:33 +02:00
|
|
|
if ($7) delete[]$7;
|
2012-11-03 17:54:07 +01:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2012-11-03 03:30:12 +01:00
|
|
|
subprogram_declaration
|
|
|
|
|
: subprogram_specification ';'
|
2013-05-06 04:05:46 +02:00
|
|
|
{ if ($1) active_scope->bind_name($1->name(), $1); }
|
2012-11-03 03:30:12 +01:00
|
|
|
;
|
|
|
|
|
|
2012-11-03 17:54:07 +01:00
|
|
|
subprogram_declarative_item /* IEEE 1079-2008 P4.3 */
|
|
|
|
|
: variable_declaration
|
2015-09-23 16:25:35 +02:00
|
|
|
| file_declaration
|
2012-11-03 17:54:07 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
subprogram_declarative_item_list
|
|
|
|
|
: subprogram_declarative_item_list subprogram_declarative_item
|
|
|
|
|
| subprogram_declarative_item
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
subprogram_declarative_part /* IEEE 1076-2008 P4.3 */
|
|
|
|
|
: subprogram_declarative_item_list
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
subprogram_kind /* IEEE 1076-2008 P4.3 */
|
|
|
|
|
: K_function
|
|
|
|
|
| K_procedure
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
subprogram_kind_opt : subprogram_kind | ;
|
|
|
|
|
|
2012-11-03 03:30:12 +01:00
|
|
|
subprogram_specification
|
2013-05-06 04:05:46 +02:00
|
|
|
: function_specification { $$ = $1; }
|
2015-06-12 10:06:56 +02:00
|
|
|
| procedure_specification { $$ = $1; }
|
2012-11-03 03:30:12 +01:00
|
|
|
;
|
|
|
|
|
|
2012-11-03 17:54:07 +01:00
|
|
|
/* This is an implementation of the rule:
|
|
|
|
|
subprogram_statement_part ::= { sequential_statement }
|
|
|
|
|
where the sequence_of_statements rule is a list of
|
2015-08-12 20:37:42 +02:00
|
|
|
sequential_statement. */
|
2012-11-03 17:54:07 +01:00
|
|
|
subprogram_statement_part
|
2013-05-19 02:36:29 +02:00
|
|
|
: sequence_of_statements { $$ = $1; }
|
2012-11-03 17:54:07 +01:00
|
|
|
;
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
subtype_declaration
|
|
|
|
|
: K_subtype IDENTIFIER K_is subtype_indication ';'
|
|
|
|
|
{ perm_string name = lex_strings.make($2);
|
2015-06-11 17:16:16 +02:00
|
|
|
delete[] $2;
|
2011-04-18 02:19:09 +02:00
|
|
|
if ($4 == 0) {
|
|
|
|
|
errormsg(@1, "Failed to declare type name %s.\n", name.str());
|
|
|
|
|
} else {
|
|
|
|
|
active_scope->bind_name(name, $4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-02-14 01:37:10 +01:00
|
|
|
subtype_indication
|
|
|
|
|
: IDENTIFIER
|
2011-04-18 02:19:09 +02:00
|
|
|
{ const VType*tmp = parse_type_by_name(lex_strings.make($1));
|
2011-10-16 02:41:48 +02:00
|
|
|
if (tmp == 0) {
|
|
|
|
|
errormsg(@1, "Can't find type name `%s'\n", $1);
|
2012-11-03 03:30:12 +01:00
|
|
|
tmp = new VTypeERROR;
|
2011-10-16 02:41:48 +02:00
|
|
|
}
|
2011-02-14 01:37:10 +01:00
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2013-06-11 01:39:53 +02:00
|
|
|
| IDENTIFIER index_constraint
|
|
|
|
|
{ const VType*tmp = calculate_subtype_array(@1, $1, active_scope, $2);
|
2011-04-18 02:19:09 +02:00
|
|
|
if (tmp == 0) {
|
|
|
|
|
errormsg(@1, "Unable to calculate bounds for array of %s.\n", $1);
|
|
|
|
|
}
|
|
|
|
|
delete[]$1;
|
2013-06-11 01:39:53 +02:00
|
|
|
delete $2;
|
2011-04-18 02:19:09 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| IDENTIFIER K_range simple_expression direction simple_expression
|
|
|
|
|
{ const VType*tmp = calculate_subtype_range(@1, $1, active_scope, $3, $4, $5);
|
|
|
|
|
if (tmp == 0) {
|
|
|
|
|
errormsg(@1, "Unable to calculate bounds for range of %s.\n", $1);
|
|
|
|
|
}
|
2011-02-14 01:37:10 +01:00
|
|
|
delete[]$1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2011-03-29 10:33:09 +02:00
|
|
|
suffix
|
|
|
|
|
: IDENTIFIER
|
2012-09-01 21:05:40 +02:00
|
|
|
{ $$ = $1; }
|
2011-03-29 10:33:09 +02:00
|
|
|
| CHARACTER_LITERAL
|
2012-09-01 21:05:40 +02:00
|
|
|
{ $$ = $1; }
|
2011-03-29 10:33:09 +02:00
|
|
|
| K_all
|
2012-09-01 21:05:40 +02:00
|
|
|
{ //do not have now better idea than using char constant
|
2015-08-27 16:32:37 +02:00
|
|
|
$$ = strdup("all");
|
2011-03-29 10:33:09 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
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
|
|
|
|
2011-10-02 02:04:04 +02:00
|
|
|
type_declaration
|
|
|
|
|
: K_type IDENTIFIER K_is type_definition ';'
|
2011-10-10 00:25:35 +02:00
|
|
|
{ perm_string name = lex_strings.make($2);
|
|
|
|
|
if ($4 == 0) {
|
|
|
|
|
errormsg(@1, "Failed to declare type name %s.\n", name.str());
|
|
|
|
|
} else {
|
2012-05-06 00:15:45 +02:00
|
|
|
VTypeDef*tmp;
|
|
|
|
|
map<perm_string,VTypeDef*>::iterator cur = active_scope->incomplete_types.find(name);
|
|
|
|
|
if (cur == active_scope->incomplete_types.end()) {
|
|
|
|
|
tmp = new VTypeDef(name, $4);
|
|
|
|
|
active_scope->bind_name(name, tmp);
|
|
|
|
|
} else {
|
|
|
|
|
tmp = cur->second;
|
|
|
|
|
tmp->set_definition($4);
|
|
|
|
|
active_scope->incomplete_types.erase(cur);
|
|
|
|
|
}
|
2015-02-06 10:44:22 +01:00
|
|
|
if(const VTypeEnum*enum_type = dynamic_cast<const VTypeEnum*>($4)) {
|
|
|
|
|
active_scope->use_enum(enum_type);
|
|
|
|
|
}
|
2011-10-10 00:25:35 +02:00
|
|
|
}
|
2011-11-05 23:55:17 +01:00
|
|
|
delete[]$2;
|
|
|
|
|
}
|
2012-05-06 00:15:45 +02:00
|
|
|
| K_type IDENTIFIER ';'
|
|
|
|
|
{ perm_string name = lex_strings.make($2);
|
|
|
|
|
VTypeDef*tmp = new VTypeDef(name);
|
|
|
|
|
active_scope->incomplete_types[name] = tmp;
|
|
|
|
|
active_scope->bind_name(name, tmp);
|
|
|
|
|
delete[]$2;
|
|
|
|
|
}
|
2011-11-05 23:55:17 +01:00
|
|
|
| K_type IDENTIFIER K_is error ';'
|
|
|
|
|
{ errormsg(@4, "Error in type definition for %s\n", $2);
|
|
|
|
|
yyerrok;
|
|
|
|
|
delete[]$2;
|
2011-10-10 00:25:35 +02:00
|
|
|
}
|
2012-04-06 05:20:34 +02:00
|
|
|
| K_type error ';'
|
|
|
|
|
{ errormsg(@1, "Error in type definition\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
2011-10-02 02:04:04 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
type_definition
|
|
|
|
|
: '(' enumeration_literal_list ')'
|
|
|
|
|
{ VTypeEnum*tmp = new VTypeEnum($2);
|
|
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2012-03-17 23:03:19 +01:00
|
|
|
| composite_type_definition
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
|
2011-10-02 02:04:04 +02:00
|
|
|
;
|
|
|
|
|
|
2010-12-15 06:36:47 +01:00
|
|
|
use_clause
|
2011-03-29 10:33:09 +02:00
|
|
|
: K_use selected_names ';'
|
2012-09-01 21:05:40 +02:00
|
|
|
{ $$ = $2; }
|
2011-03-29 10:33:09 +02:00
|
|
|
| K_use error ';'
|
|
|
|
|
{ errormsg(@1, "Syntax error in use clause.\n"); yyerrok; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
use_clause_lib
|
2012-09-01 21:05:40 +02:00
|
|
|
: K_use selected_names_lib ';'
|
2010-12-15 06:36:47 +01:00
|
|
|
| K_use error ';'
|
|
|
|
|
{ errormsg(@1, "Syntax error in use clause.\n"); yyerrok; }
|
|
|
|
|
;
|
|
|
|
|
|
2012-09-01 21:05:40 +02:00
|
|
|
use_clauses_lib
|
|
|
|
|
: use_clauses_lib use_clause_lib
|
|
|
|
|
| use_clause_lib
|
2011-03-28 18:59:04 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
use_clauses_opt
|
2012-09-01 21:05:40 +02:00
|
|
|
: use_clauses_lib
|
2011-03-28 18:59:04 +02:00
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
2012-09-01 21:05:40 +02:00
|
|
|
variable_assignment_statement /* IEEE 1076-2008 P10.6.1 */
|
2015-02-09 15:36:40 +01:00
|
|
|
: variable_assignment
|
2015-06-11 17:16:16 +02:00
|
|
|
| IDENTIFIER ':' variable_assignment
|
|
|
|
|
{ delete[] $1;
|
|
|
|
|
$$ = $3;
|
|
|
|
|
}
|
2015-02-09 15:36:40 +01:00
|
|
|
|
|
|
|
|
variable_assignment
|
2011-08-18 05:19:15 +02:00
|
|
|
: name VASSIGN expression ';'
|
|
|
|
|
{ VariableSeqAssignment*tmp = new VariableSeqAssignment($1, $3);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2011-08-22 01:52:18 +02:00
|
|
|
| name VASSIGN error ';'
|
|
|
|
|
{ errormsg(@3, "Syntax error in r-value expression of assignment.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
|
|
|
|
| error VASSIGN expression ';'
|
|
|
|
|
{ errormsg(@1, "Syntax error in l-value expression of assignment.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
2011-08-18 05:19:15 +02:00
|
|
|
;
|
|
|
|
|
|
2012-11-03 17:54:07 +01:00
|
|
|
variable_declaration /* IEEE 1076-2008 P6.4.2.4 */
|
2015-06-09 10:59:33 +02:00
|
|
|
: K_shared_opt K_variable identifier_list ':' subtype_indication
|
|
|
|
|
variable_declaration_assign_opt ';'
|
2014-09-29 11:41:16 +02:00
|
|
|
{ /* Save the signal declaration in the block_signals map. */
|
|
|
|
|
for (std::list<perm_string>::iterator cur = $3->begin()
|
|
|
|
|
; cur != $3->end() ; ++cur) {
|
2015-06-09 10:59:33 +02:00
|
|
|
Variable*sig = new Variable(*cur, $5, $6);
|
2014-09-29 11:41:16 +02:00
|
|
|
FILE_NAME(sig, @2);
|
|
|
|
|
active_scope->bind_name(*cur, sig);
|
|
|
|
|
}
|
|
|
|
|
delete $3;
|
|
|
|
|
}
|
2012-11-03 17:54:07 +01:00
|
|
|
| K_shared_opt K_variable error ';'
|
|
|
|
|
{ errormsg(@2, "Syntax error in variable declaration.\n");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2015-06-09 10:59:33 +02:00
|
|
|
variable_declaration_assign_opt
|
|
|
|
|
: VASSIGN expression { $$ = $2; }
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
2015-05-29 10:54:29 +02:00
|
|
|
wait_statement
|
2015-05-22 18:07:31 +02:00
|
|
|
: K_wait K_for expression ';'
|
|
|
|
|
{ WaitForStmt*tmp = new WaitForStmt($3);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2015-05-29 10:54:29 +02:00
|
|
|
| K_wait K_on expression ';'
|
|
|
|
|
{ WaitStmt*tmp = new WaitStmt(WaitStmt::ON, $3);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_wait K_until expression ';'
|
|
|
|
|
{ WaitStmt*tmp = new WaitStmt(WaitStmt::UNTIL, $3);
|
|
|
|
|
FILE_NAME(tmp, @1);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2015-05-22 18:07:31 +02:00
|
|
|
;
|
|
|
|
|
|
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-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 | ;
|
2012-11-03 17:54:07 +01:00
|
|
|
K_is_opt : K_is | ;
|
2011-03-28 18:59:04 +02:00
|
|
|
K_package_opt : K_package | ;
|
2011-05-08 22:51:21 +02:00
|
|
|
K_postponed_opt : K_postponed | ;
|
2012-11-03 17:54:07 +01:00
|
|
|
K_shared_opt : K_shared | ;
|
2010-12-13 05:02:18 +01:00
|
|
|
%%
|
|
|
|
|
|
2015-02-03 15:07:19 +01:00
|
|
|
static void yyerror(YYLTYPE*loc, yyscan_t, const char*, bool, const char*msg)
|
2010-12-13 05:02:18 +01:00
|
|
|
{
|
2015-02-03 15:07:19 +01:00
|
|
|
fprintf(stderr, "%s:%u: %s\n", loc->text, loc->first_line, msg);
|
2010-12-15 06:36:47 +01:00
|
|
|
parse_errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
|
2013-09-09 22:32:55 +02:00
|
|
|
fprintf(stderr, "%s:%u: error: ", loc.text, 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);
|
|
|
|
|
|
2013-09-09 22:32:55 +02:00
|
|
|
fprintf(stderr, "%s:%u: sorry: ", loc.text, loc.first_line);
|
2011-03-20 02:26:43 +01:00
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
parse_sorrys += 1;
|
|
|
|
|
}
|
2011-07-23 19:07:20 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The reset_lexor function takes the fd and makes it the input file
|
|
|
|
|
* for the lexor. The path argument is used in lexor/parser error messages.
|
|
|
|
|
*/
|
|
|
|
|
extern yyscan_t prepare_lexor(FILE*fd);
|
|
|
|
|
extern void destroy_lexor(yyscan_t scanner);
|
|
|
|
|
|
2011-07-31 00:04:07 +02:00
|
|
|
int parse_source_file(const char*file_path, perm_string parse_library_name)
|
2011-07-23 19:07:20 +02:00
|
|
|
{
|
|
|
|
|
FILE*fd = fopen(file_path, "r");
|
|
|
|
|
if (fd == 0) {
|
|
|
|
|
perror(file_path);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yyscan_t scanner = prepare_lexor(fd);
|
2011-07-31 00:04:07 +02:00
|
|
|
int rc = yyparse(scanner, file_path, parse_library_name);
|
2011-07-23 19:07:20 +02:00
|
|
|
fclose(fd);
|
|
|
|
|
destroy_lexor(scanner);
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|