static char *SccsId = "@(#)timing.c 4.1 (TU-Delft) 05/24/90";
/**********************************************************

Name/Version      : sls/4.1

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

Author(s)         : A.C. de Graaf, A.J. van Genderen
Creation date     : 10-Jul-1986
Modified by       : S. de Graaf
Modification date : 10-Jul-1986


        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 "extern.h"

NODE ** rfront = NULL;   /* search front paths to source nodes */
NODE ** surround = NULL; /* nodes surrounding the forced nodes */
int     f_cnt;
int     s_cnt;

float	kchange;

inittiming () {
    if (rfront != NULL)
	CFREE (rfront);
    if (surround != NULL)
	CFREE (surround);
    PPALLOC (rfront, maxnvicin, NODE);
    PPALLOC (surround, maxnvicin, NODE);
}

timing () {               /* determine the dynamic behavior parameters */
    int     risefast;
    int     fallfast;
    int     riseslow;
    int     fallslow;
    int     minnotmax;
    int     cnt;
    float   Tt;
    NODE ** nn;
    NODE * n;
    int help;

    risefast = FALSE;
    fallfast = FALSE;
    riseslow = FALSE;
    fallslow = FALSE;
    minnotmax = FALSE;

    /* first it is investigated what kind of time constant calculations
       have to be done */

    nn = vicin.nodes;
    for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	n = *nn++;

	if (n -> type == Forced) {
	    continue;
	}

	if (n -> svmax > n -> ei -> umax)
	    risefast = TRUE;
	else
	    if (n -> svmax < n -> ei -> umax)
		fallslow = TRUE;

	if (n -> svmin < n -> ei -> umin)
	    fallfast = TRUE;
	else
	    if (n -> svmin > n -> ei -> umin)
		riseslow = TRUE;

	if (n -> ei -> umin != n -> ei -> umax)
	    minnotmax = TRUE;
    }

    riseslow = riseslow 
	       && (minnotmax || vicin.undeftors || vicin.forcedsX || !risefast);
    fallslow = fallslow 
	       && (minnotmax || vicin.undeftors || vicin.forcedsX || !fallfast);

    if (risefast) {
	det_TD (RISE, FAST);

	nn = vicin.nodes;
	for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	    n = *nn++;

	    if (n -> type == Forced) {
		continue;
	    }

	    if (n -> svmax > n -> ei -> umax) {
    	        Tt = 2 * n -> ei -> TD
		     / ((n -> svmax - n -> ei -> umax) * inttimeaccur);
                if (Tt > MAXINT) {
                    slserror (NULL, 0, ERROR1, 
                    "too large delay occurred", NULL);
                }
                else
                    n -> Ttmax = Tt;
	    }
	    if (n -> svmin > n -> ei -> umin && !riseslow) {
		Tt = 2 * n -> ei -> TD
		     / ((n -> svmin - n -> ei -> umin) * inttimeaccur);
                if (Tt > MAXINT) {
                    slserror (NULL, 0, ERROR1, 
                    "too large delay occurred", NULL);
                }
                else
                    n -> Ttmin = Tt;
	    }
	}
    }

    if (fallfast) {
	det_TD (FALL, FAST);

	nn = vicin.nodes;
	for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	    n = *nn++;

	    if (n -> type == Forced) {
		continue;
	    }

	    if (n -> svmin < n -> ei -> umin) {
		Tt = 2 * n -> ei -> TD
		     / ((n -> ei -> umin - n -> svmin) * inttimeaccur);
                if (Tt > MAXINT) {
                    slserror (NULL, 0, ERROR1, 
                    "too large delay occurred", NULL);
                }
                else
                    n -> Ttmin = Tt;
	    }
	    if (n -> svmax < n -> ei -> umax && !fallslow) {
		Tt = 2 * n -> ei -> TD
		     / ((n -> ei -> umax - n -> svmax) * inttimeaccur);
                if (Tt > MAXINT) {
                    slserror (NULL, 0, ERROR1, 
                    "too large delay occurred", NULL);
                }
                else
                    n -> Ttmax = Tt;
	    }
	}
    }

    if (riseslow) {
	det_TD (RISE, SLOW);

	nn = vicin.nodes;
	for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	    n = *nn++;

	    if (n -> type == Forced) {
		continue;
	    }

	    if (n -> svmin > n -> ei -> umin) {
		Tt = 2 * n -> ei -> TD
		     / ((n -> svmin - n -> ei -> umin) * inttimeaccur);
                if (Tt > MAXINT) {
                    slserror (NULL, 0, ERROR1, 
                    "too large delay occurred", NULL);
                }
                else
                    n -> Ttmin = Tt;
	    }
	}
    }

    if (fallslow) {
	det_TD (FALL, SLOW);

	nn = vicin.nodes;
	for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	    n = *nn++;

	    if (n -> type == Forced) {
		continue;
	    }

	    if (n -> svmax < n -> ei -> umax) {
		Tt = 2 * n -> ei -> TD
		     / ((n -> ei -> umax - n -> svmax) * inttimeaccur);
                if (Tt > MAXINT) {
                    slserror (NULL, 0, ERROR1, 
                    "too large delay occurred", NULL);
                }
                else
                    n -> Ttmax = Tt;
	    }
	}
    }

    nn = vicin.nodes;
    for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	n = *nn++;

	if (n -> type == Forced)
	    continue;

	if (n -> Ttmin < 0)
	    n -> Ttmin = 0;
	if (n -> Ttmax < 0)
	    n -> Ttmax = 0;
        /* this namely may occur sometimes */

        if (n -> svmin > n -> ivmax) {
 	    if (n -> Ttmin < n -> Ttmax
 		&& n -> svmin > 
 	           n -> ivmax + ((float)(n -> Ttmin) / (float)(n -> Ttmax))
 				* ((float)(n -> svmax) - (float)(n -> ivmax))) {
 		help = n -> Ttmax;
 		n -> Ttmax = n -> Ttmin;
 		n -> Ttmin = help;
 	    }
 	}
        else if (n -> svmax < n -> ivmin) {
 	    if (n -> Ttmax < n -> Ttmin
 		&& n -> svmax < 
 	           n -> ivmin + ((float)(n -> Ttmax) / (float)(n -> Ttmin)) 
 				* ((float)(n -> svmin) - (float)(n -> ivmin))) {
 		help = n -> Ttmin;
 		n -> Ttmin = n -> Ttmax;
 		n -> Ttmax = help;
 	    }
 	}
 	/* to be sure that umin(t) <= umax(t) for all t */

        if (n -> svmin > n -> ei -> umin) {
	    n -> Ttmin = n -> Ttmin * maxdevtime;
	    n -> tstabmin = tcurr + n -> Ttmin;
	}
	else if (n -> svmin < n -> ei -> umin) {
	    n -> Ttmin = n -> Ttmin * mindevtime;
	    n -> tstabmin = tcurr + n -> Ttmin;
	}

        if (n -> svmax > n -> ei -> umax) {
	    n -> Ttmax = n -> Ttmax * mindevtime;
	    n -> tstabmax = tcurr + n -> Ttmax;
	}
	else if (n -> svmax < n -> ei -> umax) {
	    n -> Ttmax = n -> Ttmax * maxdevtime;
	    n -> tstabmax = tcurr + n -> Ttmax;
	}

	if (debugsim) {
	    fprintf (debug, "\nnode: %s\n", hiername (n - N) );
	    fprintf (debug, "tcurr: %d\n", tcurr);
	    fprintf (debug, 
	    "ei -> umin: %f ei -> umax: %f svmin: %d svmax: %d\n"
	    ,n -> ei -> umin, n -> ei -> umax, n -> svmin, n -> svmax);
	    fprintf (debug, "Ttmin: %d  ", n -> Ttmin);
	    fprintf (debug, "Ttmax: %d\n", n -> Ttmax);
	    fprintf (debug, "tstabmin: %d  ", n -> tstabmin);
	    fprintf (debug, "tstabmax: %d", n -> tstabmax);
	    fprintf (debug, "\n");
	}
    }

    if (debugsim)
	fprintf (debug, "\n");
}

