/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  optimiseur de netlist                                      */
/*    Fichier :  no_system.c                                                */
/*                                                                          */
/*    (c) copyright 1991 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) :  L. Burgun                            le : 06/05/1992     */
/*                                                                          */
/*    Modifie par : N. DICTUS                           le : 22/09/1993     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include <stdlib.h>
#include <string.h>
#include MUT_H
#include MLO_H
#include LOG_H
#include "ctype.h"
#include "../load/types_map.h"
#include "no_type.h"
#include "no_system.h"
#include "enveloppe.h"
#include "../load/no_optim.h"

char *getenv();

/*---------------------------------------------------------------------------
calculEnveloppe   : 
-----------------------------------------------------------------------------
retour          : 
---------------------------------------------------------------------------*/
void calculEnveloppe(listeCellules)
cellList *listeCellules;
{
cellList *cells;

for(cells = listeCellules; cells; cells = cells->NEXT)
   if (cells->envel)
   {
   chain_list *liste;
    
   cells->envel = completeListe(filtreListeAtom(listeAtom(cells->envel)),
                                cells->entrees);
   }
}

/*---------------------------------------------------------------------------
addConDirLofig   :
-----------------------------------------------------------------------------
retour          :
---------------------------------------------------------------------------*/
void addConDirLofig(lofig)
lofig_list *lofig;
{
locon_list *connect;

for(connect = lofig->LOCON; connect; connect = connect->NEXT)
   {
   chain_list *l;
   ptype_list *liste = getptype(connect->SIG->USER, (long)LOFIGCHAIN);
   char dir = ((locon_list *)(((chain_list *)(liste->DATA))->DATA))->DIRECTION;
 
   for (l = (chain_list *)(liste->DATA); l; l = l->NEXT)
       if (((locon_list *)(l->DATA))->TYPE != EXTERNAL &&
           dir != INOUT && ((locon_list*)(l->DATA))->DIRECTION != dir)
          dir = INOUT;
   connect->DIRECTION = dir;
   }
}

/*---------------------------------------------------------------------------
initializeNet   : initialise la lofig et les cellules
-----------------------------------------------------------------------------
retour          : pointeur sur la lofig.
---------------------------------------------------------------------------*/
lofig_list *initializeNet()
{
lofig_list *lofig;
losig_list *sigAux;

        /* initialisation du systeme de chargement des cellules */
cellInit();

        /* chargement de la figure */
printf("Loading %s...\n",NO_NAME);
lofig = getlofig(NO_NAME,'A');
printf("Flattening %s...\n",NO_NAME);
rflattenlofig(lofig, YES, YES);

        /* chainages signaux -> connecteurs */
lofigchain(lofig);
 
indexMaximum = 0;

        /* parcours des signaux de la figure : calcul de l'index max */
for(sigAux = lofig->LOSIG; sigAux; sigAux = sigAux->NEXT)
   {
   if (sigAux->INDEX > indexMaximum)
      indexMaximum = sigAux->INDEX;
   }

        /* chargement des modeles en memoire : structure *cellList */
cellLoad(lofig->MODELCHAIN);
 
        /* calcul de l'enveloppe des cellules */
calculEnveloppe(NO_CELLS);
 
                /* mise a jour de la direction des connecteurs d'instances */
if (!restorealldir(lofig))
   {
   printf("Adding connection direction failed on %s\n\n", lofig->NAME);
   exit(1);
   }
 
        /* mise a jour de la direction des connecteurs EXTERNES */
addConDirLofig(lofig);
 
return lofig;
}
 
/*---------------------------------------------------------------------------
cellEnd         : termine le systeme de chargement de cellules .
-----------------------------------------------------------------------------
retour          : rien
---------------------------------------------------------------------------*/
void cellEnd()
{

        /* destruction de la TH des cellules deja chargees */
destroyTH(NO_CELLTH);
destroyBdd(1);

        /* VH_LIBLST reprend son ancienne valeur
char *newVhdl = (char *)mbkalloc(strlen(vhdl) + 12);
if (vhdl)
   {
   sprintf(newVhdl,"VH_LIBLST=%s",vhdl);
   printf("vhdl : %s -\n",newVhdl);
   putenv(newVhdl);
   }
        */
}

/*----------------------------------------------------------------------------
verifArgs	: verifie les arguments de la ligne de commande.
------------------------------------------------------------------------------
retour		: un entier a 1 si OK, 0 sinon.
------------------------------------------------------------------------------*/

