
/*
 * $Id: template.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $ * This file ensures that for all
 * sockets that are in
 *
 * $Log: template.c,v $
 * Revision 1.1.1.1  2003/11/04 23:34:57  mjames
 * Imported into local repositrory
 *
 * Revision 1.22  2003/01/02 21:37:18  mjames
 * Experiment on creating NOT_ROUTABLE_H and NOT_ROUTABLE_L
 * properties on the nets so that pin jumpers can be made without a problem.
 *
 * Still need to sort out pin assignments made to these not_routable nets
 * which will become legal in some cases so that pullups and pulldown
 * pins can be used on the FPGA.
 *
 * Revision 1.21  2002/12/09 10:31:50  mjames
 * Corrected 2 warnings about #ident
 * Added warning about "chip X1" which gets confused with component called "X1"
 *
 * Revision 1.20  2002/09/18 08:50:48  mjames
 * Cleared 'use before assign' warning
 *
 * Revision 1.19  2002/09/09 10:14:26  mjames
 * Moved pin remapping function to pin ident editing function from
 * sorting pin name routine.
 *
 * Revision 1.18  2002/09/09 09:51:27  mjames
 * Change to #ident
 *
 * Revision 1.17  2001/12/20 13:38:57  mjames
 * Forced net not routable if fpga pin is disconnected from it. Brutal
 *
 * Revision 1.16  2001/12/11 21:26:18  mjames
 * Corrected pin deletion by setting correct flags.
 *
 * Revision 1.15  2001/11/30 22:24:35  mjames
 * Improved diagnostic debug messages.
 * Used the correct sense of missing template
 * pins to remove unused pins of the component.
 *
 * Revision 1.14  2001/11/19 10:41:34  mjames
 * Merged back DTC release
 *
 * Revision 1.13.2.1  2001/11/15 22:01:53  mjames
 * Added counters for diagnostics
 *
 * Revision 1.13  2001/11/01 11:01:33  mjames
 * Template pins are created whether or not a net is routable.
 *
 * Revision 1.12  2001/10/31 22:20:18  mjames
 * Tidying up problematical comments caused by CVS
 * 'intelligent' comment guessing
 *
 * Revision 1.11  2001/10/31 16:18:04  mjames
 * Added a datastructure to hide regular expression information from programs.
 * Changed call to regexec to indicate 0 subexpressions to be matched
 * rather than a number dependent on strlen(string) which was wrong.
 *
 * Revision 1.10  2001/10/22 10:45:45  mjames
 * Added template options to create and /or disconnect pins on
 * sockets according to flags passed in to the template core routine
 *
 * Revision 1.9  2001/10/10 20:18:20  mjames
 * Added a vert_regcomp function to compile regular expressions
 * with '^' (match start string) and  '$' (match end string) bracketing
 * this => wildcard must match entire string not just a part of it.
 *
 * Revision 1.8  2001/10/10 12:49:47  mjames
 * Passed wrong argument to wildcard validator within template ensure . Fixed
 *
 * Revision 1.7  2001/10/07 20:50:51  mjames
 * Added wildcard checking (warn user about
 * using wildcard '*' on the end of a string in stead of wildcard '.*')
 *
 * Revision 1.6  2001/09/25 23:15:22  mjames
 * Converted wildcards to use proper regexp pattern match library
 *
 * Revision 1.5  2001/09/21 14:23:28  mjames
 * Cleared out template flags before checking pin compatibility rather than
 * while checking.
 *
 * Revision 1.4  2001/07/16 15:54:57  MJAMES
 * Conversion to correctly print port list of  extracted components.
 *
 * Revision 1.3  2001/06/22 11:08:07  mjames
 * Added a function to extract templates (common component types) from
 * ACF style netlists. This then permits Verilog printout to avoid duplication
 * of declaration ( problem before )
 *
 * Revision 1.2  2001/06/06 12:10:17  mjames
 * Move from HPUX
 *
 * Revision 1.1.1.1  2000/10/19 21:58:40  mjames
 * Mike put it here
 *
 *
 * Revision 1.32  2000/10/12  14:27:52  14:27:52  mjames (Mike James)
 * changed listing vhdl signals to expand expressions
 * until a constant is located
 *
 * Revision 1.31  2000/10/04  10:37:10  10:37:10  mjames (Mike James)
 * Modified for Vertical2 : support COMPONENTS and SIGNALS
 *
 * Revision 1.31  2000/10/04  10:37:10  10:37:10  mjames (Mike James)
 * Part of Release PSAVAT01
 *
 * Revision 1.30  2000/10/02  11:04:21  11:04:21  mjames (Mike James)
 * new_vhdl
 *
 * Revision 1.29  2000/09/27  14:42:22  14:42:22  mjames (Mike James)
 * Part of Release Sep_27_ST_2000
 *
 * Revision 1.28  2000/09/21  10:15:52  10:15:52  mjames (Mike James)
 * Part of Release Sep21Alpha
 *
 * Revision 1.27  2000/09/21  09:47:46  09:47:46  mjames (Mike James)
 * Added code to handle pin equivalents in templates
 * calling a function to copy over the pin equivalnets
 * from a template.
 *
 *
 * Revision 1.26  2000/08/25  09:57:17  09:57:17  mjames (Mike James)
 * Part of Release Aug25_alpha
 *
 * Revision 1.25  2000/08/16  08:57:33  08:57:33  mjames (Mike James)
 * Part of Release CD01_Aug2000
 *
 * Revision 1.24  2000/08/14  14:45:14  14:45:14  mjames (Mike James)
 * Part of Release Aug_14_2000
 *
 * Revision 1.23  2000/08/14  14:43:37  14:43:37  mjames (Mike James)
 * Added power pins
 *
 * Revision 1.22  2000/08/11  08:30:34  08:30:34  mjames (Mike James)
 * Part of Release Aug_11_2000
 *
 * Revision 1.21  2000/08/09  10:31:50  10:31:50  mjames (Mike James)
 * Part of Release Aug__9_2000
 *
 * Revision 1.20  2000/05/31  11:43:01  11:43:01  mjames (Mike James)
 * Part of Release May_31_2000
 *
 * Revision 1.19  2000/05/08  17:01:40  17:01:40  mjames (Mike James)
 * Part of Release May__8_2000
 *
 * Revision 1.18  2000/05/08  16:59:33  16:59:33  mjames (Mike James)
 * Part of Release May__8_2000
 *
 * Revision 1.17  2000/05/08  16:57:10  16:57:10  mjames (Mike James)
 * Part of Release May__8_2000
 *
 * Revision 1.16  2000/03/08  16:19:34  16:19:34  mjames (Mike James)
 * New version including PC
 *
 * Revision 1.13  2000/01/20  15:58:51  15:58:51  mjames (Mike James)
 * Part of Release R22
 *
 * Revision 1.12  99/12/22  11:15:32  11:15:32  mjames (Mike James)
 * Part of Release Dec_22_1999
 *
 * Revision 1.11  99/11/23  13:55:21  13:55:21  mjames (Mike James)
 * Added Certify support
 *
 * Revision 1.10  99/06/25  14:35:53  14:35:53  mjames (Mike James)
 * Added in reference to expression.h, but no changes made
 * to the function of acfread yet.
 *
 * Revision 1.9  99/06/18  09:26:33  09:26:33  mjames (Mike James)
 * Templating behaviour still incorrect. Under investigation.
 *
 * Revision 1.8  98/11/30  11:58:59  11:58:59  mjames (Mike James)
 * Altered behaviour for pins of type 'none' , also related
 * stuff in unrouted.c, to set a pin direction on chip
 * nodes when node references are made in the unnnamed list of
 * pins.
 *
 * Revision 1.7  98/11/13  15:22:23  15:22:23  mjames (Mike James)
 * Fixed core dump on non-existent pin identifier
 * in template application function.
 * Previously locating pins was  called with
 * a Create rather than Find flag. So it always retuned some pointer
 * to some object. Now I use Find and it can return NULL. I needed to
 * check for that null pointer.
 *
 * Revision 1.6  98/10/01  15:28:08  15:28:08  mjames (Mike James)
 * Altered behaviour to search for pins on line 204
 *
 * Revision 1.5  98/08/12  14:23:02  14:23:02  mjames (Mike James)
 * extending the templating algorithms
 *
 * Revision 1.4  98/07/14  13:26:39  13:26:39  mjames (Mike James)
 * Now hase three levels of checking templates
 *
 * Revision 1.3  98/06/15  14:20:49  14:20:49  mjames (Mike James)
 * Made tempaltes chip specific.
 *
 * Revision 1.2  98/02/11  11:27:29  11:27:29  mjames (Mike James)
 * Checked in for version 6.2a
 *
 * Revision 1.1  97/04/23  08:43:27  08:43:27  mjames (Mike James)
 * Initial revision
 *  */