det_TD (change, speed)     /* determine a TD for a fast or slow rising or */
int     change;            /* falling voltage */
int     speed;
{
    int     cnt;
    NODE ** nn;
    NODE * n;
    TRANSISTOR ** tt;
    TRANSISTOR * t;
    int     findforcedsource ();

    if (debugsim) {
	fprintf (debug, "***** det_TD *****");
	if (change == RISE)
	    fprintf (debug, " RISE");
	else
	    fprintf (debug, " FALL");
	if (speed == FAST)
	    fprintf (debug, " FAST");
	else
	    fprintf (debug, " SLOW");
	fprintf (debug, " ******\n\n");
    }

    if (vicin.type == Forced) {
	if (!findforcedsource (change, speed))
	    findnormalsource (change, speed);
    }
    else {
	findnormalsource (change, speed);
    }

    modedeterm (change, speed);
    fillparam (change, speed);

    if (debugsim) {
	nn = vicin.nodes;
	for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	    n = *nn++;
	    fprintf (debug, "node=%s  dyncap=%e\n",
		    hiername (n - N), n -> ei -> dyncap);
	}

        tt = vicin.tors;
        for (cnt = vicin.tor_cnt; cnt > 0; cnt--) {
	    t = *tt++;

	    fprintf (debug, "tor=%d  mode=", t - T);
	    switch (t -> ei -> mode) {
		case Pulldown :
		    fprintf (debug, "Pulldown");
		    break;
		case Pullup :
		    fprintf (debug, "Pullup");
		    break;
		case Passdown :
		    fprintf (debug, "Passdown");
		    break;
		case Passup :
		    fprintf (debug, "Passup");
		    break;
		case Load :
		    fprintf (debug, "Load");
		    break;
		case Superload :
		    fprintf (debug, "Superload");
		    break;
		case NULL :
		    if (t -> type == Res)
			fprintf (debug, "NULL(Resistor)");
		    else
			ERROR_EXIT (1);
		    break;
		default :
		    ERROR_EXIT (1);
	    }

            fprintf (debug, " ");
	    switch (t -> state) {
		case Open :
		    fprintf (debug, "Open");
		    break;
		case Closed :
		    fprintf (debug, "Closed");
		    break;
		case Undefined :
		    fprintf (debug, "Undefined");
		    break;
	    }
	    fprintf (debug, " resist=%e\n", t -> ei -> resist);
	}

	fprintf (debug, "\n");
    }

    tree_TD (change, speed);
}

