Subversion Repositories Vertical

Rev

Go to most recent revision | 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
  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. }
  893.