iverilog/parse.y

2170 lines
51 KiB
Plaintext
Raw Normal View History

1998-11-04 00:28:49 +01:00
%{
/*
* Copyright (c) 1998-2000 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
*/
#if !defined(WINNT) && !defined(macintosh)
2000-04-01 21:31:57 +02:00
#ident "$Id: parse.y,v 1.87 2000/04/01 19:31:57 steve Exp $"
1998-11-04 00:28:49 +01:00
#endif
# include "parse_misc.h"
# include "pform.h"
extern void lex_start_table();
extern void lex_end_table();
1998-11-04 00:28:49 +01:00
%}
%union {
char letter;
1999-07-10 03:03:18 +02:00
char*text;
1998-11-04 00:28:49 +01:00
list<string>*strings;
PCase::Item*citem;
svector<PCase::Item*>*citems;
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
Module::port_t *mport;
svector<Module::port_t*>*mports;
1999-05-29 04:36:17 +02:00
portname_t*portname;
svector<portname_t*>*portnames;
struct parmvalue_t*parmvalue;
1999-05-29 04:36:17 +02:00
1998-11-04 00:28:49 +01:00
PExpr*expr;
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;
1999-07-03 04:12:51 +02:00
PTask*task;
PFunction*function;
1999-07-03 04:12:51 +02:00
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;
svector<Statement*>*statement_list;
1998-11-04 00:28:49 +01:00
verinum* number;
1999-06-15 04:50:02 +02:00
verireal* realtime;
1998-11-04 00:28:49 +01:00
};
1999-06-16 05:13:29 +02:00
%token <text> HIDENTIFIER IDENTIFIER PORTNAME SYSTEM_IDENTIFIER STRING
1998-11-04 00:28:49 +01:00
%token <number> NUMBER
1999-06-15 04:50:02 +02:00
%token <realtime> REALTIME
1999-06-19 05:21:21 +02:00
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_SG
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
1998-11-04 00:28:49 +01:00
%token K_always K_and K_assign K_begin K_buf K_bufif0 K_bufif1 K_case
%token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable
%token K_edge K_else K_end K_endcase K_endfunction K_endmodule
%token K_endprimitive K_endspecify K_endtable K_endtask K_event K_for
%token K_force K_forever K_fork K_function K_highz0 K_highz1 K_if
2000-03-12 18:09:40 +01:00
%token K_initial K_inout K_input K_integer K_join K_large K_localparam
%token 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
%token K_pull0 K_pull1 K_pulldown K_pullup K_rcmos K_real K_realtime
%token K_reg K_release K_repeat
1998-11-04 00:28:49 +01:00
%token K_rnmos K_rpmos K_rtran K_rtranif0 K_rtranif1 K_scalered
%token K_small K_specify
%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
1998-11-04 00:28:49 +01:00
%token K_wor K_xnor K_xor
%token KK_attribute
%type <letter> udp_input_sym udp_output_sym
%type <text> udp_input_list udp_sequ_entry udp_comb_entry
%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
%type <text> identifier register_variable
%type <strings> register_variable_list
1998-11-04 00:28:49 +01:00
%type <strings> list_of_variables
1999-06-02 04:56:29 +02:00
%type <text> net_decl_assign
%type <strings> net_decl_assigns
1999-09-17 04:06:25 +02:00
%type <mport> port port_opt port_reference port_reference_list
%type <mports> list_of_ports list_of_ports_opt
1999-07-24 04:11:19 +02:00
%type <wires> task_item task_item_list task_item_list_opt
%type <wires> function_item function_item_list
1998-11-04 00:28:49 +01:00
%type <portname> port_name parameter_value_byname
%type <portnames> port_name_list parameter_value_byname_list
1999-05-29 04:36:17 +02: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
%type <expr> expression expr_primary
%type <expr> lavalue lpvalue
%type <expr> delay_value delay_value_simple
%type <exprs> delay1 delay3 delay3_opt
1998-11-04 00:28:49 +01:00
%type <exprs> expression_list
1999-08-27 17:08:37 +02:00
%type <exprs> assign assign_list
1998-11-04 00:28:49 +01:00
%type <exprs> range range_opt
%type <nettype> net_type
%type <gatetype> gatetype
%type <porttype> port_type
%type <parmvalue> parameter_value_opt
1998-11-04 00:28:49 +01:00
1999-07-03 04:12:51 +02:00
%type <task> task_body
%type <function> func_body
1999-08-26 00:22:41 +02:00
%type <exprs> range_or_type_opt
%type <event_expr> event_expression_list
1999-04-29 04:16:26 +02:00
%type <event_expr> event_expression
%type <event_statement> event_control
1998-11-04 00:28:49 +01:00
%type <statement> statement statement_opt
%type <statement_list> statement_list
%right '?' ':'
%left K_LOR
%left K_LAND
%left '|'
1999-09-30 04:43:01 +02:00
%left '^' K_NXOR K_NOR
%left '&' K_NAND
%left K_EQ K_NE K_CEQ K_CNE
%left K_GE K_LE '<' '>'
%left K_LS K_RS
%left '+' '-'
%left '*' '/' '%'
%left UNARY_PREC
1998-11-04 00:28:49 +01:00
/* to resolve dangling else ambiguity: */
%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
;
/* 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. */
block_item_decl
1999-09-10 07:02:09 +02:00
: K_reg range register_variable_list ';'
{ pform_set_net_range($3, $2);
delete $2;
delete $3;
}
| K_reg register_variable_list ';'
{ delete $2; }
| K_integer list_of_variables ';'
1999-09-10 07:02:09 +02:00
{ pform_set_reg_integer($2);
delete $2;
}
;
block_item_decls
: block_item_decl
| block_item_decls block_item_decl
;
block_item_decls_opt
: block_item_decls
|
;
case_item
1999-06-12 05:42:57 +02:00
: expression_list ':' statement_opt
{ PCase::Item*tmp = new PCase::Item;
1999-06-15 07:38:39 +02:00
tmp->expr = *$1;
tmp->stat = $3;
1999-06-15 07:38:39 +02:00
delete $1;
$$ = tmp;
}
| K_default ':' statement_opt
{ PCase::Item*tmp = new PCase::Item;
tmp->stat = $3;
$$ = tmp;
}
| K_default statement_opt
{ PCase::Item*tmp = new PCase::Item;
tmp->stat = $2;
$$ = tmp;
}
1999-06-12 05:42:57 +02:00
| error ':' statement_opt
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "error: Incomprehensible case expression.");
1999-06-12 05:42:57 +02:00
yyerrok;
}
;
case_items
: case_items case_item
{ svector<PCase::Item*>*tmp;
tmp = new svector<PCase::Item*>(*$1, $2);
delete $1;
$$ = tmp;
}
| case_item
{ svector<PCase::Item*>*tmp = new svector<PCase::Item*>(1);
(*tmp)[0] = $1;
$$ = 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
: identifier '=' expression
{ 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;
}
pform_set_defparam($1, $3);
1999-06-16 05:13:29 +02:00
delete $1;
}
;
defparam_assign_list
: defparam_assign
| range defparam_assign
1999-09-29 23:16:32 +02:00
{ yywarn(@1, "Ranges in parameter definition "
"are not supported.");
1999-06-16 05:13:29 +02:00
delete $1;
}
| defparam_assign_list ',' defparam_assign
;
delay1
: '#' delay_value_simple
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
(*tmp)[0] = $2;
$$ = tmp;
}
| '#' '(' delay_value ')'
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
(*tmp)[0] = $3;
$$ = tmp;
}
;
delay3
: '#' delay_value_simple
{ 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;
(*tmp)[1] = $7;
$$ = tmp;
}
;
delay3_opt
: delay3 { $$ = $1; }
| { $$ = 0; }
;
delay_value
: expression
{ PExpr*tmp = $1;
if (! pform_expression_is_constant(tmp))
yyerror(@1, "error: delay expression must "
"be constant.");
$$ = tmp;
}
| expression ':' expression ':' expression
{ yyerror(@1, "sorry: (min:typ:max) not supported.");
$$ = $3;
delete $1;
delete $5;
}
;
delay_value_simple
: NUMBER
{ verinum*tmp = $1;
if (tmp == 0) {
1999-09-29 23:16:32 +02:00
yyerror(@1, "internal error: delay.");
$$ = 0;
} else {
$$ = new PENumber(tmp);
1999-07-12 02:59:36 +02:00
$$->set_file(@1.text);
$$->set_lineno(@1.first_line);
}
1998-11-04 00:28:49 +01:00
}
| IDENTIFIER
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
1999-05-08 22:19:20 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
delete $1;
}
1998-11-04 00:28:49 +01:00
;
description
: module
| udp_primitive
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')'
1999-07-10 03:03:18 +02:00
{ pform_set_type_attrib($3, $5, $7);
delete $3;
delete $5;
delete $7;
}
1998-11-04 00:28:49 +01:00
;
1999-11-05 20:36:36 +01:00
drive_strength
: '(' dr_strength0 ',' dr_strength1 ')'
| '(' dr_strength1 ',' dr_strength0 ')'
| '(' dr_strength0 ',' K_highz1 ')'
| '(' dr_strength1 ',' K_highz0 ')'
| '(' K_highz1 ',' dr_strength0 ')'
| '(' K_highz0 ',' dr_strength1 ')'
;
drive_strength_opt
: drive_strength
|
;
dr_strength0 : K_supply0 | K_strong0 | K_pull0 | K_weak0 ;
dr_strength1 : K_supply1 | K_strong1 | K_pull1 | K_weak1 ;
1998-11-04 00:28:49 +01:00
event_control
: '@' IDENTIFIER
2000-04-01 21:31:57 +02:00
{ PEEvent*tmpe = new PEEvent($2);
tmpe->set_file(@2.text);
tmpe->set_lineno(@2.first_line);
delete[]$2;
PEventStatement*tmps = new PEventStatement(tmpe);
tmps->set_file(@1.text);
tmps->set_lineno(@1.first_line);
$$ = tmps;
1998-11-04 00:28:49 +01:00
}
| '@' '(' event_expression_list ')'
1999-04-29 04:16:26 +02:00
{ PEventStatement*tmp = new PEventStatement(*$3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
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
}
;
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;
}
;
1998-11-04 00:28:49 +01:00
event_expression
: K_posedge expression
{ PEEvent*tmp = new PEEvent(NetNEvent::POSEDGE, $2);
1999-04-29 04:16:26 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
svector<PEEvent*>*tl = new svector<PEEvent*>(1);
(*tl)[0] = tmp;
$$ = tl;
1998-11-04 00:28:49 +01:00
}
| K_negedge expression
{ PEEvent*tmp = new PEEvent(NetNEvent::NEGEDGE, $2);
1999-04-29 04:16:26 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
svector<PEEvent*>*tl = new svector<PEEvent*>(1);
(*tl)[0] = tmp;
$$ = tl;
}
| expression
{ PEEvent*tmp = new PEEvent(NetNEvent::ANYEDGE, $1);
1999-04-29 04:16:26 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
svector<PEEvent*>*tl = new svector<PEEvent*>(1);
(*tl)[0] = tmp;
$$ = tl;
}
1998-11-04 00:28:49 +01:00
;
expression
: expr_primary
{ $$ = $1; }
| '+' expr_primary %prec UNARY_PREC
1999-06-13 19:30:23 +02:00
{ $$ = $2; }
| '-' expr_primary %prec UNARY_PREC
1999-05-27 05:31:29 +02:00
{ PEUnary*tmp = new PEUnary('-', $2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| '~' expr_primary %prec UNARY_PREC
1999-05-27 05:31:29 +02:00
{ PEUnary*tmp = new PEUnary('~', $2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
}
| '&' expr_primary %prec UNARY_PREC
1999-05-27 05:31:29 +02:00
{ PEUnary*tmp = new PEUnary('&', $2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
}
| '!' expr_primary %prec UNARY_PREC
1999-05-27 05:31:29 +02:00
{ PEUnary*tmp = new PEUnary('!', $2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| '|' expr_primary %prec UNARY_PREC
1999-05-27 05:31:29 +02:00
{ PEUnary*tmp = new PEUnary('|', $2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| '^' expr_primary %prec UNARY_PREC
1999-05-27 05:31:29 +02:00
{ PEUnary*tmp = new PEUnary('^', $2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
1999-06-13 19:30:23 +02:00
| K_NAND expr_primary %prec UNARY_PREC
{ PEUnary*tmp = new PEUnary('A', $2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| K_NOR expr_primary %prec UNARY_PREC
{ PEUnary*tmp = new PEUnary('N', $2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| K_NXOR expr_primary %prec UNARY_PREC
{ PEUnary*tmp = new PEUnary('X', $2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
1998-11-04 00:28:49 +01:00
| expression '^' expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('^', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
}
| expression '*' expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('*', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression '/' expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('/', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression '%' expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('%', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
1998-11-04 00:28:49 +01:00
| expression '+' expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('+', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
}
| expression '-' expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('-', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
1998-11-04 00:28:49 +01:00
| expression '&' expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('&', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
}
| expression '|' expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('|', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
1999-09-30 04:43:01 +02:00
| expression K_NOR expression
{ PEBinary*tmp = new PEBinary('O', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_NXOR expression
{ PEBinary*tmp = new PEBinary('X', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
1999-05-08 22:19:20 +02:00
| expression '<' expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('<', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
1999-05-08 22:19:20 +02:00
}
| expression '>' expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('>', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
1999-05-08 22:19:20 +02:00
}
| expression K_LS expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('l', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_RS expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('r', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_EQ expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('e', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_CEQ expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('E', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_LE expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('L', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_GE expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('G', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_NE expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('n', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_CNE expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('N', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_LOR expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('o', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_LAND expression
1999-05-27 05:31:29 +02:00
{ PEBinary*tmp = new PEBinary('a', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression '?' expression ':' expression
{ PETernary*tmp = new PETernary($1, $3, $5);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
1998-11-04 00:28:49 +01:00
;
1998-11-04 00:28:49 +01:00
expression_list
: expression_list ',' expression
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
delete $1;
1998-11-04 00:28:49 +01:00
$$ = tmp;
}
| expression
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
(*tmp)[0] = $1;
1998-11-04 00:28:49 +01:00
$$ = tmp;
}
| expression_list ','
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, 0);
delete $1;
1998-11-04 00:28:49 +01:00
$$ = tmp;
}
;
expr_primary
: NUMBER
1999-06-15 04:50:02 +02:00
{ assert($1);
PENumber*tmp = new PENumber($1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| REALTIME
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "sorry: real constants not supported.");
1999-06-15 04:50:02 +02:00
delete $1;
$$ = 0;
1998-11-04 00:28:49 +01:00
}
| STRING
1999-07-10 03:03:18 +02:00
{ PEString*tmp = new PEString($1);
1999-05-27 05:31:29 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
delete $1;
}
| identifier
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
delete $1;
}
| SYSTEM_IDENTIFIER
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
1999-05-27 05:31:29 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
delete $1;
}
| identifier '[' expression ']'
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
1998-11-04 00:28:49 +01:00
tmp->msb_ = $3;
delete $1;
$$ = tmp;
}
| identifier '[' expression ':' expression ']'
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
1998-11-04 00:28:49 +01:00
tmp->msb_ = $3;
tmp->lsb_ = $5;
delete $1;
$$ = tmp;
}
1999-06-16 05:13:29 +02:00
| identifier '(' expression_list ')'
{ PECallFunction*tmp = new PECallFunction($1, *$3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1999-06-16 05:13:29 +02:00
}
| SYSTEM_IDENTIFIER '(' expression_list ')'
1999-09-25 04:57:29 +02:00
{ PECallFunction*tmp = new PECallFunction($1, *$3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1999-06-16 05:13:29 +02:00
}
| '(' expression ')'
{ $$ = $2; }
| '{' expression_list '}'
{ PEConcat*tmp = new PEConcat(*$2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
delete $2;
$$ = tmp;
}
| '{' expression '{' expression_list '}' '}'
{ PExpr*rep = $2;
if (!pform_expression_is_constant($2)) {
1999-09-29 23:16:32 +02:00
yyerror(@2, "error: Repeat expression "
"must be constant.");
delete rep;
delete $2;
rep = 0;
}
PEConcat*tmp = new PEConcat(*$4, rep);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $4;
$$ = tmp;
}
1998-11-04 00:28:49 +01:00
;
func_body
: function_item_list statement
{ $$ = new PFunction($1, $2); }
1999-06-19 05:21:21 +02:00
| function_item_list
1999-09-30 02:48:04 +02:00
{ yyerror(@1, "error: function body has no statement.");
$$ = new PFunction($1, 0);
}
;
/* 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. */
function_item
: K_input range_opt list_of_variables ';'
{ svector<PWire*>*tmp
1999-09-10 07:02:09 +02:00
= pform_make_task_ports(NetNet::PINPUT, $2, $3,
@1.text, @1.first_line);
delete $2;
delete $3;
$$ = tmp;
}
| block_item_decl
{ $$ = 0; }
;
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. */
function_item_list
: function_item
{ $$ = $1; }
| 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-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
: IDENTIFIER '(' expression_list ')'
{ lgate*tmp = new lgate;
tmp->name = $1;
1998-11-04 00:28:49 +01:00
tmp->parms = $3;
tmp->file = @1.text;
tmp->lineno = @1.first_line;
1998-11-04 00:28:49 +01:00
delete $1;
$$ = tmp;
}
| IDENTIFIER '(' ')'
{ lgate*tmp = new lgate;
tmp->name = $1;
tmp->parms = 0;
tmp->file = @1.text;
tmp->lineno = @1.first_line;
delete $1;
$$ = tmp;
}
1999-02-15 03:06:15 +01:00
| IDENTIFIER range '(' expression_list ')'
{ lgate*tmp = new lgate;
svector<PExpr*>*rng = $2;
tmp->name = $1;
1999-02-15 03:06:15 +01:00
tmp->parms = $4;
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;
}
1998-11-04 00:28:49 +01:00
| '(' expression_list ')'
{ lgate*tmp = new lgate;
tmp->name = "";
tmp->parms = $2;
tmp->file = @1.text;
tmp->lineno = @1.first_line;
1998-11-04 00:28:49 +01:00
$$ = tmp;
}
1999-05-08 22:19:20 +02:00
| IDENTIFIER '(' port_name_list ')'
{ lgate*tmp = new lgate;
tmp->name = $1;
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;
}
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_pulldown { $$ = PGBuiltin::PULLDOWN; }
| K_pullup { $$ = PGBuiltin::PULLUP; }
| 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; }
;
identifier
1999-06-16 05:13:29 +02:00
: IDENTIFIER
{ $$ = $1; }
| HIDENTIFIER
{ $$ = $1;
1998-11-04 00:28:49 +01:00
}
;
list_of_ports
1999-09-17 04:06:25 +02:00
: port_opt
{ 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
{ 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;
}
;
list_of_ports_opt
: '(' list_of_ports ')' { $$ = $2; }
| { $$ = 0; }
;
list_of_variables
: IDENTIFIER
{ list<string>*tmp = new list<string>;
1999-07-10 03:03:18 +02:00
tmp->push_back($1);
1998-11-04 00:28:49 +01:00
delete $1;
$$ = tmp;
}
| list_of_variables ',' IDENTIFIER
{ list<string>*tmp = $1;
1999-07-10 03:03:18 +02:00
tmp->push_back($3);
1998-11-04 00:28:49 +01:00
delete $3;
$$ = tmp;
}
;
/* An lavalue is the expression that can go on the left side of a
continuous assign statement. This checks (where it can) that the
expression meets the constraints of continuous assignments. */
lavalue
1999-06-16 05:13:29 +02:00
: identifier
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
}
1999-06-16 05:13:29 +02:00
| identifier '[' expression ']'
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
PExpr*sel = $3;
if (! pform_expression_is_constant(sel)) {
1999-09-29 23:16:32 +02:00
yyerror(@2, "eror: Bit select in lvalue must "
"contain a constant expression.");
delete sel;
} else {
tmp->msb_ = sel;
}
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
}
1999-06-16 05:13:29 +02:00
| identifier range
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
assert($2->count() == 2);
tmp->msb_ = (*$2)[0];
tmp->lsb_ = (*$2)[1];
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
delete $2;
$$ = tmp;
}
| '{' expression_list '}'
1999-07-10 04:19:26 +02:00
{ PEConcat*tmp = new PEConcat(*$2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $2;
1999-07-10 04:19:26 +02:00
$$ = tmp;
}
;
/* An lpvalue is the expression that can go on the left side of a
procedural assignment. This rule handles only procedural assignments. */
lpvalue
: identifier
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
}
1999-05-06 06:09:28 +02:00
| identifier '[' expression ']'
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
tmp->msb_ = $3;
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
1999-05-06 06:09:28 +02:00
}
| identifier '[' expression ':' expression ']'
1999-07-10 03:03:18 +02:00
{ PEIdent*tmp = new PEIdent($1);
tmp->msb_ = $3;
tmp->lsb_ = $5;
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
}
| '{' expression_list '}'
1999-07-10 04:19:26 +02:00
{ PEConcat*tmp = new PEConcat(*$2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $2;
1999-07-10 04:19:26 +02:00
$$ = tmp;
}
1998-11-04 00:28:49 +01:00
;
1999-08-27 17:08:37 +02:00
assign
: lavalue '=' expression
{ svector<PExpr*>*tmp = new svector<PExpr*>(2);
(*tmp)[0] = $1;
(*tmp)[1] = $3;
$$ = tmp;
}
;
assign_list
: assign_list ',' assign
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, *$3);
delete $1;
delete $3;
$$ = tmp;
}
| assign
{ $$ = $1; }
;
1998-11-04 00:28:49 +01:00
module
: K_module IDENTIFIER list_of_ports_opt ';'
1999-07-10 03:03:18 +02:00
{ pform_startmodule($2, $3);
1998-11-04 00:28:49 +01:00
}
module_item_list
K_endmodule
1999-07-10 03:03:18 +02:00
{ pform_endmodule($2);
1998-11-04 00:28:49 +01:00
delete $2;
}
1999-06-16 05:13:29 +02:00
| K_module IDENTIFIER list_of_ports_opt ';'
1999-07-10 03:03:18 +02:00
{ pform_startmodule($2, $3);
1999-06-16 05:13:29 +02:00
}
K_endmodule
1999-07-10 03:03:18 +02:00
{ pform_endmodule($2);
1999-06-16 05:13:29 +02:00
delete $2;
}
1998-11-04 00:28:49 +01:00
;
module_item
: net_type range_opt list_of_variables ';'
1999-06-02 17:38:46 +02:00
{ pform_makewire(@1, $3, $1);
1998-11-04 00:28:49 +01:00
if ($2) {
pform_set_net_range($3, $2);
delete $2;
}
delete $3;
}
1999-06-02 04:56:29 +02:00
| net_type range_opt net_decl_assigns ';'
1999-06-02 17:38:46 +02:00
{ pform_makewire(@1, $3, $1);
1999-06-02 04:56:29 +02:00
if ($2) {
pform_set_net_range($3, $2);
delete $2;
}
delete $3;
}
| K_trireg charge_strength_opt range_opt delay3_opt list_of_variables ';'
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "sorry: trireg nets not supported.");
1999-06-15 04:50:02 +02:00
delete $3;
}
1998-11-04 00:28:49 +01:00
| port_type range_opt list_of_variables ';'
{ pform_set_port_type($3, $1);
if ($2) {
pform_set_net_range($3, $2);
delete $2;
}
delete $3;
}
1999-09-10 07:02:09 +02:00
| block_item_decl
1999-06-16 05:13:29 +02:00
| K_defparam defparam_assign_list ';'
| K_event list_of_variables ';'
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
delete $2;
}
1999-02-21 18:01:57 +01:00
| K_parameter parameter_assign_list ';'
2000-03-12 18:09:40 +01:00
| K_localparam localparam_assign_list ';'
| gatetype delay3_opt gate_instance_list ';'
1998-11-04 00:28:49 +01:00
{ pform_makegates($1, $2, $3);
}
2000-01-02 00:47:58 +01:00
| IDENTIFIER parameter_value_opt gate_instance_list ';'
{ pform_make_modgates($1, $2, $3);
1998-11-04 00:28:49 +01:00
delete $1;
}
| K_assign drive_strength_opt delay3_opt assign_list ';'
1999-11-05 20:36:36 +01:00
{ pform_make_pgassign_list($4, $3, @1.text, @1.first_line); }
| K_assign error '=' expression ';'
1998-11-04 00:28:49 +01:00
| K_always statement
{ PProcess*tmp = pform_make_behavior(PProcess::PR_ALWAYS, $2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
1998-11-04 00:28:49 +01:00
}
| K_initial statement
{ PProcess*tmp = pform_make_behavior(PProcess::PR_INITIAL, $2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
1998-11-04 00:28:49 +01:00
}
1999-07-03 04:12:51 +02:00
| K_task IDENTIFIER ';'
1999-07-10 03:03:18 +02:00
{ pform_push_scope($2); }
1999-07-03 04:12:51 +02:00
task_body
{ pform_pop_scope(); }
K_endtask
{ PTask*tmp = $5;
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
1999-07-10 03:03:18 +02:00
pform_set_task($2, $5);
1999-07-03 04:12:51 +02:00
delete $2;
1999-05-08 22:19:20 +02:00
}
| K_function range_or_type_opt IDENTIFIER ';'
{ pform_push_scope($3); }
func_body
{ pform_pop_scope(); }
K_endfunction
{ PFunction *tmp = $6;
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
1999-08-26 00:22:41 +02:00
pform_set_function($3, $2, $6);
delete $3;
}
1999-06-12 05:42:57 +02:00
| K_specify specify_item_list K_endspecify
{
}
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')' ';'
1999-07-10 03:03:18 +02:00
{ pform_set_attrib($3, $5, $7);
delete $3;
delete $5;
delete $7;
}
| KK_attribute '(' error ')' ';'
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "error: Misformed $attribute parameter list."); }
1998-11-04 00:28:49 +01:00
;
module_item_list
: module_item_list module_item
| module_item
;
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
statement. */
net_decl_assign
: IDENTIFIER '=' expression
1999-07-10 03:03:18 +02:00
{ PEIdent*id = new PEIdent($1);
PGAssign*tmp = pform_make_pgassign(id, $3, 0);
1999-06-02 04:56:29 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = $1;
}
| delay1 IDENTIFIER '=' expression
1999-07-10 03:03:18 +02:00
{ PEIdent*id = new PEIdent($2);
PGAssign*tmp = pform_make_pgassign(id, $4, $1);
1999-06-12 05:42:57 +02:00
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = $2;
}
1999-06-02 04:56:29 +02:00
;
net_decl_assigns
: net_decl_assigns ',' net_decl_assign
{ list<string>*tmp = $1;
1999-07-10 03:03:18 +02:00
tmp->push_back($3);
1999-06-02 04:56:29 +02:00
delete $3;
$$ = tmp;
}
| net_decl_assign
{ list<string>*tmp = new list<string>;
1999-07-10 03:03:18 +02:00
tmp->push_back($1);
1999-06-02 04:56:29 +02:00
delete $1;
$$ = tmp;
}
;
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; }
;
1999-02-21 18:01:57 +01:00
parameter_assign
: IDENTIFIER '=' expression
{ 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.");
delete tmp;
tmp = 0;
}
1999-07-10 03:03:18 +02:00
pform_set_parameter($1, tmp);
1999-02-21 18:01:57 +01:00
delete $1;
}
;
parameter_assign_list
: parameter_assign
| range parameter_assign
1999-09-29 23:16:32 +02:00
{ yywarn(@1, "Ranges in parameter definition "
"are not supported.");
delete $1;
}
1999-02-21 18:01:57 +01:00
| parameter_assign_list ',' parameter_assign
;
2000-01-02 00:47:58 +01:00
2000-03-12 18:09:40 +01:00
/* Localparam assignments and asignment lists are broken into
separate BNF so that I can call slightly different paramter
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;
}
pform_set_localparam($1, tmp);
delete $1;
}
;
localparam_assign_list
: localparam_assign
| range localparam_assign
{ yywarn(@1, "Ranges in localparam definition "
"are not supported.");
delete $1;
}
| localparam_assign_list ',' localparam_assign
;
2000-01-02 00:47:58 +01:00
/* The parameters of a module instance can be overridden by writing
a list of expressions in a syntax much line a delay list. (The
difference being the list can have any length.) The pform that
attaches the expression list to the module checks that the
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
: '#' '(' expression_list ')'
{ 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;
}
| '#' NUMBER
{ assert($2);
PENumber*tmp = new PENumber($2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
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;
}
| '#' error
{ yyerror(@1, "error: syntax error in parameter value "
"assignment list.");
$$ = 0;
}
2000-01-02 00:47:58 +01:00
|
{ $$ = 0; }
;
parameter_value_byname
: PORTNAME '(' expression ')'
{ portname_t*tmp = new portname_t;
tmp->name = $1;
tmp->parm = $3;
free($1);
$$ = tmp;
}
| PORTNAME '(' ')'
{ portname_t*tmp = new portname_t;
tmp->name = $1;
tmp->parm = 0;
free($1);
$$ = tmp;
}
;
parameter_value_byname_list
: parameter_value_byname
{ svector<portname_t*>*tmp = new svector<portname_t*>(1);
(*tmp)[0] = $1;
$$ = tmp;
}
| parameter_value_byname_list ',' parameter_value_byname
{ svector<portname_t*>*tmp = new svector<portname_t*>(*$1,$3);
delete $1;
$$ = tmp;
}
;
/* The port (of a module) is a fairly complex item. Each port is
handled as a Module::port_t object. A simple port reference has a
name and a PWire object, but more complex constructs are possible
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
: port_reference
{ $$ = $1; }
| PORTNAME '(' port_reference ')'
{ Module::port_t*tmp = $3;
tmp->name = $1;
delete $1;
$$ = tmp;
}
| '{' port_reference_list '}'
{ Module::port_t*tmp = $2;
tmp->name = "";
$$ = tmp;
}
| PORTNAME '(' '{' port_reference_list '}' ')'
{ Module::port_t*tmp = $4;
tmp->name = $1;
delete $1;
$$ = tmp;
}
;
1999-09-17 04:06:25 +02:00
port_opt
: port { $$ = $1; }
| { $$ = 0; }
;
port_reference
1998-11-04 00:28:49 +01:00
: IDENTIFIER
{ Module::port_t*ptmp = new Module::port_t(1);
PWire*wtmp = new PWire($1, NetNet::IMPLICIT,
NetNet::PIMPLICIT);
wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line);
ptmp->name = $1;
ptmp->wires[0] = wtmp;
1998-11-04 00:28:49 +01:00
delete $1;
$$ = ptmp;
1998-11-04 00:28:49 +01:00
}
| IDENTIFIER '[' expression ':' expression ']'
{ PWire*wtmp = new PWire($1, NetNet::IMPLICIT,
NetNet::PIMPLICIT);
wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line);
if (!pform_expression_is_constant($3)) {
1999-09-29 23:16:32 +02:00
yyerror(@3, "error: msb expression of port bit select "
"must be constant.");
}
if (!pform_expression_is_constant($5)) {
1999-09-29 23:16:32 +02:00
yyerror(@5, "error: lsb expression of port bit select "
"must be constant.");
}
wtmp->set_range($3, $5);
Module::port_t*ptmp = new Module::port_t(1);
ptmp->name = $1;
ptmp->wires[0] = wtmp;
1998-11-04 00:28:49 +01:00
delete $1;
$$ = ptmp;
1998-11-04 00:28:49 +01:00
}
| IDENTIFIER '[' error ']'
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "error: invalid port bit select");
Module::port_t*ptmp = new Module::port_t(1);
PWire*wtmp = new PWire($1, NetNet::IMPLICIT,
NetNet::PIMPLICIT);
wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line);
ptmp->name = $1;
ptmp->wires[0] = wtmp;
1998-11-04 00:28:49 +01:00
delete $1;
$$ = ptmp;
1998-11-04 00:28:49 +01:00
}
;
port_reference_list
: port_reference
{ $$ = $1; }
| port_reference_list ',' port_reference
{ Module::port_t*tmp = $1;
tmp->wires = svector<PWire*>(tmp->wires, $3->wires);
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
: PORTNAME '(' expression ')'
1999-05-29 04:36:17 +02:00
{ portname_t*tmp = new portname_t;
tmp->name = $1;
1999-05-29 04:36:17 +02:00
tmp->parm = $3;
delete $1;
$$ = tmp;
1999-05-08 22:19:20 +02:00
}
| PORTNAME '(' error ')'
1999-09-29 23:16:32 +02:00
{ yyerror(@3, "error: invalid port connection expression.");
1999-05-29 04:36:17 +02:00
portname_t*tmp = new portname_t;
tmp->name = $1;
1999-05-29 04:36:17 +02:00
tmp->parm = 0;
delete $1;
1999-05-29 04:36:17 +02:00
$$ = tmp;
}
1999-05-08 22:19:20 +02:00
| PORTNAME '(' ')'
1999-05-29 04:36:17 +02:00
{ portname_t*tmp = new portname_t;
tmp->name = $1;
1999-05-29 04:36:17 +02:00
tmp->parm = 0;
delete $1;
$$ = tmp;
1999-05-08 22:19:20 +02:00
}
;
port_name_list
: port_name_list ',' port_name
1999-05-29 04:36:17 +02:00
{ svector<portname_t*>*tmp;
tmp = new svector<portname_t*>(*$1, $3);
delete $1;
$$ = tmp;
}
1999-05-08 22:19:20 +02:00
| port_name
1999-05-29 04:36:17 +02:00
{ svector<portname_t*>*tmp = new svector<portname_t*>(1);
(*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
: '[' expression ':' expression ']'
{ 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))
1999-09-29 23:16:32 +02:00
yyerror(@4, "error: msb 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; }
;
range_or_type_opt
1999-08-26 00:22:41 +02:00
: range { $$ = $1; }
| K_integer { $$ = 0; }
| K_real { $$ = 0; }
| K_realtime { $$ = 0; }
| K_time { $$ = 0; }
| { $$ = 0; }
;
/* 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
: IDENTIFIER
1999-07-10 03:03:18 +02:00
{ pform_makewire(@1, $1, NetNet::REG);
1998-11-04 00:28:49 +01:00
$$ = $1;
}
1999-06-12 22:35:27 +02:00
| IDENTIFIER '=' expression
1999-07-10 03:03:18 +02:00
{ pform_makewire(@1, $1, NetNet::REG);
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;
}
| IDENTIFIER '[' expression ':' expression ']'
1999-07-10 03:03:18 +02:00
{ pform_makewire(@1, $1, NetNet::REG);
if (! pform_expression_is_constant($3))
1999-09-29 23:16:32 +02:00
yyerror(@3, "error: msb of register range must be constant.");
if (! pform_expression_is_constant($5))
1999-09-29 23:16:32 +02:00
yyerror(@3, "error: lsb of register range must be constant.");
1999-07-10 03:03:18 +02:00
pform_set_reg_idx($1, $3, $5);
$$ = $1;
}
;
register_variable_list
: register_variable
{ list<string>*tmp = new list<string>;
1999-07-10 03:03:18 +02:00
tmp->push_back($1);
delete $1;
$$ = tmp;
}
| register_variable_list ',' register_variable
{ list<string>*tmp = $1;
1999-07-10 03:03:18 +02:00
tmp->push_back($3);
delete $3;
$$ = tmp;
}
1998-11-04 00:28:49 +01:00
;
1999-06-12 05:42:57 +02:00
specify_item
: K_specparam specparam_list ';'
1999-06-19 05:21:21 +02:00
| specify_simple_path '=' '(' expression_list ')' ';'
1999-09-29 23:16:32 +02:00
{ delete $4;
1999-06-19 05:21:21 +02:00
}
1999-06-12 05:42:57 +02:00
;
specify_item_list
: specify_item
| specify_item_list specify_item
;
1999-06-19 05:21:21 +02:00
specify_simple_path
: '(' IDENTIFIER spec_polarity K_EG IDENTIFIER ')'
| '(' IDENTIFIER spec_polarity K_SG IDENTIFIER ')'
;
1999-06-12 05:42:57 +02:00
specparam
: IDENTIFIER '=' expression
1999-09-29 23:16:32 +02:00
{ delete $1;
1999-06-12 05:42:57 +02:00
delete $3;
}
;
specparam_list
: specparam
| specparam_list ',' specparam
;
1999-06-19 05:21:21 +02:00
spec_polarity: '+' | '-' | ;
1998-11-04 00:28:49 +01:00
statement
: K_assign lavalue '=' expression ';'
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "sorry: procedural continuous assign not supported.");
$$ = 0;
}
| K_begin statement_list K_end
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ, *$2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $2;
$$ = tmp;
}
| K_begin ':' IDENTIFIER
1999-07-10 03:03:18 +02:00
{ pform_push_scope($3); }
block_item_decls_opt
statement_list K_end
{ pform_pop_scope();
1999-07-10 03:03:18 +02:00
PBlock*tmp = new PBlock($3, PBlock::BL_SEQ, *$6);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $3;
delete $6;
$$ = tmp;
}
| K_begin K_end
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_begin ':' IDENTIFIER K_end
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1999-06-12 05:42:57 +02:00
}
| K_begin error K_end
{ yyerrok; }
1999-06-16 05:13:29 +02:00
| K_deassign lavalue';'
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "sorry:, deassign not supported.");
1999-06-16 05:13:29 +02:00
$$ = 0;
}
1999-06-12 05:42:57 +02:00
| K_disable IDENTIFIER ';'
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "sorry: disable statements not supported.");
1999-06-12 05:42:57 +02:00
delete $2;
1999-06-12 22:35:27 +02:00
$$ = 0;
}
1999-06-16 05:13:29 +02:00
| K_force lavalue '=' expression ';'
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "sorry: procedural force assign not supported.");
1999-06-16 05:13:29 +02:00
$$ = 0;
}
| K_TRIGGER IDENTIFIER ';'
2000-04-01 21:31:57 +02:00
{ PTrigger*tmp = new PTrigger($2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
1999-06-12 22:35:27 +02:00
| K_forever statement
{ PForever*tmp = new PForever($2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1999-06-12 05:42:57 +02:00
}
1998-11-04 00:28:49 +01:00
| K_fork statement_list K_join
{ PBlock*tmp = new PBlock(PBlock::BL_PAR, *$2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $2;
$$ = tmp;
}
| K_fork ':' IDENTIFIER
{ pform_push_scope($3); }
block_item_decls_opt
statement_list K_join
{ pform_pop_scope();
PBlock*tmp = new PBlock($3, PBlock::BL_PAR, *$6);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $3;
delete $6;
$$ = tmp;
1999-06-12 22:35:27 +02:00
}
1998-11-04 00:28:49 +01:00
| K_fork K_join
{ PBlock*tmp = new PBlock(PBlock::BL_PAR);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_fork ':' IDENTIFIER K_join
{ PBlock*tmp = new PBlock(PBlock::BL_PAR);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_release lavalue ';'
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "sorry: release not supported.");
$$ = 0;
}
| K_repeat '(' expression ')' statement
{ PRepeat*tmp = new PRepeat($3, $5);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_case '(' expression ')' case_items K_endcase
1999-09-29 20:36:02 +02:00
{ PCase*tmp = new PCase(NetCase::EQ, $3, $5);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_casex '(' expression ')' case_items K_endcase
1999-09-29 20:36:02 +02:00
{ PCase*tmp = new PCase(NetCase::EQX, $3, $5);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_casez '(' expression ')' case_items K_endcase
1999-09-29 20:36:02 +02:00
{ PCase*tmp = new PCase(NetCase::EQZ, $3, $5);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = 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; }
| K_if '(' expression ')' statement_opt %prec less_than_K_else
{ PCondit*tmp = new PCondit($3, $5, 0);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_if '(' expression ')' statement_opt K_else statement_opt
{ PCondit*tmp = new PCondit($3, $5, $7);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_if '(' error ')' statement_opt %prec less_than_K_else
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $5;
}
| K_if '(' error ')' statement_opt K_else statement_opt
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $5;
}
| K_for '(' lpvalue '=' expression ';' expression ';'
lpvalue '=' expression ')' statement
{ PForStatement*tmp = new PForStatement($3, $5, $7, $9, $11, $13);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_for '(' lpvalue '=' expression ';' expression ';'
error ')' statement
{ $$ = 0;
1999-09-29 23:16:32 +02:00
yyerror(@9, "error: Error in for loop step assigment.");
}
| K_for '(' lpvalue '=' expression ';' error ';'
lpvalue '=' expression ')' statement
{ $$ = 0;
1999-09-29 23:16:32 +02:00
yyerror(@7, "error: Error in for loop condition expression.");
}
| K_for '(' error ')' statement
{ $$ = 0;
1999-09-29 23:16:32 +02:00
yyerror(@3, "error: Incomprehensible for loop.");
}
| K_while '(' expression ')' statement
1998-11-11 04:13:04 +01:00
{ PWhile*tmp = new PWhile($3, $5);
$$ = tmp;
}
| K_while '(' error ')' statement
{ $$ = 0;
1999-09-29 23:16:32 +02:00
yyerror(@3, "error: Error in while loop condition.");
}
| delay1 statement_opt
{ PExpr*del = (*$1)[0];
assert($1->count() == 1);
PDelayStatement*tmp = new PDelayStatement(del, $2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
1998-11-04 00:28:49 +01:00
$$ = tmp;
}
| event_control statement_opt
{ 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
}
| lpvalue '=' expression ';'
{ PAssign*tmp = new PAssign($1,$3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
}
| lpvalue K_LE expression ';'
{ PAssignNB*tmp = new PAssignNB($1,$3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
}
| lpvalue '=' delay1 expression ';'
{ assert($3->count() == 1);
PExpr*del = (*$3)[0];
PAssign*tmp = new PAssign($1,del,$4);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1999-05-08 22:19:20 +02: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);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
1999-09-22 04:00:48 +02:00
$$ = tmp;
}
| lpvalue '=' event_control expression ';'
{ PAssign*tmp = new PAssign($1,$3,$4);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| lpvalue '=' K_repeat '(' expression ')' event_control expression ';'
{ PAssign*tmp = new PAssign($1,$7,$8);
tmp->set_file(@1.text);
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);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = 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);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
1999-09-02 03:59:27 +02:00
$$ = tmp;
}
| K_wait '(' expression ')' statement_opt
{ PEventStatement*tmp;
PEEvent*etmp = new PEEvent(NetNEvent::POSITIVE, $3);
1999-04-29 04:16:26 +02:00
tmp = new PEventStatement(etmp);
tmp->set_statement($5);
$$ = tmp;
}
1998-11-04 00:28:49 +01:00
| SYSTEM_IDENTIFIER '(' expression_list ')' ';'
1999-07-10 03:03:18 +02:00
{ PCallTask*tmp = new PCallTask($1, *$3);
1999-07-03 04:12:51 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
delete $3;
$$ = tmp;
1998-11-04 00:28:49 +01:00
}
1999-06-16 05:13:29 +02:00
| SYSTEM_IDENTIFIER '(' ')' ';'
1999-07-03 04:12:51 +02:00
{ svector<PExpr*>pt (0);
1999-07-10 03:03:18 +02:00
PCallTask*tmp = new PCallTask($1, pt);
1999-07-03 04:12:51 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
1999-06-16 05:13:29 +02:00
}
1998-11-04 00:28:49 +01:00
| SYSTEM_IDENTIFIER ';'
1999-07-03 04:12:51 +02:00
{ svector<PExpr*>pt (0);
1999-07-10 03:03:18 +02:00
PCallTask*tmp = new PCallTask($1, pt);
1999-07-03 04:12:51 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
1998-11-04 00:28:49 +01:00
}
1999-06-16 05:13:29 +02:00
| identifier '(' expression_list ')' ';'
1999-07-10 03:03:18 +02:00
{ PCallTask*tmp = new PCallTask($1, *$3);
1999-07-03 04:12:51 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
delete $3;
$$ = tmp;
1999-06-16 05:13:29 +02:00
}
| identifier '(' ')' ';'
1999-07-03 04:12:51 +02:00
{ svector<PExpr*>pt (0);
1999-07-10 03:03:18 +02:00
PCallTask*tmp = new PCallTask($1, pt);
1999-07-03 04:12:51 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
1999-05-08 22:19:20 +02:00
}
1999-06-16 05:13:29 +02:00
| identifier ';'
1999-07-03 04:12:51 +02:00
{ svector<PExpr*>pt (0);
1999-07-10 03:03:18 +02:00
PCallTask*tmp = new PCallTask($1, pt);
1999-07-03 04:12:51 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
1999-05-08 22:19:20 +02:00
}
1998-11-04 00:28:49 +01:00
| error ';'
1999-09-29 23:16:32 +02:00
{ yyerror(@1, "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
{ svector<Statement*>*tmp = new svector<Statement*>(*$1, $2);
delete $1;
1998-11-04 00:28:49 +01:00
$$ = tmp;
}
| statement
{ svector<Statement*>*tmp = new svector<Statement*>(1);
(*tmp)[0] = $1;
1998-11-04 00:28:49 +01:00
$$ = tmp;
}
;
statement_opt
: statement
| ';' { $$ = 0; }
;
task_body
1999-06-12 05:42:57 +02:00
: task_item_list_opt statement_opt
1999-07-24 04:11:19 +02:00
{ PTask*tmp = new PTask($1, $2);
1999-07-03 04:12:51 +02:00
$$ = tmp;
}
;
task_item
: block_item_decl
1999-09-10 07:02:09 +02:00
{ $$ = new svector<PWire*>(0); }
| K_input range_opt list_of_variables ';'
1999-07-24 04:11:19 +02:00
{ svector<PWire*>*tmp
1999-09-10 07:02:09 +02:00
= pform_make_task_ports(NetNet::PINPUT, $2,
$3, @1.text, @1.first_line);
1999-07-24 04:11:19 +02:00
delete $2;
delete $3;
$$ = tmp;
1999-07-03 04:12:51 +02:00
}
| K_output range_opt list_of_variables ';'
1999-07-24 04:11:19 +02:00
{ svector<PWire*>*tmp
1999-09-10 07:02:09 +02:00
= pform_make_task_ports(NetNet::POUTPUT, $2, $3,
@1.text, @1.first_line);
1999-07-24 04:11:19 +02:00
delete $2;
delete $3;
$$ = tmp;
1999-07-03 04:12:51 +02:00
}
| K_inout range_opt list_of_variables ';'
1999-07-24 04:11:19 +02:00
{ svector<PWire*>*tmp
1999-09-10 07:02:09 +02:00
= pform_make_task_ports(NetNet::PINOUT, $2, $3,
@1.text, @1.first_line);
1999-07-24 04:11:19 +02:00
delete $2;
delete $3;
$$ = tmp;
1999-07-03 04:12:51 +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;
}
| task_item
1999-07-24 04:11:19 +02:00
{ $$ = $1; }
;
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
;
udp_body
: K_table { lex_start_table(); }
udp_entry_list
K_endtable { lex_end_table(); $$ = $3; }
;
udp_entry_list
: udp_comb_entry_list
| udp_sequ_entry_list
;
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;
$$ = tmp;
}
;
udp_comb_entry_list
: udp_comb_entry
{ list<string>*tmp = new list<string>;
1999-07-10 03:03:18 +02:00
tmp->push_back($1);
delete $1;
$$ = tmp;
}
| udp_comb_entry_list udp_comb_entry
{ list<string>*tmp = $1;
1999-07-10 03:03:18 +02:00
tmp->push_back($2);
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);
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);
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;
$$ = tmp;
}
;
udp_initial
: K_initial IDENTIFIER '=' NUMBER ';'
{ PExpr*etmp = new PENumber($4);
1999-07-10 03:03:18 +02:00
PEIdent*itmp = new PEIdent($2);
PAssign*atmp = new PAssign(itmp, etmp);
atmp->set_file(@2.text);
atmp->set_lineno(@2.first_line);
delete $2;
$$ = atmp;
}
;
udp_init_opt
: udp_initial { $$ = $1; }
| { $$ = 0; }
;
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;
$$ = tmp;
}
| 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;
$$ = tmp;
}
;
udp_input_sym
: '0' { $$ = '0'; }
| '1' { $$ = '1'; }
| 'x' { $$ = 'x'; }
| '?' { $$ = '?'; }
| 'b' { $$ = 'b'; }
| '*' { $$ = '*'; }
2000-03-05 19:26:51 +01:00
| '%' { $$ = '%'; }
| 'f' { $$ = 'f'; }
2000-03-05 19:26:51 +01:00
| 'F' { $$ = 'F'; }
| 'r' { $$ = 'r'; }
2000-03-05 19:26:51 +01:00
| 'R' { $$ = 'R'; }
| 'n' { $$ = 'n'; }
2000-03-05 19:26:51 +01:00
| 'N' { $$ = 'N'; }
| 'p' { $$ = 'p'; }
2000-03-05 19:26:51 +01:00
| 'P' { $$ = 'P'; }
| '_' { $$ = '_'; }
2000-03-05 19:26:51 +01:00
| '+' { $$ = '+'; }
;
udp_output_sym
: '0' { $$ = '0'; }
| '1' { $$ = '1'; }
| 'x' { $$ = 'x'; }
| '-' { $$ = '-'; }
;
udp_port_decl
: K_input list_of_variables ';'
{ $$ = pform_make_udp_input_ports($2); }
| K_output IDENTIFIER ';'
1999-07-10 03:03:18 +02:00
{ PWire*pp = new PWire($2, NetNet::IMPLICIT, NetNet::POUTPUT);
1999-06-12 22:35:27 +02:00
svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp;
delete $2;
$$ = tmp;
}
| K_reg IDENTIFIER ';'
1999-07-10 03:03:18 +02:00
{ PWire*pp = new PWire($2, NetNet::REG, NetNet::PIMPLICIT);
1999-06-12 22:35:27 +02:00
svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp;
delete $2;
$$ = tmp;
}
;
udp_port_decls
: udp_port_decl
{ $$ = $1; }
| udp_port_decls udp_port_decl
1999-06-12 22:35:27 +02:00
{ svector<PWire*>*tmp = new svector<PWire*>(*$1, *$2);
delete $1;
delete $2;
$$ = tmp;
}
;
udp_port_list
: IDENTIFIER
{ list<string>*tmp = new list<string>;
1999-07-10 03:03:18 +02:00
tmp->push_back($1);
delete $1;
$$ = tmp;
}
| udp_port_list ',' IDENTIFIER
{ list<string>*tmp = $1;
1999-07-10 03:03:18 +02:00
tmp->push_back($3);
delete $3;
$$ = tmp;
}
;
udp_primitive
: K_primitive IDENTIFIER '(' udp_port_list ')' ';'
udp_port_decls
udp_init_opt
udp_body
K_endprimitive
1999-07-10 03:03:18 +02:00
{ pform_make_udp($2, $4, $7, $9, $8);
delete[]$2;
}
;