int     findforcedsource (change, speed)   /* find source(s) which is (are)  */
int     change;                            /* Forced node.  returns FALSE if */
int     speed;                             /* no source can be found         */
{
    int     sourcefound;
    int     cnt;
    NODE ** nn;
    NODE * n;

    sourcefound = FALSE;
    nn = vicin.nodes;
    for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	n = *nn++;
	if (n -> type == Forced
	    && ( (n -> ei -> lstate == X_state && speed == FAST)
	         || (n -> ei -> lstate == H_state && change == RISE)
	         || (n -> ei -> lstate == L_state && change == FALL))) {
	    n -> ei -> source = TRUE;
	    n -> ei -> TD = 0;
	    sourcefound = TRUE;

	    if (debugsim)
		fprintf (debug, "source: %s\n", hiername (n - N) );
	}
	else {
	    n -> ei -> source = FALSE;
	}
    }

    return (sourcefound);
}

findnormalsource (change, speed)   /* find source which is a Normal node */
int     change;
int     speed;
{
    float   maxamount;
    float   amount;
    int     cnt;
    NODE ** nn;
    NODE * n;
    NODE * source_n;

    maxamount = 0;
    source_n = NULL;
    nn = vicin.nodes;
    for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	n = *nn++;
	n -> ei -> source = FALSE;

	if (n -> type == Forced)
	    continue;

	if (change == RISE) {
	    if (speed == FAST)
		amount = n -> statcap * n -> ei -> umax;
	    else
		amount = n -> statcap * n -> ei -> umin;
	}
	else {
	    if (speed == FAST)
		amount = n -> statcap * (vH - n -> ei -> umin);
	    else
		amount = n -> statcap * (vH - n -> ei -> umax);
	}
	if (amount > maxamount || source_n == NULL) {
	    source_n = n;
	    maxamount = amount;
	}
    }

    if (source_n == NULL) {
	ERROR_EXIT (1);  /* can't find source node */
    }

    source_n -> ei -> source = TRUE;
    source_n -> ei -> TD = 0;

    if (debugsim)
	fprintf (debug, "source: %s\n", hiername (source_n - N) );
}

