Subversion Repositories Vertical

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/*
2
 * $Header: c:\\cygwin\\cvsroot/Vert03/vertlib/routing.c,v 1.1.1.1 2003/11/04 23:34:57 mjames
3
 * Exp $
4
 *
5
 * $Log: routing.c,v $
6
 * Revision 1.1.1.1  2003/11/04 23:34:57  mjames
7
 * Imported into local repositrory
8
 *
9
 * Revision 1.19  2003/01/02 21:37:17  mjames
10
 * Experiment on creating NOT_ROUTABLE_H and NOT_ROUTABLE_L
11
 * properties on the nets so that pin jumpers can be made without a problem.
12
 *
13
 * Still need to sort out pin assignments made to these not_routable nets
14
 * which will become legal in some cases so that pullups and pulldown
15
 * pins can be used on the FPGA.
16
 *
17
 * Revision 1.18  2002/12/09 10:31:49  mjames
18
 * Corrected 2 warnings about #ident
19
 * Added warning about "chip X1" which gets confused with component called "X1"
20
 *
21
 * Revision 1.17  2002/09/27 22:29:31  MJAMES
22
 * Added lhs_expr for cases like
23
 *
24
 * x(0) <= y
25
 *
26
 * where x is std_logic_vector(0 downto 0) and y is std_logic.
27
 *
28
 * Revision 1.16  2002/08/23 09:50:21  mjames
29
 * Altered pin_group search pattern from
30
 * chip_exp.pin_exp to chip_exp(pin_exp) as this is clearer.
31
 *
32
 * Revision 1.15  2001/10/31 22:20:16  mjames
33
 * Tidying up problematical comments caused by CVS
34
 * 'intelligent' comment guessing
35
 *
36
 * Revision 1.14  2001/10/31 16:18:04  mjames
37
 * Added a datastructure to hide regular expression information from programs.
38
 * Changed call to regexec to indicate 0 subexpressions to be matched
39
 * rather than a number dependent on strlen(string) which was wrong.
40
 *
41
 * Revision 1.13  2001/10/10 20:18:21  mjames
42
 * Added a vert_regcomp function to compile regular expressions
43
 * with '^' (match start string) and  '$' (match end string) bracketing
44
 * this => wildcard must match entire string not just a part of it.
45
 *
46
 * Revision 1.12  2001/10/07 20:50:51  mjames
47
 * Added wildcard checking (warn user about
48
 * using wildcard '*' on the end of a string in stead of wildcard '.*')
49
 *
50
 * Revision 1.11  2001/09/28 10:16:20  mjames
51
 * Modified to use auto variable pointing at regular expression instead of
52
 * allocating one via calloc.
53
 *
54
 * Revision 1.10  2001/09/25 23:15:23  mjames
55
 * Converted wildcards to use proper regexp pattern match library
56
 *
57
 * Revision 1.9  2001/08/23 20:06:44  mjames
58
 * Added 'reserve' command for use with preroute commands.
59
 * This command provides the 'correct' documented pin reservation
60
 * behaviour.
61
 *
62
 * Revision 1.8  2001/08/09 20:04:03  mjames
63
 * Tidying up indentation
64
 *
65
 * Revision 1.7  2001/07/20 14:49:42  mjames
66
 * Corrected reading names in on multiple boards : if present in a database file
67
 * when reading in a suffixed design
68
 * e.g. CHIP fred
69
 * Will also get its name suffixed.
70
 *
71
 * Revision 1.6  2001/07/20 10:47:43  mjames
72
 * Allowed setting of pin routing group properties on pins on nets
73
 * by the
74
 * "set pin" command
75
 *
76
 * Revision 1.5  2001/07/09 15:39:38  mjames
77
 * Reduced verbose diagnostics
78
 *
79
 * Revision 1.4  2001/06/07 14:00:04  MJAMES
80
 * Producing an error on failing to fix pins
81
 *
82
 * Revision 1.3  2001/06/06 12:10:17  mjames
83
 * Move from HPUX
84
 *
85
 * Revision 1.2  2001/01/02 07:53:53  mjames
86
 * Made changes to allow for interface with TCL/Tk
87
 *
88
 * Revision 1.1.1.1  2000/10/19 21:58:39  mjames
89
 * Mike put it here
90
 *
91
 * Revision 1.57  2000/10/04  10:37:09  10:37:09  mjames (Mike James)
92
 * Modified for Vertical2 : support COMPONENTS and SIGNALS
93
 *
94
 * Revision 1.57  2000/10/04  10:37:09  10:37:09  mjames (Mike James)
95
 * Part of Release PSAVAT01
96
 *
97
 * Revision 1.56  2000/10/02  11:04:20  11:04:20  mjames (Mike James)
98
 * new_vhdl
99
 *
100
 * Revision 1.55  2000/09/27  14:42:20  14:42:20  mjames (Mike James)
101
 * Part of Release Sep_27_ST_2000
102
 *
103
 * Revision 1.54  2000/09/21  10:15:50  10:15:50  mjames (Mike James)
104
 * Part of Release Sep21Alpha
105
 *
106
 * Revision 1.53  2000/08/25  09:57:16  09:57:16  mjames (Mike James)
107
 * Part of Release Aug25_alpha
108
 *
109
 * Revision 1.52  2000/08/16  08:57:32  08:57:32  mjames (Mike James)
110
 * Part of Release CD01_Aug2000
111
 *
112
 * Revision 1.51  2000/08/16  08:55:43  08:55:43  mjames (Mike James)
113
 * corrected routing/unroutable nets errors
114
 *
115
 * Revision 1.50  2000/08/14  14:45:13  14:45:13  mjames (Mike James)
116
 * Part of Release Aug_14_2000
117
 *
118
 * Revision 1.49  2000/08/14  14:43:31  14:43:31  mjames (Mike James)
119
 * Added power pins
120
 *
121
 * Revision 1.48  2000/08/11  08:30:33  08:30:33  mjames (Mike James)
122
 * Part of Release Aug_11_2000
123
 *
124
 * Revision 1.47  2000/08/09  10:31:49  10:31:49  mjames (Mike James)
125
 * Part of Release Aug_9_2000
126
 *
127
 * Revision 1.46  2000/05/31  11:43:00  11:43:00  mjames (Mike James)
128
 * Part of Release May_31_2000
129
 *
130
 * Revision 1.45  2000/05/08  17:01:39  17:01:39  mjames (Mike James)
131
 * Part of Release May_8_2000
132
 *
133
 * Revision 1.44  2000/05/08  16:59:32  16:59:32  mjames (Mike James)
134
 * Part of Release May_8_2000
135
 *
136
 * Revision 1.43  2000/05/08  16:57:09  16:57:09  mjames (Mike James)
137
 * Part of Release May_8_2000
138
 *
139
 * Revision 1.42  2000/03/08  16:19:29  16:19:29  mjames (Mike James)
140
 * New version including PC
141
 *
142
 * Revision 1.39  2000/01/20  15:58:50  15:58:50  mjames (Mike James)
143
 * Part of Release R22
144
 *
145
 * Revision 1.38  99/12/22  11:15:30  11:15:30  mjames (Mike James)
146
 * Part of Release Dec_22_1999
147
 *
148
 * Revision 1.37  99/06/25  14:35:50  14:35:50  mjames (Mike James)
149
 * Added in reference to expression.h, but no changes made
150
 * to the function of acfread yet.
151
 *
152
 * Revision 1.36  99/06/18  09:26:23  09:26:23  mjames (Mike James)
153
 *
154
 * Revision 1.35  99/05/04  09:52:46  09:52:46  mjames (Mike James)
155
 * General checkin
156
 *
157
 * Revision 1.33  98/11/27  15:16:05  15:16:05  mjames (Mike James)
158
 * FIxed small errors
159
 *
160
 * Revision 1.32  98/06/15  14:19:24  14:19:24  mjames (Mike James)
161
 * Removed and added Route Create from general routing algorithm.
162
 * Added routing routing groups
163
 *
164
 * Revision 1.31  98/04/24  14:09:05  14:09:05  mjames (Mike James)
165
 * Removed 'create routes' from default routing algorithm set
166
 * used when route command is used.
167
 *
168
 * Revision 1.30  98/03/16  11:39:50  11:39:50  mjames (Mike James)
169
 * Removed an old bug - suffixing of PCB names has been broken for about
170
 * a year. If a pcb were read in non-suffixed and then another with a suffix,
171
 * the suffix would be applied over all of the sockets and nets, not just the new ones.
172
 *
173
 * Revision 1.29  98/02/11  11:27:14  11:27:14  mjames (Mike James)
174
 * Checked in for version 6.2a
175
 *
176
 * Revision 1.28  97/04/23  08:43:23  08:43414:23  mjames (Mike James)
177
 * CHecked in for release rel23041997
178
 *
179
 * Revision 1.27  97/01/03  13:35:24  13:35:24  mjames (Mike James)
180
 * Tidied up the ensure_reserved() function. Added in a flag to
181
 * indicate that a net has been processed by ensure_reserved()
182
 * And so is not in error for only having 0 or 1 nodes names (which is the
183
 * case for a 1 or 2 node net that has been processed. One of the nodes will
184
 * remain unnnamed and this will result in 0 or 1 nodes apparently in use
185
 *
186
 * Revision 1.26  96/12/23  15:14:38  15:14:38  mjames (Mike James)
187
 * This code for fixing pins has been split from the 'exact path'
188
 * routing as the algorithm has become more reliable
189
 * if there are two independednt routines.
190
 *
191
 * Revision 1.25  96/12/13  08:43:11  08:43:11  mjames (Mike James)
192
 * Update to v5.1, added Write ID , exact routing
193
 *
194
 * Revision 1.24  96/08/06  13:38:54  13:38:54  mjames (Mike James)
195
 * Added FIX_LOCATION pin attribute to netlist
196
 *
197
 * Revision 1.23  96/07/19  14:38:44  14:38:44  mjames (Mike James)
198
 * Update to give to PRL
199
 *
200
 * Revision 1.22  1996/07/12  15:52:12  mjames
201
 * Sorted out things like Alias and Jumpers
202
 * Work Correctly
203
 * Print COrrectly
204
 *
205
 * Revision 1.21  96/07/09  15:54:04  15:54:04  mjames (Mike James)
206
 * Altered aliasing to make it hierarchical, also for jumpering
207
 *
208
 * Revision 1.20  96/06/17  13:01:45  13:01:45  mjames (Mike James)
209
 * Altered the printing of JUMPERED and ALIASED nets
210
 * ,
211
 *
212
 * Revision 1.19  96/06/11  14:46:00  14:46:00  mjames (Mike James)
213
 * Tidying up done to remove an error created by
214
 * trying to fix the wrong symprom of a bug
215
 *
216
 * Revision 1.18  96/06/11  14:11:47  14:11:47  mjames (Mike James)
217
 * Added hierarchical jumpering
218
 *
219
 * Revision 1.17  96/06/04  11:53:22  11:53:22  mjames (Mike James)
220
 * Added the ability to jumper nets by reference to a node on the nets
221
 *
222
 * Revision 1.16  96/05/29  10:53:34  10:53:34  mjames (Mike James)
223
 * Added renaming of IDs for nets and sockets.
224
 *
225
 * Revision 1.15  96/04/26  16:02:28  16:02:28  mjames (Mike James)
226
 * Altered inside/outside determination of signal directions
227
 *
228
 * Revision 1.14  96/04/15  14:19:36  14:19:36  mjames (Mike James)
229
 * Checkin before datatype printing
230
 * modifications
231
 *
232
 * Revision 1.13  96/03/29  14:46:32  14:46:32  mjames (Mike James)
233
 * Added VHDL netlist writing to the capabilities of ACFREAD
234
 *
235
 * Revision 1.12  96/03/26  07:21:16  07:21:16  mjames (Mike James)
236
 * Added LIST XREF socket-name command
237
 *
238
 * Revision 1.11  96/03/19  08:53:43  08:53:43  mjames (Mike James)
239
 * Minor tweaks
240
 *
241
 * Revision 1.7  96/03/13  15:37:34  15:37:34  mjames (Mike James)
242
 * Altered the name_pref field to be used to indicate the routing algorithm used
243
 * to route this net.
244
 *
245
 * Revision 1.6  96/02/13  09:13:30  09:13:30  mjames (Mike James)
246
 * Updated to be version 2.0 with net joining
247
 *
248
 * Revision 1.5  96/02/08  15:28:31  15:28:31  mjames (Mike James)
249
 * First release
250
 *
251
 * Revision 1.4  96/02/07  16:01:35  16:01:35  mjames (Mike James)
252
 * Added correct RCS header
253
 *
254
 * Revision 1.3  96/02/07  15:50:45  15:50:45  mjames (Mike James)
255
 * Added RCS ident message
256
 *
257
 * Revision 1.2  96/02/07  11:04:25  11:04:25  mjames (Mike James)
258
 * Checkin before adding new command parsing to program
259
 *
260
 * Revision 1.1  96/01/10  13:14:36  13:14:36  mjames (Mike James)
261
 * Initial revision
262
 *  */
