static char *SccsId = "@(#)trmctree.c 4.12 (TU-Delft) 04/23/93";
/**********************************************************

Name/Version      : makebox/4.12

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)         : S. de Graaf
Creation date     : 22-Apr-1986
Modified by       : S. de Graaf
Modification date : 28-Aug-1987


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1987 , All rights reserved
**********************************************************/
#include "extern.h"

#define HASHSIZE 256
struct clist *Hashtab[HASHSIZE];

/*
** traverse the mc-tree of the cell recursively
*/
trav_mctree (pcl, image_done)
struct clist *pcl;
int image_done;
{
    register char  *s;
    register struct clist   *clp;
    register struct clist   *c_list = 0;
    register struct mc_elmt *mcp;
    DM_PROJECT *proj;
    DM_STREAM  *fp;
    DM_STREAM  *dsp;
    char **equiv4;
    int    hashval;
    int    flag;
    struct stat buf;

#ifdef DEBUG
P_E "=> trav_mctree(%08x): level = %d\n", pcl, level);
P_E "   cell: %s, pkey: %08x, ckey: %08x, mc_p: %08x\n",
pcl -> ckey -> cell, pcl -> ckey -> dmproject, pcl -> ckey, pcl -> mc_p);
#endif

    fp = dmOpenStream (pcl -> ckey, "mc", "r");

    while (dmGetDesignData (fp, GEO_MC) > 0) {

	if (part_exp && level == 1) {
	    if (samples * gmc.bxr <= exp_reg[0]
	    ||  samples * gmc.bxl >= exp_reg[1]
	    ||  samples * gmc.byt <= exp_reg[2]
	    ||  samples * gmc.byb >= exp_reg[3]) {
	    /*
	    ** the mc-bbox coordinates have no overlap
	    ** with the expansion region
	    */
		continue;
	    }
	}

	/* See if instance is an image, and if so, if it can be skipped.
	 */
	if (imageName && strcmp (imageName, gmc.inst_name) == 0) {
	    if (image_done) {
		/* already done on higher level in hierarchy,
		 * skip it here.
		 */
		/* fprintf (stderr, "skipping image on level %d\n", level);/**/
		continue;
	    }
	    else {
		/* not done on higher level in hierarchy,
		 * do it here.
		 */
		/* fprintf (stderr, "proc'ing image on level %d\n", level);/**/
		image_done = 1;
	    }
	}

	/*
	** allocate and add a mc-element to mc-list
	*/
	ALLOCPTR (mcp, mc_elmt);
	mcp -> parent = pcl;
	strcpy (mcp -> name, gmc.cell_name);
	strcpy (mcp -> inst_name, gmc.inst_name);
	mcp -> mtx[0] = gmc.mtx[0];
	mcp -> mtx[1] = gmc.mtx[1];
	mcp -> mtx[2] = samples * gmc.mtx[2];
	mcp -> mtx[3] = gmc.mtx[3];
	mcp -> mtx[4] = gmc.mtx[4];
	mcp -> mtx[5] = samples * gmc.mtx[5];
	mcp -> dx = samples * gmc.dx;
	mcp -> nx = gmc.nx;
	mcp -> dy = samples * gmc.dy;
	mcp -> ny = gmc.ny;

	if (gmc.imported) {
	    proj = dmFindProjKey (gmc.imported, gmc.cell_name,
			pcl -> ckey -> dmproject, &cellname, LAYOUT);
	}
	else {
	    proj = pcl -> ckey -> dmproject;
	    cellname = gmc.cell_name;
	}

	s = cellname;
	hashval = 0;
	while (*s) hashval += *s++;
	hashval %= HASHSIZE;

	for (clp = Hashtab[hashval]; clp; clp = clp -> ht_next)
	    if (strcmp (cellname, clp -> ckey -> cell) == 0
		    && proj == clp -> ckey -> dmproject)
		break; /* found */

	if (!clp) {
	/*
	** allocate new cell-element
	** add it to the cell-list and hash-table
	*/
	    ALLOCPTR (clp, clist);
	    clp -> ht_next = Hashtab[hashval];
	    Hashtab[hashval] = clp;

	    clp -> ckey = dmCheckOut (proj, cellname,
			    ACTUAL, DONTCARE, LAYOUT, READONLY);
	    clp -> hier = 0;

#if NCF_RELEASE >= 400
	    equiv4 = (char **) dmGetMetaDesignData
		            (CELLEQUIVALENCE, proj, cellname, LAYOUT, CIRCUIT);
	    if (equiv4 && equiv4[0]) {
		/* take the first equivalence to see if the cell is a device */
#else
	    if ((int) dmGetMetaDesignData 
			    (EXISTCELL, proj, cellname, CIRCUIT) != 0) {
#endif
		DM_CELL *cirkey;

                noErrMes = 1;
#if NCF_RELEASE >= 400
		if ((cirkey = dmCheckOut (proj, equiv4[0], ACTUAL,
				    DONTCARE, CIRCUIT, READONLY)) != NULL) {
#else
		if ((cirkey = dmCheckOut (proj, cellname, ACTUAL,
				    DONTCARE, CIRCUIT, READONLY)) != NULL) {
#endif

		    if (dmStat (cirkey, "devmod", &buf) == 0)
			clp -> hier = 1;
		}
		noErrMes = 0;
	    }

	    if (clp -> hier == 0) {

		if (hier_mode) {
		    if (dmStat (clp -> ckey, "is_macro", &buf) == 0) {
			dsp = dmOpenStream (clp -> ckey, "is_macro", "r");
			if (fscanf (dsp -> dmfp, "%d", &flag) <= 0 || flag == 0)
			    clp -> hier = 1;
			dmCloseStream (dsp, COMPLETE);
		    }
		    else {
			clp -> hier = 1;
		    }
		}
	    }
	    else {
		if (dmStat (clp -> ckey, "is_macro", &buf) == 0) {
		    dsp = dmOpenStream (clp -> ckey, "is_macro", "r");
		    if (fscanf (dsp -> dmfp, "%d", &flag) > 0 && flag == 1)
			clp -> hier = 2;
		    dmCloseStream (dsp, COMPLETE);
                }
	    }

	    clp -> mc_p = mcp;
	    clp -> mc_p_last = mcp;
	    if (exp_depth == 1 || (Lflag && gmc.imported)) {
		clp -> cl_next = celllist;
		celllist = clp;
	    }
	    else {
		clp -> cl_next = c_list;
		c_list = clp;
	    }
	}
	else {
	    if (clp -> mc_p_last)
		clp -> mc_p_last -> mc_next = mcp;
	    else 
		clp -> mc_p = mcp;
	    clp -> mc_p_last = mcp;
	}
	mcp -> mc_next = 0;
    }

    dmCloseStream (fp, COMPLETE);

    ++level;

    while (clp = c_list) {
	c_list = clp -> cl_next;
	clp -> cl_next = celllist;
	celllist = clp;
	if (clp -> hier != 1) {
	    trav_mctree (clp, image_done);
	}
    }

    --level;

#ifdef DEBUG
P_E "<= trav_mctree()\n");
#endif
}
