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/jumpering.c,v 1.1.1.1 2003/11/04 23:34:57 mjames
3
 * Exp $
4
 *
5
 * $Log: jumpering.c,v $
6
 * Revision 1.1.1.1  2003/11/04 23:34:57  mjames
7
 * Imported into local repositrory
8
 *
9
 * Revision 1.10  2003/01/02 21:37:15  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.9  2002/10/02 18:41:54  MJAMES
18
 * Removed diagnostic printout
19
 *
20
 * Revision 1.8  2002/09/27 22:37:25  MJAMES
21
 * Added definition of create_vhdl_connections
22
 *
23
 * Revision 1.7  2002/09/09 10:13:32  mjames
24
 * Moved pin remapping function to pin ident editing function from
25
 * sorting pin name routine.
26
 *
27
 * Revision 1.6  2002/01/15 12:35:58  mjames
28
 * DLL declarations put in,
29
 *
30
 * #ident used
31
 *
32
 * Revision 1.5  2001/11/19 10:41:51  mjames
33
 * Merged back DTC release
34
 *
35
 * Revision 1.4.2.2  2001/11/15 21:06:43  mjames
36
 * Promoted a jumper deletion message to an error status.
37
 *
38
 * Revision 1.4.2.1  2001/11/15 21:01:21  mjames
39
 * Tidying up unused variables
40
 *
41
 * Revision 1.4  2001/10/31 22:20:07  mjames
42
 * Tidying up problematical comments caused by CVS
43
 * 'intelligent' comment guessing
44
 *
45
 * Revision 1.3  2001/06/19 05:23:59  mjames
46
 * Moved some code dealing with finding nets with external connections
47
 * to ext_nets.c
48
 *
49
 * Revision 1.2  2001/06/06 12:10:21  mjames
50
 * Move from HPUX
51
 *
52
 * Revision 1.1.1.1  2000/10/19 21:58:38  mjames
53
 * Mike put it here
54
 *
55
 * Revision 1.32  2000/10/04  10:37:06  10:37:06  mjames (Mike James)
56
 * Modified for Vertical2 : support COMPONENTS and SIGNALS
57
 *
58
 * Revision 1.32  2000/10/04  10:37:06  10:37:06  mjames (Mike James)
59
 * Part of Release PSAVAT01
60
 *
61
 * Revision 1.31  2000/10/02  11:04:15  11:04:15  mjames (Mike James)
62
 * new_vhdl
63
 *
64
 * Revision 1.30  2000/09/27  14:42:16  14:42:16  mjames (Mike James)
65
 * Part of Release Sep_27_ST_2000
66
 *
67
 * Revision 1.29  2000/09/21  10:15:46  10:15:46  mjames (Mike James)
68
 * Part of Release Sep21Alpha
69
 *
70
 * Revision 1.28  2000/09/21  09:46:54  09:46:54  mjames (Mike James)
71
 * Added code to deal with pin equivalents
72
 *
73
 * Revision 1.27  2000/08/25  09:57:12  09:57:12  mjames (Mike James)
74
 * Part of Release Aug25_alpha
75
 *
76
 * Revision 1.26  2000/08/16  08:57:28  08:57:28  mjames (Mike James)
77
 * Part of Release CD01_Aug2000
78
 *
79
 * Revision 1.25  2000/08/14  14:45:10  14:45:10  mjames (Mike James)
80
 * Part of Release Aug_14_2000
81
 *
82
 * Revision 1.24  2000/08/14  14:42:53  14:42:53  mjames (Mike James)
83
 * Changed checks for hierarchical jumpers
84
 *
85
 * Revision 1.23  2000/08/11  08:30:30  08:30:30  mjames (Mike James)
86
 * Part of Release Aug_11_2000
87
 *
88
 * Revision 1.22  2000/08/09  10:31:44  10:31:44  mjames (Mike James)
89
 * Part of Release Aug__9_2000
90
 *
91
 * Revision 1.21  2000/05/31  11:42:53  11:42:53  mjames (Mike James)
92
 * Part of Release May_31_2000
93
 *
94
 * Revision 1.20  2000/05/08  17:01:35  17:01:35  mjames (Mike James)
95
 * Part of Release May__8_2000
96
 *
97
 * Revision 1.19  2000/05/08  16:59:29  16:59:29  mjames (Mike James)
