/*
 * gcr.h --
 *
 * Routines to implement a modified version of Rivest's Greedy Router.
 *
 *     *********************************************************************
 *     * Copyright (C) 1985, 1990 Regents of the University of California. *
 *     * Permission to use, copy, modify, and distribute this              *
 *     * software and its documentation for any purpose and without        *
 *     * fee is hereby granted, provided that the above copyright          *
 *     * notice appear in all copies.  The University of California        *
 *     * makes no representations about the suitability of this            *
 *     * software for any purpose.  It is provided "as is" without         *
 *     * express or implied warranty.  Export of this software outside     *
 *     * of the United States of America may require an export license.    *
 *     *********************************************************************
 *
 *
 * rcsid "$Header: /usr/cvsroot/magic-8.0/gcr/gcr.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"
 */

#ifndef _MAGIC__GCR__GCR_H
#define _MAGIC__GCR__GCR_H

#include "utils/magic.h"

/* GCRPin:  One of these for each pin location along each edge of a channel.
 *	All of the pins for a given net are stored on a doubly-linked list
 *	for the net, sorted from left to right and bottom to top.  Stored
 *	with the pin are its track and column coordinates (not the actual
 *	locations of terminals).
 *
 *	A pin also stores crossing information for use by the global router,
 *	namely gcr_cost (the best cost known so far to reach this pin),
 *	gcr_side (GEO_NORTH, GEO_SOUTH, GEO_EAST, or GEO_WEST, giving the
 *	side of the channel that the pin lies on), and gcr_linked, pointing
 *	to the pin (in the neighboring channel) that shares the same crossing
 *	point as this one.
 *
 *	x= 0  	    means the pin is at the left edge of the channel.
 *	x= length+1 means the pin is at the right edge of the channel.
 *	y= 0 	    means the pin is at the bottom edge of the channel.
 *	y= width+1  means the pin is at the top edge of the channel.
 *
 *	A net id is in two parts, a net id (gcr_pId) and a segment
 *	id (gcr_pSeg).  During global routing the net id is an integer
 *	net id, not a pointer to a struct (it doesn't turn into a
 *	pointer until just before channel routing).  The segment id
 *	distinguishes parts of a net which are not connected within a
 *	channel because they are connected elsewhere (this prevents
 *	the router from generating loops in the routing).
 */
typedef struct pin
{
    int			 gcr_x, gcr_y;	/* Column and track coordinates */

    /* Information on nearest obstacle */
    int			 gcr_pFlags;	/* 0=clear,1=Obstacle,2=Hazard */
    short		 gcr_pSize;	/* Size of nearest obstacle */
    short		 gcr_pDist;	/* Distance to nearest obstacle */

    /*
     * Net id and segment id assigned to this pin.
     * Special semantics:
     *	gcr_pId == GCR_BLOCKEDNETID means this pin is blocked.
     *	gcr_pSeg == GCR_STEMSEGID means this pin is a stem tip;
     *		gcr_pId gives the net to which the stem tip belongs.
     */
    int                  gcr_pSeg;	/* Id naming part of a net id */
    struct gcrnet	*gcr_pId;	/* Net structure for pin's net */

    /*
     * These fields link available pins along the side of a channel
     * during global routing, and link pins in a net during channel
     * routing.
     */
    struct pin		*gcr_pNext;	/* Next pin to the right or up */
    struct pin		*gcr_pPrev;	/* Next pin left or down */

    /*
     * Stuff for the global router.
     * This is NOT valid in transformed channels, so should
     * not be used by the channel router.
     */
    int			 gcr_cost;	/* Used during global routing */
    struct chan		*gcr_ch;	/* Channel to which this pin belongs */
    int			 gcr_side;	/* Side of channel this pin lies on */
    struct pin		*gcr_linked;	/* Pin (in channel abutting this one)
					 * sharing same crossing point.
					 */
    Point		 gcr_point;	/* Point along channel boundary
					 * in edit cell coords.
					 */
} GCRPin;

