/*
 * Electric(tm) VLSI Design System
 *
 * File: database.h
 * Database manager: header file
 * Written by: Steven M. Rubin, Static Free Software
 *
 * Copyright (c) 2000 Static Free Software.
 *
 * Electric(tm) is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Electric(tm) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Electric(tm); see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, Mass 02111-1307, USA.
 *
 * Static Free Software
 * 4119 Alpine Road
 * Portola Valley, California 94028
 * info@staticfreesoft.com
 */

/*************************** FLAG BIT SETTINGS ****************************/

#define	MARKN             040				/* NODEINST->userbits: nodeinst is marked */
#define	TOUCHN           0100				/* NODEINST->userbits: nodeinst is touched */

#define	FIXEDMOD   0100000000				/* ARCINST->userbits: fixed arc was changed */
#define	FACETMOD      0400000				/* NODEPROTO->userbits: facet is changed */
#define	FACETNOMOD   01000000				/* NODEPROTO->userbits: facet is not changed */

/*************************** CHANGES ****************************/

#define	NOCHANGE	((CHANGE *)-1)

/* meaning of "changetype" */
#define	NODEINSTNEW      0					/* new nodeinst */
#define	NODEINSTKILL     1					/* killed nodeinst */
#define	NODEINSTMOD      2					/* modified nodeinst */

#define	ARCINSTCHANGE    3					/* base of ARCINST changes */
#define	ARCINSTNEW       3					/* new arcinst */
#define	ARCINSTKILL      4					/* deleted arcinst */
#define	ARCINSTMOD       5					/* modified arcinst */

#define	PORTPROTOCHANGE  6					/* base of PORTPROTO changes */
#define	PORTPROTONEW     6					/* new portinst on a nodeproto */
#define	PORTPROTOKILL    7					/* deleted portinst on a nodeproto */
#define	PORTPROTOMOD     8					/* motified portinst on a nodeproto */

#define	NODEPROTOCHANGE  9					/* base of NODEPROTO changes */
#define	NODEPROTONEW     9					/* new nodeproto */
#define	NODEPROTOKILL   10					/* killed nodeproto */
#define	NODEPROTOMOD    11					/* modified nodeproto */

#define	VARIABLECHANGE  12					/* base of VARIABLE changes */
#define	OBJECTSTART     12					/* start of object change */
#define	OBJECTEND       13					/* end of object change */
#define	OBJECTNEW       14					/* new object */
#define	OBJECTKILL      15					/* deleted object */
#define	VARIABLENEW     16					/* new variable */
#define	VARIABLEKILL    17					/* deleted variable */
#define	VARIABLEMOD     18					/* changed single entry in array variable */
#define	VARIABLEINS     19					/* inserted single entry in array variable */
#define	VARIABLEDEL     20					/* deleted single entry in array variable */
#define	DESCRIPTMOD     21					/* changed text descriptor */

typedef struct Ichange
{
	INTSML          changetype;				/* type of change */
	INTBIG          entryaddr;				/* address of object that was changed */
	struct Ichange *nextchange;				/* address of next change module in list */
	struct Ichange *prevchange;				/* address of previous change module */
	INTBIG          p1,p2,p3,p4,p5,p6;		/* old values before the change */
} CHANGE;

/*************************** CHANGE BATCHES ****************************/

#define	NOCHANGEFACET	((CHANGEFACET *)-1)

typedef struct Ichangefacet
{
	NODEPROTO           *changefacet;		/* the facet that changed */
	INTSML               forcedlook;		/* nonzero if library must be re-examined */
	struct Ichangefacet *nextchangefacet;	/* next in list */
} CHANGEFACET;


#define	NOCHANGEBATCH	((CHANGEBATCH *)-1)

typedef struct Ichangebatch
{
	CHANGE              *changehead;		/* head of list of things to change */
	CHANGE              *changetail;		/* tail of list of things to change */
	struct Ichangebatch *nextchangebatch;	/* next in list */
	struct Ichangebatch *lastchangebatch;	/* last in list */
	CHANGEFACET         *firstchangefacet;	/* the facet in which this change was made */
	AIDENTRY            *aid;				/* aid that made this batch */
	char                *activity;			/* description of activity */
	INTBIG               batchnumber;		/* identifying index of this batch */
	INTSML               done;				/* nonzero if this batch was done */
} CHANGEBATCH;

