Subversion Repositories Vertical

Rev

Rev 2 | Blame | Last modification | View Log | Download | RSS feed

/* contains the database functions that store the pin configurations 
 *
 * $Header: c:\\cygwin\\cvsroot/Vert03/vertlib/database.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $ 
 * $Log: database.c,v $
 * Revision 1.1.1.1  2003/11/04 23:34:57  mjames
 * Imported into local repositrory
 *
 * Revision 1.13  2003/01/02 21:37:15  mjames
 * Experiment on creating NOT_ROUTABLE_H and NOT_ROUTABLE_L
 * properties on the nets so that pin jumpers can be made without a problem.
 *
 * Still need to sort out pin assignments made to these not_routable nets
 * which will become legal in some cases so that pullups and pulldown
 * pins can be used on the FPGA.
 *
 * Revision 1.12  2002/09/30 13:26:49  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.11  2002/08/06 12:52:54  mjames
 * Merge in from latest version
 *
 *
 * Revision 1.11  2002/03/21 17:13:05  mjames
 * Added search path to vertical file opening for read
 *
 * Revision 1.10  2002/01/15 12:32:42  mjames
 * DLL declarations put in,
 *
 * #ident used
 *
 * Revision 1.9  2001/11/19 09:45:25  mjames
 * Corrected some case statments with no default action
 *
 * Revision 1.8  2001/10/31 22:20:02  mjames
 * Tidying up problematical comments caused by CVS
 * 'intelligent' comment guessing
 *
 * Revision 1.7  2001/10/31 16:22:55  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.
 * Net disconnection works on routed and named nets
 *
 * Revision 1.6  2001/10/23 21:12:43  mjames
 * Created preliminary 'disconnect_node' function
 *
 * Revision 1.5  2001/10/10 20:18:24  mjames
 * Added a vert_regcomp function to compile regular expressions
 * with '^' (match start string) and  '$' (match end string) bracketing
 * this => wildcard must match entire string not just a part of it.
 *
 * Revision 1.4  2001/10/07 20:50:53  mjames
 * Added wildcard checking (warn user about
 * using wildcard '*' on the end of a string in stead of wildcard '.*')
 *
 * Revision 1.3  2001/09/25 23:15:24  mjames
 * Converted wildcards to use proper regexp pattern match library
 *
 * Revision 1.2  2001/06/06 12:10:24  mjames
 * Move from HPUX
 *
 * Revision 1.1.1.1  2000/10/19 21:58:35  mjames
 * Mike put it here
 *
 *
 * Revision 1.61  2000/10/04  10:37:03  10:37:03  mjames (Mike James)
 * COnversion to Vertical2, supports signals and components
 * 
 * Revision 1.61  2000/10/04  10:37:03  10:37:03  mjames (Mike James)
 * Part of Release PSAVAT01
 * 
 * Revision 1.60  2000/10/03  10:05:27  10:05:27  mjames (Mike James)
 * Added CONSTANTS and SIGNALS to architecture
 * 
 * Revision 1.58  2000/09/27  14:42:11  14:42:11  mjames (Mike James)
 * Part of Release Sep_27_ST_2000
 * 
 * Revision 1.57  2000/09/21  10:15:40  10:15:40  mjames (Mike James)
 * Part of Release Sep21Alpha
 * 
 * Revision 1.56  2000/09/21  09:44:29  09:44:29  mjames (Mike James)
 * Added in code to deal with pin equivalents, and removed some
 * spurious diagnostic puts() calls .
 * 
 * Revision 1.55  2000/08/25  09:57:09  09:57:09  mjames (Mike James)
 * Part of Release Aug25_alpha
 * 
 * Revision 1.54  2000/08/16  08:57:26  08:57:26  mjames (Mike James)
 * Part of Release CD01_Aug2000
 * 
 * Revision 1.53  2000/08/14  14:45:07  14:45:07  mjames (Mike James)
 * Part of Release Aug_14_2000
 * 
 * Revision 1.52  2000/08/11  08:30:28  08:30:28  mjames (Mike James)
 * Part of Release Aug_11_2000
 * 
 * Revision 1.51  2000/08/09  10:31:41  10:31:41  mjames (Mike James)
 * Part of Release Aug__9_2000
 * 
 * Revision 1.50  2000/05/31  11:42:48  11:42:48  mjames (Mike James)
 * Part of Release May_31_2000
 * 
 * Revision 1.49  2000/05/08  17:01:33  17:01:33  mjames (Mike James)
 * Part of Release May__8_2000
 * 
 * Revision 1.48  2000/05/08  16:59:26  16:59:26  mjames (Mike James)
 * Part of Release May__8_2000
 * 
 * Revision 1.47  2000/05/08  16:57:03  16:57:03  mjames (Mike James)
 * Part of Release May__8_2000
 * 
 * Revision 1.46  2000/03/08  16:18:48  16:18:48  mjames (Mike James)
 * New version including PC
 * 
 * Revision 1.43  2000/02/18  15:45:24  15:45:24  mjames (Mike James)
 * Amended to support PC 
 * 
 * Revision 1.42  2000/01/20  15:58:41  15:58:41  mjames (Mike James)
 * Part of Release R22
 * 
 * Revision 1.41  99/12/22  11:15:22  11:15:22  mjames (Mike James)
 * Part of Release Dec_22_1999
 * 
 * Revision 1.40  99/06/25  14:34:42  14:34:42  mjames (Mike James)
 * Added in reference to expression.h, but no changes made 
 * to the function of acfread yet.
 * 
 * Revision 1.39  99/06/18  09:23:19  09:23:19  mjames (Mike James)
 * 
 * Revision 1.38  99/05/04  09:50:36  09:50:36  mjames (Mike James)
 * General checkin
 * 
 * Revision 1.34  98/08/12  14:19:52  14:19:52  mjames (Mike James)
 * Changed pin definition code to work with VHDL 
 * parsing
 * as well as include file list being updated
 * 
 * Revision 1.33  98/06/15  14:17:51  14:17:51  mjames (Mike James)
 * Added socket templating pointers - reference to parent template
 * for child template. 
 * 
 * Revision 1.32  98/02/11  11:25:52  11:25:52  mjames (Mike James)
 * Checked in for version 6.2a
 * 
 * Revision 1.31  98/01/13  11:33:35  11:33:35  mjames (Mike James)
 * Added the bility to use a VHDL template file
 * containing $ENT$ and $ARCH$ in the position where one
 * wants the entity and architecture to be given.
 * 
 * Revision 1.30  97/04/23  08:42:49  08:42:49  mjames (Mike James)
 * CHecked in for release rel23041997
 * 
 * Revision 1.29  96/12/23  15:13:48  15:13:48  mjames (Mike James)
 * Added reverse pointer to show which unrouted net was 
 * responsible for the fixing of the pins.
 * 
 * Revision 1.28  96/12/23  10:24:02  10:24:02  mjames (Mike James)
 * Altered to make it sort the results
 * of listing COMPONENTS and CHIP pins.
 * /
 * 
 * Revision 1.27  96/12/13  08:43:08  08:43:08  mjames (Mike James)
 * Update to v5.1, added Write ID , exact routing
 * 
 * Revision 1.26  96/08/06  13:38:51  13:38:51  mjames (Mike James)
 * Added FIX_LOCATION pin attribute to netlist
 *
 * Revision 1.25  96/07/19  14:38:43  14:38:43  mjames (Mike James)
 * Update to give to PRL
 *
 * Revision 1.24  1996/07/12  15:52:12  mjames
 * Sorted out things like Alias and Jumpers
 * Work Correctly
 * Print COrrectly
 *
 * Revision 1.23  96/07/09  15:53:59  15:53:59  mjames (Mike James)
 * Altered aliasing to make it hierarchical, also for jumpering
 *
 * Revision 1.22  96/06/17  11:02:43  11:02:43  mjames (Mike James)
 * Altered the printing of JUMPERED and ALIASED nets
 * ,
 *
 * Revision 1.21  96/06/11  14:11:44  14:11:44  mjames (Mike James)
 * Added hierarchical jumpering
 *
 * Revision 1.20  96/06/04  11:53:18  11:53:18  mjames (Mike James)
 * Added the ability to jumper nets by reference to a node on the nets
 *
 * Revision 1.19  96/05/29  10:52:29  10:52:29  mjames (Mike James)
 *  Added name suffixing to socket ID's and net ID's
 *
 * Revision 1.18  96/04/26  16:01:30  16:01:30  mjames (Mike James)
 * Added SET PORT to force ports on partition
 * ,
 *
 * Revision 1.17  96/04/15  14:19:24  14:19:24  mjames (Mike James)
 * Checkin before datatype printing
 * modifications
 *
 * Revision 1.16  96/03/29  14:46:05  14:46:05  mjames (Mike James)
 * Added VHDL netlist writing to the capabilities of ACFREAD
 *
 * Revision 1.14  96/03/18  13:50:28  13:50:28  mjames (Mike James)
 * Real Revision 2.1
 *
 * Revision 1.11  96/03/13  15:35:30  15:35:30  mjames (Mike James)
 * Changed the name_pref filed to reflect how a net has been routed
 *
 * Revision 1.10  96/02/13  09:13:28  09:13:28  mjames (Mike James)
 * Updated to be version 2.0 with net joining
 *
 * Revision 1.9  96/02/09  10:50:24  10:50:24  mjames (Mike James)
 * Added different behaviour for 'write id' and 'write name'
 * 'write id' now writes all pins including unused ones
 * 'write name' only writes used pins in the ACF file
 *
 *  .
 *
 *
 * Revision 1.8  96/02/08  15:28:29  15:28:29  mjames (Mike James)
 * First release
 *
 * Revision 1.7  96/02/07  16:01:34  16:01:34  mjames (Mike James)
 * Added correct RCS header
 *
 * Revision 1.6  96/02/07  15:50:44  15:50:44  mjames (Mike James)
 * Added RCS ident message
 *
 * Revision 1.5  96/02/07  11:04:07  11:04:07  mjames (Mike James)
 * Checkin before adding new command parsing to program
 *
 * Revision 1.4  96/01/10  13:14:11  13:14:11  mjames (Mike James)
 *  Works in debug mode with EPLD listings and PCB layout
 *
 * Revision 1.3  96/01/08  15:22:51  15:22:51  mjames (Mike James)
 * Managing to make sense of things now
 *
 * Revision 1.2  96/01/07  20:22:29  Mike_James
 * extending database routines
 *
 * Revision 1.1  96/01/07  12:38:12  Mike_James
 * Initial revision
 *
 * Revision 1.2  96/01/04  17:55:52  17:55:52  mjames (Mike James)
 * Correcly reading ACF
 *
 * Revision 1.1  96/01/04  11:37:22  11:37:22  mjames (Mike James)
 * Initial revision
 *
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <regex.h>


#include "vertcl_main.h"
#include "expression.h"
#include "generic.h"
#include "database.h"
#include "lx_support.h"
#include "cmdparse.h"
#include "cmdlog.h"
#include "acf_yacc.h"
#include "chck_names.h"
#include "sorting.h"
#include "version.h"

#ident  "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/database.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $"



vhdl_t * default_vhdl_datatype;
vhdl_t * default_vhdl_bustype;

/* string constants used around the place*/

