#include MUT_H
#include LOG_H
#include BEH_H
#include "c4_local.h"
#include "c4.h"


/******************************************************************************
 ***  Version 1.0b02                                            14/06/1991  ***
 ******************************************************************************

 ******************************************************************************
 ******************************************************************************
 ***									    ***
 ***				c.c.c.c tools				    ***
 ***			Complex Cmos Cells Compiler			    ***
 ***									    ***
 ******************************************************************************
 ******************************************************************************

 ******************************************************************************
 ***                            MAIN  MODULE                                ***
 ******************************************************************************/


/*----------------------------------------------------------------------------
  -------- very low-level func -------------------------[genFiles/genBehave]--
  ----------------------------------------------------------------------------
  SYNTAX : chain_list *expr2Model(chain_list*)
  ----------------------------------------------------------------------------
  EXEMPLE : modelExpr = expr2Model(expr)
  ----------------------------------------------------------------------------
  FONCTION :
  ----------------------------------------------------------------------------
  ERROR : none
  ----------------------------------------------------------------------------*/

/*:::::::::::::::::::::::::: start of genFiles  ::::::::::::::::::::::::::::::*/

chain_list *expr2ModelInt(expr,i)
chain_list *expr;
int *i;
{
  chain_list *pt, *ptrTmp;

  if (ATOM(expr))
    if (VALUE_ATOM(expr) != _C4cutSymb)
      {
      pt =  createAtom(genNAME("%s%d", IN_SYMB, *i));
      *i = *i + 1;
      return pt;
      }
    else
      return NULL;
  else
    pt = createExpr(OPER(expr));
    while (expr = CDR(expr)) {
      ptrTmp = expr2ModelInt(CAR(expr),i);
      if (ptrTmp != NULL)
        addQExpr(pt, ptrTmp);
    }
    return pt;
}

chain_list *expr2Model(expr)
chain_list *expr;
{
int i=0;
return expr2ModelInt(expr,&i);
}


/*::::::::::::::::::::::::::::: end of genFiles ::::::::::::::::::::::::::::::*/

/*:::::::::::::::::::::::::: start of defMemFig ::::::::::::::::::::::::::::::*/

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*
  =-=-=-=- low-level func =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-[]=-
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  SYNTAX : MemFig* defMemFig(chain_list *,char *)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  EXEMPLE : cell = memFig(expr, fileName)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  FONCTION : Create a new structure of type MemFig from the ABL expression
    expr. Initialize some other things...
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  ERROR : if the malloc abort.						exit
          if expr = NULL.						cont
 *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/

MemFig *defMemFig(expr, fileName)
chain_list *expr;
char *fileName;
{
  MemFig *cell;
  register short i;

  if ((cell = (MemFig *)malloc((unsigned)sizeof(MemFig))) == NULL) {
    (void)fprintf(stderr, "\nc4_Error : malloc failed. [defMemFig]\n\n");
    exit(-1);
  }
  else {
    if (expr == NULL) {
      (void)fprintf(stderr, "\nc4_Warning : invalid  ABL ");
      (void)fprintf(stderr, "expression (NULL). [defMemFig]\n\n");
      return NULL;
    }
    else
      cell->inExprABL = copyExpr(expr);
    _C4cutSymb = namealloc(CUT_SYMB);
    for (i = 0; i < MAX_EQ; i++) {
      cell->mRout[N_GRAPH][i] = NULL;
      cell->mRout[P_GRAPH][i] = NULL;
    }
    for (i = 0; i < MAX_H_PITCH; i++)
      cell->tGraph[i] = NULL;
    cell->assocList = NULL;
    cell->fName = namealloc(fileName);
    cell->result = (ResCheck *)  malloc (sizeof (ResCheck));
    cell->result->polarity  = 2;
    cell->result->nbTPSer = 0;
    cell->result->nbTNSer = 0;
    cell->result->nbNot   = 0;
    cell->status.checkExprOK = 0;
    cell->status.placeInputsOK = 0;
    cell->status.createInterconOK = 0;
    cell->status.routTransOK = 0;
    cell->nbCut = 0;
    cell->nbEq[P_GRAPH] = 0;
    cell->nbEq[N_GRAPH] = 0;
    cell->status.defMemFigOK = 1;
    cell->segInv.xPos = -1;
    cell->segInv.y1 = -1;
    cell->segInv.y2 = -1;
    cell->segTrsp.xPos = -1;
    cell->nbCh[P_GRAPH] = 0;
    cell->nbCh[N_GRAPH] = 0;
    cell->nbMaxCh[P_GRAPH] = -1;
    cell->nbMaxCh[N_GRAPH] = -1;
    return cell;
  }
}

/*:::::::::::::::::::::::::::: end of defMemFig ::::::::::::::::::::::::::::::*/

/*::::::::::::::::::::::::::: start of checkExpr :::::::::::::::::::::::::::::*/

/*----------------------------------------------------------------------------*
  -------- very low-level func -----------------------[ checkExpr\flatOper ]--
  ----------------------------------------------------------------------------
  SYNTAX : short posOper(short)
  ----------------------------------------------------------------------------
  EXEMPLE : newOper = posOper(oldOper);
  ----------------------------------------------------------------------------
  FONCTION : If oldOper = AND, OR, XOR or NOT operator, then return oldOper.
    If oldOper = NAND, NOR or NXOR, then return the positive equivalent
    operator (i.e. AND, OR or XOR).
  ----------------------------------------------------------------------------
  ERROR : if unknown operators						exit
 *----------------------------------------------------------------------------*/

short posOper(oper)
short oper;
{
  switch (oper) {
    case OR :
    case AND :
    case XOR :
    case NOT :
      return oper;
    case NOR :
      return OR;
    case NAND :
      return AND;
    case NXOR :
      return XOR;
    default :
      (void)fprintf(stderr, "\nc4_Error : unknown operator ");
      (void)fprintf(stderr, "'%s'. [posOper]\n\n", operToChar(oper));
      exit(-1);
  }
}

/*----------------------------------------------------------------------------*
  -------- very low-level func --------------------------------[ checkExpr ]--
  ----------------------------------------------------------------------------
  SYNTAX : chain_list *flatOper(chain_list *)
  ----------------------------------------------------------------------------
  EXEMPLE : expr = flatOper(expr, signe);
  ----------------------------------------------------------------------------
  FONCTION : Flat all the operators in the expression expr. The expression
    returned olny contain NOT, OR and AND operators. If signe = NEG, the
    transformation is done and the complemeted expression, if signe = POS,
    on the expression itself.
  ----------------------------------------------------------------------------
  ERROR : if unknown operators						exit
          if arity of NOT expression > 1				exit
          if arity of AND, OR or XOR expression < 2			exit
 *----------------------------------------------------------------------------*/

chain_list *flatOper(expr, signe)
chain_list *expr;
short signe;
{
  short op, nbArg;
  chain_list *pt;

  if (ATOM(expr))
    return createAtom(VALUE_ATOM(expr));
  else {
    op = OPER(expr);
    if (op == OR || op == AND || op == XOR || op == NOT || signe == NEG) 
      {
      pt = createExpr(posOper(op));
      nbArg = 0;
      while (expr = CDR(expr))
        {
        nbArg++;
        addQExpr(pt, flatOper(CAR(expr), POS));
        }
      if (op == XOR || op == NXOR)
        pt = devXorExpr(pt);
      return pt;
      }
    else 
      {
      pt = createExpr(NOT);
      addQExpr(pt, flatOper(expr, NEG));
      return pt;
      }
  }
}

/*----------------------------------------------------------------------------*
  -------- very low-level func --------------------------------[ checkExpr ]--
  ----------------------------------------------------------------------------
  SYNTAX : void lowCheckExpr(chain_list *, ResCheck *)
  ----------------------------------------------------------------------------
  EXEMPLE :  lowCheckExpr(expr,checkRes);
  ----------------------------------------------------------------------------
  FONCTION : Check a boolean expression. The result is modified in a Rescheck
    pointer. The syntax of the expression is supposed to be correct.
  ----------------------------------------------------------------------------
  ERROR : if more than MAX_T_SER serial tansistors			exit
 *----------------------------------------------------------------------------*/

