/*                      Chaine de CAO & VLSI   Alliance                     */
/*                                                                          */
/*    Produit : Synthetiseur logique                                        */
/*    Fichier : mapper.c                                                    */
/*                                                                          */
/*    (c) copyright 1991 Laboratoire MASI equipe CAO & VLSI                 */
/*    Tous droits reserves                                                  */
/*    Support : e-mail cao-vlsi@masi.ibp.fr                                 */
/*                                                                          */
/*    Auteur(s) :   ALLEGRE P.                           le : 28/08/1991     */
/*                                                                          */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*    Modifie par :                                     le : ../../....     */
/*                                                                          */
/****************************************************************************/

#include <stdio.h>
#include MUT_H
#include LOG_H
#include BEH_H
#include "../compil/lax_param.h"
#include "../synthe/sl_type.h"
#include "../menu/sl_corps.h"
#include "../compil/sl_util.h"
#include "types.h"
#include "arbres.h"
#include "compile.h"
#include "cout.h"
#include "decomp.h"
#include "display.h"
#include "moteur.h"
#include "oper.h"
#include "regles.h"
#include "util.h"
#include "mapper.h"
extern long mbkalloc_stat;

long memberDelaypi(name,listeDel)
char *name;
ptype_list *listeDel;

{
ptype_list *l;

for(l = listeDel;l;l = l->NEXT)
	if ((char *)l->DATA == name) return l->TYPE;
return 0;
}

short memberOptimpo(name,listeOptim)
char *name;
chain_list *listeOptim;

{
chain_list *l;

for(l = listeOptim;l;l = l->NEXT)
	if ((char *)l->DATA == name) return 1;
return 0;
}

void genBd()