98
 * Part of Release May__8_2000
99
 *
100
 * Revision 1.18  2000/05/08  16:57:05  16:57:05  mjames (Mike James)
101
 * Part of Release May__8_2000
102
 *
103
 * Revision 1.17  2000/03/08  16:19:09  16:19:09  mjames (Mike James)
104
 * New version including PC
105
 *
106
 * Revision 1.14  2000/01/20  15:58:45  15:58:45  mjames (Mike James)
107
 * Part of Release R22
108
 *
109
 * Revision 1.13  99/12/22  11:15:25  11:15:25  mjames (Mike James)
110
 * Part of Release Dec_22_1999
111
 *
112
 * Revision 1.12  99/06/25  14:35:36  14:35:36  mjames (Mike James)
113
 * Added in reference to expression.h, but no changes made
114
 * to the function of acfread yet.
115
 *
116
 * Revision 1.11  99/05/04  09:51:47  09:51:47  mjames (Mike James)
117
 * General checkin
118
 * ls
119
 *
120
 * Revision 1.9  98/11/30  13:48:12  13:48:12  mjames (Mike James)
121
 * Corrected a create-jumper-with-no-nodes = core dump
122
 * problem
123
 *
124
 * Revision 1.8  98/11/27  15:15:08  15:15:08  mjames (Mike James)
125
 * Amended algorithm to work with newer database
126
 * format
127
 *
128
 * Revision 1.7  98/11/25  12:46:54  12:46:54  mjames (Mike James)
129
 * Checked in with some errors to do with not creating a jumper name !!
130
 *
131
 * Revision 1.6  98/11/16  13:18:30  13:18:30  mjames (Mike James)
132
 *
133
 * Revision 1.5  98/03/16  11:32:31  11:32:31  mjames (Mike James)
134
 * Attempting to correct the jumpering of already jumpered jumper lists.
135
 *
136
 * Revision 1.4  98/02/11  11:26:28  11:26:28  mjames (Mike James)
137
 * Checked in for version 6.2a
138
 *
139
 * Revision 1.3  97/04/23  08:42:54  08:42:54  mjames (Mike James)
140
 * CHecked in for release rel23041997
141
 *
142
 * Revision 1.2  96/12/13  08:43:23  08:43:23  mjames (Mike James)
143
 * Update to v5.1, added Write ID , exact routing
144
 *
145
 * Revision 1.1  96/08/06  13:39:40  13:39:40  mjames (Mike James)
146
 * Initial revision
147
 *
148
 *  */
149
 
150
#include "jumpering.h"
151
 
152
#include "cmdlog.h"
153
#include "cmdparse.h"
154
#include "database.h"
155
#include "expression.h"
156
#include "generic.h"
157
#include "routing.h"
158
#include "vertcl_main.h"
159
 
160
#include <ctype.h>
161
#include <stdio.h>
162
#include <stdlib.h>
163
#include <string.h>
164
 
165
#ident                                                                                        \
166
    "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/jumpering.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $"
167
 
168
/* resolve not routable H or L */
169
HowRouted_t routing_resolve (HowRouted_t curr, HowRouted_t next)
170
{
171
        /* the H property can be destroyed if it meets L or plain not_routable */
172
        if (curr == Not_Routable_H)
173
        {
174
                if (next == Not_Routable || next == Not_Routable_L)
175
                        return Not_Routable;
176
        }
177
        if (curr == Not_Routable_L)
178
        {
179
                if (next == Not_Routable || next == Not_Routable_H)
180
                        return Not_Routable;
181
        }
182
        return next;
183
}
184
 
185
/* takes a net and removes it from the list of nets directly searchable
186
   by routing algorithms, copying all its node references to the new net,
187
   This is used in creating jumpers  */