char   nullstr[]        =   "";


/* database pointers */
__declspec (dllexport) socket_t * socket_head = NULL;

__declspec (dllexport)socket_t * template_head = NULL;



net_t    * routed_list   = NULL;
net_t    * named_list   = NULL;
net_t    * named_tail   = NULL; /* as routed nets are moved to the named list */
net_t    * unrouted_list = NULL;


/* these are ident counters. The first counts net identifiers */
static int n_idents = 1; /* net identifiers */
static int s_idents = 1; /* socket identifiers */
static int i_idents = 1; /* pin identifiers */

/* compares two strings case insensitive with a pointer sanity check */

int strcmp2(char * s, char * t)
{
  if(!s || !t)
    return(-1);
  for(;tolower(*s) == tolower(*t);s++,t++)
    if(*s==0)
      return(0);
  return(tolower(*s) - tolower(*t));
}

/* allocates a space for a string */


#if !defined allocstr
/* we now use strdup.... */
char * allocstr(char * s)
{
  char * t;
  /* added a check for allocating null string
   *  (its strlen that bombs in CygWin) */
  if (!s) return NULL;

  t=malloc(strlen(s)+1);
  strcpy(t,s);
  return t;
}
#endif

/* allocates a space for a string and a suffix dependent on property */

#if defined USE_ALLOCSTR_PROP
static char * allocstr_prop(char * s,property_t prop)
{
  char * t;
  switch (prop) {
    case Ident:
    case Type:
    case Name:
    case Value:  t=strdup(s);
                 break;
  }
  return t;
}
#endif