int verifArgs(argc,argv)
int argc;
char *argv[];
{
FILE *fic;
FILE *fopen();
char *work_lib;
char *par_lib;
char *in_lo;

work_lib   = (char *) mbkalloc (100);
par_lib   = (char *) mbkalloc (100);
in_lo      = (char *) mbkalloc (10);

if (!getenv("MBK_WORK_LIB"))
   strcpy(work_lib,".");
else
   strcpy(work_lib,getenv("MBK_WORK_LIB"));

if (!existDirectory(work_lib))
   {
   printf("\nnetoptim %s : the directory '%s' (for MBK_WORK_LIB) doesn't exist\n",VERSION, work_lib);
   exit(-1);
   }

if (!getenv("MBK_WORK_LIB"))
   strcpy(par_lib,".");
else
   strcpy(par_lib,getenv("MBK_WORK_LIB"));
 
if (!getenv("MBK_IN_LO"))
   strcpy(in_lo,"al");
else
   strcpy(in_lo,getenv("MBK_IN_LO"));

if (argc == 1)
   {
   printf("\nnetoptim  %s - usage :\n   netoptim -option <file_entity> <file_output> [<file_par>]\n\n", VERSION);
   printf("option         : -f   local optimization with max fanout\n");
   printf("                 -g   global optimization with timing analysis\n"); 
   printf("                 -t   timing informations\n"); 
   printf("                 -i   fanout informations\n"); 
   return(0) ;
   }
	/* test de la ligne de commande */
if (argv[1][0] != '-')
   {
		/* appel interactif */
   if (argc == 2)
      {
      printf("\nnetoptim  %s - usage :\n   netoptim -option <file_entity> <file_output> [<file_par>]\n\n", VERSION);
      printf("option         : -f   local optimization with max fanout\n");
      printf("                 -g   global optimization with timing analysis\n"); 
      printf("                 -t   timing informations\n"); 
      printf("                 -i   fanout informations\n"); 
      return(0) ;
      }
   if (argc == 3)
      {
	   /* netoptim source destination */
      argv[1] = (char *) genNAME("%s.%s",argv[1],in_lo);
      return(1);
      }
   if (argc == 4)
      {
		/* netoptim source destination param */
      argv[3] = (char *) genNAME("%s.lax",argv[3]);
      if (!strcmp(par_lib,"."))
         {
         if (!(fic = fopen(argv[3],"r")))
      	    {
	    printf("\nnetoptim %s      : unable to open %s\n\n", VERSION, argv[3]) ;
	    return(0) ;
	    }
         }
      else
         {
         char *parFile = mbkalloc(strlen(par_lib)+strlen(argv[3])+3);

         sprintf(parFile, "%s/%s",par_lib,argv[3]);
         if (!(fic = fopen(parFile, "r")))
            {
	    printf("\nnetoptim %s      : unable to open %s\n\n", VERSION, parFile) ;
	    return(0) ;
	    }
         mbkfree(parFile);
         }
      argv[1] = (char *) genNAME("%s.%s",argv[1],in_lo);
      return(1);
      }
   }
 		/* fin appel version interactive */

if ((strcmp(argv[1],"-f") && strcmp(argv[1],"-t") && 
    strcmp(argv[1],"-g") && strcmp(argv[1],"-i")) ||
    (argc < 4))
   {
	/* version batch */
   if (argc >= 4)
      printf("\nnetoptim %s     : bad option '%s'\n\n", VERSION, argv[1]) ;
   printf("\nnetoptim  %s - usage :\n   netoptim -option <file_entity> <file_output> [<file_par>]\n\n", VERSION);
   printf("option         : -f   local optimization with max fanout\n");
   printf("                 -g   global optimization with timing analysis\n"); 
   printf("                 -t   timing informations\n"); 
   printf("                 -i   fanout informations\n"); 
   return(0) ;
   }

		/* netlist dans work_lib (MBK_WORK_LIB) */
argv[2] = (char *) genNAME("%s.%s",argv[2],in_lo);

		/* fichier de parametres dans par_lib (MBK_WORK_LIB) */
if (argc == 5)
   {
   argv[4] = (char *) genNAME("%s.lax",argv[4]);
   if (!strcmp(par_lib,"."))
      {
      if(!(fic = fopen(argv[4],"r")))
      	{
	printf("\nnetoptim %s      : unable to open '%s'\n\n", VERSION, argv[4]) ;
	return(0) ;
	}
      }
   else
      {
      char *parLib = mbkalloc(strlen(par_lib)+strlen(argv[4])+3);

      sprintf(parLib, "%s/%s",par_lib,argv[4]);
      if(!(fic = fopen(parLib, "r")))
      	{
	printf("\nnetoptim %s      : unable to open %s\n\n", VERSION, parLib) ;
	return(0) ;
	}
      mbkfree(parLib);
      }
   }

return 1;
}