188
__declspec(dllexport) int transfer_net_to_subnet (net_t **list, net_t *topnet, net_t *subnet)
189
{
190
        net_t *prev_net;
191
        net_t *next_net;
192
        char *subnet_orig_ident;
193
        HowRouted_t subnet_how_routed;
194
        int hierarchy;
195
        hierarchy = 0;
196
 
197
        /* algorithms check to see if there is a hierarchy of jumpers.
198
           if there is then check to see if the jumper is basically a connection
199
           to itself. If it is give up. */
200
 
201
        subnet_how_routed = subnet->how_routed;
202
        subnet_orig_ident = subnet->identifier;
203
 
204
        /*      Log(LOG_GENERAL,"# JUMPER: Net '%s' jumpered to '%s'\n",
205
                            topnet->identifier,subnet->identifier);
206
        */
207
        if (subnet->join_parent)
208
        {
209
                hierarchy = 1;
210
                while (subnet->join_parent)
211
                {
212
                        /*      Log(LOG_GENERAL,"# Info : Net '%s' is already jumpered to '%s':
213
                           trying parent jumper\n",
214
                                            subnet->identifier,subnet->join_parent->identifier);
215
                        */
216
                        subnet = subnet->join_parent;
217
                }
218
        }
219
 
220
        if (topnet == subnet)
221
        {
222
                Log (
223
                    LOG_ERROR,
224
                    "# Error : - Cant join a net to itself !!! %s to %s : Suppressing "
225
                    "Jumper\n",
226
                    subnet_orig_ident,
227
                    topnet->identifier);
228
                return 0;
229
        }
230
        else if (hierarchy)
231
        {
232
                Log (
233
                    LOG_GENERAL,
234
                    "# -- Info : Net '%s' will be jumpered via '%s' to '%s' \n",
235
                    subnet_orig_ident,
236
                    subnet->identifier,
237
                    topnet->identifier);
238
        }
239
        prev_net = subnet->prev;
240
        next_net = subnet->next;
241
 
242
        /* Remove subnet from directly searchable list */
243
 
244
        /* if at head of list, correct list and point back at NULL */
245
        if (subnet == *list)
246
        {
247
                *list = next_net;
248
                if (next_net)
249
                        next_net->prev = NULL;
250
        }
251
        else if (next_net)
252
                next_net->prev = subnet->prev;
253
        if (prev_net)
254
                prev_net->next = subnet->next;
255
 
256
        /* attach net to topnet's subnet list */
257
        /*  printf("before: topnet->subnets = %p\n",topnet->subnets); */
258
        /*  printf("before: subnet          = %p\n",subnet); */
259
 
260
        subnet->prev = NULL;
261
        subnet->next = NULL;
262
        subnet->joined_nets = topnet->subnets; /* The subnets are linked horizontally via
263
                                        the 'joined_nets' rather than subnet pointer now */
264
 
265
        subnet->join_parent = topnet; /* The subnet is joined to the parent */
266
        topnet->join_parent = NULL;   /* this net does not have a parent */
267
        topnet->subnets = subnet;
268
 
269
        /* propagate up properties */
270
 
271
        if (subnet->has_fix_location)
272
                topnet->has_fix_location = 1;
273
 
274
        if (IS_NOT_ROUTABLE (subnet_how_routed))
275
        {
276
                Log (
277
                    LOG_ERROR,
278
                    "# Warning - Jumpering  '%s' and  '%s' will be NON ROUTABLE\n",
279
                    subnet->identifier,
280
                    topnet->identifier);
281
        }
282
        topnet->how_routed = routing_resolve (topnet->how_routed, subnet_how_routed);
283
 
284
        /*  subnet->name    = topnet->name;*/
285
 
286
        /*  printf("after:  topnet->subnets = %p\n",topnet->subnets); */
287
        /*  printf("after:  subnet->next    = %p\n",subnet->next); */
288
 
289
        /* now copy the noderef list from subnet to topnet */
290
        {
291
                noderef_t *newref;
292
                noderef_t *oldref = subnet->nodes;
293
                while (oldref)
294
                {
295
                        /* create a new node reference */
296
                        newref = calloc (1, sizeof (noderef_t));
297
 
298
                        newref->base_noderef = oldref->base_noderef; /* point down to the
299
                                                          original node reference */
300
 
301
                        /* copy information : probably is not needed */
302
                        /* SNIP from here ? ************************************** */
303
                        newref->pindir = oldref->pindir;
304
                        /*      newref->datatype   = oldref->datatype; */
305
                        /*      get_vhdl_buswidth(newref);*/ /* sort out the VHDL bus
306
                                                                declaration */
307
                        newref->vhdltype = copy_vhdl (oldref->vhdltype, NULL);
308
 
309
                        newref->node = oldref->node;
310
                        /* added as forgotten 05/11/1998 */
311
                        newref->orig_name = allocstr (oldref->orig_name);
312
                        newref->orig_vhdltype = copy_vhdl (oldref->orig_vhdltype, NULL);
313
                        /* end edit */
314
 
315
                        /* SNIP to here ? ************************************** */
316
                        /* new node refers to information on the top net if joined,
317
                           otherwise it is the sub net if aliased */
318
                        if (topnet->how_joined == Jumpered)
319
                        {
320
                                newref->net = topnet;
321
                                newref->node->routed_net =
322
                                    topnet; /* change routed net reference to
323
                                               point at jumper net rather than originals */
324
                        }
325
                        else
326
                                newref->net = subnet;
327
 
328
                        /* attach it to the net */
329
                        newref->next = topnet->nodes;
330
                        topnet->nodes = newref;
331
 
332
                        /* count nodes */
333
                        topnet->nodecount++;
334
 
335
                        oldref = oldref->next;
336
                }
337
        }
338
        return 1; /* success on a plate */
339
}
340
 
