Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / cns / coneexpr.c
1 /* 10/26/95 Cone Netlist Structure functions: coneexpr.c */
2
3 #include"cnsall.h"
4
5 static chain_list *getSwitchExpr(link_list *ptlink)
6 {
7 lotrs_list *ptlotrs;
8 ptype_list *ptuser;
9
10 if ((ptlink->TYPE & CNS_TNLINK) == CNS_TNLINK) {
11 ptuser = getptype(ptlink->ULINK.LOTRS->USER, CNS_DRIVINGCONE);
12 if (ptuser == NULL) return NULL;
13 if (ptuser->DATA == NULL) return NULL;
14 return (createAtom(((cone_list *)ptuser->DATA)->NAME));
15 }
16 else {
17 ptuser = getptype(ptlink->ULINK.LOTRS->USER, CNS_SWITCH);
18 if (ptuser == NULL) return NULL;
19 ptlotrs = (lotrs_list *)ptuser->DATA;
20 ptuser = getptype(ptlotrs->USER, CNS_DRIVINGCONE);
21 if (ptuser == NULL) return NULL;
22 if (ptuser->DATA == NULL) return NULL;
23 return (createAtom(((cone_list *)ptuser->DATA)->NAME));
24 }
25 }
26
27 static int isSwitchOn(link_list *ptlink)
28 {
29 ptype_list *ptuser;
30 lotrs_list *ptlotrs;
31 cone_list *ptcone;
32
33 ptlotrs = ptlink->ULINK.LOTRS;
34 ptuser = getptype(ptlotrs->USER, CNS_DRIVINGCONE);
35 if (ptuser != NULL && ptuser->DATA != NULL) {
36 ptcone = (cone_list *)ptuser->DATA;
37 if ((ptlotrs->TYPE & CNS_TN) == CNS_TN && (ptcone->TYPE & CNS_VDD) == CNS_VDD) {
38 return 1;
39 }
40 if ((ptlotrs->TYPE & CNS_TP) == CNS_TP && (ptcone->TYPE & CNS_VSS) == CNS_VSS) {
41 return 1;
42 }
43 }
44 ptuser = getptype(ptlink->ULINK.LOTRS->USER, CNS_SWITCH);
45 if (ptuser != NULL) {
46 ptlotrs = (lotrs_list *)ptuser->DATA;
47 ptuser = getptype(ptlotrs->USER, CNS_DRIVINGCONE);
48 if (ptuser != NULL && ptuser->DATA != NULL) {
49 ptcone = (cone_list *)ptuser->DATA;
50 if ((ptlotrs->TYPE & CNS_TN) == CNS_TN && (ptcone->TYPE & CNS_VDD) == CNS_VDD) {
51 return 1;
52 }
53 if ((ptlotrs->TYPE & CNS_TP) == CNS_TP && (ptcone->TYPE & CNS_VSS) == CNS_VSS) {
54 return 1;
55 }
56 }
57 }
58 return 0;
59 }
60
61 static int isTransOn(link_list *ptlink)
62 {
63 lotrs_list *ptlotrs;
64 cone_list *ptcone;
65 ptype_list *ptuser;
66
67 ptlotrs = ptlink->ULINK.LOTRS;
68 ptuser = getptype(ptlotrs->USER, CNS_DRIVINGCONE);
69 if (ptuser != NULL && ptuser->DATA != NULL) {
70 ptcone = (cone_list *)ptuser->DATA;
71 if ((ptlotrs->TYPE & CNS_TN) == CNS_TN && (ptcone->TYPE & CNS_VDD) == CNS_VDD) {
72 return 1;
73 }
74 if ((ptlotrs->TYPE & CNS_TP) == CNS_TP && (ptcone->TYPE & CNS_VSS) == CNS_VSS) {
75 return 1;
76 }
77 }
78 return 0;
79 }
80
81 static int isTransOff(link_list *ptlink)
82 {
83 lotrs_list *ptlotrs;
84 cone_list *ptcone;
85 ptype_list *ptuser;
86
87 ptlotrs = ptlink->ULINK.LOTRS;
88 ptuser = getptype(ptlotrs->USER, CNS_DRIVINGCONE);
89 if (ptuser != NULL && ptuser->DATA != NULL) {
90 ptcone = (cone_list *)ptuser->DATA;
91 if ((ptlotrs->TYPE & CNS_TN) == CNS_TN && (ptcone->TYPE & CNS_VSS) == CNS_VSS) {
92 return 1;
93 }
94 if ((ptlotrs->TYPE & CNS_TP) == CNS_TP && (ptcone->TYPE & CNS_VDD) == CNS_VDD) {
95 return 1;
96 }
97 }
98 return 0;
99 }
100
101 /****************************************************************************
102 * function cnsAddConeInversion(); *
103 ****************************************************************************/
104 /*----------------------------------------------------*
105 | Mechanism to substitute inversion function for a |
106 | cone (used for switches in YAGLE) |
107 *----------------------------------------------------*/
108
109 void cnsAddConeInversion(cone_list *ptexprcone, cone_list *ptcone)
110 {
111 ptype_list *ptuser;
112 chain_list *ptchain;
113
114 ptuser = getptype(ptexprcone->USER, CNS_INVCONE);
115 if (ptuser == NULL || ptuser->DATA != ptcone) {
116 if ((ptuser = getptype(ptcone->USER, CNS_INVCONE)) != NULL) {
117 ptchain = (chain_list *)ptuser->DATA;
118 if (getchain(ptchain, ptexprcone) == NULL) {
119 ptuser->DATA = addchain(ptchain, ptexprcone);
120 }
121 }
122 else ptcone->USER = addptype(ptcone->USER, CNS_INVCONE, addchain(NULL, ptexprcone));
123 }
124 }
125
126
127 /****************************************************************************
128 * function cnsMakeBranchExpr(); *
129 ****************************************************************************/
130 /*----------------------------------------------------*
131 | Returns the ABL of a branch |
132 | N.B. Does not verify the functionality |
133 *----------------------------------------------------*/
134
135 chain_list *cnsMakeBranchExpr(branch_list *ptbranch, long linkmask, int simplify)
136 {
137 chain_list *abl;
138 link_list *ptlink;
139 link_list *ptfirstlink;
140 chain_list *atom;
141 cone_list *ptcone;
142 short n_link = 0;
143 short n_resist = 0;
144 ptype_list *ptuser ;
145
146 abl = NULL;
147
148 ptfirstlink = ptbranch->LINK;
149 while (ptfirstlink && (ptfirstlink->TYPE & linkmask) != 0)
150 ptfirstlink = ptfirstlink->NEXT;
151
152 if (ptfirstlink == NULL) return NULL;
153
154 /*--------------------------------*
155 | Single link case |
156 *--------------------------------*/
157 if(ptfirstlink->NEXT == NULL ) {
158 /*-------------------*
159 | Resistance |
160 *-------------------*/
161
162 if ((ptfirstlink->TYPE & CNS_RESIST) == CNS_RESIST) {
163 ptbranch->TYPE |= CNS_RESBRANCH;
164 if (simplify && isTransOn(ptfirstlink)) {
165 abl = createAtom("'1'");
166 return(abl);
167 }
168 }
169
170 /*-------------------*
171 | Switch |
172 *-------------------*/
173
174 if (simplify && (ptfirstlink->TYPE & CNS_SWITCH) == CNS_SWITCH) {
175 if (isSwitchOn(ptfirstlink)) {
176 abl = createAtom("'1'");
177 return(abl);
178 }
179 else return getSwitchExpr(ptfirstlink);
180 }
181
182 /*-------------------*
183 | Diode |
184 *-------------------*/
185
186 if ((ptfirstlink->TYPE & CNS_DIODE_UP) == CNS_DIODE_UP
187 || (ptfirstlink->TYPE & CNS_DIODE_DOWN) == CNS_DIODE_DOWN) {
188 ptbranch->TYPE |= CNS_RESBRANCH;
189 abl = createAtom("'1'");
190 return(abl);
191 }
192
193 if ((ptfirstlink->TYPE & CNS_SHORT) == CNS_SHORT) {
194 if (simplify) {
195 abl = createAtom("'1'");
196 return(abl);
197 }
198 }
199
200 if (simplify) {
201 if (isTransOn(ptfirstlink)) {
202 abl = createAtom("'1'");
203 return(abl);
204 }
205 if (isTransOff(ptfirstlink)) {
206 abl = createAtom("'0'");
207 return(abl);
208 }
209 }
210 if ((ptfirstlink->TYPE & CNS_TNLINK) == CNS_TNLINK) {
211 ptuser = getptype(ptfirstlink->ULINK.LOTRS->USER, CNS_DRIVINGCONE);
212 if (ptuser == NULL || ptuser->DATA == NULL) {
213 freeExpr(abl);
214 return NULL;
215 }
216 else ptcone = (cone_list*)ptuser->DATA ;
217 abl = createAtom(ptcone->NAME);
218 return(abl);
219 }
220 else if ((ptfirstlink->TYPE & CNS_TPLINK) == CNS_TPLINK) {
221 ptuser = getptype(ptfirstlink->ULINK.LOTRS->USER, CNS_DRIVINGCONE);
222 if (ptuser == NULL || ptuser->DATA == NULL) {
223 freeExpr(abl);
224 return NULL;
225 }
226 else ptcone = (cone_list*)ptuser->DATA ;
227 abl = createAtom(ptcone->NAME);
228 return(notExpr(abl));
229 }
230 }
231
232 /*----------------------------*
233 | Multiple link branch |
234 *----------------------------*/
235 else {
236 abl = createExpr(AND);
237
238 for (ptlink = ptfirstlink; ptlink; ptlink = ptlink->NEXT) {
239 n_link++;
240 if ((ptlink->TYPE & CNS_RESIST) == CNS_RESIST) {
241 n_resist++;
242 if (!simplify) {
243 atom = createAtom("'1'");
244 addQExpr(abl,atom);
245 continue;
246 }
247 }
248 if (simplify && (ptlink->TYPE & CNS_SWITCH) == CNS_SWITCH) {
249 if (isSwitchOn(ptlink)) {
250 atom = createAtom("'1'");
251 addQExpr(abl,atom);
252 }
253 else {
254 atom = getSwitchExpr(ptlink);
255 if (atom == NULL) {
256 freeExpr(abl);
257 return NULL;
258 }
259 addQExpr(abl, atom);
260 }
261 continue;
262 }
263
264 if ((ptlink->TYPE & CNS_SHORT) == CNS_SHORT) {
265 atom = createAtom("'1'");
266 addQExpr(abl,atom);
267 continue;
268 }
269
270 if ((ptlink->TYPE & CNS_DIODE_UP) == CNS_DIODE_UP
271 || (ptlink->TYPE & CNS_DIODE_DOWN) == CNS_DIODE_DOWN) {
272 n_resist++;
273 atom = createAtom("'1'");
274 addQExpr(abl,atom);
275 continue;
276 }
277
278 ptuser = getptype(ptlink->ULINK.LOTRS->USER, CNS_DRIVINGCONE);
279 if (ptuser == NULL || ptuser->DATA == NULL) {
280 freeExpr(abl);
281 return NULL;
282 }
283 else ptcone = (cone_list*)ptuser->DATA ;
284
285 if (simplify) {
286 if (isTransOn(ptlink)) {
287 atom = createAtom("'1'");
288 addQExpr(abl,atom);
289 continue;
290 }
291 if (isTransOff(ptlink)) {
292 atom = createAtom("'0'");
293 addQExpr(abl,atom);
294 continue;
295 }
296 }
297 if ((ptlink->TYPE & CNS_TNLINK) == CNS_TNLINK) {
298 atom = createAtom(ptcone->NAME);
299 addQExpr(abl,atom);
300 }
301 else if ((ptlink->TYPE & CNS_TPLINK) == CNS_TPLINK) {
302 atom = createAtom(ptcone->NAME);
303 addQExpr(abl,notExpr(atom));
304 }
305 }
306
307 if (n_resist == n_link) ptbranch->TYPE |= CNS_RESBRANCH;
308
309 return(abl);
310 }
311 return NULL;
312 }
313
314 /****************************************************************************
315 * function cnsMakeExtBranchExpr(); *
316 ****************************************************************************/
317 /*----------------------------------------------------*
318 | Returns the ABLs of an external branch |
319 | N.B. Does not verify the functionality |
320 | Two values given to an external connector |
321 *----------------------------------------------------*/
322
323 void cnsMakeExtBranchExpr(branch_list *ptbranch, abl_pair *branch_abl, long linkmask, int simplify)
324 {
325 link_list *ptfirstlink, *ptlink;
326 chain_list *atom;
327 cone_list *ptcone;
328 chain_list *ablUp;
329 chain_list *ablDn;
330 short n_link = 0;
331 short n_resist = 0;
332 ptype_list *ptuser;
333
334 branch_abl->UP = NULL;
335
336 ptlink = ptbranch->LINK;
337
338 ptfirstlink = ptbranch->LINK;
339 while ((ptfirstlink->TYPE & linkmask) != 0)
340 ptfirstlink = ptfirstlink->NEXT;
341
342 /*--------------------------------*
343 | Single link case |
344 *--------------------------------*/
345 if(ptfirstlink->NEXT == NULL ) {
346 branch_abl->UP = createAtom(ptfirstlink->ULINK.LOCON->NAME);
347 branch_abl->DN = notExpr(copyExpr(branch_abl->UP));
348 }
349
350 /*----------------------------------------*
351 | EXT branch with multiple links |
352 *----------------------------------------*/
353 else {
354
355 ablUp = createExpr(AND);
356
357 for (ptlink = ptfirstlink; ptlink->NEXT != NULL; ptlink = ptlink->NEXT) {
358 n_link++;
359 if ((ptlink->TYPE & CNS_RESIST) == CNS_RESIST) {
360 n_resist++;
361 if (!simplify) {
362 atom = createAtom("'1'");
363 addQExpr(ablUp,atom);
364 continue;
365 }
366 }
367 if (simplify && (ptlink->TYPE & CNS_SWITCH) == CNS_SWITCH) {
368 if (isSwitchOn(ptlink)) {
369 atom = createAtom("'1'");
370 addQExpr(ablUp,atom);
371 }
372 else {
373 atom = getSwitchExpr(ptlink);
374 if (atom == NULL) {
375 freeExpr(ablUp);
376 return;
377 }
378 addQExpr(ablUp, atom);
379 }
380 continue;
381 }
382
383 if ((ptlink->TYPE & CNS_SHORT) == CNS_SHORT) {
384 atom = createAtom("'1'");
385 addQExpr(ablUp,atom);
386 continue;
387 }
388
389 if ((ptlink->TYPE & CNS_DIODE_UP) == CNS_DIODE_UP
390 || (ptlink->TYPE & CNS_DIODE_DOWN) == CNS_DIODE_DOWN) {
391 n_resist++;
392 atom = createAtom("'1'");
393 addQExpr(ablUp,atom);
394 continue;
395 }
396
397 ptuser = getptype(ptlink->ULINK.LOTRS->USER, CNS_DRIVINGCONE);
398 if (ptuser == NULL || ptuser->DATA == NULL) {
399 freeExpr(ablUp);
400 return;
401 }
402 else ptcone = (cone_list*)ptuser->DATA ;
403
404 if (simplify) {
405 if (isTransOn(ptlink)) {
406 atom = createAtom("'1'");
407 addQExpr(ablUp,atom);
408 continue;
409 }
410 if (isTransOff(ptlink)) {
411 atom = createAtom("'0'");
412 addQExpr(ablUp,atom);
413 continue;
414 }
415 }
416 if ((ptlink->TYPE & CNS_TNLINK) == CNS_TNLINK) {
417 atom = createAtom(ptcone->NAME);
418 addQExpr(ablUp,atom);
419 }
420 else if ((ptlink->TYPE & CNS_TPLINK) == CNS_TPLINK) {
421 atom = createAtom(ptcone->NAME);
422 addQExpr(ablUp,notExpr(atom));
423 }
424 }
425
426 /* Treatment of connector link */
427 if (n_link == n_resist) {
428 freeExpr(ablUp);
429 branch_abl->UP = createAtom(ptlink->ULINK.LOCON->NAME);
430 branch_abl->DN = notExpr(createAtom(ptlink->ULINK.LOCON->NAME));
431 }
432 else {
433 ablDn = copyExpr(ablUp);
434 atom = createAtom(ptlink->ULINK.LOCON->NAME);
435 addQExpr(ablUp,atom);
436 atom = createAtom(ptlink->ULINK.LOCON->NAME);
437 addQExpr(ablDn,notExpr(atom));
438 branch_abl->UP = ablUp;
439 branch_abl->DN = ablDn;
440 }
441 }
442 }
443
444 /****************************************************************************
445 * function cnsMakeConeExpr(); *
446 ****************************************************************************/
447
448 void cnsMakeConeExpr(cone_list *ptcone, abl_pair *cone_abl, long branchmask, long linkmask, int simplify)
449 {
450 branch_list *ptbranch;
451 abl_pair ablXt;
452 int n_branch = 0;
453 int n_dn = 0;
454 int n_up = 0;
455
456 cone_abl->UP = NULL;
457 cone_abl->DN = NULL;
458
459 /*-------------------------*
460 | Count the branches |
461 *-------------------------*/
462 for (ptbranch = ptcone->BRVSS; ptbranch != NULL; ptbranch = ptbranch->NEXT) {
463 if ((ptbranch->TYPE & branchmask) == 0) n_dn++;
464 }
465 for (ptbranch = ptcone->BRVDD; ptbranch != NULL; ptbranch = ptbranch->NEXT) {
466 if ((ptbranch->TYPE & branchmask) == 0) n_up++;
467 }
468 for (ptbranch = ptcone->BREXT; ptbranch != NULL; ptbranch = ptbranch->NEXT) {
469 /* ignore external connector branch */
470 if (ptbranch->LINK->NEXT == NULL) continue;
471 if ((ptbranch->TYPE & branchmask) == 0) {
472 if ((ptbranch->TYPE & CNS_NOT_UP) == 0) n_up++;
473 if ((ptbranch->TYPE & CNS_NOT_DOWN) == 0)n_dn++;
474 }
475 }
476 n_branch = n_up + n_dn;
477
478 /* external input only cone */
479 if ((ptcone->TYPE & CNS_EXT) != 0 && n_branch == 0) return;
480
481 /*--------------------------*
482 | Single branch case |
483 *--------------------------*/
484 if (n_branch == 1) {
485 for (ptbranch = ptcone->BRVSS; ptbranch != NULL; ptbranch = ptbranch->NEXT) {
486 if ((ptbranch->TYPE & branchmask) == 0) {
487 cone_abl->DN = cnsMakeBranchExpr(ptbranch, linkmask, simplify);
488 return;
489 }
490 }
491 for (ptbranch = ptcone->BRVDD; ptbranch != NULL; ptbranch = ptbranch->NEXT) {
492 if ((ptbranch->TYPE & branchmask) == 0) {
493 cone_abl->UP = cnsMakeBranchExpr(ptbranch, linkmask, simplify);
494 return;
495 }
496 }
497 }
498
499 /*--------------------------*
500 | Multiple branches |
501 *--------------------------*/
502 else if (n_branch >=2) {
503
504 if (n_up >= 2) cone_abl->UP = createExpr(OR);
505 if (n_dn >= 2) cone_abl->DN = createExpr(OR);
506
507 /*-------------------------------------------*
508 | Create intermediary ABLs |
509 *-------------------------------------------*/
510 for (ptbranch = ptcone->BRVSS; ptbranch; ptbranch = ptbranch->NEXT) {
511 if((ptbranch->TYPE & branchmask) != 0) continue;
512 if (n_dn >= 2) addQExpr(cone_abl->DN, cnsMakeBranchExpr(ptbranch, linkmask, simplify));
513 else cone_abl->DN = cnsMakeBranchExpr(ptbranch, 0, simplify);
514 }
515
516 for (ptbranch = ptcone->BRVDD; ptbranch; ptbranch = ptbranch->NEXT) {
517 if((ptbranch->TYPE & branchmask) != 0) continue;
518 if (n_up >= 2) addQExpr(cone_abl->UP, cnsMakeBranchExpr(ptbranch, linkmask, simplify));
519 else cone_abl->UP = cnsMakeBranchExpr(ptbranch, linkmask, simplify);
520 }
521
522 for (ptbranch = ptcone->BREXT; ptbranch; ptbranch = ptbranch->NEXT) {
523 /* ignore external connector branch */
524 if (ptbranch->LINK->NEXT == NULL) continue;
525 if((ptbranch->TYPE & branchmask) != 0) continue;
526 cnsMakeExtBranchExpr(ptbranch, &ablXt, linkmask, simplify);
527 if ((ptbranch->TYPE & CNS_NOT_UP) == 0) {
528 if (n_up >= 2) addQExpr(cone_abl->UP, ablXt.UP);
529 else cone_abl->UP = ablXt.UP;
530 }
531 else freeExpr(ablXt.UP);
532 if ((ptbranch->TYPE & CNS_NOT_DOWN) == 0) {
533 if (n_dn >= 2) addQExpr(cone_abl->DN, ablXt.DN);
534 else cone_abl->DN = ablXt.DN;
535 }
536 else freeExpr(ablXt.DN);
537 }
538 }
539 }
540
541 /****************************************************************************
542 * function cnsConeFunction(); *
543 ****************************************************************************/
544 /*--------------------------------------------+
545 | Calculates the local cone function and puts |
546 | the required abl pointers in the USER field |
547 +--------------------------------------------*/
548
549 void cnsConeFunction(cone_list *ptcone, int simplify)
550 {
551 abl_pair cone_abl;
552 ptype_list *user;
553 chain_list *sw_chain, *pairlist;
554 chain_list *ptchain;
555 lotrs_list *ptlotrs1, *ptlotrs2;
556 cone_list *ptcone1, *ptcone2;
557 edge_list *ptinput;
558 ptype_list *ptuser;
559
560 ptcone->USER=testanddelptype(ptcone->USER, CNS_CONEFUNCTION_SIMPLIFIED);
561
562 user = getptype(ptcone->USER, CNS_UPEXPR);
563 if (user != NULL) {
564 freeExpr((chain_list *)user->DATA);
565 ptcone->USER = delptype(ptcone->USER, CNS_UPEXPR);
566 }
567 user = getptype(ptcone->USER, CNS_DNEXPR);
568 if (user != NULL) {
569 freeExpr((chain_list *)user->DATA);
570 ptcone->USER = delptype(ptcone->USER, CNS_DNEXPR);
571 }
572
573 cnsMakeConeExpr(ptcone, &cone_abl, CNS_NOT_FUNCTIONAL|CNS_MASK_PARA|CNS_IGNORE, 0, simplify);
574
575 ptcone->USER = addptype(ptcone->USER, CNS_UPEXPR, (void *)cone_abl.UP);
576 ptcone->USER = addptype(ptcone->USER, CNS_DNEXPR, (void *)cone_abl.DN);
577
578 if (simplify && (ptuser = getptype(ptcone->USER, CNS_SWITCH)) != NULL) {
579 sw_chain = (chain_list *)ptuser->DATA;
580 for (ptchain = sw_chain; ptchain; ptchain = ptchain->NEXT) {
581 pairlist = (chain_list *)ptchain->DATA;
582 ptlotrs1 = (lotrs_list *)pairlist->DATA;
583 ptcone1 = (cone_list *)getptype(ptlotrs1->USER, CNS_DRIVINGCONE)->DATA;
584 ptlotrs2 = (lotrs_list *)pairlist->NEXT->DATA;
585 ptcone2 = (cone_list *)getptype(ptlotrs2->USER, CNS_DRIVINGCONE)->DATA;
586 for (ptinput = ptcone->INCONE; ptinput; ptinput = ptinput->NEXT) {
587 if (ptinput->UEDGE.CONE == ptcone1 && getptype(ptinput->USER, CNS_SWITCHPAIR) == NULL) {
588 ptinput->USER = addptype(ptinput->USER, CNS_SWITCHPAIR, ptcone2);
589 }
590 else if (ptinput->UEDGE.CONE == ptcone2 && getptype(ptinput->USER, CNS_SWITCHPAIR) == NULL) {
591 ptinput->USER = addptype(ptinput->USER, CNS_SWITCHPAIR, ptcone1);
592 }
593 }
594 }
595 }
596 }
597
598 void cnsConeFunction_once(cone_list *ptcone, int simplify)
599 {
600 ptype_list *pt;
601 if ((pt=getptype(ptcone->USER, CNS_CONEFUNCTION_SIMPLIFIED))!=NULL && (int)(long)pt->DATA==simplify) return;
602 cnsConeFunction(ptcone, simplify);
603 ptcone->USER=addptype(ptcone->USER, CNS_CONEFUNCTION_SIMPLIFIED, (void *)(long)simplify);
604 }
605
606 /****************************************************************************
607 * function cnsCalcConeState(); *
608 ****************************************************************************/
609 /*----------------------------------------------+
610 | Calculates the local cone state as a function |
611 | of the input states |
612 +----------------------------------------------*/
613
614 static pCircuit cnsBuildDirectCct(cone_list *ptcone)
615 {
616 pCircuit circuit;
617 edge_list *ptedge;
618 char *name;
619 int numinputs;
620
621 numinputs = countchain((chain_list *)ptcone->INCONE);
622 circuit = initializeCct(ptcone->NAME, numinputs, 10);
623
624 for (ptedge = ptcone->INCONE; ptedge; ptedge = ptedge->NEXT) {
625 if ((ptedge->TYPE & CNS_IGNORE) != 0) continue;
626 if ((ptedge->TYPE & CNS_BLEEDER) != 0) continue;
627 if ((ptedge->TYPE & CNS_EXT) != CNS_EXT) {
628 name = ptedge->UEDGE.CONE->NAME;
629 }
630 else name = ptedge->UEDGE.LOCON->NAME;
631 addInputCct_no_NA(circuit, name);
632 }
633
634 return circuit;
635 }
636
637 int
638 cnsCalcConeState(cone_list *ptcone, long defaultstate)
639 {
640 edge_list *ptedge;
641 pCircuit circuit;
642 ptype_list *ptuser;
643 pNode upbdd, dnbdd, ptconstraintbdd;
644 cone_list *ptincone;
645 locon_list *ptinlocon;
646 chain_list *ptupexpr;
647 chain_list *ptdnexpr;
648 chain_list *ptconstraint;
649 long oldstate, newstate;
650 char freeup = FALSE, freedown = FALSE;
651
652 /* stuck cones have state set accordingly and register a change on first visit */
653 if ((ptcone->TECTYPE & CNS_ONE) == CNS_ONE) {
654 if ((ptcone->TECTYPE & CNS_STATE_ONE) != CNS_STATE_ONE) {
655 ptcone->TECTYPE |= CNS_STATE_ONE;
656 return 1;
657 }
658 else return 0;
659 }
660 if ((ptcone->TECTYPE & CNS_ZERO) == CNS_ZERO) {
661 if ((ptcone->TECTYPE & CNS_STATE_ZERO) != CNS_STATE_ZERO) {
662 ptcone->TECTYPE |= CNS_STATE_ZERO;
663 return 1;
664 }
665 else return 0;
666 }
667
668 oldstate = ptcone->TECTYPE & (CNS_STATE_ONE|CNS_STATE_ZERO);
669 ptcone->TECTYPE &= ~(CNS_STATE_UNKNOWN|CNS_STATE_ONE|CNS_STATE_ZERO);
670 if (defaultstate == CNS_STATE_UNKNOWN && oldstate != 0) defaultstate = oldstate;
671
672 cnsConeFunction_once(ptcone, 1);
673 if ((ptuser = getptype(ptcone->USER, CNS_UPEXPR)) != NULL) {
674 ptupexpr = (chain_list *)ptuser->DATA;
675 if (!ptupexpr) {
676 ptupexpr = createAtom("'0'");
677 freeup = TRUE;
678 }
679 }
680 else return 0;
681 if ((ptuser = getptype(ptcone->USER, CNS_DNEXPR)) != NULL) {
682 ptdnexpr = (chain_list *)ptuser->DATA;
683 if (!ptdnexpr) {
684 ptdnexpr = createAtom("'0'");
685 freedown=TRUE;
686 }
687 }
688 else return 0;
689
690 circuit = cnsBuildDirectCct(ptcone);
691 upbdd = ablToBddCct(circuit, ptupexpr);
692 dnbdd = ablToBddCct(circuit, ptdnexpr);
693
694 for (ptedge = ptcone->INCONE; ptedge; ptedge = ptedge->NEXT) {
695 ptconstraint = NULL;
696 if ((ptedge->TYPE & CNS_EXT) == CNS_EXT) {
697 ptinlocon = ptedge->UEDGE.LOCON;
698 ptuser = getptype(ptinlocon->USER, CNS_TYPELOCON);
699 if (ptuser == NULL) continue;
700 if (((long)ptuser->DATA & (CNS_ZERO|CNS_STATE_ZERO)) != 0) {
701 ptconstraint = createAtom(ptinlocon->NAME);
702 ptconstraintbdd = notBdd(ablToBddCct(circuit, ptconstraint));
703 }
704 else if (((long)ptuser->DATA & (CNS_ONE|CNS_STATE_ONE)) != 0) {
705 ptconstraint = createAtom(ptinlocon->NAME);
706 ptconstraintbdd = ablToBddCct(circuit, ptconstraint);
707 }
708 }
709 else {
710 ptincone = ptedge->UEDGE.CONE;
711 if ((ptincone->TECTYPE & (CNS_ZERO|CNS_STATE_ZERO)) != 0) {
712 ptconstraint = createAtom(ptincone->NAME);
713 ptconstraintbdd = notBdd(ablToBddCct(circuit, ptconstraint));
714 }
715 else if ((ptincone->TECTYPE & (CNS_ONE|CNS_STATE_ONE)) != 0) {
716 ptconstraint = createAtom(ptincone->NAME);
717 ptconstraintbdd = ablToBddCct(circuit, ptconstraint);
718 }
719 }
720 if (ptconstraint != NULL) {
721 upbdd = constraintBdd(upbdd, ptconstraintbdd);
722 if (ptdnexpr) dnbdd = constraintBdd(dnbdd, ptconstraintbdd);
723 freeExpr(ptconstraint);
724 }
725 }
726
727 if (upbdd == BDD_one && (dnbdd == BDD_zero || dnbdd == NULL)) {
728 ptcone->TECTYPE |= CNS_STATE_ONE;
729 }
730 else if (upbdd == BDD_zero && (dnbdd == BDD_one || dnbdd == NULL)) {
731 ptcone->TECTYPE |= CNS_STATE_ZERO;
732 }
733 else ptcone->TECTYPE |= defaultstate;
734
735 newstate = ptcone->TECTYPE & (CNS_STATE_ONE|CNS_STATE_ZERO);
736
737 destroyCct(circuit);
738 if (freeup) freeExpr(ptupexpr);
739 if (freedown) freeExpr(ptdnexpr);
740 if (newstate != oldstate) return 1;
741 return 0;
742 }
743
744 /****************************************************************************
745 * function cnsCalcFigState(); *
746 ****************************************************************************/
747 /*------------------------------------------------+
748 | Calculates the local cnsfig state as a function |
749 | of the input connector states |
750 +------------------------------------------------*/
751
752 static void
753 cnsFIFOPush(chain_list **ptpthead, void *ptdata)
754 {
755 chain_list *ptchain;
756
757 if (*ptpthead == NULL) {
758 *ptpthead = addchain(NULL, ptdata);
759 return;
760 }
761 for (ptchain = *ptpthead; ptchain->NEXT; ptchain = ptchain->NEXT) {
762 if (ptchain->DATA == ptdata) return;
763 }
764 ptchain->NEXT = addchain(NULL, ptdata);
765 }
766
767 static void *
768 cnsFIFOPop(chain_list **ptpthead)
769 {
770 void *ptdata;
771
772 ptdata = (*ptpthead)->DATA;
773 *ptpthead = delchain(*ptpthead, *ptpthead);
774 return ptdata;
775 }
776
777 static long
778 cnsCalcLatchCbhState(cone_list *ptcone, cbhseq *ptcbhseq, long cbhseq_state)
779 {
780 int invert;
781
782 if (ptcone->NAME != ptcbhseq->LATCHNAME && ptcone->NAME != ptcbhseq->SLAVENAME) {
783 return CNS_STATE_UNKNOWN;
784 }
785 if (ptcbhseq->POLARITY != CBH_INVERT && ptcbhseq->POLARITY != CBH_NONINVERT) {
786 return CNS_STATE_UNKNOWN;
787 }
788 if (ptcbhseq->POLARITY != CBH_INVERT && ptcbhseq->POLARITY != CBH_NONINVERT) {
789 return CNS_STATE_UNKNOWN;
790 }
791
792 if (ptcbhseq->STATEPIN == ptcbhseq->NEGPIN || ptcbhseq->STATEPIN == ptcbhseq->HZNEGPIN) {
793 invert = TRUE;
794 }
795 else invert = FALSE;
796 if (invert && ptcbhseq->POLARITY == CBH_INVERT) invert = FALSE;
797 else if (!invert && ptcbhseq->POLARITY == CBH_INVERT) invert = TRUE;
798
799 if (ptcone->NAME == ptcbhseq->SLAVENAME) {
800 if (invert && ptcbhseq->MSPOLARITY == CBH_INVERT) invert = FALSE;
801 else if (!invert && ptcbhseq->MSPOLARITY == CBH_INVERT) invert = TRUE;
802 }
803
804 if ((cbhseq_state & (CNS_ZERO|CNS_STATE_ZERO)) != 0) {
805 if (invert) return CNS_STATE_ONE;
806 else return CNS_STATE_ZERO;
807 }
808 if ((cbhseq_state & (CNS_ONE|CNS_STATE_ONE)) != 0) {
809 if (invert) return CNS_STATE_ZERO;
810 else return CNS_STATE_ONE;
811 }
812 return CNS_STATE_UNKNOWN;
813 }
814
815 void
816 cnsCalcFigState(cnsfig_list *ptcnsfig, cbhseq *ptcbhseq)
817 {
818 locon_list *ptlocon;
819 cone_list *ptloconcone, *ptcone, *ptoutcone;
820 edge_list *ptedge;
821 ptype_list *ptuser;
822 chain_list *ptFIFO = NULL;
823 chain_list *ptchain;
824 long state_type;
825 long cbhseq_state = 0;
826 long default_state;
827 int changed;
828
829
830 /* Initialize cones to unknown until we can say otherwise */
831 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
832 ptcone->TECTYPE |= CNS_STATE_UNKNOWN;
833 }
834
835 /* Initialize FIFO with cone driven by input connectors */
836 for (ptlocon = ptcnsfig->LOCON; ptlocon; ptlocon = ptlocon->NEXT) {
837 ptuser = getptype(ptlocon->USER, CNS_TYPELOCON);
838 if (ptuser == NULL) continue;
839 state_type = ((long)ptuser->DATA) & (CNS_ZERO|CNS_INIT_ZERO|CNS_ONE|CNS_INIT_ONE);
840 if (state_type != 0) {
841 if ((state_type & CNS_INIT_ONE) != 0) state_type |= CNS_STATE_ONE;
842 if ((state_type & CNS_INIT_ZERO) != 0) state_type |= CNS_STATE_ZERO;
843 state_type &= (CNS_ZERO|CNS_STATE_ZERO|CNS_ONE|CNS_STATE_ONE);
844 ptuser->DATA = (void *)((long)ptuser->DATA | state_type);
845 ptloconcone = NULL;
846 if ((ptuser = getptype(ptlocon->USER, CNS_EXT)) != NULL) {
847 ptloconcone = (cone_list *)ptuser->DATA;
848 ptloconcone->TECTYPE &= ~CNS_STATE_UNKNOWN;
849 ptloconcone->TECTYPE |= state_type;
850 for (ptedge = ptloconcone->OUTCONE; ptedge; ptedge = ptedge->NEXT) {
851 if ((ptedge->TYPE & CNS_EXT) == 0) {
852 cnsFIFOPush(&ptFIFO, ptedge->UEDGE.CONE);
853 }
854 }
855 }
856 if ((ptuser = getptype(ptlocon->USER, CNS_CONE)) != NULL) {
857 for (ptchain = (chain_list *)ptuser->DATA; ptchain; ptchain = ptchain->NEXT) {
858 ptcone = (cone_list *)ptchain->DATA;
859 if (ptcone != ptloconcone) cnsFIFOPush(&ptFIFO, ptcone);
860 }
861 }
862 if (ptcbhseq && ptlocon->NAME == ptcbhseq->STATEPIN) cbhseq_state = state_type;
863 }
864 }
865
866 /* run until the FIFO is empty */
867 while (ptFIFO != NULL) {
868 ptcone = (cone_list *)cnsFIFOPop(&ptFIFO);
869 if (ptcbhseq && (ptcone->NAME == ptcbhseq->LATCHNAME || ptcone->NAME == ptcbhseq->SLAVENAME)) {
870 default_state = cnsCalcLatchCbhState(ptcone, ptcbhseq, cbhseq_state);
871 }
872 else default_state = CNS_STATE_UNKNOWN;
873 changed = cnsCalcConeState(ptcone, default_state);
874 state_type = ptcone->TECTYPE & (CNS_ZERO|CNS_STATE_ZERO|CNS_ONE|CNS_STATE_ONE);
875 if (changed && state_type != 0) {
876 for (ptedge = ptcone->OUTCONE; ptedge; ptedge = ptedge->NEXT) {
877 if ((ptedge->TYPE & CNS_EXT) == 0) {
878 ptoutcone = ptedge->UEDGE.CONE;
879 cnsFIFOPush(&ptFIFO, ptedge->UEDGE.CONE);
880 }
881 else {
882 ptlocon = ptedge->UEDGE.LOCON;
883 if ((ptuser = getptype(ptlocon->USER, CNS_TYPELOCON)) != NULL) {
884 ptuser->DATA = (void *)((long)ptuser->DATA | state_type);
885 }
886 else ptlocon->USER = addptype(ptlocon->USER, CNS_TYPELOCON, (void *)state_type);
887 }
888 }
889 }
890 }
891 }
892
893 /****************************************************************************
894 * function cnsCleanFigState(); *
895 ****************************************************************************/
896 /*------------------------------------------------+
897 | Removes thee calculated state markings leaving |
898 | just those of the input connectors |
899 +------------------------------------------------*/
900
901 void
902 cnsCleanFigState(cnsfig_list *ptcnsfig, cbhseq *ptcbhseq)
903 {
904 locon_list *ptlocon;
905 cone_list *ptcone;
906 ptype_list *ptuser;
907
908 for (ptlocon = ptcnsfig->LOCON; ptlocon; ptlocon = ptlocon->NEXT) {
909 if (ptlocon->DIRECTION == CNS_I || ptlocon->DIRECTION == CNS_T) continue;
910 if (ptcbhseq && ptlocon->NAME == ptcbhseq->STATEPIN) continue;
911 if ((ptuser = getptype(ptlocon->USER, CNS_TYPELOCON)) != NULL) {
912 ptuser->DATA = (void *)((long)ptuser->DATA & ~(CNS_STATE_ZERO|CNS_STATE_ONE));
913 if (ptuser->DATA == NULL) {
914 ptlocon->USER = delptype(ptlocon->USER, CNS_TYPELOCON);
915 }
916 }
917 }
918 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
919 ptcone->TECTYPE &= ~(CNS_STATE_ZERO|CNS_STATE_ONE|CNS_STATE_UNKNOWN);
920 }
921 }