{
berin_list *i;
beout_list *o,*sav = NULL;
bereg_list *r;
bebus_list *b;
bebux_list *u;
beaux_list *a;
chain_list *ablsimplif;
num_list *del = NULL,*d;
int delaiMoyen,delai;
pTH caracBeh();
pTH caracTH;

                   /* caracterisation */

   caracTH = caracBeh(SL_BEH,SL_DELAYPI,0);       

                /* ----- a correler avec le mode d'optimisation */

   delaiMoyen = delaisCarac(caracTH,SL_OPTIM);                          

cptVirtuel = 1;
for(o = SL_BEH->BEOUT;o;o = o->NEXT)
{
sig *auxSig = (sig *)mbkalloc(sizeof(sig));

   if (o->ABL)
   {
	auxSig->type = 5;
	auxSig->name = o->NAME;
	auxSig->delais = -1;
	auxSig->capa = 0;
	auxSig->util = (chain_list *)NULL;
	ablsimplif = copyExpr(o->ABL);
	addArite(ablsimplif);
	auxSig->ablList = createATOM(ablsimplif);
	delai = searchTH(caracTH,o->ABL);
        if (delai == EMPTYTH)
           {
           PRINTF("genBD : error bad characterization\n");
           exit(-1);
           }
	if (inChain_list(SL_OPTIMPO,o->NAME))
	   auxSig->cout = 4;
	else
        /* pas touche si optim en surface */
           if (SL_OPTIM != 0 && delai > delaiMoyen && SL_OPTIM < 4)
	      auxSig->cout = SL_OPTIM + 1;
           else 
	      auxSig->cout = SL_OPTIM;
	addTH(mappSys->sig_hash,o->NAME,(int)auxSig);
	sav = o;
	if (!ATOM(o->ABL))
	{
	   freeExpr(o->ABL);
	   o->ABL = NULL;
	}
   }
   else
	if (!sav)
	   SL_BEH->BEOUT = o->NEXT;
	else
	   sav->NEXT = o->NEXT;
}

for(b = SL_BEH->BEBUS;b;b = b->NEXT)
	{
	sig *auxSig = (sig *)mbkalloc(sizeof(sig));
	biabl_list *bi;

	auxSig->type = 3;
	auxSig->name = b->NAME;
	auxSig->delais = 0;
	auxSig->capa = 0;
	auxSig->util = (chain_list *)NULL;
	auxSig->cout =0;
	bi = b->BIABL;
	while (bi)
	{
	   delai = searchTH(caracTH,bi->VALABL);
           if (delai == EMPTYTH)
           {
              PRINTF("genBD : error bad characterization\n");
              exit(-1);
           }
	   if (inChain_list(SL_OPTIMPO,b->NAME))
	      auxSig->cout = 4;
	   else
              if (SL_OPTIM != 0 && auxSig->cout < (SL_OPTIM + 1) &&
	          delai > delaiMoyen && SL_OPTIM < 4)
	         auxSig->cout = SL_OPTIM + 1;
              else 
	         auxSig->cout = SL_OPTIM;
	   bi = CDR(bi);
	}
	auxSig->ablList = traiteBus(b->BIABL);
	addTH(mappSys->sig_hash,b->NAME,(int)auxSig);
	}

for(u = SL_BEH->BEBUX;u;u = u->NEXT)
	{
	sig *auxSig = (sig *)mbkalloc(sizeof(sig));
	biabl_list *bi;

	auxSig->type = 3;
	auxSig->name = u->NAME;
	auxSig->delais = 0;
	auxSig->capa = 0;
	auxSig->util = (chain_list *)NULL;
	auxSig->cout =0;
	bi = u->BIABL;
	while (bi)
	{
	   delai = searchTH(caracTH,bi->VALABL);
           if (delai == EMPTYTH)
           {
              PRINTF("genBD : error bad characterization\n");
              exit(-1);
           }
	   if (inChain_list(SL_OPTIMPO,u->NAME))
	      auxSig->cout = 4;
	   else
              if (SL_OPTIM != 0 && auxSig->cout < (SL_OPTIM + 1) &&
	          delai > delaiMoyen && SL_OPTIM < 4)
	         auxSig->cout = SL_OPTIM + 1;
              else 
	         auxSig->cout = SL_OPTIM;
	   bi = CDR(bi);
	}
	auxSig->ablList = traiteBus(u->BIABL);
	addTH(mappSys->sig_hash,u->NAME,(int)auxSig);
	}

for(r = SL_BEH->BEREG;r;r = r->NEXT)
	{
	sig *auxSig = (sig *)mbkalloc(sizeof(sig));
	biabl_list *bi;

	auxSig->type = 4;
	auxSig->name = r->NAME;
	auxSig->delais_in = -1;
	auxSig->delais = 0;
	auxSig->capa = 0;
	auxSig->util = (chain_list *)NULL;
	auxSig->cout =0;
	bi = r->BIABL;
	while (bi)
	{
	   delai = searchTH(caracTH,bi->VALABL);
           if (delai == EMPTYTH)
           {
              PRINTF("genBD : error bad characterization\n");
              exit(-1);
           }
	   if (inChain_list(SL_OPTIMPO,r->NAME))
	      auxSig->cout = 4;
	   else
              if (SL_OPTIM != 0 && auxSig->cout < (SL_OPTIM + 1) &&
	          delai > delaiMoyen && SL_OPTIM < 4)
	         auxSig->cout = SL_OPTIM + 1;
              else 
	         auxSig->cout = SL_OPTIM;
	   bi = CDR(bi);
	}
	auxSig->ablList = traiteReg(r->BIABL);
	addTH(mappSys->sig_hash,r->NAME,(int)auxSig);
	}
for(a = SL_BEH->BEAUX;a;a = a->NEXT)
	{
	sig *auxSig = (sig *)mbkalloc(sizeof(sig));

	auxSig->type = 2;
	auxSig->name = a->NAME;
	auxSig->delais = -1;
	auxSig->capa = 0;
	auxSig->cout = 0;
	auxSig->util = (chain_list *)NULL;
	ablsimplif = copyExpr(a->ABL);
	addArite(ablsimplif);
	auxSig->ablList = createATOM(ablsimplif);
	addTH(mappSys->sig_hash,a->NAME,(int)auxSig);
	if (!ATOM(a->ABL))
	{
	   freeExpr(a->ABL);
	   a->ABL = NULL;
	}
	}
for(i = SL_BEH->BERIN;i;i = CDR(i))
   if(testObj(i->NAME,'s'))
   	{
	del = addnum(del,i);
	}
   else
	{
	sig *auxSig = (sig *)mbkalloc(sizeof(sig));

	auxSig->type = 1;
	auxSig->name = i->NAME;
	auxSig->delais = memberDelaypi(i->NAME,SL_DELAYPI);
	auxSig->capa = 0;
	auxSig->util = (chain_list *)NULL;
	auxSig->ablList =NULL;
	auxSig->cout = 0;
	addTH(mappSys->sig_hash,i->NAME,(int)auxSig);
	}
for (d=del;d;d=CDR(d))
	SL_BEH->BERIN=beh_delberin(SL_BEH->BERIN,(berin_list *)d->DATA);
freenum(del);
destroyTH(caracTH);
}