/*************************** MEMORY ALLOCATION ****************************/

/*
 * the original memory allocation scheme presumed that it would be more
 * efficient to allocate many of a given object whenever more are needed.
 * A linked list of unused objects would then be maintained, and only when
 * the list was empty would the system allocate more.  Freeing simply added
 * the object to the unused list.
 *
 * One problem, though, is that for very large libraries that have been
 * edited for a long time, the memory arena gets fragmented as bits of
 * the library get scattered throughout memory.  On virtual machines with
 * small amounts of physical memory, this causes painful thrashing, because
 * a small facet may require hundreds of page faults simply to display.
 *
 * The solution is to break memory into clusters of activity, as is
 * documented in the module "dbmemory.c".  When using clustering, however,
 * one cannot do bulk allocation because each object might need to be
 * allocated from a different cluster.
 */

extern CLUSTER     *db_clusterfree;			/* list of free memory clusters */
extern CLUSTER     *db_firstcluster;		/* top of list of clusters */
extern WINDOWPART  *db_windowpartfree;		/* top of free list of windows */

/*************************** BOX MERGING ****************************/

/* box descriptor */
typedef struct Iboxpoly
{
	INTBIG             ll[2], lr[2], ul[2], ur[2];
	INTBIG             top, bot, left, right;
	INTBIG             ishor;				/* "ishor" unused */
	INTBIG             numsides, numint[4];
	struct Iboxpoly   *nextbox;
	struct Ipolycoord *polyint[4];
	struct Ipolycoord *auxpolyint[4];
} BOXPOLY;

/* box list head */
typedef struct Iboxlisthead
{
	INTSML               layer;
	TECHNOLOGY          *tech;
	struct Iboxpoly     *box;
	struct Iboxlisthead *nextlayer;
} BOXLISTHEAD;

/* polygon edge descriptor */
typedef struct Ipolycoord
{
	INTBIG             indx, ed_or, ed_start[2], ed_end[2], ed_val, seen;
	struct Ipolycoord *nextpoly;
} POLYCOORD;

/* polygon edge ring head */
typedef struct Ipolylisthead
{
	struct Ipolycoord *firstpoly;
	INTSML             numedge, modified;
} POLYLISTHEAD;

/* polygon edge ring head name */
extern POLYLISTHEAD db_mrg_polycoordlist;

/* free list heads */
extern POLYCOORD   *db_mrg_free_poly_list;
extern BOXPOLY     *db_mrg_free_box_list;
extern BOXLISTHEAD *db_mrg_free_boxhead_list;

extern BOXLISTHEAD *db_mrg_curr_facet;

extern POLYGON     *db_staticpolygons;

/*************************** ERROR CODES ****************************/

/* error messages */
#define	DBNOERROR       0					/* no error */
#define	DBNOMEM	        1					/* no memory */
#define	DBBADTRANS      2					/* bad transposition */
#define	DBBADROT        3					/* bad rotation */
#define	DBBADPROTO      4					/* bad prototype */
#define	DBBADPARENT     5					/* bad parent */
#define	DBBADINST       6					/* invalid instance */
#define	DBBADNAME       7					/* invalid name */
#define	DBBADWIDTH      8					/* bad width */
#define	DBBADENDAN      9					/* bad end A node/port */
#define	DBBADENDBN     10					/* bad end B node/port */
#define	DBBADENDAC     11					/* bad end A connection */
#define	DBBADENDBC     12					/* bad end B connection */
#define	DBBADENDAP     13					/* bad end A position */
#define	DBBADENDBP     14					/* bad end B position */
#define	DBBADNEWWID    15					/* bad new width */
#define	DBBADFACET     16					/* bad facet */
#define	DBBADLIB       17					/* bad library */
#define	DBBADSIZE      18					/* bad size */
#define	DBBADOBJECT    19					/* bad object type */
#define	DBBADSUBPORT   20					/* bad sub port */
#define	DBHASARCS      21					/* still has arcs */
#define	DBHASPORTS     22					/* still has ports */
#define	DBHASINSTANCES 23					/* facet has instances */
#define	DBRECURSIVE    24					/* recursive call */
#define	DBNOTINPORT    25					/* arc not in port */
#define	DBCONFLICT     26					/* conflicts with primitive */
#define	DBPORTMM       27					/* port mismatch */
#define	DBDUPLICATE    28					/* duplicate name */
#define	DBPRIMITIVE    29					/* primitive prototype */
#define	DBBADTMAT      30					/* bad transformation matrix */
#define	DBNOVAR        31					/* variable does not exist */
#define	DBVARFIXED     32					/* variable cannot be set */
#define	DBVARARRDIS    33					/* variable cannot be displayable array */
#define	DBLASTECH      34					/* this is the last technology */
#define	DBTECINUSE     35					/* technology is still in use */

