#ifndef lint
static char *SccsId = "@(#)tile.c 4.7 (TU-Delft) 04/20/93";
#endif /* lint */
/**********************************************************

Name/Version      : space/4.7

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

Author(s)         : A.J. van Genderen
		  : N.P. van der Meijs
Creation date     : 15-Mar-1988
Modified by       :
Modification date :


        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) 1988. All rights reserved.
**********************************************************/
#ifdef DRIVER
#define DISPLAY
#endif /* DRIVER */

#include <stdio.h>
#include "include/config.h"
#include "include/type.h"
#include "aux/aux.h"
#include "scan.h"

extern bool_t optRes;
extern bool_t optAccWL;
extern bool_t alsoPrePass;
extern bool_t optOnlyPrePass;
extern bool_t optReadNetTerm;
extern bool_t optNoCore;
#define optDisplay 0
extern int nrOfExtConductors;

static int allocs = 0,
	   frees  = 0,
	   max    = 0;

static tile_t * list = NULL;

/* local operations */
private tile_t * allocTile ();

/*  Create a fresh tile
*/
tile_t * createTile (xl, bl, xr, br, color, stb, stl) 
coor_t xl, bl;
coor_t xr, br;
mask_t color;
tile_t * stb, * stl;		/* bot-bot and bot-left stitch */
{
    int i;
    tile_t * t;

#   ifdef DEBUG
    /* the xr-coordinate is the right bbox coordinate of the cell.
     * An assertion xr>xl fails if xl==right bounding box,
     * but it should not fail otherwise.
     */
    static coor_t right;
    ASSERT (xr > xl || xl == right);
    right = xr;
#   endif

    if (list) {
	t = list;
	list = list -> next_tor;
    }
    else {
	t = allocTile ();
    }

    t -> xl = xl, t -> bl = bl;
    t -> xr = xr, t -> br = br;
    t -> color = color;
    t -> known = 0;
    t -> tl = t -> tr = INF;
    t -> tor = NULL, t -> next_tor = NULL;
    t -> tlPoints = t -> rbPoints = NULL;
    t -> terms = NULL;

    if (optRes == FALSE && optAccWL == FALSE) {
	for (i = 0; i < nrOfExtConductors; i++) {
	    t -> cons[i] = NULL;
       }
    }

#   ifdef DEBUG
    if (optDisplay == TRUE 
	|| (alsoPrePass == TRUE && optOnlyPrePass == FALSE)) {
	ASSERT ((char *) t -> cons == (char *) t + sizeof (tile_t));
    }
    else if (optRes == FALSE && optAccWL == FALSE) {
	ASSERT ((char *) t -> cons == (char *) t + sizeof (tile_t));
    }
    else {
	ASSERT (t -> cons == NULL);
    }

#   if 0
    /* The following causes a segmentation violation when running space -r */
    if (optRes == TRUE || optAccWL == TRUE) {
	/* this will force a segmentation violation if
	 * t -> cons[i] is (inadvertedly) used.
	 */
	for (i = 0; i < nrOfExtConductors; i++) {
	    t -> cons[i] = (subnode_t *) 123; 
       }
    }
#   endif
#   endif /* DEBUG */





    Debug (printTile ("new tile", t));

    ASSERT (((!optRes) && (!optAccWL) && (t -> cons != NULL))
          || ((optRes || optAccWL) && t -> cons == NULL) 
	  ||  optDisplay || (alsoPrePass && !optOnlyPrePass));

    if (++allocs - frees > max) max = allocs - frees;
    return (t);
}

/*  Dispose a tile
*/
void disposeTile (tile)
tile_t * tile;
{
    frees++;
    tile -> next_tor = list;
    list = tile;
}

/*  Print a tile
*/
void printTile (s, tile)
char * s;
tile_t * tile;
{
    fprintf (stderr, "%s: xl=%g bl=%g tl=%g xr=%g br=%g tr=%g\n",
	s, (double) tile -> xl, (double) tile -> bl,
 	   (double) tile -> tl, (double) tile -> xr,
	   (double) tile -> br, (double) tile -> tr);
}

void tileStatistics (fp)
FILE * fp;
{
    fprintf (fp, "\ttiles allocated    : %d\n", allocs);
    fprintf (fp, "\ttiles freed        : %d\n", frees);
    fprintf (fp, "\tmax tiles in core  : %d\n", max);
}

private tile_t * allocTile ()
/*
 * Allocate a tile, add a cons array when not extracting resistances.
 * Allignment is a tricky issue;
 * This routine works on all hardware we have tried
 * thanks to the fact that all items in the allocated structs
 * have a size that is a multiple of 4 and can be allocated 
 * on a 4-byte boundary.
 * However, allignment is easily testable with the test driver
 * included in this file, compile with -DDriver.
 */
{

    static unsigned size;
    tile_t * tile;
    char * p;

    if (size == 0) {
	size = sizeof (tile_t);
	if (!(optRes || optAccWL) 
	    || optDisplay || (alsoPrePass && !optOnlyPrePass))
	    size += nrOfExtConductors * sizeof (subnode_t *) 
		  + nrOfExtConductors * sizeof (subnode_t);
    }
    /*
     * ASSERT (sizeof (char) == 1);
     * Otherwise next NEW won't work.
     */
    p = NEW (char, size);

    tile = (tile_t *) p;
    p += sizeof (tile_t);

    if ((optRes == TRUE || optAccWL == TRUE) 
	 && optDisplay == FALSE 
	 && (alsoPrePass == FALSE || optOnlyPrePass == TRUE))
	tile -> cons = NULL;

    else {
	tile -> cons = (subnode_t **) p;
	ASSERT (p + nrOfExtConductors * sizeof (subnode_t *)
	          + nrOfExtConductors * sizeof (subnode_t)
	       <= (char *) tile + size);
    }


    return (tile);
}


#ifdef DRIVER
bool_t optRes = TRUE;
bool_t optAccWL = TRUE;
bool_t alsoPrePass = FALSE;
bool_t optOnlyPrePass = FALSE;
bool_t optCap3D = TRUE;
bool_t optDisplay = FALSE;
int nrOfExtConductors = 3;

main () {
    int i, j, k;
    tile_t * t[10];

    for (j = 0; j < 10; j++)
	t[j] = createTile (-INF, j, INF, INF, 0, NULL, NULL);

    for (j = 0; j < 10; j++) {
	for (i = 0; i < nrOfExtConductors; i++) {
	    if (t[j] -> cons[i]) {
		fprintf (stderr, "i=%d x=%d y=%d\n",
		    i, t[j] -> cons[i] -> x, t[j] -> cons[i] -> y);
	    }
	}
    }

    for (j = 0; j < 10; j++)
	disposeTile (t[j]);

    tileStatistics (stderr);
}
#endif /* DRIVER */