void lowCheckExpr(expr,res)
chain_list *expr;
ResCheck *res;
{
  ResCheck resToRet;
  short operExpr;

  resToRet.nbTNSer = 0;
  resToRet.nbTPSer = 0;
  if (!ATOM(expr)) 
    {			/* process expression */
    operExpr = OPER(expr);

    if (operExpr == NOT)
      res->nbNot = res->nbNot + 1;

    while (CDR(expr)) {
      lowCheckExpr(CAR((expr = CDR(expr))),res);
      switch (operExpr) {		/* calculate number of serial trans.
					in both graph, depending of the
					operator */
        case AND :
          resToRet.nbTPSer = MAX(res->nbTPSer, resToRet.nbTPSer);
          resToRet.nbTNSer = res->nbTNSer + resToRet.nbTNSer;
          break;
        case OR  :
          resToRet.nbTNSer = MAX(res->nbTNSer, resToRet.nbTNSer);
          resToRet.nbTPSer = res->nbTPSer + resToRet.nbTPSer;
          break;
        case NOT :
          resToRet.nbTPSer = resToRet.nbTNSer = 1;
          break;
      }
    }
    if ((resToRet.nbTPSer > MAX_T_SER) || (resToRet.nbTNSer > MAX_T_SER)) {
      (void)fprintf(stderr, "\nc4_Error : more than %d serial ", MAX_T_SER);
      (void)fprintf(stderr, "trans; change define ");
      (void)fprintf(stderr, "MAX_T_SER. [lowCheckExpr]\n\n");
      exit(-1);
    }
  res->nbTPSer = resToRet.nbTPSer;
  res->nbTNSer = resToRet.nbTNSer;
  }
  else				/* Atomic Process */
    res->nbTPSer = res->nbTNSer = 1;
}

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*
  =-=-=-=- low-level func =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-[]=-
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  SYNTAX : void checkExpr(MemFig *)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  EXEMPLE : checkExpr(cell)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  FONCTION : Change the form of the expression (in cell->inExprABL), if
    possible, to obtain a expression containing only OR and AND operators;
    this transformed expression is then stored into th field cell->trExprABL.
    The Rescheck structure of cell (field cell->result) is set with the good
    values. The field cell->nbInp is also set.
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  ERROR : if defMemFig not successfully achieved.			cont
          if cell = NULL.						cont
 *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/

void checkExpr(cell)
MemFig *cell;
{
  chain_list *tmp1ExprABL, *tmp2ExprABL;
  chain_list *support;

  if (cell == NULL) {
    (void)fprintf(stderr, "\nc4_Warning : Input param of checkExpr is NULL. ");
    (void)fprintf(stderr, "[checkExpr]\n\n");
    return;
  }
  else
    if (!(cell->status.defMemFigOK)) {
      (void)fprintf(stderr, "\nc4_Warning : defMemFig hasn't successfully ");
      (void)fprintf(stderr, "achieved. [checkExpr]\n\n");
      return;
    }
  tmp1ExprABL = flatOper(cell->inExprABL, POS);
  tmp2ExprABL = flatPolarityExpr(tmp1ExprABL, POS);
  freeExpr(tmp1ExprABL);
  lowCheckExpr(tmp2ExprABL,cell->result);
  cell->nbInp = numberAtomExpr(tmp2ExprABL);;

		/* search polarity */

  if (cell->result->nbNot == 0)
     cell->result->polarity = POS;
  else
     if (cell->result->nbNot == cell->nbInp)
        cell->result->polarity = NEG;
     else
        cell->result->polarity = NOT_POSNEG;
       
  if (((cell->result)->polarity) == NEG) {
    cell->inExprABL = flatPolarityExpr(tmp2ExprABL, NEG);
    cell->trExprABL = copyExpr(cell->inExprABL);
    freeExpr(tmp2ExprABL);
  }
  else
    if (((cell->result)->polarity) == POS) {
      cell->inExprABL = tmp2ExprABL;
      cell->trExprABL = copyExpr(cell->inExprABL);
    }
    else
      freeExpr(tmp2ExprABL);
  cell->status.checkExprOK = (cell->result->polarity != NOT_POSNEG);
}

/*:::::::::::::::::::::::::::: end of checkExpr ::::::::::::::::::::::::::::::*/

/*:::::::::::::::::::::::::: start of placeInputs ::::::::::::::::::::::::::::*/

/*----------------------------------------------------------------------------
  -------- very low-level func -------[placeInputs\lowPlaceInputs\placeArgs]--
  ----------------------------------------------------------------------------
  SYNTAX : void permutExpr(chain_list *)
  ----------------------------------------------------------------------------
  EXEMPLE : permutExpr(expr)
  ----------------------------------------------------------------------------
  FONCTION : Permut all the atoms of the expression expr without, of course,
    changing the logical function.
  ----------------------------------------------------------------------------
  ERROR : none
  ----------------------------------------------------------------------------*/

void permutExpr(expr)
chain_list *expr;
{
  register short index;
  short arity;
  chain_list *tmpExpr, *insExpr;

  arity = lengthExpr(expr);
  insExpr = expr;
  for (index = 0; index < arity; index++) insExpr = CDR(insExpr);
  for (index = 1; index < arity; index++) {
    if (!ATOM((CAR((CDR(expr))))))
      permutExpr(CAR((CDR(expr))));
    tmpExpr = CDR((CDR(expr)));
    CDR((CDR(expr))) = CDR(insExpr);
    CDR(insExpr) = CDR(expr);
    CDR(expr) = tmpExpr;
  }
  if (!ATOM((CAR((CDR(expr))))))
    permutExpr(CAR((CDR(expr))));
}

/*----------------------------------------------------------------------------
  -------- very low-level func -----------------[placeInputs\lowPlaceInputs]--
  ----------------------------------------------------------------------------
  SYNTAX : short placeArgs(chain_list[4][MAX_T_SER] **, short[4])
  ----------------------------------------------------------------------------
  EXEMPLE : cutTyp = placeArgs(tabCut,indexCut)
  ----------------------------------------------------------------------------
  FONCTION : Place the arguments of an expression according to the
    'Uehara-Vancleemput' heuristic. Each argument is valued with a number that
    means that this argument is a 'cone' with no cut (NO_CUT=0), with one cut
    at right side (RIGHT_CUT=1), or with two cuts at both sides
    (RIGHLEFT_CUTS=2).  indexCut[i] is the number of cones of type i (n.b. for
    i=EVERY_CUT=3, indexCut[3] is the number of arguments). tabCut[i][j] is an
    array that contains a pointer to a pointer to the argument (atome or
    expression) of type i and of order j.
  ----------------------------------------------------------------------------
  ERROR : none
  ----------------------------------------------------------------------------*/

short placeArgs(tabCutA, nbCut)
short nbCut[4];
chain_list **tabCutA[4][MAX_T_SER];
{
  register short index, st, en;
  chain_list *tabTmp[MAX_T_SER];

  if (nbCut[NO_CUT] == nbCut[EVERY_CUT])/* case of only NO_CUT arguments, 
					so, return NO_CUT */
    return NO_CUT;
  st = 0;
  en = nbCut[EVERY_CUT] - 1;
					/* process RIGHTLEFT_CUTS arguments */	
  for (index = 0; index < nbCut[RIGHTLEFT_CUTS]; index++) {
    if (index % 2)
      tabTmp[st++] = *(tabCutA[RIGHTLEFT_CUTS][index]);
    else
      tabTmp[en--] = *(tabCutA[RIGHTLEFT_CUTS][index]);
  }
					/* process RIGHT_CUT arguments */
  for (index = 0; index < nbCut[RIGHT_CUT]; index ++) 
    if ((index % 4) < 2) {
      if (index == 0)
        tabTmp[en--] = *(tabCutA[RIGHT_CUT][index]);
      else
        tabTmp[st++] = *(tabCutA[RIGHT_CUT][index]);
      if (((index % 4) == 1) || ((index % 4) == 2))
        permutExpr(tabTmp[st - 1]);
    }
    else {
      tabTmp[en--] = *(tabCutA[RIGHT_CUT][index]);
      if (((index % 4) == 1) || ((index % 4) == 2))
        permutExpr(tabTmp[en + 1]);
    }
					/* process NO_CUT arguments */
  for (index = 0; index < nbCut[NO_CUT]; index++)
    tabTmp[st++] = *(tabCutA[NO_CUT][index]);
  for (index = 0; index < nbCut[EVERY_CUT]; index++)
    *(tabCutA[EVERY_CUT][index]) = tabTmp[index];
  if ((nbCut[RIGHT_CUT] + nbCut[RIGHTLEFT_CUTS]) > 1)
    return RIGHTLEFT_CUTS;
  else
    return nbCut[1] + nbCut[2];
}

/*----------------------------------------------------------------------------
  -------- very low-level func --------------------------------[placeInputs]--
  ----------------------------------------------------------------------------
  SYNTAX : short lowPlaceInputs(chain_list *)
  ----------------------------------------------------------------------------
  EXEMPLE : cutType = lowPlaceInputs(expr)
  ----------------------------------------------------------------------------
  FONCTION : Process the arguments of the expression recursively to apply the
    'Uehara-Vancleemput' heuristic. Add phantom-inputs when the arity is even.
  ----------------------------------------------------------------------------
  ERROR : none
  ----------------------------------------------------------------------------*/

short lowPlaceInputs(expr)
chain_list *expr;
{
  short res, arity, index[4];
  chain_list **tabCutArg[4][MAX_T_SER];
  chain_list *tmpExpr;

  index[NO_CUT] =
  index[RIGHT_CUT] =
  index[RIGHTLEFT_CUTS] =
  index[EVERY_CUT] = 0;
  if (!ATOM(expr)) {
    tmpExpr = expr;
    arity = lengthExpr(expr);
    CDR((CAR(expr))) = (chain_list *) arity;
    while (expr = CDR(expr)) {
      res = lowPlaceInputs(CAR(expr));
      tabCutArg[res][index[res]++] = (chain_list **) &(expr->DATA);
      tabCutArg[EVERY_CUT][index[EVERY_CUT]++] = (chain_list **)&(expr->DATA);
    }
    res = placeArgs(tabCutArg, index);
					/* ad phantom-input if needed */
    if ((!(index[EVERY_CUT] % 2)) && (res == NO_CUT)) {
      addQExpr(tmpExpr, createAtom(_C4cutSymb));
      return RIGHT_CUT;
    }
    else
      return res;
  }
  else
    return NO_CUT; 
}