void genDecomp(ref)
ptype_list *ref;
{
chain_list *niveau = CAR(ref);

   do
   {
   virtuelList *virtCour = (virtuelList *)(testObj((char *)niveau->DATA,'v'));
   chain_list *solAux = copyExpr(CAR(virtCour->solutions));
   ptype_list *r;
      
    if ((virtCour->delais == -1) &&
       (!ATOM(solAux) && OPER(solAux) < 10))
    {

      if (SL_TRACE)
      {printf("  genDecomp : %s, level %d\n",niveau->DATA,ref->TYPE);
	displayArite(solAux);printf("\n");}
      solAux = decomp(solAux);
      if (OPER(solAux) == XOR)
	{
	cellList *cellXor = operToCell(solAux);
	int ar = ARITE(solAux);

	if (!cellXor)
	   {
	   chain_list *sol = devXorExpr(solAux);
	   freeExpr(solAux);
	   solAux = sol;
	   addArite(solAux);
	   }
	}
      if (!equalVarExpr(CAR(virtCour->solutions),solAux))
      {
      short prof = profExpr(solAux);

	/* modifie le 23/12/92 : on ne garde qu'une solution */
	/* sauf si SL_LEVEL = 5				     */
	if (SL_LEVEL < 5 || cout(CAR(virtCour->solutions)) == -2)
	{
	   freeExpr(CAR(virtCour->solutions));
	   virtCour->solutions->DATA = (void *)solAux;
	}
	else
	  virtCour->solutions = addchain(virtCour->solutions,(void *)solAux);
	if (prof > 1)
	{
           genVar(virtCour,niveau->DATA,(short)ref->TYPE,0);
           for (r = mappSys->ref;r && (r->TYPE > ref->TYPE);r = CDR(r))
	      if ((r->TYPE < (ref->TYPE + prof)) && r->DATA)
	      {
		 if (prof > 2) genDecomp(r);
		 genInfer(r);
	      }
	}
      }
    }
    else freeExpr(solAux);
   }
   while (niveau = CDR(niveau));
}