341
/****************************************************************************/
342
/* this procedure takes a jumper apart as a result of failure */
343
/* it takes the subnets and links them back into the main routed net list,
344
   removes the top net that was the jumper */
345
__declspec(dllexport) int disconnect_jumper (net_t **list, net_t *jumper)
346
 
347
{
348
        net_t *first_member = jumper->subnets;
349
        net_t *current_member;
350
        net_t *previous_member = jumper;
351
        net_t *next_list = jumper->next;
352
        /* at this point we have
353
 
354
        previous net<-->jumper<-->next net
355
                           |
356
                          sub1-->sub2-->sub3...
357
 
358
 
359
        */
360
        current_member = first_member;
361
 
362
        if (first_member)
363
        {
364
                while (current_member)
365
                {
366
                        current_member->next =
367
                            current_member->joined_nets; /* copy next pointer from join list*/
368
                        current_member->prev = previous_member;
369
                        current_member->joined_nets = NULL;
370
                        current_member->join_parent = NULL; /* no longer part of a jumper */
371
 
372
                        previous_member->next = current_member;
373
                        previous_member = current_member;
374
                        Log (
375
                            LOG_ERROR,
376
                            "--   disconnecting '%s'\n",
377
                            current_member->identifier);
378
                        current_member = current_member->next;
379
                };
380
                previous_member->next = next_list;
381
                if (previous_member->next)
382
                        previous_member->next->prev = previous_member;
383
        }
384
 
385
        /* converted to
386
        previous net<-->jumper<-->sub1<-->sub2<-->sub3<-->next net
387
        */
388
 
389
        Log (LOG_GENERAL, "-- From jumper '%s'\n\n", jumper->identifier);
390
        remove_net (list, jumper);
391
        return 1;
392
}
393
 
394
/* ******************************************** */
395
 
396
static net_t *
397
check_net (int *accept_nodes, net_t **best_net, net_t *routed_net, net_t *unrouted_net)
398
{
399
        if (routed_net->has_external && routed_net->nodecount >= *accept_nodes &&
400
            IS_ROUTABLE (routed_net->how_routed))
401
        {
402
                /* possibly enough nodes, but does it go the right places ?? */
403
                int visit_count = 0;
404
                noderef_t *unrouted_nodes = unrouted_net->nodes;
405
                noderef_t *routed_nodes = routed_net->nodes;
406
                clear_routing_flags (routed_nodes);
407
                /* search for as yet unused but needed nodes on the unrouted net */
408
                while (unrouted_nodes)
409
                {
410
                        if (unrouted_nodes->r_flag == 0 &&
411
                            search_net_for_socket (unrouted_nodes, routed_nodes, 0) != NULL)
412
                                visit_count++;
413
                        unrouted_nodes = unrouted_nodes->next;
414
                }
415
                if (visit_count > *accept_nodes)
416
                {
417
                        *accept_nodes = visit_count;
418
                        *best_net = routed_net;
419
                }
420
        }
421
        return *best_net;
422
}
423
 
424
/* ******************************************** */
425
/* This function tries to tidy up all nets that are currently
426
   still in the unrouted list because they are blocked
427
   The algorithm is to try and locate the routed net which visits
428
   the highest number of sockets referred to by the unrouted net
429
   and which has an external connection on it. Mark this, assign its
430
   nodes to a jumpered net. Remove nodes used from the unrouted
431
   net and search again.
432
   Repeat until either no jumper candidates are found or all
433
   nodes on the unrouted net are used up. */