/*----------------------------------------------------------------------------
  -------- very low-level func ----------------------[placeInputs/assocList]--
  ----------------------------------------------------------------------------
  SYNTAX : chain_list *makeInList(chain_list *)
  ----------------------------------------------------------------------------
  EXEMPLE : inList = makeInList(expr)
  ----------------------------------------------------------------------------
  FONCTION :
  ----------------------------------------------------------------------------
  ERROR : none
  ----------------------------------------------------------------------------*/

chain_list *makeInList(expr)
chain_list *expr;
{
  chain_list  *resLst, *inList = NULL, *inLst;

  if (ATOM(expr))
    if (VALUE_ATOM(expr) != _C4cutSymb)
      return addchain(NULL, namealloc(VALUE_ATOM(expr)));
    else
      return  NULL;
  else {
    while (expr = CDR(expr))
      if (inList == NULL)
        inList = makeInList(CAR(expr));
      else {
        inLst = inList;
        while (inLst->NEXT)
          inLst = inLst->NEXT;
        inLst->NEXT = makeInList(CAR(expr));
    }
    return inList;
  }
}

/*----------------------------------------------------------------------------
  -------- very low-level func --------------------------------[placeInputs]--
  ----------------------------------------------------------------------------
  SYNTAX : chain_list *assocList(chain_list *, chain_list *)
  ----------------------------------------------------------------------------
  EXEMPLE : assList = assocList(expr1, expr2)
  ----------------------------------------------------------------------------
  FONCTION :
  ----------------------------------------------------------------------------
  ERROR : none
  ----------------------------------------------------------------------------*/

chain_list *assocList(firstExpr, placeExpr)
chain_list *firstExpr, placeExpr;
{
  chain_list *firList, *fList, *plaList, *pList, *assList = NULL, *tmpL;
  short ind;

  firList = makeInList(firstExpr);
  plaList = makeInList(placeExpr);
  pList = plaList;
  while (pList) {
    tmpL = firList;
    ind = 0;
    while (tmpL->DATA != pList->DATA) {
      tmpL = tmpL->NEXT;
      ind++;
    }
    if (assList == NULL)
      assList = addchain(NULL, (void *)ind);
    else {
      tmpL = assList;
      while (tmpL->NEXT)
        tmpL = tmpL->NEXT;
      tmpL->NEXT = addchain(NULL, (void *)ind);
    }
    pList = pList->NEXT;
  }
  freechain(firList);
  freechain(plaList);
  return assList;
}

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*
  =-=-=-=- low-level func =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-[]=-
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  SYNTAX : void placeInputs(MemFig *)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  EXEMPLE : placeInputs(cell)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  FONCTION : Apply the 'Uehara-Vancleemputs' heuristic on the expression (in
    cell->trExprABL). Some phantom-inputs are added; this inputs are then
    named with the var 'cutSymb'.
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  ERROR : if checkExpr not successfully achieved.			cont
          if cell = NULL.						cont
 *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/

void placeInputs(cell)
MemFig *cell;
{
  chain_list *tmpExprABL, *iL;

  if (cell == NULL) {
    (void)fprintf(stderr, "\nc4_Warning : Input param of placeInputs is ");
    (void)fprintf(stderr, "NULL. [placeInputs]\n\n");
    return;
  }
  tmpExprABL = cell->trExprABL;
  (void)lowPlaceInputs(tmpExprABL);
  cell->trExprABL = tmpExprABL;
  cell->assocList = assocList(cell->inExprABL, cell->trExprABL);
  cell->status.placeInputsOK = 1;
}

/*:::::::::::::::::::::::::: end of placeInputs ::::::::::::::::::::::::::::::*/

/*:::::::::::::::::::::::: start of createIntercon :::::::::::::::::::::::::::*/

/*----------------------------------------------------------------------------
  -------- very low-level func ----------------[createIntercon\lowCreateInt]--
  ----------------------------------------------------------------------------
  SYNTAX : short getNewNoEq(char)
  ----------------------------------------------------------------------------
  EXEMPLE : newNbEquip = getNewNoEq(grTyp)
  ----------------------------------------------------------------------------
  FONCTION : Return the next free number of equip for the grTyp graph.
  ----------------------------------------------------------------------------
  ERROR : none
  ----------------------------------------------------------------------------*/

short getNewNoEq(graphType)
char graphType;
{
  return (graphType == P_GRAPH) ? pEqIndex++ : nEqIndex++;
}

/*----------------------------------------------------------------------------
  -------- very low-level func -----[createIntercon\lowCreateInter\newTrans]--
  ----------------------------------------------------------------------------
  SYNTAX : void insertCont(short, short, char, MetalEq, short[2])
  ----------------------------------------------------------------------------
  EXEMPLE : insertCont(noEq, xPos, gTyp, mRout, nbEq)
  ----------------------------------------------------------------------------
  FONCTION : Calculate and insert the position of each contact between diff
    and routing segment.
  ----------------------------------------------------------------------------
  ERROR : if the malloc abort.						exit
  ----------------------------------------------------------------------------*/

void insertCont(eq, x, gTyp, mRou, nbEq)
short eq, x;
short nbEq[];
char gTyp;
MetalEq *mRou[][MAX_EQ];
{
  char insertOk;
  register short ind;

  insertOk = 0;
  for(ind = 0; ind < nbEq[gTyp]; ind++)
    if ((mRou[gTyp][ind]->noEq) == eq) {
      if (mRou[gTyp][ind]->contPos[mRou[gTyp][ind]->nbCont - 1] != x)
        mRou[gTyp][ind]->contPos[(mRou[gTyp][ind]->nbCont)++] = x;
      insertOk = 1;
    }
  if (!insertOk) {
    if ((mRou[gTyp][nbEq[gTyp]] =
          (MetalEq *)malloc((unsigned)sizeof(MetalEq))) == NULL) {
      (void)fprintf(stderr, "\nc4_Error : malloc failed. [insertCont]\n\n");
      exit(-1);
    }
    mRou[gTyp][nbEq[gTyp]]->noEq = eq;
    mRou[gTyp][nbEq[gTyp]]->noCh = -1;
    mRou[gTyp][nbEq[gTyp]]->nbCont = 1;
    mRou[gTyp][(nbEq[gTyp])++]->contPos[0] = x;
  }
}

/*----------------------------------------------------------------------------
  -------- very low-level func ----------------[createIntercon\lowCreateInt]--
  ----------------------------------------------------------------------------
  SYNTAX : void newTrans(char *, short, short, short, short, MemFig *,int *)
  ----------------------------------------------------------------------------
  EXEMPLE : newTrans(gridName, hiPEq, loPEq, hiNEq, loNEq, cell,xpos)
  ----------------------------------------------------------------------------
  FONCTION : Set a new line of the tGraph array and of the mRout array for
    each graph (cell->mRout, cell->tGraph).
  ----------------------------------------------------------------------------
  ERROR : if the malloc abort.						exit
  ----------------------------------------------------------------------------*/

void newTrans(sigGrid, hiPEq, loPEq, hiNEq, loNEq, cell,xPos)
char *sigGrid;
short hiPEq, loPEq, hiNEq, loNEq;
MemFig *cell;
int *xPos;
{

  if (inpProc == (cell->nbInp))
    return;
  if (waitCut || (sigGrid != _C4cutSymb)) {
    waitCut = (sigGrid != _C4cutSymb);
    if ((cell->tGraph[*xPos] =
          (TrGraph *)malloc((unsigned)sizeof(TrGraph))) == NULL) {
      (void)fprintf(stderr, "\nc4_Error : malloc failed. [newTrans]\n\n");
      exit(-1);
    }
    if (waitCut) {
      cell->tGraph[*xPos]->trName = sigGrid;
					/* update of tGraph */
      cell->tGraph[*xPos]->loPEq = loPEq;
      cell->tGraph[*xPos]->hiPEq = hiPEq;
      cell->tGraph[*xPos]->loNEq = loNEq;
      cell->tGraph[*xPos]->hiNEq = hiNEq;
					/* update of mRout */
      insertCont(hiPEq, *xPos, P_GRAPH, cell->mRout, cell->nbEq);
      insertCont(hiNEq, *xPos, N_GRAPH, cell->mRout, cell->nbEq);
      *xPos = *xPos + 1;
      insertCont(loPEq, *xPos, P_GRAPH, cell->mRout, cell->nbEq);
      insertCont(loNEq, *xPos, N_GRAPH, cell->mRout, cell->nbEq);
    }
    else {
      cell->tGraph[*xPos]->trName = NULL;
      cell->tGraph[*xPos]->blkType = TRSP_BLK;
      *xPos = *xPos + 1;
    }
    _C4stGr = 0;
    if (sigGrid != _C4cutSymb)
      inpProc++;
    else {
      cell->nbCut++;
      _C4stGr = 1;
    }
  }
}

