1 /****************************************************************************/
3 /* Chaine de CAO & VLSI Alliance */
5 /* Produit : YAGLE v3.50 */
6 /* Fichier : yag_latch.c */
8 /* (c) copyright 1994 Laboratoire MASI equipe CAO & VLSI */
9 /* Tous droits reserves */
10 /* Support : e-mail alliance-support@asim.lip6.fr */
12 /* Auteur(s) : Anthony LESTER le : 09/08/1994 */
14 /* Modifie par : le : ../../.... */
15 /* Modifie par : le : ../../.... */
16 /* Modifie par : le : ../../.... */
18 /****************************************************************************/
20 #include "yag_headers.h"
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
);
34 /*************************************************************************
35 * function yagExtractBleeder() *
36 *************************************************************************/
38 /* test whether a given cone has a bleeder or a level_hold on one of its inputs */
41 yagMarkLevelHold(cone_list
*ptbleedcone
, cone_list
*ptcone
, chain_list
*transchain
)
43 branch_list
*ptbranch
;
44 edge_list
*ptbleededge
;
46 cone_list
*ptlinkcone
;
47 branch_list
*brlist
[2];
50 chain_list
*bleeder_branches
= NULL
;
51 long linktype
, conetype
;
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
);
64 ptbleededge
= yagGetEdge(ptbleedcone
->INCONE
, ptcone
);
65 if (ptbleededge
) ptbleededge
->TYPE
|= CNS_BLEEDER
;
66 brlist
[0] = ptbleedcone
->BRVDD
;
67 brlist
[1] = ptbleedcone
->BRVSS
;
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
);
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
) {
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
;
89 for (ptchain
= transchain
; ptchain
; ptchain
= ptchain
->NEXT
) {
90 ((lotrs_list
*)ptchain
->DATA
)->TYPE
|= BLEEDER
;
92 if (bleeder_branches
) {
93 ptuser
= getptype(ptbleedcone
->USER
, CNS_BLEEDER
);
95 freechain((chain_list
*)ptuser
->DATA
);
96 ptuser
->DATA
= bleeder_branches
;
98 else ptbleedcone
->USER
= addptype(ptbleedcone
->USER
, CNS_BLEEDER
, bleeder_branches
);
103 yagFclMarkTrans(lotrs_list
*ptlotrs
, long type
)
107 if ((ptuser
= getptype(ptlotrs
->USER
, FCL_TRANSFER_PTYPE
)) != NULL
) {
108 ptuser
->DATA
= (void *) ((long) ptuser
->DATA
| type
);
110 else ptlotrs
->USER
= addptype(ptlotrs
->USER
, FCL_TRANSFER_PTYPE
, (void *) type
);
114 yagFclMarkSig(losig_list
*ptlosig
, long type
)
118 if ((ptuser
= getptype(ptlosig
->USER
, FCL_TRANSFER_PTYPE
)) != NULL
) {
119 ptuser
->DATA
= (void *) ((long) ptuser
->DATA
| type
);
121 else ptlosig
->USER
= addptype(ptlosig
->USER
, FCL_TRANSFER_PTYPE
, (void *) type
);
124 /* count connected transistors ignoring parallel instances and bulks*/
126 yagCountConnections(chain_list
*loconchain
, int only_source_drain
)
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;
144 if (getptype(pttrans
->USER
, MBK_TRANS_MARK
) != NULL
) continue;
147 else if (!only_source_drain
) count
++;
152 /* Return the connector of unique possible next transistor in bleeder chain, null otherwise */
154 yagCheckNextCon(chain_list
*loconchain
, locon_list
*ptprevcon
)
157 locon_list
*ptlocon
, *ptnextcon
= NULL
;
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;
170 if (!ptnextcon
) ptnextcon
= ptlocon
;
176 /* Return a list of transistor making bleeder branch of required type */
178 yagFindBleedTrans(losig_list
*ptsig
, locon_list
*ptcon
, char type
, cone_list
*ptincone
)
180 chain_list
*visit_list
= NULL
;
181 chain_list
*transchain
= NULL
;
182 chain_list
*loconchain
;
183 losig_list
*ptcurrentsig
, *ptnextsig
;
184 locon_list
*ptprevcon
;
188 int found
= FALSE
, done
= FALSE
;
189 int bleeder
, resistance
;
192 visit_list
= addchain(visit_list
, ptsig
);
193 ptcurrentsig
= ptsig
;
195 supply_type
= ((type
== CNS_TN
)?CNS_SIGVSS
:CNS_SIGVDD
);
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) {
208 /* filter transistors without driver */
209 if (pttrans
->GRID
== NULL
) {
214 if (pttrans
->SOURCE
->SIG
== ptcurrentsig
) {
215 ptnextsig
= pttrans
->DRAIN
->SIG
;
216 ptprevcon
= pttrans
->DRAIN
;
219 ptnextsig
= pttrans
->SOURCE
->SIG
;
220 ptprevcon
= pttrans
->SOURCE
;
222 if (yagGetChain(visit_list
, ptnextsig
) || yagCountChains(visit_list
) > 4) {
226 visit_list
= addchain(visit_list
, ptnextsig
);
227 ptdriver
= (cone_list
*)pttrans
->GRID
;
228 if ((pttrans
->TYPE
& type
) == type
&& ptdriver
== ptincone
) {
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
)) {
235 if (bleeder
) found
= TRUE
;
236 if (bleeder
|| resistance
) {
237 transchain
= addchain(transchain
, pttrans
);
238 if (ptnextsig
->TYPE
== supply_type
) {
241 else if (ptnextsig
->TYPE
!= CNS_SIGINT
) {
246 ptcurrentsig
= ptnextsig
;
247 loconchain
= (chain_list
*) getptype(ptcurrentsig
->USER
, LOFIGCHAIN
)->DATA
;
248 if ((ptcon
= yagCheckNextCon(loconchain
, ptprevcon
)) == NULL
) found
= FALSE
;
255 } while (ptcon
&& !done
);
257 freechain(visit_list
);
259 freechain(transchain
);
266 yagCalcChainResistance(chain_list
*transchain
)
268 double resistance
= 0.0;
272 for (ptchain
= transchain
; ptchain
; ptchain
= ptchain
->NEXT
) {
273 ptlotrs
= (lotrs_list
*)ptchain
->DATA
;
274 resistance
+= (ptlotrs
->LENGTH
/ ptlotrs
->WIDTH
);
280 yagMatchNOTbyLotrs(cone_list
*ptcone
, cone_list
*ptincone
, float *up_resistance
, float *down_resistance
)
285 cone_list
*testinput
;
286 branch_list
*ptbranch
;
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
;
293 int found_nmos
= FALSE
, found_pmos
= FALSE
;
295 ptsig
= (losig_list
*)getptype(ptcone
->USER
, CNS_SIGNAL
)->DATA
;
296 if (ptsig
->TYPE
== CNS_SIGVDD
|| ptsig
->TYPE
== CNS_SIGVSS
) return NULL
;
298 /* Dual cone already extracted */
299 if ((ptcone
->TECTYPE
& CNS_DUAL_CMOS
) == CNS_DUAL_CMOS
) {
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;
305 testinput
= ptinput
->UEDGE
.CONE
;
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
);
312 up_branches
= addchain(up_branches
, ptbranch
);
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
);
318 down_branches
= addchain(down_branches
, ptbranch
);
320 *up_resistance
= yagCalcParallelResistance(up_branches
);
321 *down_resistance
= yagCalcParallelResistance(down_branches
);
322 freechain(up_branches
);
323 freechain(down_branches
);
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
) {
339 transchain
= append(transchain
, bleedtranschain
);
340 down_conductance
+= 1 / yagCalcChainResistance(bleedtranschain
);
342 bleedtranschain
= yagFindBleedTrans(ptsig
, ptcon
, CNS_TP
, ptincone
);
343 if (bleedtranschain
) {
345 transchain
= append(transchain
, bleedtranschain
);
346 up_conductance
+= 1 / (2.3 * yagCalcChainResistance(bleedtranschain
));
350 if (found_nmos
&& found_pmos
) {
351 *up_resistance
= 1/up_conductance
;
352 *down_resistance
= 1/down_conductance
;
355 if (transchain
) freechain(transchain
);
360 checkStrictLevelHold(cone_list
*ptcone
, chain_list
*transchain
)
365 chain_list
*loconchain
, *ptchain
;
368 /* Cone on external pin cannot be a strict level-hold */
369 if ((ptcone
->TYPE
& CNS_EXT
) == CNS_EXT
) return FALSE
;
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
;
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;
382 if (getptype(pttrans
->USER
, MBK_TRANS_MARK
) != NULL
) continue;
383 if (yagGetChain(transchain
, pttrans
) == NULL
) return FALSE
;
386 /* Check number of source/drain connections */
387 if (yagCountConnections(loconchain
, TRUE
) == yagCountBranches(ptcone
)) return TRUE
;
392 yagExtractBleeder(inffig_list
*ifl
, cone_list
*ptcone
)
394 losig_list
*ptsig
, *ptbleedsig
;
396 cone_list
*ptbleedcone
;
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
;
407 int isLevelHold
= FALSE
;
410 avt_log(LOGYAG
,1, "Checking for bled input on cone '%s' : ", ptcone
->NAME
);
412 ptsig
= (losig_list
*)getptype(ptcone
->USER
, CNS_SIGNAL
)->DATA
;
413 loconchain
= (chain_list
*) getptype(ptsig
->USER
, LOFIGCHAIN
)->DATA
;
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
);
429 yagMarkLevelHold(ptbleedcone
, ptcone
, transchain
);
430 freechain(transchain
);
431 avt_log(LOGYAG
,1, "LEVEL-HOLD FOUND\n");
434 else if (YAG_CONTEXT
->YAG_DETECT_SIMPLE_MEMSYM
) {
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
;
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
;
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
;
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
);
493 freechain(transchain
);
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
);
515 if ((newchain
= yagFindBleedTrans(ptbleedsig
, ptcon
, CNS_TP
, ptcone
)) != NULL
) {
516 bleedtype
|= CNS_VDD
;
517 bleedtranslist
= append(bleedtranslist
, newchain
);
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;
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
;
539 freechain(bleedtranslist
);
540 bleedtranslist
= NULL
;
543 avt_log(LOGYAG
,1, "FOUND\n");
545 avt_log(LOGYAG
,1, "NOT FOUND\n");
548 /****************************************************************************
549 * function yagDetectBleeder() *
550 ****************************************************************************/
552 /* test for any bleeders missed in the initial bleeder detection phase */
555 yagDetectBleeder(cone_list
*ptcone
)
557 branch_list
*ptbranch
;
560 chain_list
*bleeders
= NULL
;
561 chain_list
*maybe
= NULL
;
564 branch_list
*brlist
[4];
568 brlist
[0] = ptcone
->BRVDD
;
569 brlist
[1] = ptcone
->BRVSS
;
570 brlist
[2] = ptcone
->BREXT
;
571 brlist
[3] = ptcone
->BRGND
;
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
;
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
) {
593 looptype
|= (ptbranch
->TYPE
& (CNS_VDD
|CNS_VSS
));
594 maybe
= addchain(maybe
, ptbranch
);
598 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
599 if ((cone_list
*)(ptlink
->ULINK
.LOTRS
->GRID
) == loopcone
) {
600 if ((ptbranch
->TYPE
& looptype
) != looptype
) {
604 looptype
|= (ptbranch
->TYPE
& (CNS_VDD
|CNS_VSS
));
607 if (looptype
== -1L) break;
610 if (looptype
== -1L) break;
612 if ((looptype
== CNS_VDD
|| looptype
== CNS_VSS
) && maybe
!= NULL
) {
613 bleeders
= append(bleeders
, maybe
);
614 ptedge
->TYPE
|= CNS_BLEEDER
;
616 else freechain(maybe
);
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
;
628 ptcone
->USER
= addptype(ptcone
->USER
, CNS_BLEEDER
, bleeders
);
629 ptcone
->TYPE
|= YAG_MARK
;
633 /****************************************************************************
634 * function yagRmvThruBleed() *
635 ****************************************************************************/
637 /* remove branches terminating with bleed transistors */
638 /* and branches whose final link input is a bleeder input */
641 yagRmvThruBleed(cone_list
*ptcone
)
643 branch_list
*ptbranch
;
644 branch_list
*ptnextbranch
;
646 branch_list
*brlist
[2];
652 brlist
[0] = ptcone
->BRVDD
;
653 brlist
[1] = ptcone
->BRVSS
;
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
);
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
);
675 if (changed
) ptcone
->TYPE
|= YAG_MARK
;
678 /*************************************************************************
679 * function yagMarkLoopConf() *
680 *************************************************************************/
683 yagMarkLoopConf(cone_list
*ptcone
)
685 edge_list
*ptedgelist0
, *ptedgelist1
;
686 edge_list
*ptedge0
, *ptedge1
;
689 if ((ptcone
->TYPE
& YAG_LOOPCONF
) != 0) return;
690 if ((ptcone
->TYPE
& YAG_PARTIAL
) == 0) return;
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
;
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
;
712 /*************************************************************************
713 * function yagMatchLatch() *
714 *************************************************************************/
716 /* general latch pattern-matching entry point */
719 yagMatchLatch(cone_list
*ptcone
)
721 chain_list
*looplist
;
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");
734 found
= checkMemory(ptcone
, loopcone
);
735 if (found
) avt_log(LOGYAG
,1, "\tMemory found\n");
738 found
= checkDiffLatch(ptcone
, loopcone
);
739 if (found
) avt_log(LOGYAG
,1, "\tMemory found\n");
742 avt_log(LOGYAG
,1, "\tNothing found\n");
750 yagMatchSimpleLatch(cone_list
*ptcone
)
752 chain_list
*looplist
;
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
);
764 avt_log(LOGYAG
,1, "\tNothing found\n");
771 /*************************************************************************
772 * function checkLoop() *
773 *************************************************************************/
775 /* check if given cone is part of a two cone loop */
776 /* and return the other cone of the loop. */
779 yagCheckLoop(ptcone
, fIgnoreFalse
)
786 chain_list
*looplist
= NULL
;
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
);
803 /*************************************************************************
804 * function checkLatch() *
805 *************************************************************************/
807 /* test whether two cones form a standard latch */
810 checkLatch(cone_list
*ptcone0
, cone_list
*ptcone1
, int simple
)
812 float strength0
, strength1
;
813 chain_list
*translist0
= NULL
;
814 chain_list
*translist1
= NULL
;
815 chain_list
*translist
= NULL
;
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
);
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
);
834 freechain(translist0
);
835 freechain(translist1
);
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
);
845 else if ((strength1
/strength0
) > 1.2 && (ptcone1
->TYPE
& CNS_PRECHARGE
) == 0) {
846 addLatchType(ptcone1
, ptcone0
, translist1
, type1
, type0
);
848 else if (yagCountEdges(ptcone0
->INCONE
) > 1 && type0
== PM_INV
&& yagCountEdges(ptcone1
->INCONE
) == 1 && type1
== PM_INV
) {
849 addLatchType(ptcone0
, ptcone1
, translist0
, type0
, type1
);
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
);
855 freechain(translist0
);
856 freechain(translist1
);
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
);
866 freechain(translist0
);
867 freechain(translist1
);
868 freechain(translist
);
873 if ((type0
= yagMatchSwitchedInversion(ptcone0
, ptcone1
, &translist
)) != FB_UNKNOWN
) {
874 addLatchType(ptcone0
, ptcone1
, translist
, type0
, type1
);
877 freechain(translist0
);
878 freechain(translist1
);
879 freechain(translist
);
884 freechain(translist0
);
885 freechain(translist1
);
886 freechain(translist
);
890 /*************************************************************************
891 * function addLatchType() *
892 *************************************************************************/
894 /* add the necessary type fields to latch cone, branches and links */
897 addLatchType(cone_list
*ptcone
, cone_list
*feedbackcone
, chain_list
*feedbacktrans
, int feedbacktype
, int forwardtype
)
899 branch_list
*ptbranch
;
900 branch_list
*brlist
[4];
906 ptcone
->TYPE
|= CNS_LATCH
;
907 ptcone
->TYPE
|= YAG_MARK
;
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;
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;
927 ptcone
->USER
= addptype(ptcone
->USER
, YAG_LATCHINFO_PTYPE
, (void *)latchtype
);
929 brlist
[0] = ptcone
->BRVDD
;
930 brlist
[1] = ptcone
->BRVSS
;
931 brlist
[2] = ptcone
->BREXT
;
932 brlist
[3] = ptcone
->BRGND
;
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;
939 if (ptlink
== NULL
) ptbranch
->TYPE
|= (CNS_NOT_FUNCTIONAL
|CNS_FEEDBACK
);
943 ptedge
= yagGetEdge(ptcone
->INCONE
, feedbackcone
);
944 ptedge
->TYPE
|= CNS_FEEDBACK
;
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
;
964 /*************************************************************************
965 * function checkMemory() *
966 *************************************************************************/
968 /* test whether two cones form a symmetric memory point */
971 checkMemory(cone_list
*ptcone0
, cone_list
*ptcone1
)
974 branch_list
*ptbranch
;
976 chain_list
*ptpossiblecommands
= NULL
;
977 chain_list
*ptcommands
= NULL
;
978 cone_list
*ptcommand
= NULL
;
982 branch_list
*brlist0
[4];
983 branch_list
*brlist1
[4];
984 int commanded
= FALSE
;
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) {
992 brlist0
[0] = ptcone0
->BRVDD
;
993 brlist0
[1] = ptcone0
->BRVSS
;
994 brlist0
[2] = ptcone0
->BREXT
;
995 brlist0
[3] = ptcone0
->BRGND
;
997 brlist1
[0] = ptcone1
->BRVDD
;
998 brlist1
[1] = ptcone1
->BRVSS
;
999 brlist1
[2] = ptcone1
->BREXT
;
1000 brlist1
[3] = ptcone1
->BRGND
;
1002 /* Generate list of possible command inputs on Cone 0 */
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
);
1017 /* Check for command on Cone 1 identical to one on Cone 0 */
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
) {
1031 freechain(ptpossiblecommands
);
1032 if (commanded
== FALSE
) return FALSE
;
1034 /* list of commands is intersection of INCONE lists */
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
);
1043 /* memory detected so mark accordingly */
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
));
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
;
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
;
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
;
1086 ptcone0
->TYPE
|= YAG_MARK
;
1087 ptcone1
->TYPE
|= YAG_MARK
;
1089 freechain(ptcommands
);
1096 /*************************************************************************
1097 * function checkDiffLatch() *
1098 *************************************************************************/
1100 /* test whether two cones form a differential latch */
1103 checkDiffLatch(cone_list
*ptcone0
, cone_list
*ptcone1
)
1105 cone_list
*ptincone
;
1106 branch_list
*ptbranch
;
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];
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) {
1122 brlist0
[0] = ptcone0
->BRVDD
;
1123 brlist0
[1] = ptcone0
->BRVSS
;
1125 brlist1
[0] = ptcone1
->BRVDD
;
1126 brlist1
[1] = ptcone1
->BRVSS
;
1128 /* Generate list of possible command inputs on Cone 0 */
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
);
1144 /* Check for command on Cone 1 identical to one on Cone 0 */
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
);
1159 freechain(ptpossiblecommands
);
1161 if (ptcommands
== NULL
) return FALSE
;
1163 /* memory detected so mark accordingly */
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
));
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
;
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
;
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
;
1212 ptcone0
->TYPE
|= YAG_MARK
;
1213 ptcone1
->TYPE
|= YAG_MARK
;
1215 freechain(ptcommands
);
1222 /****************************************************************************
1223 * function yagPairMemsym(); *
1224 ****************************************************************************/
1227 yagPairMemsym(inffig_list
*ifl
, cone_list
*ptcone
)
1229 cone_list
*ptsymcone
, *pttestcone
;
1231 chain_list
*looplist
= NULL
;
1232 chain_list
*ptchain
;
1234 edge_list
*ptloopin
;
1235 cone_list
*ptincone
;
1236 chain_list
*ptinflist
;
1237 char *ptsymname
= NULL
;
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
;
1246 if (mbk_LosigTestREGEX(ptsig
, ((inf_assoc
*)ptchain
->DATA
)->dest
)) {
1247 ptsymname
= ((inf_assoc
*)ptchain
->DATA
)->orig
;
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
);
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) {
1267 ptsig
= (losig_list
*)getptype(pttestcone
->USER
, CNS_SIGNAL
)->DATA
;
1268 if (mbk_LosigTestREGEX(ptsig
, ptsymname
)) {
1269 ptsymcone
= pttestcone
;
1275 ptsymcone
= pttestcone
;
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
;
1288 freechain(looplist
);
1292 /*************************************************************************
1293 * function yagCheckBistable() *
1294 *************************************************************************/
1296 /* test whether two cones form a double NAND/NOR bistable */
1299 yagCheckBistable(cone_list
*ptcone0
, cone_list
*ptcone1
)
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
);
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
);
1330 /*************************************************************************
1331 * function yagMatchNAND() *
1332 *************************************************************************/
1334 /* check if NAND exists between two cones and return # of inputs */
1337 yagMatchNAND(cone_list
*ptcone
, cone_list
*ptincone
)
1339 chain_list
*ptconechain
= NULL
;
1340 chain_list
*ptchain
;
1341 branch_list
*ptbranch
;
1342 link_list
*ptlink
, *ptdrivenlink
;
1345 /* search for down branch driven by incone */
1346 /* and containing only N type transistors */
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
;
1357 if (ptlink
== NULL
&& ptdrivenlink
!= NULL
) break;
1360 if (ptbranch
== NULL
) return 0;
1362 /* build list if NAND inputs */
1363 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1364 ptconechain
= addchain(ptconechain
, ptlink
->ULINK
.LOTRS
->GRID
);
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
);
1378 if (ptconechain
== NULL
) return numinputs
;
1380 freechain(ptconechain
);
1385 /*************************************************************************
1386 * function yagMatchNOR() *
1387 *************************************************************************/
1389 /* check if NOR exists between two cones and return # of inputs */
1392 yagMatchNOR(cone_list
*ptcone
, cone_list
*ptincone
)
1394 chain_list
*ptconechain
= NULL
;
1395 chain_list
*ptchain
;
1396 branch_list
*ptbranch
;
1397 link_list
*ptlink
, *ptdrivenlink
;
1400 /* search for up branch driven by incone */
1401 /* and containing only P type transistors */
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
;
1412 if (ptlink
== NULL
&& ptdrivenlink
!= NULL
) break;
1415 if (ptbranch
== NULL
) return 0;
1417 /* build list if NOR inputs */
1418 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1419 ptconechain
= addchain(ptconechain
, ptlink
->ULINK
.LOTRS
->GRID
);
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
);
1433 if (ptconechain
== NULL
) return numinputs
;
1435 freechain(ptconechain
);
1440 /****************************************************************************
1441 * function yagSelectRSLatch(); *
1442 ****************************************************************************/
1445 yagSelectRSLatch(cone_list
*ptcone0
, cone_list
*ptcone1
)
1447 cone_list
*ptlatchcone
;
1448 cone_list
*ptfeedbackcone
;
1451 if (yagCountEdges(ptcone0
->OUTCONE
) >= yagCountEdges(ptcone1
->OUTCONE
)) {
1452 ptlatchcone
= ptcone0
;
1453 ptfeedbackcone
= ptcone1
;
1456 ptlatchcone
= ptcone1
;
1457 ptfeedbackcone
= ptcone0
;
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
;
1467 /*************************************************************************
1468 * function yagInverterStrength() *
1469 *************************************************************************/
1471 /* returns the W/L of a CMOS inverter cone */
1474 yagInverterStrength(cone_list
*ptcone0
, cone_list
*ptcone1
)
1476 branch_list
*ptbranch
;
1478 lotrs_list
*pttrans
;
1479 float test_strength
;
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
;
1494 /*************************************************************************
1495 * function yagMatchNOT() *
1496 *************************************************************************/
1498 /* test whether a simple inverter */
1499 /* lies between the two given cones */
1502 yagMatchNOT(cone_list
*ptcone
, cone_list
*ptincone
)
1504 branch_list
*ptbranch
;
1506 cone_list
*ptlinkcone
;
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;
1515 if (ptlink
== NULL
) break;
1518 if (ptbranch
== NULL
) return FALSE
;
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;
1527 if (ptlink
== NULL
) return TRUE
;
1532 /*************************************************************************
1533 * function isTristate() *
1534 *************************************************************************/
1536 /* test whether a simple tristate */
1537 /* lies between the two given cones */
1540 isTristate(cone_list
*ptcone
, cone_list
*ptincone
, chain_list
**pttranslist
)
1542 branch_list
*ptbranch
;
1544 chain_list
*templist
= NULL
;
1545 chain_list
*ptchain
;
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
);
1564 if (found
== FALSE
) return 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
);
1583 for (ptchain
= templist
; ptchain
; ptchain
= ptchain
->NEXT
) {
1584 if (yagGetChain(*pttranslist
, ptchain
->DATA
) == NULL
) {
1585 *pttranslist
= addchain(*pttranslist
, ptchain
->DATA
);
1588 freechain(templist
);
1594 /*************************************************************************
1595 * function yagMatchInversion() *
1596 *************************************************************************/
1598 /* check for simple inversion (INV, NAND or NOR) */
1599 /* between two cones and return corresponding W/L */
1602 yagMatchInversion(cone_list
*ptcone
, cone_list
*ptincone
, float *ptstrength
, chain_list
**pttranslist
)
1604 branch_list
*ptbranch
;
1606 lotrs_list
*pttrans
= NULL
;
1607 cone_list
*ptgatecone
= NULL
;
1608 chain_list
*templist
= NULL
;
1609 chain_list
*ptchain
;
1610 int fConfirmNOR
, fConfirmNAND
;
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;
1623 if (fConfirmNOR
== FALSE
) {
1624 if ((cone_list
*)ptlink
->ULINK
.LOTRS
->GRID
== ptincone
) break;
1627 if ((cone_list
*)ptlink
->ULINK
.LOTRS
->GRID
== ptincone
) {
1628 ptgatecone
= (cone_list
*)ptlink
->NEXT
->ULINK
.LOTRS
->GRID
;
1631 else if ((cone_list
*)ptlink
->NEXT
->ULINK
.LOTRS
->GRID
== ptincone
) {
1632 ptgatecone
= (cone_list
*)ptlink
->ULINK
.LOTRS
->GRID
;
1637 if (ptbranch
== NULL
) {
1638 if (ptstrength
!= NULL
) *ptstrength
= 0.0;
1642 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1643 templist
= addchain(templist
, ptlink
->ULINK
.LOTRS
);
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
;
1657 if (fConfirmNAND
== FALSE
) {
1658 if ((cone_list
*)ptlink
->ULINK
.LOTRS
->GRID
== ptincone
) {
1659 pttrans
= ptlink
->ULINK
.LOTRS
;
1664 if ((cone_list
*)ptlink
->ULINK
.LOTRS
->GRID
== ptincone
) {
1665 pttrans
= ptlink
->ULINK
.LOTRS
;
1666 ptgatecone
= (cone_list
*)ptlink
->NEXT
->ULINK
.LOTRS
->GRID
;
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
;
1676 if (ptbranch
== NULL
) {
1677 if (ptstrength
!= NULL
) *ptstrength
= 0.0;
1678 freechain(templist
);
1682 /* confirm gatecone in down branches for NOR */
1683 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1684 templist
= addchain(templist
, ptlink
->ULINK
.LOTRS
);
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;
1694 if (ptbranch
== NULL
) {
1695 if (ptstrength
!= NULL
) *ptstrength
= 0.0;
1696 freechain(templist
);
1701 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1702 templist
= addchain(templist
, ptlink
->ULINK
.LOTRS
);
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;
1714 if (ptbranch
== NULL
) {
1715 if (ptstrength
!= NULL
) *ptstrength
= 0.0;
1716 freechain(templist
);
1719 matchtype
= PM_NAND
;
1721 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1722 templist
= addchain(templist
, ptlink
->ULINK
.LOTRS
);
1726 else matchtype
= PM_INV
;
1728 if (ptstrength
!= NULL
) {
1729 *ptstrength
= ((float)pttrans
->WIDTH
/ (float)pttrans
->LENGTH
);
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
);
1738 freechain(templist
);
1742 /*************************************************************************
1743 * function yagMatchSwitchedInversion() *
1744 *************************************************************************/
1746 /* check for inverted feedback (INV, NAND, NOR) */
1747 /* via a pass-transistor, a switch or tri-state */
1750 yagMatchSwitchedInversion(cone_list
*ptcone
, cone_list
*ptincone
, chain_list
**pttranslist
)
1752 branch_list
*ptbranch
;
1754 lotrs_list
*pttrans
;
1755 losig_list
*ptsig
, *ptnextsig
;
1756 cone_list
*ptdualcone
;
1760 int type
, dualtype
= PM_UNKNOWN
;
1762 ptsig
= getlosig(YAG_CONTEXT
->YAG_CURLOFIG
, ptcone
->INDEX
);
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;
1776 linktype
|= (ptlink
->TYPE
& (CNS_TNLINK
|CNS_TPLINK
));
1777 if (yagGetChain(*pttranslist
, ptlink
->ULINK
.LOTRS
) == NULL
) {
1778 *pttranslist
= addchain(*pttranslist
, ptlink
->ULINK
.LOTRS
);
1782 if (dualtype
!= PM_UNKNOWN
) {
1783 if (linktype
== (CNS_TNLINK
|CNS_TPLINK
)) {
1785 case PM_INV
: return PM_SWITCHINV
;
1786 case PM_NAND
: return PM_SWITCHNAND
;
1787 case PM_NOR
: return PM_SWITCHNOR
;
1790 else if (linktype
== CNS_TNLINK
) {
1792 case PM_INV
: return PM_PASSINV
;
1793 case PM_NAND
: return PM_PASSNAND
;
1794 case PM_NOR
: return PM_PASSNOR
;
1797 else return PM_UNKNOWN
;
1800 if (isTristate(ptcone
, ptincone
, pttranslist
)) return PM_TRISTATE
;
1801 else return PM_UNKNOWN
;
1804 /*************************************************************************
1805 * function yagIsInverse() *
1806 *************************************************************************/
1809 yagIsInverse(cone_list
*ptcone
, cone_list
*ptincone
)
1811 branch_list
*ptbranch
;
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
) {
1821 if ((ptlink
->TYPE
& CNS_TPLINK
) == 0) bad
= TRUE
;
1826 if (found
== FALSE
|| bad
== TRUE
) return 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
) {
1835 if ((ptlink
->TYPE
& CNS_TNLINK
) == 0) bad
= TRUE
;
1840 if (found
== FALSE
|| bad
== TRUE
) return FALSE
;
1844 /*************************************************************************
1845 * function yagRmvThruLatch() *
1846 *************************************************************************/
1848 /* delete the branches which pass through latches */
1851 yagRmvThruLatch(cone_list
*ptcone
)
1853 branch_list
*ptbranch
, *ptnextbranch
= NULL
;
1855 cone_list
*ptsigcone
;
1856 losig_list
*ptsig
, *ptnextsig
, *ptlastsig
;
1858 branch_list
*brlist
[4];
1859 int i
, changed
= FALSE
;
1861 ptsig
= (losig_list
*)getptype(ptcone
->USER
, CNS_SIGNAL
)->DATA
;
1863 brlist
[0] = ptcone
->BRVDD
;
1864 brlist
[1] = ptcone
->BRVSS
;
1865 brlist
[2] = ptcone
->BREXT
;
1866 brlist
[3] = ptcone
->BRGND
;
1868 avt_log(LOGYAG
,1, "Check for latch branches on cone '%s'\n", ptcone
->NAME
);
1870 for (i
= 0; i
< 4; i
++) {
1871 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptnextbranch
) {
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
;
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
);
1894 /* re-verify the cone if branches have been removed */
1896 ptcone
->TYPE
|= YAG_MARK
;
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 +-------------------------------------------------------------------------*/
1908 invChain(cone_list
*ptcone
, chain_list
*ptchain
)
1910 cone_list
*ptincone
;
1914 for (ptin
= ptcone
->INCONE
; ptin
!= NULL
; ptin
= ptin
->NEXT
) {
1915 if ((ptin
->TYPE
& CNS_CONE
) == CNS_CONE
) {
1917 ptincone
= ptin
->UEDGE
.CONE
;
1921 if (numinputs
!= 1) return ptchain
;
1923 if (yagGetChain(ptchain
, ptincone
) != NULL
) return ptchain
;
1924 if (yagMatchNOT(ptcone
, ptincone
) == FALSE
) return ptchain
;
1926 ptchain
= addchain(ptchain
, (void *)ptincone
);
1927 ptchain
= invChain(ptincone
, ptchain
);