extern void improve_capa_critical_path(lofig_list* lofig, int optim_level) { ptype_list* ptype, *ptype2; loins_list* loins; locon_list* locon; chain_list *lofigchain; losig_list* losig; ptype_list* long_path; int change=1; /*relaxation algorithm*/ while (change) { change=0; long_path=critical_path(lofig); long_path=sort_capa(long_path); /* on all signals of the critical path, improve capa*/ for (ptype=long_path; ptype; ptype=ptype->NEXT) { losig=(losig_list*) ptype->DATA; if (!losig->NAMECHAIN) { fprintf(stderr,"improve_capa_critical_path: no name on signal\n"); autexit(1); } /*seek latest driver*/ ptype2=getptype(losig->USER,LOFIGCHAIN); if (!ptype2) { fprintf(stderr, "improve_capa_critical_path: no lofigchain on losig '%s'\n", (char*) losig->NAMECHAIN->DATA); autexit(1); } loins=NULL; for (lofigchain=ptype2->DATA; lofigchain; lofigchain=lofigchain->NEXT){ locon= (locon_list*) lofigchain->DATA; if (locon->DIRECTION==UNKNOWN) { fprintf(stderr,"BEH: 'linkage %s' isn't accepted\n", locon->NAME); autexit(1); } if (locon->TYPE==EXTERNAL || locon->DIRECTION==IN) continue; loins=locon->ROOT; if (loins_delay(loins,losig->NAMECHAIN->DATA)>ptype->TYPE) break; } /*instance has changed, re-evaluate critical path*/ if (loins && change_instance(loins, losig, lofig, optim_level)) { change=1; break; } } freeptype(long_path); } }
static ptype_list* search_long_path(losig_list* losig, int ck_include) { loins_list* best_loins=NULL; locon_list* locon; losig_list *best_losig=NULL; loins_list* loins; befig_list* befig; char* signame, *ck=NULL; int reg=0; /*flag for flip-flop*/ chain_list* lofigchain; ptype_list* ptype, *ret; double max_delay=-1, delay; cell_list* cell; biabl_list* biabl; if (!losig) { fprintf(stderr,"search_long_path: NULL pointer\n"); autexit(1); } if (!losig->NAMECHAIN) { fprintf(stderr,"search_long_path: no losig name\n"); autexit(1); } signame=(char*) losig->NAMECHAIN->DATA; /*control combinational loop, not to recurse infinitively*/ if ( searchauthelem( ControlLoop, (char*) losig ) ) { fprintf(stderr,"Warning: combinational loop on signal %s\n", signame ); return ret; } addauthelem( ControlLoop, (char*) losig, 1 ); /*search drivers*/ ptype=getptype(losig->USER,LOFIGCHAIN); if (!ptype || !ptype->DATA) { fprintf(stderr,"search_long_path: no lofigchain found\n"); autexit(1); } for (lofigchain=(chain_list*) ptype->DATA; lofigchain; lofigchain=lofigchain->NEXT) { locon=(locon_list*) lofigchain->DATA; if (locon->DIRECTION==UNKNOWN) { fprintf(stderr,"BEH: 'linkage %s' isn't accepted\n", locon->NAME); autexit(1); } /*only outputs*/ if (isvss(locon->NAME) || isvdd(locon->NAME) || locon->DIRECTION==IN || locon->TYPE==EXTERNAL) continue; loins=locon->ROOT; delay=loins_delay(loins,signame); if (delay>max_delay) { best_loins=loins; max_delay=delay; } } loins=best_loins; ret=addptype(NULL, (long) max_delay>=0?max_delay:getdelay(signame), losig); if (!loins) return ret; /*stop at flip-flop*/ cell=getCell(loins->FIGNAME); if (!cell) { fprintf(stderr,"library error: no cell '%s.vbe' found\n", loins->FIGNAME); autexit(1); } befig=cell->BEFIG; if (befig->BEREG) { for ( biabl = cell->BEFIG->BEREG->BIABL; biabl; biabl = biabl->NEXT ) { ptype=getptype(biabl->USER,ABL_STABLE); if (ptype) { /*do not include clock in path*/ if (!ck_include) return ret; reg=1; ck=ptype->DATA; break; } } } max_delay=-1; /*seek the latest input in cell*/ for (locon=loins->LOCON; locon; locon=locon->NEXT) { if (locon->DIRECTION==UNKNOWN) { fprintf(stderr,"BEH: 'linkage %s' in figure '%s' isn't accepted\n", locon->NAME,loins->FIGNAME); autexit(1); } /*only inputs*/ if (locon->DIRECTION==OUT || locon->DIRECTION==TRISTATE || isvss(locon->NAME) || isvdd(locon->NAME)) continue; /* if flip-flop, accept only clock */ if (reg && ck!=locon->NAME) continue; losig=locon->SIG; if (!losig->NAMECHAIN) { fprintf(stderr,"search_long_path: no name on signal\n"); autexit(1); } signame=(char*) losig->NAMECHAIN->DATA; delay=getdelay(signame); if (delay>max_delay) { best_losig=losig; max_delay=delay; } } losig=best_losig; /*no input found -> constant*/ if (!losig) return ret; ret->NEXT=search_long_path(losig,ck_include); return ret; }
static int change_instance(loins_list* loins, losig_list* losig, lofig_list* lofig, int optim_level) { losig_list* losig_aux; lofig_list* lofig_aux; double critical, best_critical, delay, best_delay; double RC_max, T_max; locon_list* locon, *locon_aux; int change=0; cell_list* cell, *best; best=getCell(loins->FIGNAME); if (!best || best->NAME!=loins->FIGNAME) { fprintf(stderr,"library error: no cell '%s.vbe' found\n",loins->FIGNAME); autexit(1); } if (!losig->NAMECHAIN) { fprintf(stderr,"change_instance: no name on signal\n"); autexit(1); } best_critical=critical_delay(lofig); best_delay=loins_delay(loins,losig->NAMECHAIN->DATA); /*compare RC and delay of instance*/ RC_max=loins_max_RC(loins,losig->NAMECHAIN->DATA); T_max=loins_max_T(loins); /*check all cell of the same kind*/ for (cell=sameCells(loins->FIGNAME); cell; cell=cell->NEXT) { /*eval critical*/ loins_capacitance(loins,0); /*remove own capacity*/ loins->FIGNAME=cell->NAME; /*change cell*/ loins_capacitance(loins,1); /*add its own capacity (cell has changed)*/ propagate_loins_delay(loins); critical=critical_delay(lofig); delay=loins_delay(loins,losig->NAMECHAIN->DATA); /*take new solution?*/ if ( (critical<best_critical && (cell->AREA<=best->AREA || optim_level>OPTIM_DELAY0)) || (critical==best_critical && delay<best_delay && (cell->AREA<=best->AREA || optim_level>=OPTIM_DELAY4 || (RC_max>T_max && optim_level>=OPTIM_DELAY1))) || (critical==best_critical && delay==best_delay && cell->AREA<best->AREA) ) { best_critical=critical; best=cell; best_delay=delay; change=1; } } /*end of loop on cell*/ loins_capacitance(loins,0); /*substract own capacity*/ loins->FIGNAME=best->NAME; /*capacitance and critical delay*/ loins_capacitance(loins,1); /*add it own capacity (cell has changed)*/ propagate_loins_delay(loins); /*verify change of loins*/ critical=critical_delay(lofig); delay=loins_delay(loins,losig->NAMECHAIN->DATA); if ((int)critical!=(int)best_critical || (int)delay!=(int)best_delay) { fprintf(stderr, "change_instance: compute error %f!=%f ps %f!=%f ps (%sdue to caller)\n", critical,best_critical,delay,best_delay,change?"not ":""); autexit(1); } /*if cell doesn't exist but is composed by several cells*/ /*map port with real order*/ if (best->MODE=='A' || best->MODE=='a') { loins_capacitance(loins,0); /*substract own capacity*/ /*change names*/ loins->FIGNAME=best->BEFIG->NAME; lofig_aux=getlofig(best->NAME,'A'); for (locon=loins->LOCON; locon; locon=locon->NEXT) { /*search locon in model*/ for (locon_aux=lofig_aux->LOCON; locon_aux; locon_aux=locon_aux->NEXT){ if (locon->NAME==locon_aux->NAME) break; } if (!locon_aux) { fprintf(stderr,"change_instance: locon '%s' not found\n", locon->NAME); autexit(1); } losig_aux=locon_aux->SIG; /*search real connection*/ for (locon_aux=lofig_aux->LOINS->LOCON; locon_aux; locon_aux=locon_aux->NEXT){ if (losig_aux==locon_aux->SIG) break; } if (!locon_aux) { fprintf(stderr,"change_instance: locon '%s' not found in cell\n", locon->NAME); autexit(1); } locon->NAME=locon_aux->NAME; } /*capacitance and critical delay*/ loins_capacitance(loins,1); /*add it own capacity (cell has changed)*/ propagate_loins_delay(loins); /*verify change of loins*/ critical=critical_delay(lofig); delay=loins_delay(loins,losig->NAMECHAIN->DATA); if ((int)critical!=(int)best_critical || (int)delay!=(int)best_delay) { fprintf(stderr, "change_instance: flatten error %f!=%f ps %f!=%f ps\n", critical,best_critical,delay,best_delay); autexit(1); } } /*end of change loins*/ return change; }