/* this is a check on a socket ident - if absent, generates one  */

__declspec (dllexport) void ensure_socket_ident(socket_t * chip)
{
  char id[10];
  if (chip->identifier == nullstr)
  {
    sprintf(id,"ID%d",s_idents++);
    set_socket(chip,Ident,id);
  };
}


/* set a socket property */
__declspec (dllexport)void set_socket(socket_t * chip,property_t prop,char * str)
{
  char * s;
  s = strdup(str);

/*   printf("(Set socket prop%d to %s)",prop,s); */
  switch(prop)
  {
    case Ident:  chip->identifier = s; break;
    case Type:   chip->type       = s; break;
    case Name:   chip->name       = s; break;
    case Value:  chip->value      = s; break;
    default: break;
  };
}

/* find a socket property */
__declspec (dllexport) socket_t * find_socket(property_t prop,
                       char * str,
                       int srchonly,
                       socket_t ** headref)
{
  socket_t * c=*headref, *p=NULL;
  int f=0;
/* printf("-- Socket %s : prop %d pointer=%p\n",str,prop,c); */

  while(c)
    {
    switch(prop)
      {
      case Ident: f=strcmp2(c->identifier,str)==0;/*puts(c->identifier); */ break;
      case Type:  f=strcmp2(c->type,str)==0;       break;
      case Name:  f=strcmp2(c->name,str)==0; /*puts(c->name);*/      break;
      case Value: f=strcmp2(c->value,str)==0;      break;
      default : break; /* never find if wrong field specified */
      };
    if(f) break;
    p=c;
    c=c->next;
    };

  if(srchonly || f )
    return(c);

  c=calloc(1,sizeof(socket_t)); /* all pointers are set to be null */

  c->identifier = nullstr;
  c->type       = nullstr;
  c->name       = nullstr;
  c->value      = nullstr;

  set_socket(c,prop,allocstr(str));

  /* link in otherwise */
  if(p)
    p->next = c;
  if (!(*headref))
    *headref = c;
  return c;
}

