Subversion Repositories Vertical

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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