#include "template.h"

#include "chck_names.h"
#include "cmdlog.h"
#include "cmdparse.h"
#include "database.h"
#include "equivalent.h"
#include "expression.h"
#include "generic.h"
#include "print_vlog.h"
#include "printout.h"
#include "routing.h"
#include "sorting.h"
#include "unrouted.h"
#include "vertcl_main.h"

#include <ctype.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#ident                                                                                        \
    "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/template.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $"

/* We have to check all sockets to see if there is a template for them.
   If there is then we ensure that all of the template pins exist on the main
   chip socket */

/* the following pin table indicates if a device pin is compatible with a template pin */

/* compat_pins[device][template] : relies on the declaration of pindir_t */
/* The array is looked up by chip pin in the y direction and
   template pin in the x direction */
char *compat_pins[] = {"1111110", /* NONE  : is it best to claim it is compatible with all pins
                                     : routing later will sort out mistakes here !*/
                       "0100100", /* INPUT */
                       "0011100", /* OUTPUT */
                       "0011100", /* BUFFER */
                       "0000100", /* BIDIR */
                       "0000010", /* CONFIG */
                       "0000001"}; /* POWER  */

static char *decode_pin_dir[] = {"UNKNOWN",
                                 "INPUT",
                                 "OUTPUT",
                                 "BUFFER", /* buffer is a sort of Output pin */
                                 "BIDIR",
                                 "CONFIG",
                                 "POWER"}; /* added Aug 2000 */