263
 
264
#include "routing.h"
265
 
266
#include "chck_names.h"
267
#include "cmdlog.h"
268
#include "cmdparse.h"
269
#include "database.h"
270
#include "expression.h"
271
#include "generic.h"
272
#include "lx_support.h"
273
#include "sorting.h"
274
#include "statistics.h"
275
#include "unrouted.h"
276
#include "vertcl_main.h"
277
 
278
#include <ctype.h>
279
#include <regex.h>
280
#include <stdio.h>
281
#include <stdlib.h>
282
#include <string.h>
283
#include <sys/types.h>
284
 
285
#ident                                                                                        \
286
    "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/routing.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $"
287
 
288
/* used in search for pre-existing path */
289
int MaxNodesForSearch = MAX_NODES_FOR_PATH_SEARCH;
290
 
291
int global_group_flag = 0;
292
 
293
static void get_num_nets (net_t *list, char *message)
294
{
295
        int i = 0;
296
        while (list)
297
        {
298
                list = list->next;
299
                i++;
300
        }
301
        Log (LOG_GENERAL, "-- %-4d %s\n", i, message);
302
}
303
 
304
void count_nets (char *message)
305
{
306
        Log (LOG_GENERAL, "-- Routing Statistics : %s\n", message);
307
 
308
        get_num_nets (unrouted_list, "Connections not routed");
309
        get_num_nets (routed_list, "Nets connected but not in use");
310
        get_num_nets (named_list, "Nets connected and used by named signals");
311
        Log (LOG_GENERAL, "-- \n");
312
}
313
 
314
/* clear the routing flags on the node references on a particular net */
315
/* this tries to avoid the situation where two unrouted nets both find the
316
   same pin connection on the routed net when it is searched to see if
317
   it is connected to a socket. The old algorithm found the first
318
   connected pin on a socket and then used this  */
319
void clear_routing_flags (noderef_t *net_nodes)
320
{
321
        while (net_nodes)
322
        {
323
                /* Indicate not already visited all nodes on this net */
324
                net_nodes->r_flag = 0;
325
                net_nodes = net_nodes->next;
326
        }
327
}
328
 
329
/* does a net reach the wanted socket with the pin direction correct
330
   and if we are using pin_groups is this pin in the correct group */
331
noderef_t *
332
search_net_for_socket (noderef_t *wanted_ref, noderef_t *net_nodes, int use_group_mask)
333
{
334
        int route_flags = 0;
335
        node_t *wanted = wanted_ref->node;
336
        if (use_group_mask)
337
                route_flags = wanted->socket->route_flags;
338
        while (net_nodes)
339
        {
340
                node_t *nnode = net_nodes->node;
341
 
342
                /* if we have not already visited this node */
343
                if ((net_nodes->r_flag == 0) && (nnode->socket == wanted->socket) &&
344
                    /* either
345
                       NOT a fixed pin (pin direction NOT pin location ) or
346
                       IS a fixed pin and in the right direction : probably can use compat_pins
347
                       info from template.c here MDJ Aug 2000 */
348
                    (nnode->fixed_pin == 0 || nnode->pindir == wanted_ref->pindir) &&
349
                    /* either
350
                       Not using pin groups
351
                       or the pin group is the same */
352
                    (!route_flags ||
353
                     ((nnode->pin_group & route_flags) == (wanted->pin_group & route_flags))))
354
                {
355
                        net_nodes->r_flag = 1;
356
                        return (net_nodes);
357
                }
358
                net_nodes = net_nodes->next;
359
        }
360
        return NULL;
361
}
362
 