/* matches s into a table of n strings r[], default value is d */
int str_to_int(char * s,char * r[],int n,int d)
{
  int i;
  for(i=0;i<n;i++)
    if(strcmp2(s,r[i])==0)
    {
      d=i;
      break;
    };
  return d;
}



char * decode_how_routed[]= {
  "FREE_NAME",
  "MATCHED_NAME",
  "USED_WIRES",
  "USED_FIXED_WIRES",
  "USED_EXACT_WIRES",
  "CREATED_NET",
  "CREATED_JUMPER",
  "FIXED_PINS",
  "NOT_ROUTABLE",
  "NOT_ROUTABLE_L", /* additions V16.5 onward */
  "NOT_ROUTABLE_H"
};

/* set a net property */
__declspec (dllexport) void set_net(net_t * net,property_t prop,char * str)
{
  char * s;
  s = strdup(str);
  switch(prop)
  {
    case Ident:     net->identifier = s; break;
    case Name:      net->name       = s; break;
/*
    case Datatype:  net->datatype   = s; break;
*/
    case How_Routed:
           net->how_routed  = (HowRouted_t)str_to_int(str,
                                                      decode_how_routed,
                                                      sizeof(decode_how_routed)/sizeof(char *),
                                                      0);
       break;
    default: break;
   };
}