/* The function here checks pin identifiers
 *   a) to see if the pin IDs on the chip match those on the template.
 *   b) to reassign any invalid  pin IDs on the chip to valid
 *      compatible ones on the template.
 *   c) If options & TEMPLATE_CREATE_MISSING_PINS
 *         to create any remaining pin IDs on the chip that
 *         still are available on the template
 *   d) to make sure all fixed pin directions are OK
 *   e) If options & TEMPLATE_DISCONNECT_PINS to disconnect any pins
        on the chip that are not present on the template
        Any net that loses an FPGA pin is set not routable.
 */

void template_ensure (char *chip_id_template, int options)
{
        socket_t *skt = socket_head, *template = NULL;
        int found = 0, rc;
        int pins_used, pins_count;

        int chip_count, processed_count;

        node_t *chip_node, *template_node;

        char *pattern;
        /* compile regular expression */
        vert_regex_t *preg;

        chip_count = 0;
        processed_count = 0;

        create_unrouted_list ();

        /* pick out a wildcard if any ID given, else wildcard anyway */
        if (!chip_id_template)
        {
                pattern = ".*";
                Log (LOG_GENERAL, "-- Beginning setting pin template on all chips\n");
        }
        else
        {
                pattern = chip_id_template;
                Log (
                    LOG_GENERAL,
                    "-- Beginning setting pin template: prefix '%s' --\n",
                    chip_id_template);
        }

        rc = vert_regcomp (&preg, pattern);

        if (rc != 0)
        {
                char errbuff[100];
                regerror (rc, preg->preg, errbuff, 100);
                Log (
                    LOG_ERROR,
                    "-- Problem (rc=%d) %s with '%s' as regular expression\n",
                    rc,
                    errbuff,
                    pattern);

                /*    return TCL_ERROR;
                 */
                return;
        }
        else
        {
                Log (LOG_GENERAL, "-- Using '%s' as match pattern\n", pattern);
        }

        while (skt)
        {
                chip_count++;
                skt->template_socket = NULL;

                found = regexec (preg->preg, skt->identifier, 0, preg->regpatt, 0);

                if (!found)
                {
                        char *chiptype = skt->type;
                        if (!ISNULLSTR (chiptype))
                        {
                                template =
                                    find_socket (Type, chiptype, Search, &template_head);
                                if (level & 1)
                                {
                                        Log (
                                            LOG_GENERAL,
                                            "-- **** Processing chip '%s' : type='%s' ****\n",
                                            skt->identifier,
                                            chiptype);
                                }
                                /* assign_declaration_directives(skt,global_generics);
                                 */
                                if (template)
                                { /* we have located a template for this chip */

                                        processed_count++;

                                        skt->template_socket = template;
                                        if (level & 1)
                                        {
                                                Log (LOG_GENERAL, "-- Which has a template\n");
                                        }

                                        /* examine all of the template entries and add in any
                                           IS_DECLARATION_DIRECTIVE ones */
                                        assign_declaration_directives (
                                            skt, template->generics);

                                        /*
                                                 copy_declaration_generics(skt,template);
                                        */
                                        /* clear template flags on chip nodes */
                                        chip_node = skt->nodes;
                                        while (chip_node)
                                        {
                                                chip_node->template_flag = 0;
                                                chip_node = chip_node->sktnext;
                                        }
                                        template_node = template->nodes;
                                        while (template_node)
                                        {
                                                template_node->template_flag = 0;
                                                template_node = template_node->sktnext;
                                        }
                                        /* search for nodes that already have valid identifiers
                                           according to the chip templates, and mark these as
                                           being OK  */

                                        template_node = template->nodes;
                                        if (level & 1)
                                        {
                                                Log (
                                                    LOG_GENERAL,
                                                    "-- Matching template node identifiers\n");
                                        }
                                        while (template_node)
                                        {
                                                chip_node = find_node (
                                                    skt,
                                                    Ident,
                                                    template_node->identifier,
                                                    Search);
                                                if (chip_node)
                                                {
                                                        /* need also to confirm that this pin
                                                           connection is of a compatible type
                                                           -- added checking code here */
                                                        if (level & 2)
                                                                Log (
                                                                    LOG_GENERAL,
                                                                    "-- node '%s' chip=%d "
                                                                    "template=%d compat %c\n",
                                                                    chip_node->identifier,
                                                                    chip_node->pindir,
                                                                    template_node->pindir,
                                                                    compat_pins[chip_node
                                                                                    ->pindir]
                                                                               [template_node
                                                                                    ->pindir]);

                                                        if (compat_pins[chip_node->pindir]
                                                                       [template_node
                                                                            ->pindir] == '1')
                                                        {
                                                                chip_node
                                                                    ->vhdltype = copy_vhdl (
                                                                    template_node->vhdltype,
                                                                    skt);

                                                                template_node->template_flag =
                                                                    1;
                                                                chip_node->template_flag = 1;
                                                                if (level & 2)
                                                                        Log (
                                                                            LOG_GENERAL,
                                                                            "-- pin '%s' "
                                                                            "compatible\n",
                                                                            template_node
                                                                                ->identifier);
                                                        }
                                                };
                                                /*
                                                else
                                                    Log(LOG_GENERAL,"-- node '%s' not
                                                matched\n",template_node->identifier);
                                                */
                                                template_node = template_node->sktnext;
                                        }

                                        /* now look through chip for all identifiers that
                                           havent been found on the template. These are
                                           incorrect and need to be replaced  by an unused
                                           template pin*/
                                        if (level & 1)
                                        {
                                                Log (
                                                    LOG_GENERAL,
                                                    "-- Altering node identifiers\n");
                                        }
                                        /* clear template flags on chip nodes */
                                        chip_node = skt->nodes;

                                        /* search each chip node to see if validated OK */
                                        while (chip_node)
                                        {
                                                /* if it does not have a correct template pin ,
                                                 * go and find one */
                                                if (!chip_node->template_flag)
                                                {
                                                        template_node = template->nodes;
                                                        while (template_node)
                                                        {
                                                                if (template_node
                                                                        ->template_flag == 0)
                                                                {
                                                                        /* possible pin unused
                                                                         * candidate : look at
                                                                         * the pin direction */
                                                                        if (compat_pins
                                                                                [chip_node
                                                                                     ->pindir]
                                                                                [template_node
                                                                                     ->pindir] ==
                                                                            '1')
                                                                        {
                                                                                template_node
                                                                                    ->template_flag =
                                                                                    1;
                                                                                chip_node
                                                                                    ->template_flag =
                                                                                    1;
                                                                                if (level & 2)
                                                                                        Log (
                                                                                            LOG_GENERAL,
                                                                                            "-"
                                                                                            "-"
                                                                                            " "
                                                                                            "c"
                                                                                            "h"
                                                                                            "a"
                                                                                            "n"
                                                                                            "g"
                                                                                            "i"
                                                                                            "n"
                                                                                            "g"
                                                                                            " "
                                                                                            "p"
                                                                                            "i"
                                                                                            "n"
                                                                                            " "
                                                                                            "I"
                                                                                            "D"
                                                                                            " "
                                                                                            "'"
                                                                                            "%"
                                                                                            "s"
                                                                                            "'"
                                                                                            " "
                                                                                            "t"
                                                                                            "o"
                                                                                            " "
                                                                                            "n"
                                                                                            "e"
                                                                                            "w"
                                                                                            " "
                                                                                            "I"
                                                                                            "D"
                                                                                            " "
                                                                                            "="
                                                                                            " "
                                                                                            "%"
                                                                                            "s"
                                                                                            "\n",
                                                                                            chip_node
                                                                                                ->identifier,
                                                                                            template_node
                                                                                                ->identifier);
                                                                                chip_node
                                                                                    ->identifier =
                                                                                    template_node
                                                                                        ->identifier;
                                                                                chip_node
                                                                                    ->vhdltype =
                                                                                    copy_vhdl (
                                                                                        template_node
                                                                                            ->vhdltype,
                                                                                        skt);
                                                                                break; /* from
                                                                                          while
                                                                                          template_node
                                                                                        */
                                                                        }
                                                                        /*
                                                                        else
                                                                          Log(LOG_GENERAL,"--
                                                                        ?? node ID '%s' new ID
                                                                        = %s .. %d\n",
                                                                                chip_node->identifier,
                                                                               template_node->identifier,template_node->pindir);
                                                                      */
                                                                }
                                                                template_node =
                                                                    template_node->sktnext;
                                                        }
                                                        /* if we havent found a valid possible
                                                           template node ID for the chip pin
                                                           then template_node == NULL at this
                                                           point (run out of possibilities)
                                                           Except if we are deleting missing
                                                           pins then its worth  */
                                                        if (!(options &
                                                              TEMPLATE_DISCONNECT_PINS) &&
                                                            !template_node)
                                                                Log (
                                                                    LOG_ERROR,
                                                                    "-- ERROR (perhaps): "
                                                                    "Cannot find a valid ID "
                                                                    "to replace %s pin '%s'\n",
                                                                    decode_pin_dir
                                                                        [chip_node->pindir],
                                                                    chip_node->identifier);
                                                }
                                                chip_node = chip_node->sktnext;
                                        }
                                        if (level & 1)
                                        {
                                                Log (
                                                    LOG_GENERAL,
                                                    "-- Creating additional pins , correcting "
                                                    "fixed pin directions\n");
                                        }
                                        /* to apply template :
                                        Find/create the chip pin . If the
                                        matching template pin directional is BIDIR_PIN,
                                        do not touch the current pin direction.
                                        Otherwise override the physical pin direction */

                                        template_node = template->nodes;
                                        pins_used = 0;
                                        pins_count = 0;

                                        while (template_node)
                                        {
                                                /* find the chip pin (node)  */
                                                node_t *chip_node;

                                                chip_node = find_node (
                                                    skt,
                                                    Ident,
                                                    template_node->identifier,
                                                    options & TEMPLATE_CREATE_MISSING_PINS);
                                                if (level & 2)
                                                {
                                                        Log (
                                                            LOG_GENERAL,
                                                            "-- template '%s' template flag "
                                                            "%d exists %d\n",
                                                            template_node->identifier,
                                                            template_node->template_flag,
                                                            chip_node ? 1 : 0);
                                                }
                                                pins_count++;
                                                if (chip_node != NULL)
                                                {
                                                        pins_used++;
                                                        /* fix the pin direction down !! */

                                                        if (template_node->template_flag == 0)
                                                        {
                                                                /* next line had chip_node  in
                                                                 * it */
                                                                if ((template_node->pindir !=
                                                                     BIDIR) &&
                                                                    (template_node->pindir !=
                                                                     NONE))
                                                                {
                                                                        chip_node->fixed_pin =
                                                                            1; /* routes must
                                                                                  use the
                                                                                  appropriate
                                                                                  pin direction
                                                                                */
                                                                        chip_node->pindir =
                                                                            template_node
                                                                                ->pindir;
                                                                        if (level & 2)
                                                                                Log (
                                                                                    LOG_GENERAL,
                                                                                    "-- pin "
                                                                                    "'%s' "
                                                                                    "fixing "
                                                                                    "pindir "
                                                                                    "as %d\n",
                                                                                    chip_node
                                                                                        ->identifier,
                                                                                    chip_node
                                                                                        ->pindir);
                                                                }
                                                        }
                                                        chip_node->template_flag =
                                                            1; /* templating applied OK */
                                                        chip_node->pin_group =
                                                            template_node->pin_group;
                                                }
                                                template_node = template_node->sktnext;
                                        }
                                        if (level & 1)
                                        {
                                                Log (
                                                    LOG_GENERAL,
                                                    "-- %d pins out of %d in use\n",
                                                    pins_used,
                                                    pins_count);
                                        }
                                }

                                /* new stuff October 2001 : If any chip pins do not have their
                                   template flag set now then
                                   they _may_ be deleted as they are not on the template in any
                                   case */
                                if (template && (options & TEMPLATE_DISCONNECT_PINS))
                                {
                                        pins_count = 0;
                                        if (level & 1)
                                        {
                                                Log (
                                                    LOG_GENERAL,
                                                    "-- Disconnecting pins missing on "
                                                    "template\n");
                                        }
                                        chip_node = skt->nodes;
                                        while (chip_node)
                                        {
                                                if (!chip_node->template_flag)
                                                {
                                                        if (level & 2)
                                                        {
                                                                Log (
                                                                    LOG_GENERAL,
                                                                    "--  pin '%s' being "
                                                                    "disconnected\n",
                                                                    chip_node->identifier);
                                                        }

                                                        pins_count++;
                                                        /* questionable approach to problem */
                                                        if (chip_node->net)
                                                        {
                                                                chip_node->net->how_routed =
                                                                    Not_Routable; /* checked */
                                                        }
                                                        disconnect_node (skt, chip_node);
                                                }
                                                chip_node = chip_node->sktnext;
                                        }
                                        if (level & 1)
                                        {
                                                Log (
                                                    LOG_GENERAL,
                                                    "-- Disconnected %d pins missing on "
                                                    "template\n",
                                                    pins_count);
                                        }
                                }
                                if (level & 1)
                                {
                                        Log (LOG_GENERAL, "-- Finished chip\n");
                                }
                        }

                        copy_equivalent_pins (
                            template, skt); /* any pin connections that are equivalent
                                               by default will be copied from the template */
                }
                skt = skt->next;
        }
        Log (
            LOG_GENERAL,
            "-- checked %d objects, applied template to %d of them\n",
            chip_count,
            processed_count);
        vert_regfree (&preg);
}

