OpenSTA/verilog/VerilogParse.yy

528 lines
12 KiB
Plaintext
Raw Normal View History

2018-09-28 17:54:21 +02:00
%{
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2024, Parallax Software, Inc.
2018-09-28 17:54:21 +02:00
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 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
2018-09-28 17:54:21 +02:00
// 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, see <https://www.gnu.org/licenses/>.
2018-09-28 17:54:21 +02:00
#include <cstdlib>
2022-07-11 17:49:12 +02:00
#include <string>
#include <iostream>
2020-04-05 20:35:51 +02:00
2020-04-05 23:53:44 +02:00
#include "PortDirection.hh"
2020-04-05 20:35:51 +02:00
#include "verilog/VerilogReaderPvt.hh"
2020-04-06 01:56:38 +02:00
#include "VerilogReader.hh"
2018-09-28 17:54:21 +02:00
int VerilogLex_lex();
#define VerilogParse_lex VerilogLex_lex
// Use yacc generated parser errors.
#define YYERROR_VERBOSE
%}
%union{
int ival;
const char *string;
const char *constant;
const char *attribute_spec_value;
2018-09-28 17:54:21 +02:00
sta::VerilogModule *module;
sta::VerilogStmt *stmt;
sta::VerilogStmtSeq *stmt_seq;
sta::PortDirection *port_type;
sta::VerilogDclArgSeq *dcl_arg_seq;
sta::VerilogDclArg *dcl_arg;
sta::VerilogAssign *assign;
sta::VerilogInst *inst;
sta::VerilogNet *net;
sta::VerilogNetBitSelect *net_bit;
sta::VerilogNetSeq *nets;
2022-07-11 17:49:12 +02:00
sta::VerilogAttributeEntry *attribute_entry;
sta::VerilogAttributeEntrySeq *attribute_seq;
sta::VerilogAttributeStmt *attribute_stmt;
sta::VerilogAttributeStmtSeq *attribute_stmt_seq;
2018-09-28 17:54:21 +02:00
}
%token INT CONSTANT ID STRING MODULE ENDMODULE ASSIGN PARAMETER DEFPARAM
%token WIRE WAND WOR TRI INPUT OUTPUT INOUT SUPPLY1 SUPPLY0 REG
2022-07-11 17:49:12 +02:00
%token ATTRIBUTE_OPEN ATTRIBUTE_CLOSED
2018-09-28 17:54:21 +02:00
%left '-' '+'
%left '*' '/'
%left NEG /* negation--unary minus */
%type <string> ID STRING
%type <ival> WIRE WAND WOR TRI INPUT OUTPUT INOUT SUPPLY1 SUPPLY0
2022-07-11 17:49:12 +02:00
%type <ival> ATTRIBUTE_OPEN ATTRIBUTE_CLOSED
2018-09-28 17:54:21 +02:00
%type <ival> INT parameter_exprs parameter_expr module_begin
%type <constant> CONSTANT
2022-07-11 17:49:12 +02:00
%type <attribute_spec_value> attr_spec_value
2018-09-28 17:54:21 +02:00
%type <port_type> dcl_type port_dcl_type
%type <stmt> stmt declaration instance parameter parameter_dcls parameter_dcl
%type <stmt> defparam param_values param_value port_dcl
%type <stmt_seq> stmts stmt_seq net_assignments continuous_assign port_dcls
%type <assign> net_assignment
%type <dcl_arg> dcl_arg
%type <dcl_arg_seq> dcl_args
2021-01-19 19:17:13 +01:00
%type <net> port net_scalar net_bit_select net_part_select net_assign_lhs
2018-09-28 17:54:21 +02:00
%type <net> net_constant net_expr port_ref port_expr named_pin_net_expr
%type <net> inst_named_pin net_named net_expr_concat
%type <nets> port_list port_refs inst_ordered_pins
%type <nets> inst_named_pins net_exprs inst_pins
2022-07-11 17:49:12 +02:00
%type <attribute_entry> attr_spec
%type <attribute_seq> attr_specs
%type <attribute_stmt> attribute_instance
%type <attribute_stmt_seq> attribute_instance_seq
2018-09-28 17:54:21 +02:00
%start file
%{
%}
%%
file:
modules
;
modules:
// empty
| modules module
;
module_begin:
MODULE { $<ival>$ = sta::verilog_reader->line(); }
{ $$ = $<ival>2; }
;
module:
2022-07-11 17:49:12 +02:00
attribute_instance_seq module_begin ID ';' stmts ENDMODULE
{ sta::verilog_reader->makeModule($3, new sta::VerilogNetSeq, $5, $1, $2);}
| attribute_instance_seq module_begin ID '(' ')' ';' stmts ENDMODULE
{ sta::verilog_reader->makeModule($3, new sta::VerilogNetSeq, $7, $1, $2);}
| attribute_instance_seq module_begin ID '(' port_list ')' ';' stmts ENDMODULE
{ sta::verilog_reader->makeModule($3, $5, $8, $1, $2); }
| attribute_instance_seq module_begin ID '(' port_dcls ')' ';' stmts ENDMODULE
{ sta::verilog_reader->makeModule($3, $5, $8, $1, $2); }
2018-09-28 17:54:21 +02:00
;
port_list:
port
{ $$ = new sta::VerilogNetSeq;
$$->push_back($1);
}
| port_list ',' port
{ $1->push_back($3); }
;
port:
port_expr
| '.' ID '(' ')'
{ $$=sta::verilog_reader->makeNetNamedPortRefScalar($2, NULL);}
| '.' ID '(' port_expr ')'
{ $$=sta::verilog_reader->makeNetNamedPortRefScalar($2, $4);}
;
port_expr:
port_ref
| '{' port_refs '}'
{ $$ = sta::verilog_reader->makeNetConcat($2); } ;
port_refs:
port_ref
{ $$ = new sta::VerilogNetSeq;
$$->push_back($1);
}
| port_refs ',' port_ref
{ $1->push_back($3); }
;
port_ref:
net_scalar
| net_bit_select
| net_part_select
;
port_dcls:
port_dcl
{ $$ = new sta::VerilogStmtSeq;
$$->push_back($1);
}
| port_dcls ',' port_dcl
{ $$ = $1;
$1->push_back($3);
}
| port_dcls ',' dcl_arg
{
sta::VerilogDcl *dcl = dynamic_cast<sta::VerilogDcl*>($1->back());
dcl->appendArg($3);
$$ = $1;
}
;
port_dcl:
2022-07-11 17:49:12 +02:00
attribute_instance_seq port_dcl_type
{ $<ival>$ = sta::verilog_reader->line(); } dcl_arg
{ $$ = sta::verilog_reader->makeDcl($2, $4, $1, $<ival>3); }
| attribute_instance_seq port_dcl_type
{ $<ival>$ = sta::verilog_reader->line(); } '[' INT ':' INT ']' dcl_arg
{ $$ = sta::verilog_reader->makeDclBus($2, $5, $7, $9, $1, $<ival>3); }
2018-09-28 17:54:21 +02:00
;
port_dcl_type:
INPUT { $$ = sta::PortDirection::input(); }
| INPUT WIRE { $$ = sta::PortDirection::input(); }
| INOUT { $$ = sta::PortDirection::bidirect(); }
| INOUT REG { $$ = sta::PortDirection::bidirect(); }
| INOUT WIRE { $$ = sta::PortDirection::bidirect(); }
| OUTPUT { $$ = sta::PortDirection::output(); }
2019-01-06 01:09:27 +01:00
| OUTPUT WIRE { $$ = sta::PortDirection::output(); }
2018-09-28 17:54:21 +02:00
| OUTPUT REG { $$ = sta::PortDirection::output(); }
;
stmts:
// empty
{ $$ = new sta::VerilogStmtSeq; }
| stmts stmt
{ if ($2) $1->push_back($2); }
| stmts stmt_seq
// Append stmt_seq to stmts.
{ sta::VerilogStmtSeq::Iterator iter($2);
while (iter.hasNext())
$1->push_back(iter.next());
delete $2;
}
;
stmt:
parameter
| defparam
| declaration
| instance
| error ';'
{ yyerrok; $$ = NULL; }
;
stmt_seq:
continuous_assign
;
/* Parameters are parsed and ignored. */
parameter:
PARAMETER parameter_dcls ';'
{ $$ = NULL; }
| PARAMETER '[' INT ':' INT ']' parameter_dcls ';'
{ $$ = NULL; }
;
parameter_dcls:
parameter_dcl
{ $$ = NULL; }
| parameter_dcls ',' parameter_dcl
{ $$ = NULL; }
;
parameter_dcl:
ID '=' parameter_expr
{ sta::stringDelete($1);
$$ = NULL;
}
| ID '=' STRING
{ sta::stringDelete($1);
sta::stringDelete($3);
$$ = NULL;
}
;
parameter_expr:
ID
{ sta::stringDelete($1);
$$ = 0;
}
| '`' ID
{ sta::stringDelete($2);
$$ = 0;
}
| CONSTANT
{ sta::stringDelete($1);
$$ = 0;
}
| INT
| '-' parameter_expr %prec NEG
{ $$ = - $2; }
| parameter_expr '+' parameter_expr
{ $$ = $1 + $3; }
| parameter_expr '-' parameter_expr
{ $$ = $1 - $3; }
| parameter_expr '*' parameter_expr
{ $$ = $1 * $3; }
| parameter_expr '/' parameter_expr
{ $$ = $1 / $3; }
| '(' parameter_expr ')'
{ $$ = $2; }
;
defparam:
DEFPARAM param_values ';'
{ $$ = NULL; }
;
param_values:
param_value
{ $$ = NULL; }
| param_values ',' param_value
{ $$ = NULL; }
;
param_value:
ID '=' parameter_expr
{ sta::stringDelete($1);
$$ = NULL;
}
| ID '=' STRING
{ sta::stringDelete($1);
sta::stringDelete($3);
$$ = NULL;
}
;
declaration:
2022-07-11 17:49:12 +02:00
attribute_instance_seq dcl_type { $<ival>$ = sta::verilog_reader->line(); } dcl_args ';'
{ $$ = sta::verilog_reader->makeDcl($2, $4, $1, $<ival>3); }
| attribute_instance_seq dcl_type { $<ival>$ = sta::verilog_reader->line(); }
2018-09-28 17:54:21 +02:00
'[' INT ':' INT ']' dcl_args ';'
2022-07-11 17:49:12 +02:00
{ $$ = sta::verilog_reader->makeDclBus($2, $5, $7, $9, $1,$<ival>3); }
2018-09-28 17:54:21 +02:00
;
dcl_type:
INPUT { $$ = sta::PortDirection::input(); }
| INOUT { $$ = sta::PortDirection::bidirect(); }
| OUTPUT { $$ = sta::PortDirection::output(); }
| SUPPLY0 { $$ = sta::PortDirection::ground(); }
| SUPPLY1 { $$ = sta::PortDirection::power(); }
| TRI { $$ = sta::PortDirection::tristate(); }
| WAND { $$ = sta::PortDirection::internal(); }
| WIRE { $$ = sta::PortDirection::internal(); }
| WOR { $$ = sta::PortDirection::internal(); }
;
dcl_args:
dcl_arg
{ $$ = new sta::VerilogDclArgSeq;
$$->push_back($1);
}
| dcl_args ',' dcl_arg
{ $1->push_back($3);
$$ = $1;
}
;
dcl_arg:
ID
{ $$ = sta::verilog_reader->makeDclArg($1); }
| net_assignment
{ $$ = sta::verilog_reader->makeDclArg($1); }
;
continuous_assign:
ASSIGN net_assignments ';'
{ $$ = $2; }
;
net_assignments:
net_assignment
{ $$ = new sta::VerilogStmtSeq();
$$->push_back($1);
}
| net_assignments ',' net_assignment
{ $1->push_back($3); }
;
net_assignment:
2021-01-19 19:17:13 +01:00
net_assign_lhs { $<ival>$ = sta::verilog_reader->line(); } '=' net_expr
2018-09-28 17:54:21 +02:00
{ $$ = sta::verilog_reader->makeAssign($1, $4, $<ival>2); }
;
2021-01-19 19:17:13 +01:00
net_assign_lhs:
net_named
| net_expr_concat
;
2018-09-28 17:54:21 +02:00
instance:
2022-07-11 17:49:12 +02:00
attribute_instance_seq ID { $<ival>$ = sta::verilog_reader->line(); } ID '(' inst_pins ')' ';'
{ $$ = sta::verilog_reader->makeModuleInst($2, $4, $6, $1, $<ival>3); }
| attribute_instance_seq ID { $<ival>$ = sta::verilog_reader->line(); } parameter_values
2018-09-28 17:54:21 +02:00
ID '(' inst_pins ')' ';'
2022-07-11 17:49:12 +02:00
{ $$ = sta::verilog_reader->makeModuleInst($2, $5, $7, $1, $<ival>3); }
2018-09-28 17:54:21 +02:00
;
parameter_values:
'#' '(' parameter_exprs ')'
;
parameter_exprs:
parameter_expr
| '{' parameter_exprs '}'
{ $$ = $2; }
| parameter_exprs ',' parameter_expr
;
inst_pins:
// empty
{ $$ = NULL; }
| inst_ordered_pins
| inst_named_pins
;
// Positional pin connections.
inst_ordered_pins:
net_expr
{ $$ = new sta::VerilogNetSeq;
$$->push_back($1);
}
| inst_ordered_pins ',' net_expr
{ $1->push_back($3); }
;
// Named pin connections.
inst_named_pins:
inst_named_pin
{ $$ = new sta::VerilogNetSeq;
$$->push_back($1);
}
| inst_named_pins ',' inst_named_pin
{ $1->push_back($3); }
;
// The port reference is split out into cases to special case
// the most frequent case of .port_scalar(net_scalar).
inst_named_pin:
// Scalar port.
'.' ID '(' ')'
rm tmp string uses commit 2d0a4f8e9a8b46faa2ba91e1be636c3c3ad95a7f Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 21:25:37 2023 -0700 leaks Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 5514910a91707d615bac0bbed3a29f579eca8de2 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 18:21:54 2023 -0700 foo Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 076a51d5816444e883232933c2ded7309291d0bc Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 16:38:42 2023 -0700 parse bus string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 2b80e563cbbb6563a6b716431f391bbb6639f816 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 15:57:05 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 9e4f2308658232d0b1ee9efcd948bb19ae5dd30f Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 14:37:35 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ebad3afd49b08e7194452dd082c3c7c05767f875 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 10:59:11 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 69647913932312a04ca06e7a04cca17ed50d4daf Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 21:02:20 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 55e67996a7b0651dbb5ee06cb89fe0410648c3c1 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 10:42:43 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 73cee43925c0d32940989c616440b4da18640121 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 09:55:17 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit eba6d1413b8d87a64a90141e5263a56eede1df51 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 09:40:16 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 95d6ed78144512a37fd7c1d3d8a62fc4c8965818 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 08:18:46 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit faf82464d7be7fd6c958a21d401fa48ece4ac341 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 07:49:11 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit cfc9064496cb6f46ec562b104bc7fff2fbc1b32e Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 07:37:12 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 057933a6ac356a7541883aa64b5109c7a0e8b8d1 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 21:02:20 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit fdeb6436a72413356a627dd1de1d8cec7fca4c4a Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 19:53:44 2023 -0700 rm TmpString uses Signed-off-by: James Cherry <cherry@parallaxsw.com> Signed-off-by: James Cherry <cherry@parallaxsw.com>
2023-03-26 15:34:36 +02:00
{ $$ = sta::verilog_reader->makeNetNamedPortRefScalarNet($2); }
2018-09-28 17:54:21 +02:00
| '.' ID '(' ID ')'
{ $$ = sta::verilog_reader->makeNetNamedPortRefScalarNet($2, $4); }
| '.' ID '(' ID '[' INT ']' ')'
{ $$ = sta::verilog_reader->makeNetNamedPortRefBitSelect($2, $4, $6); }
| '.' ID '(' named_pin_net_expr ')'
{ $$ = sta::verilog_reader->makeNetNamedPortRefScalar($2, $4); }
// Bus port bit select.
| '.' ID '[' INT ']' '(' ')'
{ $$ = sta::verilog_reader->makeNetNamedPortRefBit($2, $4, NULL); }
| '.' ID '[' INT ']' '(' net_expr ')'
{ $$ = sta::verilog_reader->makeNetNamedPortRefBit($2, $4, $7); }
// Bus port part select.
| '.' ID '[' INT ':' INT ']' '(' ')'
{ $$ = sta::verilog_reader->makeNetNamedPortRefPart($2, $4, $6, NULL); }
| '.' ID '[' INT ':' INT ']' '(' net_expr ')'
{ $$ = sta::verilog_reader->makeNetNamedPortRefPart($2, $4, $6, $9); }
;
named_pin_net_expr:
net_part_select
| net_constant
| net_expr_concat
;
net_named:
net_scalar
| net_bit_select
| net_part_select
;
net_scalar:
ID
{ $$ = sta::verilog_reader->makeNetScalar($1); }
;
net_bit_select:
ID '[' INT ']'
{ $$ = sta::verilog_reader->makeNetBitSelect($1, $3); }
;
net_part_select:
ID '[' INT ':' INT ']'
{ $$ = sta::verilog_reader->makeNetPartSelect($1, $3, $5); }
;
net_constant:
CONSTANT
{ $$ = sta::verilog_reader->makeNetConstant($1); }
;
net_expr_concat:
'{' net_exprs '}'
{ $$ = sta::verilog_reader->makeNetConcat($2); }
;
net_exprs:
net_expr
{ $$ = new sta::VerilogNetSeq;
$$->push_back($1);
}
| net_exprs ',' net_expr
{ $$->push_back($3); }
;
net_expr:
net_scalar
| net_bit_select
| net_part_select
| net_constant
| net_expr_concat
;
2022-07-11 17:49:12 +02:00
attribute_instance_seq:
// empty
{ $$ = new sta::VerilogAttributeStmtSeq; }
| attribute_instance_seq attribute_instance
{ if ($2) $1->push_back($2); }
;
attribute_instance:
ATTRIBUTE_OPEN attr_specs ATTRIBUTE_CLOSED
{ $$ = new sta::VerilogAttributeStmt($2); }
2022-07-11 17:49:12 +02:00
;
attr_specs:
attr_spec
{ $$ = new sta::VerilogAttributeEntrySeq;
$$->push_back($1);
2022-07-11 17:49:12 +02:00
}
2024-03-28 03:33:58 +01:00
| attr_specs ',' attr_spec
2022-07-11 17:49:12 +02:00
{ $$->push_back($3); }
;
attr_spec:
ID
{ $$ = new sta::VerilogAttributeEntry($1, "1");
delete[] $1;
}
| ID '=' attr_spec_value
{ $$ = new sta::VerilogAttributeEntry($1, $3);
delete[] $1;
delete[] $3;
}
2022-07-11 17:49:12 +02:00
;
attr_spec_value:
CONSTANT
{ $$ = $1; }
| STRING
{ $$ = $1; }
| INT
{ $$ = sta::stringCopy(std::to_string($1).c_str()); }
2022-07-11 17:49:12 +02:00
;
2018-09-28 17:54:21 +02:00
%%