/*----------------------------------------------------------------------------
majNOSystem: verifie les arguments de la ligne de commande.
------------------------------------------------------------------------------
retour		: un pointeur sur une structure systeme. 
------------------------------------------------------------------------------*/
void majNOSystem(no, mode,argc,argv,version)
no_system *no;
   /* mode batch = 1, mode interactif = 0, relax = 2 */
int mode,argc;
char *argv[];
char *version;
{
short i = 0;

strcpy(no->version,version);

if (!getenv("MBK_WORK_LIB"))
   strcpy(no->log_lib,".");
else
   strcpy(no->log_lib,getenv("MBK_WORK_LIB"));

if (!existDirectory(no->log_lib))
   {
   printf("\nnetoptim %s : the directory '%s' (for MBK_WORK_LIB) doesn't exist\n",VERSION, no->log_lib);
   exit(-1);
   }

if (!getenv("MBK_CATA_LIB"))
   no->cata_lib = addptype((chain_list *)NULL, 0, ".");
else
   {
   char *sauve = getenv("MBK_CATA_LIB"), *s;
   char *str = (char *)mbkalloc(strlen(sauve) + 1);

	/* constructuion de la liste chainee des differentes bibliotheques */
   sprintf(str, "%s\0", sauve);
   no->cata_lib = (ptype_list *)NULL;
   while (1)
      {
      if ((s = strchr(str, ':')) == NULL)
         {
         if (!existDirectory(str))
            {
            printf("\nnetoptim %s : the directory '%s' (for MBK_CATA_LIB) doesn't exist\n",VERSION, str);
            exit(-1);
            }
         no->cata_lib = addptype(no->cata_lib, 0, str);
         break;
         }
      *(s++) = '\0';
      if (!existDirectory(str))
         {
         printf("\nnetoptim %s : the directory '%s' (for MBK_CATA_LIB) doesn't exist\n",VERSION, str);
         exit(-1);
         }
      no->cata_lib = addptype(no->cata_lib, 0, str);
      str = s;
      }
   }

if (!getenv("MBK_WORK_LIB"))
   strcpy(no->par_lib,".");
else
   strcpy(no->par_lib,getenv("MBK_WORK_LIB"));

if (!existDirectory(no->par_lib))
   {
   printf("\nnetoptim %s : the directory '%s' (for MBK_WORK_LIB) doesn't exist\n",VERSION, no->par_lib);
   exit(-1);
   }

if (!getenv("MBK_IN_LO"))
   strcpy(no->in_lo,"al");
else
   strcpy(no->in_lo,getenv("MBK_IN_LO"));

if (!getenv("MBK_OUT_LO"))
   strcpy(no->out_lo,"al");
else
   strcpy(no->out_lo,getenv("MBK_OUT_LO"));

if (getenv("MBK_TRACE") == NULL)
   no->trace = 0; 
else
   no->trace = atoi(getenv("MBK_TRACE"));

no->mode     = mode;
if (mode == 1)
   {
	/* Mode BATCH */
   strcpy(no->name,argv[2]) ;
   strcpy(no->file,argv[2]) ;
   strcpy(no->fileOut, argv[3]) ;

   if (!strcmp(no->log_lib,"."))
      strcpy(no->fileLog,argv[2]) ;
   else
      sprintf(no->fileLog,"%s/%s",no->log_lib,argv[2]);

   no->par = initializeNOParam(0,1000,NULL,NULL,NULL,NULL,NULL,NULL);
   if (argc == 5)
      {
      strcpy(no->filePar,argv[4]) ;

      if (!strcmp(no->par_lib,"."))
         strcpy(no->fileParam,argv[4]) ;
      else
         sprintf(no->fileParam,"%s/%s",no->par_lib,argv[4]);

      if ((no->par = loadParam(no->fileParam)) == NULL ) 
		{ 
		printf("NetOptimptim %s - loadParam error: bad parameters file '%s'\n", VERSION, no->fileParam);
		exit( -1 );
		}
      }
   else
      {
      strcpy(no->filePar,"default.lax");
      if (!strcmp(no->par_lib,"."))
         strcpy(no->fileParam,"default.lax");
      else
         sprintf(no->fileParam,"%s/default.lax",no->par_lib);
      }
   no->option = *(argv[1]+1);
   }
else		/* mode 0 ou 2 */
   {
	/* mode interactif */
   strcpy(no->name,argv[1]) ;
   strcpy(no->file,argv[1]) ;
   strcpy(no->fileOut,argv[2]) ;

   if (!strcmp(no->log_lib,"."))
      strcpy(no->fileLog,argv[1]) ;
   else
      sprintf(no->fileLog,"%s/%s",no->log_lib,argv[1]);
   no->par = initializeNOParam(0,1000,NULL,NULL,NULL,NULL,NULL,NULL);
   if (argc != 4)
      {
      strcpy(no->filePar,"default.lax");
      if (!strcmp(no->par_lib,"."))
         strcpy(no->fileParam,"default.lax");
      else
         sprintf(no->fileParam,"%s/default.lax",no->par_lib);
      }
   else		/* mode 2 */
      {
      strcpy(no->filePar,argv[3]) ;
      if (!strcmp(no->par_lib,"."))
         strcpy(no->fileParam,argv[3]) ;
      else
         sprintf(no->fileParam,"%s/%s",no->par_lib,argv[3]);
      if ((no->par = loadParam(no->fileParam)) == NULL ) 
		{ 
		printf("NetOptimptim %s - loadParam error: bad parameters file '%s'\n", VERSION, no->fileParam);
		exit( -1 );
		}
      }
   no->option = '\0';
   }

while((no->name)[i] != '.')
     i++;
(no->name)[i] = '\0';

saveParam(no->par, no->fileParam);

mbkenv();
}

