/* * This file is part of the Alliance CAD System * Copyright (C) Laboratoire LIP6 - Département ASIM * Universite Pierre et Marie Curie * * Home page : http://www-asim.lip6.fr/alliance/ * E-mail : mailto:alliance-users@asim.lip6.fr * * This progam is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * Alliance VLSI CAD System is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with the GNU C Library; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Tool : LooN - Light optimizing on Nets * Author : Francois Donnet */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lon_lax_param.h" #include "lon_signal_utils.h" #include "lon_signal_netlist.h" #include "lon_signal_critical.h" #include "lon_optim_capa.h" #include "lon_lib_utils.h" #include "lon_lax_param.h" #include "lon_xsch_driver.h" #include "lon_lib_reader.h" #include "lon_optim_stats.h" #ifndef LOON #define LOON "loon" #endif #define USAGE \ "usage: "LOON" []\n" /*usage with options*/ #define OPT_USAGE USAGE \ " "LOON" -h\n"\ " "LOON" -o \n"\ " "LOON" [-l ] [-x ] [-m ]\n" #define HELP_USAGE OPT_USAGE "\n"\ "\t-h Displays this help page.\n"\ "\t-o Overwrites with new netlist.\n"\ "\t-m Optimization mode number. Area(0) to delay(4).\n"\ "\t-x XSC color mode. Critical path(0) or delay gradient(1).\n"\ "\t VST input file name.\n"\ "\t VST output file name.\n"\ "\t-l LAX parameter file name. See lax(1) for more info.\n" /*options*/ #define LAX_FILE 'l' #define HELP_MODE 'h' #define OPTIM_MODE 'm' #define XSCH_MODE 'x' #define OVERWRITE_MODE 'o' /*options variables*/ extern char *optarg; static int verbose_mode=0, optim_mode=DEFAULT_OPTIM, xsch_mode=XSCH_CRITICAL_PATH, overwrite_mode=0; static char *input_file=NULL, *output_file=NULL, *lax_file=NULL, *xsch_file=NULL; static char *mbk_target_lib=NULL, *mbk_in_lo=NULL, *mbk_out_lo=NULL; /******************************************************************************/ /* set variables to values of command line */ /******************************************************************************/ static void set_param(int argc, char* argv[]) { int i; #if 0 /*incompatibilite entre Linux et Solaris */ char opt; /*options*/ while ((opt=getopt (argc, argv,"-l:m:x:ho")) != EOF) { switch (opt) { case OVERWRITE_MODE: overwrite_mode=1; break; case OPTIM_MODE: if (strlen(optarg)==1 && isdigit((int) optarg[0])) { optim_mode=optarg[0]-'0'; if (optim_mode<=OPTIM_DELAY4) break; } fprintf(stderr,OPT_USAGE "\n"); autexit(1); case XSCH_MODE: if (strlen(optarg)==1 && isdigit((int) optarg[0])) { xsch_mode=optarg[0]-'0'; if (xsch_mode<=XSCH_GRADIENT) break; } fprintf(stderr,OPT_USAGE "\n"); autexit(1); case LAX_FILE: if (!lax_file) {lax_file=optarg; break;} fprintf(stderr,OPT_USAGE "\n"); autexit(1); case 1 : /*all the other parameters without options (Linux only)*/ if (!input_file || input_file==argv[i]) {input_file=optarg; break;} if (!output_file || output_file==argv[i]) {output_file=optarg; break;} if (!lax_file || lax_file==argv[i]) {lax_file=optarg; break;} fprintf(stderr,OPT_USAGE "\n"); autexit(1); case HELP_MODE: fprintf(stdout,HELP_USAGE "\n"); autexit(0); case '?': default: fprintf(stderr,OPT_USAGE "\n"); autexit(1); } } #endif /*verify for Sun and Solaris. getopt() isn't the same than Linux_elf */ for (i=1; i extension\n"); autexit(1); } mbk_out_lo=mbkgetenv ("MBK_OUT_LO"); if (mbk_out_lo) fprintf(stdout,"\tMBK_OUT_LO\t: %s\n",mbk_out_lo); else { fprintf(stderr, "Environment Error: no 'MBK_OUT_LO' defined for extension\n"); autexit(1); } /*if no library defined*/ mbk_target_lib=mbkgetenv ("MBK_TARGET_LIB"); if (mbk_target_lib) fprintf(stdout,"\tMBK_TARGET_LIB\t: %s\n",mbk_target_lib); else { fprintf(stderr, "Environment Error: no 'MBK_TARGET_LIB' defined for cells directory\n"); autexit(1); } /*coherence in options*/ if (!input_file) { fprintf(stderr,OPT_USAGE "\n"); autexit(1); } if (!output_file) { if (overwrite_mode) output_file=input_file; else { fprintf(stderr,OPT_USAGE "\n"); autexit(1); } } if (!strcmp(output_file,input_file) && !strcmp(mbk_in_lo,mbk_out_lo) && !overwrite_mode) { fprintf(stderr," must be different from \n"); fprintf(stderr,OPT_USAGE "\n"); autexit(1); } /*take default values*/ xsch_file=output_file; verbose_mode=1; } /******************************************************************************/ /* main LOON */ /******************************************************************************/ extern int main (int argc, char* argv[]) { lofig_list *lofig; ptype_list *long_path=NULL; /*init*/ mbkenv(); /*mbk*/ autenv(); /*hash table*/ ablenv(); /*abl*/ bddenv(); /*for vhdlloadbefig() in library reader*/ alliancebanner_with_authors("LooN", VERSION " [2003/12/07]", "Local optimization on Nets", "2000", ALLIANCE_VERSION, "François Donnet"); /*set options*/ set_param(argc,argv); /*clear*/ fprintf(stdout,"\n"); /*read lax parameter first*/ if (lax_file) { fprintf(stdout,"Reading parameter file '%s.lax'...\n",lax_file); parsefilelax(lax_file); } else { fprintf(stdout,"Reading default parameter...\n"); defaultlax(optim_mode); } switch (getoptimlax()) { case OPTIM_DELAY0: fprintf(stdout,"100%% area optimization\n"); break; case OPTIM_DELAY1: fprintf(stdout,"75%% area - 25%% delay optimization\n"); break; case OPTIM_DELAY2: fprintf(stdout,"50%% area - 50%% delay optimization\n"); break; case OPTIM_DELAY3: fprintf(stdout,"25%% area - 75%% delay optimization\n"); break; case OPTIM_DELAY4: fprintf(stdout,"100%% delay optimization\n"); break; default: fprintf(stderr,"LAX: Optimization mode greater than 4\n"); autexit(1); } /*read vst*/ fprintf(stdout,"Reading file '%s.%s'...\n",input_file,mbk_in_lo); lofig=getlofig(input_file, 'A'/*all the figure*/); if (!lofig) { fprintf(stderr,"Cannot find '%s.%s'\n",input_file,mbk_in_lo); autexit(1); } /*flatten all instance at cells level*/ rflattenlofig(lofig, YES, YES); /*check coherence between LAX and lofig*/ if (lax_file) { fprintf(stdout,"Controlling file '%s.lax'...\n",lax_file); if (!coherencelaxlofig(lofig)) autexit(1); } /*read cell library*/ fprintf(stdout,"Reading lib '%s'...\n",mbk_target_lib); library_reader(mbk_target_lib); /*set signal properties*/ fprintf(stdout,"Capacitances on file '%s.%s'...\n",input_file,mbk_in_lo); if (!lofig->LOINS || !lofig->LOSIG) { fprintf(stderr,"Figure '%s' is empty!\n",lofig->NAME); autexit(1); } /*prepare source*/ lofigchain(lofig); set_circuit_capacitance(lofig); fprintf(stdout,"Delays on file '%s.%s'...",input_file,mbk_in_lo); fflush(stdout); set_circuit_delay(lofig); fprintf(stdout,"%ld ps\n",(long) critical_delay(lofig)); /*eval area*/ if (verbose_mode) { ptype_list* ptype, *ptype2, *old_percentage, *old_model; fprintf(stdout,"Area on file '%s.%s'...",input_file,mbk_in_lo); fflush(stdout); old_model=count_instance(lofig); old_percentage=percent_instance(old_model); fprintf(stdout,"%ld lamda² (with over-cell routing)\n",getarea(lofig)); /*Details of use*/ if (!old_model) fprintf(stdout,"No instance...\n"); else { fprintf(stdout,"Details...\n"); ptype2=old_percentage; for (ptype=old_model; ptype; ptype=ptype->NEXT) { fprintf(stdout,"\t%s: %ld (%ld%%)\n",(char*)ptype->DATA, ptype->TYPE,ptype2->TYPE); ptype2=ptype2->NEXT; } fprintf(stdout,"\tTotal: %ld\n",getnum_ins(lofig)); } freeptype(old_model); freeptype(old_percentage); fprintf(stdout,"Worst RC on file '%s.%s'...",input_file,mbk_in_lo); fflush(stdout); fprintf(stdout,"%ld ps\n",(long) getmaxRC(lofig)); } /*inserting buffer on critical path*/ if (getoptimlax()>=OPTIM_DELAY2) { int buffers; fprintf(stdout,"Inserting buffers on critical path for file '%s.%s'...", output_file,mbk_out_lo); fflush(stdout); buffers=insert_buffer_critical_path(lofig,getoptimlax()); if (buffers==0) fprintf(stdout,"None inserted\n"); else if (buffers==1) fprintf(stdout,"%d buffer inserted -> %ld ps\n", buffers,(long) critical_delay(lofig)); else fprintf(stdout,"%d buffers inserted -> %ld ps\n", buffers,(long) critical_delay(lofig)); } /*improve RC*/ fprintf(stdout,"Improving RC on critical path for file '%s.%s'...", output_file,mbk_out_lo); fflush(stdout); improve_capa_critical_path(lofig,getoptimlax()); fprintf(stdout,"%ld ps\n",(long) critical_delay(lofig)); /*global optimization*/ fprintf(stdout,"Improving all RC for file '%s.%s'...\n", output_file,mbk_out_lo); fprintf(stdout,"Worst RC on file '%s.%s'...",output_file,mbk_out_lo); fflush(stdout); fprintf(stdout,"%ld ps\n",(long) getmaxRC(lofig)); if (verbose_mode) { ptype_list* ptype, *ptype2, *new_percentage, *new_model; losig_list* losig; locon_list* locon; chain_list* lofigchain; loins_list* loins; /*eval area*/ fprintf(stdout,"Area on file '%s.%s'...",output_file,mbk_out_lo); fflush(stdout); new_model=count_instance(lofig); new_percentage=percent_instance(new_model); fprintf(stdout,"%ld lamda² (with over-cell routing)\n",getarea(lofig)); /*Details of use*/ if (!new_model) fprintf(stdout,"No instance...\n"); else { fprintf(stdout,"Details...\n"); ptype2=new_percentage; for (ptype=new_model; ptype; ptype=ptype->NEXT) { fprintf(stdout,"\t%s: %ld (%ld%%)\n",(char*)ptype->DATA, ptype->TYPE,ptype2->TYPE); ptype2=ptype2->NEXT; } fprintf(stdout,"\tTotal: %ld\n",getnum_ins(lofig)); } freeptype(new_model); freeptype(new_percentage); /*get list of signal in critical path*/ long_path=critical_path_without_clock(lofig); if (long_path) { losig=long_path->DATA; if (!losig->NAMECHAIN) { fprintf(stderr,"main: no name on signal\n"); autexit(1); } fprintf(stdout,"Critical path (no warranty)...%ld ps from '%s' to ", (long) critical_delay(lofig),(char*) losig->NAMECHAIN->DATA); fflush(stdout); /*seek last*/ for (ptype=long_path; ptype->NEXT; ptype=ptype->NEXT) ; losig=(losig_list*) ptype->DATA; if (!losig->NAMECHAIN) { fprintf(stderr,"main: no name on signal\n"); autexit(1); } if (losig->TYPE==EXTERNAL) { fprintf(stdout,"'%s'\n",(char*) losig->NAMECHAIN->DATA); } else { /*it is a register entry, search name of the register*/ ptype=getptype(losig->USER,LOFIGCHAIN); for (lofigchain=ptype->DATA; lofigchain; lofigchain=lofigchain->NEXT) { locon=lofigchain->DATA; if (locon->DIRECTION==IN) { loins=locon->ROOT; fprintf(stdout,"'%s'\n", loins->INSNAME); break; } } } } } /*saving file*/ if (output_file) { fprintf(stdout,"Saving file '%s.%s'...\n",output_file,mbk_out_lo); lofig->NAME=output_file; savelofig(lofig); /*change la lofigchain en mode .al*/ lofigchain(lofig); } /*colors and weight informations for xsch alliance displayer*/ if (xsch_file) { FILE* xsch_stream; ptype_list* ptype; char* signame; losig_list* losig; switch (xsch_mode) { case XSCH_GRADIENT: fprintf(stdout, "Saving delay gradient in xsch color file '%s.xsc'...\n",xsch_file); break; case XSCH_CRITICAL_PATH: default: fprintf(stdout, "Saving critical path in xsch color file '%s.xsc'...\n",xsch_file); } xsch_stream=mbkfopen(xsch_file,"xsc",WRITE_TEXT); if (!xsch_stream){ fprintf(stderr,"Cannot save file %s.xsc\n",xsch_file); autexit(1); } /*replace losig by names*/ for (ptype=long_path; ptype; ptype=ptype->NEXT) { losig=(losig_list*) ptype->DATA; signame=losig->NAMECHAIN->DATA; ptype->DATA=signame; } save_xsch(xsch_stream,lofig,long_path,xsch_mode); fclose(xsch_stream); } fprintf(stdout,"End of %s...\n\n",LOON); return(0); }