/****************************************************************************/
/*                                                                          */
/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit :  NetOptim                                                   */
/*    Fichier :  util.c                                                     */
/*                                                                          */
/*    (c) copyright 1992 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) : N. Dictus                             le : 10/04/1992     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include <stdio.h>
#include MUT_H
#include MLO_H
#include LOG_H
#include BEH_H
#include "types_map.h"
#include "no_optim.h"
#include "../net/no_type.h"
#include "../net/no_system.h"
#include "../mapping/generic.h"

/*---------------------------------------------------------------------------
displayLofig	: affiche une lofig (INSTANCE - CONNECTEUR - SIGNAL - 
                                     CONNECTEUR - INSTANCE)
                  level = 0 -> liste des instances et leurs interconnexions
                  level = 1 -> liste des instances et leurs interconnexions
                               + somme des Cin
                  level = 2 -> liste des instances et leurs interconnexions
                               + Resistance * somme des Cin
                  level = 3 -> liste des instances a problemes
                  level = 4 -> liste des instances et les portes qu'elles
                               attaquent
-----------------------------------------------------------------------------
retour		: void
---------------------------------------------------------------------------*/
void displayLofig(lofig, level)
lofig_list *lofig;
short level;
{
locon_list *con;
loins_list *inst;
chain_list *mod;
int countMod = 0;
int totalInst = 0;
int nbPbs = 0;
int totalSurf = 0;

PRINTI("\n\nFIGURE NAME : %s\n",lofig->NAME);

	/* parcours des modeles et calcul du nombre d'instances par modele */
for(mod = lofig->MODELCHAIN; mod; mod = mod->NEXT)
   {
   int countInst = 0;

   for(inst = lofig->LOINS; inst; inst = inst->NEXT)
      if (inst->FIGNAME == (char *)mod->DATA)
         countInst++;
   PRINTI("  Model = %s (area=%d) ==> %d cell%s\n",(char *)(mod->DATA),
          cellLoadSurface((char *)mod->DATA),
          countInst, (countInst > 1) ? "s" : "");
   countMod++;
   totalInst += countInst;
   totalSurf += countInst * cellLoadSurface((char *)mod->DATA);
   }
PRINTI("     %d models - %d instances => %d pitches\n\n", countMod, totalInst,
       totalSurf);

	/* parcours des instances de la figure */
for(inst = lofig->LOINS; inst; inst = inst->NEXT)
   {
   int nbOut = 0;
   ptype_list *fanout = NULL;

   if (level < 3) PRINTI("  INSTANCE : %s [%s] Fanout Max = %d\n",
                          inst->INSNAME,inst->FIGNAME,
                          cellLoadFanout(inst->FIGNAME));

	/* parcours des connecteurs de l'instance */
   for(con = inst->LOCON; con; con = con->NEXT)
      {
      ptype_list *liste;
      chain_list *l;

      if (!isvdd(con->NAME) && !isvss(con->NAME))
         {
         if (level < 3) 
            PRINTI("   CONNECTOR : %s (%c) --- SIGNAL %s --- ",
                   con->NAME,con->DIRECTION,
                   (char *)(con->SIG->NAMECHAIN->DATA));

         if (con->DIRECTION == OUT && level < 3)
            PRINTI("CELLS :");

		/* liste des liaisons signaux --> connecteurs */
         liste = getptype(con->SIG->USER,(long)LOFIGCHAIN);

         for(l = (chain_list *)liste->DATA; l; l = l->NEXT)
            {
            if (((locon_list *)(l->DATA))->ROOT != (void *)inst)
               {
               if (((locon_list *)(l->DATA))->TYPE == EXTERNAL)
                  {
			/* connecteurs externes : E/S primaires */
                  if (level < 3)
                     if (con->DIRECTION == OUT)
                        PRINTI(" Extern");
                     else
                        PRINTI("CELLS : Extern");
                  if (con->DIRECTION == OUT)
                     {
                     fanout = addptype(fanout,
                                       (long)(((locon_list *)(l->DATA))->NAME),
                                       (void *)NULL);
                     nbOut++;
                     }
                  }
               else
                  {
   			/* connecteur interne */
                  loins_list *cellOut =
                                 (loins_list *)((locon_list *)(l->DATA))->ROOT;

		    /* DETERMINE LE FANOUT DE CHAQUE CELLULE */

                  if (con->DIRECTION == OUT &&
                      ((locon_list *)(l->DATA))->DIRECTION == IN)
                     {
                     fanout = addptype(fanout,
                                       (long)(((locon_list *)(l->DATA))->NAME),
                                       (void *)cellOut);
                     nbOut++;
                     if (level < 3) PRINTI(" %s,",cellOut->INSNAME);
                     }
                  }
               }
            }
         if (level < 3) PRINTI("\n");
         }
      }	/* fin parcours connecteurs */

   if (fanout)
      {
      int somCin = 0, nbDrived = 0;
      int charge = 0;
      ptype_list *f;

      if (level == 4)
         {
         PRINTI("  INSTANCE : %s [%s] Fanout Max = %d, drives %d gate%s :\n",
                inst->INSNAME,inst->FIGNAME,cellLoadFanout(inst->FIGNAME),
                nbOut,(nbOut>1)?"s":"");
         }
      if (level < 3) PRINTI("     %s drives %d gate%s :",
                             inst->INSNAME,nbOut,(nbOut > 1)? "s":"");
      for(f = fanout; f; f = f->NEXT)
         {
         loins_list *att = (loins_list *)f->DATA;

		/* compteur de portes attaquees */
         nbDrived ++;

         if (level < 3) 
            if (att)
               PRINTI(" %s/%s -",att->INSNAME, (char *)(f->TYPE));
            else
               PRINTI(" EXTERN/%s -",(char *)f->TYPE);

         if (level == 4) 
            if (att)
               PRINTI("    %s [%s/%s] Cin = %d\n",att->INSNAME,att->FIGNAME,
                      (char *)(f->TYPE),
                      cellLoadCin(att->FIGNAME,(char *)(f->TYPE)));
            else
               PRINTI("    EXTERN [CONNECTOR %s] Cin = %d\n", (char *)(f->TYPE),
                      cellLoadCin((char *)NULL,(char *)f->TYPE));
         if (level > 0)
            if (att)
               somCin += cellLoadCin(att->FIGNAME, (char *)f->TYPE);
            else
               somCin += cellLoadCin((char *)NULL, (char *)f->TYPE);
         }
      if (level == 0)
         PRINTI("\n");
      if (level == 1)
         PRINTI("\n     Sum Cin = %d\n", 
                somCin);
      charge = MAX(cellLoadR(inst->FIGNAME,NULL,DOWN),
                   cellLoadR(inst->FIGNAME,NULL,UP)) * somCin ;
      if (level == 2)
         {
         PRINTI("\n     R Max x Sum Cin = %d x %d = %d - RC Max = %d\n",
                MAX(cellLoadR(inst->FIGNAME,NULL,DOWN),
                    cellLoadR(inst->FIGNAME,NULL,UP)),
                somCin, charge, 800);
         }
      if (level >= 3 && somCin > cellLoadFanout(inst->FIGNAME))
         {
         nbPbs++;

         if (level == 3)
            {
            PRINTI("  INSTANCE : %s [%s] Fanout max = %d\n",
                   inst->INSNAME,inst->FIGNAME, cellLoadFanout(inst->FIGNAME));
            PRINTI("      Sum Cin = %d, %d gate%s drived\n",
                   somCin, nbDrived, nbDrived>1?"s":"");
            }
         }
      if (level == 4)
         PRINTI("      Sum Cin = %d%s\n",somCin,
                (somCin>cellLoadFanout(inst->FIGNAME))?"  ! ##### !":"");
      }
   if (level < 3) 
      PRINTI("\n");
   }
if (level >= 3)
   PRINTI("\n Number of problem%s = %d\n\n",nbPbs>1?"s":"",nbPbs);
}

