Blame | Last modification | View Log | Download | RSS feed
/* generics.c */
/* contains the database functions for lookup of generic information */
/*
* $Header: c:\\cygwin\\cvsroot/Vert03/vertlib/generic.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $
* $Log: generic.c,v $
* Revision 1.1.1.1 2003/11/04 23:34:57 mjames
* Imported into local repositrory
*
* Revision 1.15 2002/09/30 13:27:43 MJAMES
* Created function to tidy up partition generics.
*
* Revision 1.14 2002/09/18 08:51:33 mjames
* Removed unused variables
*
* Revision 1.13 2002/09/09 10:27:53 mjames
* Removed set generic range and replaced it with a set generic value command
* that takes both integers and ranges.
*
* Revision 1.12 2002/01/15 12:35:23 mjames
* DLL declarations put in
*
* Revision 1.11 2001/12/14 15:01:39 mjames
* Removed unecessary 'generic_waste' function
*
* Revision 1.10 2001/12/13 22:20:11 mjames
* Using #ident with header to identify file
*
* Corrected GENERIC MAP printout (partially !)
*
* Revision 1.9 2001/11/19 10:41:51 mjames
* Merged back DTC release
*
* Revision 1.8.2.1 2001/11/16 15:06:57 mjames
* Corrected an error in the return value of a function
*
* Revision 1.8 2001/11/01 11:05:32 mjames
* Printing a list of generic definitiions for ACFP files: case
* for handling integer constants was omitted.
*
* Revision 1.7 2001/10/31 22:20:07 mjames
* Tidying up problematical comments caused by CVS
* 'intelligent' comment guessing
*
* Revision 1.6 2001/10/22 10:59:57 mjames
* Added IS_ATTRIBUTE : a generic attribute used for controlling VERTICAL.
* Can have either string or expression here.
*
* Revision 1.5 2001/06/06 12:10:21 mjames
* Move from HPUX
*
* Revision 1.4 2001/04/09 14:58:29 mjames
* Added capability to delete generics from specific sockets.
*
* Revision 1.3 2001/04/06 22:47:02 mjames
* Added doc2, the creator of documentation to Vertical scripts uses PERL
*
*
* Also correcting generic behaviour and the printing of Verilog.
*
* Revision 1.2 2000/11/29 21:51:18 mjames
* Fine tuning of software
*
* Revision 1.1.1.1 2000/10/19 21:58:38 mjames
* Mike put it here
*
*
* Revision 1.28 2000/10/12 15:32:26 15:32:26 mjames (Mike James)
* Removed <cr>
*
* Revision 1.27 2000/10/04 10:37:06 10:37:06 mjames (Mike James)
* Modified for Vertical2 : support COMPONENTS and SIGNALS
*
* Revision 1.27 2000/10/04 10:37:06 10:37:06 mjames (Mike James)
* Part of Release PSAVAT01
*
* Revision 1.26 2000/10/02 11:04:14 11:04:14 mjames (Mike James)
* new_vhdl
*
* Revision 1.25 2000/09/27 14:42:15 14:42:15 mjames (Mike James)
* Part of Release Sep_27_ST_2000
*
* Revision 1.24 2000/09/27 10:45:43 10:45:43 mjames (Mike James)
* Started using the g_class member of the generic structu[re
*
* Revision 1.23 2000/09/21 10:15:45 10:15:45 mjames (Mike James)
* Part of Release Sep21Alpha
*
* Revision 1.22 2000/08/25 09:57:12 09:57:12 mjames (Mike James)
* Part of Release Aug25_alpha
*
* Revision 1.21 2000/08/16 08:57:28 08:57:28 mjames (Mike James)
* Part of Release CD01_Aug2000
*
* Revision 1.20 2000/08/14 14:45:09 14:45:09 mjames (Mike James)
* Part of Release Aug_14_2000
*
* Revision 1.19 2000/08/11 08:30:30 08:30:30 mjames (Mike James)
* Part of Release Aug_11_2000
*
* Revision 1.18 2000/08/09 10:31:44 10:31:44 mjames (Mike James)
* Part of Release Aug__9_2000
*
* Revision 1.17 2000/05/31 11:42:53 11:42:53 mjames (Mike James)
* Part of Release May_31_2000
*
* Revision 1.16 2000/05/08 17:01:35 17:01:35 mjames (Mike James)
* Part of Release May__8_2000
*
* Revision 1.15 2000/05/08 16:59:28 16:59:28 mjames (Mike James)
* Part of Release May__8_2000
*
* Revision 1.14 2000/05/08 16:57:05 16:57:05 mjames (Mike James)
* Part of Release May__8_2000
*
* Revision 1.13 2000/03/08 16:19:08 16:19:08 mjames (Mike James)
* New version including PC
*
* Revision 1.10 2000/01/20 15:58:44 15:58:44 mjames (Mike James)
* Part of Release R22
*
* Revision 1.9 99/12/22 11:15:25 11:15:25 mjames (Mike James)
* Part of Release Dec_22_1999
*
* Revision 1.8 99/11/23 13:52:05 13:52:05 mjames (Mike James)
* Addded syntax to support special generics for Certify support
*
* Revision 1.7 99/06/25 14:35:35 14:35:35 mjames (Mike James)
* Added in reference to expression.h, but no changes made
* to the function of acfread yet.
*
* Revision 1.6 99/06/18 09:24:17 09:24:17 mjames (Mike James)
* Added new VHDL printing of generic information
*
* Revision 1.5 99/05/04 09:51:21 09:51:21 mjames (Mike James)
* Amended generic lookup rules
*
* Revision 1.4 98/08/12 14:20:50 14:20:50 mjames (Mike James)
* removed bug in generic lookup.
*
* Revision 1.3 98/07/14 13:24:16 13:24:16 mjames (Mike James)
* fixed errors in lookup of generic variables -
* now works better
*
* Revision 1.2 98/03/16 11:37:09 11:37:09 mjames (Mike James)
* Updated generic storage and lookup
*
* Revision 1.1 98/02/11 11:26:11 11:26:11 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 "cmdparse.h"
#include "cmdlog.h"
/* this is included regardless of the translator being built */
#include "acf_yacc.h"
#ident "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/generic.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $"
generic_info_t * global_generics=NULL; /* list of user set generics */
generic_info_t * partition_generics = NULL; /* list of all unique generic names found on
entities within a partition */
/* This function converts an integer value expressed in a number base
e.g. 2_1010110 binary
16_0xf002 hex
3234 decimal */
int convert_num(char * string,int * value) {
char * endptr;
int base;
long val;
/* identify numbers like base_nnnnnn */
if(isdigit(string[0])) {
val = strtol(string,&endptr,10);
if (*endptr=='_') {
base=(int)val;
endptr++;
val = (int)strtol(endptr,&endptr,base);
}
*value = (int)val;
return 1; /* success */
}
else {
/* *value = 1; */
return 0;/* fail */
}
}
__declspec (dllexport) generic_type_t get_generic_value(
generic_info_t ** list, char * string,
generic_info_t * result) {
generic_info_t * ptr ;
int val;
if(list)
ptr = * list;
result->g_type = NO_VALUE; /* Unknown information */
/* identify numbers like base_nnnnnn */
if(convert_num(string,&val)==1) {
result->g_type = IS_INTEGER;
result->expr = compile_constant(val);
}
else {
/* look up name and see if it has an integer value */
while(ptr) {
if(strcmp2(ptr->name,string)==0)
break;
ptr=ptr->next;
}
if(ptr) {
/* printf("%s : found value = %d\n",string,ptr->value); */
*result = *ptr;
/* printf("%s : found value = %s\n",string,ptr->name); */
}
/* check to see if the string returned is valid in future at this point */
}
#if defined DEBUG_EXPRESSION
if(ptr)
printf("GET %s %p looked up\n",ptr->name,ptr);
#endif
return result->g_type;
}
__declspec (dllexport) generic_info_t * get_generic_ref(
generic_info_t ** list, char * string) {
generic_info_t * ptr ;
if(list)
{
ptr = * list;
}
else
{
return NULL;
}
/* look up name and see if it has an integer value */
while(ptr) {
if(strcmp2(ptr->name,string)==0)
break;
#if defined DEBUG_EXPRESSION
if(ptr)
printf("REF %s %p looked up\n",ptr->name,ptr);
#endif
ptr=ptr->next;
}
#if defined DEBUG_EXPRESSION
if(ptr)
printf("REF %s %p looked up\n",ptr->name,ptr);
#endif
return ptr;
}
/* this function makes a copy of the generic passed to it */
/* but it cannot make a copy of the expression because it
* requires knowledge of whether this generic is local to
* a component instance or global : this is done by the caller
*/
__declspec (dllexport) generic_info_t * set_generic_value(generic_info_t ** list, generic_info_t * info) {
generic_info_t * ptr,* prev;
prev = NULL;
if(list)
ptr = * list;
else
return NULL;
while(ptr) {
if(strcmp2(ptr->name,info->name)==0)
break;
prev=ptr;
ptr=ptr->next;
}
/* there is no existing generic of the appropriate name */
if (!ptr) {
ptr=calloc(1,sizeof(generic_info_t));
if(!prev)
*list = ptr;
else
prev->next = ptr;
ptr->next = NULL;
ptr->expr_ref = NULL;
ptr->is_component_generic = info->is_component_generic; /* allows me to find which list defined on */
ptr->name = allocstr(info->name);
}
else {
/* free(ptr->typename); */
/* free(ptr->valuename); */
}
if(ptr) {
#if defined DEBUG_EXPRESSION
printf("SET %s %p assign '",info->name,ptr);
print_expression(stdout,info->expr,0);
printf("'=%d was '",eval_expression(info->expr,list));
print_expression(stdout,ptr->expr,0);
printf("'\n");
#endif
ptr->typename = allocstr(info->typename);
ptr->valid = 0;
ptr->expr = info->expr;
ptr->g_type = info->g_type;
ptr->g_class = info->g_class;
}
return ptr;
}
/* new delete generic call is used to clean up databases */
__declspec (dllexport) int del_generic_value(generic_info_t ** list, generic_info_t * info) {
generic_info_t * ptr,* prev = NULL;
if(list)
ptr = * list;
else
return 1;
while(ptr) {
if(strcmp2(ptr->name,info->name)==0)
break;
prev=ptr;
ptr=ptr->next;
}
if (!ptr)
return 1;
/* we have found a generic of the appropriate name and now
* it will be deleted. We cannot remove any of the expressions
* or strings used as they may be shared if they were declared
* with the use of a wildcard assignment. Pay the price
* of a potential memory leak here .... */
if (prev)
prev->next = ptr->next;
else
*list = ptr->next;
free(ptr); /* we can be sure this is unique however */
return 0;
}
#define MAXINDENT 8
static char linebuff[MAXIDLEN];
static char * escape_quote(char * str) {
char *f = str,*t = linebuff;
while (*f) {
if (*f=='\"' || *f=='\\')
*t++ = '\\';
*t++ = *f++;
}
*t=0;
return linebuff;
}
__declspec (dllexport)void list_generic_values(FILE * f,generic_info_t ** list,int indent) {
generic_info_t * ptr;
int i;
char indents[MAXINDENT+1];
if(list)
ptr = *list;
else
ptr = NULL;
/* build up the line of indents */
for(i=0;(i<indent) && (i<MAXINDENT); indents[i++]=' ');
indents[indent] = 0;
fprintf(f,"%sGENERIC -- Generic constants \n",indents);
while(ptr) {
char * string = NULL;
if (ptr->expr)
string = ptr->expr->left.s; /* pickup string for future use */
fprintf(f,"%s %-20s : ",indents,ptr->name); /* print its name */
switch(ptr->g_type) {
case NO_VALUE:
case IS_STRING:
case IS_ENV_VAL:
fprintf(f," %-10s := \"%s\"",
ptr->typename? ptr->typename :"",
string?escape_quote(string):"");
break;
case IS_ATTRIBUTE:
fprintf(f," attribute ");
if (ptr->g_class == DEFINED) {
fprintf(f," := ");
print_expression(f,ptr->expr,0);
}
break;
case IS_BOOLEAN:
fprintf(f," boolean ");
if (ptr->g_class == DEFINED) {
fprintf(f," := ");
print_expression(f,ptr->expr,0);
}
break;
case IS_INTEGER:
fprintf(f," integer ");
if (ptr->g_class == DEFINED) {
fprintf(f," := ");
print_expression(f,ptr->expr,0);
}
break;
case TO:
case DOWNTO:
fprintf(f," integer range ");
if (ptr->g_class == DEFINED) {
fprintf(f," := ");
print_range_expression(f,ptr->expr,0);
}
break;
case IS_DECLARATION_DIRECTIVE:
if (!ISNULLSTR(string))
fprintf(f," declaration := \"%s\"",escape_quote(string));
else
fprintf(f," declaration");
break;
case IS_INSTANCE_DIRECTIVE:
if (!ISNULLSTR(string))
fprintf(f," instance := \"%s\"",escape_quote(string));
else
fprintf(f," instance");
break;
};
if(ptr->next)
fprintf(f,";\n");
ptr=ptr->next;
}
fprintf(f,"\n%sEND;\n\n",indents);
}
__declspec (dllexport) void list_VHDL_generic_map_values(FILE * f,generic_info_t ** list ) {
generic_info_t * ptr = *list;
if (ptr) {
fprintf(f,"-- Generic constants\n");
fprintf(f," GENERIC MAP ( \n" );
}
while(ptr) {
/* only integer and string generic constants OK */
switch(ptr->g_type) {
case IS_STRING:
case IS_INTEGER:
case IS_BOOLEAN:
fprintf(f," %-10s => ",
ptr->name? ptr->name :"");
print_expression(f,ptr->expr,0);
break;
default:
fprintf(f,"-- %-10s",
ptr->name? ptr->name :"");
break;
}
if(ptr->next)
fprintf(f,",\n");
else
fprintf(f,"\n )\n"); /* no closing semi on GENERIC MAP */
ptr=ptr->next;
}
}
/********************************************************************/
__declspec (dllexport) int print_VHDL_constant(FILE * f,char * s,generic_info_t * ptr,generic_print_style recurse_generics) {
expression_t * exp;
if (!ptr)
return 0;
exp = ptr->expr;
if (exp) {
switch(ptr->g_type) {
case TXT_STRING:
fprintf(f," %s %-20s : string := ",s,ptr->name);
print_expression(f,exp,recurse_generics);
return 1;
break;
case TO:
case DOWNTO:
fprintf(f," %s %-20s : integer range:= ",s,ptr->name);
print_range_expression(f,exp,recurse_generics);
return 1;
break;
case IS_INTEGER:
fprintf(f," %s %-20s : integer:= ",s,ptr->name);
print_expression(f,exp,recurse_generics);
return 1;
break;
case IS_BOOLEAN:
fprintf(f," %s %-20s : boolean:= ",s,ptr->name);
print_expression(f,exp,recurse_generics);
return 1;
break;
default:
return 0;
/* nothing */
};
}
return 0;
}
/********************************************************************/
__declspec (dllexport) void list_VHDL_generic_values(FILE * f,generic_info_t ** list ) {
generic_info_t * ptr;
int printed;
ptr = *list;
if (ptr) {
fprintf(f,"-- Generic constants\n");
fprintf(f," GENERIC ( \n" );
}
printed = 0;
while(ptr) {
if (printed)
fprintf(f,";\n");
printed = print_VHDL_constant(f,"",ptr,0);
ptr=ptr->next;
}
if (*list)
fprintf(f,");\n"); /* closing semi on GENERIC */
}
/********************************************************************/
void list_VHDL_constants(FILE * f,generic_info_t ** list ) {
generic_info_t * ptr = *list;
while(ptr) { /* recursively expand generics to the full expression */
if(print_VHDL_constant(f," CONSTANT ",ptr,1))
fprintf(f,";\n");
ptr=ptr->next;
}
fprintf(f,"\n");
}
/********************************************************************/
/* this was used before CONSTANTS were used. Keeping it because it
* will be useful when name spaces are properly implemented : if there
* are any unresolved global generics then partition generics should be
* created
*/
/********************************************************************/
void setup_generic_types(generic_info_t* list) {
generic_info_t * ptr = list;
/* invalidate all values */
while (ptr) {
ptr->valid = 0;
ptr= ptr->next;
}
ptr = list;
while (ptr) {
if (!ptr->valid) {
/* this simply does type extraction from the expression
component now */
eval_gen_expression(ptr);
}
ptr->valid = 1;
ptr= ptr->next;
}
}
/* if a generic has an expression which is a string or integer constant,
transfer it to the other list */
void transfer_constant_generics(generic_info_t ** src,generic_info_t ** dst) {
generic_info_t * prev, * curr, * next;
prev = NULL;
curr = *src;
while(curr) {
expression_t * exp;
exp = curr->expr;
next= curr->next; /* remember the next pointer for later */
if (exp && (exp->opcode == EXP_STRING || exp->opcode == EXP_CONSTANT)) {
if(prev)
prev->next = curr->next; /* link over it */
if(curr == *src) /* if was first element of list, set head to next */
*src = curr->next;
curr->next = *dst; /* link to old head of destination list */
*dst = curr; /* place on head of destination list */
}
else
prev = curr; /* only move on prev if we have not removed curr..*/
curr = next;
}
}
extern void clear_partition_generics(generic_info_t ** list)
{
generic_info_t* ptr, * prev_ptr;
expr_ref_t * refs, * prev_refs;
ptr = * list;
while(ptr)
{
prev_ptr = ptr;
refs = ptr->expr_ref;
while (refs)
{
prev_refs = refs;
if(refs->expr)
{
refs -> expr->opcode = EXP_UNDEF_VAR;
refs -> expr->left.g = NULL;
}
refs = refs->expr_ref;
free(prev_refs);
};
ptr = ptr -> next;
free(prev_ptr);
};
*list = NULL;
}
/* compute the values of all expressions */
void elaborate_all(void) {
socket_t * socket;
printf("elaborate\n");
setup_generic_types(global_generics);
setup_generic_types(partition_generics);
transfer_constant_generics(&global_generics,&partition_generics);
socket = socket_head;
while (socket) {
setup_generic_types(socket->generics);
socket = socket->next;
}
}
void copy_declaration_generics(socket_t * skt,socket_t * from) {
generic_info_t * src;
/* puts("copy_declaration_generics"); */
src = from->generics;
while(src) {
if (get_generic_ref(&skt->generics,src->name))
set_generic_value(&(skt->generics), src) ;
src = src->next;
}
src = skt->unrouted_generics;
while(src) {
if (get_generic_ref(&skt->generics,src->name))
set_generic_value(&(skt->generics), src) ;
src = src->next;
}
puts("done declaration generics");
}