434
 
435
__declspec(dllexport) void perform_routing_by_making_jumpers (char *Suffix)
436
{
437
        int jumper_count = 1;
438
        net_t *unrouted_net = unrouted_list;
439
        net_t *next_net;
440
        HowRouted_t route_type = Free;
441
 
442
        if (!Suffix)
443
                Suffix = "";
444
 
445
        /* firstly, set up the has_external flags on all of the nets, by checking to see if any
446
           nodes on any nets are connected to external sockets  */
447
 
448
        /* code moved to ext_nets.c
449
           while (routed_net)
450
            {
451
              noderef_t *noderefs = routed_net->nodes;
452
              routed_net->has_external = 0;
453
              while (noderefs)
454
                {
455
                  if (noderefs->node->socket->is_external)
456
                    routed_net->has_external = 1;
457
                  noderefs = noderefs->next;
458
                }
459
              routed_net = routed_net->next;
460
            }
461
        */
462
        /* tidy up */
463
 
464
        while (unrouted_net)
465
        { /* loop through all unrouted nets */
466
                int routed_ok = 1;
467
                int accept_nodes = 0;
468
                int nets_used = 0;
469
                int nodes_left = unrouted_net->nodecount;
470
                net_t *best_net;
471
                net_t *routed_net;
472
                noderef_t *unrouted_nodes;
473
 
474
                char jumper_name[JUMP_NAMLEN + 1];
475
                net_t *jumper_net = NULL;
476
 
477
                Log (
478
                    LOG_GENERAL,
479
                    "\n--Looking to create net '%s' which has %d nodes\n",
480
                    unrouted_net->identifier,
481
                    nodes_left);
482
                /* using the routing flags to indicate a net has sucessfully visited node .
483
                   Only clear the flags if there is actually a node list !! */
484
                if (unrouted_net->nodes)
485
                        clear_routing_flags (unrouted_net->nodes);
486
 
487
                /* iterate until a loop fails to do better, or we have jumpered all of the
488
                   nodes we need */
489
                while (routed_ok && nodes_left)
490
                {
491
                        net_t **list;
492
                        int pass;
493
                        best_net = NULL;
494
                        accept_nodes = 0;
495
                        for (pass = 0; pass < 1 && !best_net; pass++)
496
                        {
497
                                if (pass == 0)
498
                                        list = &routed_list;
499
                                else
500
                                        list = &named_list;
501
                                /* check for FIX_LOCATION pins as these are most important
502
                                   In this case, the best_net is one that can be connected to
503
                                   the FIX_LOCATION pin because it is not yet in use */
504
                                unrouted_nodes = unrouted_net->nodes;
505
                                /* scan through until we find an unrouted node that has no
506
                                 * routing flag set */
507
                                while (unrouted_nodes && !best_net)
508
                                {
509
                                        if (unrouted_nodes->r_flag == 0)
510
                                        {
511
                                                net_t *poss_routed_net =
512
                                                    unrouted_nodes->node->routed_net;
513
                                                if (poss_routed_net &&
514
                                                    poss_routed_net->list_ref == list)
515
                                                {
516
                                                        if (level & 2)
517
                                                        {
518
                                                                Log (
519
                                                                    LOG_GENERAL,
520
                                                                    "\n-- pass %d checking  "
521
                                                                    "net '%s'\n",
522
                                                                    pass,
523
                                                                    poss_routed_net
524
                                                                        ->identifier);
525
                                                        }
526
                                                        /* is routed net still available on the
527
                                                         * routed list ? */
528
                                                        /* &&
529
                                                         * poss_routed_net->has_fix_location)
530
                                                         */    /* only fix_location nets on pass 1, then all nets */
531
                                                        check_net (
532
                                                            &accept_nodes,
533
                                                            &best_net,
534
                                                            poss_routed_net, /* ???? was
535
                                                                                routed_net . no
536
                                                                                sense here !!
537
                                                                              */
538
                                                            unrouted_net);
539
                                                }
540
                                        }
541
                                        unrouted_nodes = unrouted_nodes->next;
542
                                }
543
                                if ((level & 2) && best_net)
544
                                {
545
                                        Log (
546
                                            LOG_GENERAL,
547
                                            "-- Phase 1 search Found as best match net '%s' "
548
                                            "with %d corresponding nodes\n",
549
                                            best_net->identifier,
550
                                            accept_nodes);
551
                                }
552
 
553
                                if (!best_net)
554
                                {
555
                                        /* check for any position to jumper if there are no
556
                                        FIX_LOCATION pins Now, search simply for any useful
557
                                        net, and try the one with the most sockets visited */
558
 
559
                                        routed_net = *list;
560
                                        accept_nodes = 0;
561
                                        while (routed_net)
562
                                        {
563
                                                if (level & 2)
564
                                                        Log (
565
                                                            LOG_GENERAL,
566
                                                            "\n-- pass %d generally checking  "
567
                                                            "net '%s'\n",
568
                                                            pass,
569
                                                            routed_net->identifier);
570
                                                check_net (
571
                                                    &accept_nodes,
572
                                                    &best_net,
573
                                                    routed_net,
574
                                                    unrouted_net);
575
 
576
                                                routed_net = routed_net->next;
577
                                        }
578
                                        if ((level & 2) && best_net)
579
                                                Log (
580
                                                    LOG_GENERAL,
581
                                                    "-- Phase 2 search Found as best match "
582
                                                    "net '%s' with %d corresponding nodes\n",
583
                                                    best_net->identifier,
584
                                                    accept_nodes);
585
                                }
586
                        }
587
 
588
                        if (best_net)
589
                        {
590
                                Log (
591
                                    LOG_GENERAL,
592
                                    "-- Found as best match net '%s' with %d corresponding "
593
                                    "nodes\n",
594
                                    best_net->identifier,
595
                                    accept_nodes);
596
                                nodes_left -=
597
                                    accept_nodes; /* Count down how many nodes left to go */
598
 
599
                                {
600
                                        noderef_t *unrouted_nodes = unrouted_net->nodes;
601
                                        clear_routing_flags (best_net->nodes);
602
                                        while (unrouted_nodes)
603
                                        {
604
                                                if (search_net_for_socket (
605
                                                        unrouted_nodes, best_net->nodes, 0) !=
606
                                                    NULL)
607
                                                {
608
                                                        unrouted_nodes->r_flag = 1;
609
                                                }
610
 
611
                                                /* when all flags on unrouted nets go to '1'
612
                                                   then we have finished the jumpering */
613
                                                if (level & 2)
614
                                                        Log (
615
                                                            LOG_GENERAL,
616
                                                            "--  flag on %s(%s) is %d\n",
617
                                                            unrouted_nodes->node->socket
618
                                                                ->identifier,
619
                                                            unrouted_nodes->node->identifier,
620
                                                            unrouted_nodes->r_flag);
621
                                                unrouted_nodes = unrouted_nodes->next;
622
                                        }
623
                                }
624
 
625
                                if (nets_used++ == 0 && nodes_left == 0)
626
                                {
627
                                        /* we seem to have found a complete path already with
628
                                           all the nodes on it. the user is obviously using
629
                                           'jumper' before 'route' */
630
                                        if (level & 2)
631
                                                Log (
632
                                                    LOG_GENERAL,
633
                                                    "-- This net contains all nodes "
634
                                                    "requested, simply connecting\n\n");
635
                                        jumper_net = best_net;
636
                                        route_type = By_Net;
637
                                }
638
                                else
639
                                {
640
                                        route_type = By_Jumpering;
641
                                        /* try hard to create a unique jumper ID */
642
                                        while (!jumper_net)
643
                                        {
644
                                                sprintf (
645
                                                    jumper_name,
646
                                                    JUMP_FMT,
647
                                                    Suffix,
648
                                                    jumper_count++);
649
                                                jumper_net = find_net (
650
                                                    &routed_list, Ident, jumper_name, Search);
651
                                                /* if it is not found then the name proposed is
652
                                                 * unique */
653
                                                if (!jumper_net)
654
                                                {
655
                                                        jumper_net = find_net (
656
                                                            &routed_list,
657
                                                            Ident,
658
                                                            jumper_name,
659
                                                            Create);
660
                                                        /*
661
                                                                                  Log
662
                                                           (LOG_GENERAL, "-- Creating jumper
663
                                                           %s\n", jumper_net->identifier);
664
                                                        */
665
                                                        jumper_net->how_joined = Jumpered;
666
                                                        break;
667
                                                }
668
                                                else
669
                                                        jumper_net =
670
                                                            NULL; /* if found already, it
671
                                                                     should not terminate the
672
                                                                     loop */
673
                                        }
674
                                        Log (
675
                                            LOG_GENERAL,
676
                                            "-- Jumpering %s to net %s (nodes_left=%d)\n",
677
                                            jumper_net->identifier,
678
                                            best_net->identifier,
679
                                            nodes_left);
680
                                        /* mark the used nodes by setting the r_flag on the
681
                                         * used unrouted nodes */
682
 
683
                                        /* find the first node that is connected to an external
684
                                         * pin on the best_net */
685
                                        /* record this as the external node */
686
 
687
                                        {
688
                                                noderef_t *routed_nodes = best_net->nodes;
689
                                                while (routed_nodes)
690
                                                {
691
                                                        if (routed_nodes->node->socket
692
                                                                ->is_external)
693
                                                        {
694
                                                                best_net->external_node =
695
                                                                    routed_nodes->node;
696
                                                                break;
697
                                                        }
698
                                                        routed_nodes = routed_nodes->next;
699
                                                }
700
                                        }
701
 
702
                                        /* make the jumper */
703
                                        transfer_net_to_subnet (
704
                                            &routed_list, jumper_net, best_net);
705
                                        routed_ok = 1;
706
                                }
707
                        }
708
                        else
709
                        {
710
                                routed_ok = 0;
711
                                Log (
712
                                    LOG_ERROR,
713
                                    "-- Error : insufficient/no jumperable nets free\n"
714
                                    "--   to create net '%s' which requires %d more nodes\n",
715
                                    unrouted_net->identifier,
716
                                    nodes_left);
717
                        }
718
                }
719
                next_net = unrouted_net->next;
720
 
721
                if (routed_ok)
722
                {
723
                        combine_routed_and_unrouted (jumper_net, unrouted_net);
724
                        transfer_net_to_named (&routed_list, jumper_net); /* jumpers are in
725
                                                                             routed list */
726
                        jumper_net->how_routed = route_type;
727
                        next_net = remove_net (&unrouted_list, unrouted_net);
728
                }
729
                else
730
                {
731
                        /* Failure to complete, so remove the partially completed jumper net
732
                         * from the list */
733
                        if (jumper_net)
734
                        {
735
                                Log (
736
                                    LOG_ERROR,
737
                                    "-- failure : disconnecting partially completed jumper\n");
738
                                disconnect_jumper (&routed_list, jumper_net);
739
                        }
740
                }
741
 
742
                unrouted_net = next_net;
743
        }
744
        count_nets ("After using new paths created by jumpers");
745
}
746
 
