Blame | Last modification | View Log | Download | RSS feed
%{
/*
* $Header: C:/cvsroot/Vert03/acf_src/acf_yacc.y,v 1.1.1.1 2003/11/04 23:34:58 mjames Exp $ *//*
*
* $Log: acf_yacc.y,v $
* Revision 1.1.1.1 2003/11/04 23:34:58 mjames
* Imported into local repositrory
*
* Revision 1.38 2002/12/06 23:28:04 mjames
* Corrected locations where GND was being a
* reserved word and in fact was legal as pin/port ident
*
* Also error checked problems of duplicate idents appearing
*
* Revision 1.37 2002/10/02 18:45:23 MJAMES
* use routed_net member in place of net member when jumpers are processed
*
* Revision 1.36 2002/09/30 13:25:31 MJAMES
* Upgraded nets to include 'lhs_expression' being the range on the
* left hand side of a signal connection to a port
*
* std_logic_vector (0) <= std_logic , on a port of a chip
*
* Revision 1.35 2002/09/16 11:02:44 mjames
* Added some of the generic string types to the input parser.
*
* Revision 1.34 2002/09/09 10:14:58 mjames
* Modified expression parser to match CC as previous one was
* broken
*
* Revision 1.33 2002/08/23 14:21:54 mjames
* Added the <VHDL> string keyword.
*
* Revision 1.32 2002/08/19 14:31:26 mjames
* Removed an incompatibility with env_string generics where the output
* of Vertical caused an error under some circumstances.
*
* Revision 1.31 2002/08/14 12:00:15 mjames
* cleaned up on end of file code
*
* Revision 1.30 2002/08/06 12:54:14 mjames
* Merge in from latest version
*
*
* Revision 1.32 2002/03/22 16:16:28 mjames
* Modifications to undo over-zealous checking of
* current chip even in incorrect scenarios.
*
* Revision 1.31 2002/03/19 11:59:34 mjames
* Applying paranoid programming to the use of current_chip pointer
* as there were some address exceptions created in cases of missing
* components being instantiated in VHDL
*
* Revision 1.30 2002/03/08 11:53:57 mjames
* Corrected verilog module instance code
*
* Revision 1.29 2002/01/16 22:02:36 mjames
* Prevented coredumps while reading Verilog file
* s.g. Should permit further analysis of added
* requirements for complete Verilog reading
*
* Revision 1.28 2002/01/16 10:06:19 mjames
* Added package definitions to VHDL syntax
* According to report by John Marquis
*
* Revision 1.27 2002/01/03 16:39:17 mjames
* Removed unused rule causing coredump
*
* Revision 1.26 2001/12/13 22:12:15 mjames
* Vertical now supports nested include database files
* This allows wrappers around 'pure' VHDL or Verilog files
*
* Revision 1.25 2001/12/11 21:29:56 mjames
* Verilog syntax now read in by Vertical allows pin templates
* defined by Certify to be used.
*
* Revision 1.24 2001/11/30 22:47:37 mjames
* small corrections
*
* Revision 1.23 2001/11/30 22:21:19 mjames
* Modifying Verilog reading syntax to accept valid code.
*
* Revision 1.22 2001/11/19 09:46:14 mjames
* Semicolons missing: caused error with byacc
*
* Revision 1.21 2001/10/31 22:19:57 mjames
* Tidying up problematical comments caused by CVS
* 'intelligent' comment guessing
*
* Revision 1.20 2001/10/31 16:27:25 mjames
* Added a datastructure to hide regular expression information from programs.
* Changed call to regexec to indicate 0 subexpressions to be matched
* rather than a number dependent on strlen(string) which was wrong.
*
* Revision 1.19 2001/10/02 20:55:37 mjames
* Moved documentation about code to main program module.
*
* Revision 1.18 2001/09/21 14:13:10 mjames
* Corrected the creation of chip pinouts from VHDL source so that both
* ENTITY and COMPONENT port declarations assign a pin identifier that is
* the same as the pin name. Otherwise templating does not work, to create
* pin identifiers for a PCB
*
* Revision 1.17 2001/08/31 09:36:54 mjames
* removed DOS line endings
*
* Revision 1.16 2001/07/09 09:36:30 mjames
* Amending the syntax and end of file behaviour to allow Quartus pin fit files
* to be read .
* They are harder to read because they are not block structured. The end of file is used as a marker. Vertical has been persuaded to handle end of file events properly.
*
* Revision 1.15 2001/07/06 12:50:36 mjames
* Added the ability to read in Quartus pinfit files
*
* Revision 1.14 2001/07/05 15:12:37 MJAMES
* Amended to read Quartus pin files. not fully working
*
* Revision 1.13 2001/06/07 11:59:05 MJAMES
* Strange GCC optimiser error on line 1172. Changed code to trap possible error that
* should not happen anyway: probably a PII optimiser bug.
*
* Revision 1.12 2001/06/06 14:46:03 mjames
* Added further Verilog support.
* Corrected write ext command to not require additional argument.
* Added write quartus for creation of a pinfit file relevant to Quartus
*
* Revision 1.11 2001/06/06 12:10:26 mjames
* Move from HPUX
*
* Revision 1.10 2001/04/30 13:31:44 Administrator
* Started to add in Verilog parsing
*
*
* Revision 1.1 96/01/04 10:18:07 10:18:07 mjames (Mike James)
* Initial revision
*
* */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "vertcl_main.h"
#include "expression.h"
#include "generic.h"
#include "database.h"
#include "routing.h"
#include "cmdparse.h"
#include "cmdlog.h"
#include "jumpering.h"
#include "unrouted.h"
#include "lx_support.h"
#include "equivalent.h"
#include "acf_lex_ext.h"
#define YYERROR_VERBOSE
int lineno;
/* Structure to hold a set of identifiers for later processing */
struct str * y_first = NULL, * y1_first=NULL;
struct str * y_last = NULL, * y1_last =NULL ;
int id_count = 0;
#ident "@(#)$Header: C:/cvsroot/Vert03/acf_src/acf_yacc.y,v 1.1.1.1 2003/11/04 23:34:58 mjames Exp $"
static socket_t * current_chip, * current_comp;
static node_t * current_node, * current_comp_node;
static net_t * current_net;
static net_t ** current_list;
/* used in net joining in the YACC parser */
static net_t ** join_context;
static JoinMode_t join_mode;
static net_t * top_net;
static vhdl_t * vhdl;
static generic_info_t ** generic_context;
static equivalent_node_set_t * curr_equiv_list;
static char curr_pin_name[MAXIDLEN];
static char curr_pin_ident[MAXIDLEN];
static int curr_pin_dir;
static int curr_pin_group;
static generic_info_t info[1]; /* this is a local scratch area */
/* handed back to the command line expression parser */
static char * rename_pin_string;
static char text_buff[MAXIDLEN];
void process_tdf_pins(struct str * s);
int inside_block ;
extern void exit_lex_block(void); /* means to return LEX to initial state */
extern void create_pins_or_signals(void);
/* is the current component instance running implicit or explicit
port mapping ? */
typedef enum { UNKNOWN,IMPLICIT,EXPLICIT } port_map_method;
port_map_method curr_comp_port_map;
%}
%union { char * string;
int integer;
generic_info_t * range ;
expression_t * exp; };
%token FILEMODE CMDMODE
%token CHIP BEGIN_TOK END DEVICE
%token COMPONENTS WIRED_NETS CONN
%token END_CONN JOINED_NETS ALIAS JUMPER RENAME_PINS
%token TEMPLATE FIX_LOCATION LOCATION UNROUTED ROUTED NAMED
%token ASSIGN SIG_ASSIGN CONNECTED ROUTE_FLAGS DECLARATION INSTANCE
%token AHDL VERILOG SUBDESIGN OPEN BOOLEAN TRUE FALSE
%token TO DOWNTO GENERIC RANGE INTEGER NATURAL SIGNAL CONSTANT
%token VHDL PORT ENTITY IS COMPONENT MAP ARCHITECTURE OF
%token EQUIVALENT TO_POW MODULE ENDMODULE LIBRARY USE ALL
%token PACKAGE FOR PROCESS
%token ASSIGNED AN WIRE GND_RES_IO GND_RES_IN
%token ATTRIBUTE ENV_STRING STRING SHL SHR EQ_EQ N_EQ LOG_AND LOG_OR
%token QUOTE VHDL_CONN
%token <string> QUOTED_STRING
%token <string> TXT_STRING
%token <string> NUM_STRING
%token <integer> PINDIR
%token <string> VCC
%token <string> GND
%type <integer> generic_pindir_opt
%type <exp> expr
%type <exp> primary_expr
%type <exp> add_expr
%type <exp> mult_expr
%type <exp> shift_expr
%type <exp> relational_expr
%type <exp> equality_expr
%type <exp> and_expr
%type <exp> exor_expr
%type <exp> or_expr
%type <exp> logand_expr
%type <exp> logor_expr
%type <exp> cond_expr
%type <exp> expr1
%type <exp> bus_range
%type <string> astring
%type <string> netname
%type <string> vhdl_lib_member_select
%type <exp> opt_integer
%type <exp> opt_bus_range
%type <exp> verilog_bus_expr
%type <exp> colon_expr
%type <exp> vhdl_type_default_value_opt
%type <exp> vhdl_port_map_slice_opt
%type <exp> simple_range_expr
%left UMINUS '~'
%left '('
%%
/* two grammars present, one is vertical .acfp file,
the other is from the command line. Eventually these two grammars
will be merged */
file : FILEMODE objects
| CMDMODE cmd_objects;
/************************************************************************/
/* COMMAND MODE GRAMMAR */
/************************************************************************/
cmd_objects : cmd_objects cmd_object
| cmd_object
;
cmd_object : bus_range { cmd_expression = $1; }
;
/************************************************************************/
/* FILE MODE GRAMMAR */
/************************************************************************/
objects : objects object
| object
;
object : chip_decl
| components_decl
| template_decl
| joined_decl
| nets_decl
| rename_pins_block
| global_generic_decl
| vhdl_region
| verilog_region
| ahdl_region
|
;
/****************************************************************/
/* all string types */
astring : QUOTED_STRING { $$=$1; }
| TXT_STRING { $$=$1; }
| NUM_STRING { $$=$1; };
/****************************************************************/
/* beginning finding the chip declaration */
/****************************************************************/
chip_decl : chip_id_decl chip_body;
chip_body : BEGIN_TOK flex_chip_body
| ASSIGNED apex_chip_body
;
/******************************************************************/
/* old style FLEX/acfp CHIP declaration */
flex_chip_body : chip_info_lines
pin_declarations
pin_equivalences
END end_item {
free_lex_strings();
exit_lex_block();
current_chip = NULL;}
;
chip_id_decl : CHIP astring
{ id_count = 0; /* used in pin ID lists */
current_chip=find_socket(Name,$2,Create,&socket_head);
/* current_chip is unlikely to be null .. but */
if (current_chip)
{
current_chip->is_template = 0;
current_chip->parent_template_ref = NULL;
current_chip->route_flags = 0;
/* ensure_socket_ident(current_chip); */
if(ISNULLSTR(current_chip->identifier))
{
socket_t * test = find_socket(Ident,$2,Search,&socket_head);
if (!test)
set_socket(current_chip,Ident,$2);
else
{
Log(LOG_ERROR,"-- ERROR :name '%s' clashes with another ID in CHIP declaration\n",$2);
set_socket(current_chip,Ident,"name clashes with another chip ident in CHIP declaration");
}
}
}
};
chip_info_lines : chip_info_lines chip_info_line
| chip_info_line
| /* nothing */
;
chip_info_line : device_declaration
| route_flags_info
| routing_status
| chip_generic_decl;
device_declaration : DEVICE '=' astring end_item
{ if(current_chip)
set_socket(current_chip,Type,$3);
};
pin_equivalences : pin_equivalence pin_equivalences
| pin_equivalence
| /* nothing */
;
/* gap : NL gap
| NL
|
;
*/
end_item : ';' ;
routing_status : UNROUTED end_item
;
/* routing flags are used in fasttrack routing */
route_flags_info : ROUTE_FLAGS '=' route_flag_value end_item
;
route_flag_value : NUM_STRING { if(current_chip)
convert_num($1,¤t_chip->route_flags); };
/****************************************************************/
/* these patterns are shared between CHIP and TEMPLATE .
A flag is set in the form of chip_context to slightly modify
undesirable behaviour */
pin_declarations : pin_declarations pin_declaration
| pin_declaration
|
;
pin_declaration : name_part ':' pin_rest end_item
;
/* if the chip pin is given a name in the template , suppress it. It
will attempt to link the template to a real net if the pin has a name */
name_part : netname { char * s ;
s = make_string($1,&y_first,&y_last);
strcpy(curr_pin_name,"Still_Using_pin_name_somewhere");
curr_pin_dir = NONE; /* default bidirectional */
if(ISNULLSTR(s))/* the null strings tell acfread that the pin exists and */
current_list = &routed_list ;/* available for routing */
else
current_list = &unrouted_list ;
};
pin_rest : pin_dir pin_group '=' pin_ident vhdl_type_opt
| UNROUTED /* no action */
| LOCATION '=' astring /* no action */
;
pin_dir : PINDIR { curr_pin_dir = $1; }
;
pin_group : '(' NUM_STRING ')' { convert_num($2,&curr_pin_group); }
| /* nothing */ { curr_pin_group = 0; };
pin_ident : netname { strcpy(curr_pin_ident,$1); };
/***********************************************************************************/
/* APEX handler */
apex_chip_body : apex_device_declaration
apex_info_lines ;
apex_device_declaration : TO AN astring apex_speed_grade
{ if(current_chip)
set_socket(current_chip,Type,$3);
};
apex_speed_grade : '-' NUM_STRING { generic_info_t info;
char * sbuff = malloc(strlen($2)+2);
sprintf(sbuff,"-%s",$2);
info.expr = compile_string(sbuff);
free(sbuff);
info.name = "speed_grade";
info.typename = "string";
info.g_type = IS_DECLARATION_DIRECTIVE;
if(current_chip)
set_generic_value(¤t_chip->generics,&info);
}
| /* nothing */
;
apex_info_lines : apex_info_lines apex_info_line
| apex_info_line;
apex_info_line : GND ':' astring more_colons { /* ground pin .. no op */ }
| GND_RES_IO ':' astring more_colons { /* reserved pin .. no op */ }
| GND_RES_IN ':' astring more_colons { /* reserved pin .. no op */ }
| VCC ':' astring ':' NUM_STRING { /* power pin .. no op */ }
| VCC ':' astring more_colons { /* as this pattern shows.. power pin .. no op */ }
| TXT_STRING ':' astring more_colons {/*printf("ignore pin %s at %s\n",$1,$3);*//* reserved pin .. no op */ }
| TXT_STRING ':' astring ':' PINDIR ':' astring ':' { current_list = &unrouted_list ;
make_string($1,&y_first,&y_last);
/*printf("pin %s at %s\n",$1,$3);*/
strcpy(curr_pin_ident,$3);
curr_pin_dir = $5;
vhdl = default_vhdl_datatype;
create_pins_or_signals();
}
| TXT_STRING '[' expr ']' ':' astring ':' PINDIR ':' astring ':' { current_list = &unrouted_list ;
make_string($1,&y_first,&y_last);
/*printf("pin %s at %s\n",$1,$3);*/
vhdl = calloc(1,sizeof(vhdl_t));
vhdl->is_vector = 1;
vhdl->expr = $3;
strcpy(curr_pin_ident,$6);
curr_pin_dir = $8;
/* vhdl = default_vhdl_datatype; */
create_pins_or_signals();
}
;
more_colons : ':' more_colons
| ':'
;
/************************************************************************************/
/* begin to recognise the possible VHDL syntax for a VHDL type */
/* this declaration is where the pin type is purely optional in ACFP files */
vhdl_type_opt : ':' vhdl_type
| /* nothing */ { /* use a default type if none given */
vhdl = default_vhdl_datatype;
create_pins_or_signals();
} ;/* altering define pin to take a pointer to VHDL type */
/* this declaration is a 'pure' VHDL that can be used in VHDL chunks */
vhdl_type : astring vhdl_type_default_value_opt { /* single bit types */
vhdl = (vhdl_t *)calloc(1,sizeof(vhdl_t));
if(vhdl){
vhdl->basetype = allocstr($1);
vhdl->is_vector = 0;
vhdl->is_downto = 0;
vhdl->expr = NULL;
vhdl->default_expr = $2;/* added default assignment expression */
create_pins_or_signals();
}
}
| astring '(' bus_range ')' vhdl_type_default_value_opt { /* vhdl vector types */
vhdl = (vhdl_t *)calloc(1,sizeof(vhdl_t));
if(vhdl){
vhdl->basetype = allocstr($1);
vhdl->is_vector = 1; /* not known for sure yet */
vhdl->is_downto = 0;
vhdl->expr = $3;
vhdl->default_expr = $5;/* added default assignment expression */
create_pins_or_signals();
}
#if defined DEBUG_EXPRESSION
print_msg_expression(stdout,"seen bus ",$3);
#endif
}
| INTEGER vhdl_type_default_value_opt { /* added Nov 2000 */
vhdl = (vhdl_t *)calloc(1,sizeof(vhdl_t));
if(vhdl){
vhdl->basetype = "integer";
vhdl->is_vector = 0; /* not known for sure yet */
vhdl->is_downto = 0;
vhdl->expr = NULL;
vhdl->default_expr = $2;/* added default assignment expression */
create_pins_or_signals();
}
}
| INTEGER RANGE simple_range_expr vhdl_type_default_value_opt { /* added Nov 2000 */
vhdl = (vhdl_t *)calloc(1,sizeof(vhdl_t));
if(vhdl){
vhdl->basetype = "integer range";
vhdl->decl_expr = $3;
vhdl->is_vector = 0; /* not known for sure yet */
vhdl->is_downto = 0;
vhdl->expr = NULL;
vhdl->default_expr = $4;/* added default assignment expression */
create_pins_or_signals();
}
}
| NATURAL vhdl_type_default_value_opt { /* added Nov 2000 */
vhdl = (vhdl_t *)calloc(1,sizeof(vhdl_t));
if(vhdl){
vhdl->basetype = "natural";
vhdl->is_vector = 0; /* not known for sure yet */
vhdl->is_downto = 0;
vhdl->expr = NULL;
vhdl->default_expr = $2;/* added default assignment expression */
create_pins_or_signals();
}
}
| NATURAL RANGE simple_range_expr vhdl_type_default_value_opt { /* added Nov 2000 */
vhdl = (vhdl_t *)calloc(1,sizeof(vhdl_t));
if(vhdl){
vhdl->basetype = "natural range";
vhdl->decl_expr = $3;
vhdl->is_vector = 0; /* not known for sure yet */
vhdl->is_downto = 0;
vhdl->expr = $3;
vhdl->default_expr = $4;/* added default assignment expression */
create_pins_or_signals();
}
}
| BOOLEAN vhdl_type_default_value_opt { /* added May 2001 */
vhdl = (vhdl_t *)calloc(1,sizeof(vhdl_t));
if(vhdl){
vhdl->basetype = "boolean";
vhdl->is_vector = 0; /* not known for sure yet */
vhdl->is_downto = 0;
vhdl->expr = NULL;
vhdl->default_expr = $2;/* added default assignment expression */
create_pins_or_signals();
}
};
vhdl_type_default_value_opt : ASSIGN bus_range { $$ = $2; /* printf("found default assign\n");*/ }
| /* nothing */ { $$ = NULL; }
;
/* general generic stuff */
bus_range : expr1
| expr
;
/* an expression of type range at top level is allowed */
expr1 : simple_range_expr {
$$ = $1;
}
|QUOTED_STRING {
$$ = compile_string($1);
}
| QUOTE astring QUOTE{
$$ = compile_char($2[0]);
}
;
simple_range_expr : expr TO expr {
$$ = compile_expression(TO,$1,$3);
}
| expr DOWNTO expr {
$$ = compile_expression(DOWNTO,$1,$3);
}
;
/* an expression calculator that will use the generics
attached to the current chip to work out the values */
primary_expr :'(' expr ')'
{
$$ = compile_expression('(',$2,NULL);
}
| '~' expr %prec UMINUS
{
$$ = compile_expression('~',$2,NULL);
}
| '-' expr %prec UMINUS
{
$$ = compile_expression(UMINUS,$2,NULL);
}
| NUM_STRING { int t;
convert_num($1,&t);
$$ = compile_constant_string(t,$1);
}
| TXT_STRING
{
$$ = compile_reference($1);
}
| TRUE {
$$=compile_constant_string(1,"true"); /* should really respect boolean type */
}
| FALSE {
$$=compile_constant_string(0,"false");
}
;
mult_expr : primary_expr
{
$$ = $1;
}
| mult_expr '*' primary_expr
{
$$ = compile_expression('*',$1,$3);
}
| mult_expr '/' primary_expr
{
$$ = compile_expression('/',$1,$3);
}
| mult_expr '%' primary_expr
{
$$ = compile_expression('%',$1,$3);
}
| mult_expr TO_POW primary_expr {
$$ = compile_expression(TO_POW,$1,$3);
}
;
add_expr : mult_expr
{
$$ = $1;
}
| add_expr '+' mult_expr
{
$$ = compile_expression('+',$1,$3);
}
| add_expr '-' mult_expr
{
$$ = compile_expression('-',$1,$3);
}
;
shift_expr : add_expr
{
$$ = $1;
}
| shift_expr SHL add_expr
{
$$ = compile_expression(SHL,$1,$3);
}
| shift_expr SHR add_expr
{
$$ = compile_expression(SHR,$1,$3);
}
;
relational_expr : shift_expr
{
$$ = $1;
}
| relational_expr '>' shift_expr
{
$$ = compile_expression('>',$1,$3);
}
| relational_expr '<' shift_expr
{
$$ = compile_expression('<',$1,$3);
}
;
equality_expr : relational_expr
{
$$ = $1;
}
| equality_expr EQ_EQ relational_expr
{
$$ = compile_expression(EQ_EQ,$1,$3);
}
| equality_expr N_EQ relational_expr
{
$$ = compile_expression(N_EQ,$1,$3);
}
;
and_expr : equality_expr
{
$$ = $1;
}
| and_expr '&' equality_expr
{
$$ = compile_expression('&',$1,$3);
}
;
exor_expr : and_expr
{
$$ = $1;
}
| exor_expr '^' and_expr
{
$$ = compile_expression('^',$1,$3);
}
;
or_expr : exor_expr
{
$$ = $1;
}
| or_expr '|' or_expr
{
$$ = compile_expression('|',$1,$3);
}
;
logand_expr: or_expr
{
$$ = $1;
}
| logand_expr LOG_AND or_expr
{
$$ = compile_expression(LOG_AND,$1,$3);
}
;
logor_expr : logand_expr
{
$$ = $1;
}
| logor_expr LOG_OR logand_expr
{
$$ = compile_expression(LOG_OR,$1,$3);
}
;
cond_expr : logor_expr '?' colon_expr
{
$$ = compile_expression('?',$1,$3);
}
;
colon_expr : expr ':' expr
{ /* change from cond_expr on rhs */
$$ = compile_expression(':',$1,$3);
};
expr : cond_expr
{
$$ = $1;
}
| logor_expr
{
$$ = $1;
}
;
/**************************************************************************/
/* pin equivalence Declarations */
/**************************************************************************/
pin_equivalence : EQUIVALENT { curr_equiv_list = begin_equivalent_pins(); }
'(' equivalent_pins ')'
end_item { if(current_chip)
check_equivalent_pins(current_chip,curr_equiv_list); }
;
equivalent_pins : equivalent_pin end_item equivalent_pins
| equivalent_pin
| /* nothing */
;
equivalent_pin : astring { if(current_chip)
add_equivalent_pin( current_chip,curr_equiv_list,$1); };
/**************************************************************************/
/* VHDL Block Declarations */
/**************************************************************************/
vhdl_region : VHDL
vhdl_blocks
END end_item { exit_lex_block(); free_lex_strings(); }
;
vhdl_blocks : vhdl_blocks vhdl_block
| vhdl_block
;
/* now includes the idea of a VHDL architecture as the equivalent of a template */
vhdl_block : vhdl_chip_decl
| vhdl_architecture
| vhdl_package_decl /* but not a package body... */
| vhdl_library_decl
| vhdl_use_decl
| /* nothing */
;
/**************************************************************************/
/* VHDL Chip Entity Declaration */
/**************************************************************************/
vhdl_chip_decl : ENTITY hdl_entityname_decl IS {
Log(LOG_GENERAL,
"(line %d) Using ENTITY declaration for %s : prefer to use COMPONENT\n",lineno,current_chip->type);
}
vhdl_generic_decl_opt
vhdl_port_decl_opt
END TXT_STRING end_item {
current_chip = NULL; };
/* this shared with verilog */
hdl_entityname_decl : TXT_STRING
{
current_chip=find_socket(Name,$1,Create,&socket_head);
if(current_chip)
{
current_chip->is_template = 0;
current_chip->parent_template_ref = NULL;
current_chip->route_flags = 0;
set_socket(current_chip,Type,$1);
if(ISNULLSTR(current_chip->identifier))
set_socket(current_chip,Ident,$1);
if(ISNULLSTR(current_chip->type))
set_socket(current_chip,Type,$1);
generic_context = ¤t_chip->generics;
curr_pin_ident[0] = 0; /* use the signal name instead if this string is empty */
}
};
vhdl_generic_decl_opt : vhdl_generic_decl
| /* nothing */ ;
/* the generic information here shares the standard generic declaration
from the ACFp declaration */
vhdl_generic_decl : GENERIC '(' { if (current_chip)
generic_context = ¤t_chip->generics; }
generic_defn_lines
')' end_item
;
/**************************************************************/
/* port list */
/**************************************************************/
vhdl_port_decl_opt : vhdl_port_decl
| /* nothing */
;
vhdl_port_decl : PORT '(' vhdl_port_list ')' end_item;
vhdl_port_list : vhdl_port_list end_item vhdl_port_item
| vhdl_port_item
| /* nothing */
;
/* the VHDL Port item , inherits the pin_dir from a standard chip declaration
and the vhdl type extraction from the generic type declaration
*/
vhdl_port_item : vhdl_name_list ':' pin_dir vhdl_type
vhdl_assign_opt {if(current_chip)
create_nodes_from_refs(current_chip,0); };
vhdl_name_list : vhdl_name_list ',' hdl_name_part
| hdl_name_part
;
/* null the pin identifier to allow for creation of an ident in define_pin
*/
/* this is a pin on a component declaration */
hdl_name_part : netname {
char * s = make_string($1,&y_first,&y_last);
if(current_chip)
{
curr_pin_dir = NONE; /* default bidirectional */
if(current_chip->is_template ==1 ||
(ISNULLSTR(s) && id_count ==0))/* the null strings tell acfread that the pin exists and */
current_list = &routed_list ;/* available for routing */
else
current_list = &unrouted_list ;
id_count++;
}
};
vhdl_assign_opt : ASSIGN expr
| /* nothing */
;
/***********************************************************************/
/* VHDL Architecture Declaration */
/***********************************************************************/
vhdl_architecture : ARCHITECTURE astring OF astring IS
vhdl_architecture_declarations
BEGIN_TOK
vhdl_architecture_body_items
END astring end_item;
vhdl_architecture_declarations: vhdl_architecture_declarations vhdl_architecture_decl
| vhdl_architecture_decl
| /* nothing */
;
vhdl_architecture_decl : vhdl_component_decl
| vhdl_constant_decl
| vhdl_signal_decl
| vhdl_configuration_decl
;
/**********************************************************************/
/* VHDL Package Declaration */
/**********************************************************************/
vhdl_package_decl : PACKAGE package_name IS
vhdl_package_declarations
END astring end_item ;
package_name : astring { Log(LOG_GENERAL,"-- (line %d) package %s being read\n",lineno,$1); };
vhdl_package_declarations: vhdl_package_declarations vhdl_package_decl_item
| vhdl_package_decl_item
| /* nothing */
;
vhdl_package_decl_item : vhdl_component_decl
| vhdl_constant_decl
| vhdl_signal_decl
| vhdl_configuration_decl
;
/***********************************************************************/
/* VHDL Component Declaration */
/***********************************************************************/
vhdl_component_decl: COMPONENT
hdl_compname_decl
vhdl_generic_decl_opt
vhdl_port_decl_opt
END COMPONENT
end_item { if(current_chip)
create_nodes_from_refs(current_chip,0);
current_chip = NULL; };
hdl_compname_decl : TXT_STRING
{
current_chip=find_socket(Name,$1,Create,&template_head);
if(current_chip)
{
current_chip->is_template = 1;/* components look like templates */
current_chip->parent_template_ref = NULL;
current_chip->route_flags = 0;
ensure_socket_ident(current_chip);
set_socket(current_chip,Type,$1); /* socket name is also a type */
generic_context = ¤t_chip->generics;
}
};
/***********************************************************************/
/* VHDL Constant Declaration */
/***********************************************************************/
vhdl_constant_decl : CONSTANT { generic_context = & global_generics; }
generic_defn_text end_item;
/***********************************************************************/
/* VHDL Signal Declaration */
/***********************************************************************/
vhdl_signal_decl : SIGNAL { id_count = 0 ; y_first = NULL;y_last = NULL; }
hdl_signal_names ':' vhdl_type
/* { char buf[200];
printf("... type='%s'\n",decode_vhdl_type(buf,vhdl));
}
*/
end_item;
/* collect together all of the signal names that share the type declaration */
hdl_signal_names : hdl_signal_names ',' hdl_signal_name
| hdl_signal_name
;
hdl_signal_name : astring {
/* y_first is defined as null so we do not create any
pins (as they do not belong to any particular chip) */
#if defined DEBUG_EXPRESSION
printf("making sig name %s\n",$1);
#endif
make_string($1,&y1_first,&y1_last);
id_count++;
};
/***********************************************************************/
/* VHDL Configuration Declaration */
/***********************************************************************/
/* for <scope> ':' <component> use entity <library>.<entity>(<architecture>) */
/* for ALL : draw USE ENTITY work.draw(rtl); */
vhdl_configuration_decl : FOR
vhdl_lib_member_select ':' astring USE ENTITY
astring '.' astring '(' astring ')' ';'
{ Log(LOG_GENERAL,"-- (line %d) for %s: %s use entity %s.%s(%s);\n",lineno,$2,$4,$7,$9,$11); };
/* code currently omitted */
/***********************************************************************/
/* VHDL Architecture body items */
/***********************************************************************/
vhdl_architecture_body_items: vhdl_architecture_body_items vhdl_architecture_body_item
| vhdl_architecture_body_item
| /* nothing */
;
vhdl_architecture_body_item : vhdl_concurrent_assignment
| vhdl_component_instance
;
/************************************************************************/
/* VHDL Component Instantiation */
/************************************************************************/
/* this code now sets up all unused ports to be bound to signals of the
same name as the ports (makes setting up simple architectures using
Vertical shorthand easier */
vhdl_component_instance : vhdl_inst_comp_binding
vhdl_inst_generic_map
vhdl_inst_port_map end_item {
if(current_comp && current_chip) { /* scan for unused nodes */
current_comp_node = current_comp->nodes;
while(current_comp_node) {
if (current_comp_node->in_use == 0) {
/* hookup to an unroutd signal */
define_pin(&unrouted_list,
current_chip,
current_comp_node->name,
current_comp_node->pindir,
current_comp_node->pin_group,
current_comp_node->identifier,
current_comp_node->vhdltype,
NULL);
}
current_comp_node =current_comp_node->sktnext;
}
}
current_chip = NULL; } ;
vhdl_inst_comp_binding : TXT_STRING ':' TXT_STRING {
current_comp=find_socket(Type,$3,Search,&template_head);
if(!current_comp) {
Log(LOG_ERROR,
"-- (line %d) No component of type %s can be found\n",lineno,$3);
current_chip = NULL;
}
else {
current_chip=find_socket(Ident,$1,Create,&socket_head);
if(current_chip) {
/* setup the current chip */
current_chip->is_template =0 ;
current_chip->parent_template_ref = NULL;
current_chip->route_flags = 0;
set_socket(current_chip,Name,""); /* socket has no name */
set_socket(current_chip,Type,$3); /* socket has a type */
current_comp_node = current_comp->nodes;
while(current_comp_node) {
current_comp_node->in_use = 0; /* clear in use/duplicate use flags */
current_comp_node=current_comp_node->sktnext;
}
current_comp_node = current_comp->nodes;
curr_comp_port_map = UNKNOWN;
}
}
};
vhdl_inst_generic_map : GENERIC MAP { if(current_chip)
{
generic_context = ¤t_chip->generics;
}
else
{
generic_context = NULL;
}
}
'(' vhdl_gen_map_list ')'
|
;
vhdl_inst_port_map : PORT MAP '(' vhdl_port_map_list ')'
|
;
/**************************************************************************/
vhdl_gen_map_list : vhdl_gen_map_list ',' vhdl_gen_map
| vhdl_gen_map
;
/* generics can only be mapped explicitly : change to bus_range as valid expression */
vhdl_gen_map: astring CONNECTED bus_range {
info->name = $1;
/* info->valuename = NULL; */
info->typename = NULL;
info->expr = $3 ;
info->valid = 0;
set_generic_value(generic_context,info);
};
/**************************************************************************/
vhdl_port_map_list : vhdl_port_map_list ',' vhdl_port_map
| vhdl_port_map
;
/* +++++++++++++++++ this is where a bus range can be given on LHS !! */
vhdl_port_map : astring vhdl_port_map_slice_opt CONNECTED rename_new_name {
if(current_chip && current_comp)
{
if (curr_comp_port_map == IMPLICIT)
Log(LOG_ERROR,"-- (line %d) Attempting use of mixed explicit and implicit port maps\n",lineno);
else {
curr_comp_port_map = EXPLICIT;
current_comp_node = find_node(current_comp,
Name,
$1,
Search);
if(current_comp_node) {
current_comp_node ->lhs_expr = $2; /* try2*/
if(current_comp_node->in_use == 0) {
current_comp_node->in_use = 1;
define_pin(&unrouted_list,
current_chip,
current_comp_node->name,
current_comp_node->pindir,
current_comp_node->pin_group,
current_comp_node->identifier,
current_comp_node->vhdltype,
current_comp_node->lhs_expr);
rename_unrouted_pin_socket(current_chip,$1,rename_pin_string,vhdl);
}
else
Log(LOG_ERROR,"# (line %d) Error, port '%s.%s' already used\n",
lineno,
current_chip->identifier,$1);
}
else
Log(LOG_ERROR,"# (line %d) Error : cannot find port '%s.%s' \n",
lineno,
current_chip->identifier,$1);
}
}
}
| astring vhdl_port_map_slice_opt CONNECTED OPEN {
if(current_chip && current_comp)
{
if (curr_comp_port_map == IMPLICIT)
Log(LOG_ERROR,"-- (line %d) Attempting use of mixed explicit and implicit port maps\n",lineno);
else {
curr_comp_port_map = EXPLICIT;
current_comp_node = find_node(current_comp,
Name,
$1,
Search);
if(current_comp_node) {
current_comp_node ->lhs_expr = $2; /* try2*/
if(current_comp_node->in_use == 0) {
current_comp_node->in_use = 1;
}
else
Log(LOG_ERROR,"# (line %d) Error, port '%s.%s' already used\n",
lineno,
current_chip->identifier,$1);
}
else
Log(LOG_ERROR,"# (line %d) Error : cannot find port '%s.%s' \n",
lineno,
current_chip->identifier,$1);
}
}
}
| rename_new_name vhdl_port_map_slice_opt {
if(current_chip && current_comp)
{
if (curr_comp_port_map == EXPLICIT)
Log(LOG_ERROR,"-- (line %d) Attempting use of mixed explicit and implicit port maps\n",lineno);
else {
curr_comp_port_map = IMPLICIT;
if(current_comp_node) {
current_comp_node->in_use = 1;
current_comp_node ->lhs_expr = $2; /* try2*/
define_pin(&unrouted_list,
current_chip,
current_comp_node->name,
current_comp_node->pindir,
current_comp_node->pin_group,
current_comp_node->identifier,
current_comp_node->vhdltype,
current_comp_node ->lhs_expr);
rename_unrouted_pin_socket(current_chip,current_comp_node->name,
rename_pin_string,vhdl);
if(vhdl != default_vhdl_datatype)
{
free(vhdl);
}
current_comp_node =current_comp_node->sktnext;
}
else
Log(LOG_ERROR,
"-- (line %d) Run out of pins while attempting implicit port map with '%s'\n",
lineno,
rename_pin_string);
}
}
}
| OPEN { /* tag open ports */
if(current_chip && current_comp)
{
if (curr_comp_port_map == EXPLICIT)
Log(LOG_ERROR,"-- (line %d) Attempting use of mixed explicit and implicit port maps\n",lineno);
else {
curr_comp_port_map = IMPLICIT;
if(current_comp_node) {
current_comp_node->in_use = 1;
current_comp_node ->lhs_expr = NULL; /* try2*/
current_comp_node =current_comp_node->sktnext;
}
else
Log(LOG_ERROR,
"-- (line %d) Run out of pins while attempting implicit port map with '%s'\n",
lineno,
rename_pin_string);
}
}
}
;
/**************************************************************************/
/* Pin bus slicing */
/**************************************************************************/
vhdl_port_map_slice_opt : '(' bus_range ')'
{ /* vhdl vector types */
$$ = $2;
printf("Seen a slice of a bus ..\n");
}
| /* nothing */ {
$$ = NULL;
}
;
/**************************************************************************/
/* VHDL concurrent assignment */
/**************************************************************************/
vhdl_concurrent_assignment : astring SIG_ASSIGN astring end_item
{
/* try using Alias on routed list to represent
signal assignment */
Log(LOG_GENERAL,"-- (line %d) Seen concurrent assignment %s\n",lineno,$1);
join_context = &unrouted_list;
top_net = find_net(join_context,Ident,$1,Search);
if(!top_net) /* Net cannot be created here , must exist already */
{
Log(LOG_ERROR,"# (line %d) ERROR : Cannot locate net '%s'\n",lineno,$3);
}
else
{
if(top_net->how_joined != NotJoined)
{
/* trap attempts to jumper extend a non-jumper net */
Log(LOG_ERROR,"# (line %d) ERROR : Net '%s' already connected, cannot connect to another\n",
lineno,
top_net->identifier);
}
printf(" additional net found '%s'\n",$3);
current_net = find_net(join_context,Ident,$3,Search);
if(!current_net)
{
Log(LOG_ERROR,"# (line %d) ERROR : Cannot locate net '%s'\n",lineno,$3);
}
else
{
if(current_net == top_net)
{
Log(LOG_ERROR,"# (line %d) ERROR : Cannot assign '%s' to itself\n",lineno,$1);
}
else
{
/* mark this as a net referred to by net name */
top_net->vhdl_connect_net = current_net;
}
}
};
};
/**************************************************************************/
/* VHDL Library Block Declaration */
/**************************************************************************/
vhdl_library_decl : LIBRARY vhdl_library_list ';';
vhdl_library_list : vhdl_library_name ',' vhdl_library_list
| vhdl_library_name
;
vhdl_library_name : astring { Log(LOG_GENERAL,"-- (line %d) library %s;\n",lineno,$1);} ;
/**************************************************************************/
/* VHDL USE Block Declaration */
/**************************************************************************/
vhdl_use_decl : USE vhdl_lib_members ';';
vhdl_lib_members : vhdl_lib_member ',' vhdl_lib_members
| vhdl_lib_member ;
/* modified to allow library members to be all of a library not just a single package */
vhdl_lib_member : astring '.' astring '.' vhdl_lib_member_select { Log(LOG_GENERAL,"-- use %s.%s.%s;\n",$1,$3,$5); }
| astring '.' vhdl_lib_member_select { Log(LOG_GENERAL,"-- use %s.%s;\n",$1,$3); }
;
vhdl_lib_member_select : ALL { $$="All"; }
| astring { $$=$1; }
;
/* code currently omitted */
/**************************************************************************/
/* Verilog Block Declarations */
/**************************************************************************/
verilog_region : VERILOG
verilog_blocks
END end_item { exit_lex_block(); free_lex_strings(); }
;
verilog_blocks : verilog_blocks verilog_block
| verilog_block
;
/* */
verilog_block : verilog_module_decl
| verilog_toplevel_decl
| /* nothing */
;
/**************************************************************************/
/* verilog module declaration */
/**************************************************************************/
/* this is not complete : need to look : If there is an endmodule we
have a component declaration : if it has a body then it is a
top level */
/* assuming we have a component */
/* need to check if name is duplicate but not assign to list unless */
/* it is definitely a component : for now , top level entities */
/* do not own netlists !! */
verilog_module_header : MODULE hdl_compname_decl verilog_port_list
verilog_pindir_block ;
/* toplevel contains structure */
verilog_toplevel_decl : verilog_module_header verilog_module_body ENDMODULE { current_chip = NULL; };
verilog_module_decl : verilog_module_header ENDMODULE { current_chip = NULL;} ;
/* wrong place as we need to know all about the types of wires within the port list */
verilog_port_list : '(' verilog_ports ')' ';' { if(current_chip)
create_nodes_from_refs(current_chip,0); }
verilog_pindir_block
|/* nothing */ ;
verilog_ports : verilog_ports ',' verilog_port
| verilog_port
| /* no ports */ ;
/* port has no datatype on it : k&R C style */
verilog_port : /* hdl_signal_name */ hdl_name_part { create_pins_or_signals(); };
verilog_bus_expr : '[' expr ']' { vhdl = calloc(1,sizeof(vhdl_t));
vhdl->is_vector = 1;
vhdl->expr = $2; }
| '[' expr ':' expr ']' { vhdl = calloc(1,sizeof(vhdl_t));
vhdl->is_vector = 1;
vhdl->expr = compile_expression(DOWNTO,$2,$4); }
| /* blank */ { vhdl = calloc(1,sizeof(vhdl_t)); *vhdl=*default_vhdl_datatype; };
/**********************************************************************/
/* if it doesnt have a body its a declaration : needs fixing ! */
/* currently need read_on / read_off declarations */
verilog_module_body : verilog_wires_block
verilog_module_instance_block
;
/**********************************************************************/
verilog_pindir_block : verilog_pindir_block verilog_pindir_decl
| verilog_pindir_decl
| /* nothing */
;
/* inout [3:0] gr for example */
verilog_pindir_decl : pin_dir {
id_count = 0 ; y1_first = NULL;y1_last = NULL; } verilog_bus_expr hdl_signal_names
';' { if(current_chip)
create_nodes_from_refs(current_chip,0); };
/**********************************************************************/
verilog_wires_block : verilog_wires_decl verilog_wires_block
| verilog_wires_decl
| /* nothing */
;
verilog_wires_decl : verilog_wire_start
verilog_bus_expr
hdl_signal_names
verilog_wire_end ;
verilog_wire_start : WIRE { id_count = 0 ; y_first = NULL;y_last = NULL; };
verilog_wire_end : ';' { if(current_chip)
create_nodes_from_refs(current_chip,0); };
/**********************************************************************/
/* verilog instance declarations */
/**********************************************************************/
verilog_module_instance_block : verilog_module_instances;
verilog_module_instances: verilog_module_instances verilog_module_instance
| verilog_module_instance
| /* nothing */;
verilog_module_instance: astring astring '(' verilog_port_map_list ')' ';' {
current_comp=find_socket(Type,$1,Search,&template_head);
if(!current_comp) {
Log(LOG_ERROR,
"-- (line %d) No component of type %s can be found : creating an instance\n",lineno,$1); current_chip = NULL;
}
else {
current_chip=find_socket(Ident,$2,Create,&socket_head);
if(current_chip) {
/* setup the current chip */
current_chip->template_socket = current_comp;
current_chip->is_template =0 ;
current_chip->parent_template_ref = NULL;
current_chip->route_flags = 0;
set_socket(current_chip,Name,""); /* socket has no name */
set_socket(current_chip,Type,$1); /* socket has a type */
current_comp_node = current_comp->nodes;
while(current_comp_node) {
current_comp_node->in_use = 0; /* clear in use/duplicate use flags */
current_comp_node=current_comp_node->sktnext;
}
current_comp_node = current_comp->nodes;
curr_comp_port_map = UNKNOWN;
}
}
};
/**********************************************************************/
/* the declaration may contain nothing or a list */
/**********************************************************************/
verilog_port_map_list : verilog_port_maps | /* nothing */;
verilog_port_maps : verilog_port_maps ',' verilog_port_map
| verilog_port_map ;
verilog_port_map : '.' astring '(' astring verilog_bus_expr ')' {
/* strip off the pin_ prefix */
if(current_comp) {
current_comp_node = find_node(current_comp,
Name,
$2,
Create); /* was 'search' */
}
if(current_chip && current_comp_node) {
if(current_comp_node->in_use == 0) {
current_comp_node->in_use = 1;
current_comp_node->lhs_expr = NULL;
define_pin(&unrouted_list,
current_chip,
current_comp_node->name,
current_comp_node->pindir,
current_comp_node->pin_group,
current_comp_node->identifier,
current_comp_node->vhdltype,
current_comp_node->lhs_expr);
rename_unrouted_pin_socket(current_chip,$2,rename_pin_string,vhdl);
}
else
Log(LOG_ERROR,"# (line %d) Error, port '%s.%s' already used\n",
lineno,
current_chip->identifier,$2);
}
else
{
if(!current_chip)
{
Log(LOG_ERROR,"# (line %d) Error no chip in context for port '%s'\n",lineno,$2);
}
else
{
Log(LOG_ERROR,"# (line %d) Error : cannot find port '%s.%s' \n",
lineno,
current_chip->identifier,$2);
}
}
}
| '.' astring '(' ')' {
current_comp_node = find_node(current_comp,
Name,
$2,
Search);
if(current_chip && current_comp_node) {
if(current_comp_node->in_use == 0) {
current_comp_node->in_use = 1;
}
else
Log(LOG_ERROR,"# (line %d) Error, port '%s.%s' already used\n",
lineno,
current_chip->identifier,$2);
}
else
{
if(!current_chip)
{
Log(LOG_ERROR,"# (line %d) Error no chip in context for port '%s'\n",lineno,$2);
}
else
{
Log(LOG_ERROR,"# (line %d) Error : cannot find port '%s.%s' \n",
lineno,
current_chip->identifier,$2);
}
}
}
;
/**************************************************************************/
/* ACFP generics : either global or device specific */
/**************************************************************************/
global_generic_decl :
GENERIC { generic_context = &global_generics; }
generic_defn_lines
END end_item { exit_lex_block(); free_lex_strings(); }
;
chip_generic_decl :
GENERIC { if(current_chip)
generic_context = ¤t_chip->generics; }
generic_defn_lines
END end_item
;
generic_defn_lines : generic_defn_lines end_item generic_defn_text
| generic_defn_text
| /* nothing */
;
/* added to allow more complete VHDL syntax */
generic_const_opt : CONSTANT
| /* nothing */
;
generic_pindir_opt : PINDIR { $$= $1; }
| /* nothing */ { $$= INPUT; }
;
generic_defn_text : generic_const_opt generic_defn_name_list ':' generic_pindir_opt generic_defn_type ;
generic_defn_name_list : generic_defn_name_list ',' generic_defn_name
| generic_defn_name ;
generic_defn_name : astring { make_string($1,&y_first,&y_last); };
generic_defn_type : INTEGER opt_integer {
struct str * s;
s = y_first;
while(s) {
info->name = s->dat;
info->typename = NULL;
info->g_type = IS_INTEGER;
info->expr = copy_expression($2,current_chip) ; /* ok allocated elsewhere */
info->valid = 0;
/* generic is tagged for elaboration */
info->is_component_generic = current_chip? current_chip->is_template:0;
set_generic_value(generic_context,info);
s = s?s->next:s; /* bizarre gcc 2.95 problem */
}
free_strings(&y_first,&y_last);}
| BOOLEAN opt_integer {
struct str * s;
s = y_first;
while(s) {
info->name = s->dat;
info->typename = NULL;
info->g_type = IS_BOOLEAN;
info->expr = copy_expression($2,current_chip) ; /* ok allocated elsewhere */
info->valid = 0;
/* generic is tagged for elaboration */
info->is_component_generic = current_chip? current_chip->is_template:0;
set_generic_value(generic_context,info);
s = s?s->next:s; /* bizarre gcc 2.95 problem */
}
free_strings(&y_first,&y_last);}
| INTEGER RANGE opt_bus_range {
struct str * s;
s = y_first;
while(s) {
info->name = s->dat;
info->g_type = $3->opcode;
info->typename = NULL;
info->expr = copy_expression($3,current_chip) ;
info->valid = 0;
info->is_component_generic = current_chip?current_chip->is_template:0;
set_generic_value(generic_context,info);
s = s->next;
}
free_strings(&y_first,&y_last);
}
| DECLARATION { text_buff[0]='\0'; }
assign_words {
struct str * s;
s = y_first;
while(s) {
info->name = s->dat;
info->typename = "declaration";
info->g_type = IS_DECLARATION_DIRECTIVE;
info->expr = compile_string(text_buff);
set_generic_value(generic_context,info);
s = s->next;
}
free_strings(&y_first,&y_last);
}
| INSTANCE { text_buff[0]='\0'; }
assign_words {
struct str * s;
s = y_first;
while(s) {
info->name = s->dat;
info->typename = "instance";
info->g_type = IS_INSTANCE_DIRECTIVE;
info->expr = compile_string(text_buff);
set_generic_value(generic_context,info);
s = s->next;
}
free_strings(&y_first,&y_last);}
| STRING { text_buff[0]='\0'; }
assign_words {
struct str * s;
s = y_first;
while(s) {
info->name = s->dat;
info->typename = "string";
info->g_type = IS_STRING; /* environment value : string */
info->expr = compile_string(text_buff);
set_generic_value(generic_context,info);
s = s->next;
}
free_strings(&y_first,&y_last);}
| ENV_STRING { text_buff[0]='\0'; }
assign_words {
struct str * s;
s = y_first;
while(s) {
info->name = s->dat;
info->typename = "env_string";
info->g_type = IS_ENV_VAL; /* environment value : string */
info->expr = compile_string(text_buff);
set_generic_value(generic_context,info);
s = s->next;
}
free_strings(&y_first,&y_last);}
/* setting up the attribute in a database file */
| ATTRIBUTE opt_integer {
struct str * s;
s = y_first;
while(s) {
info->name = s->dat;
info->typename = NULL;
info->g_type = IS_ATTRIBUTE;
info->expr = copy_expression($2,current_chip) ; /* ok allocated elsewhere */
info->valid = 0;
/* generic is tagged for elaboration */
info->is_component_generic = current_chip? current_chip->is_template:0;
set_generic_value(generic_context,info);
s=s->next;
}
free_strings(&y_first,&y_last);}
;
opt_integer : ASSIGN expr { info->g_class= DEFINED; $$ = $2; }
| /* nothing */ { info->g_class= DEFAULT; $$ = compile_constant(0); }
;
opt_bus_range : ASSIGN bus_range { info->g_class= DEFINED;$$ = $2; }
| /*nothing */ { expression_t * tmp;
info->g_class= DEFAULT;
tmp = compile_constant(0);
$$ = compile_expression(TO,tmp,tmp);}
;
assign_words : ASSIGN several_words
| /* nothing */;
/* pattern for picking up several space delimited words */
several_words : word several_words
| word
;
/* add a space if this int the first string */
word : astring { if(text_buff[0]) strcat(text_buff," "); strcat(text_buff,$1); };
/*****************************************************************************/
components_decl : COMPONENTS
BEGIN_TOK
comp_defn_lines
END end_item { exit_lex_block(); free_lex_strings(); }
;
comp_defn_lines : comp_defn_lines comp_defn_line
| comp_defn_line
|
;
comp_defn_line : chip_ident ':' chip_name chip_type chip_value end_item
;
chip_ident : astring { current_chip = find_socket(Ident,$1,Create,&socket_head);
};
chip_name : astring { if(current_chip)
set_socket(current_chip,Name,$1); };
chip_type : astring { if(current_chip)
set_socket(current_chip,Type,$1); };
chip_value : astring { if(current_chip)
set_socket(current_chip,Value,$1);
/* printf("Set up id %s \n",current_chip->identifier); */
};
/************************************************************************/
/* joining of net declarations jumpers=wired nets alias=unrouted nets */
joined_decl : JOINED_NETS
BEGIN_TOK
join_decls
END end_item { exit_lex_block(); free_lex_strings(); }
;
join_decls : join_decls join_decl
| join_decl
|
;
/* root_net is the one net that will continue to exist after the join.
Its properties will be kept , name and identifier */
join_decl : alias_part root_net '=' '(' joined_nets ')' end_item
| CONN astring astring { Log(LOG_GENERAL,
"# (line %d) Connecting all nodes on SOckets '%s' and '%s'\n",
lineno,
$2 ,$3); /* this creates all possible connections between two ID's */
create_all_jumpers($2,$3);} end_item
| VHDL_CONN vhdl_concurrent_assignment
;
alias_part : ALIAS { join_context = &unrouted_list;join_mode = Aliased;
create_unrouted_list();
}
| JUMPER { join_context = &routed_list; join_mode = Jumpered;}
| { join_context = &routed_list; join_mode = Jumpered;}
;
root_net : netname {/* printf("root net found '%s'\n",$1); */
top_net = find_net(join_context,Ident,$1,Search);
if(top_net) {
if(top_net->how_joined == NotJoined) {
/* trap attempts to jumper extend a non-jumper net */
Log(LOG_ERROR,"# (line %d) ERROR : Net '%s' already exists, cannot create jumper\n",
lineno,
top_net->identifier);
top_net = NULL;
}
else {
Log(LOG_ERROR,"# Warning : %s net '%s' already exists, net is being extended from %d nodes\n",
lineno,
top_net->how_joined == Jumpered ? "Jumpered" : "Aliased",
top_net->identifier,top_net->nodecount);
/* if the net is already in existence, it will have nodes */
}
}
else {
top_net = find_net(join_context,Ident,$1,Create);
top_net->how_joined = join_mode;
top_net->vhdltype = default_vhdl_datatype;
/* printf(" Join mode - %d\n",join_mode); */
}
/* top_net->name = top_net->identifier; */
printf("TOP NET = %s \n",top_net->identifier);
};
joined_nets : joined_nets joined_net
| joined_net
;
joined_net : single_net end_item
| jumper_node end_item
;
single_net : netname { /* printf(" additional net found '%s'\n",$1); */
if (top_net) {
current_net = find_net(join_context,Ident,$1,Search);
if(!current_net)
Log(LOG_ERROR,"# (line %d) ERROR : Cannot locate net '%s'\n",lineno,$1);
else {
if(current_net == top_net)
Log(LOG_ERROR,"# (line %d) ERROR : Cannot jumper '%s' to itself\n",lineno,$1);
else {
/* mark this as a net referred to by net name */
current_net->external_node = NULL;
transfer_net_to_subnet(join_context,
top_net, current_net);
}
}
};
};
/* this looks for the net that a node is on : this will be a Jumper connection */
jumper_node : netname '(' astring ')' {
if( top_net) {
/* find socket that node is connected to*/
current_chip = find_socket(Ident,$1,Search,&socket_head);
if (!current_chip)
Log(LOG_ERROR,"-- (line %d) Cannot locate socket '%s'\n",lineno,$1);
else {
/* find node itself */
current_node = find_node(current_chip,Ident,$3,Search);
if (!current_node)
Log(LOG_ERROR,"-- (line %d) Cannot locate node '%s(%s)'\n",lineno,$1,$3);
else {
/* use net that node is on */
if(!current_node->routed_net)
Log(LOG_ERROR,"-- (line %d) Cannot locate net for node '%s(%s)'\n",lineno,$1,$3);
else
if (current_node->routed_net->list_ref == &routed_list)
{
/* mark this as a net referred to by node ID not net name */
/* printf("Current net is %s : node is %s(%s)\n",current_node->routed_net->identifier,current_chip->identifier,current_node->identifier); */
if (transfer_net_to_subnet(join_context,top_net, current_node->routed_net))
{
current_node->routed_net->external_node = current_node;
}
else
{
Log(LOG_ERROR,"-- (line %d) jumper foulup with net referred to by %s(%s)\n",lineno,$1,$3);
}
}
else
Log(LOG_ERROR,"-- (line %d) node '%s(%s)' is on %s: not routed list\n",
lineno,$1,$3,decode_which_list(current_node->routed_net->list_ref));
}
}
}
};
/* new stuff Feb 1997 ******************************************************************** */
/* this can be replaced by VHDL component instances within an architecture
block Sep 2000 */
rename_pins_block : RENAME_PINS
BEGIN_TOK
rename_pin_decls
END end_item { exit_lex_block(); free_lex_strings(); }
;
rename_pin_decls : rename_pin_decls rename_pin_decl
| rename_pin_decl
;
rename_pin_decl : rename_new_name '=' '(' rename_pin_items ')' end_item;
rename_new_name : netname { rename_pin_string = $1;
vhdl = default_vhdl_datatype;}
| netname '(' bus_range ')' { rename_pin_string = $1;
vhdl = calloc(1,sizeof(vhdl_t));
/* acquire datatype later */
vhdl->expr = $3;
vhdl->is_vector =1;
vhdl->valid = 0;
}
;
rename_pin_items : rename_pin_items rename_pin_item
| rename_pin_item
;
rename_pin_item : astring '.' astring end_item {
rename_unrouted_pin($1,$3,rename_pin_string,vhdl);
}
| /* nothing */
;
/************************************************************************/
/* net declarations : as predefined by either wiring or previous passes */
nets_decl : WIRED_NETS { current_list = &routed_list ; }
BEGIN_TOK
connection_block
END end_item { exit_lex_block(); }
;
connection_block : connection_block connection_block_item
| connection_block_item
;
connection_block_item : routed_decl
| unrouted_decl
| named_decl
| conn_decls
| /* nothing */
;
routed_decl : ROUTED { current_list = &routed_list ; }
;
unrouted_decl: UNROUTED { current_list = &unrouted_list ; }
;
named_decl : NAMED { Log(LOG_GENERAL,"-- (line %d) Netlist contains NAMED block,converting signals to ROUTED as its more useful\n",lineno);
current_list = &routed_list ; }
;
conn_decls : conn_decls conn_decl
| conn_decl
;
/* in here we can add mentions of other net attibutes */
conn_decl : CONN conn_ident conn_name last_route_status end_item
nodelist
END_CONN { free_lex_strings(); } end_item
;
conn_ident : netname { current_net = find_net(current_list,Ident,$1,Create);
};
conn_name : astring { set_net(current_net,Name,$1);
};
last_route_status : astring { set_net(current_net,How_Routed,$1);
};
nodelist : nodelist net_node
| net_node
|
;
net_node : skt_id '(' node_id ')' fix_loc_part force_pin_dir node_group end_item
;
/* if a pin direction is given in the pin list then the pin is forced to
be an input or an output.
The reference to the node has its pin direction set the same as
the fixed pin direction if it is a fixed pin. */
/* the null added in order to define no pin name alias at present */
force_pin_dir : PINDIR { connect_node_net(NULL,current_node,current_net,$1,default_vhdl_datatype,NULL,NULL);
/* these set the actual pin up */
current_node->fixed_pin = ($1 != BIDIR);
current_node->pindir = $1;
if(current_list == &routed_list)
current_node->routed_net= current_net;
}
/* no direction, must be dont care direction */
| /* nothing*/ { connect_node_net(NULL,current_node,current_net,BIDIR,default_vhdl_datatype,NULL,NULL);
/* this sets the actual pin up */
current_node->fixed_pin = 0;
current_node->pindir = BIDIR;
if(current_list == &routed_list)
current_node->routed_net= current_net; }
;
skt_id : astring { current_chip = find_socket(Ident,$1,Create,
&socket_head);
};
node_id : netname { if(current_chip)
current_node = find_node(current_chip,Ident,$1,Create); }
;
/* we can try and force unrouted nets referring to this pin to be fixed to it */
fix_loc_part : FIX_LOCATION { current_node->fix_location = 1;
current_net->has_fix_location = 1; }
| /* nothing */ { current_node->fix_location = 0; }
;
node_group : '(' NUM_STRING ')' { convert_num($2,¤t_node->pin_group); }
| /* nothing */
;
/************************************************************/
/* Netname is a catch all for special names that are now picked up
separately by the lex parser for some special cases */
netname : VCC { $$=$1; }
| GND { $$=$1; }
| astring { $$=$1; };
/*************************************************************************/
/* The definition of a template that fixes pins as inputs, outputs or */
/* configuration pins or pin groups */
/*************************************************************************/
/* The basic template is just like a chip delcaration */
/* remembering to convert all of the pin name references
to actual pins on the template */
template_decl: template_id_decl
BEGIN_TOK
template_info_lines
pin_declarations
pin_equivalences
END end_item { if(current_chip)
{
create_nodes_from_refs(current_chip,0);
Log(LOG_GENERAL,"-- (line %d) Template '%s' created\n",
lineno,
current_chip->type);
if (current_chip->parent_template_ref )
Log(LOG_GENERAL,"-- as alias to '%s'\n",
current_chip->parent_template_ref->type);
exit_lex_block() ;
free_lex_strings();
}
}
;
template_id_decl: TEMPLATE template_name ;
template_name : astring {
current_chip=find_socket(Type,$1,Create,&template_head);
if(current_chip)
current_chip->is_template = 1; };
template_info_lines : template_info_lines template_info_line
| template_info_line
;
template_info_line : chip_generic_decl
| alias_to_another_template
| /* blank */
;
/* this allows one template to say it is the Alias of another template */
alias_to_another_template : ALIAS astring end_item {
if (current_chip && current_chip->parent_template_ref) {
Log(LOG_ERROR,
"-- (line %d) chip '%s' already alias of '%s'\n",
lineno,
$2,current_chip->parent_template_ref->type);
}
else {
socket_t* original_chip = find_socket(Type,$2,Search,&template_head);
if(!original_chip) {
Log(LOG_ERROR,
"-- (line %d) Cannot find original template for alias '%s'\n",lineno,$2);
}
else {
if(current_chip)
{
current_chip->parent_template_ref = original_chip;
current_chip->nodes = original_chip->nodes;
current_chip->lastnode = original_chip->lastnode;
current_chip->equivalent_node_set = original_chip->equivalent_node_set;
}
}
}
};
/* end alias stuff */
/*************************************************************************/
/* Extensions to syntax to read TDF files */
/**************************************************************************/
/*AHDL Chip Declarations */
/**************************************************************************/
ahdl_region : AHDL
ahdl_chip_decls
END end_item { exit_lex_block(); free_lex_strings(); }
;
ahdl_chip_decls : ahdl_chip_decl ahdl_chip_decls
| ahdl_chip_decl
;
ahdl_chip_decl : ahdl_entityname_decl
| ahdl_port_decl
| /* nothing */
;
ahdl_entityname_decl : SUBDESIGN TXT_STRING
{
current_chip=find_socket(Name,$2,Create,&socket_head);
if(current_chip)
{
current_chip->is_template = 0;
current_chip->parent_template_ref = NULL;
current_chip->route_flags = 0;
ensure_socket_ident(current_chip);
set_socket(current_chip,Type,"AHDL");
generic_context = ¤t_chip->generics;
}
};
/* mandatory port list */
ahdl_port_decl : '(' ahdl_port_list ')';
ahdl_port_list : ahdl_port_list end_item ahdl_port_item
| ahdl_port_item
| /* nothing */
;
/* the AHDL Port item , inherits the pin_dir from a standard chip declaration
and the vhdl type extraction from the generic type declaration
*/
ahdl_port_item : ahdl_name_list ':' pin_dir {
process_tdf_pins(y_first);
free_strings(&y_first,&y_last);
} ;
ahdl_name_list : ahdl_name_list ',' ahdl_name_part
| ahdl_name_part ;
/* null the pin identifier to allow for creation of an ident in define_pin */
ahdl_name_part : astring {
char * s = make_string($1,&y_first,&y_last);
curr_pin_ident[0] = '\0';
curr_pin_dir = NONE; /* default bidirectional */
if(ISNULLSTR(s) && id_count ==0)/* the null strings tell acfread that the pin exists and */
current_list = &routed_list ;/* available for routing */
else
current_list = &unrouted_list ;
id_count++;
};
%%
/* defining lineno at top of code so it is in scope */
int errorseen = 0;
#if defined IS_HPUX
extern unsigned char * yytext[];
#else
extern char * yytext;
#endif
extern FILE * yyin;
void process_tdf_pins(struct str * s) {
char * basename;
vhdl_t * defvhdl;
int is_vec,idx=0,l,hi=0,lo=0;
int numeric ;
basename = NULL;
is_vec = 0;
while(s) {
l = strlen(s->dat);
if(l){
/* name ends in underscore, this forces mapping
name_nn_ --> vector entry name(nn) */
numeric = 0;
l--;
if(s->dat[l] =='_'){
l--;
numeric = 1;
while(l>=0 && s->dat[l] != '_')
if(!isdigit(s->dat[l--]))
numeric = 0;
if(l>= 0 && s->dat[l]=='_' && numeric)
/* we have found a valid vector element entry */
idx = atoi(s->dat+l+1);
}
/* we know if its numeric it is probably a vector element */
if(numeric && (!basename || strncmp(basename,s->dat,l)==0) ) {
if(!is_vec) {
/* if it is the first one then save a reference */
hi =idx;
lo =idx;
basename = s->dat;
basename[l] = 0;
is_vec=1;
}
else {
if(idx>hi)hi =idx;
if(idx<lo)lo =idx;
}
}
else {
if (is_vec) {
defvhdl = calloc(1,sizeof(vhdl_t));
*defvhdl = *default_vhdl_bustype;
defvhdl->expr = compile_expression(DOWNTO,
compile_constant(hi),
compile_constant(lo));
#if defined DEBUG_EXPRESSION
printf("Data bus '%s' h=%d l=%d\n",basename,hi,lo);
#endif
/* defvhdl.is_vector = defvhdl.low!=defvhdl.high; */
/* single bit or bus */
define_pin(current_list,
current_chip,
basename,
curr_pin_dir,
curr_pin_group,
curr_pin_ident,
defvhdl,
NULL) ;
basename = NULL;
is_vec = 0;
}
else {
#if defined DEBUG_EXPRESSION
printf("Pin '%s'\n",s->dat);
#endif
define_pin(current_list,
current_chip,
s->dat,
curr_pin_dir,
curr_pin_group,
curr_pin_ident,
default_vhdl_datatype,NULL) ;
}
}
} /* if l */
s=s->next;
} /* while s */
}
/* function used in definition of ports or signals of a
particular type */
void create_pins_or_signals(void) {
struct str * s;
s = y_first;
/* function called in define_pin context */
while(s) {
#if defined DEBUG_EXPRESSION
printf("define pin %s,",s->dat);
#endif
define_pin(current_list,
current_chip,
s->dat,
curr_pin_dir,
curr_pin_group,
/* if known use curr_pin_ident */
curr_pin_ident[0] ? curr_pin_ident : s->dat,
copy_vhdl(vhdl,current_chip),
NULL) ;
s=s->next;
}
#if defined DEBUG_EXPRESSION
printf("\n");
#endif
/* function is called in define signal context. */
s = y1_first;
while(s) {
net_t * net;
#if defined DEBUG_EXPRESSION
printf("define signal %s\n",s->dat);
#endif
net = find_net(&unrouted_list,Ident,s->dat,Create);
if(net) {
net->type_defined = 1; /* we have defined the correct datatype */
net->vhdltype = copy_vhdl(vhdl,NULL); /* ???? do we need malloc/copy here */
/* as all signals defined at the same time share the memory for
type declaration */
}
s=s->next;
}
#if defined DEBUG_EXPRESSION
printf("\n");
#endif
if(y1_first)
free_strings(&y1_first,&y1_last);
if(y_first)
free_strings(&y_first,&y_last);
id_count = 0;
}