/*----------------------------------------------------------------------------
displaySystem   : affiche les arguments de l'optimisation
------------------------------------------------------------------------------
retour		: void 
------------------------------------------------------------------------------*/

void displaySystem(sys)
no_system *sys;
{
	/* nouvelle banniere : octobre 93 */
alliancebanner("NetOptim", VERSION, "a NETlist OPTIMizer", "90-93", ALLIANCE_VERSION);

if (NO_MODE == 1)		/* mode batch */
   {
   printf("     ==========================  Environnement  ========================\n");

   printf("     MBK_WORK_LIB        = %s\n",NO_LOG_LIB);
   if (NO_TRACE > 0)
      printf("     MBK_TRACE           = %d\n",NO_TRACE);
   printf("     MBK_CATA_LIB        = %s\n", getenv("MBK_CATA_LIB"));
   printf("     =================  Files, Options and Parameters  =================\n");
   printf("     Netlist file       = %s\n",NO_FILELOG);
   printf("     Parameters file    = %s\n",NO_PARAM);

   printf("     Mode               = ");
   switch (NO_OPTION)
       {
       case 'f' : printf("local optimization with max fanout\n");
                  break;
       case 'g' : printf("global optimization with timing analysis\n");
                  break;
       case 't' : printf("timing informations\n");
                  break;
       case 'i' : printf("fanout informations\n");
                  break;
       }
  printf("     ===================================================================\n");

  printf("\n");
  }
}


/*----------------------------------------------------------------------------
OPTIMISATION_LOCALE : optimisation locale d'une netlist 
------------------------------------------------------------------------------
retour		: void 
------------------------------------------------------------------------------*/
void OPTIMISATION_LOCALE()
{
mainOptimFanMax();
}

/*----------------------------------------------------------------------------
OPTIMISATION_GLOBALE : optimisation globale d'une netlist 
------------------------------------------------------------------------------
retour		: void 
------------------------------------------------------------------------------*/
void OPTIMISATION_GLOBALE()
{
mainOptimGlobal();
}

/*----------------------------------------------------------------------------
INFORMATION     : information sur une netlist 
------------------------------------------------------------------------------
retour		: void 
------------------------------------------------------------------------------*/
void INFORMATION(type)
char type;
{
mainInfo(type);
}