#define	GCR_BLOCKEDNETID	((GCRNet *) -1)
#define	GCR_STEMSEGID		(-1)

/* GCRNet:  One structure for each net to be routed.  Nets have pointers,
 * 	to their leftmost and rightmost pins.  The dist field stores the
 *	distance from an unsplit rising or falling active net's current
 *	track to its next connection.  Nets are linked so they may be
 *	freed when the routing is complete.
 *
 *	Each net_id/seg_id pair generates a unique gcrnet struct.
 */
typedef struct gcrnet
{
    int			 gcr_Id;	/* Integer identifying the net */
    int			 gcr_dist;	/* Distance to target track +/- */
    int			 gcr_sortKey;	/* Use to prioritize nets */
    int	  	    	 gcr_track;	/* Track index, used for working
					 * storage in colInit.
					 */
    GCRPin		*gcr_lPin;	/* Leftmost pin of net */
    GCRPin		*gcr_rPin;	/* Rightmost pin of net */
    struct gcrnet	*gcr_next;	/* Next on a linked list of nets */
} GCRNet;


/* GRColEl:  Used in array form, this struct stores horizontal and vertical
 *	wiring for the current column as it is routed.  Locations 1..width are
 *	valid tracks, while 0 and width+1 are wiring to channel top and bottom.
 *
 *	gcr_hi and gcr_lo are used to maintain ordered doubly linked lists of
 *	all tracks occupied by the same net.
 *
 *	gcr_hOk and gcr_lOk are tricky.  They are needed because we
 *	artificially split nets near the end of a channel if there
 *	are multiple end connections.  The net must stay split, but
 *	what's tricky is that several groups of tracks may exist that
 *	are connected within the groups, but the groups haven't been
 *	connected together yet.  These flags keep track of this information.
 *	For example, if gcr_hOk is TRUE but gcr_lOk is false, it
 *	means we don't need to collapse this track with the next one
 *	up, but we do need to join this track with the next one down.
 *	These flags are only used near the ends of channels, and are
 *	normally FALSE.
 */
typedef struct gcrColEl
{
    GCRNet *	gcr_h;		/* Net for horizontal wiring		*/
    GCRNet *	gcr_v;		/* Net for vertical wiring		*/
    int 	gcr_hi;		/* Next higher track for net gcr_h	*/
    int   	gcr_lo;		/* Next lower track for net gcr_h	*/
    bool	gcr_hOk;	/* TRUE if don't need to collapse up	*/
    bool	gcr_lOk;	/* TRUE if don't need to collapse dn	*/
    int		gcr_flags;	/* Flags from the "result" array	*/
    GCRNet *	gcr_wanted;	/* Net that wants this track for end pin*/
} GCRColEl;


/* GCRChannel:
 *
 * Represents all information concerning a channel to be routed.
 * In order to handle boundary conditions more easily, the grid
 * arrays, such as gcr_lCol and gcr_result hold an extra grid
 * point's worth on each side:  the grids run from 0 through
 * length+1 in x, and from 0 through width+1 in y.  The actual
 * channel is from 1..length and 1..width
 */

#define	CHAN_NORMAL	0
#define	CHAN_HRIVER	1
#define	CHAN_VRIVER	2

