Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / yagle / yagle / yag_loops.c
1 /****************************************************************************/
2 /* */
3 /* Verification Tools */
4 /* */
5 /* Product: Yagle/HiTas */
6 /* */
7 /* (c) copyright AVERTEC */
8 /* All Rights Reserved */
9 /* Support : e-mail support@avertec.com */
10 /* */
11 /****************************************************************************/
12
13 #include "yag_headers.h"
14
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);
33
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 )
38
39 /*************************************************************************
40 * function yagAnalyseLoop() *
41 *************************************************************************/
42
43 void
44 yagAnalyseLoop(cone_list *ptcone, int fIgnoreFalse)
45 {
46 cone_list *ptloopcone, *ptsymcone = NULL;
47 abl_pair local_abl;
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;
52 chain_list *looplist;
53 chain_list *support;
54 chain_list *tempabl;
55 chain_list *command_list = NULL;
56 chain_list *symcommand_list = NULL;
57 chain_list *ptchain;
58 pCircuit directCct;
59 pCircuit latchCct;
60 pCircuit savecircuit;
61 edge_list *ptedge;
62 branch_list *ptbranch;
63 graph *savegraph;
64 pNode sup, sdn;
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;
70 pNode local_expr;
71 pNode memorise, sure_memorise, sure_write, async_write = NULL;
72 long branchmask;
73 int numvars;
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;
79 int loglvl3 = 0;
80 int restored;
81 int trylevelhold = FALSE;
82 int has_conflict = FALSE, has_hz = FALSE;
83 int count_forward, count_reverse;
84 int res;
85
86 loglvl3 = avt_islog(3,LOGYAG);
87
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;
96
97 if ((looplist = yagCheckLoop(ptcone, fIgnoreFalse)) != NULL) {
98 freechain(looplist);
99 adjust_cone(ptcone, fIgnoreFalse);
100 restored = FALSE;
101 looplist = yagCheckLoop(ptcone, fIgnoreFalse);
102 if (YAG_CONTEXT->YAG_AUTO_MEMSYM) adjust_cone_list(looplist, fIgnoreFalse);
103
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);
115 freechain(looplist);
116 return;
117 }
118 }
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);
123 freechain(looplist);
124 return;
125 }
126 if ((ptcone->TECTYPE & CNS_DUAL_CMOS) != CNS_DUAL_CMOS
127 && (ptloopcone->TECTYPE & CNS_DUAL_CMOS) != CNS_DUAL_CMOS) {
128 res = 0;
129 if (V_FLOAT_TAB[__YAGLE_LATCHLOOP_RATIO].VALUE > 1) {
130 res = check_stronger(ptloopcone, ptcone, V_FLOAT_TAB[__YAGLE_LATCHLOOP_RATIO].VALUE);
131 }
132 if (res != 1) {
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);
138 freechain(looplist);
139 return;
140 }
141 }
142 }
143 }
144
145 /* remove electrical conflicts in loop cones */
146
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;
153 }
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);
158 freechain(looplist);
159 return;
160 }
161 }
162
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 */
166
167 savegraph = YAG_CONTEXT->YAG_CONE_GRAPH;
168 savecircuit = YAG_CONTEXT->YAG_CURCIRCUIT;
169
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);
180 }
181 }
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);
188 }
189 }
190 YAG_CONTEXT->YAG_PROP_HZ = save_prop_hz;
191 ptcone->TYPE &= ~YAG_FORCEPRIM;
192
193 directCct = yagBuildDirectCct(ptcone);
194
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;
207 }
208 }
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);
213 freechain(looplist);
214 return;
215 }
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);
219
220 /* Generate expression for cone as a function of its direct inputs */
221
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'");
227
228 /* Build BDDs for direct inputs in terms of primary variables */
229 /* created as outputs for the current circuit */
230
231 yagBuildDirectInputBdds(ptcone);
232
233 /* Generate up and down expressions for cone in terms of direct inputs */
234
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);
242 freeExpr(tempabl);
243 freechain(support);
244
245 /* Generate up and down expressions for cone in terms of primary variables */
246
247 sup = ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, local_abl.UP);
248 sdn = ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, local_abl.DN);
249
250 /* apply the contraints */
251 sup = yagApplyConstraints(sup, NULL);
252 sdn = yagApplyConstraints(sdn, NULL);
253
254 freeExpr(local_abl.UP);
255 freeExpr(local_abl.DN);
256
257 /* Generate condition for electrical conflict */
258
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);
269 freeExpr(tempabl);
270 avt_log(LOGYAG,1," = '1'\n");
271 }
272 local_hz = notBdd(applyBinBdd(OR, local_sup, local_sdn));
273 has_hz = TRUE;
274 }
275 else local_hz = BDD_zero;
276
277 /* Generate conflict resolved expression for cone */
278
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);
283 }
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");
292 }
293 freeExpr(tempabl);
294 has_conflict = TRUE;
295 }
296 else res_global_conflict = BDD_zero;
297 }
298 else {
299 local_resconf = BDD_zero;
300 res_local_conflict = BDD_zero;
301 res_global_conflict = BDD_zero;
302 }
303
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);
322 }
323 local_conf_abl = bddToAblCct(directCct, res_local_conflict);
324 local_hz_abl = bddToAblCct(directCct, local_hz);
325
326 /* check loop stability and obtain memorisation condition */
327
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);
330 }
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);
336
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));
343 freechain(support);
344 }
345 local_expr_abl = bddToAblCct(directCct, local_expr);
346 latchCct = buildLatchCct(ptcone, looplist, local_expr_abl);
347 freeExpr(local_expr_abl);
348
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);
355 }
356 if (YAG_CONTEXT->YAG_AUTO_RS > 0) {
357 yagAutoRSCheck(ptcone, looplist);
358 }
359 if (YAG_CONTEXT->YAG_AUTO_ASYNC > 0) {
360 latch_async_inputs = yagGetAsyncLatchInputs(ptcone, looplist, YAG_CONTEXT->YAG_CURCIRCUIT, sure_write, &async_write);
361 }
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);
366 }
367 restore_cone(ptcone, fIgnoreFalse);
368 if (YAG_CONTEXT->YAG_AUTO_MEMSYM) restore_cone_list(looplist, fIgnoreFalse);
369 restored = TRUE;
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);
373 }
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);
378 if (has_conflict) {
379 ptcone->TYPE |= CNS_CONFLICT;
380 if (ptsymcone) ptsymcone->TYPE |= CNS_CONFLICT;
381 }
382 if (has_hz) {
383 ptcone->TYPE |= CNS_TRI;
384 if (ptsymcone) ptsymcone->TYPE |= CNS_TRI;
385 }
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);
393 }
394 }
395 else if (memorise == BDD_zero) {
396 trylevelhold = TRUE;
397 }
398
399 freeExpr(local_conf_abl);
400 freeExpr(local_hz_abl);
401 }
402 }
403 else trylevelhold = TRUE;
404
405 if (!restored) {
406 restore_cone(ptcone, fIgnoreFalse);
407 if (YAG_CONTEXT->YAG_AUTO_MEMSYM) restore_cone_list(looplist, fIgnoreFalse);
408 }
409 if (trylevelhold) {
410 test_levelhold(ptcone, looplist);
411 }
412 freechain(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;
419 }
420 }
421
422 static void
423 test_levelhold(cone_list *ptcone, chain_list *looplist)
424 {
425 losig_list *ptloopsig;
426 chain_list *ptchain;
427 cone_list *ptloopcone;
428
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);
435 }
436 }
437 }
438
439 /* Adjust and restore functions to allow ignoring of possible false */
440 /* branches and to treat level-hold nodes as external connectors */
441
442 static void
443 adjust_cone_list(chain_list *ptconelist, int fIgnoreFalse)
444 {
445 chain_list *ptchain;
446
447 for (ptchain = ptconelist; ptchain; ptchain = ptchain->NEXT) {
448 adjust_cone((cone_list *)ptchain->DATA, fIgnoreFalse);
449 }
450 }
451
452 static void
453 restore_cone_list(chain_list *ptconelist, int fIgnoreFalse)
454 {
455 chain_list *ptchain;
456
457 for (ptchain = ptconelist; ptchain; ptchain = ptchain->NEXT) {
458 restore_cone((cone_list *)ptchain->DATA, fIgnoreFalse);
459 }
460 }
461
462 static void
463 adjust_cone(cone_list *ptcone, int fIgnoreFalse)
464 {
465 branch_list *ptbranch;
466 link_list *ptlink;
467 cone_list *ptsigcone;
468 losig_list *ptsig, *ptnextsig, *ptlastsig;
469 ptype_list *ptuser;
470 branch_list *brlist[4];
471 edge_list *save_inputs, *ptedge;
472 link_list *ptlink1, *ptlinklist;
473 locon_list *ptcon;
474 int i, changed = FALSE;
475
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;
481
482 for (i = 0; i < 4; i++) {
483 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptbranch->NEXT) {
484 ptlastsig = ptsig;
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;
490 }
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) {
498 changed = TRUE;
499 ptlinklist = NULL;
500 for (ptlink1 = ptbranch->LINK; ptlink1 && ptlink1 != ptlink->NEXT; ptlink1 = ptlink1->NEXT) {
501 ptlinklist = addlink(ptlinklist, ptlink1->TYPE, ptlink1->ULINK.PTR, ptlink1->SIG);
502 }
503 ptcon = (locon_list *)mbkalloc(sizeof(locon_list));
504 ptcon->NAME = ptsigcone->NAME;
505 ptcon->SIG = ptnextsig;
506 ptcon->ROOT = NULL;
507 ptcon->TYPE = 'I';
508 ptcon->DIRECTION = 'I';
509 ptcon->USER = NULL;
510 ptcon->PNODE = NULL;
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));
513 }
514 break;
515 }
516 }
517 }
518 }
519 }
520
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);
526 else {
527 for (ptedge = save_inputs; ptedge; ptedge = ptedge->NEXT) {
528 if ((ptedge->TYPE & YAG_FALSECONF) == 0) {
529 addincone(ptcone, ptedge->TYPE, ptedge->UEDGE.PTR);
530 }
531 }
532 }
533 }
534
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;
541 }
542 }
543 }
544
545 static int
546 exist_tempbranch(cone_list *ptcone, branch_list *ptbranch)
547 {
548 branch_list *pttestbranch;
549 link_list *ptlink, *pttestlink;
550
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;
555 }
556 if (pttestlink->NEXT == NULL) break;
557 }
558 if (ptcone->BREXT != NULL && pttestbranch != NULL) return TRUE;
559 return FALSE;
560 }
561
562 static void
563 restore_cone(cone_list *ptcone, int fIgnoreFalse)
564 {
565 branch_list *ptbranch, *ptnextbranch;
566 branch_list *brlist[4];
567 link_list *ptlink;
568 edge_list *ptedge;
569 int i, changed = FALSE;
570
571 brlist[0] = ptcone->BRVDD;
572 brlist[1] = ptcone->BRVSS;
573 brlist[2] = ptcone->BREXT;
574 brlist[3] = ptcone->BRGND;
575
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;
580 changed = TRUE;
581 }
582 }
583 }
584
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);
591 }
592 }
593
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);
598 }
599
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;
605 }
606 }
607 }
608
609 static int
610 count_possible_data(cone_list *ptcone, cone_list *ptloopcone)
611 {
612 branch_list *ptbranch;
613 branch_list *brlist[3];
614 link_list *ptlink;
615 edge_list *ptedge;
616 lotrs_list *pttrans;
617 cone_list *ptincone;
618 chain_list *tmpchain;
619 chain_list *list[3];
620 int i, count = 0;
621
622
623 brlist[0] = ptcone->BRVDD;
624 brlist[1] = ptcone->BRVSS;
625 brlist[2] = ptcone->BREXT;
626 list[0] = NULL;
627 list[1] = NULL;
628 list[2] = NULL;
629
630 for (i = 0; i < 3; i++) {
631 for (ptbranch = brlist[i]; ptbranch; ptbranch = ptbranch->NEXT) {
632 tmpchain = NULL;
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);
639 }
640 else {
641 pttrans = ptlink->ULINK.LOTRS;
642 ptincone = (cone_list *)getptype(pttrans->USER, CNS_DRIVINGCONE)->DATA;
643 ptedge = yagGetEdge(ptcone->INCONE, ptincone);
644 }
645 tmpchain = addchain(tmpchain, ptedge);
646 }
647 if (ptlink != NULL) freechain (tmpchain);
648 else list[i] = append(list[i], tmpchain);
649 }
650 }
651 for (ptedge = ptcone->INCONE; ptedge; ptedge = ptedge->NEXT) {
652 if (yagGetChain(list[2], ptedge) || (yagGetChain(list[0], ptedge) && yagGetChain(list[1], ptedge))) count++;
653 }
654 freechain(list[0]);
655 freechain(list[1]);
656 freechain(list[2]);
657
658 return count;
659 }
660
661 static int
662 check_stronger(cone_list *ptcone1, cone_list *ptcone2, float ratio)
663 {
664 branch_list *ptbranch;
665 link_list *ptlink;
666 chain_list *ptchain;
667 lotrs_list *pttrans;
668 float resistance1, resistance2;
669
670 ptchain = NULL;
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);
678 break;
679 }
680 }
681 }
682 resistance1 = yagCalcParallelResistance(ptchain);
683 freechain(ptchain);
684
685 ptchain = NULL;
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);
693 break;
694 }
695 }
696 }
697 resistance2 = yagCalcParallelResistance(ptchain);
698 freechain(ptchain);
699
700 if (resistance2 > ratio * resistance1) return 1;
701 if (resistance1 > ratio * resistance2) return -1;
702 return 0;
703 }
704
705 /*************************************************************************
706 * function yagAnalyseElectric() *
707 *************************************************************************/
708
709 pNode
710 yagAnalyseElectric(cone_list *ptcone, pCircuit conecct, int fIgnoreFalse)
711 {
712 pCircuit directCct;
713 pCircuit savecircuit;
714 graph *savegraph;
715 edge_list *save_inputs, *ptedge;
716 abl_pair local_abl;
717 chain_list *local_expr_abl;
718 pNode local_sup, local_sdn;
719 pNode local_conflict;
720 pNode local_resconf;
721 pNode local_expr;
722 long branchmask;
723 short save_prop_hz;
724 ptype_list *ptuser;
725
726 savegraph = YAG_CONTEXT->YAG_CONE_GRAPH;
727 savecircuit = YAG_CONTEXT->YAG_CURCIRCUIT;
728
729 if (fIgnoreFalse) {
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);
735 }
736 }
737 }
738
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;
743
744 /* Generate expression for cone as a function of its direct inputs */
745
746 branchmask = CNS_NOT_FUNCTIONAL|CNS_IGNORE|CNS_MASK_PARA;
747 if (fIgnoreFalse) branchmask |= YAG_FALSECONF;
748 cnsMakeConeExpr(ptcone, &local_abl, branchmask, 0, FALSE);
749
750 /* Build BDDs for direct inputs in terms of primary variables */
751 /* created as outputs for the current circuit */
752
753 yagBuildDirectInputBdds(ptcone);
754
755 if (conecct == NULL) directCct = yagBuildDirectCct(ptcone);
756 else directCct = conecct;
757
758 if (directCct->countI <= YAG_CONTEXT->YAG_AUTOLOOP_CEILING) {
759 /* Generate up and down expressions for cone in terms of direct inputs */
760
761 if (local_abl.UP != NULL) {
762 local_sup = ablToBddCct(directCct, local_abl.UP);
763 freeExpr(local_abl.UP);
764 }
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);
769 }
770 else local_sdn = BDD_zero;
771
772 /* Generate condition for electrical conflict */
773
774 local_conflict = applyBinBdd(AND, local_sup, local_sdn);
775
776 /* Generate conflict resolved expression for cone */
777
778 local_resconf = yagResolveConflicts(directCct, YAG_CONTEXT->YAG_CURCIRCUIT, &local_conflict, ptcone);
779 if (local_conflict == BDD_zero) {
780 ptcone->TECTYPE |= YAG_RESCONF;
781 }
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;
787 }
788 else ptcone->USER = addptype(ptcone->USER, CNS_UPEXPR, local_expr_abl);
789 }
790
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;
795
796 if (fIgnoreFalse) {
797 yagFreeEdgeList(ptcone->INCONE);
798 ptcone->INCONE = save_inputs;
799 }
800 if (conecct != NULL) return local_conflict;
801 else return NULL;
802 }
803
804 /*************************************************************************
805 * function buildDirectInputBdds() *
806 *************************************************************************/
807
808 /* build BDDs for roots of the current graph */
809 /* store as outputs of the current circuit */
810
811 void
812 yagBuildDirectInputBdds(cone_list *ptcone)
813 {
814 char *name;
815 pNode bdd;
816 edge_list *ptedge;
817 chain_list *expr;
818 chain_list *tempexpr;
819 gnode_list *ptnode;
820
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;
826 }
827 else {
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;
831 }
832 tempexpr = createAtom(name);
833 expr = yagExpandExpr(ptnode, tempexpr, 0);
834 freeExpr(tempexpr);
835 bdd = ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, expr);
836 addOutputCct_no_NA(YAG_CONTEXT->YAG_CURCIRCUIT, name, bdd);
837 freeExpr(expr);
838 }
839 }
840
841 /*************************************************************************
842 * function buildDirectCct() *
843 *************************************************************************/
844
845 /* build circuit for cone direct inputs */
846
847 pCircuit
848 yagBuildDirectCct(cone_list *ptcone)
849 {
850 pCircuit circuit;
851 edge_list *ptedge;
852 char *name;
853 int numinputs;
854
855 numinputs = yagCountEdges(ptcone->INCONE);
856 circuit = initializeCct(ptcone->NAME, numinputs, 10);
857
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;
863 }
864 else name = ptedge->UEDGE.LOCON->NAME;
865 addInputCct_no_NA(circuit, name);
866 }
867
868 avt_log(LOGYAG,1, "Number of direct inputs : %d\n", circuit->countI);
869 return circuit;
870 }
871
872 /*************************************************************************
873 * function buildLatchCct() *
874 *************************************************************************/
875
876 /* build circuit for latch analysis */
877
878 static pCircuit
879 buildLatchCct(cone_list *ptcone, chain_list *looplist, chain_list *latchexpr)
880 {
881 pCircuit circuit;
882 pNode bdd;
883 edge_list *ptedge;
884 cone_list *ptloopcone;
885 gnode_list *ptloopnode;
886 gnode_list *ptnode;
887 chain_list *ptchain0, *ptchain1;
888 chain_list *tempexpr, *expr;
889 chain_list *nodelist;
890 ptype_list *ptuser;
891 char *name;
892 int numinputs;
893 int flag;
894 int stuck;
895
896 numinputs = yagCountEdges(ptcone->INCONE) - yagCountChains(looplist) + 1;
897 circuit = initializeCct(ptcone->NAME, numinputs, 10);
898
899 /* Add all inputs which are not on the loop */
900
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);
908 flag = FALSE;
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;
913 }
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));
917 freeExpr(expr);
918 }
919 else addInputCct_no_NA(circuit, ptedge->UEDGE.CONE->NAME);
920 freechain(nodelist);
921 }
922 else addInputCct_no_NA(circuit, ptedge->UEDGE.LOCON->NAME);
923 }
924
925 /* Add union of inputs of all cones on the loop */
926
927 for (ptchain0 = looplist; ptchain0; ptchain0 = ptchain0->NEXT) {
928
929 /* Add loop cone inputs to latch circuit and */
930 /* add BDDs for them to global circuit */
931
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;
937 }
938 else {
939 /* node is an external connector */
940 name = ptnode->OBJECT.LOCON->NAME;
941 }
942 if (searchInputCct_no_NA(circuit, name) == EMPTYTH) {
943 addInputCct_no_NA(circuit, name);
944 }
945 if (searchOutputCct_no_NA(YAG_CONTEXT->YAG_CURCIRCUIT, name) != NULL) continue;
946 tempexpr = createAtom(name);
947 expr = yagExpandExpr(ptnode, tempexpr, 0);
948 freeExpr(tempexpr);
949 bdd = ablToBddCct(YAG_CONTEXT->YAG_CURCIRCUIT, expr);
950 addOutputCct_no_NA(YAG_CONTEXT->YAG_CURCIRCUIT, name, bdd);
951 freeExpr(expr);
952 }
953
954 /* Add loop cone expr to output of latch circuit */
955
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);
959 }
960 else ptuser = getptype(ptloopcone->USER, CNS_UPEXPR);
961 if (ptuser == NULL) {
962 yagBug(DBG_NO_ABL, "buildLatchCct", ptloopcone->NAME, NULL, 0);
963 }
964 addOutputCct_no_NA(circuit, ptloopcone->NAME, ablToBddCct(circuit, (chain_list *)ptuser->DATA));
965 }
966
967 /* Add bdd for latch output */
968 addOutputCct_no_NA(circuit, ptcone->NAME, ablToBddCct(circuit, latchexpr));
969
970 if ( avt_islog(2,LOGYAG) ) {
971 displayCctLog(LOGYAG,2,circuit, 1);
972 }
973 return circuit;
974 }
975
976 /*************************************************************************
977 * function checkLoopStability() *
978 *************************************************************************/
979
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 */
983
984 static int
985 checkLoopStability(pCircuit circuit, pNode expr, char *name, pNode *ptmem)
986 {
987 pNode f0, f1;
988 pNode loopvar;
989 int index;
990
991 index = searchInputCct_no_NA(circuit, name); // called with a cone name => already namealloced
992 if (index <= 1) {
993 avt_log(LOGYAG,1, "loopname: %s\n", name);
994 displayCctLog(LOGYAG,1,circuit, 0);
995 }
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);
1002 }
1003 *ptmem = applyBinBdd(AND, f1, notBdd(f0));
1004
1005 if (applyBinBdd(AND, f0, notBdd(f1)) != BDD_zero) return FALSE;
1006 else return TRUE;
1007 }
1008
1009 /*************************************************************************
1010 * function isInversion() *
1011 *************************************************************************/
1012
1013 /* check for inverse relation between given input and output */
1014
1015 int
1016 yagIsInversion(pCircuit circuit, char *input, char *output)
1017 {
1018 pNode f0, f1;
1019 pNode loopvar;
1020 pNode expr;
1021 int index;
1022
1023 index = searchInputCct_no_NA(circuit, input); // called with a cone name => already namealloced
1024 if (index <= 1) {
1025 avt_log(LOGYAG,1, "input: %s\n", input);
1026 displayCctLog(LOGYAG,1,circuit, 0);
1027 return TRUE;
1028 }
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);
1033 return TRUE;
1034 }
1035 f1 = constraintBdd(expr, loopvar);
1036 f0 = constraintBdd(expr, notBdd(loopvar));
1037
1038 if (applyBinBdd(AND, f0, notBdd(f1)) != BDD_zero) return TRUE;
1039 else return FALSE;
1040 }
1041
1042 /*************************************************************************
1043 * function getWriteSupport() *
1044 *************************************************************************/
1045
1046 /* given a global write condition obtain list of */
1047 /* all constrained inputs of the latch circuit */
1048
1049 chain_list *
1050 yagGetCorrelatedWriteSupport(pCircuit globalCct, pCircuit latchCct, pNode write, chain_list *ptallsupport)
1051 {
1052 chain_list *result = NULL, *name_result = NULL;
1053 chain_list *global_support;
1054 chain_list *ptchain;
1055 pNode globalvar;
1056 char *varname, *opposite_name;
1057 pNode varbdd;
1058 short index, opposite_index;
1059
1060 global_support = supportChain_listBdd(write);
1061
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;
1069 }
1070 if (ptchain != NULL) {
1071 if (yagGetChain(name_result, varname) == NULL) {
1072 result = addchain(result, createNodeTermBdd(index));
1073 name_result = addchain(name_result, varname);
1074 }
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);
1082 }
1083 }
1084 }
1085 freechain(ptchain);
1086 }
1087 }
1088 }
1089 /* Test whether all support are commands */
1090 if (ptallsupport) {
1091 for (ptchain = ptallsupport; ptchain; ptchain = ptchain->NEXT) {
1092 if (yagGetChain(name_result, ptchain->DATA) == NULL) break;
1093 }
1094 if (ptchain == NULL) {
1095 freechain(result);
1096 result = NULL;
1097 }
1098 }
1099 freechain(global_support);
1100 freechain(name_result);
1101 return result;
1102 }
1103
1104 chain_list *
1105 yagGetWriteSupport(pCircuit globalCct, pCircuit latchCct, pNode write, chain_list *ptallsupport)
1106 {
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;
1112 pNode varbdd;
1113 short index, opposite_index;
1114
1115 write_support = supportChain_listBddExpr(globalCct, write);
1116
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);
1123
1124 support = supportChain_listBddExpr(globalCct, varbdd);
1125 for (ptchain = support; ptchain; ptchain = ptchain->NEXT) {
1126 if (yagGetChain(write_support, ptchain->DATA) == NULL) break;
1127 }
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);
1132 }
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);
1140 }
1141 }
1142 }
1143 }
1144 }
1145 freechain(support);
1146 }
1147 /* try correlated support */
1148 if (result == NULL) {
1149 result = yagGetCorrelatedWriteSupport(globalCct, latchCct, write, ptallsupport);
1150 }
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;
1155 }
1156 if (ptchain == NULL) {
1157 freechain(result);
1158 result = NULL;
1159 }
1160 }
1161 freechain(write_support);
1162 freechain(name_result);
1163 return result;
1164 }
1165
1166 static chain_list *
1167 yagGetOppositeNames(char *name)
1168 {
1169 ptype_list *ptptype;
1170 chain_list *support;
1171 chain_list *reschain = NULL;
1172 char *opposite_name;
1173
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);
1180 }
1181 }
1182 return reschain;
1183 }
1184
1185 /*************************************************************************
1186 * function checkBranchBlocked() *
1187 *************************************************************************/
1188
1189 static int
1190 checkBranchBlocked(branch_list *ptbranch, pNode check)
1191 {
1192 pNode branchexpr, branch_check;
1193
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;
1198 return FALSE;
1199 }
1200
1201 /*************************************************************************
1202 * function checkFeedbackFunctional() *
1203 *************************************************************************/
1204
1205 static void
1206 checkFeedbackFunctional(branch_list *ptbranch, pNode write, cone_list *ptcone)
1207 {
1208 branch_list *ptbranchlist, *testbranch;
1209 pNode branchexpr, feedback_write, testexpr;
1210 ptype_list *ptuser;
1211
1212 if ((ptbranch->TYPE & CNS_VSS) == CNS_VSS) ptbranchlist = ptcone->BRVSS;
1213 else ptbranchlist = ptcone->BRVDD;
1214
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;
1225 }
1226 if (testbranch == NULL) ptbranch->TYPE &= ~(CNS_NOT_FUNCTIONAL|YAG_LATCH_NF);
1227 }
1228 }
1229
1230 /*************************************************************************
1231 * function markMemory() *
1232 *************************************************************************/
1233
1234 void
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)
1236 {
1237 link_list *ptlink;
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;
1247 ptype_list *ptuser;
1248 pNode sync_write, branchexpr, branch_mem;
1249 int i, hasdata, ismemsym;
1250 char *asyncname;
1251
1252 ptcone->TYPE |= YAG_AUTOLATCH;
1253 ptcone->TYPE &= ~YAG_LOOPCONF;
1254
1255 ismemsym = ((ptcone->TYPE & CNS_MEMSYM) == CNS_MEMSYM);
1256
1257 if ((ptcone->TYPE & CNS_RS) == CNS_RS) return;
1258 ptcone->TYPE |= CNS_LATCH;
1259
1260 if (async_write && write) sync_write = applyBinBdd(AND, write, notBdd(async_write));
1261 else sync_write = NULL;
1262
1263 brlist[0] = ptcone->BRVDD;
1264 brlist[1] = ptcone->BRVSS;
1265 brlist[2] = ptcone->BREXT;
1266
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;
1276 }
1277 }
1278 if (yagGetChain(commandlist, ptincone->NAME) != NULL) {
1279 ptinedge->TYPE |= CNS_COMMAND;
1280 }
1281 if (yagGetChain(async_command_list, ptincone->NAME) != NULL) {
1282 ptinedge->TYPE |= CNS_ASYNC|((V_BOOL_TAB[__YAGLE_ASYNC_COMMAND].VALUE)?CNS_COMMAND:0);
1283 }
1284 }
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;
1302 }
1303 }
1304 asyncname = NULL;
1305 hasdata = FALSE;
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;
1313 }
1314 /* asynchronous driver branch */
1315 if (asyncname && sync_write && checkBranchBlocked(ptbranch, sync_write)) {
1316 ptbranch->TYPE |= YAG_ASYNC;
1317 continue;
1318 }
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;
1322 }
1323 if ((ptbranch->TYPE & (CNS_FEEDBACK|CNS_NOT_FUNCTIONAL)) == (CNS_FEEDBACK|CNS_NOT_FUNCTIONAL)) {
1324 continue;
1325 }
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);
1335 }
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);
1342 }
1343 }
1344 }
1345 else {
1346 if (yagGetChain(commandlist, ptincone->NAME) != NULL) {
1347 ptlink->TYPE |= CNS_COMMAND;
1348 }
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;
1355 }
1356 }
1357 }
1358 }
1359 }
1360 }
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);
1367 }
1368 if ((ptbranch->TYPE & CNS_NOT_FUNCTIONAL) == CNS_NOT_FUNCTIONAL) continue;
1369 if ((ptbranch->TYPE & YAG_ASYNC) == YAG_ASYNC) {
1370 loopcone = NULL;
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);
1377 }
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);
1382 }
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);
1389 }
1390 }
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;
1398 }
1399 ptbranch->TYPE &= ~CNS_FEEDBACK;
1400 }
1401 }
1402 }
1403 }
1404 else {
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;
1410 }
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;
1415 }
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;
1422 }
1423 }
1424 }
1425 }
1426 }
1427 }
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);
1433 }
1434 }
1435 }
1436
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);
1441 }
1442 }
1443 }
1444 if (YAG_CONTEXT->YAG_AUTO_ASYNC > 0) {
1445 yagDisableAsyncTimings(ptcone, commandlist, async_command_list, fIgnoreFalse);
1446 }
1447 if (ismemsym) {
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);
1451 }
1452 }
1453 for (ptinedge = ptcone->INCONE; ptinedge; ptinedge = ptinedge->NEXT) {
1454 ptinedge->TYPE &= ~CNS_FEEDBACK;
1455 }
1456 }
1457 }
1458
1459 /*************************************************************************
1460 * function yagDisableAsyncTimings() *
1461 *************************************************************************/
1462
1463 static void
1464 yagDisableAsyncTimings(cone_list *ptcone, chain_list *commandlist, chain_list *async_command_list, int fIgnoreFalse)
1465 {
1466 link_list *ptlink;
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;
1474 int i, j;
1475 char *inname;
1476 inffig_list *ifl;
1477
1478 if (async_command_list) {
1479 ifl=getloadedinffig(YAG_CONTEXT->YAG_FIGNAME);
1480 if (ifl == NULL) ifl = addinffig(YAG_CONTEXT->YAG_FIGNAME);
1481
1482 brlist[0] = ptcone->BRVDD;
1483 brlist[1] = ptcone->BRVSS;
1484 brlist[2] = ptcone->BREXT;
1485
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;
1505 }
1506 else {
1507 ptincone = (cone_list *)getptype(pttrans->USER, CNS_DRIVINGCONE)->DATA;
1508 if (ptincone == NULL) continue;
1509 inname = ptincone->NAME;
1510 }
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;
1516 }
1517 if (i == 2) {
1518 if ((ptptype2 = getptype(comtypelist[1], (long)inname)) == NULL) {
1519 ptptype2 = addptype(comtypelist[1], (long)inname, NULL);
1520 comtypelist[1] = ptptype2;
1521 }
1522 }
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));
1527 }
1528 else {
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));
1531 }
1532 }
1533 }
1534 }
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);
1542 }
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);
1546 }
1547 }
1548 freeptype(comtypelist[i]);
1549 }
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;
1565 }
1566 else {
1567 ptincone = (cone_list *)getptype(pttrans->USER, CNS_DRIVINGCONE)->DATA;
1568 if (ptincone == NULL) continue;
1569 inname = ptincone->NAME;
1570 }
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;
1576 }
1577 if (i == 2) {
1578 if ((ptptype2 = getptype(asynctypelist[1], (long)inname)) == NULL) {
1579 ptptype2 = addptype(asynctypelist[1], (long)inname, NULL);
1580 asynctypelist[1] = ptptype2;
1581 }
1582 }
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));
1587 }
1588 else {
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));
1591 }
1592 }
1593 }
1594 }
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);
1602 }
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);
1606 }
1607 }
1608 freeptype(asynctypelist[i]);
1609 }
1610 }
1611 }
1612
1613 static chain_list *
1614 yagGetAsyncCommands(cone_list *ptcone, chain_list **command_list, pCircuit globalCct, chain_list *latch_async_inputs)
1615 {
1616 edge_list *ptedge;
1617 chain_list *async_commands = NULL;
1618 chain_list *ptchain;
1619 chain_list *tmp_expr;
1620 chain_list *support;
1621 pNode expr;
1622 int added;
1623 char *name, *invname;
1624 chain_list *invlist, *invchain;
1625
1626 if ((ptcone->TYPE & CNS_RS) == CNS_RS) return NULL;
1627
1628 for (ptedge = ptcone->INCONE; ptedge; ptedge = ptedge->NEXT) {
1629 added = FALSE;
1630 if ((ptedge->TYPE & CNS_BLEEDER) != 0) continue;
1631 if ((ptedge->TYPE & CNS_EXT) != CNS_EXT) {
1632 name = ptedge->UEDGE.CONE->NAME;
1633 }
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);
1638 freeExpr(tmp_expr);
1639 if (expr == NULL) continue;
1640
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;
1646 }
1647 if (ptchain != NULL) {
1648 async_commands = addchain(async_commands, name);
1649 *command_list = delchaindata(*command_list, name);
1650 added = TRUE;
1651 }
1652 freechain(support);
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);
1659 freeExpr(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;
1666 }
1667 freechain(support);
1668 if (ptchain != NULL) {
1669 async_commands = addchain(async_commands, name);
1670 *command_list = delchaindata(*command_list, name);
1671 break;
1672 }
1673 }
1674 freechain(invlist);
1675 }
1676 return async_commands;
1677 }
1678
1679 static chain_list *
1680 yagGetAsyncLatchInputs(cone_list *ptcone, chain_list *looplist, pCircuit globalCct, pNode write, pNode *ptasync_write)
1681 {
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;
1692 ptype_list *ptuser;
1693 pNode async_check, command, check;
1694 char *command_name;
1695 int changes, abandon = FALSE;
1696
1697 *ptasync_write = BDD_zero;
1698 if ((ptcone->TYPE & CNS_RS) != 0) return NULL;
1699
1700 ptuser = getptype(ptcone->USER, YAG_LATCHBEFIG_PTYPE);
1701 if (ptuser) {
1702 ptbefig = (befig_list *)ptuser->DATA;
1703 if (ptbefig->BEREG) drivers = ptbefig->BEREG->BIABL;
1704 }
1705 if (drivers == NULL) return NULL;
1706
1707 ptuser = getptype(ptcone->USER, YAG_LATCHBEFIG_PTYPE);
1708 if (ptuser) {
1709 ptbefig = (befig_list *)ptuser->DATA;
1710 if (ptbefig->BEREG) drivers = ptbefig->BEREG->BIABL;
1711 }
1712 if (drivers == NULL) return NULL;
1713
1714 write_support = supportChain_listBddExpr(globalCct, write);
1715
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));
1723 }
1724 else cmd_exprs = addchain(cmd_exprs, yagApplyConstraints(ablToBddCct(globalCct, ptbiabl->CNDABL), NULL));
1725 }
1726 if (oneBdd(async_check)) {
1727 freechain(write_support);
1728 freechain(cmd_exprs);
1729 return NULL;
1730 }
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));
1738 }
1739 else {
1740 if ((ptuser = getptype(ptloopcone->USER, CNS_UPEXPR)) != NULL) {
1741 expr = (chain_list *)ptuser->DATA;
1742 check_exprs = addchain(check_exprs, ablToBddCct(globalCct, expr));
1743 }
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));
1747 }
1748 }
1749 }
1750
1751 /* Separate commands into list of clock commands and list of asynchronous commands */
1752 do {
1753 changes = FALSE;
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);
1758 freeExpr(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));
1764 changes = TRUE;
1765 }
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);
1770 changes = TRUE;
1771 }
1772 }
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);
1778 }
1779 ptchain->DATA = (chain_list *)check;
1780 if (zeroBdd(check) || oneBdd(check)) {
1781 abandon = TRUE;
1782 break;
1783 }
1784 }
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);
1790 }
1791 ptchain->DATA = (chain_list *)check;
1792 if (zeroBdd(check) || oneBdd(check)) {
1793 abandon = TRUE;
1794 break;
1795 }
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);
1804 changes = TRUE;
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)));
1807 }
1808 freechain(support);
1809 }
1810 } while (changes && (yagCountChains(async_bdd_list) + yagCountChains(clock_commands) < yagCountChains(write_support)));
1811
1812 freechain(cmd_exprs);
1813 freechain(check_exprs);
1814 freechain(async_bdd_list);
1815 freechain(clock_commands);
1816 freechain(write_support);
1817 if (abandon) {
1818 freechain(async_one);
1819 freechain(async_zero);
1820 return NULL;
1821 }
1822 else return append(async_one, async_zero);
1823 }
1824
1825 chain_list *
1826 yagGetCommands(pCircuit globalCct, cone_list *ptcone, pNode condition, int strict, chain_list **ptdatacommands)
1827 {
1828 edge_list *ptedge;
1829 chain_list *ptcommands = NULL;
1830 chain_list *ptchain;
1831 chain_list *support;
1832 chain_list *condition_support;
1833 pNode expr;
1834 int added;
1835 char *name, *invname;
1836 chain_list *invlist, *invchain;
1837
1838 if ((ptcone->TYPE & CNS_RS) == CNS_RS) return NULL;
1839 condition_support = supportChain_listBddExpr(globalCct, condition);
1840
1841 for (ptedge = ptcone->INCONE; ptedge; ptedge = ptedge->NEXT) {
1842 added = FALSE;
1843 if ((ptedge->TYPE & CNS_BLEEDER) != 0) continue;
1844 if ((ptedge->TYPE & CNS_EXT) != CNS_EXT) {
1845 name = ptedge->UEDGE.CONE->NAME;
1846 }
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);
1852
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;
1859 }
1860 }
1861 if (ptchain == NULL) {
1862 ptcommands = addchain(ptcommands, name);
1863 added = TRUE;
1864 }
1865 }
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;
1869 }
1870 if (ptchain != NULL) {
1871 ptcommands = addchain(ptcommands, name);
1872 added = TRUE;
1873 }
1874 }
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;
1878 }
1879 if (ptchain != NULL) {
1880 if (ptcommands == NULL || ptcommands->DATA != name) {
1881 *ptdatacommands = addchain(*ptdatacommands, name);
1882 added = TRUE;
1883 }
1884 }
1885 }
1886 freechain(support);
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);
1895
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;
1902 }
1903 }
1904 if (ptchain == NULL) {
1905 ptcommands = addchain(ptcommands, name);
1906 freechain(support);
1907 break;
1908 }
1909 }
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;
1913 }
1914 if (ptchain != NULL) {
1915 ptcommands = addchain(ptcommands, name);
1916 freechain(support);
1917 break;
1918 }
1919 }
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;
1923 }
1924 if (ptchain != NULL) {
1925 if (ptcommands == NULL || ptcommands->DATA != name) {
1926 *ptdatacommands = addchain(*ptdatacommands, name);
1927 freechain(support);
1928 break;
1929 }
1930 }
1931 }
1932 freechain(support);
1933 }
1934 freechain(invlist);
1935 }
1936 freechain(condition_support);
1937 return ptcommands;
1938 }
1939
1940 void
1941 yagDisableRSArcs(cone_list *ptcone1, cone_list *ptcone2, cone_list *ptloopcone1, cone_list *ptloopcone2, long rstype, short cuttype)
1942 {
1943 chain_list *ptinlist1 = NULL, *ptinlist2 = NULL;
1944 chain_list *ptchain;
1945 cone_list *ptincone1, *ptincone2;
1946 edge_list *ptedge;
1947 inffig_list *ifl;
1948 ptype_list *ptuser;
1949 long infotype;
1950 int count1 = 0, count2 = 0;
1951
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);
1955 count1++;
1956 }
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);
1960 count2++;
1961 }
1962
1963 infotype = 0;
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);
1968 switch (infotype) {
1969 case 0: break;
1970 case YAG_INFORSMARK:
1971 freechain(ptinlist1);
1972 freechain(ptinlist2);
1973 return;
1974 case YAG_INFORSLEGAL: cuttype = YAG_RS_LEGAL; break;
1975 case YAG_INFORSILLEGAL: cuttype = YAG_RS_ILLEGAL; break;
1976 default:
1977 freechain(ptinlist1);
1978 freechain(ptinlist2);
1979 return;
1980 }
1981
1982 if (cuttype == 0)
1983 {
1984 freechain(ptinlist1);
1985 freechain(ptinlist2);
1986 return;
1987 }
1988
1989 ifl=getloadedinffig(YAG_CONTEXT->YAG_FIGNAME);
1990 if (ifl == NULL) ifl = addinffig(YAG_CONTEXT->YAG_FIGNAME);
1991
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);
1999 }
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);
2003 }
2004 }
2005 }
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);
2013 }
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);
2017 }
2018 }
2019 }
2020 freechain(ptinlist1);
2021 freechain(ptinlist2);
2022 }
2023
2024 static void
2025 yagAutoRSCheck(cone_list *ptcone, chain_list *looplist)
2026 {
2027 cone_list *loopcone;
2028 biabl_list *drivers = NULL;
2029 biabl_list *ptbiabl, *weakdriver = NULL;
2030 befig_list *ptbefig = NULL;
2031 ptype_list *ptuser;
2032 long rstype = 0;
2033 int rslatch = FALSE, has_set = FALSE, has_reset = FALSE;
2034
2035 ptuser = getptype(ptcone->USER, YAG_LATCHBEFIG_PTYPE);
2036 if (ptuser) {
2037 ptbefig = (befig_list *)ptuser->DATA;
2038 if (ptbefig->BEREG) drivers = ptbefig->BEREG->BIABL;
2039 }
2040 if (drivers == NULL) return;
2041
2042 if (YAG_CONTEXT->YAG_AUTO_RS > 0) {
2043 rslatch = TRUE;
2044 has_set = FALSE;
2045 has_reset = FALSE;
2046 for (ptbiabl = drivers; ptbiabl; ptbiabl = ptbiabl->NEXT) {
2047 if ((ptbiabl->FLAG & BEH_CND_WEAK) == BEH_CND_WEAK) {
2048 weakdriver = ptbiabl;
2049 continue;
2050 }
2051 if (!yagOneExpr(ptbiabl->VALABL) && !yagZeroExpr(ptbiabl->VALABL)) {
2052 rslatch = FALSE;
2053 }
2054 if (yagOneExpr(ptbiabl->VALABL)) has_set = TRUE;
2055 if (yagZeroExpr(ptbiabl->VALABL)) has_reset = TRUE;
2056 }
2057 if (has_set == FALSE || has_reset == FALSE) rslatch = FALSE;
2058 if (yagCountChains(looplist) != 1) rslatch = FALSE;
2059 else {
2060 loopcone = (cone_list *)looplist->DATA;
2061 if (yagMatchNAND(ptcone, loopcone) > 0 && yagMatchNAND(loopcone, ptcone) > 0) {
2062 rstype = CNS_NAND;
2063 }
2064 if (yagMatchNOR(ptcone, loopcone) > 0 && yagMatchNOR(loopcone, ptcone) > 0) {
2065 rstype = CNS_NOR;
2066 }
2067 if (rstype == 0 && (YAG_CONTEXT->YAG_AUTO_RS & YAG_RS_TOLERANT) == 0) rslatch = FALSE;
2068 if (rslatch) {
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);
2072 }
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;
2080 }
2081 }
2082 }
2083 }
2084
2085 static cone_list *
2086 yagAutoMemsymCheck(cone_list *ptcone, chain_list *looplist, pNode condition, chain_list *commandlist, chain_list **ptptloopcommands)
2087 {
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;
2093 edge_list *ptedge;
2094 pNode dataexpr, loopdataexpr;
2095 char *name;
2096
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);
2100
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;
2104 }
2105 if (ptchain1 == NULL) continue;
2106
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);
2113 }
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);
2119 }
2120
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);
2127 freeExpr(data_abl);
2128 freeExpr(loopdata_abl);
2129 if (checkMemsymData(dataexpr, loopdataexpr)) break;
2130 }
2131 if (ptloopdata) break;
2132 }
2133 if (ptdata) break;
2134 }
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);
2144 return ptloopcone;
2145 }
2146 return NULL;
2147 }
2148
2149 static int
2150 checkMemsymData(pNode dataexpr, pNode loopdataexpr)
2151 {
2152 chain_list *datasupport, *loopdatasupport;
2153 chain_list *ptchain;
2154 pNode xor_expr, test_expr;
2155
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;
2163 }
2164 freechain(datasupport);
2165 freechain(loopdatasupport);
2166 if (ptchain || (xor_expr != test_expr)) return TRUE;
2167 }
2168 return FALSE;
2169 }
2170
2171 static chain_list *
2172 getInvList(char *name)
2173 {
2174 ptype_list *ptptype;
2175 chain_list *ptsupport;
2176 chain_list *result = NULL;
2177
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);
2182 }
2183 return result;
2184 }