363
/* removes a net from the list of nets */
364
 
365
net_t *remove_net (net_t **list, net_t *net)
366
{
367
        noderef_t *refs, *temp;
368
        net_t *next_net, *prev_net;
369
        /*
370
           printf("-- removing %s (%s) (%p) list %p\n",
371
           net->identifier,net->name,*list,net);
372
         */
373
        next_net = net->next;
374
        prev_net = net->prev;
375
        /* fill in the gap */
376
        /* removal from head of list is different */
377
        if (net == *list)
378
        {
379
                *list = next_net;
380
                if (next_net)
381
                        next_net->prev = NULL;
382
        }
383
        else
384
        {
385
                if (prev_net)
386
                        prev_net->next = net->next;
387
                if (next_net)
388
                        next_net->prev = net->prev;
389
        };
390
 
391
        /* get pointer to the nodes on this net */
392
        refs = net->nodes;
393
 
394
        /* do not destroy the net linking structure
395
           as it could still be pointed at by unused unrouted
396
           nodes that are still attached to sockets which you will
397
           find if you examine all of the nodes attached to a socket. */
398
        net->list_ref = NULL; /* this net is not held on any list now */
399
        net->nodecount = 0;
400
        net->nodes = NULL;
401
        /*net->subnets  = NULL; do not destroy subnets , used for alias listing */
402
        /*change name to something worrying */
403
        net->name = "[DELETED so this is INVISIBLE]";
404
 
405
        /* remove the nodes on this net */
406
        while (refs)
407
        {
408
                refs->node->refcount--; /* one less reference */
409
                temp = refs->next;
410
                free (refs);
411
                refs = temp;
412
        };
413
 
414
        return next_net;
415
}
416
 
417
/* moves a net from one list to another */
418
void transfer_net_to_named (net_t **from_list, net_t *net)
419
{
420
        /* remove the node from the 'from' list */
421
        /*
422
           printf("-- transferring %s (%s) (%p) list
423
           %p\n",net->identifier,net->name,*from_list,net);
424
         */
425
        if (net->next)
426
                net->next->prev = net->prev;
427
        if (net->prev)
428
                net->prev->next = net->next;
429
 
430
        if (net == *from_list)
431
                *from_list = net->next;
432
 
433
        net->list_ref = &named_list; /* net now is on the named list */
434
 
435
        /* stick net on tail of 'to' list */
436
        if (named_tail)
437
                named_tail->next = net;
438
        net->prev = named_tail;
439
 
440
        if (!named_list)
441
                named_list = net;
442
        net->next = NULL;
443
 
444
        named_tail = net;
445
}
446
 
447
/* ******************************************** */
448
/*
449
   This function tidies up, setting net names for all of the pins on the
450
   net that have not been used by the unrouted net, to a net whose name
451
   is RSV00001Z  where the 00001 is a sequence number .
452
   it also names the routed net
453
 
454
   Recently modified such that external connections do not get this treatment
455
   These pins take on the names of the nets connected regardless, as they are
456
   not EPLDs, so there won't be a complaint by Maxplus2.
457
 */
458
 
459
/* the dummy node count is external to the naming routine, as it
460
   is used in the ensure_reservation code */
461
static int nodecount = 0;
462
 
463
void name_unused_nodes (net_t *routed_net, char *identifier)
464
{
465
        noderef_t *routed_nodes;
466
        char *unused_ident;
467
 
468
        routed_nodes = routed_net->nodes;
469
        while (routed_nodes)
470
        {
471
                node_t *cnode = routed_nodes->node;
472
                if (routed_nodes->node->net_assigned == 0)
473
                { /* this node hasnt yet been used by a net */
474
                        if (cnode->socket->is_external == 0)
475
                        { /* EPLD or internal node */
476
                                /* every reserved pin is unique, so make it a new name c */
477
                                unused_ident = calloc (RES_NAMLEN + 1, sizeof (char));
478
                                sprintf (unused_ident, RES_FMT, nodecount++);
479
                                cnode->name = unused_ident; /* use the created name */
480
 
481
                                cnode->net =
482
                                    routed_net; /* tell the node its got a net assigned */
483
                                cnode->pindir = INPUT;
484
                                /*            cnode->datatype = "Named through naming unused
485
                                 * nodes";*/
486
                                /*        cnode->datatype = routed_net->datatype; */
487
                                cnode->vhdltype =
488
                                    default_vhdl_datatype; /* put something there */
489
                                cnode->lhs_expr = NULL;
490
 
491
                                cnode->orig_vhdltype = NULL; /* put something there */
492
                        }
493
                        else
494
                        { /* An external flag See SET EXTERNAL <prefix> */
495
                                cnode->name = identifier; /* same name as the net */
496
 
497
                                cnode->net =
498
                                    routed_net; /* tell the node its got a net assigned */
499
                                cnode->pindir = INPUT;
500
                                /*            cnode->datatype = routed_net->datatype;   */ /* routed_net->datatype;
501
                                                                                            */
502
                                cnode->vhdltype =
503
                                    routed_net->vhdltype; /* put something there */
504
                                cnode->lhs_expr = NULL;
505
                                cnode->orig_vhdltype = NULL; /* put something there */
506
                        }
507
 
508
                        cnode->net_assigned = 1; /* tell the node its got a net assigned */
509
                        cnode->in_use = 0;       /* if the node is in use then set its flag */
510
                }
511
                routed_nodes = routed_nodes->next;
512
        }
513
}
514
 
515
/* ******************************************** */
516
/* connect up the routed and  unrouted nets */
517
 
518
void combine_sub (net_t *routed_net, net_t *unrouted_net)
519
{
520
        noderef_t *routed_nodes, *unrouted_nodes;
521
 
522
        /*
523
           printf("-- Moving net %s onto routing of %s\n",
524
           unrouted_net->identifier,routed_net->identifier);
525
         */
526
 
527
        unrouted_nodes = unrouted_net->nodes;
528
        routed_nodes = routed_net->nodes;
529
        if (level & 2)
530
        {
531
                Log (
532
                    LOG_GENERAL,
533
                    "#COMBINE_SUB routed=%s, unrouted=%s\n",
534
                    unrouted_net->name,
535
                    routed_net->name);
536
                Log (
537
                    LOG_GENERAL,
538
                    " type def routed = %d unrouted=%d\n",
539
                    unrouted_net->type_defined,
540
                    routed_net->type_defined);
541
        }
542
        /* for each node on the routed net, is this net needed on
543
           the unrouted net */
544
        while (unrouted_nodes)
545
        {
546
                noderef_t *route_ref;
547
                node_t *routed_node, *unrouted_node;
548
                unrouted_node = unrouted_nodes->node;
549
 
550
                /* we have a route, this search _will succeed .. if it doesnt .. oops. */
551
                /* do not need to worry about the groups here as the nets have already
552
                   been found */
553
 
554
                /* Changed MDJ July 2001 : made it a prerequisite to check if the pin_group
555
                 * matches */
556
 
557
                route_ref = search_net_for_socket (
558
                    unrouted_nodes, routed_nodes, unrouted_node->pin_group);
559
 
560
                /* if we have found a node on the right socket on the
561
                   routed net that has not yet been used  */
562
 
563
                if (route_ref)
564
                {
565
                        routed_node = route_ref->node;
566
                        if (level & 2)
567
                                Log (
568
                                    LOG_GENERAL,
569
                                    "info %s(%s)   '%s'\n",
570
                                    routed_node->socket->name,
571
                                    routed_node->identifier,
572
                                    route_ref->orig_name ? route_ref->orig_name
573
                                                         : unrouted_net->name);
574
 
575
                        /*
576
                           route_ref->r_flag = 1;
577
                         *//* we are using this node */
578
                        routed_node->pindir =
579
                            unrouted_nodes->pindir; /* the node reference holds the
580
                                                       pin direction */
581
 
582
                        /*        routed_node->name = unrouted_net->identifier; Previous !!!*/
583
                        if (route_ref->orig_name)
584
                        {
585
                                routed_node->name = route_ref->orig_name;
586
                                routed_node->vhdltype = route_ref->vhdltype;
587
                                routed_node->orig_vhdltype = route_ref->orig_vhdltype;
588
                                routed_node->lhs_expr = route_ref->lhs_expr;
589
                                if (level & 2)
590
                                        Log (
591
                                            LOG_GENERAL,
592
                                            "# Info : found  rename to %s on %s\n",
593
                                            route_ref->orig_name,
594
                                            unrouted_net->identifier);
595
                        }
596
                        else
597
                        {
598
                                routed_node->name = unrouted_net->identifier;
599
                                routed_node->vhdltype = unrouted_nodes->vhdltype;
600
                                routed_node->lhs_expr = unrouted_nodes->lhs_expr;
601
                                routed_node->orig_vhdltype = unrouted_nodes->orig_vhdltype;
602
                        }
603
                        /*        routed_node->datatype = unrouted_nodes->datatype; */
604
                        routed_node->net =
605
                            routed_net;          /* tell the node its got a net assigned */
606
                        routed_node->in_use = 1; /* if the node is in use then set its flag */
607
                        routed_node->net_assigned = 1;
608
                        routed_node->routed_net = NULL; /* all nodes on the routed net are
609
                                                           about to belong to the named list */
610
                }
611
                if (level & 2)
612
                        Log (LOG_GENERAL, "#\n");
613
                unrouted_nodes = unrouted_nodes->next;
614
        };
615
}
616
 