#define	DBADDSTRINGTOINFSTR		(1<<16)
#define	DBADDTECHNOLOGY			(2<<16)
#define	DBADDTOINFSTR			(3<<16)
#define	DBALLOCARCINST			(4<<16)
#define	DBALLOCCELL				(5<<16)
#define	DBALLOCGEOM				(6<<16)
#define	DBALLOCLIBRARY			(7<<16)
#define	DBALLOCNODEINST			(8<<16)
#define	DBALLOCNODEPROTO		(9<<16)
#define	DBALLOCPOLYGON			(10<<16)
#define	DBALLOCPORTARCINST		(11<<16)
#define	DBALLOCPORTEXPINST		(12<<16)
#define	DBALLOCPORTPROTO		(13<<16)
#define	DBALLOCSTRING			(14<<16)
#define	DBALLOCTECHNOLOGY		(15<<16)
#define	DBALLOCVIEW				(16<<16)
#define	DBCOPYNODEPROTO			(17<<16)
#define	DBDELIND				(18<<16)
#define	DBDELINDKEY				(19<<16)
#define	DBDELVALKEY				(20<<16)
#define	DBDESCRIBEVARIABLE		(21<<16)
#define	DBEXTENDPOLYGON			(22<<16)
#define	DBINITINFSTR			(23<<16)
#define	DBINITOBJLIST			(24<<16)
#define	DBINSIND				(25<<16)
#define	DBINSINDKEY				(26<<16)
#define	DBKILLARCINST			(27<<16)
#define	DBKILLLIBRARY			(28<<16)
#define	DBKILLNODEINST			(29<<16)
#define	DBKILLNODEPROTO			(30<<16)
#define	DBKILLPORTPROTO			(31<<16)
#define	DBKILLTECHNOLOGY		(32<<16)
#define	DBMAKEKEY				(33<<16)
#define	DBMODIFYARCINST			(34<<16)
#define	DBMOVEPORTPROTO			(35<<16)
#define	DBNEWARCINST			(36<<16)
#define	DBNEWLIBRARY			(37<<16)
#define	DBNEWNODEINST			(38<<16)
#define	DBNEWNODEPROTO			(39<<16)
#define	DBNEWPORTPROTO			(40<<16)
#define	DBNEWVIEW				(41<<16)
#define	DBREPLACEARCINST		(42<<16)
#define	DBREPLACENODEINST		(43<<16)
#define	DBRETURNINFSTR			(44<<16)
#define	DBSETIND				(45<<16)
#define	DBSETINDKEY				(46<<16)
#define	DBSETVAL				(47<<16)
#define	DBSETVALKEY				(48<<16)
#define	DBTRANSMULT				(49<<16)
#define	DBXFORM					(50<<16)

extern INTBIG       db_lasterror;			/* last error message */
extern INTSML       db_printerrors;			/* flag for printing internal errors */