/*----------------------------------------------------------------------------
  -------- very low-level func -----------------------------[createIntercon]--
  ----------------------------------------------------------------------------
  SYNTAX : void lowCreateInt(chain_list *, short, short, short, short
                                            , MemFig *,int *)
  ----------------------------------------------------------------------------
  EXEMPLE : lowCreateInter(expr, hiPEq, loPEq, hiNEq, loNEq, cell,xpos)
  ----------------------------------------------------------------------------
  FONCTION : The expression is recursively scaned, and the equip are propaged
    according to the operators (serial or parallel construction). When an atom
    is found, a call to newTrans is done.
  ----------------------------------------------------------------------------
  ERROR : none
  ----------------------------------------------------------------------------*/

void lowCreateInter(expr, hiPEq, loPEq, hiNEq, loNEq, cell,xpos)
chain_list *expr;
short hiPEq, loPEq, hiNEq, loNEq;
MemFig *cell;
int *xpos;
{
  short tmpPEq, tmpNEq, tmpPEqPred, tmpNEqPred;
  short count = 0, operOr, arity, nbArg = 0;


  if (intLev == 2)
    intLev = 0;
  else
    if (intLev == 0)
      intLev = 1;
  if (!ATOM(expr)) {
    tmpPEq = hiPEq;
    tmpNEq = hiNEq;
    operOr = (OPER(expr) == OR);
    arity = (short) CDR((CAR(expr)));
    while (expr = CDR(expr))
					/* if phantom-input */
      if ((ATOM((CAR(expr)))) && ((VALUE_ATOM((CAR(expr)))) == _C4cutSymb))
        newTrans(_C4cutSymb, NULL, NULL, NULL, NULL, cell,xpos);
      else {				/* if real input */
        if (!(arity % 2) && intLev)
          count += _C4stGr;
					/* the type of recursive call 
					is calculate with the operator, the
					order of the trans in a parallel
					construction, and the difference
					beetween the arity and the number of
					arguments already processed */
        switch (operOr * 4 + ((count++) % 2) * 2 + ((++nbArg) != arity)){
          case 0 :
            lowCreateInter(CAR(expr), hiPEq, loPEq, tmpNEq, loNEq, cell,xpos);
            break;
          case 1 :
            tmpNEqPred = tmpNEq;
            lowCreateInter(CAR(expr), hiPEq, loPEq,
                         tmpNEqPred, tmpNEq = getNewNoEq(N_GRAPH), cell,xpos);
            break;
          case 2 :
            lowCreateInter(CAR(expr), loPEq, hiPEq, tmpNEq, loNEq, cell,xpos);
            break;
          case 3 :
            tmpNEqPred = tmpNEq;
            lowCreateInter(CAR(expr), loPEq, hiPEq,
                         tmpNEqPred, tmpNEq = getNewNoEq(N_GRAPH), cell,xpos);
            break;
          case 4 :
            lowCreateInter(CAR(expr), tmpPEq, loPEq, hiNEq, loNEq, cell,xpos); 
            break;
          case 5 :
            tmpPEqPred = tmpPEq;
            lowCreateInter(CAR(expr), tmpPEqPred, tmpPEq = getNewNoEq(P_GRAPH),
                         hiNEq, loNEq, cell,xpos);
            break;
          case 6 :
            lowCreateInter(CAR(expr), tmpPEq, loPEq, loNEq, hiNEq, cell,xpos); 
            break;
          case 7 :
            tmpPEqPred = tmpPEq;
            lowCreateInter(CAR(expr), tmpPEqPred, tmpPEq = getNewNoEq(P_GRAPH),
                         loNEq, hiNEq, cell,xpos);
            break;
        }
      }
  }
  else					/* atom, call newTrans */
    newTrans(VALUE_ATOM(expr), hiPEq, loPEq, hiNEq, loNEq, cell,xpos);
}

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*
  =-=-=-=- low-level func =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-[]=-
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  SYNTAX : void createIntercon(MemFig *)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  EXEMPLE : createIntercon(cell)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  FONCTION : Create the net-list of the cells. The array of transistors
    (cell->tGraph), the array of connexion segments (cell->mRout) and the
    numbers of 'cuts' (cell->nbCut) are set. The number of internal equip of
    each graph is also set (cell->nbEq[]).
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  ERROR : if placeInputs not successfully achieved.			cont
          if cell = NULL.						cont
 *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/

void createIntercon(cell)
MemFig *cell;
{
int i=0;

  if (cell == NULL) {
    (void)fprintf(stderr, "\nc4_Warning : Input param of createIntercon is ");
    (void)fprintf(stderr, "NULL. [createIntercon]\n\n");
    return;
  }
  _C4stGr = 1;

	/* initialisation des ex-static... */

  intLev = 2;
  pEqIndex = 2;
  nEqIndex = 2;
  waitCut = 0;
  inpProc = 0;

  (void)lowCreateInter(cell->trExprABL, VDD, P_OUT, VSS, N_OUT, cell,&i);
  cell->status.createInterconOK = 1;
}

/*:::::::::::::::::::::::: end of createIntercon :::::::::::::::::::::::::::::*/

/*:::::::::::::::::::::::::: start of routTrans ::::::::::::::::::::::::::::::*/

/*----------------------------------------------------------------------------*
  -------- very low-level func ----------------------------------[routTrans]--
  ----------------------------------------------------------------------------
  SYNTAX : short setChanNo(MetalEq[2][MAX_EQ] *, short, short[2]
			   short[2])
  ----------------------------------------------------------------------------
  EXEMPLE : setChanNo(mRout, nbPitch, nbCh, indOut);
  ----------------------------------------------------------------------------
  FONCTION : 
  ----------------------------------------------------------------------------
  ERROR : none
 *----------------------------------------------------------------------------*/

void setChanNo(mRou, nbPit, nbCh, indOut)
MetalEq *mRou[][MAX_EQ];
short nbPit, nbCh[], indOut[]; 
{
  short segEnd[MAX_CHAN], delta, indCh, cp0ind, cplind;
  register short gT, i;
  char done;

  for (gT = N_GRAPH; gT <= P_GRAPH; gT++) {
    i = 0;
    while (mRou[gT][i]) {
      cplind = mRou[gT][i]->contPos[mRou[gT][i]->nbCont - 1];
      cp0ind = mRou[gT][i]->contPos[0];
      switch (mRou[gT][i]->noEq) {
        case ALIM :
          mRou[gT][i]->noCh = 0;
          break;
        case OUTPUT :
          indOut[gT] = i;
          break;
        default :
          if (mRou[gT][i]->nbCont != 1) {
            done = 0;
            delta = 2 * (nbPit);          
            for (indCh = 1; indCh <= nbCh[gT]; indCh++)
              if ((cp0ind - segEnd[indCh - 1] > 0) &&
                    (cp0ind - segEnd[indCh - 1] < delta)) {
                delta = cp0ind - segEnd[indCh - 1];
                mRou[gT][i]->noCh = indCh;      
                done = 1;
              }
            if (done == 1)
              segEnd[mRou[gT][i]->noCh - 1] = cplind;
            else {
              mRou[gT][i]->noCh = indCh;
              segEnd[indCh - 1] =
                    mRou[gT][i]->contPos[mRou[gT][i]->nbCont - 1];
              nbCh[gT] = indCh;
            }
          }
      }
      i++;
    }
  }
}

/*----------------------------------------------------------------------------*
  -------- very low-level func ----------------------------------[routTrans]--
  ----------------------------------------------------------------------------
  SYNTAX : short insertSegOut(MetalEq[2][MAX_EQ] *, short, short[2]
			   short[2], SegFree[MAX_CHAN], short[2])
  ----------------------------------------------------------------------------
  EXEMPLE : insertSegOut(mRout, nbPitch, nbCh, nbMaxCh, maxFree, indOut);
  ----------------------------------------------------------------------------
  FONCTION : 
  ----------------------------------------------------------------------------
  ERROR : none
 *----------------------------------------------------------------------------*/

