1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
%{
|
|
|
|
|
/*
|
2007-05-24 06:07:11 +02:00
|
|
|
* Copyright (c) 1998-2007 Stephen Williams (steve@icarus.com)
|
1998-11-04 00:28:49 +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
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
|
|
|
*/
|
|
|
|
|
|
2001-07-25 05:10:48 +02:00
|
|
|
# include "config.h"
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
# include "parse_misc.h"
|
2004-02-18 18:11:54 +01:00
|
|
|
# include "compiler.h"
|
1998-11-04 00:28:49 +01:00
|
|
|
# include "pform.h"
|
2005-12-05 22:21:18 +01:00
|
|
|
# include "Statement.h"
|
2007-02-12 02:52:21 +01:00
|
|
|
# include "PSpec.h"
|
2008-01-05 00:23:47 +01:00
|
|
|
# include <cstring>
|
2003-02-08 00:16:09 +01:00
|
|
|
# include <sstream>
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2006-09-23 06:57:19 +02:00
|
|
|
class PSpecPath;
|
|
|
|
|
|
1998-11-23 01:20:22 +01:00
|
|
|
extern void lex_start_table();
|
|
|
|
|
extern void lex_end_table();
|
2000-05-08 07:30:19 +02:00
|
|
|
|
2002-08-19 04:39:16 +02:00
|
|
|
static svector<PExpr*>* active_range = 0;
|
2002-09-01 05:01:48 +02:00
|
|
|
static bool active_signed = false;
|
2002-08-19 04:39:16 +02:00
|
|
|
|
2003-04-25 04:28:53 +02:00
|
|
|
/* Port declaration lists use this structure for context. */
|
|
|
|
|
static struct {
|
|
|
|
|
NetNet::Type port_net_type;
|
|
|
|
|
NetNet::PortType port_type;
|
|
|
|
|
bool sign_flag;
|
|
|
|
|
svector<PExpr*>* range;
|
|
|
|
|
} port_declaration_context;
|
|
|
|
|
|
2002-12-10 06:49:51 +01:00
|
|
|
/* Later version of bison (including 1.35) will not compile in stack
|
|
|
|
|
extension if the output is compiled with C++ and either the YYSTYPE
|
|
|
|
|
or YYLTYPE are provided by the source code. However, I can get the
|
|
|
|
|
old behavior back by defining these symbols. */
|
|
|
|
|
# define YYSTYPE_IS_TRIVIAL 1
|
|
|
|
|
# define YYLTYPE_IS_TRIVIAL 1
|
|
|
|
|
|
2003-01-17 06:48:02 +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. */
|
2004-01-13 03:55:50 +01:00
|
|
|
# define YYLLOC_DEFAULT(Current, Rhs, N) do { \
|
|
|
|
|
(Current).first_line = (Rhs)[1].first_line; \
|
|
|
|
|
(Current).first_column = (Rhs)[1].first_column; \
|
|
|
|
|
(Current).last_line = (Rhs)[N].last_line; \
|
|
|
|
|
(Current).last_column = (Rhs)[N].last_column; \
|
|
|
|
|
(Current).text = (Rhs)[1].text; } while (0)
|
2003-01-17 06:48:02 +01:00
|
|
|
|
2000-05-08 07:30:19 +02:00
|
|
|
/*
|
2002-01-12 05:03:39 +01:00
|
|
|
* These are some common strength pairs that are used as defaults when
|
|
|
|
|
* the user is not otherwise specific.
|
2000-05-08 07:30:19 +02:00
|
|
|
*/
|
2002-01-12 05:03:39 +01:00
|
|
|
const static struct str_pair_t pull_strength = { PGate::PULL, PGate::PULL };
|
|
|
|
|
const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
2006-05-11 05:26:57 +02:00
|
|
|
|
|
|
|
|
static list<perm_string>* list_from_identifier(char*id)
|
|
|
|
|
{
|
|
|
|
|
list<perm_string>*tmp = new list<perm_string>;
|
|
|
|
|
tmp->push_back(lex_strings.make(id));
|
|
|
|
|
delete id;
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
|
|
|
|
|
{
|
|
|
|
|
tmp->push_back(lex_strings.make(id));
|
|
|
|
|
delete id;
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-20 18:31:01 +01:00
|
|
|
static inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where)
|
|
|
|
|
{
|
|
|
|
|
tmp->set_lineno(where.first_line);
|
|
|
|
|
tmp->set_file(filename_strings.make(where.text));
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
%}
|
|
|
|
|
|
|
|
|
|
%union {
|
2002-05-20 04:06:01 +02:00
|
|
|
bool flag;
|
|
|
|
|
|
1998-11-25 03:35:53 +01:00
|
|
|
char letter;
|
2002-05-20 04:06:01 +02:00
|
|
|
|
2000-10-31 18:00:04 +01:00
|
|
|
/* text items are C strings allocated by the lexor using
|
|
|
|
|
strdup. They can be put into lists with the texts type. */
|
1999-07-10 03:03:18 +02:00
|
|
|
char*text;
|
2004-03-08 01:10:29 +01:00
|
|
|
list<perm_string>*perm_strings;
|
2007-05-24 06:07:11 +02:00
|
|
|
pform_name_t*pform_name;
|
2000-10-31 18:00:04 +01:00
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
hname_t*hier;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
list<string>*strings;
|
|
|
|
|
|
2000-05-06 17:41:56 +02:00
|
|
|
struct str_pair_t drive;
|
|
|
|
|
|
1999-02-03 05:20:11 +01:00
|
|
|
PCase::Item*citem;
|
1999-06-06 22:45:38 +02:00
|
|
|
svector<PCase::Item*>*citems;
|
1999-02-03 05:20:11 +01:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
lgate*gate;
|
1999-05-06 06:37:17 +02:00
|
|
|
svector<lgate>*gates;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-08-03 06:14:49 +02:00
|
|
|
Module::port_t *mport;
|
|
|
|
|
svector<Module::port_t*>*mports;
|
|
|
|
|
|
2002-05-23 05:08:50 +02:00
|
|
|
named_pexpr_t*named_pexpr;
|
|
|
|
|
svector<named_pexpr_t*>*named_pexprs;
|
2000-01-09 06:50:48 +01:00
|
|
|
struct parmvalue_t*parmvalue;
|
1999-05-29 04:36:17 +02:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
PExpr*expr;
|
1999-05-10 02:16:57 +02:00
|
|
|
svector<PExpr*>*exprs;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1999-04-29 04:16:26 +02:00
|
|
|
svector<PEEvent*>*event_expr;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
NetNet::Type nettype;
|
|
|
|
|
PGBuiltin::Type gatetype;
|
|
|
|
|
NetNet::PortType porttype;
|
2005-07-07 18:22:49 +02:00
|
|
|
ivl_variable_type_t datatype;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
PWire*wire;
|
1999-06-12 22:35:27 +02:00
|
|
|
svector<PWire*>*wires;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
PEventStatement*event_statement;
|
|
|
|
|
Statement*statement;
|
1999-06-24 06:24:18 +02:00
|
|
|
svector<Statement*>*statement_list;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2004-06-01 01:34:36 +02:00
|
|
|
PTaskFuncArg function_type;
|
2001-12-07 06:03:13 +01:00
|
|
|
|
2001-11-29 18:37:51 +01:00
|
|
|
net_decl_assign_t*net_decl_assign;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
verinum* number;
|
1999-06-15 04:50:02 +02:00
|
|
|
|
|
|
|
|
verireal* realtime;
|
2006-09-23 06:57:19 +02:00
|
|
|
|
|
|
|
|
PSpecPath* specpath;
|
2007-11-07 23:18:36 +01:00
|
|
|
list<index_component_t> *dimensions;
|
1998-11-04 00:28:49 +01:00
|
|
|
};
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING
|
2001-11-06 03:52:19 +01:00
|
|
|
%token <text> PATHPULSE_IDENTIFIER
|
2003-04-14 05:37:47 +02:00
|
|
|
%token <number> BASED_NUMBER DEC_NUMBER
|
1999-06-15 04:50:02 +02:00
|
|
|
%token <realtime> REALTIME
|
2003-06-18 05:55:18 +02:00
|
|
|
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_RSS K_SG
|
2006-07-31 05:50:17 +02:00
|
|
|
%token K_PO_POS K_PO_NEG K_POW
|
2002-05-23 05:08:50 +02:00
|
|
|
%token K_PSTAR K_STARP
|
1999-12-31 04:24:30 +01:00
|
|
|
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
|
2005-07-07 18:22:49 +02:00
|
|
|
%token K_always K_and K_assign K_begin K_bool K_buf K_bufif0 K_bufif1 K_case
|
1998-11-04 00:28:49 +01:00
|
|
|
%token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable
|
2007-06-14 05:50:00 +02:00
|
|
|
%token K_edge K_edge_descriptor
|
|
|
|
|
%token K_else K_end K_endcase K_endfunction K_endgenerate K_endmodule
|
1998-11-04 00:28:49 +01:00
|
|
|
%token K_endprimitive K_endspecify K_endtable K_endtask K_event K_for
|
2006-04-10 02:37:42 +02:00
|
|
|
%token K_force K_forever K_fork K_function K_generate K_genvar
|
2006-04-17 06:35:49 +02:00
|
|
|
%token K_highz0 K_highz1 K_if K_ifnone
|
2000-03-12 18:09:40 +01:00
|
|
|
%token K_initial K_inout K_input K_integer K_join K_large K_localparam
|
2005-07-07 18:22:49 +02:00
|
|
|
%token K_logic K_macromodule
|
1998-11-04 00:28:49 +01:00
|
|
|
%token K_medium K_module K_nand K_negedge K_nmos K_nor K_not K_notif0
|
1999-02-21 18:01:57 +01:00
|
|
|
%token K_notif1 K_or K_output K_parameter K_pmos K_posedge K_primitive
|
1999-05-20 06:31:45 +02:00
|
|
|
%token K_pull0 K_pull1 K_pulldown K_pullup K_rcmos K_real K_realtime
|
|
|
|
|
%token K_reg K_release K_repeat
|
2002-10-13 07:01:44 +02:00
|
|
|
%token K_rnmos K_rpmos K_rtran K_rtranif0 K_rtranif1 K_scalared
|
2000-04-02 06:25:39 +02:00
|
|
|
%token K_signed K_small K_specify
|
1998-11-04 00:28:49 +01:00
|
|
|
%token K_specparam K_strong0 K_strong1 K_supply0 K_supply1 K_table K_task
|
|
|
|
|
%token K_time K_tran K_tranif0 K_tranif1 K_tri K_tri0 K_tri1 K_triand
|
1999-06-15 04:50:02 +02:00
|
|
|
%token K_trior K_trireg K_vectored K_wait K_wand K_weak0 K_weak1
|
|
|
|
|
%token K_while K_wire
|
2005-07-07 18:22:49 +02:00
|
|
|
%token K_wone K_wor K_xnor K_xor
|
2003-08-31 23:14:28 +02:00
|
|
|
%token K_Shold K_Speriod K_Srecovery K_Srecrem K_Ssetup K_Swidth K_Ssetuphold
|
1998-11-04 00:28:49 +01:00
|
|
|
|
1998-11-23 01:20:22 +01:00
|
|
|
%token KK_attribute
|
|
|
|
|
|
2003-04-14 05:37:47 +02:00
|
|
|
%type <number> number
|
2007-02-12 02:52:21 +01:00
|
|
|
%type <flag> signed_opt udp_reg_opt edge_operator
|
2000-05-06 17:41:56 +02:00
|
|
|
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
1998-11-25 03:35:53 +01:00
|
|
|
%type <letter> udp_input_sym udp_output_sym
|
|
|
|
|
%type <text> udp_input_list udp_sequ_entry udp_comb_entry
|
2004-03-08 01:10:29 +01:00
|
|
|
%type <perm_strings> udp_input_declaration_list
|
1998-11-25 03:35:53 +01:00
|
|
|
%type <strings> udp_entry_list udp_comb_entry_list udp_sequ_entry_list
|
|
|
|
|
%type <strings> udp_body udp_port_list
|
|
|
|
|
%type <wires> udp_port_decl udp_port_decls
|
|
|
|
|
%type <statement> udp_initial udp_init_opt
|
2004-03-08 01:10:29 +01:00
|
|
|
%type <expr> udp_initial_expr_opt
|
1998-11-25 03:35:53 +01:00
|
|
|
|
2007-08-05 06:50:06 +02:00
|
|
|
%type <text> register_variable net_variable real_variable
|
|
|
|
|
%type <perm_strings> register_variable_list net_variable_list real_variable_list list_of_identifiers
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2001-11-29 18:37:51 +01:00
|
|
|
%type <net_decl_assign> net_decl_assign net_decl_assigns
|
1999-06-02 04:56:29 +02:00
|
|
|
|
2003-02-08 00:16:09 +01:00
|
|
|
%type <mport> port port_opt port_reference port_reference_list
|
2003-04-25 04:28:53 +02:00
|
|
|
%type <mport> port_declaration
|
2004-01-21 04:37:12 +01:00
|
|
|
%type <mports> list_of_ports module_port_list_opt list_of_port_declarations
|
1999-08-03 06:14:49 +02:00
|
|
|
|
1999-07-24 04:11:19 +02:00
|
|
|
%type <wires> task_item task_item_list task_item_list_opt
|
2006-05-11 05:26:57 +02:00
|
|
|
%type <wires> task_port_item task_port_decl task_port_decl_list
|
1999-07-31 21:14:47 +02:00
|
|
|
%type <wires> function_item function_item_list
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2002-05-23 05:08:50 +02:00
|
|
|
%type <named_pexpr> port_name parameter_value_byname
|
|
|
|
|
%type <named_pexprs> port_name_list parameter_value_byname_list
|
|
|
|
|
|
|
|
|
|
%type <named_pexpr> attribute
|
|
|
|
|
%type <named_pexprs> attribute_list attribute_list_opt
|
1999-05-29 04:36:17 +02:00
|
|
|
|
1999-02-03 05:20:11 +01:00
|
|
|
%type <citem> case_item
|
|
|
|
|
%type <citems> case_items
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
%type <gate> gate_instance
|
|
|
|
|
%type <gates> gate_instance_list
|
|
|
|
|
|
2008-01-25 22:34:51 +01:00
|
|
|
%type <pform_name> hierarchy_identifier
|
2007-09-16 17:25:03 +02:00
|
|
|
%type <expr> expression expr_primary expr_mintypmax
|
2006-02-02 03:43:57 +01:00
|
|
|
%type <expr> lpvalue
|
2000-01-02 02:59:52 +01:00
|
|
|
%type <expr> delay_value delay_value_simple
|
2006-09-23 06:57:19 +02:00
|
|
|
%type <exprs> delay1 delay3 delay3_opt delay_value_list
|
2007-04-02 01:02:03 +02:00
|
|
|
%type <exprs> expression_list_with_nuls expression_list_proper
|
2007-04-21 06:45:36 +02:00
|
|
|
%type <exprs> cont_assign cont_assign_list
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
%type <exprs> range range_opt
|
2007-11-14 05:49:05 +01:00
|
|
|
%type <dimensions> dimensions_opt dimensions
|
2003-02-08 00:16:09 +01:00
|
|
|
%type <nettype> net_type var_type net_type_opt
|
1998-11-04 00:28:49 +01:00
|
|
|
%type <gatetype> gatetype
|
|
|
|
|
%type <porttype> port_type
|
2005-07-07 18:22:49 +02:00
|
|
|
%type <datatype> primitive_type primitive_type_opt
|
2000-01-09 06:50:48 +01:00
|
|
|
%type <parmvalue> parameter_value_opt
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2004-06-01 01:34:36 +02:00
|
|
|
%type <function_type> function_range_or_type_opt
|
1999-09-30 00:56:31 +02:00
|
|
|
%type <event_expr> event_expression_list
|
1999-04-29 04:16:26 +02:00
|
|
|
%type <event_expr> event_expression
|
|
|
|
|
%type <event_statement> event_control
|
2007-04-02 01:02:03 +02:00
|
|
|
%type <statement> statement statement_or_null
|
1998-11-04 00:28:49 +01:00
|
|
|
%type <statement_list> statement_list
|
|
|
|
|
|
2003-02-27 07:45:11 +01:00
|
|
|
%type <letter> spec_polarity
|
2004-05-25 21:21:06 +02:00
|
|
|
%type <perm_strings> specify_path_identifiers
|
2003-02-27 07:45:11 +01:00
|
|
|
|
2006-09-23 06:57:19 +02:00
|
|
|
%type <specpath> specify_simple_path specify_simple_path_decl
|
2007-02-12 02:52:21 +01:00
|
|
|
%type <specpath> specify_edge_path specify_edge_path_decl
|
2006-09-23 06:57:19 +02:00
|
|
|
|
2001-07-02 01:44:43 +02:00
|
|
|
%token K_TAND
|
1999-09-30 00:56:31 +02:00
|
|
|
%right '?' ':'
|
1999-03-15 03:43:32 +01:00
|
|
|
%left K_LOR
|
1999-03-16 05:44:45 +01:00
|
|
|
%left K_LAND
|
|
|
|
|
%left '|'
|
1999-09-30 04:43:01 +02:00
|
|
|
%left '^' K_NXOR K_NOR
|
|
|
|
|
%left '&' K_NAND
|
1999-03-16 05:44:45 +01:00
|
|
|
%left K_EQ K_NE K_CEQ K_CNE
|
|
|
|
|
%left K_GE K_LE '<' '>'
|
2003-06-18 05:55:18 +02:00
|
|
|
%left K_LS K_RS K_RSS
|
1999-03-16 05:44:45 +01:00
|
|
|
%left '+' '-'
|
1999-05-16 07:08:42 +02:00
|
|
|
%left '*' '/' '%'
|
2006-07-31 05:50:17 +02:00
|
|
|
%left K_POW
|
1999-03-16 05:44:45 +01:00
|
|
|
%left UNARY_PREC
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2003-12-19 06:15:04 +01:00
|
|
|
/* to resolve dangling else ambiguity. */
|
1999-09-30 00:56:31 +02:00
|
|
|
%nonassoc less_than_K_else
|
|
|
|
|
%nonassoc K_else
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
%%
|
|
|
|
|
|
1999-10-15 07:03:33 +02:00
|
|
|
/* A degenerate source file can be completely empty. */
|
|
|
|
|
main : source_file | ;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
source_file
|
|
|
|
|
: description
|
|
|
|
|
| source_file description
|
|
|
|
|
;
|
|
|
|
|
|
2003-04-14 05:37:47 +02:00
|
|
|
number : BASED_NUMBER
|
2007-10-12 01:37:57 +02:00
|
|
|
{ $$ = $1; based_size = 0;}
|
2003-04-14 05:37:47 +02:00
|
|
|
| DEC_NUMBER
|
2007-10-12 01:37:57 +02:00
|
|
|
{ $$ = $1; based_size = 0;}
|
2003-04-14 05:37:47 +02:00
|
|
|
| DEC_NUMBER BASED_NUMBER
|
2007-10-12 01:37:57 +02:00
|
|
|
{ $$ = pform_verinum_with_size($1,$2, @2.text, @2.first_line);
|
|
|
|
|
based_size = 0; }
|
2003-04-14 05:37:47 +02:00
|
|
|
;
|
|
|
|
|
|
2002-05-23 05:08:50 +02:00
|
|
|
/* Verilog-2001 supports attribute lists, which can be attached to a
|
|
|
|
|
variety of different objects. The syntax inside the (* *) is a
|
|
|
|
|
comma separated list of names or names with assigned values. */
|
|
|
|
|
attribute_list_opt
|
|
|
|
|
: K_PSTAR attribute_list K_STARP { $$ = $2; }
|
|
|
|
|
| K_PSTAR K_STARP { $$ = 0; }
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
attribute_list
|
|
|
|
|
: attribute_list ',' attribute
|
|
|
|
|
{ svector<named_pexpr_t*>*tmp =
|
|
|
|
|
new svector<named_pexpr_t*>(*$1,$3);
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| attribute
|
|
|
|
|
{ svector<named_pexpr_t*>*tmp = new svector<named_pexpr_t*>(1);
|
|
|
|
|
(*tmp)[0] = $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
attribute
|
|
|
|
|
: IDENTIFIER
|
|
|
|
|
{ named_pexpr_t*tmp = new named_pexpr_t;
|
2004-02-20 07:22:56 +01:00
|
|
|
tmp->name = lex_strings.make($1);
|
2002-05-23 05:08:50 +02:00
|
|
|
tmp->parm = 0;
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| IDENTIFIER '=' expression
|
|
|
|
|
{ PExpr*tmp = $3;
|
|
|
|
|
if (!pform_expression_is_constant(tmp)) {
|
2002-06-11 05:34:33 +02:00
|
|
|
yyerror(@3, "error: attribute value "
|
2002-05-23 05:08:50 +02:00
|
|
|
"expression must be constant.");
|
|
|
|
|
delete tmp;
|
|
|
|
|
tmp = 0;
|
|
|
|
|
}
|
|
|
|
|
named_pexpr_t*tmp2 = new named_pexpr_t;
|
2004-02-20 07:22:56 +01:00
|
|
|
tmp2->name = lex_strings.make($1);
|
2002-05-23 05:08:50 +02:00
|
|
|
tmp2->parm = tmp;
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp2;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
1999-09-30 03:22:37 +02:00
|
|
|
/* The block_item_decl is used in function definitions, task
|
|
|
|
|
definitions, module definitions and named blocks. Wherever a new
|
|
|
|
|
scope is entered, the source may declare new registers and
|
|
|
|
|
integers. This rule matches those declarations. The containing
|
|
|
|
|
rule has presumably set up the scope. */
|
2005-07-07 18:22:49 +02:00
|
|
|
|
1999-06-24 06:24:18 +02:00
|
|
|
block_item_decl
|
2005-07-07 18:22:49 +02:00
|
|
|
: attribute_list_opt K_reg
|
|
|
|
|
primitive_type_opt signed_opt range
|
|
|
|
|
register_variable_list ';'
|
|
|
|
|
{ ivl_variable_type_t dtype = $3;
|
|
|
|
|
if (dtype == IVL_VT_NO_TYPE)
|
|
|
|
|
dtype = IVL_VT_LOGIC;
|
|
|
|
|
pform_set_net_range($6, $5, $4, dtype);
|
2004-09-14 20:24:56 +02:00
|
|
|
if ($1) delete $1;
|
1999-09-10 07:02:09 +02:00
|
|
|
}
|
2005-07-07 18:22:49 +02:00
|
|
|
|
|
|
|
|
/* This differs from the above pattern only in the absence of the
|
|
|
|
|
range. This is the rule for a scalar. */
|
|
|
|
|
|
|
|
|
|
| attribute_list_opt K_reg
|
|
|
|
|
primitive_type_opt signed_opt
|
|
|
|
|
register_variable_list ';'
|
|
|
|
|
{ ivl_variable_type_t dtype = $3;
|
|
|
|
|
if (dtype == IVL_VT_NO_TYPE)
|
|
|
|
|
dtype = IVL_VT_LOGIC;
|
|
|
|
|
pform_set_net_range($5, 0, $4, dtype);
|
2004-09-14 20:24:56 +02:00
|
|
|
if ($1) delete $1;
|
2000-04-02 06:25:39 +02:00
|
|
|
}
|
2005-07-07 18:22:49 +02:00
|
|
|
|
|
|
|
|
/* Integer declarations are simpler in that they do not have all the
|
|
|
|
|
trappings of a general variable declaration. All of that is
|
|
|
|
|
implicit in the "integer" of the declaratin. */
|
|
|
|
|
|
2004-09-14 20:24:56 +02:00
|
|
|
| attribute_list_opt K_integer register_variable_list ';'
|
|
|
|
|
{ pform_set_reg_integer($3);
|
|
|
|
|
if ($1) delete $1;
|
1999-09-10 07:02:09 +02:00
|
|
|
}
|
2005-07-07 18:22:49 +02:00
|
|
|
|
2007-08-05 06:50:06 +02:00
|
|
|
| attribute_list_opt K_time register_variable_list ';'
|
|
|
|
|
{ pform_set_reg_time($3);
|
2000-10-31 18:49:02 +01:00
|
|
|
}
|
2005-07-07 18:22:49 +02:00
|
|
|
|
2005-07-11 18:56:50 +02:00
|
|
|
/* real declarations are fairly simple as there is no range of
|
|
|
|
|
signed flag in the declaration. Create the real as a NetNet::REG
|
|
|
|
|
with real value. Note that real and realtime are interchangable
|
|
|
|
|
in this context. */
|
|
|
|
|
|
2007-08-05 06:50:06 +02:00
|
|
|
| attribute_list_opt K_real real_variable_list ';'
|
|
|
|
|
{ delete $3; }
|
|
|
|
|
| attribute_list_opt K_realtime real_variable_list ';'
|
|
|
|
|
{ delete $3; }
|
2005-07-07 18:22:49 +02:00
|
|
|
|
2002-08-19 04:39:16 +02:00
|
|
|
| K_parameter parameter_assign_decl ';'
|
2004-08-26 06:02:03 +02:00
|
|
|
| K_localparam localparam_assign_decl ';'
|
2001-01-06 07:31:58 +01:00
|
|
|
|
|
|
|
|
/* Recover from errors that happen within variable lists. Use the
|
|
|
|
|
trailing semi-colon to resync the parser. */
|
|
|
|
|
|
2004-09-14 20:24:56 +02:00
|
|
|
| attribute_list_opt K_reg error ';'
|
|
|
|
|
{ yyerror(@2, "error: syntax error in reg variable list.");
|
2001-01-06 07:31:58 +01:00
|
|
|
yyerrok;
|
2004-09-14 20:24:56 +02:00
|
|
|
if ($1) delete $1;
|
2001-01-06 07:31:58 +01:00
|
|
|
}
|
2004-09-14 20:24:56 +02:00
|
|
|
| attribute_list_opt K_integer error ';'
|
|
|
|
|
{ yyerror(@2, "error: syntax error in integer variable list.");
|
2001-01-06 07:31:58 +01:00
|
|
|
yyerrok;
|
2004-09-14 20:24:56 +02:00
|
|
|
if ($1) delete $1;
|
2001-01-06 07:31:58 +01:00
|
|
|
}
|
2007-08-05 06:50:06 +02:00
|
|
|
| attribute_list_opt K_time error ';'
|
|
|
|
|
{ yyerror(@2, "error: syntax error in time variable list.");
|
2001-01-06 07:31:58 +01:00
|
|
|
yyerrok;
|
|
|
|
|
}
|
2007-08-05 06:50:06 +02:00
|
|
|
| attribute_list_opt K_real error ';'
|
|
|
|
|
{ yyerror(@2, "error: syntax error in real variable list.");
|
2001-01-06 07:31:58 +01:00
|
|
|
yyerrok;
|
|
|
|
|
}
|
2007-08-05 06:50:06 +02:00
|
|
|
| attribute_list_opt K_realtime error ';'
|
2007-12-03 21:31:34 +01:00
|
|
|
{ yyerror(@2, "error: syntax error in realtime variable list.");
|
2001-01-06 07:31:58 +01:00
|
|
|
yyerrok;
|
|
|
|
|
}
|
2001-01-13 23:20:08 +01:00
|
|
|
| K_parameter error ';'
|
|
|
|
|
{ yyerror(@1, "error: syntax error in parameter list.");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
| K_localparam error ';'
|
|
|
|
|
{ yyerror(@1, "error: syntax error localparam list.");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
1999-06-24 06:24:18 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
block_item_decls
|
|
|
|
|
: block_item_decl
|
|
|
|
|
| block_item_decls block_item_decl
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
block_item_decls_opt
|
|
|
|
|
: block_item_decls
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
1999-02-03 05:20:11 +01:00
|
|
|
case_item
|
2007-04-02 01:02:03 +02:00
|
|
|
: expression_list_proper ':' statement_or_null
|
1999-02-03 05:20:11 +01:00
|
|
|
{ PCase::Item*tmp = new PCase::Item;
|
1999-06-15 07:38:39 +02:00
|
|
|
tmp->expr = *$1;
|
1999-02-03 05:20:11 +01:00
|
|
|
tmp->stat = $3;
|
1999-06-15 07:38:39 +02:00
|
|
|
delete $1;
|
1999-02-03 05:20:11 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| K_default ':' statement_or_null
|
1999-02-03 05:20:11 +01:00
|
|
|
{ PCase::Item*tmp = new PCase::Item;
|
|
|
|
|
tmp->stat = $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| K_default statement_or_null
|
1999-02-03 05:20:11 +01:00
|
|
|
{ PCase::Item*tmp = new PCase::Item;
|
|
|
|
|
tmp->stat = $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| error ':' statement_or_null
|
2007-12-03 21:31:34 +01:00
|
|
|
{ yyerror(@2, "error: Incomprehensible case expression.");
|
1999-06-12 05:42:57 +02:00
|
|
|
yyerrok;
|
|
|
|
|
}
|
1999-02-03 05:20:11 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
case_items
|
|
|
|
|
: case_items case_item
|
1999-06-06 22:45:38 +02:00
|
|
|
{ svector<PCase::Item*>*tmp;
|
|
|
|
|
tmp = new svector<PCase::Item*>(*$1, $2);
|
|
|
|
|
delete $1;
|
1999-02-03 05:20:11 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| case_item
|
1999-06-06 22:45:38 +02:00
|
|
|
{ svector<PCase::Item*>*tmp = new svector<PCase::Item*>(1);
|
|
|
|
|
(*tmp)[0] = $1;
|
1999-02-03 05:20:11 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-06-15 04:50:02 +02:00
|
|
|
charge_strength
|
|
|
|
|
: '(' K_small ')'
|
|
|
|
|
| '(' K_medium ')'
|
|
|
|
|
| '(' K_large ')'
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
charge_strength_opt
|
|
|
|
|
: charge_strength
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
1999-06-16 05:13:29 +02:00
|
|
|
defparam_assign
|
2008-01-25 22:34:51 +01:00
|
|
|
: hierarchy_identifier '=' expression
|
1999-06-16 05:13:29 +02:00
|
|
|
{ PExpr*tmp = $3;
|
|
|
|
|
if (!pform_expression_is_constant(tmp)) {
|
1999-09-29 23:16:32 +02:00
|
|
|
yyerror(@3, "error: parameter value "
|
|
|
|
|
"must be constant.");
|
1999-06-16 05:13:29 +02:00
|
|
|
delete tmp;
|
|
|
|
|
tmp = 0;
|
|
|
|
|
}
|
2001-12-03 05:47:14 +01:00
|
|
|
pform_set_defparam(*$1, $3);
|
1999-06-16 05:13:29 +02:00
|
|
|
delete $1;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
defparam_assign_list
|
|
|
|
|
: defparam_assign
|
|
|
|
|
| range defparam_assign
|
2002-08-19 04:39:16 +02:00
|
|
|
{ yyerror(@1, "error: defparam may not include a range.");
|
1999-06-16 05:13:29 +02:00
|
|
|
delete $1;
|
|
|
|
|
}
|
|
|
|
|
| defparam_assign_list ',' defparam_assign
|
|
|
|
|
;
|
|
|
|
|
|
1999-12-31 04:24:30 +01:00
|
|
|
delay1
|
2000-01-02 02:59:52 +01:00
|
|
|
: '#' delay_value_simple
|
1999-08-01 18:34:50 +02:00
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
|
|
|
|
(*tmp)[0] = $2;
|
|
|
|
|
$$ = tmp;
|
1999-05-30 05:12:56 +02:00
|
|
|
}
|
1999-12-31 18:39:00 +01:00
|
|
|
| '#' '(' delay_value ')'
|
|
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
|
|
|
|
(*tmp)[0] = $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-12-31 04:24:30 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
delay3
|
2000-01-02 02:59:52 +01:00
|
|
|
: '#' delay_value_simple
|
1999-12-31 04:24:30 +01:00
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
|
|
|
|
(*tmp)[0] = $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| '#' '(' delay_value ')'
|
|
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
|
|
|
|
(*tmp)[0] = $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| '#' '(' delay_value ',' delay_value ')'
|
|
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(2);
|
|
|
|
|
(*tmp)[0] = $3;
|
|
|
|
|
(*tmp)[1] = $5;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| '#' '(' delay_value ',' delay_value ',' delay_value ')'
|
|
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(3);
|
|
|
|
|
(*tmp)[0] = $3;
|
|
|
|
|
(*tmp)[1] = $5;
|
2000-05-31 03:31:52 +02:00
|
|
|
(*tmp)[2] = $7;
|
1999-12-31 04:24:30 +01:00
|
|
|
$$ = tmp;
|
1999-05-30 05:12:56 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-12-31 04:24:30 +01:00
|
|
|
delay3_opt
|
|
|
|
|
: delay3 { $$ = $1; }
|
|
|
|
|
| { $$ = 0; }
|
1999-05-30 05:12:56 +02:00
|
|
|
;
|
|
|
|
|
|
2006-09-23 06:57:19 +02:00
|
|
|
delay_value_list
|
|
|
|
|
: delay_value
|
|
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
|
|
|
|
(*tmp)[0] = $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| delay_value_list ',' delay_value
|
|
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-05-30 05:12:56 +02:00
|
|
|
delay_value
|
2000-01-02 02:59:52 +01:00
|
|
|
: expression
|
|
|
|
|
{ PExpr*tmp = $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| expression ':' expression ':' expression
|
2000-07-29 19:58:20 +02:00
|
|
|
{ $$ = pform_select_mtm_expr($1, $3, $5); }
|
2000-01-02 02:59:52 +01:00
|
|
|
;
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2000-01-02 02:59:52 +01:00
|
|
|
|
|
|
|
|
delay_value_simple
|
2003-04-14 05:37:47 +02:00
|
|
|
: DEC_NUMBER
|
1999-05-30 05:12:56 +02:00
|
|
|
{ verinum*tmp = $1;
|
1999-03-16 05:44:45 +01:00
|
|
|
if (tmp == 0) {
|
1999-09-29 23:16:32 +02:00
|
|
|
yyerror(@1, "internal error: delay.");
|
1999-03-16 05:44:45 +01:00
|
|
|
$$ = 0;
|
|
|
|
|
} else {
|
|
|
|
|
$$ = new PENumber(tmp);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME($$, @1);
|
1999-03-16 05:44:45 +01:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2000-12-10 23:01:35 +01:00
|
|
|
| REALTIME
|
|
|
|
|
{ verireal*tmp = $1;
|
|
|
|
|
if (tmp == 0) {
|
|
|
|
|
yyerror(@1, "internal error: delay.");
|
|
|
|
|
$$ = 0;
|
|
|
|
|
} else {
|
|
|
|
|
$$ = new PEFNumber(tmp);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME($$, @1);
|
2000-12-10 23:01:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
1999-05-30 05:12:56 +02:00
|
|
|
| IDENTIFIER
|
2007-05-24 06:07:11 +02:00
|
|
|
{ PEIdent*tmp = new PEIdent(lex_strings.make($1));
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-05-08 22:19:20 +02:00
|
|
|
$$ = tmp;
|
1999-05-30 05:12:56 +02:00
|
|
|
delete $1;
|
1999-05-20 06:31:45 +02:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
description
|
|
|
|
|
: module
|
1998-11-23 01:20:22 +01:00
|
|
|
| udp_primitive
|
1998-12-01 01:42:13 +01:00
|
|
|
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')'
|
2004-02-18 18:11:54 +01:00
|
|
|
{ perm_string tmp3 = lex_strings.make($3);
|
|
|
|
|
pform_set_type_attrib(tmp3, $5, $7);
|
1998-12-01 01:42:13 +01:00
|
|
|
delete $3;
|
|
|
|
|
delete $5;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
1999-11-05 20:36:36 +01:00
|
|
|
drive_strength
|
|
|
|
|
: '(' dr_strength0 ',' dr_strength1 ')'
|
2000-05-06 17:41:56 +02:00
|
|
|
{ $$.str0 = $2.str0;
|
|
|
|
|
$$.str1 = $4.str1;
|
|
|
|
|
}
|
1999-11-05 20:36:36 +01:00
|
|
|
| '(' dr_strength1 ',' dr_strength0 ')'
|
2000-05-06 17:41:56 +02:00
|
|
|
{ $$.str0 = $4.str0;
|
|
|
|
|
$$.str1 = $2.str1;
|
|
|
|
|
}
|
1999-11-05 20:36:36 +01:00
|
|
|
| '(' dr_strength0 ',' K_highz1 ')'
|
2000-05-06 17:41:56 +02:00
|
|
|
{ $$.str0 = $2.str0;
|
|
|
|
|
$$.str1 = PGate::HIGHZ;
|
|
|
|
|
}
|
1999-11-05 20:36:36 +01:00
|
|
|
| '(' dr_strength1 ',' K_highz0 ')'
|
2000-05-06 17:41:56 +02:00
|
|
|
{ $$.str0 = PGate::HIGHZ;
|
|
|
|
|
$$.str1 = $2.str1;
|
|
|
|
|
}
|
1999-11-05 20:36:36 +01:00
|
|
|
| '(' K_highz1 ',' dr_strength0 ')'
|
2000-05-06 17:41:56 +02:00
|
|
|
{ $$.str0 = $4.str0;
|
|
|
|
|
$$.str1 = PGate::HIGHZ;
|
|
|
|
|
}
|
1999-11-05 20:36:36 +01:00
|
|
|
| '(' K_highz0 ',' dr_strength1 ')'
|
2000-05-06 17:41:56 +02:00
|
|
|
{ $$.str0 = PGate::HIGHZ;
|
|
|
|
|
$$.str1 = $4.str1;
|
|
|
|
|
}
|
1999-11-05 20:36:36 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
drive_strength_opt
|
2000-05-06 17:41:56 +02:00
|
|
|
: drive_strength { $$ = $1; }
|
|
|
|
|
| { $$.str0 = PGate::STRONG; $$.str1 = PGate::STRONG; }
|
1999-11-05 20:36:36 +01:00
|
|
|
;
|
|
|
|
|
|
2000-05-06 17:41:56 +02:00
|
|
|
dr_strength0
|
|
|
|
|
: K_supply0 { $$.str0 = PGate::SUPPLY; }
|
|
|
|
|
| K_strong0 { $$.str0 = PGate::STRONG; }
|
|
|
|
|
| K_pull0 { $$.str0 = PGate::PULL; }
|
|
|
|
|
| K_weak0 { $$.str0 = PGate::WEAK; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
dr_strength1
|
|
|
|
|
: K_supply1 { $$.str1 = PGate::SUPPLY; }
|
|
|
|
|
| K_strong1 { $$.str1 = PGate::STRONG; }
|
|
|
|
|
| K_pull1 { $$.str1 = PGate::PULL; }
|
|
|
|
|
| K_weak1 { $$.str1 = PGate::WEAK; }
|
|
|
|
|
;
|
1999-11-05 20:36:36 +01:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
event_control
|
2008-01-25 22:34:51 +01:00
|
|
|
: '@' hierarchy_identifier
|
2002-11-02 04:27:51 +01:00
|
|
|
{ PEIdent*tmpi = new PEIdent(*$2);
|
2000-04-12 06:23:57 +02:00
|
|
|
PEEvent*tmpe = new PEEvent(PEEvent::ANYEDGE, tmpi);
|
2000-04-01 21:31:57 +02:00
|
|
|
PEventStatement*tmps = new PEventStatement(tmpe);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmps, @1);
|
2000-04-01 21:31:57 +02:00
|
|
|
$$ = tmps;
|
2007-05-24 06:07:11 +02:00
|
|
|
delete $2;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
1999-09-30 00:56:31 +02:00
|
|
|
| '@' '(' event_expression_list ')'
|
1999-04-29 04:16:26 +02:00
|
|
|
{ PEventStatement*tmp = new PEventStatement(*$3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-04-29 04:16:26 +02:00
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| '@' '(' error ')'
|
1999-09-29 23:16:32 +02:00
|
|
|
{ yyerror(@1, "error: Malformed event control expression.");
|
1999-04-29 04:16:26 +02:00
|
|
|
$$ = 0;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-09-30 00:56:31 +02:00
|
|
|
event_expression_list
|
|
|
|
|
: event_expression
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| event_expression_list K_or event_expression
|
|
|
|
|
{ svector<PEEvent*>*tmp = new svector<PEEvent*>(*$1, *$3);
|
|
|
|
|
delete $1;
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2000-04-15 21:51:30 +02:00
|
|
|
| event_expression_list ',' event_expression
|
|
|
|
|
{ svector<PEEvent*>*tmp = new svector<PEEvent*>(*$1, *$3);
|
|
|
|
|
delete $1;
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-09-30 00:56:31 +02:00
|
|
|
;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
event_expression
|
|
|
|
|
: K_posedge expression
|
2000-04-12 06:23:57 +02:00
|
|
|
{ PEEvent*tmp = new PEEvent(PEEvent::POSEDGE, $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-04-29 04:16:26 +02:00
|
|
|
svector<PEEvent*>*tl = new svector<PEEvent*>(1);
|
|
|
|
|
(*tl)[0] = tmp;
|
|
|
|
|
$$ = tl;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
| K_negedge expression
|
2000-04-12 06:23:57 +02:00
|
|
|
{ PEEvent*tmp = new PEEvent(PEEvent::NEGEDGE, $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-04-29 04:16:26 +02:00
|
|
|
svector<PEEvent*>*tl = new svector<PEEvent*>(1);
|
|
|
|
|
(*tl)[0] = tmp;
|
|
|
|
|
$$ = tl;
|
|
|
|
|
}
|
|
|
|
|
| expression
|
2000-04-12 06:23:57 +02:00
|
|
|
{ PEEvent*tmp = new PEEvent(PEEvent::ANYEDGE, $1);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-04-29 04:16:26 +02:00
|
|
|
svector<PEEvent*>*tl = new svector<PEEvent*>(1);
|
|
|
|
|
(*tl)[0] = tmp;
|
|
|
|
|
$$ = tl;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
expression
|
|
|
|
|
: expr_primary
|
|
|
|
|
{ $$ = $1; }
|
1999-05-20 06:31:45 +02:00
|
|
|
| '+' expr_primary %prec UNARY_PREC
|
1999-06-13 19:30:23 +02:00
|
|
|
{ $$ = $2; }
|
1999-05-20 06:31:45 +02:00
|
|
|
| '-' expr_primary %prec UNARY_PREC
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEUnary*tmp = new PEUnary('-', $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-20 06:31:45 +02:00
|
|
|
}
|
|
|
|
|
| '~' expr_primary %prec UNARY_PREC
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEUnary*tmp = new PEUnary('~', $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
1999-05-20 06:31:45 +02:00
|
|
|
| '&' expr_primary %prec UNARY_PREC
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEUnary*tmp = new PEUnary('&', $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
1999-05-20 06:31:45 +02:00
|
|
|
| '!' expr_primary %prec UNARY_PREC
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEUnary*tmp = new PEUnary('!', $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-03-15 03:43:32 +01:00
|
|
|
}
|
1999-05-20 06:31:45 +02:00
|
|
|
| '|' expr_primary %prec UNARY_PREC
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEUnary*tmp = new PEUnary('|', $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-20 06:31:45 +02:00
|
|
|
}
|
|
|
|
|
| '^' expr_primary %prec UNARY_PREC
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEUnary*tmp = new PEUnary('^', $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-20 06:31:45 +02:00
|
|
|
}
|
1999-06-13 19:30:23 +02:00
|
|
|
| K_NAND expr_primary %prec UNARY_PREC
|
|
|
|
|
{ PEUnary*tmp = new PEUnary('A', $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-06-13 19:30:23 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_NOR expr_primary %prec UNARY_PREC
|
|
|
|
|
{ PEUnary*tmp = new PEUnary('N', $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-06-13 19:30:23 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_NXOR expr_primary %prec UNARY_PREC
|
|
|
|
|
{ PEUnary*tmp = new PEUnary('X', $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-06-13 19:30:23 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2000-04-21 05:22:18 +02:00
|
|
|
| '!' error %prec UNARY_PREC
|
|
|
|
|
{ yyerror(@1, "error: Operand of unary ! "
|
|
|
|
|
"is not a primary expression.");
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
|
|
|
|
| '^' error %prec UNARY_PREC
|
|
|
|
|
{ yyerror(@1, "error: Operand of reduction ^ "
|
|
|
|
|
"is not a primary expression.");
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
| expression '^' expression
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEBinary*tmp = new PEBinary('^', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2006-07-31 05:50:17 +02:00
|
|
|
| expression K_POW expression
|
|
|
|
|
{ PEBinary*tmp = new PEBinary('p', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
2006-07-31 05:50:17 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-05-16 07:08:42 +02:00
|
|
|
| expression '*' expression
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEBinary*tmp = new PEBinary('*', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-16 07:08:42 +02:00
|
|
|
}
|
|
|
|
|
| expression '/' expression
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEBinary*tmp = new PEBinary('/', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-16 07:08:42 +02:00
|
|
|
}
|
|
|
|
|
| expression '%' expression
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEBinary*tmp = new PEBinary('%', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-16 07:08:42 +02:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
| expression '+' expression
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEBinary*tmp = new PEBinary('+', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
1998-11-09 19:55:33 +01:00
|
|
|
| expression '-' expression
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEBinary*tmp = new PEBinary('-', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-09 19:55:33 +01:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
| expression '&' expression
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEBinary*tmp = new PEBinary('&', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
1999-03-15 03:43:32 +01:00
|
|
|
| expression '|' expression
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEBinary*tmp = new PEBinary('|', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-03-15 03:43:32 +01:00
|
|
|
}
|
2002-09-12 17:49:43 +02:00
|
|
|
| expression K_NAND expression
|
|
|
|
|
{ PEBinary*tmp = new PEBinary('A', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
2002-09-12 17:49:43 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-09-30 04:43:01 +02:00
|
|
|
| expression K_NOR expression
|
|
|
|
|
{ PEBinary*tmp = new PEBinary('O', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-09-30 04:43:01 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| expression K_NXOR expression
|
|
|
|
|
{ PEBinary*tmp = new PEBinary('X', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-09-30 04:43:01 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-05-08 22:19:20 +02:00
|
|
|
| expression '<' expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBComp('<', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-08 22:19:20 +02:00
|
|
|
}
|
|
|
|
|
| expression '>' expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBComp('>', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-08 22:19:20 +02:00
|
|
|
}
|
1999-05-16 07:08:42 +02:00
|
|
|
| expression K_LS expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBShift('l', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-16 07:08:42 +02:00
|
|
|
}
|
|
|
|
|
| expression K_RS expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBShift('r', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-16 07:08:42 +02:00
|
|
|
}
|
2003-06-18 05:55:18 +02:00
|
|
|
| expression K_RSS expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBShift('R', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
2003-06-18 05:55:18 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1998-11-07 18:05:05 +01:00
|
|
|
| expression K_EQ expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBComp('e', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-07 18:05:05 +01:00
|
|
|
}
|
|
|
|
|
| expression K_CEQ expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBComp('E', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-07 18:05:05 +01:00
|
|
|
}
|
1999-05-16 07:08:42 +02:00
|
|
|
| expression K_LE expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBComp('L', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-16 07:08:42 +02:00
|
|
|
}
|
|
|
|
|
| expression K_GE expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBComp('G', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-05-16 07:08:42 +02:00
|
|
|
}
|
1998-11-07 18:05:05 +01:00
|
|
|
| expression K_NE expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBComp('n', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-07 18:05:05 +01:00
|
|
|
}
|
|
|
|
|
| expression K_CNE expression
|
2006-10-30 06:44:49 +01:00
|
|
|
{ PEBinary*tmp = new PEBComp('N', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-07 18:05:05 +01:00
|
|
|
}
|
1999-03-15 03:43:32 +01:00
|
|
|
| expression K_LOR expression
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEBinary*tmp = new PEBinary('o', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-03-15 03:43:32 +01:00
|
|
|
}
|
|
|
|
|
| expression K_LAND expression
|
1999-05-27 05:31:29 +02:00
|
|
|
{ PEBinary*tmp = new PEBinary('a', $1, $3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1999-03-15 03:43:32 +01:00
|
|
|
}
|
1999-05-20 06:31:45 +02:00
|
|
|
| expression '?' expression ':' expression
|
1999-06-10 06:03:52 +02:00
|
|
|
{ PETernary*tmp = new PETernary($1, $3, $5);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1999-06-10 06:03:52 +02:00
|
|
|
$$ = tmp;
|
1999-05-20 06:31:45 +02:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
2007-09-16 17:25:03 +02:00
|
|
|
expr_mintypmax
|
|
|
|
|
: expression
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| expression ':' expression ':' expression
|
|
|
|
|
{ switch (min_typ_max_flag) {
|
|
|
|
|
case MIN:
|
|
|
|
|
$$ = $1;
|
|
|
|
|
delete $3;
|
|
|
|
|
delete $5;
|
|
|
|
|
break;
|
|
|
|
|
case TYP:
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = $3;
|
|
|
|
|
delete $5;
|
|
|
|
|
break;
|
|
|
|
|
case MAX:
|
|
|
|
|
delete $1;
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = $5;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-11-21 20:07:40 +01:00
|
|
|
if (min_typ_max_warn > 0) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << $$->get_fileline() << ": warning: choosing ";
|
2007-11-21 20:07:40 +01:00
|
|
|
switch (min_typ_max_flag) {
|
|
|
|
|
case MIN:
|
|
|
|
|
cerr << "min";
|
|
|
|
|
break;
|
|
|
|
|
case TYP:
|
|
|
|
|
cerr << "typ";
|
|
|
|
|
break;
|
|
|
|
|
case MAX:
|
|
|
|
|
cerr << "max";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
cerr << " expression." << endl;
|
|
|
|
|
min_typ_max_warn -= 1;
|
|
|
|
|
}
|
2007-09-16 17:25:03 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-05-23 18:03:13 +02:00
|
|
|
/* Many contexts take a comma separated list of expressions. Null
|
|
|
|
|
expressions can happen anywhere in the list, so there are two
|
2007-04-02 01:02:03 +02:00
|
|
|
extra rules in expression_list_with_nuls for parsing and
|
|
|
|
|
installing those nulls.
|
|
|
|
|
|
|
|
|
|
The expression_list_proper rules do not allow null items in the
|
|
|
|
|
expression list, so can be used where nul expressions are not allowed. */
|
|
|
|
|
|
|
|
|
|
expression_list_with_nuls
|
|
|
|
|
: expression_list_with_nuls ',' expression
|
1999-05-10 02:16:57 +02:00
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
|
|
|
|
|
delete $1;
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| expression
|
1999-05-10 02:16:57 +02:00
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
|
|
|
|
(*tmp)[0] = $1;
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2000-05-23 18:03:13 +02:00
|
|
|
|
|
|
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
|
|
|
|
(*tmp)[0] = 0;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2007-04-02 01:02:03 +02:00
|
|
|
| expression_list_with_nuls ','
|
1999-05-10 02:16:57 +02:00
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, 0);
|
|
|
|
|
delete $1;
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
2000-10-14 04:23:02 +02:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
2007-04-02 01:02:03 +02:00
|
|
|
expression_list_proper
|
|
|
|
|
: expression_list_proper ',' expression
|
|
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| expression
|
|
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
|
|
|
|
(*tmp)[0] = $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
expr_primary
|
2003-04-14 05:37:47 +02:00
|
|
|
: number
|
1999-06-15 04:50:02 +02:00
|
|
|
{ assert($1);
|
|
|
|
|
PENumber*tmp = new PENumber($1);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-15 04:50:02 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| REALTIME
|
2001-01-15 00:04:55 +01:00
|
|
|
{ PEFNumber*tmp = new PEFNumber($1);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2001-01-15 00:04:55 +01:00
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
| STRING
|
1999-07-10 03:03:18 +02:00
|
|
|
{ PEString*tmp = new PEString($1);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
| SYSTEM_IDENTIFIER
|
2007-04-26 05:06:21 +02:00
|
|
|
{ perm_string tn = lex_strings.make($1);
|
2007-05-24 06:07:11 +02:00
|
|
|
PECallFunction*tmp = new PECallFunction(tn);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-05-27 05:31:29 +02:00
|
|
|
$$ = tmp;
|
2002-09-16 02:28:51 +02:00
|
|
|
delete $1;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2006-02-02 03:43:57 +01:00
|
|
|
|
2008-01-25 22:34:51 +01:00
|
|
|
/* The hierarchy_identifier rule matches simple identifiers as well as
|
2007-05-24 06:07:11 +02:00
|
|
|
indexed arrays and part selects */
|
2005-10-04 06:09:25 +02:00
|
|
|
|
2008-01-25 22:34:51 +01:00
|
|
|
| hierarchy_identifier
|
2007-05-24 06:07:11 +02:00
|
|
|
{ PEIdent*tmp = new PEIdent(*$1);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2007-05-24 06:07:11 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
delete $1;
|
|
|
|
|
}
|
2005-10-04 06:09:25 +02:00
|
|
|
|
|
|
|
|
/* An identifer followed by an expression list in parentheses is a
|
|
|
|
|
function call. If a system identifier, then a system function
|
|
|
|
|
call. */
|
|
|
|
|
|
2008-01-25 22:34:51 +01:00
|
|
|
| hierarchy_identifier '(' expression_list_proper ')'
|
2001-12-03 05:47:14 +01:00
|
|
|
{ PECallFunction*tmp = new PECallFunction(*$1, *$3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2001-12-03 05:47:14 +01:00
|
|
|
delete $1;
|
1999-07-31 21:14:47 +02:00
|
|
|
$$ = tmp;
|
1999-06-16 05:13:29 +02:00
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| SYSTEM_IDENTIFIER '(' expression_list_proper ')'
|
2007-04-26 05:06:21 +02:00
|
|
|
{ perm_string tn = lex_strings.make($1);
|
2007-05-24 06:07:11 +02:00
|
|
|
PECallFunction*tmp = new PECallFunction(tn, *$3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-09-25 04:57:29 +02:00
|
|
|
$$ = tmp;
|
1999-06-16 05:13:29 +02:00
|
|
|
}
|
2005-10-04 06:09:25 +02:00
|
|
|
|
|
|
|
|
/* Parenthesized expressions are primaries. */
|
|
|
|
|
|
2007-09-16 17:25:03 +02:00
|
|
|
| '(' expr_mintypmax ')'
|
1999-06-09 05:00:05 +02:00
|
|
|
{ $$ = $2; }
|
2005-10-04 06:09:25 +02:00
|
|
|
|
|
|
|
|
/* Various kinds of concatenation expressions. */
|
|
|
|
|
|
2007-04-02 01:02:03 +02:00
|
|
|
| '{' expression_list_proper '}'
|
1999-06-10 06:03:52 +02:00
|
|
|
{ PEConcat*tmp = new PEConcat(*$2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-10 06:03:52 +02:00
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| '{' expression '{' expression_list_proper '}' '}'
|
1999-06-10 06:03:52 +02:00
|
|
|
{ PExpr*rep = $2;
|
|
|
|
|
PEConcat*tmp = new PEConcat(*$4, rep);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-10 06:03:52 +02:00
|
|
|
delete $4;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| '{' expression '{' expression_list_proper '}' error '}'
|
2007-02-27 07:10:16 +01:00
|
|
|
{ PExpr*rep = $2;
|
|
|
|
|
PEConcat*tmp = new PEConcat(*$4, rep);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2007-02-27 07:10:16 +01:00
|
|
|
delete $4;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
yyerror(@5, "error: Syntax error between internal '}' "
|
|
|
|
|
"and closing '}' of repeat concatenation.");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
1999-09-30 03:22:37 +02:00
|
|
|
/* A function_item is either a block item (i.e. a reg or integer
|
|
|
|
|
declaration) or an input declaration. There are no output or
|
|
|
|
|
inout ports. */
|
1999-05-30 05:12:56 +02:00
|
|
|
function_item
|
2006-03-30 07:22:34 +02:00
|
|
|
: K_input signed_opt range_opt list_of_identifiers ';'
|
1999-07-31 21:14:47 +02:00
|
|
|
{ svector<PWire*>*tmp
|
2006-03-30 07:22:34 +02:00
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
2007-01-29 03:07:34 +01:00
|
|
|
IVL_VT_NO_TYPE, $2,
|
2006-03-30 07:22:34 +02:00
|
|
|
$3, $4,
|
2003-06-13 02:27:09 +02:00
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2006-03-30 07:22:34 +02:00
|
|
|
| K_output signed_opt range_opt list_of_identifiers ';'
|
2003-06-13 02:27:09 +02:00
|
|
|
{ svector<PWire*>*tmp
|
2006-03-30 07:22:34 +02:00
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
2007-01-29 03:07:34 +01:00
|
|
|
IVL_VT_NO_TYPE, $2,
|
2003-06-13 02:27:09 +02:00
|
|
|
$3, $4,
|
1999-09-10 07:02:09 +02:00
|
|
|
@1.text, @1.first_line);
|
1999-07-31 21:14:47 +02:00
|
|
|
$$ = tmp;
|
2006-03-30 07:22:34 +02:00
|
|
|
yyerror(@1, "Functions may not have output ports.");
|
1999-07-31 21:14:47 +02:00
|
|
|
}
|
2006-03-30 07:22:34 +02:00
|
|
|
| K_inout signed_opt range_opt list_of_identifiers ';'
|
2002-01-23 04:35:17 +01:00
|
|
|
{ svector<PWire*>*tmp
|
2006-03-30 07:22:34 +02:00
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
2007-01-29 03:07:34 +01:00
|
|
|
IVL_VT_NO_TYPE, $2,
|
2006-03-30 07:22:34 +02:00
|
|
|
$3, $4,
|
2002-01-23 04:35:17 +01:00
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
2006-03-30 07:22:34 +02:00
|
|
|
yyerror(@1, "Functions may not have inout ports.");
|
2002-01-23 04:35:17 +01:00
|
|
|
}
|
2007-01-29 03:07:34 +01:00
|
|
|
|
2006-03-30 07:22:34 +02:00
|
|
|
/* When the port is an integer, infer a signed vector of the integer
|
|
|
|
|
shape. Generate a range to make it work. */
|
|
|
|
|
|
|
|
|
|
| K_input K_integer list_of_identifiers ';'
|
|
|
|
|
{ svector<PExpr*>*range_stub
|
|
|
|
|
= new svector<PExpr*>(2);
|
|
|
|
|
PExpr*re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum(integer_width-1,
|
|
|
|
|
integer_width));
|
2006-03-30 07:22:34 +02:00
|
|
|
(*range_stub)[0] = re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
2006-03-30 07:22:34 +02:00
|
|
|
(*range_stub)[1] = re;
|
|
|
|
|
svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
|
|
|
|
IVL_VT_LOGIC, true,
|
|
|
|
|
range_stub, $3,
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ports can be real. */
|
|
|
|
|
|
|
|
|
|
| K_input K_real list_of_identifiers ';'
|
|
|
|
|
{ svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
|
|
|
|
IVL_VT_REAL, false,
|
|
|
|
|
0, $3,
|
2002-01-23 04:35:17 +01:00
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2006-03-30 07:22:34 +02:00
|
|
|
|
1999-09-30 03:22:37 +02:00
|
|
|
| block_item_decl
|
1999-07-31 21:14:47 +02:00
|
|
|
{ $$ = 0; }
|
1999-05-30 05:12:56 +02:00
|
|
|
;
|
|
|
|
|
|
1999-09-30 02:48:04 +02:00
|
|
|
/* A function_item_list only lists the input/output/inout
|
|
|
|
|
declarations. The integer and reg declarations are handled in
|
|
|
|
|
place, so are not listed. The list builder needs to account for
|
|
|
|
|
the possibility that the various parts may be NULL. */
|
1999-05-30 05:12:56 +02:00
|
|
|
function_item_list
|
|
|
|
|
: function_item
|
1999-07-31 21:14:47 +02:00
|
|
|
{ $$ = $1; }
|
1999-05-30 05:12:56 +02:00
|
|
|
| function_item_list function_item
|
1999-09-30 02:48:04 +02:00
|
|
|
{ if ($1 && $2) {
|
|
|
|
|
svector<PWire*>*tmp = new svector<PWire*>(*$1, *$2);
|
|
|
|
|
delete $1;
|
|
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
} else if ($1) {
|
|
|
|
|
$$ = $1;
|
|
|
|
|
} else {
|
|
|
|
|
$$ = $2;
|
|
|
|
|
}
|
1999-07-31 21:14:47 +02:00
|
|
|
}
|
1999-05-30 05:12:56 +02:00
|
|
|
;
|
|
|
|
|
|
1999-05-08 22:19:20 +02:00
|
|
|
/* A gate_instance is a module instantiation or a built in part
|
|
|
|
|
type. In any case, the gate has a set of connections to ports. */
|
1998-11-04 00:28:49 +01:00
|
|
|
gate_instance
|
2007-04-02 01:02:03 +02:00
|
|
|
: IDENTIFIER '(' expression_list_with_nuls ')'
|
1998-11-04 00:28:49 +01:00
|
|
|
{ lgate*tmp = new lgate;
|
1999-08-02 01:25:51 +02:00
|
|
|
tmp->name = $1;
|
1998-11-04 00:28:49 +01:00
|
|
|
tmp->parms = $3;
|
1999-01-25 06:45:56 +01:00
|
|
|
tmp->file = @1.text;
|
|
|
|
|
tmp->lineno = @1.first_line;
|
1998-11-04 00:28:49 +01:00
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2000-05-23 18:03:13 +02:00
|
|
|
|
2007-04-02 01:02:03 +02:00
|
|
|
| IDENTIFIER range '(' expression_list_with_nuls ')'
|
1999-02-15 03:06:15 +01:00
|
|
|
{ lgate*tmp = new lgate;
|
1999-05-10 02:16:57 +02:00
|
|
|
svector<PExpr*>*rng = $2;
|
1999-08-02 01:25:51 +02:00
|
|
|
tmp->name = $1;
|
1999-02-15 03:06:15 +01:00
|
|
|
tmp->parms = $4;
|
1999-05-10 02:16:57 +02:00
|
|
|
tmp->range[0] = (*rng)[0];
|
|
|
|
|
tmp->range[1] = (*rng)[1];
|
1999-02-15 03:06:15 +01:00
|
|
|
tmp->file = @1.text;
|
|
|
|
|
tmp->lineno = @1.first_line;
|
|
|
|
|
delete $1;
|
|
|
|
|
delete rng;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| '(' expression_list_with_nuls ')'
|
1998-11-04 00:28:49 +01:00
|
|
|
{ lgate*tmp = new lgate;
|
|
|
|
|
tmp->name = "";
|
|
|
|
|
tmp->parms = $2;
|
1999-01-25 06:45:56 +01:00
|
|
|
tmp->file = @1.text;
|
|
|
|
|
tmp->lineno = @1.first_line;
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2000-05-23 18:03:13 +02:00
|
|
|
|
2004-09-05 20:09:47 +02:00
|
|
|
/* Degenerate modules can have no ports. */
|
|
|
|
|
|
|
|
|
|
| IDENTIFIER range
|
|
|
|
|
{ lgate*tmp = new lgate;
|
|
|
|
|
svector<PExpr*>*rng = $2;
|
|
|
|
|
tmp->name = $1;
|
|
|
|
|
tmp->parms = 0;
|
2006-12-06 06:32:36 +01:00
|
|
|
tmp->parms_by_name = 0;
|
2004-09-05 20:09:47 +02:00
|
|
|
tmp->range[0] = (*rng)[0];
|
|
|
|
|
tmp->range[1] = (*rng)[1];
|
|
|
|
|
tmp->file = @1.text;
|
|
|
|
|
tmp->lineno = @1.first_line;
|
|
|
|
|
delete $1;
|
|
|
|
|
delete rng;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-23 18:03:13 +02:00
|
|
|
/* Modules can also take ports by port-name expressions. */
|
|
|
|
|
|
1999-05-08 22:19:20 +02:00
|
|
|
| IDENTIFIER '(' port_name_list ')'
|
|
|
|
|
{ lgate*tmp = new lgate;
|
1999-08-02 01:25:51 +02:00
|
|
|
tmp->name = $1;
|
2006-12-06 06:32:36 +01:00
|
|
|
tmp->parms = 0;
|
1999-05-29 04:36:17 +02:00
|
|
|
tmp->parms_by_name = $3;
|
1999-05-08 22:19:20 +02:00
|
|
|
tmp->file = @1.text;
|
|
|
|
|
tmp->lineno = @1.first_line;
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2006-12-06 06:32:36 +01:00
|
|
|
|
|
|
|
|
| IDENTIFIER range '(' port_name_list ')'
|
|
|
|
|
{ lgate*tmp = new lgate;
|
|
|
|
|
svector<PExpr*>*rng = $2;
|
|
|
|
|
tmp->name = $1;
|
|
|
|
|
tmp->parms = 0;
|
|
|
|
|
tmp->parms_by_name = $4;
|
|
|
|
|
tmp->range[0] = (*rng)[0];
|
|
|
|
|
tmp->range[1] = (*rng)[1];
|
|
|
|
|
tmp->file = @1.text;
|
|
|
|
|
tmp->lineno = @1.first_line;
|
|
|
|
|
delete $1;
|
|
|
|
|
delete rng;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
gate_instance_list
|
|
|
|
|
: gate_instance_list ',' gate_instance
|
1999-05-06 06:37:17 +02:00
|
|
|
{ svector<lgate>*tmp1 = $1;
|
|
|
|
|
lgate*tmp2 = $3;
|
|
|
|
|
svector<lgate>*out = new svector<lgate> (*tmp1, *tmp2);
|
|
|
|
|
delete tmp1;
|
|
|
|
|
delete tmp2;
|
|
|
|
|
$$ = out;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
| gate_instance
|
1999-05-06 06:37:17 +02:00
|
|
|
{ svector<lgate>*tmp = new svector<lgate>(1);
|
|
|
|
|
(*tmp)[0] = *$1;
|
1998-11-04 00:28:49 +01:00
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
gatetype
|
|
|
|
|
: K_and { $$ = PGBuiltin::AND; }
|
|
|
|
|
| K_nand { $$ = PGBuiltin::NAND; }
|
|
|
|
|
| K_or { $$ = PGBuiltin::OR; }
|
|
|
|
|
| K_nor { $$ = PGBuiltin::NOR; }
|
|
|
|
|
| K_xor { $$ = PGBuiltin::XOR; }
|
|
|
|
|
| K_xnor { $$ = PGBuiltin::XNOR; }
|
|
|
|
|
| K_buf { $$ = PGBuiltin::BUF; }
|
|
|
|
|
| K_bufif0 { $$ = PGBuiltin::BUFIF0; }
|
|
|
|
|
| K_bufif1 { $$ = PGBuiltin::BUFIF1; }
|
|
|
|
|
| K_not { $$ = PGBuiltin::NOT; }
|
|
|
|
|
| K_notif0 { $$ = PGBuiltin::NOTIF0; }
|
|
|
|
|
| K_notif1 { $$ = PGBuiltin::NOTIF1; }
|
|
|
|
|
| K_nmos { $$ = PGBuiltin::NMOS; }
|
|
|
|
|
| K_rnmos { $$ = PGBuiltin::RNMOS; }
|
|
|
|
|
| K_pmos { $$ = PGBuiltin::PMOS; }
|
|
|
|
|
| K_rpmos { $$ = PGBuiltin::RPMOS; }
|
|
|
|
|
| K_cmos { $$ = PGBuiltin::CMOS; }
|
|
|
|
|
| K_rcmos { $$ = PGBuiltin::RCMOS; }
|
|
|
|
|
| K_tran { $$ = PGBuiltin::TRAN; }
|
|
|
|
|
| K_rtran { $$ = PGBuiltin::RTRAN; }
|
|
|
|
|
| K_tranif0 { $$ = PGBuiltin::TRANIF0; }
|
|
|
|
|
| K_tranif1 { $$ = PGBuiltin::TRANIF1; }
|
|
|
|
|
| K_rtranif0 { $$ = PGBuiltin::RTRANIF0; }
|
|
|
|
|
| K_rtranif1 { $$ = PGBuiltin::RTRANIF1; }
|
|
|
|
|
;
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
|
|
|
|
|
/* A general identifier is a hierarchical name, with the right most
|
|
|
|
|
name the base of the identifier. This rule builds up a
|
2007-05-24 06:07:11 +02:00
|
|
|
hierarchical name from the left to the right, forming a list of
|
|
|
|
|
names. */
|
|
|
|
|
|
2008-01-25 22:34:51 +01:00
|
|
|
hierarchy_identifier
|
2007-05-24 06:07:11 +02:00
|
|
|
: IDENTIFIER
|
|
|
|
|
{ $$ = new pform_name_t;
|
|
|
|
|
$$->push_back(name_component_t(lex_strings.make($1)));
|
|
|
|
|
delete $1;
|
|
|
|
|
}
|
2008-01-25 22:34:51 +01:00
|
|
|
| hierarchy_identifier '.' IDENTIFIER
|
2007-05-24 06:07:11 +02:00
|
|
|
{ pform_name_t * tmp = $1;
|
|
|
|
|
tmp->push_back(name_component_t(lex_strings.make($3)));
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2008-01-25 22:34:51 +01:00
|
|
|
| hierarchy_identifier '[' expression ']'
|
2007-05-24 06:07:11 +02:00
|
|
|
{ pform_name_t * tmp = $1;
|
|
|
|
|
name_component_t&tail = tmp->back();
|
|
|
|
|
index_component_t itmp;
|
|
|
|
|
itmp.sel = index_component_t::SEL_BIT;
|
|
|
|
|
itmp.msb = $3;
|
|
|
|
|
tail.index.push_back(itmp);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2008-01-25 22:34:51 +01:00
|
|
|
| hierarchy_identifier '[' expression ':' expression ']'
|
2007-05-24 06:07:11 +02:00
|
|
|
{ pform_name_t * tmp = $1;
|
|
|
|
|
name_component_t&tail = tmp->back();
|
|
|
|
|
index_component_t itmp;
|
|
|
|
|
itmp.sel = index_component_t::SEL_PART;
|
|
|
|
|
itmp.msb = $3;
|
|
|
|
|
itmp.lsb = $5;
|
|
|
|
|
tail.index.push_back(itmp);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2008-01-25 22:34:51 +01:00
|
|
|
| hierarchy_identifier '[' expression K_PO_POS expression ']'
|
2007-05-24 06:07:11 +02:00
|
|
|
{ pform_name_t * tmp = $1;
|
|
|
|
|
name_component_t&tail = tmp->back();
|
|
|
|
|
index_component_t itmp;
|
|
|
|
|
itmp.sel = index_component_t::SEL_IDX_UP;
|
|
|
|
|
itmp.msb = $3;
|
|
|
|
|
itmp.lsb = $5;
|
|
|
|
|
tail.index.push_back(itmp);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2008-01-25 22:34:51 +01:00
|
|
|
| hierarchy_identifier '[' expression K_PO_NEG expression ']'
|
2007-05-24 06:07:11 +02:00
|
|
|
{ pform_name_t * tmp = $1;
|
|
|
|
|
name_component_t&tail = tmp->back();
|
|
|
|
|
index_component_t itmp;
|
|
|
|
|
itmp.sel = index_component_t::SEL_IDX_DO;
|
|
|
|
|
itmp.msb = $3;
|
|
|
|
|
itmp.lsb = $5;
|
|
|
|
|
tail.index.push_back(itmp);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
2006-02-02 03:43:57 +01:00
|
|
|
|
2002-05-20 01:37:28 +02:00
|
|
|
/* This is a list of identifiers. The result is a list of strings,
|
|
|
|
|
each one of the identifiers in the list. These are simple,
|
|
|
|
|
non-hierarchical names separated by ',' characters. */
|
|
|
|
|
list_of_identifiers
|
|
|
|
|
: IDENTIFIER
|
2006-05-11 05:26:57 +02:00
|
|
|
{ $$ = list_from_identifier($1); }
|
2002-05-20 01:37:28 +02:00
|
|
|
| list_of_identifiers ',' IDENTIFIER
|
2006-05-11 05:26:57 +02:00
|
|
|
{ $$ = list_from_identifier($1, $3); }
|
2002-05-20 01:37:28 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The list_of_ports and list_of_port_declarations rules are the
|
2002-06-11 05:34:33 +02:00
|
|
|
port list formats for module ports. The list_of_ports_opt rule is
|
2002-05-20 01:37:28 +02:00
|
|
|
only used by the module start rule.
|
|
|
|
|
|
|
|
|
|
The first, the list_of_ports, is the 1364-1995 format, a list of
|
|
|
|
|
port names, including .name() syntax.
|
|
|
|
|
|
2002-06-11 05:34:33 +02:00
|
|
|
The list_of_port_declarations the 1364-2001 format, an in-line
|
2002-05-20 01:37:28 +02:00
|
|
|
declaration of the ports.
|
|
|
|
|
|
2002-06-11 05:34:33 +02:00
|
|
|
In both cases, the list_of_ports and list_of_port_declarations
|
2002-05-20 01:37:28 +02:00
|
|
|
returns an array of Module::port_t* items that include the name
|
|
|
|
|
of the port internally and externally. The actual creation of the
|
|
|
|
|
nets/variables is done in the declaration, whether internal to
|
|
|
|
|
the port list or in amongst the module items. */
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
list_of_ports
|
1999-09-17 04:06:25 +02:00
|
|
|
: port_opt
|
1999-08-03 06:14:49 +02:00
|
|
|
{ svector<Module::port_t*>*tmp
|
|
|
|
|
= new svector<Module::port_t*>(1);
|
1999-06-12 22:35:27 +02:00
|
|
|
(*tmp)[0] = $1;
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-09-17 04:06:25 +02:00
|
|
|
| list_of_ports ',' port_opt
|
1999-08-03 06:14:49 +02:00
|
|
|
{ svector<Module::port_t*>*tmp
|
|
|
|
|
= new svector<Module::port_t*>(*$1, $3);
|
1999-06-12 22:35:27 +02:00
|
|
|
delete $1;
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-20 01:37:28 +02:00
|
|
|
list_of_port_declarations
|
|
|
|
|
: port_declaration
|
|
|
|
|
{ svector<Module::port_t*>*tmp
|
|
|
|
|
= new svector<Module::port_t*>(1);
|
|
|
|
|
(*tmp)[0] = $1;
|
2007-08-24 04:15:47 +02:00
|
|
|
/*
|
|
|
|
|
* Uncommenting this makes lopd always fully specified.
|
|
|
|
|
* Some wanted an implicit net to not be fully defined.
|
|
|
|
|
*
|
|
|
|
|
* pform_set_net_range($1[0].name);
|
|
|
|
|
*/
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2002-05-20 01:37:28 +02:00
|
|
|
| list_of_port_declarations ',' port_declaration
|
|
|
|
|
{ svector<Module::port_t*>*tmp
|
|
|
|
|
= new svector<Module::port_t*>(*$1, $3);
|
|
|
|
|
delete $1;
|
2007-08-24 04:15:47 +02:00
|
|
|
/*
|
|
|
|
|
* Same as above.
|
|
|
|
|
*
|
|
|
|
|
* pform_set_net_range($3[0].name);
|
|
|
|
|
*/
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2003-04-25 04:28:53 +02:00
|
|
|
| list_of_port_declarations ',' IDENTIFIER
|
|
|
|
|
{ Module::port_t*ptmp;
|
|
|
|
|
ptmp = pform_module_port_reference($3, @3.text,
|
|
|
|
|
@3.first_line);
|
|
|
|
|
svector<Module::port_t*>*tmp
|
|
|
|
|
= new svector<Module::port_t*>(*$1, ptmp);
|
|
|
|
|
|
|
|
|
|
/* Get the port declaration details, the port type
|
|
|
|
|
and what not, from context data stored by the
|
|
|
|
|
last port_declaration rule. */
|
|
|
|
|
pform_module_define_port(@3, $3,
|
|
|
|
|
port_declaration_context.port_type,
|
|
|
|
|
port_declaration_context.port_net_type,
|
|
|
|
|
port_declaration_context.sign_flag,
|
2003-07-04 05:57:18 +02:00
|
|
|
port_declaration_context.range, 0);
|
2003-04-25 04:28:53 +02:00
|
|
|
delete $1;
|
2007-08-24 04:15:47 +02:00
|
|
|
/*
|
|
|
|
|
* Same as above.
|
|
|
|
|
*
|
|
|
|
|
* pform_set_net_range($3);
|
|
|
|
|
*/
|
2003-04-25 04:28:53 +02:00
|
|
|
$$ = tmp;
|
2003-02-08 00:16:09 +01:00
|
|
|
}
|
2007-12-29 08:47:20 +01:00
|
|
|
| list_of_port_declarations ','
|
|
|
|
|
{
|
|
|
|
|
yyerror(@2, "error: NULL port declarations are not "
|
|
|
|
|
"allowed.");
|
|
|
|
|
}
|
|
|
|
|
| list_of_port_declarations ';'
|
|
|
|
|
{
|
|
|
|
|
yyerror(@2, "error: ';' is an invalid port declaration "
|
|
|
|
|
"separator.");
|
|
|
|
|
}
|
2002-05-20 01:37:28 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
port_declaration
|
2003-07-04 05:57:18 +02:00
|
|
|
: attribute_list_opt
|
|
|
|
|
K_input net_type_opt signed_opt range_opt IDENTIFIER
|
2002-05-20 01:37:28 +02:00
|
|
|
{ Module::port_t*ptmp;
|
2003-07-04 05:57:18 +02:00
|
|
|
ptmp = pform_module_port_reference($6, @2.text,
|
|
|
|
|
@2.first_line);
|
|
|
|
|
pform_module_define_port(@2, $6, NetNet::PINPUT,
|
|
|
|
|
$3, $4, $5, $1);
|
2003-04-25 04:28:53 +02:00
|
|
|
port_declaration_context.port_type = NetNet::PINPUT;
|
2003-07-04 05:57:18 +02:00
|
|
|
port_declaration_context.port_net_type = $3;
|
|
|
|
|
port_declaration_context.sign_flag = $4;
|
|
|
|
|
port_declaration_context.range = $5;
|
|
|
|
|
delete $1;
|
|
|
|
|
delete $6;
|
2002-05-20 01:37:28 +02:00
|
|
|
$$ = ptmp;
|
|
|
|
|
}
|
2003-07-04 05:57:18 +02:00
|
|
|
| attribute_list_opt
|
|
|
|
|
K_inout net_type_opt signed_opt range_opt IDENTIFIER
|
2002-05-20 01:37:28 +02:00
|
|
|
{ Module::port_t*ptmp;
|
2003-07-04 05:57:18 +02:00
|
|
|
ptmp = pform_module_port_reference($6, @2.text,
|
|
|
|
|
@2.first_line);
|
|
|
|
|
pform_module_define_port(@2, $6, NetNet::PINOUT,
|
|
|
|
|
$3, $4, $5, $1);
|
2003-04-25 04:28:53 +02:00
|
|
|
port_declaration_context.port_type = NetNet::PINOUT;
|
2003-07-04 05:57:18 +02:00
|
|
|
port_declaration_context.port_net_type = $3;
|
|
|
|
|
port_declaration_context.sign_flag = $4;
|
|
|
|
|
port_declaration_context.range = $5;
|
|
|
|
|
delete $1;
|
|
|
|
|
delete $6;
|
2002-05-20 01:37:28 +02:00
|
|
|
$$ = ptmp;
|
|
|
|
|
}
|
2003-07-04 05:57:18 +02:00
|
|
|
| attribute_list_opt
|
|
|
|
|
K_output net_type_opt signed_opt range_opt IDENTIFIER
|
2002-05-20 01:37:28 +02:00
|
|
|
{ Module::port_t*ptmp;
|
2003-07-04 05:57:18 +02:00
|
|
|
ptmp = pform_module_port_reference($6, @2.text,
|
|
|
|
|
@2.first_line);
|
|
|
|
|
pform_module_define_port(@2, $6, NetNet::POUTPUT,
|
|
|
|
|
$3, $4, $5, $1);
|
2003-04-25 04:28:53 +02:00
|
|
|
port_declaration_context.port_type = NetNet::POUTPUT;
|
2003-07-04 05:57:18 +02:00
|
|
|
port_declaration_context.port_net_type = $3;
|
|
|
|
|
port_declaration_context.sign_flag = $4;
|
|
|
|
|
port_declaration_context.range = $5;
|
|
|
|
|
delete $1;
|
|
|
|
|
delete $6;
|
2002-05-20 01:37:28 +02:00
|
|
|
$$ = ptmp;
|
|
|
|
|
}
|
2003-07-04 05:57:18 +02:00
|
|
|
| attribute_list_opt
|
|
|
|
|
K_output var_type signed_opt range_opt IDENTIFIER
|
2002-05-20 01:37:28 +02:00
|
|
|
{ Module::port_t*ptmp;
|
2003-07-04 05:57:18 +02:00
|
|
|
ptmp = pform_module_port_reference($6, @2.text,
|
|
|
|
|
@2.first_line);
|
|
|
|
|
pform_module_define_port(@2, $6, NetNet::POUTPUT,
|
|
|
|
|
$3, $4, $5, $1);
|
2003-04-25 04:28:53 +02:00
|
|
|
port_declaration_context.port_type = NetNet::POUTPUT;
|
2003-07-04 05:57:18 +02:00
|
|
|
port_declaration_context.port_net_type = $3;
|
|
|
|
|
port_declaration_context.sign_flag = $4;
|
|
|
|
|
port_declaration_context.range = $5;
|
2004-01-21 04:37:12 +01:00
|
|
|
delete $1;
|
|
|
|
|
delete $6;
|
|
|
|
|
$$ = ptmp;
|
|
|
|
|
}
|
|
|
|
|
| attribute_list_opt
|
|
|
|
|
K_output var_type signed_opt range_opt IDENTIFIER '=' expression
|
|
|
|
|
{ Module::port_t*ptmp;
|
|
|
|
|
ptmp = pform_module_port_reference($6, @2.text,
|
|
|
|
|
@2.first_line);
|
|
|
|
|
pform_module_define_port(@2, $6, NetNet::POUTPUT,
|
|
|
|
|
$3, $4, $5, $1);
|
|
|
|
|
port_declaration_context.port_type = NetNet::POUTPUT;
|
|
|
|
|
port_declaration_context.port_net_type = $3;
|
|
|
|
|
port_declaration_context.sign_flag = $4;
|
|
|
|
|
port_declaration_context.range = $5;
|
|
|
|
|
|
|
|
|
|
if (! pform_expression_is_constant($8))
|
|
|
|
|
yyerror(@8, "error: register declaration assignment"
|
|
|
|
|
" value must be a constant expression.");
|
|
|
|
|
pform_make_reginit(@6, $6, $8);
|
|
|
|
|
|
2003-07-04 05:57:18 +02:00
|
|
|
delete $1;
|
|
|
|
|
delete $6;
|
2002-05-20 01:37:28 +02:00
|
|
|
$$ = ptmp;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
2003-02-08 00:16:09 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
net_type_opt
|
|
|
|
|
: net_type { $$ = $1; }
|
|
|
|
|
| { $$ = NetNet::IMPLICIT; }
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-20 04:06:01 +02:00
|
|
|
signed_opt : K_signed { $$ = true; } | {$$ = false; } ;
|
2002-05-20 01:37:28 +02:00
|
|
|
|
1999-05-07 06:26:49 +02:00
|
|
|
/* An lpvalue is the expression that can go on the left side of a
|
2006-02-02 03:43:57 +01:00
|
|
|
procedural assignment. This rule handles only procedural
|
|
|
|
|
assignments. It is more limited then the general expr_primary
|
|
|
|
|
rule to reflect the rules for assignment l-values. */
|
1999-05-07 06:26:49 +02:00
|
|
|
lpvalue
|
2008-01-25 22:34:51 +01:00
|
|
|
: hierarchy_identifier
|
2007-05-24 06:07:11 +02:00
|
|
|
{ PEIdent*tmp = new PEIdent(*$1);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2007-05-24 06:07:11 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
delete $1;
|
|
|
|
|
}
|
|
|
|
|
| '{' expression_list_proper '}'
|
|
|
|
|
{ PEConcat*tmp = new PEConcat(*$2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2007-05-24 06:07:11 +02:00
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2007-04-21 06:45:36 +02:00
|
|
|
|
|
|
|
|
/* Continuous assignments have a list of individual assignments. */
|
|
|
|
|
|
|
|
|
|
cont_assign
|
2006-02-02 03:43:57 +01:00
|
|
|
: lpvalue '=' expression
|
1999-08-27 17:08:37 +02:00
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(2);
|
|
|
|
|
(*tmp)[0] = $1;
|
|
|
|
|
(*tmp)[1] = $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2007-04-21 06:45:36 +02:00
|
|
|
cont_assign_list
|
|
|
|
|
: cont_assign_list ',' cont_assign
|
1999-08-27 17:08:37 +02:00
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, *$3);
|
|
|
|
|
delete $1;
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-21 06:45:36 +02:00
|
|
|
| cont_assign
|
1999-08-27 17:08:37 +02:00
|
|
|
{ $$ = $1; }
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-20 01:37:28 +02:00
|
|
|
|
|
|
|
|
/* This is the global structure of a module. A module in a start
|
2002-06-11 05:34:33 +02:00
|
|
|
section, with optional ports, then an optional list of module
|
2002-05-20 01:37:28 +02:00
|
|
|
items, and finally an end marker. */
|
|
|
|
|
|
2003-06-19 20:54:49 +02:00
|
|
|
module : attribute_list_opt module_start IDENTIFIER
|
2003-06-20 02:53:19 +02:00
|
|
|
{ pform_startmodule($3, @2.text, @2.first_line, $1); }
|
2003-12-19 06:15:04 +01:00
|
|
|
module_parameter_port_list_opt
|
2004-01-21 04:37:12 +01:00
|
|
|
module_port_list_opt ';'
|
2003-12-19 06:15:04 +01:00
|
|
|
{ pform_module_set_ports($6); }
|
2002-05-20 01:37:28 +02:00
|
|
|
module_item_list_opt
|
1999-06-16 05:13:29 +02:00
|
|
|
K_endmodule
|
2003-06-19 20:54:49 +02:00
|
|
|
{ pform_endmodule($3);
|
|
|
|
|
delete $3;
|
1999-06-16 05:13:29 +02:00
|
|
|
}
|
2002-05-20 01:37:28 +02:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
2001-06-23 02:31:06 +02:00
|
|
|
module_start : K_module | K_macromodule ;
|
|
|
|
|
|
2004-01-21 04:37:12 +01:00
|
|
|
module_port_list_opt
|
|
|
|
|
: '(' list_of_ports ')' { $$ = $2; }
|
|
|
|
|
| '(' list_of_port_declarations ')' { $$ = $2; }
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
2003-12-19 06:15:04 +01:00
|
|
|
/* Module declarations include optional ANSII style module parameter
|
|
|
|
|
ports. These are simply advance ways to declare parameters, so
|
|
|
|
|
that the port declarations may use them. */
|
|
|
|
|
module_parameter_port_list_opt
|
|
|
|
|
:
|
|
|
|
|
| '#' '(' module_parameter_port_list ')'
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
module_parameter_port_list
|
|
|
|
|
: K_parameter parameter_assign
|
|
|
|
|
| module_parameter_port_list ',' parameter_assign
|
|
|
|
|
| module_parameter_port_list ',' K_parameter parameter_assign
|
|
|
|
|
;
|
2001-11-29 18:37:51 +01:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
module_item
|
2005-07-07 18:22:49 +02:00
|
|
|
|
|
|
|
|
/* This rule detects net declarations that possibly include a
|
|
|
|
|
primitive type, an optional vector range and signed flag. This
|
|
|
|
|
also includes an optional delay set. The values are then applied
|
|
|
|
|
to a list of names. If the primitive type is not specified, then
|
|
|
|
|
resort to the default type LOGIC. */
|
|
|
|
|
|
|
|
|
|
: attribute_list_opt net_type
|
|
|
|
|
primitive_type_opt signed_opt range_opt
|
|
|
|
|
delay3_opt
|
2007-01-16 06:44:14 +01:00
|
|
|
net_variable_list ';'
|
2005-07-07 18:22:49 +02:00
|
|
|
|
|
|
|
|
{ ivl_variable_type_t dtype = $3;
|
|
|
|
|
if (dtype == IVL_VT_NO_TYPE)
|
|
|
|
|
dtype = IVL_VT_LOGIC;
|
|
|
|
|
pform_makewire(@2, $5, $4, $7, $2,
|
|
|
|
|
NetNet::NOT_A_PORT, dtype, $1);
|
|
|
|
|
if ($6 != 0) {
|
|
|
|
|
yyerror(@6, "sorry: net delays not supported.");
|
|
|
|
|
delete $6;
|
2002-05-24 06:36:23 +02:00
|
|
|
}
|
|
|
|
|
if ($1) delete $1;
|
|
|
|
|
}
|
2005-07-07 18:22:49 +02:00
|
|
|
|
|
|
|
|
/* Very similar to the rule above, but this takes a list of
|
|
|
|
|
net_decl_assigns, which are <name> = <expr> assignment
|
|
|
|
|
declarations. */
|
|
|
|
|
|
|
|
|
|
| attribute_list_opt net_type
|
|
|
|
|
primitive_type_opt signed_opt range_opt
|
|
|
|
|
delay3_opt net_decl_assigns ';'
|
|
|
|
|
|
|
|
|
|
{ ivl_variable_type_t dtype = $3;
|
|
|
|
|
if (dtype == IVL_VT_NO_TYPE)
|
|
|
|
|
dtype = IVL_VT_LOGIC;
|
|
|
|
|
pform_makewire(@2, $5, $4, $6,
|
|
|
|
|
str_strength, $7, $2, dtype);
|
2002-05-24 06:36:23 +02:00
|
|
|
if ($1) {
|
2005-07-07 18:22:49 +02:00
|
|
|
yyerror(@2, "sorry: Attributes not supported "
|
2002-05-24 06:36:23 +02:00
|
|
|
"on net declaration assignments.");
|
|
|
|
|
delete $1;
|
2001-11-29 18:37:51 +01:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2005-07-07 18:22:49 +02:00
|
|
|
|
|
|
|
|
/* This form doesn't have the range, but does have strengths. This
|
|
|
|
|
gives strength to the assignment drivers. */
|
|
|
|
|
|
|
|
|
|
| attribute_list_opt net_type
|
|
|
|
|
primitive_type_opt signed_opt
|
|
|
|
|
drive_strength net_decl_assigns ';'
|
|
|
|
|
|
|
|
|
|
{ ivl_variable_type_t dtype = $3;
|
|
|
|
|
if (dtype == IVL_VT_NO_TYPE)
|
|
|
|
|
dtype = IVL_VT_LOGIC;
|
|
|
|
|
pform_makewire(@2, 0, $4, 0, $5, $6, $2, dtype);
|
2002-05-24 06:36:23 +02:00
|
|
|
if ($1) {
|
2005-07-07 18:22:49 +02:00
|
|
|
yyerror(@2, "sorry: Attributes not supported "
|
2002-05-24 06:36:23 +02:00
|
|
|
"on net declaration assignments.");
|
|
|
|
|
delete $1;
|
|
|
|
|
}
|
2000-05-08 07:30:19 +02:00
|
|
|
}
|
2005-07-07 18:22:49 +02:00
|
|
|
|
|
|
|
|
| K_trireg charge_strength_opt range_opt delay3_opt list_of_identifiers ';'
|
1999-09-29 23:16:32 +02:00
|
|
|
{ yyerror(@1, "sorry: trireg nets not supported.");
|
2005-07-07 18:22:49 +02:00
|
|
|
delete $3;
|
|
|
|
|
delete $4;
|
1999-06-15 04:50:02 +02:00
|
|
|
}
|
2000-05-08 07:30:19 +02:00
|
|
|
|
2005-07-07 18:22:49 +02:00
|
|
|
| port_type signed_opt range_opt delay3_opt list_of_identifiers ';'
|
|
|
|
|
{ pform_set_port_type(@1, $5, $3, $2, $1);
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2003-04-28 19:50:57 +02:00
|
|
|
|
|
|
|
|
/* The next two rules handle Verilog 2001 statements of the form:
|
|
|
|
|
input wire signed [h:l] <list>;
|
|
|
|
|
This creates the wire and sets the port type all at once. */
|
|
|
|
|
|
|
|
|
|
| port_type net_type signed_opt range_opt list_of_identifiers ';'
|
2007-08-22 04:52:42 +02:00
|
|
|
{ pform_makewire(@1, $4, $3, $5, $2, $1, IVL_VT_NO_TYPE, 0,
|
|
|
|
|
SR_BOTH);
|
2003-04-28 19:50:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| K_output var_type signed_opt range_opt list_of_identifiers ';'
|
2007-08-22 04:52:42 +02:00
|
|
|
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::POUTPUT,
|
|
|
|
|
IVL_VT_NO_TYPE, 0, SR_BOTH);
|
2003-04-28 19:50:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* var_type declaration (reg variables) cannot be input or output,
|
|
|
|
|
because the port declaration implies an external driver, which
|
|
|
|
|
cannot be attached to a reg. These rules catch that error early. */
|
|
|
|
|
|
|
|
|
|
| K_input var_type signed_opt range_opt list_of_identifiers ';'
|
2005-07-07 18:22:49 +02:00
|
|
|
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::PINPUT,
|
|
|
|
|
IVL_VT_NO_TYPE, 0);
|
2003-04-28 19:50:57 +02:00
|
|
|
yyerror(@2, "error: reg variables cannot be inputs.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| K_inout var_type signed_opt range_opt list_of_identifiers ';'
|
2005-07-07 18:22:49 +02:00
|
|
|
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::PINOUT,
|
|
|
|
|
IVL_VT_NO_TYPE, 0);
|
2003-04-28 19:50:57 +02:00
|
|
|
yyerror(@2, "error: reg variables cannot be inouts.");
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-07 18:22:49 +02:00
|
|
|
| port_type signed_opt range_opt delay3_opt error ';'
|
2006-03-30 07:22:34 +02:00
|
|
|
{ yyerror(@1, "error: Invalid variable list"
|
2000-09-13 18:32:26 +02:00
|
|
|
" in port declaration.");
|
2005-07-07 18:22:49 +02:00
|
|
|
if ($3) delete $3;
|
|
|
|
|
if ($4) delete $4;
|
2000-09-13 18:32:26 +02:00
|
|
|
yyerrok;
|
|
|
|
|
}
|
2003-04-28 19:50:57 +02:00
|
|
|
|
|
|
|
|
/* block_item_decl rule is shared with task blocks and named
|
|
|
|
|
begin/end. */
|
|
|
|
|
|
1999-09-10 07:02:09 +02:00
|
|
|
| block_item_decl
|
2003-04-28 19:50:57 +02:00
|
|
|
|
|
|
|
|
/* */
|
|
|
|
|
|
1999-06-16 05:13:29 +02:00
|
|
|
| K_defparam defparam_assign_list ';'
|
2002-05-20 01:37:28 +02:00
|
|
|
| K_event list_of_identifiers ';'
|
2000-04-01 21:31:57 +02:00
|
|
|
{ pform_make_events($2, @1.text, @1.first_line);
|
1999-06-16 05:13:29 +02:00
|
|
|
}
|
2000-05-08 07:30:19 +02:00
|
|
|
|
|
|
|
|
/* Most gate types have an optional drive strength and optional
|
|
|
|
|
three-value delay. These rules handle the different cases. */
|
|
|
|
|
|
2002-05-23 05:08:50 +02:00
|
|
|
| attribute_list_opt gatetype gate_instance_list ';'
|
|
|
|
|
{ pform_makegates($2, str_strength, 0, $3, $1);
|
2000-05-08 07:30:19 +02:00
|
|
|
}
|
|
|
|
|
|
2002-05-23 05:08:50 +02:00
|
|
|
| attribute_list_opt gatetype delay3 gate_instance_list ';'
|
|
|
|
|
{ pform_makegates($2, str_strength, $3, $4, $1);
|
2000-05-08 07:30:19 +02:00
|
|
|
}
|
|
|
|
|
|
2002-05-23 05:08:50 +02:00
|
|
|
| attribute_list_opt gatetype drive_strength gate_instance_list ';'
|
|
|
|
|
{ pform_makegates($2, $3, 0, $4, $1);
|
2000-05-08 07:30:19 +02:00
|
|
|
}
|
|
|
|
|
|
2002-05-23 05:08:50 +02:00
|
|
|
| attribute_list_opt gatetype drive_strength delay3 gate_instance_list ';'
|
|
|
|
|
{ pform_makegates($2, $3, $4, $5, $1);
|
2000-05-08 07:30:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Pullup and pulldown devices cannot have delays, and their
|
|
|
|
|
strengths are limited. */
|
|
|
|
|
|
|
|
|
|
| K_pullup gate_instance_list ';'
|
2002-05-23 05:08:50 +02:00
|
|
|
{ pform_makegates(PGBuiltin::PULLUP, pull_strength, 0,
|
|
|
|
|
$2, 0);
|
2000-05-08 07:30:19 +02:00
|
|
|
}
|
|
|
|
|
| K_pulldown gate_instance_list ';'
|
2002-05-23 05:08:50 +02:00
|
|
|
{ pform_makegates(PGBuiltin::PULLDOWN, pull_strength,
|
|
|
|
|
0, $2, 0);
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2000-05-08 07:30:19 +02:00
|
|
|
|
2001-04-29 00:56:15 +02:00
|
|
|
| K_pullup '(' dr_strength1 ')' gate_instance_list ';'
|
2002-05-23 05:08:50 +02:00
|
|
|
{ pform_makegates(PGBuiltin::PULLUP, $3, 0, $5, 0);
|
2001-04-29 00:56:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| K_pulldown '(' dr_strength0 ')' gate_instance_list ';'
|
2002-05-23 05:08:50 +02:00
|
|
|
{ pform_makegates(PGBuiltin::PULLDOWN, $3, 0, $5, 0);
|
2001-04-29 00:56:15 +02:00
|
|
|
}
|
|
|
|
|
|
2000-05-08 07:30:19 +02:00
|
|
|
/* This rule handles instantiations of modules and user defined
|
|
|
|
|
primitives. These devices to not have delay lists or strengths,
|
|
|
|
|
but then can have parameter lists. */
|
|
|
|
|
|
2006-03-25 03:42:58 +01:00
|
|
|
| attribute_list_opt
|
|
|
|
|
IDENTIFIER parameter_value_opt gate_instance_list ';'
|
|
|
|
|
{ perm_string tmp1 = lex_strings.make($2);
|
|
|
|
|
pform_make_modgates(tmp1, $3, $4);
|
|
|
|
|
delete $2;
|
|
|
|
|
if ($1) delete $1;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2000-05-08 07:30:19 +02:00
|
|
|
|
2006-03-25 03:42:58 +01:00
|
|
|
| attribute_list_opt
|
|
|
|
|
IDENTIFIER parameter_value_opt error ';'
|
|
|
|
|
{ yyerror(@2, "error: Invalid module instantiation");
|
|
|
|
|
if ($1) delete $1;
|
2004-09-05 20:09:47 +02:00
|
|
|
}
|
|
|
|
|
|
2000-05-08 07:30:19 +02:00
|
|
|
/* Continuous assignment can have an optional drive strength, then
|
|
|
|
|
an optional delay3 that applies to all the assignments in the
|
2007-04-21 06:45:36 +02:00
|
|
|
cont_assign_list. */
|
2000-05-08 07:30:19 +02:00
|
|
|
|
2007-04-21 06:45:36 +02:00
|
|
|
| K_assign drive_strength_opt delay3_opt cont_assign_list ';'
|
2000-05-06 17:41:56 +02:00
|
|
|
{ pform_make_pgassign_list($4, $3, $2, @1.text, @1.first_line); }
|
2002-05-26 03:39:02 +02:00
|
|
|
|
|
|
|
|
/* Always and initial items are behavioral processes. */
|
|
|
|
|
|
|
|
|
|
| attribute_list_opt K_always statement
|
|
|
|
|
{ PProcess*tmp = pform_make_behavior(PProcess::PR_ALWAYS,
|
|
|
|
|
$3, $1);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2002-05-26 03:39:02 +02:00
|
|
|
| attribute_list_opt K_initial statement
|
|
|
|
|
{ PProcess*tmp = pform_make_behavior(PProcess::PR_INITIAL,
|
|
|
|
|
$3, $1);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @2);
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2000-05-08 07:30:19 +02:00
|
|
|
|
|
|
|
|
/* The task declaration rule matches the task declaration
|
|
|
|
|
header, then pushes the function scope. This causes the
|
|
|
|
|
definitions in the task_body to take on the scope of the task
|
2007-04-02 01:02:03 +02:00
|
|
|
instead of the module. Note that these runs accept for the task
|
|
|
|
|
body statement_or_null, although the standard does not allow null
|
|
|
|
|
statements in the task body. But we continue to accept it as an
|
|
|
|
|
extension. */
|
2000-05-08 07:30:19 +02:00
|
|
|
|
1999-07-03 04:12:51 +02:00
|
|
|
| K_task IDENTIFIER ';'
|
1999-07-10 03:03:18 +02:00
|
|
|
{ pform_push_scope($2); }
|
2006-05-11 05:26:57 +02:00
|
|
|
task_item_list_opt
|
2007-04-02 01:02:03 +02:00
|
|
|
statement_or_null
|
1999-07-03 04:12:51 +02:00
|
|
|
K_endtask
|
2001-01-13 23:20:08 +01:00
|
|
|
{ PTask*tmp = new PTask;
|
2004-02-18 18:11:54 +01:00
|
|
|
perm_string tmp2 = lex_strings.make($2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2001-01-13 23:20:08 +01:00
|
|
|
tmp->set_ports($5);
|
|
|
|
|
tmp->set_statement($6);
|
2004-02-18 18:11:54 +01:00
|
|
|
pform_set_task(tmp2, tmp);
|
2001-01-13 23:20:08 +01:00
|
|
|
pform_pop_scope();
|
1999-07-03 04:12:51 +02:00
|
|
|
delete $2;
|
1999-05-08 22:19:20 +02:00
|
|
|
}
|
2000-05-08 07:30:19 +02:00
|
|
|
|
2006-05-11 05:26:57 +02:00
|
|
|
| K_task IDENTIFIER
|
|
|
|
|
{ pform_push_scope($2); }
|
|
|
|
|
'(' task_port_decl_list ')' ';'
|
|
|
|
|
task_item_list_opt
|
2007-04-02 01:02:03 +02:00
|
|
|
statement_or_null
|
2006-05-11 05:26:57 +02:00
|
|
|
K_endtask
|
|
|
|
|
{ PTask*tmp = new PTask;
|
|
|
|
|
perm_string tmp2 = lex_strings.make($2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2006-05-11 05:26:57 +02:00
|
|
|
tmp->set_ports($5);
|
|
|
|
|
tmp->set_statement($9);
|
|
|
|
|
pform_set_task(tmp2, tmp);
|
|
|
|
|
pform_pop_scope();
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-08 07:30:19 +02:00
|
|
|
/* The function declaration rule matches the function declaration
|
|
|
|
|
header, then pushes the function scope. This causes the
|
|
|
|
|
definitions in the func_body to take on the scope of the function
|
|
|
|
|
instead of the module. */
|
|
|
|
|
|
2004-06-01 01:34:36 +02:00
|
|
|
| K_function function_range_or_type_opt IDENTIFIER ';'
|
1999-07-31 21:14:47 +02:00
|
|
|
{ pform_push_scope($3); }
|
2001-01-13 23:20:08 +01:00
|
|
|
function_item_list statement
|
1999-07-31 21:14:47 +02:00
|
|
|
K_endfunction
|
2004-06-01 01:34:36 +02:00
|
|
|
{ perm_string name = lex_strings.make($3);
|
|
|
|
|
PFunction *tmp = new PFunction(name);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2001-01-13 23:20:08 +01:00
|
|
|
tmp->set_ports($6);
|
|
|
|
|
tmp->set_statement($7);
|
2004-06-01 01:34:36 +02:00
|
|
|
tmp->set_return($2);
|
|
|
|
|
pform_set_function(name, tmp);
|
2001-01-13 23:20:08 +01:00
|
|
|
pform_pop_scope();
|
1999-07-31 21:14:47 +02:00
|
|
|
delete $3;
|
1999-05-20 06:31:45 +02:00
|
|
|
}
|
2000-05-08 07:30:19 +02:00
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
/* A generate region can contain further module items. Actually, it
|
|
|
|
|
is supposed to be limited to certain kinds of module items, but
|
|
|
|
|
the semantic tests will check that for us. */
|
|
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
| K_generate module_item_list_opt K_endgenerate
|
2006-04-10 02:37:42 +02:00
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
| K_genvar list_of_identifiers ';'
|
|
|
|
|
{ pform_genvars($2); }
|
2006-04-10 02:37:42 +02:00
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
| K_for '(' IDENTIFIER '=' expression ';'
|
|
|
|
|
expression ';'
|
|
|
|
|
IDENTIFIER '=' expression ')'
|
|
|
|
|
{ pform_start_generate_for(@1, $3, $5, $7, $9, $11); }
|
|
|
|
|
generate_block
|
|
|
|
|
{ pform_endgenerate(); }
|
2006-04-10 02:37:42 +02:00
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
| generate_if
|
|
|
|
|
generate_block_opt
|
|
|
|
|
K_else
|
|
|
|
|
{ pform_start_generate_else(@1); }
|
|
|
|
|
generate_block
|
|
|
|
|
{ pform_endgenerate(); }
|
2006-04-10 02:37:42 +02:00
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
| generate_if
|
|
|
|
|
generate_block_opt %prec less_than_K_else
|
|
|
|
|
{ pform_endgenerate(); }
|
2006-04-10 02:37:42 +02:00
|
|
|
|
2000-05-08 07:30:19 +02:00
|
|
|
/* specify blocks are parsed but ignored. */
|
|
|
|
|
|
2001-07-02 01:44:43 +02:00
|
|
|
| K_specify K_endspecify
|
|
|
|
|
{ /* empty lists are legal syntax. */ }
|
|
|
|
|
|
1999-06-12 05:42:57 +02:00
|
|
|
| K_specify specify_item_list K_endspecify
|
|
|
|
|
{
|
|
|
|
|
}
|
2000-05-08 07:30:19 +02:00
|
|
|
|
2001-07-02 01:44:43 +02:00
|
|
|
| K_specify error K_endspecify
|
|
|
|
|
{ yyerror(@1, "error: syntax error in specify block");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-06 07:31:58 +01:00
|
|
|
/* These rules match various errors that the user can type into
|
|
|
|
|
module items. These rules try to catch them at a point where a
|
|
|
|
|
reasonable error message can be produced. */
|
2001-01-06 03:29:35 +01:00
|
|
|
|
2007-08-17 19:10:28 +02:00
|
|
|
| K_module error ';'
|
2007-12-03 21:31:34 +01:00
|
|
|
{ yyerror(@1, "error: missing endmodule or attempt to "
|
2007-08-17 19:10:28 +02:00
|
|
|
"nest modules.");
|
|
|
|
|
pform_error_nested_modules();
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-29 22:18:34 +02:00
|
|
|
| error ';'
|
2005-07-07 18:22:49 +02:00
|
|
|
{ yyerror(@2, "error: invalid module item.");
|
2001-04-29 22:18:34 +02:00
|
|
|
yyerrok;
|
2001-01-06 03:29:35 +01:00
|
|
|
}
|
|
|
|
|
|
2001-01-06 07:31:58 +01:00
|
|
|
| K_assign error '=' expression ';'
|
|
|
|
|
{ yyerror(@1, "error: syntax error in left side "
|
|
|
|
|
"of continuous assignment.");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| K_assign error ';'
|
|
|
|
|
{ yyerror(@1, "error: syntax error in "
|
|
|
|
|
"continuous assignment");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-13 23:20:08 +01:00
|
|
|
| K_function error K_endfunction
|
|
|
|
|
{ yyerror(@1, "error: I give up on this "
|
|
|
|
|
"function definition.");
|
|
|
|
|
yyerrok;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-11 05:34:33 +02:00
|
|
|
/* These rules are for the Icarus Verilog specific $attribute
|
2000-05-08 07:30:19 +02:00
|
|
|
extensions. Then catch the parameters of the $attribute keyword. */
|
|
|
|
|
|
1998-11-23 01:20:22 +01:00
|
|
|
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')' ';'
|
2004-02-18 18:11:54 +01:00
|
|
|
{ perm_string tmp3 = lex_strings.make($3);
|
2004-02-20 19:53:33 +01:00
|
|
|
perm_string tmp5 = lex_strings.make($5);
|
|
|
|
|
pform_set_attrib(tmp3, tmp5, $7);
|
1998-11-23 01:20:22 +01:00
|
|
|
delete $3;
|
|
|
|
|
delete $5;
|
|
|
|
|
}
|
|
|
|
|
| KK_attribute '(' error ')' ';'
|
2002-06-11 05:34:33 +02:00
|
|
|
{ yyerror(@1, "error: Malformed $attribute parameter list."); }
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
generate_if : K_if '(' expression ')' { pform_start_generate_if(@1, $3); }
|
2000-05-08 07:30:19 +02:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
module_item_list
|
|
|
|
|
: module_item_list module_item
|
|
|
|
|
| module_item
|
|
|
|
|
;
|
|
|
|
|
|
2002-05-20 01:37:28 +02:00
|
|
|
module_item_list_opt
|
|
|
|
|
: module_item_list
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
/* A generate block is the thing within a generate scheme. It may be
|
|
|
|
|
a single module item, an anonymous block of module items, or a
|
|
|
|
|
named module item. In all cases, the meat is in the module items
|
|
|
|
|
inside, and the processing is done by the module_item rules. We
|
|
|
|
|
only need to take note here of the scope name, if any. */
|
|
|
|
|
|
|
|
|
|
generate_block
|
|
|
|
|
: module_item
|
|
|
|
|
| K_begin module_item_list_opt K_end
|
|
|
|
|
| K_begin ':' IDENTIFIER module_item_list_opt K_end
|
|
|
|
|
{ pform_generate_block_name($3); }
|
|
|
|
|
;
|
|
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
generate_block_opt : generate_block | ';' ;
|
2006-04-10 02:37:42 +02:00
|
|
|
|
2000-10-31 18:00:04 +01:00
|
|
|
|
1999-06-02 04:56:29 +02:00
|
|
|
/* A net declaration assignment allows the programmer to combine the
|
|
|
|
|
net declaration and the continuous assignment into a single
|
2000-10-31 18:00:04 +01:00
|
|
|
statement.
|
|
|
|
|
|
|
|
|
|
Note that the continuous assignment statement is generated as a
|
|
|
|
|
side effect, and all I pass up is the name of the l-value. */
|
|
|
|
|
|
1999-06-02 04:56:29 +02:00
|
|
|
net_decl_assign
|
|
|
|
|
: IDENTIFIER '=' expression
|
2001-11-29 18:37:51 +01:00
|
|
|
{ net_decl_assign_t*tmp = new net_decl_assign_t;
|
|
|
|
|
tmp->next = tmp;
|
|
|
|
|
tmp->name = $1;
|
|
|
|
|
tmp->expr = $3;
|
|
|
|
|
$$ = tmp;
|
1999-06-12 05:42:57 +02:00
|
|
|
}
|
1999-06-02 04:56:29 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
net_decl_assigns
|
|
|
|
|
: net_decl_assigns ',' net_decl_assign
|
2001-11-29 18:37:51 +01:00
|
|
|
{ net_decl_assign_t*tmp = $1;
|
|
|
|
|
$3->next = tmp->next;
|
|
|
|
|
tmp->next = $3;
|
1999-06-02 04:56:29 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| net_decl_assign
|
2001-11-29 18:37:51 +01:00
|
|
|
{ $$ = $1;
|
1999-06-02 04:56:29 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2005-07-07 18:22:49 +02:00
|
|
|
primitive_type
|
|
|
|
|
: K_logic { $$ = IVL_VT_LOGIC; }
|
|
|
|
|
| K_bool { $$ = IVL_VT_BOOL; }
|
|
|
|
|
| K_real { $$ = IVL_VT_REAL; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
primitive_type_opt : primitive_type { $$ = $1; } | { $$ = IVL_VT_NO_TYPE; } ;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
net_type
|
|
|
|
|
: K_wire { $$ = NetNet::WIRE; }
|
|
|
|
|
| K_tri { $$ = NetNet::TRI; }
|
|
|
|
|
| K_tri1 { $$ = NetNet::TRI1; }
|
|
|
|
|
| K_supply0 { $$ = NetNet::SUPPLY0; }
|
|
|
|
|
| K_wand { $$ = NetNet::WAND; }
|
|
|
|
|
| K_triand { $$ = NetNet::TRIAND; }
|
|
|
|
|
| K_tri0 { $$ = NetNet::TRI0; }
|
|
|
|
|
| K_supply1 { $$ = NetNet::SUPPLY1; }
|
|
|
|
|
| K_wor { $$ = NetNet::WOR; }
|
|
|
|
|
| K_trior { $$ = NetNet::TRIOR; }
|
2005-07-07 18:22:49 +02:00
|
|
|
| K_wone { $$ = NetNet::WONE; }
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
2002-05-20 01:37:28 +02:00
|
|
|
var_type
|
|
|
|
|
: K_reg { $$ = NetNet::REG; }
|
|
|
|
|
;
|
|
|
|
|
|
2006-03-18 23:53:38 +01:00
|
|
|
/* In this rule we have matched the "parameter" keyword. The rule
|
|
|
|
|
generates a type (optional) and a list of assignments. */
|
1999-02-21 18:01:57 +01:00
|
|
|
|
2002-08-19 04:39:16 +02:00
|
|
|
parameter_assign_decl
|
|
|
|
|
: parameter_assign_list
|
2006-03-18 23:53:38 +01:00
|
|
|
| range { active_range = $1; active_signed = false; }
|
2002-09-01 05:01:48 +02:00
|
|
|
parameter_assign_list
|
2002-08-19 04:39:16 +02:00
|
|
|
{ active_range = 0;
|
2002-09-01 05:01:48 +02:00
|
|
|
active_signed = false;
|
|
|
|
|
}
|
|
|
|
|
| K_signed range { active_range = $2; active_signed = true; }
|
|
|
|
|
parameter_assign_list
|
|
|
|
|
{ active_range = 0;
|
|
|
|
|
active_signed = false;
|
2002-08-19 04:39:16 +02:00
|
|
|
}
|
2006-03-18 23:53:38 +01:00
|
|
|
| K_integer { active_range = 0; active_signed = true; }
|
|
|
|
|
parameter_assign_list
|
|
|
|
|
{ active_range = 0;
|
|
|
|
|
active_signed = false;
|
|
|
|
|
}
|
2002-08-19 04:39:16 +02:00
|
|
|
;
|
|
|
|
|
|
1999-02-21 18:01:57 +01:00
|
|
|
parameter_assign_list
|
|
|
|
|
: parameter_assign
|
|
|
|
|
| parameter_assign_list ',' parameter_assign
|
|
|
|
|
;
|
|
|
|
|
|
2006-03-18 23:53:38 +01:00
|
|
|
parameter_assign
|
|
|
|
|
: IDENTIFIER '=' expression
|
|
|
|
|
{ PExpr*tmp = $3;
|
|
|
|
|
if (!pform_expression_is_constant(tmp)) {
|
|
|
|
|
yyerror(@3, "error: parameter value "
|
|
|
|
|
"must be a constant expression.");
|
|
|
|
|
delete tmp;
|
|
|
|
|
tmp = 0;
|
|
|
|
|
} else {
|
|
|
|
|
pform_set_parameter(lex_strings.make($1),
|
|
|
|
|
active_signed,
|
|
|
|
|
active_range, tmp);
|
|
|
|
|
}
|
|
|
|
|
delete $1;
|
|
|
|
|
}
|
|
|
|
|
;
|
2000-01-02 00:47:58 +01:00
|
|
|
|
2002-06-11 05:34:33 +02:00
|
|
|
/* Localparam assignments and assignment lists are broken into
|
|
|
|
|
separate BNF so that I can call slightly different parameter
|
2000-03-12 18:09:40 +01:00
|
|
|
handling code. They parse the same as parameters, they just
|
|
|
|
|
behave differently when someone tries to override them. */
|
|
|
|
|
|
|
|
|
|
localparam_assign
|
|
|
|
|
: IDENTIFIER '=' expression
|
|
|
|
|
{ PExpr*tmp = $3;
|
|
|
|
|
if (!pform_expression_is_constant(tmp)) {
|
|
|
|
|
yyerror(@3, "error: parameter value "
|
|
|
|
|
"must be constant.");
|
|
|
|
|
delete tmp;
|
|
|
|
|
tmp = 0;
|
2004-08-26 06:02:03 +02:00
|
|
|
} else {
|
|
|
|
|
pform_set_localparam(lex_strings.make($1),
|
|
|
|
|
active_signed,
|
|
|
|
|
active_range, tmp);
|
2000-03-12 18:09:40 +01:00
|
|
|
}
|
|
|
|
|
delete $1;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2004-08-26 06:02:03 +02:00
|
|
|
localparam_assign_decl
|
|
|
|
|
: localparam_assign_list
|
|
|
|
|
| range { active_range = $1; active_signed = false; }
|
|
|
|
|
localparam_assign_list
|
|
|
|
|
{ active_range = 0;
|
|
|
|
|
active_signed = false;
|
|
|
|
|
}
|
|
|
|
|
| K_signed range { active_range = $2; active_signed = true; }
|
|
|
|
|
localparam_assign_list
|
|
|
|
|
{ active_range = 0;
|
|
|
|
|
active_signed = false;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2000-03-12 18:09:40 +01:00
|
|
|
localparam_assign_list
|
|
|
|
|
: localparam_assign
|
|
|
|
|
| localparam_assign_list ',' localparam_assign
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
2004-08-26 06:02:03 +02:00
|
|
|
|
2000-01-02 00:47:58 +01:00
|
|
|
/* The parameters of a module instance can be overridden by writing
|
2002-11-09 03:22:07 +01:00
|
|
|
a list of expressions in a syntax much like a delay list. (The
|
2000-01-02 00:47:58 +01:00
|
|
|
difference being the list can have any length.) The pform that
|
|
|
|
|
attaches the expression list to the module checks that the
|
2000-01-09 06:50:48 +01:00
|
|
|
expressions are constant.
|
|
|
|
|
|
|
|
|
|
Although the BNF in IEEE1364-1995 implies that parameter value
|
|
|
|
|
lists must be in parentheses, in practice most compilers will
|
|
|
|
|
accept simple expressions outside of parentheses if there is only
|
|
|
|
|
one value, so I'll accept simple numbers here.
|
|
|
|
|
|
|
|
|
|
The parameter value by name syntax is OVI enhancement BTF-B06 as
|
|
|
|
|
approved by WG1364 on 6/28/1998. */
|
2000-01-02 00:47:58 +01:00
|
|
|
|
|
|
|
|
parameter_value_opt
|
2007-04-02 01:02:03 +02:00
|
|
|
: '#' '(' expression_list_with_nuls ')'
|
2000-01-09 06:50:48 +01:00
|
|
|
{ struct parmvalue_t*tmp = new struct parmvalue_t;
|
|
|
|
|
tmp->by_order = $3;
|
|
|
|
|
tmp->by_name = 0;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| '#' '(' parameter_value_byname_list ')'
|
|
|
|
|
{ struct parmvalue_t*tmp = new struct parmvalue_t;
|
|
|
|
|
tmp->by_order = 0;
|
|
|
|
|
tmp->by_name = $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2003-04-14 05:37:47 +02:00
|
|
|
| '#' DEC_NUMBER
|
2000-01-09 06:50:48 +01:00
|
|
|
{ assert($2);
|
|
|
|
|
PENumber*tmp = new PENumber($2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2000-01-09 06:50:48 +01:00
|
|
|
|
|
|
|
|
struct parmvalue_t*lst = new struct parmvalue_t;
|
|
|
|
|
lst->by_order = new svector<PExpr*>(1);
|
|
|
|
|
(*lst->by_order)[0] = tmp;
|
|
|
|
|
lst->by_name = 0;
|
|
|
|
|
$$ = lst;
|
|
|
|
|
}
|
2000-01-02 02:59:52 +01:00
|
|
|
| '#' error
|
|
|
|
|
{ yyerror(@1, "error: syntax error in parameter value "
|
|
|
|
|
"assignment list.");
|
|
|
|
|
$$ = 0;
|
|
|
|
|
}
|
2000-01-02 00:47:58 +01:00
|
|
|
|
|
|
|
|
|
{ $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
2000-01-09 06:50:48 +01:00
|
|
|
parameter_value_byname
|
2001-12-03 05:47:14 +01:00
|
|
|
: '.' IDENTIFIER '(' expression ')'
|
2002-05-23 05:08:50 +02:00
|
|
|
{ named_pexpr_t*tmp = new named_pexpr_t;
|
2004-02-20 07:22:56 +01:00
|
|
|
tmp->name = lex_strings.make($2);
|
2001-12-03 05:47:14 +01:00
|
|
|
tmp->parm = $4;
|
|
|
|
|
free($2);
|
2000-01-09 06:50:48 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2001-12-03 05:47:14 +01:00
|
|
|
| '.' IDENTIFIER '(' ')'
|
2002-05-23 05:08:50 +02:00
|
|
|
{ named_pexpr_t*tmp = new named_pexpr_t;
|
2004-02-20 07:22:56 +01:00
|
|
|
tmp->name = lex_strings.make($2);
|
2000-01-09 06:50:48 +01:00
|
|
|
tmp->parm = 0;
|
2001-12-03 05:47:14 +01:00
|
|
|
free($2);
|
2000-01-09 06:50:48 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
parameter_value_byname_list
|
|
|
|
|
: parameter_value_byname
|
2002-05-23 05:08:50 +02:00
|
|
|
{ svector<named_pexpr_t*>*tmp = new svector<named_pexpr_t*>(1);
|
2000-01-09 06:50:48 +01:00
|
|
|
(*tmp)[0] = $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| parameter_value_byname_list ',' parameter_value_byname
|
2002-05-23 05:08:50 +02:00
|
|
|
{ svector<named_pexpr_t*>*tmp =
|
|
|
|
|
new svector<named_pexpr_t*>(*$1,$3);
|
2000-01-09 06:50:48 +01:00
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2000-05-16 06:05:15 +02:00
|
|
|
|
2000-01-09 06:50:48 +01:00
|
|
|
/* The port (of a module) is a fairly complex item. Each port is
|
1999-08-03 06:14:49 +02:00
|
|
|
handled as a Module::port_t object. A simple port reference has a
|
2000-05-16 06:05:15 +02:00
|
|
|
name and a PExpr object, but more complex constructs are possible
|
1999-08-03 06:14:49 +02:00
|
|
|
where the name can be attached to a list of PWire objects.
|
|
|
|
|
|
|
|
|
|
The port_reference returns a Module::port_t, and so does the
|
|
|
|
|
port_reference_list. The port_reference_list may have built up a
|
|
|
|
|
list of PWires in the port_t object, but it is still a single
|
|
|
|
|
Module::port_t object.
|
|
|
|
|
|
|
|
|
|
The port rule below takes the built up Module::port_t object and
|
|
|
|
|
tweaks its name as needed. */
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
port
|
1999-08-03 06:14:49 +02:00
|
|
|
: port_reference
|
|
|
|
|
{ $$ = $1; }
|
2000-05-16 06:05:15 +02:00
|
|
|
|
|
|
|
|
/* This syntax attaches an external name to the port reference so
|
|
|
|
|
that the caller can bind by name to non-trivial port
|
|
|
|
|
references. The port_t object gets its PWire from the
|
2001-12-03 05:47:14 +01:00
|
|
|
port_reference, but its name from the IDENTIFIER. */
|
2000-05-16 06:05:15 +02:00
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
| '.' IDENTIFIER '(' port_reference ')'
|
|
|
|
|
{ Module::port_t*tmp = $4;
|
2004-02-20 07:22:56 +01:00
|
|
|
tmp->name = lex_strings.make($2);
|
2001-12-03 05:47:14 +01:00
|
|
|
delete $2;
|
1999-08-03 06:14:49 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2000-05-16 06:05:15 +02:00
|
|
|
|
|
|
|
|
/* A port can also be a concatenation of port references. In this
|
|
|
|
|
case the port does not have a name available to the outside, only
|
|
|
|
|
positional parameter passing is possible here. */
|
|
|
|
|
|
1999-08-03 06:14:49 +02:00
|
|
|
| '{' port_reference_list '}'
|
|
|
|
|
{ Module::port_t*tmp = $2;
|
2004-02-20 07:22:56 +01:00
|
|
|
tmp->name = perm_string();
|
1999-08-03 06:14:49 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2000-05-16 06:05:15 +02:00
|
|
|
|
2002-06-11 05:34:33 +02:00
|
|
|
/* This attaches a name to a port reference concatenation list so
|
2000-05-16 06:05:15 +02:00
|
|
|
that parameter passing be name is possible. */
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
| '.' IDENTIFIER '(' '{' port_reference_list '}' ')'
|
|
|
|
|
{ Module::port_t*tmp = $5;
|
2004-02-20 07:22:56 +01:00
|
|
|
tmp->name = lex_strings.make($2);
|
2001-12-03 05:47:14 +01:00
|
|
|
delete $2;
|
1999-08-03 06:14:49 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-09-17 04:06:25 +02:00
|
|
|
port_opt
|
|
|
|
|
: port { $$ = $1; }
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
2000-05-16 06:05:15 +02:00
|
|
|
|
|
|
|
|
/* A port reference is an internal (to the module) name of the port,
|
|
|
|
|
possibly with a part of bit select to attach it to specific bits
|
|
|
|
|
of a signal fully declared inside the module.
|
|
|
|
|
|
|
|
|
|
The parser creates a PEIdent for every port reference, even if the
|
|
|
|
|
signal is bound to different ports. The elaboration figures out
|
|
|
|
|
the mess that this creates. The port_reference (and the
|
|
|
|
|
port_reference_list below) puts the port reference PEIdent into the
|
|
|
|
|
port_t object to pass it up to the module declaration code. */
|
|
|
|
|
|
1999-08-03 06:14:49 +02:00
|
|
|
port_reference
|
2000-05-16 06:05:15 +02:00
|
|
|
|
2007-05-24 06:07:11 +02:00
|
|
|
: IDENTIFIER
|
|
|
|
|
{ Module::port_t*ptmp;
|
|
|
|
|
ptmp = pform_module_port_reference($1, @1.text, @1.first_line);
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = ptmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| IDENTIFIER '[' expression ':' expression ']'
|
|
|
|
|
{ if (!pform_expression_is_constant($3)) {
|
|
|
|
|
yyerror(@3, "error: msb expression of "
|
|
|
|
|
"port part select must be constant.");
|
|
|
|
|
}
|
|
|
|
|
if (!pform_expression_is_constant($5)) {
|
|
|
|
|
yyerror(@5, "error: lsb expression of "
|
|
|
|
|
"port part select must be constant.");
|
|
|
|
|
}
|
|
|
|
|
index_component_t itmp;
|
|
|
|
|
itmp.sel = index_component_t::SEL_PART;
|
|
|
|
|
itmp.msb = $3;
|
|
|
|
|
itmp.lsb = $5;
|
|
|
|
|
|
|
|
|
|
name_component_t ntmp (lex_strings.make($1));
|
|
|
|
|
ntmp.index.push_back(itmp);
|
|
|
|
|
|
|
|
|
|
pform_name_t pname;
|
|
|
|
|
pname.push_back(ntmp);
|
|
|
|
|
|
|
|
|
|
PEIdent*wtmp = new PEIdent(pname);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(wtmp, @1);
|
2007-05-24 06:07:11 +02:00
|
|
|
|
|
|
|
|
Module::port_t*ptmp = new Module::port_t;
|
|
|
|
|
ptmp->name = perm_string();
|
|
|
|
|
ptmp->expr = svector<PEIdent*>(1);
|
|
|
|
|
ptmp->expr[0] = wtmp;
|
|
|
|
|
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = ptmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| IDENTIFIER '[' expression ']'
|
|
|
|
|
{ if (!pform_expression_is_constant($3)) {
|
|
|
|
|
yyerror(@3, "error: port bit select "
|
|
|
|
|
"must be constant.");
|
|
|
|
|
}
|
|
|
|
|
index_component_t itmp;
|
|
|
|
|
itmp.sel = index_component_t::SEL_BIT;
|
|
|
|
|
itmp.msb = $3;
|
|
|
|
|
itmp.lsb = 0;
|
|
|
|
|
|
|
|
|
|
name_component_t ntmp (lex_strings.make($1));
|
|
|
|
|
ntmp.index.push_back(itmp);
|
|
|
|
|
|
|
|
|
|
pform_name_t pname;
|
|
|
|
|
pname.push_back(ntmp);
|
|
|
|
|
|
|
|
|
|
PEIdent*tmp = new PEIdent(pname);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2007-05-24 06:07:11 +02:00
|
|
|
|
|
|
|
|
Module::port_t*ptmp = new Module::port_t;
|
|
|
|
|
ptmp->name = perm_string();
|
|
|
|
|
ptmp->expr = svector<PEIdent*>(1);
|
|
|
|
|
ptmp->expr[0] = tmp;
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = ptmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| IDENTIFIER '[' error ']'
|
|
|
|
|
{ yyerror(@1, "error: invalid port bit select");
|
|
|
|
|
Module::port_t*ptmp = new Module::port_t;
|
|
|
|
|
PEIdent*wtmp = new PEIdent(lex_strings.make($1));
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(wtmp, @1);
|
2007-05-24 06:07:11 +02:00
|
|
|
ptmp->name = lex_strings.make($1);
|
|
|
|
|
ptmp->expr = svector<PEIdent*>(1);
|
|
|
|
|
ptmp->expr[0] = wtmp;
|
|
|
|
|
delete $1;
|
|
|
|
|
$$ = ptmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2000-05-16 06:05:15 +02:00
|
|
|
|
1999-08-03 06:14:49 +02:00
|
|
|
port_reference_list
|
|
|
|
|
: port_reference
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
| port_reference_list ',' port_reference
|
|
|
|
|
{ Module::port_t*tmp = $1;
|
2000-05-16 06:05:15 +02:00
|
|
|
tmp->expr = svector<PEIdent*>(tmp->expr, $3->expr);
|
1999-08-03 06:14:49 +02:00
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* The port_name rule is used with a module is being *instantiated*,
|
|
|
|
|
and not when it is being declared. See the port rule if you are
|
|
|
|
|
looking for the ports of a module declaration. */
|
|
|
|
|
|
1999-05-08 22:19:20 +02:00
|
|
|
port_name
|
2001-12-03 05:47:14 +01:00
|
|
|
: '.' IDENTIFIER '(' expression ')'
|
2002-05-23 05:08:50 +02:00
|
|
|
{ named_pexpr_t*tmp = new named_pexpr_t;
|
2004-02-20 07:22:56 +01:00
|
|
|
tmp->name = lex_strings.make($2);
|
2001-12-03 05:47:14 +01:00
|
|
|
tmp->parm = $4;
|
|
|
|
|
delete $2;
|
1999-05-29 04:36:17 +02:00
|
|
|
$$ = tmp;
|
1999-05-08 22:19:20 +02:00
|
|
|
}
|
2001-12-03 05:47:14 +01:00
|
|
|
| '.' IDENTIFIER '(' error ')'
|
2007-12-03 21:31:34 +01:00
|
|
|
{ yyerror(@3, "error: invalid port connection expression.");
|
2002-05-23 05:08:50 +02:00
|
|
|
named_pexpr_t*tmp = new named_pexpr_t;
|
2004-02-20 07:22:56 +01:00
|
|
|
tmp->name = lex_strings.make($2);
|
1999-05-29 04:36:17 +02:00
|
|
|
tmp->parm = 0;
|
2001-12-03 05:47:14 +01:00
|
|
|
delete $2;
|
1999-05-29 04:36:17 +02:00
|
|
|
$$ = tmp;
|
1999-05-16 07:08:42 +02:00
|
|
|
}
|
2001-12-03 05:47:14 +01:00
|
|
|
| '.' IDENTIFIER '(' ')'
|
2002-05-23 05:08:50 +02:00
|
|
|
{ named_pexpr_t*tmp = new named_pexpr_t;
|
2004-02-20 07:22:56 +01:00
|
|
|
tmp->name = lex_strings.make($2);
|
1999-05-29 04:36:17 +02:00
|
|
|
tmp->parm = 0;
|
2001-12-03 05:47:14 +01:00
|
|
|
delete $2;
|
1999-05-29 04:36:17 +02:00
|
|
|
$$ = tmp;
|
1999-05-08 22:19:20 +02:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
port_name_list
|
|
|
|
|
: port_name_list ',' port_name
|
2002-05-23 05:08:50 +02:00
|
|
|
{ svector<named_pexpr_t*>*tmp;
|
|
|
|
|
tmp = new svector<named_pexpr_t*>(*$1, $3);
|
1999-05-29 04:36:17 +02:00
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-05-08 22:19:20 +02:00
|
|
|
| port_name
|
2002-05-23 05:08:50 +02:00
|
|
|
{ svector<named_pexpr_t*>*tmp = new svector<named_pexpr_t*>(1);
|
1999-05-29 04:36:17 +02:00
|
|
|
(*tmp)[0] = $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-05-08 22:19:20 +02:00
|
|
|
;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
port_type
|
|
|
|
|
: K_input { $$ = NetNet::PINPUT; }
|
|
|
|
|
| K_output { $$ = NetNet::POUTPUT; }
|
|
|
|
|
| K_inout { $$ = NetNet::PINOUT; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
range
|
1999-05-16 07:08:42 +02:00
|
|
|
: '[' expression ':' expression ']'
|
1999-05-10 02:16:57 +02:00
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*> (2);
|
1999-06-16 05:13:29 +02:00
|
|
|
if (!pform_expression_is_constant($2))
|
1999-09-29 23:16:32 +02:00
|
|
|
yyerror(@2, "error: msb of range must be constant.");
|
1999-06-16 05:13:29 +02:00
|
|
|
|
|
|
|
|
(*tmp)[0] = $2;
|
|
|
|
|
|
|
|
|
|
if (!pform_expression_is_constant($4))
|
2001-07-29 00:00:27 +02:00
|
|
|
yyerror(@4, "error: lsb of range must be constant.");
|
1999-06-16 05:13:29 +02:00
|
|
|
|
|
|
|
|
(*tmp)[1] = $4;
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
range_opt
|
|
|
|
|
: range
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
2007-11-07 23:18:36 +01:00
|
|
|
dimensions_opt
|
|
|
|
|
: { $$ = 0; }
|
2007-11-14 05:49:05 +01:00
|
|
|
| dimensions { $$ = $1; }
|
|
|
|
|
|
|
|
|
|
dimensions
|
|
|
|
|
: '[' expression ':' expression ']'
|
2007-11-07 23:18:36 +01:00
|
|
|
{ list<index_component_t> *tmp = new list<index_component_t>;
|
|
|
|
|
index_component_t index;
|
|
|
|
|
if (!pform_expression_is_constant($2))
|
|
|
|
|
yyerror(@2, "error: left array address must be "
|
|
|
|
|
"constant.");
|
|
|
|
|
index.msb = $2;
|
|
|
|
|
if (!pform_expression_is_constant($4))
|
|
|
|
|
yyerror(@4, "error: right array address must be "
|
|
|
|
|
"constant.");
|
|
|
|
|
index.lsb = $4;
|
|
|
|
|
tmp->push_back(index);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-11-14 05:49:05 +01:00
|
|
|
| dimensions '[' expression ':' expression ']'
|
2007-11-07 23:18:36 +01:00
|
|
|
{ list<index_component_t> *tmp = $1;
|
|
|
|
|
index_component_t index;
|
|
|
|
|
if (!pform_expression_is_constant($3))
|
|
|
|
|
yyerror(@3, "error: left array address must be "
|
|
|
|
|
"constant.");
|
|
|
|
|
index.msb = $3;
|
|
|
|
|
if (!pform_expression_is_constant($5))
|
|
|
|
|
yyerror(@5, "error: right array address must be "
|
|
|
|
|
"constant.");
|
|
|
|
|
index.lsb = $5;
|
|
|
|
|
tmp->push_back(index);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2001-12-07 06:03:13 +01:00
|
|
|
/* This is used to express the return type of a function. */
|
2004-06-01 01:34:36 +02:00
|
|
|
function_range_or_type_opt
|
2007-03-06 06:22:49 +01:00
|
|
|
: range { $$.range = $1; $$.type = PTF_REG; }
|
|
|
|
|
| K_signed range { $$.range = $2; $$.type = PTF_REG_S; }
|
2004-06-01 01:34:36 +02:00
|
|
|
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
|
|
|
|
|
| K_real { $$.range = 0; $$.type = PTF_REAL; }
|
|
|
|
|
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
|
|
|
|
|
| K_time { $$.range = 0; $$.type = PTF_TIME; }
|
|
|
|
|
| { $$.range = 0; $$.type = PTF_REG; }
|
1999-05-20 06:31:45 +02:00
|
|
|
;
|
2000-12-05 23:32:05 +01:00
|
|
|
|
1999-04-19 03:59:36 +02:00
|
|
|
/* The register_variable rule is matched only when I am parsing
|
|
|
|
|
variables in a "reg" definition. I therefore know that I am
|
|
|
|
|
creating registers and I do not need to let the containing rule
|
|
|
|
|
handle it. The register variable list simply packs them together
|
|
|
|
|
so that bit ranges can be assigned. */
|
1998-11-04 00:28:49 +01:00
|
|
|
register_variable
|
2007-11-07 23:18:36 +01:00
|
|
|
: IDENTIFIER dimensions_opt
|
2003-04-28 19:50:57 +02:00
|
|
|
{ pform_makewire(@1, $1, NetNet::REG,
|
2007-11-07 23:18:36 +01:00
|
|
|
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
|
|
|
|
if ($2 != 0) {
|
|
|
|
|
index_component_t index;
|
|
|
|
|
if ($2->size() > 1) {
|
|
|
|
|
yyerror(@2, "sorry: only 1 dimensional arrays "
|
|
|
|
|
"are currently supported.");
|
|
|
|
|
}
|
|
|
|
|
index = $2->front();
|
|
|
|
|
pform_set_reg_idx($1, index.msb, index.lsb);
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = $1;
|
|
|
|
|
}
|
1999-06-12 22:35:27 +02:00
|
|
|
| IDENTIFIER '=' expression
|
2003-04-28 19:50:57 +02:00
|
|
|
{ pform_makewire(@1, $1, NetNet::REG,
|
2005-07-07 18:22:49 +02:00
|
|
|
NetNet::NOT_A_PORT,
|
|
|
|
|
IVL_VT_NO_TYPE, 0);
|
1999-12-30 20:06:14 +01:00
|
|
|
if (! pform_expression_is_constant($3))
|
|
|
|
|
yyerror(@3, "error: register declaration assignment"
|
|
|
|
|
" value must be a constant expression.");
|
|
|
|
|
pform_make_reginit(@1, $1, $3);
|
1999-06-12 22:35:27 +02:00
|
|
|
$$ = $1;
|
|
|
|
|
}
|
1999-04-19 03:59:36 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
register_variable_list
|
|
|
|
|
: register_variable
|
2004-05-25 21:21:06 +02:00
|
|
|
{ list<perm_string>*tmp = new list<perm_string>;
|
|
|
|
|
tmp->push_back(lex_strings.make($1));
|
1999-04-19 03:59:36 +02:00
|
|
|
$$ = tmp;
|
2004-05-25 21:21:06 +02:00
|
|
|
delete[]$1;
|
1999-04-19 03:59:36 +02:00
|
|
|
}
|
|
|
|
|
| register_variable_list ',' register_variable
|
2004-05-25 21:21:06 +02:00
|
|
|
{ list<perm_string>*tmp = $1;
|
|
|
|
|
tmp->push_back(lex_strings.make($3));
|
1999-04-19 03:59:36 +02:00
|
|
|
$$ = tmp;
|
2004-05-25 21:21:06 +02:00
|
|
|
delete[]$3;
|
1999-04-19 03:59:36 +02:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
;
|
|
|
|
|
|
2007-08-05 06:50:06 +02:00
|
|
|
real_variable
|
2007-11-07 23:18:36 +01:00
|
|
|
: IDENTIFIER dimensions_opt
|
2007-08-05 06:50:06 +02:00
|
|
|
{ pform_makewire(@1, $1, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
2007-11-07 23:18:36 +01:00
|
|
|
if ($2 != 0) {
|
|
|
|
|
yyerror(@2, "sorry: real variables do not currently support arrays.");
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
2007-08-05 06:50:06 +02:00
|
|
|
$$ = $1;
|
|
|
|
|
}
|
|
|
|
|
| IDENTIFIER '=' expression
|
|
|
|
|
{ pform_makewire(@1, $1, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
|
|
|
|
pform_make_reginit(@1, $1, $3);
|
|
|
|
|
$$ = $1;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
real_variable_list
|
|
|
|
|
: real_variable
|
|
|
|
|
{ list<perm_string>*tmp = new list<perm_string>;
|
|
|
|
|
tmp->push_back(lex_strings.make($1));
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
delete[]$1;
|
|
|
|
|
}
|
|
|
|
|
| real_variable_list ',' real_variable
|
|
|
|
|
{ list<perm_string>*tmp = $1;
|
|
|
|
|
tmp->push_back(lex_strings.make($3));
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
delete[]$3;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
net_variable
|
2007-11-07 23:18:36 +01:00
|
|
|
: IDENTIFIER dimensions_opt
|
2007-01-16 06:44:14 +01:00
|
|
|
{ pform_makewire(@1, $1, NetNet::IMPLICIT,
|
2007-11-07 23:18:36 +01:00
|
|
|
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
|
|
|
|
if ($2 != 0) {
|
|
|
|
|
index_component_t index;
|
|
|
|
|
if ($2->size() > 1) {
|
|
|
|
|
yyerror(@2, "sorry: only 1 dimensional arrays "
|
|
|
|
|
"are currently supported.");
|
|
|
|
|
}
|
|
|
|
|
index = $2->front();
|
|
|
|
|
pform_set_reg_idx($1, index.msb, index.lsb);
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
2007-01-16 06:44:14 +01:00
|
|
|
$$ = $1;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
net_variable_list
|
|
|
|
|
: net_variable
|
|
|
|
|
{ list<perm_string>*tmp = new list<perm_string>;
|
|
|
|
|
tmp->push_back(lex_strings.make($1));
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
delete[]$1;
|
|
|
|
|
}
|
|
|
|
|
| net_variable_list ',' net_variable
|
|
|
|
|
{ list<perm_string>*tmp = $1;
|
|
|
|
|
tmp->push_back(lex_strings.make($3));
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
delete[]$3;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1999-06-12 05:42:57 +02:00
|
|
|
specify_item
|
|
|
|
|
: K_specparam specparam_list ';'
|
2001-07-02 01:44:43 +02:00
|
|
|
| specify_simple_path_decl ';'
|
2006-09-23 06:57:19 +02:00
|
|
|
{ pform_module_specify_path($1);
|
2001-07-02 01:44:43 +02:00
|
|
|
}
|
|
|
|
|
| specify_edge_path_decl ';'
|
2007-02-12 02:52:21 +01:00
|
|
|
{ pform_module_specify_path($1);
|
2000-09-23 05:04:10 +02:00
|
|
|
}
|
2001-07-02 01:44:43 +02:00
|
|
|
| K_if '(' expression ')' specify_simple_path_decl ';'
|
2007-02-12 02:52:21 +01:00
|
|
|
{ PSpecPath*tmp = $5;
|
2007-03-01 07:19:38 +01:00
|
|
|
if (tmp) {
|
|
|
|
|
tmp->conditional = true;
|
|
|
|
|
tmp->condition = $3;
|
|
|
|
|
}
|
2007-02-12 02:52:21 +01:00
|
|
|
pform_module_specify_path(tmp);
|
1999-06-19 05:21:21 +02:00
|
|
|
}
|
2001-07-02 01:44:43 +02:00
|
|
|
| K_if '(' expression ')' specify_edge_path_decl ';'
|
2007-02-12 02:52:21 +01:00
|
|
|
{ PSpecPath*tmp = $5;
|
|
|
|
|
if (tmp) {
|
|
|
|
|
tmp->conditional = true;
|
|
|
|
|
tmp->condition = $3;
|
|
|
|
|
}
|
|
|
|
|
pform_module_specify_path(tmp);
|
2001-07-02 01:44:43 +02:00
|
|
|
}
|
2006-04-17 06:35:49 +02:00
|
|
|
| K_ifnone specify_simple_path_decl ';'
|
2007-02-12 02:52:21 +01:00
|
|
|
{ PSpecPath*tmp = $2;
|
|
|
|
|
if (tmp) {
|
|
|
|
|
tmp->conditional = true;
|
|
|
|
|
tmp->condition = 0;
|
|
|
|
|
}
|
|
|
|
|
pform_module_specify_path(tmp);
|
2006-04-17 06:35:49 +02:00
|
|
|
}
|
2001-07-02 01:44:43 +02:00
|
|
|
| K_Shold '(' spec_reference_event ',' spec_reference_event
|
2005-07-27 16:54:51 +02:00
|
|
|
',' delay_value spec_notifier_opt ')' ';'
|
2001-07-02 01:44:43 +02:00
|
|
|
{ delete $7;
|
|
|
|
|
}
|
2004-09-05 23:01:51 +02:00
|
|
|
| K_Speriod '(' spec_reference_event ',' delay_value
|
2001-10-26 05:22:56 +02:00
|
|
|
spec_notifier_opt ')' ';'
|
2001-07-02 01:44:43 +02:00
|
|
|
{ delete $5;
|
|
|
|
|
}
|
|
|
|
|
| K_Srecovery '(' spec_reference_event ',' spec_reference_event
|
2005-07-27 16:54:51 +02:00
|
|
|
',' delay_value spec_notifier_opt ')' ';'
|
2001-07-02 01:44:43 +02:00
|
|
|
{ delete $7;
|
|
|
|
|
}
|
|
|
|
|
| K_Ssetup '(' spec_reference_event ',' spec_reference_event
|
2005-07-27 16:54:51 +02:00
|
|
|
',' delay_value spec_notifier_opt ')' ';'
|
2001-07-02 01:44:43 +02:00
|
|
|
{ delete $7;
|
|
|
|
|
}
|
2001-10-26 05:22:56 +02:00
|
|
|
| K_Ssetuphold '(' spec_reference_event ',' spec_reference_event
|
2003-09-21 23:16:05 +02:00
|
|
|
',' delay_value ',' delay_value spec_notifier_opt ')' ';'
|
2001-07-02 01:44:43 +02:00
|
|
|
{ delete $7;
|
|
|
|
|
delete $9;
|
|
|
|
|
}
|
2003-08-31 23:14:28 +02:00
|
|
|
| K_Srecrem '(' spec_reference_event ',' spec_reference_event
|
2003-09-21 23:16:05 +02:00
|
|
|
',' delay_value ',' delay_value spec_notifier_opt ')' ';'
|
2003-08-31 23:14:28 +02:00
|
|
|
{ delete $7;
|
|
|
|
|
delete $9;
|
|
|
|
|
}
|
2003-09-21 23:16:05 +02:00
|
|
|
| K_Swidth '(' spec_reference_event ',' delay_value ',' expression
|
2001-10-26 05:22:56 +02:00
|
|
|
spec_notifier_opt ')' ';'
|
2001-07-02 01:44:43 +02:00
|
|
|
{ delete $5;
|
|
|
|
|
delete $7;
|
|
|
|
|
}
|
2005-07-27 16:54:51 +02:00
|
|
|
| K_Swidth '(' spec_reference_event ',' delay_value ')' ';'
|
2001-10-14 04:03:51 +02:00
|
|
|
{ delete $5;
|
|
|
|
|
}
|
1999-06-12 05:42:57 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
specify_item_list
|
|
|
|
|
: specify_item
|
|
|
|
|
| specify_item_list specify_item
|
|
|
|
|
;
|
|
|
|
|
|
2001-07-02 01:44:43 +02:00
|
|
|
specify_edge_path_decl
|
2006-09-23 06:57:19 +02:00
|
|
|
: specify_edge_path '=' '(' delay_value_list ')'
|
2007-02-12 02:52:21 +01:00
|
|
|
{ $$ = pform_assign_path_delay($1, $4); }
|
2002-11-26 04:56:10 +01:00
|
|
|
| specify_edge_path '=' delay_value_simple
|
2007-02-12 02:52:21 +01:00
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
|
|
|
|
(*tmp)[0] = $3;
|
|
|
|
|
$$ = pform_assign_path_delay($1, tmp);
|
|
|
|
|
}
|
2001-07-02 01:44:43 +02:00
|
|
|
;
|
|
|
|
|
|
2007-02-12 02:52:21 +01:00
|
|
|
edge_operator : K_posedge { $$ = true; } | K_negedge { $$ = false; } ;
|
|
|
|
|
|
2001-07-02 01:44:43 +02:00
|
|
|
specify_edge_path
|
2007-04-13 04:34:35 +02:00
|
|
|
: '(' specify_path_identifiers spec_polarity
|
2007-02-12 02:52:21 +01:00
|
|
|
K_EG '(' specify_path_identifiers polarity_operator expression ')' ')'
|
2007-04-13 04:34:35 +02:00
|
|
|
{ int edge_flag = 0;
|
|
|
|
|
$$ = pform_make_specify_edge_path(@1, edge_flag, $2, $3, false, $6, $8); }
|
2007-02-12 02:52:21 +01:00
|
|
|
| '(' edge_operator specify_path_identifiers spec_polarity
|
2007-04-13 04:34:35 +02:00
|
|
|
K_EG '(' specify_path_identifiers polarity_operator expression ')' ')'
|
|
|
|
|
{ int edge_flag = $2? 1 : -1;
|
|
|
|
|
$$ = pform_make_specify_edge_path(@1, edge_flag, $3, $4, false, $7, $9);}
|
|
|
|
|
| '(' specify_path_identifiers spec_polarity
|
|
|
|
|
K_SG '(' specify_path_identifiers polarity_operator expression ')' ')'
|
|
|
|
|
{ int edge_flag = 0;
|
|
|
|
|
$$ = pform_make_specify_edge_path(@1, edge_flag, $2, $3, true, $6, $8); }
|
2007-02-12 02:52:21 +01:00
|
|
|
| '(' edge_operator specify_path_identifiers spec_polarity
|
|
|
|
|
K_SG '(' specify_path_identifiers polarity_operator expression ')' ')'
|
2007-04-13 04:34:35 +02:00
|
|
|
{ int edge_flag = $2? 1 : -1;
|
|
|
|
|
$$ = pform_make_specify_edge_path(@1, edge_flag, $3, $4, true, $7, $9); }
|
2001-08-31 23:08:35 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
polarity_operator
|
|
|
|
|
: K_PO_POS
|
|
|
|
|
| K_PO_NEG
|
|
|
|
|
| ':'
|
2001-07-02 01:44:43 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
specify_simple_path_decl
|
2006-09-23 06:57:19 +02:00
|
|
|
: specify_simple_path '=' '(' delay_value_list ')'
|
|
|
|
|
{ $$ = pform_assign_path_delay($1, $4); }
|
2001-07-02 01:44:43 +02:00
|
|
|
| specify_simple_path '=' delay_value_simple
|
2006-09-23 06:57:19 +02:00
|
|
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
|
|
|
|
(*tmp)[0] = $3;
|
|
|
|
|
$$ = pform_assign_path_delay($1, tmp);
|
|
|
|
|
}
|
2001-12-01 03:42:39 +01:00
|
|
|
| specify_simple_path '=' '(' error ')'
|
2007-12-03 21:31:34 +01:00
|
|
|
{ yyerror(@3, "Syntax error in delay value list.");
|
2001-12-01 03:42:39 +01:00
|
|
|
yyerrok;
|
2006-09-23 06:57:19 +02:00
|
|
|
$$ = 0;
|
2001-12-01 03:42:39 +01:00
|
|
|
}
|
2001-07-02 01:44:43 +02:00
|
|
|
;
|
|
|
|
|
|
1999-06-19 05:21:21 +02:00
|
|
|
specify_simple_path
|
2003-02-27 07:45:11 +01:00
|
|
|
: '(' specify_path_identifiers spec_polarity
|
|
|
|
|
K_EG specify_path_identifiers ')'
|
2006-09-23 06:57:19 +02:00
|
|
|
{ $$ = pform_make_specify_path(@1, $2, $3, false, $5); }
|
2003-02-27 07:45:11 +01:00
|
|
|
| '(' specify_path_identifiers spec_polarity
|
|
|
|
|
K_SG specify_path_identifiers ')'
|
2006-09-23 06:57:19 +02:00
|
|
|
{ $$ = pform_make_specify_path(@1, $2, $3, true, $5); }
|
2001-12-01 03:42:39 +01:00
|
|
|
| '(' error ')'
|
2007-12-03 21:31:34 +01:00
|
|
|
{ yyerror(@1, "Invalid simple path");
|
2001-12-01 03:42:39 +01:00
|
|
|
yyerrok;
|
|
|
|
|
}
|
2001-04-21 02:55:46 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
specify_path_identifiers
|
2003-02-27 07:45:11 +01:00
|
|
|
: IDENTIFIER
|
2004-05-25 21:21:06 +02:00
|
|
|
{ list<perm_string>*tmp = new list<perm_string>;
|
|
|
|
|
tmp->push_back(lex_strings.make($1));
|
2003-02-27 07:45:11 +01:00
|
|
|
$$ = tmp;
|
2004-05-25 21:21:06 +02:00
|
|
|
delete[]$1;
|
2003-02-27 07:45:11 +01:00
|
|
|
}
|
|
|
|
|
| IDENTIFIER '[' expr_primary ']'
|
2004-05-25 21:21:06 +02:00
|
|
|
{ list<perm_string>*tmp = new list<perm_string>;
|
|
|
|
|
tmp->push_back(lex_strings.make($1));
|
2003-02-27 07:45:11 +01:00
|
|
|
$$ = tmp;
|
2004-05-25 21:21:06 +02:00
|
|
|
delete[]$1;
|
2003-02-27 07:45:11 +01:00
|
|
|
}
|
|
|
|
|
| specify_path_identifiers ',' IDENTIFIER
|
2004-05-25 21:21:06 +02:00
|
|
|
{ list<perm_string>*tmp = $1;
|
|
|
|
|
tmp->push_back(lex_strings.make($3));
|
2003-02-27 07:45:11 +01:00
|
|
|
$$ = tmp;
|
2004-05-25 21:21:06 +02:00
|
|
|
delete[]$3;
|
2003-02-27 07:45:11 +01:00
|
|
|
}
|
|
|
|
|
| specify_path_identifiers ',' IDENTIFIER '[' expr_primary ']'
|
2004-05-25 21:21:06 +02:00
|
|
|
{ list<perm_string>*tmp = $1;
|
|
|
|
|
tmp->push_back(lex_strings.make($3));
|
2003-02-27 07:45:11 +01:00
|
|
|
$$ = tmp;
|
2004-05-25 21:21:06 +02:00
|
|
|
delete[]$3;
|
2003-02-27 07:45:11 +01:00
|
|
|
}
|
1999-06-19 05:21:21 +02:00
|
|
|
;
|
|
|
|
|
|
1999-06-12 05:42:57 +02:00
|
|
|
specparam
|
|
|
|
|
: IDENTIFIER '=' expression
|
2003-02-27 07:45:11 +01:00
|
|
|
{ PExpr*tmp = $3;
|
2007-02-13 05:39:25 +01:00
|
|
|
pform_set_specparam(lex_strings.make($1), tmp);
|
2003-02-27 07:45:11 +01:00
|
|
|
delete $1;
|
1999-06-12 05:42:57 +02:00
|
|
|
}
|
2001-07-02 01:44:43 +02:00
|
|
|
| IDENTIFIER '=' expression ':' expression ':' expression
|
2007-02-13 05:39:25 +01:00
|
|
|
{ PExpr*tmp = 0;
|
|
|
|
|
switch (min_typ_max_flag) {
|
|
|
|
|
case MIN:
|
|
|
|
|
tmp = $3;
|
|
|
|
|
delete $5;
|
|
|
|
|
delete $7;
|
|
|
|
|
break;
|
|
|
|
|
case TYP:
|
|
|
|
|
delete $3;
|
|
|
|
|
tmp = $5;
|
|
|
|
|
delete $7;
|
|
|
|
|
break;
|
|
|
|
|
case MAX:
|
|
|
|
|
delete $3;
|
|
|
|
|
delete $5;
|
|
|
|
|
tmp = $7;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-11-21 20:07:40 +01:00
|
|
|
if (min_typ_max_warn > 0) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << tmp->get_fileline() << ": warning: choosing ";
|
2007-11-21 20:07:40 +01:00
|
|
|
switch (min_typ_max_flag) {
|
|
|
|
|
case MIN:
|
|
|
|
|
cerr << "min";
|
|
|
|
|
break;
|
|
|
|
|
case TYP:
|
|
|
|
|
cerr << "typ";
|
|
|
|
|
break;
|
|
|
|
|
case MAX:
|
|
|
|
|
cerr << "max";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
cerr << " expression." << endl;
|
|
|
|
|
min_typ_max_warn -= 1;
|
|
|
|
|
}
|
2007-02-13 05:39:25 +01:00
|
|
|
pform_set_specparam(lex_strings.make($1), tmp);
|
|
|
|
|
delete $1;
|
2001-07-02 01:44:43 +02:00
|
|
|
}
|
2002-11-21 18:40:11 +01:00
|
|
|
| PATHPULSE_IDENTIFIER '=' expression
|
2001-11-06 03:52:19 +01:00
|
|
|
{ delete $1;
|
2002-11-21 18:40:11 +01:00
|
|
|
delete $3;
|
2001-11-06 03:52:19 +01:00
|
|
|
}
|
|
|
|
|
| PATHPULSE_IDENTIFIER '=' '(' expression ',' expression ')'
|
|
|
|
|
{ delete $1;
|
|
|
|
|
delete $4;
|
|
|
|
|
delete $6;
|
|
|
|
|
}
|
1999-06-12 05:42:57 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
specparam_list
|
|
|
|
|
: specparam
|
|
|
|
|
| specparam_list ',' specparam
|
|
|
|
|
;
|
|
|
|
|
|
2003-02-27 07:45:11 +01:00
|
|
|
spec_polarity
|
|
|
|
|
: '+' { $$ = '+'; }
|
|
|
|
|
| '-' { $$ = '-'; }
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
1999-06-19 05:21:21 +02:00
|
|
|
|
2001-07-02 01:44:43 +02:00
|
|
|
spec_reference_event
|
2007-06-14 05:50:00 +02:00
|
|
|
: K_posedge expression
|
|
|
|
|
{ delete $2; }
|
|
|
|
|
| K_negedge expression
|
|
|
|
|
{ delete $2; }
|
|
|
|
|
| K_posedge expr_primary K_TAND expression
|
|
|
|
|
{ delete $2;
|
|
|
|
|
delete $4;
|
|
|
|
|
}
|
|
|
|
|
| K_negedge expr_primary K_TAND expression
|
|
|
|
|
{ delete $2;
|
|
|
|
|
delete $4;
|
|
|
|
|
}
|
2008-01-10 02:06:01 +01:00
|
|
|
| K_edge '[' edge_descriptor_list ']' expr_primary
|
|
|
|
|
{ delete $5; }
|
2007-06-14 05:50:00 +02:00
|
|
|
| K_edge '[' edge_descriptor_list ']' expr_primary K_TAND expression
|
|
|
|
|
{ delete $5;
|
|
|
|
|
delete $7;
|
|
|
|
|
}
|
|
|
|
|
| expr_primary K_TAND expression
|
|
|
|
|
{ delete $1;
|
|
|
|
|
delete $3;
|
|
|
|
|
}
|
|
|
|
|
| expr_primary
|
|
|
|
|
{ delete $1; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/* The edge_descriptor is detected by the lexor as the various
|
|
|
|
|
2-letter edge sequences that are supported here. For now, we
|
|
|
|
|
don't care what they are, because we do not yet support specify
|
|
|
|
|
edge events. */
|
|
|
|
|
edge_descriptor_list
|
|
|
|
|
: edge_descriptor_list ',' K_edge_descriptor
|
|
|
|
|
| K_edge_descriptor
|
|
|
|
|
;
|
2001-10-26 05:22:56 +02:00
|
|
|
|
|
|
|
|
spec_notifier_opt
|
|
|
|
|
: /* empty */
|
2001-12-03 05:47:14 +01:00
|
|
|
{ }
|
2001-10-26 05:22:56 +02:00
|
|
|
| spec_notifier
|
2001-12-03 05:47:14 +01:00
|
|
|
{ }
|
2001-10-26 05:22:56 +02:00
|
|
|
;
|
|
|
|
|
spec_notifier
|
|
|
|
|
: ','
|
2001-12-03 05:47:14 +01:00
|
|
|
{ }
|
2008-01-25 22:34:51 +01:00
|
|
|
| ',' hierarchy_identifier
|
2001-12-03 05:47:14 +01:00
|
|
|
{ delete $2; }
|
2004-10-04 03:10:51 +02:00
|
|
|
| spec_notifier ','
|
2001-12-03 05:47:14 +01:00
|
|
|
{ }
|
2008-01-25 22:34:51 +01:00
|
|
|
| spec_notifier ',' hierarchy_identifier
|
2006-12-03 05:46:51 +01:00
|
|
|
{ delete $3; }
|
2001-10-09 20:11:58 +02:00
|
|
|
| IDENTIFIER
|
|
|
|
|
{ delete $1; }
|
2001-07-02 01:44:43 +02:00
|
|
|
;
|
2000-05-12 01:37:26 +02:00
|
|
|
|
2001-10-26 05:22:56 +02:00
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
statement
|
2000-05-12 01:37:26 +02:00
|
|
|
|
|
|
|
|
/* assign and deassign statements are procedural code to do
|
|
|
|
|
structural assignments, and to turn that structural assignment
|
|
|
|
|
off. This stronger then any other assign, but weaker then the
|
|
|
|
|
force assignments. */
|
|
|
|
|
|
2006-02-02 03:43:57 +01:00
|
|
|
: K_assign lpvalue '=' expression ';'
|
2000-05-12 01:37:26 +02:00
|
|
|
{ PCAssign*tmp = new PCAssign($2, $4);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2000-05-12 01:37:26 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2006-02-02 03:43:57 +01:00
|
|
|
| K_deassign lpvalue ';'
|
2000-05-12 01:37:26 +02:00
|
|
|
{ PDeassign*tmp = new PDeassign($2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2000-05-12 01:37:26 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Force and release statements are similar to assignments,
|
|
|
|
|
syntactically, but they will be elaborated differently. */
|
|
|
|
|
|
2006-02-02 03:43:57 +01:00
|
|
|
| K_force lpvalue '=' expression ';'
|
2000-05-12 01:37:26 +02:00
|
|
|
{ PForce*tmp = new PForce($2, $4);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2000-05-12 01:37:26 +02:00
|
|
|
$$ = tmp;
|
1999-05-30 05:12:56 +02:00
|
|
|
}
|
2006-02-02 03:43:57 +01:00
|
|
|
| K_release lpvalue ';'
|
2000-05-12 01:37:26 +02:00
|
|
|
{ PRelease*tmp = new PRelease($2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2000-05-12 01:37:26 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* begin-end blocks come in a variety of forms, including named and
|
|
|
|
|
anonymous. The named blocks can also carry their own reg
|
|
|
|
|
variables, which are placed in the scope created by the block
|
|
|
|
|
name. These are handled by pushing the scope name then matching
|
|
|
|
|
the declarations. The scope is popped at the end of the block. */
|
|
|
|
|
|
1999-05-30 05:12:56 +02:00
|
|
|
| K_begin statement_list K_end
|
1999-06-24 06:24:18 +02:00
|
|
|
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ, *$2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-24 06:24:18 +02:00
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_begin ':' IDENTIFIER
|
1999-07-10 03:03:18 +02:00
|
|
|
{ pform_push_scope($3); }
|
1999-06-24 06:24:18 +02:00
|
|
|
block_item_decls_opt
|
|
|
|
|
statement_list K_end
|
|
|
|
|
{ pform_pop_scope();
|
2004-02-18 18:11:54 +01:00
|
|
|
PBlock*tmp = new PBlock(lex_strings.make($3),
|
|
|
|
|
PBlock::BL_SEQ, *$6);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-24 06:24:18 +02:00
|
|
|
delete $3;
|
|
|
|
|
delete $6;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_begin K_end
|
|
|
|
|
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-24 06:24:18 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_begin ':' IDENTIFIER K_end
|
|
|
|
|
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-24 06:24:18 +02:00
|
|
|
$$ = tmp;
|
1999-06-12 05:42:57 +02:00
|
|
|
}
|
|
|
|
|
| K_begin error K_end
|
|
|
|
|
{ yyerrok; }
|
2000-05-12 01:37:26 +02:00
|
|
|
|
|
|
|
|
/* fork-join blocks are very similar to begin-end blocks. In fact,
|
|
|
|
|
from the parser's perspective there is no real difference. All we
|
|
|
|
|
need to do is remember that this is a parallel block so that the
|
|
|
|
|
code generator can do the right thing. */
|
|
|
|
|
|
1999-09-22 06:30:04 +02:00
|
|
|
| K_fork ':' IDENTIFIER
|
|
|
|
|
{ pform_push_scope($3); }
|
|
|
|
|
block_item_decls_opt
|
|
|
|
|
statement_list K_join
|
|
|
|
|
{ pform_pop_scope();
|
2004-02-18 18:11:54 +01:00
|
|
|
PBlock*tmp = new PBlock(lex_strings.make($3),
|
|
|
|
|
PBlock::BL_PAR, *$6);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-09-22 06:30:04 +02:00
|
|
|
delete $3;
|
|
|
|
|
delete $6;
|
1999-06-19 23:06:16 +02:00
|
|
|
$$ = tmp;
|
1999-06-12 22:35:27 +02:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
| K_fork K_join
|
1999-06-24 06:24:18 +02:00
|
|
|
{ PBlock*tmp = new PBlock(PBlock::BL_PAR);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-24 06:24:18 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-09-22 06:30:04 +02:00
|
|
|
| K_fork ':' IDENTIFIER K_join
|
|
|
|
|
{ PBlock*tmp = new PBlock(PBlock::BL_PAR);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2000-07-26 07:08:07 +02:00
|
|
|
delete $3;
|
1999-09-22 06:30:04 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2000-05-12 01:37:26 +02:00
|
|
|
|
2008-01-25 22:34:51 +01:00
|
|
|
| K_disable hierarchy_identifier ';'
|
2001-12-03 05:47:14 +01:00
|
|
|
{ PDisable*tmp = new PDisable(*$2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2000-05-12 01:37:26 +02:00
|
|
|
delete $2;
|
2000-07-26 07:08:07 +02:00
|
|
|
$$ = tmp;
|
2000-05-12 01:37:26 +02:00
|
|
|
}
|
2008-01-25 22:34:51 +01:00
|
|
|
| K_TRIGGER hierarchy_identifier ';'
|
2002-12-07 03:49:24 +01:00
|
|
|
{ PTrigger*tmp = new PTrigger(*$2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2000-07-26 07:08:07 +02:00
|
|
|
delete $2;
|
2000-05-12 01:37:26 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_forever statement
|
|
|
|
|
{ PForever*tmp = new PForever($2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2000-04-22 06:20:19 +02:00
|
|
|
$$ = tmp;
|
1999-09-22 06:30:04 +02:00
|
|
|
}
|
2000-05-12 01:37:26 +02:00
|
|
|
| K_fork statement_list K_join
|
|
|
|
|
{ PBlock*tmp = new PBlock(PBlock::BL_PAR, *$2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2000-05-12 01:37:26 +02:00
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-09-22 06:30:04 +02:00
|
|
|
| K_repeat '(' expression ')' statement
|
|
|
|
|
{ PRepeat*tmp = new PRepeat($3, $5);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-09-22 06:30:04 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-02-03 05:20:11 +01:00
|
|
|
| K_case '(' expression ')' case_items K_endcase
|
1999-09-29 20:36:02 +02:00
|
|
|
{ PCase*tmp = new PCase(NetCase::EQ, $3, $5);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-02-03 05:20:11 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-06-10 06:03:52 +02:00
|
|
|
| K_casex '(' expression ')' case_items K_endcase
|
1999-09-29 20:36:02 +02:00
|
|
|
{ PCase*tmp = new PCase(NetCase::EQX, $3, $5);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-10 06:03:52 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_casez '(' expression ')' case_items K_endcase
|
1999-09-29 20:36:02 +02:00
|
|
|
{ PCase*tmp = new PCase(NetCase::EQZ, $3, $5);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-10 06:03:52 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-06-12 05:42:57 +02:00
|
|
|
| K_case '(' expression ')' error K_endcase
|
|
|
|
|
{ yyerrok; }
|
|
|
|
|
| K_casex '(' expression ')' error K_endcase
|
|
|
|
|
{ yyerrok; }
|
|
|
|
|
| K_casez '(' expression ')' error K_endcase
|
|
|
|
|
{ yyerrok; }
|
2007-04-02 01:02:03 +02:00
|
|
|
| K_if '(' expression ')' statement_or_null %prec less_than_K_else
|
1998-11-07 18:05:05 +01:00
|
|
|
{ PCondit*tmp = new PCondit($3, $5, 0);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1998-11-07 18:05:05 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| K_if '(' expression ')' statement_or_null K_else statement_or_null
|
1998-11-07 18:05:05 +01:00
|
|
|
{ PCondit*tmp = new PCondit($3, $5, $7);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1998-11-07 18:05:05 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| K_if '(' error ')' statement_or_null %prec less_than_K_else
|
1999-09-29 23:16:32 +02:00
|
|
|
{ yyerror(@1, "error: Malformed conditional expression.");
|
1998-11-07 18:05:05 +01:00
|
|
|
$$ = $5;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| K_if '(' error ')' statement_or_null K_else statement_or_null
|
1999-09-29 23:16:32 +02:00
|
|
|
{ yyerror(@1, "error: Malformed conditional expression.");
|
1998-11-07 18:05:05 +01:00
|
|
|
$$ = $5;
|
|
|
|
|
}
|
1999-05-07 06:26:49 +02:00
|
|
|
| K_for '(' lpvalue '=' expression ';' expression ';'
|
|
|
|
|
lpvalue '=' expression ')' statement
|
1999-06-10 06:03:52 +02:00
|
|
|
{ PForStatement*tmp = new PForStatement($3, $5, $7, $9, $11, $13);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-06-10 07:33:12 +02:00
|
|
|
$$ = tmp;
|
1998-11-09 19:55:33 +01:00
|
|
|
}
|
1999-05-07 06:26:49 +02:00
|
|
|
| K_for '(' lpvalue '=' expression ';' expression ';'
|
1998-11-09 19:55:33 +01:00
|
|
|
error ')' statement
|
|
|
|
|
{ $$ = 0;
|
2007-12-03 21:31:34 +01:00
|
|
|
yyerror(@1, "error: Error in for loop step assignment.");
|
1998-11-09 19:55:33 +01:00
|
|
|
}
|
1999-05-07 06:26:49 +02:00
|
|
|
| K_for '(' lpvalue '=' expression ';' error ';'
|
|
|
|
|
lpvalue '=' expression ')' statement
|
1998-11-09 19:55:33 +01:00
|
|
|
{ $$ = 0;
|
2007-12-03 21:31:34 +01:00
|
|
|
yyerror(@1, "error: Error in for loop condition expression.");
|
1998-11-09 19:55:33 +01:00
|
|
|
}
|
|
|
|
|
| K_for '(' error ')' statement
|
|
|
|
|
{ $$ = 0;
|
2007-12-03 21:31:34 +01:00
|
|
|
yyerror(@1, "error: Incomprehensible for loop.");
|
1998-11-09 19:55:33 +01:00
|
|
|
}
|
|
|
|
|
| K_while '(' expression ')' statement
|
1998-11-11 04:13:04 +01:00
|
|
|
{ PWhile*tmp = new PWhile($3, $5);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1998-11-11 04:13:04 +01:00
|
|
|
$$ = tmp;
|
1998-11-09 19:55:33 +01:00
|
|
|
}
|
|
|
|
|
| K_while '(' error ')' statement
|
|
|
|
|
{ $$ = 0;
|
2007-12-03 21:31:34 +01:00
|
|
|
yyerror(@1, "error: Error in while loop condition.");
|
1998-11-09 19:55:33 +01:00
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| delay1 statement_or_null
|
1999-08-01 18:34:50 +02:00
|
|
|
{ PExpr*del = (*$1)[0];
|
1999-12-31 04:24:30 +01:00
|
|
|
assert($1->count() == 1);
|
1999-08-01 18:34:50 +02:00
|
|
|
PDelayStatement*tmp = new PDelayStatement(del, $2);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| event_control statement_or_null
|
1998-11-04 00:28:49 +01:00
|
|
|
{ PEventStatement*tmp = $1;
|
1999-04-29 04:16:26 +02:00
|
|
|
if (tmp == 0) {
|
1999-09-29 23:16:32 +02:00
|
|
|
yyerror(@1, "error: Invalid event control.");
|
1999-04-29 04:16:26 +02:00
|
|
|
$$ = 0;
|
|
|
|
|
} else {
|
|
|
|
|
tmp->set_statement($2);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| '@' '*' statement_or_null
|
2002-04-21 06:59:07 +02:00
|
|
|
{ PEventStatement*tmp = new PEventStatement;
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2002-04-21 06:59:07 +02:00
|
|
|
tmp->set_statement($3);
|
|
|
|
|
$$ = tmp;
|
2001-12-31 06:23:13 +01:00
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| '@' '(' '*' ')' statement_or_null
|
2002-04-21 19:43:12 +02:00
|
|
|
{ PEventStatement*tmp = new PEventStatement;
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2002-04-21 19:43:12 +02:00
|
|
|
tmp->set_statement($5);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-05-07 06:26:49 +02:00
|
|
|
| lpvalue '=' expression ';'
|
1999-05-10 02:16:57 +02:00
|
|
|
{ PAssign*tmp = new PAssign($1,$3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-01-25 06:45:56 +01:00
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2006-02-02 03:43:57 +01:00
|
|
|
| error '=' expression ';'
|
2007-12-03 21:31:34 +01:00
|
|
|
{ yyerror(@2, "Syntax in assignment statement l-value.");
|
2006-02-02 03:43:57 +01:00
|
|
|
yyerrok;
|
|
|
|
|
$$ = new PNoop;
|
|
|
|
|
}
|
1999-05-07 06:26:49 +02:00
|
|
|
| lpvalue K_LE expression ';'
|
1999-06-06 22:45:38 +02:00
|
|
|
{ PAssignNB*tmp = new PAssignNB($1,$3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-05-10 02:16:57 +02:00
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2006-02-02 03:43:57 +01:00
|
|
|
| error K_LE expression ';'
|
2007-12-03 21:31:34 +01:00
|
|
|
{ yyerror(@2, "Syntax in assignment statement l-value.");
|
2006-02-02 03:43:57 +01:00
|
|
|
yyerrok;
|
|
|
|
|
$$ = new PNoop;
|
|
|
|
|
}
|
1999-12-31 04:24:30 +01:00
|
|
|
| lpvalue '=' delay1 expression ';'
|
|
|
|
|
{ assert($3->count() == 1);
|
|
|
|
|
PExpr*del = (*$3)[0];
|
1999-08-01 18:34:50 +02:00
|
|
|
PAssign*tmp = new PAssign($1,del,$4);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-05-10 02:16:57 +02:00
|
|
|
$$ = tmp;
|
1999-05-08 22:19:20 +02:00
|
|
|
}
|
1999-12-31 04:24:30 +01:00
|
|
|
| lpvalue K_LE delay1 expression ';'
|
|
|
|
|
{ assert($3->count() == 1);
|
|
|
|
|
PExpr*del = (*$3)[0];
|
1999-09-02 03:59:27 +02:00
|
|
|
PAssignNB*tmp = new PAssignNB($1,del,$4);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-09-22 04:00:48 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| lpvalue '=' event_control expression ';'
|
|
|
|
|
{ PAssign*tmp = new PAssign($1,$3,$4);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-09-22 04:00:48 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-12-31 04:24:30 +01:00
|
|
|
| lpvalue '=' K_repeat '(' expression ')' event_control expression ';'
|
|
|
|
|
{ PAssign*tmp = new PAssign($1,$7,$8);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp,@1);
|
1999-12-31 04:24:30 +01:00
|
|
|
tmp->set_lineno(@1.first_line);
|
|
|
|
|
yyerror(@3, "sorry: repeat event control not supported.");
|
|
|
|
|
delete $5;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-09-22 04:00:48 +02:00
|
|
|
| lpvalue K_LE event_control expression ';'
|
|
|
|
|
{ yyerror(@1, "sorry: Event controls not supported here.");
|
|
|
|
|
PAssignNB*tmp = new PAssignNB($1,$4);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-12-31 04:24:30 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| lpvalue K_LE K_repeat '(' expression ')' event_control expression ';'
|
|
|
|
|
{ yyerror(@1, "sorry: Event controls not supported here.");
|
|
|
|
|
delete $5;
|
|
|
|
|
PAssignNB*tmp = new PAssignNB($1,$8);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-09-02 03:59:27 +02:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| K_wait '(' expression ')' statement_or_null
|
1998-11-09 19:55:33 +01:00
|
|
|
{ PEventStatement*tmp;
|
2000-04-12 06:23:57 +02:00
|
|
|
PEEvent*etmp = new PEEvent(PEEvent::POSITIVE, $3);
|
1999-04-29 04:16:26 +02:00
|
|
|
tmp = new PEventStatement(etmp);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp,@1);
|
1998-11-09 19:55:33 +01:00
|
|
|
tmp->set_statement($5);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
| SYSTEM_IDENTIFIER '(' expression_list_with_nuls ')' ';'
|
2007-05-24 06:07:11 +02:00
|
|
|
{ PCallTask*tmp = new PCallTask(lex_strings.make($1), *$3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp,@1);
|
1999-07-03 04:12:51 +02:00
|
|
|
delete $1;
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
| SYSTEM_IDENTIFIER ';'
|
1999-07-03 04:12:51 +02:00
|
|
|
{ svector<PExpr*>pt (0);
|
2007-05-24 06:07:11 +02:00
|
|
|
PCallTask*tmp = new PCallTask(lex_strings.make($1), pt);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp,@1);
|
1999-07-03 04:12:51 +02:00
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2008-01-25 22:34:51 +01:00
|
|
|
| hierarchy_identifier '(' expression_list_proper ')' ';'
|
2001-12-03 05:47:14 +01:00
|
|
|
{ PCallTask*tmp = new PCallTask(*$1, *$3);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-07-03 04:12:51 +02:00
|
|
|
delete $1;
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
1999-06-16 05:13:29 +02:00
|
|
|
}
|
2007-04-02 01:02:03 +02:00
|
|
|
|
|
|
|
|
/* NOTE: The standard doesn't really support an empty argument list
|
|
|
|
|
between parentheses, but it seems natural, and people commonly
|
|
|
|
|
want it. So accept it explicitly. */
|
|
|
|
|
|
2008-01-25 22:34:51 +01:00
|
|
|
| hierarchy_identifier '(' ')' ';'
|
2007-04-02 01:02:03 +02:00
|
|
|
{ svector<PExpr*>pt (0);
|
|
|
|
|
PCallTask*tmp = new PCallTask(*$1, pt);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
2007-04-02 01:02:03 +02:00
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
2008-01-25 22:34:51 +01:00
|
|
|
| hierarchy_identifier ';'
|
1999-07-03 04:12:51 +02:00
|
|
|
{ svector<PExpr*>pt (0);
|
2001-12-03 05:47:14 +01:00
|
|
|
PCallTask*tmp = new PCallTask(*$1, pt);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(tmp, @1);
|
1999-07-03 04:12:51 +02:00
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
1999-05-08 22:19:20 +02:00
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
| error ';'
|
2007-12-03 21:31:34 +01:00
|
|
|
{ yyerror(@2, "error: malformed statement");
|
1999-06-12 05:42:57 +02:00
|
|
|
yyerrok;
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = new PNoop;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
statement_list
|
|
|
|
|
: statement_list statement
|
1999-06-24 06:24:18 +02:00
|
|
|
{ svector<Statement*>*tmp = new svector<Statement*>(*$1, $2);
|
|
|
|
|
delete $1;
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| statement
|
1999-06-24 06:24:18 +02:00
|
|
|
{ svector<Statement*>*tmp = new svector<Statement*>(1);
|
|
|
|
|
(*tmp)[0] = $1;
|
1998-11-04 00:28:49 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2007-04-02 01:02:03 +02:00
|
|
|
statement_or_null
|
1998-11-04 00:28:49 +01:00
|
|
|
: statement
|
|
|
|
|
| ';' { $$ = 0; }
|
|
|
|
|
;
|
1998-11-23 01:20:22 +01:00
|
|
|
|
2007-03-22 17:08:14 +01:00
|
|
|
/* Task items are, other than the statement, task port items and
|
2006-05-11 05:26:57 +02:00
|
|
|
other block items. */
|
1999-05-30 05:12:56 +02:00
|
|
|
task_item
|
2006-05-11 05:26:57 +02:00
|
|
|
: block_item_decl { $$ = new svector<PWire*>(0); }
|
|
|
|
|
| task_port_item { $$ = $1; }
|
|
|
|
|
;
|
2006-03-30 07:22:34 +02:00
|
|
|
|
2006-05-11 05:26:57 +02:00
|
|
|
task_port_item
|
2006-03-30 07:22:34 +02:00
|
|
|
|
2006-05-11 05:26:57 +02:00
|
|
|
: K_input signed_opt range_opt list_of_identifiers ';'
|
2006-03-30 07:22:34 +02:00
|
|
|
{ svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
|
|
|
|
IVL_VT_LOGIC, $2,
|
|
|
|
|
$3, $4,
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_output signed_opt range_opt list_of_identifiers ';'
|
|
|
|
|
{ svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::POUTPUT,
|
|
|
|
|
IVL_VT_LOGIC, $2,
|
|
|
|
|
$3, $4,
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_inout signed_opt range_opt list_of_identifiers ';'
|
|
|
|
|
{ svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINOUT,
|
|
|
|
|
IVL_VT_LOGIC, $2,
|
|
|
|
|
$3, $4,
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* When the port is an integer, infer a signed vector of the integer
|
|
|
|
|
shape. Generate a range to make it work. */
|
|
|
|
|
|
|
|
|
|
| K_input K_integer list_of_identifiers ';'
|
|
|
|
|
{ svector<PExpr*>*range_stub
|
|
|
|
|
= new svector<PExpr*>(2);
|
|
|
|
|
PExpr*re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum(integer_width-1,
|
|
|
|
|
integer_width));
|
2006-03-30 07:22:34 +02:00
|
|
|
(*range_stub)[0] = re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
2006-03-30 07:22:34 +02:00
|
|
|
(*range_stub)[1] = re;
|
|
|
|
|
svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
|
|
|
|
IVL_VT_LOGIC, true,
|
|
|
|
|
range_stub, $3,
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_output K_integer list_of_identifiers ';'
|
|
|
|
|
{ svector<PExpr*>*range_stub
|
|
|
|
|
= new svector<PExpr*>(2);
|
|
|
|
|
PExpr*re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum(integer_width-1,
|
|
|
|
|
integer_width));
|
2006-03-30 07:22:34 +02:00
|
|
|
(*range_stub)[0] = re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
2006-03-30 07:22:34 +02:00
|
|
|
(*range_stub)[1] = re;
|
|
|
|
|
svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::POUTPUT,
|
|
|
|
|
IVL_VT_LOGIC, true,
|
|
|
|
|
range_stub, $3,
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_inout K_integer list_of_identifiers ';'
|
|
|
|
|
{ svector<PExpr*>*range_stub
|
|
|
|
|
= new svector<PExpr*>(2);
|
|
|
|
|
PExpr*re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum(integer_width-1,
|
|
|
|
|
integer_width));
|
2006-03-30 07:22:34 +02:00
|
|
|
(*range_stub)[0] = re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
2006-03-30 07:22:34 +02:00
|
|
|
(*range_stub)[1] = re;
|
|
|
|
|
svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINOUT,
|
|
|
|
|
IVL_VT_LOGIC, true,
|
|
|
|
|
range_stub, $3,
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ports can be real. */
|
|
|
|
|
|
|
|
|
|
| K_input K_real list_of_identifiers ';'
|
1999-07-24 04:11:19 +02:00
|
|
|
{ svector<PWire*>*tmp
|
2006-03-30 07:22:34 +02:00
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
|
|
|
|
IVL_VT_REAL, false,
|
|
|
|
|
0, $3,
|
2003-06-13 02:27:09 +02:00
|
|
|
@1.text, @1.first_line);
|
1999-07-24 04:11:19 +02:00
|
|
|
$$ = tmp;
|
1999-07-03 04:12:51 +02:00
|
|
|
}
|
2006-03-30 07:22:34 +02:00
|
|
|
| K_output K_real list_of_identifiers ';'
|
1999-07-24 04:11:19 +02:00
|
|
|
{ svector<PWire*>*tmp
|
2006-03-30 07:22:34 +02:00
|
|
|
= pform_make_task_ports(NetNet::POUTPUT,
|
|
|
|
|
IVL_VT_REAL, true,
|
|
|
|
|
0, $3,
|
1999-09-10 07:02:09 +02:00
|
|
|
@1.text, @1.first_line);
|
1999-07-24 04:11:19 +02:00
|
|
|
$$ = tmp;
|
1999-07-03 04:12:51 +02:00
|
|
|
}
|
2006-03-30 07:22:34 +02:00
|
|
|
| K_inout K_real list_of_identifiers ';'
|
1999-07-24 04:11:19 +02:00
|
|
|
{ svector<PWire*>*tmp
|
2006-03-30 07:22:34 +02:00
|
|
|
= pform_make_task_ports(NetNet::PINOUT,
|
|
|
|
|
IVL_VT_REAL, true,
|
|
|
|
|
0, $3,
|
1999-09-10 07:02:09 +02:00
|
|
|
@1.text, @1.first_line);
|
1999-07-24 04:11:19 +02:00
|
|
|
$$ = tmp;
|
1999-07-03 04:12:51 +02:00
|
|
|
}
|
1999-05-30 05:12:56 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
task_item_list
|
|
|
|
|
: task_item_list task_item
|
1999-07-24 04:11:19 +02:00
|
|
|
{ svector<PWire*>*tmp = new svector<PWire*>(*$1, *$2);
|
|
|
|
|
delete $1;
|
|
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1999-05-30 05:12:56 +02:00
|
|
|
| task_item
|
1999-07-24 04:11:19 +02:00
|
|
|
{ $$ = $1; }
|
1999-05-30 05:12:56 +02:00
|
|
|
;
|
|
|
|
|
|
1999-06-12 05:42:57 +02:00
|
|
|
task_item_list_opt
|
|
|
|
|
: task_item_list
|
1999-07-24 04:11:19 +02:00
|
|
|
{ $$ = $1; }
|
1999-06-12 05:42:57 +02:00
|
|
|
|
|
1999-07-24 04:11:19 +02:00
|
|
|
{ $$ = 0; }
|
1999-06-12 05:42:57 +02:00
|
|
|
;
|
2006-05-11 05:26:57 +02:00
|
|
|
|
|
|
|
|
task_port_decl
|
|
|
|
|
|
|
|
|
|
: K_input signed_opt range_opt IDENTIFIER
|
|
|
|
|
{ svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
|
|
|
|
IVL_VT_LOGIC, $2,
|
|
|
|
|
$3, list_from_identifier($4),
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| K_output signed_opt range_opt IDENTIFIER
|
|
|
|
|
{ svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::POUTPUT,
|
|
|
|
|
IVL_VT_LOGIC, $2,
|
|
|
|
|
$3, list_from_identifier($4),
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_inout signed_opt range_opt IDENTIFIER
|
|
|
|
|
{ svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINOUT,
|
|
|
|
|
IVL_VT_LOGIC, $2,
|
|
|
|
|
$3, list_from_identifier($4),
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
| K_input K_integer IDENTIFIER
|
|
|
|
|
{ svector<PExpr*>*range_stub
|
|
|
|
|
= new svector<PExpr*>(2);
|
|
|
|
|
PExpr*re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum(integer_width-1,
|
|
|
|
|
integer_width));
|
2006-05-11 05:26:57 +02:00
|
|
|
(*range_stub)[0] = re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
2006-05-11 05:26:57 +02:00
|
|
|
(*range_stub)[1] = re;
|
|
|
|
|
svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
|
|
|
|
IVL_VT_LOGIC, true,
|
|
|
|
|
range_stub,
|
|
|
|
|
list_from_identifier($3),
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_output K_integer IDENTIFIER
|
|
|
|
|
{ svector<PExpr*>*range_stub
|
|
|
|
|
= new svector<PExpr*>(2);
|
|
|
|
|
PExpr*re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum(integer_width-1,
|
|
|
|
|
integer_width));
|
2006-05-11 05:26:57 +02:00
|
|
|
(*range_stub)[0] = re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
2006-05-11 05:26:57 +02:00
|
|
|
(*range_stub)[1] = re;
|
|
|
|
|
svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::POUTPUT,
|
|
|
|
|
IVL_VT_LOGIC, true,
|
|
|
|
|
range_stub,
|
|
|
|
|
list_from_identifier($3),
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_inout K_integer IDENTIFIER
|
|
|
|
|
{ svector<PExpr*>*range_stub
|
|
|
|
|
= new svector<PExpr*>(2);
|
|
|
|
|
PExpr*re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum(integer_width-1,
|
|
|
|
|
integer_width));
|
2006-05-11 05:26:57 +02:00
|
|
|
(*range_stub)[0] = re;
|
2007-03-07 05:24:59 +01:00
|
|
|
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
2006-05-11 05:26:57 +02:00
|
|
|
(*range_stub)[1] = re;
|
|
|
|
|
svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINOUT,
|
|
|
|
|
IVL_VT_LOGIC, true,
|
|
|
|
|
range_stub,
|
|
|
|
|
list_from_identifier($3),
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ports can be real. */
|
|
|
|
|
|
|
|
|
|
| K_input K_real IDENTIFIER
|
|
|
|
|
{ svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINPUT,
|
|
|
|
|
IVL_VT_REAL, false,
|
|
|
|
|
0, list_from_identifier($3),
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_output K_real IDENTIFIER
|
|
|
|
|
{ svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::POUTPUT,
|
|
|
|
|
IVL_VT_REAL, false,
|
|
|
|
|
0, list_from_identifier($3),
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| K_inout K_real IDENTIFIER
|
|
|
|
|
{ svector<PWire*>*tmp
|
|
|
|
|
= pform_make_task_ports(NetNet::PINOUT,
|
|
|
|
|
IVL_VT_REAL, false,
|
|
|
|
|
0, list_from_identifier($3),
|
|
|
|
|
@1.text, @1.first_line);
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
task_port_decl_list
|
|
|
|
|
: task_port_decl_list ',' task_port_decl
|
|
|
|
|
{ svector<PWire*>*tmp = new svector<PWire*>(*$1, *$3);
|
|
|
|
|
delete $1;
|
|
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| task_port_decl
|
|
|
|
|
{ $$ = $1; }
|
|
|
|
|
;
|
1999-06-12 05:42:57 +02:00
|
|
|
|
1998-11-23 01:20:22 +01:00
|
|
|
udp_body
|
|
|
|
|
: K_table { lex_start_table(); }
|
1998-11-25 03:35:53 +01:00
|
|
|
udp_entry_list
|
|
|
|
|
K_endtable { lex_end_table(); $$ = $3; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_entry_list
|
|
|
|
|
: udp_comb_entry_list
|
|
|
|
|
| udp_sequ_entry_list
|
1998-11-23 01:20:22 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_comb_entry
|
|
|
|
|
: udp_input_list ':' udp_output_sym ';'
|
1999-07-10 03:03:18 +02:00
|
|
|
{ char*tmp = new char[strlen($1)+3];
|
|
|
|
|
strcpy(tmp, $1);
|
|
|
|
|
char*tp = tmp+strlen(tmp);
|
|
|
|
|
*tp++ = ':';
|
|
|
|
|
*tp++ = $3;
|
|
|
|
|
*tp++ = 0;
|
|
|
|
|
delete[]$1;
|
1998-11-25 03:35:53 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1998-11-23 01:20:22 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_comb_entry_list
|
|
|
|
|
: udp_comb_entry
|
1998-11-25 03:35:53 +01:00
|
|
|
{ list<string>*tmp = new list<string>;
|
1999-07-10 03:03:18 +02:00
|
|
|
tmp->push_back($1);
|
1998-11-25 03:35:53 +01:00
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1998-11-23 01:20:22 +01:00
|
|
|
| udp_comb_entry_list udp_comb_entry
|
1998-11-25 03:35:53 +01:00
|
|
|
{ list<string>*tmp = $1;
|
1999-07-10 03:03:18 +02:00
|
|
|
tmp->push_back($2);
|
1998-11-25 03:35:53 +01:00
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_sequ_entry_list
|
|
|
|
|
: udp_sequ_entry
|
|
|
|
|
{ list<string>*tmp = new list<string>;
|
1999-07-10 03:03:18 +02:00
|
|
|
tmp->push_back($1);
|
1998-11-25 03:35:53 +01:00
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| udp_sequ_entry_list udp_sequ_entry
|
|
|
|
|
{ list<string>*tmp = $1;
|
1999-07-10 03:03:18 +02:00
|
|
|
tmp->push_back($2);
|
1998-11-25 03:35:53 +01:00
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_sequ_entry
|
|
|
|
|
: udp_input_list ':' udp_input_sym ':' udp_output_sym ';'
|
1999-07-10 03:03:18 +02:00
|
|
|
{ char*tmp = new char[strlen($1)+5];
|
|
|
|
|
strcpy(tmp, $1);
|
|
|
|
|
char*tp = tmp+strlen(tmp);
|
|
|
|
|
*tp++ = ':';
|
|
|
|
|
*tp++ = $3;
|
|
|
|
|
*tp++ = ':';
|
|
|
|
|
*tp++ = $5;
|
|
|
|
|
*tp++ = 0;
|
1998-11-25 03:35:53 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_initial
|
2003-04-14 05:37:47 +02:00
|
|
|
: K_initial IDENTIFIER '=' number ';'
|
1998-11-25 03:35:53 +01:00
|
|
|
{ PExpr*etmp = new PENumber($4);
|
2007-05-24 06:07:11 +02:00
|
|
|
PEIdent*itmp = new PEIdent(lex_strings.make($2));
|
1999-05-10 02:16:57 +02:00
|
|
|
PAssign*atmp = new PAssign(itmp, etmp);
|
2007-12-20 18:31:01 +01:00
|
|
|
FILE_NAME(atmp, @2);
|
1998-11-25 03:35:53 +01:00
|
|
|
delete $2;
|
|
|
|
|
$$ = atmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_init_opt
|
|
|
|
|
: udp_initial { $$ = $1; }
|
|
|
|
|
| { $$ = 0; }
|
1998-11-23 01:20:22 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_input_list
|
|
|
|
|
: udp_input_sym
|
1999-07-10 03:03:18 +02:00
|
|
|
{ char*tmp = new char[2];
|
|
|
|
|
tmp[0] = $1;
|
|
|
|
|
tmp[1] = 0;
|
1998-11-25 03:35:53 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1998-11-23 01:20:22 +01:00
|
|
|
| udp_input_list udp_input_sym
|
1999-07-10 03:03:18 +02:00
|
|
|
{ char*tmp = new char[strlen($1)+2];
|
|
|
|
|
strcpy(tmp, $1);
|
|
|
|
|
char*tp = tmp+strlen(tmp);
|
|
|
|
|
*tp++ = $2;
|
|
|
|
|
*tp++ = 0;
|
|
|
|
|
delete[]$1;
|
1998-11-25 03:35:53 +01:00
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_input_sym
|
|
|
|
|
: '0' { $$ = '0'; }
|
|
|
|
|
| '1' { $$ = '1'; }
|
|
|
|
|
| 'x' { $$ = 'x'; }
|
|
|
|
|
| '?' { $$ = '?'; }
|
|
|
|
|
| 'b' { $$ = 'b'; }
|
|
|
|
|
| '*' { $$ = '*'; }
|
2000-03-05 19:26:51 +01:00
|
|
|
| '%' { $$ = '%'; }
|
1998-11-25 03:35:53 +01:00
|
|
|
| 'f' { $$ = 'f'; }
|
2000-03-05 19:26:51 +01:00
|
|
|
| 'F' { $$ = 'F'; }
|
2001-06-18 02:51:23 +02:00
|
|
|
| 'l' { $$ = 'l'; }
|
|
|
|
|
| 'h' { $$ = 'H'; }
|
|
|
|
|
| 'B' { $$ = 'B'; }
|
1998-12-14 03:01:34 +01:00
|
|
|
| 'r' { $$ = 'r'; }
|
2000-03-05 19:26:51 +01:00
|
|
|
| 'R' { $$ = 'R'; }
|
2001-06-18 02:51:23 +02:00
|
|
|
| 'M' { $$ = 'M'; }
|
1998-12-18 06:16:25 +01:00
|
|
|
| 'n' { $$ = 'n'; }
|
2000-03-05 19:26:51 +01:00
|
|
|
| 'N' { $$ = 'N'; }
|
1998-12-18 06:16:25 +01:00
|
|
|
| 'p' { $$ = 'p'; }
|
2000-03-05 19:26:51 +01:00
|
|
|
| 'P' { $$ = 'P'; }
|
2001-06-18 02:51:23 +02:00
|
|
|
| 'Q' { $$ = 'Q'; }
|
2003-03-18 02:36:14 +01:00
|
|
|
| 'q' { $$ = 'q'; }
|
1998-12-18 06:16:25 +01:00
|
|
|
| '_' { $$ = '_'; }
|
2000-03-05 19:26:51 +01:00
|
|
|
| '+' { $$ = '+'; }
|
1998-11-23 01:20:22 +01:00
|
|
|
;
|
|
|
|
|
|
1998-11-25 03:35:53 +01:00
|
|
|
udp_output_sym
|
|
|
|
|
: '0' { $$ = '0'; }
|
|
|
|
|
| '1' { $$ = '1'; }
|
|
|
|
|
| 'x' { $$ = 'x'; }
|
|
|
|
|
| '-' { $$ = '-'; }
|
|
|
|
|
;
|
1998-11-23 01:20:22 +01:00
|
|
|
|
2007-05-24 06:07:11 +02:00
|
|
|
/* Port declarations create wires for the inputs and the output. The
|
|
|
|
|
makes for these ports are scoped within the UDP, so there is no
|
2008-01-25 22:34:51 +01:00
|
|
|
hierarchy involved. */
|
1998-11-23 01:20:22 +01:00
|
|
|
udp_port_decl
|
2007-05-24 06:07:11 +02:00
|
|
|
: K_input list_of_identifiers ';'
|
|
|
|
|
{ $$ = pform_make_udp_input_ports($2); }
|
|
|
|
|
| K_output IDENTIFIER ';'
|
|
|
|
|
{ pform_name_t pname;
|
2007-06-04 04:19:07 +02:00
|
|
|
pname.push_back(name_component_t(lex_strings.make($2)));
|
2007-05-24 06:07:11 +02:00
|
|
|
PWire*pp = new PWire(pname, NetNet::IMPLICIT, NetNet::POUTPUT, IVL_VT_LOGIC);
|
|
|
|
|
svector<PWire*>*tmp = new svector<PWire*>(1);
|
|
|
|
|
(*tmp)[0] = pp;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
|
|
|
|
| K_reg IDENTIFIER ';'
|
|
|
|
|
{ pform_name_t pname;
|
2007-06-04 04:19:07 +02:00
|
|
|
pname.push_back(name_component_t(lex_strings.make($2)));
|
2007-05-24 06:07:11 +02:00
|
|
|
PWire*pp = new PWire(pname, NetNet::REG, NetNet::PIMPLICIT, IVL_VT_LOGIC);
|
|
|
|
|
svector<PWire*>*tmp = new svector<PWire*>(1);
|
|
|
|
|
(*tmp)[0] = pp;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
delete $2;
|
|
|
|
|
}
|
|
|
|
|
| K_reg K_output IDENTIFIER ';'
|
|
|
|
|
{ pform_name_t pname;
|
2007-06-04 04:19:07 +02:00
|
|
|
pname.push_back(name_component_t(lex_strings.make($3)));
|
2007-05-24 06:07:11 +02:00
|
|
|
PWire*pp = new PWire(pname, NetNet::REG, NetNet::POUTPUT, IVL_VT_LOGIC);
|
|
|
|
|
svector<PWire*>*tmp = new svector<PWire*>(1);
|
|
|
|
|
(*tmp)[0] = pp;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
delete $3;
|
|
|
|
|
}
|
|
|
|
|
;
|
1998-11-23 01:20:22 +01:00
|
|
|
|
|
|
|
|
udp_port_decls
|
|
|
|
|
: udp_port_decl
|
1998-11-25 03:35:53 +01:00
|
|
|
{ $$ = $1; }
|
1998-11-23 01:20:22 +01:00
|
|
|
| udp_port_decls udp_port_decl
|
1999-06-12 22:35:27 +02:00
|
|
|
{ svector<PWire*>*tmp = new svector<PWire*>(*$1, *$2);
|
|
|
|
|
delete $1;
|
1998-11-25 03:35:53 +01:00
|
|
|
delete $2;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1998-11-23 01:20:22 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_port_list
|
1998-11-25 03:35:53 +01:00
|
|
|
: IDENTIFIER
|
|
|
|
|
{ list<string>*tmp = new list<string>;
|
1999-07-10 03:03:18 +02:00
|
|
|
tmp->push_back($1);
|
1998-11-25 03:35:53 +01:00
|
|
|
delete $1;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
|
|
|
|
| udp_port_list ',' IDENTIFIER
|
|
|
|
|
{ list<string>*tmp = $1;
|
1999-07-10 03:03:18 +02:00
|
|
|
tmp->push_back($3);
|
1998-11-25 03:35:53 +01:00
|
|
|
delete $3;
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
}
|
1998-11-23 01:20:22 +01:00
|
|
|
;
|
|
|
|
|
|
2004-03-08 01:10:29 +01:00
|
|
|
udp_reg_opt: K_reg { $$ = true; } | { $$ = false; };
|
|
|
|
|
|
|
|
|
|
udp_initial_expr_opt
|
|
|
|
|
: '=' expression { $$ = $2; }
|
|
|
|
|
| { $$ = 0; }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
udp_input_declaration_list
|
|
|
|
|
: K_input IDENTIFIER
|
|
|
|
|
{ list<perm_string>*tmp = new list<perm_string>;
|
|
|
|
|
tmp->push_back(lex_strings.make($2));
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
delete[]$2;
|
|
|
|
|
}
|
|
|
|
|
| udp_input_declaration_list ',' K_input IDENTIFIER
|
|
|
|
|
{ list<perm_string>*tmp = $1;
|
|
|
|
|
tmp->push_back(lex_strings.make($4));
|
|
|
|
|
$$ = tmp;
|
|
|
|
|
delete[]$4;
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
1998-11-23 01:20:22 +01:00
|
|
|
udp_primitive
|
2004-03-08 01:10:29 +01:00
|
|
|
/* This is the syntax for primitives that uses the IEEE1364-1995
|
|
|
|
|
format. The ports are simply names in the port list, and the
|
|
|
|
|
declarations are in the body. */
|
|
|
|
|
|
1998-11-23 01:20:22 +01:00
|
|
|
: K_primitive IDENTIFIER '(' udp_port_list ')' ';'
|
|
|
|
|
udp_port_decls
|
1998-11-25 03:35:53 +01:00
|
|
|
udp_init_opt
|
1998-11-23 01:20:22 +01:00
|
|
|
udp_body
|
|
|
|
|
K_endprimitive
|
2004-03-08 01:10:29 +01:00
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
{ perm_string tmp2 = lex_strings.make($2);
|
|
|
|
|
pform_make_udp(tmp2, $4, $7, $9, $8,
|
2001-10-21 03:55:24 +02:00
|
|
|
@2.text, @2.first_line);
|
1999-07-10 03:03:18 +02:00
|
|
|
delete[]$2;
|
|
|
|
|
}
|
2004-03-08 01:10:29 +01:00
|
|
|
|
|
|
|
|
/* This is the syntax for IEEE1364-2001 format definitions. The port
|
|
|
|
|
names and declarations are all in the parameter list. */
|
|
|
|
|
|
|
|
|
|
| K_primitive IDENTIFIER
|
|
|
|
|
'(' K_output udp_reg_opt IDENTIFIER udp_initial_expr_opt ','
|
|
|
|
|
udp_input_declaration_list ')' ';'
|
|
|
|
|
udp_body
|
|
|
|
|
K_endprimitive
|
|
|
|
|
|
|
|
|
|
{ perm_string tmp2 = lex_strings.make($2);
|
|
|
|
|
perm_string tmp6 = lex_strings.make($6);
|
|
|
|
|
pform_make_udp(tmp2, $5, tmp6, $7, $9, $12,
|
|
|
|
|
@2.text, @2.first_line);
|
|
|
|
|
delete[]$2;
|
|
|
|
|
delete[]$6;
|
|
|
|
|
}
|
1998-11-23 01:20:22 +01:00
|
|
|
;
|