1 /****************************************************************************/
3 /* Chaine de CAO & VLSI Alliance */
5 /* Produit : YAGLE v3.50 */
6 /* Fichier : yag_detect.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 : ../../.... */
14 /* Modifie par : le : ../../.... */
15 /* Modifie par : le : ../../.... */
16 /* Modifie par : le : ../../.... */
18 /****************************************************************************/
20 #include "yag_headers.h"
22 static chain_list
*yagSortBranches(chain_list
*ptbranches
);
23 static void yagPropClockLatch (cone_list
*ptcone
, void *ptprev
);
24 static void yagUnmarkCommands (cone_list
*ptcone
);
25 static void yagPropNotClockLatch (cone_list
*ptcone
);
26 static void yagUnmarkNotCommands (cone_list
*ptcone
);
27 static void yagPropClockPrech(cone_list
*ptcone
, void *ptprev
);
28 static void yagMarkStuck(cone_list
*ptcone
, pCircuit circuit
, chain_list
*constraint_list
);
29 static void yagUpdateStuck(cone_list
*ptcone
, pCircuit circuit
, chain_list
*constraint_list
);
30 static void yagPropClockGating(cone_list
*ptcone
, void *ptprev
);
31 static int yagDetectConditionedState(chain_list
*gateexpr
, char *varname
, int *ptoutput_state
);
33 /****************************************************************************
34 * function yagDetectBadBranches() *
35 ****************************************************************************/
37 /* test for branches containing max. number of links */
39 void yagDetectBadBranches(cone_list
*ptcone
)
41 branch_list
*brlist
[4];
42 branch_list
*ptbranch
;
45 /* clean up from previous pass */
46 ptcone
->TECTYPE
&= ~YAG_BADCONE
;
48 brlist
[0] = ptcone
->BRVDD
;
49 brlist
[1] = ptcone
->BRVSS
;
50 brlist
[2] = ptcone
->BREXT
;
51 brlist
[3] = ptcone
->BRGND
;
54 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
55 if (yagCountLinks(ptbranch
->LINK
) == YAG_CONTEXT
->YAG_MAX_LINKS
) {
56 ptcone
->TECTYPE
|= YAG_BADCONE
;
62 /****************************************************************************
63 * function yagDetectParaTrans() *
64 ****************************************************************************/
66 /* test for parallel connected transistors */
68 void yagDetectParaTrans(cone_list
*ptcone
)
70 branch_list
*brlist
[4];
73 branch_list
*ptbranch
;
75 chain_list
*paralist
= NULL
;
78 /* clean up from previous pass */
80 ptuser
= getptype(ptcone
->USER
, CNS_PARATRANS
);
82 freechain((chain_list
*)ptuser
->DATA
);
83 ptcone
->USER
= delptype(ptcone
->USER
, CNS_PARATRANS
);
86 brlist
[0] = ptcone
->BRVDD
;
87 brlist
[1] = ptcone
->BRVSS
;
88 brlist
[2] = ptcone
->BREXT
;
89 brlist
[3] = ptcone
->BRGND
;
92 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
93 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
94 if ((ptlink
->TYPE
& CNS_EXT
) == 0) {
95 pttrans
= ptlink
->ULINK
.LOTRS
;
96 if (getptype(pttrans
->USER
, MBK_TRANS_PARALLEL
) != NULL
) {
97 if (yagGetChain(paralist
, pttrans
) == NULL
) {
98 paralist
= addchain(paralist
, pttrans
);
101 if ((ptuser
= getptype(pttrans
->USER
, CNS_SWITCH
)) != NULL
) {
102 pttrans
= (lotrs_list
*)ptuser
->DATA
;
103 if (getptype(pttrans
->USER
, MBK_TRANS_PARALLEL
) != NULL
) {
104 if (yagGetChain(paralist
, pttrans
) == NULL
) {
105 paralist
= addchain(paralist
, pttrans
);
113 if (paralist
!= NULL
) ptcone
->USER
= addptype(ptcone
->USER
, CNS_PARATRANS
, paralist
);
116 /****************************************************************************
117 * function yagAddSwitchInversion() *
118 ****************************************************************************/
120 void yagAddSwitchInversion(cnsfig_list
*ptcnsfig
)
122 lotrs_list
*pttrans1
, *pttrans2
;
123 cone_list
*ptcone1
, *ptcone2
;
124 chain_list
*ptloconlist1
, *ptloconlist2
;
127 for (pttrans1
= ptcnsfig
->LOTRS
; pttrans1
; pttrans1
= pttrans1
->NEXT
) {
128 if ((ptuser
= getptype(pttrans1
->USER
, CNS_SWITCH
)) == NULL
) continue;
129 pttrans2
= (lotrs_list
*)ptuser
->DATA
;
130 ptcone1
= (cone_list
*)pttrans1
->GRID
;
131 ptcone2
= (cone_list
*)pttrans2
->GRID
;
132 if (ptcone1
== NULL
|| ptcone2
== NULL
) continue;
133 if ((ptuser
= getptype(ptcone1
->USER
, CNS_EXT
)) != NULL
) {
134 ptloconlist1
= (chain_list
*)ptuser
->DATA
;
136 else ptloconlist1
= NULL
;
137 if ((ptuser
= getptype(ptcone2
->USER
, CNS_EXT
)) != NULL
) {
138 ptloconlist2
= (chain_list
*)ptuser
->DATA
;
140 else ptloconlist2
= NULL
;
141 if (ptloconlist1
== NULL
&& ptloconlist2
== NULL
) {
142 cnsAddConeInversion(ptcone1
, ptcone2
);
144 else if (ptloconlist1
== NULL
&& ptloconlist2
!= NULL
) {
145 cnsAddConeInversion(ptcone2
, ptcone1
);
147 else if (ptloconlist1
!= NULL
&& ptloconlist2
== NULL
) {
148 cnsAddConeInversion(ptcone1
, ptcone2
);
150 else { /* ptloconlist1 != NULL && ptloconlist2 != NULL */
151 cnsAddConeInversion(ptcone1
, ptcone2
);
156 /****************************************************************************
157 * function yagCorrectSwitch() *
158 ****************************************************************************/
160 /* Use the PMOS in VDD branch and NMOS in VSS branch */
161 /* For EXT , there is one NMOS branch, and one PMOS */
163 void yagCorrectSwitch(cone_list
*ptcone
)
165 branch_list
*ptbranch
;
167 lotrs_list
*pttrans_n
, *pttrans_p
, *pttrans
, *ptothertrans
;
168 edge_list
*ptedge
, *ptotheredge
;
170 chain_list
*ptchain1
, *ptchain2
;
174 for (ptbranch
= ptcone
->BRVDD
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
175 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
176 if ((ptlink
->TYPE
& CNS_SWITCH
) == CNS_SWITCH
) {
177 pttrans_n
= ptlink
->ULINK
.LOTRS
;
178 pttrans_p
= (lotrs_list
*)getptype(pttrans_n
->USER
, CNS_SWITCH
)->DATA
;
179 ptlink
->ULINK
.LOTRS
= pttrans_p
;
180 ptlink
->TYPE
&=~CNS_TNLINK
;
181 ptlink
->TYPE
|=CNS_TPLINK
;
186 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
187 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
188 if ((ptlink
->TYPE
& CNS_SWITCH
) == CNS_SWITCH
) break;
190 if (ptlink
!= NULL
) {
191 ptcone
->BREXT
= yagCopyBranch(ptcone
->BREXT
, ptbranch
);
192 ptbranch
->TYPE
|= CNS_NOT_UP
;
193 if ((ptbranch
->TYPE
& (CNS_NOT_UP
|CNS_NOT_DOWN
)) == (CNS_NOT_UP
|CNS_NOT_DOWN
)) {
194 ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
195 ptbranch
->TYPE
&= ~(CNS_NOT_UP
|CNS_NOT_DOWN
);
197 ptcone
->BREXT
->TYPE
|= CNS_NOT_DOWN
;
198 if ((ptcone
->BREXT
->TYPE
& (CNS_NOT_UP
|CNS_NOT_DOWN
)) == (CNS_NOT_UP
|CNS_NOT_DOWN
)) {
199 ptcone
->BREXT
->TYPE
|= CNS_NOT_FUNCTIONAL
;
200 ptcone
->BREXT
->TYPE
&= ~(CNS_NOT_UP
|CNS_NOT_DOWN
);
202 for (ptlink
= ptcone
->BREXT
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
203 if ((ptlink
->TYPE
& CNS_SWITCH
) == CNS_SWITCH
) {
204 pttrans_n
= ptlink
->ULINK
.LOTRS
;
205 pttrans_p
= (lotrs_list
*)getptype(pttrans_n
->USER
, CNS_SWITCH
)->DATA
;
206 ptlink
->ULINK
.LOTRS
= pttrans_p
;
207 ptlink
->TYPE
&=~CNS_TNLINK
;
208 ptlink
->TYPE
|=CNS_TPLINK
;
214 if (changed
) yagChainCone(ptcone
);
216 /* Check incone list to see that all switch inputs exist, add if necessary, and synchronise input markings */
218 ptuser
= getptype(ptcone
->USER
, CNS_SWITCH
);
220 for (ptchain1
= (chain_list
*)ptuser
->DATA
; ptchain1
; ptchain1
= ptchain1
->NEXT
) {
221 for (ptchain2
= (chain_list
*)ptchain1
->DATA
; ptchain2
; ptchain2
= ptchain2
->NEXT
) {
222 pttrans
= (lotrs_list
*)ptchain2
->DATA
;
223 ptedge
= yagGetEdge(ptcone
->INCONE
, pttrans
->GRID
);
224 ptothertrans
= (lotrs_list
*)getptype(pttrans
->USER
, CNS_SWITCH
)->DATA
;
225 ptotheredge
= yagGetEdge(ptcone
->INCONE
, ptothertrans
->GRID
);
226 if (ptedge
== NULL
) {
227 if (ptotheredge
) inputtype
= ptotheredge
->TYPE
;
228 else inputtype
= CNS_CONE
;
229 addincone(ptcone
, inputtype
, pttrans
->GRID
);
232 if (ptotheredge
&& (ptotheredge
->TYPE
& CNS_HZCOM
) == CNS_HZCOM
) ptedge
->TYPE
|= CNS_HZCOM
;
239 /****************************************************************************
240 * function yagDetectSwitch() *
241 ****************************************************************************/
243 /* test for a CMOS switch but do not test for gate signal inversion */
245 void yagDetectSwitch(cone_list
*ptcone
)
247 branch_list
*brlist
[4];
249 chain_list
*ptchain
, *testchain
= NULL
;
250 lotrs_list
*pttrans_n
, *pttrans_p
;
251 branch_list
*ptbranch
;
253 chain_list
*switchpair
, *switchlist
= NULL
;
256 /* clean up from previous pass */
258 ptuser
= getptype(ptcone
->USER
, CNS_SWITCH
);
259 if (ptuser
!= NULL
) {
260 for (ptchain
= (chain_list
*)ptuser
->DATA
; ptchain
; ptchain
= ptchain
->NEXT
) {
261 freechain((chain_list
*)ptchain
->DATA
);
263 freechain((chain_list
*)ptuser
->DATA
);
264 ptcone
->USER
= delptype(ptcone
->USER
, CNS_SWITCH
);
267 brlist
[0] = ptcone
->BRVDD
;
268 brlist
[1] = ptcone
->BRVSS
;
269 brlist
[2] = ptcone
->BREXT
;
270 brlist
[3] = ptcone
->BRGND
;
272 for (i
=0; i
<4; i
++) {
273 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
274 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
275 if ((ptlink
->TYPE
& CNS_SWITCH
) == CNS_SWITCH
) {
276 pttrans_n
= ptlink
->ULINK
.LOTRS
;
277 if (yagGetChain(testchain
, pttrans_n
) == NULL
) {
278 pttrans_p
= (lotrs_list
*)getptype(pttrans_n
->USER
, CNS_SWITCH
)->DATA
;
279 testchain
= addchain(testchain
, pttrans_n
);
280 switchpair
= addchain(NULL
, pttrans_n
);
281 switchpair
= addchain(switchpair
, pttrans_p
);
282 switchlist
= addchain(switchlist
, switchpair
);
288 freechain(testchain
);
289 if (switchlist
) ptcone
->USER
= addptype(ptcone
->USER
, CNS_SWITCH
, switchlist
);
292 /****************************************************************************
293 * function yagDetectParallelBranches() *
294 ****************************************************************************/
296 /* test for branches which have identical inputs */
299 yagDetectParallelBranches(cone_list
*ptcone
)
301 branch_list
*ptbranch
;
302 chain_list
*ptchain
= NULL
;
303 chain_list
*ptchain0
;
304 chain_list
*sortedchain
;
307 /* clean up from previous pass */
309 ptuser
= getptype(ptcone
->USER
, CNS_PARALLEL
);
310 if (ptuser
!= NULL
) {
311 for (ptchain0
= (chain_list
*)ptuser
->DATA
; ptchain0
; ptchain0
= ptchain0
->NEXT
) {
312 freechain((chain_list
*)ptchain0
->DATA
);
314 freechain((chain_list
*)ptuser
->DATA
);
315 ptcone
->USER
= delptype(ptcone
->USER
, CNS_PARALLEL
);
318 ptchain
= parabrs(ptcone
->BRVDD
);
319 if (YAG_CONTEXT
->YAG_MINIMISE_CONES
&& ptchain
!= NULL
) {
320 for (ptchain0
= ptchain
; ptchain0
; ptchain0
= ptchain0
->NEXT
) {
321 freechain((chain_list
*)ptchain0
->DATA
);
325 for (ptbranch
= ptcone
->BRVDD
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
326 if ((ptbranch
->TYPE
& CNS_PARALLEL_INS
) == CNS_PARALLEL_INS
) {
327 yagDestroyBranch(ptcone
, ptbranch
);
329 else ptbranch
->TYPE
&= ~CNS_PARALLEL
;
333 ptchain
= append(ptchain
, parabrs(ptcone
->BRVSS
));
334 if (YAG_CONTEXT
->YAG_MINIMISE_CONES
&& ptchain
!= NULL
) {
335 for (ptchain0
= ptchain
; ptchain0
; ptchain0
= ptchain0
->NEXT
) {
336 freechain((chain_list
*)ptchain0
->DATA
);
340 for (ptbranch
= ptcone
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
341 if ((ptbranch
->TYPE
& CNS_PARALLEL_INS
) == CNS_PARALLEL_INS
) {
342 yagDestroyBranch(ptcone
, ptbranch
);
344 else ptbranch
->TYPE
&= ~CNS_PARALLEL
;
348 ptchain
= append(ptchain
, parabrs(ptcone
->BREXT
));
349 if (YAG_CONTEXT
->YAG_MINIMISE_CONES
&& ptchain
!= NULL
) {
350 for (ptchain0
= ptchain
; ptchain0
; ptchain0
= ptchain0
->NEXT
) {
351 freechain((chain_list
*)ptchain0
->DATA
);
355 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
356 if ((ptbranch
->TYPE
& CNS_PARALLEL_INS
) == CNS_PARALLEL_INS
) {
357 yagDestroyBranch(ptcone
, ptbranch
);
359 else ptbranch
->TYPE
&= ~CNS_PARALLEL
;
363 /* sort each list of parallel branches so the the head of the list */
364 /* is the least resistive branch so as to improve the approximation */
365 /* due to the equivalent transistors generated for the timing. */
366 for (ptchain0
= ptchain
; ptchain0
; ptchain0
= ptchain0
->NEXT
) {
367 sortedchain
= yagSortBranches((chain_list
*)ptchain0
->DATA
);
368 freechain((chain_list
*)ptchain0
->DATA
);
369 ptchain0
->DATA
= sortedchain
;
372 if (ptchain
!= NULL
) {
373 ptcone
->USER
= addptype(ptcone
->USER
, CNS_PARALLEL
, ptchain
);
377 static int yagBranchCompare (const void *elem1
, const void *elem2
)
381 res1
= yagCalcBranchResistance(*(branch_list
**)elem1
);
382 res2
= yagCalcBranchResistance(*(branch_list
**)elem2
);
384 if (res1
< res2
) return 1;
385 else if (res2
> res1
) return -1;
392 yagSortBranches(chain_list
*ptbranches
)
394 branch_list
**branchtable
;
395 branch_list
*ptbranch
;
397 chain_list
*reschain
= NULL
;
400 numbranches
= yagCountChains(ptbranches
);
401 branchtable
= (branch_list
**)mbkalloc(numbranches
* sizeof(branch_list
*));
403 for (ptchain
= ptbranches
; ptchain
; ptchain
= ptchain
->NEXT
) {
404 ptbranch
= (branch_list
*)ptchain
->DATA
;
405 branchtable
[i
++] = ptbranch
;
407 qsort(branchtable
, numbranches
, sizeof(branch_list
*), yagBranchCompare
);
408 for (i
= 0; i
< numbranches
; i
++) reschain
= addchain(reschain
, branchtable
[i
]);
410 mbkfree(branchtable
);
414 /****************************************************************************
415 * function yagDetectPullup() *
416 ****************************************************************************/
418 /* mark strongly resistive VDD branches (resistance > 10 x max. down resistance */
420 void yagDetectPullup(cone_list
*ptcone
)
422 branch_list
*ptbranch
;
424 float downres
, branchres
;
425 int donecalc
= FALSE
;
427 for (ptbranch
=ptcone
->BRVDD
; ptbranch
; ptbranch
=ptbranch
->NEXT
) {
428 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
429 if ((ptlink
->TYPE
& CNS_RESIST
) == 0) break;
431 if (ptlink
!= NULL
) continue;
433 downres
= yagCalcMaxDownRes(ptcone
);
436 branchres
= yagCalcBranchResistance(ptbranch
);
437 if ((downres
!= 0.0 && branchres
>= V_FLOAT_TAB
[__YAGLE_PULL_RATIO
].VALUE
* downres
)
438 || (downres
== 0.0 && branchres
>= 1.5 && (ptcone
->TYPE
& CNS_EXT
) == CNS_EXT
)) {
439 ptbranch
->TYPE
|= CNS_RESBRANCH
;
444 /****************************************************************************
445 * function yagDetectPulldown() *
446 ****************************************************************************/
448 /* mark strongly resistive VSS branches (resistance > 10 x max. up resistance */
451 yagDetectPulldown(cone_list
*ptcone
)
453 branch_list
*ptbranch
;
455 float upres
, branchres
;
456 int donecalc
= FALSE
;
458 for (ptbranch
=ptcone
->BRVSS
; ptbranch
; ptbranch
=ptbranch
->NEXT
) {
459 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
460 if ((ptlink
->TYPE
& CNS_RESIST
) == 0) break;
462 if (ptlink
!= NULL
) continue;
464 upres
= yagCalcMaxUpRes(ptcone
);
467 branchres
= yagCalcBranchResistance(ptbranch
);
468 if ((upres
!= 0.0 && branchres
>= V_FLOAT_TAB
[__YAGLE_PULL_RATIO
].VALUE
* upres
)
469 || (upres
== 0.0 && branchres
>= 1.5 && (ptcone
->TYPE
& CNS_EXT
) == CNS_EXT
)) {
470 ptbranch
->TYPE
|= CNS_RESBRANCH
;
475 /****************************************************************************
476 * function yagDetectLoop() *
477 ****************************************************************************/
480 yagDetectLoops(cone_list
*ptcone
)
485 edge_list
*ptloopout
;
488 for (ptinput
= ptcone
->INCONE
; ptinput
; ptinput
= ptinput
->NEXT
) {
489 if ((ptinput
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
490 if ((ptinput
->TYPE
& YAG_MARK
) != 0) {
491 ptinput
->TYPE
&= ~YAG_MARK
;
494 ptincone
= ptinput
->UEDGE
.CONE
;
495 if ((ptloopin
= yagGetEdge(ptincone
->INCONE
, ptcone
)) != NULL
) {
496 ptinput
->TYPE
|= CNS_LOOP
;
497 ptloopin
->TYPE
|= CNS_LOOP
;
498 ptoutput
= yagGetEdge(ptcone
->OUTCONE
, ptincone
);
499 ptoutput
->TYPE
|= CNS_LOOP
;
500 ptloopout
= yagGetEdge(ptincone
->OUTCONE
, ptcone
);
501 ptloopout
->TYPE
|= CNS_LOOP
;
502 if ((ptinput
->TYPE
& CNS_BLEEDER
) != CNS_BLEEDER
503 && (ptloopin
->TYPE
& CNS_BLEEDER
) != CNS_BLEEDER
504 && (ptinput
->TYPE
& CNS_FEEDBACK
) != CNS_FEEDBACK
505 && (ptloopin
->TYPE
& CNS_FEEDBACK
) != CNS_FEEDBACK
) {
506 ptloopin
->TYPE
|= YAG_MARK
;
513 yagCountLoops(cone_list
*ptcone
, int warning
)
518 edge_list
*ptloopout
;
523 if ((ptcone
->TYPE
& CNS_RS
) == CNS_RS
) return 0;
524 for (ptinput
= ptcone
->INCONE
; ptinput
; ptinput
= ptinput
->NEXT
) {
525 if ((ptinput
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
526 if (warning
&& (ptinput
->TYPE
& YAG_MARK
) != 0) {
527 ptinput
->TYPE
&= ~YAG_MARK
;
530 ptincone
= ptinput
->UEDGE
.CONE
;
531 if ((ptloopin
= yagGetEdge(ptincone
->INCONE
, ptcone
)) != NULL
) {
532 ptoutput
= yagGetEdge(ptcone
->OUTCONE
, ptincone
);
533 ptloopout
= yagGetEdge(ptincone
->OUTCONE
, ptcone
);
534 if ((ptinput
->TYPE
& CNS_BLEEDER
) != CNS_BLEEDER
535 && (ptloopin
->TYPE
& CNS_BLEEDER
) != CNS_BLEEDER
536 && (ptinput
->TYPE
& CNS_MEMSYM
) != CNS_MEMSYM
537 && (ptloopin
->TYPE
& CNS_MEMSYM
) != CNS_MEMSYM
538 && (ptinput
->TYPE
& CNS_FEEDBACK
) != CNS_FEEDBACK
539 && (ptloopin
->TYPE
& CNS_FEEDBACK
) != CNS_FEEDBACK
) {
540 if (warning
) ptloopin
->TYPE
|= YAG_MARK
;
542 if ((ptcone
->TECTYPE
& (CNS_ONE
|CNS_ZERO
)) != 0 || (ptincone
->TECTYPE
& (CNS_ONE
|CNS_ZERO
)) != 0) {
543 yagWarning(WAR_STUCK_LOOP
, ptcone
->NAME
, ptincone
->NAME
, NULL
, 0);
545 else yagWarning(WAR_UNKNOWN_LOOP
, ptcone
->NAME
, ptincone
->NAME
, NULL
, 0);
554 /****************************************************************************
555 * function yagDetectTransfer() *
556 ****************************************************************************/
558 /* test for transfer PTYPE on the cone transistors */
561 yagDetectTransfer(cone_list
*ptcone
)
564 branch_list
*brlist
[4];
565 branch_list
*ptbranch
;
569 chain_list
*bleeders
= NULL
;
571 int bleeder
, not_func
, feedback
;
573 int change_chain
= FALSE
;
576 if (getptype(ptcone
->USER
, CNS_BLEEDER
) == NULL
) done_bleeders
= FALSE
;
577 else done_bleeders
= TRUE
;
579 brlist
[0] = ptcone
->BRVDD
;
580 brlist
[1] = ptcone
->BRVSS
;
581 brlist
[2] = ptcone
->BREXT
;
582 brlist
[3] = ptcone
->BRGND
;
584 for (i
=0; i
<4; i
++) {
585 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
586 if ((ptbranch
->TYPE
& CNS_EXT
) != 0 && ptbranch
->LINK
->NEXT
== NULL
) continue;
590 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
591 if ((ptlink
->TYPE
& CNS_EXT
) != CNS_EXT
) {
592 pttrans
= ptlink
->ULINK
.LOTRS
;
593 if ((ptuser
= getptype(pttrans
->USER
, FCL_TRANSFER_PTYPE
)) != NULL
) {
594 ptedge
= yagGetEdge(ptcone
->INCONE
, pttrans
->GRID
);
595 if (ptedge
== NULL
) continue;
596 fcltype
= (long)ptuser
->DATA
;
598 if ((fcltype
& FCL_BLEEDER
) != 0) {
599 ptedge
->TYPE
|= CNS_BLEEDER
;
602 if ((fcltype
& FCL_FEEDBACK
) != 0) {
603 ptedge
->TYPE
|= CNS_FEEDBACK
;
606 if ((fcltype
& FCL_COMMAND
) != 0) {
607 ptlink
->TYPE
|= CNS_COMMAND
;
608 ptedge
->TYPE
|= CNS_COMMAND
;
610 if ((fcltype
& FCL_NOT_FUNCTIONAL
) == 0)
612 if ((fcltype
& FCL_SHORT
) != 0) {
613 ptlink
->TYPE
|= CNS_SHORT
;
614 ptlink
->TYPE
|= CNS_RESIST
;
624 ptbranch
->TYPE
|= CNS_BLEEDER
|CNS_NOT_FUNCTIONAL
;
625 if (!done_bleeders
) bleeders
= addchain(bleeders
, ptbranch
);
627 if (not_func
) ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
628 if (feedback
) ptbranch
->TYPE
|= CNS_FEEDBACK
;
631 if (!done_bleeders
&& bleeders
!= NULL
) {
632 ptcone
->USER
= addptype(ptcone
->USER
, CNS_BLEEDER
, bleeders
);
637 /****************************************************************************
638 * function yagDetectDegraded() *
639 ****************************************************************************/
641 /* test for degraded branches */
644 yagDetectDegraded(cone_list
*ptcone
)
646 branch_list
*ptbranch
;
647 branch_list
*brlist
[4];
652 int has_degraded_vdd
= FALSE
, has_degraded_vss
= FALSE
;
653 int bleeder_up
= FALSE
, bleeder_down
= FALSE
;
655 brlist
[0] = ptcone
->BRVDD
;
656 brlist
[1] = ptcone
->BRVSS
;
657 brlist
[2] = ptcone
->BREXT
;
658 brlist
[3] = ptcone
->BRGND
;
660 ptcone
->TECTYPE
&= ~(CNS_VDD_DEGRADED
|CNS_VSS_DEGRADED
);
661 ptcone
->TECTYPE
&= ~(CNS_CMOS
);
663 for (i
=0; i
<4; i
++) {
664 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
665 branchtype
= ptbranch
->TYPE
& (CNS_VSS
|CNS_VDD
|CNS_EXT
);
666 if ((ptbranch
->TYPE
& CNS_BLEEDER
) != 0) {
667 if (branchtype
== CNS_VDD
) bleeder_up
= TRUE
;
668 if (branchtype
== CNS_VSS
) bleeder_down
= TRUE
;
670 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
671 ptbranch
->TYPE
&= ~(CNS_VDD_DEGRADED
|CNS_VSS_DEGRADED
);
672 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
673 if ((ptlink
->TYPE
& CNS_SWITCH
) == CNS_SWITCH
) continue;
675 linktype
= ptlink
->TYPE
& (CNS_TNLINK
|CNS_TPLINK
|CNS_IN
|CNS_INOUT
);
677 if (linktype
== CNS_TNLINK
|| linktype
== CNS_TPLINK
) {
678 if (linktype
== CNS_TNLINK
&& (branchtype
== CNS_VDD
|| branchtype
== CNS_EXT
)) {
679 ptbranch
->TYPE
|= CNS_VDD_DEGRADED
;
680 if ((ptbranch
->TYPE
& CNS_NOT_UP
) == 0) has_degraded_vdd
= TRUE
;
682 else if (linktype
== CNS_TPLINK
&& (branchtype
== CNS_VSS
|| branchtype
== CNS_EXT
)) {
683 ptbranch
->TYPE
|= CNS_VSS_DEGRADED
;
684 if ((ptbranch
->TYPE
& CNS_NOT_DOWN
) == 0) has_degraded_vss
= TRUE
;
690 if ((ptcone
->TYPE
& CNS_LATCH
) == 0) {
691 if (has_degraded_vdd
&& !bleeder_up
) ptcone
->TECTYPE
|= CNS_VDD_DEGRADED
;
692 if (has_degraded_vss
&& !bleeder_down
) ptcone
->TECTYPE
|= CNS_VSS_DEGRADED
;
694 if ((ptcone
->TECTYPE
& (CNS_VDD_DEGRADED
|CNS_VSS_DEGRADED
)) == 0) {
695 ptcone
->TECTYPE
|= CNS_CMOS
;
699 /****************************************************************************
700 * Functions to update FALSECONF status *
701 ****************************************************************************/
703 int yagDetectFalseConf(cone_list
*ptcone
)
705 branch_list
*ptbranch
;
706 branch_list
*brlist
[4];
707 losig_list
*ptconesig
;
708 int i
, changed
= FALSE
;
710 if ((ptcone
->TYPE
& YAG_FALSECONF
) == 0) return 0;
711 ptconesig
= (losig_list
*)getptype(ptcone
->USER
, CNS_SIGNAL
)->DATA
;
712 ptcone
->TYPE
&= ~YAG_FALSECONF
;
714 brlist
[0] = ptcone
->BRVDD
;
715 brlist
[1] = ptcone
->BRVSS
;
716 brlist
[2] = ptcone
->BREXT
;
717 brlist
[3] = ptcone
->BRGND
;
719 for (i
=0; i
<4; i
++) {
720 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
721 if ((ptbranch
->TYPE
& YAG_FALSECONF
) != 0) {
722 if (yagCheckFalseConfBranch(ptbranch
, ptconesig
)) {
723 ptcone
->TYPE
|= YAG_FALSECONF
;
733 yagCheckFalseConfBranch(branch_list
*ptbranch
, losig_list
*ptfirstsig
)
736 losig_list
*ptlastsig
, *ptnextsig
;
737 cone_list
*ptsigcone
;
740 ptbranch
->TYPE
&= ~YAG_FALSECONF
;
741 ptlastsig
= ptfirstsig
;
743 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
744 if ((ptlink
->TYPE
& (CNS_TNLINK
|CNS_TPLINK
)) == 0) continue;
745 if ((ptnextsig
= ptlink
->ULINK
.LOTRS
->DRAIN
->SIG
) == ptlastsig
) {
746 ptnextsig
= ptlink
->ULINK
.LOTRS
->SOURCE
->SIG
;
748 ptlastsig
= ptnextsig
;
749 ptuser
= getptype(ptnextsig
->USER
, YAG_CONE_PTYPE
);
750 if (ptuser
!= NULL
) {
751 ptsigcone
= (cone_list
*)ptuser
->DATA
;
752 if ((ptsigcone
->TYPE
& YAG_LOOPCONF
) != 0) break;
755 if (ptlink
!= NULL
) {
756 ptbranch
->TYPE
|= YAG_FALSECONF
;
763 yagDetectLoopConf(cone_list
*ptcone
)
765 edge_list
*ptedgelist0
, *ptedgelist1
;
766 edge_list
*ptedge0
, *ptedge1
;
769 ptcone
->TYPE
&= ~YAG_LOOPCONF
;
771 ptedgelist0
= ptcone
->INCONE
;
772 for (ptedge0
= ptedgelist0
; ptedge0
; ptedge0
= ptedge0
->NEXT
) {
773 if ((ptedge0
->TYPE
& CNS_EXT
) != 0) continue;
774 if ((ptedge0
->TYPE
& CNS_BLEEDER
) == CNS_BLEEDER
) continue;
775 if ((ptedge0
->TYPE
& CNS_FEEDBACK
) == CNS_FEEDBACK
) continue;
776 ptincone
= ptedge0
->UEDGE
.CONE
;
777 if ((ptincone
->TYPE
& YAG_PARTIAL
) != 0) {
778 ptedgelist1
= (edge_list
*)getptype(ptincone
->USER
, YAG_INPUTS_PTYPE
)->DATA
;
780 else ptedgelist1
= ptincone
->INCONE
;
781 ptedge1
= yagGetEdge(ptedgelist1
, ptcone
);
782 if (ptedge1
!= NULL
) {
783 if ((ptedge1
->TYPE
& CNS_BLEEDER
) == CNS_BLEEDER
) continue;
784 if ((ptedge1
->TYPE
& CNS_FEEDBACK
) == CNS_FEEDBACK
) continue;
785 ptcone
->TYPE
|= YAG_LOOPCONF
;
791 /****************************************************************************
792 * function yagRemoveRedundantBranches() *
793 ****************************************************************************/
795 /* test for redundant branches */
798 yagRemoveRedundantBranches(cone_list
*ptcone
)
800 branch_list
*ptbranch
;
801 branch_list
*ptnextbranch
;
802 branch_list
*brlist
[4];
806 brlist
[0] = ptcone
->BRVDD
;
807 brlist
[1] = ptcone
->BRVSS
;
808 brlist
[2] = ptcone
->BREXT
;
809 brlist
[3] = ptcone
->BRGND
;
811 if ((ptcone
->TYPE
& (CNS_CONFLICT
|CNS_TRI
)) != 0) return;
812 if ((ptcone
->TYPE
& YAG_HASDUAL
) == 0) return;
813 if ((ptcone
->TYPE
& (CNS_LATCH
|CNS_MEMSYM
|CNS_FLIP_FLOP
|CNS_MASTER
|CNS_SLAVE
|CNS_BLEEDER
)) != 0) return;
815 for (i
=0; i
<4; i
++) {
816 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptnextbranch
) {
817 ptnextbranch
= ptbranch
->NEXT
;
818 if ((ptbranch
->TYPE
& YAG_DUALBRANCH
) == 0) {
819 yagDestroyBranch(ptcone
, ptbranch
);
825 yagChainCone(ptcone
);
826 yagDetectParallelBranches(ptcone
);
827 yagDetectSwitch(ptcone
);
828 yagDetectDegraded(ptcone
);
829 ptcone
->TECTYPE
|= CNS_DUAL_CMOS
;
833 /****************************************************************************
834 * function yagTransferParallel() *
835 ****************************************************************************/
837 /* test for transfer PTYPE on parallel transistors */
838 /* (to be called before parallel restoration) */
841 yagTransferParallel(lofig_list
*ptlofig
)
844 lotrs_list
*ptlotrs
, *ptparatrans
;
846 chain_list
*transchain
, *ptchain
;
848 for (ptlotrs
= ptlofig
->LOTRS
; ptlotrs
; ptlotrs
= ptlotrs
->NEXT
) {
849 if ((ptuser
= getptype(ptlotrs
->USER
, FCL_TRANSFER_PTYPE
)) != NULL
) {
850 transtype
= (long)ptuser
->DATA
;
851 if ((ptuser
= getptype(ptlotrs
->USER
, MBK_TRANS_PARALLEL
)) != NULL
) {
852 transchain
= (chain_list
*)ptuser
->DATA
;
853 for (ptchain
= transchain
; ptchain
; ptchain
= ptchain
->NEXT
) {
854 ptparatrans
= (lotrs_list
*)ptchain
->DATA
;
855 if (ptparatrans
== ptlotrs
) continue;
856 if ((ptuser
= getptype(ptparatrans
->USER
, FCL_TRANSFER_PTYPE
)) != NULL
) {
857 ptuser
->DATA
= (void *)(transtype
| (long)ptuser
->DATA
);
859 else ptparatrans
->USER
= addptype(ptparatrans
->USER
, FCL_TRANSFER_PTYPE
, (void *)transtype
);
866 /****************************************************************************
867 * function yagDetectGlitcher() *
868 ****************************************************************************/
870 /* detect two transistor branches which serve no purpose */
871 /* unless considered to be dynamically active */
874 unconnectedcommon(lotrs_list
*pttrans1
, lotrs_list
*pttrans2
)
876 losig_list
*ptcommonsig
= NULL
;
877 chain_list
*loconchain
;
879 if (pttrans1
->DRAIN
->SIG
== pttrans2
->DRAIN
->SIG
) ptcommonsig
= pttrans1
->DRAIN
->SIG
;
880 else if (pttrans1
->SOURCE
->SIG
== pttrans2
->SOURCE
->SIG
) ptcommonsig
= pttrans1
->SOURCE
->SIG
;
881 else if (pttrans1
->DRAIN
->SIG
== pttrans2
->SOURCE
->SIG
) ptcommonsig
= pttrans1
->DRAIN
->SIG
;
882 else if (pttrans1
->SOURCE
->SIG
== pttrans2
->DRAIN
->SIG
) ptcommonsig
= pttrans1
->SOURCE
->SIG
;
884 loconchain
= (chain_list
*)getptype(ptcommonsig
->USER
, LOFIGCHAIN
)->DATA
;
885 if (yagCountChains(loconchain
) == 2) return TRUE
;
891 yagDetectGlitcher(branch_list
*ptbranch
, lotrs_list
*pttrans
, int mark
)
893 lotrs_list
*ptprevtrans
;
898 numlinks
= yagCountLinks(ptbranch
->LINK
);
899 if ((ptbranch
->TYPE
& CNS_EXT
) != 0) numlinks
--;
900 if (pttrans
!= NULL
) {
901 if (numlinks
> V_INT_TAB
[__YAGLE_GLITCH_LINKS
].VALUE
- 1 || numlinks
< 1) return FALSE
;
902 for (ptlink
= ptbranch
->LINK
; ptlink
->NEXT
; ptlink
= ptlink
->NEXT
);
903 ptprevtrans
= ptlink
->ULINK
.LOTRS
;
906 if (numlinks
> V_INT_TAB
[__YAGLE_GLITCH_LINKS
].VALUE
|| numlinks
< 2) return FALSE
;
907 pttrans
= ptbranch
->LINK
->ULINK
.LOTRS
;
908 for (ptlink
= ptbranch
->LINK
->NEXT
; ptlink
; ptlink
= ptlink
->NEXT
) {
909 if ((ptbranch
->TYPE
& CNS_EXT
) != 0 && !ptlink
->NEXT
) break;
910 ptprevtrans
= pttrans
;
911 pttrans
= ptlink
->ULINK
.LOTRS
;
914 if (!unconnectedcommon(pttrans
, ptprevtrans
)) return FALSE
;
917 ptcone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
918 ptcone
->TYPE
|= YAG_STOP
;
919 ptcone
= (cone_list
*)getptype(ptprevtrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
920 ptcone
->TYPE
|= YAG_STOP
;
925 /****************************************************************************
926 * function yagDetectClockLatch() *
927 ****************************************************************************/
929 /* unmark latches with no command on a clock path */
932 yagDetectClockLatch(inffig_list
*ifl
, cnsfig_list
*ptcnsfig
)
936 cone_list
*ptextcone
;
942 chain_list
*cklatchlist
= NULL
;
944 if (YAG_CONTEXT
->YAG_LATCH_REQUIRE_CLOCK
) {
945 cklatchlist
= inf_GetEntriesByType(ifl
, INF_CLOCK_TYPE
, INF_ANY_VALUES
);
946 cklatchlist
= append(cklatchlist
, inf_GetEntriesByType(ifl
, INF_CKLATCH
, INF_YES
));
948 else if ((cklatchlist
= inf_GetEntriesByType(ifl
, INF_CKLATCH
, INF_YES
))==NULL
) return;
950 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
951 ptcone
->TYPE
&= ~YAG_MARK
;
954 /* Propagate from input connectors */
955 for (ptlocon
= ptcnsfig
->LOCON
; ptlocon
; ptlocon
= ptlocon
->NEXT
) {
956 if (yagGetChain(cklatchlist
, ptlocon
->NAME
) != NULL
) {
958 ptuser
= getptype(ptlocon
->USER
, CNS_EXT
);
959 if (ptuser
!= NULL
) ptextcone
= (cone_list
*)ptuser
->DATA
;
960 for (ptout
= ptextcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
961 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
962 yagPropClockLatch(ptout
->UEDGE
.CONE
, ptextcone
);
964 ptuser
= getptype(ptlocon
->USER
, CNS_CONE
);
965 if (ptuser
!= NULL
) {
966 for (ptchain
= (chain_list
*)ptuser
->DATA
; ptchain
; ptchain
= ptchain
->NEXT
) {
967 ptcone
= (cone_list
*)ptchain
->DATA
;
968 if (ptcone
!= ptextcone
) yagPropClockLatch(ptcone
, ptlocon
);
973 /* Propagate from internal cones */
974 if (count
!= yagCountChains(cklatchlist
)) {
975 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
976 if (yagGetChain(cklatchlist
, ptcone
->NAME
) != NULL
) {
977 for (ptout
= ptcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
978 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
979 yagPropClockLatch(ptout
->UEDGE
.CONE
, ptcone
);
984 /* Perform the unmarking */
985 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
987 ptcone
->TYPE
&= ~YAG_VISITED
;
988 if ((ptcone
->TYPE
& YAG_MARK
) == YAG_MARK
) {
990 ptcone
->TYPE
&= ~YAG_MARK
;
992 if ((ptcone
->TYPE
& (CNS_FLIP_FLOP
|CNS_MEMSYM
)) != 0) continue;
993 if ((ptcone
->TYPE
& CNS_EXT
) == CNS_EXT
) {
994 if ((ptcone
->TYPE
& CNS_TRI
) == CNS_TRI
995 || (ptcone
->TYPE
& CNS_CONFLICT
) == CNS_CONFLICT
) {
999 if (!real_latch
&& (ptcone
->TYPE
& CNS_LATCH
) == CNS_LATCH
) {
1000 yagUnmarkLatch(ptcone
, TRUE
, TRUE
);
1001 yagWarning(WAR_UNMARKEDLATCH_LOOP
, NULL
, ptcone
->NAME
, (char *)ptcone
->INDEX
, 0);
1003 else if (YAG_CONTEXT
->YAG_STRICT_CKLATCH
&& real_latch
&& (ptcone
->TYPE
& CNS_LATCH
) == CNS_LATCH
) {
1004 yagUnmarkCommands(ptcone
);
1008 freechain(cklatchlist
);
1012 yagPropClockLatch(cone_list
*ptcone
, void *ptprev
)
1014 edge_list
*ptout
, *ptin
;
1016 if ((ptcone
->TYPE
& (CNS_FLIP_FLOP
|CNS_MEMSYM
)) != 0) return;
1017 if ((ptcone
->TYPE
& CNS_EXT
) == CNS_EXT
) {
1018 if ((ptcone
->TYPE
& CNS_TRI
) == CNS_TRI
1019 || (ptcone
->TYPE
& CNS_CONFLICT
) == CNS_CONFLICT
) {
1023 if ((ptcone
->TYPE
& CNS_LATCH
) == CNS_LATCH
) {
1024 for (ptin
= ptcone
->INCONE
; ptin
; ptin
= ptin
->NEXT
) {
1025 if (ptin
->UEDGE
.PTR
== ptprev
) break;
1027 if (ptin
!= NULL
&& (ptin
->TYPE
& CNS_COMMAND
) != CNS_COMMAND
) {
1028 /* PROPAGATE THROUGH */
1031 ptin
->TYPE
|= YAG_MARK
;
1032 ptcone
->TYPE
|= YAG_MARK
;
1036 if ((ptcone
->TYPE
& YAG_VISITED
) == YAG_VISITED
) return;
1037 ptcone
->TYPE
|= YAG_VISITED
;
1038 for (ptout
= ptcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
1039 if ((ptout
->TYPE
& CNS_FEEDBACK
) == CNS_FEEDBACK
) continue;
1040 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1041 yagPropClockLatch(ptout
->UEDGE
.CONE
, ptcone
);
1046 yagUnmarkLatch(cone_list
*ptcone
, int cutloop
, int warn
)
1048 branch_list
*brlist
[3];
1049 branch_list
*ptbranch
;
1051 edge_list
*ptinedge
;
1052 cone_list
*ptloopcone
;
1053 chain_list
*new_bleeders
= NULL
;
1057 if ((ptcone
->TYPE
& CNS_MEMSYM
) == CNS_MEMSYM
) {
1058 if ((ptuser
= getptype(ptcone
->USER
, YAG_MEMORY_PTYPE
)) != NULL
) {
1059 ptloopcone
= (cone_list
*)ptuser
->DATA
;
1060 ptcone
->USER
= delptype(ptcone
->USER
, YAG_MEMORY_PTYPE
);
1061 ptloopcone
->USER
= delptype(ptloopcone
->USER
, YAG_MEMORY_PTYPE
);
1062 yagUnmarkLatch(ptloopcone
, cutloop
, warn
);
1066 if ((ptcone
->TYPE
& CNS_RS
) != 0) {
1067 if ((ptuser
= getptype(ptcone
->USER
, YAG_BISTABLE_PTYPE
)) != NULL
) {
1068 ptloopcone
= (cone_list
*)ptuser
->DATA
;
1069 ptcone
->USER
= delptype(ptcone
->USER
, YAG_BISTABLE_PTYPE
);
1070 ptloopcone
->USER
= delptype(ptloopcone
->USER
, YAG_BISTABLE_PTYPE
);
1071 yagUnmarkLatch(ptloopcone
, cutloop
, warn
);
1075 ptcone
->TYPE
&= ~(CNS_LATCH
|CNS_RS
|CNS_MASTER
|CNS_SLAVE
|CNS_FLIP_FLOP
|CNS_MEMSYM
|YAG_AUTOLATCH
);
1076 ptcone
->TECTYPE
&= ~(CNS_NAND
|CNS_NOR
);
1078 for (ptinedge
= ptcone
->INCONE
; ptinedge
; ptinedge
= ptinedge
->NEXT
) {
1079 ptinedge
->TYPE
&= ~CNS_COMMAND
;
1080 ptinedge
->TYPE
&= ~CNS_MEMSYM
;
1081 ptinedge
->TYPE
&= ~CNS_ASYNC
;
1082 if ((ptcone
->TECTYPE
& YAG_LEVELHOLD
) != 0) ptinedge
->TYPE
&= ~CNS_BLEEDER
;
1083 if ((ptinedge
->TYPE
& CNS_FEEDBACK
) != 0) {
1084 ptinedge
->TYPE
&= ~CNS_FEEDBACK
;
1085 if (cutloop
) ptinedge
->TYPE
|= CNS_BLEEDER
;
1089 brlist
[0] = ptcone
->BRVDD
;
1090 brlist
[1] = ptcone
->BRVSS
;
1091 brlist
[2] = ptcone
->BREXT
;
1092 for (i
=0; i
<3; i
++) {
1093 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1094 if ((ptbranch
->TYPE
& YAG_LATCH_NF
) == YAG_LATCH_NF
) ptbranch
->TYPE
&= ~(CNS_NOT_FUNCTIONAL
|YAG_LATCH_NF
);
1095 if ((ptcone
->TECTYPE
& YAG_LEVELHOLD
) != 0) {
1096 ptbranch
->TYPE
&= ~CNS_NOT_FUNCTIONAL
;
1097 ptbranch
->TYPE
&= ~CNS_BLEEDER
;
1099 if ((ptbranch
->TYPE
& CNS_FEEDBACK
) == CNS_FEEDBACK
) {
1100 ptbranch
->TYPE
&= ~CNS_FEEDBACK
;
1101 ptbranch
->TYPE
&= ~CNS_NOTCONFLICTUAL
;
1103 ptbranch
->TYPE
|= CNS_BLEEDER
;
1104 new_bleeders
= addchain(new_bleeders
, ptbranch
);
1106 else ptbranch
->TYPE
&= ~CNS_NOT_FUNCTIONAL
;
1108 ptbranch
->TYPE
&= ~YAG_ASYNC
;
1109 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1110 ptlink
->TYPE
&= ~CNS_COMMAND
;
1111 ptlink
->TYPE
&= ~CNS_ASYNCLINK
;
1115 if (new_bleeders
!= NULL
) {
1116 ptuser
= getptype(ptcone
->USER
, CNS_BLEEDER
);
1117 if (ptuser
!= NULL
) {
1118 ptuser
->DATA
= append(ptuser
->DATA
, new_bleeders
);
1120 else ptcone
->USER
= addptype(ptcone
->USER
, CNS_BLEEDER
, (void *)new_bleeders
);
1122 if (!new_bleeders
&& (ptcone
->TECTYPE
& YAG_LEVELHOLD
) != 0) {
1123 ptuser
= getptype(ptcone
->USER
, CNS_BLEEDER
);
1125 freechain((chain_list
*)ptuser
->DATA
);
1126 ptcone
->USER
= delptype(ptcone
->USER
, CNS_BLEEDER
);
1129 /* remove stuck for latches but not LHs */
1130 if ((ptcone
->TECTYPE
& YAG_LEVELHOLD
) == 0) {
1131 ptcone
->TECTYPE
&= ~(CNS_ONE
|CNS_ZERO
);
1133 ptcone
->TECTYPE
&= ~YAG_LEVELHOLD
;
1134 if (warn
) yagWarning(WAR_UNMARKEDLATCH_LOOP
, NULL
, ptcone
->NAME
, (char *)ptcone
->INDEX
, 0);
1138 yagUnmarkCommands(cone_list
*ptcone
)
1140 cone_list
*ptdrivingcone
;
1141 branch_list
*brlist
[3];
1142 branch_list
*ptbranch
;
1144 edge_list
*ptinedge
;
1148 brlist
[0] = ptcone
->BRVDD
;
1149 brlist
[1] = ptcone
->BRVSS
;
1150 brlist
[2] = ptcone
->BREXT
;
1151 for (i
=0; i
<3; i
++) {
1152 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1153 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1154 if ((ptlink
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1155 if ((ptlink
->TYPE
& CNS_COMMAND
) == CNS_COMMAND
) {
1156 ptuser
= getptype(ptlink
->ULINK
.LOTRS
->USER
, CNS_DRIVINGCONE
);
1157 if (ptuser
== NULL
) continue;
1158 ptdrivingcone
= (cone_list
*)ptuser
->DATA
;
1159 ptinedge
= yagGetEdge(ptcone
->INCONE
, ptdrivingcone
);
1160 if (ptinedge
!= NULL
&& (ptinedge
->TYPE
& YAG_MARK
) == 0) {
1161 ptlink
->TYPE
&= ~CNS_COMMAND
;
1168 for (ptinedge
= ptcone
->INCONE
; ptinedge
; ptinedge
= ptinedge
->NEXT
) {
1169 if ((ptinedge
->TYPE
& YAG_MARK
) == 0) {
1170 ptinedge
->TYPE
&= ~CNS_COMMAND
;
1173 ptinedge
->TYPE
&= ~YAG_MARK
;
1178 /****************************************************************************
1179 * function yagDetectNotClockLatch() *
1180 ****************************************************************************/
1182 /* unmark latch commands on a not-clock path */
1185 yagDetectNotClockLatch(inffig_list
*ifl
, cnsfig_list
*ptcnsfig
)
1187 locon_list
*ptlocon
;
1189 cone_list
*ptextcone
;
1191 chain_list
*ptchain
;
1194 chain_list
*notcklatchlist
;
1196 if ((notcklatchlist
=inf_GetEntriesByType(ifl
, INF_CKLATCH
, INF_NO
))==NULL
) return;
1198 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
1199 ptcone
->TYPE
&= ~YAG_MARK
;
1202 /* Propagate from input connectors */
1203 for (ptlocon
= ptcnsfig
->LOCON
; ptlocon
; ptlocon
= ptlocon
->NEXT
) {
1204 if (yagGetChain(notcklatchlist
, ptlocon
->NAME
) != NULL
) {
1206 ptuser
= getptype(ptlocon
->USER
, CNS_EXT
);
1207 if (ptuser
!= NULL
) ptextcone
= (cone_list
*)ptuser
->DATA
;
1208 for (ptout
= ptextcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
1209 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1210 yagPropNotClockLatch(ptout
->UEDGE
.CONE
);
1212 ptuser
= getptype(ptlocon
->USER
, CNS_CONE
);
1213 if (ptuser
!= NULL
) {
1214 for (ptchain
= (chain_list
*)ptuser
->DATA
; ptchain
; ptchain
= ptchain
->NEXT
) {
1215 ptcone
= (cone_list
*)ptchain
->DATA
;
1216 if (ptcone
!= ptextcone
) yagPropNotClockLatch(ptcone
);
1221 /* Propagate from internal cones */
1222 if (count
!= yagCountChains(notcklatchlist
)) {
1223 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
1224 if (yagGetChain(notcklatchlist
, ptcone
->NAME
) != NULL
) {
1225 for (ptout
= ptcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
1226 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1227 yagPropNotClockLatch(ptout
->UEDGE
.CONE
);
1232 /* Perform the unmarking */
1233 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
1234 ptcone
->TYPE
&= ~YAG_VISITED
;
1235 if ((ptcone
->TYPE
& YAG_MARK
) == YAG_MARK
) {
1236 ptcone
->TYPE
&= ~YAG_MARK
;
1237 yagUnmarkNotCommands(ptcone
);
1241 freechain(notcklatchlist
);
1245 yagPropNotClockLatch(cone_list
*ptcone
)
1249 if ((ptcone
->TYPE
& CNS_EXT
) == CNS_EXT
) {
1250 if ((ptcone
->TYPE
& CNS_TRI
) == CNS_TRI
1251 || (ptcone
->TYPE
& CNS_CONFLICT
) == CNS_CONFLICT
) {
1255 if ((ptcone
->TYPE
& (CNS_LATCH
|CNS_FLIP_FLOP
|CNS_MEMSYM
|CNS_MASTER
|CNS_SLAVE
)) != 0) {
1256 ptcone
->TYPE
|= YAG_MARK
;
1259 if ((ptcone
->TYPE
& YAG_VISITED
) == YAG_VISITED
) return;
1260 ptcone
->TYPE
|= YAG_VISITED
;
1261 for (ptout
= ptcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
1262 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1263 yagPropNotClockLatch(ptout
->UEDGE
.CONE
);
1268 yagUnmarkNotCommands(cone_list
*ptcone
)
1270 cone_list
*ptdrivingcone
;
1271 branch_list
*brlist
[3];
1272 branch_list
*ptbranch
;
1274 edge_list
*ptinedge
;
1278 brlist
[0] = ptcone
->BRVDD
;
1279 brlist
[1] = ptcone
->BRVSS
;
1280 brlist
[2] = ptcone
->BREXT
;
1281 for (i
=0; i
<3; i
++) {
1282 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1283 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1284 if ((ptlink
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1285 if ((ptlink
->TYPE
& CNS_COMMAND
) == CNS_COMMAND
) {
1286 ptuser
= getptype(ptlink
->ULINK
.LOTRS
->USER
, CNS_DRIVINGCONE
);
1287 if (ptuser
== NULL
) continue;
1288 ptdrivingcone
= (cone_list
*)ptuser
->DATA
;
1289 ptinedge
= yagGetEdge(ptcone
->INCONE
, ptdrivingcone
);
1290 if (ptinedge
!= NULL
&& (ptinedge
->TYPE
& YAG_MARK
) != 0) {
1291 ptlink
->TYPE
&= ~CNS_COMMAND
;
1298 for (ptinedge
= ptcone
->INCONE
; ptinedge
; ptinedge
= ptinedge
->NEXT
) {
1299 if ((ptinedge
->TYPE
& YAG_MARK
) != 0) {
1300 ptinedge
->TYPE
&= ~CNS_COMMAND
;
1301 ptinedge
->TYPE
&= ~YAG_MARK
;
1306 /****************************************************************************
1307 * function yagDetectClockPrecharge() *
1308 ****************************************************************************/
1310 /* unmark any precharge whose clock is not a precharge clock path */
1313 yagDetectClockPrech(inffig_list
*ifl
, cnsfig_list
*ptcnsfig
)
1315 locon_list
*ptlocon
;
1317 cone_list
*ptextcone
;
1319 chain_list
*ptchain
;
1322 chain_list
*ckprechlist
;
1324 if ((ckprechlist
=inf_GetEntriesByType(ifl
, INF_CKPRECH
, INF_ANY_VALUES
))==NULL
) return;
1326 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
1327 ptcone
->TYPE
&= ~YAG_MARK
;
1330 /* Propagate from input connectors */
1331 for (ptlocon
= ptcnsfig
->LOCON
; ptlocon
; ptlocon
= ptlocon
->NEXT
) {
1332 if (yagGetChain(ckprechlist
, ptlocon
->NAME
) != NULL
) {
1334 ptuser
= getptype(ptlocon
->USER
, CNS_EXT
);
1335 if (ptuser
!= NULL
) ptextcone
= (cone_list
*)ptuser
->DATA
;
1336 for (ptout
= ptextcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
1337 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1338 yagPropClockLatch(ptout
->UEDGE
.CONE
, ptextcone
);
1340 ptuser
= getptype(ptlocon
->USER
, CNS_CONE
);
1341 if (ptuser
!= NULL
) {
1342 for (ptchain
= (chain_list
*)ptuser
->DATA
; ptchain
; ptchain
= ptchain
->NEXT
) {
1343 ptcone
= (cone_list
*)ptchain
->DATA
;
1344 if (ptcone
!= ptextcone
) yagPropClockPrech(ptcone
, ptlocon
);
1349 /* Propagate from internal cones */
1350 if (count
!= yagCountChains(ckprechlist
)) {
1351 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
1352 if (yagGetChain(ckprechlist
, ptcone
->NAME
) != NULL
) {
1353 for (ptout
= ptcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
1354 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1355 yagPropClockPrech(ptout
->UEDGE
.CONE
, ptcone
);
1360 /* Perform the unmarking */
1361 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
1362 ptcone
->TYPE
&= ~YAG_VISITED
;
1363 if ((ptcone
->TYPE
& YAG_MARK
) != YAG_MARK
&& (ptcone
->TYPE
& CNS_PRECHARGE
) == CNS_PRECHARGE
) {
1364 ptcone
->TYPE
&= ~CNS_PRECHARGE
;
1365 yagWarning(WAR_UNMARKED_PRECHARGE
, NULL
, ptcone
->NAME
, (char *)ptcone
->INDEX
, 0);
1367 ptcone
->TYPE
&= ~YAG_MARK
;
1370 freechain(ckprechlist
);
1374 yagPropClockPrech(cone_list
*ptcone
, void *ptprev
)
1376 edge_list
*ptout
, *ptin
;
1378 if ((ptcone
->TYPE
& YAG_VISITED
) == YAG_VISITED
) return;
1379 ptcone
->TYPE
|= YAG_VISITED
;
1380 if ((ptcone
->TYPE
& (CNS_FLIP_FLOP
|CNS_MEMSYM
)) != 0) return;
1381 if ((ptcone
->TYPE
& CNS_EXT
) == CNS_EXT
) {
1382 if ((ptcone
->TYPE
& CNS_TRI
) == CNS_TRI
1383 || (ptcone
->TYPE
& CNS_CONFLICT
) == CNS_CONFLICT
) {
1387 if ((ptcone
->TYPE
& CNS_LATCH
) == CNS_LATCH
) {
1388 for (ptin
= ptcone
->INCONE
; ptin
; ptin
= ptin
->NEXT
) {
1389 if (ptin
->UEDGE
.PTR
== ptprev
) break;
1391 if (ptin
!= NULL
&& (ptin
->TYPE
& CNS_COMMAND
) == CNS_COMMAND
) return;
1393 if ((ptcone
->TYPE
& CNS_PRECHARGE
) == CNS_PRECHARGE
) {
1394 for (ptin
= ptcone
->INCONE
; ptin
; ptin
= ptin
->NEXT
) {
1395 if (ptin
->UEDGE
.PTR
== ptprev
) break;
1397 if (ptin
!= NULL
&& (ptin
->TYPE
& YAG_PRECHCOM
) == YAG_PRECHCOM
) {
1398 ptcone
->TYPE
|= YAG_MARK
;
1402 for (ptout
= ptcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
1403 if ((ptout
->TYPE
& CNS_FEEDBACK
) == CNS_FEEDBACK
) continue;
1404 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1405 yagPropClockPrech(ptout
->UEDGE
.CONE
, ptcone
);
1409 /****************************************************************************
1410 * function yagPropagateStuck() *
1411 ****************************************************************************/
1414 yagPropagateStuck(cone_list
*ptcone
)
1417 cone_list
*ptnextcone
;
1418 int changes
= FALSE
;
1420 for (ptedge
= ptcone
->OUTCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
1421 if ((ptedge
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1422 ptnextcone
= ptedge
->UEDGE
.CONE
;
1423 if (yagGetEdge(ptnextcone
->INCONE
, ptcone
) == NULL
) continue;
1424 if (yagDetectStuck(ptnextcone
)) {
1426 yagPropagateStuck(ptnextcone
);
1433 yagDetectStuck(cone_list
*ptcone
)
1438 pNode upbdd
, dnbdd
, ptconstraintbdd
;
1439 cone_list
*ptincone
;
1440 locon_list
*ptinlocon
;
1441 chain_list
*ptupexpr
;
1442 chain_list
*ptdnexpr
;
1443 chain_list
*ptconstraint
;
1444 chain_list
*constraint_list
= NULL
;
1446 char freeup
= FALSE
, freedown
= FALSE
;
1448 avt_log(LOGYAG
, 2, "\tChecking stuck at cone '%s'\n", ptcone
->NAME
);
1449 if ((ptcone
->TECTYPE
& (CNS_ZERO
|CNS_ONE
)) != 0) return FALSE
;
1450 if ((ptcone
->TYPE
& YAG_PARTIAL
) != 0 && (ptcone
->TECTYPE
& CNS_DUAL_CMOS
) == 0) return FALSE
;
1451 if ((ptcone
->TYPE
& CNS_LATCH
) == 0 && (ptuser
= getptype(ptcone
->USER
, YAG_DUALEXPR_PTYPE
)) != NULL
) {
1452 ptupexpr
= (chain_list
*)ptuser
->DATA
;
1456 if ((ptuser
= getptype(ptcone
->USER
, CNS_UPEXPR
)) != NULL
) {
1457 ptupexpr
= (chain_list
*)ptuser
->DATA
;
1458 if (!ptupexpr
) ptupexpr
= createAtom("'0'"), freeup
=TRUE
;
1459 } else return FALSE
;
1460 if ((ptuser
= getptype(ptcone
->USER
, CNS_DNEXPR
)) != NULL
) {
1461 ptdnexpr
= (chain_list
*)ptuser
->DATA
;
1462 if (!ptdnexpr
) ptdnexpr
= createAtom("'0'"), freedown
=TRUE
;
1463 } else return FALSE
;
1466 circuit
= yagBuildDirectCct(ptcone
);
1467 upbdd
= ablToBddCct(circuit
, ptupexpr
);
1468 if (ptdnexpr
) dnbdd
= ablToBddCct(circuit
, ptdnexpr
);
1471 for (ptedge
= ptcone
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
1472 ptconstraint
= NULL
;
1473 if ((ptedge
->TYPE
& CNS_EXT
) == CNS_EXT
) {
1474 ptinlocon
= ptedge
->UEDGE
.LOCON
;
1475 ptuser
= getptype(ptinlocon
->USER
, CNS_TYPELOCON
);
1476 if (ptuser
== NULL
) continue;
1477 if (((long)ptuser
->DATA
& CNS_ZERO
) == CNS_ZERO
) {
1478 ptconstraint
= createAtom(ptinlocon
->NAME
);
1479 ptconstraintbdd
= notBdd(ablToBddCct(circuit
, ptconstraint
));
1481 else if (((long)ptuser
->DATA
& CNS_ONE
) == CNS_ONE
) {
1482 ptconstraint
= createAtom(ptinlocon
->NAME
);
1483 ptconstraintbdd
= ablToBddCct(circuit
, ptconstraint
);
1487 ptincone
= ptedge
->UEDGE
.CONE
;
1488 if ((ptincone
->TECTYPE
& CNS_ZERO
) == CNS_ZERO
) {
1489 ptconstraint
= createAtom(ptincone
->NAME
);
1490 ptconstraintbdd
= notBdd(ablToBddCct(circuit
, ptconstraint
));
1492 else if ((ptincone
->TECTYPE
& CNS_ONE
) == CNS_ONE
) {
1493 ptconstraint
= createAtom(ptincone
->NAME
);
1494 ptconstraintbdd
= ablToBddCct(circuit
, ptconstraint
);
1497 if (ptconstraint
!= NULL
) {
1498 constraint_list
= addchain(constraint_list
, ptconstraintbdd
);
1499 upbdd
= constraintBdd(upbdd
, ptconstraintbdd
);
1500 if (ptdnexpr
) dnbdd
= constraintBdd(dnbdd
, ptconstraintbdd
);
1501 freeExpr(ptconstraint
);
1505 if (upbdd
== BDD_one
&& (dnbdd
== BDD_zero
|| dnbdd
== NULL
)) {
1506 ptcone
->TECTYPE
|= CNS_ONE
;
1507 ptcone
->TYPE
|= YAG_FORCEPRIM
;
1508 avt_log(LOGYAG
, 2, "\t\tStuck ONE\n", ptcone
->NAME
);
1509 if (V_BOOL_TAB
[__YAGLE_ANALYSE_STUCK
].VALUE
) yagMarkStuck(ptcone
, circuit
, constraint_list
);
1511 else if (upbdd
== BDD_zero
&& (dnbdd
== BDD_one
|| dnbdd
== NULL
)) {
1512 ptcone
->TECTYPE
|= CNS_ZERO
;
1513 ptcone
->TYPE
|= YAG_FORCEPRIM
;
1514 avt_log(LOGYAG
, 2, "\t\tStuck ZERO\n", ptcone
->NAME
);
1515 if (V_BOOL_TAB
[__YAGLE_ANALYSE_STUCK
].VALUE
) yagMarkStuck(ptcone
, circuit
, constraint_list
);
1517 else if (YAG_CONTEXT
->YAG_STUCK_LATCH
&& (ptcone
->TYPE
& CNS_LATCH
) != 0 && dnbdd
!= NULL
) {
1518 if (upbdd
!= BDD_zero
&& dnbdd
== BDD_zero
) {
1519 ptcone
->TECTYPE
|= CNS_ONE
;
1520 ptcone
->TYPE
|= YAG_FORCEPRIM
;
1521 avt_log(LOGYAG
, 2, "\t\tLatch Stuck ONE\n", ptcone
->NAME
);
1522 if (V_BOOL_TAB
[__YAGLE_ANALYSE_STUCK
].VALUE
) yagMarkStuck(ptcone
, circuit
, constraint_list
);
1524 else if (upbdd
== BDD_zero
&& dnbdd
!= BDD_zero
) {
1525 ptcone
->TECTYPE
|= CNS_ZERO
;
1526 ptcone
->TYPE
|= YAG_FORCEPRIM
;
1527 avt_log(LOGYAG
, 2, "\t\tLatch Stuck ONE\n", ptcone
->NAME
);
1528 if (V_BOOL_TAB
[__YAGLE_ANALYSE_STUCK
].VALUE
) yagMarkStuck(ptcone
, circuit
, constraint_list
);
1530 else result
= FALSE
;
1532 else result
= FALSE
;
1534 if (result
== FALSE
&& constraint_list
!= NULL
&& V_BOOL_TAB
[__YAGLE_ANALYSE_STUCK
].VALUE
) {
1535 yagUpdateStuck(ptcone
, circuit
, constraint_list
);
1538 freechain(constraint_list
);
1539 destroyCct(circuit
);
1541 if (freeup
) freeExpr(ptupexpr
);
1542 if (freedown
) freeExpr(ptdnexpr
);
1548 yagMarkStuck(cone_list
*ptcone
, pCircuit circuit
, chain_list
*constraint_list
)
1550 branch_list
*ptbranch
;
1551 branch_list
*ptfalsebranch
;
1552 branch_list
*ptresbranch
;
1553 chain_list
*ptchain
;
1554 chain_list
*branch_expr
;
1559 if ((ptcone
->TECTYPE
& CNS_ONE
) == CNS_ONE
) {
1560 ptfalsebranch
= ptcone
->BRVSS
;
1561 ptresbranch
= ptcone
->BRVDD
;
1563 else if ((ptcone
->TECTYPE
& CNS_ZERO
) == CNS_ZERO
) {
1564 ptfalsebranch
= ptcone
->BRVDD
;
1565 ptresbranch
= ptcone
->BRVSS
;
1569 for (ptbranch
= ptfalsebranch
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1570 ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
1572 if (avt_islog(3,LOGYAG
) && YAG_CONTEXT
->YAG_DEBUG_CONE
== ptcone
->NAME
) {
1573 avt_log(LOGYAG
, 3, "\nAnalysing stuck cone structure :-\n\n");
1574 displayconelog(LOGYAG
, 3, ptcone
);
1576 avt_log(LOGYAG
, 3, "\t\tDetecting non-functional up/down branches\n");
1577 for (ptbranch
= ptresbranch
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1578 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) == CNS_NOT_FUNCTIONAL
) continue;
1579 if ((branch_expr
= cnsMakeBranchExpr(ptbranch
, CNS_COMMAND
, FALSE
)) == NULL
) continue;
1580 branch_bdd
= ablToBddCct(circuit
, branch_expr
);
1581 freeExpr(branch_expr
);
1582 for (ptchain
= constraint_list
; ptchain
; ptchain
= ptchain
->NEXT
) {
1583 branch_bdd
= constraintBdd(branch_bdd
, (pNode
)ptchain
->DATA
);
1585 if (branch_bdd
== BDD_zero
) ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
1587 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1588 if ((ptlink
->TYPE
& CNS_COMMAND
) == 0) ptlink
->TYPE
|= CNS_RESIST
;
1592 avt_log(LOGYAG
, 3, "\t\tDetecting non-functional external branches\n");
1593 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1594 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) == CNS_NOT_FUNCTIONAL
) continue;
1595 cnsMakeExtBranchExpr(ptbranch
, &ablXt
, CNS_COMMAND
, FALSE
);
1597 if ((branch_expr
= ablXt
.UP
) == NULL
) continue;
1598 branch_bdd
= ablToBddCct(circuit
, branch_expr
);
1599 freeExpr(branch_expr
);
1600 for (ptchain
= constraint_list
; ptchain
; ptchain
= ptchain
->NEXT
) {
1601 branch_bdd
= constraintBdd(branch_bdd
, (pNode
)ptchain
->DATA
);
1603 if (branch_bdd
== BDD_zero
) ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
1605 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1606 if ((ptlink
->TYPE
& CNS_COMMAND
) == 0) ptlink
->TYPE
|= CNS_RESIST
;
1613 yagUpdateStuck(cone_list
*ptcone
, pCircuit circuit
, chain_list
*constraint_list
)
1615 branch_list
*brlist
[3];
1616 branch_list
*ptbranch
;
1617 chain_list
*ptchain
;
1618 chain_list
*branch_expr
;
1620 cone_list
*ptlinkcone
;
1626 if (avt_islog(3,LOGYAG
) && YAG_CONTEXT
->YAG_DEBUG_CONE
== ptcone
->NAME
) {
1627 avt_log(LOGYAG
, 3, "\nUpdating cone structure from stuck inputs :-\n\n");
1628 displayconelog(LOGYAG
, 3, ptcone
);
1630 brlist
[0] = ptcone
->BRVDD
;
1631 brlist
[1] = ptcone
->BRVSS
;
1632 brlist
[2] = ptcone
->BREXT
;
1633 for (i
=0; i
<3; i
++) {
1634 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1635 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) == CNS_NOT_FUNCTIONAL
) continue;
1637 if ((branch_expr
= cnsMakeBranchExpr(ptbranch
, CNS_COMMAND
, FALSE
)) == NULL
) continue;
1640 cnsMakeExtBranchExpr(ptbranch
, &ablXt
, CNS_COMMAND
, FALSE
);
1642 if ((branch_expr
= ablXt
.UP
) == NULL
) continue;
1644 branch_bdd
= ablToBddCct(circuit
, branch_expr
);
1645 freeExpr(branch_expr
);
1646 for (ptchain
= constraint_list
; ptchain
; ptchain
= ptchain
->NEXT
) {
1647 branch_bdd
= constraintBdd(branch_bdd
, (pNode
)ptchain
->DATA
);
1649 if (branch_bdd
== BDD_zero
) ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
1651 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1652 if (i
== 2 && !ptlink
->NEXT
) break;
1653 ptuser
= getptype(ptlink
->ULINK
.LOTRS
->USER
, CNS_DRIVINGCONE
);
1654 if (ptuser
== NULL
|| ptuser
->DATA
== NULL
) continue;
1655 else ptlinkcone
= (cone_list
*)ptuser
->DATA
;
1656 if ((ptlink
->TYPE
& CNS_TNLINK
) == CNS_TNLINK
&& (ptlinkcone
->TECTYPE
& CNS_ONE
) == CNS_ONE
) {
1657 ptlink
->TYPE
|= CNS_RESIST
;
1659 else if ((ptlink
->TYPE
& CNS_TPLINK
) == CNS_TNLINK
&& (ptlinkcone
->TECTYPE
& CNS_ZERO
) == CNS_ZERO
) {
1660 ptlink
->TYPE
|= CNS_RESIST
;
1668 /****************************************************************************
1669 * function yagInfUnmarkLatches() *
1670 ****************************************************************************/
1673 yagInfUnmarkLatches(inffig_list
*ifl
, cnsfig_list
*ptcnsfig
)
1675 chain_list
*ptchain
, *ptnotlatchchain
;
1678 ptnotlatchchain
=inf_GetEntriesByType(ifl
, INF_NOTLATCH
, INF_ANY_VALUES
);
1679 if (ptnotlatchchain
!= NULL
) {
1680 for (ptcone
= ptcnsfig
->CONE
; ptcone
!= NULL
; ptcone
= ptcone
->NEXT
) {
1681 if ((ptcone
->TYPE
& CNS_LATCH
) != CNS_LATCH
) continue;
1682 for (ptchain
= ptnotlatchchain
; ptchain
; ptchain
= ptchain
->NEXT
) {
1683 if (mbk_TestREGEX(ptcone
->NAME
, (char *)ptchain
->DATA
)) {
1684 yagUnmarkLatch(ptcone
, TRUE
, TRUE
);
1689 freechain(ptnotlatchchain
);
1693 /****************************************************************************
1694 * function yagDetectClockGating() *
1695 ****************************************************************************/
1697 /* detect convergence between clock and non-clock paths */
1700 yagDetectClockGating(inffig_list
*ifl
, cnsfig_list
*ptcnsfig
)
1702 locon_list
*ptlocon
, *ptinlocon
;
1703 cone_list
*ptcone
, *ptincone
;
1704 cone_list
*ptextcone
;
1705 edge_list
*ptout
, *ptin
;
1706 chain_list
*ptchain
;
1708 chain_list
*clocklist
= NULL
;
1709 chain_list
*datalist
= NULL
;
1710 chain_list
*gateexpr
;
1712 int numclock
, numdata
, conditioned_state
, output_state
;
1714 clocklist
= inf_GetEntriesByType(ifl
, INF_CLOCK_TYPE
, INF_ANY_VALUES
);
1715 if (clocklist
== NULL
) return;
1717 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
1718 ptcone
->TYPE
&= ~YAG_MARK
;
1720 /* Propagate from input connectors */
1721 for (ptlocon
= ptcnsfig
->LOCON
; ptlocon
; ptlocon
= ptlocon
->NEXT
) {
1722 for (ptchain
= clocklist
; ptchain
; ptchain
= ptchain
->NEXT
) {
1723 if (mbk_TestREGEX(ptlocon
->NAME
, (char *)ptchain
->DATA
)) break;
1725 if (ptchain
!= NULL
) {
1726 ptuser
= getptype(ptlocon
->USER
, CNS_EXT
);
1727 if (ptuser
!= NULL
) {
1728 ptextcone
= (cone_list
*)ptuser
->DATA
;
1729 if ((ptextcone
->TECTYPE
& (CNS_ZERO
|CNS_ONE
)) != 0) continue;
1730 for (ptout
= ptextcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
1731 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1732 yagPropClockGating(ptout
->UEDGE
.CONE
, ptextcone
);
1735 ptuser
= getptype(ptlocon
->USER
, CNS_CONE
);
1736 if (ptuser
!= NULL
) {
1737 for (ptchain
= (chain_list
*)ptuser
->DATA
; ptchain
; ptchain
= ptchain
->NEXT
) {
1738 ptcone
= (cone_list
*)ptchain
->DATA
;
1739 if ((ptcone
->TECTYPE
& (CNS_ZERO
|CNS_ONE
)) != 0) continue;
1740 if (ptcone
!= ptextcone
) yagPropClockGating(ptcone
, ptlocon
);
1745 /* Propagate from internal cones */
1746 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
1747 if ((ptcone
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1748 if ((ptcone
->TECTYPE
& (CNS_ZERO
|CNS_ONE
)) != 0) continue;
1749 for (ptchain
= clocklist
; ptchain
; ptchain
= ptchain
->NEXT
) {
1750 if (mbk_TestREGEX(ptcone
->NAME
, (char *)ptchain
->DATA
)) break;
1752 if (ptchain
!= NULL
) {
1753 for (ptout
= ptcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
1754 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1755 yagPropClockGating(ptout
->UEDGE
.CONE
, ptcone
);
1759 /* add the clock gating check */
1760 for (ptcone
= ptcnsfig
->CONE
; ptcone
; ptcone
= ptcone
->NEXT
) {
1762 if ((ptcone
->TYPE
& YAG_MARK
) == YAG_MARK
) {
1763 ptcone
->TYPE
&= ~YAG_MARK
;
1764 if ((ptcone
->TECTYPE
& (CNS_ZERO
|CNS_ONE
)) != 0) continue;
1767 for (ptin
= ptcone
->INCONE
; ptin
; ptin
= ptin
->NEXT
) {
1768 if ((ptin
->TYPE
& YAG_MARK
) != YAG_MARK
) {
1769 ptin
->TYPE
&= ~YAG_MARK
;
1771 if ((ptin
->TYPE
& CNS_EXT
) == CNS_EXT
) {
1772 ptinlocon
= ptin
->UEDGE
.LOCON
;
1773 /* ignore external connector link */
1774 ptuser
= getptype(ptinlocon
->USER
, CNS_EXT
);
1775 if (ptuser
&& (cone_list
*)ptuser
->DATA
== ptcone
) continue;
1776 /* ignore stuck data */
1777 ptuser
= getptype(ptinlocon
->USER
, CNS_TYPELOCON
);
1778 if (ptuser
&& (((long)ptuser
->DATA
) & (CNS_ZERO
|CNS_ONE
)) != 0) continue;
1779 datalist
= addchain(datalist
, ptinlocon
->NAME
);
1782 ptincone
= ptin
->UEDGE
.CONE
;
1783 if ((ptincone
->TECTYPE
& (CNS_ZERO
|CNS_ONE
)) != 0) continue;
1784 datalist
= addchain(datalist
, ptincone
->NAME
);
1788 if ((ptin
->TYPE
& CNS_EXT
) == CNS_EXT
) clockname
= ptin
->UEDGE
.LOCON
->NAME
;
1789 else clockname
= ptin
->UEDGE
.CONE
->NAME
;
1793 if (numclock
== 1 && numdata
> 0 && (ptcone
->TYPE
& (CNS_CONFLICT
|CNS_TRI
)) == 0 && (ptcone
->TECTYPE
& (CNS_ONE
|CNS_ZERO
)) == 0) {
1794 if ((ptuser
= getptype(ptcone
->USER
, YAG_DUALEXPR_PTYPE
)) != NULL
) {
1795 gateexpr
= ptuser
->DATA
;
1797 else if ((ptuser
= getptype(ptcone
->USER
, CNS_UPEXPR
)) != NULL
) {
1798 gateexpr
= ptuser
->DATA
;
1801 conditioned_state
= yagDetectConditionedState(gateexpr
, clockname
, &output_state
);
1802 if (conditioned_state
>= 0) {
1803 if (YAG_CONTEXT
->YAG_CLOCK_GATE
& (short)0x1) {
1804 for (ptchain
= datalist
; ptchain
; ptchain
= ptchain
->NEXT
) {
1805 if (yagAddCheckDirective(ifl
, (char *)ptchain
->DATA
, clockname
, conditioned_state
)) {
1806 yagWarning(WAR_CLOCK_GATING
, (char *)ptchain
->DATA
, clockname
, NULL
, conditioned_state
);
1810 if (YAG_CONTEXT
->YAG_CLOCK_GATE
& (short)0x2) yagAddFilterDirective(ifl
, ptcone
->NAME
, output_state
);
1813 freechain(datalist
);
1817 freechain(clocklist
);
1818 yagEndAddCheckDirective();
1822 yagPropClockGating(cone_list
*ptcone
, void *ptprev
)
1824 edge_list
*ptout
, *ptin
;
1826 if ((ptcone
->TECTYPE
& (CNS_ZERO
|CNS_ONE
)) != 0) return;
1827 if ((ptcone
->TYPE
& (CNS_FLIP_FLOP
|CNS_MEMSYM
)) != 0) return;
1828 if ((ptcone
->TYPE
& (CNS_LATCH
|CNS_PRECHARGE
|CNS_RS
)) != 0) return;
1829 if ((ptcone
->TYPE
& CNS_EXT
) == CNS_EXT
) {
1830 if ((ptcone
->TYPE
& CNS_TRI
) == CNS_TRI
1831 || (ptcone
->TYPE
& CNS_CONFLICT
) == CNS_CONFLICT
) {
1835 for (ptin
= ptcone
->INCONE
; ptin
; ptin
= ptin
->NEXT
) {
1836 if (ptin
->UEDGE
.PTR
== ptprev
) ptin
->TYPE
|= YAG_MARK
;
1838 if ((ptcone
->TYPE
& YAG_MARK
) == YAG_MARK
) return;
1839 ptcone
->TYPE
|= YAG_MARK
;
1840 for (ptout
= ptcone
->OUTCONE
; ptout
; ptout
= ptout
->NEXT
) {
1841 if ((ptout
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1842 yagPropClockGating(ptout
->UEDGE
.CONE
, ptcone
);
1847 yagDetectConditionedState(chain_list
*gateexpr
, char *varname
, int *ptoutput_state
)
1850 chain_list
*ptsupport
;
1851 chain_list
*ptchain
;
1852 pNode var
, expr
, f0
, f1
, blocking_condition
, output_state
;
1855 ptsupport
= supportChain_listExpr(gateexpr
);
1856 circuit
= initializeCct("temp", yagCountChains(ptsupport
), 10);
1857 for (ptchain
= ptsupport
; ptchain
; ptchain
= ptchain
->NEXT
) {
1858 addInputCct_no_NA(circuit
, (char *)ptchain
->DATA
);
1861 index
= searchInputCct_no_NA(circuit
, varname
);
1862 if (index
<= 1) return -1;
1863 var
= createNodeTermBdd(index
);
1864 expr
= ablToBddCct(circuit
, gateexpr
);
1865 f1
= constraintBdd(expr
, var
);
1866 f0
= constraintBdd(expr
, notBdd(var
));
1868 blocking_condition
= notBdd(applyBinBdd(OR
, applyBinBdd(AND
, f0
, notBdd(f1
)), applyBinBdd(AND
, notBdd(f0
), f1
)));
1870 output_state
= constraintBdd(expr
, blocking_condition
);
1872 destroyCct(circuit
);
1873 freechain(ptsupport
);
1874 if (zeroBdd(output_state
)) {
1875 *ptoutput_state
= 1;
1876 if (zeroBdd(f0
) && !zeroBdd(f1
)) return 1;
1877 if (!zeroBdd(f0
) && zeroBdd(f1
)) return 0;
1879 else if (oneBdd(output_state
)) {
1880 *ptoutput_state
= 0;
1881 if (oneBdd(f0
) && !oneBdd(f1
)) return 1;
1882 if (!oneBdd(f0
) && oneBdd(f1
)) return 0;
1888 void yagDetectDelayedRS(cnsfig_list
*ptcnsfig
)
1890 cone_list
*ptcone1
, *ptdelaycone1
, *ptcone2
, *ptdelaycone2
, *ptinput
, *ptprevcone
;
1895 for (ptcone1
= ptcnsfig
->CONE
; ptcone1
; ptcone1
= ptcone1
->NEXT
) {
1897 if ((ptcone1
->TYPE
& CNS_RS
) == CNS_RS
) continue;
1898 if ((ptcone1
->TECTYPE
& CNS_DUAL_CMOS
) != CNS_DUAL_CMOS
) continue;
1899 if (yagCountConeEdges(ptcone1
->INCONE
) <= 1) continue;
1900 ptinput
= yagGetNextConeEdge(ptcone1
->INCONE
);
1901 if (!ptinput
) continue;
1902 if (yagMatchNAND(ptcone1
, ptinput
)) rstype
= CNS_NAND
;
1903 if (yagMatchNOR(ptcone1
, ptinput
)) rstype
= CNS_NOR
;
1904 if (rstype
== 0) continue;
1905 if (yagCountConeEdges(ptcone1
->OUTCONE
) != 1) continue;
1906 ptdelaycone1
= yagGetNextConeEdge(ptcone1
->OUTCONE
);
1907 ptprevcone
= ptcone1
;
1909 while (yagCountConeEdges(ptdelaycone1
->OUTCONE
) == 1 && (ptdelaycone1
->TECTYPE
& CNS_DUAL_CMOS
) == CNS_DUAL_CMOS
&& yagCountConeEdges(ptdelaycone1
->INCONE
) == 1) {
1910 ptprevcone
= ptdelaycone1
;
1911 ptdelaycone1
= yagGetNextConeEdge(ptdelaycone1
->OUTCONE
);
1914 if ((ptdelaycone1
->TECTYPE
& CNS_DUAL_CMOS
) != CNS_DUAL_CMOS
|| yagCountConeEdges(ptdelaycone1
->INCONE
) != 1) {
1915 ptdelaycone1
= ptprevcone
;
1918 if (numdelaycones
== 0 || numdelaycones
% 2 != 0) continue;
1919 for (ptedge
= ptdelaycone1
->OUTCONE
; ptedge
!= NULL
; ptedge
= ptedge
->NEXT
) {
1920 if ((ptedge
->TYPE
& CNS_EXT
) == CNS_EXT
) continue;
1921 ptcone2
= ptedge
->UEDGE
.CONE
;
1922 if (rstype
== CNS_NAND
) {
1923 if (!yagMatchNAND(ptcone2
, ptdelaycone1
)) continue;
1925 if (rstype
== CNS_NOR
) {
1926 if (!yagMatchNOR(ptcone2
, ptdelaycone1
)) continue;
1928 if (yagCountConeEdges(ptcone2
->OUTCONE
) != 1) continue;
1929 ptdelaycone2
= yagGetNextConeEdge(ptcone2
->OUTCONE
);
1930 ptprevcone
= ptcone2
;
1932 while (yagCountConeEdges(ptdelaycone2
->OUTCONE
) == 1 && (ptdelaycone2
->TECTYPE
& CNS_DUAL_CMOS
) == CNS_DUAL_CMOS
&& yagCountConeEdges(ptdelaycone2
->INCONE
) == 1) {
1933 ptprevcone
= ptdelaycone2
;
1934 ptdelaycone2
= yagGetNextConeEdge(ptdelaycone2
->OUTCONE
);
1937 if ((ptdelaycone2
->TECTYPE
& CNS_DUAL_CMOS
) != CNS_DUAL_CMOS
|| yagCountConeEdges(ptdelaycone2
->INCONE
) != 1) {
1938 ptdelaycone2
= ptprevcone
;
1941 if (numdelaycones
== 0 || numdelaycones
% 2 != 0) continue;
1942 if (yagGetEdge(ptcone1
->INCONE
, ptdelaycone2
) != NULL
) { /* found */
1943 yagDisableRSArcs(ptcone1
, ptcone2
, ptdelaycone1
, ptdelaycone2
, rstype
, YAG_RS_LEGAL
);
1944 yagWarning(WAR_DELAYED_RS
, ptcone1
->NAME
, ptcone2
->NAME
, NULL
, 0);
1945 ptcone1
->TYPE
|= CNS_RS
;
1946 ptcone2
->TYPE
|= CNS_RS
;
1947 ptcone1
->USER
= addptype(ptcone1
->USER
, YAG_BISTABLE_PTYPE
, ptcone2
);
1948 ptcone2
->USER
= addptype(ptcone2
->USER
, YAG_BISTABLE_PTYPE
, ptcone1
);