Subversion Repositories Vertical

Rev

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 structue
 * 
 * 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");

  }