Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / yagle / yagle / yag_detect.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI Alliance */
4 /* */
5 /* Produit : YAGLE v3.50 */
6 /* Fichier : yag_detect.c */
7 /* */
8 /* (c) copyright 1994 Laboratoire MASI equipe CAO & VLSI */
9 /* Tous droits reserves */
10 /* Support : e-mail alliance-support@asim.lip6.fr */
11 /* */
12 /* Auteur(s) : Anthony LESTER le : ../../.... */
13 /* */
14 /* Modifie par : le : ../../.... */
15 /* Modifie par : le : ../../.... */
16 /* Modifie par : le : ../../.... */
17 /* */
18 /****************************************************************************/
19
20 #include "yag_headers.h"
21
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);
32
33 /****************************************************************************
34 * function yagDetectBadBranches() *
35 ****************************************************************************/
36
37 /* test for branches containing max. number of links */
38
39 void yagDetectBadBranches(cone_list *ptcone)
40 {
41 branch_list *brlist[4];
42 branch_list *ptbranch;
43 int i;
44
45 /* clean up from previous pass */
46 ptcone->TECTYPE &= ~YAG_BADCONE;
47
48 brlist[0] = ptcone->BRVDD;
49 brlist[1] = ptcone->BRVSS;
50 brlist[2] = ptcone->BREXT;
51 brlist[3] = ptcone->BRGND;
52
53 for (i=0; i<4; i++) {
54 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptbranch->NEXT) {
55 if (yagCountLinks(ptbranch->LINK) == YAG_CONTEXT->YAG_MAX_LINKS) {
56 ptcone->TECTYPE |= YAG_BADCONE;
57 }
58 }
59 }
60 }
61
62 /****************************************************************************
63 * function yagDetectParaTrans() *
64 ****************************************************************************/
65
66 /* test for parallel connected transistors */
67
68 void yagDetectParaTrans(cone_list *ptcone)
69 {
70 branch_list *brlist[4];
71 ptype_list *ptuser;
72 lotrs_list *pttrans;
73 branch_list *ptbranch;
74 link_list *ptlink;
75 chain_list *paralist = NULL;
76 int i;
77
78 /* clean up from previous pass */
79
80 ptuser = getptype(ptcone->USER, CNS_PARATRANS);
81 if (ptuser != NULL) {
82 freechain((chain_list *)ptuser->DATA);
83 ptcone->USER = delptype(ptcone->USER, CNS_PARATRANS);
84 }
85
86 brlist[0] = ptcone->BRVDD;
87 brlist[1] = ptcone->BRVSS;
88 brlist[2] = ptcone->BREXT;
89 brlist[3] = ptcone->BRGND;
90
91 for (i=0; i<4; i++) {
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);
99 }
100 }
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);
106 }
107 }
108 }
109 }
110 }
111 }
112 }
113 if (paralist != NULL) ptcone->USER = addptype(ptcone->USER, CNS_PARATRANS, paralist);
114 }
115
116 /****************************************************************************
117 * function yagAddSwitchInversion() *
118 ****************************************************************************/
119
120 void yagAddSwitchInversion(cnsfig_list *ptcnsfig)
121 {
122 lotrs_list *pttrans1, *pttrans2;
123 cone_list *ptcone1, *ptcone2;
124 chain_list *ptloconlist1, *ptloconlist2;
125 ptype_list *ptuser;
126
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;
135 }
136 else ptloconlist1 = NULL;
137 if ((ptuser = getptype(ptcone2->USER, CNS_EXT)) != NULL) {
138 ptloconlist2 = (chain_list *)ptuser->DATA;
139 }
140 else ptloconlist2 = NULL;
141 if (ptloconlist1 == NULL && ptloconlist2 == NULL) {
142 cnsAddConeInversion(ptcone1, ptcone2);
143 }
144 else if (ptloconlist1 == NULL && ptloconlist2 != NULL) {
145 cnsAddConeInversion(ptcone2, ptcone1);
146 }
147 else if (ptloconlist1 != NULL && ptloconlist2 == NULL) {
148 cnsAddConeInversion(ptcone1, ptcone2);
149 }
150 else { /* ptloconlist1 != NULL && ptloconlist2 != NULL */
151 cnsAddConeInversion(ptcone1, ptcone2);
152 }
153 }
154 }
155
156 /****************************************************************************
157 * function yagCorrectSwitch() *
158 ****************************************************************************/
159
160 /* Use the PMOS in VDD branch and NMOS in VSS branch */
161 /* For EXT , there is one NMOS branch, and one PMOS */
162
163 void yagCorrectSwitch(cone_list *ptcone)
164 {
165 branch_list *ptbranch;
166 link_list *ptlink;
167 lotrs_list *pttrans_n, *pttrans_p, *pttrans, *ptothertrans;
168 edge_list *ptedge, *ptotheredge;
169 ptype_list *ptuser;
170 chain_list *ptchain1, *ptchain2;
171 long inputtype;
172 int changed = FALSE;
173
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;
182 changed = TRUE;
183 }
184 }
185 }
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;
189 }
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);
196 }
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);
201 }
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;
209 changed = TRUE;
210 }
211 }
212 }
213 }
214 if (changed) yagChainCone(ptcone);
215
216 /* Check incone list to see that all switch inputs exist, add if necessary, and synchronise input markings */
217
218 ptuser = getptype(ptcone->USER, CNS_SWITCH);
219 if (ptuser) {
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);
230 }
231 else {
232 if (ptotheredge && (ptotheredge->TYPE & CNS_HZCOM) == CNS_HZCOM) ptedge->TYPE |= CNS_HZCOM;
233 }
234 }
235 }
236 }
237 }
238
239 /****************************************************************************
240 * function yagDetectSwitch() *
241 ****************************************************************************/
242
243 /* test for a CMOS switch but do not test for gate signal inversion */
244
245 void yagDetectSwitch(cone_list *ptcone)
246 {
247 branch_list *brlist[4];
248 ptype_list *ptuser;
249 chain_list *ptchain, *testchain = NULL;
250 lotrs_list *pttrans_n, *pttrans_p;
251 branch_list *ptbranch;
252 link_list *ptlink;
253 chain_list *switchpair, *switchlist = NULL;
254 int i;
255
256 /* clean up from previous pass */
257
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);
262 }
263 freechain((chain_list *)ptuser->DATA);
264 ptcone->USER = delptype(ptcone->USER, CNS_SWITCH);
265 }
266
267 brlist[0] = ptcone->BRVDD;
268 brlist[1] = ptcone->BRVSS;
269 brlist[2] = ptcone->BREXT;
270 brlist[3] = ptcone->BRGND;
271
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);
283 }
284 }
285 }
286 }
287 }
288 freechain(testchain);
289 if (switchlist) ptcone->USER = addptype(ptcone->USER, CNS_SWITCH, switchlist);
290 }
291
292 /****************************************************************************
293 * function yagDetectParallelBranches() *
294 ****************************************************************************/
295
296 /* test for branches which have identical inputs */
297
298 void
299 yagDetectParallelBranches(cone_list *ptcone)
300 {
301 branch_list *ptbranch;
302 chain_list *ptchain = NULL;
303 chain_list *ptchain0;
304 chain_list *sortedchain;
305 ptype_list *ptuser;
306
307 /* clean up from previous pass */
308
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);
313 }
314 freechain((chain_list *)ptuser->DATA);
315 ptcone->USER = delptype(ptcone->USER, CNS_PARALLEL);
316 }
317
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);
322 }
323 freechain(ptchain);
324 ptchain = NULL;
325 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
326 if ((ptbranch->TYPE & CNS_PARALLEL_INS) == CNS_PARALLEL_INS) {
327 yagDestroyBranch(ptcone, ptbranch);
328 }
329 else ptbranch->TYPE &= ~CNS_PARALLEL;
330 }
331 }
332
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);
337 }
338 freechain(ptchain);
339 ptchain = NULL;
340 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
341 if ((ptbranch->TYPE & CNS_PARALLEL_INS) == CNS_PARALLEL_INS) {
342 yagDestroyBranch(ptcone, ptbranch);
343 }
344 else ptbranch->TYPE &= ~CNS_PARALLEL;
345 }
346 }
347
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);
352 }
353 freechain(ptchain);
354 ptchain = NULL;
355 for (ptbranch = ptcone->BREXT; ptbranch; ptbranch = ptbranch->NEXT) {
356 if ((ptbranch->TYPE & CNS_PARALLEL_INS) == CNS_PARALLEL_INS) {
357 yagDestroyBranch(ptcone, ptbranch);
358 }
359 else ptbranch->TYPE &= ~CNS_PARALLEL;
360 }
361 }
362
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;
370 }
371
372 if (ptchain != NULL) {
373 ptcone->USER = addptype(ptcone->USER, CNS_PARALLEL, ptchain);
374 }
375 }
376
377 static int yagBranchCompare (const void *elem1, const void *elem2)
378 {
379 float res1, res2;
380
381 res1 = yagCalcBranchResistance(*(branch_list **)elem1);
382 res2 = yagCalcBranchResistance(*(branch_list **)elem2);
383
384 if (res1 < res2) return 1;
385 else if (res2 > res1) return -1;
386
387 return 0;
388 }
389
390
391 static chain_list *
392 yagSortBranches(chain_list *ptbranches)
393 {
394 branch_list **branchtable;
395 branch_list *ptbranch;
396 chain_list *ptchain;
397 chain_list *reschain = NULL;
398 int numbranches, i;
399
400 numbranches = yagCountChains(ptbranches);
401 branchtable = (branch_list **)mbkalloc(numbranches * sizeof(branch_list *));
402 i = 0;
403 for (ptchain = ptbranches; ptchain; ptchain = ptchain->NEXT) {
404 ptbranch = (branch_list *)ptchain->DATA;
405 branchtable[i++] = ptbranch;
406 }
407 qsort(branchtable, numbranches, sizeof(branch_list *), yagBranchCompare);
408 for (i = 0; i < numbranches; i++) reschain = addchain(reschain, branchtable[i]);
409
410 mbkfree(branchtable);
411 return reschain;
412 }
413
414 /****************************************************************************
415 * function yagDetectPullup() *
416 ****************************************************************************/
417
418 /* mark strongly resistive VDD branches (resistance > 10 x max. down resistance */
419
420 void yagDetectPullup(cone_list *ptcone)
421 {
422 branch_list *ptbranch;
423 link_list *ptlink;
424 float downres, branchres;
425 int donecalc = FALSE;
426
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;
430 }
431 if (ptlink != NULL) continue;
432 if (!donecalc) {
433 downres = yagCalcMaxDownRes(ptcone);
434 donecalc = TRUE;
435 }
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;
440 }
441 }
442 }
443
444 /****************************************************************************
445 * function yagDetectPulldown() *
446 ****************************************************************************/
447
448 /* mark strongly resistive VSS branches (resistance > 10 x max. up resistance */
449
450 void
451 yagDetectPulldown(cone_list *ptcone)
452 {
453 branch_list *ptbranch;
454 link_list *ptlink;
455 float upres, branchres;
456 int donecalc = FALSE;
457
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;
461 }
462 if (ptlink != NULL) continue;
463 if (!donecalc) {
464 upres = yagCalcMaxUpRes(ptcone);
465 donecalc = TRUE;
466 }
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;
471 }
472 }
473 }
474
475 /****************************************************************************
476 * function yagDetectLoop() *
477 ****************************************************************************/
478
479 void
480 yagDetectLoops(cone_list *ptcone)
481 {
482 edge_list *ptinput;
483 edge_list *ptloopin;
484 edge_list *ptoutput;
485 edge_list *ptloopout;
486 cone_list *ptincone;
487
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;
492 continue;
493 }
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;
507 }
508 }
509 }
510 }
511
512 int
513 yagCountLoops(cone_list *ptcone, int warning)
514 {
515 edge_list *ptinput;
516 edge_list *ptloopin;
517 edge_list *ptoutput;
518 edge_list *ptloopout;
519 cone_list *ptincone;
520 int numloops;
521
522 numloops = 0;
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;
528 continue;
529 }
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;
541 if (warning) {
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);
544 }
545 else yagWarning(WAR_UNKNOWN_LOOP, ptcone->NAME, ptincone->NAME, NULL, 0);
546 }
547 numloops++;
548 }
549 }
550 }
551 return numloops;
552 }
553
554 /****************************************************************************
555 * function yagDetectTransfer() *
556 ****************************************************************************/
557
558 /* test for transfer PTYPE on the cone transistors */
559
560 int
561 yagDetectTransfer(cone_list *ptcone)
562 {
563 lotrs_list *pttrans;
564 branch_list *brlist[4];
565 branch_list *ptbranch;
566 link_list *ptlink;
567 edge_list *ptedge;
568 ptype_list *ptuser;
569 chain_list *bleeders = NULL;
570 long fcltype;
571 int bleeder, not_func, feedback;
572 int done_bleeders;
573 int change_chain = FALSE;
574 int i;
575
576 if (getptype(ptcone->USER, CNS_BLEEDER) == NULL) done_bleeders = FALSE;
577 else done_bleeders = TRUE;
578
579 brlist[0] = ptcone->BRVDD;
580 brlist[1] = ptcone->BRVSS;
581 brlist[2] = ptcone->BREXT;
582 brlist[3] = ptcone->BRGND;
583
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;
587 bleeder = FALSE;
588 not_func = TRUE;
589 feedback = FALSE;
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;
597
598 if ((fcltype & FCL_BLEEDER) != 0) {
599 ptedge->TYPE |= CNS_BLEEDER;
600 bleeder = TRUE;
601 }
602 if ((fcltype & FCL_FEEDBACK) != 0) {
603 ptedge->TYPE |= CNS_FEEDBACK;
604 feedback = TRUE;
605 }
606 if ((fcltype & FCL_COMMAND) != 0) {
607 ptlink->TYPE |= CNS_COMMAND;
608 ptedge->TYPE |= CNS_COMMAND;
609 }
610 if ((fcltype & FCL_NOT_FUNCTIONAL) == 0)
611 not_func = FALSE;
612 if ((fcltype & FCL_SHORT) != 0) {
613 ptlink->TYPE |= CNS_SHORT;
614 ptlink->TYPE |= CNS_RESIST;
615 change_chain = TRUE;
616 }
617 }
618 else {
619 not_func = FALSE;
620 }
621 }
622 }
623 if (bleeder) {
624 ptbranch->TYPE |= CNS_BLEEDER|CNS_NOT_FUNCTIONAL;
625 if (!done_bleeders) bleeders = addchain(bleeders, ptbranch);
626 }
627 if (not_func) ptbranch->TYPE |= CNS_NOT_FUNCTIONAL;
628 if (feedback) ptbranch->TYPE |= CNS_FEEDBACK;
629 }
630 }
631 if (!done_bleeders && bleeders != NULL) {
632 ptcone->USER = addptype(ptcone->USER, CNS_BLEEDER, bleeders);
633 }
634 return change_chain;
635 }
636
637 /****************************************************************************
638 * function yagDetectDegraded() *
639 ****************************************************************************/
640
641 /* test for degraded branches */
642
643 void
644 yagDetectDegraded(cone_list *ptcone)
645 {
646 branch_list *ptbranch;
647 branch_list *brlist[4];
648 link_list *ptlink;
649 long branchtype;
650 long linktype;
651 int i;
652 int has_degraded_vdd = FALSE, has_degraded_vss = FALSE;
653 int bleeder_up = FALSE, bleeder_down = FALSE;
654
655 brlist[0] = ptcone->BRVDD;
656 brlist[1] = ptcone->BRVSS;
657 brlist[2] = ptcone->BREXT;
658 brlist[3] = ptcone->BRGND;
659
660 ptcone->TECTYPE &= ~(CNS_VDD_DEGRADED|CNS_VSS_DEGRADED);
661 ptcone->TECTYPE &= ~(CNS_CMOS);
662
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;
669 }
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;
674
675 linktype = ptlink->TYPE & (CNS_TNLINK|CNS_TPLINK|CNS_IN|CNS_INOUT);
676
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;
681 }
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;
685 }
686 }
687 }
688 }
689 }
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;
693 }
694 if ((ptcone->TECTYPE & (CNS_VDD_DEGRADED|CNS_VSS_DEGRADED)) == 0) {
695 ptcone->TECTYPE |= CNS_CMOS;
696 }
697 }
698
699 /****************************************************************************
700 * Functions to update FALSECONF status *
701 ****************************************************************************/
702
703 int yagDetectFalseConf(cone_list *ptcone)
704 {
705 branch_list *ptbranch;
706 branch_list *brlist[4];
707 losig_list *ptconesig;
708 int i, changed = FALSE;
709
710 if ((ptcone->TYPE & YAG_FALSECONF) == 0) return 0;
711 ptconesig = (losig_list *)getptype(ptcone->USER, CNS_SIGNAL)->DATA;
712 ptcone->TYPE &= ~YAG_FALSECONF;
713
714 brlist[0] = ptcone->BRVDD;
715 brlist[1] = ptcone->BRVSS;
716 brlist[2] = ptcone->BREXT;
717 brlist[3] = ptcone->BRGND;
718
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;
724 }
725 else changed = TRUE;
726 }
727 }
728 }
729 return changed;
730 }
731
732 int
733 yagCheckFalseConfBranch(branch_list *ptbranch, losig_list *ptfirstsig)
734 {
735 link_list *ptlink;
736 losig_list *ptlastsig, *ptnextsig;
737 cone_list *ptsigcone;
738 ptype_list *ptuser;
739
740 ptbranch->TYPE &= ~YAG_FALSECONF;
741 ptlastsig = ptfirstsig;
742
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;
747 }
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;
753 }
754 }
755 if (ptlink != NULL) {
756 ptbranch->TYPE |= YAG_FALSECONF;
757 return TRUE;
758 }
759 return FALSE;
760 }
761
762 void
763 yagDetectLoopConf(cone_list *ptcone)
764 {
765 edge_list *ptedgelist0, *ptedgelist1;
766 edge_list *ptedge0, *ptedge1;
767 cone_list *ptincone;
768
769 ptcone->TYPE &= ~YAG_LOOPCONF;
770
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;
779 }
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;
786 break;
787 }
788 }
789 }
790
791 /****************************************************************************
792 * function yagRemoveRedundantBranches() *
793 ****************************************************************************/
794
795 /* test for redundant branches */
796
797 void
798 yagRemoveRedundantBranches(cone_list *ptcone)
799 {
800 branch_list *ptbranch;
801 branch_list *ptnextbranch;
802 branch_list *brlist[4];
803 int changes = FALSE;
804 int i;
805
806 brlist[0] = ptcone->BRVDD;
807 brlist[1] = ptcone->BRVSS;
808 brlist[2] = ptcone->BREXT;
809 brlist[3] = ptcone->BRGND;
810
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;
814
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);
820 changes = TRUE;
821 }
822 }
823 }
824 if (changes) {
825 yagChainCone(ptcone);
826 yagDetectParallelBranches(ptcone);
827 yagDetectSwitch(ptcone);
828 yagDetectDegraded(ptcone);
829 ptcone->TECTYPE |= CNS_DUAL_CMOS;
830 }
831 }
832
833 /****************************************************************************
834 * function yagTransferParallel() *
835 ****************************************************************************/
836
837 /* test for transfer PTYPE on parallel transistors */
838 /* (to be called before parallel restoration) */
839
840 void
841 yagTransferParallel(lofig_list *ptlofig)
842 {
843 long transtype;
844 lotrs_list *ptlotrs, *ptparatrans;
845 ptype_list *ptuser;
846 chain_list *transchain, *ptchain;
847
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);
858 }
859 else ptparatrans->USER = addptype(ptparatrans->USER, FCL_TRANSFER_PTYPE, (void *)transtype);
860 }
861 }
862 }
863 }
864 }
865
866 /****************************************************************************
867 * function yagDetectGlitcher() *
868 ****************************************************************************/
869
870 /* detect two transistor branches which serve no purpose */
871 /* unless considered to be dynamically active */
872
873 static int
874 unconnectedcommon(lotrs_list *pttrans1, lotrs_list *pttrans2)
875 {
876 losig_list *ptcommonsig = NULL;
877 chain_list *loconchain;
878
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;
883 if (ptcommonsig) {
884 loconchain = (chain_list *)getptype(ptcommonsig->USER, LOFIGCHAIN)->DATA;
885 if (yagCountChains(loconchain) == 2) return TRUE;
886 }
887 return FALSE;
888 }
889
890 int
891 yagDetectGlitcher(branch_list *ptbranch, lotrs_list *pttrans, int mark)
892 {
893 lotrs_list *ptprevtrans;
894 cone_list *ptcone;
895 link_list *ptlink;
896 int numlinks;
897
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;
904 }
905 else {
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;
912 }
913 }
914 if (!unconnectedcommon(pttrans, ptprevtrans)) return FALSE;
915
916 if (mark) {
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;
921 }
922 return TRUE;
923 }
924
925 /****************************************************************************
926 * function yagDetectClockLatch() *
927 ****************************************************************************/
928
929 /* unmark latches with no command on a clock path */
930
931 void
932 yagDetectClockLatch(inffig_list *ifl, cnsfig_list *ptcnsfig)
933 {
934 locon_list *ptlocon;
935 cone_list *ptcone;
936 cone_list *ptextcone;
937 edge_list *ptout;
938 chain_list *ptchain;
939 ptype_list *ptuser;
940 int real_latch;
941 int count;
942 chain_list *cklatchlist = NULL;
943
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));
947 }
948 else if ((cklatchlist = inf_GetEntriesByType(ifl, INF_CKLATCH, INF_YES))==NULL) return;
949
950 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
951 ptcone->TYPE &= ~YAG_MARK;
952 }
953 count = 0;
954 /* Propagate from input connectors */
955 for (ptlocon = ptcnsfig->LOCON; ptlocon; ptlocon = ptlocon->NEXT) {
956 if (yagGetChain(cklatchlist, ptlocon->NAME) != NULL) {
957 count++;
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);
963 }
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);
969 }
970 }
971 }
972 }
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);
980 }
981 }
982 }
983 }
984 /* Perform the unmarking */
985 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
986 real_latch = FALSE;
987 ptcone->TYPE &= ~YAG_VISITED;
988 if ((ptcone->TYPE & YAG_MARK) == YAG_MARK) {
989 real_latch = TRUE;
990 ptcone->TYPE &= ~YAG_MARK;
991 }
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) {
996 continue;
997 }
998 }
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);
1002 }
1003 else if (YAG_CONTEXT->YAG_STRICT_CKLATCH && real_latch && (ptcone->TYPE & CNS_LATCH) == CNS_LATCH) {
1004 yagUnmarkCommands(ptcone);
1005 }
1006 }
1007
1008 freechain(cklatchlist);
1009 }
1010
1011 static void
1012 yagPropClockLatch(cone_list *ptcone, void *ptprev)
1013 {
1014 edge_list *ptout, *ptin;
1015
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) {
1020 return;
1021 }
1022 }
1023 if ((ptcone->TYPE & CNS_LATCH) == CNS_LATCH) {
1024 for (ptin = ptcone->INCONE; ptin; ptin = ptin->NEXT) {
1025 if (ptin->UEDGE.PTR == ptprev) break;
1026 }
1027 if (ptin != NULL && (ptin->TYPE & CNS_COMMAND) != CNS_COMMAND) {
1028 /* PROPAGATE THROUGH */
1029 }
1030 else {
1031 ptin->TYPE |= YAG_MARK;
1032 ptcone->TYPE |= YAG_MARK;
1033 return;
1034 }
1035 }
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);
1042 }
1043 }
1044
1045 void
1046 yagUnmarkLatch(cone_list *ptcone, int cutloop, int warn)
1047 {
1048 branch_list *brlist[3];
1049 branch_list *ptbranch;
1050 link_list *ptlink;
1051 edge_list *ptinedge;
1052 cone_list *ptloopcone;
1053 chain_list *new_bleeders = NULL;
1054 ptype_list *ptuser;
1055 int i;
1056
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);
1063 }
1064 }
1065
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);
1072 }
1073 cutloop = FALSE;
1074 }
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);
1077
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;
1086 }
1087 }
1088
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;
1098 }
1099 if ((ptbranch->TYPE & CNS_FEEDBACK) == CNS_FEEDBACK) {
1100 ptbranch->TYPE &= ~CNS_FEEDBACK;
1101 ptbranch->TYPE &= ~CNS_NOTCONFLICTUAL;
1102 if (cutloop) {
1103 ptbranch->TYPE |= CNS_BLEEDER;
1104 new_bleeders = addchain(new_bleeders, ptbranch);
1105 }
1106 else ptbranch->TYPE &= ~CNS_NOT_FUNCTIONAL;
1107 }
1108 ptbranch->TYPE &= ~YAG_ASYNC;
1109 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1110 ptlink->TYPE &= ~CNS_COMMAND;
1111 ptlink->TYPE &= ~CNS_ASYNCLINK;
1112 }
1113 }
1114 }
1115 if (new_bleeders != NULL) {
1116 ptuser = getptype(ptcone->USER, CNS_BLEEDER);
1117 if (ptuser != NULL) {
1118 ptuser->DATA = append(ptuser->DATA, new_bleeders);
1119 }
1120 else ptcone->USER = addptype(ptcone->USER, CNS_BLEEDER, (void *)new_bleeders);
1121 }
1122 if (!new_bleeders && (ptcone->TECTYPE & YAG_LEVELHOLD) != 0) {
1123 ptuser = getptype(ptcone->USER, CNS_BLEEDER);
1124 if (ptuser) {
1125 freechain((chain_list *)ptuser->DATA);
1126 ptcone->USER = delptype(ptcone->USER, CNS_BLEEDER);
1127 }
1128 }
1129 /* remove stuck for latches but not LHs */
1130 if ((ptcone->TECTYPE & YAG_LEVELHOLD) == 0) {
1131 ptcone->TECTYPE &= ~(CNS_ONE|CNS_ZERO);
1132 }
1133 ptcone->TECTYPE &= ~YAG_LEVELHOLD;
1134 if (warn) yagWarning(WAR_UNMARKEDLATCH_LOOP, NULL, ptcone->NAME, (char *)ptcone->INDEX, 0);
1135 }
1136
1137 static void
1138 yagUnmarkCommands(cone_list *ptcone)
1139 {
1140 cone_list *ptdrivingcone;
1141 branch_list *brlist[3];
1142 branch_list *ptbranch;
1143 link_list *ptlink;
1144 edge_list *ptinedge;
1145 ptype_list *ptuser;
1146 int i;
1147
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;
1162 }
1163 }
1164 }
1165 }
1166 }
1167
1168 for (ptinedge = ptcone->INCONE; ptinedge; ptinedge = ptinedge->NEXT) {
1169 if ((ptinedge->TYPE & YAG_MARK) == 0) {
1170 ptinedge->TYPE &= ~CNS_COMMAND;
1171 }
1172 else {
1173 ptinedge->TYPE &= ~YAG_MARK;
1174 }
1175 }
1176 }
1177
1178 /****************************************************************************
1179 * function yagDetectNotClockLatch() *
1180 ****************************************************************************/
1181
1182 /* unmark latch commands on a not-clock path */
1183
1184 void
1185 yagDetectNotClockLatch(inffig_list *ifl, cnsfig_list *ptcnsfig)
1186 {
1187 locon_list *ptlocon;
1188 cone_list *ptcone;
1189 cone_list *ptextcone;
1190 edge_list *ptout;
1191 chain_list *ptchain;
1192 ptype_list *ptuser;
1193 int count;
1194 chain_list *notcklatchlist;
1195
1196 if ((notcklatchlist=inf_GetEntriesByType(ifl, INF_CKLATCH, INF_NO))==NULL) return;
1197
1198 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
1199 ptcone->TYPE &= ~YAG_MARK;
1200 }
1201 count = 0;
1202 /* Propagate from input connectors */
1203 for (ptlocon = ptcnsfig->LOCON; ptlocon; ptlocon = ptlocon->NEXT) {
1204 if (yagGetChain(notcklatchlist, ptlocon->NAME) != NULL) {
1205 count++;
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);
1211 }
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);
1217 }
1218 }
1219 }
1220 }
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);
1228 }
1229 }
1230 }
1231 }
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);
1238 }
1239 }
1240
1241 freechain(notcklatchlist);
1242 }
1243
1244 static void
1245 yagPropNotClockLatch(cone_list *ptcone)
1246 {
1247 edge_list *ptout;
1248
1249 if ((ptcone->TYPE & CNS_EXT) == CNS_EXT) {
1250 if ((ptcone->TYPE & CNS_TRI) == CNS_TRI
1251 || (ptcone->TYPE & CNS_CONFLICT) == CNS_CONFLICT) {
1252 return;
1253 }
1254 }
1255 if ((ptcone->TYPE & (CNS_LATCH|CNS_FLIP_FLOP|CNS_MEMSYM|CNS_MASTER|CNS_SLAVE)) != 0) {
1256 ptcone->TYPE |= YAG_MARK;
1257 return;
1258 }
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);
1264 }
1265 }
1266
1267 static void
1268 yagUnmarkNotCommands(cone_list *ptcone)
1269 {
1270 cone_list *ptdrivingcone;
1271 branch_list *brlist[3];
1272 branch_list *ptbranch;
1273 link_list *ptlink;
1274 edge_list *ptinedge;
1275 ptype_list *ptuser;
1276 int i;
1277
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;
1292 }
1293 }
1294 }
1295 }
1296 }
1297
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;
1302 }
1303 }
1304 }
1305
1306 /****************************************************************************
1307 * function yagDetectClockPrecharge() *
1308 ****************************************************************************/
1309
1310 /* unmark any precharge whose clock is not a precharge clock path */
1311
1312 void
1313 yagDetectClockPrech(inffig_list *ifl, cnsfig_list *ptcnsfig)
1314 {
1315 locon_list *ptlocon;
1316 cone_list *ptcone;
1317 cone_list *ptextcone;
1318 edge_list *ptout;
1319 chain_list *ptchain;
1320 ptype_list *ptuser;
1321 int count;
1322 chain_list *ckprechlist;
1323
1324 if ((ckprechlist=inf_GetEntriesByType(ifl, INF_CKPRECH, INF_ANY_VALUES))==NULL) return;
1325
1326 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
1327 ptcone->TYPE &= ~YAG_MARK;
1328 }
1329 count = 0;
1330 /* Propagate from input connectors */
1331 for (ptlocon = ptcnsfig->LOCON; ptlocon; ptlocon = ptlocon->NEXT) {
1332 if (yagGetChain(ckprechlist, ptlocon->NAME) != NULL) {
1333 count++;
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);
1339 }
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);
1345 }
1346 }
1347 }
1348 }
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);
1356 }
1357 }
1358 }
1359 }
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);
1366 }
1367 ptcone->TYPE &= ~YAG_MARK;
1368 }
1369
1370 freechain(ckprechlist);
1371 }
1372
1373 static void
1374 yagPropClockPrech(cone_list *ptcone, void *ptprev)
1375 {
1376 edge_list *ptout, *ptin;
1377
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) {
1384 return;
1385 }
1386 }
1387 if ((ptcone->TYPE & CNS_LATCH) == CNS_LATCH) {
1388 for (ptin = ptcone->INCONE; ptin; ptin = ptin->NEXT) {
1389 if (ptin->UEDGE.PTR == ptprev) break;
1390 }
1391 if (ptin != NULL && (ptin->TYPE & CNS_COMMAND) == CNS_COMMAND) return;
1392 }
1393 if ((ptcone->TYPE & CNS_PRECHARGE) == CNS_PRECHARGE) {
1394 for (ptin = ptcone->INCONE; ptin; ptin = ptin->NEXT) {
1395 if (ptin->UEDGE.PTR == ptprev) break;
1396 }
1397 if (ptin != NULL && (ptin->TYPE & YAG_PRECHCOM) == YAG_PRECHCOM) {
1398 ptcone->TYPE |= YAG_MARK;
1399 return;
1400 }
1401 }
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);
1406 }
1407 }
1408
1409 /****************************************************************************
1410 * function yagPropagateStuck() *
1411 ****************************************************************************/
1412
1413 int
1414 yagPropagateStuck(cone_list *ptcone)
1415 {
1416 edge_list *ptedge;
1417 cone_list *ptnextcone;
1418 int changes = FALSE;
1419
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)) {
1425 changes = TRUE;
1426 yagPropagateStuck(ptnextcone);
1427 }
1428 }
1429 return changes;
1430 }
1431
1432 int
1433 yagDetectStuck(cone_list *ptcone)
1434 {
1435 edge_list *ptedge;
1436 pCircuit circuit;
1437 ptype_list *ptuser;
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;
1445 int result = TRUE;
1446 char freeup = FALSE, freedown = FALSE;
1447
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;
1453 ptdnexpr = NULL;
1454 }
1455 else {
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;
1464 }
1465
1466 circuit = yagBuildDirectCct(ptcone);
1467 upbdd = ablToBddCct(circuit, ptupexpr);
1468 if (ptdnexpr) dnbdd = ablToBddCct(circuit, ptdnexpr);
1469 else dnbdd = NULL;
1470
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));
1480 }
1481 else if (((long)ptuser->DATA & CNS_ONE) == CNS_ONE) {
1482 ptconstraint = createAtom(ptinlocon->NAME);
1483 ptconstraintbdd = ablToBddCct(circuit, ptconstraint);
1484 }
1485 }
1486 else {
1487 ptincone = ptedge->UEDGE.CONE;
1488 if ((ptincone->TECTYPE & CNS_ZERO) == CNS_ZERO) {
1489 ptconstraint = createAtom(ptincone->NAME);
1490 ptconstraintbdd = notBdd(ablToBddCct(circuit, ptconstraint));
1491 }
1492 else if ((ptincone->TECTYPE & CNS_ONE) == CNS_ONE) {
1493 ptconstraint = createAtom(ptincone->NAME);
1494 ptconstraintbdd = ablToBddCct(circuit, ptconstraint);
1495 }
1496 }
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);
1502 }
1503 }
1504
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);
1510 }
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);
1516 }
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);
1523 }
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);
1529 }
1530 else result = FALSE;
1531 }
1532 else result = FALSE;
1533
1534 if (result == FALSE && constraint_list != NULL && V_BOOL_TAB[__YAGLE_ANALYSE_STUCK].VALUE) {
1535 yagUpdateStuck(ptcone, circuit, constraint_list);
1536 }
1537
1538 freechain(constraint_list);
1539 destroyCct(circuit);
1540
1541 if (freeup) freeExpr(ptupexpr);
1542 if (freedown) freeExpr(ptdnexpr);
1543
1544 return result;
1545 }
1546
1547 static void
1548 yagMarkStuck(cone_list *ptcone, pCircuit circuit, chain_list *constraint_list)
1549 {
1550 branch_list *ptbranch;
1551 branch_list *ptfalsebranch;
1552 branch_list *ptresbranch;
1553 chain_list *ptchain;
1554 chain_list *branch_expr;
1555 link_list *ptlink;
1556 abl_pair ablXt;
1557 pNode branch_bdd;
1558
1559 if ((ptcone->TECTYPE & CNS_ONE) == CNS_ONE) {
1560 ptfalsebranch = ptcone->BRVSS;
1561 ptresbranch = ptcone->BRVDD;
1562 }
1563 else if ((ptcone->TECTYPE & CNS_ZERO) == CNS_ZERO) {
1564 ptfalsebranch = ptcone->BRVDD;
1565 ptresbranch = ptcone->BRVSS;
1566 }
1567 else return;
1568
1569 for (ptbranch = ptfalsebranch; ptbranch; ptbranch = ptbranch->NEXT) {
1570 ptbranch->TYPE |= CNS_NOT_FUNCTIONAL;
1571 }
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);
1575 }
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);
1584 }
1585 if (branch_bdd == BDD_zero) ptbranch->TYPE |= CNS_NOT_FUNCTIONAL;
1586 else {
1587 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1588 if ((ptlink->TYPE & CNS_COMMAND) == 0) ptlink->TYPE |= CNS_RESIST;
1589 }
1590 }
1591 }
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);
1596 freeExpr(ablXt.DN);
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);
1602 }
1603 if (branch_bdd == BDD_zero) ptbranch->TYPE |= CNS_NOT_FUNCTIONAL;
1604 else {
1605 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1606 if ((ptlink->TYPE & CNS_COMMAND) == 0) ptlink->TYPE |= CNS_RESIST;
1607 }
1608 }
1609 }
1610 }
1611
1612 static void
1613 yagUpdateStuck(cone_list *ptcone, pCircuit circuit, chain_list *constraint_list)
1614 {
1615 branch_list *brlist[3];
1616 branch_list *ptbranch;
1617 chain_list *ptchain;
1618 chain_list *branch_expr;
1619 link_list *ptlink;
1620 cone_list *ptlinkcone;
1621 ptype_list *ptuser;
1622 abl_pair ablXt;
1623 pNode branch_bdd;
1624 int i;
1625
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);
1629 }
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;
1636 if (i != 2) {
1637 if ((branch_expr = cnsMakeBranchExpr(ptbranch, CNS_COMMAND, FALSE)) == NULL) continue;
1638 }
1639 else {
1640 cnsMakeExtBranchExpr(ptbranch, &ablXt, CNS_COMMAND, FALSE);
1641 freeExpr(ablXt.DN);
1642 if ((branch_expr = ablXt.UP) == NULL) continue;
1643 }
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);
1648 }
1649 if (branch_bdd == BDD_zero) ptbranch->TYPE |= CNS_NOT_FUNCTIONAL;
1650 else {
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;
1658 }
1659 else if ((ptlink->TYPE & CNS_TPLINK) == CNS_TNLINK && (ptlinkcone->TECTYPE & CNS_ZERO) == CNS_ZERO) {
1660 ptlink->TYPE |= CNS_RESIST;
1661 }
1662 }
1663 }
1664 }
1665 }
1666 }
1667
1668 /****************************************************************************
1669 * function yagInfUnmarkLatches() *
1670 ****************************************************************************/
1671
1672 void
1673 yagInfUnmarkLatches(inffig_list *ifl, cnsfig_list *ptcnsfig)
1674 {
1675 chain_list *ptchain, *ptnotlatchchain;
1676 cone_list *ptcone;
1677
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);
1685 break;
1686 }
1687 }
1688 }
1689 freechain(ptnotlatchchain);
1690 }
1691 }
1692
1693 /****************************************************************************
1694 * function yagDetectClockGating() *
1695 ****************************************************************************/
1696
1697 /* detect convergence between clock and non-clock paths */
1698
1699 void
1700 yagDetectClockGating(inffig_list *ifl, cnsfig_list *ptcnsfig)
1701 {
1702 locon_list *ptlocon, *ptinlocon;
1703 cone_list *ptcone, *ptincone;
1704 cone_list *ptextcone;
1705 edge_list *ptout, *ptin;
1706 chain_list *ptchain;
1707 ptype_list *ptuser;
1708 chain_list *clocklist = NULL;
1709 chain_list *datalist = NULL;
1710 chain_list *gateexpr;
1711 char *clockname;
1712 int numclock, numdata, conditioned_state, output_state;
1713
1714 clocklist = inf_GetEntriesByType(ifl, INF_CLOCK_TYPE, INF_ANY_VALUES);
1715 if (clocklist == NULL) return;
1716
1717 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
1718 ptcone->TYPE &= ~YAG_MARK;
1719 }
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;
1724 }
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);
1733 }
1734 }
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);
1741 }
1742 }
1743 }
1744 }
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;
1751 }
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);
1756 }
1757 }
1758 }
1759 /* add the clock gating check */
1760 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
1761 datalist = NULL;
1762 if ((ptcone->TYPE & YAG_MARK) == YAG_MARK) {
1763 ptcone->TYPE &= ~YAG_MARK;
1764 if ((ptcone->TECTYPE & (CNS_ZERO|CNS_ONE)) != 0) continue;
1765 numclock = 0;
1766 numdata = 0;
1767 for (ptin = ptcone->INCONE; ptin; ptin = ptin->NEXT) {
1768 if ((ptin->TYPE & YAG_MARK) != YAG_MARK) {
1769 ptin->TYPE &= ~YAG_MARK;
1770 numdata++;
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);
1780 }
1781 else {
1782 ptincone = ptin->UEDGE.CONE;
1783 if ((ptincone->TECTYPE & (CNS_ZERO|CNS_ONE)) != 0) continue;
1784 datalist = addchain(datalist, ptincone->NAME);
1785 }
1786 }
1787 else {
1788 if ((ptin->TYPE & CNS_EXT) == CNS_EXT) clockname = ptin->UEDGE.LOCON->NAME;
1789 else clockname = ptin->UEDGE.CONE->NAME;
1790 numclock++;
1791 }
1792 }
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;
1796 }
1797 else if ((ptuser = getptype(ptcone->USER, CNS_UPEXPR)) != NULL) {
1798 gateexpr = ptuser->DATA;
1799 }
1800 else continue;
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);
1807 }
1808 }
1809 }
1810 if (YAG_CONTEXT->YAG_CLOCK_GATE & (short)0x2) yagAddFilterDirective(ifl, ptcone->NAME, output_state);
1811 }
1812 }
1813 freechain(datalist);
1814 }
1815 }
1816
1817 freechain(clocklist);
1818 yagEndAddCheckDirective();
1819 }
1820
1821 static void
1822 yagPropClockGating(cone_list *ptcone, void *ptprev)
1823 {
1824 edge_list *ptout, *ptin;
1825
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) {
1832 return;
1833 }
1834 }
1835 for (ptin = ptcone->INCONE; ptin; ptin = ptin->NEXT) {
1836 if (ptin->UEDGE.PTR == ptprev) ptin->TYPE |= YAG_MARK;
1837 }
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);
1843 }
1844 }
1845
1846 static int
1847 yagDetectConditionedState(chain_list *gateexpr, char *varname, int *ptoutput_state)
1848 {
1849 pCircuit circuit;
1850 chain_list *ptsupport;
1851 chain_list *ptchain;
1852 pNode var, expr, f0, f1, blocking_condition, output_state;
1853 int index;
1854
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);
1859 }
1860
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));
1867
1868 blocking_condition = notBdd(applyBinBdd(OR, applyBinBdd(AND, f0, notBdd(f1)), applyBinBdd(AND, notBdd(f0), f1)));
1869
1870 output_state = constraintBdd(expr, blocking_condition);
1871
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;
1878 }
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;
1883 }
1884
1885 return -1;
1886 }
1887
1888 void yagDetectDelayedRS(cnsfig_list *ptcnsfig)
1889 {
1890 cone_list *ptcone1, *ptdelaycone1, *ptcone2, *ptdelaycone2, *ptinput, *ptprevcone;
1891 edge_list *ptedge;
1892 long rstype;
1893 int numdelaycones;
1894
1895 for (ptcone1 = ptcnsfig->CONE; ptcone1; ptcone1 = ptcone1->NEXT) {
1896 rstype = 0;
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;
1908 numdelaycones = 1;
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);
1912 numdelaycones++;
1913 }
1914 if ((ptdelaycone1->TECTYPE & CNS_DUAL_CMOS) != CNS_DUAL_CMOS || yagCountConeEdges(ptdelaycone1->INCONE) != 1) {
1915 ptdelaycone1 = ptprevcone;
1916 numdelaycones--;
1917 }
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;
1924 }
1925 if (rstype == CNS_NOR) {
1926 if (!yagMatchNOR(ptcone2, ptdelaycone1)) continue;
1927 }
1928 if (yagCountConeEdges(ptcone2->OUTCONE) != 1) continue;
1929 ptdelaycone2 = yagGetNextConeEdge(ptcone2->OUTCONE);
1930 ptprevcone = ptcone2;
1931 numdelaycones = 1;
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);
1935 numdelaycones++;
1936 }
1937 if ((ptdelaycone2->TECTYPE & CNS_DUAL_CMOS) != CNS_DUAL_CMOS || yagCountConeEdges(ptdelaycone2->INCONE) != 1) {
1938 ptdelaycone2 = ptprevcone;
1939 numdelaycones--;
1940 }
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);
1949 }
1950 }
1951 }
1952 }