617
static void combine_alias (net_t *routed_net, net_t *unrouted_net)
618
{
619
        /*    printf("combining alias %s with routed %s\n",unrouted_net->identifier,
620
           routed_net->identifier);    */
621
        while (unrouted_net)
622
        {
623
                if (unrouted_net->how_joined == Aliased)
624
                { /* recursion for alias */
625
                        if (unrouted_net->subnets)
626
                                combine_alias (routed_net, unrouted_net->subnets);
627
                }
628
                else
629
                {
630
                        /* and for each aliased subnet ... */
631
                        clear_routing_flags (unrouted_net->nodes);
632
                        /* printf("moving aliased net .%s.\n",unrouted_net->identifier); */
633
                        combine_sub (routed_net, unrouted_net);
634
                        /*  name_unused_nodes (routed_net, unrouted_net->identifier); */
635
                }
636
                unrouted_net = unrouted_net->joined_nets;
637
        }
638
}
639
/* ******************************************** */
640
/* if a net was created by aliasing names, now we have to copy out each of
641
   the unrouted sub nets to the routed net - getting node names right
642
   in particular . Otherwise just do the one */
643
 
644
void combine_routed_and_unrouted (net_t *routed_net, net_t *unrouted_net)
645
{
646
        clear_routing_flags (routed_net->nodes);
647
        /* refer across to unrouted net for printout */
648
        /*
649
           printf("Combining '%s' and '%s' \n",routed_net->identifier,
650
           unrouted_net->identifier);
651
         */
652
        routed_net->unrouted_reference = unrouted_net;
653
        routed_net->name = unrouted_net->identifier;
654
        /* assumption here is that the datatype and vhdltype are the same */
655
        /*  routed_net->datatype = unrouted_net->datatype; */
656
 
657
        routed_net->vhdltype = unrouted_net->vhdltype;
658
 
659
        if (unrouted_net->how_joined == Aliased)
660
        {
661
                /* preserve aliasing information */
662
                combine_alias (routed_net, unrouted_net);
663
        }
664
        else
665
        {
666
                clear_routing_flags (unrouted_net->nodes);
667
                combine_sub (routed_net, unrouted_net);
668
 
669
                /*  name_unused_nodes (routed_net, unrouted_net->identifier); */
670
        }
671
}
672
 
673
/* **************************************************************** */
674
/* This function ensures net reservation is made for all internal
675
   nodes that are on internal sockets .
676
   If any external socket is on the net then all internal pins are reserved.
677
   Otherwise a single internal pin is left as a non-reserved driver */
678
 
679
void ensure_reservation (void)
680
{
681
        char *unused_ident;
682
        net_t *net_head = routed_list;
683
        int skip; /* the number of nodes on the net to leave unreserved */
684
 
685
        /*
686
           puts("ensure_reservation entered");
687
        */
688
        while (net_head)
689
        {
690
                net_t *altered_net = NULL;
691
                if (net_head->nodecount > 1 && IS_ROUTABLE (net_head->how_routed))
692
                { /* ignore single node nets as they need to be external */
693
                        noderef_t *routed_nodes = net_head->nodes;
694
                        net_head->nodes_reserved = 0; /* Begin by clearing the flag */
695
                        /* nets with external sockets cannot be allowed */
696
                        if (net_head->has_external)
697
                                skip = 0;
698
                        else
699
                                skip = 1;
700
                        /*
701
                              printf("Net '%s'\n",net_head->identifier);
702
                        */
703
                        while (routed_nodes)
704
                        {
705
                                node_t *cnode = routed_nodes->node;
706
                                if (cnode->net_assigned == 0 && /* this node hasnt yet been
707
                                                                   used by a net */
708
                                    /* set the flag to stop count_nets_with_few_nodes() in
709
                                       statistics.c from complaining */
710
                                        cnode->socket->is_external == 0)
711
                                { /* EPLD or internal node */
712
                                        net_head->nodes_reserved = 1;
713
                                        /* every reserved pin is unique, so make it a new name
714
                                         */
715
                                        if (skip == 0)
716
                                        { /* skipped enough ? */
717
                                                unused_ident =
718
                                                    calloc (RES_NAMLEN + 1, sizeof (char));
719
                                                sprintf (
720
                                                    unused_ident,
721
                                                    RES_FMT,
722
                                                    nodecount++); /* shared node counter */
723
                                                cnode->name =
724
                                                    unused_ident; /* use the created name */
725
 
726
                                                cnode->net = net_head; /* tell the node its got
727
                                                                          a net assigned */
728
                                                cnode->pindir = INPUT;
729
                                                /*              cnode->datatype = "Named
730
                                                 * through naming unused nodes";*/      /* routed_net->datatype; */
731
                                                cnode->vhdltype =
732
                                                    default_vhdl_datatype; /* put something
733
                                                                              there */
734
                                                cnode->net_assigned = 1;
735
                                                cnode->lhs_expr = NULL;
736
                                                altered_net = net_head;
737
                                        }
738
                                        else
739
                                                skip--;
740
                                }
741
 
742
                                routed_nodes = routed_nodes->next;
743
                        }
744
                } /* nodecount */
745
                net_head = net_head->next;
746
                if (altered_net)
747
                {
748
/*
749
          transfer_net_to_named (&routed_list, altered_net);
750
*/    }
751
        }
752
}
753
 
754
/* this function checks to see if the net identifier of an unrouted net matches that
755
   of a routed net, which is itself not routable */
756
void validate_unrouted (void)
757
{
758
        net_t *routed_net, *unrouted_net;
759
 
760
        unrouted_net = unrouted_list;
761
        while (unrouted_net)
762
        {
763
                if (unrouted_net->identifier[0])
764
                {
765
                        /* search first for matching Identifier */
766
                        routed_net =
767
                            find_net (&routed_list, Ident, unrouted_net->identifier, Search);
768
 
769
                        /* located a net that could be a candidate . Validate routing status
770
                           and report an error if there is a problem */
771
 
772
                        if (routed_net && IS_NOT_ROUTABLE (routed_net->how_routed))
773
                        {
774
                                noderef_t *nodes = unrouted_net->nodes;
775
                                unrouted_net->how_routed = routed_net->how_routed;
776
                                Log (
777
                                    LOG_ERROR,
778
                                    "-- WARNING : Routing : Net '%s' with following unrouted\n"
779
                                    "--   nodes cannot be connected to an UNROUTABLE routed "
780
                                    "net\n",
781
                                    unrouted_net->identifier);
782
                                while (nodes)
783
                                {
784
                                        Log (
785
                                            LOG_ERROR,
786
                                            "--   %s(%s)\n",
787
                                            nodes->node->socket->identifier,
788
                                            nodes->node->identifier);
789
                                        nodes = nodes->next;
790
                                }
791
                        }
792
                        else
793
                                unrouted_net->how_routed =
794
                                    Free; /* can keep on routing this net */
795
                }
796
                unrouted_net = unrouted_net->next;
797
        }
798
}
799
 