/* list what we have as a template */
void template_list (void)
{
        socket_t *templates = template_head;
        /* for now list out the templates */
        Log (LOG_GENERAL, "-- List of socket templates\n");
        while (templates)
        {
                Log (LOG_GENERAL, "-- Template '%s' ", templates->type);
                if (templates->parent_template_ref)
                        Log (
                            LOG_GENERAL, "alias '%s'\n", templates->parent_template_ref->type);
                else
                        Log (LOG_GENERAL, "\n");

                templates = templates->next;
        }
}

/* list what we have as a template */
void template_list_pins (FILE *f)
{
        socket_t *templates = template_head;
        /* for now list out the templates */
        while (templates)
        {
                fprintf (f, "-- Template '%s'\n", templates->type);
                print_device (
                    f,
                    templates,
                    PRINT_ALL | PRINT_GROUP | PRINT_GENERIC | PRINT_EQUIVALENT_PINS |
                        PRINT_EXPAND_BUS);
                templates = templates->next;
        }
}

/******************************************************************************************/
/* Extracting component templates from the list of components in the circuit design       */
/******************************************************************************************/

void extract_templates (void)
{
        socket_t *skt = socket_head, *template;
        node_t *chip_node, *template_node;
        Log (
            LOG_GENERAL,
            "-- Extracting device templates (verilog modules or VHDL components)\n");

        /* is this needed ? */
        create_unrouted_list ();

        while (skt)
        {
                char *chiptype = skt->type;
                /* locate or create the template for this socket */
                if (!ISNULLSTR (chiptype))
                {
                        template = find_socket (Type, chiptype, Search, &template_head);
                        skt->template_socket = template;

                        if (!template) /* act only if no template */
                        {
                                if (level & 4)
                                        Log (
                                            LOG_GENERAL,
                                            "-- Creating template from chip '%s' : "
                                            "type='%s'\n",
                                            skt->identifier,
                                            chiptype);
                                template =
                                    find_socket (Type, chiptype, Create, &template_head);
                                template->is_template = 1; /* flag for later use */
                        }
                        assign_declaration_directives (template, skt->generics);

                        skt->template_socket = template;

                        copy_equivalent_pins (
                            skt, template); /* any pin connections that are equivalent
                                                by default will be copied to the template */

                        /* assign_declaration_directives(skt,template->generics);   */

                        /*
                                 copy_declaration_generics(skt,template);
                        */

                        chip_node = skt->nodes;
                        if (level & 4)
                                Log (LOG_GENERAL, "-- Copying/checking node identifiers\n");
                        while (chip_node)
                        {
                                if (level & 4)
                                        Log (
                                            LOG_GENERAL,
                                            "-- Node %s\n",
                                            chip_node->identifier);
                                template_node =
                                    find_node (template, Ident, chip_node->identifier, Search);
                                /* add pins to template if there is a net connected to this pin
                                 * and it is routable */

                                if (!template_node && chip_node->net /*&& chip_node->net->how_routed != Not_Routable */ )
                                {
                                        template_node = find_node (
                                            template, Ident, chip_node->identifier, Create);

                                        template_node->pindir = chip_node->pindir;
                                        template_node->vhdltype =
                                            copy_vhdl (chip_node->vhdltype, skt);

                                        if (level & 4)
                                                Log (
                                                    LOG_GENERAL,
                                                    "-- node '%s' dircode=%d\n",
                                                    template_node->identifier,
                                                    template_node->pindir);
                                }
                                chip_node = chip_node->sktnext;
                        }

                        if (level & 4)
                        {
                                Log (LOG_GENERAL, "-- Finished chip\n");
                        }
                }

                skt = skt->next;
        }
        Log (LOG_GENERAL, "-- Finished extracting device templates\n");
}