Subversion Repositories Vertical

Rev

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

  1. /*
  2.  * $Header: c:\\cygwin\\cvsroot/Vert03/vertlib/jumpering.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $
  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
  56.  *
  57.  * Revision 1.32  2000/10/04  10:37:06  10:37:06  mjames (Mike James)
  58.  * Part of Release PSAVAT01
  59.  *
  60.  * Revision 1.31  2000/10/02  11:04:15  11:04:15  mjames (Mike James)
  61.  * new_vhdl
  62.  *
  63.  * Revision 1.30  2000/09/27  14:42:16  14:42:16  mjames (Mike James)
  64.  * Part of Release Sep_27_ST_2000
  65.  *
  66.  * Revision 1.29  2000/09/21  10:15:46  10:15:46  mjames (Mike James)
  67.  * Part of Release Sep21Alpha
  68.  *
  69.  * Revision 1.28  2000/09/21  09:46:54  09:46:54  mjames (Mike James)
  70.  * Added code to deal with pin equivalents
  71.  *
  72.  * Revision 1.27  2000/08/25  09:57:12  09:57:12  mjames (Mike James)
  73.  * Part of Release Aug25_alpha
  74.  *
  75.  * Revision 1.26  2000/08/16  08:57:28  08:57:28  mjames (Mike James)
  76.  * Part of Release CD01_Aug2000
  77.  *
  78.  * Revision 1.25  2000/08/14  14:45:10  14:45:10  mjames (Mike James)
  79.  * Part of Release Aug_14_2000
  80.  *
  81.  * Revision 1.24  2000/08/14  14:42:53  14:42:53  mjames (Mike James)
  82.  * Changed checks for hierarchical jumpers
  83.  *
  84.  * Revision 1.23  2000/08/11  08:30:30  08:30:30  mjames (Mike James)
  85.  * Part of Release Aug_11_2000
  86.  *
  87.  * Revision 1.22  2000/08/09  10:31:44  10:31:44  mjames (Mike James)
  88.  * Part of Release Aug__9_2000
  89.  *
  90.  * Revision 1.21  2000/05/31  11:42:53  11:42:53  mjames (Mike James)
  91.  * Part of Release May_31_2000
  92.  *
  93.  * Revision 1.20  2000/05/08  17:01:35  17:01:35  mjames (Mike James)
  94.  * Part of Release May__8_2000
  95.  *
  96.  * Revision 1.19  2000/05/08  16:59:29  16:59:29  mjames (Mike James)
  97.  * Part of Release May__8_2000
  98.  *
  99.  * Revision 1.18  2000/05/08  16:57:05  16:57:05  mjames (Mike James)
  100.  * Part of Release May__8_2000
  101.  *
  102.  * Revision 1.17  2000/03/08  16:19:09  16:19:09  mjames (Mike James)
  103.  * New version including PC
  104.  *
  105.  * Revision 1.14  2000/01/20  15:58:45  15:58:45  mjames (Mike James)
  106.  * Part of Release R22
  107.  *
  108.  * Revision 1.13  99/12/22  11:15:25  11:15:25  mjames (Mike James)
  109.  * Part of Release Dec_22_1999
  110.  *
  111.  * Revision 1.12  99/06/25  14:35:36  14:35:36  mjames (Mike James)
  112.  * Added in reference to expression.h, but no changes made
  113.  * to the function of acfread yet.
  114.  *
  115.  * Revision 1.11  99/05/04  09:51:47  09:51:47  mjames (Mike James)
  116.  * General checkin
  117.  * ls
  118.  *
  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
  122.  *
  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
  126.  *
  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 !!
  129.  *
  130.  * Revision 1.6  98/11/16  13:18:30  13:18:30  mjames (Mike James)
  131.  *
  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.
  134.  *
  135.  * Revision 1.4  98/02/11  11:26:28  11:26:28  mjames (Mike James)
  136.  * Checked in for version 6.2a
  137.  *
  138.  * Revision 1.3  97/04/23  08:42:54  08:42:54  mjames (Mike James)
  139.  * CHecked in for release rel23041997
  140.  *
  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
  143.  *
  144.  * Revision 1.1  96/08/06  13:39:40  13:39:40  mjames (Mike James)
  145.  * Initial revision
  146.  *
  147.  *  */
  148.  
  149. #include <stdio.h>
  150. #include <string.h>
  151. #include <stdlib.h>
  152. #include <ctype.h>
  153.  
  154. #include "vertcl_main.h"
  155. #include "expression.h"
  156. #include "generic.h"
  157. #include "database.h"
  158. #include "routing.h"
  159. #include "jumpering.h"
  160. #include "cmdparse.h"
  161. #include "cmdlog.h"
  162.  
  163. #ident "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/jumpering.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $"
  164.  
  165. /* resolve not routable H or L */
  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.   }
  181.  
  182.  
  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  */
  186. __declspec (dllexport) int  transfer_net_to_subnet(net_t ** list,net_t * topnet, net_t * subnet)
  187. {
  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;  
  194.  
  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. */
  198.  
  199.  
  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;
  230.  
  231.  
  232.  
  233. /* Remove subnet from directly searchable list */
  234.  
  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;
  246.  
  247.  /* attach net to topnet's subnet list */
  248.  /*  printf("before: topnet->subnets = %p\n",topnet->subnets); */
  249.  /*  printf("before: subnet          = %p\n",subnet); */
  250.  
  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 */
  255.  
  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;
  259.  
  260. /* propagate up properties */
  261.  
  262.   if (subnet->has_fix_location)
  263.     topnet->has_fix_location = 1;
  264.  
  265.  
  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);
  270.  
  271.     }
  272.   topnet->how_routed = routing_resolve(topnet->how_routed,subnet_how_routed);
  273.  
  274.  
  275.  
  276. /*  subnet->name    = topnet->name;*/
  277.  
  278.  
  279.  
  280.  /*  printf("after:  topnet->subnets = %p\n",topnet->subnets); */
  281.  /*  printf("after:  subnet->next    = %p\n",subnet->next); */
  282.  
  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 */
  317.         }
  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.  
  335. }
  336.  
  337. /****************************************************************************/
  338. /* this procedure takes a jumper apart as a result of failure */
  339. /* it takes the subnets and links them back into the main routed net list,
  340.    removes the top net that was the jumper */
  341. __declspec (dllexport) int disconnect_jumper(net_t ** list,
  342.                                    net_t * jumper)
  343.                                    
  344. {
  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
  350.  
  351. previous net<-->jumper<-->next net
  352.                    |      
  353.                   sub1-->sub2-->sub3...
  354.  
  355. */  
  356.   current_member = first_member;
  357.  
  358.   if(first_member) {
  359.    
  360.     while(current_member) {
  361.  
  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 */
  366.  
  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.  
  378.  
  379.  
  380. /* converted to
  381. previous net<-->jumper<-->sub1<-->sub2<-->sub3<-->next net
  382. */                    
  383.  
  384.  
  385.   Log(LOG_GENERAL,"-- From jumper '%s'\n\n",jumper->identifier);
  386.   remove_net(list,jumper);
  387.   return 1;
  388.   }
  389.  
  390.  
  391. /* ******************************************** */
  392.  
  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;
  423. }
  424.  
  425.  
  426.  
  427.  
  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.  
  439.  
  440. __declspec (dllexport) void
  441. perform_routing_by_making_jumpers (char *Suffix)
  442. {
  443.   int jumper_count = 1;
  444.   net_t *unrouted_net = unrouted_list;
  445.   net_t *next_net;
  446.   HowRouted_t  route_type = Free;
  447.  
  448.   if (!Suffix)
  449.     Suffix = "";
  450.  
  451.  
  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  */
  454.  
  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 */
  470.  
  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;
  480.  
  481.  
  482.       char jumper_name[JUMP_NAMLEN + 1];
  483.       net_t *jumper_net = NULL;
  484.  
  485.  
  486.  
  487.  
  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);
  494.  
  495.  
  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 */
  543.  
  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 */
  568.  
  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.                           }
  578.  
  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.                   }
  587.  
  588.       if (nets_used++ == 0 && nodes_left == 0)  {
  589.  
  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;
  640.                 }
  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");
  669.  
  670.  
  671. }
  672.  
  673.  
  674. /* ******************************************** */
  675. __declspec (dllexport) void
  676. perform_jumpering (char *Suffix)
  677. {
  678.  
  679.   count_nets ("Before jumper creation");
  680. /* remove any connections we can already make */
  681. /*  perform_routing_by_exact_path (); */
  682.  
  683. /* make the jumpers */
  684.   perform_routing_by_making_jumpers (Suffix);
  685.  
  686. /* then use the jumpers */
  687. /*  perform_routing_by_exact_path ();*/
  688.  
  689. /* then use the jumpers */
  690. /*  perform_routing_by_path (); */
  691. }
  692. /* ******************************************** */
  693.  
  694. /* try to join all the pins seen on ID1 to ID2 */
  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. */
  718.  
  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.  
  739.  
  740.  
  741.           strcpy(append_point,ID1_node->identifier); /* create the totla new net name */
  742. /*
  743.           printf("Can make jumper '%s'\n",rootname);
  744. */
  745.  
  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;
  752.  
  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.          
  770.  
  771.  
  772.   }
  773.  
  774. /*******************************************************/
  775.  
  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)
  788.         {
  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 */
  793.         }
  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.   }
  800.