800
/* ******************************************** */
801
/* this procedure searches the unrouted nets one by one.
802
   if an unrouted net has the same name as a
803
   routed net, then all nodes on the unrouted net take on the
804
   routed net name , and the routed net's status is changed to reflect this
805
   name. All 'spare' nodes on the routed net are set to point at a 'reserved' net
806
   for future safety */
807
void perform_routing_by_name (void)
808
{
809
        net_t *routed_net;
810
        noderef_t *routed_nodes, *unrouted_nodes;
811
        net_t *unrouted_net, *prev_net;
812
        int routed_ok;
813
 
814
        prev_net = NULL;
815
        unrouted_net = unrouted_list;
816
        while (unrouted_net)
817
        {
818
                routed_ok = 0;
819
                if (unrouted_net->identifier[0] && IS_ROUTABLE (unrouted_net->how_routed))
820
                {
821
                        /* search first for matching Name then for matching Identifier */
822
 
823
                        routed_net =
824
                            find_net (&routed_list, Name, unrouted_net->identifier, Search);
825
                        if (!routed_net)
826
                                routed_net = find_net (
827
                                    &routed_list, Ident, unrouted_net->identifier, Search);
828
 
829
                        if (routed_net && IS_ROUTABLE (routed_net->how_routed))
830
                        {
831
                                /* found a routed net,                    with this name or
832
                                 * ident */
833
                                /* check status of this net, see if it connects the right
834
                                 * places */
835
                                int f = 1;
836
                                /*
837
                                   printf("Found matching routed net \n");
838
                                 */
839
                                unrouted_nodes = unrouted_net->nodes;
840
                                routed_nodes = routed_net->nodes;
841
                                clear_routing_flags (routed_nodes);
842
 
843
                                while (unrouted_nodes && f)
844
                                {
845
                                        f = search_net_for_socket (
846
                                                unrouted_nodes, routed_nodes, 1) != NULL;
847
                                        unrouted_nodes = unrouted_nodes->next;
848
                                }
849
 
850
                                /* if f is 1 then the routed net connects all of the nodes on
851
                                   the unrouted net */
852
                                if (f)
853
                                {
854
                                        /*
855
                                           printf("and can join together sockets \n");
856
                                         */
857
                                        /* Can fit nets together */
858
                                        combine_routed_and_unrouted (routed_net, unrouted_net);
859
                                        /* prevent this net from being recycled, move to
860
                                           the fully named and routed list */
861
                                        transfer_net_to_named (&routed_list, routed_net);
862
                                        routed_net->how_routed =
863
                                            By_Name; /* This net was routed by name !! */
864
                                        routed_ok = 1;
865
                                }
866
                        }
867
                }
868
                if (routed_ok)
869
                        /* remove the unrouted net from the list */
870
                        unrouted_net = remove_net (&unrouted_list, unrouted_net);
871
                else
872
                        /* Not removing net as algorithm hasnt found a match */
873
                        unrouted_net = unrouted_net->next;
874
        };
875
        count_nets ("After routing by matching existing net names");
876
}
877
 
878
/************************************************************************/
879
/* this algorithm works by considering each of the routed nets in turn
880
   to see if there is an unrouted net 'fixed' to it. */
881
/************************************************************************/
882
 
883
void perform_routing_by_fixed_net (void)
884
{
885
        net_t *unrouted_net, *routed_next;
886
        net_t *routed_net = routed_list;
887
        int routed_ok, f;
888
        while (routed_net)
889
        {
890
                routed_next = routed_net->next; /* 'next' will  be changed when a routed
891
                                                   net is moved onto  the named list */
892
                routed_ok = 0;
893
                f = 1;
894
                /*
895
                    printf("Considering ROUTED '%s'\n",routed_net->identifier);
896
                */
897
                if (IS_ROUTABLE (routed_net->how_routed) && routed_net->has_fix_location &&
898
                    routed_net->unrouted_fix_net)
899
                {
900
                        unrouted_net = routed_net->unrouted_fix_net;
901
                        /*
902
                              printf("  with UNROUTED '%s'\n",unrouted_net->identifier);
903
                        */
904
 
905
                        if (unrouted_net->nodecount > 0 &&
906
                            IS_NOT_ROUTABLE (unrouted_net->how_routed))
907
                        /* skip all 1-node nets, these will be dealt with by
908
                                                               a later routing algorithm */
909
                        {
910
                                if (routed_net->nodecount >= unrouted_net->nodecount)
911
                                {
912
                                        /* enough nodes, but does it go the right places ?? */
913
                                        noderef_t *unrouted_nodes = unrouted_net->nodes;
914
                                        noderef_t *routed_nodes = routed_net->nodes;
915
                                        clear_routing_flags (routed_nodes);
916
                                        while (unrouted_nodes && f)
917
                                        {
918
                                                f = search_net_for_socket (
919
                                                        unrouted_nodes, routed_nodes, 1) !=
920
                                                    NULL;
921
                                                unrouted_nodes = unrouted_nodes->next;
922
                                        }
923
                                        /* if f is 1 then the routed net connects all of the
924
                                           nodes on the unrouted net */
925
                                        if (f)
926
                                        {
927
                                                /* Can join Routed & Unrouted nets together */
928
                                                /*
929
                                                          printf("Managed '%s' for fixed net
930
                                                   routing '%s' \n",routed_net -> identifier,
931
                                                                     unrouted_net->identifier);
932
                                                */
933
                                                combine_routed_and_unrouted (
934
                                                    routed_net, unrouted_net);
935
 
936
                                                /* prevent this net from being recycled, move
937
                                                   to the fully named and routed list */
938
                                                transfer_net_to_named (
939
                                                    &routed_list, routed_net);
940
                                                routed_net->how_routed =
941
                                                    By_Fixed_Net; /* This net was routed by
942
                                                                     finding a wire! */
943
                                                routed_ok = 1;
944
                                                /*
945
                                                                    Log (LOG_GENERAL, "#
946
                                                   Sucessfully routed net '%s' by fixing
947
                                                   pins\n", routed_net->name);
948
                                                */
949
                                        }
950
                                }
951
                        };
952
 
953
                        if (routed_ok)
954
                        {
955
                                /*      printf("Removing '%s' from
956
                                 * list\n",unrouted_net->identifier);
957
                                 */
958
                                /* remove the unrouted net from the list */
959
                                remove_net (&unrouted_list, unrouted_net);
960
                        }
961
                        else
962
                                Log (
963
                                    LOG_ERROR,
964
                                    "-- Error (probably) : net '%s':  Fix pin attempt has "
965
                                    "failed on this net !!\n",
966
                                    unrouted_net->identifier);
967
                }
968
                routed_net = routed_next;
969
        }
970
        count_nets ("After routing fixed nets");
971
}
972
 
973
/* ******************************************** */
974
/* this code deals with trying to find if a Routed net with
975
   exactly the same connections as the Unrouted net exists.
976
   Preference is to be given to any routed nets that have fixed pins */
977
/* ******************************************** */
978
 