void insertSegOut(mRou, nbPit, nbCh, nbMCh, maxFree, indOut)
MetalEq *mRou[][MAX_EQ];
short nbPit, nbCh[], nbMCh[], indOut[];
SegFree maxFree[];
{
  short cplout, cp0out, maxL, maxR;
  register short i, indCh, gT;
  char insertOutDone;

  for (gT = N_GRAPH; gT <= P_GRAPH; gT++) {
    cplout = mRou[gT][indOut[gT]]->contPos[mRou[gT][indOut[gT]]->nbCont - 1];
    cp0out = mRou[gT][indOut[gT]]->contPos[0];
    maxFree[gT].noChL = maxFree[gT].noChR = -1;
    maxFree[gT].lenL = maxFree[gT].lenR = -1;
    maxFree[gT].all = 0;
    insertOutDone = 0;
    if (nbCh[gT] < nbMCh[gT]) {
      nbCh[gT]++;
      mRou[gT][indOut[gT]]->noCh = nbCh[gT];
      maxFree[gT].noChL = maxFree[gT].noChR = nbCh[gT];
      maxFree[gT].lenL = cp0out;
      maxFree[gT].lenR = nbPit - cplout;
      maxFree[gT].all = 1;
    }
    else {
      for (indCh = 1; indCh <= nbCh[gT]; indCh++) {
        maxL = cp0out;
        maxR = -1;
        i = 0;
        while (mRou[gT][i] && (((mRou[gT][i]->noCh == indCh)
              && (mRou[gT][i]->contPos[0] < cplout))
              || (mRou[gT][i]->noCh != indCh))) {
          if (mRou[gT][i]->noCh == indCh) {
            if (mRou[gT][i]->contPos[mRou[gT][i]->nbCont - 1] < cp0out)
              maxL = cp0out -
                    mRou[gT][i]->contPos[mRou[gT][i]->nbCont - 1] - 1;
            else
              maxL = -1;
          }
          i++;
        }
        if (!(mRou[gT][i]))
          maxR = nbPit - cplout;
        else
          if ((mRou[gT][i]->noCh == indCh)
                && (mRou[gT][i]->contPos[0] > cplout))
            maxR = mRou[gT][i]->contPos[0] - cplout - 1;
        if ((maxL != -1) && (maxR != -1)) {
          insertOutDone = 1;
          if (maxL >= maxFree[gT].lenL) {
            maxFree[gT].noChL = indCh;
            maxFree[gT].lenL = maxL;
          }
          if (maxR >= maxFree[gT].lenR) {
            maxFree[gT].noChR = indCh;
            maxFree[gT].lenR = maxR;
          }
        }  
      }
      if (!(insertOutDone)) {
        nbCh[gT]++;
        mRou[gT][indOut[gT]]->noCh = nbCh[gT];
        maxFree[gT].noChL = maxFree[gT].noChR = nbCh[gT];
        maxFree[gT].lenL = cp0out;
        maxFree[gT].lenR = nbPit - cplout;
        maxFree[gT].all = 1;
      }
    }
  }
}

/*----------------------------------------------------------------------------*
  -------- very low-level func ----------------------------------[routTrans]--
  ----------------------------------------------------------------------------
  SYNTAX : void insertGraph(TrGraph[MAH_H_PITCH] *, short, short, short)
  ----------------------------------------------------------------------------
  EXEMPLE : insertGraph(tGr, OUT_BLK, nbPit, posOut)
  ----------------------------------------------------------------------------
  FONCTION :
  ----------------------------------------------------------------------------
  ERROR : none
 *----------------------------------------------------------------------------*/
void insertGraph(tGr, type, nbPit, posOut)
TrGraph *tGr[];
short type, nbPit, posOut;
{
  short ind;
 
  if ((tGr[nbPit] = (TrGraph *)malloc((unsigned)sizeof(TrGraph))) == NULL) {
    (void)fprintf(stderr, "\nc4_Error : malloc failed. [insertGraph]\n\n");
    exit(-1);
  } 
  if (type == TRSP_BLK)
    _C4nbAddCuts++;
  for (ind = nbPit; ind >= posOut; ind--) {
    if (ind == posOut) {
      tGr[ind]->trName = NULL;
      tGr[ind]->blkType = type;
    }
    else
      *tGr[ind] = *tGr[ind - 1];
  } 
}
 
/*----------------------------------------------------------------------------*
  -------- very low-level func ----------------------------------[routTrans]--
  ----------------------------------------------------------------------------
  SYNTAX : void invertCh(MetalEq[2][MAX_EQ] *, short, short, short,
                   short)
  ----------------------------------------------------------------------------
  EXEMPLE : invertCh(mRou, gT, mRou[N_GRAPH][indOut[N_GRAPH]]->noCh,
                nbMCh[N_GRAPH], nbCh[N_GRAPH])
  ----------------------------------------------------------------------------
  FONCTION :
  ----------------------------------------------------------------------------
  ERROR : none
 *----------------------------------------------------------------------------*/
void invertCh(mRou, gT, indCh, destCh, nbCh)
MetalEq *mRou[][MAX_EQ];
short gT, indCh, destCh, nbCh;
{
  short ind;

  if ((indCh != destCh) && (nbCh == destCh)) {
    for(ind = 0; mRou[gT][ind]; ind++)
      if (mRou[gT][ind]->noCh == destCh)
        mRou[gT][ind]->noCh = nbCh + 1;
    for(ind = 0; mRou[gT][ind]; ind++)
      if (mRou[gT][ind]->noCh == indCh)
        mRou[gT][ind]->noCh = destCh;
    for(ind = 0; mRou[gT][ind]; ind++)
      if (mRou[gT][ind]->noCh == nbCh + 1)
        mRou[gT][ind]->noCh = indCh;
  }
  else
    if (indCh != destCh)
      for(ind = 0; mRou[gT][ind]; ind++)
        if (mRou[gT][ind]->noCh == indCh)
          mRou[gT][ind]->noCh = destCh;
}

/*----------------------------------------------------------------------------*
  -------- very low-level func ----------------------------------[routTrans]--
  ----------------------------------------------------------------------------
  SYNTAX : void moveCont(MetalEq[2][MAX_EQ] *, short, short)
  ----------------------------------------------------------------------------
  EXEMPLE : moveCont(mRou, posOut, nbO)
  ----------------------------------------------------------------------------
  FONCTION :
  ----------------------------------------------------------------------------
  ERROR : none
 *----------------------------------------------------------------------------*/
void moveCont(mRou, posOut, nbO)
MetalEq *mRou[][MAX_EQ];
short posOut, nbO;
{
  short gT, ind, indct;
 
  for (gT = N_GRAPH; gT <= P_GRAPH; gT++)
    for(ind=0; mRou[gT][ind]; ind++)
      for(indct = 0; indct < mRou[gT][ind]->nbCont; indct++)
        if (mRou[gT][ind]->contPos[indct] >= posOut)
          mRou[gT][ind]->contPos[indct] += nbO;
}

 /*----------------------------------------------------------------------------*
  -------- very low-level func ----------------------------------[routTrans]--
  ----------------------------------------------------------------------------
  SYNTAX : void expandSegOut(MetalEq[2][MAX_EQ] *, short, short, short,
                    short, short)
  ----------------------------------------------------------------------------
  EXEMPLE : expandSegOut(mRou, N_GRAPH, posOut, indOut[N_GRAPH],
                cp0out[N_GRAPH], cplout[N_GRAPH])
  ----------------------------------------------------------------------------
  FONCTION :
  ----------------------------------------------------------------------------
  ERROR : none
 *----------------------------------------------------------------------------*/
void expandSegOut(mRou, gT, posOut, indOut, cp0out, cplout)
MetalEq *mRou[][MAX_EQ];
short gT, posOut, indOut, cp0out, cplout;
{
  short i;
 
  if (posOut < cp0out) {
    mRou[gT][indOut]->nbCont++;
    for (i = mRou[gT][indOut]->nbCont - 1; i >= 0; i--) {
      if (i == 0)
        mRou[gT][indOut]->contPos[0] = -posOut - 1;
      else
        mRou[gT][indOut]->contPos[i] =
              mRou[gT][indOut]->contPos[i - 1];
    }
  }
  else
    if (posOut > cplout) {
      mRou[gT][indOut]->nbCont++;
      mRou[gT][indOut]->contPos[mRou[gT][indOut]->nbCont - 1] = -posOut - 1;
    }
}
 
/*----------------------------------------------------------------------------*
  -------- very low-level func ----------------------------------[routTrans]--
  ----------------------------------------------------------------------------
  SYNTAX : void connectSegOut(MetalEq[2][MAX_EQ] *, TrGraph[MAH_H_PITCH] *,
		   short, short[2], short[2], SegFree[MAX_CHAN], short[2])
  ----------------------------------------------------------------------------
  EXEMPLE : connectSegOut(mRout, trGraph, nbPitch, nbCh, nbMaxCh, maxFree,
                   indOut);
  ----------------------------------------------------------------------------
  FONCTION : 
  ----------------------------------------------------------------------------
  ERROR : none
 *----------------------------------------------------------------------------*/

