/* 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 "database.h"
#include "acf_yacc.h"
#include "chck_names.h"
#include "cmdlog.h"
#include "cmdparse.h"
#include "expression.h"
#include "generic.h"
#include "lx_support.h"
#include "sorting.h"
#include "version.h"
#include "vertcl_main.h"
#include <ctype.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.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);
if (*s == 0)
return (0);
}
/* 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;
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)
{
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;
}
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
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";
}