1 /****************************************************************************/
3 /* Verification Tools */
5 /* Product: Yagle/HiTas */
7 /* (c) copyright AVERTEC */
8 /* All Rights Reserved */
9 /* Support : e-mail support@avertec.com */
11 /****************************************************************************/
13 #include "yag_headers.h"
15 static void test_levelhold(cone_list
*ptcone
, chain_list
*looplist
);
16 static void adjust_cone(cone_list
*ptcone
, int fIgnoreFalse
);
17 static void restore_cone(cone_list
*ptcone
, int fIgnorefalse
);
18 static void adjust_cone_list(chain_list
*ptconelist
, int fIgnoreFalse
);
19 static void restore_cone_list(chain_list
*ptconelist
, int fIgnorefalse
);
20 static int exist_tempbranch(cone_list
*ptcone
, branch_list
*ptbranch
);
21 static int count_possible_data(cone_list
*ptcone
, cone_list
*ptloopcone
);
22 static int check_stronger(cone_list
*ptcone1
, cone_list
*ptcone2
, float ratio
);
23 static chain_list
*yagGetOppositeNames(char *name
);
24 static pCircuit
buildLatchCct(cone_list
*ptcone
, chain_list
*looplist
, chain_list
*latchexpr
);
25 static chain_list
*yagGetAsyncLatchInputs(cone_list
*ptcone
, chain_list
*looplist
, pCircuit globalCct
, pNode write
, pNode
*ptasync_write
);
26 static chain_list
*yagGetAsyncCommands(cone_list
*ptcone
, chain_list
**command_list
, pCircuit globalCct
, chain_list
*latch_async_commands
);
27 static int checkLoopStability(pCircuit circuit
, pNode expr
, char *name
, pNode
*ptmem
);
28 static void yagAutoRSCheck(cone_list
*ptcone
, chain_list
*looplist
);
29 static cone_list
*yagAutoMemsymCheck(cone_list
*ptcone
, chain_list
*looplist
, pNode condition
, chain_list
*commandlist
, chain_list
**ptptloopcommands
);
30 static void yagDisableAsyncTimings(cone_list
*ptcone
, chain_list
*commandlist
, chain_list
*async_command_list
, int fIgnoreFalse
);
31 static int checkMemsymData(pNode dataexpr
, pNode loopdataexpr
);
32 static chain_list
*getInvList(char *name
);
34 #define YAG_TN_SYNC ((long) 0x10000000 )
35 #define YAG_TP_SYNC ((long) 0x20000000 )
36 #define YAG_TN_ASYNC ((long) 0x40000000 )
37 #define YAG_TP_ASYNC ((long) 0x80000000 )
39 /*************************************************************************
40 * function yagAnalyseLoop() *
41 *************************************************************************/
44 yagAnalyseLoop(cone_list
*ptcone
, int fIgnoreFalse
)
46 cone_list
*ptloopcone
, *ptsymcone
= NULL
;
48 chain_list
*resconf_abl
;
49 chain_list
*local_expr_abl
;
50 chain_list
*local_conf_abl
, *local_hz_abl
;
51 chain_list
*latch_write_support
;
55 chain_list
*command_list
= NULL
;
56 chain_list
*symcommand_list
= NULL
;
62 branch_list
*ptbranch
;
65 pNode local_sup
, local_sdn
;
66 pNode local_conflict
, global_conflict
, res_local_conflict
, res_global_conflict
, local_hz
;
67 pNode latch_conflict
, latch_hz
;
68 pNode local_resconf
, global_resconf
;
69 pNode global_expr
, global_hz
;
71 pNode memorise
, sure_memorise
, sure_write
, async_write
= NULL
;
74 short save_prop_hz
, save_depth
;
75 chain_list
*datacommands
= NULL
;
76 chain_list
*latch_async_inputs
= NULL
;
77 chain_list
*async_command_list
= NULL
;
78 chain_list
*sym_async_command_list
= NULL
;
81 int trylevelhold
= FALSE
;
82 int has_conflict
= FALSE
, has_hz
= FALSE
;
83 int count_forward
, count_reverse
;
86 loglvl3
= avt_islog(3,LOGYAG
);
88 if ((ptcone
->TECTYPE
& YAG_NOTLATCH
) == YAG_NOTLATCH
) return;
89 if ((ptcone
->TYPE
& CNS_PRECHARGE
) == CNS_PRECHARGE
) return;
90 if ((ptcone
->TYPE
& CNS_LATCH
) == CNS_LATCH
) return;
91 if ((ptcone
->TYPE
& CNS_MEMSYM
) == CNS_MEMSYM
) return;
92 if ((ptcone
->TYPE
& CNS_RS
) == CNS_RS
) return;
93 if ((ptcone
->TYPE
& CNS_FLIP_FLOP
) == CNS_FLIP_FLOP
) return;
94 if ((ptcone
->TYPE
& CNS_MASTER
) == CNS_MASTER
) return;
95 if ((ptcone
->TYPE
& CNS_SLAVE
) == CNS_SLAVE
) return;
97 if ((looplist
= yagCheckLoop(ptcone
, fIgnoreFalse
)) != NULL
) {
99 adjust_cone(ptcone
, fIgnoreFalse
);
101 looplist
= yagCheckLoop(ptcone
, fIgnoreFalse
);
102 if (YAG_CONTEXT
->YAG_AUTO_MEMSYM
) adjust_cone_list(looplist
, fIgnoreFalse
);
104 /* If loop between 2 CMOS dual cones then privilege the one */
105 /* with the greatest number of inputs */
106 /* If loop between 1 CMOS dual cone and 1 non CMOS DUAL */
107 /* then privilege the non CMOS DUAL */
108 if (yagCountChains(looplist
) == 1) {
109 ptloopcone
= (cone_list
*)looplist
->DATA
;
110 if ((ptcone
->TECTYPE
& CNS_DUAL_CMOS
) == CNS_DUAL_CMOS
111 && (ptloopcone
->TECTYPE
& CNS_DUAL_CMOS
) == CNS_DUAL_CMOS
) {
112 if (yagCountEdges(ptloopcone
->INCONE
) > yagCountEdges(ptcone
->INCONE
)) {
113 restore_cone(ptcone
, fIgnoreFalse
);
114 if (YAG_CONTEXT
->YAG_AUTO_MEMSYM
) restore_cone_list(looplist
, fIgnoreFalse
);
119 if ((ptcone
->TECTYPE
& CNS_DUAL_CMOS
) == CNS_DUAL_CMOS
120 && (ptloopcone
->TECTYPE
& CNS_DUAL_CMOS
) != CNS_DUAL_CMOS
) {
121 restore_cone(ptcone
, fIgnoreFalse
);
122 if (YAG_CONTEXT
->YAG_AUTO_MEMSYM
) restore_cone_list(looplist
, fIgnoreFalse
);
126 if ((ptcone
->TECTYPE
& CNS_DUAL_CMOS
) != CNS_DUAL_CMOS
127 && (ptloopcone
->TECTYPE
& CNS_DUAL_CMOS
) != CNS_DUAL_CMOS
) {
129 if (V_FLOAT_TAB
[__YAGLE_LATCHLOOP_RATIO
].VALUE
> 1) {
130 res
= check_stronger(ptloopcone
, ptcone
, V_FLOAT_TAB
[__YAGLE_LATCHLOOP_RATIO
].VALUE
);
133 count_forward
= count_possible_data(ptcone
, ptloopcone
);
134 count_reverse
= count_possible_data(ptloopcone
, ptcone
);
135 if (res
== -1 || count_reverse
> count_forward
|| (count_reverse
== count_forward
&& yagCountEdges(ptcone
->OUTCONE
) > 1 && yagCountEdges(ptloopcone
->OUTCONE
) == 1)) {
136 restore_cone(ptcone
, fIgnoreFalse
);
137 if (YAG_CONTEXT
->YAG_AUTO_MEMSYM
) restore_cone_list(looplist
, fIgnoreFalse
);
145 /* remove electrical conflicts in loop cones */
147 for (ptchain
= looplist
; ptchain
; ptchain
= ptchain
->NEXT
) {
148 ptloopcone
= (cone_list
*)ptchain
->DATA
;
149 if ((ptloopcone
->TYPE
& CNS_CONFLICT
) == CNS_CONFLICT
&& (ptloopcone
->TYPE
& YAG_HASDUAL
) != YAG_HASDUAL
) {
150 ptcone
->TYPE
|= YAG_PARTIAL
;
151 yagAnalyseElectric(ptloopcone
, NULL
, fIgnoreFalse
);
152 ptcone
->TYPE
&= ~YAG_PARTIAL
;
154 if ((ptloopcone
->TYPE
& (CNS_CONFLICT
|CNS_TRI
)) != 0 && (ptloopcone
->TYPE
& YAG_HASDUAL
) == 0 && (ptloopcone
->TECTYPE
& YAG_RESCONF
) == 0) {
155 restore_cone(ptcone
, fIgnoreFalse
);
156 if (YAG_CONTEXT
->YAG_AUTO_MEMSYM
) restore_cone_list(looplist
, fIgnoreFalse
);
157 test_levelhold(ptcone
, looplist
);
163 /* Need to build graph for cone which has itself as a primary */
164 /* variable so we mark cone as constrained. */
165 /* We never exploit beyond HZ cones */
167 savegraph
= YAG_CONTEXT
->YAG_CONE_GRAPH
;
168 savecircuit
= YAG_CONTEXT
->YAG_CURCIRCUIT
;
170 save_prop_hz
= YAG_CONTEXT
->YAG_PROP_HZ
;
171 save_depth
= YAG_CONTEXT
->YAG_DEPTH
;
172 YAG_CONTEXT
->YAG_DEPTH
= YAG_CONTEXT
->YAG_AUTOLOOP_DEPTH
;
173 YAG_CONTEXT
->YAG_PROP_HZ
= FALSE
;
174 ptcone
->TYPE
|= YAG_FORCEPRIM
;
175 for (ptchain
= looplist
; ptchain
; ptchain
= ptchain
->NEXT
) {
176 ptloopcone
= (cone_list
*)ptchain
->DATA
;
177 if ((ptloopcone
->TYPE
& YAG_STOP
) == YAG_STOP
) {
178 ptloopcone
->TYPE
&= ~YAG_STOP
;
179 ptloopcone
->USER
= addptype(ptloopcone
->USER
, YAG_STOP_PTYPE
, NULL
);
182 YAG_CONTEXT
->YAG_CONE_GRAPH
= yagMakeConeGraph(ptcone
);
183 for (ptchain
= looplist
; ptchain
; ptchain
= ptchain
->NEXT
) {
184 ptloopcone
= (cone_list
*)ptchain
->DATA
;
185 if (getptype(ptloopcone
->USER
, YAG_STOP_PTYPE
) != NULL
) {
186 ptloopcone
->TYPE
|= YAG_STOP
;
187 ptloopcone
->USER
= delptype(ptloopcone
->USER
, YAG_STOP_PTYPE
);
190 YAG_CONTEXT
->YAG_PROP_HZ
= save_prop_hz
;
191 ptcone
->TYPE
&= ~YAG_FORCEPRIM
;
193 directCct
= yagBuildDirectCct(ptcone
);
195 /* check that cone has itself as a primary variable */
196 if (searchInputCct_no_NA(YAG_CONTEXT
->YAG_CURCIRCUIT
, ptcone
->NAME
) == EMPTYTH
) {
197 yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
198 YAG_CONTEXT
->YAG_CURCIRCUIT
= savecircuit
;
199 YAG_CONTEXT
->YAG_CONE_GRAPH
= savegraph
;
200 YAG_CONTEXT
->YAG_PROP_HZ
= save_prop_hz
;
201 YAG_CONTEXT
->YAG_DEPTH
= save_depth
;
202 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
203 if (ptbranch
->LINK
->NEXT
== NULL
) {
204 ptbranch
->TYPE
&= ~CNS_BLEEDER
;
205 ptedge
= yagGetEdge(ptcone
->INCONE
, ptbranch
->LINK
->ULINK
.LOCON
);
206 ptedge
->TYPE
&= ~CNS_BLEEDER
;
209 restore_cone(ptcone
, fIgnoreFalse
);
210 if (YAG_CONTEXT
->YAG_AUTO_MEMSYM
) restore_cone_list(looplist
, fIgnoreFalse
);
211 test_levelhold(ptcone
, looplist
);
212 destroyCct(directCct
);
216 if (directCct
->countI
<= YAG_CONTEXT
->YAG_AUTOLOOP_CEILING
) {
217 if (fIgnoreFalse
) avt_log(LOGYAG
,1, "Attempting loop analysis on cone '%s' ignoring suspected false branches\n", ptcone
->NAME
);
218 else avt_log(LOGYAG
,1, "Attempting loop analysis on cone '%s' with all branches\n", ptcone
->NAME
);
220 /* Generate expression for cone as a function of its direct inputs */
222 branchmask
= CNS_NOT_FUNCTIONAL
|CNS_IGNORE
|CNS_MASK_PARA
|YAG_IGNORE
;
223 if (fIgnoreFalse
) branchmask
|= YAG_FALSECONF
;
224 cnsMakeConeExpr(ptcone
, &local_abl
, branchmask
, 0, FALSE
);
225 if (local_abl
.UP
== NULL
) local_abl
.UP
= createAtom("'0'");
226 if (local_abl
.DN
== NULL
) local_abl
.DN
= createAtom("'0'");
228 /* Build BDDs for direct inputs in terms of primary variables */
229 /* created as outputs for the current circuit */
231 yagBuildDirectInputBdds(ptcone
);
233 /* Generate up and down expressions for cone in terms of direct inputs */
235 local_sup
= ablToBddCct(directCct
, local_abl
.UP
);
236 local_sdn
= ablToBddCct(directCct
, local_abl
.DN
);
237 tempabl
= createExpr(OR
);
238 addQExpr(tempabl
, copyExpr(local_abl
.UP
));
239 addQExpr(tempabl
, copyExpr(local_abl
.DN
));
240 support
= supportChain_listExpr(tempabl
);
241 numvars
= yagCountChains(support
);
245 /* Generate up and down expressions for cone in terms of primary variables */
247 sup
= ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, local_abl
.UP
);
248 sdn
= ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, local_abl
.DN
);
250 /* apply the contraints */
251 sup
= yagApplyConstraints(sup
, NULL
);
252 sdn
= yagApplyConstraints(sdn
, NULL
);
254 freeExpr(local_abl
.UP
);
255 freeExpr(local_abl
.DN
);
257 /* Generate condition for electrical conflict */
259 local_conflict
= applyBinBdd(AND
, local_sup
, local_sdn
);
260 global_conflict
= applyBinBdd(AND
, sup
, sdn
);
261 global_conflict
= yagApplyConstraints(global_conflict
, NULL
);
262 global_hz
= notBdd(applyBinBdd(OR
, sup
, sdn
));
263 global_hz
= yagApplyConstraints(global_hz
, NULL
);
264 if (global_hz
!= BDD_zero
) {
265 if ((loglvl3
|| YAG_CONTEXT
->YAG_DEBUG_CONE
== ptcone
->NAME
) && global_hz
!= BDD_zero
) {
266 avt_log(LOGYAG
,1,"Warning: Latch can be HZ when : ");
267 tempabl
= bddToAblCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, global_hz
);
268 displayInfExprLog(LOGYAG
, 1, tempabl
);
270 avt_log(LOGYAG
,1," = '1'\n");
272 local_hz
= notBdd(applyBinBdd(OR
, local_sup
, local_sdn
));
275 else local_hz
= BDD_zero
;
277 /* Generate conflict resolved expression for cone */
279 if (global_conflict
!= BDD_zero
) {
280 res_local_conflict
= local_conflict
;
281 if (directCct
->countI
<= YAG_CONTEXT
->YAG_AUTOLOOP_CEILING
) {
282 local_resconf
= yagResolveConflicts(directCct
, YAG_CONTEXT
->YAG_CURCIRCUIT
, &res_local_conflict
, ptcone
);
284 else local_resconf
= BDD_zero
;
285 if (res_local_conflict
!= BDD_zero
) {
286 tempabl
= bddToAblCct(directCct
, res_local_conflict
);
287 res_global_conflict
= ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, tempabl
);
288 if ( loglvl3
|| YAG_CONTEXT
->YAG_DEBUG_CONE
== ptcone
->NAME
) {
289 avt_log(LOGYAG
,1,"Conflict when : ");
290 displayInfExprLog(LOGYAG
, 1, tempabl
);
291 avt_log(LOGYAG
,1," = '1'\n");
296 else res_global_conflict
= BDD_zero
;
299 local_resconf
= BDD_zero
;
300 res_local_conflict
= BDD_zero
;
301 res_global_conflict
= BDD_zero
;
304 if (local_resconf
!= NULL
) {
305 resconf_abl
= bddToAblCct(directCct
, local_resconf
);
306 global_resconf
= ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, resconf_abl
);
307 freeExpr(resconf_abl
);
308 /* Local and global expression calculation */
309 local_expr
= applyBinBdd(OR
, local_resconf
, applyBinBdd(AND
, local_sup
, notBdd(local_sdn
)));
310 global_expr
= applyBinBdd(OR
, global_resconf
, applyBinBdd(AND
, sup
, notBdd(sdn
)));
311 /* apply the contraints */
312 global_expr
= yagApplyConstraints(global_expr
, NULL
);
313 if ( avt_islog(2,LOGYAG
) ) {
314 yagDisplayBddExprLog(LOGYAG
, 2, "Local sup", directCct
, local_sup
);
315 yagDisplayBddExprLog(LOGYAG
, 2, "Local sdn", directCct
, local_sdn
);
316 yagDisplayBddExprLog(LOGYAG
, 2, "Local resconf", directCct
, local_resconf
);
317 yagDisplayBddExprLog(LOGYAG
, 2, "Local expression", directCct
, local_expr
);
318 yagDisplayBddExprLog(LOGYAG
, 2, "Global sup", YAG_CONTEXT
->YAG_CURCIRCUIT
, sup
);
319 yagDisplayBddExprLog(LOGYAG
, 2, "Global sdn", YAG_CONTEXT
->YAG_CURCIRCUIT
, sdn
);
320 yagDisplayBddExprLog(LOGYAG
, 2, "Global resconf", YAG_CONTEXT
->YAG_CURCIRCUIT
, global_resconf
);
321 yagDisplayBddExprLog(LOGYAG
, 2, "Global expression", YAG_CONTEXT
->YAG_CURCIRCUIT
, global_expr
);
323 local_conf_abl
= bddToAblCct(directCct
, res_local_conflict
);
324 local_hz_abl
= bddToAblCct(directCct
, local_hz
);
326 /* check loop stability and obtain memorisation condition */
328 if (checkLoopStability(YAG_CONTEXT
->YAG_CURCIRCUIT
, global_expr
, ptcone
->NAME
, &memorise
) == FALSE
) {
329 avt_log(LOGYAG
,1, "Unstable loop at '%s'\n", ptcone
->NAME
);
331 else if (memorise
!= BDD_zero
&& memorise
!= BDD_one
) {
332 sure_memorise
= yagSimplestBdd(memorise
, applyBinBdd(AND
, memorise
, notBdd(res_global_conflict
)));
333 sure_memorise
= yagApplyConstraints(sure_memorise
, NULL
);
334 sure_write
= yagSimplestBdd(notBdd(memorise
), applyBinBdd(AND
, notBdd(memorise
), notBdd(res_global_conflict
)));
335 sure_write
= yagApplyConstraints(sure_write
, NULL
);
337 avt_log(LOGYAG
,1, "Stable Latch loop at %ld '%s'\n", ptcone
->INDEX
, ptcone
->NAME
);
338 if ( loglvl3
|| YAG_CONTEXT
->YAG_DEBUG_CONE
== ptcone
->NAME
) {
339 yagDisplayBddExprLog(LOGYAG
, 1, "Global memory condition", YAG_CONTEXT
->YAG_CURCIRCUIT
, memorise
);
340 yagDisplayBddExprLog(LOGYAG
, 1, "Sure memory condition", YAG_CONTEXT
->YAG_CURCIRCUIT
, sure_memorise
);
341 support
= supportChain_listBdd(sure_memorise
);
342 avt_log(LOGYAG
,1, "Support size = %d\n", yagCountChains(support
));
345 local_expr_abl
= bddToAblCct(directCct
, local_expr
);
346 latchCct
= buildLatchCct(ptcone
, looplist
, local_expr_abl
);
347 freeExpr(local_expr_abl
);
349 latch_write_support
= yagGetWriteSupport(YAG_CONTEXT
->YAG_CURCIRCUIT
, latchCct
, sure_write
, NULL
);
350 if (latch_write_support
!= NULL
) {
351 if (directCct
->countI
<= YAG_CONTEXT
->YAG_AUTOLOOP_CEILING
) {
352 latch_conflict
= ablToBddCct(latchCct
, local_conf_abl
);
353 latch_hz
= ablToBddCct(latchCct
, local_hz_abl
);
354 yagExtractLatchDrivers(latchCct
, ptcone
, latch_write_support
, latch_conflict
, latch_hz
, sure_write
, looplist
);
356 if (YAG_CONTEXT
->YAG_AUTO_RS
> 0) {
357 yagAutoRSCheck(ptcone
, looplist
);
359 if (YAG_CONTEXT
->YAG_AUTO_ASYNC
> 0) {
360 latch_async_inputs
= yagGetAsyncLatchInputs(ptcone
, looplist
, YAG_CONTEXT
->YAG_CURCIRCUIT
, sure_write
, &async_write
);
362 freechain(latch_write_support
);
363 command_list
= yagGetCommands(YAG_CONTEXT
->YAG_CURCIRCUIT
, ptcone
, sure_memorise
, TRUE
, &datacommands
);
364 if (YAG_CONTEXT
->YAG_AUTO_MEMSYM
> 0) {
365 ptsymcone
= yagAutoMemsymCheck(ptcone
, looplist
, sure_memorise
, command_list
, &symcommand_list
);
367 restore_cone(ptcone
, fIgnoreFalse
);
368 if (YAG_CONTEXT
->YAG_AUTO_MEMSYM
) restore_cone_list(looplist
, fIgnoreFalse
);
370 if (latch_async_inputs
) {
371 async_command_list
= yagGetAsyncCommands(ptcone
, &command_list
, YAG_CONTEXT
->YAG_CURCIRCUIT
, latch_async_inputs
);
372 if (ptsymcone
) sym_async_command_list
= yagGetAsyncCommands(ptsymcone
, &symcommand_list
, YAG_CONTEXT
->YAG_CURCIRCUIT
, latch_async_inputs
);
374 yagMarkMemory(YAG_CONTEXT
->YAG_CURCIRCUIT
, ptcone
, command_list
, async_command_list
, looplist
, sure_memorise
, sure_write
, global_conflict
, async_write
, fIgnoreFalse
);
375 if (ptsymcone
) yagMarkMemory(YAG_CONTEXT
->YAG_CURCIRCUIT
, ptsymcone
, symcommand_list
, sym_async_command_list
, looplist
, sure_memorise
, sure_write
, global_conflict
, async_write
, fIgnoreFalse
);
376 ptcone
->TYPE
&= ~(CNS_CONFLICT
|CNS_TRI
);
377 if (ptsymcone
) ptsymcone
->TYPE
&= ~(CNS_CONFLICT
|CNS_TRI
);
379 ptcone
->TYPE
|= CNS_CONFLICT
;
380 if (ptsymcone
) ptsymcone
->TYPE
|= CNS_CONFLICT
;
383 ptcone
->TYPE
|= CNS_TRI
;
384 if (ptsymcone
) ptsymcone
->TYPE
|= CNS_TRI
;
386 freechain(async_command_list
);
387 freechain(sym_async_command_list
);
388 destroyCct(latchCct
);
389 freechain(command_list
);
390 freechain(symcommand_list
);
391 freechain(datacommands
);
392 freechain(latch_async_inputs
);
395 else if (memorise
== BDD_zero
) {
399 freeExpr(local_conf_abl
);
400 freeExpr(local_hz_abl
);
403 else trylevelhold
= TRUE
;
406 restore_cone(ptcone
, fIgnoreFalse
);
407 if (YAG_CONTEXT
->YAG_AUTO_MEMSYM
) restore_cone_list(looplist
, fIgnoreFalse
);
410 test_levelhold(ptcone
, looplist
);
413 destroyCct(directCct
);
414 yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
415 YAG_CONTEXT
->YAG_CONE_GRAPH
= savegraph
;
416 YAG_CONTEXT
->YAG_CURCIRCUIT
= savecircuit
;
417 YAG_CONTEXT
->YAG_PROP_HZ
= save_prop_hz
;
418 YAG_CONTEXT
->YAG_DEPTH
= save_depth
;
423 test_levelhold(cone_list
*ptcone
, chain_list
*looplist
)
425 losig_list
*ptloopsig
;
427 cone_list
*ptloopcone
;
429 if (looplist
->NEXT
== NULL
) {
430 ptloopcone
= (cone_list
*)looplist
->DATA
;
431 if (yagMatchNOT(ptcone
, ptloopcone
) && yagMatchNOT(ptloopcone
, ptcone
)) {
432 ptcone
->TYPE
|= YAG_AUTOLATCH
;
433 yagMarkLevelHold(ptcone
, ptloopcone
, NULL
);
434 cnsConeFunction(ptcone
, FALSE
);
439 /* Adjust and restore functions to allow ignoring of possible false */
440 /* branches and to treat level-hold nodes as external connectors */
443 adjust_cone_list(chain_list
*ptconelist
, int fIgnoreFalse
)
447 for (ptchain
= ptconelist
; ptchain
; ptchain
= ptchain
->NEXT
) {
448 adjust_cone((cone_list
*)ptchain
->DATA
, fIgnoreFalse
);
453 restore_cone_list(chain_list
*ptconelist
, int fIgnoreFalse
)
457 for (ptchain
= ptconelist
; ptchain
; ptchain
= ptchain
->NEXT
) {
458 restore_cone((cone_list
*)ptchain
->DATA
, fIgnoreFalse
);
463 adjust_cone(cone_list
*ptcone
, int fIgnoreFalse
)
465 branch_list
*ptbranch
;
467 cone_list
*ptsigcone
;
468 losig_list
*ptsig
, *ptnextsig
, *ptlastsig
;
470 branch_list
*brlist
[4];
471 edge_list
*save_inputs
, *ptedge
;
472 link_list
*ptlink1
, *ptlinklist
;
474 int i
, changed
= FALSE
;
476 ptsig
= (losig_list
*)getptype(ptcone
->USER
, CNS_SIGNAL
)->DATA
;
477 brlist
[0] = ptcone
->BRVDD
;
478 brlist
[1] = ptcone
->BRVSS
;
479 brlist
[2] = ptcone
->BREXT
;
480 brlist
[3] = ptcone
->BRGND
;
482 for (i
= 0; i
< 4; i
++) {
483 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
485 if (fIgnoreFalse
&& (ptbranch
->TYPE
& YAG_FALSECONF
) != 0) ptbranch
->TYPE
|= YAG_IGNORE
;
486 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
487 if ((ptlink
->TYPE
& (CNS_TNLINK
|CNS_TPLINK
)) == 0) continue;
488 if ((ptnextsig
= ptlink
->ULINK
.LOTRS
->DRAIN
->SIG
) == ptlastsig
) {
489 ptnextsig
= ptlink
->ULINK
.LOTRS
->SOURCE
->SIG
;
491 ptlastsig
= ptnextsig
;
492 ptuser
= getptype(ptnextsig
->USER
, YAG_CONE_PTYPE
);
493 if (ptuser
!= NULL
) {
494 ptsigcone
= (cone_list
*)ptuser
->DATA
;
495 if ((ptsigcone
->TECTYPE
& YAG_LEVELHOLD
) != 0) {
496 ptbranch
->TYPE
|= YAG_IGNORE
;
497 if (exist_tempbranch(ptcone
, ptbranch
) == FALSE
) {
500 for (ptlink1
= ptbranch
->LINK
; ptlink1
&& ptlink1
!= ptlink
->NEXT
; ptlink1
= ptlink1
->NEXT
) {
501 ptlinklist
= addlink(ptlinklist
, ptlink1
->TYPE
, ptlink1
->ULINK
.PTR
, ptlink1
->SIG
);
503 ptcon
= (locon_list
*)mbkalloc(sizeof(locon_list
));
504 ptcon
->NAME
= ptsigcone
->NAME
;
505 ptcon
->SIG
= ptnextsig
;
508 ptcon
->DIRECTION
= 'I';
511 ptlinklist
= addlink(ptlinklist
, CNS_EXT
|CNS_IN
, ptcon
, ptnextsig
);
512 ptcone
->BREXT
= addbranch(ptcone
->BREXT
, CNS_EXT
|YAG_TEMPBRANCH
, (link_list
*)reverse((chain_list
*)ptlinklist
));
521 if (fIgnoreFalse
|| changed
) {
522 save_inputs
= ptcone
->INCONE
;
523 ptcone
->USER
= addptype(ptcone
->USER
, YAG_SAVEINPUTS_PTYPE
, save_inputs
);
524 ptcone
->INCONE
= NULL
;
525 if (changed
) yagChainCone(ptcone
);
527 for (ptedge
= save_inputs
; ptedge
; ptedge
= ptedge
->NEXT
) {
528 if ((ptedge
->TYPE
& YAG_FALSECONF
) == 0) {
529 addincone(ptcone
, ptedge
->TYPE
, ptedge
->UEDGE
.PTR
);
535 /* Ignore simple external connector branch and input */
536 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
537 if (ptbranch
->LINK
->NEXT
== NULL
) {
538 ptbranch
->TYPE
|= CNS_BLEEDER
;
539 ptedge
= yagGetEdge(ptcone
->INCONE
, ptbranch
->LINK
->ULINK
.LOCON
);
540 ptedge
->TYPE
|= CNS_BLEEDER
;
546 exist_tempbranch(cone_list
*ptcone
, branch_list
*ptbranch
)
548 branch_list
*pttestbranch
;
549 link_list
*ptlink
, *pttestlink
;
551 for (pttestbranch
= ptcone
->BREXT
; pttestbranch
; pttestbranch
= pttestbranch
->NEXT
) {
552 if ((pttestbranch
->TYPE
& YAG_TEMPBRANCH
) == 0) continue;
553 for (ptlink
= ptbranch
->LINK
, pttestlink
= pttestbranch
->LINK
; ptlink
&& pttestlink
->NEXT
; ptlink
= ptlink
->NEXT
, pttestlink
= pttestlink
->NEXT
) {
554 if (ptlink
->ULINK
.PTR
!= pttestlink
->ULINK
.PTR
) break;
556 if (pttestlink
->NEXT
== NULL
) break;
558 if (ptcone
->BREXT
!= NULL
&& pttestbranch
!= NULL
) return TRUE
;
563 restore_cone(cone_list
*ptcone
, int fIgnoreFalse
)
565 branch_list
*ptbranch
, *ptnextbranch
;
566 branch_list
*brlist
[4];
569 int i
, changed
= FALSE
;
571 brlist
[0] = ptcone
->BRVDD
;
572 brlist
[1] = ptcone
->BRVSS
;
573 brlist
[2] = ptcone
->BREXT
;
574 brlist
[3] = ptcone
->BRGND
;
576 for (i
= 0; i
< 4; i
++) {
577 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
578 if ((ptbranch
->TYPE
& YAG_IGNORE
) != 0) {
579 ptbranch
->TYPE
&= ~YAG_IGNORE
;
585 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptnextbranch
) {
586 ptnextbranch
= ptbranch
->NEXT
;
587 if ((ptbranch
->TYPE
& YAG_TEMPBRANCH
) != 0) {
588 for (ptlink
= ptbranch
->LINK
; ptlink
->NEXT
!= NULL
; ptlink
= ptlink
->NEXT
);
589 mbkfree(ptlink
->ULINK
.LOCON
);
590 yagDestroyBranch(ptcone
, ptbranch
);
594 if (fIgnoreFalse
|| changed
) {
595 if (ptcone
->INCONE
) yagFreeEdgeList(ptcone
->INCONE
);
596 ptcone
->INCONE
= (edge_list
*)getptype(ptcone
->USER
, YAG_SAVEINPUTS_PTYPE
)->DATA
;
597 ptcone
->USER
= delptype(ptcone
->USER
, YAG_SAVEINPUTS_PTYPE
);
600 for (ptbranch
= ptcone
->BREXT
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
601 if (ptbranch
->LINK
->NEXT
== NULL
) {
602 ptbranch
->TYPE
&= ~CNS_BLEEDER
;
603 ptedge
= yagGetEdge(ptcone
->INCONE
, ptbranch
->LINK
->ULINK
.LOCON
);
604 ptedge
->TYPE
&= ~CNS_BLEEDER
;
610 count_possible_data(cone_list
*ptcone
, cone_list
*ptloopcone
)
612 branch_list
*ptbranch
;
613 branch_list
*brlist
[3];
618 chain_list
*tmpchain
;
623 brlist
[0] = ptcone
->BRVDD
;
624 brlist
[1] = ptcone
->BRVSS
;
625 brlist
[2] = ptcone
->BREXT
;
630 for (i
= 0; i
< 3; i
++) {
631 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
633 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
634 if ((ptbranch
->TYPE
& YAG_IGNORE
) != 0) continue;
635 if (i
== 2 && ptbranch
->LINK
->NEXT
== NULL
) continue;
636 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
637 if ((ptlink
->TYPE
& CNS_EXT
) == CNS_EXT
) {
638 ptedge
= yagGetEdge(ptcone
->INCONE
, ptlink
->ULINK
.LOCON
);
641 pttrans
= ptlink
->ULINK
.LOTRS
;
642 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
643 ptedge
= yagGetEdge(ptcone
->INCONE
, ptincone
);
645 tmpchain
= addchain(tmpchain
, ptedge
);
647 if (ptlink
!= NULL
) freechain (tmpchain
);
648 else list
[i
] = append(list
[i
], tmpchain
);
651 for (ptedge
= ptcone
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
652 if (yagGetChain(list
[2], ptedge
) || (yagGetChain(list
[0], ptedge
) && yagGetChain(list
[1], ptedge
))) count
++;
662 check_stronger(cone_list
*ptcone1
, cone_list
*ptcone2
, float ratio
)
664 branch_list
*ptbranch
;
668 float resistance1
, resistance2
;
671 for (ptbranch
= ptcone1
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
672 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
673 if ((ptbranch
->TYPE
& YAG_IGNORE
) != 0) continue;
674 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
675 pttrans
= ptlink
->ULINK
.LOTRS
;
676 if ((cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
== ptcone2
) {
677 ptchain
= addchain(ptchain
, ptbranch
);
682 resistance1
= yagCalcParallelResistance(ptchain
);
686 for (ptbranch
= ptcone2
->BRVSS
; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
687 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) != 0) continue;
688 if ((ptbranch
->TYPE
& YAG_IGNORE
) != 0) continue;
689 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
690 pttrans
= ptlink
->ULINK
.LOTRS
;
691 if ((cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
== ptcone1
) {
692 ptchain
= addchain(ptchain
, ptbranch
);
697 resistance2
= yagCalcParallelResistance(ptchain
);
700 if (resistance2
> ratio
* resistance1
) return 1;
701 if (resistance1
> ratio
* resistance2
) return -1;
705 /*************************************************************************
706 * function yagAnalyseElectric() *
707 *************************************************************************/
710 yagAnalyseElectric(cone_list
*ptcone
, pCircuit conecct
, int fIgnoreFalse
)
713 pCircuit savecircuit
;
715 edge_list
*save_inputs
, *ptedge
;
717 chain_list
*local_expr_abl
;
718 pNode local_sup
, local_sdn
;
719 pNode local_conflict
;
726 savegraph
= YAG_CONTEXT
->YAG_CONE_GRAPH
;
727 savecircuit
= YAG_CONTEXT
->YAG_CURCIRCUIT
;
730 save_inputs
= ptcone
->INCONE
;
731 ptcone
->INCONE
= NULL
;
732 for (ptedge
= save_inputs
; ptedge
; ptedge
= ptedge
->NEXT
) {
733 if ((ptedge
->TYPE
& YAG_FALSECONF
) == 0) {
734 addincone(ptcone
, ptedge
->TYPE
, ptedge
->UEDGE
.PTR
);
739 save_prop_hz
= YAG_CONTEXT
->YAG_PROP_HZ
;
740 YAG_CONTEXT
->YAG_PROP_HZ
= FALSE
;
741 YAG_CONTEXT
->YAG_CONE_GRAPH
= yagMakeConeGraph(ptcone
);
742 YAG_CONTEXT
->YAG_PROP_HZ
= save_prop_hz
;
744 /* Generate expression for cone as a function of its direct inputs */
746 branchmask
= CNS_NOT_FUNCTIONAL
|CNS_IGNORE
|CNS_MASK_PARA
;
747 if (fIgnoreFalse
) branchmask
|= YAG_FALSECONF
;
748 cnsMakeConeExpr(ptcone
, &local_abl
, branchmask
, 0, FALSE
);
750 /* Build BDDs for direct inputs in terms of primary variables */
751 /* created as outputs for the current circuit */
753 yagBuildDirectInputBdds(ptcone
);
755 if (conecct
== NULL
) directCct
= yagBuildDirectCct(ptcone
);
756 else directCct
= conecct
;
758 if (directCct
->countI
<= YAG_CONTEXT
->YAG_AUTOLOOP_CEILING
) {
759 /* Generate up and down expressions for cone in terms of direct inputs */
761 if (local_abl
.UP
!= NULL
) {
762 local_sup
= ablToBddCct(directCct
, local_abl
.UP
);
763 freeExpr(local_abl
.UP
);
765 else local_sup
= BDD_zero
;
766 if (local_abl
.DN
!= NULL
) {
767 local_sdn
= ablToBddCct(directCct
, local_abl
.DN
);
768 freeExpr(local_abl
.DN
);
770 else local_sdn
= BDD_zero
;
772 /* Generate condition for electrical conflict */
774 local_conflict
= applyBinBdd(AND
, local_sup
, local_sdn
);
776 /* Generate conflict resolved expression for cone */
778 local_resconf
= yagResolveConflicts(directCct
, YAG_CONTEXT
->YAG_CURCIRCUIT
, &local_conflict
, ptcone
);
779 if (local_conflict
== BDD_zero
) {
780 ptcone
->TECTYPE
|= YAG_RESCONF
;
782 local_expr
= applyBinBdd(OR
, local_resconf
, applyBinBdd(AND
, local_sup
, notBdd(local_sdn
)));
783 local_expr_abl
= bddToAblCct(directCct
, local_expr
);
784 if ((ptuser
= getptype(ptcone
->USER
, CNS_UPEXPR
)) != NULL
) {
785 freeExpr(ptuser
->DATA
);
786 ptuser
->DATA
= local_expr_abl
;
788 else ptcone
->USER
= addptype(ptcone
->USER
, CNS_UPEXPR
, local_expr_abl
);
791 if (conecct
== NULL
) destroyCct(directCct
);
792 yagDeleteConeGraph(YAG_CONTEXT
->YAG_CONE_GRAPH
);
793 YAG_CONTEXT
->YAG_CONE_GRAPH
= savegraph
;
794 YAG_CONTEXT
->YAG_CURCIRCUIT
= savecircuit
;
797 yagFreeEdgeList(ptcone
->INCONE
);
798 ptcone
->INCONE
= save_inputs
;
800 if (conecct
!= NULL
) return local_conflict
;
804 /*************************************************************************
805 * function buildDirectInputBdds() *
806 *************************************************************************/
808 /* build BDDs for roots of the current graph */
809 /* store as outputs of the current circuit */
812 yagBuildDirectInputBdds(cone_list
*ptcone
)
818 chain_list
*tempexpr
;
821 for (ptedge
= ptcone
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
822 if ((ptedge
->TYPE
& CNS_BLEEDER
) == CNS_BLEEDER
) continue;
823 if ((ptedge
->TYPE
& CNS_EXT
) == 0) {
824 ptnode
= (gnode_list
*)gethtitem(YAG_CONTEXT
->YAG_CONE_GRAPH
->HASHTAB
, ptedge
->UEDGE
.CONE
);
825 name
= ptnode
->OBJECT
.CONE
->NAME
;
828 /* node is an external connector */
829 ptnode
= (gnode_list
*)gethtitem(YAG_CONTEXT
->YAG_CONE_GRAPH
->HASHTAB
, ptedge
->UEDGE
.LOCON
);
830 name
= ptnode
->OBJECT
.LOCON
->NAME
;
832 tempexpr
= createAtom(name
);
833 expr
= yagExpandExpr(ptnode
, tempexpr
, 0);
835 bdd
= ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, expr
);
836 addOutputCct_no_NA(YAG_CONTEXT
->YAG_CURCIRCUIT
, name
, bdd
);
841 /*************************************************************************
842 * function buildDirectCct() *
843 *************************************************************************/
845 /* build circuit for cone direct inputs */
848 yagBuildDirectCct(cone_list
*ptcone
)
855 numinputs
= yagCountEdges(ptcone
->INCONE
);
856 circuit
= initializeCct(ptcone
->NAME
, numinputs
, 10);
858 for (ptedge
= ptcone
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
859 if ((ptedge
->TYPE
& CNS_IGNORE
) != 0) continue;
860 if ((ptedge
->TYPE
& CNS_BLEEDER
) != 0) continue;
861 if ((ptedge
->TYPE
& CNS_EXT
) != CNS_EXT
) {
862 name
= ptedge
->UEDGE
.CONE
->NAME
;
864 else name
= ptedge
->UEDGE
.LOCON
->NAME
;
865 addInputCct_no_NA(circuit
, name
);
868 avt_log(LOGYAG
,1, "Number of direct inputs : %d\n", circuit
->countI
);
872 /*************************************************************************
873 * function buildLatchCct() *
874 *************************************************************************/
876 /* build circuit for latch analysis */
879 buildLatchCct(cone_list
*ptcone
, chain_list
*looplist
, chain_list
*latchexpr
)
884 cone_list
*ptloopcone
;
885 gnode_list
*ptloopnode
;
887 chain_list
*ptchain0
, *ptchain1
;
888 chain_list
*tempexpr
, *expr
;
889 chain_list
*nodelist
;
896 numinputs
= yagCountEdges(ptcone
->INCONE
) - yagCountChains(looplist
) + 1;
897 circuit
= initializeCct(ptcone
->NAME
, numinputs
, 10);
899 /* Add all inputs which are not on the loop */
901 for (ptedge
= ptcone
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
902 if ((ptedge
->TYPE
& CNS_IGNORE
) != 0) continue;
903 if ((ptedge
->TYPE
& CNS_BLEEDER
) != 0) continue;
904 if ((ptedge
->TYPE
& CNS_EXT
) != CNS_EXT
) {
905 if (yagGetChain(looplist
, ptedge
->UEDGE
.CONE
) != NULL
) continue;
906 ptnode
= (gnode_list
*)gethtitem(YAG_CONTEXT
->YAG_CONE_GRAPH
->HASHTAB
, ptedge
->UEDGE
.CONE
);
907 nodelist
= yagGetPrimVars(YAG_CONTEXT
->YAG_CONE_GRAPH
, ptnode
);
909 stuck
= ((ptedge
->UEDGE
.CONE
->TECTYPE
& (CNS_ONE
|CNS_ZERO
)) != 0);
910 for (ptchain0
= nodelist
; ptchain0
; ptchain0
= ptchain0
->NEXT
) {
911 if ((gnode_list
*)ptchain0
->DATA
!= ptnode
) flag
= TRUE
;
912 if ((((gnode_list
*)ptchain0
->DATA
)->TYPE
& ROOT_NODE
) != ROOT_NODE
) break;
914 if (stuck
|| (flag
== TRUE
&& ptchain0
== NULL
)) {
915 expr
= bddToAblCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, searchOutputCct_no_NA(YAG_CONTEXT
->YAG_CURCIRCUIT
, ptedge
->UEDGE
.CONE
->NAME
));
916 addOutputCct_no_NA(circuit
, ptedge
->UEDGE
.CONE
->NAME
, ablToBddCct(circuit
, expr
));
919 else addInputCct_no_NA(circuit
, ptedge
->UEDGE
.CONE
->NAME
);
922 else addInputCct_no_NA(circuit
, ptedge
->UEDGE
.LOCON
->NAME
);
925 /* Add union of inputs of all cones on the loop */
927 for (ptchain0
= looplist
; ptchain0
; ptchain0
= ptchain0
->NEXT
) {
929 /* Add loop cone inputs to latch circuit and */
930 /* add BDDs for them to global circuit */
932 ptloopnode
= (gnode_list
*)gethtitem(YAG_CONTEXT
->YAG_CONE_GRAPH
->HASHTAB
, ptchain0
->DATA
);
933 for (ptchain1
= ptloopnode
->FATHERS
; ptchain1
; ptchain1
= ptchain1
->NEXT
) {
934 ptnode
= (gnode_list
*)ptchain1
->DATA
;
935 if ((ptnode
->TYPE
& CONE_TYPE
) != 0) {
936 name
= ptnode
->OBJECT
.CONE
->NAME
;
939 /* node is an external connector */
940 name
= ptnode
->OBJECT
.LOCON
->NAME
;
942 if (searchInputCct_no_NA(circuit
, name
) == EMPTYTH
) {
943 addInputCct_no_NA(circuit
, name
);
945 if (searchOutputCct_no_NA(YAG_CONTEXT
->YAG_CURCIRCUIT
, name
) != NULL
) continue;
946 tempexpr
= createAtom(name
);
947 expr
= yagExpandExpr(ptnode
, tempexpr
, 0);
949 bdd
= ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, expr
);
950 addOutputCct_no_NA(YAG_CONTEXT
->YAG_CURCIRCUIT
, name
, bdd
);
954 /* Add loop cone expr to output of latch circuit */
956 ptloopcone
= (cone_list
*)ptchain0
->DATA
;
957 if ((ptloopcone
->TYPE
& CNS_CONFLICT
) != 0 && (ptloopcone
->TYPE
& YAG_HASDUAL
) != 0) {
958 ptuser
= getptype(ptloopcone
->USER
, YAG_DUALEXPR_PTYPE
);
960 else ptuser
= getptype(ptloopcone
->USER
, CNS_UPEXPR
);
961 if (ptuser
== NULL
) {
962 yagBug(DBG_NO_ABL
, "buildLatchCct", ptloopcone
->NAME
, NULL
, 0);
964 addOutputCct_no_NA(circuit
, ptloopcone
->NAME
, ablToBddCct(circuit
, (chain_list
*)ptuser
->DATA
));
967 /* Add bdd for latch output */
968 addOutputCct_no_NA(circuit
, ptcone
->NAME
, ablToBddCct(circuit
, latchexpr
));
970 if ( avt_islog(2,LOGYAG
) ) {
971 displayCctLog(LOGYAG
,2,circuit
, 1);
976 /*************************************************************************
977 * function checkLoopStability() *
978 *************************************************************************/
980 /* given a conflict resolved global expression for a cone */
981 /* on a two cone loop, returns whether the loop can be */
982 /* unstable and the condition for loop memorisation */
985 checkLoopStability(pCircuit circuit
, pNode expr
, char *name
, pNode
*ptmem
)
991 index
= searchInputCct_no_NA(circuit
, name
); // called with a cone name => already namealloced
993 avt_log(LOGYAG
,1, "loopname: %s\n", name
);
994 displayCctLog(LOGYAG
,1,circuit
, 0);
996 loopvar
= createNodeTermBdd(index
);
997 f1
= constraintBdd(expr
, loopvar
);
998 f0
= constraintBdd(expr
, notBdd(loopvar
));
999 if ( avt_islog(3,LOGYAG
) || YAG_CONTEXT
->YAG_DEBUG_CONE
== YAG_CONTEXT
->YAG_CURCIRCUIT
->name
) {
1000 yagDisplayBddExprLog(LOGYAG
, 1, "f0", circuit
, f0
);
1001 yagDisplayBddExprLog(LOGYAG
, 1, "f1", circuit
, f1
);
1003 *ptmem
= applyBinBdd(AND
, f1
, notBdd(f0
));
1005 if (applyBinBdd(AND
, f0
, notBdd(f1
)) != BDD_zero
) return FALSE
;
1009 /*************************************************************************
1010 * function isInversion() *
1011 *************************************************************************/
1013 /* check for inverse relation between given input and output */
1016 yagIsInversion(pCircuit circuit
, char *input
, char *output
)
1023 index
= searchInputCct_no_NA(circuit
, input
); // called with a cone name => already namealloced
1025 avt_log(LOGYAG
,1, "input: %s\n", input
);
1026 displayCctLog(LOGYAG
,1,circuit
, 0);
1029 loopvar
= createNodeTermBdd(index
);
1030 if ((expr
= searchOutputCct_no_NA(circuit
, output
)) == NULL
) {
1031 avt_log(LOGYAG
,1, "output: %s\n", output
);
1032 displayCctLog(LOGYAG
,1,circuit
, 0);
1035 f1
= constraintBdd(expr
, loopvar
);
1036 f0
= constraintBdd(expr
, notBdd(loopvar
));
1038 if (applyBinBdd(AND
, f0
, notBdd(f1
)) != BDD_zero
) return TRUE
;
1042 /*************************************************************************
1043 * function getWriteSupport() *
1044 *************************************************************************/
1046 /* given a global write condition obtain list of */
1047 /* all constrained inputs of the latch circuit */
1050 yagGetCorrelatedWriteSupport(pCircuit globalCct
, pCircuit latchCct
, pNode write
, chain_list
*ptallsupport
)
1052 chain_list
*result
= NULL
, *name_result
= NULL
;
1053 chain_list
*global_support
;
1054 chain_list
*ptchain
;
1056 char *varname
, *opposite_name
;
1058 short index
, opposite_index
;
1060 global_support
= supportChain_listBdd(write
);
1062 for (index
= latchCct
->countI
- 1; index
> 1; index
--) {
1063 varname
= searchIndexCct(latchCct
, index
);
1064 varbdd
= searchOutputCct_no_NA(globalCct
, varname
);
1065 if (varbdd
== NULL
) continue;
1066 for (ptchain
= global_support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1067 globalvar
= createNodeTermBdd(((pNode
)ptchain
->DATA
)->index
);
1068 if (constraintBdd(varbdd
, globalvar
) != varbdd
) break;
1070 if (ptchain
!= NULL
) {
1071 if (yagGetChain(name_result
, varname
) == NULL
) {
1072 result
= addchain(result
, createNodeTermBdd(index
));
1073 name_result
= addchain(name_result
, varname
);
1075 if ((ptchain
= yagGetOppositeNames(varname
))) {
1076 for (; ptchain
; ptchain
= ptchain
->NEXT
) {
1077 opposite_name
= (char *)ptchain
->DATA
;
1078 if ((opposite_index
= searchInputCct_no_NA(latchCct
, opposite_name
)) != (short)EMPTYHT
) {
1079 if (yagGetChain(name_result
, opposite_name
) == NULL
) {
1080 result
= addchain(result
, createNodeTermBdd(opposite_index
));
1081 name_result
= addchain(name_result
, opposite_name
);
1089 /* Test whether all support are commands */
1091 for (ptchain
= ptallsupport
; ptchain
; ptchain
= ptchain
->NEXT
) {
1092 if (yagGetChain(name_result
, ptchain
->DATA
) == NULL
) break;
1094 if (ptchain
== NULL
) {
1099 freechain(global_support
);
1100 freechain(name_result
);
1105 yagGetWriteSupport(pCircuit globalCct
, pCircuit latchCct
, pNode write
, chain_list
*ptallsupport
)
1107 chain_list
*result
= NULL
, *name_result
= NULL
;
1108 chain_list
*write_support
;
1109 chain_list
*support
;
1110 chain_list
*ptchain
;
1111 char *varname
, *opposite_name
;
1113 short index
, opposite_index
;
1115 write_support
= supportChain_listBddExpr(globalCct
, write
);
1117 for (index
= latchCct
->countI
- 1; index
> 1; index
--) {
1118 varname
= searchIndexCct(latchCct
, index
);
1119 varbdd
= searchOutputCct_no_NA(globalCct
, varname
);
1120 if (varbdd
== NULL
) continue;
1121 /* apply the contraints */
1122 varbdd
= yagApplyConstraints(varbdd
, NULL
);
1124 support
= supportChain_listBddExpr(globalCct
, varbdd
);
1125 for (ptchain
= support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1126 if (yagGetChain(write_support
, ptchain
->DATA
) == NULL
) break;
1128 if (ptchain
== NULL
&& support
) {
1129 if (yagGetChain(name_result
, varname
) == NULL
) {
1130 result
= addchain(result
, createNodeTermBdd(index
));
1131 name_result
= addchain(name_result
, varname
);
1133 if ((ptchain
= yagGetOppositeNames(varname
))) {
1134 for (; ptchain
; ptchain
= delchain(ptchain
, ptchain
)) {
1135 opposite_name
= (char *)ptchain
->DATA
;
1136 if ((opposite_index
= searchInputCct_no_NA(latchCct
, opposite_name
)) != (short)EMPTYHT
) {
1137 if (yagGetChain(name_result
, opposite_name
) == NULL
) {
1138 result
= addchain(result
, createNodeTermBdd(opposite_index
));
1139 name_result
= addchain(name_result
, opposite_name
);
1147 /* try correlated support */
1148 if (result
== NULL
) {
1149 result
= yagGetCorrelatedWriteSupport(globalCct
, latchCct
, write
, ptallsupport
);
1151 /* else Test whether all support are commands */
1152 else if (ptallsupport
) {
1153 for (ptchain
= ptallsupport
; ptchain
; ptchain
= ptchain
->NEXT
) {
1154 if (yagGetChain(name_result
, ptchain
->DATA
) == NULL
) break;
1156 if (ptchain
== NULL
) {
1161 freechain(write_support
);
1162 freechain(name_result
);
1167 yagGetOppositeNames(char *name
)
1169 ptype_list
*ptptype
;
1170 chain_list
*support
;
1171 chain_list
*reschain
= NULL
;
1172 char *opposite_name
;
1174 for (ptptype
= YAG_CONTEXT
->YAG_CONE_GRAPH
->EXTRA_CONSTRAINTS
; ptptype
; ptptype
= ptptype
->NEXT
) {
1175 support
= (chain_list
*)ptptype
->TYPE
;
1176 if (yagGetChain(support
, name
) != NULL
&& yagCountChains(support
) == 2) {
1177 if ((char *)support
->DATA
== name
) opposite_name
= (char *)support
->NEXT
->DATA
;
1178 else opposite_name
= (char *)support
->DATA
;
1179 if (yagGetChain(reschain
, opposite_name
) == NULL
) reschain
= addchain(reschain
, opposite_name
);
1185 /*************************************************************************
1186 * function checkBranchBlocked() *
1187 *************************************************************************/
1190 checkBranchBlocked(branch_list
*ptbranch
, pNode check
)
1192 pNode branchexpr
, branch_check
;
1194 branchexpr
= (pNode
)getptype(ptbranch
->USER
, YAG_BRANCHEXPR_PTYPE
)->DATA
;
1195 branch_check
= applyBinBdd(AND
, branchexpr
, check
);
1196 branch_check
= yagApplyConstraints(branch_check
, NULL
);
1197 if (branch_check
== BDD_zero
) return TRUE
;
1201 /*************************************************************************
1202 * function checkFeedbackFunctional() *
1203 *************************************************************************/
1206 checkFeedbackFunctional(branch_list
*ptbranch
, pNode write
, cone_list
*ptcone
)
1208 branch_list
*ptbranchlist
, *testbranch
;
1209 pNode branchexpr
, feedback_write
, testexpr
;
1212 if ((ptbranch
->TYPE
& CNS_VSS
) == CNS_VSS
) ptbranchlist
= ptcone
->BRVSS
;
1213 else ptbranchlist
= ptcone
->BRVDD
;
1215 branchexpr
= (pNode
)getptype(ptbranch
->USER
, YAG_BRANCHEXPR_PTYPE
)->DATA
;
1216 feedback_write
= applyBinBdd(AND
, branchexpr
, write
);
1217 feedback_write
= yagApplyConstraints(feedback_write
, NULL
);
1218 if (feedback_write
!= BDD_zero
) {
1219 for (testbranch
= ptbranchlist
; testbranch
; testbranch
= testbranch
->NEXT
) {
1220 if ((testbranch
->TYPE
& CNS_FEEDBACK
) == CNS_FEEDBACK
) continue;
1221 ptuser
= getptype(testbranch
->USER
, YAG_BRANCHEXPR_PTYPE
);
1222 if (ptuser
== NULL
) continue;
1223 testexpr
= (pNode
)ptuser
->DATA
;
1224 if (applyBinBdd(AND
, testexpr
, feedback_write
) == feedback_write
) break;
1226 if (testbranch
== NULL
) ptbranch
->TYPE
&= ~(CNS_NOT_FUNCTIONAL
|YAG_LATCH_NF
);
1230 /*************************************************************************
1231 * function markMemory() *
1232 *************************************************************************/
1235 yagMarkMemory(pCircuit ptcircuit
, cone_list
*ptcone
, chain_list
*commandlist
, chain_list
*async_command_list
, chain_list
*looplist
, pNode memorize
, pNode write
, pNode conflict
, pNode async_write
, int fIgnoreFalse
)
1238 branch_list
*ptbranch
;
1239 branch_list
*brlist
[3];
1240 cone_list
*loopcone
;
1241 cone_list
*ptincone
;
1242 edge_list
*ptinedge
;
1243 edge_list
*ptoutedge
;
1244 lotrs_list
*pttrans
;
1245 chain_list
*ptchain
;
1246 chain_list
*branchabl
;
1248 pNode sync_write
, branchexpr
, branch_mem
;
1249 int i
, hasdata
, ismemsym
;
1252 ptcone
->TYPE
|= YAG_AUTOLATCH
;
1253 ptcone
->TYPE
&= ~YAG_LOOPCONF
;
1255 ismemsym
= ((ptcone
->TYPE
& CNS_MEMSYM
) == CNS_MEMSYM
);
1257 if ((ptcone
->TYPE
& CNS_RS
) == CNS_RS
) return;
1258 ptcone
->TYPE
|= CNS_LATCH
;
1260 if (async_write
&& write
) sync_write
= applyBinBdd(AND
, write
, notBdd(async_write
));
1261 else sync_write
= NULL
;
1263 brlist
[0] = ptcone
->BRVDD
;
1264 brlist
[1] = ptcone
->BRVSS
;
1265 brlist
[2] = ptcone
->BREXT
;
1267 for (ptinedge
= ptcone
->INCONE
; ptinedge
; ptinedge
= ptinedge
->NEXT
) {
1268 if ((ptinedge
->TYPE
& CNS_BLEEDER
) == CNS_BLEEDER
) continue;
1269 if ((ptinedge
->TYPE
& CNS_EXT
) != 0) continue;
1270 ptincone
= ptinedge
->UEDGE
.CONE
;
1271 ptincone
->TYPE
&= ~YAG_LOOPCONF
;
1272 if (yagGetChain(looplist
, ptincone
) != NULL
) {
1273 ptinedge
->TYPE
|= CNS_FEEDBACK
;
1274 if ((ptoutedge
= yagGetEdge(ptincone
->OUTCONE
, ptcone
)) != NULL
) {
1275 ptoutedge
->TYPE
|= CNS_FEEDBACK
;
1278 if (yagGetChain(commandlist
, ptincone
->NAME
) != NULL
) {
1279 ptinedge
->TYPE
|= CNS_COMMAND
;
1281 if (yagGetChain(async_command_list
, ptincone
->NAME
) != NULL
) {
1282 ptinedge
->TYPE
|= CNS_ASYNC
|((V_BOOL_TAB
[__YAGLE_ASYNC_COMMAND
].VALUE
)?CNS_COMMAND
:0);
1285 /* If a branch is opened by the memorising condition then that */
1286 /* branch is marked as feedback and not-functional, if there */
1287 /* exists a non-memorising condition where only a feedback */
1288 /* branch is open then that branch must be considered functional */
1289 for (i
=0; i
<3; i
++) {
1290 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1291 if (fIgnoreFalse
&& (ptbranch
->TYPE
& YAG_FALSECONF
) != 0) continue;
1292 if ((ptbranch
->TYPE
& CNS_BLEEDER
) == CNS_BLEEDER
) continue;
1293 if (i
< 2 && ptcircuit
!= NULL
) {
1294 branchabl
= cnsMakeBranchExpr(ptbranch
, 0, FALSE
);
1295 branchexpr
= ablToBddCct(ptcircuit
, branchabl
);
1296 ptbranch
->USER
= addptype(ptbranch
->USER
, YAG_BRANCHEXPR_PTYPE
, branchexpr
);
1297 freeExpr(branchabl
);
1298 branch_mem
= applyBinBdd(AND
, branchexpr
, memorize
);
1299 branch_mem
= yagApplyConstraints(branch_mem
, NULL
);
1300 if (branch_mem
!= BDD_zero
) {
1301 ptbranch
->TYPE
|= CNS_FEEDBACK
|CNS_NOT_FUNCTIONAL
|YAG_LATCH_NF
;
1306 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1307 if (i
== 2 && ptlink
->NEXT
== NULL
) continue;
1308 pttrans
= ptlink
->ULINK
.LOTRS
;
1309 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1310 if (ptincone
== NULL
) continue;
1311 if (yagGetChain(async_command_list
, ptincone
->NAME
) == NULL
&& yagGetChain(commandlist
, ptincone
->NAME
) == NULL
) hasdata
= TRUE
;
1312 if (!asyncname
&& (ptchain
= yagGetChain(async_command_list
, ptincone
->NAME
))) asyncname
= ptchain
->DATA
;
1314 /* asynchronous driver branch */
1315 if (asyncname
&& sync_write
&& checkBranchBlocked(ptbranch
, sync_write
)) {
1316 ptbranch
->TYPE
|= YAG_ASYNC
;
1319 /* synchronous driver branch */
1320 else if (asyncname
&& hasdata
&& async_write
&& checkBranchBlocked(ptbranch
, async_write
) && (ptbranch
->TYPE
& (CNS_FEEDBACK
|CNS_NOT_FUNCTIONAL
)) != (CNS_FEEDBACK
|CNS_NOT_FUNCTIONAL
)) {
1321 ptbranch
->TYPE
|= YAG_SYNC
;
1323 if ((ptbranch
->TYPE
& (CNS_FEEDBACK
|CNS_NOT_FUNCTIONAL
)) == (CNS_FEEDBACK
|CNS_NOT_FUNCTIONAL
)) {
1326 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1327 if (i
== 2 && ptlink
->NEXT
== NULL
) continue;
1328 if ((ptbranch
->TYPE
& YAG_ASYNC
) == YAG_ASYNC
) continue;
1329 pttrans
= ptlink
->ULINK
.LOTRS
;
1330 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1331 if (ptincone
== NULL
) continue;
1332 if ((ptbranch
->TYPE
& YAG_ASYNC
) == YAG_ASYNC
) {
1333 if (yagGetChain(async_command_list
, ptincone
->NAME
) != NULL
) {
1334 ptlink
->TYPE
|= CNS_ASYNCLINK
|((V_BOOL_TAB
[__YAGLE_ASYNC_COMMAND
].VALUE
)?CNS_COMMAND
:0);
1336 else if ((ptuser
= getptype(pttrans
->USER
, CNS_SWITCH
)) != NULL
) {
1337 pttrans
= (lotrs_list
*)ptuser
->DATA
;
1338 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1339 if (ptincone
== NULL
) continue;
1340 if (yagGetChain(async_command_list
, ptincone
->NAME
) != NULL
) {
1341 ptlink
->TYPE
|= CNS_ASYNCLINK
|((V_BOOL_TAB
[__YAGLE_ASYNC_COMMAND
].VALUE
)?CNS_COMMAND
:0);
1346 if (yagGetChain(commandlist
, ptincone
->NAME
) != NULL
) {
1347 ptlink
->TYPE
|= CNS_COMMAND
;
1349 else if ((ptuser
= getptype(pttrans
->USER
, CNS_SWITCH
)) != NULL
) {
1350 pttrans
= (lotrs_list
*)ptuser
->DATA
;
1351 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1352 if (ptincone
== NULL
) continue;
1353 if (yagGetChain(commandlist
, ptincone
->NAME
) != NULL
) {
1354 ptlink
->TYPE
|= CNS_COMMAND
;
1361 if (ptcircuit
!= NULL
) {
1362 for (i
=0; i
<2; i
++) {
1363 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1364 if (fIgnoreFalse
&& (ptbranch
->TYPE
& YAG_FALSECONF
) != 0) continue;
1365 if (conflict
!= NULL
&& conflict
== BDD_zero
) {
1366 checkFeedbackFunctional(ptbranch
, write
, ptcone
);
1368 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) == CNS_NOT_FUNCTIONAL
) continue;
1369 if ((ptbranch
->TYPE
& YAG_ASYNC
) == YAG_ASYNC
) {
1371 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1372 pttrans
= ptlink
->ULINK
.LOTRS
;
1373 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1374 if (ptincone
== NULL
) continue;
1375 if (yagGetChain(async_command_list
, ptincone
->NAME
) != NULL
) {
1376 ptlink
->TYPE
|= CNS_ASYNCLINK
|((V_BOOL_TAB
[__YAGLE_ASYNC_COMMAND
].VALUE
)?CNS_COMMAND
:0);
1378 else if (ptlink
== ptbranch
->LINK
&& ptlink
->NEXT
== NULL
) {
1379 ptlink
->TYPE
|= CNS_ASYNCLINK
|((V_BOOL_TAB
[__YAGLE_ASYNC_COMMAND
].VALUE
)?CNS_COMMAND
:0);
1380 ptinedge
= yagGetEdge(ptcone
->INCONE
, ptincone
);
1381 ptinedge
->TYPE
|= CNS_ASYNC
|((V_BOOL_TAB
[__YAGLE_ASYNC_COMMAND
].VALUE
)?CNS_COMMAND
:0);
1383 else if ((ptuser
= getptype(pttrans
->USER
, CNS_SWITCH
)) != NULL
) {
1384 pttrans
= (lotrs_list
*)ptuser
->DATA
;
1385 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1386 if (ptincone
== NULL
) continue;
1387 if (yagGetChain(async_command_list
, ptincone
->NAME
) != NULL
) {
1388 ptlink
->TYPE
|= CNS_ASYNCLINK
|((V_BOOL_TAB
[__YAGLE_ASYNC_COMMAND
].VALUE
)?CNS_COMMAND
:0);
1391 /* no cut of feedback loop in case of set/reset on loop (need to be strict) */
1392 ptinedge
= yagGetEdge(ptcone
->INCONE
, ptincone
);
1393 if ((ptinedge
->TYPE
& CNS_FEEDBACK
) == CNS_FEEDBACK
&& yagGetChain(async_command_list
, ptincone
->NAME
)) {
1394 if (yagCheckUniqueConnection(ptincone
, ptcone
)) {
1395 ptinedge
->TYPE
&= ~CNS_FEEDBACK
;
1396 if ((ptoutedge
= yagGetEdge(ptincone
->OUTCONE
, ptcone
)) != NULL
) {
1397 ptoutedge
->TYPE
&= ~CNS_FEEDBACK
;
1399 ptbranch
->TYPE
&= ~CNS_FEEDBACK
;
1405 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1406 pttrans
= ptlink
->ULINK
.LOTRS
;
1407 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1408 if (yagGetChain(commandlist
, ptincone
->NAME
) != NULL
) {
1409 ptlink
->TYPE
|= CNS_COMMAND
;
1411 else if (ptlink
== ptbranch
->LINK
&& ptlink
->NEXT
== NULL
) {
1412 ptlink
->TYPE
|= CNS_COMMAND
;
1413 ptinedge
= yagGetEdge(ptcone
->INCONE
, ptincone
);
1414 ptinedge
->TYPE
|= CNS_COMMAND
;
1416 else if ((ptuser
= getptype(pttrans
->USER
, CNS_SWITCH
)) != NULL
) {
1417 pttrans
= (lotrs_list
*)ptuser
->DATA
;
1418 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1419 if (ptincone
== NULL
) continue;
1420 if (yagGetChain(commandlist
, ptincone
->NAME
) != NULL
) {
1421 ptlink
->TYPE
|= CNS_COMMAND
;
1428 for (i
=0; i
<2; i
++) {
1429 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1430 if (fIgnoreFalse
&& (ptbranch
->TYPE
& YAG_FALSECONF
) != 0) continue;
1431 if ((ptbranch
->TYPE
& CNS_BLEEDER
) != 0) continue;
1432 ptbranch
->USER
= delptype(ptbranch
->USER
, YAG_BRANCHEXPR_PTYPE
);
1437 if (YAG_CONTEXT
->YAG_AUTO_ASYNC
> 1) {
1438 for (i
=0; i
<2; i
++) {
1439 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1440 if ((ptbranch
->TYPE
& YAG_ASYNC
) == YAG_ASYNC
) ptbranch
->TYPE
|= (CNS_NOT_FUNCTIONAL
|YAG_LATCH_NF
);
1444 if (YAG_CONTEXT
->YAG_AUTO_ASYNC
> 0) {
1445 yagDisableAsyncTimings(ptcone
, commandlist
, async_command_list
, fIgnoreFalse
);
1448 for (i
=0; i
<3; i
++) {
1449 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1450 ptbranch
->TYPE
&= ~(CNS_FEEDBACK
|CNS_NOT_FUNCTIONAL
|YAG_LATCH_NF
);
1453 for (ptinedge
= ptcone
->INCONE
; ptinedge
; ptinedge
= ptinedge
->NEXT
) {
1454 ptinedge
->TYPE
&= ~CNS_FEEDBACK
;
1459 /*************************************************************************
1460 * function yagDisableAsyncTimings() *
1461 *************************************************************************/
1464 yagDisableAsyncTimings(cone_list
*ptcone
, chain_list
*commandlist
, chain_list
*async_command_list
, int fIgnoreFalse
)
1467 branch_list
*ptbranch
;
1468 branch_list
*brlist
[3];
1469 cone_list
*ptincone
;
1470 lotrs_list
*pttrans
;
1471 ptype_list
*ptuser
, *ptptype
, *ptptype2
;
1472 ptype_list
*comtypelist
[2], *asynctypelist
[2];
1473 long linktype
, comtype
, asynctype
;
1478 if (async_command_list
) {
1479 ifl
=getloadedinffig(YAG_CONTEXT
->YAG_FIGNAME
);
1480 if (ifl
== NULL
) ifl
= addinffig(YAG_CONTEXT
->YAG_FIGNAME
);
1482 brlist
[0] = ptcone
->BRVDD
;
1483 brlist
[1] = ptcone
->BRVSS
;
1484 brlist
[2] = ptcone
->BREXT
;
1486 /* disable access timing arcs from opposite command edge if necessary */
1487 comtypelist
[0] = NULL
;
1488 comtypelist
[1] = NULL
;
1489 asynctypelist
[0] = NULL
;
1490 asynctypelist
[1] = NULL
;
1491 for (i
=0; i
<3; i
++) {
1492 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1493 if (fIgnoreFalse
&& (ptbranch
->TYPE
& YAG_FALSECONF
) != 0) continue;
1494 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) == CNS_NOT_FUNCTIONAL
) continue;
1495 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1496 if (i
== 2 && ptlink
->NEXT
== NULL
) continue;
1497 linktype
= ptlink
->TYPE
& (CNS_TNLINK
|CNS_TPLINK
);
1498 pttrans
= ptlink
->ULINK
.LOTRS
;
1499 if ((ptuser
= getptype(pttrans
->USER
, CNS_SWITCH
)) != NULL
&& ((i
== 0 && linktype
== CNS_TNLINK
) || (i
== 1 && linktype
== CNS_TPLINK
))) {
1500 pttrans
= (lotrs_list
*)ptuser
->DATA
;
1501 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1502 if (ptincone
== NULL
) continue;
1503 linktype
= (linktype
== CNS_TNLINK
) ? CNS_TPLINK
: CNS_TNLINK
;
1504 inname
= ptincone
->NAME
;
1507 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1508 if (ptincone
== NULL
) continue;
1509 inname
= ptincone
->NAME
;
1511 if (yagGetChain(commandlist
, inname
) == NULL
) continue;
1512 j
= (i
== 2) ? 0 : i
;
1513 if ((ptptype
= getptype(comtypelist
[j
], (long)inname
)) == NULL
) {
1514 ptptype
= addptype(comtypelist
[j
], (long)inname
, NULL
);
1515 comtypelist
[j
] = ptptype
;
1518 if ((ptptype2
= getptype(comtypelist
[1], (long)inname
)) == NULL
) {
1519 ptptype2
= addptype(comtypelist
[1], (long)inname
, NULL
);
1520 comtypelist
[1] = ptptype2
;
1523 else ptptype2
= NULL
;
1524 if ((ptbranch
->TYPE
& YAG_ASYNC
) == YAG_ASYNC
) {
1525 ptptype
->DATA
= (char *)(((long)ptptype
->DATA
)|((linktype
== CNS_TNLINK
) ? YAG_TN_ASYNC
: YAG_TP_ASYNC
));
1526 if (ptptype2
) ptptype2
->DATA
= (char *)(((long)ptptype2
->DATA
)|((linktype
== CNS_TNLINK
) ? YAG_TN_ASYNC
: YAG_TP_ASYNC
));
1529 ptptype
->DATA
= (char *)(((long)ptptype
->DATA
)|((linktype
== CNS_TNLINK
) ? YAG_TN_SYNC
: YAG_TP_SYNC
));
1530 if (ptptype2
) ptptype2
->DATA
= (char *)(((long)ptptype2
->DATA
)|((linktype
== CNS_TNLINK
) ? YAG_TN_SYNC
: YAG_TP_SYNC
));
1535 for (i
=0; i
<2; i
++) {
1536 for (ptptype
= comtypelist
[i
]; ptptype
; ptptype
= ptptype
->NEXT
) {
1537 comtype
= (long)ptptype
->DATA
;
1538 if ((comtype
& (YAG_TN_SYNC
|YAG_TP_SYNC
)) == (YAG_TN_SYNC
|YAG_TP_SYNC
)) continue;
1539 if ((comtype
& (YAG_TP_SYNC
|YAG_TP_ASYNC
)) == YAG_TP_ASYNC
) {
1540 if (i
== 0) inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName((char *)ptptype
->TYPE
), NULL
, 0x12, 0, NULL
);
1541 if (i
== 1) inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName((char *)ptptype
->TYPE
), NULL
, 0x11, 0, NULL
);
1543 if ((comtype
& (YAG_TN_SYNC
|YAG_TN_ASYNC
)) == YAG_TN_ASYNC
) {
1544 if (i
== 0) inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName((char *)ptptype
->TYPE
), NULL
, 0x22, 0, NULL
);
1545 if (i
== 1) inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName((char *)ptptype
->TYPE
), NULL
, 0x21, 0, NULL
);
1548 freeptype(comtypelist
[i
]);
1550 /* disable async timing arcs from opposite async event if necessary */
1551 for (i
=0; i
<3; i
++) {
1552 for (ptbranch
= brlist
[i
]; ptbranch
; ptbranch
= ptbranch
->NEXT
) {
1553 if (fIgnoreFalse
&& (ptbranch
->TYPE
& YAG_FALSECONF
) != 0) continue;
1554 if ((ptbranch
->TYPE
& CNS_NOT_FUNCTIONAL
) == CNS_NOT_FUNCTIONAL
) continue;
1555 for (ptlink
= ptbranch
->LINK
; ptlink
; ptlink
= ptlink
->NEXT
) {
1556 if (i
== 2 && ptlink
->NEXT
== NULL
) continue;
1557 linktype
= ptlink
->TYPE
& (CNS_TNLINK
|CNS_TPLINK
);
1558 pttrans
= ptlink
->ULINK
.LOTRS
;
1559 if ((ptuser
= getptype(pttrans
->USER
, CNS_SWITCH
)) != NULL
&& ((i
== 0 && linktype
== CNS_TNLINK
) || (i
== 1 && linktype
== CNS_TPLINK
))) {
1560 pttrans
= (lotrs_list
*)ptuser
->DATA
;
1561 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1562 if (ptincone
== NULL
) continue;
1563 linktype
= (linktype
== CNS_TNLINK
) ? CNS_TPLINK
: CNS_TNLINK
;
1564 inname
= ptincone
->NAME
;
1567 ptincone
= (cone_list
*)getptype(pttrans
->USER
, CNS_DRIVINGCONE
)->DATA
;
1568 if (ptincone
== NULL
) continue;
1569 inname
= ptincone
->NAME
;
1571 if (yagGetChain(async_command_list
, inname
) == NULL
) continue;
1572 j
= (i
== 2) ? 0 : i
;
1573 if ((ptptype
= getptype(asynctypelist
[j
], (long)inname
)) == NULL
) {
1574 ptptype
= addptype(asynctypelist
[j
], (long)inname
, NULL
);
1575 asynctypelist
[j
] = ptptype
;
1578 if ((ptptype2
= getptype(asynctypelist
[1], (long)inname
)) == NULL
) {
1579 ptptype2
= addptype(asynctypelist
[1], (long)inname
, NULL
);
1580 asynctypelist
[1] = ptptype2
;
1583 else ptptype2
= NULL
;
1584 if ((ptbranch
->TYPE
& YAG_ASYNC
) == YAG_ASYNC
) {
1585 ptptype
->DATA
= (char *)(((long)ptptype
->DATA
)|((linktype
== CNS_TNLINK
) ? YAG_TN_ASYNC
: YAG_TP_ASYNC
));
1586 if (ptptype2
) ptptype2
->DATA
= (char *)(((long)ptptype2
->DATA
)|((linktype
== CNS_TNLINK
) ? YAG_TN_ASYNC
: YAG_TP_ASYNC
));
1589 ptptype
->DATA
= (char *)(((long)ptptype
->DATA
)|((linktype
== CNS_TNLINK
) ? YAG_TN_SYNC
: YAG_TP_SYNC
));
1590 if (ptptype2
) ptptype2
->DATA
= (char *)(((long)ptptype2
->DATA
)|((linktype
== CNS_TNLINK
) ? YAG_TN_SYNC
: YAG_TP_SYNC
));
1595 for (i
=0; i
<2; i
++) {
1596 for (ptptype
= asynctypelist
[i
]; ptptype
; ptptype
= ptptype
->NEXT
) {
1597 asynctype
= (long)ptptype
->DATA
;
1598 if ((asynctype
& (YAG_TN_ASYNC
|YAG_TP_ASYNC
)) == (YAG_TN_ASYNC
|YAG_TP_ASYNC
)) continue;
1599 if ((asynctype
& (YAG_TP_ASYNC
|YAG_TP_SYNC
)) == YAG_TP_SYNC
) {
1600 if (i
== 0) inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName((char *)ptptype
->TYPE
), NULL
, 0x12, 0, NULL
);
1601 if (i
== 1) inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName((char *)ptptype
->TYPE
), NULL
, 0x11, 0, NULL
);
1603 if ((asynctype
& (YAG_TN_ASYNC
|YAG_TN_SYNC
)) == YAG_TN_SYNC
) {
1604 if (i
== 0) inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName((char *)ptptype
->TYPE
), NULL
, 0x22, 0, NULL
);
1605 if (i
== 1) inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName((char *)ptptype
->TYPE
), NULL
, 0x21, 0, NULL
);
1608 freeptype(asynctypelist
[i
]);
1614 yagGetAsyncCommands(cone_list
*ptcone
, chain_list
**command_list
, pCircuit globalCct
, chain_list
*latch_async_inputs
)
1617 chain_list
*async_commands
= NULL
;
1618 chain_list
*ptchain
;
1619 chain_list
*tmp_expr
;
1620 chain_list
*support
;
1623 char *name
, *invname
;
1624 chain_list
*invlist
, *invchain
;
1626 if ((ptcone
->TYPE
& CNS_RS
) == CNS_RS
) return NULL
;
1628 for (ptedge
= ptcone
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
1630 if ((ptedge
->TYPE
& CNS_BLEEDER
) != 0) continue;
1631 if ((ptedge
->TYPE
& CNS_EXT
) != CNS_EXT
) {
1632 name
= ptedge
->UEDGE
.CONE
->NAME
;
1634 else name
= ptedge
->UEDGE
.LOCON
->NAME
;
1635 if (yagGetChain(*command_list
, name
) == NULL
) continue;
1636 tmp_expr
= createAtom_no_NA(name
);
1637 expr
= ablToBddCct(globalCct
, tmp_expr
);
1639 if (expr
== NULL
) continue;
1641 support
= supportChain_listBddExpr(globalCct
, expr
);
1642 if (support
== NULL
) continue;
1643 /* async command if at all influenced by latch async list */
1644 for (ptchain
= support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1645 if (yagGetChain(latch_async_inputs
, ptchain
->DATA
) != NULL
) break;
1647 if (ptchain
!= NULL
) {
1648 async_commands
= addchain(async_commands
, name
);
1649 *command_list
= delchaindata(*command_list
, name
);
1653 if (added
) continue;
1654 invlist
= getInvList(name
);
1655 for (invchain
= invlist
; invchain
; invchain
= invchain
->NEXT
) {
1656 invname
= (char *)invchain
->DATA
;
1657 tmp_expr
= createAtom_no_NA(invname
);
1658 expr
= ablToBddCct(globalCct
, tmp_expr
);
1660 if (expr
== NULL
) continue;
1661 support
= supportChain_listBddExpr(globalCct
, expr
);
1662 if (support
== NULL
) continue;
1663 /* async command if at all influenced by latch async list */
1664 for (ptchain
= support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1665 if (yagGetChain(latch_async_inputs
, ptchain
->DATA
) != NULL
) break;
1668 if (ptchain
!= NULL
) {
1669 async_commands
= addchain(async_commands
, name
);
1670 *command_list
= delchaindata(*command_list
, name
);
1676 return async_commands
;
1680 yagGetAsyncLatchInputs(cone_list
*ptcone
, chain_list
*looplist
, pCircuit globalCct
, pNode write
, pNode
*ptasync_write
)
1682 chain_list
*check_exprs
= NULL
, *cmd_exprs
= NULL
;
1683 chain_list
*expr
, *command_expr
;
1684 chain_list
*ptchain
, *ptchain1
, *ptnextchain
;
1685 chain_list
*support
;
1686 chain_list
*clock_commands
= NULL
, *async_one
= NULL
, *async_zero
= NULL
, *async_bdd_list
= NULL
;
1687 biabl_list
*ptbiabl
;
1688 biabl_list
*drivers
= NULL
;
1689 befig_list
*ptbefig
;
1690 cone_list
*ptloopcone
;
1691 chain_list
*write_support
;
1693 pNode async_check
, command
, check
;
1695 int changes
, abandon
= FALSE
;
1697 *ptasync_write
= BDD_zero
;
1698 if ((ptcone
->TYPE
& CNS_RS
) != 0) return NULL
;
1700 ptuser
= getptype(ptcone
->USER
, YAG_LATCHBEFIG_PTYPE
);
1702 ptbefig
= (befig_list
*)ptuser
->DATA
;
1703 if (ptbefig
->BEREG
) drivers
= ptbefig
->BEREG
->BIABL
;
1705 if (drivers
== NULL
) return NULL
;
1707 ptuser
= getptype(ptcone
->USER
, YAG_LATCHBEFIG_PTYPE
);
1709 ptbefig
= (befig_list
*)ptuser
->DATA
;
1710 if (ptbefig
->BEREG
) drivers
= ptbefig
->BEREG
->BIABL
;
1712 if (drivers
== NULL
) return NULL
;
1714 write_support
= supportChain_listBddExpr(globalCct
, write
);
1716 /* generate list of expressions which must be non-constant */
1717 /* and condition for non-asynchronous write */
1718 async_check
= BDD_one
;
1719 for (ptbiabl
= drivers
; ptbiabl
; ptbiabl
= ptbiabl
->NEXT
) {
1720 if (yagOneExpr(ptbiabl
->VALABL
) || yagZeroExpr(ptbiabl
->VALABL
)) {
1721 async_check
= applyBinBdd(AND
, async_check
, notBdd(ablToBddCct(globalCct
, ptbiabl
->CNDABL
)));
1722 *ptasync_write
= applyBinBdd(OR
, *ptasync_write
, ablToBddCct(globalCct
, ptbiabl
->CNDABL
));
1724 else cmd_exprs
= addchain(cmd_exprs
, yagApplyConstraints(ablToBddCct(globalCct
, ptbiabl
->CNDABL
), NULL
));
1726 if (oneBdd(async_check
)) {
1727 freechain(write_support
);
1728 freechain(cmd_exprs
);
1731 async_check
= yagApplyConstraints(async_check
, NULL
);
1732 *ptasync_write
= yagApplyConstraints(*ptasync_write
, NULL
);
1733 for (ptchain
= looplist
; ptchain
; ptchain
= ptchain
->NEXT
) {
1734 ptloopcone
= (cone_list
*)ptchain
->DATA
;
1735 if ((ptuser
= getptype(ptloopcone
->USER
, YAG_DUALEXPR_PTYPE
)) != NULL
) {
1736 expr
= (chain_list
*)ptuser
->DATA
;
1737 check_exprs
= addchain(check_exprs
, ablToBddCct(globalCct
, expr
));
1740 if ((ptuser
= getptype(ptloopcone
->USER
, CNS_UPEXPR
)) != NULL
) {
1741 expr
= (chain_list
*)ptuser
->DATA
;
1742 check_exprs
= addchain(check_exprs
, ablToBddCct(globalCct
, expr
));
1744 if ((ptuser
= getptype(ptloopcone
->USER
, CNS_DNEXPR
)) != NULL
) {
1745 expr
= (chain_list
*)ptuser
->DATA
;
1746 check_exprs
= addchain(check_exprs
, yagApplyConstraints(ablToBddCct(globalCct
, expr
), NULL
));
1751 /* Separate commands into list of clock commands and list of asynchronous commands */
1754 for (ptchain
= write_support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1755 command_name
= (char *)ptchain
->DATA
;
1756 expr
= createAtom(command_name
);
1757 command
= ablToBddCct(globalCct
, expr
);
1759 if (yagGetChain(clock_commands
, command_name
) != NULL
) continue;
1760 if (zeroBdd(constraintBdd(async_check
, command
))) {
1761 async_zero
= addchain(async_zero
, command_name
);
1762 async_check
= constraintBdd(async_check
, notBdd(command
));
1763 async_bdd_list
= addchain(async_bdd_list
, notBdd(command
));
1766 else if (zeroBdd(constraintBdd(async_check
, notBdd(command
)))) {
1767 async_one
= addchain(async_one
, command_name
);
1768 async_check
= constraintBdd(async_check
, command
);
1769 async_bdd_list
= addchain(async_bdd_list
, command
);
1773 for (ptchain
= check_exprs
; ptchain
; ptchain
= ptnextchain
) {
1774 ptnextchain
= ptchain
->NEXT
;
1775 check
= (pNode
)ptchain
->DATA
;
1776 for (ptchain1
= async_bdd_list
; ptchain1
; ptchain1
= ptchain1
->NEXT
) {
1777 check
= constraintBdd(check
, (pNode
)ptchain1
->DATA
);
1779 ptchain
->DATA
= (chain_list
*)check
;
1780 if (zeroBdd(check
) || oneBdd(check
)) {
1785 for (ptchain
= cmd_exprs
; ptchain
; ptchain
= ptnextchain
) {
1786 ptnextchain
= ptchain
->NEXT
;
1787 check
= (pNode
)ptchain
->DATA
;
1788 for (ptchain1
= async_bdd_list
; ptchain1
; ptchain1
= ptchain1
->NEXT
) {
1789 check
= constraintBdd(check
, (pNode
)ptchain1
->DATA
);
1791 ptchain
->DATA
= (chain_list
*)check
;
1792 if (zeroBdd(check
) || oneBdd(check
)) {
1796 support
= supportChain_listBddExpr(globalCct
, check
);
1797 if (yagCountChains(support
) == 1) {
1798 command_name
= (char *)support
->DATA
;
1799 clock_commands
= addchain(clock_commands
, command_name
);
1800 command_expr
= createAtom(command_name
);
1801 command
= ablToBddCct(globalCct
, command_expr
);
1802 freeExpr(command_expr
);
1803 cmd_exprs
= delchain(cmd_exprs
, ptchain
);
1805 /* adapt the async_check expr with info of sure clock */
1806 async_check
= applyBinBdd(AND
, constraintBdd(async_check
, command
), constraintBdd(async_check
, notBdd(command
)));
1810 } while (changes
&& (yagCountChains(async_bdd_list
) + yagCountChains(clock_commands
) < yagCountChains(write_support
)));
1812 freechain(cmd_exprs
);
1813 freechain(check_exprs
);
1814 freechain(async_bdd_list
);
1815 freechain(clock_commands
);
1816 freechain(write_support
);
1818 freechain(async_one
);
1819 freechain(async_zero
);
1822 else return append(async_one
, async_zero
);
1826 yagGetCommands(pCircuit globalCct
, cone_list
*ptcone
, pNode condition
, int strict
, chain_list
**ptdatacommands
)
1829 chain_list
*ptcommands
= NULL
;
1830 chain_list
*ptchain
;
1831 chain_list
*support
;
1832 chain_list
*condition_support
;
1835 char *name
, *invname
;
1836 chain_list
*invlist
, *invchain
;
1838 if ((ptcone
->TYPE
& CNS_RS
) == CNS_RS
) return NULL
;
1839 condition_support
= supportChain_listBddExpr(globalCct
, condition
);
1841 for (ptedge
= ptcone
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
1843 if ((ptedge
->TYPE
& CNS_BLEEDER
) != 0) continue;
1844 if ((ptedge
->TYPE
& CNS_EXT
) != CNS_EXT
) {
1845 name
= ptedge
->UEDGE
.CONE
->NAME
;
1847 else name
= ptedge
->UEDGE
.LOCON
->NAME
;
1848 expr
= searchOutputCct_no_NA(globalCct
, name
);
1849 if (expr
== NULL
) continue;
1850 /* apply the contraints */
1851 expr
= yagApplyConstraints(expr
, NULL
);
1853 support
= supportChain_listBddExpr(globalCct
, expr
);
1854 if (support
== NULL
) continue;
1855 if (strict
) { /* a command must only be influenced by write support */
1856 for (ptchain
= support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1857 if (yagGetChain(condition_support
, ptchain
->DATA
) == NULL
) {
1858 if (ptchain
->DATA
!= ptcone
->NAME
|| support
->NEXT
== NULL
) break;
1861 if (ptchain
== NULL
) {
1862 ptcommands
= addchain(ptcommands
, name
);
1866 else { /* command if at all influenced by write support */
1867 for (ptchain
= support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1868 if (yagGetChain(condition_support
, ptchain
->DATA
) != NULL
) break;
1870 if (ptchain
!= NULL
) {
1871 ptcommands
= addchain(ptcommands
, name
);
1875 if (ptdatacommands
!= NULL
&& strict
) { /* datacommand if at all influenced but not in strict list */
1876 for (ptchain
= support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1877 if (yagGetChain(condition_support
, ptchain
->DATA
) != NULL
) break;
1879 if (ptchain
!= NULL
) {
1880 if (ptcommands
== NULL
|| ptcommands
->DATA
!= name
) {
1881 *ptdatacommands
= addchain(*ptdatacommands
, name
);
1887 if (added
) continue;
1888 invlist
= getInvList(name
);
1889 for (invchain
= invlist
; invchain
; invchain
= invchain
->NEXT
) {
1890 invname
= (char *)invchain
->DATA
;
1891 expr
= searchOutputCct_no_NA(globalCct
, invname
);
1892 if (expr
== NULL
) continue;
1893 /* apply the contraints */
1894 expr
= yagApplyConstraints(expr
, NULL
);
1896 support
= supportChain_listBddExpr(globalCct
, expr
);
1897 if (support
== NULL
) continue;
1898 if (strict
) { /* a command must only be influenced by write support */
1899 for (ptchain
= support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1900 if (yagGetChain(condition_support
, ptchain
->DATA
) == NULL
) {
1901 if (ptchain
->DATA
!= ptcone
->NAME
|| support
->NEXT
== NULL
) break;
1904 if (ptchain
== NULL
) {
1905 ptcommands
= addchain(ptcommands
, name
);
1910 else { /* command if at all influenced by write support */
1911 for (ptchain
= support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1912 if (yagGetChain(condition_support
, ptchain
->DATA
) != NULL
) break;
1914 if (ptchain
!= NULL
) {
1915 ptcommands
= addchain(ptcommands
, name
);
1920 if (ptdatacommands
!= NULL
&& strict
) { /* datacommand if at all influenced but not in strict list */
1921 for (ptchain
= support
; ptchain
; ptchain
= ptchain
->NEXT
) {
1922 if (yagGetChain(condition_support
, ptchain
->DATA
) != NULL
) break;
1924 if (ptchain
!= NULL
) {
1925 if (ptcommands
== NULL
|| ptcommands
->DATA
!= name
) {
1926 *ptdatacommands
= addchain(*ptdatacommands
, name
);
1936 freechain(condition_support
);
1941 yagDisableRSArcs(cone_list
*ptcone1
, cone_list
*ptcone2
, cone_list
*ptloopcone1
, cone_list
*ptloopcone2
, long rstype
, short cuttype
)
1943 chain_list
*ptinlist1
= NULL
, *ptinlist2
= NULL
;
1944 chain_list
*ptchain
;
1945 cone_list
*ptincone1
, *ptincone2
;
1950 int count1
= 0, count2
= 0;
1952 for (ptedge
= ptcone1
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
1953 if ((ptedge
->TYPE
& CNS_EXT
) != 0) continue;
1954 if (ptedge
->UEDGE
.CONE
!= ptloopcone2
) ptinlist1
= addchain(ptinlist1
, ptedge
->UEDGE
.CONE
);
1957 for (ptedge
= ptcone2
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
1958 if ((ptedge
->TYPE
& CNS_EXT
) != 0) continue;
1959 if (ptedge
->UEDGE
.CONE
!= ptloopcone1
) ptinlist2
= addchain(ptinlist2
, ptedge
->UEDGE
.CONE
);
1964 ptuser
= getptype(ptcone1
->USER
, YAG_INFO_PTYPE
);
1965 if (ptuser
!= NULL
) infotype
|= (long)ptuser
->DATA
& (YAG_INFORSMARK
|YAG_INFORSLEGAL
|YAG_INFORSILLEGAL
);
1966 ptuser
= getptype(ptcone2
->USER
, YAG_INFO_PTYPE
);
1967 if (ptuser
!= NULL
) infotype
|= (long)ptuser
->DATA
& (YAG_INFORSMARK
|YAG_INFORSLEGAL
|YAG_INFORSILLEGAL
);
1970 case YAG_INFORSMARK
:
1971 freechain(ptinlist1
);
1972 freechain(ptinlist2
);
1974 case YAG_INFORSLEGAL
: cuttype
= YAG_RS_LEGAL
; break;
1975 case YAG_INFORSILLEGAL
: cuttype
= YAG_RS_ILLEGAL
; break;
1977 freechain(ptinlist1
);
1978 freechain(ptinlist2
);
1984 freechain(ptinlist1
);
1985 freechain(ptinlist2
);
1989 ifl
=getloadedinffig(YAG_CONTEXT
->YAG_FIGNAME
);
1990 if (ifl
== NULL
) ifl
= addinffig(YAG_CONTEXT
->YAG_FIGNAME
);
1992 if (rstype
== CNS_NOR
) {
1993 inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone1
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName(ptloopcone2
->NAME
), NULL
, 0x21, 0, NULL
);
1994 inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone2
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName(ptloopcone1
->NAME
), NULL
, 0x21, 0, NULL
);
1995 if ((cuttype
& YAG_RS_LEGAL
) != 0) {
1996 for (ptchain
= ptinlist1
; ptchain
; ptchain
= ptchain
->NEXT
) {
1997 ptincone1
= (cone_list
*)ptchain
->DATA
;
1998 inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone1
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName(ptincone1
->NAME
), NULL
, 0x12, 0, NULL
);
2000 for (ptchain
= ptinlist2
; ptchain
; ptchain
= ptchain
->NEXT
) {
2001 ptincone2
= (cone_list
*)ptchain
->DATA
;
2002 inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone2
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName(ptincone2
->NAME
), NULL
, 0x12, 0, NULL
);
2006 if (rstype
== CNS_NAND
) {
2007 inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone1
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName(ptloopcone2
->NAME
), NULL
, 0x12, 0, NULL
);
2008 inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone2
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName(ptloopcone1
->NAME
), NULL
, 0x12, 0, NULL
);
2009 if ((cuttype
& YAG_RS_LEGAL
) != 0) {
2010 for (ptchain
= ptinlist1
; ptchain
; ptchain
= ptchain
->NEXT
) {
2011 ptincone1
= (cone_list
*)ptchain
->DATA
;
2012 inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone1
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName(ptincone1
->NAME
), NULL
, 0x21, 0, NULL
);
2014 for (ptchain
= ptinlist2
; ptchain
; ptchain
= ptchain
->NEXT
) {
2015 ptincone2
= (cone_list
*)ptchain
->DATA
;
2016 inf_AddAssociation(ifl
, INF_LOADED_LOCATION
, infTasVectName(ptcone2
->NAME
), INF_DISABLE_GATE_DELAY
, infTasVectName(ptincone2
->NAME
), NULL
, 0x21, 0, NULL
);
2020 freechain(ptinlist1
);
2021 freechain(ptinlist2
);
2025 yagAutoRSCheck(cone_list
*ptcone
, chain_list
*looplist
)
2027 cone_list
*loopcone
;
2028 biabl_list
*drivers
= NULL
;
2029 biabl_list
*ptbiabl
, *weakdriver
= NULL
;
2030 befig_list
*ptbefig
= NULL
;
2033 int rslatch
= FALSE
, has_set
= FALSE
, has_reset
= FALSE
;
2035 ptuser
= getptype(ptcone
->USER
, YAG_LATCHBEFIG_PTYPE
);
2037 ptbefig
= (befig_list
*)ptuser
->DATA
;
2038 if (ptbefig
->BEREG
) drivers
= ptbefig
->BEREG
->BIABL
;
2040 if (drivers
== NULL
) return;
2042 if (YAG_CONTEXT
->YAG_AUTO_RS
> 0) {
2046 for (ptbiabl
= drivers
; ptbiabl
; ptbiabl
= ptbiabl
->NEXT
) {
2047 if ((ptbiabl
->FLAG
& BEH_CND_WEAK
) == BEH_CND_WEAK
) {
2048 weakdriver
= ptbiabl
;
2051 if (!yagOneExpr(ptbiabl
->VALABL
) && !yagZeroExpr(ptbiabl
->VALABL
)) {
2054 if (yagOneExpr(ptbiabl
->VALABL
)) has_set
= TRUE
;
2055 if (yagZeroExpr(ptbiabl
->VALABL
)) has_reset
= TRUE
;
2057 if (has_set
== FALSE
|| has_reset
== FALSE
) rslatch
= FALSE
;
2058 if (yagCountChains(looplist
) != 1) rslatch
= FALSE
;
2060 loopcone
= (cone_list
*)looplist
->DATA
;
2061 if (yagMatchNAND(ptcone
, loopcone
) > 0 && yagMatchNAND(loopcone
, ptcone
) > 0) {
2064 if (yagMatchNOR(ptcone
, loopcone
) > 0 && yagMatchNOR(loopcone
, ptcone
) > 0) {
2067 if (rstype
== 0 && (YAG_CONTEXT
->YAG_AUTO_RS
& YAG_RS_TOLERANT
) == 0) rslatch
= FALSE
;
2069 if ((YAG_CONTEXT
->YAG_AUTO_RS
& YAG_RS_MODEL
) == 0) {
2070 beh_delbefig(ptbefig
, ptbefig
, 'Y');
2071 ptcone
->USER
= delptype(ptcone
->USER
, YAG_LATCHBEFIG_PTYPE
);
2073 else ptbefig
->BEREG
->BIABL
= beh_delbiabl(ptbefig
->BEREG
->BIABL
, weakdriver
, 'Y');
2074 ptcone
->USER
= addptype(ptcone
->USER
, YAG_BISTABLE_PTYPE
, loopcone
);
2075 loopcone
->USER
= addptype(loopcone
->USER
, YAG_BISTABLE_PTYPE
, ptcone
);
2076 ptcone
->TECTYPE
|= rstype
;
2077 loopcone
->TECTYPE
|= rstype
;
2078 ptcone
->TYPE
|= CNS_RS
;
2079 loopcone
->TYPE
|= CNS_RS
;
2086 yagAutoMemsymCheck(cone_list
*ptcone
, chain_list
*looplist
, pNode condition
, chain_list
*commandlist
, chain_list
**ptptloopcommands
)
2088 chain_list
*ptchain
, *ptchain1
;
2089 chain_list
*ptdata
, *ptloopdata
;
2090 chain_list
*ptdatachain
= NULL
, *ptloopdatachain
= NULL
;
2091 chain_list
*data_abl
, *loopdata_abl
;
2092 cone_list
*ptloopcone
;
2094 pNode dataexpr
, loopdataexpr
;
2097 for (ptchain
= looplist
; ptchain
; ptchain
= ptchain
->NEXT
) {
2098 ptloopcone
= (cone_list
*)ptchain
->DATA
;
2099 *ptptloopcommands
= yagGetCommands(YAG_CONTEXT
->YAG_CURCIRCUIT
, ptloopcone
, condition
, TRUE
, NULL
);
2101 /* check there is at least one command in common */
2102 for (ptchain1
= commandlist
; ptchain1
; ptchain1
= ptchain1
->NEXT
) {
2103 if (yagGetChain(*ptptloopcommands
, ptchain1
->DATA
) != NULL
) break;
2105 if (ptchain1
== NULL
) continue;
2107 /* build list of data inputs for cone and loopcone */
2108 for (ptedge
= ptcone
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
2109 if (ptedge
->UEDGE
.PTR
== ptloopcone
) continue;
2110 if ((ptedge
->TYPE
& CNS_EXT
) == CNS_EXT
) name
= ptedge
->UEDGE
.LOCON
->NAME
;
2111 else name
= ptedge
->UEDGE
.CONE
->NAME
;
2112 if (yagGetChain(commandlist
, name
) == NULL
) ptdatachain
= addchain(ptdatachain
, name
);
2114 for (ptedge
= ptloopcone
->INCONE
; ptedge
; ptedge
= ptedge
->NEXT
) {
2115 if (ptedge
->UEDGE
.PTR
== ptcone
) continue;
2116 if ((ptedge
->TYPE
& CNS_EXT
) == CNS_EXT
) name
= ptedge
->UEDGE
.LOCON
->NAME
;
2117 else name
= ptedge
->UEDGE
.CONE
->NAME
;
2118 if (yagGetChain(*ptptloopcommands
, name
) == NULL
) ptloopdatachain
= addchain(ptloopdatachain
, name
);
2121 for (ptdata
= ptdatachain
; ptdata
; ptdata
= ptdata
->NEXT
) {
2122 for (ptloopdata
= ptloopdatachain
; ptloopdata
; ptloopdata
= ptloopdata
->NEXT
) {
2123 data_abl
= createAtom(ptdata
->DATA
);
2124 dataexpr
= ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, data_abl
);
2125 loopdata_abl
= createAtom(ptloopdata
->DATA
);
2126 loopdataexpr
= ablToBddCct(YAG_CONTEXT
->YAG_CURCIRCUIT
, loopdata_abl
);
2128 freeExpr(loopdata_abl
);
2129 if (checkMemsymData(dataexpr
, loopdataexpr
)) break;
2131 if (ptloopdata
) break;
2135 if (ptchain
) { /* Memsym found */
2136 ptcone
->TYPE
|= CNS_MEMSYM
;
2137 ptloopcone
->TYPE
|= CNS_MEMSYM
;
2138 ptedge
= yagGetEdge(ptcone
->INCONE
, ptloopcone
);
2139 ptedge
->TYPE
|= CNS_MEMSYM
;
2140 ptedge
= yagGetEdge(ptloopcone
->INCONE
, ptcone
);
2141 ptedge
->TYPE
|= CNS_MEMSYM
;
2142 ptcone
->USER
= addptype(ptcone
->USER
, YAG_MEMORY_PTYPE
, ptloopcone
);
2143 ptloopcone
->USER
= addptype(ptloopcone
->USER
, YAG_MEMORY_PTYPE
, ptcone
);
2150 checkMemsymData(pNode dataexpr
, pNode loopdataexpr
)
2152 chain_list
*datasupport
, *loopdatasupport
;
2153 chain_list
*ptchain
;
2154 pNode xor_expr
, test_expr
;
2156 xor_expr
= applyBinBdd(OR
, applyBinBdd(AND
, dataexpr
, notBdd(loopdataexpr
)), applyBinBdd(AND
, notBdd(dataexpr
), loopdataexpr
));
2157 test_expr
= yagApplyConstraints(xor_expr
, NULL
);
2158 if (!zeroBdd(test_expr
)) {
2159 datasupport
= supportChain_listBddExpr(YAG_CONTEXT
->YAG_CURCIRCUIT
, dataexpr
);
2160 loopdatasupport
= supportChain_listBddExpr(YAG_CONTEXT
->YAG_CURCIRCUIT
, loopdataexpr
);
2161 for (ptchain
= datasupport
; ptchain
; ptchain
= ptchain
->NEXT
) {
2162 if (yagGetChain(loopdatasupport
, ptchain
->DATA
) != NULL
) break;
2164 freechain(datasupport
);
2165 freechain(loopdatasupport
);
2166 if (ptchain
|| (xor_expr
!= test_expr
)) return TRUE
;
2172 getInvList(char *name
)
2174 ptype_list
*ptptype
;
2175 chain_list
*ptsupport
;
2176 chain_list
*result
= NULL
;
2178 for (ptptype
= YAG_CONTEXT
->YAG_CONE_GRAPH
->EXTRA_CONSTRAINTS
; ptptype
; ptptype
= ptptype
->NEXT
) {
2179 ptsupport
= (chain_list
*)ptptype
->TYPE
;
2180 if (ptsupport
->DATA
== name
) result
= addchain(result
, ptsupport
->NEXT
->DATA
);
2181 else if (ptsupport
->NEXT
->DATA
== name
) result
= addchain(result
, ptsupport
->DATA
);