Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / yagle / yagle / yag_timing.c
1 /****************************************************************************/
2 /* */
3 /* Chaine de CAO & VLSI Alliance */
4 /* */
5 /* Produit : YAGLE v3.50 */
6 /* Fichier : yag_timing.c */
7 /* */
8 /* (c) copyright 1991 Laboratoire MASI equipe CAO & VLSI */
9 /* Tous droits reserves */
10 /* Support : e-mail alliance-support@asim.lip6.fr */
11 /* */
12 /* Auteur(s) : Anthony LESTER le : ../../.... */
13 /* */
14 /* Modifie par : le : ../../.... */
15 /* Modifie par : le : ../../.... */
16 /* Modifie par : le : ../../.... */
17 /* */
18 /****************************************************************************/
19
20 #ifndef WITHOUT_TAS
21 #include "yag_headers.h"
22
23 static void yagTimeBefig(befig_list *ptbefig);
24 static void yagDetectSensitive(cnsfig_list *ptcnsfig);
25 static unsigned int yagGetTotalDelay(chain_list *ptconelist);
26 static unsigned int yagGetDelay(cone_list *ptcone, chain_list *cndexpr, chain_list *valexpr);
27 static int yagConstantAbl(chain_list *ptexpr);
28 static int yagTimeSensitiveBebux(bebux_list *ptbebux, cone_list *ptcone);
29 static int yagTimeSensitiveBereg(bereg_list *ptbereg, cone_list *ptcone);
30 static int yagTimeSensitiveBebus(bebus_list *ptbebus, cone_list *ptcone);
31
32 /****************************************************************************
33 * function yagPrepTiming(); *
34 ****************************************************************************/
35 void
36 yagPrepTiming(lofig_list *ptlofig)
37 {
38 inffig_list *ifl;
39
40 tas_setenv();
41 TAS_CONTEXT->TAS_CALCRCX = 'Y';
42 // TAS_CONTEXT->TAS_MERGERCN = 'Y';
43 TAS_CONTEXT->FRONT_CON = TAS_NOFRONT;
44 if (YAG_CONTEXT->YAG_TAS_TIMING == YAG_MIN_TIMING) {
45 TAS_CONTEXT->TAS_FIND_MIN = 'Y';
46 }
47 TAS_CONTEXT->TAS_SILENTMODE = 'Y';
48 if ((ifl=getloadedinffig(ptlofig->NAME))!=NULL)
49 tas_update_mcctemp (ifl);
50 tas_TechnoParameters();
51 }
52
53 static chain_list *yag_buildminterms(cone_list *ptcone, chain_list *cndabl, chain_list *valabl)
54 {
55 chain_list *support, *list=NULL, *tmpexpr, *samedelay, *expr, *cl, *ch;
56 pCircuit cct;
57 pNode exprbdd;
58 int nb, count;
59 long timing, l;
60 ht *ht;
61
62 support=supportChain_listExpr(cndabl);
63 nb=countchain(support);
64 freechain(support);
65 if (nb>1)
66 {
67 list=ablCreateMintermList(cndabl);
68 /* exprbdd=ablToBddCct(cct, cndabl);
69 displayExpr(bddToAblCct(cct, exprbdd));*/
70 ht=addht(20);
71 while (list!=NULL)
72 {
73 expr=(chain_list *)list->DATA;
74 timing=yagGetDelay(ptcone, expr, valabl);
75 if ((l=gethtitem(ht, (void *)timing))==EMPTYHT) support=NULL;
76 else support=(chain_list *)l;
77 support=addchain(support, expr);
78 addhtitem(ht, (void *)timing, (long)support);
79 list=delchain(list, list);
80 }
81 samedelay=GetAllHTElems(ht);
82 delht(ht);
83
84 if (countchain(samedelay)<=1)
85 {
86 while (samedelay)
87 {
88 for (list=(chain_list *)samedelay->DATA; list!=NULL; list=list->NEXT)
89 freeExpr((chain_list *)list->DATA);
90 freechain((chain_list *)samedelay->DATA);
91 samedelay=delchain(samedelay, samedelay);
92 }
93 return NULL;
94 }
95
96 support=NULL;
97 while (samedelay)
98 {
99 list=(chain_list *)samedelay->DATA;
100 if (list->NEXT==NULL)
101 support=addchain(support, list->DATA);
102 else
103 {
104 chain_list *sublist=NULL;
105 int cnt=countchain(list);
106 if (cnt<=8) {cnt=100;}
107 else cnt=1;
108 cl=list;
109 while (cl!=NULL)
110 {
111 count =0;
112 ch=NULL;
113 cct=initializeCct("temp",nb, 10);
114 while (cl!=NULL)
115 {
116 if (count>=cnt && cl->NEXT!=NULL) break;
117 tmpexpr=(chain_list *)cl->DATA;
118 ch=addchain(ch, ablToBddCct(cct, tmpexpr));
119 freeExpr(tmpexpr);
120 count++;
121 cl=cl->NEXT;
122 }
123 if (countchain(ch)>1)
124 exprbdd=applyBdd (OR, ch);
125 else
126 exprbdd=(pNode)ch->DATA;
127 sublist=addchain(sublist, bddToAblCct(cct, exprbdd));
128 freechain(ch);
129 // support=addchain(support, bddToAblCct(cct, exprbdd));
130 destroyCct(cct);
131 }
132 if (sublist!=NULL && sublist->NEXT!=NULL)
133 {
134 tmpexpr=createExpr (OR);
135 while (sublist!=NULL)
136 {
137 addQExpr(tmpexpr, (chain_list *)sublist->DATA);
138 sublist=delchain(sublist, sublist);
139 }
140 support=addchain(support, tmpexpr);
141 }
142 else
143 {
144 support=addchain(support, sublist->DATA);
145 freechain(sublist);
146 }
147 }
148 freechain(list);
149 samedelay=delchain(samedelay, samedelay);
150 }
151 // destroyCct(cct);
152 list=support;
153 }
154 return list;
155 }
156
157 static int
158 yagSplitIntoMinterms(biabl_list **biabl, cone_list *ptcone)
159 {
160 biabl_list *ptbiabl;
161 biabl_list *ptnewbiabl = NULL, *tmpb, *knext;
162 chain_list *ptchain;
163
164 if (!ptcone) return FALSE;
165
166 for (ptbiabl = *biabl; ptbiabl; ptbiabl = ptbiabl->NEXT)
167 {
168 ptchain=yag_buildminterms(ptcone, ptbiabl->CNDABL, ptbiabl->VALABL);
169 if (ptchain==NULL || countchain(ptchain)>V_INT_TAB[__YAG_MAX_SPLIT_CMD_TIMING].VALUE)
170 {
171 knext=ptbiabl->NEXT; ptbiabl->NEXT=NULL;
172 tmpb=beh_dupbiabl(ptbiabl);
173 ptbiabl->NEXT=knext;
174 tmpb->NEXT=ptnewbiabl;
175 ptnewbiabl = tmpb;
176 while (ptchain!=NULL)
177 {
178 freeExpr((chain_list *)ptchain->DATA);
179 ptchain=delchain(ptchain, ptchain);
180 }
181 }
182 else
183 {
184 /* if (ptchain!=NULL && ptchain->NEXT!=NULL)
185 printf("split %s\n",ptcone->NAME);*/
186 while (ptchain!=NULL)
187 {
188 knext=ptbiabl->NEXT; ptbiabl->NEXT=NULL;
189 tmpb=beh_dupbiabl(ptbiabl);
190 ptbiabl->NEXT=knext;
191 tmpb->NEXT=ptnewbiabl;
192 ptnewbiabl = tmpb;
193 freeExpr(tmpb->CNDABL);
194 tmpb->CNDABL=(chain_list *)ptchain->DATA;
195 ptchain=delchain(ptchain, ptchain);
196 }
197 }
198 }
199 ptnewbiabl = (biabl_list *)reverse((chain_list *)ptnewbiabl);
200 beh_frebiabl(*biabl);
201 *biabl = ptnewbiabl;
202 return TRUE;
203 }
204
205
206 static void
207 yagDetectSensitive(cnsfig_list *ptcnsfig)
208 {
209 cone_list *ptcone;
210 edge_list *ptinput;
211 unsigned int upmax, upmin;
212 unsigned int dnmax, dnmin;
213 unsigned int delay;
214 chain_list *name_expr;
215 chain_list *one_expr, *zero_expr;
216 char *name;
217
218 if (YAG_CONTEXT->YAG_SENSITIVE_RATIO < 1) return;
219 one_expr = createAtom("'1'");
220 zero_expr = createAtom("'0'");
221
222 for (ptcone = ptcnsfig->CONE; ptcone; ptcone = ptcone->NEXT) {
223 if (YAG_CONTEXT->YAG_SENSITIVE_MAX > 0 && yagCountEdges(ptcone->INCONE) > YAG_CONTEXT->YAG_SENSITIVE_MAX) continue;
224 upmax = 0;
225 upmin = 0;
226 dnmax = 0;
227 dnmin = 0;
228 for (ptinput = ptcone->INCONE; ptinput; ptinput = ptinput->NEXT) {
229 if ((ptinput->TYPE & CNS_EXT) != 0) {
230 name = ptinput->UEDGE.LOCON->NAME;
231 }
232 else name = ptinput->UEDGE.CONE->NAME;
233 name_expr = createAtom(mbk_devect(name, "[", "]"));
234 delay = yagGetDelay(ptcone, name_expr, createAtom("'1'"));
235 if (delay != 0) {
236 if (upmax == 0 || delay > upmax) upmax = delay;
237 if (upmin == 0 || delay < upmin) upmin = delay;
238 }
239 delay = yagGetDelay(ptcone, name_expr, createAtom("'0'"));
240 if (delay != 0) {
241 if (dnmax == 0 || delay > dnmax) dnmax = delay;
242 if (dnmin == 0 || delay < dnmin) dnmin = delay;
243 }
244 freeExpr(name_expr);
245 }
246 if (upmax > upmin * YAG_CONTEXT->YAG_SENSITIVE_RATIO
247 || dnmax > dnmin * YAG_CONTEXT->YAG_SENSITIVE_RATIO) {
248 ptcone->TECTYPE |= YAG_SENSITIVE;
249 }
250 }
251 freeExpr(one_expr);
252 freeExpr(zero_expr);
253 }
254
255 static unsigned int
256 yagGetRCDelay(cone_list *ptcone, char *input, int dir)
257 {
258 edge_list *ptincone;
259 ptype_list *ptuser;
260 delay_list *delay;
261 char *inputname;
262 long delaymax = 0;
263 int useRising = TRUE;
264 int useFalling = TRUE;
265 int n = 0;
266
267 if (ptcone == NULL) return 0;
268
269 if (dir==1) useFalling = FALSE;
270 else if (dir==0) useRising = FALSE;
271
272 for (ptincone = ptcone->INCONE; ptincone; ptincone = ptincone->NEXT) {
273 if ((ptincone->TYPE & CNS_EXT) == 0) inputname = ptincone->UEDGE.CONE->NAME;
274 else inputname = ptincone->UEDGE.LOCON->NAME;
275 if (input!=mbk_devect(inputname, "[", "]")) continue;
276 ptuser = getptype(ptincone->USER, TAS_DELAY_MAX);
277 if (ptuser != NULL) {
278 delay = (delay_list *)ptuser->DATA;
279 if (useRising && delay->RCHH != TAS_NOTIME) {
280 delaymax += delay->RCHH;
281 n++;
282 }
283 if (useFalling && delay->RCLL != TAS_NOTIME) {
284 delaymax += delay->RCLL;
285 n++;
286 }
287 }
288 if (n!=0) delaymax/=n;
289 delaymax=mbk_long_round(delaymax/TTV_UNIT);
290 if (delaymax > 0) return ((unsigned int)delaymax);
291 else return 0;
292 }
293 return 0;
294 }
295
296 static ht *RC_WRAP_HT;
297 static cone_list *RC_WRAP_CONE;
298
299 static char *rc_wrap_func(char *input)
300 {
301 char buf[2048];
302 int rcvalup, rcvaldown;
303 char *inputrc, *c;
304 int minrc, rcstep;
305
306 minrc=mbk_long_round(V_FLOAT_TAB[__YAG_MIN_RC].VALUE*1e12);
307 if (minrc<=0) minrc=1;
308 rcstep=mbk_long_round(V_FLOAT_TAB[__YAG_RC_STEP].VALUE*1e12);
309 if (rcstep<1) rcstep=1;
310
311 rcvaldown=yagGetRCDelay(RC_WRAP_CONE, input, 0);
312 rcvalup=yagGetRCDelay(RC_WRAP_CONE, input, 1);
313 if (rcvalup>minrc || rcvaldown>minrc)
314 {
315 rcvalup=mbk_long_round((float)rcvalup/rcstep)*rcstep;
316 rcvaldown=mbk_long_round((float)rcvaldown/rcstep)*rcstep;
317 if (rcvalup==0) rcvalup=minrc;
318 if (rcvaldown==0) rcvaldown=minrc;
319 if (rcvalup==rcvaldown)
320 sprintf(buf, "%s|%dps", input, rcvalup);
321 else
322 sprintf(buf, "%s|%dps|%dps", input, rcvalup,rcvaldown);
323 if ((c=strchr(buf, ' '))!=NULL) *c='|';
324 inputrc=namealloc(buf);
325 if (gethtitem(RC_WRAP_HT, inputrc)==EMPTYHT)
326 addhtitem(RC_WRAP_HT, inputrc, (long)addptype(addptype(NULL, rcvaldown, input), rcvalup, input));
327 return inputrc;
328 }
329 return input;
330 }
331
332 static void yagCheckRCandUpdateNames(cone_list *cn, ht *rcht, chain_list *cndexpr, chain_list *valexpr)
333 {
334 RC_WRAP_HT=rcht;
335 RC_WRAP_CONE=cn;
336
337 if (cndexpr!=NULL) beh_wrapAtomExpr(cndexpr, rc_wrap_func);
338 if (valexpr!=NULL) beh_wrapAtomExpr(valexpr, rc_wrap_func);
339 }
340
341 static void yadAddRC(ht *rcht, befig_list *ptbefig)
342 {
343 chain_list *allrc;
344 ptype_list *pt;
345 char *inputrc;
346
347 allrc=GetAllHTKeys(rcht);
348 while (allrc!=NULL)
349 {
350 inputrc=(char *)allrc->DATA;
351 pt=(ptype_list *)gethtitem(rcht, inputrc);
352 ptbefig->BEAUX = beh_addbeaux (ptbefig->BEAUX, inputrc, createAtom((char *)pt->DATA), NULL, 0);
353 ptbefig->BEAUX->TIMER=pt->TYPE;
354 ptbefig->BEAUX->TIMEF=pt->NEXT->TYPE;
355 freeptype(pt);
356 allrc=delchain(allrc, allrc);
357 }
358 }
359
360 /****************************************************************************
361 * function yagAddTiming(); *
362 ****************************************************************************/
363 void
364 yagAddTiming(cnsfig_list *ptcnsfig, lofig_list *ptlofig)
365 {
366 time_t start = 0;
367 time_t end = 0;
368 struct rusage END;
369 struct rusage START;
370 locon_list *ptlocon;
371 inffig_list *ifl;
372
373 ifl = getloadedinffig(YAG_CONTEXT->YAG_FIGNAME);
374
375 cns_addmultivoltage(ifl, ptcnsfig);
376
377 yagChrono(&START,&start);
378 if (!YAG_CONTEXT->YAG_SILENT_MODE) yagMessage(MES_TAS_TECHNO, NULL);
379 if (MCC_HEADTECHNO == NULL && ELP_MODEL_LIST == NULL) {
380 if (!YAG_CONTEXT->YAG_SILENT_MODE) {
381 yagChrono(&END,&end);
382 if (!YAG_CONTEXT->YAG_SILENT_MODE) yagPrintTime(&START,&END,start,end);
383 yagMessage(MES_NO_TECHNO_FILE, NULL);
384 }
385 YAG_CONTEXT->YAG_TAS_TIMING = YAG_NO_TIMING;
386 }
387 else {
388 elpLofigAddCapas (ptlofig,( (mcc_use_multicorner() == 0 ) ? elpTYPICAL : elpWORST ));
389 yagChrono(&END,&end);
390 if (!YAG_CONTEXT->YAG_SILENT_MODE) yagPrintTime(&START,&END,start,end);
391 }
392
393 if (YAG_CONTEXT->YAG_TAS_TIMING != YAG_NO_TIMING) {
394 yagChrono(&START,&start);
395 yagMessage(MES_TAS_TIMING, NULL);
396 tas_detectinout(ptcnsfig);
397 tas_initcnsfigalloc(ptcnsfig);
398 TAS_CONTEXT->TAS_LOFIG = ptlofig;
399
400 tas_loconorient(ptlofig, NULL);
401 tas_timing(ptcnsfig, ptlofig, NULL);
402 for (ptlocon = ptlofig->LOCON; ptlocon; ptlocon = ptlocon->NEXT) {
403 ptlocon->NAME = mbk_devect(ptlocon->NAME, "[", "]");
404 }
405 trcflushdelaycache();
406
407 yagDetectSensitive(ptcnsfig);
408 if (ptcnsfig->BEFIG != NULL) yagTimeBefig(ptcnsfig->BEFIG);
409 tas_freecnsfigalloc(ptcnsfig);
410 yagChrono(&END,&end);
411 yagPrintTime(&START,&END,start,end);
412 }
413 }
414
415 static int
416 already_timed(biabl_list *ptbiabl)
417 {
418 for (;ptbiabl; ptbiabl = ptbiabl->NEXT) {
419 if (ptbiabl->TIME != 0) return TRUE;
420 }
421 return FALSE;
422 }
423
424 static void yag_check_single_delay(biabl_list *BIABL)
425 {
426 unsigned int uptime, downtime;
427 biabl_list *ptbiabl;
428
429 if (V_FLOAT_TAB[__YAG_SINGLE_DELAY_RATIO].VALUE>1.0)
430 {
431 uptime = 0;
432 downtime = INT_MAX;
433 for (ptbiabl = BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
434 if (downtime>ptbiabl->TIME) downtime=ptbiabl->TIME;
435 if (uptime<ptbiabl->TIME) uptime=ptbiabl->TIME;
436 }
437 if (downtime>0 && (float)(uptime-downtime)/(float)downtime<V_FLOAT_TAB[__YAG_SINGLE_DELAY_RATIO].VALUE) {
438 for (ptbiabl = BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
439 ptbiabl->TIME=(int)(0.5+(uptime+downtime)/2.0);
440 }
441 }
442 }
443 }
444
445 /****************************************************************************
446 * function yagTimeBefig(); *
447 ****************************************************************************/
448 static void
449 yagTimeBefig(befig_list *ptbefig)
450 {
451 beaux_list *ptbeaux;
452 beaux_list *ptprevbeaux = NULL;
453 beaux_list *ptnextbeaux = NULL;
454 beout_list *ptbeout;
455 beout_list *ptprevbeout = NULL;
456 beout_list *ptnextbeout = NULL;
457 bebux_list *ptbebux;
458 bebux_list *ptprevbebux = NULL;
459 bebux_list *ptnextbebux = NULL;
460 bebus_list *ptbebus;
461 bebus_list *ptprevbebus = NULL;
462 bebus_list *ptnextbebus = NULL;
463 bereg_list *ptbereg;
464 bequad_list *ptquad;
465 biabl_list *ptbiabl;
466 cone_list *ptcone;
467 ptype_list *ptuser;
468 unsigned int conedelay;
469 unsigned int uptime, downtime;
470 int processed, sensitive, split;
471 chain_list *oneexpr, *zeroexpr;
472 ht *rcht;
473
474 oneexpr = createAtom("'1'");
475 zeroexpr = createAtom("'0'");
476
477 initializeBdd(0);
478 rcht=addht(10000);
479
480 for (ptbebux = ptbefig->BEBUX; ptbebux; ptbebux = ptbebux->NEXT) {
481 if (already_timed(ptbebux->BIABL)) continue;
482 conedelay = 0;
483 processed = FALSE;
484 if (ptbebux->BINODE != NULL) ptquad = (bequad_list *)ptbebux->BINODE->VALNODE;
485 else ptquad = NULL;
486 if (ptquad != NULL) {
487 ptuser = getptype(ptquad->USER, YAG_CONE_PTYPE);
488 if (ptuser != NULL) {
489 ptcone = (cone_list *)ptuser->DATA;
490 if (ptcone != NULL) {
491 if ((ptcone->TECTYPE & YAG_SENSITIVE) == YAG_SENSITIVE && strchr(ptbebux->NAME, ' ') == NULL) {
492 processed = yagTimeSensitiveBebux(ptbebux, ptcone);
493 if (processed) {
494 ptbefig->BEREG = beh_addbereg(ptbefig->BEREG, ptbebux->NAME, ptbebux->BIABL, NULL,0);
495 ptbebux->BIABL = NULL;
496 ptbebux->NAME = NULL;
497 }
498 }
499 else if (V_INT_TAB[__YAG_MAX_SPLIT_CMD_TIMING].VALUE>0)
500 yagSplitIntoMinterms(&ptbebux->BIABL, ptcone);
501 }
502 if (!processed) {
503 for (ptbiabl = ptbebux->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
504 ptbiabl->TIME = yagGetDelay(ptcone, ptbiabl->CNDABL, ptbiabl->VALABL);
505 }
506 }
507 for (ptbiabl = ptbebux->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT)
508 yagCheckRCandUpdateNames(ptcone, rcht, ptbiabl->CNDABL, ptbiabl->VALABL);
509 }
510 else {
511 ptuser = getptype(ptquad->USER, YAG_CONELIST_PTYPE);
512 if (ptuser != NULL) {
513 conedelay = yagGetTotalDelay((chain_list *)ptuser->DATA);
514 }
515 if (conedelay != 0) {
516 for (ptbiabl = ptbebux->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
517 if (ptbiabl->TIME != 0) continue;
518 ptbiabl->TIME = conedelay;
519 }
520 }
521 }
522 if (!processed) yag_check_single_delay(ptbebux->BIABL);
523 }
524 }
525 for (ptbebus = ptbefig->BEBUS; ptbebus; ptbebus = ptbebus->NEXT) {
526 if (already_timed(ptbebus->BIABL)) continue;
527 processed = FALSE;
528 if (ptbebus->BINODE != NULL) ptquad = (bequad_list *)ptbebus->BINODE->VALNODE;
529 else ptquad = NULL;
530 if (ptquad != NULL) {
531 ptuser = getptype(ptquad->USER, YAG_CONE_PTYPE);
532 if (ptuser != NULL) {
533 ptcone = (cone_list *)ptuser->DATA;
534 if (ptcone != NULL) {
535 if ((ptcone->TECTYPE & YAG_SENSITIVE) == YAG_SENSITIVE && strchr(ptbebus->NAME, ' ') == NULL) {
536 processed = yagTimeSensitiveBebus(ptbebus, ptcone);
537 if (processed) {
538 ptbefig->BEREG = beh_addbereg(ptbefig->BEREG, ptbebus->NAME, ptbebus->BIABL, NULL,0);
539 ptbebus->BIABL = NULL;
540 ptbebus->NAME = NULL;
541 }
542 }
543 else if (V_INT_TAB[__YAG_MAX_SPLIT_CMD_TIMING].VALUE>0)
544 yagSplitIntoMinterms(&ptbebus->BIABL, ptcone);
545 }
546 if (!processed) {
547 for (ptbiabl = ptbebus->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
548 ptbiabl->TIME = yagGetDelay(ptcone, ptbiabl->CNDABL, ptbiabl->VALABL);
549 }
550 }
551 for (ptbiabl = ptbebus->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT)
552 yagCheckRCandUpdateNames(ptcone, rcht, ptbiabl->CNDABL, ptbiabl->VALABL);
553 }
554 else {
555 ptuser = getptype(ptquad->USER, YAG_CONELIST_PTYPE);
556 if (ptuser != NULL) {
557 conedelay = yagGetTotalDelay((chain_list *)ptuser->DATA);
558 }
559 if (conedelay != 0) {
560 for (ptbiabl = ptbebus->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
561 if (ptbiabl->TIME != 0) continue;
562 ptbiabl->TIME = conedelay;
563 }
564 }
565 }
566 if (!processed) yag_check_single_delay(ptbebus->BIABL);
567 }
568 }
569 for (ptbereg = ptbefig->BEREG; ptbereg; ptbereg = ptbereg->NEXT) {
570 if (already_timed(ptbereg->BIABL)) continue;
571 processed = FALSE;
572 if (ptbereg->BINODE != NULL) ptquad = (bequad_list *)ptbereg->BINODE->VALNODE;
573 else ptquad = NULL;
574 if (ptquad != NULL) {
575 ptuser = getptype(ptquad->USER, YAG_CONE_PTYPE);
576 if (ptuser != NULL) {
577 ptcone = (cone_list *)ptuser->DATA;
578 if (ptcone != NULL) {
579 if ((ptcone->TECTYPE & YAG_SENSITIVE) == YAG_SENSITIVE) {
580 processed = yagTimeSensitiveBereg(ptbereg, ptcone);
581 }
582 else if (V_INT_TAB[__YAG_MAX_SPLIT_CMD_TIMING].VALUE>0)
583 yagSplitIntoMinterms(&ptbereg->BIABL, ptcone);
584 }
585 if (!processed) {
586 for (ptbiabl = ptbereg->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
587 ptbiabl->TIME = yagGetDelay(ptcone, ptbiabl->CNDABL, ptbiabl->VALABL);
588 }
589 }
590 for (ptbiabl = ptbereg->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT)
591 yagCheckRCandUpdateNames(ptcone, rcht, ptbiabl->CNDABL, ptbiabl->VALABL);
592 }
593 else {
594 ptuser = getptype(ptquad->USER, YAG_CONELIST_PTYPE);
595 if (ptuser != NULL) {
596 conedelay = yagGetTotalDelay((chain_list *)ptuser->DATA);
597 }
598 if (conedelay != 0) {
599 for (ptbiabl = ptbereg->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
600 if (ptbiabl->TIME != 0) continue;
601 ptbiabl->TIME = conedelay;
602 }
603 }
604 }
605 if (!processed) yag_check_single_delay(ptbereg->BIABL);
606 }
607 }
608 for (ptbeaux = ptbefig->BEAUX; ptbeaux; ptbeaux = ptbeaux->NEXT) {
609 if (ptbeaux->TIME != 0) continue;
610 processed = FALSE;
611 if (ptbeaux->TIME != 0) continue;
612 ptquad = (bequad_list *)ptbeaux->NODE;
613 if (ptquad != NULL) {
614 ptuser = getptype(ptquad->USER, YAG_CONE_PTYPE);
615 if (ptuser != NULL) {
616 ptcone = (cone_list *)ptuser->DATA;
617 uptime = yagGetDelay(ptcone, NULL, oneexpr);
618 downtime = yagGetDelay(ptcone, NULL, zeroexpr);
619 if (ptcone != NULL) sensitive = ((ptcone->TECTYPE & YAG_SENSITIVE) == YAG_SENSITIVE);
620 else sensitive = FALSE;
621 if (ptcone != NULL) split = ((ptcone->TECTYPE & YAG_SPLITTIMING) == YAG_SPLITTIMING);
622 else split = FALSE;
623 if (((YAG_CONTEXT->YAG_SPLITTIMING_RATIO >= 1.0 && (uptime > downtime * YAG_CONTEXT->YAG_SPLITTIMING_RATIO || downtime > uptime * YAG_CONTEXT->YAG_SPLITTIMING_RATIO)) || sensitive || split)
624 && strchr(ptbeaux->NAME, ' ') == NULL) {
625 ptbiabl = beh_addbiabl(NULL, "label", copyExpr(oneexpr), createAtom(namealloc("'u'")));
626 ptbiabl->FLAG |= BEH_CND_PRECEDE;
627 ptbiabl = beh_addbiabl(ptbiabl, "label", notExpr(copyExpr(ptbeaux->ABL)), copyExpr(zeroexpr));
628 ptbiabl->FLAG |= BEH_CND_PRECEDE;
629 ptbiabl->TIME = downtime;
630 ptbiabl = beh_addbiabl(ptbiabl, "label", copyExpr(ptbeaux->ABL), copyExpr(oneexpr));
631 ptbiabl->TIME = uptime;
632 if (sensitive) {
633 ptbefig->BEREG = beh_addbereg(ptbefig->BEREG, ptbeaux->NAME, ptbiabl, NULL,0);
634 processed = yagTimeSensitiveBereg(ptbefig->BEREG, ptcone);
635 if (V_INT_TAB[__YAG_MAX_SPLIT_CMD_TIMING].VALUE>0)
636 yagSplitIntoMinterms(&ptbefig->BEREG->BIABL, ptcone);
637 for (ptbiabl = ptbefig->BEREG->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT)
638 yagCheckRCandUpdateNames(ptcone, rcht, ptbiabl->CNDABL, ptbiabl->VALABL);
639 }
640 else {
641 ptbefig->BEBUX = beh_addbebux(ptbefig->BEBUX, ptbeaux->NAME, ptbiabl, NULL, 'M',0);
642 yagWarning(WAR_SPLIT_TIMING, NULL, ptbeaux->NAME, NULL, 0);
643 if (V_INT_TAB[__YAG_MAX_SPLIT_CMD_TIMING].VALUE>0)
644 yagSplitIntoMinterms(&ptbefig->BEBUX->BIABL, ptcone);
645 for (ptbiabl = ptbefig->BEBUX->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT)
646 yagCheckRCandUpdateNames(ptcone, rcht, ptbiabl->CNDABL, ptbiabl->VALABL);
647 }
648 ptbeaux->NAME = NULL;
649 }
650 else {
651 ptbeaux->TIME = yagGetDelay((cone_list *)ptuser->DATA, NULL, NULL);
652 ptbeaux->TIMER = uptime;
653 ptbeaux->TIMEF = downtime;
654 yagCheckRCandUpdateNames(ptcone, rcht, NULL, ptbeaux->ABL);
655 }
656 }
657 else {
658 ptuser = getptype(ptquad->USER, YAG_CONELIST_PTYPE);
659 if (ptuser != NULL) {
660 ptbeaux->TIME = yagGetTotalDelay((chain_list *)ptuser->DATA);
661 }
662 }
663 }
664 }
665 for (ptbeout = ptbefig->BEOUT; ptbeout; ptbeout = ptbeout->NEXT) {
666 if (ptbeout->TIME != 0) continue;
667 processed = FALSE;
668 if (ptbeout->TIME != 0) continue;
669 ptquad = (bequad_list *)ptbeout->NODE;
670 if (ptquad != NULL) {
671 ptuser = getptype(ptquad->USER, YAG_CONE_PTYPE);
672 if (ptuser != NULL) {
673 ptcone = (cone_list *)ptuser->DATA;
674 uptime = yagGetDelay(ptcone, NULL, oneexpr);
675 downtime = yagGetDelay(ptcone, NULL, zeroexpr);
676 if (ptcone != NULL) sensitive = ((ptcone->TECTYPE & YAG_SENSITIVE) == YAG_SENSITIVE);
677 else sensitive = FALSE;
678 if (ptcone != NULL) split = ((ptcone->TECTYPE & YAG_SPLITTIMING) == YAG_SPLITTIMING);
679 else split = FALSE;
680 if (((YAG_CONTEXT->YAG_SPLITTIMING_RATIO >= 1.0 && (uptime > downtime * YAG_CONTEXT->YAG_SPLITTIMING_RATIO || downtime > uptime * YAG_CONTEXT->YAG_SPLITTIMING_RATIO)) || sensitive || split)
681 && strchr(ptbeout->NAME, ' ') == NULL) {
682 ptbiabl = beh_addbiabl(NULL, "label", copyExpr(oneexpr), createAtom(namealloc("'u'")));
683 ptbiabl->FLAG |= BEH_CND_PRECEDE;
684 ptbiabl = beh_addbiabl(ptbiabl, "label", notExpr(copyExpr(ptbeout->ABL)), copyExpr(zeroexpr));
685 ptbiabl->FLAG |= BEH_CND_PRECEDE;
686 ptbiabl->TIME = downtime;
687 ptbiabl = beh_addbiabl(ptbiabl, "label", copyExpr(ptbeout->ABL), copyExpr(oneexpr));
688 ptbiabl->TIME = uptime;
689 if (sensitive) {
690 ptbefig->BEREG = beh_addbereg(ptbefig->BEREG, ptbeout->NAME, ptbiabl, NULL,0);
691 processed = yagTimeSensitiveBereg(ptbefig->BEREG, ptcone);
692 if (V_INT_TAB[__YAG_MAX_SPLIT_CMD_TIMING].VALUE>0)
693 yagSplitIntoMinterms(&ptbefig->BEREG->BIABL, ptcone);
694 for (ptbiabl = ptbefig->BEREG->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT)
695 yagCheckRCandUpdateNames(ptcone, rcht, ptbiabl->CNDABL, ptbiabl->VALABL);
696 }
697 else {
698 ptbefig->BEBUS = beh_addbebus(ptbefig->BEBUS, ptbeout->NAME, ptbiabl, NULL, 'M',0);
699 yagWarning(WAR_SPLIT_TIMING, NULL, ptbeout->NAME, NULL, 0);
700 if (V_INT_TAB[__YAG_MAX_SPLIT_CMD_TIMING].VALUE>0)
701 yagSplitIntoMinterms(&ptbefig->BEBUS->BIABL, ptcone);
702 for (ptbiabl = ptbefig->BEBUS->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT)
703 yagCheckRCandUpdateNames(ptcone, rcht, ptbiabl->CNDABL, ptbiabl->VALABL);
704 }
705 ptbeout->NAME = NULL;
706 }
707 else {
708 ptbeout->TIME = yagGetDelay((cone_list *)ptuser->DATA, NULL, NULL);
709 ptbeout->TIMER = uptime;
710 ptbeout->TIMEF = downtime;
711 yagCheckRCandUpdateNames(ptcone, rcht, NULL, ptbeout->ABL);
712 }
713 }
714 else {
715 ptuser = getptype(ptquad->USER, YAG_CONELIST_PTYPE);
716 if (ptuser != NULL) {
717 ptbeout->TIME = yagGetTotalDelay((chain_list *)ptuser->DATA);
718 }
719 }
720 }
721 }
722 for (ptbeaux = ptbefig->BEAUX; ptbeaux; ptbeaux = ptnextbeaux) {
723 ptnextbeaux = ptbeaux->NEXT;
724 if (ptbeaux->NAME == NULL) {
725 freeExpr(ptbeaux->ABL);
726 mbkfree(ptbeaux);
727 if (ptprevbeaux == NULL) {
728 ptbefig->BEAUX = ptnextbeaux;
729 }
730 else ptprevbeaux->NEXT = ptnextbeaux;
731 }
732 else ptprevbeaux = ptbeaux;
733 }
734 for (ptbeout = ptbefig->BEOUT; ptbeout; ptbeout = ptnextbeout) {
735 ptnextbeout = ptbeout->NEXT;
736 if (ptbeout->NAME == NULL) {
737 freeExpr(ptbeout->ABL);
738 mbkfree(ptbeout);
739 if (ptprevbeout == NULL) {
740 ptbefig->BEOUT = ptnextbeout;
741 }
742 else ptprevbeout->NEXT = ptnextbeout;
743 }
744 else ptprevbeout = ptbeout;
745 }
746 for (ptbebux = ptbefig->BEBUX; ptbebux; ptbebux = ptnextbebux) {
747 ptnextbebux = ptbebux->NEXT;
748 if (ptbebux->NAME == NULL) {
749 mbkfree(ptbebux);
750 if (ptprevbebux == NULL) {
751 ptbefig->BEBUX = ptnextbebux;
752 }
753 else ptprevbebux->NEXT = ptnextbebux;
754 }
755 else ptprevbebux = ptbebux;
756 }
757 for (ptbebus = ptbefig->BEBUS; ptbebus; ptbebus = ptnextbebus) {
758 ptnextbebus = ptbebus->NEXT;
759 if (ptbebus->NAME == NULL) {
760 mbkfree(ptbebus);
761 if (ptprevbebus == NULL) {
762 ptbefig->BEBUS = ptnextbebus;
763 }
764 else ptprevbebus->NEXT = ptnextbebus;
765 }
766 else ptprevbebus = ptbebus;
767 }
768
769 destroyBdd(1);
770
771 freeExpr(zeroexpr);
772 freeExpr(oneexpr);
773
774 // creating transmission lines
775 yadAddRC(rcht, ptbefig);
776 delht(rcht);
777 }
778
779 /****************************************************************************
780 * function yagGetTotalDelay(); *
781 ****************************************************************************/
782 static unsigned int
783 yagGetTotalDelay(chain_list *ptconelist)
784 {
785 chain_list *ptchain;
786 unsigned int result = 0;
787
788 for (ptchain = ptconelist; ptchain; ptchain = ptchain->NEXT) {
789 result += yagGetDelay((cone_list *)ptchain->DATA, NULL, NULL);
790 }
791 return result;
792 }
793
794 /****************************************************************************
795 * function yagGetDelay(); *
796 ****************************************************************************/
797 static unsigned int
798 yagGetDelay(cone_list *ptcone, chain_list *cndexpr, chain_list *valexpr)
799 {
800 edge_list *ptincone;
801 ptype_list *ptuser;
802 delay_list *delay;
803 chain_list *driverinputs = NULL;
804 char *inputname;
805 long delaymax = 0;
806 long delaymin = 0;
807 long delaysum = 0;
808 int useRising = TRUE;
809 int useFalling = TRUE;
810 int n = 0;
811
812 if (ptcone == NULL) return 0;
813
814 if (valexpr != NULL) {
815 if (ATOM(valexpr)) {
816 if (!strcmp (VALUE_ATOM (valexpr), "'1'")) useFalling = FALSE;
817 if (!strcmp (VALUE_ATOM (valexpr), "'0'")) useRising = FALSE;
818 if (!strcmp (VALUE_ATOM (valexpr), "'z'") || !strcmp (VALUE_ATOM (valexpr), "'u'")) {
819 return 0;
820 }
821 }
822 }
823
824 if (cndexpr != NULL) driverinputs = supportChain_listExpr(cndexpr);
825 if (valexpr != NULL) driverinputs = append(driverinputs, supportChain_listExpr(valexpr));
826
827 switch (YAG_CONTEXT->YAG_TAS_TIMING) {
828 case YAG_MAX_TIMING:
829 for (ptincone = ptcone->INCONE; ptincone; ptincone = ptincone->NEXT) {
830 if ((ptincone->TYPE & CNS_EXT) == 0) inputname = ptincone->UEDGE.CONE->NAME;
831 else inputname = ptincone->UEDGE.LOCON->NAME;
832 if (driverinputs != NULL && yagGetChain(driverinputs, mbk_devect(inputname, "[", "]")) == NULL) continue;
833 ptuser = getptype(ptincone->USER, TAS_DELAY_MAX);
834 if (ptuser != NULL) {
835 delay = (delay_list *)ptuser->DATA;
836 if (useRising && (delay->TPHH != TAS_NOTIME) && (n == 0 || delay->TPHH > delaymax)) {
837 delaymax = delay->TPHH;
838 n++;
839 }
840 if (useFalling && (delay->TPHL != TAS_NOTIME) && (n == 0 || delay->TPHL > delaymax)) {
841 delaymax = delay->TPHL;
842 n++;
843 }
844 if (useRising && (delay->TPLH != TAS_NOTIME) && (n == 0 || delay->TPLH > delaymax)) {
845 delaymax = delay->TPLH;
846 n++;
847 }
848 if (useFalling && (delay->TPLL != TAS_NOTIME) && (n == 0 || delay->TPLL > delaymax)) {
849 delaymax = delay->TPLL;
850 n++;
851 }
852 }
853 }
854 delaymax=mbk_long_round(delaymax/TTV_UNIT);
855 freechain(driverinputs);
856 if (delaymax > 0) return ((unsigned int)delaymax);
857 else return (unsigned int)(V_FLOAT_TAB[__YAG_DELTA_DELAY].VALUE*1e12*BEH_CNV_PS+0.5);
858 break;
859 case YAG_MIN_TIMING:
860 for (ptincone = ptcone->INCONE; ptincone; ptincone = ptincone->NEXT) {
861 if ((ptincone->TYPE & CNS_EXT) == 0) inputname = ptincone->UEDGE.CONE->NAME;
862 else inputname = ptincone->UEDGE.LOCON->NAME;
863 if (driverinputs != NULL && yagGetChain(driverinputs, inputname) == NULL) continue;
864 ptuser = getptype(ptincone->USER, TAS_DELAY_MIN);
865 if (ptuser != NULL) {
866 delay = (delay_list *)ptuser->DATA;
867 if (useRising && (delay->TPHH != TAS_NOTIME) && (n == 0 || delay->TPHH < delaymin)) {
868 delaymin = delay->TPHH;
869 n++;
870 }
871 if (useFalling && (delay->TPHL != TAS_NOTIME) && (n == 0 || delay->TPHL < delaymin)) {
872 delaymin = delay->TPHL;
873 n++;
874 }
875 if (useRising && (delay->TPLH != TAS_NOTIME) && (n == 0 || delay->TPLH < delaymin)) {
876 delaymin = delay->TPLH;
877 n++;
878 }
879 if (useFalling && (delay->TPLL != TAS_NOTIME) && (n == 0 || delay->TPLL < delaymin)) {
880 delaymin = delay->TPLL;
881 n++;
882 }
883 }
884 }
885 delaymin=mbk_long_round(delaymin/TTV_UNIT);
886 freechain(driverinputs);
887 if (delaymin > 0) return ((unsigned int)delaymin);
888 else return (unsigned int)(V_FLOAT_TAB[__YAG_DELTA_DELAY].VALUE*1e12*BEH_CNV_PS+0.5);
889 break;
890 case YAG_MED_TIMING:
891 for (ptincone = ptcone->INCONE; ptincone; ptincone = ptincone->NEXT) {
892 if ((ptincone->TYPE & CNS_EXT) == 0) inputname = ptincone->UEDGE.CONE->NAME;
893 else inputname = ptincone->UEDGE.LOCON->NAME;
894 if (driverinputs != NULL && yagGetChain(driverinputs, inputname) == NULL) continue;
895 ptuser = getptype(ptincone->USER, TAS_DELAY_MAX);
896 if (ptuser != NULL) {
897 delay = (delay_list *)ptuser->DATA;
898 if (useRising && delay->TPHH != TAS_NOTIME) {
899 delaysum += delay->TPHH;
900 n++;
901 }
902 if (useFalling && delay->TPHL != TAS_NOTIME) {
903 delaysum += delay->TPHL;
904 n++;
905 }
906 if (useRising && delay->TPLH != TAS_NOTIME) {
907 delaysum += delay->TPLH;
908 n++;
909 }
910 if (useFalling && delay->TPLL != TAS_NOTIME) {
911 delaysum += delay->TPLL;
912 n++;
913 }
914 }
915 }
916 if (n) delaysum=mbk_long_round(delaysum/(TTV_UNIT*n));
917 freechain(driverinputs);
918 if (delaysum > 0) return ((unsigned int)(delaysum));
919 else return (unsigned int)(V_FLOAT_TAB[__YAG_DELTA_DELAY].VALUE*1e12*BEH_CNV_PS+0.5);
920 break;
921 }
922 return 0;
923 }
924
925 static int
926 yagConstantAbl(ptexpr)
927 chain_list *ptexpr;
928 {
929 if (!ATOM(ptexpr)) return FALSE;
930 if (!strcmp(VALUE_ATOM(ptexpr), "'0'")
931 || !strcmp(VALUE_ATOM(ptexpr), "'1'")
932 || !strcmp(VALUE_ATOM(ptexpr), "'z'")
933 || !strcmp(VALUE_ATOM(ptexpr), "'u'")) {
934 return TRUE;
935 }
936 return FALSE;
937 }
938
939 /****************************************************************************
940 * function yagTimeSensitiveBebux(); *
941 ****************************************************************************/
942 static int
943 yagTimeSensitiveBebux(bebux_list *ptbebux, cone_list *ptcone)
944 {
945 biabl_list *ptbiabl;
946 biabl_list *ptnewbiabl = NULL;
947 chain_list *ptsupport;
948 chain_list *ptchain;
949 chain_list *ptinputexpr, *trigger, *ptnewcnd;
950 unsigned int delay;
951
952 /* Check that all drivers are constants */
953 for (ptbiabl = ptbebux->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
954 if (!yagConstantAbl(ptbiabl->VALABL)) return FALSE;
955 }
956
957 for (ptbiabl = ptbebux->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
958 ptsupport = supportChain_listExpr(ptbiabl->CNDABL);
959 for (ptchain = ptsupport; ptchain; ptchain = ptchain->NEXT) {
960 ptinputexpr = createAtom(ptchain->DATA);
961 delay = yagGetDelay(ptcone, ptinputexpr, ptbiabl->VALABL);
962 trigger = createExpr(STABLE);
963 addQExpr(trigger, ptinputexpr);
964 ptnewcnd = createExpr(AND);
965 addQExpr(ptnewcnd, copyExpr(ptbiabl->CNDABL));
966 addQExpr(ptnewcnd, notExpr(trigger));
967 ptnewbiabl = beh_addbiabl(ptnewbiabl, "label", ptnewcnd, copyExpr(ptbiabl->VALABL));
968 ptnewbiabl->TIME = delay;
969 }
970 }
971 ptnewbiabl = (biabl_list *)reverse((chain_list *)ptnewbiabl);
972 beh_frebiabl(ptbebux->BIABL);
973 ptbebux->BIABL = ptnewbiabl;
974 return TRUE;
975 }
976
977 /****************************************************************************
978 * function yagTimeSensitiveBereg(); *
979 ****************************************************************************/
980 static int
981 yagTimeSensitiveBereg(bereg_list *ptbereg, cone_list *ptcone)
982 {
983 biabl_list *ptbiabl;
984 biabl_list *ptnewbiabl = NULL;
985 chain_list *ptsupport;
986 chain_list *ptchain;
987 chain_list *ptinputexpr, *trigger, *ptnewcnd;
988 unsigned int delay;
989
990 /* Check that all drivers are constants */
991 for (ptbiabl = ptbereg->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
992 if (!yagConstantAbl(ptbiabl->VALABL)) return FALSE;
993 }
994
995 for (ptbiabl = ptbereg->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
996 ptsupport = supportChain_listExpr(ptbiabl->CNDABL);
997 for (ptchain = ptsupport; ptchain; ptchain = ptchain->NEXT) {
998 ptinputexpr = createAtom(ptchain->DATA);
999 delay = yagGetDelay(ptcone, ptinputexpr, ptbiabl->VALABL);
1000 trigger = createExpr(STABLE);
1001 addQExpr(trigger, ptinputexpr);
1002 ptnewcnd = createExpr(AND);
1003 addQExpr(ptnewcnd, copyExpr(ptbiabl->CNDABL));
1004 addQExpr(ptnewcnd, notExpr(trigger));
1005 ptnewbiabl = beh_addbiabl(ptnewbiabl, "label", ptnewcnd, copyExpr(ptbiabl->VALABL));
1006 ptnewbiabl->TIME = delay;
1007 }
1008 }
1009 ptnewbiabl = (biabl_list *)reverse((chain_list *)ptnewbiabl);
1010 beh_frebiabl(ptbereg->BIABL);
1011 ptbereg->BIABL = ptnewbiabl;
1012 return TRUE;
1013 }
1014
1015 /****************************************************************************
1016 * function yagTimeSensitiveBebus(); *
1017 ****************************************************************************/
1018 static int
1019 yagTimeSensitiveBebus(bebus_list *ptbebus, cone_list *ptcone)
1020 {
1021 biabl_list *ptbiabl;
1022 biabl_list *ptnewbiabl = NULL;
1023 chain_list *ptsupport;
1024 chain_list *ptchain;
1025 chain_list *ptinputexpr, *trigger, *ptnewcnd;
1026 unsigned int delay;
1027
1028 /* Check that all drivers are constants */
1029 for (ptbiabl = ptbebus->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
1030 if (!yagConstantAbl(ptbiabl->VALABL)) return FALSE;
1031 }
1032
1033 for (ptbiabl = ptbebus->BIABL; ptbiabl; ptbiabl = ptbiabl->NEXT) {
1034 ptsupport = supportChain_listExpr(ptbiabl->CNDABL);
1035 for (ptchain = ptsupport; ptchain; ptchain = ptchain->NEXT) {
1036 ptinputexpr = createAtom(ptchain->DATA);
1037 delay = yagGetDelay(ptcone, ptinputexpr, ptbiabl->VALABL);
1038 trigger = createExpr(STABLE);
1039 addQExpr(trigger, ptinputexpr);
1040 ptnewcnd = createExpr(AND);
1041 addQExpr(ptnewcnd, copyExpr(ptbiabl->CNDABL));
1042 addQExpr(ptnewcnd, notExpr(trigger));
1043 ptnewbiabl = beh_addbiabl(ptnewbiabl, "label", ptnewcnd, copyExpr(ptbiabl->VALABL));
1044 ptnewbiabl->TIME = delay;
1045 }
1046 }
1047 ptnewbiabl = (biabl_list *)reverse((chain_list *)ptnewbiabl);
1048 beh_frebiabl(ptbebus->BIABL);
1049 ptbebus->BIABL = ptnewbiabl;
1050 return TRUE;
1051 }
1052
1053 /****************************************************************************
1054 * function yagCalcStmResPair(); *
1055 ****************************************************************************/
1056 int
1057 yagCalcStmResPair(chain_list *uplist, chain_list *downlist, cone_list *ptcone, float *ptupresistance, float *ptdownresistance)
1058 {
1059 int result = FALSE;
1060
1061 if (yagCalcStmResistance(uplist, ptcone, CNS_VDD, ptupresistance)) {
1062 result = yagCalcStmResistance(downlist, ptcone, CNS_VSS, ptdownresistance);
1063 }
1064 return result;
1065 }
1066
1067 /****************************************************************************
1068 * function yagCalcStmResistance(); *
1069 ****************************************************************************/
1070 int
1071 yagCalcStmResistance(chain_list *ptbranchlist, cone_list *ptcone, long type, float *ptresistance)
1072 {
1073 chain_list *ptchain;
1074 alim_list *powercone;
1075 float sum = 0.0;
1076 float current;
1077 float vout, vsupply, vin;
1078 int result;
1079
1080 powercone =cns_get_multivoltage(ptcone);
1081 if (powercone == NULL) {
1082 vout = V_FLOAT_TAB[__SIM_POWER_SUPPLY].VALUE / 2;
1083 if (type == CNS_VDD) {
1084 vsupply = V_FLOAT_TAB[__SIM_POWER_SUPPLY].VALUE;
1085 vin = 0.0;
1086 }
1087 else {
1088 vsupply = 0.0;
1089 vin = V_FLOAT_TAB[__SIM_POWER_SUPPLY].VALUE;
1090 }
1091 }
1092 else {
1093 vout = powercone->VSSMIN + (powercone->VDDMAX - powercone->VSSMIN) / 2;
1094 if (type == CNS_VDD) {
1095 vsupply = powercone->VDDMAX;
1096 vin = 0.0;
1097 }
1098 else {
1099 vsupply = powercone->VSSMIN;
1100 vin = V_FLOAT_TAB[__SIM_POWER_SUPPLY].VALUE;
1101 }
1102 }
1103 for (ptchain = ptbranchlist; ptchain; ptchain = ptchain->NEXT) {
1104 result = yagStmBranchCurrent((branch_list *)ptchain->DATA, vin, vout, vsupply, &current);
1105 if (!result) return FALSE;
1106 sum += current;
1107 }
1108 if (type == CNS_VSS) sum = -sum;
1109 *ptresistance = 1 / sum;
1110 return TRUE;
1111 }
1112
1113 int
1114 yagStmBranchCurrent(branch_list *ptbranch, float vin, float vout, float vsupply, float *ptcurrent)
1115 {
1116 stm_solver_maillon_list *ptstmlink;
1117 tpiv *ptstmbranch;
1118 link_list *ptlink;
1119 cone_list *prevcone;
1120 lotrs_list *ptparatrans, *ptlotrs;
1121 ptype_list *ptuser;
1122 alim_list *power;
1123 chain_list *ptparachain, *ptchain;
1124 double vbulk;
1125 int result;
1126 long width, length;
1127 char brtype;
1128
1129 /* Only for non-degraded branches with at least one transistor */
1130 if ((ptbranch->TYPE & CNS_EXT) == CNS_EXT && ptbranch->LINK->NEXT == NULL) return FALSE;
1131 if ((ptbranch->TYPE & CNS_DEGRADED) == CNS_DEGRADED) return FALSE;
1132
1133 /* temporarily modify width for parallel transistors */
1134 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1135 if ((ptlink->TYPE & CNS_EXT) == 0) {
1136 ptlotrs = ptlink->ULINK.LOTRS;
1137 if ((ptuser = getptype(ptlotrs->USER, MBK_TRANS_PARALLEL)) != NULL) {
1138 ptparachain = (chain_list *)ptuser->DATA;
1139 ptlotrs->USER = addptype(ptlotrs->USER, YAG_WIDTH_PTYPE, (void *)ptlotrs->WIDTH);
1140 length = ptlotrs->LENGTH;
1141 width = 0;
1142 for (ptchain = ptparachain; ptchain; ptchain = ptchain->NEXT) {
1143 ptparatrans = (lotrs_list *)ptchain->DATA;
1144 width += ptparatrans->WIDTH * (length / ptparatrans->LENGTH);
1145 }
1146 ptlotrs->WIDTH = width;
1147 }
1148 }
1149 }
1150
1151 switch (TAS_CONTEXT->TAS_LEVEL) {
1152 case 2:
1153 case 4:
1154 brtype = TAS_TRMODEL_SPICE;
1155 break;
1156 default:
1157 brtype = TAS_TRMODEL_MCCRSAT;
1158 }
1159
1160 /* create tpiv style branch and set supply */
1161 ptstmbranch = tpiv_createbranch(ptbranch->LINK, brtype);
1162 for (ptstmlink = ptstmbranch->HEAD; ptstmlink->NEXT; ptstmlink = ptstmlink->NEXT);
1163 ptstmlink->MAILLON->VS = vsupply;
1164
1165 /* fix gate and bulk voltages */
1166 for( ptstmlink = ptstmbranch->HEAD, ptlink = ptbranch->LINK; ptstmlink; ptstmlink = ptstmlink->NEXT, ptlink = ptlink->NEXT) {
1167 if (TAS_CONTEXT->TAS_LEVEL == 2) {
1168 elp_lotrs_param_get(ptlink->ULINK.LOTRS,NULL,NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, &vbulk, NULL, NULL, NULL, NULL);
1169 }
1170 else vbulk = vsupply;
1171 tas_tpiv_set_vb( ptstmlink->MAILLON, vbulk );
1172
1173 if ((ptlink->ULINK.LOTRS->TYPE & CNS_TN) == CNS_TN) {
1174 prevcone = (cone_list *)getptype(ptlink->ULINK.LOTRS->USER, CNS_DRIVINGCONE)->DATA;
1175 power=cns_get_multivoltage(prevcone);
1176 if (power) {
1177 tas_tpiv_set_vg( ptstmlink->MAILLON, power->VDDMAX - power->VSSMIN );
1178 continue;
1179 }
1180 }
1181 tas_tpiv_set_vg( ptstmlink->MAILLON, vin );
1182 }
1183
1184 result = stm_solver_i(ptstmbranch->HEAD, vout, ptcurrent);
1185
1186 tpiv_freebranch(ptstmbranch);
1187
1188 /* restore width */
1189 for (ptlink = ptbranch->LINK; ptlink; ptlink = ptlink->NEXT) {
1190 if ((ptlink->TYPE & CNS_EXT) == 0) {
1191 ptlotrs = ptlink->ULINK.LOTRS;
1192 if ((ptuser = getptype(ptlotrs->USER, YAG_WIDTH_PTYPE)) != NULL) {
1193 ptlotrs->WIDTH = (long)ptuser->DATA;
1194 ptlotrs->USER = delptype(ptlotrs->USER, YAG_WIDTH_PTYPE);
1195 }
1196 }
1197 }
1198
1199 return result;
1200 }
1201
1202 void
1203 yagPrepStmSolver(cone_list *ptcone)
1204 {
1205 inffig_list *ifl;
1206
1207 ifl = getloadedinffig(YAG_CONTEXT->YAG_FIGNAME);
1208 cns_addmultivoltage_cone(NULL, ifl, ptcone);
1209 }
1210
1211 #endif