Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / yagle / yagle / yag_analyse.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI Alliance */
4 /* */
5 /* Produit : YAGLE v3.50 */
6 /* Fichier : yag_analyse.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 : 10/06/1994 */
13 /* */
14 /* Modifie par : le : ../../.... */
15 /* Modifie par : le : ../../.... */
16 /* Modifie par : le : ../../.... */
17 /* */
18 /****************************************************************************/
19
20 #include "yag_headers.h"
21
22 static jmp_buf abandon_analyse;
23
24 static int get_opinion(void);
25 static chain_list *add_node_bdd(chain_list *bddlist, gnode_list *ptnode);
26 static void build_circuit(branch_list *ptbranch, jmp_buf abandon_env);
27 static pNode extend_circuit(cone_list *ptcone, long type, jmp_buf abandon_env);
28 static void add_mutex_pair(chain_list **ptmutex, char *name1, char *name2);
29 static void check_cone(cone_list *ptcone);
30 static void yagCheckGlobalDuality (cone_list *ptcone);
31 static void check_big_cone(cone_list *ptcone, gnode_list *rootnode);
32 static ht *order(branch_list *ptbranchlist, table *ptnames);
33 static void clean_precharge_marks(cone_list *ptcone, cone_list *ptloopcone);
34
35 jmp_buf *yagAbandonAnalyse()
36 {
37 return &abandon_analyse;
38 }
39
40 int
41 yagCheckAddTransLink(branch_list *ptbranch, lotrs_list *pttrans)
42 {
43 cone_list *ptcone;
44 long nodetype;
45 pNode bdd;
46 int result, transblocked = FALSE;
47
48 if (!YAG_CONTEXT->YAG_USE_FCF) return YAG_YES;
49
50 /* recreate support graph and circuit if nonexistent */
51
52 if (YAG_CONTEXT->YAG_SUPPORT_GRAPH == NULL) {
53 YAG_CONTEXT->YAG_SUPPORT_GRAPH = yagNewGraph();
54 YAG_CONTEXT->YAG_SUPPORT_GRAPH->COMPLETE = TRUE;
55 build_circuit(ptbranch, *yagAbandonGrow());
56 }
57
58 /* extend support graph and circuit */
59 ptcone = (cone_list *)pttrans->GRID;
60 nodetype = ((pttrans->TYPE & CNS_TN) == CNS_TN ? TN_NODE : TP_NODE);
61
62 if (YAG_CONTEXT->YAG_DEBUG_CONE == YAG_CONTEXT->YAG_CURCIRCUIT->name) {
63 avt_log(LOGYAG, 3, "Try to add transistor '%s' type %ld driven by '%s'\n", (pttrans->TRNAME != NULL) ? pttrans->TRNAME : "", nodetype, ptcone->NAME);
64 }
65
66 if ((bdd = extend_circuit(ptcone, nodetype, *yagAbandonGrow())) == NULL) return YAG_NO;
67
68 /* detect constants to mark resistive links */
69 if ((bdd == BDD_one && nodetype == TN_NODE) || (bdd == BDD_zero && nodetype == TP_NODE)) {
70 pttrans->TYPE |= RESIST;
71 }
72
73 if ((bdd == BDD_one && nodetype == TP_NODE) || (bdd == BDD_zero && nodetype == TN_NODE)) {
74 if (avt_islog(3,LOGYAG) && YAG_CONTEXT->YAG_DEBUG_CONE == YAG_CONTEXT->YAG_CURCIRCUIT->name) {
75 avt_log(LOGYAG, 3, "\tTransistor blocked\n");
76 }
77 result = YAG_NO;
78 transblocked = TRUE;
79 }
80 else result = get_opinion();
81
82 if (avt_islog(3,LOGYAG) && YAG_CONTEXT->YAG_DEBUG_CONE == YAG_CONTEXT->YAG_CURCIRCUIT->name) {
83 if (result == YAG_NO) avt_log(LOGYAG, 3, "\tNO\n");
84 else avt_log(LOGYAG, 3, "\tYES\n");
85 }
86 if (!transblocked && result == YAG_NO && V_INT_TAB[__YAGLE_KEEP_GLITCHERS].VALUE && yagDetectGlitcher(ptbranch, pttrans, TRUE)) {
87 yagWarning(WAR_GLITCHER, YAG_CONTEXT->YAG_CURCIRCUIT->name, NULL, NULL, 0);
88 return YAG_YES;
89 }
90
91 return result;
92 }
93
94 int
95 yagRemoveFalseBranches(cone_list *ptcone)
96 {
97 branch_list *brlist[4];
98 branch_list *ptbranch, *ptnextbranch;
99 long savetype, typemask;
100 int changed, redo, conflictual, destroy;
101 int i;
102 short save_depth;
103
104 if ((ptcone->TECTYPE & CNS_DUAL_CMOS) == CNS_DUAL_CMOS) return FALSE;
105 if (yagCheckBranches(ptcone) == FALSE) return FALSE;
106
107 brlist[0] = ptcone->BRVDD;
108 brlist[1] = ptcone->BRVSS;
109 brlist[2] = ptcone->BREXT;
110 brlist[3] = ptcone->BRGND;
111
112 avt_log(LOGYAG, 1, "Attempting to clean cone '%s'\n", ptcone->NAME);
113
114 /* To handle a return from BDD explosion */
115 save_depth = YAG_CONTEXT->YAG_DEPTH;
116 setBddCeiling(YAG_CONTEXT->YAG_BDDCEILING);
117 if (setjmp(abandon_analyse) != 0) {
118 yagDeleteConeGraph(YAG_CONTEXT->YAG_CONE_GRAPH);
119 YAG_CONTEXT->YAG_DEPTH--;
120 if (YAG_CONTEXT->YAG_DEPTH == 0) unsetBddCeiling();
121 }
122
123 YAG_CONTEXT->YAG_CONE_GRAPH = yagMakeConeGraph(ptcone);
124
125 typemask = CNS_CONFLICT|CNS_TRI|CNS_MEMSYM;
126 savetype = ptcone->TYPE & typemask;
127 conflictual = ((ptcone->TYPE & CNS_CONFLICT) == CNS_CONFLICT);
128 changed = FALSE;
129
130 for (i=0; i<4; i++) {
131 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptnextbranch) {
132 ptnextbranch = ptbranch->NEXT;
133 if ((ptbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
134 if (i==2 && ptbranch->LINK->NEXT == NULL) continue;
135 destroy = zeroBdd(yagCalcBranchConductance(ptbranch));
136 if (destroy && V_INT_TAB[__YAGLE_KEEP_GLITCHERS].VALUE && yagDetectGlitcher(ptbranch, NULL, TRUE)) {
137 yagWarning(WAR_GLITCHER, YAG_CONTEXT->YAG_CURCIRCUIT->name, NULL, NULL, 0);
138 destroy = FALSE;
139 }
140 if (destroy) {
141 yagDestroyBranch(ptcone, ptbranch);
142 changed = TRUE;
143 }
144 }
145 }
146
147 unsetBddCeiling();
148
149 if ((ptcone->TYPE & YAG_AUTOLATCH) != 0) {
150 /* yagUnmarkLatch(ptcone, FALSE, FALSE);*/
151 if (YAG_CONTEXT->YAG_CONE_GRAPH) yagDeleteConeGraph(YAG_CONTEXT->YAG_CONE_GRAPH);
152 YAG_CONTEXT->YAG_CONE_GRAPH = NULL;
153 redo = TRUE;
154 }
155 else redo = FALSE;
156
157 /* re-verify the cone */
158 if (conflictual || changed || redo) {
159 yagChainCone(ptcone);
160 yagAnalyseCone(ptcone);
161 }
162 if ((ptcone->TYPE & typemask) != savetype) {
163 changed = TRUE;
164 }
165
166 if (YAG_CONTEXT->YAG_CONE_GRAPH) yagDeleteConeGraph(YAG_CONTEXT->YAG_CONE_GRAPH);
167 YAG_CONTEXT->YAG_CONE_GRAPH = NULL;
168
169 YAG_CONTEXT->YAG_DEPTH = save_depth;
170
171 return changed;
172 }
173
174 int
175 yagDetectDualGlitcherBranches(cone_list *ptcone)
176 {
177 branch_list *brlist[2];
178 branch_list *ptbranch, *ptnextbranch;
179 long savetype, typemask;
180 int changed, redo, conflictual, destroy;
181 int i;
182 short save_depth;
183 int setup = FALSE, ret=FALSE;
184
185 if ((ptcone->TECTYPE & CNS_DUAL_CMOS) != CNS_DUAL_CMOS) return FALSE;
186 if (yagCheckBranches(ptcone) == FALSE) return FALSE;
187
188 brlist[0] = ptcone->BRVDD;
189 brlist[1] = ptcone->BRVSS;
190
191 avt_log(LOGYAG, 1, "Detecting glitchers on dual cone '%s'\n", ptcone->NAME);
192
193 /* To handle a return from BDD explosion */
194 save_depth = YAG_CONTEXT->YAG_DEPTH;
195 setBddCeiling(YAG_CONTEXT->YAG_BDDCEILING);
196 if (setjmp(abandon_analyse) != 0) {
197 yagDeleteConeGraph(YAG_CONTEXT->YAG_CONE_GRAPH);
198 YAG_CONTEXT->YAG_DEPTH--;
199 if (YAG_CONTEXT->YAG_DEPTH == 0) unsetBddCeiling();
200 setup = FALSE;
201 }
202
203 YAG_CONTEXT->YAG_CONE_GRAPH = yagMakeConeGraph(ptcone);
204
205 for (i=0; i<2; i++) {
206 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptnextbranch) {
207 ptnextbranch = ptbranch->NEXT;
208 if ((ptbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
209 destroy = zeroBdd(yagCalcBranchConductance(ptbranch));
210 if (yagDetectGlitcher(ptbranch, NULL, FALSE)) {
211 if (!setup) {
212 yagDeleteConeGraph(YAG_CONTEXT->YAG_CONE_GRAPH);
213 YAG_CONTEXT->YAG_CONE_GRAPH = yagMakeConeGraph(ptcone);
214 setup = TRUE;
215 }
216 if (zeroBdd(yagCalcBranchConductance(ptbranch)) && yagDetectGlitcher(ptbranch, NULL, TRUE)) {
217 yagWarning(WAR_GLITCHER, YAG_CONTEXT->YAG_CURCIRCUIT->name, NULL, NULL, 0);
218 ret=TRUE;
219 }
220 }
221 }
222 }
223
224 unsetBddCeiling();
225
226 if (YAG_CONTEXT->YAG_CONE_GRAPH) yagDeleteConeGraph(YAG_CONTEXT->YAG_CONE_GRAPH);
227 YAG_CONTEXT->YAG_CONE_GRAPH = NULL;
228
229 YAG_CONTEXT->YAG_DEPTH = save_depth;
230 return ret;
231 }
232
233 pNode
234 yagCalcBranchConductance(branch_list *ptbranch)
235 {
236 cone_list *ptcone;
237 gnode_list *node;
238 ptype_list *root;
239 chain_list *bddlist = NULL;
240 pNode bdd, conductance;
241 char *name;
242 int negate;
243
244 /* recreate support graph and circuit */
245
246 YAG_CONTEXT->YAG_SUPPORT_GRAPH = yagNewGraph();
247 YAG_CONTEXT->YAG_SUPPORT_GRAPH->COMPLETE = TRUE;
248 build_circuit(ptbranch, abandon_analyse);
249
250 for (root = YAG_CONTEXT->YAG_SUPPORT_GRAPH->ROOTNODES; root; root = root->NEXT) {
251
252 node = (gnode_list *)root->DATA;
253 ptcone = node->OBJECT.CONE;
254 negate = (ptcone->TYPE & CNS_TRI) != 0 && (root->TYPE == TP_NODE);
255 if (negate) {
256 name = yagDownName(ptcone->NAME);
257 }
258 else name = ptcone->NAME;
259
260 if ((bdd = searchOutputCct_no_NA(YAG_CONTEXT->YAG_CURCIRCUIT, name)) == NULL) {
261 yagBug(DBG_NO_BDD, "yagCalcBranchConductance", YAG_CONTEXT->YAG_CURCIRCUIT->name, name, 0);
262 continue;
263 }
264 /* invert bdd for P type transistor */
265 if (root->TYPE == TP_NODE) bdd = yagNotBdd(bdd, abandon_analyse);
266
267 bddlist = addchain(bddlist, (void *)bdd);
268 }
269 if (bddlist == NULL) conductance = BDD_one;
270 else if (bddlist->NEXT == NULL) conductance = (pNode)bddlist->DATA;
271 else conductance = yagApplyBdd(AND, bddlist, abandon_analyse);
272 if (zeroBdd(conductance)) {
273 yagFreeGraph(YAG_CONTEXT->YAG_SUPPORT_GRAPH);
274 YAG_CONTEXT->YAG_SUPPORT_GRAPH = NULL;
275 freechain(bddlist);
276 return conductance;
277 }
278
279 /* apply the contraints */
280 conductance = yagApplyConstraints(conductance, yagAbandonAnalyse());
281
282 freechain(bddlist);
283 yagFreeGraph(YAG_CONTEXT->YAG_SUPPORT_GRAPH);
284 YAG_CONTEXT->YAG_SUPPORT_GRAPH = NULL;
285
286 return conductance;
287 }
288
289 int
290 yagCheckAddExtLink(cone_list *ptcone, locon_list *ptcon, cone_list *ptrootcone)
291 {
292 int result;
293
294 if (YAG_CONTEXT->YAG_DEBUG_CONE == YAG_CONTEXT->YAG_CURCIRCUIT->name) {
295 avt_log(LOGYAG, 1, "Try to add connector link '%s'\n", ptcon->NAME);
296 }
297
298 /* if ((ptrootcone->TECTYPE & CNS_DUAL_CMOS) == CNS_DUAL_CMOS) {
299 result = YAG_NO;
300 }
301 else*/ if (ptcone == NULL) result = YAG_YES;
302 else {
303 if ((ptcone->TECTYPE & CNS_DUAL_CMOS) == CNS_DUAL_CMOS) {
304 result = YAG_NO;
305 }
306 else result = YAG_YES;
307 }
308
309 if (YAG_CONTEXT->YAG_DEBUG_CONE == YAG_CONTEXT->YAG_CURCIRCUIT->name) {
310 if (result == YAG_NO) avt_log(LOGYAG, 3, "\tNO\n");
311 else avt_log(LOGYAG, 3, "\tYES\n");
312 }
313
314 return result;
315 }
316
317 static int
318 get_opinion()
319 {
320 gnode_list *ptnewnode, *ptfather, *ptson;
321 chain_list *ptchain1, *ptchain2;
322 ptype_list *ptlist;
323 chain_list *bddlist = NULL;
324 pNode conductance;
325 static int called = 0;
326
327 called++;
328
329 for (ptlist = YAG_CONTEXT->YAG_SUPPORT_GRAPH->ROOTNODES; ptlist; ptlist = ptlist->NEXT) {
330 ((gnode_list *)ptlist->DATA)->VISITED = FALSE;
331 }
332
333 /* build list of BDDs for correlated outputs */
334
335 ptnewnode = (gnode_list *)YAG_CONTEXT->YAG_SUPPORT_GRAPH->ROOTNODES->DATA;
336 bddlist = add_node_bdd(bddlist, ptnewnode);
337 ptnewnode->VISITED = TRUE;
338
339 for (ptchain1 = ptnewnode->FATHERS; ptchain1; ptchain1 = ptchain1->NEXT) {
340 ptfather = (gnode_list *)ptchain1->DATA;
341 for (ptchain2 = ptfather->SONS; ptchain2; ptchain2 = ptchain2->NEXT) {
342 ptson = (gnode_list *)ptchain2->DATA;
343 if (!ptson->VISITED) {
344 bddlist = add_node_bdd(bddlist, ptson);
345 ptson->VISITED = TRUE;
346 }
347 }
348 }
349
350 /* verify the conduction function of the branch */
351
352 if (bddlist->NEXT == NULL) conductance = (pNode)bddlist->DATA;
353 else conductance = yagApplyBdd(AND, bddlist, *yagAbandonGrow());
354 freechain(bddlist);
355 if (zeroBdd(conductance)) return YAG_NO;
356
357 /* apply the contraints */
358 conductance = yagApplyConstraints(conductance, yagAbandonGrow());
359
360 if (!zeroBdd(conductance)) return YAG_YES;
361 else return YAG_NO;
362 }
363
364 static chain_list *
365 add_node_bdd(chain_list *bddlist, gnode_list *ptnode)
366 {
367 cone_list *ptcone;
368 char *name;
369 pNode bdd;
370 int negate;
371
372 ptcone = ptnode->OBJECT.CONE;
373 negate = FALSE;
374 name = ptcone->NAME;
375 if ((ptnode->TYPE & TP_NODE) != 0) {
376 if ((ptcone->TYPE & CNS_TRI) != 0) name = yagDownName(ptcone->NAME);
377 else negate = TRUE;
378 }
379
380 bdd = searchOutputCct_no_NA(YAG_CONTEXT->YAG_CURCIRCUIT, name);
381 if (negate) bdd = yagNotBdd(bdd, *yagAbandonGrow());
382 return(addchain(bddlist, bdd));
383 }
384
385 graph *
386 yagMakeConeGraph(cone_list *ptcone)
387 {
388 graph *ptgraph;
389 edge_list *inedgelist;
390 chain_list *ptchain;
391 list_list *varlist;
392 gnode_list *ptnode;
393 ptype_list *ptuser;
394 char *name;
395 int numinputs, numoutputs;
396
397 if ((ptcone->TYPE & YAG_PARTIAL) != 0 && (ptuser = getptype(ptcone->USER, YAG_INPUTS_PTYPE))) {
398 inedgelist = (edge_list *)ptuser->DATA;
399 }
400 else inedgelist = ptcone->INCONE;
401 ptgraph = yagBuildGraph(inedgelist, ptcone, FALSE);
402
403 yagTraverseGraph(ptgraph);
404
405 if (YAG_CONTEXT->YAG_CONSTRAINT_LIST) {
406 for (ptchain = yagGetConstraint(YAG_CONTEXT->YAG_CONSTRAINT_LIST->NEXT); ptchain; ptchain = yagGetConstraint(ptchain)) {
407 varlist = (list_list *)ptchain->DATA;
408 ptgraph->CONSTRAINTS = addptype(ptgraph->CONSTRAINTS, (long)varlist->SUPDATA, (void *)varlist->USER);
409 ptchain = ptchain->NEXT;
410 }
411 }
412
413 yagAddExtraConstraints(ptgraph);
414
415 /* initialise circuit for analysis */
416 numinputs = yagCountChains(ptgraph->PRIMVARS);
417 numoutputs = ptgraph->WIDTH;
418 YAG_CONTEXT->YAG_CURCIRCUIT = initializeCct(ptcone->NAME, numinputs, numoutputs);
419
420 /* add primary variables to circuit input list */
421 for (ptchain = ptgraph->PRIMVARS; ptchain; ptchain = ptchain->NEXT) {
422 ptnode = (gnode_list *)ptchain->DATA;
423 if ((ptnode->TYPE & CONE_TYPE) != 0) {
424 name = ptnode->OBJECT.CONE->NAME;
425 }
426 else {
427 /* node is an external connector */
428 name = ptnode->OBJECT.LOCON->NAME;
429 }
430 addInputCct_no_NA(YAG_CONTEXT->YAG_CURCIRCUIT, name);
431 }
432
433 return ptgraph;
434 }
435
436 void
437 yagDeleteConeGraph(graph *ptgraph)
438 {
439 yagFreeGraph(ptgraph);
440
441 /* destroy the circuit */
442 destroyCct(YAG_CONTEXT->YAG_CURCIRCUIT);
443 YAG_CONTEXT->YAG_CURCIRCUIT = NULL;
444 }
445
446 static void
447 build_circuit(branch_list *ptbranch, jmp_buf abandon_env)
448 {
449 link_list *ptlink;
450 lotrs_list *pttrans;
451 cone_list *ptcone;
452 pNode bdd;
453 long nodetype;
454
455 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
456 if ((ptlink->TYPE & (CNS_IN|CNS_INOUT)) != 0) break;
457 pttrans = ptlink->ULINK.LOTRS;
458 if ((pttrans->TYPE & DIODE) != 0) continue;
459 ptcone = (cone_list *)pttrans->GRID;
460 nodetype = ((pttrans->TYPE & CNS_TN) == CNS_TN ? TN_NODE : TP_NODE);
461 bdd = extend_circuit(ptcone, nodetype, abandon_env);
462
463 /* detect constants to mark resistive links */
464 if ((bdd == BDD_one && nodetype == TN_NODE) || (bdd == BDD_zero && nodetype == TP_NODE)) {
465 pttrans->TYPE |= RESIST;
466 ptlink->TYPE |= CNS_RESIST;
467 }
468 }
469 }
470
471 static pNode
472 extend_circuit(cone_list *ptcone, long type, jmp_buf abandon_env)
473 {
474 chain_list *expr, *tempexpr;
475 chain_list *support;
476 gnode_list *ptsupportnode, *ptnode;
477 char *name;
478 pNode bdd;
479 int negate;
480 int complete, existbdd;
481
482 negate = (ptcone->TYPE & CNS_TRI) != 0 && type == TP_NODE;
483 if (negate) {
484 name = yagDownName(ptcone->NAME);
485 }
486 else name = ptcone->NAME;
487
488 complete = yagExtendSupportRoot(YAG_CONTEXT->YAG_SUPPORT_GRAPH, ptcone, type);
489 ptsupportnode = (gnode_list *)YAG_CONTEXT->YAG_SUPPORT_GRAPH->ROOTNODES->DATA;
490 if (complete) {
491 if ((ptsupportnode->TYPE & (TN_NODE|TP_NODE)) == (TN_NODE|TP_NODE)) {
492 return NULL;
493 }
494 }
495
496 ptnode = (gnode_list *)gethtitem(YAG_CONTEXT->YAG_CONE_GRAPH->HASHTAB, ptcone);
497 if (ptnode == (gnode_list *)EMPTYHT) {
498 yagBug(DBG_NO_GRAPHNODE, "extend_circuit", ptcone->NAME, NULL, 0);
499 return NULL;
500 }
501
502 bdd = searchOutputCct_no_NA(YAG_CONTEXT->YAG_CURCIRCUIT, name);
503 existbdd = (bdd != NULL);
504
505 if (existbdd) {
506 support = yagGetPrimVars(YAG_CONTEXT->YAG_CONE_GRAPH, ptnode);
507 }
508 else {
509 tempexpr = createAtom_no_NA(name);
510 expr = yagExpandExpr(ptnode, tempexpr, negate);
511 freeExpr(tempexpr);
512 bdd = yagAblToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, expr, abandon_env);
513 addOutputCct_no_NA(YAG_CONTEXT->YAG_CURCIRCUIT, name, bdd);
514 freeExpr(expr);
515 support = yagGetPrimVars(YAG_CONTEXT->YAG_CONE_GRAPH, ptnode);
516 }
517 yagExtendSupportGraph(YAG_CONTEXT->YAG_SUPPORT_GRAPH, ptsupportnode, support);
518
519 if (support != NULL) freechain(support);
520
521 return bdd;
522 }
523
524 chain_list *
525 yagGuessMutex(cnsfig_list *ptcnsfig)
526 {
527 cone_list *ptcone, *ptincone;
528 locon_list *ptlocon;
529 branch_list *brlist[4];
530 branch_list *ptbranch;
531 link_list *ptlink;
532 lotrs_list *pttrans;
533 gnode_list *ptnode, *ptsupportnode;
534 chain_list *support, *ptchain;
535 char *candidate[3];
536 long nodetype;
537 int linkcount, i;
538 chain_list *guess_mutex = NULL;
539
540 /* Mark all latches and connectors constrained */
541 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
542 if ((ptcone->TYPE & (CNS_LATCH|CNS_MEMSYM|CNS_EXT)) != 0) ptcone->TYPE |= YAG_CONSTRAINT;
543 }
544 for (ptlocon = ptcnsfig->LOCON; ptlocon; ptlocon = ptlocon->NEXT) {
545 if (getptype(ptlocon->USER, YAG_CONSTRAINT_PTYPE) == NULL) {
546 ptlocon->USER = addptype(ptlocon->USER, YAG_CONSTRAINT_PTYPE, NULL);
547 }
548 }
549
550 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
551 if ((ptcone->TECTYPE & YAG_BADCONE) == 0) continue;
552 brlist[0] = ptcone->BRVDD;
553 brlist[1] = ptcone->BRVSS;
554 brlist[2] = ptcone->BREXT;
555 brlist[3] = ptcone->BRGND;
556
557 avt_log(LOGYAG, 1, "MUTEX guessing on cone '%s'\n", ptcone->NAME);
558 YAG_CONTEXT->YAG_CONE_GRAPH = yagMakeConeGraph(ptcone);
559
560 /* Try to find MUTEX candidate pair in 2nd and 3rd link of bad branch (on fail try 1st and 2nd if not latch) */
561 for (i=0; i<4; i++) {
562 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptbranch->NEXT) {
563 if (yagCountLinks(ptbranch->LINK) < YAG_CONTEXT->YAG_MAX_LINKS) continue;
564 YAG_CONTEXT->YAG_SUPPORT_GRAPH = yagNewGraph();
565 YAG_CONTEXT->YAG_SUPPORT_GRAPH->COMPLETE = TRUE;
566 linkcount = 0;
567 candidate[0] = NULL; candidate[1] = NULL; candidate[2] = NULL;
568 for (ptlink = ptbranch->LINK; ptlink && linkcount < 3; ptlink = ptlink->NEXT) {
569 if ((ptlink->TYPE & (CNS_IN|CNS_INOUT)) != 0) break;
570 pttrans = ptlink->ULINK.LOTRS;
571 if ((pttrans->TYPE & DIODE) != 0) continue;
572 ptincone = (cone_list *)pttrans->GRID;
573 nodetype = ((pttrans->TYPE & CNS_TN) == CNS_TN ? TN_NODE : TP_NODE);
574 yagExtendSupportRoot(YAG_CONTEXT->YAG_SUPPORT_GRAPH, ptincone, nodetype);
575 ptsupportnode = (gnode_list *)YAG_CONTEXT->YAG_SUPPORT_GRAPH->ROOTNODES->DATA;
576 ptnode = (gnode_list *)gethtitem(YAG_CONTEXT->YAG_CONE_GRAPH->HASHTAB, ptincone);
577 support = yagGetJustPrimVars(YAG_CONTEXT->YAG_CONE_GRAPH, ptnode);
578 yagExtendSupportGraph(YAG_CONTEXT->YAG_SUPPORT_GRAPH, ptsupportnode, support);
579 if ((ptcone->TYPE & (CNS_LATCH|CNS_MEMSYM)) != 0 && linkcount == 0) continue;
580 for (ptchain = support; ptchain; ptchain = ptchain->NEXT) {
581 ptnode = (gnode_list *)ptchain->DATA;
582 if ((ptnode->TYPE & CONSTRAINT_NODE) != 0) {
583 if (!candidate[linkcount]) {
584 if ((ptnode->TYPE & EXT) != 0) {
585 candidate[linkcount] = ptnode->OBJECT.LOCON->NAME;
586 }
587 else candidate[linkcount] = ptnode->OBJECT.CONE->NAME;
588 }
589 else {
590 candidate[linkcount] = NULL;
591 break;
592 }
593 }
594 }
595 linkcount++;
596 }
597 if (candidate[2] && candidate[1]) {
598 add_mutex_pair(&guess_mutex, candidate[2], candidate[1]);
599 }
600 else if (candidate[1] && candidate[0]) {
601 add_mutex_pair(&guess_mutex, candidate[1], candidate[0]);
602 }
603 yagFreeGraph(YAG_CONTEXT->YAG_SUPPORT_GRAPH);
604 YAG_CONTEXT->YAG_SUPPORT_GRAPH = NULL;
605 }
606 }
607 if (YAG_CONTEXT->YAG_CONE_GRAPH) yagDeleteConeGraph(YAG_CONTEXT->YAG_CONE_GRAPH);
608 YAG_CONTEXT->YAG_CONE_GRAPH = NULL;
609 }
610 return guess_mutex;
611 }
612
613 static void
614 add_mutex_pair(chain_list **ptmutex, char *name1, char *name2)
615 {
616 chain_list *list1 = NULL, *list2 = NULL;
617 chain_list *ptmutexchain, *ptchain;
618
619 for (ptmutexchain = *ptmutex; ptmutexchain; ptmutexchain = ptmutexchain->NEXT) {
620 ptchain = (chain_list *)ptmutexchain->DATA;
621 if (yagGetChain(ptchain, name1) != NULL) list1 = ptmutexchain;
622 if (yagGetChain(ptchain, name2) != NULL) list2 = ptmutexchain;
623 if (list1 && list2) break;
624 }
625 if (!list1 && !list2) {
626 ptchain = addchain(NULL, name1);
627 ptchain = addchain(ptchain, name2);
628 *ptmutex = addchain(*ptmutex, ptchain);
629 }
630 else if (!list1 && list2) {
631 list2->DATA = addchain(list2->DATA, name1);
632 }
633 else if (list1 && !list2) {
634 list1->DATA = addchain(list1->DATA, name2);
635 }
636 else if (list1 != list2) {
637 list1->DATA = append(list1->DATA, list2->DATA);
638 list2->DATA = NULL;
639 *ptmutex = delchain(*ptmutex, list2);
640 }
641 }
642
643 void
644 yagAnalyseCone(cone_list *ptcone)
645 {
646 ptype_list *ptuser;
647 int isLocalDual;
648
649 avt_log(LOGYAG, 1, "\tAnalysing cone '%s'\n", ptcone->NAME);
650
651 if (yagDetectFalseConf(ptcone)) yagChainCone(ptcone);
652 yagDetectLoopConf(ptcone);
653
654 if ((ptcone->TECTYPE & CNS_DUAL_CMOS) == CNS_DUAL_CMOS) {
655 ptcone->TYPE &= ~(YAG_FALSECONF|YAG_LOOPCONF);
656 return;
657 }
658
659 yagDetectBadBranches(ptcone);
660 yagDetectParallelBranches(ptcone);
661 yagDetectParaTrans(ptcone);
662 yagDetectSwitch(ptcone);
663 yagDetectPullup(ptcone);
664 yagDetectPulldown(ptcone);
665 if (yagDetectTransfer(ptcone)) yagChainCone(ptcone);
666 yagDetectDegraded(ptcone);
667
668 if ((ptuser = getptype(ptcone->USER, YAG_BUSBEFIG_PTYPE)) != NULL) {
669 beh_delbefig((befig_list *)ptuser->DATA, (befig_list *)ptuser->DATA, 'Y');
670 ptcone->USER = delptype(ptcone->USER, YAG_BUSBEFIG_PTYPE);
671 }
672 if ((ptuser = getptype(ptcone->USER, YAG_LATCHBEFIG_PTYPE)) != NULL) {
673 beh_delbefig((befig_list *)ptuser->DATA, (befig_list *)ptuser->DATA, 'Y');
674 ptcone->USER = delptype(ptcone->USER, YAG_LATCHBEFIG_PTYPE);
675 }
676
677 if ((ptcone->TYPE & YAG_AUTOLATCH) != 0) {
678 yagUnmarkLatch(ptcone, FALSE, FALSE);
679 }
680
681 if (yagCheckExtOut(ptcone) == FALSE) return;
682 if (yagCheckBranches(ptcone) == FALSE) return;
683
684 if ((ptcone->TYPE & (YAG_GLUECONE|YAG_TEMPCONE)) == 0) yagBuildOutputs(ptcone);
685
686 cnsConeFunction(ptcone, FALSE);
687 #ifndef WITHOUT_TAS
688 if (YAG_CONTEXT->YAG_USESTMSOLVER) {
689 yagPrepStmSolver(ptcone);
690 }
691 #endif
692
693 if ((ptcone->TYPE & YAG_FALSECONF) != 0) {
694 ptcone->TYPE |= CNS_CONFLICT;
695 }
696 else {
697 isLocalDual = FALSE;
698 if ((ptcone->TECTYPE & (CNS_VSS_DEGRADED|CNS_VDD_DEGRADED)) == 0
699 && getptype(ptcone->USER, CNS_SWITCH) == NULL) {
700 isLocalDual = yagCheckLocalDuality(ptcone);
701 if (isLocalDual) {
702 ptcone->TECTYPE |= CNS_DUAL_CMOS;
703 if (YAG_CONTEXT->YAG_LOOP_ANALYSIS) {
704 yagAnalyseLoop(ptcone, FALSE);
705 }
706 }
707 }
708 if (!isLocalDual) {
709 if (YAG_CONTEXT->YAG_USE_FCF) check_cone(ptcone);
710 else ptcone->TYPE |= CNS_CONFLICT;
711 }
712 }
713
714
715 if (!YAG_CONTEXT->YAG_KEEP_REDUNDANT) {
716 yagRemoveRedundantBranches(ptcone);
717 }
718
719 avt_log(LOGYAG, 1, "\tBDD system used %d/%d reduced nodes\n", numberNodeAllBdd() - YAG_CONTEXT->YAG_LASTNODECOUNT, numberNodeAllBdd());
720 if (numberNodeAllBdd() - YAG_CONTEXT->YAG_LASTNODECOUNT > YAG_CONTEXT->YAG_MAXNODES) {
721 YAG_CONTEXT->YAG_MAXNODES = numberNodeAllBdd() - YAG_CONTEXT->YAG_LASTNODECOUNT;
722 }
723 yagControlBdd(0);
724
725 if (avt_islog(1,LOGYAG) && YAG_CONTEXT->YAG_DEBUG_CONE == ptcone->NAME) {
726 avt_log(LOGYAG, 1, "\nDisplaying Cone Structure :-\n\n");
727 displayconelog(LOGYAG, 1, ptcone);
728 }
729 }
730
731 /****************************************************************************
732 * function check_cone(); *
733 ****************************************************************************/
734 /*----------------------------------------------------*
735 | Check if completed cone is conflictual or HZ |
736 *----------------------------------------------------*/
737
738 static void
739 check_cone(cone_list *ptcone)
740 {
741 ptype_list *ptuser;
742 chain_list *sup_abl, *sdn_abl;
743 gnode_list *rootnode;
744 branch_list *ptbranch;
745 int resist_up, resist_dn;
746 int destroy;
747 int isdlatch, forcedlatch;
748 int isprecharge = FALSE;
749 short save_depth;
750
751 /* To handle a return from BDD explosion */
752 save_depth = YAG_CONTEXT->YAG_DEPTH;
753 setBddCeiling(YAG_CONTEXT->YAG_BDDCEILING);
754 if (setjmp(abandon_analyse) != 0) {
755 yagDeleteConeGraph(YAG_CONTEXT->YAG_CONE_GRAPH);
756 YAG_CONTEXT->YAG_CONE_GRAPH = NULL;
757 if (YAG_CONTEXT->YAG_DEPTH == 0) {
758 ptcone->TYPE |= CNS_CONFLICT;
759 fprintf(stderr,"\n*** YAG DANGER : unable to analyse cone '%s' ***\n", ptcone->NAME);
760 fprintf(stderr," increase BDD Ceiling or identify constraints\n");
761 fflush(stderr);
762 unsetBddCeiling();
763 YAG_CONTEXT->YAG_DEPTH = save_depth;
764 return;
765 }
766 YAG_CONTEXT->YAG_DEPTH--;
767 cnsConeFunction(ptcone, FALSE);
768 }
769
770 /* build the clean global graph */
771 if (YAG_CONTEXT->YAG_CONE_GRAPH == NULL) {
772 YAG_CONTEXT->YAG_CONE_GRAPH = yagMakeConeGraph(ptcone);
773 destroy = TRUE;
774 }
775 else destroy = FALSE;
776
777 rootnode = yagRootGraph(YAG_CONTEXT->YAG_CONE_GRAPH, ptcone);
778
779 if (avt_islog(1,LOGYAG) && YAG_CONTEXT->YAG_DEBUG_CONE == ptcone->NAME) {
780 avt_log(LOGYAG, 1, "\nAfter Construction :-\n");
781 yagDisplayUsedGraphLog(LOGYAG, 1, YAG_CONTEXT->YAG_CONE_GRAPH, 1);
782 }
783
784 resist_up = FALSE;
785 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
786 if ((ptbranch->TYPE & CNS_RESBRANCH) != 0) resist_up = TRUE;
787 }
788 resist_dn = FALSE;
789 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
790 if ((ptbranch->TYPE & CNS_RESBRANCH) != 0) resist_dn = TRUE;
791 }
792
793 if (yagCountBranches(ptcone) >= A_LOT_OF_BRANCHES) {
794 check_big_cone(ptcone,rootnode);
795 }
796 else {
797 yagCheckGlobalDuality(ptcone);
798 }
799
800 if ((ptcone->TYPE & (CNS_CONFLICT|CNS_TRI)) == 0) {
801
802 /* use YAG_DNEXPR_PTYPE to express functionality for pseudo CMOS or cones with no UP */
803 ptuser = getptype(ptcone->USER, CNS_UPEXPR);
804 sup_abl = (chain_list *)ptuser->DATA;
805 sdn_abl = (chain_list *)getptype(ptcone->USER, CNS_DNEXPR)->DATA;
806 if (sdn_abl != NULL) {
807 if ((sup_abl == NULL) || (resist_up && !resist_dn)) {
808 ptuser->DATA = notExpr(copyExpr(sdn_abl));
809 if (sup_abl != NULL) freeExpr(sup_abl);
810 }
811 freeExpr(sdn_abl);
812 }
813 ptcone->USER = delptype(ptcone->USER, CNS_DNEXPR);
814 }
815 else {
816 if (avt_islog(1,LOGYAG)) {
817 avt_log(LOGYAG, 1, "\t\t");
818 if ((ptcone->TYPE & CNS_CONFLICT) != 0) avt_log(LOGYAG, 1, "CONFLICT ");
819 if ((ptcone->TYPE & CNS_TRI) != 0) avt_log(LOGYAG, 1, "HZ ");
820 avt_log(LOGYAG, 1, "\n");
821 }
822 }
823 unsetBddCeiling();
824
825 /* Precharge detection */
826 if ((ptuser = getptype(ptcone->USER, YAG_INFO_PTYPE)) != NULL) {
827 if (((long)ptuser->DATA & YAG_INFOPRECHARGE) != 0) isprecharge = TRUE;;
828 }
829 if (isprecharge || (YAG_CONTEXT->YAG_DETECT_PRECHARGE && (ptcone->TYPE & (CNS_CONFLICT|CNS_TRI)) != 0)) {
830 yagDetectPrecharge(ptcone, TRUE);
831 }
832 /* Simple latch detection */
833 if (YAG_CONTEXT->YAG_SIMPLE_LATCH && (ptcone->TYPE & CNS_PRECHARGE) == 0) {
834 yagMatchSimpleLatch(ptcone);
835 }
836 /* Automatic latch detection */
837 if (YAG_CONTEXT->YAG_LOOP_ANALYSIS && (ptcone->TYPE & CNS_PRECHARGE) == 0 && (ptcone->TYPE & YAG_FALSECONF) == 0) {
838 yagAnalyseLoop(ptcone, FALSE);
839 }
840 /* Automatic dynamic latch and bus handling detection */
841 if (((ptcone->TYPE & (CNS_CONFLICT|CNS_TRI)) != 0 || (ptcone->TECTYPE & YAG_LEVELHOLD) != 0) && (ptcone->TYPE & (CNS_PRECHARGE|CNS_LATCH)) == 0) {
842 isdlatch = FALSE;
843 forcedlatch = FALSE;
844 if ((ptcone->TECTYPE & YAG_LEVELHOLD) == 0) {
845 if (YAG_CONTEXT->YAG_MARK_TRISTATE_MEMORY) {
846 isdlatch = TRUE;
847 if ((ptuser = getptype(ptcone->USER, YAG_INFO_PTYPE)) != NULL) {
848 if (((long)ptuser->DATA & YAG_INFONOTDLATCH) != 0) isdlatch = FALSE;
849 }
850 if ((ptcone->TECTYPE & YAG_NOTLATCH) == YAG_NOTLATCH) isdlatch = FALSE;
851 }
852 if ((ptuser = getptype(ptcone->USER, YAG_INFO_PTYPE)) != NULL) {
853 if (((long)ptuser->DATA & YAG_INFODLATCH) != 0) forcedlatch = TRUE;
854 }
855 }
856 if ((YAG_CONTEXT->YAG_BUS_ANALYSIS || isdlatch || forcedlatch || ((ptcone->TYPE & CNS_EXT) == CNS_EXT && !strcmp(YAG_CONTEXT->YAGLE_TOOLNAME,"hitas")))
857 && (ptcone->TYPE & CNS_TRI) != 0 && (ptcone->TYPE & CNS_PRECHARGE) == 0) {
858 if ((isdlatch && ((ptcone->TYPE & CNS_EXT) != CNS_EXT)) || forcedlatch) {
859 ptcone->TYPE |= CNS_LATCH;
860 ptcone->TYPE &= ~CNS_TRI;
861 }
862 yagAnalyseBus(ptcone, TRUE);
863 }
864 else if ((ptcone->TECTYPE & YAG_LEVELHOLD) != 0 && V_BOOL_TAB[__YAGLE_LEVELHOLD_ANALYSIS].VALUE) {
865 yagAnalyseBus(ptcone, TRUE);
866 }
867 }
868
869 /* Mark non-conflictual feedback branches in latch cones */
870 if ((ptcone->TYPE & (CNS_LATCH|CNS_MEMSYM|CNS_MASTER|CNS_SLAVE|CNS_RS)) != 0) {
871 yagDetectNonConflictualFeedback(ptcone);
872 }
873
874 /* delete graph */
875 if (destroy) {
876 if (YAG_CONTEXT->YAG_CONE_GRAPH) yagDeleteConeGraph(YAG_CONTEXT->YAG_CONE_GRAPH);
877 YAG_CONTEXT->YAG_CONE_GRAPH = NULL;
878 }
879
880 YAG_CONTEXT->YAG_DEPTH = save_depth;
881
882 if ((ptcone->TYPE & CNS_LATCH) != 0) {
883 if ((ptcone->TYPE & YAG_AUTOLATCH) == 0) {
884 cnsConeFunction(ptcone, FALSE);
885 yagDetectStuck(ptcone);
886 }
887 if ((ptcone->TECTYPE & (CNS_ONE|CNS_ZERO)) != 0) yagPropagateStuck(ptcone);
888 }
889 }
890
891 static void
892 check_big_cone(cone_list *ptcone, gnode_list *rootnode)
893 {
894 branch_list *ptbranch0, *ptbranch1;
895 pNode bdd0, bdd1;
896 pNode sup, sdn;
897 pNode sum;
898 chain_list *sup_abl, *sdn_abl;
899 chain_list *name_expr;
900
901 ptcone->TYPE &= ~(CNS_CONFLICT|CNS_TRI);
902
903 for (ptbranch0 = ptcone->BRVDD; ptbranch0; ptbranch0 = ptbranch0->NEXT) {
904 if ((ptbranch0->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
905 for (ptbranch1 = ptcone->BRVSS; ptbranch1; ptbranch1 = ptbranch1->NEXT) {
906 if ((ptbranch1->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
907 bdd0 = yagCalcBranchConductance(ptbranch0);
908 bdd1 = yagCalcBranchConductance(ptbranch1);
909 if (!zeroBdd(yagApplyBinBdd(AND, bdd0, bdd1, abandon_analyse))) break;
910 }
911 if (ptbranch1 != NULL) break;
912 for (ptbranch1 = ptcone->BREXT; ptbranch1; ptbranch1 = ptbranch1->NEXT) {
913 if ((ptbranch1->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
914 if (ptbranch1->LINK->NEXT == NULL) continue;
915 bdd0 = yagCalcBranchConductance(ptbranch0);
916 bdd1 = yagCalcBranchConductance(ptbranch1);
917 if (!zeroBdd(yagApplyBinBdd(AND, bdd0, bdd1, abandon_analyse))) break;
918 }
919 if (ptbranch1 != NULL) break;
920 }
921 if (ptbranch0 != NULL) {
922 ptcone->TYPE |= (CNS_CONFLICT|CNS_TRI);
923 return;
924 }
925 else {
926 for (ptbranch0 = ptcone->BRVSS; ptbranch0; ptbranch0 = ptbranch0->NEXT) {
927 if ((ptbranch0->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
928 for (ptbranch1 = ptcone->BREXT; ptbranch1; ptbranch1 = ptbranch1->NEXT) {
929 if ((ptbranch1->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
930 if (ptbranch1->LINK->NEXT == NULL) continue;
931 bdd0 = yagCalcBranchConductance(ptbranch0);
932 bdd1 = yagCalcBranchConductance(ptbranch1);
933 if (!zeroBdd(yagApplyBinBdd(AND, bdd0, bdd1, abandon_analyse))) break;
934 }
935 if (ptbranch1 != NULL) break;
936 }
937 if (ptbranch0 != NULL) {
938 ptcone->TYPE |= (CNS_CONFLICT|CNS_TRI);
939 return;
940 }
941 }
942
943 /* Set to HZ to generate down function */
944 ptcone->TYPE |= CNS_TRI;
945
946 name_expr = createAtom_no_NA(ptcone->NAME);
947
948 sup_abl = yagExpandExpr(rootnode, name_expr, FALSE);
949 sdn_abl = yagExpandExpr(rootnode, name_expr, TRUE);
950
951 freeExpr(name_expr);
952
953 sup = yagAblToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, sup_abl, abandon_analyse);
954 sdn = yagAblToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, sdn_abl, abandon_analyse);
955 freeExpr(sup_abl);
956 freeExpr(sdn_abl);
957
958 /* apply the contraints */
959 sup = yagApplyConstraints(sup, yagAbandonAnalyse());
960 sdn = yagApplyConstraints(sdn, yagAbandonAnalyse());
961
962 /* test for high impedance */
963
964 sum = yagApplyBinBdd(OR, sup, sdn, abandon_analyse);
965 if (oneBdd(sum) || (ptcone->TYPE & (CNS_LATCH|CNS_MEMSYM|CNS_MASTER|CNS_SLAVE)) != 0) {
966 ptcone->TYPE ^= CNS_TRI;
967 }
968 }
969
970 int
971 yagCheckLocalDuality(cone_list *ptcone)
972 {
973 ht *ptorder;
974 table *ptnames;
975 branch_list *ptbranch;
976 link_list *ptlink;
977 pNode sup = BDD_zero;
978 pNode sdown = BDD_zero;
979 pNode sum, product;
980 pNode term, symbol;
981 long index;
982
983 /* not dual if external branch containing more than just connector link */
984 if (ptcone->BREXT != NULL) {
985 if (ptcone->BREXT->LINK->NEXT != NULL) return FALSE;
986 }
987
988 ptnames = newtable();
989 ptorder = order(ptcone->BRVSS, ptnames);
990
991 /* To calculate Sup */
992
993 for (ptbranch = ptcone->BRVDD; ptbranch != NULL; ptbranch = ptbranch->NEXT) {
994 term = BDD_one;
995 for (ptlink = ptbranch->LINK; ptlink != NULL; ptlink = ptlink->NEXT) {
996 if ((index = gethtitem(ptorder, ptlink->ULINK.LOTRS->GRID)) == EMPTYHT) {
997 delht(ptorder);
998 deltable(ptnames);
999 return FALSE;
1000 }
1001 symbol = notBdd(createNodeTermBdd(index));
1002 term = applyBinBdd(AND, term, symbol);
1003 }
1004 sup = applyBinBdd(OR, sup, term);
1005 }
1006
1007 /* To calculate Sdown */
1008
1009 for (ptbranch = ptcone->BRVSS; ptbranch != NULL; ptbranch = ptbranch->NEXT) {
1010 term = BDD_one;
1011 for (ptlink = ptbranch->LINK; ptlink != NULL; ptlink = ptlink->NEXT) {
1012 index = gethtitem(ptorder, ptlink->ULINK.LOTRS->GRID);
1013 symbol = createNodeTermBdd(index);
1014 term = applyBinBdd(AND, term, symbol);
1015 }
1016 sdown = applyBinBdd(OR, sdown, term);
1017 }
1018
1019 delht(ptorder);
1020 ptcone->TYPE &= ~(CNS_CONFLICT|CNS_TRI);
1021 product = applyBinBdd(AND, sup, sdown);
1022 if (!zeroBdd(product)) ptcone->TYPE |= CNS_CONFLICT;
1023 sum = applyBinBdd(OR, sup, sdown);
1024 if (!oneBdd(sum)) ptcone->TYPE |= CNS_TRI;
1025 deltable(ptnames);
1026 if ((ptcone->TYPE & (CNS_CONFLICT|CNS_TRI)) != 0) return FALSE;
1027 else return TRUE;
1028 }
1029
1030 static void
1031 yagCheckGlobalDuality(cone_list *ptcone)
1032 {
1033 chain_list *sup_abl, *sdn_abl;
1034 chain_list *name_expr, *tmpabl;
1035 branch_list *ptbranch;
1036 pNode sup, sdn;
1037 pNode sum, product;
1038 gnode_list *rootnode;
1039 abl_pair conf_abl, hz_abl;
1040 int resist_up, resist_dn;
1041 int loglvl2=0;
1042 int hasdual = FALSE;
1043
1044 if ((ptcone->TYPE & YAG_HASDUAL) != 0) hasdual = TRUE;
1045 ptcone->TYPE &= ~YAG_HASDUAL;
1046 loglvl2 = avt_islog(2,LOGYAG);
1047 resist_up = FALSE;
1048 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1049 if ((ptbranch->TYPE & CNS_RESBRANCH) != 0) resist_up = TRUE;
1050 }
1051 resist_dn = FALSE;
1052 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1053 if ((ptbranch->TYPE & CNS_RESBRANCH) != 0) resist_dn = TRUE;
1054 }
1055
1056 /* Set to HZ to generate down function */
1057 ptcone->TYPE |= CNS_TRI;
1058 ptcone->TYPE &= ~CNS_CONFLICT;
1059
1060 name_expr = createAtom_no_NA(ptcone->NAME);
1061 rootnode = (gnode_list *)gethtitem(YAG_CONTEXT->YAG_CONE_GRAPH->HASHTAB, ptcone);
1062
1063 sup_abl = yagExpandExpr(rootnode, name_expr, FALSE);
1064 sdn_abl = yagExpandExpr(rootnode, name_expr, TRUE);
1065
1066 freeExpr(name_expr);
1067
1068 if ( loglvl2 && YAG_CONTEXT->YAG_DEBUG_CONE == ptcone->NAME) {
1069 avt_log(LOGYAG, 2, "Sup expr: ");
1070 displayInfExprLog(LOGYAG, 2, sup_abl);
1071 avt_log(LOGYAG, 2, "\n");
1072 avt_log(LOGYAG, 2, "Sdn expr: ");
1073 displayInfExprLog(LOGYAG, 2, sdn_abl);
1074 avt_log(LOGYAG, 2, "\n");
1075 }
1076
1077 sup = yagAblToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, sup_abl, abandon_analyse);
1078 sdn = yagAblToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, sdn_abl, abandon_analyse);
1079 freeExpr(sup_abl);
1080 freeExpr(sdn_abl);
1081
1082 if ((ptcone->TYPE & CNS_EXT) != 0 && ptcone->BREXT != NULL) {
1083 if (resist_up) {
1084 cnsMakeConeExpr(ptcone, &hz_abl, CNS_RESBRANCH|CNS_NOT_FUNCTIONAL|CNS_MASK_PARA|CNS_IGNORE|(CNS_VSS&~CNS_POWER), 0, FALSE);
1085 if (hz_abl.UP != NULL) {
1086 sup_abl = yagExpandTerm(rootnode, hz_abl.UP);
1087 sup = yagAblToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, sup_abl, abandon_analyse);
1088 freeExpr(sup_abl);
1089 }
1090 else sup = BDD_zero;
1091 }
1092 if (resist_dn) {
1093 cnsMakeConeExpr(ptcone, &hz_abl, CNS_RESBRANCH|CNS_NOT_FUNCTIONAL|CNS_MASK_PARA|CNS_IGNORE|(CNS_VDD&~CNS_POWER), 0, FALSE);
1094 if (hz_abl.DN != NULL) {
1095 sdn_abl = yagExpandTerm(rootnode, hz_abl.DN);
1096 sdn = yagAblToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, sdn_abl, abandon_analyse);
1097 freeExpr(sdn_abl);
1098 }
1099 else sdn = BDD_zero;
1100 }
1101 }
1102
1103 if ( loglvl2 || YAG_CONTEXT->YAG_DEBUG_CONE == ptcone->NAME) {
1104 avt_log(LOGYAG,1,"Sup reduced: ");
1105 displayInfExprLog(LOGYAG, 1, tmpabl=bddToAblCct(YAG_CONTEXT->YAG_CURCIRCUIT, sup));
1106 freeExpr(tmpabl);
1107 avt_log(LOGYAG,1,"\n");
1108 avt_log(LOGYAG,1,"Sdn reduced: ");
1109 displayInfExprLog(LOGYAG, 1, tmpabl=bddToAblCct(YAG_CONTEXT->YAG_CURCIRCUIT, sdn));
1110 freeExpr(tmpabl);
1111 avt_log(LOGYAG,1,"\n");
1112 }
1113
1114 /* apply the contraints */
1115 sup = yagApplyConstraints(sup, yagAbandonAnalyse());
1116 sdn = yagApplyConstraints(sdn, yagAbandonAnalyse());
1117
1118 /* test for constants */
1119 if (sup == BDD_one && sdn == BDD_zero) {
1120 ptcone->TECTYPE |= CNS_ONE;
1121 ptcone->TYPE |= YAG_FORCEPRIM;
1122 yagPropagateStuck(ptcone);
1123 }
1124 if (sup == BDD_zero && sdn == BDD_one) {
1125 ptcone->TECTYPE |= CNS_ZERO;
1126 ptcone->TYPE |= YAG_FORCEPRIM;
1127 yagPropagateStuck(ptcone);
1128 }
1129
1130 /* test for high impedance */
1131
1132 sum = yagApplyBinBdd(OR, sup, sdn, abandon_analyse);
1133 if (oneBdd(sum) || (ptcone->TYPE & (CNS_LATCH|CNS_MEMSYM|CNS_MASTER|CNS_SLAVE)) != 0) ptcone->TYPE ^= CNS_TRI;
1134
1135 /* test for conflicts but must ignore resistance branches */
1136
1137 if (resist_up) {
1138 cnsMakeConeExpr(ptcone, &conf_abl, CNS_RESBRANCH|CNS_NOT_FUNCTIONAL|CNS_MASK_PARA|CNS_IGNORE|(CNS_VSS&~CNS_POWER), 0, FALSE);
1139 if (conf_abl.UP != NULL) {
1140 sup_abl = yagExpandTerm(rootnode, conf_abl.UP);
1141 sup = yagAblToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, sup_abl, abandon_analyse);
1142 freeExpr(sup_abl);
1143 }
1144 else sup = BDD_zero;
1145 }
1146 if (resist_dn) {
1147 cnsMakeConeExpr(ptcone, &conf_abl, CNS_RESBRANCH|CNS_NOT_FUNCTIONAL|CNS_MASK_PARA|CNS_IGNORE|(CNS_VDD&~CNS_POWER), 0, FALSE);
1148 if (conf_abl.DN != NULL) {
1149 sdn_abl = yagExpandTerm(rootnode, conf_abl.DN);
1150 sdn = yagAblToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, sdn_abl, abandon_analyse);
1151 freeExpr(sdn_abl);
1152 }
1153 else sdn = BDD_zero;
1154 }
1155
1156 product = yagApplyBinBdd(AND, sup, sdn, abandon_analyse);
1157 if (!zeroBdd(product)) ptcone->TYPE |= CNS_CONFLICT;
1158 if (hasdual) ptcone->TYPE |= YAG_HASDUAL;
1159 }
1160
1161 static
1162 ht *order(branch_list *ptbranchlist, table *ptnames)
1163 {
1164 ht *ptorder;
1165 branch_list *ptbranch;
1166 link_list *ptlink;
1167 cone_list *ptcone;
1168 long index = 2;
1169
1170 ptorder = addht(20);
1171
1172 for (ptbranch = ptbranchlist; ptbranch != NULL; ptbranch = ptbranch->NEXT) {
1173 for (ptlink = ptbranch->LINK; ptlink != NULL; ptlink = ptlink->NEXT) {
1174 ptcone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1175 if (gethtitem(ptorder, ptcone) == EMPTYHT) {
1176 addhtitem(ptorder, ptcone, index++);
1177 addtableitem(ptnames, ptcone->NAME);
1178 }
1179 }
1180 }
1181 return ptorder;
1182 }
1183
1184 void
1185 yagDetectNonConflictualFeedback(cone_list *ptcone)
1186 {
1187 branch_list *ptbranch0, *ptbranch1;
1188 pNode bdd0, bdd1;
1189 pNode resbdd;
1190 int conflict;
1191
1192 for (ptbranch0 = ptcone->BRVDD; ptbranch0; ptbranch0 = ptbranch0->NEXT) {
1193 if ((ptbranch0->TYPE & CNS_FEEDBACK) != CNS_FEEDBACK) continue;
1194 conflict = FALSE;
1195 for (ptbranch1 = ptcone->BRVSS; ptbranch1; ptbranch1 = ptbranch1->NEXT) {
1196 if ((ptbranch1->TYPE & (CNS_FEEDBACK|CNS_NOT_FUNCTIONAL)) != 0) continue;
1197 bdd0 = yagCalcBranchConductance(ptbranch0);
1198 bdd1 = yagCalcBranchConductance(ptbranch1);
1199 resbdd = yagApplyBinBdd(AND, bdd0, bdd1, abandon_analyse);
1200 resbdd = yagApplyConstraints(resbdd, yagAbandonAnalyse());
1201 if (!zeroBdd(resbdd)) conflict = TRUE;
1202 }
1203 for (ptbranch1 = ptcone->BREXT; ptbranch1; ptbranch1 = ptbranch1->NEXT) {
1204 if ((ptbranch1->TYPE & (CNS_FEEDBACK|CNS_NOT_FUNCTIONAL)) != 0) continue;
1205 if (ptbranch1->LINK->NEXT == NULL) continue;
1206 bdd0 = yagCalcBranchConductance(ptbranch0);
1207 bdd1 = yagCalcBranchConductance(ptbranch1);
1208 resbdd = yagApplyBinBdd(AND, bdd0, bdd1, abandon_analyse);
1209 resbdd = yagApplyConstraints(resbdd, yagAbandonAnalyse());
1210 if (!zeroBdd(resbdd)) conflict = TRUE;
1211 }
1212 if (!conflict) ptbranch0->TYPE |= CNS_NOTCONFLICTUAL;
1213 }
1214 for (ptbranch0 = ptcone->BRVSS; ptbranch0; ptbranch0 = ptbranch0->NEXT) {
1215 if ((ptbranch0->TYPE & CNS_FEEDBACK) != CNS_FEEDBACK) continue;
1216 conflict = FALSE;
1217 for (ptbranch1 = ptcone->BRVDD; ptbranch1; ptbranch1 = ptbranch1->NEXT) {
1218 if ((ptbranch1->TYPE & (CNS_FEEDBACK|CNS_NOT_FUNCTIONAL)) != 0) continue;
1219 bdd0 = yagCalcBranchConductance(ptbranch0);
1220 bdd1 = yagCalcBranchConductance(ptbranch1);
1221 resbdd = yagApplyBinBdd(AND, bdd0, bdd1, abandon_analyse);
1222 resbdd = yagApplyConstraints(resbdd, yagAbandonAnalyse());
1223 if (!zeroBdd(resbdd)) conflict = TRUE;
1224 }
1225 for (ptbranch1 = ptcone->BREXT; ptbranch1; ptbranch1 = ptbranch1->NEXT) {
1226 if ((ptbranch1->TYPE & (CNS_FEEDBACK|CNS_NOT_FUNCTIONAL)) != 0) continue;
1227 if (ptbranch1->LINK->NEXT == NULL) continue;
1228 bdd0 = yagCalcBranchConductance(ptbranch0);
1229 bdd1 = yagCalcBranchConductance(ptbranch1);
1230 resbdd = yagApplyBinBdd(AND, bdd0, bdd1, abandon_analyse);
1231 resbdd = yagApplyConstraints(resbdd, yagAbandonAnalyse());
1232 if (!zeroBdd(resbdd)) conflict = TRUE;
1233 }
1234 if (!conflict) ptbranch0->TYPE |= CNS_NOTCONFLICTUAL;
1235 }
1236 }
1237
1238 pNode
1239 yagApplyConstraints(pNode expr, jmp_buf *ptabandon_env)
1240 {
1241 chain_list *support;
1242 chain_list *constraint_support;
1243 chain_list *ptabl;
1244 chain_list *constraint_abl;
1245 ptype_list *ptptype;
1246 pNode constraint;
1247 ht *FASTSEARCH=NULL;
1248
1249 if (YAG_CONTEXT->YAG_CONE_GRAPH->CONSTRAINTS != NULL) {
1250 support=supportChain_listBddExpr(YAG_CONTEXT->YAG_CURCIRCUIT, expr);
1251 for (ptptype = YAG_CONTEXT->YAG_CONE_GRAPH->CONSTRAINTS; ptptype; ptptype = ptptype->NEXT) {
1252 constraint_support = (chain_list *)ptptype->TYPE;
1253 if ((constraint_abl = yagCheckConstraint(support, constraint_support, (chain_list *)ptptype->DATA, &FASTSEARCH)) != NULL) {
1254 if (ptabandon_env != NULL) {
1255 constraint = yagAblToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, constraint_abl, *ptabandon_env);
1256 expr = yagConstraintBdd(expr, constraint, *ptabandon_env);
1257 }
1258 else {
1259 constraint = ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, constraint_abl);
1260 expr = constraintBdd(expr, constraint);
1261 }
1262 if (constraint_abl != (chain_list *)ptptype->DATA) freeExpr(constraint_abl);
1263 }
1264 if (zeroBdd(expr)) break;
1265 }
1266 freechain(support);
1267 }
1268 if (FASTSEARCH!=NULL) delht(FASTSEARCH);
1269 return expr;
1270 }
1271
1272 /****************************************************************************
1273 * function yagDetectPrecharge() *
1274 ****************************************************************************/
1275
1276 /* detect precharge */
1277
1278 void
1279 yagDetectPrecharge(cone_list *ptcone, int fIgnoreFalse)
1280 {
1281 edge_list *save_inputs, *ptedge;
1282 cone_list *ptloopcone;
1283 branch_list *ptbranch;
1284 pCircuit directCct;
1285 long branchmask;
1286 abl_pair local_abl;
1287 pNode local_sup, local_sdn;
1288 chain_list *ptsupport, *ptloopchain;
1289 chain_list *ptchain;
1290 ptype_list *ptuser;
1291 float ratio;
1292 char *name;
1293 int invloop = FALSE;
1294 int found = FALSE;
1295 long savetype;
1296
1297 ptcone->TYPE &= ~CNS_PRECHARGE;
1298 if ((ptuser = getptype(ptcone->USER, YAG_INFO_PTYPE)) != NULL) {
1299 if (((long)ptuser->DATA & YAG_INFONOTPRECHARGE) != 0) return;
1300 }
1301
1302 savetype = ptcone->TYPE;
1303
1304 /* Check for correctly dimensioned 2 cone loop */
1305 if ((ptloopchain = yagCheckLoop(ptcone, TRUE)) != NULL) {
1306 for (ptchain = ptloopchain; ptchain; ptchain = ptchain->NEXT) {
1307 ptloopcone = (cone_list *)ptchain->DATA;
1308 if (yagMatchNOT(ptcone, ptloopcone) == TRUE && yagMatchNOT(ptloopcone, ptcone) == TRUE) {
1309 ratio = yagInverterStrength(ptcone, ptloopcone)/yagInverterStrength(ptloopcone, ptcone);
1310 if (ratio > 1.2) invloop = TRUE;
1311 break;
1312 }
1313 }
1314 freechain(ptloopchain);
1315 }
1316
1317 /* Mark inverter loop as bleeder and re-analyse*/
1318 if (invloop) {
1319 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1320 if (ptbranch->LINK->NEXT == NULL && (cone_list *)ptbranch->LINK->ULINK.LOTRS->GRID == ptloopcone) {
1321 ptbranch->TYPE |= CNS_BLEEDER|CNS_NOT_FUNCTIONAL;
1322 }
1323 }
1324 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1325 if (ptbranch->LINK->NEXT == NULL && (cone_list *)ptbranch->LINK->ULINK.LOTRS->GRID == ptloopcone) {
1326 ptbranch->TYPE |= CNS_BLEEDER|CNS_NOT_FUNCTIONAL;
1327 }
1328 }
1329 ptedge = yagGetEdge(ptcone->INCONE, ptloopcone);
1330 ptedge->TYPE |= CNS_BLEEDER;
1331
1332 cnsConeFunction(ptcone, FALSE);
1333 yagCheckGlobalDuality(ptcone);
1334 }
1335
1336 if ((ptuser = getptype(ptcone->USER, YAG_INFO_PTYPE)) != NULL) {
1337 if (((long)ptuser->DATA & YAG_INFOPRECHARGE) != 0) {
1338 ptcone->TYPE |= CNS_PRECHARGE;
1339 return;
1340 }
1341 }
1342
1343 /* A precharge is globally tristate and globally non-conflictual */
1344 if ((ptcone->TYPE & CNS_TRI) != CNS_TRI) {
1345 if (invloop) clean_precharge_marks(ptcone, ptloopcone);
1346 ptcone->TYPE = savetype;
1347 return;
1348 }
1349
1350 /* Ignore simple external connector branch and input */
1351 if (ptcone->BREXT != NULL) {
1352 ptbranch = ptcone->BREXT;
1353 if (ptbranch->NEXT != NULL || ptbranch->LINK->NEXT != NULL) {
1354 if (invloop) clean_precharge_marks(ptcone, ptloopcone);
1355 ptcone->TYPE = savetype;
1356 return;
1357 }
1358 ptbranch->TYPE |= CNS_BLEEDER|CNS_NOT_FUNCTIONAL;
1359 ptedge = yagGetEdge(ptcone->INCONE, ptbranch->LINK->ULINK.LOCON);
1360 ptedge->TYPE |= CNS_BLEEDER;
1361 }
1362
1363 avt_log(LOGYAG,1, "Analysing Precharge at '%s'\n", ptcone->NAME);
1364
1365 if (fIgnoreFalse) {
1366 save_inputs = ptcone->INCONE;
1367 ptcone->INCONE = NULL;
1368 for (ptedge = save_inputs; ptedge; ptedge = ptedge->NEXT) {
1369 if ((ptedge->TYPE & YAG_FALSECONF) == 0) {
1370 addincone(ptcone, ptedge->TYPE, ptedge->UEDGE.PTR);
1371 }
1372 }
1373 }
1374
1375 directCct = yagBuildDirectCct(ptcone);
1376
1377 /* Generate expression for cone as a function of its direct inputs */
1378
1379 branchmask = CNS_NOT_FUNCTIONAL|CNS_IGNORE|CNS_MASK_PARA;
1380 if (fIgnoreFalse) branchmask |= YAG_FALSECONF;
1381 cnsMakeConeExpr(ptcone, &local_abl, branchmask, 0, FALSE);
1382 if (local_abl.UP == NULL) local_abl.UP = createAtom("'0'");
1383 if (local_abl.DN == NULL) local_abl.DN = createAtom("'0'");
1384
1385 /* Generate up and down expressions for cone in terms of direct inputs */
1386
1387 local_sup = ablToBddCct(directCct, local_abl.UP);
1388 local_sdn = ablToBddCct(directCct, local_abl.DN);
1389 ptsupport = supportChain_listExpr(local_abl.UP);
1390 freeExpr(local_abl.UP);
1391 freeExpr(local_abl.DN);
1392
1393 if (fIgnoreFalse) {
1394 yagFreeEdgeList(ptcone->INCONE);
1395 ptcone->INCONE = save_inputs;
1396 }
1397
1398 /* A precharge is locally tristate and and possibly locally conflictual */
1399 /* and has a single variable in the local up expression */
1400 if (!zeroBdd(local_sup) && !zeroBdd(local_sdn) && !oneBdd(applyBinBdd(OR, local_sup, local_sdn))
1401 && yagCountChains(ptsupport) == 1) {
1402 ptcone->TYPE |= CNS_PRECHARGE;
1403 for (ptedge = ptcone->INCONE; ptedge; ptedge = ptedge->NEXT) {
1404 if ((ptedge->TYPE & CNS_EXT) == CNS_EXT) name = ptedge->UEDGE.LOCON->NAME;
1405 else name = ptedge->UEDGE.CONE->NAME;
1406 if (name == (char *)ptsupport->DATA) break;
1407 }
1408 if (ptedge != NULL) ptedge->TYPE |= YAG_PRECHCOM;
1409 avt_log(LOGYAG,1, "\tFound\n");
1410 found = TRUE;
1411 }
1412 else {
1413 avt_log(LOGYAG,1, "\tNot Found\n");
1414 }
1415 freechain(ptsupport);
1416
1417 for (ptbranch = ptcone->BREXT; ptbranch; ptbranch = ptbranch->NEXT) {
1418 if (ptbranch->LINK->NEXT == NULL) {
1419 ptbranch->TYPE &= ~(CNS_BLEEDER|CNS_NOT_FUNCTIONAL);
1420 ptedge = yagGetEdge(ptcone->INCONE, ptbranch->LINK->ULINK.LOCON); {
1421 ptedge->TYPE &= ~CNS_BLEEDER;
1422 }
1423 }
1424 }
1425
1426 /* Remove bleeder loop markings if not precharge */
1427 if (!found && invloop) {
1428 clean_precharge_marks(ptcone, ptloopcone);
1429 ptcone->TYPE = savetype;
1430 }
1431
1432 destroyCct(directCct);
1433 }
1434
1435 static void
1436 clean_precharge_marks(cone_list *ptcone, cone_list *ptloopcone)
1437 {
1438 branch_list *ptbranch;
1439 edge_list *ptedge;
1440
1441 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1442 if (ptbranch->LINK->NEXT == NULL && (cone_list *)ptbranch->LINK->ULINK.LOTRS->GRID == ptloopcone) {
1443 ptbranch->TYPE &= ~(CNS_BLEEDER|CNS_NOT_FUNCTIONAL);
1444 }
1445 }
1446 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1447 if (ptbranch->LINK->NEXT == NULL && (cone_list *)ptbranch->LINK->ULINK.LOTRS->GRID == ptloopcone) {
1448 ptbranch->TYPE &= ~(CNS_BLEEDER|CNS_NOT_FUNCTIONAL);
1449 }
1450 }
1451 ptedge = yagGetEdge(ptcone->INCONE, ptloopcone);
1452 ptedge->TYPE &= ~CNS_BLEEDER;
1453 cnsConeFunction(ptcone, FALSE);
1454 }
1455
1456 /****************************************************************************
1457 * function yagDetectRedundant() *
1458 ****************************************************************************/
1459
1460 /* detect electrically poor branches for which a functional alternative exists */
1461
1462 static int
1463 yagTestSatisfy(pNode pBddref, pNode pBddtest)
1464 {
1465 if (applyBinBdd(AND, pBddref, pBddtest) == pBddref) return TRUE;
1466 return FALSE;
1467 }
1468
1469 void
1470 yagDetectRedundant(cone_list *ptcone)
1471 {
1472 graph *savegraph;
1473 pCircuit savecircuit;
1474 branch_list *ptbranch, *ptotherbranch;
1475 link_list *ptlink;
1476 chain_list *locon_abl;
1477 pNode badbranch_bdd, otherbranch_bdd;
1478 short save_prop_hz, save_depth;
1479 int bad_vdd;
1480 int bad_vss;
1481
1482 avt_log(LOGYAG,1, "Analysing Redundancy at '%s'\n", ptcone->NAME);
1483
1484 /* save context and build local cone graph */
1485 save_prop_hz = YAG_CONTEXT->YAG_PROP_HZ;
1486 savegraph = YAG_CONTEXT->YAG_CONE_GRAPH;
1487 savecircuit = YAG_CONTEXT->YAG_CURCIRCUIT;
1488 save_depth = YAG_CONTEXT->YAG_DEPTH;
1489 YAG_CONTEXT->YAG_DEPTH = 1;
1490 YAG_CONTEXT->YAG_PROP_HZ = TRUE;
1491 YAG_CONTEXT->YAG_CONE_GRAPH = yagMakeConeGraph(ptcone);
1492 YAG_CONTEXT->YAG_PROP_HZ = save_prop_hz;
1493
1494 /* check for bad Vdd branches */
1495 if ((ptcone->TECTYPE & CNS_VDD_DEGRADED) == CNS_VDD_DEGRADED) bad_vdd = TRUE;
1496 else {
1497 bad_vdd = FALSE;
1498 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1499 if ((ptbranch->TYPE & CNS_VDD_DEGRADED) != 0 || yagCountLinks(ptbranch->LINK) > 3) {
1500 bad_vdd = TRUE;
1501 break;
1502 }
1503 }
1504 }
1505
1506 /* check for bad Vss branches */
1507 if ((ptcone->TECTYPE & CNS_VSS_DEGRADED) == CNS_VSS_DEGRADED) bad_vss = TRUE;
1508 else {
1509 bad_vss = FALSE;
1510 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1511 if ((ptbranch->TYPE & CNS_VSS_DEGRADED) != 0 || yagCountLinks(ptbranch->LINK) > 3) {
1512 bad_vss = TRUE;
1513 break;
1514 }
1515 }
1516 }
1517
1518 /* Prepare branch conductance functions */
1519 if (bad_vdd) {
1520 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1521 if ((ptbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1522 ptbranch->USER = addptype(ptbranch->USER, YAG_BRANCHBDD_PTYPE, yagCalcBranchConductance(ptbranch));
1523 }
1524 }
1525 if (bad_vss) {
1526 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1527 if ((ptbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1528 ptbranch->USER = addptype(ptbranch->USER, YAG_BRANCHBDD_PTYPE, yagCalcBranchConductance(ptbranch));
1529 }
1530 }
1531 if (bad_vdd || bad_vss) {
1532 for (ptbranch = ptcone->BREXT; ptbranch; ptbranch = ptbranch->NEXT) {
1533 if ((ptbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1534 ptbranch->USER = addptype(ptbranch->USER, YAG_BRANCHBDD_PTYPE, yagCalcBranchConductance(ptbranch));
1535 }
1536 }
1537
1538 /* check whether replacement for bad Vdd branch exists */
1539 if (bad_vdd) {
1540 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1541 if ((ptbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1542 if ((ptbranch->TYPE & CNS_DEGRADED) == CNS_DEGRADED || yagCountLinks(ptbranch->LINK) > 3) {
1543 badbranch_bdd = (pNode)getptype(ptbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1544 for (ptotherbranch = ptcone->BRVDD; ptotherbranch; ptotherbranch = ptotherbranch->NEXT) {
1545 if ((ptotherbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1546 if ((ptotherbranch->TYPE & CNS_DEGRADED) == CNS_DEGRADED || yagCountLinks(ptotherbranch->LINK) > 3) continue;
1547 otherbranch_bdd = (pNode)getptype(ptotherbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1548 if (yagTestSatisfy(badbranch_bdd, otherbranch_bdd)) ptbranch->TYPE |= CNS_NOT_FUNCTIONAL;
1549 }
1550 for (ptotherbranch = ptcone->BREXT; ptotherbranch; ptotherbranch = ptotherbranch->NEXT) {
1551 if ((ptotherbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1552 if ((ptotherbranch->TYPE & CNS_VDD_DEGRADED) == CNS_VDD_DEGRADED || yagCountLinks(ptotherbranch->LINK) > 4) continue;
1553 otherbranch_bdd = (pNode)getptype(ptotherbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1554 for (ptlink = ptotherbranch->LINK; ptlink->NEXT != NULL; ptlink = ptlink->NEXT);
1555 locon_abl = createAtom(ptlink->ULINK.LOCON->NAME);
1556 otherbranch_bdd = applyBinBdd(AND, otherbranch_bdd, ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, locon_abl));
1557 freeExpr(locon_abl);
1558 if (yagTestSatisfy(badbranch_bdd, otherbranch_bdd)) ptbranch->TYPE |= CNS_NOT_FUNCTIONAL;
1559 }
1560 }
1561 }
1562 }
1563
1564 /* check whether replacement for bad Vss branch exists */
1565 if (bad_vss) {
1566 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1567 if ((ptbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1568 if ((ptbranch->TYPE & CNS_DEGRADED) == CNS_DEGRADED || yagCountLinks(ptbranch->LINK) > 3) {
1569 badbranch_bdd = (pNode)getptype(ptbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1570 for (ptotherbranch = ptcone->BRVSS; ptotherbranch; ptotherbranch = ptotherbranch->NEXT) {
1571 if ((ptotherbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1572 if ((ptotherbranch->TYPE & CNS_DEGRADED) == CNS_DEGRADED || yagCountLinks(ptotherbranch->LINK) > 3) continue;
1573 otherbranch_bdd = (pNode)getptype(ptotherbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1574 if (yagTestSatisfy(badbranch_bdd, otherbranch_bdd)) ptbranch->TYPE |= CNS_NOT_FUNCTIONAL;
1575 }
1576 for (ptotherbranch = ptcone->BREXT; ptotherbranch; ptotherbranch = ptotherbranch->NEXT) {
1577 if ((ptotherbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1578 if ((ptotherbranch->TYPE & CNS_VSS_DEGRADED) == CNS_VSS_DEGRADED || yagCountLinks(ptotherbranch->LINK) > 4) continue;
1579 otherbranch_bdd = (pNode)getptype(ptotherbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1580 for (ptlink = ptotherbranch->LINK; ptlink->NEXT != NULL; ptlink = ptlink->NEXT);
1581 locon_abl = createAtom(ptlink->ULINK.LOCON->NAME);
1582 otherbranch_bdd = applyBinBdd(AND, otherbranch_bdd, notBdd(ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, locon_abl)));
1583 freeExpr(locon_abl);
1584 if (yagTestSatisfy(badbranch_bdd, otherbranch_bdd)) ptbranch->TYPE |= CNS_NOT_FUNCTIONAL;
1585 }
1586 }
1587 }
1588 }
1589
1590 /* check whether replacement for bad Ext branch exists */
1591 if (bad_vdd) {
1592 for (ptbranch = ptcone->BREXT; ptbranch; ptbranch = ptbranch->NEXT) {
1593 if ((ptbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1594 if ((ptbranch->TYPE & CNS_VDD_DEGRADED) == CNS_VDD_DEGRADED) {
1595 badbranch_bdd = (pNode)getptype(ptbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1596 for (ptlink = ptbranch->LINK; ptlink->NEXT != NULL; ptlink = ptlink->NEXT);
1597 locon_abl = createAtom(ptlink->ULINK.LOCON->NAME);
1598 badbranch_bdd = applyBinBdd(AND, badbranch_bdd, ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, locon_abl));
1599 freeExpr(locon_abl);
1600 for (ptotherbranch = ptcone->BRVDD; ptotherbranch; ptotherbranch = ptotherbranch->NEXT) {
1601 if ((ptotherbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1602 if ((ptotherbranch->TYPE & CNS_DEGRADED) == CNS_DEGRADED || yagCountLinks(ptotherbranch->LINK) > 3) continue;
1603 otherbranch_bdd = (pNode)getptype(ptotherbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1604 if (yagTestSatisfy(badbranch_bdd, otherbranch_bdd)) ptbranch->TYPE |= CNS_NOT_UP;
1605 }
1606 for (ptotherbranch = ptcone->BREXT; ptotherbranch; ptotherbranch = ptotherbranch->NEXT) {
1607 if ((ptotherbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1608 if ((ptotherbranch->TYPE & CNS_VDD_DEGRADED) == CNS_VDD_DEGRADED || yagCountLinks(ptotherbranch->LINK) > 4) continue;
1609 otherbranch_bdd = (pNode)getptype(ptotherbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1610 for (ptlink = ptotherbranch->LINK; ptlink->NEXT != NULL; ptlink = ptlink->NEXT);
1611 locon_abl = createAtom(ptlink->ULINK.LOCON->NAME);
1612 otherbranch_bdd = applyBinBdd(AND, otherbranch_bdd, ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, locon_abl));
1613 freeExpr(locon_abl);
1614 if (yagTestSatisfy(badbranch_bdd, otherbranch_bdd)) ptbranch->TYPE |= CNS_NOT_UP;
1615 }
1616 }
1617 if ((ptbranch->TYPE & CNS_VSS_DEGRADED) == CNS_VSS_DEGRADED) {
1618 badbranch_bdd = (pNode)getptype(ptbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1619 for (ptlink = ptbranch->LINK; ptlink->NEXT != NULL; ptlink = ptlink->NEXT);
1620 locon_abl = createAtom(ptlink->ULINK.LOCON->NAME);
1621 badbranch_bdd = applyBinBdd(AND, badbranch_bdd, notBdd(ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, locon_abl)));
1622 freeExpr(locon_abl);
1623 for (ptotherbranch = ptcone->BRVSS; ptotherbranch; ptotherbranch = ptotherbranch->NEXT) {
1624 if ((ptotherbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1625 if ((ptotherbranch->TYPE & CNS_DEGRADED) == CNS_DEGRADED || yagCountLinks(ptotherbranch->LINK) > 3) continue;
1626 otherbranch_bdd = (pNode)getptype(ptotherbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1627 if (yagTestSatisfy(badbranch_bdd, otherbranch_bdd)) ptbranch->TYPE |= CNS_NOT_DOWN;
1628 }
1629 for (ptotherbranch = ptcone->BREXT; ptotherbranch; ptotherbranch = ptotherbranch->NEXT) {
1630 if ((ptotherbranch->TYPE & CNS_NOT_FUNCTIONAL) != 0) continue;
1631 if ((ptotherbranch->TYPE & CNS_VSS_DEGRADED) == CNS_VSS_DEGRADED || yagCountLinks(ptotherbranch->LINK) > 4) continue;
1632 otherbranch_bdd = (pNode)getptype(ptotherbranch->USER, YAG_BRANCHBDD_PTYPE)->DATA;
1633 for (ptlink = ptotherbranch->LINK; ptlink->NEXT != NULL; ptlink = ptlink->NEXT);
1634 locon_abl = createAtom(ptlink->ULINK.LOCON->NAME);
1635 otherbranch_bdd = applyBinBdd(AND, otherbranch_bdd, notBdd(ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, locon_abl)));
1636 freeExpr(locon_abl);
1637 if (yagTestSatisfy(badbranch_bdd, otherbranch_bdd)) ptbranch->TYPE |= CNS_NOT_DOWN;
1638 }
1639 }
1640 }
1641 for (ptbranch = ptcone->BREXT; ptbranch; ptbranch = ptbranch->NEXT) {
1642 if ((ptbranch->TYPE & (CNS_VDD_DEGRADED|CNS_VSS_DEGRADED|CNS_NOT_UP|CNS_NOT_DOWN)) == (CNS_VDD_DEGRADED|CNS_VSS_DEGRADED|CNS_NOT_UP|CNS_NOT_DOWN)) {
1643 ptbranch->TYPE |= CNS_NOT_FUNCTIONAL;
1644 ptbranch->TYPE &= ~(CNS_NOT_UP|CNS_NOT_DOWN);
1645 }
1646 }
1647 }
1648
1649 /* Clean branch conductance functions */
1650 if (bad_vdd) {
1651 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1652 ptbranch->USER = testanddelptype(ptbranch->USER, YAG_BRANCHBDD_PTYPE);
1653 }
1654 }
1655 if (bad_vss) {
1656 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1657 ptbranch->USER = testanddelptype(ptbranch->USER, YAG_BRANCHBDD_PTYPE);
1658 }
1659 }
1660 if (bad_vdd || bad_vss) {
1661 for (ptbranch = ptcone->BREXT; ptbranch; ptbranch = ptbranch->NEXT) {
1662 ptbranch->USER = testanddelptype(ptbranch->USER, YAG_BRANCHBDD_PTYPE);
1663 }
1664 }
1665
1666 yagDeleteConeGraph(YAG_CONTEXT->YAG_CONE_GRAPH);
1667 YAG_CONTEXT->YAG_CONE_GRAPH = savegraph;
1668 YAG_CONTEXT->YAG_CURCIRCUIT = savecircuit;
1669 YAG_CONTEXT->YAG_DEPTH = save_depth;
1670 }
1671