979
void perform_routing_by_exact_path (void)
980
{
981
        net_t *unrouted_net;
982
        net_t *routed_net;
983
        int routed_ok, f;
984
        enum
985
        {
986
                CheckFixed,
987
                DoAny
988
        } pass;
989
 
990
        for (pass = CheckFixed; pass <= DoAny; pass++)
991
        {
992
                unrouted_net = unrouted_list;
993
                while (unrouted_net)
994
                {
995
                        routed_ok = 0;
996
                        f = 1;
997
 
998
                        /* if we are looking for EXACT path matching, then ANY node on the
999
                           unrouted list
1000
                           will be connected to the SAME routed net, so just pick the first
1001
                           node        */
1002
 
1003
                        if (unrouted_net->nodes)
1004
                                routed_net = unrouted_net->nodes->node->routed_net;
1005
                        else
1006
                                routed_net = NULL;
1007
 
1008
                        if (IS_ROUTABLE (unrouted_net->how_routed) &&
1009
                            routed_net && /* any nodes ? */
1010
                            /* on pass= DoAny, consider all. */
1011
                            /* on pass= CheckFixed, only those with a fixed pin on the net */
1012
                            (pass == DoAny ||
1013
                             (pass == CheckFixed && routed_net->has_fix_location)) &&
1014
 
1015
                            routed_net->list_ref == &routed_list && /* is routed net still
1016
                                                                       available on the routed
1017
                                                                       list ? */
1018
                            unrouted_net->nodecount > 0) /* skip all 1-node nets, these will be
1019
                                                            dealt with by a later routing
1020
                                                            algorithm */
1021
                        {
1022
                                if (routed_net->nodecount >= unrouted_net->nodecount &&
1023
                                    IS_ROUTABLE (routed_net->how_routed))
1024
                                {
1025
                                        /* enough nodes, but does it go the right places ?? */
1026
                                        noderef_t *unrouted_nodes = unrouted_net->nodes;
1027
                                        noderef_t *routed_nodes = routed_net->nodes;
1028
                                        clear_routing_flags (routed_nodes);
1029
                                        while (unrouted_nodes && f)
1030
                                        {
1031
                                                f = search_net_for_socket (
1032
                                                        unrouted_nodes, routed_nodes, 1) !=
1033
                                                    NULL;
1034
                                                unrouted_nodes = unrouted_nodes->next;
1035
                                        }
1036
                                        /* if f is 1 then the routed net connects all of the
1037
                                           nodes on the unrouted net */
1038
                                        if (f)
1039
                                        {
1040
                                                /* Can join Routed & Unrouted nets together */
1041
                                                /*        printf("Managed '%s' for exact path
1042
                                                   routing '%s' \n",routed_net -> identifier,
1043
                                                   unrouted_net->identifier);
1044
                                                */
1045
                                                combine_routed_and_unrouted (
1046
                                                    routed_net, unrouted_net);
1047
 
1048
                                                /* prevent this net from being recycled, move
1049
                                                   to the fully named and routed list */
1050
                                                transfer_net_to_named (
1051
                                                    &routed_list, routed_net);
1052
                                                routed_net->how_routed =
1053
                                                    By_Exact_Net; /* This net was routed by
1054
                                                                     finding a wire! */
1055
                                                routed_ok = 1;
1056
                                                /*
1057
                                                                      Log (LOG_GENERAL, "#
1058
                                                   Sucessfully routed net '%s' by exact
1059
                                                   path\n", routed_net->name);
1060
                                                */
1061
                                        }
1062
                                }
1063
                        };
1064
                        if (routed_ok)
1065
                        {
1066
                                /*      printf("Removing '%s' from
1067
                                 * list\n",unrouted_net->identifier);
1068
                                 */
1069
                                /* remove the unrouted net from the list */
1070
                                unrouted_net = remove_net (&unrouted_list, unrouted_net);
1071
                        }
1072
                        else
1073
                        {
1074
                                /* Not removing net as algorithm hasnt found a match */
1075
                                unrouted_net = unrouted_net->next;
1076
                        }
1077
                }
1078
        } /* pass counter loop */
1079
        count_nets ("After routing by finding exactly identical paths");
1080
}
1081
 
1082
/* ******************************************** */
1083
void perform_routing_by_path (void)
1084
{
1085
        net_t *unrouted_net = unrouted_list;
1086
        net_t *routed_net;
1087
        int accept_nodes;
1088
 
1089
        while (unrouted_net)
1090
        {
1091
                int routed_ok = 0;
1092
 
1093
                /*
1094
                   printf("-- by path : identifier %s\n",unrouted_net->identifier);
1095
                 */
1096
                /* repeatedly search the routed nodes list for one with more or the same
1097
                   number of connections wanted */
1098
                /* skip all 1-node nets, these will be dealt with by a later routing algorithm
1099
                 */
1100
                if (unrouted_net->nodecount > 0 && IS_ROUTABLE (unrouted_net->how_routed))
1101
                {
1102
                        for (accept_nodes = unrouted_net->nodecount;
1103
                             accept_nodes < MaxNodesForSearch && !routed_ok;
1104
                             accept_nodes++)
1105
                        {
1106
                                /* locate any fix_location nodes here eventually */
1107
                                routed_net = routed_list;
1108
 
1109
                                while (routed_net && !routed_ok)
1110
                                {
1111
                                        if (routed_net->nodecount == accept_nodes &&
1112
                                            IS_ROUTABLE (routed_net->how_routed))
1113
                                        {
1114
                                                /* enough nodes, but does it go the right
1115
                                                 * places ?? */
1116
                                                int f = 1;
1117
                                                noderef_t *unrouted_nodes =
1118
                                                    unrouted_net->nodes;
1119
                                                noderef_t *routed_nodes = routed_net->nodes;
1120
                                                clear_routing_flags (routed_nodes);
1121
                                                while (unrouted_nodes && f)
1122
                                                {
1123
                                                        f = search_net_for_socket (
1124
                                                                unrouted_nodes,
1125
                                                                routed_nodes,
1126
                                                                1) != NULL;
1127
                                                        unrouted_nodes = unrouted_nodes->next;
1128
                                                }
1129
                                                /* if f is 1 then the routed net connects all
1130
                                                   of the nodes on the unrouted net */
1131
                                                if (f)
1132
                                                {
1133
                                                        /* Can join Routed & Unrouted nets
1134
                                                         * together */
1135
                                                        combine_routed_and_unrouted (
1136
                                                            routed_net, unrouted_net);
1137
 
1138
                                                        /* prevent this net from being
1139
                                                           recycled, move to the fully named
1140
                                                           and routed list */
1141
                                                        transfer_net_to_named (
1142
                                                            &routed_list, routed_net);
1143
                                                        routed_net->how_routed =
1144
                                                            By_Net; /* This net was routed by
1145
                                                                       finding a wire! */
1146
                                                        routed_ok = 1;
1147
                                                }
1148
                                        }
1149
                                        routed_net = routed_net->next;
1150
                                };
1151
                        }
1152
                }
1153
                if (routed_ok)
1154
                {
1155
                        /* remove the unrouted net from the list */
1156
                        unrouted_net = remove_net (&unrouted_list, unrouted_net);
1157
                }
1158
                else
1159
                        /* Not removing net as algorithm hasnt found a match */
1160
                        unrouted_net = unrouted_net->next;
1161
        }
1162
 
1163
        count_nets ("After routing by finding existing net paths");
1164
}
1165
 
1166
/* ******************************************** */
1167
/* this function checks all the unrouted nets to see if any of them
1168
   are connected to nodes that are known to exist on a connector, but
1169
   are not on any net. This works to join up unrouted nets mentioned in
1170
   CHIP descriptions */
1171
 