747
/* ******************************************** */
748
__declspec(dllexport) void perform_jumpering (char *Suffix)
749
{
750
        count_nets ("Before jumper creation");
751
        /* remove any connections we can already make */
752
        /*  perform_routing_by_exact_path (); */
753
 
754
        /* make the jumpers */
755
        perform_routing_by_making_jumpers (Suffix);
756
 
757
        /* then use the jumpers */
758
        /*  perform_routing_by_exact_path ();*/
759
 
760
        /* then use the jumpers */
761
        /*  perform_routing_by_path (); */
762
}
763
/* ******************************************** */
764
 
765
/* try to join all the pins seen on ID1 to ID2 */
766
__declspec(dllexport) void create_all_jumpers (char *ID1, char *ID2)
767
{
768
        socket_t *ID1_skt, *ID2_skt;
769
        node_t *ID1_node, *ID2_node;
770
        net_t *jumper_net, *ID1_net, *ID2_net;
771
        char rootname[MAXIDLEN];
772
        char *append_point;
773
        ID1_skt = find_socket (Ident, ID1, Search, &socket_head);
774
        ID2_skt = find_socket (Ident, ID2, Search, &socket_head);
775
        if (!ID1_skt)
776
        {
777
                Log (LOG_ERROR, "# ERROR : CONNECTION cannot find socket '%s'\n", ID1);
778
                return;
779
        }
780
        if (!ID2_skt)
781
        {
782
                Log (LOG_ERROR, "# ERROR : CONNECTION cannot find socket '%s'\n", ID2);
783
                return;
784
        }
785
 
786
        sprintf (rootname, "cn_%s_%s_", ID1_skt->identifier, ID2_skt->identifier);
787
        Log (LOG_GENERAL, "-- Creating CONNECTION  '%s'\n", rootname);
788
 
789
        append_point = rootname + strlen (rootname); /* where to append the final pin ID */
790
        /* for each node on the first chip, try and find the net that it is on in
791
          the routed list, and jumper it to the net that is on the same pin ID on the second
792
          chip. */
793
 
794
        ID1_node = ID1_skt->nodes;
795
        while (ID1_node)
796
        {
797
                if (ID1_node->net && ID1_node->net->list_ref == &routed_list)
798
                {
799
                        /* find the highest level of jumper and join it */
800
                        ID1_net = ID1_node->net;
801
                        while (ID1_net->join_parent)
802
                                ID1_net = ID1_net->join_parent;
803
 
804
                        ID2_node = find_node (ID2_skt, Ident, ID1_node->identifier, Search);
805
                        if (ID2_node)
806
                        {
807
                                if (ID2_node->net && ID2_node->net->list_ref == &routed_list)
808
                                {
809
                                        /* find the highest level of jumper and join it */
810
                                        ID2_net = ID2_node->net;
811
                                        while (ID2_net->join_parent)
812
                                                ID2_net = ID2_net->join_parent;
813
 
814
                                        /* we now have a matched pair of nodes for which we
815
                                        have to find the nets.
816
                                        If the nets are both on the list of routed net, create
817
                                        a named jumper between them */
818
 
819
                                        strcpy (
820
                                            append_point,
821
                                            ID1_node->identifier); /* create the totla new net
822
                                                                      name */
823
                                                                   /*
824
                                                                             printf("Can make jumper '%s'\n",rootname);
825
                                                                   */
826
 
827
                                        jumper_net =
828
                                            find_net (&routed_list, Ident, rootname, Create);
829
                                        jumper_net->how_joined = Jumpered;
830
                                        if (transfer_net_to_subnet (
831
                                                &routed_list, jumper_net, ID1_net))
832
                                                ID1_node->net->external_node = ID1_node;
833
                                        if (transfer_net_to_subnet (
834
                                                &routed_list, jumper_net, ID2_net))
835
                                                ID2_node->net->external_node = ID2_node;
836
                                }
837
                                else
838
                                        Log (
839
                                            LOG_ERROR,
840
                                            "-- Warning : Node '%s(%s)' does not appear on a "
841
                                            "routed net\n",
842
                                            ID2_skt->identifier,
843
                                            ID2_node->identifier);
844
                        }
845
                        else
846
                                Log (
847
                                    LOG_ERROR,
848
                                    "-- Warning : Cannot locate pin '%s' on socket '%s'\n",
849
                                    ID1_node->identifier,
850
                                    ID2_skt->identifier);
851
                }
852
                else
853
                        Log (
854
                            LOG_ERROR,
855
                            "-- Warning : Node '%s(%s)' does not appear on a routed net\n",
856
                            ID1_skt->identifier,
857
                            ID1_node->identifier);
858
                ID1_node = ID1_node->sktnext; /* move along the socket pins */
859
        }
860
}
861
 
862
/*******************************************************/
863
 
864
void create_vhdl_connections (void)
865
{
866
        net_t *top_net;
867
        net_t *subnet;
868
        /* assume that create_unrouted_list has already happened */
869
        top_net = unrouted_list;
870
        while (top_net)
871
        {
872
                if (top_net->vhdl_connect_net)
873
                {
874
                        printf ("root net found '%s'\n", top_net->name);
875
                        if (top_net->how_joined != NotJoined)
876
                        {
877
                                Log (
878
                                    LOG_ERROR,
879
                                    "# Warning : %s net '%s' already exists, net is being "
880
                                    "extended from %d nodes\n",
881
                                    top_net->how_joined == Jumpered ? "Jumpered" : "Aliased",
882
                                    top_net->identifier,
883
                                    top_net->nodecount);
884
                                /* if the net is already in existence, it will have nodes */
885
                        }
886
                        top_net->how_joined = Jumpered;
887
                        transfer_net_to_subnet (
888
                            &unrouted_list, top_net, top_net->vhdl_connect_net);
889
                }
890
                top_net = top_net->next;
891
        }
892
}