typedef struct chan
{
/* Description of the channel	 */
    int		 gcr_type;	/* CHAN_NORMAL (0) if a normal channel,
				 * CHAN_HRIVER if only horizontal river routes
				 * are allowed, CHAN_VRIVER if only vertical
				 * river routes are allowed.
				 */
    int		 gcr_length;	/* Number of columns in the channel */
    int		 gcr_width;	/* Number of tracks in the channel */
    Point	 gcr_origin;	/* Grid 0 point */
    Rect	 gcr_area;	/* Area of channel in edit cell coords */
    Transform	 gcr_transform;	/* Transform used when cell has been flipped
				 * or rotated.  Apply this transfrom to grid
				 * coords, scale by grid size, then displace
				 * by gcr_origin to get edit cell coords.
				 */

/* For use by the global router */
    short	*gcr_dRowsByCol;/* Horizontal density during global routing */
    short	*gcr_dColsByRow;/* Vertical density during global routing */
    short	 gcr_dMaxByCol;	/* Max horizontal density */
    short	 gcr_dMaxByRow;	/* Max vertical density */
#define	IDENSITY
#ifdef	IDENSITY
    short	*gcr_iRowsByCol;/* FOR DEBUGGING */
    short	*gcr_iColsByRow;/* FOR DEBUGGING */
#endif	/* IDENSITY */
    struct chan	*gcr_next;	/* For linked lists of channels */

/* Description of the connections */
    GCRPin	*gcr_tPins;	/* Pins at the top of the channel */
    GCRPin	*gcr_bPins;	/* Pins at the bottom of the channel */
    GCRPin	*gcr_lPins;	/* Pins at the left edge of the channel */
    GCRPin	*gcr_rPins;	/* Pins at the right edge of the channel */
    GCRNet	*gcr_nets;	/* Data for each net */

/* Working storage */
    GCRColEl	*gcr_lCol;	/* Column for vertical wiring */
    int		*gcr_density;	/* Density for each column */
    short      **gcr_result;	/* Array of columns, storing the result */

/* For hanging additional information in channels */
    ClientData	 gcr_client;	/* For hire */
    int		 gcr_orient;	/* Channel orientation */
} GCRChannel;

/* Macros that look like procedures */

/************************************************************************
 * Is1stPin(pin)
 *	GCRPin *	pin;
 *
 * Return TRUE if the indexed pin is the first pin on its list.
 */
#define Is1stPin(pin) ((pin)==(pin)->gcr_pId->gcr_lPin)

/************************************************************************
 * IsLstPin(pin)
 *	GCRPin *	pin;
 *
 * Return TRUE if the indexed pin is the last pin on its list.
 */
#define IsLstPin(pin) ((pin)==(pin)->gcr_pId->gcr_rPin)

/************************************************************************
 * GCRNearEnd(channel, column)
 *	GCRChannel * channel;
 *	int          column;
 *
 * Return TRUE if the column is within GCREndDist of the end of the channel.
 */
#define GCRNearEnd(ch,col) (((ch)->gcr_length+1-(col)) <= GCREndDist)

/************************************************************************
 * GCRPin1st(net)
 *	GCRNet * net;
 *
 * Return a pointer to the net's first pin.
 */
#define GCRPin1st(n) ((n)->gcr_lPin)

/************************************************************************
 * GCRPinNext(pin)
 *	GCRPin * pin;
 *
 * Return a pointer to a net's next pin.
 */
#define GCRPinNext(p) ((p)->gcr_pNext)

#define BLOCK(i)	(((i)&GCRBLKM) && ((i)&GCRBLKP))
#define CLEAR(i)	(!((i)&(GCRBLKM|GCRBLKP)))
#define HAS_M(i)	(((i)&GCRBLKM) && (!((i)&GCRBLKP)))
#define HAS_P(i)	(((i)&GCRBLKP) && (!((i)&GCRBLKM)))
#define IS_EMPTY(c,x,y)	((x)<0 ? TRUE : ((x)>(c)->gcr_length ? TRUE : \
			    CLEAR((c)->gcr_result[x][y])))


/*
 * Constants for the result array bits.  Metal and poly here refer to
 * the preferred materials for the long and short dimension of the
 * channel.
 */

    /*
     * The input routine sets these to show where the obstacles are.
     * These entries need to be present in these positions.
     */
#define	GCRBLKM	0x0001	/* 1 if the location is blocked	with metal */
#define GCRBLKP	0x0002 	/* 1 if the location is blocked with poly */

    /* The router sets these bits to show the wiring it produces */