1172
void perform_routing_by_making_nets (void)
1173
{
1174
        net_t *unrouted_net = unrouted_list;
1175
        net_t *next_net;
1176
        int failcount = 0;
1177
        while (unrouted_net)
1178
        {
1179
                int routed_ok = 0;
1180
                int f = 1;
1181
                noderef_t *unrouted_nodes;
1182
                next_net = unrouted_net->next;
1183
                if (IS_ROUTABLE (unrouted_net->how_routed))
1184
                {
1185
                        unrouted_nodes = unrouted_net->nodes;
1186
 
1187
                        /*
1188
                           printf("-- by making nets : identifier
1189
                           %s\n",unrouted_net->identifier);
1190
                         */
1191
                        /* repeatedly search the unrouted net list */
1192
                        /* only route unconnected nodes referred to by one net,
1193
                           whether routed or unrouted otherwise shorts will happen */
1194
                        while (IS_ROUTABLE (unrouted_net->how_routed) && unrouted_nodes &&
1195
                               ((f = unrouted_nodes->node->net_assigned == 0) &&
1196
                                unrouted_nodes->node->refcount == 1))
1197
                                unrouted_nodes = unrouted_nodes->next;
1198
                        if (!f && unrouted_nodes)
1199
                        {
1200
                                failcount++;
1201
                                Log (
1202
                                    LOG_ERROR,
1203
                                    "-- FAIL on : net %s\n",
1204
                                    unrouted_net->identifier);
1205
                                Log (
1206
                                    LOG_ERROR,
1207
                                    "--   node %s(%s)\n",
1208
                                    unrouted_nodes->node->socket->identifier,
1209
                                    unrouted_nodes->node->identifier);
1210
                                if (unrouted_nodes->node->net_assigned)
1211
                                        Log (
1212
                                            LOG_ERROR,
1213
                                            "-- Node is on an already assigned net\n");
1214
                                if (unrouted_nodes->node->refcount > 1)
1215
                                        Log (
1216
                                            LOG_ERROR,
1217
                                            "-- Node is referred to by %d nets\n",
1218
                                            unrouted_nodes->node->refcount);
1219
                        }
1220
 
1221
                        /* if f is 1 then the unrouted net contains only unassigned nodes */
1222
                        if (f)
1223
                        {
1224
                                net_t *poss_routed_net;
1225
                                /* now we need to confirm that the name is unique:
1226
                                   search for it to see if there already*/
1227
                                poss_routed_net = find_net (
1228
                                    &routed_list, Ident, unrouted_net->identifier, Search);
1229
                                if (!poss_routed_net)
1230
                                { /* its unique */
1231
                                        /* prevent this net from being recycled, move to
1232
                                          the fully named and routed list */
1233
                                        combine_routed_and_unrouted (
1234
                                            unrouted_net, unrouted_net);
1235
                                        transfer_net_to_named (&unrouted_list, unrouted_net);
1236
                                        unrouted_net->how_routed =
1237
                                            By_Creating; /* This net was routed by creating a
1238
                                                            new one !! */
1239
                                        Log (
1240
                                            LOG_GENERAL,
1241
                                            "-- Info: Created Wiring for net '%s'\n",
1242
                                            unrouted_net->identifier);
1243
                                        routed_ok = 1;
1244
                                }
1245
                                else
1246
                                {
1247
                                        Log (
1248
                                            LOG_ERROR,
1249
                                            "-- ERROR: Net identifier '%s' already in use in "
1250
                                            "routed list: cannot create\n",
1251
                                            unrouted_net->identifier);
1252
                                        routed_ok = 0;
1253
                                }
1254
                        }
1255
                }
1256
                /* move on , either its been moved from one list to the other or its still
1257
                 * there */
1258
                unrouted_net = next_net;
1259
        }
1260
 
1261
        count_nets ("After routing by making nets");
1262
}
1263
 
1264
/* ******************************************** */
1265
/* Pruning nets that have names like rsv00000z  */
1266
/* from a list                                  */
1267
/* ******************************************** */
1268
 
1269
void prune_nets_from_list (net_t **list, char *res_tpl)
1270
{
1271
        net_t *curr_net = *list;
1272
        while (curr_net)
1273
        {
1274
                int i = 0;
1275
                while ((i < RES_NAMLEN) &&
1276
                       /* string match */
1277
                       (res_tpl[i] == tolower (curr_net->identifier[i]) ||
1278
                        /* 0 in template matches a digit */
1279
                        ((res_tpl[i] == '0') && isdigit (curr_net->identifier[i]))))
1280
                        i++;
1281
                if (i == RES_NAMLEN)
1282
                        curr_net = remove_net (list, curr_net);
1283
                else
1284
                        curr_net = curr_net->next;
1285
        }
1286
}
1287
 
1288
/* ******************************************** */
1289
 
1290
void prune_nets ()
1291
{
1292
        char res_tpl[RES_NAMLEN + 1];
1293
        sprintf (res_tpl, RES_FMT, 0); /* create a template, with 00000 in it  */
1294
        prune_nets_from_list (&routed_list, res_tpl);
1295
        prune_nets_from_list (&unrouted_list, res_tpl);
1296
 
1297
        count_nets ("After deleting dummy nets e.g. 'rsv00001z'");
1298
}
1299
 
1300
/* ******************************************** */
1301
/* this function is intended to check to see how many nets have got
1302
   how_routed = By_FixPins .  */
1303
 
1304
void check_for_unused_fixed_nets (char *why)
1305
{
1306
        net_t *curr_net = routed_list;
1307
        int print_flag = 1;
1308
        while (curr_net)
1309
        {
1310
                if (curr_net->how_routed == By_FixPins)
1311
                {
1312
                        if (print_flag)
1313
                        {
1314
                                print_flag = 0;
1315
                                Log (
1316
                                    LOG_ERROR,
1317
                                    "-- ERROR : fix_pin fails due to %s:\n-- Failures :\n",
1318
                                    why);
1319
                        }
1320
                        Log (
1321
                            LOG_ERROR,
1322
                            "--   '%s' to routed net='%s'\n",
1323
                            curr_net->name,
1324
                            curr_net->identifier);
1325
                }
1326
                curr_net = curr_net->next;
1327
        }
1328
        puts ("--");
1329
}
1330
 
1331
/* ******************************************** */
1332
 
1333
void perform_routing (HowRouted_t how)
1334
{
1335
        count_nets ("Before fixing up pin aliases");
1336
 
1337
        create_unrouted_list ();
1338
 
1339
        if (need_validate_names)
1340
        {
1341
                Log (LOG_GENERAL, "# Validating net names and identifiers\n");
1342
                validate_names ();
1343
                need_validate_names = 0;
1344
        }
1345
        count_nets ("Before routing");
1346
        validate_unrouted ();
1347
 
1348
        prune_nets ();
1349
 
1350
        if (how == Free || how == By_Name)
1351
        {
1352
                /* get rid of all unrouted nets that have been invented in the first place */
1353
                perform_routing_by_name ();
1354
                check_for_unused_fixed_nets ("Nets already routed by name");
1355
        };
1356
        if (how == Free || how == By_Fixed_Net)
1357
        {
1358
                perform_routing_by_fixed_net ();
1359
                check_for_unused_fixed_nets ("Routed nets with fixed pins do not match "
1360
                                             "unrouted");
1361
        };
1362
        if (how == Free || how == By_Exact_Net)
1363
                perform_routing_by_exact_path ();
1364
        if (how == Free || how == By_Net)
1365
                perform_routing_by_path ();
1366
        if (how == By_Creating) /* Will not  create missing nets !! : use creation */
1367
                perform_routing_by_making_nets ();
1368
        if (how == Free)
1369
                ensure_reservation ();
1370
        count_nets_with_few_nodes (1); /* summarise single connection nets */
1371
}
1372
 
1373
/* ******************************************** */
1374
/* Experimental bit of code : For all nets that connect to
1375
   a pin of an external socket in the unrouted list ,
1376
   check to see if the routed net connected to the same pin has a name assigned.
1377
   If it does not then try setting the name of the net to the identifier
1378
   of the unrouted net . Use this before routing */
1379
 
1380
void perform_trial_naming (void)
1381
{
1382
        net_t *cur_net;
1383
        int fixed_counter = 0;
1384
 
1385
        create_unrouted_list ();
1386
 
1387
        cur_net = unrouted_list; /* after pin renames etc have been executed */
1388
 
1389
        prune_nets (); /* will not fix rsv00000z pins !! */
1390
 
1391
        while (cur_net)
1392
        {
1393
                noderef_t *nodes = cur_net->nodes;
1394
                if (level & 8)
1395
                        Log (LOG_GENERAL, "# Trying to fix net '%s'\n", cur_net->identifier);
1396
                while (nodes)
1397
                {
1398
                        /* is this node pointing at an external socket */
1399
                        node_t *n = nodes->node;
1400
                        /* only fix one routed net to this un_routed net */
1401
                        if (n->socket->is_external)
1402
                        { /* on an external socket */
1403
 
1404
                                n->fix_location = 1; /* set the location fixed flag a*/
1405
                                if (n->routed_net)
1406
                                { /* and set the flag on the routed net */
1407
                                        n->routed_net->unrouted_fix_net = cur_net;
1408
                                        n->routed_net->has_fix_location = 1;
1409
                                        fixed_counter++;
1410
                                        if (level & 8)
1411
                                                Log (
1412
                                                    LOG_GENERAL,
1413
                                                    "#    to net '%s'\n",
1414
                                                    n->routed_net->identifier);
1415
                                }
1416
                        }
1417
                        nodes = nodes->next;
1418
                }
1419
                /*
1420
                          Log (LOG_GENERAL, "#\n");
1421
                */
1422
                cur_net = cur_net->next;
1423
        }
1424
        Log (LOG_GENERAL, "# Fixed %d pins\n", fixed_counter);
1425
}
1426
 
