1 /****************************************************************************/
3 /* Chaine de CAO & VLSI Alliance */
5 /* Produit : YAGLE v3.50 */
6 /* Fichier : yag_analyse.c */
8 /* (c) copyright 1994 Laboratoire MASI equipe CAO & VLSI */
9 /* Tous droits reserves */
10 /* Support : e-mail alliance-support@asim.lip6.fr */
12 /* Auteur(s) : Anthony LESTER le : 10/06/1994 */
14 /* Modifie par : le : ../../.... */
15 /* Modifie par : le : ../../.... */
16 /* Modifie par : le : ../../.... */
18 /****************************************************************************/
20 #include "yag_headers.h"
22 static jmp_buf abandon_analyse
;
24 static int get_opinion(void);
25 static chain_list
*add_node_bdd(chain_list
*bddlist
, gnode_list
*ptnode
);
26 static void build_circuit(branch_list
*ptbranch
, jmp_buf abandon_env
);
27 static pNode
extend_circuit(cone_list
*ptcone
, long type
, jmp_buf abandon_env
);
28 static void add_mutex_pair(chain_list
**ptmutex
, char *name1
, char *name2
);
29 static void check_cone(cone_list
*ptcone
);
30 static void yagCheckGlobalDuality (cone_list
*ptcone
);
31 static void check_big_cone(cone_list
*ptcone
, gnode_list
*rootnode
);
32 static ht
*order(branch_list
*ptbranchlist
, table
*ptnames
);
33 static void clean_precharge_marks(cone_list
*ptcone
, cone_list
*ptloopcone
);
35 jmp_buf *yagAbandonAnalyse()
37 return &abandon_analyse
;
41 yagCheckAddTransLink(branch_list
*ptbranch
, lotrs_list
*pttrans
)
46 int result
, transblocked
= FALSE
;
48 if (!YAG_CONTEXT
->YAG_USE_FCF
) return YAG_YES
;
50 /* recreate support graph and circuit if nonexistent */
52 if (YAG_CONTEXT
->YAG_SUPPORT_GRAPH
== NULL
) {
53 YAG_CONTEXT
->YAG_SUPPORT_GRAPH
= yagNewGraph();
54 YAG_CONTEXT
->YAG_SUPPORT_GRAPH
->COMPLETE
= TRUE
;
55 build_circuit(ptbranch
, *yagAbandonGrow());
58 /* extend support graph and circuit */
59 ptcone
= (cone_list
*)pttrans
->GRID
;
60 nodetype
= ((pttrans
->TYPE
& CNS_TN
) == CNS_TN
? TN_NODE
: TP_NODE
);
62 if (YAG_CONTEXT
->YAG_DEBUG_CONE
== YAG_CONTEXT
->YAG_CURCIRCUIT
->name
) {
63 avt_log(LOGYAG
, 3, "Try to add transistor '%s' type %ld driven by '%s'\n", (pttrans
->TRNAME
!= NULL
) ? pttrans
->TRNAME
: "", nodetype
, ptcone
->NAME
);
66 if ((bdd
= extend_circuit(ptcone
, nodetype
, *yagAbandonGrow())) == NULL
) return YAG_NO
;
68 /* detect constants to mark resistive links */
69 if ((bdd
== BDD_one
&& nodetype
== TN_NODE
) || (bdd
== BDD_zero
&& nodetype
== TP_NODE
)) {
70 pttrans
->TYPE
|= RESIST
;
73 if ((bdd
== BDD_one
&& nodetype
== TP_NODE
) || (bdd
== BDD_zero
&& nodetype
== TN_NODE
)) {
74 if (avt_islog(3,LOGYAG
) && YAG_CONTEXT
->YAG_DEBUG_CONE
== YAG_CONTEXT
->YAG_CURCIRCUIT
->name
) {
75 avt_log(LOGYAG
, 3, "\tTransistor blocked\n");
80 else result
= get_opinion();
82 if (avt_islog(3,LOGYAG
) && YAG_CONTEXT
->YAG_DEBUG_CONE
== YAG_CONTEXT
->YAG_CURCIRCUIT
->name
) {
83 if (result
== YAG_NO
) avt_log(LOGYAG
, 3, "\tNO\n");
84 else avt_log(LOGYAG
, 3, "\tYES\n");
86 if (!transblocked
&& result
== YAG_NO
&& V_INT_TAB
[__YAGLE_KEEP_GLITCHERS
].VALUE
&& yagDetectGlitcher(ptbranch
, pttrans
, TRUE
)) {
87 yagWarning(WAR_GLITCHER
, YAG_CONTEXT
->YAG_CURCIRCUIT
->name
, NULL
, NULL
, 0);
95 yagRemoveFalseBranches(cone_list
*ptcone
)
97 branch_list
*brlist
[4];
98 branch_list
*ptbranch
, *ptnextbranch
;
99 long savetype
, typemask
;
100 int changed
, redo
, conflictual
, destroy
;
104 if ((ptcone
->TECTYPE
& CNS_DUAL_CMOS
) == CNS_DUAL_CMOS
) return FALSE
;
105 if (yagCheckBranches(ptcone
) == FALSE
) return FALSE
;
107 brlist
[0] = ptcone
->BRVDD
;
108 brlist
[1] = ptcone
->BRVSS
;
109 brlist
[2] = ptcone
->BREXT
;
110 brlist
[3] = ptcone
->BRGND
;
112 avt_log(LOGYAG
, 1, "Attempting to clean cone '%s'\n", ptcone
->NAME
);
114 /* To handle a return from BDD explosion */
115 save_depth
= YAG_CONTEXT
->YAG_DEPTH
;
116 setBddCeiling(YAG_CONTEXT
->YAG_BDDCEILING
);
117 if (setjmp(abandon_analyse
) != 0) {
118 yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
119 YAG_CONTEXT
->YAG_DEPTH
--;
120 if (YAG_CONTEXT
->YAG_DEPTH
== 0) unsetBddCeiling();
123 YAG_CONTEXT
->YAG_CONE_GRAPH
= yagMakeConeGraph(ptcone
);
125 typemask
= CNS_CONFLICT
|CNS_TRI
|CNS_MEMSYM
;
126 savetype
= ptcone
->TYPE
& typemask
;
127 conflictual
= ((ptcone
->TYPE
& CNS_CONFLICT
) == CNS_CONFLICT
);
130 for (i
=0; i
<4; i
++) {
131 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptnextbranch
) {
132 ptnextbranch
= ptbranch
->NEXT
;
133 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
134 if (i
==2 && ptbranch
->LINK
->NEXT
== NULL
) continue;
135 destroy
= zeroBdd(yagCalcBranchConductance(ptbranch
));
136 if (destroy
&& V_INT_TAB
[__YAGLE_KEEP_GLITCHERS
].VALUE
&& yagDetectGlitcher(ptbranch
, NULL
, TRUE
)) {
137 yagWarning(WAR_GLITCHER
, YAG_CONTEXT
->YAG_CURCIRCUIT
->name
, NULL
, NULL
, 0);
141 yagDestroyBranch(ptcone
, ptbranch
);
149 if ((ptcone
->TYPE
& YAG_AUTOLATCH
) != 0) {
150 /* yagUnmarkLatch(ptcone, FALSE, FALSE);*/
151 if (YAG_CONTEXT
->YAG_CONE_GRAPH
) yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
152 YAG_CONTEXT
->YAG_CONE_GRAPH
= NULL
;
157 /* re-verify the cone */
158 if (conflictual
|| changed
|| redo
) {
159 yagChainCone(ptcone
);
160 yagAnalyseCone(ptcone
);
162 if ((ptcone
->TYPE
& typemask
) != savetype
) {
166 if (YAG_CONTEXT
->YAG_CONE_GRAPH
) yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
167 YAG_CONTEXT
->YAG_CONE_GRAPH
= NULL
;
169 YAG_CONTEXT
->YAG_DEPTH
= save_depth
;
175 yagDetectDualGlitcherBranches(cone_list
*ptcone
)
177 branch_list
*brlist
[2];
178 branch_list
*ptbranch
, *ptnextbranch
;
179 long savetype
, typemask
;
180 int changed
, redo
, conflictual
, destroy
;
183 int setup
= FALSE
, ret
=FALSE
;
185 if ((ptcone
->TECTYPE
& CNS_DUAL_CMOS
) != CNS_DUAL_CMOS
) return FALSE
;
186 if (yagCheckBranches(ptcone
) == FALSE
) return FALSE
;
188 brlist
[0] = ptcone
->BRVDD
;
189 brlist
[1] = ptcone
->BRVSS
;
191 avt_log(LOGYAG
, 1, "Detecting glitchers on dual cone '%s'\n", ptcone
->NAME
);
193 /* To handle a return from BDD explosion */
194 save_depth
= YAG_CONTEXT
->YAG_DEPTH
;
195 setBddCeiling(YAG_CONTEXT
->YAG_BDDCEILING
);
196 if (setjmp(abandon_analyse
) != 0) {
197 yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
198 YAG_CONTEXT
->YAG_DEPTH
--;
199 if (YAG_CONTEXT
->YAG_DEPTH
== 0) unsetBddCeiling();
203 YAG_CONTEXT
->YAG_CONE_GRAPH
= yagMakeConeGraph(ptcone
);
205 for (i
=0; i
<2; i
++) {
206 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptnextbranch
) {
207 ptnextbranch
= ptbranch
->NEXT
;
208 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
209 destroy
= zeroBdd(yagCalcBranchConductance(ptbranch
));
210 if (yagDetectGlitcher(ptbranch
, NULL
, FALSE
)) {
212 yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
213 YAG_CONTEXT
->YAG_CONE_GRAPH
= yagMakeConeGraph(ptcone
);
216 if (zeroBdd(yagCalcBranchConductance(ptbranch
)) && yagDetectGlitcher(ptbranch
, NULL
, TRUE
)) {
217 yagWarning(WAR_GLITCHER
, YAG_CONTEXT
->YAG_CURCIRCUIT
->name
, NULL
, NULL
, 0);
226 if (YAG_CONTEXT
->YAG_CONE_GRAPH
) yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
227 YAG_CONTEXT
->YAG_CONE_GRAPH
= NULL
;
229 YAG_CONTEXT
->YAG_DEPTH
= save_depth
;
234 yagCalcBranchConductance(branch_list
*ptbranch
)
239 chain_list
*bddlist
= NULL
;
240 pNode bdd
, conductance
;
244 /* recreate support graph and circuit */
246 YAG_CONTEXT
->YAG_SUPPORT_GRAPH
= yagNewGraph();
247 YAG_CONTEXT
->YAG_SUPPORT_GRAPH
->COMPLETE
= TRUE
;
248 build_circuit(ptbranch
, abandon_analyse
);
250 for (root
= YAG_CONTEXT
->YAG_SUPPORT_GRAPH
->ROOTNODES
; root
; root
= root
->NEXT
) {
252 node
= (gnode_list
*)root
->DATA
;
253 ptcone
= node
->OBJECT
.CONE
;
254 negate
= (ptcone
->TYPE
& CNS_TRI
) != 0 && (root
->TYPE
== TP_NODE
);
256 name
= yagDownName(ptcone
->NAME
);
258 else name
= ptcone
->NAME
;
260 if ((bdd
= searchOutputCct_no_NA(YAG_CONTEXT
->YAG_CURCIRCUIT
, name
)) == NULL
) {
261 yagBug(DBG_NO_BDD
, "yagCalcBranchConductance", YAG_CONTEXT
->YAG_CURCIRCUIT
->name
, name
, 0);
264 /* invert bdd for P type transistor */
265 if (root
->TYPE
== TP_NODE
) bdd
= yagNotBdd(bdd
, abandon_analyse
);
267 bddlist
= addchain(bddlist
, (void *)bdd
);
269 if (bddlist
== NULL
) conductance
= BDD_one
;
270 else if (bddlist
->NEXT
== NULL
) conductance
= (pNode
)bddlist
->DATA
;
271 else conductance
= yagApplyBdd(AND
, bddlist
, abandon_analyse
);
272 if (zeroBdd(conductance
)) {
273 yagFreeGraph(YAG_CONTEXT
->YAG_SUPPORT_GRAPH
);
274 YAG_CONTEXT
->YAG_SUPPORT_GRAPH
= NULL
;
279 /* apply the contraints */
280 conductance
= yagApplyConstraints(conductance
, yagAbandonAnalyse());
283 yagFreeGraph(YAG_CONTEXT
->YAG_SUPPORT_GRAPH
);
284 YAG_CONTEXT
->YAG_SUPPORT_GRAPH
= NULL
;
290 yagCheckAddExtLink(cone_list
*ptcone
, locon_list
*ptcon
, cone_list
*ptrootcone
)
294 if (YAG_CONTEXT
->YAG_DEBUG_CONE
== YAG_CONTEXT
->YAG_CURCIRCUIT
->name
) {
295 avt_log(LOGYAG
, 1, "Try to add connector link '%s'\n", ptcon
->NAME
);
298 /* if ((ptrootcone->TECTYPE & CNS_DUAL_CMOS) == CNS_DUAL_CMOS) {
301 else*/ if (ptcone
== NULL
) result
= YAG_YES
;
303 if ((ptcone
->TECTYPE
& CNS_DUAL_CMOS
) == CNS_DUAL_CMOS
) {
306 else result
= YAG_YES
;
309 if (YAG_CONTEXT
->YAG_DEBUG_CONE
== YAG_CONTEXT
->YAG_CURCIRCUIT
->name
) {
310 if (result
== YAG_NO
) avt_log(LOGYAG
, 3, "\tNO\n");
311 else avt_log(LOGYAG
, 3, "\tYES\n");
320 gnode_list
*ptnewnode
, *ptfather
, *ptson
;
321 chain_list
*ptchain1
, *ptchain2
;
323 chain_list
*bddlist
= NULL
;
325 static int called
= 0;
329 for (ptlist
= YAG_CONTEXT
->YAG_SUPPORT_GRAPH
->ROOTNODES
; ptlist
; ptlist
= ptlist
->NEXT
) {
330 ((gnode_list
*)ptlist
->DATA
)->VISITED
= FALSE
;
333 /* build list of BDDs for correlated outputs */
335 ptnewnode
= (gnode_list
*)YAG_CONTEXT
->YAG_SUPPORT_GRAPH
->ROOTNODES
->DATA
;
336 bddlist
= add_node_bdd(bddlist
, ptnewnode
);
337 ptnewnode
->VISITED
= TRUE
;
339 for (ptchain1
= ptnewnode
->FATHERS
; ptchain1
; ptchain1
= ptchain1
->NEXT
) {
340 ptfather
= (gnode_list
*)ptchain1
->DATA
;
341 for (ptchain2
= ptfather
->SONS
; ptchain2
; ptchain2
= ptchain2
->NEXT
) {
342 ptson
= (gnode_list
*)ptchain2
->DATA
;
343 if (!ptson
->VISITED
) {
344 bddlist
= add_node_bdd(bddlist
, ptson
);
345 ptson
->VISITED
= TRUE
;
350 /* verify the conduction function of the branch */
352 if (bddlist
->NEXT
== NULL
) conductance
= (pNode
)bddlist
->DATA
;
353 else conductance
= yagApplyBdd(AND
, bddlist
, *yagAbandonGrow());
355 if (zeroBdd(conductance
)) return YAG_NO
;
357 /* apply the contraints */
358 conductance
= yagApplyConstraints(conductance
, yagAbandonGrow());
360 if (!zeroBdd(conductance
)) return YAG_YES
;
365 add_node_bdd(chain_list
*bddlist
, gnode_list
*ptnode
)
372 ptcone
= ptnode
->OBJECT
.CONE
;
375 if ((ptnode
->TYPE
& TP_NODE
) != 0) {
376 if ((ptcone
->TYPE
& CNS_TRI
) != 0) name
= yagDownName(ptcone
->NAME
);
380 bdd
= searchOutputCct_no_NA(YAG_CONTEXT
->YAG_CURCIRCUIT
, name
);
381 if (negate
) bdd
= yagNotBdd(bdd
, *yagAbandonGrow());
382 return(addchain(bddlist
, bdd
));
386 yagMakeConeGraph(cone_list
*ptcone
)
389 edge_list
*inedgelist
;
395 int numinputs
, numoutputs
;
397 if ((ptcone
->TYPE
& YAG_PARTIAL
) != 0 && (ptuser
= getptype(ptcone
->USER
, YAG_INPUTS_PTYPE
))) {
398 inedgelist
= (edge_list
*)ptuser
->DATA
;
400 else inedgelist
= ptcone
->INCONE
;
401 ptgraph
= yagBuildGraph(inedgelist
, ptcone
, FALSE
);
403 yagTraverseGraph(ptgraph
);
405 if (YAG_CONTEXT
->YAG_CONSTRAINT_LIST
) {
406 for (ptchain
= yagGetConstraint(YAG_CONTEXT
->YAG_CONSTRAINT_LIST
->NEXT
); ptchain
; ptchain
= yagGetConstraint(ptchain
)) {
407 varlist
= (list_list
*)ptchain
->DATA
;
408 ptgraph
->CONSTRAINTS
= addptype(ptgraph
->CONSTRAINTS
, (long)varlist
->SUPDATA
, (void *)varlist
->USER
);
409 ptchain
= ptchain
->NEXT
;
413 yagAddExtraConstraints(ptgraph
);
415 /* initialise circuit for analysis */
416 numinputs
= yagCountChains(ptgraph
->PRIMVARS
);
417 numoutputs
= ptgraph
->WIDTH
;
418 YAG_CONTEXT
->YAG_CURCIRCUIT
= initializeCct(ptcone
->NAME
, numinputs
, numoutputs
);
420 /* add primary variables to circuit input list */
421 for (ptchain
= ptgraph
->PRIMVARS
; ptchain
; ptchain
= ptchain
->NEXT
) {
422 ptnode
= (gnode_list
*)ptchain
->DATA
;
423 if ((ptnode
->TYPE
& CONE_TYPE
) != 0) {
424 name
= ptnode
->OBJECT
.CONE
->NAME
;
427 /* node is an external connector */
428 name
= ptnode
->OBJECT
.LOCON
->NAME
;
430 addInputCct_no_NA(YAG_CONTEXT
->YAG_CURCIRCUIT
, name
);
437 yagDeleteConeGraph(graph
*ptgraph
)
439 yagFreeGraph(ptgraph
);
441 /* destroy the circuit */
442 destroyCct(YAG_CONTEXT
->YAG_CURCIRCUIT
);
443 YAG_CONTEXT
->YAG_CURCIRCUIT
= NULL
;
447 build_circuit(branch_list
*ptbranch
, jmp_buf abandon_env
)
455 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
456 if ((ptlink
->TYPE
& (CNS_IN
|CNS_INOUT
)) != 0) break;
457 pttrans
= ptlink
->ULINK
.LOTRS
;
458 if ((pttrans
->TYPE
& DIODE
) != 0) continue;
459 ptcone
= (cone_list
*)pttrans
->GRID
;
460 nodetype
= ((pttrans
->TYPE
& CNS_TN
) == CNS_TN
? TN_NODE
: TP_NODE
);
461 bdd
= extend_circuit(ptcone
, nodetype
, abandon_env
);
463 /* detect constants to mark resistive links */
464 if ((bdd
== BDD_one
&& nodetype
== TN_NODE
) || (bdd
== BDD_zero
&& nodetype
== TP_NODE
)) {
465 pttrans
->TYPE
|= RESIST
;
466 ptlink
->TYPE
|= CNS_RESIST
;
472 extend_circuit(cone_list
*ptcone
, long type
, jmp_buf abandon_env
)
474 chain_list
*expr
, *tempexpr
;
476 gnode_list
*ptsupportnode
, *ptnode
;
480 int complete
, existbdd
;
482 negate
= (ptcone
->TYPE
& CNS_TRI
) != 0 && type
== TP_NODE
;
484 name
= yagDownName(ptcone
->NAME
);
486 else name
= ptcone
->NAME
;
488 complete
= yagExtendSupportRoot(YAG_CONTEXT
->YAG_SUPPORT_GRAPH
, ptcone
, type
);
489 ptsupportnode
= (gnode_list
*)YAG_CONTEXT
->YAG_SUPPORT_GRAPH
->ROOTNODES
->DATA
;
491 if ((ptsupportnode
->TYPE
& (TN_NODE
|TP_NODE
)) == (TN_NODE
|TP_NODE
)) {
496 ptnode
= (gnode_list
*)gethtitem(YAG_CONTEXT
->YAG_CONE_GRAPH
->HASHTAB
, ptcone
);
497 if (ptnode
== (gnode_list
*)EMPTYHT
) {
498 yagBug(DBG_NO_GRAPHNODE
, "extend_circuit", ptcone
->NAME
, NULL
, 0);
502 bdd
= searchOutputCct_no_NA(YAG_CONTEXT
->YAG_CURCIRCUIT
, name
);
503 existbdd
= (bdd
!= NULL
);
506 support
= yagGetPrimVars(YAG_CONTEXT
->YAG_CONE_GRAPH
, ptnode
);
509 tempexpr
= createAtom_no_NA(name
);
510 expr
= yagExpandExpr(ptnode
, tempexpr
, negate
);
512 bdd
= yagAblToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, expr
, abandon_env
);
513 addOutputCct_no_NA(YAG_CONTEXT
->YAG_CURCIRCUIT
, name
, bdd
);
515 support
= yagGetPrimVars(YAG_CONTEXT
->YAG_CONE_GRAPH
, ptnode
);
517 yagExtendSupportGraph(YAG_CONTEXT
->YAG_SUPPORT_GRAPH
, ptsupportnode
, support
);
519 if (support
!= NULL
) freechain(support
);
525 yagGuessMutex(cnsfig_list
*ptcnsfig
)
527 cone_list
*ptcone
, *ptincone
;
529 branch_list
*brlist
[4];
530 branch_list
*ptbranch
;
533 gnode_list
*ptnode
, *ptsupportnode
;
534 chain_list
*support
, *ptchain
;
538 chain_list
*guess_mutex
= NULL
;
540 /* Mark all latches and connectors constrained */
541 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
542 if ((ptcone
->TYPE
& (CNS_LATCH
|CNS_MEMSYM
|CNS_EXT
)) != 0) ptcone
->TYPE
|= YAG_CONSTRAINT
;
544 for (ptlocon
= ptcnsfig
->LOCON
; ptlocon
; ptlocon
= ptlocon
->NEXT
) {
545 if (getptype(ptlocon
->USER
, YAG_CONSTRAINT_PTYPE
) == NULL
) {
546 ptlocon
->USER
= addptype(ptlocon
->USER
, YAG_CONSTRAINT_PTYPE
, NULL
);
550 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
551 if ((ptcone
->TECTYPE
& YAG_BADCONE
) == 0) continue;
552 brlist
[0] = ptcone
->BRVDD
;
553 brlist
[1] = ptcone
->BRVSS
;
554 brlist
[2] = ptcone
->BREXT
;
555 brlist
[3] = ptcone
->BRGND
;
557 avt_log(LOGYAG
, 1, "MUTEX guessing on cone '%s'\n", ptcone
->NAME
);
558 YAG_CONTEXT
->YAG_CONE_GRAPH
= yagMakeConeGraph(ptcone
);
560 /* Try to find MUTEX candidate pair in 2nd and 3rd link of bad branch (on fail try 1st and 2nd if not latch) */
561 for (i
=0; i
<4; i
++) {
562 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
563 if (yagCountLinks(ptbranch
->LINK
) < YAG_CONTEXT
->YAG_MAX_LINKS
) continue;
564 YAG_CONTEXT
->YAG_SUPPORT_GRAPH
= yagNewGraph();
565 YAG_CONTEXT
->YAG_SUPPORT_GRAPH
->COMPLETE
= TRUE
;
567 candidate
[0] = NULL
; candidate
[1] = NULL
; candidate
[2] = NULL
;
568 for (ptlink
= ptbranch
->LINK
; ptlink
&& linkcount
< 3; ptlink
= ptlink
->NEXT
) {
569 if ((ptlink
->TYPE
& (CNS_IN
|CNS_INOUT
)) != 0) break;
570 pttrans
= ptlink
->ULINK
.LOTRS
;
571 if ((pttrans
->TYPE
& DIODE
) != 0) continue;
572 ptincone
= (cone_list
*)pttrans
->GRID
;
573 nodetype
= ((pttrans
->TYPE
& CNS_TN
) == CNS_TN
? TN_NODE
: TP_NODE
);
574 yagExtendSupportRoot(YAG_CONTEXT
->YAG_SUPPORT_GRAPH
, ptincone
, nodetype
);
575 ptsupportnode
= (gnode_list
*)YAG_CONTEXT
->YAG_SUPPORT_GRAPH
->ROOTNODES
->DATA
;
576 ptnode
= (gnode_list
*)gethtitem(YAG_CONTEXT
->YAG_CONE_GRAPH
->HASHTAB
, ptincone
);
577 support
= yagGetJustPrimVars(YAG_CONTEXT
->YAG_CONE_GRAPH
, ptnode
);
578 yagExtendSupportGraph(YAG_CONTEXT
->YAG_SUPPORT_GRAPH
, ptsupportnode
, support
);
579 if ((ptcone
->TYPE
& (CNS_LATCH
|CNS_MEMSYM
)) != 0 && linkcount
== 0) continue;
580 for (ptchain
= support
; ptchain
; ptchain
= ptchain
->NEXT
) {
581 ptnode
= (gnode_list
*)ptchain
->DATA
;
582 if ((ptnode
->TYPE
& CONSTRAINT_NODE
) != 0) {
583 if (!candidate
[linkcount
]) {
584 if ((ptnode
->TYPE
& EXT
) != 0) {
585 candidate
[linkcount
] = ptnode
->OBJECT
.LOCON
->NAME
;
587 else candidate
[linkcount
] = ptnode
->OBJECT
.CONE
->NAME
;
590 candidate
[linkcount
] = NULL
;
597 if (candidate
[2] && candidate
[1]) {
598 add_mutex_pair(&guess_mutex
, candidate
[2], candidate
[1]);
600 else if (candidate
[1] && candidate
[0]) {
601 add_mutex_pair(&guess_mutex
, candidate
[1], candidate
[0]);
603 yagFreeGraph(YAG_CONTEXT
->YAG_SUPPORT_GRAPH
);
604 YAG_CONTEXT
->YAG_SUPPORT_GRAPH
= NULL
;
607 if (YAG_CONTEXT
->YAG_CONE_GRAPH
) yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
608 YAG_CONTEXT
->YAG_CONE_GRAPH
= NULL
;
614 add_mutex_pair(chain_list
**ptmutex
, char *name1
, char *name2
)
616 chain_list
*list1
= NULL
, *list2
= NULL
;
617 chain_list
*ptmutexchain
, *ptchain
;
619 for (ptmutexchain
= *ptmutex
; ptmutexchain
; ptmutexchain
= ptmutexchain
->NEXT
) {
620 ptchain
= (chain_list
*)ptmutexchain
->DATA
;
621 if (yagGetChain(ptchain
, name1
) != NULL
) list1
= ptmutexchain
;
622 if (yagGetChain(ptchain
, name2
) != NULL
) list2
= ptmutexchain
;
623 if (list1
&& list2
) break;
625 if (!list1
&& !list2
) {
626 ptchain
= addchain(NULL
, name1
);
627 ptchain
= addchain(ptchain
, name2
);
628 *ptmutex
= addchain(*ptmutex
, ptchain
);
630 else if (!list1
&& list2
) {
631 list2
->DATA
= addchain(list2
->DATA
, name1
);
633 else if (list1
&& !list2
) {
634 list1
->DATA
= addchain(list1
->DATA
, name2
);
636 else if (list1
!= list2
) {
637 list1
->DATA
= append(list1
->DATA
, list2
->DATA
);
639 *ptmutex
= delchain(*ptmutex
, list2
);
644 yagAnalyseCone(cone_list
*ptcone
)
649 avt_log(LOGYAG
, 1, "\tAnalysing cone '%s'\n", ptcone
->NAME
);
651 if (yagDetectFalseConf(ptcone
)) yagChainCone(ptcone
);
652 yagDetectLoopConf(ptcone
);
654 if ((ptcone
->TECTYPE
& CNS_DUAL_CMOS
) == CNS_DUAL_CMOS
) {
655 ptcone
->TYPE
&= ~(YAG_FALSECONF
|YAG_LOOPCONF
);
659 yagDetectBadBranches(ptcone
);
660 yagDetectParallelBranches(ptcone
);
661 yagDetectParaTrans(ptcone
);
662 yagDetectSwitch(ptcone
);
663 yagDetectPullup(ptcone
);
664 yagDetectPulldown(ptcone
);
665 if (yagDetectTransfer(ptcone
)) yagChainCone(ptcone
);
666 yagDetectDegraded(ptcone
);
668 if ((ptuser
= getptype(ptcone
->USER
, YAG_BUSBEFIG_PTYPE
)) != NULL
) {
669 beh_delbefig((befig_list
*)ptuser
->DATA
, (befig_list
*)ptuser
->DATA
, 'Y');
670 ptcone
->USER
= delptype(ptcone
->USER
, YAG_BUSBEFIG_PTYPE
);
672 if ((ptuser
= getptype(ptcone
->USER
, YAG_LATCHBEFIG_PTYPE
)) != NULL
) {
673 beh_delbefig((befig_list
*)ptuser
->DATA
, (befig_list
*)ptuser
->DATA
, 'Y');
674 ptcone
->USER
= delptype(ptcone
->USER
, YAG_LATCHBEFIG_PTYPE
);
677 if ((ptcone
->TYPE
& YAG_AUTOLATCH
) != 0) {
678 yagUnmarkLatch(ptcone
, FALSE
, FALSE
);
681 if (yagCheckExtOut(ptcone
) == FALSE
) return;
682 if (yagCheckBranches(ptcone
) == FALSE
) return;
684 if ((ptcone
->TYPE
& (YAG_GLUECONE
|YAG_TEMPCONE
)) == 0) yagBuildOutputs(ptcone
);
686 cnsConeFunction(ptcone
, FALSE
);
688 if (YAG_CONTEXT
->YAG_USESTMSOLVER
) {
689 yagPrepStmSolver(ptcone
);
693 if ((ptcone
->TYPE
& YAG_FALSECONF
) != 0) {
694 ptcone
->TYPE
|= CNS_CONFLICT
;
698 if ((ptcone
->TECTYPE
& (CNS_VSS_DEGRADED
|CNS_VDD_DEGRADED
)) == 0
699 && getptype(ptcone
->USER
, CNS_SWITCH
) == NULL
) {
700 isLocalDual
= yagCheckLocalDuality(ptcone
);
702 ptcone
->TECTYPE
|= CNS_DUAL_CMOS
;
703 if (YAG_CONTEXT
->YAG_LOOP_ANALYSIS
) {
704 yagAnalyseLoop(ptcone
, FALSE
);
709 if (YAG_CONTEXT
->YAG_USE_FCF
) check_cone(ptcone
);
710 else ptcone
->TYPE
|= CNS_CONFLICT
;
715 if (!YAG_CONTEXT
->YAG_KEEP_REDUNDANT
) {
716 yagRemoveRedundantBranches(ptcone
);
719 avt_log(LOGYAG
, 1, "\tBDD system used %d/%d reduced nodes\n", numberNodeAllBdd() - YAG_CONTEXT
->YAG_LASTNODECOUNT
, numberNodeAllBdd());
720 if (numberNodeAllBdd() - YAG_CONTEXT
->YAG_LASTNODECOUNT
> YAG_CONTEXT
->YAG_MAXNODES
) {
721 YAG_CONTEXT
->YAG_MAXNODES
= numberNodeAllBdd() - YAG_CONTEXT
->YAG_LASTNODECOUNT
;
725 if (avt_islog(1,LOGYAG
) && YAG_CONTEXT
->YAG_DEBUG_CONE
== ptcone
->NAME
) {
726 avt_log(LOGYAG
, 1, "\nDisplaying Cone Structure :-\n\n");
727 displayconelog(LOGYAG
, 1, ptcone
);
731 /****************************************************************************
732 * function check_cone(); *
733 ****************************************************************************/
734 /*----------------------------------------------------*
735 | Check if completed cone is conflictual or HZ |
736 *----------------------------------------------------*/
739 check_cone(cone_list
*ptcone
)
742 chain_list
*sup_abl
, *sdn_abl
;
743 gnode_list
*rootnode
;
744 branch_list
*ptbranch
;
745 int resist_up
, resist_dn
;
747 int isdlatch
, forcedlatch
;
748 int isprecharge
= FALSE
;
751 /* To handle a return from BDD explosion */
752 save_depth
= YAG_CONTEXT
->YAG_DEPTH
;
753 setBddCeiling(YAG_CONTEXT
->YAG_BDDCEILING
);
754 if (setjmp(abandon_analyse
) != 0) {
755 yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
756 YAG_CONTEXT
->YAG_CONE_GRAPH
= NULL
;
757 if (YAG_CONTEXT
->YAG_DEPTH
== 0) {
758 ptcone
->TYPE
|= CNS_CONFLICT
;
759 fprintf(stderr
,"\n*** YAG DANGER : unable to analyse cone '%s' ***\n", ptcone
->NAME
);
760 fprintf(stderr
," increase BDD Ceiling or identify constraints\n");
763 YAG_CONTEXT
->YAG_DEPTH
= save_depth
;
766 YAG_CONTEXT
->YAG_DEPTH
--;
767 cnsConeFunction(ptcone
, FALSE
);
770 /* build the clean global graph */
771 if (YAG_CONTEXT
->YAG_CONE_GRAPH
== NULL
) {
772 YAG_CONTEXT
->YAG_CONE_GRAPH
= yagMakeConeGraph(ptcone
);
775 else destroy
= FALSE
;
777 rootnode
= yagRootGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
, ptcone
);
779 if (avt_islog(1,LOGYAG
) && YAG_CONTEXT
->YAG_DEBUG_CONE
== ptcone
->NAME
) {
780 avt_log(LOGYAG
, 1, "\nAfter Construction :-\n");
781 yagDisplayUsedGraphLog(LOGYAG
, 1, YAG_CONTEXT
->YAG_CONE_GRAPH
, 1);
785 for (ptbranch
= ptcone
->BRVDD
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
786 if ((ptbranch
->TYPE
& CNS_RESBRANCH
) != 0) resist_up
= TRUE
;
789 for (ptbranch
= ptcone
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
790 if ((ptbranch
->TYPE
& CNS_RESBRANCH
) != 0) resist_dn
= TRUE
;
793 if (yagCountBranches(ptcone
) >= A_LOT_OF_BRANCHES
) {
794 check_big_cone(ptcone
,rootnode
);
797 yagCheckGlobalDuality(ptcone
);
800 if ((ptcone
->TYPE
& (CNS_CONFLICT
|CNS_TRI
)) == 0) {
802 /* use YAG_DNEXPR_PTYPE to express functionality for pseudo CMOS or cones with no UP */
803 ptuser
= getptype(ptcone
->USER
, CNS_UPEXPR
);
804 sup_abl
= (chain_list
*)ptuser
->DATA
;
805 sdn_abl
= (chain_list
*)getptype(ptcone
->USER
, CNS_DNEXPR
)->DATA
;
806 if (sdn_abl
!= NULL
) {
807 if ((sup_abl
== NULL
) || (resist_up
&& !resist_dn
)) {
808 ptuser
->DATA
= notExpr(copyExpr(sdn_abl
));
809 if (sup_abl
!= NULL
) freeExpr(sup_abl
);
813 ptcone
->USER
= delptype(ptcone
->USER
, CNS_DNEXPR
);
816 if (avt_islog(1,LOGYAG
)) {
817 avt_log(LOGYAG
, 1, "\t\t");
818 if ((ptcone
->TYPE
& CNS_CONFLICT
) != 0) avt_log(LOGYAG
, 1, "CONFLICT ");
819 if ((ptcone
->TYPE
& CNS_TRI
) != 0) avt_log(LOGYAG
, 1, "HZ ");
820 avt_log(LOGYAG
, 1, "\n");
825 /* Precharge detection */
826 if ((ptuser
= getptype(ptcone
->USER
, YAG_INFO_PTYPE
)) != NULL
) {
827 if (((long)ptuser
->DATA
& YAG_INFOPRECHARGE
) != 0) isprecharge
= TRUE
;;
829 if (isprecharge
|| (YAG_CONTEXT
->YAG_DETECT_PRECHARGE
&& (ptcone
->TYPE
& (CNS_CONFLICT
|CNS_TRI
)) != 0)) {
830 yagDetectPrecharge(ptcone
, TRUE
);
832 /* Simple latch detection */
833 if (YAG_CONTEXT
->YAG_SIMPLE_LATCH
&& (ptcone
->TYPE
& CNS_PRECHARGE
) == 0) {
834 yagMatchSimpleLatch(ptcone
);
836 /* Automatic latch detection */
837 if (YAG_CONTEXT
->YAG_LOOP_ANALYSIS
&& (ptcone
->TYPE
& CNS_PRECHARGE
) == 0 && (ptcone
->TYPE
& YAG_FALSECONF
) == 0) {
838 yagAnalyseLoop(ptcone
, FALSE
);
840 /* Automatic dynamic latch and bus handling detection */
841 if (((ptcone
->TYPE
& (CNS_CONFLICT
|CNS_TRI
)) != 0 || (ptcone
->TECTYPE
& YAG_LEVELHOLD
) != 0) && (ptcone
->TYPE
& (CNS_PRECHARGE
|CNS_LATCH
)) == 0) {
844 if ((ptcone
->TECTYPE
& YAG_LEVELHOLD
) == 0) {
845 if (YAG_CONTEXT
->YAG_MARK_TRISTATE_MEMORY
) {
847 if ((ptuser
= getptype(ptcone
->USER
, YAG_INFO_PTYPE
)) != NULL
) {
848 if (((long)ptuser
->DATA
& YAG_INFONOTDLATCH
) != 0) isdlatch
= FALSE
;
850 if ((ptcone
->TECTYPE
& YAG_NOTLATCH
) == YAG_NOTLATCH
) isdlatch
= FALSE
;
852 if ((ptuser
= getptype(ptcone
->USER
, YAG_INFO_PTYPE
)) != NULL
) {
853 if (((long)ptuser
->DATA
& YAG_INFODLATCH
) != 0) forcedlatch
= TRUE
;
856 if ((YAG_CONTEXT
->YAG_BUS_ANALYSIS
|| isdlatch
|| forcedlatch
|| ((ptcone
->TYPE
& CNS_EXT
) == CNS_EXT
&& !strcmp(YAG_CONTEXT
->YAGLE_TOOLNAME
,"hitas")))
857 && (ptcone
->TYPE
& CNS_TRI
) != 0 && (ptcone
->TYPE
& CNS_PRECHARGE
) == 0) {
858 if ((isdlatch
&& ((ptcone
->TYPE
& CNS_EXT
) != CNS_EXT
)) || forcedlatch
) {
859 ptcone
->TYPE
|= CNS_LATCH
;
860 ptcone
->TYPE
&= ~CNS_TRI
;
862 yagAnalyseBus(ptcone
, TRUE
);
864 else if ((ptcone
->TECTYPE
& YAG_LEVELHOLD
) != 0 && V_BOOL_TAB
[__YAGLE_LEVELHOLD_ANALYSIS
].VALUE
) {
865 yagAnalyseBus(ptcone
, TRUE
);
869 /* Mark non-conflictual feedback branches in latch cones */
870 if ((ptcone
->TYPE
& (CNS_LATCH
|CNS_MEMSYM
|CNS_MASTER
|CNS_SLAVE
|CNS_RS
)) != 0) {
871 yagDetectNonConflictualFeedback(ptcone
);
876 if (YAG_CONTEXT
->YAG_CONE_GRAPH
) yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
877 YAG_CONTEXT
->YAG_CONE_GRAPH
= NULL
;
880 YAG_CONTEXT
->YAG_DEPTH
= save_depth
;
882 if ((ptcone
->TYPE
& CNS_LATCH
) != 0) {
883 if ((ptcone
->TYPE
& YAG_AUTOLATCH
) == 0) {
884 cnsConeFunction(ptcone
, FALSE
);
885 yagDetectStuck(ptcone
);
887 if ((ptcone
->TECTYPE
& (CNS_ONE
|CNS_ZERO
)) != 0) yagPropagateStuck(ptcone
);
892 check_big_cone(cone_list
*ptcone
, gnode_list
*rootnode
)
894 branch_list
*ptbranch0
, *ptbranch1
;
898 chain_list
*sup_abl
, *sdn_abl
;
899 chain_list
*name_expr
;
901 ptcone
->TYPE
&= ~(CNS_CONFLICT
|CNS_TRI
);
903 for (ptbranch0
= ptcone
->BRVDD
; ptbranch0
; ptbranch0
= ptbranch0
->NEXT
) {
904 if ((ptbranch0
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
905 for (ptbranch1
= ptcone
->BRVSS
; ptbranch1
; ptbranch1
= ptbranch1
->NEXT
) {
906 if ((ptbranch1
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
907 bdd0
= yagCalcBranchConductance(ptbranch0
);
908 bdd1
= yagCalcBranchConductance(ptbranch1
);
909 if (!zeroBdd(yagApplyBinBdd(AND
, bdd0
, bdd1
, abandon_analyse
))) break;
911 if (ptbranch1
!= NULL
) break;
912 for (ptbranch1
= ptcone
->BREXT
; ptbranch1
; ptbranch1
= ptbranch1
->NEXT
) {
913 if ((ptbranch1
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
914 if (ptbranch1
->LINK
->NEXT
== NULL
) continue;
915 bdd0
= yagCalcBranchConductance(ptbranch0
);
916 bdd1
= yagCalcBranchConductance(ptbranch1
);
917 if (!zeroBdd(yagApplyBinBdd(AND
, bdd0
, bdd1
, abandon_analyse
))) break;
919 if (ptbranch1
!= NULL
) break;
921 if (ptbranch0
!= NULL
) {
922 ptcone
->TYPE
|= (CNS_CONFLICT
|CNS_TRI
);
926 for (ptbranch0
= ptcone
->BRVSS
; ptbranch0
; ptbranch0
= ptbranch0
->NEXT
) {
927 if ((ptbranch0
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
928 for (ptbranch1
= ptcone
->BREXT
; ptbranch1
; ptbranch1
= ptbranch1
->NEXT
) {
929 if ((ptbranch1
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
930 if (ptbranch1
->LINK
->NEXT
== NULL
) continue;
931 bdd0
= yagCalcBranchConductance(ptbranch0
);
932 bdd1
= yagCalcBranchConductance(ptbranch1
);
933 if (!zeroBdd(yagApplyBinBdd(AND
, bdd0
, bdd1
, abandon_analyse
))) break;
935 if (ptbranch1
!= NULL
) break;
937 if (ptbranch0
!= NULL
) {
938 ptcone
->TYPE
|= (CNS_CONFLICT
|CNS_TRI
);
943 /* Set to HZ to generate down function */
944 ptcone
->TYPE
|= CNS_TRI
;
946 name_expr
= createAtom_no_NA(ptcone
->NAME
);
948 sup_abl
= yagExpandExpr(rootnode
, name_expr
, FALSE
);
949 sdn_abl
= yagExpandExpr(rootnode
, name_expr
, TRUE
);
953 sup
= yagAblToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, sup_abl
, abandon_analyse
);
954 sdn
= yagAblToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, sdn_abl
, abandon_analyse
);
958 /* apply the contraints */
959 sup
= yagApplyConstraints(sup
, yagAbandonAnalyse());
960 sdn
= yagApplyConstraints(sdn
, yagAbandonAnalyse());
962 /* test for high impedance */
964 sum
= yagApplyBinBdd(OR
, sup
, sdn
, abandon_analyse
);
965 if (oneBdd(sum
) || (ptcone
->TYPE
& (CNS_LATCH
|CNS_MEMSYM
|CNS_MASTER
|CNS_SLAVE
)) != 0) {
966 ptcone
->TYPE
^= CNS_TRI
;
971 yagCheckLocalDuality(cone_list
*ptcone
)
975 branch_list
*ptbranch
;
977 pNode sup
= BDD_zero
;
978 pNode sdown
= BDD_zero
;
983 /* not dual if external branch containing more than just connector link */
984 if (ptcone
->BREXT
!= NULL
) {
985 if (ptcone
->BREXT
->LINK
->NEXT
!= NULL
) return FALSE
;
988 ptnames
= newtable();
989 ptorder
= order(ptcone
->BRVSS
, ptnames
);
991 /* To calculate Sup */
993 for (ptbranch
= ptcone
->BRVDD
; ptbranch
!= NULL
; ptbranch
= ptbranch
->NEXT
) {
995 for (ptlink
= ptbranch
->LINK
; ptlink
!= NULL
; ptlink
= ptlink
->NEXT
) {
996 if ((index
= gethtitem(ptorder
, ptlink
->ULINK
.LOTRS
->GRID
)) == EMPTYHT
) {
1001 symbol
= notBdd(createNodeTermBdd(index
));
1002 term
= applyBinBdd(AND
, term
, symbol
);
1004 sup
= applyBinBdd(OR
, sup
, term
);
1007 /* To calculate Sdown */
1009 for (ptbranch
= ptcone
->BRVSS
; ptbranch
!= NULL
; ptbranch
= ptbranch
->NEXT
) {
1011 for (ptlink
= ptbranch
->LINK
; ptlink
!= NULL
; ptlink
= ptlink
->NEXT
) {
1012 index
= gethtitem(ptorder
, ptlink
->ULINK
.LOTRS
->GRID
);
1013 symbol
= createNodeTermBdd(index
);
1014 term
= applyBinBdd(AND
, term
, symbol
);
1016 sdown
= applyBinBdd(OR
, sdown
, term
);
1020 ptcone
->TYPE
&= ~(CNS_CONFLICT
|CNS_TRI
);
1021 product
= applyBinBdd(AND
, sup
, sdown
);
1022 if (!zeroBdd(product
)) ptcone
->TYPE
|= CNS_CONFLICT
;
1023 sum
= applyBinBdd(OR
, sup
, sdown
);
1024 if (!oneBdd(sum
)) ptcone
->TYPE
|= CNS_TRI
;
1026 if ((ptcone
->TYPE
& (CNS_CONFLICT
|CNS_TRI
)) != 0) return FALSE
;
1031 yagCheckGlobalDuality(cone_list
*ptcone
)
1033 chain_list
*sup_abl
, *sdn_abl
;
1034 chain_list
*name_expr
, *tmpabl
;
1035 branch_list
*ptbranch
;
1038 gnode_list
*rootnode
;
1039 abl_pair conf_abl
, hz_abl
;
1040 int resist_up
, resist_dn
;
1042 int hasdual
= FALSE
;
1044 if ((ptcone
->TYPE
& YAG_HASDUAL
) != 0) hasdual
= TRUE
;
1045 ptcone
->TYPE
&= ~YAG_HASDUAL
;
1046 loglvl2
= avt_islog(2,LOGYAG
);
1048 for (ptbranch
= ptcone
->BRVDD
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1049 if ((ptbranch
->TYPE
& CNS_RESBRANCH
) != 0) resist_up
= TRUE
;
1052 for (ptbranch
= ptcone
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1053 if ((ptbranch
->TYPE
& CNS_RESBRANCH
) != 0) resist_dn
= TRUE
;
1056 /* Set to HZ to generate down function */
1057 ptcone
->TYPE
|= CNS_TRI
;
1058 ptcone
->TYPE
&= ~CNS_CONFLICT
;
1060 name_expr
= createAtom_no_NA(ptcone
->NAME
);
1061 rootnode
= (gnode_list
*)gethtitem(YAG_CONTEXT
->YAG_CONE_GRAPH
->HASHTAB
, ptcone
);
1063 sup_abl
= yagExpandExpr(rootnode
, name_expr
, FALSE
);
1064 sdn_abl
= yagExpandExpr(rootnode
, name_expr
, TRUE
);
1066 freeExpr(name_expr
);
1068 if ( loglvl2
&& YAG_CONTEXT
->YAG_DEBUG_CONE
== ptcone
->NAME
) {
1069 avt_log(LOGYAG
, 2, "Sup expr: ");
1070 displayInfExprLog(LOGYAG
, 2, sup_abl
);
1071 avt_log(LOGYAG
, 2, "\n");
1072 avt_log(LOGYAG
, 2, "Sdn expr: ");
1073 displayInfExprLog(LOGYAG
, 2, sdn_abl
);
1074 avt_log(LOGYAG
, 2, "\n");
1077 sup
= yagAblToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, sup_abl
, abandon_analyse
);
1078 sdn
= yagAblToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, sdn_abl
, abandon_analyse
);
1082 if ((ptcone
->TYPE
& CNS_EXT
) != 0 && ptcone
->BREXT
!= NULL
) {
1084 cnsMakeConeExpr(ptcone
, &hz_abl
, CNS_RESBRANCH
|CNS_NOT_FUNCTIONAL
|CNS_MASK_PARA
|CNS_IGNORE
|(CNS_VSS
&~CNS_POWER
), 0, FALSE
);
1085 if (hz_abl
.UP
!= NULL
) {
1086 sup_abl
= yagExpandTerm(rootnode
, hz_abl
.UP
);
1087 sup
= yagAblToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, sup_abl
, abandon_analyse
);
1090 else sup
= BDD_zero
;
1093 cnsMakeConeExpr(ptcone
, &hz_abl
, CNS_RESBRANCH
|CNS_NOT_FUNCTIONAL
|CNS_MASK_PARA
|CNS_IGNORE
|(CNS_VDD
&~CNS_POWER
), 0, FALSE
);
1094 if (hz_abl
.DN
!= NULL
) {
1095 sdn_abl
= yagExpandTerm(rootnode
, hz_abl
.DN
);
1096 sdn
= yagAblToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, sdn_abl
, abandon_analyse
);
1099 else sdn
= BDD_zero
;
1103 if ( loglvl2
|| YAG_CONTEXT
->YAG_DEBUG_CONE
== ptcone
->NAME
) {
1104 avt_log(LOGYAG
,1,"Sup reduced: ");
1105 displayInfExprLog(LOGYAG
, 1, tmpabl
=bddToAblCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, sup
));
1107 avt_log(LOGYAG
,1,"\n");
1108 avt_log(LOGYAG
,1,"Sdn reduced: ");
1109 displayInfExprLog(LOGYAG
, 1, tmpabl
=bddToAblCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, sdn
));
1111 avt_log(LOGYAG
,1,"\n");
1114 /* apply the contraints */
1115 sup
= yagApplyConstraints(sup
, yagAbandonAnalyse());
1116 sdn
= yagApplyConstraints(sdn
, yagAbandonAnalyse());
1118 /* test for constants */
1119 if (sup
== BDD_one
&& sdn
== BDD_zero
) {
1120 ptcone
->TECTYPE
|= CNS_ONE
;
1121 ptcone
->TYPE
|= YAG_FORCEPRIM
;
1122 yagPropagateStuck(ptcone
);
1124 if (sup
== BDD_zero
&& sdn
== BDD_one
) {
1125 ptcone
->TECTYPE
|= CNS_ZERO
;
1126 ptcone
->TYPE
|= YAG_FORCEPRIM
;
1127 yagPropagateStuck(ptcone
);
1130 /* test for high impedance */
1132 sum
= yagApplyBinBdd(OR
, sup
, sdn
, abandon_analyse
);
1133 if (oneBdd(sum
) || (ptcone
->TYPE
& (CNS_LATCH
|CNS_MEMSYM
|CNS_MASTER
|CNS_SLAVE
)) != 0) ptcone
->TYPE
^= CNS_TRI
;
1135 /* test for conflicts but must ignore resistance branches */
1138 cnsMakeConeExpr(ptcone
, &conf_abl
, CNS_RESBRANCH
|CNS_NOT_FUNCTIONAL
|CNS_MASK_PARA
|CNS_IGNORE
|(CNS_VSS
&~CNS_POWER
), 0, FALSE
);
1139 if (conf_abl
.UP
!= NULL
) {
1140 sup_abl
= yagExpandTerm(rootnode
, conf_abl
.UP
);
1141 sup
= yagAblToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, sup_abl
, abandon_analyse
);
1144 else sup
= BDD_zero
;
1147 cnsMakeConeExpr(ptcone
, &conf_abl
, CNS_RESBRANCH
|CNS_NOT_FUNCTIONAL
|CNS_MASK_PARA
|CNS_IGNORE
|(CNS_VDD
&~CNS_POWER
), 0, FALSE
);
1148 if (conf_abl
.DN
!= NULL
) {
1149 sdn_abl
= yagExpandTerm(rootnode
, conf_abl
.DN
);
1150 sdn
= yagAblToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, sdn_abl
, abandon_analyse
);
1153 else sdn
= BDD_zero
;
1156 product
= yagApplyBinBdd(AND
, sup
, sdn
, abandon_analyse
);
1157 if (!zeroBdd(product
)) ptcone
->TYPE
|= CNS_CONFLICT
;
1158 if (hasdual
) ptcone
->TYPE
|= YAG_HASDUAL
;
1162 ht
*order(branch_list
*ptbranchlist
, table
*ptnames
)
1165 branch_list
*ptbranch
;
1170 ptorder
= addht(20);
1172 for (ptbranch
= ptbranchlist
; ptbranch
!= NULL
; ptbranch
= ptbranch
->NEXT
) {
1173 for (ptlink
= ptbranch
->LINK
; ptlink
!= NULL
; ptlink
= ptlink
->NEXT
) {
1174 ptcone
= (cone_list
*)ptlink
->ULINK
.LOTRS
->GRID
;
1175 if (gethtitem(ptorder
, ptcone
) == EMPTYHT
) {
1176 addhtitem(ptorder
, ptcone
, index
++);
1177 addtableitem(ptnames
, ptcone
->NAME
);
1185 yagDetectNonConflictualFeedback(cone_list
*ptcone
)
1187 branch_list
*ptbranch0
, *ptbranch1
;
1192 for (ptbranch0
= ptcone
->BRVDD
; ptbranch0
; ptbranch0
= ptbranch0
->NEXT
) {
1193 if ((ptbranch0
->TYPE
& CNS_FEEDBACK
) != CNS_FEEDBACK
) continue;
1195 for (ptbranch1
= ptcone
->BRVSS
; ptbranch1
; ptbranch1
= ptbranch1
->NEXT
) {
1196 if ((ptbranch1
->TYPE
& (CNS_FEEDBACK
|CNS_NOT_FUNCTIONAL
)) != 0) continue;
1197 bdd0
= yagCalcBranchConductance(ptbranch0
);
1198 bdd1
= yagCalcBranchConductance(ptbranch1
);
1199 resbdd
= yagApplyBinBdd(AND
, bdd0
, bdd1
, abandon_analyse
);
1200 resbdd
= yagApplyConstraints(resbdd
, yagAbandonAnalyse());
1201 if (!zeroBdd(resbdd
)) conflict
= TRUE
;
1203 for (ptbranch1
= ptcone
->BREXT
; ptbranch1
; ptbranch1
= ptbranch1
->NEXT
) {
1204 if ((ptbranch1
->TYPE
& (CNS_FEEDBACK
|CNS_NOT_FUNCTIONAL
)) != 0) continue;
1205 if (ptbranch1
->LINK
->NEXT
== NULL
) continue;
1206 bdd0
= yagCalcBranchConductance(ptbranch0
);
1207 bdd1
= yagCalcBranchConductance(ptbranch1
);
1208 resbdd
= yagApplyBinBdd(AND
, bdd0
, bdd1
, abandon_analyse
);
1209 resbdd
= yagApplyConstraints(resbdd
, yagAbandonAnalyse());
1210 if (!zeroBdd(resbdd
)) conflict
= TRUE
;
1212 if (!conflict
) ptbranch0
->TYPE
|= CNS_NOTCONFLICTUAL
;
1214 for (ptbranch0
= ptcone
->BRVSS
; ptbranch0
; ptbranch0
= ptbranch0
->NEXT
) {
1215 if ((ptbranch0
->TYPE
& CNS_FEEDBACK
) != CNS_FEEDBACK
) continue;
1217 for (ptbranch1
= ptcone
->BRVDD
; ptbranch1
; ptbranch1
= ptbranch1
->NEXT
) {
1218 if ((ptbranch1
->TYPE
& (CNS_FEEDBACK
|CNS_NOT_FUNCTIONAL
)) != 0) continue;
1219 bdd0
= yagCalcBranchConductance(ptbranch0
);
1220 bdd1
= yagCalcBranchConductance(ptbranch1
);
1221 resbdd
= yagApplyBinBdd(AND
, bdd0
, bdd1
, abandon_analyse
);
1222 resbdd
= yagApplyConstraints(resbdd
, yagAbandonAnalyse());
1223 if (!zeroBdd(resbdd
)) conflict
= TRUE
;
1225 for (ptbranch1
= ptcone
->BREXT
; ptbranch1
; ptbranch1
= ptbranch1
->NEXT
) {
1226 if ((ptbranch1
->TYPE
& (CNS_FEEDBACK
|CNS_NOT_FUNCTIONAL
)) != 0) continue;
1227 if (ptbranch1
->LINK
->NEXT
== NULL
) continue;
1228 bdd0
= yagCalcBranchConductance(ptbranch0
);
1229 bdd1
= yagCalcBranchConductance(ptbranch1
);
1230 resbdd
= yagApplyBinBdd(AND
, bdd0
, bdd1
, abandon_analyse
);
1231 resbdd
= yagApplyConstraints(resbdd
, yagAbandonAnalyse());
1232 if (!zeroBdd(resbdd
)) conflict
= TRUE
;
1234 if (!conflict
) ptbranch0
->TYPE
|= CNS_NOTCONFLICTUAL
;
1239 yagApplyConstraints(pNode expr
, jmp_buf *ptabandon_env
)
1241 chain_list
*support
;
1242 chain_list
*constraint_support
;
1244 chain_list
*constraint_abl
;
1245 ptype_list
*ptptype
;
1247 ht
*FASTSEARCH
=NULL
;
1249 if (YAG_CONTEXT
->YAG_CONE_GRAPH
->CONSTRAINTS
!= NULL
) {
1250 support
=supportChain_listBddExpr(YAG_CONTEXT
->YAG_CURCIRCUIT
, expr
);
1251 for (ptptype
= YAG_CONTEXT
->YAG_CONE_GRAPH
->CONSTRAINTS
; ptptype
; ptptype
= ptptype
->NEXT
) {
1252 constraint_support
= (chain_list
*)ptptype
->TYPE
;
1253 if ((constraint_abl
= yagCheckConstraint(support
, constraint_support
, (chain_list
*)ptptype
->DATA
, &FASTSEARCH
)) != NULL
) {
1254 if (ptabandon_env
!= NULL
) {
1255 constraint
= yagAblToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, constraint_abl
, *ptabandon_env
);
1256 expr
= yagConstraintBdd(expr
, constraint
, *ptabandon_env
);
1259 constraint
= ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, constraint_abl
);
1260 expr
= constraintBdd(expr
, constraint
);
1262 if (constraint_abl
!= (chain_list
*)ptptype
->DATA
) freeExpr(constraint_abl
);
1264 if (zeroBdd(expr
)) break;
1268 if (FASTSEARCH
!=NULL
) delht(FASTSEARCH
);
1272 /****************************************************************************
1273 * function yagDetectPrecharge() *
1274 ****************************************************************************/
1276 /* detect precharge */
1279 yagDetectPrecharge(cone_list
*ptcone
, int fIgnoreFalse
)
1281 edge_list
*save_inputs
, *ptedge
;
1282 cone_list
*ptloopcone
;
1283 branch_list
*ptbranch
;
1287 pNode local_sup
, local_sdn
;
1288 chain_list
*ptsupport
, *ptloopchain
;
1289 chain_list
*ptchain
;
1293 int invloop
= FALSE
;
1297 ptcone
->TYPE
&= ~CNS_PRECHARGE
;
1298 if ((ptuser
= getptype(ptcone
->USER
, YAG_INFO_PTYPE
)) != NULL
) {
1299 if (((long)ptuser
->DATA
& YAG_INFONOTPRECHARGE
) != 0) return;
1302 savetype
= ptcone
->TYPE
;
1304 /* Check for correctly dimensioned 2 cone loop */
1305 if ((ptloopchain
= yagCheckLoop(ptcone
, TRUE
)) != NULL
) {
1306 for (ptchain
= ptloopchain
; ptchain
; ptchain
= ptchain
->NEXT
) {
1307 ptloopcone
= (cone_list
*)ptchain
->DATA
;
1308 if (yagMatchNOT(ptcone
, ptloopcone
) == TRUE
&& yagMatchNOT(ptloopcone
, ptcone
) == TRUE
) {
1309 ratio
= yagInverterStrength(ptcone
, ptloopcone
)/yagInverterStrength(ptloopcone
, ptcone
);
1310 if (ratio
> 1.2) invloop
= TRUE
;
1314 freechain(ptloopchain
);
1317 /* Mark inverter loop as bleeder and re-analyse*/
1319 for (ptbranch
= ptcone
->BRVDD
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1320 if (ptbranch
->LINK
->NEXT
== NULL
&& (cone_list
*)ptbranch
->LINK
->ULINK
.LOTRS
->GRID
== ptloopcone
) {
1321 ptbranch
->TYPE
|= CNS_BLEEDER
|CNS_NOT_FUNCTIONAL
;
1324 for (ptbranch
= ptcone
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1325 if (ptbranch
->LINK
->NEXT
== NULL
&& (cone_list
*)ptbranch
->LINK
->ULINK
.LOTRS
->GRID
== ptloopcone
) {
1326 ptbranch
->TYPE
|= CNS_BLEEDER
|CNS_NOT_FUNCTIONAL
;
1329 ptedge
= yagGetEdge(ptcone
->INCONE
, ptloopcone
);
1330 ptedge
->TYPE
|= CNS_BLEEDER
;
1332 cnsConeFunction(ptcone
, FALSE
);
1333 yagCheckGlobalDuality(ptcone
);
1336 if ((ptuser
= getptype(ptcone
->USER
, YAG_INFO_PTYPE
)) != NULL
) {
1337 if (((long)ptuser
->DATA
& YAG_INFOPRECHARGE
) != 0) {
1338 ptcone
->TYPE
|= CNS_PRECHARGE
;
1343 /* A precharge is globally tristate and globally non-conflictual */
1344 if ((ptcone
->TYPE
& CNS_TRI
) != CNS_TRI
) {
1345 if (invloop
) clean_precharge_marks(ptcone
, ptloopcone
);
1346 ptcone
->TYPE
= savetype
;
1350 /* Ignore simple external connector branch and input */
1351 if (ptcone
->BREXT
!= NULL
) {
1352 ptbranch
= ptcone
->BREXT
;
1353 if (ptbranch
->NEXT
!= NULL
|| ptbranch
->LINK
->NEXT
!= NULL
) {
1354 if (invloop
) clean_precharge_marks(ptcone
, ptloopcone
);
1355 ptcone
->TYPE
= savetype
;
1358 ptbranch
->TYPE
|= CNS_BLEEDER
|CNS_NOT_FUNCTIONAL
;
1359 ptedge
= yagGetEdge(ptcone
->INCONE
, ptbranch
->LINK
->ULINK
.LOCON
);
1360 ptedge
->TYPE
|= CNS_BLEEDER
;
1363 avt_log(LOGYAG
,1, "Analysing Precharge at '%s'\n", ptcone
->NAME
);
1366 save_inputs
= ptcone
->INCONE
;
1367 ptcone
->INCONE
= NULL
;
1368 for (ptedge
= save_inputs
; ptedge
; ptedge
= ptedge
->NEXT
) {
1369 if ((ptedge
->TYPE
& YAG_FALSECONF
) == 0) {
1370 addincone(ptcone
, ptedge
->TYPE
, ptedge
->UEDGE
.PTR
);
1375 directCct
= yagBuildDirectCct(ptcone
);
1377 /* Generate expression for cone as a function of its direct inputs */
1379 branchmask
= CNS_NOT_FUNCTIONAL
|CNS_IGNORE
|CNS_MASK_PARA
;
1380 if (fIgnoreFalse
) branchmask
|= YAG_FALSECONF
;
1381 cnsMakeConeExpr(ptcone
, &local_abl
, branchmask
, 0, FALSE
);
1382 if (local_abl
.UP
== NULL
) local_abl
.UP
= createAtom("'0'");
1383 if (local_abl
.DN
== NULL
) local_abl
.DN
= createAtom("'0'");
1385 /* Generate up and down expressions for cone in terms of direct inputs */
1387 local_sup
= ablToBddCct(directCct
, local_abl
.UP
);
1388 local_sdn
= ablToBddCct(directCct
, local_abl
.DN
);
1389 ptsupport
= supportChain_listExpr(local_abl
.UP
);
1390 freeExpr(local_abl
.UP
);
1391 freeExpr(local_abl
.DN
);
1394 yagFreeEdgeList(ptcone
->INCONE
);
1395 ptcone
->INCONE
= save_inputs
;
1398 /* A precharge is locally tristate and and possibly locally conflictual */
1399 /* and has a single variable in the local up expression */
1400 if (!zeroBdd(local_sup
) && !zeroBdd(local_sdn
) && !oneBdd(applyBinBdd(OR
, local_sup
, local_sdn
))
1401 && yagCountChains(ptsupport
) == 1) {
1402 ptcone
->TYPE
|= CNS_PRECHARGE
;
1403 for (ptedge
= ptcone
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
1404 if ((ptedge
->TYPE
& CNS_EXT
) == CNS_EXT
) name
= ptedge
->UEDGE
.LOCON
->NAME
;
1405 else name
= ptedge
->UEDGE
.CONE
->NAME
;
1406 if (name
== (char *)ptsupport
->DATA
) break;
1408 if (ptedge
!= NULL
) ptedge
->TYPE
|= YAG_PRECHCOM
;
1409 avt_log(LOGYAG
,1, "\tFound\n");
1413 avt_log(LOGYAG
,1, "\tNot Found\n");
1415 freechain(ptsupport
);
1417 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1418 if (ptbranch
->LINK
->NEXT
== NULL
) {
1419 ptbranch
->TYPE
&= ~(CNS_BLEEDER
|CNS_NOT_FUNCTIONAL
);
1420 ptedge
= yagGetEdge(ptcone
->INCONE
, ptbranch
->LINK
->ULINK
.LOCON
); {
1421 ptedge
->TYPE
&= ~CNS_BLEEDER
;
1426 /* Remove bleeder loop markings if not precharge */
1427 if (!found
&& invloop
) {
1428 clean_precharge_marks(ptcone
, ptloopcone
);
1429 ptcone
->TYPE
= savetype
;
1432 destroyCct(directCct
);
1436 clean_precharge_marks(cone_list
*ptcone
, cone_list
*ptloopcone
)
1438 branch_list
*ptbranch
;
1441 for (ptbranch
= ptcone
->BRVDD
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1442 if (ptbranch
->LINK
->NEXT
== NULL
&& (cone_list
*)ptbranch
->LINK
->ULINK
.LOTRS
->GRID
== ptloopcone
) {
1443 ptbranch
->TYPE
&= ~(CNS_BLEEDER
|CNS_NOT_FUNCTIONAL
);
1446 for (ptbranch
= ptcone
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1447 if (ptbranch
->LINK
->NEXT
== NULL
&& (cone_list
*)ptbranch
->LINK
->ULINK
.LOTRS
->GRID
== ptloopcone
) {
1448 ptbranch
->TYPE
&= ~(CNS_BLEEDER
|CNS_NOT_FUNCTIONAL
);
1451 ptedge
= yagGetEdge(ptcone
->INCONE
, ptloopcone
);
1452 ptedge
->TYPE
&= ~CNS_BLEEDER
;
1453 cnsConeFunction(ptcone
, FALSE
);
1456 /****************************************************************************
1457 * function yagDetectRedundant() *
1458 ****************************************************************************/
1460 /* detect electrically poor branches for which a functional alternative exists */
1463 yagTestSatisfy(pNode pBddref
, pNode pBddtest
)
1465 if (applyBinBdd(AND
, pBddref
, pBddtest
) == pBddref
) return TRUE
;
1470 yagDetectRedundant(cone_list
*ptcone
)
1473 pCircuit savecircuit
;
1474 branch_list
*ptbranch
, *ptotherbranch
;
1476 chain_list
*locon_abl
;
1477 pNode badbranch_bdd
, otherbranch_bdd
;
1478 short save_prop_hz
, save_depth
;
1482 avt_log(LOGYAG
,1, "Analysing Redundancy at '%s'\n", ptcone
->NAME
);
1484 /* save context and build local cone graph */
1485 save_prop_hz
= YAG_CONTEXT
->YAG_PROP_HZ
;
1486 savegraph
= YAG_CONTEXT
->YAG_CONE_GRAPH
;
1487 savecircuit
= YAG_CONTEXT
->YAG_CURCIRCUIT
;
1488 save_depth
= YAG_CONTEXT
->YAG_DEPTH
;
1489 YAG_CONTEXT
->YAG_DEPTH
= 1;
1490 YAG_CONTEXT
->YAG_PROP_HZ
= TRUE
;
1491 YAG_CONTEXT
->YAG_CONE_GRAPH
= yagMakeConeGraph(ptcone
);
1492 YAG_CONTEXT
->YAG_PROP_HZ
= save_prop_hz
;
1494 /* check for bad Vdd branches */
1495 if ((ptcone
->TECTYPE
& CNS_VDD_DEGRADED
) == CNS_VDD_DEGRADED
) bad_vdd
= TRUE
;
1498 for (ptbranch
= ptcone
->BRVDD
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1499 if ((ptbranch
->TYPE
& CNS_VDD_DEGRADED
) != 0 || yagCountLinks(ptbranch
->LINK
) > 3) {
1506 /* check for bad Vss branches */
1507 if ((ptcone
->TECTYPE
& CNS_VSS_DEGRADED
) == CNS_VSS_DEGRADED
) bad_vss
= TRUE
;
1510 for (ptbranch
= ptcone
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1511 if ((ptbranch
->TYPE
& CNS_VSS_DEGRADED
) != 0 || yagCountLinks(ptbranch
->LINK
) > 3) {
1518 /* Prepare branch conductance functions */
1520 for (ptbranch
= ptcone
->BRVDD
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1521 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1522 ptbranch
->USER
= addptype(ptbranch
->USER
, YAG_BRANCHBDD_PTYPE
, yagCalcBranchConductance(ptbranch
));
1526 for (ptbranch
= ptcone
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1527 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1528 ptbranch
->USER
= addptype(ptbranch
->USER
, YAG_BRANCHBDD_PTYPE
, yagCalcBranchConductance(ptbranch
));
1531 if (bad_vdd
|| bad_vss
) {
1532 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1533 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1534 ptbranch
->USER
= addptype(ptbranch
->USER
, YAG_BRANCHBDD_PTYPE
, yagCalcBranchConductance(ptbranch
));
1538 /* check whether replacement for bad Vdd branch exists */
1540 for (ptbranch
= ptcone
->BRVDD
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1541 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1542 if ((ptbranch
->TYPE
& CNS_DEGRADED
) == CNS_DEGRADED
|| yagCountLinks(ptbranch
->LINK
) > 3) {
1543 badbranch_bdd
= (pNode
)getptype(ptbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1544 for (ptotherbranch
= ptcone
->BRVDD
; ptotherbranch
; ptotherbranch
= ptotherbranch
->NEXT
) {
1545 if ((ptotherbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1546 if ((ptotherbranch
->TYPE
& CNS_DEGRADED
) == CNS_DEGRADED
|| yagCountLinks(ptotherbranch
->LINK
) > 3) continue;
1547 otherbranch_bdd
= (pNode
)getptype(ptotherbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1548 if (yagTestSatisfy(badbranch_bdd
, otherbranch_bdd
)) ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
1550 for (ptotherbranch
= ptcone
->BREXT
; ptotherbranch
; ptotherbranch
= ptotherbranch
->NEXT
) {
1551 if ((ptotherbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1552 if ((ptotherbranch
->TYPE
& CNS_VDD_DEGRADED
) == CNS_VDD_DEGRADED
|| yagCountLinks(ptotherbranch
->LINK
) > 4) continue;
1553 otherbranch_bdd
= (pNode
)getptype(ptotherbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1554 for (ptlink
= ptotherbranch
->LINK
; ptlink
->NEXT
!= NULL
; ptlink
= ptlink
->NEXT
);
1555 locon_abl
= createAtom(ptlink
->ULINK
.LOCON
->NAME
);
1556 otherbranch_bdd
= applyBinBdd(AND
, otherbranch_bdd
, ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, locon_abl
));
1557 freeExpr(locon_abl
);
1558 if (yagTestSatisfy(badbranch_bdd
, otherbranch_bdd
)) ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
1564 /* check whether replacement for bad Vss branch exists */
1566 for (ptbranch
= ptcone
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1567 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1568 if ((ptbranch
->TYPE
& CNS_DEGRADED
) == CNS_DEGRADED
|| yagCountLinks(ptbranch
->LINK
) > 3) {
1569 badbranch_bdd
= (pNode
)getptype(ptbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1570 for (ptotherbranch
= ptcone
->BRVSS
; ptotherbranch
; ptotherbranch
= ptotherbranch
->NEXT
) {
1571 if ((ptotherbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1572 if ((ptotherbranch
->TYPE
& CNS_DEGRADED
) == CNS_DEGRADED
|| yagCountLinks(ptotherbranch
->LINK
) > 3) continue;
1573 otherbranch_bdd
= (pNode
)getptype(ptotherbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1574 if (yagTestSatisfy(badbranch_bdd
, otherbranch_bdd
)) ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
1576 for (ptotherbranch
= ptcone
->BREXT
; ptotherbranch
; ptotherbranch
= ptotherbranch
->NEXT
) {
1577 if ((ptotherbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1578 if ((ptotherbranch
->TYPE
& CNS_VSS_DEGRADED
) == CNS_VSS_DEGRADED
|| yagCountLinks(ptotherbranch
->LINK
) > 4) continue;
1579 otherbranch_bdd
= (pNode
)getptype(ptotherbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1580 for (ptlink
= ptotherbranch
->LINK
; ptlink
->NEXT
!= NULL
; ptlink
= ptlink
->NEXT
);
1581 locon_abl
= createAtom(ptlink
->ULINK
.LOCON
->NAME
);
1582 otherbranch_bdd
= applyBinBdd(AND
, otherbranch_bdd
, notBdd(ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, locon_abl
)));
1583 freeExpr(locon_abl
);
1584 if (yagTestSatisfy(badbranch_bdd
, otherbranch_bdd
)) ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
1590 /* check whether replacement for bad Ext branch exists */
1592 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1593 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1594 if ((ptbranch
->TYPE
& CNS_VDD_DEGRADED
) == CNS_VDD_DEGRADED
) {
1595 badbranch_bdd
= (pNode
)getptype(ptbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1596 for (ptlink
= ptbranch
->LINK
; ptlink
->NEXT
!= NULL
; ptlink
= ptlink
->NEXT
);
1597 locon_abl
= createAtom(ptlink
->ULINK
.LOCON
->NAME
);
1598 badbranch_bdd
= applyBinBdd(AND
, badbranch_bdd
, ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, locon_abl
));
1599 freeExpr(locon_abl
);
1600 for (ptotherbranch
= ptcone
->BRVDD
; ptotherbranch
; ptotherbranch
= ptotherbranch
->NEXT
) {
1601 if ((ptotherbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1602 if ((ptotherbranch
->TYPE
& CNS_DEGRADED
) == CNS_DEGRADED
|| yagCountLinks(ptotherbranch
->LINK
) > 3) continue;
1603 otherbranch_bdd
= (pNode
)getptype(ptotherbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1604 if (yagTestSatisfy(badbranch_bdd
, otherbranch_bdd
)) ptbranch
->TYPE
|= CNS_NOT_UP
;
1606 for (ptotherbranch
= ptcone
->BREXT
; ptotherbranch
; ptotherbranch
= ptotherbranch
->NEXT
) {
1607 if ((ptotherbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1608 if ((ptotherbranch
->TYPE
& CNS_VDD_DEGRADED
) == CNS_VDD_DEGRADED
|| yagCountLinks(ptotherbranch
->LINK
) > 4) continue;
1609 otherbranch_bdd
= (pNode
)getptype(ptotherbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1610 for (ptlink
= ptotherbranch
->LINK
; ptlink
->NEXT
!= NULL
; ptlink
= ptlink
->NEXT
);
1611 locon_abl
= createAtom(ptlink
->ULINK
.LOCON
->NAME
);
1612 otherbranch_bdd
= applyBinBdd(AND
, otherbranch_bdd
, ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, locon_abl
));
1613 freeExpr(locon_abl
);
1614 if (yagTestSatisfy(badbranch_bdd
, otherbranch_bdd
)) ptbranch
->TYPE
|= CNS_NOT_UP
;
1617 if ((ptbranch
->TYPE
& CNS_VSS_DEGRADED
) == CNS_VSS_DEGRADED
) {
1618 badbranch_bdd
= (pNode
)getptype(ptbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1619 for (ptlink
= ptbranch
->LINK
; ptlink
->NEXT
!= NULL
; ptlink
= ptlink
->NEXT
);
1620 locon_abl
= createAtom(ptlink
->ULINK
.LOCON
->NAME
);
1621 badbranch_bdd
= applyBinBdd(AND
, badbranch_bdd
, notBdd(ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, locon_abl
)));
1622 freeExpr(locon_abl
);
1623 for (ptotherbranch
= ptcone
->BRVSS
; ptotherbranch
; ptotherbranch
= ptotherbranch
->NEXT
) {
1624 if ((ptotherbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1625 if ((ptotherbranch
->TYPE
& CNS_DEGRADED
) == CNS_DEGRADED
|| yagCountLinks(ptotherbranch
->LINK
) > 3) continue;
1626 otherbranch_bdd
= (pNode
)getptype(ptotherbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1627 if (yagTestSatisfy(badbranch_bdd
, otherbranch_bdd
)) ptbranch
->TYPE
|= CNS_NOT_DOWN
;
1629 for (ptotherbranch
= ptcone
->BREXT
; ptotherbranch
; ptotherbranch
= ptotherbranch
->NEXT
) {
1630 if ((ptotherbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
1631 if ((ptotherbranch
->TYPE
& CNS_VSS_DEGRADED
) == CNS_VSS_DEGRADED
|| yagCountLinks(ptotherbranch
->LINK
) > 4) continue;
1632 otherbranch_bdd
= (pNode
)getptype(ptotherbranch
->USER
, YAG_BRANCHBDD_PTYPE
)->DATA
;
1633 for (ptlink
= ptotherbranch
->LINK
; ptlink
->NEXT
!= NULL
; ptlink
= ptlink
->NEXT
);
1634 locon_abl
= createAtom(ptlink
->ULINK
.LOCON
->NAME
);
1635 otherbranch_bdd
= applyBinBdd(AND
, otherbranch_bdd
, notBdd(ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, locon_abl
)));
1636 freeExpr(locon_abl
);
1637 if (yagTestSatisfy(badbranch_bdd
, otherbranch_bdd
)) ptbranch
->TYPE
|= CNS_NOT_DOWN
;
1641 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1642 if ((ptbranch
->TYPE
& (CNS_VDD_DEGRADED
|CNS_VSS_DEGRADED
|CNS_NOT_UP
|CNS_NOT_DOWN
)) == (CNS_VDD_DEGRADED
|CNS_VSS_DEGRADED
|CNS_NOT_UP
|CNS_NOT_DOWN
)) {
1643 ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
1644 ptbranch
->TYPE
&= ~(CNS_NOT_UP
|CNS_NOT_DOWN
);
1649 /* Clean branch conductance functions */
1651 for (ptbranch
= ptcone
->BRVDD
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1652 ptbranch
->USER
= testanddelptype(ptbranch
->USER
, YAG_BRANCHBDD_PTYPE
);
1656 for (ptbranch
= ptcone
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1657 ptbranch
->USER
= testanddelptype(ptbranch
->USER
, YAG_BRANCHBDD_PTYPE
);
1660 if (bad_vdd
|| bad_vss
) {
1661 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1662 ptbranch
->USER
= testanddelptype(ptbranch
->USER
, YAG_BRANCHBDD_PTYPE
);
1666 yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
1667 YAG_CONTEXT
->YAG_CONE_GRAPH
= savegraph
;
1668 YAG_CONTEXT
->YAG_CURCIRCUIT
= savecircuit
;
1669 YAG_CONTEXT
->YAG_DEPTH
= save_depth
;