int main(int argc, char** argv) { std::set_new_handler(MemoryExhausted); ProgramConfig flags; UNIQUE_PTR<Config> config; UNIQUE_PTR<MGSystem> sys; UNIQUE_PTR<Monitor> mo; UNIQUE_PTR<Communicator> comm; //// // Early initialization. // Argument parsing, no simulation yet. try { // Parse command line arguments argp_parse(&argp, argc, argv, 0, 0, &flags); } catch (const exception& e) { PrintException(NULL, cerr, e); return 1; } if (flags.m_interactive) { // Interactive mode: print name & version first clog << argp_program_version << endl << endl; // Then print also command name & arguments clog << "Command line:"; for (int i = 0; i < argc; ++i) clog << ' ' << argv[i]; char buf[MAXPATHLEN]; getcwd(buf, MAXPATHLEN); clog << endl << "Current working directory: " << buf << endl; } // Convert the remaining m_regs to an override if (!flags.m_regs.empty()) { ostringstream s; for (size_t i = 0; i < flags.m_regs.size(); ++i) { if (i) s << ','; s << flags.m_regs[i]; } flags.m_overrides.append("CmdLineRegs", s.str()); } // Convert the extra devices created with -L to an override if (!flags.m_extradevs.empty()) { string n; for (size_t i = 0; i < flags.m_extradevs.size(); ++i) { if (i > 0) n += ','; n += flags.m_extradevs[i]; } flags.m_overrides.append("CmdLineFileDevs", n); } if (flags.m_quiet) { // Silence the ROM loads. flags.m_overrides.append("*.ROMVerboseLoad", "false"); } //// // Load the simulation configuration. // Process -c, group with overrides and argv. try { // Read configuration from file ConfigMap base_config; ConfigParser parser(base_config); try { parser(read_file(flags.m_configFile)); } catch (runtime_error& e) { throw runtime_error("Error reading configuration file: " + flags.m_configFile + "\n" + e.what()); } config.reset(new Config(base_config, flags.m_overrides, flags.m_argv)); } catch (const exception& e) { PrintException(NULL, cerr, e); return 1; } //// // Initialize the random seed. // We place it in the configuration, so that dumpConfiguration below // can print it too (for reproducability). try { (void)config->getValue<string>("RandomSeed"); } catch (const exception& e) { // Not in configuration(yet) char s[20]; snprintf(s, 20, "%u", (unsigned)time(NULL)); flags.m_overrides.append("RandomSeed", s); } { unsigned seed = config->getValue<unsigned>("RandomSeed"); clog << "### random seed: " << seed << endl; srand(seed); } if (flags.m_dumpconf) { // Printing the configuration if requested. We need to // do/check this early, in case constructing the system // (below) fails. clog << "### simulator version: " PACKAGE_VERSION << endl; config->dumpConfiguration(clog, flags.m_configFile); } //// // Construct the simulator. // This instantiates all the components, in the initial (stopped) state. // It also populates the "config" object with a cache of all // values effectively looked up by the instantiated components. try { // Create the system sys.reset(new MGSystem(*config, !flags.m_interactive)); } catch (const exception& e) { PrintException(NULL, cerr, e); return 1; } if (flags.m_dumpcache) { // Dump the configuration cache if requested. config->dumpConfigurationCache(clog); } if (flags.m_dumpvars) { // Dump the list of monitoring variables if requested. clog << "### begin monitor variables" << endl; ListSampleVariables(clog); clog << "### end monitor variables" << endl; } if (flags.m_areaTech > 0) { // Dump the area estimation information if requested. clog << "### begin area information" << endl; #ifdef ENABLE_CACTI sys->DumpArea(cout, flags.m_areaTech); #else clog << "# Warning: CACTI not enabled; reconfigure with --enable-cacti" << endl; #endif clog << "### end area information" << endl; } if (flags.m_dumptopo) { // Dump the component topology diagram if requested. ofstream of(flags.m_topofile.c_str(), ios::out); config->dumpComponentGraph(of, flags.m_dumpnodeprops, flags.m_dumpedgeprops); of.close(); } if (flags.m_earlyquit) // At this point the simulation is ready and we have dumped // everything requested. If the user requested to not do anything, // we can just stop here. return 0; // Otherwise, the simulation should start. CommandLineReader clr; comm.reset(new Communicator(*sys, &clr, flags.m_visual, flags.m_quiet)); //// // Start the simulation. // First construct the monitor thread, if enabled. string mo_mdfile = config->getValueOrDefault<string>("MonitorMetadataFile", "mgtrace.md"); string mo_tfile = config->getValueOrDefault<string>("MonitorTraceFile", "mgtrace.out"); mo.reset(new Monitor(*sys, flags.m_enableMonitor, mo_mdfile, flags.m_earlyquit ? "" : mo_tfile, !flags.m_interactive)); // Simulation proper. // Rules: // - if interactive, then do not automatically start the simulation. // - if interactive at start, always remain interactive. // - if not interactive at start and the simulation stops abnormally, then become interactive unless -t is specified. // - upon becoming interative because of an exception, print the exception. // - always print statistics at termination if not quiet. // - always print final variables at termination. bool interactive = flags.m_interactive; try { if (!interactive) { // Non-interactive: automatically start and run until simulation terminates. try { mo->start(); StepSystem(*sys, INFINITE_CYCLES); mo->stop(); } catch (const exception& e) { mo->stop(); if (flags.m_terminate) { // Re-throw to terminate. throw; } // else // Print the exception and become interactive. PrintException(sys.get(), cerr, e); interactive = true; } } if (interactive) { // Command loop cout << endl; cli_context ctx = { clr, *sys, *mo }; while (HandleCommandLine(ctx) == false) /* just loop */; } } catch (const exception& e) { const ProgramTerminationException *ex = dynamic_cast<const ProgramTerminationException*>(&e); if (!flags.m_quiet || ex == NULL) // Print exception. PrintException(sys.get(), cerr, e); // Print statistics & final variables. AtEnd(*sys, flags); if (ex != NULL) { // The program is telling us how to terminate. Do it. if (ex->TerminateWithAbort()) abort(); else return ex->GetExitCode(); } else // No more information, simply terminate with error. return 1; } // Print statistics & final variables. AtEnd(*sys, flags); return 0; }
int main(int argc, char** argv) { struct timeval tv1, tv2, tv3; struct rusage ru1, ru2, ru3; gettimeofday(&tv1, 0); getrusage(RUSAGE_SELF, &ru1); srand(time(NULL)); ProgramConfig flags; UNIQUE_PTR<Config> config; UNIQUE_PTR<MGSystem> sys; #ifdef ENABLE_MONITOR UNIQUE_PTR<Monitor> mo; #endif //// // Early initialization. // Argument parsing, no simulation yet. try { // Parse command line arguments argp_parse(&argp, argc, argv, 0, 0, &flags); } catch (const exception& e) { PrintException(NULL, cerr, e); return 1; } if (flags.m_interactive) { // Interactive mode: print name & version first clog << argp_program_version << endl; } // Convert the remaining m_regs to an override if (!flags.m_regs.empty()) { ostringstream s; for (size_t i = 0; i < flags.m_regs.size(); ++i) { if (i) s << ','; s << flags.m_regs[i]; } flags.m_overrides.append("CmdLineRegs", s.str()); } // Convert the extra devices created with -L to an override if (!flags.m_extradevs.empty()) { string n; for (size_t i = 0; i < flags.m_extradevs.size(); ++i) { if (i > 0) n += ','; n += flags.m_extradevs[i]; } flags.m_overrides.append("CmdLineFileDevs", n); } if (flags.m_quiet) { // Silence the ROM loads. flags.m_overrides.append("*.ROMVerboseLoad", "false"); } //// // Load the simulation configuration. // Process -c, group with overrides and argv. try { // Read configuration from file config.reset(new Config(flags.m_configFile, flags.m_overrides, flags.m_argv)); } catch (const exception& e) { PrintException(NULL, cerr, e); return 1; } if (flags.m_dumpconf) { // Printing the configuration if requested. We need to // do/check this early, in case constructing the system // (below) fails. clog << "### simulator version: " PACKAGE_VERSION << endl; config->dumpConfiguration(clog, flags.m_configFile); } //// // Construct the simulator. // This instantiates all the components, in the initial (stopped) state. // It also populates the "config" object with a cache of all // values effectively looked up by the instantiated components. try { // Create the system sys.reset(new MGSystem(*config, !flags.m_interactive)); } catch (const exception& e) { PrintException(NULL, cerr, e); return 1; } if (flags.m_dumpcache) { // Dump the configuration cache if requested. config->dumpConfigurationCache(clog); } if (flags.m_dumpvars) { // Dump the list of monitoring variables if requested. clog << "### begin monitor variables" << endl; ListSampleVariables(clog); clog << "### end monitor variables" << endl; } if (flags.m_areaTech > 0) { // Dump the area estimation information if requested. clog << "### begin area information" << endl; #ifdef ENABLE_CACTI sys->DumpArea(cout, flags.m_areaTech); #else clog << "# Warning: CACTI not enabled; reconfigure with --enable-cacti" << endl; #endif clog << "### end area information" << endl; } if (flags.m_dumptopo) { // Dump the component topology diagram if requested. ofstream of(flags.m_topofile.c_str(), ios::out); config->dumpComponentGraph(of, flags.m_dumpnodeprops, flags.m_dumpedgeprops); of.close(); } if (flags.m_earlyquit) // At this point the simulation is ready and we have dumped // everything requested. If the user requested to not do anything, // we can just stop here. return 0; // Otherwise, the simulation should start. //// // Start the simulation. // First construct the monitor thread, if enabled. #ifdef ENABLE_MONITOR string mo_mdfile = config->getValueOrDefault<string>("MonitorMetadataFile", "mgtrace.md"); string mo_tfile = config->getValueOrDefault<string>("MonitorTraceFile", "mgtrace.out"); mo.reset(new Monitor(*sys, flags.m_enableMonitor, mo_mdfile, flags.m_earlyquit ? "" : mo_tfile, !flags.m_interactive)); #endif // Simulation proper. // Rules: // - if interactive, then do not automatically start the simulation. // - if interactive at start, always remain interactive. // - if not interactive at start and the simulation stops abnormally, then become interactive unless -t is specified. // - upon becoming interative because of an exception, print the exception. // - always print statistics at termination if not quiet. // - always print final variables at termination. gettimeofday(&tv2, 0); getrusage(RUSAGE_SELF, &ru2); bool interactive = flags.m_interactive; try { if (!interactive) { // Non-interactive: automatically start and run until simulation terminates. try { #ifdef ENABLE_MONITOR mo->start(); #endif StepSystem(*sys, INFINITE_CYCLES); #ifdef ENABLE_MONITOR mo->stop(); #endif } catch (const exception& e) { #ifdef ENABLE_MONITOR mo->stop(); #endif if (flags.m_terminate) { // Re-throw to terminate. throw; } // else // Print the exception and become interactive. PrintException(sys.get(), cerr, e); interactive = true; } } if (interactive) { // Command loop cout << endl; CommandLineReader clr; cli_context ctx = { clr, *sys #ifdef ENABLE_MONITOR , *mo #endif }; while (HandleCommandLine(ctx) == false) /* just loop */; } } catch (const exception& e) { const ProgramTerminationException *ex = dynamic_cast<const ProgramTerminationException*>(&e); if (!flags.m_quiet || ex == NULL) // Print exception. PrintException(sys.get(), cerr, e); gettimeofday(&tv3, 0); getrusage(RUSAGE_SELF, &ru3); std::cerr << "Init time wallclock: " << tv2.tv_sec - tv1.tv_sec + tv2.tv_usec*0.000001 - tv1.tv_usec*0.000001 << std::endl << "Init time self: " << ru2.ru_utime.tv_sec - ru1.ru_utime.tv_sec + ru2.ru_utime.tv_usec*0.000001 - ru1.ru_utime.tv_usec*0.000001 << std::endl << "Sim time wallclock: " << tv3.tv_sec - tv2.tv_sec + tv3.tv_usec*0.000001 - tv2.tv_usec*0.000001 << std::endl << "Sim time self: " << ru3.ru_utime.tv_sec - ru2.ru_utime.tv_sec + ru3.ru_utime.tv_usec*0.000001 - ru2.ru_utime.tv_usec*0.000001 << std::endl ; // Print statistics & final variables. AtEnd(*sys, flags); if (ex != NULL) { // The program is telling us how to terminate. Do it. if (ex->TerminateWithAbort()) abort(); else return ex->GetExitCode(); } else // No more information, simply terminate with error. return 1; } gettimeofday(&tv3, 0); getrusage(RUSAGE_SELF, &ru3); std::cerr << "Init time wallclock: " << tv2.tv_sec - tv1.tv_sec + tv2.tv_usec*0.000001 - tv1.tv_usec*0.000001 << std::endl << "Init time self: " << ru2.ru_utime.tv_sec - ru1.ru_utime.tv_sec + ru2.ru_utime.tv_usec*0.000001 - ru1.ru_utime.tv_usec*0.000001 << std::endl << "Sim time wallclock: " << tv3.tv_sec - tv2.tv_sec + tv3.tv_usec*0.000001 - tv2.tv_usec*0.000001 << std::endl << "Sim time self: " << ru3.ru_utime.tv_sec - ru2.ru_utime.tv_sec + ru3.ru_utime.tv_usec*0.000001 - ru2.ru_utime.tv_usec*0.000001 << std::endl ; // Print statistics & final variables. AtEnd(*sys, flags); return 0; }