void parsekeys(const char *s, Key *spec) { const char *p, *e; Key *k; XPRINTF("Parsing key: '%s'\n", s); for (p = s; *p != '\0'; p = (*e == ',' ? e + 1 : e)) { /* need to escape ',' in command */ for (e = p; *e != '\0' && (*e != ',' || (e > p && *(e - 1) == '\\')); e++) ; if ((k = parsechain(p, e, spec))) { XPRINTF("Adding key: '%s'\n", s); addchain(k); } } }
extern void save_xsch(FILE* xsch_stream, lofig_list* lofig, ptype_list* long_path, int color_mode) { long color; ptype_list* ptype, *ptype2=NULL; float delay=0, delay_out=0; char mes[1024]; char* signame = NULL; locon_list* locon; losig_list* losig; float gradient=1; int count; loins_list* loins; char *source, *dest=NULL, *last_sig; chain_list* chain, *loinschain=NULL; chain_list* lofigchain; losig_list* losig_aux; /*build gradient*/ if (long_path && color_mode==XSCH_GRADIENT) { /*get time of last entry*/ count=1; for (ptype=long_path; ptype->NEXT; ptype=ptype->NEXT) count++; if (!ptype->DATA) { fprintf(stderr,"save_xsch: compute error\n"); exit(1); } delay=ptype->TYPE; gradient=delay/((float)XSCH_COLOR_MAX); } /*color for signals*/ for (losig=lofig->LOSIG; losig; losig=losig->NEXT) { if (!losig->NAMECHAIN || !losig->NAMECHAIN->DATA) { fprintf(stderr,"save_xsch: no name for signal\n"); exit(1); } signame=losig->NAMECHAIN->DATA; if (isvdd(signame) || isvss(signame)) continue; if (losig->TYPE==EXTERNAL) { /*search external output*/ ptype=getptype(losig->USER,LOFIGCHAIN); for (lofigchain=ptype->DATA; lofigchain; lofigchain=lofigchain->NEXT) { locon=lofigchain->DATA; if (locon->TYPE==EXTERNAL && locon->DIRECTION!=IN) break; } if (lofigchain) delay=getdelay(output_name(signame)); else delay=getdelay(signame); } else delay=getdelay(signame); switch (color_mode) { case XSCH_GRADIENT: color=gradient_color(delay,gradient); break; case XSCH_CRITICAL_PATH: default: color=XSCH_NEUTRAL_COLOR; break; } flush_losig(xsch_stream, signame, color, delay, losig->TYPE); } /*color for instances*/ for (loins=lofig->LOINS; loins; loins=loins->NEXT) { /*search signal output*/ 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->INSNAME); exit(1); } if (locon->DIRECTION==OUT || locon->DIRECTION==INOUT || locon->DIRECTION==TRISTATE || locon->DIRECTION==TRANSCV) break; } if (!locon) { fprintf(stderr,"save_xsch: no output found for '%s'\n",loins->INSNAME); exit(1); } losig=locon->SIG; signame=losig->NAMECHAIN->DATA; delay=getdelay(loins->INSNAME); switch (color_mode) { case XSCH_GRADIENT: color=gradient_color(delay,gradient); break; case XSCH_CRITICAL_PATH: default: /*is instance in critical path?*/ for (ptype=long_path; ptype; ptype=ptype->NEXT) { if ((char*)ptype->DATA!=signame) continue; /*if output and input signals belong to critical path, then instance belongs*/ for (locon=loins->LOCON; locon; locon=locon->NEXT) { if (locon->DIRECTION==OUT || locon->DIRECTION==TRISTATE) continue; losig_aux=locon->SIG; /*is signal in critical path?*/ for (ptype2=long_path; ptype2; ptype2=ptype2->NEXT) { if ((char*)ptype2->DATA==losig_aux->NAMECHAIN->DATA) break; } if (ptype2) break; } ptype=ptype2; /*found?*/ break; } /*build critical path list*/ if (ptype) loinschain=addchain(loinschain,loins); if (ptype) color=XSCH_RED_COLOR; else color=XSCH_NEUTRAL_COLOR; } flush_loins(xsch_stream, loins->INSNAME, color, delay); } /*color for connectors*/ for (locon=lofig->LOCON; locon; locon=locon->NEXT) { if (isvdd(locon->NAME) || isvss(locon->NAME)) continue; switch (locon->DIRECTION) { case IN: delay_out=getdelay(locon->NAME); sprintf(mes, "%d ps",(int)delay_out); break; case OUT: case TRISTATE: delay_out=getdelay(output_name(locon->NAME)); sprintf(mes, "%d ps",(int)delay_out); break; case INOUT: case TRANSCV: delay=getdelay(locon->NAME); delay_out=getdelay(output_name(locon->NAME)); sprintf(mes, "%d ps on input; %d ps on output",(int)delay,(int)delay_out); break; } switch (color_mode) { case XSCH_GRADIENT: color=gradient_color(delay_out,gradient); break; case XSCH_CRITICAL_PATH: default: /* seek if signal is in a long path*/ for (ptype=long_path; ptype; ptype=ptype->NEXT) { if ((char*)ptype->DATA==locon->NAME) break; } if (ptype) color=XSCH_RED_COLOR; else color=XSCH_NEUTRAL_COLOR; } flush_stream_special(xsch_stream, locon->NAME, color, mes); } /*critical path*/ if (loinschain && long_path && color_mode==XSCH_CRITICAL_PATH) { source=NULL; last_sig=NULL; for (ptype=long_path; ptype; ptype=ptype->NEXT) { signame=ptype->DATA; for (chain=loinschain; chain; chain=chain->NEXT) { loins=chain->DATA; /*search signal output*/ for (locon=loins->LOCON; locon; locon=locon->NEXT) { if (locon->DIRECTION==OUT || locon->DIRECTION==INOUT || locon->DIRECTION==TRISTATE || locon->DIRECTION==TRANSCV) { losig=locon->SIG; if (losig->NAMECHAIN->DATA==signame) { dest=loins->INSNAME; break; } } } if (locon) break; } /*if no instance found it is external connector. it has the same name than signal*/ if (!locon) dest=signame; if (source) flush_path(xsch_stream, source, last_sig, dest, XSCH_RED_COLOR, delay, INTERNAL); source=dest; last_sig=signame; } /*for last signal search output*/ if (losig) { ptype=getptype(losig->USER,LOFIGCHAIN); for (chain=ptype->DATA; chain; chain=chain->NEXT) { locon=chain->DATA; /*port of circuit*/ if (locon->TYPE==EXTERNAL) {dest=locon->NAME; break;} loins=locon->ROOT; /*register input if no error*/ if (locon->DIRECTION==IN || locon->DIRECTION==INOUT || locon->DIRECTION==TRANSCV) {dest=loins->INSNAME; break;} } flush_path(xsch_stream, source, signame, dest, XSCH_RED_COLOR, delay, losig->TYPE); } } freechain(loinschain); }
void verif_con_estouest(chain_list *liste_plotsph, chain_list **lst_conestouest) { static phfig_list *firstfig = NULL; phfig_list * figcour; phcon_list * lstcon, *con; chain_list * lst, *lstwork; static int cptest = 0, cptouest = 0; int cptestcour = 0, cptouestcour = 0; int index = 0; /* renumeroter les connecteurs physiques */ if (mode_debug) printf("modele plot %s\n", ((phfig_list * )liste_plotsph->DATA)->NAME); if (NULL == liste_plotsph) ringerreur(ERR_INTERNE_CON, NULL, NULL); if (NULL == firstfig) { (*lst_conestouest ) = NULL; firstfig = (phfig_list * ) liste_plotsph->DATA; lstcon = firstfig->PHCON; while (NULL != lstcon) { if ('W' == lstcon->ORIENT) { cptouest++; if (mode_debug) printf("REFERENCE con plot %s\n", lstcon->NAME); (*lst_conestouest) = addchain((*lst_conestouest), (void * ) lstcon); } lstcon->INDEX = index; index++; lstcon = lstcon->NEXT; } lstcon = firstfig->PHCON; while (NULL != lstcon) { if ('E' == lstcon->ORIENT) cptest++; lstcon->INDEX = index; index++; lstcon = lstcon->NEXT; } if (cptouest != cptest) ringerreur(ERR_NBCONESTOUEST , firstfig, firstfig); lst = (*lst_conestouest); while (NULL != lst) { con = (phcon_list * ) lst->DATA; if (mode_debug) printf("REFERENCE con plot figcour %s ycon %ld width %ld\n", con->NAME, con->YCON, con->WIDTH); lstcon = firstfig->PHCON; while (NULL != lstcon) { if (mode_debug) printf("REFERENCE con plot figref %s ycon %ld width %ld\n", lstcon->NAME, lstcon->YCON, lstcon->WIDTH); if (('E' == lstcon->ORIENT) && (lstcon->NAME == con->NAME) && (lstcon->YCON == con->YCON) && (lstcon->WIDTH == con->WIDTH)) { lstwork = addchain(lst->NEXT, (void * ) lstcon); lst->NEXT = lstwork; lst = lst->NEXT; break; } else lstcon = lstcon->NEXT; } if (NULL == lstcon) ringerreur(ERR_NOCONPH , con, firstfig); lst = lst->NEXT; } if (mode_debug) printf("LISTE DES CONNECTEURS EST OUEST modele de reference\n"); lst = (*lst_conestouest); while (NULL != lst) { con = (phcon_list * ) lst->DATA; if (mode_debug) printf("con %s YCON %ld width %ld INDEX %ld face %c\n", con->NAME, con->YCON, con->WIDTH, con->INDEX, con->ORIENT); lst = lst->NEXT; } } else { figcour = (phfig_list * ) liste_plotsph->DATA; lstcon = figcour->PHCON; while (NULL != lstcon) { if (mode_debug) printf("PADCOUR lstcon plot %s ycon %ld width %ld index %ld\n", lstcon->NAME, (lstcon->YCON - figcour->YAB1) , lstcon->WIDTH, lstcon->INDEX); if (('W' == lstcon->ORIENT) || ('E' == lstcon->ORIENT)) { if ('W' == lstcon->ORIENT) cptouestcour++; else cptestcour++; lst = (*lst_conestouest); while (NULL != lst) { con = (phcon_list * ) lst->DATA; if (mode_debug) printf("\tREFERENCEcon plot %s ycon %ld width %ld index %ld\n", con->NAME, (con->YCON - firstfig->YAB1), con->WIDTH, con->INDEX); if ((con->ORIENT == lstcon->ORIENT) && (con->NAME == lstcon->NAME) && ((con->YCON - firstfig->YAB1) == (lstcon->YCON - figcour->YAB1)) && (con->WIDTH == lstcon->WIDTH)) { lstcon->INDEX = con->INDEX; break; } else lst = lst->NEXT; } if (NULL == lst) ringerreur(ERR_NOCONPH , lstcon, figcour); } lstcon = lstcon->NEXT; } if ((cptest != cptestcour) || (cptouest != cptouestcour)) ringerreur(ERR_NBCONESTOUEST , figcour, firstfig); } }
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 input_list* unflatten_area(input_list *entry, int entry_number) { input_list *pred = NULL, *input, *new_input; chain_list* abl; cell_list* cell; note_list* note, *all_note=NULL, *best_note; int cell_source_positiv, neg_cell_source_positiv; /*flag*/ if (!entry) { fprintf(stderr,"unflatten_area: no input\n"); exit(1); } /*test all the simple logic library*/ for (cell=getcell_oper_lib(); cell; cell=cell->NEXT) { all_note=eval_note(all_note, cell, entry, entry_number); } /*no result pattern, impossible to map, signal it to caller function*/ if (!all_note) return entry; /*take the best for a positiv and negativ results*/ best_note=all_note; best_note->AVERAGE_COST=(best_note->COST+best_note->NEG_COST)/2; for (note=all_note->NEXT; note; note=note->NEXT) { note->AVERAGE_COST=(note->COST+note->NEG_COST)/2; if (note->AVERAGE_COST<best_note->AVERAGE_COST) best_note=note; else if (note->AVERAGE_COST==best_note->AVERAGE_COST && note->ARITY>best_note->ARITY) best_note=note; else if (note->AVERAGE_COST==best_note->AVERAGE_COST && note->ARITY==best_note->ARITY && note->DELAY+note->NEG_DELAY<best_note->DELAY+best_note->NEG_DELAY) best_note=note; } /*one of those cells are missing, impossible to unflat*/ if (!best_note->CELL || !best_note->NEG_CELL) { fprintf(stderr, "unflatten_area: opposite cell of %s is missing (%d inputs)\n", best_note->CELL?best_note->CELL->NAME:best_note->NEG_CELL->NAME, entry_number); exit(1); } /*build new input*/ new_input=newinput(); new_input->DELAY=best_note->DELAY; new_input->NEG_DELAY=best_note->NEG_DELAY; new_input->R=best_note->R; new_input->NEG_R=best_note->NEG_R; new_input->ABL=createabloper(ABL_OPER(best_note->CELL->ABL)); new_input->NEG_ABL=createabloper(ABL_OPER(best_note->NEG_CELL->ABL)); cell_source_positiv=is_source_positiv(ABL_OPER(best_note->CELL->ABL)); neg_cell_source_positiv=is_source_positiv( ABL_OPER(best_note->NEG_CELL->ABL)); /*put operands*/ for (input=entry; input; input=input->NEXT) { if (best_note->ARITY==0) break; best_note->ARITY--; /*positiv*/ if (cell_source_positiv) { abl=input->ABL; input->ABL=NULL; /* protect from freeinput() */ } else { abl=input->NEG_ABL; input->NEG_ABL=NULL; /* protect from freeinput() */ } ABL_CDR(new_input->ABL)=addchain(ABL_CDR(new_input->ABL),abl); /*opposite*/ if (neg_cell_source_positiv) { if (input->ABL) abl=input->ABL; else abl=dupablexpr(abl); /*already used above*/ input->ABL=NULL; /* protect from freeinput() */ } else { if (input->NEG_ABL) abl=input->NEG_ABL; else abl=dupablexpr(abl); /*already used above*/ input->NEG_ABL=NULL; /* protect from freeinput() */ } ABL_CDR(new_input->NEG_ABL)=addchain(ABL_CDR(new_input->NEG_ABL),abl); pred=input; } pred->NEXT=NULL; freeinput(entry); freenote(all_note); return sort_input(input,new_input); /*return a sort list*/ }