/* find a net by property, in a list pointed to by a pointer referred to
   by net_head  */
__declspec (dllexport) net_t * find_net(net_t ** net_head,property_t prop,char * str,int srchonly )
{
  net_t * c, *p;
  int f=0;
  c= *net_head;
  p=NULL;
  while(c)
    {
    switch(prop)
      {
      case Ident: f=strcmp2(c->identifier,str)==0; break;
      case Name:  f=strcmp2(c->name,str)==0;       break;
      default: break;
      };
    if(f)
      break;
    p=c;
    c=c->next;
    };
  if(srchonly || f)
    return(c);

  c=calloc(1,sizeof(net_t)); /* all pointers are set to be null */
  c->name       = nullstr;
  c->identifier = nullstr;
  c->list_ref   = net_head; /* record which list this net is a member of */

  c->nodecount  = 0;    /* calloc does this :  put here for readability : Oct 2000 */

  c->type_defined= 0;  
  set_net(c,prop,str);

  c->list_ref = net_head; /* which list does this net begin life on */

  /* link at end of list otherwise */
  if(p)
    p->next = c;
  c->prev = p;  /* and refer back to it */
  if (!(*net_head))
    *net_head = c;

  return c;
}

/* set a node property */
__declspec (dllexport) void set_node(node_t * node,property_t prop,char * str)
{
  char * s;
  s = strdup(str);
  switch(prop)
  {
    case Ident:     node->identifier = s; break;
    case Name:      node->name       = s; break;
/*
    case Datatype:  node->datatype    = s; break;
*/
    default: break;
   };
}



/* locate a node on a chip by a property */
__declspec (dllexport) node_t * find_node(socket_t * socket,
                   property_t prop,
                   char * str,
                   int srchonly)
{
  node_t * c, *p;
  int f=0;

/* catch null pointer reference 23 May 2001 */
  if (!socket)
    return NULL;

  c=socket->nodes;

  p=NULL;
  while(c)
    {
    switch(prop)
      {

      case Ident:     f=strcmp2(c->identifier,str)==0; break;
      case Name:      f=strcmp2(c->name,str)==0;       break;
/*      case Datatype:  f=strcmp2(c->datatype,str)==0;       break; */
      default:  break;
      };
    if(f)
      break;
    p=c;
    c=c->sktnext;
    };
  if(srchonly || f)
    return(c);

  c=calloc(1,sizeof(node_t)); /* all pointers are set to be null */
  c->name       = nullstr;
  c->identifier = nullstr;
  c->socket     = socket;

  set_node(c,prop,str);
  /* link at end of list otherwise */
  if(p)
    p->sktnext = c;

  if(!socket->nodes)
    socket->nodes = c;

  socket->lastnode = c;
  return c;
}

/* this connects the node to the list of node references on the net and 
   connects the net to the list of net references on the node */

