/**************************************************************************** Copyright (C) 1987-2005 by Jeffery P. Hansen This program 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. This program 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 this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ****************************************************************************/ #include #include #include #include #include #include #include #include "gsim.h" #include "ycmalloc.h" extern SHash module_table; int yyparse(); void BeginVR(); #ifndef yyrestart void yyrestart(FILE*); #endif char *topModule = 0; int do_prompt = 0; int do_commandEcho = 0; int errCount = 0; int total_area = 0; int total_staticPower = 0; char *base_directory = 0; /* * These undoable object functions are only used in the main tkgate code, but * since they are used in the common hash table code we provide stubs here for * the hash table code to use. */ void *ob_malloc(int s,char *x) { return malloc(s); } void *ob_calloc(int n,int s,char *x) { return calloc(n,s); } void ob_free(void *p) { free(p); } char *ob_strdup(char *s) { return strdup(s); } void ob_set_type(void *o,char *n) {} void ob_touch(void *o) {} void sendMsg(char *fmt,...) { va_list ap; char buf[1024],*p; int c,l; va_start(ap,fmt); vsprintf(buf,fmt,ap); va_end(ap); l = strlen(buf); strcpy(buf+l,"\n"); l++; p = buf; while (l > 0) { c = write(1,p,l); if (c > 0) { p += c; l -= c; } if (l != 0) { fd_set ws; FD_ZERO(&ws); FD_SET(1,&ws); select(2,0,&ws,0,0); } } } void errorGate(char *gat,char *fmt,...) { char buf[STRMAX],*p; va_list ap; errCount++; va_start(ap,fmt); p = buf + sprintf(buf,"error gate %s ",gat); vsprintf(p,fmt,ap); va_end(ap); sendMsg("%s",buf); } void errorNet(char *net,char *fmt,...) { char buf[STRMAX],*p; va_list ap; errCount++; va_start(ap,fmt); p = buf + sprintf(buf,"error net %s ",net); vsprintf(p,fmt,ap); va_end(ap); sendMsg("%s",buf); } void errorFile(char *fmt,...) { char buf[STRMAX],*p; va_list ap; errCount++; va_start(ap,fmt); p = buf + sprintf(buf,"error file "); vsprintf(p,fmt,ap); va_end(ap); sendMsg("%s",buf); } void error(char *fmt,...) { char buf[STRMAX],*p; va_list ap; errCount++; va_start(ap,fmt); p = buf + sprintf(buf,"simerror "); vsprintf(p,fmt,ap); va_end(ap); sendMsg("%s",buf); } /* * Open a file in the context of the current circuit. * If the first character of 'name' is '/', then the * file is opened "as is". Otherwise the following * path is searched: * * current directory * The base_directory spoecified by -B option * user's home directory (value of HOME) */ FILE *openInPath(const char *name) { char buf[STRMAX]; FILE *f; char *r; if ((f = fopen(name,"r"))) return f; if (*name == '/') return 0; if ((r = base_directory)) { strcpy(buf,r); if ((r = strrchr(buf,'/'))) { if (r != buf) { strcpy(r+1,name); if ((f = fopen(buf,"r"))) return f; } } } if ((r = getenv("HOME"))) { strcpy(buf,r); strcat(buf,"/"); strcat(buf,name); if ((f = fopen(buf,"r"))) return f; } return 0; } void waitForExit() { char buf[STRMAX]; sendMsg("error_exit"); for (;;) { if (!fgets(buf,STRMAX,stdout)) break; if (strncmp(buf,"exit",4) == 0) break; } exit(0); } static void usage() { errorFile("Usage: gsim [-t name][file]"); if (errCount) { waitForExit(); } } int VerilogLoad(char *name) { FILE *f; if (!(f = fopen(name,"r"))) { return -1; } ycFileName = name; ycLineNumber = 1; yc_setup(); BeginVR(); yyrestart(f); yc_pushpool(); yyparse(); yc_poppool(); fclose(f); return 0; } void InitTables() { SHash_init(&module_table); init_gates(); } int main(int argc,char *argv[]) { extern char *optarg; extern int optind; #if OPTRESET extern int optreset; #endif int c; int do_print = 0; int do_expand = 0; int do_test = 0; int do_analysisMode = 0; char *delay_file = 0; char *load_file = 0; char *p; sendMsg("comment GSim V2.2 - Digital Circuit Simulator"); sendMsg("comment %s",TKGATE_COPYRIGHT); while (argc > 0) { while ((c = getopt(argc,argv,"acepPt:lB:D:")) != EOF) { switch (c) { case 'a' : do_analysisMode = 1; break; case 'l' : do_test = 1; break; case 'P' : do_prompt = 1; break; case 'p' : do_print = 1; break; case 'e' : do_expand = 1; break; case 'c' : do_commandEcho = 1; break; case 'B' : base_directory = optarg; break; case 't' : topModule = optarg; break; case 'D' : delay_file = optarg; break; default : usage(); break; } } argc -= optind; argv += optind; #if OPTRESET optreset = 1; #endif optind = 0; if (argc > 0) { load_file = argv[0]; argc--; argv++; } } if (do_test) { char buf[1024]; while (fgets(buf,1024,stdin)) { if (do_commandEcho) printf(">>> %s",buf); testLogic(buf); } exit(0); } if (!load_file) { errorFile("No circuit."); waitForExit(); } if (!delay_file) { errorFile("No delay file."); waitForExit(); } for (p = strtok(delay_file,":");p;p = strtok(0,":")) { if (GDelayDef_readFile(p) < 0) errorFile("Can not open delay file '%s'.",delay_file); if (errCount) waitForExit(); } InitTables(); if (VerilogLoad(load_file) < 0) { errorFile("Can not open circuit file '%s'.",load_file); waitForExit(); } if (errCount) { waitForExit(); } if (!topModule) { errorFile("No top-level module."); exit(0); } if (do_print) { if (do_expand) { SModule *M = (SModule*) SHash_find(&module_table,topModule); if (!M) { errorFile("No module to print."); exit(0); } SModule_expand(M); SModule_finalize(M); SModule_print(M,stdout); } else { VerilogDump(); } } else { EvQueue Q; SModule *M; M = (SModule*) SHash_find(&module_table,topModule); if (!M) { errorFile("No module to simulate."); exit(0); } SModule_expand(M); SModule_finalize(M); SModule_check(M); if (errCount) { waitForExit(); } else { sendMsg("stats area=%d static_power=%d",total_area,total_staticPower); sendMsg("ok"); EvQueue_init(&Q,M); if (!do_analysisMode) SModule_init(M,&Q); EvQueue_mainEventLoop(&Q); } } return 0; }