modedeterm (change, speed)   /* determine the mode of the transistors */
int     change;
int	speed;
{
    int     cnt;
    TRANSISTOR ** tt;
    TRANSISTOR * t;

    tt = vicin.tors;
    for (cnt = vicin.tor_cnt; cnt > 0; cnt--) {
	t = *tt++;

	switch (t -> type) {
	    case Nenh: 
	    case Penh: 
		if (t -> premode == Passup) {
		    if (change == RISE) 
			t -> ei -> mode = Passup;
		    else
			t -> ei -> mode = Passdown;
		}
		else if (t -> premode == Pullup) {
		    if (change == RISE) 
			t -> ei -> mode = Pullup;
		    else
			t -> ei -> mode = Pulldown;
		}
		else
		    t -> ei -> mode = NULL;
		break;
	    case Depl: 
		t -> ei -> mode = t -> premode;
		break;
	    case Res: 
		t -> ei -> mode = NULL;
		break;
	}
    }
}

fillparam (change, speed)   
int change;       /* fill in the appropiate capacitances and resistances */
int speed;         
{
    int     cnt;
    int     cnt2;
    int     index;
    NODE ** nn;
    NODE * n;
    TRANSISTOR ** tt;
    TRANSISTOR * t;
    float   cch;
    float   torpar ();

    nn = vicin.nodes;
    for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	n = *nn++;

        if (n -> type == Forced)
	    continue;

	n -> ei -> dyncap = n -> dyncap;

	if (n -> dsx != -1) {
	    index = n -> dsx;
	    for (cnt2 = DS[index]; cnt2 > 0; cnt2--) {
		index++;
		t = &T[DS[index]];
		if (change == RISE)
		    n -> ei -> dyncap += torpar (t, NULL, Cerise);
		else
		    n -> ei -> dyncap += torpar (t, NULL, Cefall);
	    }
	}

	if (n -> cx != -1) {
	    index = n -> cx;
	    for (cnt2 = C[index].c; cnt2 > 0; cnt2--) {
		index++;
		if (C[index].sort == Transistor) {
		    t = &T[C[index].c];
		    if (change == RISE)
			n -> ei -> dyncap += torpar (t, NULL, Cgrise);
		    else
			n -> ei -> dyncap += torpar (t, NULL, Cgfall);
		}
	    }
	}
    }

    tt = vicin.tors;
    for (cnt = vicin.tor_cnt; cnt > 0; cnt--) {
	t = *tt++;

	cch = torpar (t, (int) t -> ei -> mode, Cch);
	N[t -> drain].ei -> dyncap += cch;
	N[t -> source].ei -> dyncap += cch;

	t -> ei -> resist = torpar (t, (int) t -> ei -> mode, Rdyn);
    }
}