/*--------------------------------------------------------------------------
displaySol 	: affichage des solutions d'optimisation
----------------------------------------------------------------------------
retour 		: 
--------------------------------------------------------------------------*/
void displaySol(sol)
sol_list *sol;
{
ptype_list *p, *name;

printf("Solution ");
switch (sol->TYPE) 
  {
  case BUN : printf("Buffer with NOT\n"); break;
  case BUF : printf("BUFFER\n"); break;
  case DUP : printf("DUPLICATION\n"); break;
  }
printf("Number : %d\n", sol->NOMBRE);
printf("Cost in area : %d\n", sol->SURFACE);
if (sol->ADAPT)
   printf("cellule adaptee = %s\n", sol->ADAPT);
printf("Cost in cin : %d\n", sol->DIFFCIN);
printf("somme cin : %d\n", sol->SUMCIN);

for(p = sol->ARBRE, name = sol->NAME; p; p = p->NEXT, name = name->NEXT)
   {
   ptype_list *q;

   printf("     * %ld [%s]\n",name->TYPE, (char *)name->DATA);
   for(q = (ptype_list *)p->DATA; q; q=q->NEXT)
      if (q->DATA)
         printf("   porte %s - in %s - cin %d\n",((loins_list *)q->DATA)->INSNAME,
             (char *)q->TYPE, cellLoadCin(((loins_list *)q->DATA)->FIGNAME,
                                          (char *)q->TYPE));
      else
         printf("   con = %s - cin %d\n",q->TYPE,
                cellLoadCin((char *)NULL, (char *)q->TYPE));
   }
}
