1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
/*
* *********************************************************************
* * Copyright (C) 1988, 1990 Stanford University. *
* * 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. Stanford University *
* * 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. *
* *********************************************************************
*/
#include <stdio.h>
#include "defs.h"
#include "net.h"
#include "net_macros.h"
#include "ASSERT.h"
#include "globals.h"
public tptr parallel_xtors[ MAX_PARALLEL ];
/*
* Build a linked-list of nodes (using nlink entry in Node structure)
* which are electrically connected to node 'n'. No special order
* is required so tree walk is performed non-recursively by doing a
* breath-first traversal. The value caches for each transistor we
* come across are reset here. Loops are broken at an arbitrary point
* and parallel transistors are identified.
*/
public void BuildConnList( n )
register nptr n;
{
register nptr next, this, other;
register tptr t;
register lptr l;
int n_par = 0;
n->nflags &= ~VISITED;
withdriven = FALSE;
next = this = n->nlink = n;
do
{
for( l = this->nterm; l != NULL; l = l->next )
{
t = l->xtor;
if( t->state == OFF )
continue;
if( t->tflags & CROSSED ) /* Each transistor is crossed twice */
{
t->tflags &= ~CROSSED;
continue;
}
t->scache.r = t->dcache.r = NULL;
other = other_node( t, this );
if( other->nflags & INPUT )
{
withdriven = TRUE;
continue;
}
t->tflags |= CROSSED; /* Crossing trans 1st time */
if( other->nlink == NULL ) /* New node in this stage */
{
other->nflags &= ~VISITED;
other->nlink = n;
next->nlink = other;
next = other;
other->n.tran = t; /* we reach other through t */
}
else if( model_num != LIN_MODEL )
continue;
else if( hash_terms( other->n.tran ) == hash_terms( t ) )
{ /* parallel transistors */
register tptr tran = other->n.tran;
if( tran->tflags & PARALLEL )
t->dcache.t = par_list( tran );
else
{
if( n_par >= MAX_PARALLEL )
{
WarnTooManyParallel( this->nname, other->nname );
t->tflags |= PBROKEN; /* simply ignore it */
continue;
}
tran->n_par = n_par++;
tran->tflags |= PARALLEL;
}
par_list( tran ) = t;
t->tflags |= PBROKEN;
}
else
{ /* we have a loop, break it */
t->tflags |= BROKEN;
}
}
}
while( (this = this->nlink) != n );
next->nlink = NULL; /* terminate connection list */
}
public void WarnTooManyParallel( s1, s2 )
char *s1, *s2;
{
static int did_it = FALSE;
if( did_it )
return;
lprintf( stderr,
"There are too many transistors in parallel (> %d)\n", MAX_PARALLEL );
lprintf( stderr,
"Simulation results may be inaccurate, to fix this you may have to\n" );
lprintf( stderr,
"increase this limit in '%s'.\n", __FILE__ );
lprintf( stderr,
"Note: This condition often occurs when Vdd or Gnd are not connected\n" );
lprintf( stderr,
" to all cells. Check the vicinity of the following 2 nodes:\n" );
lprintf( stderr, " %s\n %s\n", s1, s2 );
did_it = TRUE;
}
|