tree_TD (change, speed)
int     change;
int     speed;
{
    int     cnt;
    float   resist;
    float   vdelta;
    NODE ** nn;
    NODE * n;
    NODE * conn;
    NODE * sourcen;
    NODE * wcpathn;
    TRANSISTOR ** tt;
    TRANSISTOR * t;

    /* initialize variables and find initial accum charge */

    nn = vicin.nodes;
    for (cnt = vicin.node_cnt; cnt > 0; cnt--) {
	n = *nn++;

	n -> ei -> path = NULL;
	n -> ei -> done = FALSE;
	n -> ei -> leaf = TRUE;    /* as long as no path points to n, n is
				      assumed to be a leaf */
	n -> ei -> backtraced = FALSE;
	n -> ei -> accumulated = FALSE;
	if (change == RISE) {
	    if (speed == FAST)
		vdelta = n -> svmax - n -> ei -> umax;
	    else
		vdelta = n -> svmin - n -> ei -> umin;
	}
	else {
	    if (speed == FAST)
		vdelta = n -> ei -> umin - n -> svmin;
	    else
		vdelta = n -> ei -> umax - n -> svmax;
	}
	n -> ei -> accumcharge = n -> ei -> dyncap * vdelta;
    }

    /* nodes connected to source nodes are put on the front list. */
    /* simultaneously the nodes which surround the source nodes are put */
    /* on the front list. */

    s_cnt = 0;
    f_cnt = 0;

    tt = vicin.tors;
    for (cnt = vicin.tor_cnt; cnt > 0; cnt--) {
	t = *tt++;

	if (t -> state == Undefined && speed == SLOW)
	    continue;

	if (N[t -> drain].ei -> source) {
	    conn = &N[t -> source];
	    sourcen = &N[t -> drain];
	}
	else
	    if (N[t -> source].ei -> source) {
		conn = &N[t -> drain];
		sourcen = &N[t -> source];
	    }
	    else
		continue;

	if (!conn -> ei -> source && conn -> type != Forced) {
	    resist = t -> ei -> resist;
	    if (conn -> ei -> path == NULL) {
		conn -> ei -> r = resist;
		conn -> ei -> path = sourcen;
		sourcen -> ei -> leaf = FALSE;
		rfront[f_cnt++] = conn;
		surround[s_cnt++] = conn;
		if (t -> state == Undefined)
		    conn -> ei -> xtorpath = TRUE;
		else
		    conn -> ei -> xtorpath = FALSE;
	    }
	    else
		if (conn -> ei -> r > resist) {
		    conn -> ei -> r = resist;
		    conn -> ei -> path = sourcen;
		    sourcen -> ei -> leaf = FALSE;
		    if (t -> state == Undefined)
		        conn -> ei -> xtorpath = TRUE;
		    else
		        conn -> ei -> xtorpath = FALSE;
		}
	}
    }

    /* find the minimum resistance paths */

    path (speed);

    if (speed == SLOW) {
     
	/* when speed is slow paths are not searched through Undefined
	   transistors and some nodes will have no path.  therefore
	   an additional search is done for the resulting nodes, with
	   Undefined transistors considered to be Closed */

	f_cnt = 0;

        tt = vicin.tors;
        for (cnt = vicin.tor_cnt; cnt > 0; cnt--) {
	    t = *tt++;

	    if (N[t -> drain].ei -> source 
	    || N[t -> drain].ei -> path != NULL) {
	        conn = &N[t -> source];
	        wcpathn = &N[t -> drain];
	    }
	    else
	        if (N[t -> source].ei -> source
	        || N[t -> source].ei -> path != NULL) {
		    conn = &N[t -> drain];
		    wcpathn = &N[t -> source];
	        }
	        else
		    continue;

	    if (!conn -> ei -> source && conn -> type != Forced 
		&& !conn -> ei -> done) {
	        resist = t -> ei -> resist;
	        if (conn -> ei -> path == NULL) {
		    conn -> ei -> r = resist;
		    conn -> ei -> path = wcpathn;
		    wcpathn -> ei -> leaf = FALSE;
		    rfront[f_cnt++] = conn;
		    if (wcpathn -> ei -> source)
		        surround[s_cnt++] = conn;
		    if (t -> state == Undefined)
		        conn -> ei -> xtorpath = TRUE;
		    else
		        conn -> ei -> xtorpath = FALSE;
	        }
	        else
		    if (conn -> ei -> r > resist) {
		        conn -> ei -> r = resist;
		        conn -> ei -> path = wcpathn;
		        wcpathn -> ei -> leaf = FALSE;
		        if (t -> state == Undefined)
		            conn -> ei -> xtorpath = TRUE;
		        else
		            conn -> ei -> xtorpath = FALSE;
		    }
	    }
        }

	path (FAST);
    }

    accumulate (speed);

    if (change == RISE)
	kchange = krise;
    else if (change == FALL)
	kchange = kfall;
    else
	ERROR_EXIT (1);

    /* start the back tracing at the nodes which are on the surround list */

    while (s_cnt > 0) {
	n = surround[--s_cnt];
	n -> ei -> TD = kchange * n -> ei -> r * n -> ei -> accumcharge;
	n -> ei -> backtraced = TRUE;

	if (debugsim) {
	    fprintf (debug,
		    "backtrace: %s  TD: %e  r: %e  accumcharge: %e\n",
		    hiername (n - N), n -> ei -> TD,
		    n -> ei -> r, n -> ei -> accumcharge);
	}

	backtrace_T (n, speed);
    }
}