__declspec (dllexport) void connect_node_net( char * orig_name,
                       node_t * cnode,
                       net_t * cnet,
                       pindir_t pintype,
                       vhdl_t * vhdl,
                       vhdl_t * orig_vhdl,
                       expression_t * lhs_expr)
  {
  noderef_t * noderef;
  cnet->nodecount++; /* one more node on this net */

  cnode->net = cnet; /* refer back to net this node is on */
  cnode->refcount++; /* and count references */

  noderef = calloc(1,sizeof(noderef_t));

  noderef->net = cnet; /* this node reference refers back to its parent net */

  noderef->pindir  = pintype; /* the reference has the pin direction _wanted_ */

  noderef->orig_name   = orig_name; /* copy any alias over */

/* remeved reference to datatype */
  noderef->vhdltype      = vhdl;

  noderef->orig_vhdltype = orig_vhdl;

  noderef->base_noderef = noderef; /* its original reference is itself */

  noderef->lhs_expr     = lhs_expr;

/* link node  reference to the net */
  noderef->next = cnet->nodes;
  cnet->nodes = noderef; /* place reference on head of list */
  noderef->node = cnode;
  
  }



/* disconnect a node from the netlist */
/* this intends to remove chip node from net in the routed list. If anyone has made a reference to the node
   in a manner which results in this node reappearing then there will be a problem as it will
   reappear (some route algorithms eg. create will do this) */

__declspec (dllexport) void disconnect_node(socket_t * chip, node_t * node)
  {
  noderef_t * ref, * last_ref;
  /* locate the net on the routed or named list */
  if(node->net && (node->net->list_ref== &routed_list || node->net->list_ref== &named_list))
    {
    net_t * net;
    net = node->net;
    ref = net->nodes;
    last_ref = NULL;
    /* locate the reference made */
    while(ref)
      {
      if (ref->node == node)
        break;
      last_ref = ref;
      ref = ref->next;
      }
    /* reference is located. Remove from list of node references, 
       also patch up list head if needed */
    if(ref) 
      {
      if(last_ref == NULL)
        {
        net->nodes = ref->next;
        }
      else
        {
        last_ref->next = ref->next;
        }
      free(ref);       
      node->net = NULL; /* disconnect the ned from the node */
      node->refcount = node->refcount ? node->refcount--: 0 ;
      
      }
    }
  }






__declspec (dllexport) void define_pin(net_t ** net_head,
                socket_t * chip,
                char * i_name,
                int pin_type,
                int pin_group,
                char * i_identifier,
                vhdl_t * vhdl,
                expression_t * lhs_expr)
{
  unrouted_ref_t * ref, *ptr;

  int null_name;
  char name[MAXIDLEN];
  char identifier[MAXIDLEN];

  /* actions here are :
  1: find a new node;
  2: attach a reference to it to the socket pin list;
  3: find the net it is joined to by name;
  */

  null_name = ISNULLSTR(i_name);


  /* if the name is not given, then dont create a net for it as it
     is a waste of time */
  if(null_name)
    /* count another ident for posisble use */
    sprintf(name,"NE%d",n_idents++);
  else
    strcpy(name,i_name);

  if(ISNULLSTR(i_identifier))
    /* count another ident for posisble use */
    sprintf(identifier,"ID%d",i_idents++);
  else
    strcpy(identifier,i_identifier);

/*   printf("-- Joining name %s to pin %s\n",name,identifier );
*/


  /* at this stage, simply create a potential reference */
  
  
  ref = calloc(1,sizeof(unrouted_ref_t));


  ref->pindir  = pin_type;        /* the reference has the pin direction _wanted_ */
  ref->pin_group  = pin_group;
/* removed reference to datatype */
  
  ref->vhdltype       = copy_vhdl(vhdl,chip);
  ref->orig_vhdltype  = NULL;
  ref->identifier     = allocstr(identifier);
  ref->name           = allocstr(name);
  ref->orig_name      = NULL;
  ref->listref        = net_head;  /* identify the list context */
  ref->lhs_expr       = lhs_expr;  
  ref->next = NULL; 
  if(!chip->unrouted_refs)
    chip->unrouted_refs = ref;
  else {
    ptr = chip->unrouted_refs;
    while(ptr->next) 
      ptr=ptr->next;
    ptr->next = ref;
    }  

  /* splice the unrouted reference on */
  ref->next           = NULL;
  
  
}


