
/*
 * $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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <regex.h>

#include "vertcl_main.h"
#include "expression.h"
#include "generic.h"
#include "database.h"
#include "cmdparse.h"
#include "cmdlog.h"
#include "printout.h"
#include "print_vlog.h"
#include "chck_names.h"
#include "template.h"
#include "sorting.h"
#include "unrouted.h"
#include "routing.h"
#include "equivalent.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,"-- changing pin ID '%s' to new ID = %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");
  }