#if defined(__cplusplus) && !defined(ALLCPLUSPLUS)
extern "C"
{
#endif

/* database prototypes */
void         db_addportarcinst(NODEINST*, PORTARCINST*);
void         db_addportexpinst(NODEINST*, PORTEXPINST*);
INTSML       db_addtortnode(UINTBIG, RTNODE*, NODEPROTO*);
void         db_boundfacet(NODEPROTO*, INTBIG*, INTBIG*, INTBIG*, INTBIG*);
CHANGE      *db_change(INTBIG, INTSML, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG);
void         db_changeport(PORTPROTO*, NODEINST*, PORTPROTO*);
void         db_checkallmemoryfree(void);
void         db_endbatch(void);
void         db_enterarcinst(ARCINST*);
void         db_enternodeinst(NODEINST*);
void         db_enterportproto(PORTPROTO*);
INTSML       db_enterwindowpart(WINDOWPART *w);
INTBIG       db_error(INTBIG);
void         db_forcehierarchicalanalysis(NODEPROTO*);
void         db_freearcproto(ARCPROTO *ap);
void         db_freechangememory(void);
void         db_freegeomemory(void);
void         db_freemathmemory(void);
void         db_freemergememory(void);
void         db_freenoprotomemory(void);
void         db_freertree(RTNODE *rtn);
void         db_freetclmemory(void);
void         db_freetechnologymemory(void);
void         db_freetextmemory(void);
void         db_freevar(INTBIG, INTBIG);
void         db_freevariablememory(void);
void         db_freevars(VARIABLE**, INTSML*);
CHANGEBATCH *db_getcurrentbatch(void);
float        db_getcurrentscale(INTSML, INTSML);
void         db_getinternalunitscale(INTBIG*, INTBIG*, INTSML, INTSML);
INTSML       db_getvarptr(INTBIG, INTBIG, VARIABLE***, INTSML**);
void         db_initclusters(void);
void         db_initdatabase(void);
void         db_initializechanges(void);
void         db_inittechcache(void);
void         db_insertnodeproto(NODEPROTO*);
void         db_killarcinst(ARCINST*);
void         db_killnodeinst(NODEINST*);
void         db_mrgdatainit(void);
ARCINST     *db_newarcinst(ARCPROTO*, INTBIG, INTBIG, NODEINST*, PORTPROTO*, INTBIG, INTBIG,
	NODEINST*, PORTPROTO*, INTBIG, INTBIG, NODEPROTO*);
ARCPROTO    *db_newarcproto(TECHNOLOGY*, char*, INTBIG, INTSML);
NODEINST    *db_newnodeinst(NODEPROTO*, INTBIG, INTBIG, INTBIG, INTBIG, INTSML, INTSML, NODEPROTO*);
PORTPROTO   *db_newportproto(NODEPROTO*, NODEINST*, PORTPROTO*, char*);
NODEPROTO   *db_newprimnodeproto(char*, INTBIG, INTBIG, INTSML, TECHNOLOGY*);
PORTPROTO   *db_newprimportproto(NODEPROTO*, ARCPROTO**, char*);
void         db_printclusterarena(char*);
void         db_printrtree(RTNODE*, RTNODE*, INTSML);
void         db_removechangefacet(NODEPROTO*);
void         db_removeportexpinst(PORTPROTO*);
void         db_retractarcinst(ARCINST*);
void         db_retractnodeinst(NODEINST*);
void         db_retractnodeproto(NODEPROTO*);
void         db_retractportproto(PORTPROTO*);
void         db_retractwindowpart(WINDOWPART *w);
void         db_rtnbbox(RTNODE*, INTSML, INTBIG*, INTBIG*, INTBIG*, INTBIG*);
void         db_scaleonefacet(NODEPROTO*, INTBIG, INTBIG);
void         db_scaletechnology(TECHNOLOGY*, INTBIG, INTBIG);
void         db_setchangefacet(NODEPROTO*);
void         db_setcurrenttool(AIDENTRY*);
INTSML       db_stillinport(ARCINST*, INTSML, INTBIG, INTBIG);
void         db_termlanguage(void);
void         db_undodlog(void);
LIBRARY     *db_whichlibrary(INTBIG, INTBIG);
NODEPROTO   *db_whichnodeproto(INTBIG, INTBIG);

#if defined(__cplusplus) && !defined(ALLCPLUSPLUS)
}
#endif