void genInfer(ref)
ptype_list *ref;
{
chain_list *niveau = CAR(ref);

   do
   {
   virtuelList *virtCour = (virtuelList *)(testObj((char *)niveau->DATA,'v'));
   ptype_list *p,*sol1 = NULL,*sol2,*sol3 = NULL;
   chain_list *sauv = NULL;
   int nbSol;
      
      if (virtCour->delais == -1)
      {
         if (SL_TRACE)
	 printf("  genInfer : %s, level %d\n",niveau->DATA,ref->TYPE);
	 for (nbSol = 1;nbSol <= SL_LEVEL;nbSol++)
	 {
	 chain_list *val = remp((char *)niveau->DATA,CAR(virtCour->solutions),nbSol);

	    if (!sauv || !equalVarExpr(val,sauv))
	    {
	       if (sauv) freeExpr(sauv);
	       sauv = copyExpr(val);
	       sol2 = evalue(val);
	       for (p = sol2;p;p = CDR(p))
		  if (findEqual(CAR(p),sol1))
		     freeExpr(CAR(p));
		  else
		     sol1 = addptype(sol1,p->TYPE,p->DATA);
	        freeptype(sol2);
     	    }
	 }
	 sauv = NULL;
	 if (SL_LEVEL == 5)
	 {
	  if (CDR(virtCour->solutions))
            if (ARITE(CADR(virtCour->solutions)) < 5)
	  {
	  for (nbSol = 1;nbSol <= SL_LEVEL;nbSol++)
	  {
	  chain_list *val = remp((char *)niveau->DATA,CADR(virtCour->solutions),nbSol);

	    if (!sauv || !equalVarExpr(val,sauv))
	    {
	       if (SL_TRACE == 2) {printf("*");displayArite(val);printf("\n");}
	       if (sauv) freeExpr(sauv);
	       sauv = copyExpr(val);
	       sol2 = evalue(val);
	       for (p = sol2;p;p = CDR(p))
		  if (findEqual(CAR(p),sol1))
		     freeExpr(CAR(p));
		  else
		     sol3 = addptype(sol3,p->TYPE,p->DATA);
	        freeptype(sol2);
     	    }
	  }
	  sol1 = (ptype_list *)append(sol1,sol3);
	  }
	  else
	  {
	  virtuelList *filsVirt;
	  chain_list *fils,*sauv,*f;

	  /* mise a jour du fanout des fils */

	    fils = CADR(virtCour->solutions);
   	    while (fils = CDR(fils))
   	    {
   	       filsVirt = (virtuelList *)testObj(VALUE_ATOM(CAR(fils)),'v');
	       if (filsVirt)
	       {
	          sauv = filsVirt->fanout;
	          while (f = sauv)
	          {
		      sauv = CDR(f);
		      if (f->DATA == niveau->DATA)
		         filsVirt->fanout = delchain(filsVirt->fanout,f);
 	          }
	       }
	    }
    	  }
	 }
         if (!sol1) 
	 {
	    fprintf(stderr,"no solution :");
	    if (virtCour->solutions)
	       displayArite(CAR(virtCour->solutions)); printf("\n");
	    exit(-1);
         }
	 /* tri des solutions par couts croissants */
	 sol2 = NULL;
	 if (CDR(sol1))
	 {
	    while (sol1)
	    {
	    ptype_list *minp = minPtype(sol1);
		sol2 = addptype(sol2,minp->TYPE,minp->DATA);
		minp->TYPE = -2;
		sol1 = delptype(sol1,minp->TYPE);
	    }
	    sol1 = (ptype_list *)reverse((chain_list *)sol2);
       	 }
	 if (SL_TRACE)
	    {
     	    printf("solutions =\n");
	    for(p = sol1;p;p = CDR(p))
	       {
	       displayArite(CAR(p));
	       printf(" = %d\n",p->TYPE);
	       }
	    }
	 /* destruction des solutions initiales */
	 for (sauv = virtCour->solutions;sauv;sauv=CDR(sauv))
	     freeExpr(CAR(sauv));
	 freechain(virtCour->solutions);
	 virtCour->solutions = (chain_list *)NULL;
	 /* sauvegarde des SL_LEVEL solution (couts decroissants) */
	 p = sol1;
	 for (nbSol = 1;nbSol <= SL_LEVEL && sol1;nbSol++)
	 {
	   if (nbSol == 1)
            virtCour->solutions = addchain(virtCour->solutions,(void *)CAR(sol1));
	   else
  	   {
            virtCour->solutions = 
		addchain(virtCour->solutions,(void *)remp((char *)NULL,CAR(sol1),1));
            freeExpr(CAR(sol1));
	   }
	    sol1 = CDR(sol1);
	 }
	 /* inversion de la liste (couts croissants) */
	 virtCour->solutions = reverse(virtCour->solutions);
	 libere(sol1,p);
         genVar(virtCour,niveau->DATA,(short)ref->TYPE,1);
      }
   }
   while (niveau = CDR(niveau));
}