void connectSegOut(mRou, tGr, nbPit, nbCh, nbMCh, maxFree, indOut)
MetalEq *mRou[][MAX_EQ];
TrGraph *tGr[];
short nbPit, nbCh[], nbMCh[], indOut[];
SegFree maxFree[];
{
  short cplout[2], cp0out[2], splout[2], sp0out[2];
  short posmin, posmax, posOut, gT, i, ind, indCh; 

  for (gT = N_GRAPH; gT <= P_GRAPH; gT++) {
    cplout[gT] = mRou[gT][indOut[gT]]->contPos[mRou[gT][indOut[gT]]->nbCont-1];
    cp0out[gT] = mRou[gT][indOut[gT]]->contPos[0];
    sp0out[gT] = cp0out[gT] - maxFree[gT].lenL;
    splout[gT] = cplout[gT] + maxFree[gT].lenR;   
  }

  if ((splout[1] < sp0out[0]) || (splout[0] < sp0out[1])) {
    gT = (nbCh[0] < nbCh[1] ? 0 : 1);
    nbCh[gT]++;
    mRou[gT][indOut[gT]]->noCh = nbCh[gT];
    maxFree[gT].noChL = maxFree[gT].noChR = nbCh[gT];
    maxFree[gT].lenL = cp0out[gT];
    maxFree[gT].lenR = nbPit - cplout[gT];
    maxFree[gT].all = 1;
    sp0out[gT] = cp0out[gT] - maxFree[gT].lenL;
    splout[gT] = cplout[gT] + maxFree[gT].lenR;   
  }

  nbCh[N_GRAPH] = MAX(nbMCh[N_GRAPH], MAX(2, nbCh[N_GRAPH]));
  nbCh[P_GRAPH] = MAX(nbMCh[P_GRAPH], MAX(2, nbCh[P_GRAPH]));
  posmin = MAX(sp0out[0], sp0out[1]);
  posmax = MIN(splout[0], splout[1]);
  posOut = (nbPit - posmax > posmin ? posmin : posmax);

  if (posOut == posmin) {
    mRou[N_GRAPH][indOut[N_GRAPH]]->noCh = maxFree[N_GRAPH].noChL;
    mRou[P_GRAPH][indOut[P_GRAPH]]->noCh = maxFree[P_GRAPH].noChL;
  }
  else {
    mRou[N_GRAPH][indOut[N_GRAPH]]->noCh = maxFree[N_GRAPH].noChR;
    mRou[P_GRAPH][indOut[P_GRAPH]]->noCh = maxFree[P_GRAPH].noChR;
  }

  expandSegOut(mRou, N_GRAPH, posOut, indOut[N_GRAPH],
               cp0out[N_GRAPH], cplout[N_GRAPH]);
  expandSegOut(mRou, P_GRAPH, posOut, indOut[P_GRAPH],
               cp0out[P_GRAPH], cplout[P_GRAPH]);
  invertCh(mRou, N_GRAPH, mRou[N_GRAPH][indOut[N_GRAPH]]->noCh, nbCh[N_GRAPH],
           nbCh[N_GRAPH]);
  invertCh(mRou, P_GRAPH, mRou[P_GRAPH][indOut[P_GRAPH]]->noCh, nbCh[P_GRAPH],
           nbCh[P_GRAPH]);

  insertGraph(tGr, OUT_BLK, nbPit, posOut);
}

/*----------------------------------------------------------------------------*
  -------- very low-level func ----------------------------------[routTrans]--
  ----------------------------------------------------------------------------
  SYNTAX : void connectSegInv(MetalEq[2][MAX_EQ] *, VertSeg *, VertSeg *,
                   TrGraph[MAH_H_PITCH] *, short, short[2], short[2],
                   SegFree[MAX_CHAN], short[2])
  ----------------------------------------------------------------------------
  EXEMPLE : connectSegInv(mRout, segInv, segTrsp, trGraph, nbPitch, nbCh,
                          nbMaxCh, maxFree, indOut);
  ----------------------------------------------------------------------------
  FONCTION :
  ----------------------------------------------------------------------------
  ERROR : none
 *----------------------------------------------------------------------------*/
void connectSegInv(mRou, segInv, segTrsp, tGr, nbPit, nbCh, nbMCh, maxFree, indOut)
MetalEq *mRou[][MAX_EQ];
VertSeg *segInv, *segTrsp;
TrGraph *tGr[];
short nbPit, nbCh[], nbMCh[], indOut[];
SegFree maxFree[];

