1 /****************************************************************************/
3 /* Chaine de CAO & VLSI Alliance */
5 /* Produit : YAGLE v3.50 */
6 /* Fichier : yag_duals.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 : 18/03/1994 */
14 /* Modifie par : le : ../../.... */
15 /* Modifie par : le : ../../.... */
16 /* Modifie par : le : ../../.... */
18 /****************************************************************************/
20 #include "yag_headers.h"
22 static chain_list
*VISIT_LIST
;
26 static branch_list
*dual_branches
__P((losig_list
*ptsig
, losig_list
*ptlastsig
, long *ptbranchtype
));
27 static chain_list
*verif_dual
__P((branch_group
*ptbranches
));
28 static ht
*order
__P((branch_list
*ptbranchlist
, table
*ptnames
));
30 cone_list
*yagMakeConeList(ifl
, pt_mbkfig
, pt_cnsfig
)
32 lofig_list
*pt_mbkfig
;
33 cnsfig_list
*pt_cnsfig
;
35 cone_list
*ptcone
= NULL
;
36 cone_list
*tempcone
= NULL
;
37 cone_list
*gluecone
= NULL
;
38 losig_list
*ptsig
= NULL
;
39 locon_list
*ptcon
= NULL
;
40 chain_list
*ptchain
= NULL
;
41 chain_list
*expr
= NULL
;
42 chain_list
*ptchain1
, *ptconlist
;
45 branch_group theBranches
;
53 /* signal list traversal */
54 for (ptsig
= pt_mbkfig
->LOSIG
; ptsig
!= NULL
; ptsig
= ptsig
->NEXT
) {
57 theBranches
.BRVDD
= NULL
;
58 theBranches
.BRVSS
= NULL
;
59 theBranches
.BRGND
= NULL
;
60 theBranches
.BREXT
= NULL
;
63 if (ptsig
->TYPE
== 'T') continue;
65 /* FCL_NEVER directive */
66 if ((ptuser
= getptype(ptsig
->USER
, FCL_TRANSFER_PTYPE
)) != NULL
) {
67 if (((long)ptuser
->DATA
& FCL_NEVER
) != 0) continue;
70 /* check for gates and N-P intersection */
74 for (ptchain
= (chain_list
*)getptype(ptsig
->USER
, LOFIGCHAIN
)->DATA
;
76 ptchain
= ptchain
->NEXT
) {
78 ptcon
= ptchain
->DATA
;
80 if (ptcon
->TYPE
!= 'T') continue;
81 pttrans
= (lotrs_list
*)ptcon
->ROOT
;
83 /* check for NEVER directive on transistor */
84 if ((ptuser
= getptype(pttrans
->USER
, FCL_TRANSFER_PTYPE
)) != NULL
) {
85 if (((long)ptuser
->DATA
& FCL_NEVER
) != 0) {
91 /* Don't count if transistor is a capacitance */
92 if (!(V_BOOL_TAB
[__YAGLE_CAPACITANCE_CONES
].VALUE
)) {
93 if ((pttrans
->TYPE
& CAPACITE
) == CAPACITE
) {
99 if (ptcon
->NAME
== CNS_GRIDNAME
) numGates
++;
101 if (ptcon
->NAME
!= CNS_GRIDNAME
&& ptcon
->NAME
!= CNS_BULKNAME
) nodeType
|= pttrans
->TYPE
;
104 /* Handle Inputs from INF */
105 if ((YAG_CONTEXT
->YAG_FLAGS
& YAG_HAS_INF_INPUTS
)!=0 && ptsig
->TYPE
== CNS_SIGEXT
) {
106 ptconlist
= yagGetExtLoconList(ptsig
);
107 for (ptchain1
= ptconlist
; ptchain1
; ptchain1
= ptchain1
->NEXT
) {
108 ptcon
= (locon_list
*)ptchain1
->DATA
;
109 if (getptype(ptcon
->USER
, YAG_INPUT_PTYPE
) != NULL
) {
110 nodeType
= 0; /* Force input cone if gate present */
113 freechain(ptconlist
);
116 if ((ptsig
->TYPE
!= CNS_SIGVDD
) && (ptsig
->TYPE
!= CNS_SIGVSS
)) {
118 /* extract a CMOS DUAL cone */
122 if ((nodeType
& (CNS_TN
|CNS_TP
)) == (CNS_TN
|CNS_TP
) && numCon
> 2) {
124 if ((expr
= yagTryDual(ptsig
, &theBranches
, &isPartial
)) != NULL
) {
126 coneType
|= YAG_HASDUAL
;
127 if (isPartial
) coneType
|= YAG_PARTIAL
;
128 if (ptsig
->TYPE
== CNS_SIGEXT
) {
130 ptcone
= yagMakeOutCone(ptcone
, ptsig
, &theBranches
, coneType
, CNS_DUAL_CMOS
);
133 ptcone
= yagMakeInoutCone(ptcone
, ptsig
, &theBranches
, coneType
, CNS_DUAL_CMOS
);
135 ptcone
->USER
= addptype(ptcone
->USER
, CNS_UPEXPR
, expr
);
136 ptcone
->USER
= addptype(ptcone
->USER
, YAG_DUALEXPR_PTYPE
, copyExpr(expr
));
140 /* not a real cone */
141 if (getptype(ptsig
->USER
, FCL_FORCECONE_PTYPE
) != NULL
) {
143 coneType
|= YAG_GLUECONE
;
144 gluecone
= yagMakeCone(gluecone
, ptsig
, NULL
, coneType
, 0);
148 coneType
|= YAG_TEMPCONE
;
149 tempcone
= yagMakeCone(tempcone
, ptsig
, &theBranches
, coneType
, CNS_DUAL_CMOS
);
154 ptcone
= yagMakeCone(ptcone
, ptsig
, &theBranches
, coneType
, CNS_DUAL_CMOS
);
155 ptcone
->USER
= addptype(ptcone
->USER
, CNS_UPEXPR
, expr
);
156 ptcone
->USER
= addptype(ptcone
->USER
, YAG_DUALEXPR_PTYPE
, copyExpr(expr
));
159 if (isGlue
) yagMarkUsedTrans(gluecone
);
160 else if (isTemp
) yagMarkUsedTrans(tempcone
);
161 else yagMarkUsedTrans(ptcone
);
162 if (YAG_CONTEXT
->YAG_ORIENT
) yagOrientTransistors(ptsig
);
165 yagDelBranchList(theBranches
.BRVDD
);
166 yagDelBranchList(theBranches
.BRVSS
);
170 /* add empty cones if no DUAL but signal attacks gate or connector or marked FORCECONE */
171 if (isDual
== FALSE
) {
172 if (ptsig
->TYPE
== CNS_SIGEXT
) {
173 /* add connector cones */
174 if (nodeType
== 0 && numGates
> 0) {
175 ptcone
= yagMakeInCone(ptcone
, ptsig
, 0, 0);
177 else if (nodeType
!= 0 && numGates
== 0) {
178 ptcone
= yagMakeOutCone(ptcone
, ptsig
, NULL
, YAG_PARTIAL
, 0);
180 else if (nodeType
!= 0 && numGates
> 0) {
181 ptcone
= yagMakeInoutCone(ptcone
, ptsig
, NULL
, YAG_PARTIAL
, 0);
184 else if (numGates
> 0) { /* normal empty cone */
185 ptcone
= yagMakeCone(ptcone
, ptsig
, NULL
, YAG_PARTIAL
, 0);
187 else if (getptype(ptsig
->USER
, FCL_FORCECONE_PTYPE
) != NULL
) {
188 gluecone
= yagMakeCone(gluecone
, ptsig
, NULL
, YAG_PARTIAL
|YAG_GLUECONE
, 0);
192 else if (numGates
> 0) {
193 /* power supply cones */
194 ptcone
= yagMakeSupplyCone(ptcone
, ptsig
);
198 if (tempcone
!= NULL
) {
199 pt_cnsfig
->USER
= addptype(pt_cnsfig
->USER
, YAG_TEMPCONE_PTYPE
, tempcone
);
201 if (gluecone
!= NULL
) {
202 pt_cnsfig
->USER
= addptype(pt_cnsfig
->USER
, YAG_GLUECONE_PTYPE
, gluecone
);
207 chain_list
*yagTryDual(ptsig
, ptbranches
, ptpartial
)
209 branch_group
*ptbranches
;
212 branch_list
*newbranches
;
213 branch_list
*ptbranch
;
217 losig_list
*ptnextsig
;
220 VISIT_LIST
= addchain(NULL
, ptsig
);
222 for (ptchain
= (chain_list
*)getptype(ptsig
->USER
, LOFIGCHAIN
)->DATA
; ptchain
!= NULL
; ptchain
= ptchain
->NEXT
) {
223 ptcon
= (locon_list
*)ptchain
->DATA
;
224 if (ptcon
->TYPE
== 'T') {
225 pttrans
= (lotrs_list
*)ptcon
->ROOT
;
227 /* Skip parallel transistor instances */
228 if (getptype(pttrans
->USER
, MBK_TRANS_MARK
) != NULL
) continue;
231 if (ptcon
== pttrans
->SOURCE
) {
232 ptnextsig
= pttrans
->DRAIN
->SIG
;
234 else if (ptcon
== pttrans
->DRAIN
) {
235 ptnextsig
= pttrans
->SOURCE
->SIG
;
237 else if (ptcon
== pttrans
->GRID
) continue;
238 else if (ptcon
== pttrans
->BULK
) continue;
240 if (ptnextsig
== ptsig
) continue;
242 branch_type
= (pttrans
->TYPE
& CNS_TN
) == CNS_TN
? CNS_VSS
: CNS_VDD
;
244 if (ptnextsig
->TYPE
== CNS_SIGVDD
) {
245 newbranches
= addbranch(NULL
, CNS_VDD
|YAG_DUALBRANCH
, NULL
);
246 branch_type
|= CNS_VDD
;
248 else if (ptnextsig
->TYPE
== CNS_SIGVSS
) {
249 newbranches
= addbranch(NULL
, CNS_VSS
|YAG_DUALBRANCH
, NULL
);
250 branch_type
|= CNS_VSS
;
252 else newbranches
= dual_branches(ptnextsig
, ptsig
, &branch_type
);
255 yagDelBranchList(newbranches
);
259 if (branch_type
== CNS_VDD
) {
260 for (ptbranch
= newbranches
; ptbranch
!= NULL
; ptbranch
= ptbranch
->NEXT
) {
261 ptbranch
->LINK
= yagAddTransLink(ptbranch
->LINK
, pttrans
, ptsig
);
263 ptbranches
->BRVDD
= yagAppendBranch(ptbranches
->BRVDD
, newbranches
);
265 else if (branch_type
== CNS_VSS
) {
266 for (ptbranch
= newbranches
; ptbranch
!= NULL
; ptbranch
= ptbranch
->NEXT
) {
267 ptbranch
->LINK
= yagAddTransLink(ptbranch
->LINK
, pttrans
, ptsig
);
269 ptbranches
->BRVSS
= yagAppendBranch(ptbranches
->BRVSS
, newbranches
);
272 yagDelBranchList(newbranches
);
278 freechain(VISIT_LIST
);
279 return verif_dual(ptbranches
);
283 branch_list
*dual_branches(ptsig
, ptlastsig
, ptbranchtype
)
285 losig_list
*ptlastsig
;
288 branch_list
*newbranches
= NULL
;
289 branch_list
*result_branch
= NULL
;
290 branch_list
*ptbranch
;
291 losig_list
*ptnextsig
;
292 chain_list
*ptchain
, *headchain
;
296 headchain
= (chain_list
*)getptype(ptsig
->USER
, LOFIGCHAIN
)->DATA
;
298 for (ptchain
= headchain
; ptchain
!= NULL
; ptchain
= ptchain
->NEXT
) {
299 if (((locon_list
*)ptchain
->DATA
)->NAME
== CNS_GRIDNAME
300 || ((locon_list
*)ptchain
->DATA
)->NAME
== CNS_BULKNAME
) {
306 VISIT_LIST
= addchain(VISIT_LIST
, ptsig
);
307 for (ptchain
= headchain
; ptchain
!= NULL
; ptchain
= ptchain
->NEXT
) {
308 ptcon
= (locon_list
*)ptchain
->DATA
;
310 if (ptcon
->TYPE
== 'T') {
311 pttrans
= (lotrs_list
*)ptcon
->ROOT
;
313 /* Skip parallel transistor instances */
314 if (getptype(pttrans
->USER
, MBK_TRANS_MARK
) != NULL
) continue;
316 if (ptcon
== pttrans
->SOURCE
) {
317 ptnextsig
= pttrans
->DRAIN
->SIG
;
319 else if (ptcon
== pttrans
->DRAIN
) {
320 ptnextsig
= pttrans
->SOURCE
->SIG
;
322 if (ptnextsig
== ptlastsig
) continue;
324 if (yagGetChain(VISIT_LIST
, ptnextsig
) != NULL
) continue;
326 *ptbranchtype
|= (pttrans
->TYPE
& CNS_TN
) == CNS_TN
? CNS_VSS
: CNS_VDD
;
328 if (ptnextsig
->TYPE
== CNS_SIGVDD
) {
329 newbranches
= addbranch(NULL
, CNS_VDD
|YAG_DUALBRANCH
, NULL
);
330 *ptbranchtype
|= CNS_VDD
;
332 else if (ptnextsig
->TYPE
== CNS_SIGVSS
) {
333 newbranches
= addbranch(NULL
, CNS_VSS
|YAG_DUALBRANCH
, NULL
);
334 *ptbranchtype
|= CNS_VSS
;
336 else newbranches
= dual_branches(ptnextsig
, ptsig
, ptbranchtype
);
338 if (UNRAVEL
) yagDelBranchList(newbranches
);
340 if (*ptbranchtype
== CNS_VSS
|| *ptbranchtype
== CNS_VDD
) {
341 for (ptbranch
= newbranches
; ptbranch
!= NULL
; ptbranch
= ptbranch
->NEXT
) {
342 ptbranch
->LINK
= yagAddTransLink(ptbranch
->LINK
, pttrans
, ptsig
);
344 result_branch
= yagAppendBranch(result_branch
, newbranches
);
347 yagDelBranchList(newbranches
);
352 else if (ptcon
->TYPE
== 'E' || ptcon
->TYPE
== 'I' || ptcon
->TYPE
== 'C') {
355 else yagBug(DBG_ILL_CONTYPE
,"dual_branches",NULL
,NULL
,0);
357 VISIT_LIST
= delchain(VISIT_LIST
, VISIT_LIST
);
358 return result_branch
;
361 VISIT_LIST
= delchain(VISIT_LIST
, VISIT_LIST
);
362 return result_branch
;
366 chain_list
*verif_dual(ptbranches
)
367 branch_group
*ptbranches
;
371 branch_list
*ptbranch
;
374 pNode sup
= BDD_zero
;
375 pNode sdown
= BDD_zero
;
376 pNode stot
= BDD_zero
;
381 ptnames
= newtable();
382 ptorder
= order(ptbranches
->BRVSS
, ptnames
);
384 /* To calculate Sup */
386 for (ptbranch
= ptbranches
->BRVDD
; ptbranch
!= NULL
; ptbranch
= ptbranch
->NEXT
) {
388 for (ptlink
= ptbranch
->LINK
; ptlink
!= NULL
; ptlink
= ptlink
->NEXT
) {
389 ptsig
= ((ptlink
->ULINK
).LOTRS
)->GRID
->SIG
;
390 if (ptsig
->TYPE
== CNS_SIGVDD
) symbol
= BDD_zero
;
391 else if (ptsig
->TYPE
== CNS_SIGVSS
) symbol
= BDD_one
;
393 if ((index
= gethtitem(ptorder
, ptsig
)) == EMPTYHT
) {
398 symbol
= notBdd(createNodeTermBdd(index
));
400 term
= applyBinBdd(AND
, term
, symbol
);
402 if (term
== BDD_zero
) ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
403 sup
= applyBinBdd(OR
, sup
, term
);
406 /* To calculate Sdown */
408 for (ptbranch
= ptbranches
->BRVSS
; ptbranch
!= NULL
; ptbranch
= ptbranch
->NEXT
) {
410 for (ptlink
= ptbranch
->LINK
; ptlink
!= NULL
; ptlink
= ptlink
->NEXT
) {
411 ptsig
= ((ptlink
->ULINK
).LOTRS
)->GRID
->SIG
;
412 if (ptsig
->TYPE
== CNS_SIGVDD
) symbol
= BDD_one
;
413 else if (ptsig
->TYPE
== CNS_SIGVSS
) symbol
= BDD_zero
;
415 index
= gethtitem(ptorder
, ptsig
);
416 symbol
= createNodeTermBdd(index
);
418 term
= applyBinBdd(AND
, term
, symbol
);
420 if (term
== BDD_zero
) ptbranch
->TYPE
|= CNS_NOT_FUNCTIONAL
;
421 sdown
= applyBinBdd(OR
, sdown
, term
);
425 stot
= applyBinBdd(AND
, sup
, sdown
);
426 if (stot
== BDD_zero
) {
427 stot
= applyBinBdd(OR
, sup
, sdown
);
428 if (stot
== BDD_one
) {
429 expr
= bddToAbl(sup
, (char **)ptnames
->DATA
);
441 ht
*order(ptbranchlist
, ptnames
)
442 branch_list
*ptbranchlist
;
446 branch_list
*ptbranch
;
454 for (ptbranch
= ptbranchlist
; ptbranch
!= NULL
; ptbranch
= ptbranch
->NEXT
) {
455 for (ptlink
= ptbranch
->LINK
; ptlink
!= NULL
; ptlink
= ptlink
->NEXT
) {
456 ptsig
= ((ptlink
->ULINK
).LOTRS
)->GRID
->SIG
;
457 if (ptsig
->TYPE
== CNS_SIGVDD
) continue;
458 if (ptsig
->TYPE
== CNS_SIGVSS
) continue;
459 if (gethtitem(ptorder
, ptsig
) == EMPTYHT
) {
460 addhtitem(ptorder
, ptsig
, index
++);
461 switch(ptsig
->TYPE
) {
462 case CNS_SIGEXT
: name
= (yagGetExtLocon(ptsig
))->NAME
; break;
463 default: name
= (char *)(ptsig
->NAMECHAIN
->DATA
);
465 addtableitem(ptnames
, name
);