/* this function clears the name fields on identified nets */
static void del_list_net_names(net_t * list,char * template )
  {
  int rc,found;
  char * pattern;
  /* compile regular expression */
  vert_regex_t * preg;


  if (template) 
    {
    pattern = template;
    }
  else
    {
    pattern = ".*";
    }

  rc = vert_regcomp(&preg,pattern);

  if (rc != 0 ) 
    {
    char errbuff[100];
    regerror(rc,preg->preg,errbuff,100);
    Log(LOG_ERROR,"-- Problem (rc=%d) %s with '%s' as regular expression\n",rc,errbuff,pattern);
    
    return /*TCL_ERROR*/;
    }


  Log(LOG_GENERAL,"-- Beginning clearing name fields : net ID prefix '%s' --\n",
      template?template:"[ALL ID's]");
  while(list) {
    found  = regexec(preg->preg,list->identifier,0,preg->regpatt,0);
    if(!found) {
      Log(LOG_GENERAL,"-- Cleared name field for net ID '%s'\n",list->identifier);
      list->name = nullstr;
      }
    list = list->next;
    }
  Log(LOG_GENERAL,"-- Finished clearing name fields --\n");
  vert_regfree(&preg);
  }

__declspec (dllexport)void del_net_names(char * template )
  {
  del_list_net_names(routed_list,template );
  }

/* added 8 March 2000 for PC support */

__declspec (dllexport) void ensure_env_var(char * name, char * defval) {
  generic_info_t gen[1];
  if (get_generic_value(&global_generics, name,gen) != IS_STRING) {
    char sbuff [MAXIDLEN];
    gen->name     = name;
    gen->typename = "env_string";
/* cannot use $(1) type command line variables as 
 *they are not passed here :  argc = 0 , argv = NULL*/
    expand_string(defval , sbuff,0 , NULL);
    gen->expr     = compile_string(sbuff);
    gen->g_type   = IS_ENV_VAL;
    gen->g_class  = DEFAULT;

    set_generic_value(&global_generics,gen );
    };
  }

/* initialise default information used around the design database */
__declspec (dllexport) void InitialiseData(void) {
  generic_info_t gen[1];
  InitialiseVersionStrings();  

  if (!default_vhdl_datatype)
    default_vhdl_datatype= calloc(1,sizeof(vhdl_t));
  if (!default_vhdl_bustype)
    default_vhdl_bustype = calloc(1,sizeof(vhdl_t));
  
  /* if we are using VHDL then look at the VHDL bus formatting tail*/
  if (get_generic_value(&global_generics, "vhdl_bit_type",gen) == IS_STRING) {
    default_vhdl_datatype->basetype = strdup( gen->expr->left.s );
    }
  else
    default_vhdl_datatype->basetype = "std_logic";
    
  /* if we are using VHDL then look at the VHDL bus formatting tail*/
  if (get_generic_value(&global_generics, "vhdl_bus_type",gen) == IS_STRING) {
    default_vhdl_bustype->basetype = strdup( gen->expr->left.s);
    }
  else
    default_vhdl_bustype->basetype = "std_logic_vector";
  
  default_vhdl_bustype->expr     = compile_expression(TO,compile_constant(0),compile_constant(0));
  default_vhdl_bustype->is_vector=1;  /* is this port a vector */
  default_vhdl_bustype->is_downto=1;  /* is the vector X TO Y or X DOWNTO Y  */

 /* look up VERTICAL_INIT and give it a default value if unknown */  
  ensure_env_var("VERTICAL_INIT",VERTICAL_INI_PATH);

  ensure_env_var("VERTICAL_PATH",VERTICAL_PATH);


 }  
  





__declspec (dllexport) char * decode_which_list(net_t ** list_head) {
  if(list_head == NULL)           return "No List";
  if(list_head == &routed_list)   return "routed list";
  if(list_head == &named_list)    return "named list";
  if(list_head == &unrouted_list) return "unrouted list";
  return "ERROR : unknown";
  }