iverilog/parse.y

1565 lines
36 KiB
Plaintext
Raw Normal View History

1998-11-04 00:28:49 +01:00
%{
/*
1999-04-29 04:16:26 +02:00
* Copyright (c) 1998-1999 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)
1999-06-13 19:30:23 +02:00
#ident "$Id: parse.y,v 1.40 1999/06/13 17:30:23 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;
1998-11-04 00:28:49 +01:00
string*text;
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
1999-05-29 04:36:17 +02:00
portname_t*portname;
svector<portname_t*>*portnames;
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;
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;
list<Statement*>*statement_list;
verinum* number;
};
1999-05-08 22:19:20 +02:00
%token <text> IDENTIFIER PORTNAME SYSTEM_IDENTIFIER STRING
1998-11-04 00:28:49 +01:00
%token <number> NUMBER
%token K_LE K_GE K_EQ K_NE K_CEQ K_CNE K_LS K_RS
1999-06-13 19:30:23 +02:00
%token K_LOR K_LAND K_NAND K_NOR K_NXOR
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
%token K_initial K_inout K_input K_integer K_join K_large K_macromodule
%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
%token K_trior K_vectored K_wait K_wand K_weak0 K_weak1 K_while K_wire
%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
1998-11-04 00:28:49 +01:00
%type <wire> port
%type <wires> list_of_ports list_of_ports_opt
1999-05-29 04:36:17 +02:00
%type <portname> port_name
%type <portnames> port_name_list
%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> delay delay_opt delay_value delay_value_list
%type <expr> expression expr_primary
%type <expr> lavalue lpvalue
1998-11-04 00:28:49 +01:00
%type <exprs> expression_list
%type <exprs> range range_opt
%type <nettype> net_type
%type <gatetype> gatetype
%type <porttype> port_type
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
%left '?' ':'
%left K_LOR
%left K_LAND
%left '|'
%left '^'
%left '&'
%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
%%
source_file
: description
| source_file description
;
case_item
1999-06-12 05:42:57 +02:00
: expression_list ':' statement_opt
{ PCase::Item*tmp = new PCase::Item;
1999-06-12 05:42:57 +02:00
if ($1->count() > 1) {
yyerror(@1, "Sorry, case expression lists not supported.");
}
tmp->expr = (*$1)[0];
tmp->stat = $3;
$$ = tmp;
}
| K_default ':' statement_opt
{ PCase::Item*tmp = new PCase::Item;
tmp->expr = 0;
tmp->stat = $3;
$$ = tmp;
}
| K_default statement_opt
{ PCase::Item*tmp = new PCase::Item;
tmp->expr = 0;
tmp->stat = $2;
$$ = tmp;
}
1999-06-12 05:42:57 +02:00
| error ':' statement_opt
{ yyerror(@1, "Incomprehensible case expression.");
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;
}
;
1998-11-04 00:28:49 +01:00
delay
: '#' delay_value
{ $$ = $2;
}
| '#' '(' delay_value_list ')'
{ $$ = $3;
}
;
delay_opt
: delay { $$ = $1; }
| { $$ = 0; }
;
delay_value
: NUMBER
{ verinum*tmp = $1;
if (tmp == 0) {
yyerror(@1, "XXXX internal error: delay.");
$$ = 0;
} else {
$$ = new PENumber(tmp);
}
1998-11-04 00:28:49 +01:00
}
| IDENTIFIER
{ 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
;
delay_value_list
1999-06-12 22:35:27 +02:00
: expression
{ $$ = $1; }
1999-06-12 22:35:27 +02:00
| delay_value_list ',' expression
{ yyerror(@1, "Sorry, delay value lists not supported.");
$$ = $1;
delete $3;
}
1998-11-04 00:28:49 +01:00
;
description
: module
| udp_primitive
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')'
{ pform_set_type_attrib(*$3, *$5, *$7);
delete $3;
delete $5;
delete $7;
}
1998-11-04 00:28:49 +01:00
;
event_control
: '@' IDENTIFIER
{ yyerror(@1, "Sorry, event control not supported.");
$$ = 0;
}
| '@' '(' event_expression ')'
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 ')'
{ yyerror(@1, "Malformed event control expression.");
$$ = 0;
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;
}
| event_expression 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
}
;
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-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;
}
| IDENTIFIER '(' expression_list ')'
{ yyerror(@2, "Sorry, function calls not supported.");
$$ = 0;
}
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
{ if ($1 == 0) {
yyerror(@1, "XXXX No number value in primary?");
$$ = 0;
} else {
PENumber*tmp = new PENumber($1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
1998-11-04 00:28:49 +01:00
}
| STRING
1999-05-27 05:31:29 +02:00
{ PEString*tmp = new PEString(*$1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1998-11-04 00:28:49 +01:00
delete $1;
}
| identifier
{ 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-05-27 05:31:29 +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;
}
| identifier '[' expression ']'
{ 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 ']'
{ 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;
}
| '(' expression ')'
{ $$ = $2; }
| '(' expression ':' expression ':' expression ')'
{ yyerror(@2, "Sorry, (min:typ:max) not supported.");
$$ = $4;
delete $2;
delete $6;
}
| '{' 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)) {
yyerror(@2, "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
;
function_item
: K_input range_opt list_of_variables ';'
| K_reg range_opt list_of_variables ';'
;
function_item_list
: function_item
| function_item_list function_item
;
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;
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;
1999-02-15 03:06:15 +01:00
tmp->name = *$1;
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
: identifier '.' IDENTIFIER
{ yyerror(@1, "Sorry, qualified identifiers not supported.");
$$ = $3;
delete $1;
}
| IDENTIFIER
{ $$ = $1; }
;
list_of_ports
: port
1999-06-12 22:35:27 +02:00
{ svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = $1;
1998-11-04 00:28:49 +01:00
$$ = tmp;
}
| list_of_ports ',' port
1999-06-12 22:35:27 +02:00
{ svector<PWire*>*tmp = new svector<PWire*>(*$1, $3);
delete $1;
1998-11-04 00:28:49 +01:00
$$ = tmp;
}
;
list_of_ports_opt
: '(' list_of_ports ')' { $$ = $2; }
| '(' ')' { $$ = 0; }
| { $$ = 0; }
;
list_of_variables
: IDENTIFIER
{ list<string>*tmp = new list<string>;
tmp->push_back(*$1);
delete $1;
$$ = tmp;
}
| list_of_variables ',' IDENTIFIER
{ list<string>*tmp = $1;
tmp->push_back(*$3);
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
: IDENTIFIER
{ PEIdent*tmp = new PEIdent(*$1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
}
| IDENTIFIER '[' expression ']'
{ PEIdent*tmp = new PEIdent(*$1);
PExpr*sel = $3;
if (! pform_expression_is_constant(sel)) {
yyerror(@2, "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;
}
| IDENTIFIER range
{ 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 '}'
{ yyerror(@1, "Sorry, concatenation expressions"
" not supported in lvalue.");
$$ = 0;
delete $2;
}
;
/* An lpvalue is the expression that can go on the left side of a
procedural assignment. This rule handles only procedural assignments. */
lpvalue
: identifier
{ 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 ']'
{ 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 ']'
{ 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 '}'
{ yyerror(@1, "Sorry, concatenation expressions"
" not supported in lvalue.");
$$ = 0;
delete $2;
}
1998-11-04 00:28:49 +01:00
;
module
: K_module IDENTIFIER list_of_ports_opt ';'
{ pform_startmodule(*$2, $3);
}
module_item_list
K_endmodule
{ pform_endmodule(*$2);
delete $2;
}
;
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;
}
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;
}
| K_reg range register_variable_list ';'
{ pform_set_net_range($3, $2);
delete $2;
1998-11-04 00:28:49 +01:00
delete $3;
}
| K_reg register_variable_list ';'
{ delete $2; }
| K_integer register_variable_list ';'
{ pform_set_reg_integer($2);
delete $2;
}
1999-02-21 18:01:57 +01:00
| K_parameter parameter_assign_list ';'
1998-11-04 00:28:49 +01:00
| gatetype delay_opt gate_instance_list ';'
{ pform_makegates($1, $2, $3);
}
| IDENTIFIER delay_opt gate_instance_list ';'
{ pform_make_modgates(*$1, $3);
1998-11-04 00:28:49 +01:00
delete $1;
if ($2) {
yyerror(@2, "Sorry, parameter override not supported.");
delete $2;
}
1998-11-04 00:28:49 +01:00
}
1999-06-12 05:42:57 +02:00
| K_assign delay_opt lavalue '=' expression ';'
{ PGAssign*tmp = pform_make_pgassign($3, $5);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
1999-06-12 05:42:57 +02:00
if ($2) {
yyerror(@2, "Sorry, assign delays not supported.");
delete $2;
}
}
| 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
}
| K_task IDENTIFIER ';' task_body K_endtask
1999-05-08 22:19:20 +02:00
{ yyerror(@1, "Sorry, task declarations not supported.");
}
| K_function range_or_type_opt IDENTIFIER ';' func_body K_endfunction
{ yyerror(@1, "Sorry, function declarations not supported.");
}
1999-06-12 05:42:57 +02:00
| K_specify specify_item_list K_endspecify
{
}
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')' ';'
{ pform_set_attrib(*$3, *$5, *$7);
delete $3;
delete $5;
delete $7;
}
| KK_attribute '(' error ')' ';'
{ yyerror(@1, "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
{ PEIdent*id = new PEIdent(*$1);
PGAssign*tmp = pform_make_pgassign(id, $3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = $1;
}
1999-06-12 05:42:57 +02:00
| delay IDENTIFIER '=' expression
{ PEIdent*id = new PEIdent(*$2);
PGAssign*tmp = pform_make_pgassign(id, $4);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = $2;
yyerror(@1, "Sorry, net assign delay not supported.");
}
1999-06-02 04:56:29 +02:00
;
net_decl_assigns
: net_decl_assigns ',' net_decl_assign
{ list<string>*tmp = $1;
tmp->push_back(*$3);
delete $3;
$$ = tmp;
}
| net_decl_assign
{ list<string>*tmp = new list<string>;
tmp->push_back(*$1);
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)) {
yyerror(@3, "parameter value must be constant.");
delete tmp;
tmp = 0;
}
pform_set_parameter(*$1, tmp);
1999-02-21 18:01:57 +01:00
delete $1;
}
;
parameter_assign_list
: parameter_assign
| range parameter_assign
{ yyerror(@1, "Ranges in parameter definition "
"are not supported.");
delete $1;
}
1999-02-21 18:01:57 +01:00
| parameter_assign_list ',' parameter_assign
;
1998-11-04 00:28:49 +01:00
port
: IDENTIFIER
{ $$ = new PWire(*$1, NetNet::IMPLICIT);
$$->port_type = NetNet::PIMPLICIT;
1999-06-02 17:38:46 +02:00
$$->set_file(@1.text);
$$->set_lineno(@1.first_line);
1998-11-04 00:28:49 +01:00
delete $1;
}
| IDENTIFIER '[' expression ':' expression ']'
{ PWire*tmp = new PWire(*$1, NetNet::IMPLICIT);
tmp->port_type = NetNet::PIMPLICIT;
1999-06-02 17:38:46 +02:00
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
if (!pform_expression_is_constant($3)) {
yyerror(@3, "msb expression of port bit select "
"must be constant.");
delete $3;
} else {
tmp->msb = $3;
}
if (!pform_expression_is_constant($5)) {
yyerror(@3, "lsb expression of port bit select "
"must be constant.");
delete $5;
} else {
1999-06-12 05:42:57 +02:00
tmp->lsb = $5;
}
1998-11-04 00:28:49 +01:00
delete $1;
$$ = tmp;
1998-11-04 00:28:49 +01:00
}
| IDENTIFIER '[' error ']'
{ yyerror(@1, "invalid port bit select");
$$ = new PWire(*$1, NetNet::IMPLICIT);
$$->port_type = NetNet::PIMPLICIT;
1999-06-02 17:38:46 +02:00
$$->set_file(@1.text);
$$->set_lineno(@1.first_line);
1998-11-04 00:28:49 +01:00
delete $1;
}
;
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;
tmp->parm = $3;
delete $1;
$$ = tmp;
1999-05-08 22:19:20 +02:00
}
| PORTNAME '(' error ')'
{ yyerror(@3, "invalid port connection expression.");
1999-05-29 04:36:17 +02:00
portname_t*tmp = new portname_t;
tmp->name = *$1;
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;
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);
if (!pform_expression_is_constant($2)) {
yyerror(@2, "msb of range must be constant.");
delete $2;
} else {
(*tmp)[0] = $2;
}
if (!pform_expression_is_constant($4)) {
yyerror(@4, "msb of range must be constant.");
delete $4;
} else {
(*tmp)[1] = $4;
}
1998-11-04 00:28:49 +01:00
$$ = tmp;
}
;
range_opt
: range
| { $$ = 0; }
;
range_or_type_opt
: range { }
| K_integer
| K_real
| K_realtime
| K_time
|
;
/* 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-06-02 17:38:46 +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
{ pform_makewire(@1, *$1, NetNet::REG);
yyerror(@2, "net declaration assignment to reg/integer not allowed.");
delete $3;
$$ = $1;
}
| IDENTIFIER '[' expression ':' expression ']'
1999-06-02 17:38:46 +02:00
{ pform_makewire(@1, *$1, NetNet::REG);
if (! pform_expression_is_constant($3))
yyerror(@3, "msb of register range must be constant.");
if (! pform_expression_is_constant($5))
yyerror(@3, "lsb of register range must be constant.");
pform_set_reg_idx(*$1, $3, $5);
$$ = $1;
}
;
register_variable_list
: register_variable
{ list<string>*tmp = new list<string>;
tmp->push_back(*$1);
delete $1;
$$ = tmp;
}
| register_variable_list ',' register_variable
{ list<string>*tmp = $1;
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 ';'
;
specify_item_list
: specify_item
| specify_item_list specify_item
;
specparam
: IDENTIFIER '=' expression
{ yyerror(@1, "Sorry, specparam assignments not supported.");
delete $1;
delete $3;
}
;
specparam_list
: specparam
| specparam_list ',' specparam
;
1998-11-04 00:28:49 +01:00
statement
: K_assign lavalue '=' expression ';'
{ yyerror(@1, "Sorry, procedural continuous assign not supported.");
$$ = 0;
}
| K_begin statement_list K_end
1998-11-04 00:28:49 +01:00
{ $$ = pform_make_block(PBlock::BL_SEQ, $2); }
1999-06-12 05:42:57 +02:00
| K_begin ':' IDENTIFIER statement_list K_end
{ yyerror(@3, "Sorry, block identifiers not supported.");
$$ = pform_make_block(PBlock::BL_SEQ, $4);
}
| K_begin error K_end
{ yyerrok; }
| K_disable IDENTIFIER ';'
{ yyerror(@1, "Sorry, disable statements not supported.");
delete $2;
1999-06-12 22:35:27 +02:00
$$ = 0;
}
| K_forever statement
{ yyerror(@1, "Sorry, forever statements not supported.");
delete $2;
$$ = 0;
1999-06-12 05:42:57 +02:00
}
1998-11-04 00:28:49 +01:00
| K_fork statement_list K_join
{ $$ = pform_make_block(PBlock::BL_PAR, $2); }
1999-06-12 22:35:27 +02:00
| K_repeat '(' expression ')' statement
{ yyerror(@1, "Sorry, repeat statements not supported.");
delete $3;
delete $5;
$$ = 0;
}
1998-11-04 00:28:49 +01:00
| K_begin K_end
{ $$ = pform_make_block(PBlock::BL_SEQ, 0); }
1999-06-12 05:42:57 +02:00
| K_begin ':' IDENTIFIER K_end
{ $$ = pform_make_block(PBlock::BL_SEQ, 0); }
1998-11-04 00:28:49 +01:00
| K_fork K_join
{ $$ = pform_make_block(PBlock::BL_PAR, 0); }
| K_case '(' expression ')' case_items K_endcase
{ PCase*tmp = new PCase($3, $5);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_casex '(' expression ')' case_items K_endcase
{ PCase*tmp = new PCase($3, $5);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
yywarn(@1, "casex not properly supported, using case.");
$$ = tmp;
}
| K_casez '(' expression ')' case_items K_endcase
{ PCase*tmp = new PCase($3, $5);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
yywarn(@1, "casez not properly supported, using case.");
$$ = 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
{ 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
{ yyerror(@1, "Malformed conditional expression.");
$$ = $5;
}
| K_if '(' error ')' statement_opt K_else statement_opt
{ yyerror(@1, "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;
yyerror(@9, "Error in for loop step assigment.");
}
| K_for '(' lpvalue '=' expression ';' error ';'
lpvalue '=' expression ')' statement
{ $$ = 0;
yyerror(@7, "Error in for loop condition expression.");
}
| K_for '(' error ')' statement
{ $$ = 0;
yyerror(@3, "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;
yyerror(@3, "Error in while loop condition.");
}
1998-11-04 00:28:49 +01:00
| delay statement_opt
{ PDelayStatement*tmp = new PDelayStatement($1, $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) {
yyerror(@1, "Invalid event control.");
$$ = 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
}
1999-05-08 22:19:20 +02:00
| lpvalue '=' delay expression ';'
{ yyerror(@1, "Sorry, assignment timing control not implemented.");
PAssign*tmp = new PAssign($1,$3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
1999-05-08 22:19:20 +02:00
}
| 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 ')' ';'
{ $$ = pform_make_calltask($1, $3);
}
| SYSTEM_IDENTIFIER ';'
{ $$ = pform_make_calltask($1);
}
1999-05-08 22:19:20 +02:00
| IDENTIFIER '(' expression_list ')' ';'
{ yyerror(@1, "Sorry, task enabling not implemented.");
$$ = new PNoop;
}
| IDENTIFIER ';'
{ yyerror(@1, "Sorry, task enabling not implemented.");
$$ = new PNoop;
}
1998-11-04 00:28:49 +01:00
| error ';'
{ yyerror(@1, "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
{ list<Statement*>*tmp = $1;
tmp->push_back($2);
$$ = tmp;
}
| statement
{ list<Statement*>*tmp = new list<Statement*>();
tmp->push_back($1);
$$ = tmp;
}
;
statement_opt
: statement
| ';' { $$ = 0; }
;
task_body
1999-06-12 05:42:57 +02:00
: task_item_list_opt statement_opt
;
task_item
: K_input range_opt list_of_variables ';'
| K_output range_opt list_of_variables ';'
| K_inout range_opt list_of_variables ';'
| K_reg range_opt list_of_variables ';'
;
task_item_list
: task_item_list task_item
| task_item
;
1999-06-12 05:42:57 +02:00
task_item_list_opt
: task_item_list
|
;
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 ';'
{ string*tmp = $1;
*tmp += ':';
*tmp += $3;
$$ = tmp;
}
;
udp_comb_entry_list
: udp_comb_entry
{ list<string>*tmp = new list<string>;
tmp->push_back(*$1);
delete $1;
$$ = tmp;
}
| udp_comb_entry_list udp_comb_entry
{ list<string>*tmp = $1;
tmp->push_back(*$2);
delete $2;
$$ = tmp;
}
;
udp_sequ_entry_list
: udp_sequ_entry
{ list<string>*tmp = new list<string>;
tmp->push_back(*$1);
delete $1;
$$ = tmp;
}
| udp_sequ_entry_list udp_sequ_entry
{ list<string>*tmp = $1;
tmp->push_back(*$2);
delete $2;
$$ = tmp;
}
;
udp_sequ_entry
: udp_input_list ':' udp_input_sym ':' udp_output_sym ';'
{ string*tmp = $1;
*tmp += ':';
*tmp += $3;
*tmp += ':';
*tmp += $5;
$$ = tmp;
}
;
udp_initial
: K_initial IDENTIFIER '=' NUMBER ';'
{ PExpr*etmp = new PENumber($4);
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
{ string*tmp = new string;
*tmp += $1;
$$ = tmp;
}
| udp_input_list udp_input_sym
{ string*tmp = $1;
*tmp += $2;
$$ = tmp;
}
;
udp_input_sym
: '0' { $$ = '0'; }
| '1' { $$ = '1'; }
| 'x' { $$ = 'x'; }
| '?' { $$ = '?'; }
| 'b' { $$ = 'b'; }
| '*' { $$ = '*'; }
| 'f' { $$ = 'f'; }
| 'r' { $$ = 'r'; }
| 'n' { $$ = 'n'; }
| 'p' { $$ = 'p'; }
| '_' { $$ = '_'; }
;
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 ';'
{ PWire*pp = new PWire(*$2);
pp->port_type = 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 ';'
{ PWire*pp = new PWire(*$2, NetNet::REG);
pp->port_type = 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>;
tmp->push_back(*$1);
delete $1;
$$ = tmp;
}
| udp_port_list ',' IDENTIFIER
{ list<string>*tmp = $1;
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
{ pform_make_udp($2, $4, $7, $9, $8); }
;