void mapper()
{
berin_list *i;
beout_list *o;
bereg_list *r,*sauvr;
bebus_list *b;
bebux_list *u;
beaux_list *a,*sauv;
pElemTH pEl;
int mode,j;
chain_list *optimpo;

   genBd();
   for (optimpo = SL_OPTIMPO;optimpo;optimpo = CDR(optimpo))
        traiteExpLog((sig *)testObj((char *)optimpo->DATA,'s'),4);
   for(r = SL_BEH->BEREG;r;r = r->NEXT)
	traiteExpLog((sig *)testObj(r->NAME,'s'),-1);
   for(b = SL_BEH->BEBUS;b;b = b->NEXT)
	traiteExpLog((sig *)testObj(b->NAME,'s'),-1);
   for(u = SL_BEH->BEBUX;u;u = u->NEXT)
	traiteExpLog((sig *)testObj(u->NAME,'s'),-1);
   /* on traite d'abord les sorties reliees directement a un
      signal interne 22/07/93 */
   for(o = SL_BEH->BEOUT;o;o = o->NEXT)
   {
   sig *bidon = (sig *)testObj(o->NAME,'s');
      if (ATOM(CAR(bidon->ablList)))
	traiteExpLog(bidon,-1);
   }

   for (mode = 5;mode;mode--)
      for(o = SL_BEH->BEOUT;o;o = o->NEXT)
      {
      sig *signal = (sig *)testObj(o->NAME,'s');
	   if (signal->cout == mode-1 ) traiteExpLog(signal,-1);
      }

   /* calcul des capas des entrees */

   for(i = SL_BEH->BERIN;i;i = i->NEXT)
   {
   chain_list *fan;
   sig *sigAux = (sig *)testObj(i->NAME,'s');

	for (fan = sigAux->util;fan;fan = CDR(fan))
	  if (testObj((char *)fan->DATA,'v'))
	  sigAux->capa += entrance((virtuelList *)testObj((char *)fan->DATA,'v'),i->NAME);
   }

   /* calcul des capas des portes */

   pEl = mappSys->virt_hash->pElem; 
   for (j=0;j<mappSys->virt_hash->length;j++)
    {
       if ((pEl->value != VIDETH) && (pEl->value != DELETETH))
        {
	   capa(pEl->key,(virtuelList *)(pEl->value));
	}
       pEl++;
    }

   /* calcul du delai RC */
/*
   pEl = mappSys->virt_hash->pElem; 
   for (j=0;j<mappSys->virt_hash->length;j++)
    {
       if ((pEl->value != VIDETH) && (pEl->value != DELETETH))
        {
	virtuelList *virt = (virtuelList *)pEl->value;
	   delRC(virt,CAR(virt->solutions));
	}
       pEl++;
    }
*/
   /* suppression des auxilliaires non utilises (et du virtuel correspondant) */

   if (!SL_AUX)
   {
      for(a = SL_BEH->BEAUX;a;a = sauv)
      {
      virtuelList *virt = (virtuelList *)testObj(a->NAME,'v');
   
	  sauv = CDR(a);
          if (virt &&
              (!(virt->fanout) || (virt->fanout) && !CDR(virt->fanout)))
          {
          sig *signal = (sig *)testObj(a->NAME,'s');

	     if (virt->fanout)
	     {
	        freechain(virt->fanout);
	        virt->fanout = NULL;
	     }
             suppVirtuel(a->NAME,NULL);
	     freechain(signal->ablList);
	     deleteTH(mappSys->sig_hash,signal->name);
	     if (SL_TRACE) printf("%s removed\n",a->NAME);
	     SL_BEH->BEAUX = beh_delbeaux(SL_BEH->BEAUX,a,'N');
	     mbkfree(signal);
          }
      }
   }
   /* suppression des registres non utilises (et du virtuel correspondant) */

   for(r = SL_BEH->BEREG;r;r = sauvr)
   {
   sig *signal = (sig *)testObj(r->NAME,'s');
   virtuelList *virt = (virtuelList *)testObj(r->NAME,'v');
 
      sauvr = CDR(r);
      if (!signal->util)
      {
      biabl_list *bi ,*bid;

         PRINTF("\nWarning : Register not used : %s",r->NAME);
	 freechain(virt->fanout);
	 virt->fanout = NULL;
         suppVirtuel(r->NAME,NULL);
	 freechain(signal->ablList);
	 deleteTH(mappSys->sig_hash,signal->name);
         
/* on fait manuellement ce que certains ne savent pas faire ... */
         for(bid = r->BIABL;bid;bid = bi)
 	 {
	    bi = CDR(bid);
	    mbkfree(bid);
	 }
	 r->BIABL = NULL;
	 beh_frebinode(r->BINODE);
	 r->BINODE = NULL;
	 SL_BEH->BEREG = beh_delbereg(SL_BEH->BEREG,r,'N');
	 mbkfree(signal);
      }
         
   }
   newBefig();
   statistiques();
}

chain_list *signauxFils(expr)
chain_list *expr;