{
  short cplout[2], cp0out[2], splout[2], sp0out[2], tabtrsp[MAX_H_PITCH];
  short posmin, posmax, posOut, gT, i, ind, indCh = -1, boucle, nbO, indtrsp=0;

  for (gT = 0; gT < 2; gT++) {
    cp0out[gT]=mRou[gT][indOut[gT]]->contPos[0];
    cplout[gT]=mRou[gT][indOut[gT]]->contPos[mRou[gT][indOut[gT]]->nbCont-1];
    sp0out[gT]=cp0out[gT]-maxFree[gT].lenL;
    splout[gT]=cplout[gT]+maxFree[gT].lenR;
  }
  nbCh[N_GRAPH] = MAX(nbMCh[N_GRAPH], MAX(2, nbCh[N_GRAPH]));
  nbCh[P_GRAPH] = MAX(nbMCh[P_GRAPH], MAX(2, nbCh[P_GRAPH]));

  /*Determination des positions des transparences*/
  for (ind = 0; ind < nbPit; ind++)
    if (!(tGr[ind]->trName))
        tabtrsp[indtrsp++] = ind;

  for (boucle = 0; boucle < 3; boucle++) {

    /*Calcul de la position de l'intervalle de sortie*/
    posmin=MAX(sp0out[0],sp0out[1]);
    posmax=MIN(splout[0],splout[1]);
 
    /*Positionnement en 2 pitchs*/
    nbO = 2;

    /*Test de positionnement en fin de cellule : Vdd=Vss*
     *Les deux segments en position finale*/

    if ((tGr[nbPit - 1]->loNEq == 0) && (tGr[nbPit - 1]->loPEq == 0)) {
      if ((splout[0]==nbPit) && (splout[1]==nbPit)) {
        posOut = nbPit;
        mRou[N_GRAPH][indOut[N_GRAPH]]->noCh = maxFree[N_GRAPH].noChR;
        mRou[P_GRAPH][indOut[P_GRAPH]]->noCh = maxFree[P_GRAPH].noChR;
        expandSegOut(mRou, N_GRAPH, posOut + nbO - 2, indOut[N_GRAPH],
                     cp0out[N_GRAPH], cplout[N_GRAPH]);
        expandSegOut(mRou, P_GRAPH, posOut + nbO - 2, indOut[P_GRAPH],
                     cp0out[P_GRAPH], cplout[P_GRAPH]);
        invertCh(mRou, N_GRAPH, mRou[N_GRAPH][indOut[N_GRAPH]]->noCh,
                 nbCh[N_GRAPH], nbCh[N_GRAPH]);
        invertCh(mRou, P_GRAPH, mRou[P_GRAPH][indOut[P_GRAPH]]->noCh,
                 nbCh[P_GRAPH], nbCh[P_GRAPH]);
        insertGraph(tGr, INV_BLK, nbPit, posOut);
        insertGraph(tGr, OUT_BLK, nbPit + 1, posOut + 1);
        segInv->xPos = posOut + 1;
        segInv->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
        segInv->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
        break;
      }
    }

    /*Test de positionnement en debut de cellule : Vdd=Vss*
     *Les deux segments en position initiale*/

    if ((tGr[0]->hiNEq == 0) && (tGr[0]->hiPEq == 0)) {
      if ((sp0out[0]==0) && (sp0out[1]==0)) {
        posOut = 0;
        mRou[N_GRAPH][indOut[N_GRAPH]]->noCh = maxFree[N_GRAPH].noChL;
        mRou[P_GRAPH][indOut[P_GRAPH]]->noCh = maxFree[P_GRAPH].noChL;
        moveCont(mRou, posOut, nbO - 1);
        for (i = N_GRAPH; i <= P_GRAPH; i++) {
          cp0out[i] += nbO - 1;
          cplout[i] += nbO - 1;
          sp0out[i] += nbO - 1;
          splout[i] += nbO - 1;
        }
        expandSegOut(mRou, N_GRAPH, posOut + 1, indOut[N_GRAPH],
                     cp0out[N_GRAPH], cplout[N_GRAPH]);
        expandSegOut(mRou, P_GRAPH, posOut + 1, indOut[P_GRAPH],
                     cp0out[P_GRAPH], cplout[P_GRAPH]);
        invertCh(mRou, N_GRAPH, mRou[N_GRAPH][indOut[N_GRAPH]]->noCh,
                 nbCh[N_GRAPH], nbCh[N_GRAPH]);
        invertCh(mRou, P_GRAPH, mRou[P_GRAPH][indOut[P_GRAPH]]->noCh,
                 nbCh[P_GRAPH], nbCh[P_GRAPH]);
        insertGraph(tGr, OUT_BLK, nbPit, posOut);
        insertGraph(tGr, INV_BLK, nbPit + 1, posOut + 1);
        segInv->xPos = posOut + 1;
        segInv->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
        segInv->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
        break;
      }
    }

    /*Test de positionnement en fin de cellule : Vdd=Vss*
     *Un seul segment en position finale*/

    if ((tGr[nbPit - 1]->loNEq == 0) && (tGr[nbPit - 1]->loPEq == 0)) {
      if ((splout[0] == nbPit) || (splout[1] == nbPit)) {
        gT = splout[0] == nbPit ? 0 : 1;
        ind=indtrsp - 1;
        while ((segTrsp->xPos == -1) && (ind>=0)) {
          if ((tabtrsp[ind] >= posmin) && (tabtrsp[ind] <= posmax))
            segTrsp->xPos=tabtrsp[ind];
          ind--;
        }
        if (segTrsp->xPos != -1) {
          posOut = nbPit;
          mRou[gT][indOut[gT]]->noCh = maxFree[gT].noChR;
          mRou[!gT][indOut[!gT]]->noCh = maxFree[!gT].noChR;
          expandSegOut(mRou, gT, posOut, indOut[gT],
                       cp0out[gT], cplout[gT]);
          expandSegOut(mRou, gT, segTrsp->xPos, indOut[gT],
                       cp0out[gT], cplout[gT]);
          expandSegOut(mRou, !gT, segTrsp->xPos, indOut[!gT],
                       cp0out[!gT], cplout[!gT]);
          invertCh(mRou, gT, mRou[gT][indOut[gT]]->noCh,
                   nbCh[gT], nbCh[gT]);
          invertCh(mRou, !gT, mRou[!gT][indOut[!gT]]->noCh,
                   nbCh[!gT], nbCh[!gT]);
          insertGraph(tGr, INV_BLK, nbPit, posOut);
          insertGraph(tGr, OUT_BLK, nbPit + 1, posOut + 1);
          segInv->xPos = posOut;
          if (gT == N_GRAPH)
            segInv->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
          else
            segInv->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
          segTrsp->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
          segTrsp->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
          break;
        }
      }
    } 

    /*Test de positionnement en debut de cellule : Vdd=Vss*
     *Un seul segment en position initiale*/

    if ((tGr[0]->hiNEq == 0) && (tGr[0]->hiPEq == 0)) {
      if ((sp0out[0]==0) || (sp0out[1]==0)) {
        gT = sp0out[0] == 0 ? 0 : 1;
        ind = 0;
        while ((segTrsp->xPos == -1) && (ind < indtrsp)) {
          if ((tabtrsp[ind] >= posmin) && (tabtrsp[ind] <= posmax))
            segTrsp->xPos=tabtrsp[ind] + nbO;
          ind++;
        }
        if (segTrsp->xPos != -1) {
          posOut = 0;
          mRou[N_GRAPH][indOut[N_GRAPH]]->noCh = maxFree[N_GRAPH].noChL;
          mRou[P_GRAPH][indOut[P_GRAPH]]->noCh = maxFree[P_GRAPH].noChL;
          moveCont(mRou, posOut, nbO - 1);    
          for (i = N_GRAPH; i <= P_GRAPH; i++) {   
            cp0out[i] += nbO - 1;   
            cplout[i] += nbO - 1;
            sp0out[i] += nbO - 1;
            splout[i] += nbO - 1;
          }
          expandSegOut(mRou, gT, posOut + nbO  -1, indOut[gT],
                       cp0out[gT], cplout[gT]);
          expandSegOut(mRou, gT, segTrsp->xPos, indOut[gT],
                       cp0out[gT], cplout[gT]);
          expandSegOut(mRou, !gT, segTrsp->xPos, indOut[!gT],
                       cp0out[!gT], cplout[!gT]);
          invertCh(mRou, gT, mRou[gT][indOut[gT]]->noCh,
                   nbCh[gT], nbCh[gT]);
          invertCh(mRou, !gT, mRou[!gT][indOut[!gT]]->noCh,
                   nbCh[!gT], nbCh[!gT]);
          insertGraph(tGr, OUT_BLK, nbPit, posOut);
          insertGraph(tGr, INV_BLK, nbPit + 1, posOut + 1);
          segInv->xPos = posOut + 1;
          if (gT == N_GRAPH)
            segInv->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
          else
            segInv->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
          segTrsp->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
          segTrsp->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
          break;
        }
      } 
    }

    /*Positionnement en 3 pitchs*/
    nbO = 3;

    /*Test de positionnement en fin de cellule : Vdd<>Vss*
     *Les deux segments en position finale*/

    if ((splout[0]==nbPit) && (splout[1]==nbPit)) {
      posOut = nbPit;
      mRou[N_GRAPH][indOut[N_GRAPH]]->noCh = maxFree[N_GRAPH].noChR;
      mRou[P_GRAPH][indOut[P_GRAPH]]->noCh = maxFree[P_GRAPH].noChR;
      expandSegOut(mRou, N_GRAPH, posOut + nbO - 2, indOut[N_GRAPH],
                   cp0out[N_GRAPH], cplout[N_GRAPH]);    
      expandSegOut(mRou, P_GRAPH, posOut + nbO - 2, indOut[P_GRAPH],
                   cp0out[P_GRAPH], cplout[P_GRAPH]);    
      invertCh(mRou, N_GRAPH, mRou[N_GRAPH][indOut[N_GRAPH]]->noCh,
               nbCh[N_GRAPH], nbCh[N_GRAPH]);
      invertCh(mRou, P_GRAPH, mRou[P_GRAPH][indOut[P_GRAPH]]->noCh,
               nbCh[P_GRAPH], nbCh[P_GRAPH]);
      insertGraph(tGr, TRSP_BLK, nbPit, posOut);
      insertGraph(tGr, INV_BLK, nbPit + 1, posOut + 1);
      insertGraph(tGr, OUT_BLK, nbPit + 2, posOut + 2);
      segInv->xPos = posOut + 1;
      segInv->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
      segInv->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
      break;
    } 

    /*Test de positionnement en debut de cellule : Vdd<>Vss*
     *Les deux segments en position initiale*/

    if ((sp0out[0]==0) && (sp0out[1]==0)) {
      posOut = 0;
      mRou[N_GRAPH][indOut[N_GRAPH]]->noCh = maxFree[N_GRAPH].noChL;
      mRou[P_GRAPH][indOut[P_GRAPH]]->noCh = maxFree[P_GRAPH].noChL;
      moveCont(mRou, posOut, nbO - 1);
      for (i = N_GRAPH; i <= P_GRAPH; i++) {   
        cp0out[i] += nbO - 1;
        cplout[i] += nbO - 1;
        sp0out[i] += nbO - 1;
        splout[i] += nbO - 1;
      }
      expandSegOut(mRou, N_GRAPH, posOut + 1, indOut[N_GRAPH],
                   cp0out[N_GRAPH], cplout[N_GRAPH]);
      expandSegOut(mRou, P_GRAPH, posOut + 1, indOut[P_GRAPH],
                   cp0out[P_GRAPH], cplout[P_GRAPH]);
      invertCh(mRou, N_GRAPH, mRou[N_GRAPH][indOut[N_GRAPH]]->noCh,
               nbCh[N_GRAPH], nbCh[N_GRAPH]);
      invertCh(mRou, P_GRAPH, mRou[P_GRAPH][indOut[P_GRAPH]]->noCh,
               nbCh[P_GRAPH], nbCh[P_GRAPH]);
      insertGraph(tGr, OUT_BLK, nbPit, posOut);
      insertGraph(tGr, INV_BLK, nbPit + 1, posOut + 1);
      insertGraph(tGr, TRSP_BLK, nbPit + 2, posOut + 2);
      segInv->xPos = posOut + 1;
      segInv->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
      segInv->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
      break;
    } 

    /*Test de positionnement en fin de cellule : Vdd<>Vss*
     *Un seul segment en position finale*/

    if ((splout[0] == nbPit) || (splout[1] == nbPit)) {
      gT = splout[0] == nbPit ? 0 : 1;
      ind=indtrsp - 1;
      while ((segTrsp->xPos == -1) && (ind>=0)) {
        if ((tabtrsp[ind] >= posmin) && (tabtrsp[ind] <= posmax))
          segTrsp->xPos = tabtrsp[ind];
        ind--;
      } 
      if (segTrsp->xPos != -1) {
        posOut = nbPit;
        mRou[gT][indOut[gT]]->noCh = maxFree[gT].noChR;
        mRou[!gT][indOut[!gT]]->noCh = maxFree[!gT].noChR;
        expandSegOut(mRou, gT, posOut + 1, indOut[gT],
                     cp0out[gT], cplout[gT]);
        expandSegOut(mRou, gT, segTrsp->xPos, indOut[gT],
                     cp0out[gT], cplout[gT]);
        expandSegOut(mRou, !gT, segTrsp->xPos, indOut[!gT],
                     cp0out[!gT], cplout[!gT]);
        invertCh(mRou, gT, mRou[gT][indOut[gT]]->noCh,
                 nbCh[gT], nbCh[gT]);
        invertCh(mRou, !gT, mRou[!gT][indOut[!gT]]->noCh,
                 nbCh[!gT], nbCh[!gT]);
        insertGraph(tGr, TRSP_BLK, nbPit, posOut);
        insertGraph(tGr, INV_BLK, nbPit + 1, posOut + 1);
        insertGraph(tGr, OUT_BLK, nbPit + 2, posOut + 2);

        segInv->xPos = posOut + 1;
        if (gT == N_GRAPH)
          segInv->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
        else
          segInv->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
        segTrsp->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
        segTrsp->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
        break;
      } 
    } 

    /*Test de positionnement en debut de cellule : Vdd<>Vss*
     *Un seul segment en position initiale*/

    if ((sp0out[0]==0) || (sp0out[1]==0)) {
      gT = sp0out[0] == 0 ? 0 : 1;
      ind = 0;
      while ((segTrsp->xPos == -1) && (ind < indtrsp)) {
        if ((tabtrsp[ind] >= posmin) && (tabtrsp[ind] <= posmax))
          segTrsp->xPos=tabtrsp[ind] + nbO;
        ind++;
      }
      if (segTrsp->xPos != -1) {
        posOut = 0;
        mRou[N_GRAPH][indOut[N_GRAPH]]->noCh = maxFree[N_GRAPH].noChL;
        mRou[P_GRAPH][indOut[P_GRAPH]]->noCh = maxFree[P_GRAPH].noChL;
        moveCont(mRou, posOut, nbO - 1);
        for (i = N_GRAPH; i <= P_GRAPH; i++) {
          cp0out[i] += nbO - 1;
          cplout[i] += nbO - 1;
          sp0out[i] += nbO - 1;
          splout[i] += nbO - 1;
        }
        expandSegOut(mRou, gT, posOut + nbO - 2, indOut[gT],
                     cp0out[gT], cplout[gT]);
        expandSegOut(mRou, gT, segTrsp->xPos, indOut[gT],
                     cp0out[gT], cplout[gT]);
        expandSegOut(mRou, !gT, segTrsp->xPos, indOut[!gT],
                     cp0out[!gT], cplout[!gT]);
        invertCh(mRou, gT, mRou[gT][indOut[gT]]->noCh,
                 nbCh[gT], nbCh[gT]);
        invertCh(mRou, !gT, mRou[!gT][indOut[!gT]]->noCh,
                 nbCh[!gT], nbCh[!gT]);
        insertGraph(tGr, OUT_BLK, nbPit, posOut);
        insertGraph(tGr, INV_BLK, nbPit + 1, posOut + 1);
        insertGraph(tGr, TRSP_BLK, nbPit + 2, posOut + 2);
        segInv->xPos = posOut + 1;
        if (gT == N_GRAPH)
          segInv->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
        else
          segInv->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
        segTrsp->y1 = mRou[N_GRAPH][indOut[N_GRAPH]]->noCh;
        segTrsp->y2 = mRou[P_GRAPH][indOut[P_GRAPH]]->noCh;
        break;
      }
    }

    if ((boucle == 0) || (boucle ==1)) {
      if (indCh == -1)
        indCh = nbCh[N_GRAPH] < nbCh[P_GRAPH] ? 0 : 1;
      else
        indCh = !indCh;
      nbCh[indCh]++;
      maxFree[indCh].noChR = maxFree[indCh].noChL = nbCh[indCh];
      maxFree[indCh].lenR = nbPit - cplout[indCh];
      maxFree[indCh].lenL = cp0out[indCh];
      sp0out[indCh] = 0;
      splout[indCh] = nbPit;
    }
  }
} 

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*
  =-=-=-=- low-level func =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-[]=-
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  SYNTAX : void routTrans(MemFig *, short, short)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  EXEMPLE : routTrans(cell, 3, 3)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  FONCTION : 
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  ERROR : if createIntercon not successfully achieved.			cont
          if cell = NULL.						cont
 *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/

