static char *SccsId = "@(#)dffunc.cls 4.8 (TU-Delft) 11/05/92";
/**********************************************************

Name/Version      : sls_mkdb/4.8

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

Author(s)         : A.J. van Genderen
Creation date     : 9-Oct-1986
Modified by       : A.J. van Genderen
Modification date : 20-Feb-1987
Modified by       : P.E. Menchen
Modification date : 23-Jan-1992


        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) 1986 , All rights reserved
**********************************************************/
#include "sys_incl.h"
#class
#include "class.h"
#include "mkdbdefs.h"

#define EQUI_TOOL "relate"

extern Dictionary *dff_dict;

extern DM_PROJECT *dmproject;

extern char f_view[BUFSIZ];     /* Viewtype to look for functional cells */
extern int cirflag;             /* Set if only circuit viewtype used */
extern int dummy;               /* Set if dummy cell to be made even if a
                                   circuit exists */
extern int sflag;               /* Set if running in silent mode */
extern int interact;            /* Set for user interactive mode */
extern int yylineno;            /* For possible error reporting */

Stack * xs_rf = NULL;

Network *read_dff(name)
char *name;
{
    DM_CELL * f_key;
    DM_STREAM * f_stream;

    Network * ntw;
    Xelem * stkelem;
    struct stat buf;
    char * new_name;
    DM_PROJECT *projkey;
    int imported;
    char *ftermname;

    int k;

#ifdef FUNCVIEW
    int dumbflag = 0;            /* set TRUE turns on writing to dummy cell */
    DM_CELL * dumb_key;          /* dummy circuit cell if needs to be created */
    DM_STREAM * dumb_stream;     /* term stream for dummy circuit cell */
    char dumb_id[DM_MAXNAME+1];

    int i, j;                    /* used for rows and columns of query */
    int n;
    data ** query_res;
    data ** query_use = NULL;
    char usr_in[BUFSIZ];
    int valid = 0;
    int made_equi = 0;
#endif

    int exist;
    int existCell ();

    if ((exist = existCell (name, f_view)) == 0)
	return (NULL);

    imported = ((exist == 1)?(LOCAL):(IMPORTED));

    projkey = dmFindProjKey (imported, name, dmproject, &new_name, f_view);

    f_key = dmCheckOut (projkey, new_name, ACTUAL, 
			DONTCARE, f_view, READONLY); 

#ifdef FUNCVIEW
    if (cirflag)
	ftermname = "fterm";
    else
	ftermname = "term";
#else
    ftermname = "fterm";
#endif

    if (dmStat (f_key, ftermname, &buf) == 0) {
	f_stream = dmOpenStream (f_key, ftermname, "r"); 
    }
    else {
	if (imported == IMPORTED)
	    dmCloseProject (projkey, COMPLETE);

        return (NULL);
        /* apparently, the circuit view only contains a real circuit */
    }

#ifdef FUNCVIEW
    if (!cirflag) {              /* If using functional and circuit viewtypes */

      if (!dummy) {
	 query_res = dmQuery (projkey, &i, &j, "GET Equivalence \
		ITS Derived-DesignObject ITS Module ITS Name, \
		Derived-DesignObject ITS Vnumber, Derived-DesignObject \
		ITS Vstatus, Derived-DesignObject ITS Imported WHERE \
		Derived-DesignObject ITS Vstatus != 'backup' AND \
		Tool == '%s' AND Valid == 1 AND \
		Original-DesignObject == '%s' ", EQUI_TOOL, f_key->old_object);

	 if (interact) {
	    fprintf (stderr,
		     "Functional cell %s instantiated.\n", name);
	    fprintf (stderr, "Cell has the following equivalent(s):\n");
	    if (i > 0)
	       for (n = 2; n < i + 2; n++)
		  fprintf (stderr,
			   "\t%d) %s %s #%d Vstatus: %s Imported: %d\n",
			   n - 1, query_res[n][0].point, query_res[n][1].point,
			   query_res[n][2].value, query_res[n][3].point,
			   query_res[n][4].value);
	    else
	       fprintf (stderr, "\t<none>\n");
	    while (!valid) {
	       valid = 1;
	       fprintf (stderr,
		       "Enter number of equivalence to use, or 'd' to make\n");
	       fprintf (stderr,
		       "a dummy, or 'e' to make a new equivalence: ");
	       gets (usr_in);
	       if (usr_in[0] == 'd') {
		  /* make a dummy */
		  dumbflag = 1;
	       } 
	       else if (usr_in[0] == 'e') {
		  /* make an equivalence */
		  fprintf (stderr, "Equivalent circuit name? ");
		  gets (usr_in);
		  if (make_equi (name, usr_in)) {
		     /* make_equi failed */
		     fprintf (stderr,
			      "%s failed to make equivalence to circuit %s.\n",
			      EQUI_TOOL, usr_in);
		     valid = 0;
		  } else {
		     /* made equivalence */
		     fprintf (stderr,
			  "Established equivalence to existing circuit: %s\n",
			  usr_in);
		     made_equi = 1;
		     strcpy (name, usr_in); /* IS THIS SAFE ??? */
		  }
	       } else if ( (n = atoi (usr_in)) > 0 && n <= i) {
		  /* use numbered equivalence */
		  query_use = query_res + n + 1;
	       } else {
		  /* bad input */
		  fprintf (stderr, "Bad input, try again ...\n");
		  valid = 0;
	       }
	    }

	 } 
         else if (i > 0) 
	    query_use = query_res + i + 1;       /* uses most recent equi */

	 if (query_use) {
	    imported = query_use[0][4].value;
	    if (!sflag) {
	       fprintf (stderr,
		       "\tUsing equivalence %s for functional cell %s.\n",
		       query_use[0][0].point, name);
	    }
	    if ( strcmp (name, query_use[0][1].point) ) {
	       strcpy (name, query_use[0][1].point); /* IS THIS SAFE ??? */
	       if (!sflag)
		  fprintf(stderr,"\t  Equivalent circuit name: %s\n", name);
	    }

	 } 
	 else if (!made_equi) {
	    if (!dumbflag && (int) dmGetMetaDesignData
		(EXISTCELL, projkey, name, CIRCUIT)
		&& !(make_equi (name, name)) ) { 
	       if (!sflag)
		  fprintf(stderr,
			"\tEstablished equivalence to existing circuit: %s\n",
			  name);
	    } else
	       dumbflag = 1;    /* no circuit found, or if found, could not
				   make an equivalence, so must make a dummy */
	 }
	 dmQDisposeResult (query_res, j);
      }

      if ( dummy || dumbflag ) {              /* create a dummy circuit cell */
	 dumb_key = dmCheckOut (projkey, name, WORKING, DONTCARE,
				CIRCUIT, UPDATE);
	 dumb_stream = dmOpenStream (dumb_key, "term", "w");
	 dumbflag = 1;
      }
      else {
	 DM_CELL *ck;

	 /* Also check out the equivalent cell to make it's ID known when
	    the 'mc' stream of the current cell is written.
	 */

	 ck = dmCheckOut (projkey, name, ACTUAL, 
			  DONTCARE, CIRCUIT, READONLY); 
	 dmCheckIn (ck, COMPLETE);
      }
    }
#endif

    ntw = new Network (name);
    dff_dict -> store (ntw->ntw_name, (char *) ntw);
    if (imported == IMPORTED)
	ntw -> local = 0;
    else
	ntw -> local = 1;

    if (xs_rf == NULL)
        xs_rf = new Stack (XSTACK_SIZE);

    ntw -> termq = new Queue (QueueType);

    while (dmGetDesignData (f_stream, CIR_TERM) > 0 ) {
#ifdef FUNCVIEW
        if (dumbflag)   /* If creating new, dummy circuit, write term stream */
            dmPutDesignData (dumb_stream, CIR_TERM);
#endif
        xs_rf -> reset ();
        for (k = 0; k < cterm.term_dim; k++) {
            stkelem = new Xelem (cterm.term_lower[k], 
                                 cterm.term_upper[k]);
            if (xs_rf -> push ((char *)stkelem) == STACK_OVERFLOW)
                fprintf (stderr, "xstack overflow\n");
        }
        ntw -> termq -> put ((Link *) new Netelem (cterm.term_name,
                                       (Stack *) stackcpy (xs_rf), TermType));
    }

    dmCloseStream (f_stream, COMPLETE);
    dmCheckIn (f_key, COMPLETE);

    if (imported == IMPORTED)
	dmCloseProject (projkey, COMPLETE);

#ifdef FUNCVIEW
    if (dumbflag) {
        dmCloseStream (dumb_stream, COMPLETE);
        strcpy (dumb_id, dumb_key->new_object);
        dmCheckIn (dumb_key, COMPLETE);
        if (make_equi (name, name)) {
            sls_error(yylineno, DEQUIFAIL, name);
            die();
        } 
        else {
            fprintf (stderr, "\tMade equivalent circuit cell: %s\n", name);
            /* Change Vstatus to Actual ? */
            dmChgVersionStatus (projkey, dumb_id, ACTUAL);
        }
    }
#endif

    return (ntw);
}

#ifdef FUNCVIEW
int make_equi (name1, name2) /* Attempts to make an equivalence of named cells.
			      Returns 0 if successful, 1 if not. */
      char * name1;
      char * name2;
{
   char cmdstr[BUFSIZ];
   sprintf (cmdstr, "%s -S %s %s", EQUI_TOOL, name1, name2);
   return (system (cmdstr));
}
#endif