#define GCRU	0x0004	/* 1 if connect from track upwards */
#define GCRR	0x0008	/* 1 if connect to the right */
#define GCRX	0x0010	/* 1 if metal/poly contact */

    /*
     * These bits are used to indicate whether obstacles block tracks
     * or columns for the density computation; they are reset to zero
     * after density initialization so they don't interfere with the
     * wiring bits above (which occupy the same bit positions and mean
     * something entirely different).
     */
#define	GCRBLKT	0x0004	/* Blocks a track */
#define	GCRBLKC	0x0008	/* Blocks a column */

    /* The obstacle identifier sets these to say how to avoid obstacles */
#define GCRVL	0x0020	/* 1 if the track should be vacated here */
#define GCRV2	0x0040	/* 1 if vacate here due to 2-layer obstacle */
#define GCRTC	0x0080	/* 1 if track contact needed */
#define GCRCC	0x0100	/* 1 if column contact needed */
#define GCRTE	0x0200	/* 1 if track can't be use in next column to rt */
#define GCRCE	0x0400	/* 1 if column ends beyond this point */

    /* The metal maximizer sets these bits */
#define GCRVM   0x0800	/* 1 if vertical poly changed to metal */
#define GCRXX   0x1000	/* 1 if via not deleted */

    /* The hazard generation code uses these bits */
#define GCRVR	0x2000	/* 1 if hazard to nets entering from the right */
#define GCRVU	0x4000	/* 1 if hazard to nets entering from the top */
#define GCRVD	0x8000	/* 1 if hazard to nets entering from the bottom */
#define EMPTY	-1

/* Flag bits used to indicate obstacles or hazards over pins */
#define GCRCLR	  0	/* No hazard or obstacle over crossing */
#define GCRHAZRD  1	/* Hazard over crossing */
#define GCROBST   2	/* Obstacle over crossing */
#define GCRBLK    4	/* Blocked area over crossing */
#define GCRTCC    8	/* Track or column contact near crossing */

/* Clip a value (e.g, column or track number) to lie within a range */
#define	INRANGE(x, min, max) \
	((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))

/* These are parameters the user sets to control the router. */
extern int	GCRMinJog;
extern int	GCREndDist;
extern int	GCRSteadyNet;
extern float	GCRObstDist;
extern int	GCRMinChannelSize;
extern bool	GcrShowMap;
extern bool	GcrShowEnd;
extern bool     GcrShowResult;
extern bool     GcrNoCheck;
extern bool     GcrDebug;


/* Procedures exported by the greedy router to the rest of the world: */

extern GCRChannel *GCRNewChannel();
extern void GCRFreeChannel();
extern GCRChannel *GCRRouteFromFile();
extern int GCRroute();
extern void GCRFlipLeftRight();
extern void GCRFlipXY();
extern void GCRNoFlip();
extern void GCRShow();

/* C99 compat */
extern void gcrSaveChannel();
extern bool gcrBlocked();
extern void gcrEvalPat();
extern void gcrLinkTrack();
extern void gcrMoveTrack();
extern int  gcrNextSplit();
extern void gcrUnlinkPin();
extern bool gcrVertClear();
extern void gcrWanted();
extern void gcrBuildNets();
extern void gcrCheckCol();
extern int  gcrClass();
extern void gcrCollapse();
extern int  gcrDensity();
extern void gcrDumpResult();
extern void gcrFeasible();
extern void gcrInitCol();
extern void gcrInitCollapse();
extern int  gcrLook();
extern void gcrMakeRuns();
extern void gcrMarkWanted();
extern void gcrPickBest();
extern void gcrPrintCol();
extern int  gcrRealDist();
extern void gcrReduceRange();
extern bool gcrRiverRoute();
extern void gcrSetEndDist();
extern void gcrSetFlags();
extern void gcrShellSort();
extern int  gcrTryRun();
extern void gcrUncollapse();
extern void gcrVacate();

#endif /* _MAGIC__GCR__GCR_H */
