Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / yagle / yagle / yag_latch.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI Alliance */
4 /* */
5 /* Produit : YAGLE v3.50 */
6 /* Fichier : yag_latch.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 : 09/08/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 locon_list *yagCheckNextCon(chain_list *loconchain, locon_list *ptprevcon);
23 static double yagCalcChainResistance(chain_list *transchain);
24 static chain_list *yagFindBleedTrans(losig_list *ptsig, locon_list *ptcon, char type, cone_list *ptincone);
25 static chain_list *yagMatchNOTbyLotrs (cone_list *ptcone, cone_list *ptincone, float *up_resistance, float *down_resistance);
26 static int checkLatch (cone_list *ptcone0, cone_list *ptcone1, int simple);
27 static void addLatchType (cone_list *ptcone, cone_list *feedbackcone, chain_list *feedbacktrans, int feedbacktype, int forwardtype);
28 static int checkMemory (cone_list *ptcone0, cone_list *ptcone1);
29 static int checkDiffLatch (cone_list *ptcone0, cone_list *ptcone1);
30 static int yagCheckBistable (cone_list *ptcone0, cone_list *ptcone1);
31 static int isTristate (cone_list *ptcone, cone_list *ptincone, chain_list **pttranslist);
32 static chain_list *invChain (cone_list *ptcone, chain_list *ptchain);
33
34 /*************************************************************************
35 * function yagExtractBleeder() *
36 *************************************************************************/
37
38 /* test whether a given cone has a bleeder or a level_hold on one of its inputs */
39
40 void
41 yagMarkLevelHold(cone_list *ptbleedcone, cone_list *ptcone, chain_list *transchain)
42 {
43 branch_list *ptbranch;
44 edge_list *ptbleededge;
45 link_list *ptlink;
46 cone_list *ptlinkcone;
47 branch_list *brlist[2];
48 ptype_list *ptuser;
49 chain_list *ptchain;
50 chain_list *bleeder_branches = NULL;
51 long linktype, conetype;
52 int i;
53 int isbleed;
54
55 ptbleedcone->TECTYPE &= ~CNS_DUAL_CMOS;
56 ptbleedcone->TECTYPE |= YAG_LEVELHOLD;
57 if ((ptbleedcone->TYPE & YAG_HASDUAL) != 0) {
58 ptbleedcone->TYPE &= ~YAG_HASDUAL;
59 ptuser = getptype(ptbleedcone->USER, YAG_DUALEXPR_PTYPE);
60 freeExpr((chain_list *)ptuser->DATA);
61 ptbleedcone->USER = delptype(ptbleedcone->USER, YAG_DUALEXPR_PTYPE);
62 }
63
64 ptbleededge = yagGetEdge(ptbleedcone->INCONE, ptcone);
65 if (ptbleededge) ptbleededge->TYPE |= CNS_BLEEDER;
66 brlist[0] = ptbleedcone->BRVDD;
67 brlist[1] = ptbleedcone->BRVSS;
68 for (i=0; i<2; i++) {
69 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptbranch->NEXT) {
70 linktype = ((i==0)?CNS_TPLINK:CNS_TNLINK);
71 conetype = ((i==0)?CNS_VSS:CNS_VDD);
72 isbleed = FALSE;
73 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
74 if ((ptlink->TYPE & linktype) == 0) break;
75 ptlinkcone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
76 if (ptlinkcone == ptcone) {
77 isbleed = TRUE;
78 }
79 }
80 if (ptlink == NULL && isbleed) {
81 ptbranch->TYPE |= CNS_BLEEDER|CNS_NOT_FUNCTIONAL;
82 bleeder_branches = addchain(bleeder_branches, ptbranch);
83 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
84 ptlink->ULINK.LOTRS->TYPE |= BLEEDER;
85 }
86 }
87 }
88 }
89 for (ptchain = transchain; ptchain; ptchain = ptchain->NEXT) {
90 ((lotrs_list *)ptchain->DATA)->TYPE |= BLEEDER;
91 }
92 if (bleeder_branches) {
93 ptuser = getptype(ptbleedcone->USER, CNS_BLEEDER);
94 if (ptuser) {
95 freechain((chain_list *)ptuser->DATA);
96 ptuser->DATA = bleeder_branches;
97 }
98 else ptbleedcone->USER = addptype(ptbleedcone->USER, CNS_BLEEDER, bleeder_branches);
99 }
100 }
101
102 static void
103 yagFclMarkTrans(lotrs_list *ptlotrs, long type)
104 {
105 ptype_list *ptuser;
106
107 if ((ptuser = getptype(ptlotrs->USER, FCL_TRANSFER_PTYPE)) != NULL) {
108 ptuser->DATA = (void *) ((long) ptuser->DATA | type);
109 }
110 else ptlotrs->USER = addptype(ptlotrs->USER, FCL_TRANSFER_PTYPE, (void *) type);
111 }
112
113 static void
114 yagFclMarkSig(losig_list *ptlosig, long type)
115 {
116 ptype_list *ptuser;
117
118 if ((ptuser = getptype(ptlosig->USER, FCL_TRANSFER_PTYPE)) != NULL) {
119 ptuser->DATA = (void *) ((long) ptuser->DATA | type);
120 }
121 else ptlosig->USER = addptype(ptlosig->USER, FCL_TRANSFER_PTYPE, (void *) type);
122 }
123
124 /* count connected transistors ignoring parallel instances and bulks*/
125 int
126 yagCountConnections(chain_list *loconchain, int only_source_drain)
127 {
128 chain_list *ptchain;
129 locon_list *ptlocon;
130 lotrs_list *pttrans;
131 ptype_list *ptuser;
132 int count = 0;
133
134 for (ptchain = loconchain; ptchain; ptchain = ptchain->NEXT) {
135 ptlocon = (locon_list *)ptchain->DATA;
136 if (ptlocon->TYPE == 'T') {
137 if (ptlocon->NAME == CNS_BULKNAME) continue;
138 if (ptlocon->NAME == CNS_GRIDNAME && only_source_drain) continue;
139 pttrans = (lotrs_list *)ptlocon->ROOT;
140 if (pttrans->GRID == NULL) continue;
141 if ((ptuser = getptype(pttrans->USER, FCL_TRANSFER_PTYPE)) != NULL) {
142 if (((long)ptuser->DATA & FCL_NEVER) != 0) continue;
143 }
144 if (getptype(pttrans->USER, MBK_TRANS_MARK) != NULL) continue;
145 count++;
146 }
147 else if (!only_source_drain) count++;
148 }
149 return count;
150 }
151
152 /* Return the connector of unique possible next transistor in bleeder chain, null otherwise */
153 static locon_list *
154 yagCheckNextCon(chain_list *loconchain, locon_list *ptprevcon)
155 {
156 chain_list *ptchain;
157 locon_list *ptlocon, *ptnextcon = NULL;
158 lotrs_list *pttrans;
159
160 for (ptchain = loconchain; ptchain; ptchain = ptchain->NEXT) {
161 ptlocon = (locon_list *)ptchain->DATA;
162 if (ptlocon == ptprevcon) continue;
163 if (ptlocon->TYPE == 'T') {
164 if (ptlocon->NAME == CNS_BULKNAME) continue;
165 if (ptlocon->NAME == CNS_GRIDNAME) return NULL;
166 pttrans = (lotrs_list *)ptlocon->ROOT;
167 if (getptype(pttrans->USER, MBK_TRANS_MARK) != NULL) continue;
168 }
169 else return NULL;
170 if (!ptnextcon) ptnextcon = ptlocon;
171 else return NULL;
172 }
173 return ptnextcon;
174 }
175
176 /* Return a list of transistor making bleeder branch of required type */
177 static chain_list *
178 yagFindBleedTrans(losig_list *ptsig, locon_list *ptcon, char type, cone_list *ptincone)
179 {
180 chain_list *visit_list = NULL;
181 chain_list *transchain = NULL;
182 chain_list *loconchain;
183 losig_list *ptcurrentsig, *ptnextsig;
184 locon_list *ptprevcon;
185 cone_list *ptdriver;
186 lotrs_list *pttrans;
187 ptype_list *ptuser;
188 int found = FALSE, done = FALSE;
189 int bleeder, resistance;
190 char supply_type;
191
192 visit_list = addchain(visit_list, ptsig);
193 ptcurrentsig = ptsig;
194 ptprevcon = NULL;
195 supply_type = ((type == CNS_TN)?CNS_SIGVSS:CNS_SIGVDD);
196
197 do {
198 bleeder = FALSE; resistance = FALSE;
199 pttrans = (lotrs_list *)ptcon->ROOT;
200 /* check for NEVER directive on transistor */
201 if ((ptuser = getptype(pttrans->USER, FCL_TRANSFER_PTYPE)) != NULL) {
202 if (((long)ptuser->DATA & FCL_NEVER) != 0) {
203 found = FALSE;
204 break;
205 }
206 }
207
208 /* filter transistors without driver */
209 if (pttrans->GRID == NULL) {
210 found = FALSE;
211 break;
212 }
213
214 if (pttrans->SOURCE->SIG == ptcurrentsig) {
215 ptnextsig = pttrans->DRAIN->SIG;
216 ptprevcon = pttrans->DRAIN;
217 }
218 else {
219 ptnextsig = pttrans->SOURCE->SIG;
220 ptprevcon = pttrans->SOURCE;
221 }
222 if (yagGetChain(visit_list, ptnextsig) || yagCountChains(visit_list) > 4) {
223 found = FALSE;
224 break;
225 }
226 visit_list = addchain(visit_list, ptnextsig);
227 ptdriver = (cone_list *)pttrans->GRID;
228 if ((pttrans->TYPE & type) == type && ptdriver == ptincone) {
229 bleeder = TRUE;
230 }
231 else if (((pttrans->TYPE & CNS_TN) == CNS_TN && (ptdriver->TYPE & CNS_VDD) == CNS_VDD)
232 || ((pttrans->TYPE & CNS_TP) == CNS_TP && (ptdriver->TYPE & CNS_VSS) == CNS_VSS)) {
233 resistance = TRUE;
234 }
235 if (bleeder) found = TRUE;
236 if (bleeder || resistance) {
237 transchain = addchain(transchain, pttrans);
238 if (ptnextsig->TYPE == supply_type) {
239 done = TRUE;
240 }
241 else if (ptnextsig->TYPE != CNS_SIGINT) {
242 found = FALSE;
243 done = TRUE;
244 }
245 else {
246 ptcurrentsig = ptnextsig;
247 loconchain = (chain_list *) getptype(ptcurrentsig->USER, LOFIGCHAIN)->DATA;
248 if ((ptcon = yagCheckNextCon(loconchain, ptprevcon)) == NULL) found = FALSE;
249 }
250 }
251 else {
252 found = FALSE;
253 done = TRUE;
254 }
255 } while (ptcon && !done);
256
257 freechain(visit_list);
258 if (!found) {
259 freechain(transchain);
260 transchain = NULL;
261 }
262 return transchain;
263 }
264
265 static double
266 yagCalcChainResistance(chain_list *transchain)
267 {
268 double resistance = 0.0;
269 lotrs_list *ptlotrs;
270 chain_list *ptchain;
271
272 for (ptchain = transchain; ptchain; ptchain = ptchain->NEXT) {
273 ptlotrs = (lotrs_list *)ptchain->DATA;
274 resistance += (ptlotrs->LENGTH / ptlotrs->WIDTH);
275 }
276 return resistance;
277 }
278
279 static chain_list *
280 yagMatchNOTbyLotrs(cone_list *ptcone, cone_list *ptincone, float *up_resistance, float *down_resistance)
281 {
282 losig_list *ptsig;
283 locon_list *ptcon;
284 edge_list *ptinput;
285 cone_list *testinput;
286 branch_list *ptbranch;
287 link_list *ptlink;
288 float up_conductance = 0.0, down_conductance = 0.0;
289 chain_list *loconchain, *ptchain, *bleedtranschain, *transchain = NULL;
290 chain_list *up_branches = NULL, *down_branches = NULL;
291
292 int count;
293 int found_nmos = FALSE, found_pmos = FALSE;
294
295 ptsig = (losig_list *)getptype(ptcone->USER, CNS_SIGNAL)->DATA;
296 if (ptsig->TYPE == CNS_SIGVDD || ptsig->TYPE == CNS_SIGVSS) return NULL;
297
298 /* Dual cone already extracted */
299 if ((ptcone->TECTYPE & CNS_DUAL_CMOS) == CNS_DUAL_CMOS) {
300 count = 0;
301 for (ptinput = ptcone->INCONE; ptinput; ptinput = ptinput->NEXT) {
302 if ((ptinput->TYPE & CNS_EXT) == CNS_EXT) continue;
303 if ((ptinput->TYPE & CNS_POWER) == CNS_POWER) continue;
304 count++;
305 testinput = ptinput->UEDGE.CONE;
306 }
307 if (count == 1 && testinput == ptincone) {
308 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
309 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
310 transchain = addchain(transchain, ptlink->ULINK.LOTRS);
311 }
312 up_branches = addchain(up_branches, ptbranch);
313 }
314 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
315 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
316 transchain = addchain(transchain, ptlink->ULINK.LOTRS);
317 }
318 down_branches = addchain(down_branches, ptbranch);
319 }
320 *up_resistance = yagCalcParallelResistance(up_branches);
321 *down_resistance = yagCalcParallelResistance(down_branches);
322 freechain(up_branches);
323 freechain(down_branches);
324 return transchain;
325 }
326 return NULL;
327 }
328
329 /* General case of no cone */
330 loconchain = (chain_list *) getptype(ptsig->USER, LOFIGCHAIN)->DATA;
331 for (ptchain = loconchain; ptchain; ptchain = ptchain->NEXT) {
332 ptcon = (locon_list *)ptchain->DATA;
333 if (ptcon->TYPE == 'T') {
334 if (ptcon->NAME == CNS_GRIDNAME) continue;
335 if (ptcon->NAME == CNS_BULKNAME) continue;
336 bleedtranschain = yagFindBleedTrans(ptsig, ptcon, CNS_TN, ptincone);
337 if (bleedtranschain) {
338 found_nmos = TRUE;
339 transchain = append(transchain, bleedtranschain);
340 down_conductance += 1 / yagCalcChainResistance(bleedtranschain);
341 }
342 bleedtranschain = yagFindBleedTrans(ptsig, ptcon, CNS_TP, ptincone);
343 if (bleedtranschain) {
344 found_pmos = TRUE;
345 transchain = append(transchain, bleedtranschain);
346 up_conductance += 1 / (2.3 * yagCalcChainResistance(bleedtranschain));
347 }
348 }
349 }
350 if (found_nmos && found_pmos) {
351 *up_resistance = 1/up_conductance;
352 *down_resistance = 1/down_conductance;
353 return transchain;
354 }
355 if (transchain) freechain(transchain);
356 return NULL;
357 }
358
359 static int
360 checkStrictLevelHold(cone_list *ptcone, chain_list *transchain)
361 {
362 losig_list *ptsig;
363 lotrs_list *pttrans;
364 locon_list *ptlocon;
365 chain_list *loconchain, *ptchain;
366 ptype_list *ptuser;
367
368 /* Cone on external pin cannot be a strict level-hold */
369 if ((ptcone->TYPE & CNS_EXT) == CNS_EXT) return FALSE;
370
371 /* Check that all gate connections are due to feedback */
372 ptsig = (losig_list *)getptype(ptcone->USER, CNS_SIGNAL)->DATA;
373 loconchain = (chain_list *) getptype(ptsig->USER, LOFIGCHAIN)->DATA;
374
375 for (ptchain = loconchain; ptchain; ptchain = ptchain->NEXT) {
376 ptlocon = (locon_list *)ptchain->DATA;
377 if (ptlocon->NAME != CNS_GRIDNAME) continue;
378 pttrans = ptlocon->ROOT;
379 if ((ptuser = getptype(pttrans->USER, FCL_TRANSFER_PTYPE)) != NULL) {
380 if (((long)ptuser->DATA & FCL_NEVER) != 0) continue;
381 }
382 if (getptype(pttrans->USER, MBK_TRANS_MARK) != NULL) continue;
383 if (yagGetChain(transchain, pttrans) == NULL) return FALSE;
384 }
385
386 /* Check number of source/drain connections */
387 if (yagCountConnections(loconchain, TRUE) == yagCountBranches(ptcone)) return TRUE;
388 return FALSE;
389 }
390
391 void
392 yagExtractBleeder(inffig_list *ifl, cone_list *ptcone)
393 {
394 losig_list *ptsig, *ptbleedsig;
395 edge_list *ptinput;
396 cone_list *ptbleedcone;
397 locon_list *ptcon;
398 losig_list *ptsig1, *ptsig2;
399 lotrs_list *pttrans, *ptcomtrans1, *ptcomtrans2, *ptcuttrans;
400 chain_list *loconchain, *bleedconchain, *ptchain, *transchain, *looptranschain;
401 float upres, dnres, loopupres, loopdnres, ratio;
402 chain_list *bleedtranslist = NULL;
403 chain_list *newchain;
404 long bleedtype = 0;
405 ht *translist;
406 int found = FALSE;
407 int isLevelHold = FALSE;
408
409
410 avt_log(LOGYAG,1, "Checking for bled input on cone '%s' : ", ptcone->NAME);
411
412 ptsig = (losig_list *)getptype(ptcone->USER, CNS_SIGNAL)->DATA;
413 loconchain = (chain_list *) getptype(ptsig->USER, LOFIGCHAIN)->DATA;
414
415 if (YAG_CONTEXT->YAG_DETECT_LEVELHOLD || YAG_CONTEXT->YAG_DETECT_SIMPLE_MEMSYM) {
416 for (ptinput = ptcone->INCONE; ptinput && (ptinput->TYPE & CNS_POWER) == CNS_POWER; ptinput = ptinput->NEXT);
417 if (!ptinput) return;
418 ptbleedcone = ptinput->UEDGE.CONE;
419 looptranschain = yagMatchNOTbyLotrs(ptcone, ptbleedcone, &loopupres, &loopdnres);
420 if (looptranschain == NULL) return;
421 freechain(looptranschain);
422 if ((transchain = yagMatchNOTbyLotrs(ptbleedcone, ptcone, &upres, &dnres)) != NULL) {
423 isLevelHold = checkStrictLevelHold(ptcone, transchain);
424 if (!isLevelHold && YAG_CONTEXT->YAG_DETECT_LEVELHOLD != 2) {
425 ratio = (V_FLOAT_TAB[__YAGLE_LATCHLOOP_RATIO].VALUE > 1)?V_FLOAT_TAB[__YAGLE_LATCHLOOP_RATIO].VALUE:1.5;
426 isLevelHold = (yagCountConnections(loconchain, TRUE) == yagCountBranches(ptcone)) && (upres > ratio*loopupres);
427 }
428 if (isLevelHold) {
429 yagMarkLevelHold(ptbleedcone, ptcone, transchain);
430 freechain(transchain);
431 avt_log(LOGYAG,1, "LEVEL-HOLD FOUND\n");
432 return;
433 }
434 else if (YAG_CONTEXT->YAG_DETECT_SIMPLE_MEMSYM) {
435 ptcomtrans1 = NULL;
436 ptcomtrans2 = NULL;
437 ptcuttrans = NULL;
438 ptbleedsig = (losig_list *)getptype(ptbleedcone->USER, CNS_SIGNAL)->DATA;
439 for (ptchain = loconchain; ptchain; ptchain = ptchain->NEXT) {
440 ptcon = (locon_list *) ptchain->DATA;
441 if (ptcon->TYPE != 'T') continue;
442 if (ptcon->NAME == CNS_GRIDNAME) continue;
443 if (ptcon->NAME == CNS_BULKNAME) continue;
444 pttrans = (lotrs_list *) ptcon->ROOT;
445 if ((cone_list *)pttrans->GRID == ptbleedcone) continue;
446 if (!ptcomtrans1) ptcomtrans1 = pttrans;
447 else break;
448 }
449 if (!ptchain && ptcomtrans1) {
450 if (ptcomtrans1->DRAIN->SIG == ptsig) ptsig1 = ptcomtrans1->SOURCE->SIG;
451 else ptsig1 = ptcomtrans1->DRAIN->SIG;
452 for (ptchain = (chain_list *)getptype(ptbleedsig->USER, LOFIGCHAIN)->DATA; ptchain; ptchain = ptchain->NEXT) {
453 ptcon = (locon_list *) ptchain->DATA;
454 if (ptcon->TYPE != 'T') continue;
455 if (ptcon->NAME == CNS_GRIDNAME) continue;
456 if (ptcon->NAME == CNS_BULKNAME) continue;
457 pttrans = (lotrs_list *) ptcon->ROOT;
458 if ((cone_list *)pttrans->GRID == ptcone) continue;
459 if (!ptcomtrans2) ptcomtrans2 = pttrans;
460 else break;
461 }
462 if (!ptchain && ptcomtrans2 && (ptcomtrans2->GRID == ptcomtrans1->GRID)) {
463 if (ptcomtrans2->DRAIN->SIG == ptsig) ptsig2 = ptcomtrans2->SOURCE->SIG;
464 else ptsig2 = ptcomtrans2->DRAIN->SIG;
465 for (ptchain = (chain_list *)getptype(ptsig1->USER, LOFIGCHAIN)->DATA; ptchain; ptchain = ptchain->NEXT) {
466 ptcon = (locon_list *) ptchain->DATA;
467 if (ptcon->TYPE != 'T') continue;
468 if (ptcon->NAME == CNS_GRIDNAME) continue;
469 if (ptcon->NAME == CNS_BULKNAME) continue;
470 pttrans = (lotrs_list *) ptcon->ROOT;
471 if ((pttrans->SOURCE->SIG == ptsig1 && pttrans->DRAIN->SIG == ptsig2)
472 || (pttrans->DRAIN->SIG == ptsig1 && pttrans->SOURCE->SIG == ptsig2)) {
473 ptcuttrans = pttrans;
474 }
475 }
476 ptcone->TYPE |= CNS_LATCH|CNS_MEMSYM;
477 ptinput = yagGetEdge(ptcone->INCONE, ptbleedcone);
478 if (ptinput) ptinput->TYPE |= CNS_MEMSYM;
479 ptinput = yagGetEdge(ptbleedcone->INCONE, ptcone);
480 if (ptinput) ptinput->TYPE |= CNS_MEMSYM;
481 ptbleedcone->TYPE |= CNS_LATCH|CNS_MEMSYM;
482 ptcone->USER = addptype(ptcone->USER, YAG_MEMORY_PTYPE, ptbleedcone);
483 ptbleedcone->USER = addptype(ptbleedcone->USER, YAG_MEMORY_PTYPE, ptcone);
484 yagFclMarkTrans(ptcomtrans1, FCL_COMMAND);
485 yagFclMarkTrans(ptcomtrans2, FCL_COMMAND);
486 if (ptcuttrans) yagFclMarkTrans(ptcuttrans, FCL_NEVER);
487 avt_log(LOGYAG,1, "SIMPLE MEMSYM FOUND\n");
488 freechain(transchain);
489 return;
490 }
491 }
492 }
493 freechain(transchain);
494 }
495 }
496
497 for (ptinput = ptcone->INCONE; ptinput; ptinput = ptinput->NEXT) {
498 if ((ptinput->TYPE & CNS_EXT) == CNS_EXT) continue;
499 ptbleedcone = ptinput->UEDGE.CONE;
500 if ((ptbleedcone->TYPE & YAG_PARTIAL) != YAG_PARTIAL) continue;
501 ptbleedsig = (losig_list *)getptype(ptbleedcone->USER, CNS_SIGNAL)->DATA;
502 translist = yagGetTransList(ifl, ptbleedcone, ptbleedsig);
503 bleedconchain = (chain_list *) getptype(ptbleedsig->USER, LOFIGCHAIN)->DATA;
504 for (ptchain = bleedconchain; ptchain; ptchain = ptchain->NEXT) {
505 ptcon = (locon_list *) ptchain->DATA;
506 if (ptcon->TYPE != 'T') continue;
507 if (ptcon->NAME == CNS_GRIDNAME) continue;
508 if (ptcon->NAME == CNS_BULKNAME) continue;
509 pttrans = (lotrs_list *) ptcon->ROOT;
510 if (gethtitem(translist, pttrans) == EMPTYHT) continue;
511 if ((newchain = yagFindBleedTrans(ptbleedsig, ptcon, CNS_TN, ptcone)) != NULL) {
512 bleedtype |= CNS_VSS;
513 bleedtranslist = append(bleedtranslist, newchain);
514 }
515 if ((newchain = yagFindBleedTrans(ptbleedsig, ptcon, CNS_TP, ptcone)) != NULL) {
516 bleedtype |= CNS_VDD;
517 bleedtranslist = append(bleedtranslist, newchain);
518 }
519 }
520
521 for (ptchain = loconchain; ptchain; ptchain = ptchain->NEXT) {
522 ptcon = (locon_list *) ptchain->DATA;
523 if (ptcon->TYPE != 'T') continue;
524 if (ptcon->NAME != CNS_GRIDNAME) continue;
525 pttrans = (lotrs_list *) ptcon->ROOT;
526 if (gethtitem(translist, pttrans) == EMPTYHT) continue;
527 if (yagGetChain(bleedtranslist, pttrans) == NULL) break;
528 }
529
530 if (ptchain == NULL) {
531 if (bleedtype == CNS_VDD || bleedtype == CNS_VSS) {
532 for (ptchain = bleedtranslist; ptchain; ptchain = ptchain->NEXT) {
533 ((lotrs_list *) ptchain->DATA)->TYPE |= BLEEDER;
534 found = TRUE;
535 }
536 }
537 }
538 delht(translist);
539 freechain(bleedtranslist);
540 bleedtranslist = NULL;
541 }
542 if (found)
543 avt_log(LOGYAG,1, "FOUND\n");
544 else
545 avt_log(LOGYAG,1, "NOT FOUND\n");
546 }
547
548 /****************************************************************************
549 * function yagDetectBleeder() *
550 ****************************************************************************/
551
552 /* test for any bleeders missed in the initial bleeder detection phase */
553
554 void
555 yagDetectBleeder(cone_list *ptcone)
556 {
557 branch_list *ptbranch;
558 link_list *ptlink;
559 cone_list *loopcone;
560 chain_list *bleeders = NULL;
561 chain_list *maybe = NULL;
562 chain_list *ptchain;
563 edge_list *ptedge;
564 branch_list *brlist[4];
565 long looptype;
566 int i;
567
568 brlist[0] = ptcone->BRVDD;
569 brlist[1] = ptcone->BRVSS;
570 brlist[2] = ptcone->BREXT;
571 brlist[3] = ptcone->BRGND;
572
573 for (ptedge = ptcone->INCONE; ptedge; ptedge = ptedge->NEXT) {
574 if ((ptedge->TYPE & CNS_CONE) == 0) continue;
575 if ((ptedge->TYPE & CNS_BLEEDER) == CNS_BLEEDER) continue;
576 if ((ptedge->TYPE & CNS_FEEDBACK) == CNS_FEEDBACK) continue;
577 loopcone = ptedge->UEDGE.CONE;
578 looptype = 0;
579 maybe = NULL;
580 if (yagGetEdge(loopcone->INCONE, ptcone) != NULL) {
581 if ((yagMatchInversion(loopcone, ptcone, NULL, NULL) != PM_UNKNOWN)
582 || (YAG_CONTEXT->YAG_BLEEDER_STRICTNESS == 0 && (loopcone->TECTYPE & CNS_CMOS) != 0)) {
583 if (YAG_CONTEXT->YAG_BLEEDER_STRICTNESS > 1 && yagCountConeEdges(loopcone->INCONE) != 1) continue;
584 for (i=0; i<4; i++) {
585 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptbranch->NEXT) {
586 if ((ptbranch->TYPE & (CNS_VDD|CNS_VSS)) != 0 && yagCountActiveLinks(ptbranch->LINK) == 1) {
587 for (ptlink = ptbranch->LINK; (ptlink->TYPE & CNS_RESIST) == CNS_RESIST; ptlink = ptlink->NEXT);
588 if ((cone_list *)(ptlink->ULINK.LOTRS->GRID) == loopcone) {
589 if ((ptbranch->TYPE & looptype) != looptype) {
590 looptype = -1L;
591 break;
592 }
593 looptype |= (ptbranch->TYPE & (CNS_VDD|CNS_VSS));
594 maybe = addchain(maybe, ptbranch);
595 }
596 }
597 else {
598 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
599 if ((cone_list *)(ptlink->ULINK.LOTRS->GRID) == loopcone) {
600 if ((ptbranch->TYPE & looptype) != looptype) {
601 looptype = -1L;
602 break;
603 }
604 looptype |= (ptbranch->TYPE & (CNS_VDD|CNS_VSS));
605 }
606 }
607 if (looptype == -1L) break;
608 }
609 }
610 if (looptype == -1L) break;
611 }
612 if ((looptype == CNS_VDD || looptype == CNS_VSS) && maybe != NULL) {
613 bleeders = append(bleeders, maybe);
614 ptedge->TYPE |= CNS_BLEEDER;
615 }
616 else freechain(maybe);
617 }
618 }
619 }
620
621 if (bleeders != NULL) {
622 for (ptchain = bleeders; ptchain; ptchain = ptchain->NEXT) {
623 ptbranch = (branch_list *)(ptchain->DATA);
624 ptbranch->TYPE |= CNS_BLEEDER|CNS_NOT_FUNCTIONAL;
625 ptlink = ptbranch->LINK;
626 ptlink->ULINK.LOTRS->TYPE |= BLEEDER;
627 }
628 ptcone->USER = addptype(ptcone->USER, CNS_BLEEDER, bleeders);
629 ptcone->TYPE |= YAG_MARK;
630 }
631 }
632
633 /****************************************************************************
634 * function yagRmvThruBleed() *
635 ****************************************************************************/
636
637 /* remove branches terminating with bleed transistors */
638 /* and branches whose final link input is a bleeder input */
639
640 void
641 yagRmvThruBleed(cone_list *ptcone)
642 {
643 branch_list *ptbranch;
644 branch_list *ptnextbranch;
645 link_list *ptlink;
646 branch_list *brlist[2];
647 cone_list *ptincone;
648 edge_list *ptinedge;
649 int changed = FALSE;
650 int i;
651
652 brlist[0] = ptcone->BRVDD;
653 brlist[1] = ptcone->BRVSS;
654
655 for (i=0; i<2; i++) {
656 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptnextbranch) {
657 ptnextbranch = ptbranch->NEXT;
658 if ((ptbranch->TYPE & CNS_BLEEDER) == CNS_BLEEDER) continue;
659 ptlink = ptbranch->LINK;
660 if (ptlink->NEXT == NULL) continue;
661 for (ptlink = ptlink->NEXT; ptlink->NEXT != NULL; ptlink = ptlink->NEXT);
662 if ((ptlink->ULINK.LOTRS->TYPE & BLEEDER) != 0) {
663 yagDestroyBranch(ptcone, ptbranch);
664 changed = TRUE;
665 continue;
666 }
667 ptincone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
668 ptinedge = yagGetEdge(ptcone->INCONE, ptincone);
669 if (ptinedge != NULL && (ptinedge->TYPE & CNS_BLEEDER) == CNS_BLEEDER) {
670 yagDestroyBranch(ptcone, ptbranch);
671 changed = TRUE;
672 }
673 }
674 }
675 if (changed) ptcone->TYPE |= YAG_MARK;
676 }
677
678 /*************************************************************************
679 * function yagMarkLoopConf() *
680 *************************************************************************/
681
682 void
683 yagMarkLoopConf(cone_list *ptcone)
684 {
685 edge_list *ptedgelist0, *ptedgelist1;
686 edge_list *ptedge0, *ptedge1;
687 cone_list *ptincone;
688
689 if ((ptcone->TYPE & YAG_LOOPCONF) != 0) return;
690 if ((ptcone->TYPE & YAG_PARTIAL) == 0) return;
691
692 ptedgelist0 = (edge_list *)getptype(ptcone->USER, YAG_INPUTS_PTYPE)->DATA;
693 for (ptedge0 = ptedgelist0; ptedge0; ptedge0 = ptedge0->NEXT) {
694 if ((ptedge0->TYPE & CNS_EXT) != 0) continue;
695 if ((ptedge0->TYPE & CNS_BLEEDER) == CNS_BLEEDER) continue;
696 ptincone = ptedge0->UEDGE.CONE;
697 if ((ptincone->TYPE & YAG_PARTIAL) != 0) {
698 ptedgelist1 = (edge_list *)getptype(ptincone->USER, YAG_INPUTS_PTYPE)->DATA;
699 }
700 else ptedgelist1 = ptincone->INCONE;
701 ptedge1 = yagGetEdge(ptedgelist1, ptcone);
702 if (ptedge1 != NULL) {
703 if ((ptedge1->TYPE & CNS_BLEEDER) != CNS_BLEEDER) {
704 ptcone->TYPE |= YAG_LOOPCONF;
705 if ((ptincone->TYPE & YAG_PARTIAL) != 0) ptincone->TYPE |= YAG_LOOPCONF;
706 break;
707 }
708 }
709 }
710 }
711
712 /*************************************************************************
713 * function yagMatchLatch() *
714 *************************************************************************/
715
716 /* general latch pattern-matching entry point */
717
718 void
719 yagMatchLatch(cone_list *ptcone)
720 {
721 chain_list *looplist;
722 chain_list *ptchain;
723 cone_list *loopcone;
724 int found;
725
726 if ((looplist = yagCheckLoop(ptcone, FALSE)) != NULL) {
727 for (ptchain = looplist; ptchain; ptchain = ptchain->NEXT) {
728 loopcone = (cone_list *)ptchain->DATA;
729 if ((loopcone->TECTYPE & YAG_NOTLATCH) == YAG_NOTLATCH) continue;
730 avt_log(LOGYAG,1, "Loop detected between '%s' and '%s'\n",ptcone->NAME,loopcone->NAME);
731 found = checkLatch(ptcone, loopcone, FALSE);
732 if (found) avt_log(LOGYAG,1, "\tLatch found\n");
733 if (!found) {
734 found = checkMemory(ptcone, loopcone);
735 if (found) avt_log(LOGYAG,1, "\tMemory found\n");
736 }
737 if (!found) {
738 found = checkDiffLatch(ptcone, loopcone);
739 if (found) avt_log(LOGYAG,1, "\tMemory found\n");
740 }
741 if (!found) {
742 avt_log(LOGYAG,1, "\tNothing found\n");
743 }
744 }
745 }
746 freechain(looplist);
747 }
748
749 void
750 yagMatchSimpleLatch(cone_list *ptcone)
751 {
752 chain_list *looplist;
753 chain_list *ptchain;
754 cone_list *loopcone;
755 int found;
756
757 if ((looplist = yagCheckLoop(ptcone, FALSE)) != NULL) {
758 for (ptchain = looplist; ptchain; ptchain = ptchain->NEXT) {
759 loopcone = (cone_list *)ptchain->DATA;
760 if ((loopcone->TECTYPE & YAG_NOTLATCH) == YAG_NOTLATCH) continue;
761 avt_log(LOGYAG,1, "Loop detected between '%s' and '%s'\n",ptcone->NAME,loopcone->NAME);
762 found = checkLatch(ptcone, loopcone, TRUE);
763 if (!found) {
764 avt_log(LOGYAG,1, "\tNothing found\n");
765 }
766 }
767 }
768 freechain(looplist);
769 }
770
771 /*************************************************************************
772 * function checkLoop() *
773 *************************************************************************/
774
775 /* check if given cone is part of a two cone loop */
776 /* and return the other cone of the loop. */
777
778 chain_list *
779 yagCheckLoop(ptcone, fIgnoreFalse)
780 cone_list *ptcone;
781 int fIgnoreFalse;
782 {
783 edge_list *ptinput;
784 edge_list *ptloopin;
785 cone_list *ptincone;
786 chain_list *looplist = NULL;
787
788 for (ptinput = ptcone->INCONE; ptinput; ptinput = ptinput->NEXT) {
789 if (fIgnoreFalse && (ptinput->TYPE & YAG_FALSECONF) == YAG_FALSECONF) continue;
790 if ((ptinput->TYPE & CNS_BLEEDER) == CNS_BLEEDER) continue;
791 if ((ptinput->TYPE & CNS_FEEDBACK) == CNS_FEEDBACK) continue;
792 if ((ptinput->TYPE & CNS_EXT) == CNS_EXT) continue;
793 ptincone = ptinput->UEDGE.CONE;
794 if ((ptincone->TYPE & (CNS_LATCH|CNS_MEMSYM)) != 0) continue;
795 if ((ptloopin = yagGetEdge(ptincone->INCONE, ptcone)) != NULL) {
796 if ((ptloopin->TYPE & CNS_BLEEDER) == CNS_BLEEDER) continue;
797 looplist = addchain(looplist, ptincone);
798 }
799 }
800 return looplist;
801 }
802
803 /*************************************************************************
804 * function checkLatch() *
805 *************************************************************************/
806
807 /* test whether two cones form a standard latch */
808
809 static int
810 checkLatch(cone_list *ptcone0, cone_list *ptcone1, int simple)
811 {
812 float strength0, strength1;
813 chain_list *translist0 = NULL;
814 chain_list *translist1 = NULL;
815 chain_list *translist = NULL;
816 int type0, type1;
817
818 type1 = yagMatchInversion(ptcone1, ptcone0, &strength1, &translist1);
819 type0 = yagMatchInversion(ptcone0, ptcone1, &strength0, &translist0);
820 if (type0 == PM_UNKNOWN && type1 == PM_UNKNOWN) {
821 freechain(translist0);
822 freechain(translist1);
823 return FALSE;
824 }
825
826 if (simple) {
827 if (type0 == PM_INV && type1 == PM_INV && (ptcone1->TYPE & YAG_PARTIAL) == 0 && yagCountEdges(ptcone1->INCONE) == 1) {
828 addLatchType(ptcone0, ptcone1, translist0, type0, type1);
829 freechain(translist0);
830 freechain(translist1);
831 return TRUE;
832 }
833 else {
834 freechain(translist0);
835 freechain(translist1);
836 return FALSE;
837 }
838 }
839
840 /* check for simple double inversion case (beware if other cone is precharge) */
841 if (type0 != PM_UNKNOWN && type1 != PM_UNKNOWN) {
842 if ((strength0/strength1) < 0.8) {
843 addLatchType(ptcone0, ptcone1, translist0, type0, type1);
844 }
845 else if ((strength1/strength0) > 1.2 && (ptcone1->TYPE & CNS_PRECHARGE) == 0) {
846 addLatchType(ptcone1, ptcone0, translist1, type1, type0);
847 }
848 else if (yagCountEdges(ptcone0->INCONE) > 1 && type0 == PM_INV && yagCountEdges(ptcone1->INCONE) == 1 && type1 == PM_INV) {
849 addLatchType(ptcone0, ptcone1, translist0, type0, type1);
850 }
851 else if (yagCountEdges(ptcone0->INCONE) == 1 && type0 == PM_INV && yagCountEdges(ptcone1->INCONE) > 1 && type1 == PM_INV && (ptcone1->TYPE & CNS_PRECHARGE) == 0) {
852 addLatchType(ptcone1, ptcone0, translist1, type1, type0);
853 }
854 else {
855 freechain(translist0);
856 freechain(translist1);
857 return FALSE;
858 }
859 }
860 /* check for switched or tri-state inverter feedback */
861 else if (type0 != PM_UNKNOWN) {
862 if ((type1 = yagMatchSwitchedInversion(ptcone1, ptcone0, &translist)) != FB_UNKNOWN) {
863 addLatchType(ptcone1, ptcone0, translist, type1, type0);
864 }
865 else {
866 freechain(translist0);
867 freechain(translist1);
868 freechain(translist);
869 return FALSE;
870 }
871 }
872 else {
873 if ((type0 = yagMatchSwitchedInversion(ptcone0, ptcone1, &translist)) != FB_UNKNOWN) {
874 addLatchType(ptcone0, ptcone1, translist, type0, type1);
875 }
876 else {
877 freechain(translist0);
878 freechain(translist1);
879 freechain(translist);
880 return FALSE;
881 }
882 }
883
884 freechain(translist0);
885 freechain(translist1);
886 freechain(translist);
887 return TRUE;
888 }
889
890 /*************************************************************************
891 * function addLatchType() *
892 *************************************************************************/
893
894 /* add the necessary type fields to latch cone, branches and links */
895
896 static void
897 addLatchType(cone_list *ptcone, cone_list *feedbackcone, chain_list *feedbacktrans, int feedbacktype, int forwardtype)
898 {
899 branch_list *ptbranch;
900 branch_list *brlist[4];
901 link_list *ptlink;
902 edge_list *ptedge;
903 long latchtype;
904 int i;
905
906 ptcone->TYPE |= CNS_LATCH;
907 ptcone->TYPE |= YAG_MARK;
908
909 switch (forwardtype) {
910 case PM_INV: latchtype = FW_INV; break;
911 case PM_NAND: latchtype = FW_NAND; break;
912 case PM_NOR: latchtype = FW_NOR; break;
913 }
914 switch (feedbacktype) {
915 case PM_INV: latchtype |= FB_INV; break;
916 case PM_NAND: latchtype |= FB_NAND; break;
917 case PM_NOR: latchtype |= FB_NOR; break;
918 case PM_TRISTATE: latchtype |= FB_TRISTATE; break;
919 case PM_PASSINV: latchtype |= FB_PASSINV; break;
920 case PM_SWITCHINV: latchtype |= FB_SWITCHINV; break;
921 case PM_PASSNAND: latchtype |= FB_PASSNAND; break;
922 case PM_SWITCHNAND: latchtype |= FB_SWITCHNAND; break;
923 case PM_PASSNOR: latchtype |= FB_PASSNOR; break;
924 case PM_SWITCHNOR: latchtype |= FB_SWITCHNOR; break;
925 }
926
927 ptcone->USER = addptype(ptcone->USER, YAG_LATCHINFO_PTYPE, (void *)latchtype);
928
929 brlist[0] = ptcone->BRVDD;
930 brlist[1] = ptcone->BRVSS;
931 brlist[2] = ptcone->BREXT;
932 brlist[3] = ptcone->BRGND;
933
934 for (i=0; i<2; i++) {
935 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptbranch->NEXT) {
936 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
937 if (yagGetChain(feedbacktrans, ptlink->ULINK.LOTRS) == NULL) break;
938 }
939 if (ptlink == NULL) ptbranch->TYPE |= (CNS_NOT_FUNCTIONAL|CNS_FEEDBACK);
940 }
941 }
942
943 ptedge = yagGetEdge(ptcone->INCONE, feedbackcone);
944 ptedge->TYPE |= CNS_FEEDBACK;
945
946 for (i=0; i<3; i++) {
947 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptbranch->NEXT) {
948 if ((ptbranch->TYPE & CNS_FEEDBACK) != 0) continue;
949 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
950 if ((ptlink->TYPE & CNS_SHORT) == CNS_SHORT) continue;
951 if ((ptlink->TYPE & CNS_DIODE_UP) == CNS_DIODE_UP) continue;
952 if ((ptlink->TYPE & CNS_DIODE_DOWN) == CNS_DIODE_DOWN) continue;
953 if ((ptlink->TYPE & (CNS_TNLINK|CNS_TPLINK)) != 0) {
954 ptlink->TYPE |= CNS_COMMAND;
955 ptedge = yagGetEdge(ptcone->INCONE, (cone_list *)ptlink->ULINK.LOTRS->GRID);
956 ptedge->TYPE |= CNS_COMMAND;
957 break;
958 }
959 }
960 }
961 }
962 }
963
964 /*************************************************************************
965 * function checkMemory() *
966 *************************************************************************/
967
968 /* test whether two cones form a symmetric memory point */
969
970 static int
971 checkMemory(cone_list *ptcone0, cone_list *ptcone1)
972 {
973 cone_list *ptincone;
974 branch_list *ptbranch;
975 link_list *ptlink;
976 chain_list *ptpossiblecommands = NULL;
977 chain_list *ptcommands = NULL;
978 cone_list *ptcommand = NULL;
979 edge_list *command;
980 edge_list *ptinedge;
981 chain_list *ptchain;
982 branch_list *brlist0[4];
983 branch_list *brlist1[4];
984 int commanded = FALSE;
985 float ratio;
986 int i;
987
988 if (yagMatchNOT(ptcone0, ptcone1) == TRUE && yagMatchNOT(ptcone1, ptcone0) == TRUE) {
989 ratio = yagInverterStrength(ptcone1, ptcone0)/yagInverterStrength(ptcone0, ptcone1);
990 if (ratio > 0.8 && ratio < 1.2) {
991
992 brlist0[0] = ptcone0->BRVDD;
993 brlist0[1] = ptcone0->BRVSS;
994 brlist0[2] = ptcone0->BREXT;
995 brlist0[3] = ptcone0->BRGND;
996
997 brlist1[0] = ptcone1->BRVDD;
998 brlist1[1] = ptcone1->BRVSS;
999 brlist1[2] = ptcone1->BREXT;
1000 brlist1[3] = ptcone1->BRGND;
1001
1002 /* Generate list of possible command inputs on Cone 0 */
1003
1004 for (i=0; i<4; i++) {
1005 for (ptbranch = brlist0[i]; ptbranch; ptbranch = ptbranch->NEXT) {
1006 ptlink = ptbranch->LINK;
1007 if ((ptlink->TYPE & CNS_EXT) == CNS_EXT) continue;
1008 ptincone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1009 if (ptincone != ptcone1) {
1010 if (yagGetChain(ptpossiblecommands, ptincone) == NULL) {
1011 ptpossiblecommands = addchain(ptpossiblecommands, ptincone);
1012 }
1013 }
1014 }
1015 }
1016
1017 /* Check for command on Cone 1 identical to one on Cone 0 */
1018
1019 for (i=0; i<4; i++) {
1020 for (ptbranch = brlist1[i]; ptbranch; ptbranch = ptbranch->NEXT) {
1021 ptlink = ptbranch->LINK;
1022 if ((ptlink->TYPE & CNS_EXT) == CNS_EXT) continue;
1023 ptincone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1024 if (ptincone != ptcone0) {
1025 if (yagGetChain(ptpossiblecommands, ptincone) != NULL) {
1026 commanded = TRUE;
1027 }
1028 }
1029 }
1030 }
1031 freechain(ptpossiblecommands);
1032 if (commanded == FALSE) return FALSE;
1033
1034 /* list of commands is intersection of INCONE lists */
1035
1036 for (ptinedge = ptcone0->INCONE; ptinedge; ptinedge = ptinedge->NEXT) {
1037 if ((ptinedge->TYPE & CNS_EXT) != 0) continue;
1038 if (yagGetEdge(ptcone1->INCONE, ptinedge->UEDGE.CONE) != NULL) {
1039 ptcommands = addchain(ptcommands, ptinedge->UEDGE.CONE);
1040 }
1041 }
1042
1043 /* memory detected so mark accordingly */
1044
1045 ptcone0->TYPE |= CNS_MEMSYM;
1046 ptcone1->TYPE |= CNS_MEMSYM;
1047 ptinedge = yagGetEdge(ptcone0->INCONE, ptcone1);
1048 if (ptinedge) ptinedge->TYPE |= CNS_MEMSYM;
1049 ptinedge = yagGetEdge(ptcone1->INCONE, ptcone0);
1050 if (ptinedge) ptinedge->TYPE |= CNS_MEMSYM;
1051 ptcone0->USER = addptype(ptcone0->USER, YAG_LATCHINFO_PTYPE, (void *)(FW_INV|FB_INV));
1052 ptcone1->USER = addptype(ptcone1->USER, YAG_LATCHINFO_PTYPE, (void *)(FW_INV|FB_INV));
1053
1054 for (ptchain = ptcommands; ptchain; ptchain = ptchain->NEXT) {
1055 ptcommand = (cone_list *)ptchain->DATA;
1056 command = yagGetEdge(ptcone0->INCONE, ptcommand);
1057 command->TYPE |= CNS_COMMAND;
1058 command = yagGetEdge(ptcone1->INCONE, ptcommand);
1059 command->TYPE |= CNS_COMMAND;
1060 }
1061
1062 for (i=0; i<4; i++) {
1063 for (ptbranch = brlist0[i]; ptbranch; ptbranch = ptbranch->NEXT) {
1064 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1065 if ((ptlink->TYPE & CNS_EXT) == CNS_EXT) continue;
1066 ptincone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1067 if (ptincone != ptcone1 && yagGetChain(ptcommands, ptlink->ULINK.LOTRS->GRID) != NULL) {
1068 ptlink->TYPE |= CNS_COMMAND;
1069 }
1070 }
1071 }
1072 }
1073
1074 for (i=0; i<4; i++) {
1075 for (ptbranch = brlist1[i]; ptbranch; ptbranch = ptbranch->NEXT) {
1076 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1077 if ((ptlink->TYPE & CNS_EXT) == CNS_EXT) continue;
1078 ptincone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1079 if (ptincone != ptcone0 && yagGetChain(ptcommands, ptlink->ULINK.LOTRS->GRID) != NULL) {
1080 ptlink->TYPE |= CNS_COMMAND;
1081 }
1082 }
1083 }
1084 }
1085
1086 ptcone0->TYPE |= YAG_MARK;
1087 ptcone1->TYPE |= YAG_MARK;
1088
1089 freechain(ptcommands);
1090 return TRUE;
1091 }
1092 }
1093 return FALSE;
1094 }
1095
1096 /*************************************************************************
1097 * function checkDiffLatch() *
1098 *************************************************************************/
1099
1100 /* test whether two cones form a differential latch */
1101
1102 static int
1103 checkDiffLatch(cone_list *ptcone0, cone_list *ptcone1)
1104 {
1105 cone_list *ptincone;
1106 branch_list *ptbranch;
1107 link_list *ptlink;
1108 chain_list *ptpossiblecommands = NULL;
1109 chain_list *ptcommands = NULL;
1110 cone_list *ptcommand = NULL;
1111 edge_list *command, *ptinedge;
1112 chain_list *ptchain;
1113 branch_list *brlist0[2];
1114 branch_list *brlist1[2];
1115 float ratio;
1116 int i;
1117
1118 if (yagMatchNOT(ptcone0, ptcone1) == TRUE && yagMatchNOT(ptcone1, ptcone0) == TRUE) {
1119 ratio = yagInverterStrength(ptcone1, ptcone0)/yagInverterStrength(ptcone0, ptcone1);
1120 if (ratio > 0.8 && ratio < 1.2) {
1121
1122 brlist0[0] = ptcone0->BRVDD;
1123 brlist0[1] = ptcone0->BRVSS;
1124
1125 brlist1[0] = ptcone1->BRVDD;
1126 brlist1[1] = ptcone1->BRVSS;
1127
1128 /* Generate list of possible command inputs on Cone 0 */
1129
1130 for (ptbranch = ptcone0->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1131 ptlink = ptbranch->LINK;
1132 if (ptlink->NEXT == NULL) continue;
1133 ptlink = ptlink->NEXT;
1134 if (ptlink->NEXT != NULL) continue;
1135 if ((ptlink->TYPE & CNS_EXT) == CNS_EXT) continue;
1136 ptincone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1137 if (ptincone != ptcone1) {
1138 if (yagGetChain(ptpossiblecommands, ptincone) == NULL) {
1139 ptpossiblecommands = addchain(ptpossiblecommands, ptincone);
1140 }
1141 }
1142 }
1143
1144 /* Check for command on Cone 1 identical to one on Cone 0 */
1145
1146 for (ptbranch = ptcone1->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1147 ptlink = ptbranch->LINK;
1148 if (ptlink->NEXT == NULL) continue;
1149 ptlink = ptlink->NEXT;
1150 if (ptlink->NEXT != NULL) continue;
1151 if ((ptlink->TYPE & CNS_EXT) == CNS_EXT) continue;
1152 ptincone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1153 if (ptincone != ptcone0) {
1154 if (yagGetChain(ptpossiblecommands, ptincone) != NULL) {
1155 ptcommands = addchain(ptcommands, ptincone);
1156 }
1157 }
1158 }
1159 freechain(ptpossiblecommands);
1160
1161 if (ptcommands == NULL) return FALSE;
1162
1163 /* memory detected so mark accordingly */
1164
1165 ptcone0->TYPE |= CNS_MEMSYM;
1166 ptcone1->TYPE |= CNS_MEMSYM;
1167 ptinedge = yagGetEdge(ptcone0->INCONE, ptcone1);
1168 if (ptinedge) ptinedge->TYPE |= CNS_MEMSYM;
1169 ptinedge = yagGetEdge(ptcone1->INCONE, ptcone0);
1170 if (ptinedge) ptinedge->TYPE |= CNS_MEMSYM;
1171 ptcone0->USER = addptype(ptcone0->USER, YAG_LATCHINFO_PTYPE, (void *)(FW_INV|FB_INV|DIFF));
1172 ptcone1->USER = addptype(ptcone1->USER, YAG_LATCHINFO_PTYPE, (void *)(FW_INV|FB_INV|DIFF));
1173
1174 for (ptchain = ptcommands; ptchain; ptchain = ptchain->NEXT) {
1175 ptcommand = (cone_list *)ptchain->DATA;
1176 command = yagGetEdge(ptcone0->INCONE, ptcommand);
1177 command->TYPE |= CNS_COMMAND;
1178 command = yagGetEdge(ptcone1->INCONE, ptcommand);
1179 command->TYPE |= CNS_COMMAND;
1180 }
1181
1182 for (i=0; i<2; i++) {
1183 for (ptbranch = brlist0[i]; ptbranch; ptbranch = ptbranch->NEXT) {
1184 ptlink = ptbranch->LINK;
1185 if ((ptlink->TYPE & CNS_EXT) == CNS_EXT) continue;
1186 ptincone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1187 if (ptincone == ptcone1) continue;
1188 if (ptlink->NEXT == NULL) continue;
1189 ptlink = ptlink->NEXT;
1190 if ((ptlink->TYPE & CNS_EXT) == CNS_EXT) continue;
1191 if (yagGetChain(ptcommands, ptlink->ULINK.LOTRS->GRID) != NULL) {
1192 ptlink->TYPE |= CNS_COMMAND;
1193 }
1194 }
1195 }
1196
1197 for (i=0; i<2; i++) {
1198 for (ptbranch = brlist1[i]; ptbranch; ptbranch = ptbranch->NEXT) {
1199 ptlink = ptbranch->LINK;
1200 if ((ptlink->TYPE & CNS_EXT) == CNS_EXT) continue;
1201 ptincone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1202 if (ptincone == ptcone0) continue;
1203 if (ptlink->NEXT == NULL) continue;
1204 ptlink = ptlink->NEXT;
1205 if ((ptlink->TYPE & CNS_EXT) == CNS_EXT) continue;
1206 if (yagGetChain(ptcommands, ptlink->ULINK.LOTRS->GRID) != NULL) {
1207 ptlink->TYPE |= CNS_COMMAND;
1208 }
1209 }
1210 }
1211
1212 ptcone0->TYPE |= YAG_MARK;
1213 ptcone1->TYPE |= YAG_MARK;
1214
1215 freechain(ptcommands);
1216 return TRUE;
1217 }
1218 }
1219 return FALSE;
1220 }
1221
1222 /****************************************************************************
1223 * function yagPairMemsym(); *
1224 ****************************************************************************/
1225
1226 void
1227 yagPairMemsym(inffig_list *ifl, cone_list *ptcone)
1228 {
1229 cone_list *ptsymcone, *pttestcone;
1230 losig_list *ptsig;
1231 chain_list *looplist = NULL;
1232 chain_list *ptchain;
1233 edge_list *ptinput;
1234 edge_list *ptloopin;
1235 cone_list *ptincone;
1236 chain_list *ptinflist;
1237 char *ptsymname = NULL;
1238 int numfound = 0;
1239
1240 if (inf_GetPointer(ifl, INF_MEMSYM, "", (void **)&ptinflist)) {
1241 ptsig = (losig_list *)getptype(ptcone->USER, CNS_SIGNAL)->DATA;
1242 for (ptchain = ptinflist; ptchain; ptchain = ptchain->NEXT) {
1243 if (mbk_LosigTestREGEX(ptsig, ((inf_assoc *)ptchain->DATA)->orig)) {
1244 ptsymname = ((inf_assoc *)ptchain->DATA)->dest;
1245 }
1246 if (mbk_LosigTestREGEX(ptsig, ((inf_assoc *)ptchain->DATA)->dest)) {
1247 ptsymname = ((inf_assoc *)ptchain->DATA)->orig;
1248 }
1249 }
1250 }
1251
1252 for (ptinput = ptcone->INCONE; ptinput; ptinput = ptinput->NEXT) {
1253 if ((ptinput->TYPE & CNS_BLEEDER) == CNS_BLEEDER) continue;
1254 if ((ptinput->TYPE & CNS_EXT) == CNS_EXT) continue;
1255 ptincone = ptinput->UEDGE.CONE;
1256 if ((ptloopin = yagGetEdge(ptincone->INCONE, ptcone)) != NULL) {
1257 if ((ptloopin->TYPE & CNS_BLEEDER) == CNS_BLEEDER) continue;
1258 looplist = addchain(looplist, ptincone);
1259 }
1260 }
1261
1262 if (looplist != NULL) {
1263 for (ptchain = looplist; ptchain; ptchain = ptchain->NEXT) {
1264 pttestcone = (cone_list *)ptchain->DATA;
1265 if ((pttestcone->TYPE & CNS_MEMSYM) != 0) {
1266 if (ptsymname) {
1267 ptsig = (losig_list *)getptype(pttestcone->USER, CNS_SIGNAL)->DATA;
1268 if (mbk_LosigTestREGEX(ptsig, ptsymname)) {
1269 ptsymcone = pttestcone;
1270 numfound = 1;
1271 break;
1272 }
1273 }
1274 numfound++;
1275 ptsymcone = pttestcone;
1276 }
1277 }
1278 if (numfound == 1) {
1279 ptcone->USER = addptype(ptcone->USER, YAG_MEMORY_PTYPE, ptsymcone);
1280 ptsymcone->USER = addptype(ptsymcone->USER, YAG_MEMORY_PTYPE, ptcone);
1281 ptcone->TYPE |= CNS_LATCH;
1282 ptsymcone->TYPE |= CNS_LATCH;
1283 ptloopin = yagGetEdge(ptcone->INCONE, ptsymcone);
1284 ptloopin->TYPE |= CNS_MEMSYM;
1285 ptloopin = yagGetEdge(ptsymcone->INCONE, ptcone);
1286 ptloopin->TYPE |= CNS_MEMSYM;
1287 }
1288 freechain(looplist);
1289 }
1290 }
1291
1292 /*************************************************************************
1293 * function yagCheckBistable() *
1294 *************************************************************************/
1295
1296 /* test whether two cones form a double NAND/NOR bistable */
1297
1298 static int
1299 yagCheckBistable(cone_list *ptcone0, cone_list *ptcone1)
1300 {
1301 if (yagMatchNAND(ptcone0,ptcone1) > 0) {
1302 if (yagMatchNAND(ptcone1, ptcone0) > 0) {
1303 ptcone0->TYPE |= CNS_RS;
1304 ptcone0->TECTYPE |= CNS_NAND;
1305 ptcone0->USER = addptype(ptcone0->USER, YAG_BISTABLE_PTYPE, ptcone1);
1306 ptcone0->USER = addptype(ptcone0->USER, YAG_LATCHINFO_PTYPE, (void *)BISTABLE_NAND);
1307 ptcone1->TYPE |= CNS_RS;
1308 ptcone1->TECTYPE |= CNS_NAND;
1309 ptcone1->USER = addptype(ptcone1->USER, YAG_BISTABLE_PTYPE, ptcone0);
1310 ptcone1->USER = addptype(ptcone1->USER, YAG_LATCHINFO_PTYPE, (void *)BISTABLE_NAND);
1311 return TRUE;
1312 }
1313 }
1314 if (yagMatchNOR(ptcone0,ptcone1) > 0) {
1315 if (yagMatchNOR(ptcone1, ptcone0) > 0) {
1316 ptcone0->TYPE |= CNS_RS;
1317 ptcone0->TECTYPE |= CNS_NOR;
1318 ptcone0->USER = addptype(ptcone0->USER, YAG_BISTABLE_PTYPE, ptcone1);
1319 ptcone0->USER = addptype(ptcone0->USER, YAG_LATCHINFO_PTYPE, (void *)BISTABLE_NOR);
1320 ptcone1->TYPE |= CNS_RS;
1321 ptcone1->TECTYPE |= CNS_NOR;
1322 ptcone1->USER = addptype(ptcone1->USER, YAG_BISTABLE_PTYPE, ptcone0);
1323 ptcone1->USER = addptype(ptcone1->USER, YAG_LATCHINFO_PTYPE, (void *)BISTABLE_NOR);
1324 return TRUE;
1325 }
1326 }
1327 return FALSE;
1328 }
1329
1330 /*************************************************************************
1331 * function yagMatchNAND() *
1332 *************************************************************************/
1333
1334 /* check if NAND exists between two cones and return # of inputs */
1335
1336 int
1337 yagMatchNAND(cone_list *ptcone, cone_list *ptincone)
1338 {
1339 chain_list *ptconechain = NULL;
1340 chain_list *ptchain;
1341 branch_list *ptbranch;
1342 link_list *ptlink, *ptdrivenlink;
1343 int numinputs = 0;
1344
1345 /* search for down branch driven by incone */
1346 /* and containing only N type transistors */
1347
1348 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1349 if (ptbranch->LINK->NEXT == NULL) continue;
1350 ptdrivenlink = NULL;
1351 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1352 if ((ptlink->TYPE & CNS_TPLINK) != 0) break;
1353 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptincone) {
1354 ptdrivenlink = ptlink;
1355 }
1356 }
1357 if (ptlink == NULL && ptdrivenlink != NULL) break;
1358 }
1359
1360 if (ptbranch == NULL) return 0;
1361
1362 /* build list if NAND inputs */
1363 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1364 ptconechain = addchain(ptconechain, ptlink->ULINK.LOTRS->GRID);
1365 numinputs++;
1366 }
1367
1368 /* search for single link up branches for each input */
1369 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1370 ptlink = ptbranch->LINK;
1371 if (ptlink->NEXT != NULL) continue;
1372 if ((ptlink->TYPE & CNS_TPLINK) == 0) continue;
1373 if ((ptchain = yagGetChain(ptconechain, ptlink->ULINK.LOTRS->GRID)) != NULL) {
1374 ptconechain = delchain(ptconechain, ptchain);
1375 }
1376 }
1377
1378 if (ptconechain == NULL) return numinputs;
1379 else {
1380 freechain(ptconechain);
1381 return 0;
1382 }
1383 }
1384
1385 /*************************************************************************
1386 * function yagMatchNOR() *
1387 *************************************************************************/
1388
1389 /* check if NOR exists between two cones and return # of inputs */
1390
1391 int
1392 yagMatchNOR(cone_list *ptcone, cone_list *ptincone)
1393 {
1394 chain_list *ptconechain = NULL;
1395 chain_list *ptchain;
1396 branch_list *ptbranch;
1397 link_list *ptlink, *ptdrivenlink;
1398 int numinputs = 0;
1399
1400 /* search for up branch driven by incone */
1401 /* and containing only P type transistors */
1402
1403 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1404 if (ptbranch->LINK->NEXT == NULL) continue;
1405 ptdrivenlink = NULL;
1406 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1407 if ((ptlink->TYPE & CNS_TNLINK) != 0) break;
1408 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptincone) {
1409 ptdrivenlink = ptlink;
1410 }
1411 }
1412 if (ptlink == NULL && ptdrivenlink != NULL) break;
1413 }
1414
1415 if (ptbranch == NULL) return 0;
1416
1417 /* build list if NOR inputs */
1418 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1419 ptconechain = addchain(ptconechain, ptlink->ULINK.LOTRS->GRID);
1420 numinputs++;
1421 }
1422
1423 /* search for single link down branches for each input */
1424 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1425 ptlink = ptbranch->LINK;
1426 if (ptlink->NEXT != NULL) continue;
1427 if ((ptlink->TYPE & CNS_TNLINK) == 0) continue;
1428 if ((ptchain = yagGetChain(ptconechain, ptlink->ULINK.LOTRS->GRID)) != NULL) {
1429 ptconechain = delchain(ptconechain, ptchain);
1430 }
1431 }
1432
1433 if (ptconechain == NULL) return numinputs;
1434 else {
1435 freechain(ptconechain);
1436 return 0;
1437 }
1438 }
1439
1440 /****************************************************************************
1441 * function yagSelectRSLatch(); *
1442 ****************************************************************************/
1443
1444 void
1445 yagSelectRSLatch(cone_list *ptcone0, cone_list *ptcone1)
1446 {
1447 cone_list *ptlatchcone;
1448 cone_list *ptfeedbackcone;
1449 edge_list *ptedge;
1450
1451 if (yagCountEdges(ptcone0->OUTCONE) >= yagCountEdges(ptcone1->OUTCONE)) {
1452 ptlatchcone = ptcone0;
1453 ptfeedbackcone = ptcone1;
1454 }
1455 else {
1456 ptlatchcone = ptcone1;
1457 ptfeedbackcone = ptcone0;
1458 }
1459
1460 ptlatchcone->TYPE |= CNS_LATCH;
1461 ptedge = yagGetEdge(ptlatchcone->INCONE, ptfeedbackcone);
1462 ptedge->TYPE |= CNS_FEEDBACK;
1463 ptedge = yagGetEdge(ptfeedbackcone->OUTCONE, ptlatchcone);
1464 ptedge->TYPE |= CNS_FEEDBACK;
1465 }
1466
1467 /*************************************************************************
1468 * function yagInverterStrength() *
1469 *************************************************************************/
1470
1471 /* returns the W/L of a CMOS inverter cone */
1472
1473 float
1474 yagInverterStrength(cone_list *ptcone0, cone_list *ptcone1)
1475 {
1476 branch_list *ptbranch;
1477 link_list *ptlink;
1478 lotrs_list *pttrans;
1479 float test_strength;
1480
1481 /* search for required link in down branches */
1482 for (ptbranch = ptcone1->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1483 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1484 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptcone0) {
1485 pttrans = ptlink->ULINK.LOTRS;
1486 test_strength = ((float)pttrans->WIDTH / (float)pttrans->LENGTH);
1487 return test_strength;
1488 }
1489 }
1490 }
1491 return 0.0;
1492 }
1493
1494 /*************************************************************************
1495 * function yagMatchNOT() *
1496 *************************************************************************/
1497
1498 /* test whether a simple inverter */
1499 /* lies between the two given cones */
1500
1501 int
1502 yagMatchNOT(cone_list *ptcone, cone_list *ptincone)
1503 {
1504 branch_list *ptbranch;
1505 link_list *ptlink;
1506 cone_list *ptlinkcone;
1507
1508 /* search for up branch */
1509 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1510 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1511 if ((ptlink->TYPE & CNS_TPLINK) == 0) break;
1512 ptlinkcone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1513 if (ptlinkcone != ptincone && (ptlinkcone->TYPE & CNS_VSS) == 0) break;
1514 }
1515 if (ptlink == NULL) break;
1516 }
1517
1518 if (ptbranch == NULL) return FALSE;
1519
1520 /* search for corresponding down branch */
1521 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1522 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1523 if ((ptlink->TYPE & CNS_TNLINK) == 0) break;
1524 ptlinkcone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1525 if (ptlinkcone != ptincone && (ptlinkcone->TYPE & CNS_VDD) == 0) break;
1526 }
1527 if (ptlink == NULL) return TRUE;
1528 }
1529 return FALSE;
1530 }
1531
1532 /*************************************************************************
1533 * function isTristate() *
1534 *************************************************************************/
1535
1536 /* test whether a simple tristate */
1537 /* lies between the two given cones */
1538
1539 static int
1540 isTristate(cone_list *ptcone, cone_list *ptincone, chain_list **pttranslist)
1541 {
1542 branch_list *ptbranch;
1543 link_list *ptlink;
1544 chain_list *templist = NULL;
1545 chain_list *ptchain;
1546 int found = FALSE;
1547
1548 /* search for up branch */
1549 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1550 ptlink = ptbranch->LINK;
1551 if (ptlink->NEXT == NULL) continue;
1552 if ((ptlink->TYPE & CNS_TPLINK) == 0) continue;
1553 ptlink = ptlink->NEXT;
1554 if (ptlink->NEXT != NULL) continue;
1555 if ((ptlink->TYPE & CNS_TPLINK) == 0) continue;
1556 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptincone) {
1557 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1558 templist = addchain(templist, ptlink->ULINK.LOTRS);
1559 }
1560 found = TRUE;
1561 }
1562 }
1563
1564 if (found == FALSE) return FALSE;
1565
1566 found = FALSE;
1567 /* search for corresponding down branch */
1568 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1569 ptlink = ptbranch->LINK;
1570 if (ptlink->NEXT == NULL) continue;
1571 if ((ptlink->TYPE & CNS_TNLINK) == 0) continue;
1572 ptlink = ptlink->NEXT;
1573 if (ptlink->NEXT != NULL) continue;
1574 if ((ptlink->TYPE & CNS_TNLINK) == 0) continue;
1575 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptincone) {
1576 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1577 templist = addchain(templist, ptlink->ULINK.LOTRS);
1578 }
1579 found = TRUE;
1580 }
1581 }
1582 if (found) {
1583 for (ptchain = templist; ptchain; ptchain = ptchain->NEXT) {
1584 if (yagGetChain(*pttranslist, ptchain->DATA) == NULL) {
1585 *pttranslist = addchain(*pttranslist, ptchain->DATA);
1586 }
1587 }
1588 freechain(templist);
1589 return TRUE;
1590 }
1591 else return FALSE;
1592 }
1593
1594 /*************************************************************************
1595 * function yagMatchInversion() *
1596 *************************************************************************/
1597
1598 /* check for simple inversion (INV, NAND or NOR) */
1599 /* between two cones and return corresponding W/L */
1600
1601 int
1602 yagMatchInversion(cone_list *ptcone, cone_list *ptincone, float *ptstrength, chain_list **pttranslist)
1603 {
1604 branch_list *ptbranch;
1605 link_list *ptlink;
1606 lotrs_list *pttrans = NULL;
1607 cone_list *ptgatecone = NULL;
1608 chain_list *templist = NULL;
1609 chain_list *ptchain;
1610 int fConfirmNOR, fConfirmNAND;
1611 int matchtype;
1612
1613 /* search for up branch */
1614 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1615 fConfirmNOR = FALSE;
1616 ptlink = ptbranch->LINK;
1617 if ((ptlink->TYPE & CNS_TPLINK) == 0) continue;
1618 if (ptlink->NEXT != NULL) {
1619 if ((ptlink->NEXT->TYPE & CNS_TPLINK) == 0) continue;
1620 if (ptlink->NEXT->NEXT != NULL) continue;
1621 fConfirmNOR = TRUE;
1622 }
1623 if (fConfirmNOR == FALSE) {
1624 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptincone) break;
1625 }
1626 else {
1627 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptincone) {
1628 ptgatecone = (cone_list *)ptlink->NEXT->ULINK.LOTRS->GRID;
1629 break;
1630 }
1631 else if ((cone_list *)ptlink->NEXT->ULINK.LOTRS->GRID == ptincone) {
1632 ptgatecone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1633 break;
1634 }
1635 }
1636 }
1637 if (ptbranch == NULL) {
1638 if (ptstrength != NULL) *ptstrength = 0.0;
1639 return PM_UNKNOWN;
1640 }
1641
1642 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1643 templist = addchain(templist, ptlink->ULINK.LOTRS);
1644 }
1645
1646 /* search for down branch */
1647 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1648 fConfirmNAND = FALSE;
1649 ptlink = ptbranch->LINK;
1650 if ((ptlink->TYPE & CNS_TNLINK) == 0) continue;
1651 if (ptlink->NEXT != NULL) {
1652 if (fConfirmNOR == TRUE) continue;
1653 if ((ptlink->NEXT->TYPE & CNS_TNLINK) == 0) continue;
1654 if (ptlink->NEXT->NEXT != NULL) continue;
1655 fConfirmNAND = TRUE;
1656 }
1657 if (fConfirmNAND == FALSE) {
1658 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptincone) {
1659 pttrans = ptlink->ULINK.LOTRS;
1660 break;
1661 }
1662 }
1663 else {
1664 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptincone) {
1665 pttrans = ptlink->ULINK.LOTRS;
1666 ptgatecone = (cone_list *)ptlink->NEXT->ULINK.LOTRS->GRID;
1667 break;
1668 }
1669 else if ((cone_list *)ptlink->NEXT->ULINK.LOTRS->GRID == ptincone) {
1670 pttrans = ptlink->NEXT->ULINK.LOTRS;
1671 ptgatecone = (cone_list *)ptlink->ULINK.LOTRS->GRID;
1672 break;
1673 }
1674 }
1675 }
1676 if (ptbranch == NULL) {
1677 if (ptstrength != NULL) *ptstrength = 0.0;
1678 freechain(templist);
1679 return PM_UNKNOWN;
1680 }
1681
1682 /* confirm gatecone in down branches for NOR */
1683 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1684 templist = addchain(templist, ptlink->ULINK.LOTRS);
1685 }
1686
1687 if (fConfirmNOR == TRUE) {
1688 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1689 ptlink = ptbranch->LINK;
1690 if (ptlink->NEXT != NULL) continue;
1691 if ((ptlink->TYPE & CNS_TNLINK) == 0) continue;
1692 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptgatecone) break;
1693 }
1694 if (ptbranch == NULL) {
1695 if (ptstrength != NULL) *ptstrength = 0.0;
1696 freechain(templist);
1697 return PM_UNKNOWN;
1698 }
1699 matchtype = PM_NOR;
1700
1701 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1702 templist = addchain(templist, ptlink->ULINK.LOTRS);
1703 }
1704 }
1705
1706 /* confirm gatecone in up branches for NAND */
1707 else if (fConfirmNAND == TRUE) {
1708 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1709 ptlink = ptbranch->LINK;
1710 if (ptlink->NEXT != NULL) continue;
1711 if ((ptlink->TYPE & CNS_TPLINK) == 0) continue;
1712 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptgatecone) break;
1713 }
1714 if (ptbranch == NULL) {
1715 if (ptstrength != NULL) *ptstrength = 0.0;
1716 freechain(templist);
1717 return PM_UNKNOWN;
1718 }
1719 matchtype = PM_NAND;
1720
1721 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1722 templist = addchain(templist, ptlink->ULINK.LOTRS);
1723 }
1724 }
1725
1726 else matchtype = PM_INV;
1727
1728 if (ptstrength != NULL) {
1729 *ptstrength = ((float)pttrans->WIDTH / (float)pttrans->LENGTH);
1730 }
1731 if (pttranslist != NULL) {
1732 for (ptchain = templist; ptchain; ptchain = ptchain->NEXT) {
1733 if (yagGetChain(*pttranslist, ptchain->DATA) == NULL) {
1734 *pttranslist = addchain(*pttranslist, ptchain->DATA);
1735 }
1736 }
1737 }
1738 freechain(templist);
1739 return matchtype;
1740 }
1741
1742 /*************************************************************************
1743 * function yagMatchSwitchedInversion() *
1744 *************************************************************************/
1745
1746 /* check for inverted feedback (INV, NAND, NOR) */
1747 /* via a pass-transistor, a switch or tri-state */
1748
1749 int
1750 yagMatchSwitchedInversion(cone_list *ptcone, cone_list *ptincone, chain_list **pttranslist)
1751 {
1752 branch_list *ptbranch;
1753 link_list *ptlink;
1754 lotrs_list *pttrans;
1755 losig_list *ptsig, *ptnextsig;
1756 cone_list *ptdualcone;
1757 ptype_list *ptuser;
1758 float strength;
1759 long linktype = 0;
1760 int type, dualtype = PM_UNKNOWN;
1761
1762 ptsig = getlosig(YAG_CONTEXT->YAG_CURLOFIG, ptcone->INDEX);
1763
1764 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1765 ptlink = ptbranch->LINK;
1766 if (ptlink->NEXT == NULL) continue;
1767 pttrans = ptlink->ULINK.LOTRS;
1768 if (pttrans->DRAIN->SIG != ptsig) ptnextsig = pttrans->DRAIN->SIG;
1769 else ptnextsig = pttrans->SOURCE->SIG;
1770 ptuser = getptype(ptnextsig->USER, YAG_CONE_PTYPE);
1771 if (ptuser == NULL) continue;
1772 ptdualcone = (cone_list *)ptuser->DATA;
1773 type = yagMatchInversion(ptdualcone, ptincone, &strength, pttranslist);
1774 if (type == PM_UNKNOWN) continue;
1775 dualtype = type;
1776 linktype |= (ptlink->TYPE & (CNS_TNLINK|CNS_TPLINK));
1777 if (yagGetChain(*pttranslist, ptlink->ULINK.LOTRS) == NULL) {
1778 *pttranslist = addchain(*pttranslist, ptlink->ULINK.LOTRS);
1779 }
1780 }
1781
1782 if (dualtype != PM_UNKNOWN) {
1783 if (linktype == (CNS_TNLINK|CNS_TPLINK)) {
1784 switch (dualtype) {
1785 case PM_INV: return PM_SWITCHINV;
1786 case PM_NAND: return PM_SWITCHNAND;
1787 case PM_NOR: return PM_SWITCHNOR;
1788 }
1789 }
1790 else if (linktype == CNS_TNLINK) {
1791 switch (dualtype) {
1792 case PM_INV: return PM_PASSINV;
1793 case PM_NAND: return PM_PASSNAND;
1794 case PM_NOR: return PM_PASSNOR;
1795 }
1796 }
1797 else return PM_UNKNOWN;
1798 }
1799
1800 if (isTristate(ptcone, ptincone, pttranslist)) return PM_TRISTATE;
1801 else return PM_UNKNOWN;
1802 }
1803
1804 /*************************************************************************
1805 * function yagIsInverse() *
1806 *************************************************************************/
1807
1808 int
1809 yagIsInverse(cone_list *ptcone, cone_list *ptincone)
1810 {
1811 branch_list *ptbranch;
1812 link_list *ptlink;
1813 int found = FALSE;
1814 int bad = FALSE;
1815
1816 /* search for up branch */
1817 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
1818 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1819 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptincone) {
1820 found = TRUE;
1821 if ((ptlink->TYPE & CNS_TPLINK) == 0) bad = TRUE;
1822 }
1823 }
1824 }
1825
1826 if (found == FALSE || bad == TRUE) return FALSE;
1827
1828 found = FALSE;
1829 bad = FALSE;
1830 /* search for corresponding down branch */
1831 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
1832 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1833 if ((cone_list *)ptlink->ULINK.LOTRS->GRID == ptincone) {
1834 found = TRUE;
1835 if ((ptlink->TYPE & CNS_TNLINK) == 0) bad = TRUE;
1836 }
1837 }
1838 }
1839
1840 if (found == FALSE || bad == TRUE) return FALSE;
1841 return TRUE;
1842 }
1843
1844 /*************************************************************************
1845 * function yagRmvThruLatch() *
1846 *************************************************************************/
1847
1848 /* delete the branches which pass through latches */
1849
1850 void
1851 yagRmvThruLatch(cone_list *ptcone)
1852 {
1853 branch_list *ptbranch, *ptnextbranch = NULL;
1854 link_list *ptlink;
1855 cone_list *ptsigcone;
1856 losig_list *ptsig, *ptnextsig, *ptlastsig;
1857 ptype_list *ptuser;
1858 branch_list *brlist[4];
1859 int i, changed = FALSE;
1860
1861 ptsig = (losig_list *)getptype(ptcone->USER, CNS_SIGNAL)->DATA;
1862
1863 brlist[0] = ptcone->BRVDD;
1864 brlist[1] = ptcone->BRVSS;
1865 brlist[2] = ptcone->BREXT;
1866 brlist[3] = ptcone->BRGND;
1867
1868 avt_log(LOGYAG,1, "Check for latch branches on cone '%s'\n", ptcone->NAME);
1869
1870 for (i = 0; i < 4; i++) {
1871 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptnextbranch) {
1872 ptlastsig = ptsig;
1873 ptnextbranch = ptbranch->NEXT;
1874 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1875 if ((ptlink->TYPE & (CNS_TNLINK|CNS_TPLINK)) == 0) continue;
1876 if ((ptnextsig = ptlink->ULINK.LOTRS->DRAIN->SIG) == ptlastsig) {
1877 ptnextsig = ptlink->ULINK.LOTRS->SOURCE->SIG;
1878 }
1879 ptlastsig = ptnextsig;
1880 ptuser = getptype(ptnextsig->USER, YAG_CONE_PTYPE);
1881 if (ptuser != NULL) {
1882 ptsigcone = (cone_list *)ptuser->DATA;
1883 if ((ptsigcone->TYPE & (CNS_LATCH|CNS_MEMSYM)) == CNS_LATCH
1884 || ((ptcone->TYPE & YAG_HASDUAL) != 0 && (ptcone->TYPE & (CNS_LATCH|CNS_MEMSYM)) == 0 && (ptsigcone->TYPE & CNS_MEMSYM) != 0)
1885 || (YAG_CONTEXT->YAG_MEMSYM_HEURISTIC && (ptcone->TYPE & (CNS_LATCH|CNS_MEMSYM)) != 0 && (ptsigcone->TYPE & CNS_MEMSYM) != 0)) {
1886 yagDestroyBranch(ptcone, ptbranch);
1887 changed = TRUE;
1888 break;
1889 }
1890 }
1891 }
1892 }
1893 }
1894 /* re-verify the cone if branches have been removed */
1895 if (changed) {
1896 ptcone->TYPE |= YAG_MARK;
1897 }
1898 }
1899
1900 /****************************************************************************
1901 * function invChain(); *
1902 ****************************************************************************/
1903 /*-------------------------------------------------------------------------+
1904 | remonte les couches de cones tant que ceux ci sont des inverseurs. Au |
1905 | fur et a mesure, on constitue une liste chainee des cones remontes |
1906 +-------------------------------------------------------------------------*/
1907 static chain_list *
1908 invChain(cone_list *ptcone, chain_list *ptchain)
1909 {
1910 cone_list *ptincone;
1911 edge_list *ptin;
1912 int numinputs = 0;
1913
1914 for (ptin = ptcone->INCONE; ptin != NULL; ptin = ptin->NEXT) {
1915 if ((ptin->TYPE & CNS_CONE) == CNS_CONE) {
1916 numinputs++;
1917 ptincone = ptin->UEDGE.CONE;
1918 }
1919 }
1920
1921 if (numinputs != 1) return ptchain;
1922
1923 if (yagGetChain(ptchain, ptincone) != NULL) return ptchain;
1924 if (yagMatchNOT(ptcone, ptincone) == FALSE) return ptchain;
1925
1926 ptchain = addchain(ptchain, (void *)ptincone);
1927 ptchain = invChain(ptincone, ptchain);
1928 return ptchain;
1929 }
1930