{
if (ATOM(expr))
	{
	sig *signal = (sig *)testObj(VALUE_ATOM(expr),'s');

	if (signal && (signal->delais == -1))
		return createATOM(VALUE_ATOM(expr));
	return NULL;
	}
else
	{
	chain_list *args,*liste = NULL;

	for(args = CDR(expr);args;args = CDR(args))
		liste = append(liste,signauxFils(CAR(args)));
	return liste;
	}
}

void traiteExpLog(inst,coutSig)
sig *inst;
short coutSig;
{
   if ((inst->delais == -1) || (inst->type == 3) || (inst->type == 4))
   {
	chain_list *ref;
	int max_del = 0;

      /* coutSig = cout local d'un signal */
      if (coutSig == -1) coutSig = inst->cout;
      else inst->cout = coutSig;

      for (ref = inst->ablList; ref; ref = ref->NEXT)
	if (ATOM(CAR(ref)))
	{
	   sig *sigRef =(sig *)testObj(VALUE_ATOM(CAR(ref)),'s');
	   virtuelList *virt;

	   if (sigRef)
	   {
	    if (sigRef->delais == -1) traiteExpLog(sigRef,coutSig);
	    virt = (virtuelList *)testObj(VALUE_ATOM(CAR(ref)),'v');
	    if (max_del < sigRef->delais)
	       max_del = sigRef->delais;
	    sigRef->util = addchain(sigRef->util,(void *)inst->name);
	    if ((sigRef->type != 1) && virt)
	       virt->fanout = addchain(virt->fanout,(void *)inst->name);
	   }
	   else			/* cas du '0' ou du '1'	*/
	   {
		inst->delais = 0;
	   }
	   if (SL_TRACE)
	      printf("==> %s = %s\n",inst->name,VALUE_ATOM(CAR(ref)));
	}
	else
	{
		chain_list *sigFils = signauxFils(CAR(ref)),*aux = sigFils;
		int del;

		while (sigFils)
 		   {
		   traiteExpLog((sig *)testObj((char *)sigFils->DATA,'s'),coutSig);
		   sigFils = CDR(sigFils);
 		   }
	        freechain(aux);
		parcours(inst,ref);
		del = ((virtuelList *)testObj(VALUE_ATOM(CAR(ref)),'v'))->delais;
		if (max_del < del) 
		   max_del =  del;
	}
	if ((inst->type == 3) || (inst->type == 4))
	{
	   inst->delais_in = max_del;
	   inst->delais = 0;
	}
	else
	   inst->delais = max_del;
   }
}

chain_list *traiteBus(biabl)
biabl_list *biabl;

{
chain_list *head = (chain_list *)NULL,*ablsimplif;
biabl_list *b;

   for(b = biabl;b;b = b->NEXT)
   {
   chain_list * aux = createExpr(searchNumOper(nameBus));

	ablsimplif = copyExpr(b->CNDABL);
	addHExpr(aux,ablsimplif);
	ablsimplif = b->VALABL;
	addHExpr(aux,ablsimplif);
	addArite(aux);
	head = addchain(head,(void *)aux);
	b->VALABL = NULL;
   }
   return head;
}

chain_list *traiteReg(biabl)
biabl_list *biabl;

{
chain_list *aux,*ablsimplif;
chain_list *head = NULL;
biabl_list *b;

if (biabl->USER)
   aux = createExpr(searchNumOper(nameBD));
else
   aux = createExpr(searchNumOper(nameLatch));

for(b = biabl;b;b = b->NEXT)
	{
	ablsimplif = copyExpr(b->CNDABL);
	addHExpr(aux,ablsimplif);
	ablsimplif = b->VALABL;
	addHExpr(aux,ablsimplif);
	b->VALABL = NULL;
	b->CNDABL = NULL;
	}
addArite(aux);
return addchain(head,(void *)aux);
}

void parcours(signal,abl)
sig *signal;
chain_list *abl;
{
ptype_list *r;
chain_list *expr = CAR(abl);
int nbCells = mappSys->virt_hash->count;

   mappSys->coutSig = signal->cout;
   if (SL_TRACE)
      printf("=> %s ",signal->name);
   genDelta(signal);
   if (SL_TRACE) printf("  Delta = %d\n",mappSys->delta);
   genArbo(expr,signal,1,0);
   for(r = mappSys->ref;r;r = r->NEXT)
      if (r->DATA)
      {
         genDecomp(r);
         genInfer(r);
      }
   supp();
   geleVirtuel(signal,abl);
   if (SL_TRACE)
      printf("(%d)\n",(mappSys->virt_hash->count - nbCells));
   else
      {
      PRINTF(".");
      fflush(stdout);
      }
}