void routTrans(cell, nbNChan, nbPChan)
MemFig *cell;
short nbPChan, nbNChan;
{
  short indOut[2];
  SegFree maxFree[MAX_CHAN];

  if (cell == NULL) {
    (void)fprintf(stderr, "\nc4_Warning : Input param of routTrans is ");
    (void)fprintf(stderr, "NULL. [routTrans]\n\n");
    return;
  }
  _C4nbAddCuts = 0;
  indOut[0] = 0;
  indOut[1] = 0;

  cell->nbMaxCh[P_GRAPH] = MAX(2, nbPChan);
  cell->nbMaxCh[N_GRAPH] = MAX(2, nbNChan);
  cell->nbCh[P_GRAPH] = 0;
  cell->nbCh[N_GRAPH] = 0;
  setChanNo(cell->mRout, cell->nbInp + cell->nbCut, 
            cell->nbCh, indOut);
  insertSegOut(cell->mRout, cell->nbInp + cell->nbCut, cell->nbCh,
               cell->nbMaxCh, maxFree, indOut);

  if (cell->result->polarity == NEG){
    connectSegOut(cell->mRout, cell->tGraph, cell->nbInp + cell->nbCut,
                  cell->nbCh, cell->nbMaxCh, maxFree, indOut);
  }
  else{
    connectSegInv(cell->mRout, &(cell->segInv), &(cell->segTrsp), cell->tGraph,
                  cell->nbInp + cell->nbCut, cell->nbCh, cell->nbMaxCh,
                  maxFree, indOut);
  }
  cell->nbCut = cell->nbCut + _C4nbAddCuts;
  cell->status.routTransOK = 1;
}

/*:::::::::::::::::::::::::::: end of routTrans ::::::::::::::::::::::::::::::*/


/*::::::::::::::::::::::::::: start of undefMemFig :::::::::::::::::::::::::::*/

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*
  =-=-=-=- low-level func =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-[]=-
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  SYNTAX : void undefMemFig(MemFig *)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  EXEMPLE : undefMemFig(cel)
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  FONCTION : 
  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  ERROR :
 *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/

void undefMemFig(cell)
MemFig *cell;
{
  register short i;

  if (!(cell))
    return;
  freechain(cell->assocList);
  freeExpr(cell->inExprABL);
  if (cell->trExprABL)
    freeExpr(cell->trExprABL);
  i = 0;
  while (cell->tGraph[i])
    free(cell->tGraph[i++]);
  i = 0;
  while (cell->mRout[P_GRAPH][i])
    free(cell->mRout[P_GRAPH][i++]);
  i = 0;
  while (cell->mRout[N_GRAPH][i])
    free(cell->mRout[N_GRAPH][i++]);
  free(cell);
}

/*:::::::::::::::::::::::::::: end of undefMemFig ::::::::::::::::::::::::::::*/

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::: start of user's functions : c4_comp, c4_genfree, c4_free  ::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

/*============================================================================*
  ======== high-level func ===================================================
  ============================================================================
  SYNTAX : MemFig *c4_comp(chain_list *, char *, short, short,int)
  ============================================================================
  EXEMPLE : cell = c4_comp(expr, "Cell1", 3, 3)
  ============================================================================
  FONCTION : 
  ============================================================================
  ERROR : none
 *============================================================================*/

MemFig *c4_comp(expr, fileName, nNCh, nPCh,trace)
chain_list *expr;
char *fileName;
short nPCh, nNCh;
int trace;
{
  MemFig *cell;

  cell = defMemFig(expr, fileName);
  checkExpr(cell);
  if (!(cell->status.checkExprOK)) 
     {
     if (trace)
        {
        (void)fprintf(stderr, "\nc4_Warning : checkExpr hasn't successfully ");
        (void)fprintf(stderr, "achieved. [placeInputs]\n\n");
        }
     return cell;
     }
  placeInputs(cell);
  if (!(cell->status.placeInputsOK))
     {
     if (trace)
        {
        (void)fprintf(stderr, "\nc4_Warning : placeInputs hasn't successfully ");
        (void)fprintf(stderr, "achieved. [createIntercon]\n\n");
        }
     return cell;
     }
  createIntercon(cell);
  if (!(cell->status.placeInputsOK)) 
     {
     if (trace)
        {
        (void)fprintf(stderr, "\nc4_Warning : createIntercon hasn't ");
        (void)fprintf(stderr, "successfully achieved. [routTrans]\n\n");
        }
     return cell;
     }
  routTrans(cell, nNCh, nPCh);
  if ((C4_NBPCHAN(cell) > nPCh) || (C4_NBPCHAN(cell) > nNCh)) 
     {
     if (trace)
        {
        (void)fprintf(stderr, "\nc4_Warning : rouTrans hasn't ");
        (void)fprintf(stderr, "successfully achieved. [routTrans]\n");
        displayExpr(expr);
        printf("\n");
        }
     return cell;
     }
  
  return cell;
}

/*============================================================================*
  ======== high-level func ===================================================
  ============================================================================
  SYNTAX : void c4_gen(MemFig *)
  ============================================================================
  EXEMPLE : c4_gen(cell)
  ============================================================================
  FONCTION : 
  ============================================================================
  ERROR : none
 *============================================================================*/

void c4_gen(cell)
MemFig *cell;
{
  genFiles(cell, 1, 1, 1);
}

/*============================================================================*
  ======== high-level func ===================================================
  ============================================================================
  SYNTAX : void c4_genfree(MemFig *)
  ============================================================================
  EXEMPLE : c4_genfree(cell)
  ============================================================================
  FONCTION : 
  ============================================================================
  ERROR : none
 *============================================================================*/

void c4_genfree(cell)
MemFig *cell;
{
  genFiles(cell, 1, 1, 1);
  undefMemFig(cell);
}

/*============================================================================*
  ======== high-level func ===================================================
  ============================================================================
  SYNTAX : void c4_free(MemFig *)
  ============================================================================
  EXEMPLE : c4_free(cell)
  ============================================================================
  FONCTION : 
  ============================================================================
  ERROR : none
 *============================================================================*/

void c4_free(cell)
MemFig *cell;
{
  undefMemFig(cell);
}

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::: end of user's functions : c4_comp, c4_genfree, c4_free :::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