path (speed)     /* find the minimum resistance paths to the source nodes */
int	speed;
{
    int     cnt;
    int     index;
    int     index_fn;
    int     index_m_r;
    NODE * n;
    NODE * conn;
    TRANSISTOR * cont;
    float   resist;
    float   res;
    float   min_res;

    while (f_cnt > 0) {
	min_res = MAXRESIST;
	for (index_fn = 0; index_fn < f_cnt; index_fn++) {
	    res = rfront[index_fn] -> ei -> r;
	    if (res < min_res) {
		min_res = res;
		index_m_r = index_fn;
	    }
	}
	n = rfront[index_m_r];
	n -> ei -> done = TRUE;
	rfront[index_m_r] = rfront[--f_cnt];

	index = n -> dsx;
	for (cnt = DS[index]; cnt > 0; cnt--) {
	    index++;
	    cont = &T[DS[index]];

	    if (cont -> state == Open
	    || (cont -> state == Undefined && speed == SLOW))
		continue;

	    if (&N[cont -> source] == n)
		conn = &N[cont -> drain];
	    else
		conn = &N[cont -> source];

	    if (conn -> ei -> source
	    || conn -> type == Forced
	    || conn -> ei -> done)
		continue;

	    resist = n -> ei -> r + cont -> ei -> resist;
	    if (conn -> ei -> path == NULL) {
		conn -> ei -> r = resist;
		conn -> ei -> path = n;
		n -> ei -> leaf = FALSE;
		rfront[f_cnt++] = conn;
		if (cont -> state == Undefined)
		    conn -> ei -> xtorpath = TRUE;
		else
		    conn -> ei -> xtorpath = FALSE;
	    }
	    else
		if (conn -> ei -> r > resist) {
		    conn -> ei -> r = resist;
		    conn -> ei -> path = n;
		    n -> ei -> leaf = FALSE;
		    if (cont -> state == Undefined)
		        conn -> ei -> xtorpath = TRUE;
		    else
		        conn -> ei -> xtorpath = FALSE;
		}
	}
    }
}

accumulate (speed)  /* accumulate charges from the leaves to the source nodes */
int	speed;
{
    int     followon;
    int     index;
    int     cnt;
    int     ncnt;
    NODE ** nn;
    float   loadcharge;
    NODE * n;
    TRANSISTOR * cont;

    nn = vicin.nodes;
    for (ncnt = vicin.node_cnt; ncnt > 0; ncnt--) {
	n = *nn++;

	if (!n -> ei -> leaf || n -> ei -> source || n -> type == Forced) 
	    continue; 

	followon = TRUE;
	do {
	    if (speed == FAST && n -> ei -> xtorpath)
		loadcharge = 0;
	    else
	        loadcharge = n -> ei -> accumcharge;
	    n -> ei -> accumulated = TRUE;
	    n = n -> ei -> path;
	    n -> ei -> accumcharge += loadcharge;
	    if (n -> ei -> source) {
		followon = FALSE;
	    }
	    else {
		index = n -> dsx;
		for (cnt = DS[index]; cnt > 0 && followon; cnt--) {
		    index++;
		    cont = &T[DS[index]];

		    if (cont -> state == Open)
			continue;

		    if ((!N[cont -> source].ei -> accumulated
				&& N[cont -> source].ei -> path == n)
			    || (!N[cont -> drain].ei -> accumulated
				&& N[cont -> drain].ei -> path == n)
			) {
			followon = FALSE;
		    }
		}
	    }
	}
	while (followon);

    }
}

backtrace_T (n, speed)   /* trace the paths back from n recursively     */
NODE * n;                /* and determine TD for the nodes on the paths */
int speed;
{
    int     index;
    int     cnt;
    NODE * conn;
    TRANSISTOR * cont;

    index = n -> dsx;
    for (cnt = DS[index]; cnt > 0; cnt--) {
	index++;
	cont = &T[DS[index]];

	if (cont -> state == Open)
	    continue;

	if (&N[cont -> source] == n)
	    conn = &N[cont -> drain];
	else
	    conn = &N[cont -> source];

	if (conn -> type != Forced
	&& conn -> ei -> path == n
	&& !conn -> ei -> backtraced) {
	    if (speed == FAST && conn -> ei -> xtorpath) {
	        conn -> ei -> TD = n -> ei -> TD
			           + (conn -> ei -> r)
		                     * conn -> ei -> accumcharge * kchange;
	    }
	    else {
	        conn -> ei -> TD = n -> ei -> TD
			           + (conn -> ei -> r - n -> ei -> r)
		                     * conn -> ei -> accumcharge * kchange;
	    }
	    conn -> ei -> backtraced = TRUE;

	    if (debugsim) {
		fprintf (debug,
			"backtrace: %s TD: %e  r: %e accumcharge: %e\n",
			hiername (conn - N) , conn -> ei -> TD,
			conn -> ei -> r, conn -> ei -> accumcharge);
	    }

	    backtrace_T (conn, speed);
	}
    }
}