ptype_list *evalue(expr1)
chain_list *expr1;
{
char *declName = searchCharOper(OPER(expr1));
declenList *decl;
regle_list *reg;
ptype_list *res;
int funcNormExpr();
ptype_list *p;
chain_list *abl,*zero,*un;

   /* Traitement des cas "(not 0)" et "(not 1)" */

   zero = createATOM(nameZero);
   un = createATOM(nameUn);
   if (equalExpr(expr1,abl = inversArg(zero)))
   {
      freechain(zero);
      freeExpr(abl);
      return addptype((ptype_list *)NULL,(long)0,(void *)un);
   }
   if (equalExpr(expr1,abl = inversArg(un)))
   {
      freechain(un);
      freeExpr(abl);
      return addptype((ptype_list *)NULL,(long)0,(void *)zero);
   }
   freechain(zero);
   freechain(un);

   /* assignation des entrees de expr1 et calcul de son cout */
   expr1 = triVar(copyExpr(expr1));
   res = addptype((ptype_list *)NULL,cout(expr1),(void *)copyExpr(expr1));

   /* recherche du declencheur */
   decl = mappSys->ptdecl;
   while (decl && (declName != decl->name)) decl = decl->NEXT; 

   /* normalisation de l'expression */
   
   if ((searchCharOper(OPER(expr1)) !=  nameLatch) &&
       (searchCharOper(OPER(expr1)) != nameBD) &&
       (searchCharOper(OPER(expr1)) != nameBus))
      sort2Expr(expr1,funcNormExpr,delais,1,0);
   if (!decl) 
   {
      PRINTF("no declencheur for this expression\n");
      displayArite(expr1);printf("\n");
   }
   else
   /* cas ou le declencheur est uniquement dans "pol" */
   /* bibliotheques reduites... */
   if (!decl->regles && OPER(expr1) != XOR)
   {
   short ok;
   chain_list *expr3,*expr2 = copyExpr(expr1);

      expr3 = polarite(expr2);
      ok = cout(expr3);
      if (expr3 != expr2 && ok != -2)
         res = addptype(res,ok,(void *)expr3);
      else freeExpr(expr2);
   }
   else
   for (reg = decl->regles;reg;reg = reg->NEXT)
   {
   chain_list *result = moteur(reg,expr1);

      if (result) res = addptype(res,cout(result),(void *)result);
   }
   freeExpr(expr1);	/* modif 23/07/93 : il faut recopier expr1 */
   while ((p = getptype(res,-2)) != NULL)
   {
   	freeExpr(CAR(p));
        res = delptype(res,(long)-2);
   }
   if (res && CDR(res))
   {
		/* mise en tete de la solution de cout min */
   ptype_list *minp = minPtype(res);

      res = addptype(res,minp->TYPE,minp->DATA);
      minp->TYPE = -2;
      res = delptype(res,minp->TYPE);
   }
   return res;
}

void libere(sol,head)
ptype_list *sol,*head;
{

   while (sol)
   {
      sol->TYPE = 0;
      freeExpr(CAR(sol));
      sol = CDR(sol);
   }
   freeptype(head);
}

chain_list *polarite(expr)
chain_list *expr;
{
char *declName = namealloc("pol");
declenList *decl;
regle_list *reg;

decl = mappSys->ptdecl;
while (decl && (declName != decl->name)) decl = decl->NEXT; 

reg = decl->regles;
while (reg && ((OPER(reg->premisse) != OPER(expr))
           || (ARITE(reg->premisse) != ARITE(expr))))
    reg = reg->NEXT;

if (reg)
{
   Alist *var = createAlist(NULL,reg->premisse);
   chain_list *res;

   filtre(reg->premisse,expr,var);
   ssExprArite(reg->premisse,var);

   res = remplace(reg->conclusion,var);
   freeExpr(expr);
   freeAlist(var);
if (SL_TRACE)
    {
    res = triVar(res);
    printf("Polarity ");
    displayArite(res);printf("\n");
    }
   return res;
}
return triVar(expr);
}
