2001-03-11 01:29:38 +01:00
|
|
|
/*
|
2007-12-02 17:47:06 +01:00
|
|
|
* Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com)
|
2001-03-11 01:29:38 +01:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "config.h"
|
|
|
|
|
# include "parse_misc.h"
|
|
|
|
|
# include "compile.h"
|
|
|
|
|
# include "schedule.h"
|
2001-03-16 02:44:34 +01:00
|
|
|
# include "vpi_priv.h"
|
2002-07-05 04:50:57 +02:00
|
|
|
# include "statistics.h"
|
2001-03-11 01:29:38 +01:00
|
|
|
# include <stdio.h>
|
2001-06-23 20:26:26 +02:00
|
|
|
# include <stdlib.h>
|
2001-07-16 20:40:19 +02:00
|
|
|
# include <string.h>
|
|
|
|
|
# include <unistd.h>
|
2001-10-20 03:03:42 +02:00
|
|
|
|
|
|
|
|
#if defined(HAVE_SYS_RESOURCE_H)
|
|
|
|
|
# include <sys/time.h>
|
|
|
|
|
# include <sys/resource.h>
|
|
|
|
|
# if defined(LINUX)
|
2004-10-04 03:10:51 +02:00
|
|
|
# include <asm/page.h>
|
2001-10-20 03:03:42 +02:00
|
|
|
# endif
|
|
|
|
|
#endif // defined(HAVE_SYS_RESOURCE_H)
|
|
|
|
|
|
2001-05-11 04:06:14 +02:00
|
|
|
#if defined(HAVE_GETOPT_H)
|
2001-03-11 01:29:38 +01:00
|
|
|
# include <getopt.h>
|
2001-05-11 04:06:14 +02:00
|
|
|
#endif
|
2001-03-11 01:29:38 +01:00
|
|
|
|
2001-07-30 04:44:05 +02:00
|
|
|
#if defined(__MINGW32__)
|
|
|
|
|
# include <windows.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2007-07-12 06:38:56 +02:00
|
|
|
ofstream debug_file;
|
|
|
|
|
|
2001-05-20 19:34:53 +02:00
|
|
|
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
|
|
|
|
|
extern "C" int getopt(int argc, char*argv[], const char*fmt);
|
|
|
|
|
extern "C" int optind;
|
|
|
|
|
extern "C" const char*optarg;
|
|
|
|
|
#endif
|
|
|
|
|
|
2006-04-27 07:04:59 +02:00
|
|
|
#if !defined(HAVE_LROUND)
|
|
|
|
|
/*
|
|
|
|
|
* If the system doesn't provide the lround function, then we provide
|
|
|
|
|
* it ourselves here. It is simply the nearest integer, rounded away
|
|
|
|
|
* from zero.
|
|
|
|
|
*/
|
2006-04-28 17:44:37 +02:00
|
|
|
# include <math.h>
|
2006-04-28 17:40:30 +02:00
|
|
|
extern "C" long int lround(double x)
|
2006-04-27 07:04:59 +02:00
|
|
|
{
|
|
|
|
|
if (x >= 0.0)
|
2006-04-28 17:44:37 +02:00
|
|
|
return (long)floor(x+0.5);
|
2006-04-27 07:04:59 +02:00
|
|
|
else
|
2006-04-28 17:44:37 +02:00
|
|
|
return (long)ceil(x-0.5);
|
2006-04-27 07:04:59 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-07-15 02:21:42 +02:00
|
|
|
bool verbose_flag = false;
|
|
|
|
|
|
2003-06-25 06:04:19 +02:00
|
|
|
static char log_buffer[4096];
|
2001-10-20 03:03:42 +02:00
|
|
|
|
|
|
|
|
#if defined(HAVE_SYS_RESOURCE_H)
|
|
|
|
|
static void my_getrusage(struct rusage *a)
|
2001-07-16 20:40:19 +02:00
|
|
|
{
|
2001-10-20 03:03:42 +02:00
|
|
|
getrusage(RUSAGE_SELF, a);
|
|
|
|
|
|
|
|
|
|
# if defined(LINUX)
|
|
|
|
|
{
|
|
|
|
|
FILE *statm;
|
|
|
|
|
unsigned siz, rss, shd;
|
2007-02-17 00:30:14 +01:00
|
|
|
long page_size = sysconf(_SC_PAGESIZE);
|
|
|
|
|
if (page_size==-1) page_size=0;
|
2001-10-20 03:03:42 +02:00
|
|
|
statm = fopen("/proc/self/statm", "r");
|
|
|
|
|
if (!statm) {
|
|
|
|
|
perror("/proc/self/statm");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (3<=fscanf(statm, "%u%u%u", &siz, &rss, &shd)) {
|
2007-02-17 00:30:14 +01:00
|
|
|
a->ru_maxrss = page_size * siz;
|
|
|
|
|
a->ru_idrss = page_size * rss;
|
|
|
|
|
a->ru_ixrss = page_size * shd;
|
2001-10-20 03:03:42 +02:00
|
|
|
}
|
|
|
|
|
fclose(statm);
|
|
|
|
|
}
|
|
|
|
|
# endif
|
|
|
|
|
}
|
2001-07-16 20:40:19 +02:00
|
|
|
|
2003-06-13 21:51:08 +02:00
|
|
|
static void print_rusage(struct rusage *a, struct rusage *b)
|
2001-10-20 03:03:42 +02:00
|
|
|
{
|
|
|
|
|
double delta = a->ru_utime.tv_sec
|
|
|
|
|
+ a->ru_utime.tv_usec/1E6
|
|
|
|
|
+ a->ru_stime.tv_sec
|
|
|
|
|
+ a->ru_stime.tv_usec/1E6
|
|
|
|
|
- b->ru_utime.tv_sec
|
|
|
|
|
- b->ru_utime.tv_usec/1E6
|
|
|
|
|
- b->ru_stime.tv_sec
|
|
|
|
|
- b->ru_stime.tv_usec/1E6
|
|
|
|
|
;
|
2001-07-16 20:40:19 +02:00
|
|
|
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1,
|
2001-10-20 03:03:42 +02:00
|
|
|
" ... %G seconds,"
|
|
|
|
|
" %.1f/%.1f/%.1f KBytes size/rss/shared\n",
|
|
|
|
|
delta,
|
|
|
|
|
a->ru_maxrss/1024.0,
|
|
|
|
|
(a->ru_idrss+a->ru_isrss)/1024.0,
|
|
|
|
|
a->ru_ixrss/1024.0 );
|
2001-07-16 20:40:19 +02:00
|
|
|
}
|
2001-10-20 03:03:42 +02:00
|
|
|
|
|
|
|
|
#else // ! defined(HAVE_SYS_RESOURCE_H)
|
|
|
|
|
|
2001-07-16 20:40:19 +02:00
|
|
|
// Provide dummies
|
2001-10-20 03:03:42 +02:00
|
|
|
struct rusage { int x; };
|
|
|
|
|
inline static void my_getrusage(struct rusage *) { }
|
2003-06-13 21:51:08 +02:00
|
|
|
inline static void print_rusage(struct rusage *, struct rusage *){};
|
2001-10-20 03:03:42 +02:00
|
|
|
|
|
|
|
|
#endif // ! defined(HAVE_SYS_RESOURCE_H)
|
2001-07-16 20:40:19 +02:00
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
|
2001-03-16 02:44:34 +01:00
|
|
|
unsigned module_cnt = 0;
|
|
|
|
|
const char*module_tab[64];
|
|
|
|
|
|
2001-07-16 20:40:19 +02:00
|
|
|
extern void vpi_mcd_init(FILE *log);
|
2001-06-12 05:53:10 +02:00
|
|
|
extern void vvp_vpi_init(void);
|
2001-03-18 05:35:18 +01:00
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
int main(int argc, char*argv[])
|
|
|
|
|
{
|
|
|
|
|
int opt;
|
|
|
|
|
unsigned flag_errors = 0;
|
|
|
|
|
const char*design_path = 0;
|
2001-10-20 03:03:42 +02:00
|
|
|
struct rusage cycles[3];
|
2001-07-30 04:44:05 +02:00
|
|
|
const char *logfile_name = 0x0;
|
2001-07-16 20:40:19 +02:00
|
|
|
FILE *logfile = 0x0;
|
2002-01-09 04:15:23 +01:00
|
|
|
extern void vpi_set_vlog_info(int, char**);
|
2001-03-11 01:29:38 +01:00
|
|
|
|
2001-07-26 05:13:51 +02:00
|
|
|
#ifdef __MINGW32__
|
|
|
|
|
/* In the Windows world, we get the first module path
|
|
|
|
|
component relative the location where the binary lives. */
|
|
|
|
|
{ char path[4096], *s;
|
|
|
|
|
GetModuleFileName(NULL,path,1024);
|
|
|
|
|
/* Get to the end. Search back twice for backslashes */
|
|
|
|
|
s = path + strlen(path);
|
|
|
|
|
while (*s != '\\') s--; s--;
|
2004-10-04 03:10:51 +02:00
|
|
|
while (*s != '\\') s--;
|
2001-07-26 05:13:51 +02:00
|
|
|
strcpy(s,"\\lib\\ivl");
|
|
|
|
|
vpip_module_path[0] = strdup(path);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-01-29 07:28:19 +01:00
|
|
|
while ((opt = getopt(argc, argv, "+hl:M:m:sv")) != EOF) switch (opt) {
|
2001-07-21 23:18:55 +02:00
|
|
|
case 'h':
|
|
|
|
|
fprintf(stderr,
|
2002-04-12 04:44:02 +02:00
|
|
|
"Usage: vvp [options] input-file [+plusargs...]\n"
|
2001-07-21 23:18:55 +02:00
|
|
|
"Options:\n"
|
2001-07-26 05:13:51 +02:00
|
|
|
" -h Print this help message.\n"
|
|
|
|
|
" -l file Logfile, '-' for <stderr>\n"
|
|
|
|
|
" -M path VPI module directory\n"
|
2003-01-19 00:55:35 +01:00
|
|
|
" -M - Clear VPI module path\n"
|
2001-07-26 05:13:51 +02:00
|
|
|
" -m module Load vpi module.\n"
|
2005-01-29 07:28:19 +01:00
|
|
|
" -s $stop right away.\n"
|
2001-07-26 05:13:51 +02:00
|
|
|
" -v Verbose progress messages.\n" );
|
2001-07-21 23:18:55 +02:00
|
|
|
exit(0);
|
2001-07-16 20:40:19 +02:00
|
|
|
case 'l':
|
|
|
|
|
logfile_name = optarg;
|
|
|
|
|
break;
|
2001-03-16 02:44:34 +01:00
|
|
|
case 'M':
|
2003-01-19 00:55:35 +01:00
|
|
|
if (strcmp(optarg,"-") == 0) {
|
|
|
|
|
vpip_module_path_cnt = 0;
|
|
|
|
|
vpip_module_path[0] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
vpip_module_path[vpip_module_path_cnt++] = optarg;
|
|
|
|
|
}
|
2001-03-16 02:44:34 +01:00
|
|
|
break;
|
|
|
|
|
case 'm':
|
|
|
|
|
module_tab[module_cnt++] = optarg;
|
|
|
|
|
break;
|
2005-01-29 07:28:19 +01:00
|
|
|
case 's':
|
|
|
|
|
schedule_stop(0);
|
|
|
|
|
break;
|
2001-07-16 20:40:19 +02:00
|
|
|
case 'v':
|
|
|
|
|
verbose_flag = true;
|
|
|
|
|
break;
|
2001-03-11 01:29:38 +01:00
|
|
|
default:
|
|
|
|
|
flag_errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flag_errors)
|
|
|
|
|
return flag_errors;
|
|
|
|
|
|
|
|
|
|
if (optind == argc) {
|
|
|
|
|
fprintf(stderr, "%s: no input file.\n", argv[0]);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2007-07-12 06:38:56 +02:00
|
|
|
/* If the VVP_DEBUG variable is set, then it contains the path
|
|
|
|
|
to the vvp debug file. Open it for output. */
|
|
|
|
|
|
|
|
|
|
if (char*path = getenv("VVP_DEBUG")) {
|
|
|
|
|
debug_file.open(path, ios_base::out);
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
design_path = argv[optind];
|
|
|
|
|
|
2001-03-18 05:35:18 +01:00
|
|
|
/* This is needed to get the MCD I/O routines ready for
|
|
|
|
|
anything. It is done early because it is plausible that the
|
|
|
|
|
compile might affect it, and it is cheap to do. */
|
|
|
|
|
|
2001-07-16 20:40:19 +02:00
|
|
|
if (logfile_name) {
|
|
|
|
|
if (!strcmp(logfile_name, "-"))
|
|
|
|
|
logfile = stderr;
|
2003-05-15 18:51:08 +02:00
|
|
|
else {
|
2001-07-16 20:40:19 +02:00
|
|
|
logfile = fopen(logfile_name, "w");
|
2003-05-15 18:51:08 +02:00
|
|
|
if (!logfile) {
|
|
|
|
|
perror(logfile_name);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
2003-06-25 06:04:19 +02:00
|
|
|
setvbuf(logfile, log_buffer, _IOLBF, sizeof(log_buffer));
|
2001-07-16 20:40:19 +02:00
|
|
|
}
|
|
|
|
|
}
|
2001-10-20 03:03:42 +02:00
|
|
|
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_init(logfile);
|
|
|
|
|
|
2001-07-16 20:40:19 +02:00
|
|
|
if (verbose_flag) {
|
2001-10-20 03:03:42 +02:00
|
|
|
my_getrusage(cycles+0);
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, "Compiling VVP ...\n");
|
2001-07-16 20:40:19 +02:00
|
|
|
}
|
2001-03-18 05:35:18 +01:00
|
|
|
|
2001-06-12 05:53:10 +02:00
|
|
|
vvp_vpi_init();
|
|
|
|
|
|
2002-04-12 04:44:02 +02:00
|
|
|
/* Make the extended arguments available to the simulation. */
|
|
|
|
|
vpi_set_vlog_info(argc-optind, argv+optind);
|
2002-01-09 04:15:23 +01:00
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
compile_init();
|
2001-07-26 05:13:51 +02:00
|
|
|
|
2001-03-23 03:40:22 +01:00
|
|
|
for (unsigned idx = 0 ; idx < module_cnt ; idx += 1)
|
2001-07-26 05:13:51 +02:00
|
|
|
vpip_load_module(module_tab[idx]);
|
|
|
|
|
|
2001-04-04 06:33:08 +02:00
|
|
|
if (int rc = compile_design(design_path))
|
|
|
|
|
return rc;
|
2001-03-11 01:29:38 +01:00
|
|
|
|
2001-07-16 20:40:19 +02:00
|
|
|
if (verbose_flag) {
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, "Compile cleanup...\n");
|
2001-07-16 20:40:19 +02:00
|
|
|
}
|
2002-03-01 06:43:14 +01:00
|
|
|
|
|
|
|
|
compile_cleanup();
|
|
|
|
|
|
2001-03-22 23:38:13 +01:00
|
|
|
if (compile_errors > 0) {
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, "%s: Program not runnable, %u errors.\n",
|
2001-03-22 23:38:13 +01:00
|
|
|
design_path, compile_errors);
|
|
|
|
|
return compile_errors;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-05 04:50:57 +02:00
|
|
|
if (verbose_flag) {
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, " ... %8lu functors\n", count_functors);
|
2007-12-02 17:47:06 +01:00
|
|
|
vpi_mcd_printf(1, " %8lu logic\n", count_functors_logic);
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, " %8lu bufif\n", count_functors_bufif);
|
|
|
|
|
vpi_mcd_printf(1, " %8lu resolv\n",count_functors_resolv);
|
2007-12-02 17:47:06 +01:00
|
|
|
vpi_mcd_printf(1, " %8lu signals\n", count_functors_sig);
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, " ... %8lu opcodes (%lu bytes)\n",
|
2002-09-18 05:34:07 +02:00
|
|
|
count_opcodes, (unsigned long)size_opcodes);
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, " ... %8lu nets\n", count_vpi_nets);
|
|
|
|
|
vpi_mcd_printf(1, " ... %8lu memories\n", count_vpi_memories);
|
|
|
|
|
vpi_mcd_printf(1, " ... %8lu scopes\n", count_vpi_scopes);
|
2002-07-05 04:50:57 +02:00
|
|
|
}
|
|
|
|
|
|
2002-03-01 06:43:14 +01:00
|
|
|
if (verbose_flag) {
|
|
|
|
|
my_getrusage(cycles+1);
|
2003-06-13 21:51:08 +02:00
|
|
|
print_rusage(cycles+1, cycles+0);
|
|
|
|
|
vpi_mcd_printf(1, "Running ...\n");
|
2002-03-01 06:43:14 +01:00
|
|
|
}
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2001-05-09 01:32:26 +02:00
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
schedule_simulate();
|
|
|
|
|
|
2001-07-16 20:40:19 +02:00
|
|
|
if (verbose_flag) {
|
2001-10-20 03:03:42 +02:00
|
|
|
my_getrusage(cycles+2);
|
2003-06-13 21:51:08 +02:00
|
|
|
print_rusage(cycles+2, cycles+1);
|
2003-01-07 00:57:26 +01:00
|
|
|
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, "Event counts: (event pool = %lu)\n",
|
2003-01-07 00:57:26 +01:00
|
|
|
count_event_pool);
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, " %8lu thread schedule events\n",
|
2003-01-07 00:57:26 +01:00
|
|
|
count_thread_events);
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, " %8lu propagation events\n",
|
2003-01-07 00:57:26 +01:00
|
|
|
count_prop_events);
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, " %8lu assign events\n",
|
2003-01-07 00:57:26 +01:00
|
|
|
count_assign_events);
|
2003-06-13 21:51:08 +02:00
|
|
|
vpi_mcd_printf(1, " %8lu other events\n",
|
2003-01-07 00:57:26 +01:00
|
|
|
count_gen_events);
|
2001-07-16 20:40:19 +02:00
|
|
|
}
|
|
|
|
|
|
2001-03-11 01:29:38 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|