/* $Id: sorting.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $
*
* $Log: sorting.c,v $
* Revision 1.1.1.1 2003/11/04 23:34:57 mjames
* Imported into local repositrory
*
* Revision 1.14 2002/10/02 18:39:54 MJAMES
* Stopped copying pin_col to index on every node
*
* Revision 1.13 2002/09/16 14:41:43 mjames
* Merge back pin indexing bug that meant
* pin AZ12 was indistinguishable from pin Z12 in
* rename ident/name commands
*
* Revision 1.12 2002/09/09 10:10:21 mjames
* Moved pin remapping function to pin ident editing function from
* sorting pin name routine.
*
* Revision 1.11 2002/09/09 09:53:01 mjames
* Moved pin remapping function to pin ident editing function from
* sorting pin name routine.
*
* Revision 1.10 2002/08/23 14:13:55 mjames
* Added legal/illegal pin identifying letters to the header file.
* Upgraded sort to determine row/column locations of pins identified like
* 'a1' and '1a' etc or '1' , '2'
*
* Revision 1.9 2001/10/31 22:33:27 mjames
* Suppress diagnostic print
*
* Revision 1.8 2001/10/31 22:20:17 mjames
* Tidying up problematical comments caused by CVS
* 'intelligent' comment guessing
*
* Revision 1.7 2001/10/31 16:15:36 mjames
* Added a datastructure to hide regular expression information from programs.
*
* Revision 1.6 2001/10/22 10:53:50 mjames
* Added a declaration of the Vertical regular expression compiler
* which validates and complains about older 'regular expressions'
* used by Vertical prior to using regexp in the C library
*
* Revision 1.5 2001/10/10 20:17:59 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/09/16 20:36:03 mjames
* Second attempt to modify wire bundles to be connector rather than net
* centric. Allows more than one connector to carry the same net,
*
* Revision 1.3 2001/09/16 19:48:53 mjames
* Modified sorting algorithm to have sideffect of calculating pin rows and
* columns for sockets.
*
* Revision 1.2 2001/06/06 12:10:17 mjames
* Move from HPUX
*
* Revision 1.1.1.1 2000/10/19 21:58:40 mjames
* Mike put it here
*
*
* Revision 1.24 2000/10/04 10:37:10 10:37:10 mjames (Mike James)
* Modified for Vertical2 : support COMPONENTS and SIGNALS
*
* Revision 1.24 2000/10/04 10:37:10 10:37:10 mjames (Mike James)
* Part of Release PSAVAT01
*
* Revision 1.23 2000/10/02 11:04:21 11:04:21 mjames (Mike James)
* new_vhdl
*
* Revision 1.22 2000/09/27 14:42:21 14:42:21 mjames (Mike James)
* Part of Release Sep_27_ST_2000
*
* Revision 1.21 2000/09/21 10:15:51 10:15:51 mjames (Mike James)
* Part of Release Sep21Alpha
*
* Revision 1.20 2000/08/25 09:57:16 09:57:16 mjames (Mike James)
* Part of Release Aug25_alpha
*
* Revision 1.19 2000/08/16 08:57:33 08:57:33 mjames (Mike James)
* Part of Release CD01_Aug2000
*
* Revision 1.18 2000/08/14 14:45:13 14:45:13 mjames (Mike James)
* Part of Release Aug_14_2000
*
* Revision 1.17 2000/08/11 08:30:34 08:30:34 mjames (Mike James)
* Part of Release Aug_11_2000
*
* Revision 1.16 2000/08/09 10:31:49 10:31:49 mjames (Mike James)
* Part of Release Aug__9_2000
*
* Revision 1.15 2000/05/31 11:43:00 11:43:00 mjames (Mike James)
* Part of Release May_31_2000
*
* Revision 1.14 2000/05/08 17:01:40 17:01:40 mjames (Mike James)
* Part of Release May__8_2000
*
* Revision 1.13 2000/05/08 16:59:33 16:59:33 mjames (Mike James)
* Part of Release May__8_2000
*
* Revision 1.12 2000/05/08 16:57:10 16:57:10 mjames (Mike James)
* Part of Release May__8_2000
*
* Revision 1.11 2000/03/08 16:19:31 16:19:31 mjames (Mike James)
* New version including PC
*
* Revision 1.8 2000/01/20 15:58:50 15:58:50 mjames (Mike James)
* Part of Release R22
*
* Revision 1.7 99/12/22 11:15:31 11:15:31 mjames (Mike James)
* Part of Release Dec_22_1999
*
* Revision 1.6 99/06/25 14:35:51 14:35:51 mjames (Mike James)
* Added in reference to expression.h, but no changes made
* to the function of acfread yet.
*
* Revision 1.5 99/05/04 09:52:52 09:52:52 mjames (Mike James)
* General checkin
*
* Revision 1.4 98/02/11 11:27:19 11:27:19 mjames (Mike James)
* Checked in for version 6.2a
*
* Revision 1.3 97/04/23 08:43:25 08:43:25 mjames (Mike James)
* CHecked in for release rel23041997
*
* Revision 1.2 96/12/23 15:17:00 15:17:00 mjames (Mike James)
* Altered because find_socket takes a reference
* to the head-of-list-pointer noth the pointer itself.
*
* Revision 1.1 96/12/23 10:26:21 10:26:21 mjames (Mike James)
* Initial revision * */
#include <ctype.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
/* TCL/Tk declarations */
#include "cmdlog.h"
#include "cmdparse.h"
#include "database.h"
#include "expression.h"
#include "generic.h"
#include "routing.h"
#include "sorting.h"
#include "vertcl_main.h"
#ident \
"@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/sorting.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $";
/* the comparison function : requires upgrade for checking :
A1...A10 then B1..B10 or is it 1a..10a then 1b..10b */
#if defined SORT_ORIGINAL
static int sort_nodes_compar (const void *p, const void *q)
{
char *s1 = (*(node_t **) p)->identifier;
char *s2 = (*(node_t **) q)->identifier;
if (l1 == l2) /* only call strcmp() for same length strings
This makes '2' smaller than '19' */
else
return l1 - l2; /* if different lengths, use the shorter name */
}
#else
/* this sort works for alpha - numeric strings : A1 A2
use SWAP command to swap identifiers */
static int sort_nodes_compar (const void *p, const void *q)
{
char *s1 = (*(node_t **) p)->id_alpha_chars;
char *s2 = (*(node_t **) q)->id_alpha_chars;
int l1 = (*(node_t **) p)->id_alpha_cnt;
int l2 = (*(node_t **) q)->id_alpha_cnt;
int diff = 0;
/*
printf("cmp p: a %3s[%2d] n %3s[%2d]\n",
(*(node_t **)p)->id_alpha_chars,
(*(node_t **)p)->id_alpha_cnt,
(*(node_t **)p)->id_numeric_chars,
(*(node_t **)p)->id_numeric_cnt);
printf("cmp q: a %3s[%2d] n %3s[%2d]\n",
(*(node_t **)q)->id_alpha_chars,
(*(node_t **)q)->id_alpha_cnt,
(*(node_t **)q)->id_numeric_chars,
(*(node_t **)q)->id_numeric_cnt);
*/
if (l1 == l2)
{
/* only call strcmp() for same length strings */
/*
printf("alpha cmp (%s,%s,%d) different %d\n",s1,s2,l1,diff);
*/
if (diff == 0) /* alpha same */
{
/* otherwise check the numeric parts of the strings */
/* these have been decoded already */
l1 = (*(node_t **) p)->pin_row;
l2 = (*(node_t **) q)->pin_row;
diff = l1 - l2;
/*
printf("num different %d\n",diff);
*/
}
}
else
{
diff = l1 - l2; /* if different alpha lengths, use the shorter name */
/*
printf("alpha len different %d\n",diff);
*/
}
/*
printf("diff: %d string %7s row %2d and %7s row%2d\n",diff,
(*(node_t **)p)->identifier,
(*(node_t **)p)->pin_row,
(*(node_t **)q)->identifier,
(*(node_t **)q)->pin_row);
*/
return diff;
}
#endif
/* this function sorts all of the pin references on a chip
into alphanumeric order, and also generates a unique pin index for each pin
in the case of alphanumeric pin identifiers : pin A1 or 1A will become index 1 */
#define BIG 1000000
/* mapping table has no letter 'I' or 'O' in it */
static unsigned char illegal_chars[] = PIN_MAP_ILLEGAL_CHARS;
void sort_nodes (socket_t *chip, extract_xy_t mode)
{
node_t *nodes = chip->nodes;
node_t **sort_list;
int alpha_seen = 0;
int numeric_seen = 0;
/* Use generics to find out if the user has defined pin row/column
limits (in the case where top or bottom connector rows are not
connected at all */
generic_info_t gen[1];
/*
printf("chip %s\n",chip->identifier);
*/
int nodecnt = 0;
int max_row = -BIG;
int min_row = BIG;
int max_col = -BIG;
int min_col = BIG;
while (nodes)
{
/* to do need to identify the pattern of node identifiers */
/* numeric only ? */
/* alpha only ? */
/* alpha number */
/* number alpha */
/* highest pin number ? */
/* number of different alphas */
/* assign an ordinal automatically to each node element */
/* sorting data structure */
/* the form is 23A */
if (nodes->identifier)
{
if (isdigit (nodes
->identifier
[0]))
{
nodes->id_numeric_chars = nodes->identifier;
nodes->id_numeric_cnt =
0; /* the numeric part of the identifier */
while (isdigit (nodes
->identifier
[nodes
->id_numeric_cnt
]))
nodes->id_numeric_cnt++; /* the number of numeric chars
in this part of the
identifier */
nodes->id_alpha_chars =
nodes->identifier + nodes->id_numeric_cnt;
nodes->id_alpha_cnt =
strlen (nodes
->identifier
) - nodes
->id_numeric_cnt
;
}
else
{
nodes->id_alpha_chars = nodes->identifier;
nodes->id_alpha_cnt =
0; /* the numeric part of the identifier */
while (isalpha (nodes
->identifier
[nodes
->id_alpha_cnt
]))
nodes->id_alpha_cnt++; /* the number of numeric chars
in this part of the
identifier */
nodes->id_numeric_chars =
nodes->identifier + nodes->id_alpha_cnt;
nodes->id_numeric_cnt =
strlen (nodes
->identifier
) - nodes
->id_alpha_cnt
;
}
/*
printf("node : %s : alpha=%d
num=%d\n",nodes->identifier,nodes->id_alpha_cnt,nodes->id_numeric_cnt);
*/
}
else
{
nodes->id_alpha_chars = NULL; /* the numeric part of the identifier */
nodes->id_alpha_cnt =
0; /* the number of numeric chars in this part of the identifier */
nodes->id_numeric_chars = NULL;
nodes->id_numeric_cnt = 0;
}
/* dont touch the row/col indices unless asked to */
if (mode == EXTRACT_XY)
{
/* if digits seen these are assigned as row 1..n */
if (nodes->id_numeric_cnt)
{
int index
= atoi (nodes
->id_numeric_chars
);
numeric_seen = 1;
nodes->pin_row = index;
if (index > max_row)
{
max_row = index;
}
else if (index < min_row)
{
min_row = index;
}
}
else
{
/* default is on row 1 */
nodes->pin_row = 1;
}
if (nodes->id_alpha_cnt > 0)
{
alpha_seen = 1;
}
/* between 1 and a few letters can be processed */
if (nodes->id_alpha_cnt > 0 &&
nodes->id_alpha_cnt <= MAX_ID_ALPHA_SORT)
{
int index;
int charcnt;
index = 0;
for (charcnt = 0; charcnt < nodes->id_alpha_cnt; charcnt++)
{
int i;
char c, d;
d = 0;
c
= toupper (nodes
->id_alpha_chars
[charcnt
]);
/* work out how many illegal chars are before this one
*/
/* this mapping actually collapses I onto J and O onto
* P */
/* I am assuming those two chars dont exist in the pin
* ID .... */
/* flag an error and continue for the present */
/* characters are actually coded as 1..n so that IDs
* like 'AA' look */
/* different to 'A', which they wont be if the leading
* 'A' is coded as 0 */
for (i = 0; i < PIN_MAP_ILLEGAL_CHAR_COUNT; i++)
{
if (c == illegal_chars[i])
{
Log (
LOG_GENERAL,
"-- Warning : illegal pin ident "
"character in %s(%d)\n",
chip->identifier,
nodes->identifier);
}
if (c >= illegal_chars[i])
{
d++;
}
}
index *= (PIN_MAP_LEGAL_CHAR_COUNT + 1);
index += (c - d - 'A' + 1);
}
/*
printf("'\n");
*/
nodes->pin_col = index;
if (index > max_col)
{
max_col = index;
}
else if (index < min_col)
{
min_col = index;
}
}
else
{
/* default is column zero */
nodes->pin_col = 0;
}
}
nodecnt++;
nodes = nodes->sktnext;
}
chip->max_pin_col = max_col == -BIG ? 0 : max_col;
chip->min_pin_col = min_col == BIG ? 0 : min_col;
chip->max_pin_row = max_row == -BIG ? 0 : max_row;
chip->min_pin_row = min_row == BIG ? 0 : min_row;
/*
printf("chip %10s col %3d to %3d , row %3d to
%3d\n",chip->identifier,max_col,min_col,max_row,min_row);
*/
/* know the number of nodes now allocate storage for the pointers
to be used by qsort() */
sort_list
= calloc (nodecnt
, sizeof (node_t
*));
/* grab hold of all of the pointers */
nodes = chip->nodes;
nodecnt = 0;
while (nodes)
{
sort_list[nodecnt++] = nodes;
nodes = nodes->sktnext;
}
/* sort them */
if (nodecnt)
{
int i;
qsort ((void *) sort_list
, nodecnt
, sizeof (node_t
*), &sort_nodes_compar
);
/* and now rebuild the list based on the sorted list */
chip->nodes = sort_list[0];
chip->lastnode = sort_list[nodecnt - 1];
/* relink the list */
for (i = 0; i < (nodecnt - 1); i++)
{
sort_list[i]->sktnext = sort_list[i + 1];
}
sort_list[nodecnt - 1]->sktnext = NULL;
}
/* check for overrides in case there are missing rows/cols */
if (get_generic_value (&chip->generics, "min_pin_row", gen) == IS_ATTRIBUTE)
{
chip->min_pin_row = eval_expression (gen->expr, &chip->generics);
}
if (get_generic_value (&chip->generics, "max_pin_row", gen) == IS_ATTRIBUTE)
{
chip->max_pin_row = eval_expression (gen->expr, &chip->generics);
}
if (get_generic_value (&chip->generics, "min_pin_col", gen) == IS_ATTRIBUTE)
{
chip->min_pin_col = eval_expression (gen->expr, &chip->generics);
}
if (get_generic_value (&chip->generics, "max_pin_col", gen) == IS_ATTRIBUTE)
{
chip->max_pin_col = eval_expression (gen->expr, &chip->generics);
}
}
/* we have a pair of pointers to array elements */
static int sort_socket_compar (const void *p, const void *q)
{
return strcmp ((*(socket_t
**) p
)->identifier
, (*(socket_t
**) q
)->identifier
);
}
/* this function sorts all of sockets into alphanumeric order */
socket_t *sort_sockets (socket_t **head)
{
socket_t **sort_list, *chip = *head;
int sktcnt = 0;
while (chip)
{
sktcnt++;
chip = chip->next;
}
/* know the number of nodes now allocate storage for the pointers
to be used by qsort() */
sort_list
= calloc (sktcnt
, sizeof (socket_t
*));
/* grab hold of all of the pointers */
chip = *head;
sktcnt = 0;
while (chip)
{
sort_list[sktcnt++] = chip;
chip = chip->next;
}
/* sort them */
if (sktcnt)
{
int i;
qsort ((char *) sort_list
, sktcnt
, sizeof (socket_t
*), &sort_socket_compar
);
/* and now rebuild the list based on the sorted list */
*head = sort_list[0];
/* relink the list */
for (i = 0; i < (sktcnt - 1); i++)
{
sort_list[i]->next = sort_list[i + 1];
}
sort_list[sktcnt - 1]->next = NULL;
}
return *head;
}
/* compile regular expression according
to Vertical expectations */
/* What is required is a whole string match. In order to
achieve this, the regular expression is bracketed with
^ and $ which mean in this context 'match start of string'
and 'match end of string' */
int vert_regcomp (vert_regex_t **vert_preg, char *expr)
{
int rc;
vert_regex_t *preg;
/* allocate structure members */
preg
= calloc (1, sizeof (vert_regex_t
));
*vert_preg = preg;
rc = check_wildcard (expr);
if (rc != TCL_OK)
{
}
else
{
sprintf (preg
->buff
, "^%s$", expr
);
}
/* printf("-- compare '%s'\n",preg->buff); */
rc = regcomp (preg->preg, preg->buff, REG_EXTENDED | REG_ICASE);
return rc;
}
/* tidy up */
int vert_regfree (vert_regex_t **vert_preg)
{
regfree ((*vert_preg)->preg);
free ((*vert_preg
)->buff
);
*vert_preg = NULL;
return 0;
}