1427
/* ********************************************************************* */
1428
 
1429
/* force routing flag of routed net  */
1430
void force_route (char *template, HowRouted_t flag)
1431
{
1432
        net_t *net = routed_list;
1433
        int rc, any_found = 0;
1434
        int found;
1435
 
1436
        /* compile regular expression */
1437
        vert_regex_t *preg;
1438
 
1439
        rc = vert_regcomp (&preg, template);
1440
 
1441
        if (rc != 0)
1442
        {
1443
                char errbuff[100];
1444
                regerror (rc, preg->preg, errbuff, 100);
1445
                Log (
1446
                    LOG_ERROR,
1447
                    "-- Problem (rc=%d) %s with '%s' as regular expression\n",
1448
                    rc,
1449
                    errbuff,
1450
                    template);
1451
 
1452
                /*    return TCL_ERROR;
1453
                 */
1454
                return;
1455
        }
1456
        else
1457
        {
1458
                Log (LOG_GENERAL, "-- Using '%s' as match pattern\n", template);
1459
        }
1460
 
1461
        while (net)
1462
        {
1463
                found = regexec (preg->preg, net->identifier, 0, preg->regpatt, 0);
1464
 
1465
                if (!found)
1466
                {
1467
                        char *s;
1468
                        any_found = 1;
1469
                        net->how_routed = flag;
1470
                        switch (flag)
1471
                        {
1472
                        case Not_Routable:
1473
                                s = "not routable";
1474
                                break;
1475
                        case Not_Routable_H:
1476
                                s = "not routable H";
1477
                                break;
1478
                        case Not_Routable_L:
1479
                                s = "not routable L";
1480
                                break;
1481
                        default:
1482
                                s = "routable";
1483
                                break;
1484
                        }
1485
                        Log (LOG_GENERAL, "-- Set net '%s' as %s\n", net->identifier, s);
1486
                }
1487
                net = net->next;
1488
        }
1489
        if (!any_found)
1490
                Log (LOG_GENERAL, "-- No nets match '%s'\n", template);
1491
        vert_regfree (&preg);
1492
}
1493
 
1494
/* ********************************************************************* */
1495
void set_group_route_flags (char *template, int flag)
1496
{
1497
        int found;
1498
        socket_t *socket = socket_head;
1499
        int rc, any_found = 0;
1500
 
1501
        /* compile regular expression */
1502
        vert_regex_t *preg;
1503
        rc = vert_regcomp (&preg, template);
1504
 
1505
        if (rc != 0)
1506
        {
1507
                char errbuff[100];
1508
                regerror (rc, preg->preg, errbuff, 100);
1509
                Log (
1510
                    LOG_ERROR,
1511
                    "-- Problem (rc=%d) %s with '%s' as regular expression\n",
1512
                    rc,
1513
                    errbuff,
1514
                    template);
1515
 
1516
                /*    return TCL_ERROR;
1517
                 */
1518
                return;
1519
        }
1520
        else
1521
        {
1522
                Log (LOG_GENERAL, "-- Using '%s' as match pattern\n", template);
1523
        }
1524
 
1525
        Log (LOG_GENERAL, "----- Setting pin group routing flags to %d for\n", flag);
1526
 
1527
        while (socket)
1528
        {
1529
                found = regexec (preg->preg, socket->identifier, 0, preg->regpatt, 0);
1530
                if (!found)
1531
                {
1532
                        any_found = 1;
1533
                        socket->route_flags = flag;
1534
                        Log (LOG_GENERAL, "-- socket '%s'\n", socket->identifier);
1535
                }
1536
                socket = socket->next;
1537
        }
1538
        if (!any_found)
1539
                Log (LOG_GENERAL, "-- No sockets match '%s'\n", template);
1540
        vert_regfree (&preg);
1541
}
1542
 
1543
/**************************************************************/
1544
/* Function sets the pin group flags on a device */
1545
/* pattern is ic.pin                             */
1546
/* changed to ic(pin)                            */
1547
void set_pin_group_flags (char *device_string, int flag)
1548
{
1549
        socket_t *socket;
1550
        node_t *node;
1551
        int socket_cnt = 0, pin_cnt = 0; /* counters */
1552
        int found_socket, found_pin;
1553
        char *s = strdup (device_string);
1554
        char *p, *q;
1555
        int rc;
1556
        /* compile regular expression */
1557
        vert_regex_t *skt_reg, *pin_reg;
1558
 
1559
        /* find the '(' in the socket name  name */
1560
 
1561
        p = strchr (s, '(');
1562
        q = strrchr (s, ')');
1563
        if (p == s)
1564
        {
1565
                s = ".*"; /* wildcard for chip id */
1566
        }
1567
        if (!p || !q || q < p)
1568
        {
1569
                p = ".*"; /* wilcard for pin id */
1570
        }
1571
        else
1572
        {
1573
                *p++ = 0;
1574
                *q = 0;
1575
        }
1576
 
1577
        rc = vert_regcomp (&skt_reg, s);
1578
 
1579
        if (rc != 0)
1580
        {
1581
                char errbuff[100];
1582
                regerror (rc, skt_reg->preg, errbuff, 100);
1583
                Log (
1584
                    LOG_ERROR,
1585
                    "-- Problem (rc=%d) %s with '%s' as regular expression\n",
1586
                    rc,
1587
                    errbuff,
1588
                    s);
1589
 
1590
                /*    return TCL_ERROR;
1591
                 */
1592
                return;
1593
        }
1594
        else
1595
        {
1596
                Log (LOG_GENERAL, "-- Using '%s' as socket match pattern\n", s);
1597
        }
1598
 
1599
        rc = vert_regcomp (&pin_reg, p);
1600
 
1601
        if (rc != 0)
1602
        {
1603
                char errbuff[100];
1604
                regerror (rc, pin_reg->preg, errbuff, 100);
1605
                Log (
1606
                    LOG_ERROR,
1607
                    "-- Problem (rc=%d) %s with '%s' as regular expression\n",
1608
                    rc,
1609
                    errbuff,
1610
                    p);
1611
 
1612
                /*    return TCL_ERROR;
1613
                 */
1614
                return;
1615
        }
1616
        else
1617
        {
1618
                Log (LOG_GENERAL, "-- Using '%s' as socket match pattern\n", p);
1619
        }
1620
 
1621
        socket = socket_head;
1622
        while (socket)
1623
        {
1624
                found_socket =
1625
                    regexec (skt_reg->preg, socket->identifier, 0, skt_reg->regpatt, 0);
1626
                if (!found_socket)
1627
                {
1628
                        socket_cnt++;
1629
                        node = socket->nodes;
1630
                        /*
1631
                              Log(LOG_GENERAL,"-- Chip ID %s\n",socket->identifier);
1632
                        */
1633
                        found_pin = 0;
1634
                        while (node)
1635
                        {
1636
                                found_pin = regexec (
1637
                                    pin_reg->preg, node->identifier, 0, pin_reg->regpatt, 0);
1638
 
1639
                                if (!found_pin)
1640
                                {
1641
                                        /*
1642
                                                  Log(LOG_GENERAL,"-- Pin
1643
                                           %s.%s\n",socket->identifier,node->identifier);
1644
                                        */
1645
                                        pin_cnt++;
1646
                                        node->pin_group = flag;
1647
                                }
1648
                                node = node->sktnext;
1649
                        }
1650
                }
1651
                socket = socket->next;
1652
        }
1653
        if (socket_cnt)
1654
                Log (LOG_GENERAL, "-- Checked %d sockets\n", socket_cnt);
1655
        if (pin_cnt)
1656
                Log (
1657
                    LOG_GENERAL,
1658
                    "-- Set pin group to %d on a total of %d pins\n",
1659
                    flag,
1660
                    pin_cnt);
1661
        else
1662
                Log (LOG_GENERAL, "-- Did not locate any pins matching pattern\n");
1663
 
1664
        vert_regfree (&pin_reg);
1665
        vert_regfree (&skt_reg);
1666
}