extern void average_capacitance(befig_list *befig) { bereg_list* bereg; bebux_list* bebux; beaux_list* beaux; bepor_list* bepor; char* name; float capa; /*init*/ for (beaux=befig->BEAUX; beaux; beaux=beaux->NEXT) { name=getoppositename(beaux->NAME); capa=getcapacitance(beaux->NAME); capa+=getcapacitance(name); capa=capa/2; putcapacitance(beaux->NAME,capa); putcapacitance(name,capa); } for (bereg=befig->BEREG; bereg; bereg=bereg->NEXT) { name=getoppositename(bereg->NAME); capa=getcapacitance(bereg->NAME); capa+=getcapacitance(name); capa=capa/2; putcapacitance(bereg->NAME,capa); putcapacitance(name,capa); } for (bebux=befig->BEBUX; bebux; bebux=bebux->NEXT) { name=getoppositename(bebux->NAME); capa=getcapacitance(bebux->NAME); capa+=getcapacitance(name); capa=capa/2; putcapacitance(bebux->NAME,capa); putcapacitance(name,capa); } for (bepor=befig->BEPOR; bepor; bepor=bepor->NEXT) { /*inputs only*/ if (isvss(bepor->NAME) || isvdd(bepor->NAME)) continue; switch (bepor->DIRECTION) {case OUT: case TRISTATE: continue;} name=getoppositename(bepor->NAME); capa=getcapacitance(bepor->NAME); capa+=getcapacitance(name); capa=capa/2; putcapacitance(bepor->NAME,capa); putcapacitance(name,capa); } }
static int insert_buffer(losig_list* losig, lofig_list* lofig, int optim_level, long index) { double capa, init_capa; cell_list* buffer; chain_list* namechain, *sigchain=NULL; char* signame; lofig_list* model; losig_list* losig_buf; loins_list* loins_buf; locon_list* locon; losig_list* losig_vdd=NULL, *losig_vss=NULL, *losig_aux; ptype_list* ptype, *buffer_ptype; double delay, best_delay, init_delay; loins_list* loins; chain_list* lofigchain,*newlofigchain=NULL; int buffer_is_better=0, change=1; /*flags*/ chain_list* pred; chain_list* temp; buffer=getCellbuffer(); /*no buffer in library*/ if (!buffer) return 0; if (!losig->NAMECHAIN) { fprintf(stderr,"insert_buffer: no name on signal\n"); autexit(1); } best_delay=critical_delay(lofig); init_capa=getcapacitance(losig->NAMECHAIN->DATA); /*add buffer to netlist*/ signame=getautoname(losig->NAMECHAIN->DATA); namechain=addchain(NULL,signame); losig_buf=addlosig(lofig,index,namechain,INTERNAL); putcapacitance(signame,0); putdelay(signame,0); model=getlofig(buffer->BEFIG->NAME,'A'); /*search vdd and vss*/ for (locon=lofig->LOCON; locon; locon=locon->NEXT) { if (isvdd(locon->NAME)) losig_vdd=locon->SIG; if (isvss(locon->NAME)) losig_vss=locon->SIG; } /*build list of signal*/ for (locon=model->LOCON;locon; locon=locon->NEXT) { if (locon->DIRECTION==UNKNOWN) { fprintf(stderr,"BEH: 'linkage %s' in figure '%s' isn't accepted\n", locon->NAME,model->NAME); autexit(1); } if (isvdd(locon->NAME)) losig_aux=losig_vdd; else if (isvss(locon->NAME)) losig_aux=losig_vss; else if (locon->DIRECTION==OUT) losig_aux=losig_buf; else if (locon->DIRECTION==IN) losig_aux=losig; else { fprintf(stderr,"insert_buffer: buffer port '%s' unknown\n",locon->NAME); autexit(1); } sigchain=addchain(sigchain,losig_aux); } sigchain=reverse(sigchain); loins_buf=addloins(lofig,signame,model,sigchain); freechain(sigchain); /*to check changes*/ init_delay=getdelay(losig->NAMECHAIN->DATA); init_capa=getcapacitance(losig->NAMECHAIN->DATA); loins_capacitance(loins_buf,1/*add capa*/); /*lofigchain*/ for (locon=loins_buf->LOCON;locon; locon=locon->NEXT) { if (locon->DIRECTION==UNKNOWN) { fprintf(stderr,"BEH: 'linkage %s' in figure '%s' isn't accepted\n", locon->NAME,loins_buf->INSNAME); autexit(1); } if (isvdd(locon->NAME)) losig_aux=losig_vdd; else if (isvss(locon->NAME)) losig_aux=losig_vss; else if (locon->DIRECTION==OUT) losig_aux=losig_buf; else if (locon->DIRECTION==IN) losig_aux=losig; else { fprintf(stderr,"insert_buffer: buffer port '%s' unknown\n",locon->NAME); autexit(1); } ptype=getptype(losig_aux->USER,LOFIGCHAIN); if (!ptype) losig_aux->USER=addptype(losig_aux->USER,LOFIGCHAIN,addchain(NULL,locon)); else ptype->DATA=addchain(ptype->DATA,locon); } /*move all instance after buffer*/ ptype=getptype(losig->USER,LOFIGCHAIN); buffer_ptype=getptype(losig_buf->USER,LOFIGCHAIN); if (!ptype || !buffer_ptype) { fprintf(stderr,"insert_buffer: LOFIGCHAIN not found\n"); autexit(1); } for (lofigchain=((chain_list*)ptype->DATA)->NEXT/*first is entry of buffer*/; 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); } /*do not move drivers and port of circuit*/ if (locon->TYPE==EXTERNAL || locon->DIRECTION!=IN) { newlofigchain=addchain(newlofigchain,locon); continue; } loins=locon->ROOT; /*change capacitance*/ loins_capacitance(loins,0/*remove capa*/); /*change netlist*/ locon->SIG=losig_buf; buffer_ptype->DATA=addchain(buffer_ptype->DATA,locon); loins_capacitance(loins,1/*add capa*/); } /*put back drivers*/ freechain(((chain_list*)ptype->DATA)->NEXT/*first is entry of buffer*/); ((chain_list*)ptype->DATA)->NEXT=newlofigchain; /*eval all changes*/ propagate_loins_delay(loins_buf); /*relaxation algorithm*/ while (change) { change=0; pred=NULL; buffer_ptype=getptype(losig_buf->USER,LOFIGCHAIN); ptype=getptype(losig->USER,LOFIGCHAIN); if (!buffer_ptype || !buffer_ptype->DATA) { fprintf(stderr,"insert_buffer: LOFIGCHAIN is empty\n"); autexit(1); } /*put critical path before buffer*/ for (lofigchain=buffer_ptype->DATA; lofigchain->NEXT/*last is buffer output*/; lofigchain=lofigchain->NEXT) { locon=lofigchain->DATA; loins=locon->ROOT; /*change capacitance*/ loins_capacitance(loins,0/*remove capa*/); /*change netlist*/ locon->SIG=losig; ptype->DATA=addchain(ptype->DATA,locon); loins_capacitance(loins,1/*add capa*/); /*put over*/ if (pred) pred->NEXT=lofigchain->NEXT; else buffer_ptype->DATA=lofigchain->NEXT; /*eval all changes*/ propagate_loins_delay(loins); propagate_loins_delay(loins_buf); delay=critical_delay(lofig); if (delay<best_delay) { /*finish change*/ best_delay=delay; change=1; /*flag of change*/ buffer_is_better=1; lofigchain->NEXT=NULL; freechain(lofigchain); break; } else { /*remove change*/ if (pred) pred->NEXT=lofigchain; else buffer_ptype->DATA=lofigchain; /*unchange capacitance*/ loins_capacitance(loins,0/*remove capa*/); /*unchange netlist*/ locon->SIG=losig_buf; temp=ptype->DATA; ptype->DATA=temp->NEXT; temp->NEXT=NULL; freechain(temp); loins_capacitance(loins,1/*add capa*/); /*avoid change*/ propagate_loins_delay(loins_buf); propagate_loins_delay(loins); /*for next loop*/ pred=lofigchain; } } }/*end of while*/ if (buffer_is_better) { /*chose the best buffer*/ change_instance(loins_buf, losig_buf, lofig, optim_level); } else { /*if insert buffer is worst than before, remove it*/ /*remove all references of buffer in lofigchain*/ for (locon=loins_buf->LOCON; locon; locon=locon->NEXT) { losig_aux=locon->SIG; ptype=getptype(losig_aux->USER,LOFIGCHAIN); if (!ptype) break; pred=NULL; for (lofigchain=ptype->DATA; lofigchain; lofigchain=lofigchain->NEXT) { if (lofigchain->DATA==locon) { if (pred) pred->NEXT=lofigchain->NEXT; else ptype->DATA=lofigchain->NEXT; lofigchain->NEXT=NULL; freechain(lofigchain); break; } pred=lofigchain; } } buffer_ptype=getptype(losig_buf->USER,LOFIGCHAIN); ptype=getptype(losig->USER,LOFIGCHAIN); if (buffer_ptype) { for (lofigchain=buffer_ptype->DATA; lofigchain; lofigchain=lofigchain->NEXT) { locon=lofigchain->DATA; loins=locon->ROOT; /*change capacitance*/ loins_capacitance(loins,0/*remove capa*/); /*change netlist*/ locon->SIG=losig; ptype->DATA=addchain(ptype->DATA,locon); loins_capacitance(loins,1/*add capa*/); propagate_loins_delay(loins); } freechain(buffer_ptype->DATA); buffer_ptype->DATA=NULL; } loins_capacitance(loins_buf,0/*remove capa*/); dellosig(lofig,index); delloins(lofig,loins_buf->INSNAME); propagate_losig_delay(losig); /*verify no change on timing*/ delay=critical_delay(lofig); capa=getcapacitance(losig->NAMECHAIN->DATA); //01/09/2004 xtof's modification: rounding problem if ((int)(capa + 0.5)!=(int)(init_capa + 0.5) || (int)(delay + 0.5)!=(int)(best_delay + 0.5) || (int)(init_delay + 0.5)!=(int)(getdelay(losig->NAMECHAIN->DATA) + 0.5)) { fprintf(stderr, "insert_buffer: compute error %e!=%e fF %f!=%f ps %f!=%f ps\n", capa,init_capa,delay,best_delay, init_delay, getdelay(losig->NAMECHAIN->DATA)); autexit(1); } } return buffer_is_better; }
extern void adapt_for_cell(befig_list *befig) { beout_list* beout; bebus_list* bebus; bereg_list* bereg; bebux_list* bebux; beaux_list* beaux; biabl_list* biabl; bepor_list* bepor; char* name; /*constants*/ putcapacitance(getablatomone(),0); putcapacitance(getablatomzero(),0); /*init*/ for (beaux=befig->BEAUX; beaux; beaux=beaux->NEXT) { name=getoppositename(beaux->NAME); putcapacitance(beaux->NAME,0); putcapacitance(name,0); } for (bereg=befig->BEREG; bereg; bereg=bereg->NEXT) { name=getoppositename(bereg->NAME); putcapacitance(bereg->NAME,0); putcapacitance(name,0); } for (bebux=befig->BEBUX; bebux; bebux=bebux->NEXT) { name=getoppositename(bebux->NAME); putcapacitance(bebux->NAME,0); putcapacitance(name,0); } for (bepor=befig->BEPOR; bepor; bepor=bepor->NEXT) { /*inputs only*/ if (isvss(bepor->NAME) || isvdd(bepor->NAME)) continue; switch (bepor->DIRECTION) {case OUT: case TRISTATE: continue;} name=getoppositename(bepor->NAME); putcapacitance(bepor->NAME,0); putcapacitance(name,0); } /*adapt abl for cell of library and eval capacitance*/ for (beout=befig->BEOUT; beout; beout=beout->NEXT) { beout->ABL=inv_oper(beout->ABL,0); /*propagate NOT*/ beout->ABL=build_negativ(beout->ABL); /*minimize inverters*/ /*adapt the abl to match with a big cell later*/ beout->ABL=adapt_abl(beout->ABL); /*count capacitance of leaves*/ } for (beaux=befig->BEAUX; beaux; beaux=beaux->NEXT) { beaux->ABL=inv_oper(beaux->ABL,0); /*propagate NOT*/ beaux->ABL=build_negativ(beaux->ABL); /*minmize number of NOT*/ beaux->ABL=adapt_abl(beaux->ABL); /*count capacitance of leaves*/ } for (bebus=befig->BEBUS; bebus; bebus=bebus->NEXT) { for (biabl=bebus->BIABL; biabl; biabl=biabl->NEXT) { biabl->VALABL=inv_oper(biabl->VALABL,0); /*propagate NOT*/ biabl->CNDABL=inv_oper(biabl->CNDABL,0); /*propagate NOT*/ biabl->VALABL=build_negativ(biabl->VALABL); /*minimize NOT*/ biabl->CNDABL=build_negativ(biabl->CNDABL); } bebus->BIABL=adapt_bus(bebus->BIABL); /*count capacitance of leaves*/ } for (bereg=befig->BEREG; bereg; bereg=bereg->NEXT) { for (biabl=bereg->BIABL; biabl; biabl=biabl->NEXT) { biabl->VALABL=inv_oper(biabl->VALABL,0); /*propagate NOT*/ biabl->CNDABL=inv_oper(biabl->CNDABL,0); /*propagate NOT*/ biabl->VALABL=build_negativ(biabl->VALABL); /*minimize NOT*/ biabl->CNDABL=build_negativ(biabl->CNDABL); } bereg->BIABL=adapt_reg(bereg->BIABL); /*count capacitance of leaves*/ } for (bebux=befig->BEBUX; bebux; bebux=bebux->NEXT) { for (biabl=bebux->BIABL; biabl; biabl=biabl->NEXT) { biabl->VALABL=inv_oper(biabl->VALABL,0); /*propagate NOT*/ biabl->CNDABL=inv_oper(biabl->CNDABL,0); /*propagate NOT*/ biabl->VALABL=build_negativ(biabl->VALABL); /*minimize NOT*/ biabl->CNDABL=build_negativ(biabl->CNDABL); } bebux->BIABL=adapt_bus(bebux->BIABL); /*count capacitance of leaves*/ } }