Index: sid/component/config.in =================================================================== RCS file: /cvs/src/src/sid/component/config.in,v retrieving revision 1.5 diff -c -p -r1.5 config.in *** sid/component/config.in 11 Nov 2002 22:28:26 -0000 1.5 --- sid/component/config.in 30 May 2003 20:01:04 -0000 *************** *** 36,41 **** --- 36,47 ---- /* Define if you have the usleep function. */ #undef HAVE_USLEEP + /* Define if you have the vasprintf function. */ + #undef HAVE_VASPRINTF + + /* Define if you have the vsnprintf function. */ + #undef HAVE_VSNPRINTF + /* Define if you have the <../ucbinclude/sys/ioctl.h> header file. */ #undef HAVE____UCBINCLUDE_SYS_IOCTL_H *************** *** 101,106 **** --- 107,124 ---- /* Define if curses library is usable */ #undef HAVE_CURSES_LIBRARY + + /* Define if ISO C99 Features in use */ + #undef _ISOC99_SOURCE + + /* Define if GNU extensions in use */ + #undef _GNU_SOURCE + + /* Define if SVID extensions in use */ + #undef _SVID_SOURCE + + /* Define if SVID extensions in use */ + #undef _BSD_SOURCE /* Define if ftime(3) is declared via sys/timeb.h */ #undef HAVE_FTIME_DECL Index: sid/component/configure.in =================================================================== RCS file: /cvs/src/src/sid/component/configure.in,v retrieving revision 1.10 diff -c -p -r1.10 configure.in *** sid/component/configure.in 6 May 2003 17:30:58 -0000 1.10 --- sid/component/configure.in 30 May 2003 20:01:05 -0000 *************** AC_CHECK_LIB(nsl, gethostbyname, socket_ *** 43,50 **** socket_libs="$socket_libs -lresolv")) AC_SUBST(socket_libs) ! AC_CHECK_FUNCS(ftime times gettimeofday usleep strtoul strtoull select sched_yield) old_libs="$LIBS" LIBS="$LIBS $socket_libs" AC_CHECK_FUNCS(inet_aton inet_addr) --- 43,61 ---- socket_libs="$socket_libs -lresolv")) AC_SUBST(socket_libs) ! AC_CHECK_FUNCS(ftime times gettimeofday usleep strtoul strtoull select sched_yield vsnprintf vasprintf) + dnl We want vsnprintf if available, otherwise try vasprintf + AC_CHECK_FUNC(vsnprintf, + [AC_DEFINE(_ISOC99_SOURCE, 1, [Define if ISO C99 Features in use])], + [AC_CHECK_FUNC(vasprintf, + [AC_DEFINE(_GNU_SOURCE, 1, [Define if GNU extensions in use])])]) + + dnl To pick up __USE_MISC stuff like inet_aton and putenv + AC_DEFINE(_SVID_SOURCE, 1, [Define if SVID extensions in use]) + dnl To pick up __USE_BSD stuff like usleep + AC_DEFINE(_BSD_SOURCE, 1, [Define if SVID extensions in use]) + old_libs="$LIBS" LIBS="$LIBS $socket_libs" AC_CHECK_FUNCS(inet_aton inet_addr) Index: sid/component/consoles/components.h =================================================================== RCS file: /cvs/src/src/sid/component/consoles/components.h,v retrieving revision 1.3 diff -c -p -r1.3 components.h *** sid/component/consoles/components.h 3 Aug 2001 06:02:43 -0000 1.3 --- sid/component/consoles/components.h 30 May 2003 20:01:06 -0000 *************** *** 1,7 **** // file.cxx - Joint header file for nearby component classes. // -*- C++ -*- ! // Copyright (C) 1999, 2000 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. --- 1,7 ---- // file.cxx - Joint header file for nearby component classes. // -*- C++ -*- ! // Copyright (C) 1999, 2000, 2003 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. *************** class stdioConsole: public virtual compo *** 97,106 **** --- 97,110 ---- { public: stdioConsole(); + ~stdioConsole () throw(); private: + void filename_attribute_set (); + void write(host_int_4 value); void read(host_int_4); + void closeOutStream (); callback_pin activity_pin; callback_pin stdout_pin; *************** private: *** 110,115 **** --- 114,121 ---- string save_state ( ); component::status restore_state (const string& state); + string out_filename; + ostream *out_stream; }; Index: sid/component/consoles/stdio.cxx =================================================================== RCS file: /cvs/src/src/sid/component/consoles/stdio.cxx,v retrieving revision 1.2 diff -c -p -r1.2 stdio.cxx *** sid/component/consoles/stdio.cxx 17 Jan 2001 21:05:09 -0000 1.2 --- sid/component/consoles/stdio.cxx 30 May 2003 20:01:06 -0000 *************** *** 1,10 **** // stdio.cxx - A simple console that uses standard I/O for // enunciation. -*- C++ -*- ! // Copyright (C) 1999, 2000 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. #include "config.h" #include "components.h" --- 1,11 ---- // stdio.cxx - A simple console that uses standard I/O for // enunciation. -*- C++ -*- ! // Copyright (C) 1999, 2000, 2003 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. + #include #include "config.h" #include "components.h" *************** namespace console_stuff *** 13,32 **** stdioConsole::stdioConsole() :activity_pin(this, & stdioConsole::read), ! stdout_pin(this, & stdioConsole::write) { add_pin("poll", &activity_pin); add_pin("stdin", &stdin_pin); add_pin("stdout", &stdout_pin); add_attribute_virtual ("state-snapshot", this, & stdioConsole::save_state, & stdioConsole::restore_state); } void stdioConsole::write(host_int_4 value) { ! cout << static_cast (value) << flush; } void --- 14,58 ---- stdioConsole::stdioConsole() :activity_pin(this, & stdioConsole::read), ! stdout_pin(this, & stdioConsole::write), ! out_filename ("*"), ! out_stream (&cout) { add_pin("poll", &activity_pin); add_pin("stdin", &stdin_pin); add_pin("stdout", &stdout_pin); + add_attribute_notify ("filename", & out_filename, this, & stdioConsole::filename_attribute_set, + "output file setting"); add_attribute_virtual ("state-snapshot", this, & stdioConsole::save_state, & stdioConsole::restore_state); } + stdioConsole::~stdioConsole () throw () + { + closeOutStream (); + } + + void + stdioConsole::closeOutStream () + { + if (out_stream && out_stream != &cout) + delete out_stream; + } + + void + stdioConsole::filename_attribute_set () + { + // Associate the out_stream with the new filename + closeOutStream (); + out_stream = new ofstream (out_filename.c_str ()); + } + void stdioConsole::write(host_int_4 value) { ! if (out_stream) ! (*out_stream) << static_cast (value) << flush; } void Index: sid/include/sidattrutil.h =================================================================== RCS file: /cvs/src/src/sid/include/sidattrutil.h,v retrieving revision 1.3 diff -c -p -r1.3 sidattrutil.h *** sid/include/sidattrutil.h 22 Nov 2002 20:35:00 -0000 1.3 --- sid/include/sidattrutil.h 30 May 2003 20:01:07 -0000 *************** *** 2,8 **** // mappings between application objects and their string // representations. -*- C++ -*- ! // Copyright (C) 1999, 2000, 2002 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. --- 2,8 ---- // mappings between application objects and their string // representations. -*- C++ -*- ! // Copyright (C) 1999, 2000, 2002, 2003 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. *************** *** 10,15 **** --- 10,16 ---- #define SIDATTRUTIL_H #include + #include #include "sidtypes.h" #include *************** *** 26,35 **** --- 27,39 ---- #include + #include + #include // ? ? std::? __gnu_cxx::? Too much hassle. #undef HAVE_HASHING + #include #if HAVE_SSTREAM #include #elif HAVE_STRSTREAM_H *************** make_attribute (const sid::any_intparse_attribute (value); } + }; + + // A mix-in for classes with user logging. + class fixed_attribute_map_with_logging_component + : public virtual fixed_attribute_map_component, + public virtual fixed_pin_map_component + { + protected: + fixed_attribute_map_with_logging_component () : + ulog_level (0), + ulog_mode ("less"), + ulog_out_pin (), + buffer_size (4096), // big enough for now + saved_messages (), + saved_levels () + { + add_attribute ("ulog-level", &ulog_level, "setting"); + add_attribute ("ulog-mode", &ulog_mode, "setting"); + add_pin ("ulog-out", & ulog_out_pin); + #if HAVE_VSNPRINTF || ! HAVE_VASPRINTF + buffer = new char[buffer_size]; + #endif + } + ~fixed_attribute_map_with_logging_component () /* throw() */ + { + // Output any saved messages. + output_saved_messages (); + #if HAVE_VSNPRINTF || ! HAVE_VASPRINTF + delete [] buffer; + #endif + } + + virtual void log (sid::host_int_4 level, const char *fmt, ...) + { + if (ulog_out_pin.connections ().size () != 0) + { + // Output any saved messages first + output_saved_messages (); + + // Check the logging level and mode. + if (! check_level (level)) + return; + } + + // Write the message into a buffer. + int length; + for (;;) + { + va_list ap; + va_start (ap, fmt); + #if HAVE_VSNPRINTF + length = STDCTYPE(vsnprintf) (buffer, buffer_size, fmt, ap); + va_end (ap); + if (length < buffer_size) + break; + delete [] buffer; + buffer_size = length + 256; + buffer = new char[buffer_size]; + #elif HAVE_VASPRINTF + length = STDCTYPE(vasprintf) (&buffer, fmt, ap); + va_end (ap); + break; + #else + length = STDCTYPE(vsprintf) (buffer, fmt, ap); + va_end (ap); + if (length >= buffer_size) + std::cerr << "Error: ulog buffer overflow!!!" << std::endl; + break; + #endif + } + + // If the output pin is not connected yet, Save the message for + // later. This happens when the log message is issued from the + // component's constructor. + if (ulog_out_pin.connections ().size () == 0) + { + saved_messages.push_back (std::string (buffer)); + saved_levels.push_back (level); + } + else + { + // Otherwise, output the new message. + for (int i = 0; i < length; ++i) + ulog_out_pin.drive (buffer[i]); + } + + #if ! HAVE_VSNPRINTF && HAVE_VASPRINTF + free (buffer); + #endif + } + + private: + bool check_level (sid::host_int_4 level) + { + if (level > ulog_level) + return false; + + if (level != ulog_level + && (ulog_mode == "match" || ulog_mode == "equal")) + return false; + + return true; + } + + void output_saved_messages () + { + while (saved_messages.size () > 0) + { + if (check_level (saved_levels[0])) + { + std::string s = saved_messages[0]; + for (int i = 0; i < s.size (); ++i) + ulog_out_pin.drive (s[i]); + } + saved_messages.erase (saved_messages.begin ()); + saved_levels.erase (saved_levels.begin ()); + } + } + + sid::host_int_4 ulog_level; + std::string ulog_mode; + sidutil::output_pin ulog_out_pin; + char *buffer; + long buffer_size; + std::vector saved_messages; + std::vector saved_levels; }; } Index: sid/main/dynamic/commonCfg.cxx =================================================================== RCS file: /cvs/src/src/sid/main/dynamic/commonCfg.cxx,v retrieving revision 1.3 diff -c -p -r1.3 commonCfg.cxx *** sid/main/dynamic/commonCfg.cxx 16 Apr 2003 22:01:07 -0000 1.3 --- sid/main/dynamic/commonCfg.cxx 30 May 2003 20:01:07 -0000 *************** SessionCfg::SessionCfg (const string nam *** 545,550 **** --- 545,573 ---- conn_pin (main_obj, "stopping", shutdown_seq, "input"); yield_net->add_output (0, host_sched, "yield"); init_seq->add_output (0, reset_net, "input"); + + AtomicCfg *ulog = new AtomicCfg ("ulog-*", + "libconsoles.la", + "console_component_library", + "sid-io-stdio"); + ulog_map["*"] = ulog; + add_child (ulog); + } + + void + SessionCfg::add_ulog_file (const string name) + { + if (ulog_map.find (name) != ulog_map.end ()) + return; // already there + + // There is no existing logger for this file, so add a new one. + AtomicCfg *ulog = new AtomicCfg ("ulog-" + name, + "libconsoles.la", + "console_component_library", + "sid-io-stdio"); + set (ulog, "filename", name); + ulog_map[name] = ulog; + add_child (ulog); } void SessionCfg::use_no_stdio () *************** BoardCfg::BoardCfg (const string name, *** 830,835 **** --- 853,859 ---- bool with_cpu_main_mem_connect) : ComponentCfg (name), AggregateCfg (name), + UlogCfg (), cache_flush_net (NULL), z_packet (with_z_packet), sess (s), Index: sid/main/dynamic/commonCfg.h =================================================================== RCS file: /cvs/src/src/sid/main/dynamic/commonCfg.h,v retrieving revision 1.1 diff -c -p -r1.1 commonCfg.h *** sid/main/dynamic/commonCfg.h 9 Jan 2003 04:22:50 -0000 1.1 --- sid/main/dynamic/commonCfg.h 30 May 2003 20:01:07 -0000 *************** class GlueSeqCfg : *** 166,175 **** int n; }; // you should really only make one of these, with an empty name, // unless you want some crazy multi-session support. struct SessionCfg : ! virtual public AggregateCfg { SessionCfg (const string name); virtual ~SessionCfg (); --- 166,189 ---- int n; }; + // Configs which support logging should inherit this + struct UlogCfg + { + UlogCfg (sid::host_int_4 l = 0, const string m = "less", const string f = "*") + : ulog_level (l), ulog_mode (m), ulog_file (f) + {} + virtual void set_ulog_level (sid::host_int_4 l) { ulog_level = l; } + virtual void set_ulog_mode (const string m) { ulog_mode = m; } + virtual void set_ulog_file (const string f) { ulog_file = f; } + sid::host_int_4 ulog_level; + string ulog_mode; + string ulog_file; + }; + // you should really only make one of these, with an empty name, // unless you want some crazy multi-session support. struct SessionCfg : ! virtual public AggregateCfg, public UlogCfg { SessionCfg (const string name); virtual ~SessionCfg (); *************** struct SessionCfg : *** 194,199 **** --- 208,215 ---- AtomicCfg *tcl_bridge; bool verbose; bool use_stdio; + void add_ulog_file (const string filename); + map ulog_map; }; class CpuCfg : *************** class GdbCfg : *** 278,284 **** }; class BoardCfg : ! virtual public AggregateCfg { public: BoardCfg (const string name, --- 294,300 ---- }; class BoardCfg : ! virtual public AggregateCfg, public UlogCfg { public: BoardCfg (const string name, *************** public: *** 307,312 **** --- 323,329 ---- virtual void trace_disassemble (); virtual void trace_core (); virtual void write_config (Writer &w); + virtual ~BoardCfg (); GlueSeqCfg *cache_flush_net; Index: sid/main/dynamic/mainDynamic.cxx =================================================================== RCS file: /cvs/src/src/sid/main/dynamic/mainDynamic.cxx,v retrieving revision 1.3 diff -c -p -r1.3 mainDynamic.cxx *** sid/main/dynamic/mainDynamic.cxx 9 Jan 2003 04:22:50 -0000 1.3 --- sid/main/dynamic/mainDynamic.cxx 30 May 2003 20:01:07 -0000 *************** *** 1,6 **** // mainDynamic.cxx - high-tech mainline. -*- C++ -*- ! // Copyright (C) 1999, 2000, 2001, 2002 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. --- 1,6 ---- // mainDynamic.cxx - high-tech mainline. -*- C++ -*- ! // Copyright (C) 1999, 2000, 2001, 2002, 2003 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. *************** usage () *** 120,125 **** --- 120,129 ---- << " mmap Memory map given file" << endl << " latency=r:w Set read, write latencies [0:0]" << endl << " latency=rw Set both latencies [0]" << endl; + cout << "--ulog-level=LEVEL Set the logging level for the current board" << endl; + cout << "--ulog-mode=less|match|equal" << endl + << " Set the logging mode for the current board" << endl; + cout << "--ulog-file=*|FILE Set the log file name" << endl; cout << endl << " note: most board-specific options can be used in board-neutral position " << endl << " where they are interpreted as session-specific or default settings. " << endl; *************** struct Defs { *** 462,467 **** --- 466,474 ---- trace_disassemble (false), trace_counter (false), trace_core (false), + ulog_level (0), + ulog_mode ("less"), + ulog_file ("*"), step_insn_count ("10000") {} string cpu; *************** struct Defs { *** 472,477 **** --- 479,487 ---- bool trace_disassemble; bool trace_counter; bool trace_core; + sid::host_int_4 ulog_level; + string ulog_mode; + string ulog_file; string step_insn_count; }; *************** main(int argc, char* argv[]) *** 514,520 **** opt_insn_count, opt_load, opt_icache, opt_dcache, opt_memory_region, opt_trace_extract, opt_trace_semantics, opt_trace_disassemble, opt_trace_counter, opt_trace_core, ! opt_final_insn_count, opt_eb, opt_el, opt_gprof }; int curr_opt; --- 524,531 ---- opt_insn_count, opt_load, opt_icache, opt_dcache, opt_memory_region, opt_trace_extract, opt_trace_semantics, opt_trace_disassemble, opt_trace_counter, opt_trace_core, ! opt_final_insn_count, opt_eb, opt_el, opt_gprof, ! opt_ulog_level, opt_ulog_mode, opt_ulog_file }; int curr_opt; *************** main(int argc, char* argv[]) *** 559,564 **** --- 570,578 ---- {"final-insn-count", no_argument, & curr_opt, opt_final_insn_count }, {"EB", no_argument, & curr_opt, opt_eb }, {"EL", no_argument, & curr_opt, opt_el }, + {"ulog-level", required_argument, &curr_opt, opt_ulog_level }, + {"ulog-mode", required_argument, &curr_opt, opt_ulog_mode }, + {"ulog-file", required_argument, &curr_opt, opt_ulog_file }, { 0, 0, NULL, 0 } }; *************** main(int argc, char* argv[]) *** 632,637 **** --- 646,654 ---- curr_board->trace_core(); if (defaults.enable_warnings) curr_board->enable_warnings(); + curr_board->set_ulog_level (defaults.ulog_level); + curr_board->set_ulog_mode (defaults.ulog_mode); + curr_board->set_ulog_file (defaults.ulog_file); if (defaults.step_insn_count != "10000") curr_board->set_step_insn_count(defaults.step_insn_count); break; *************** main(int argc, char* argv[]) *** 815,820 **** --- 832,871 ---- exit (8); } } + break; + + case opt_ulog_level: + if (curr_board) + curr_board->set_ulog_level (optaddr ("ulog-level")); + else + { + defaults.ulog_level = optaddr ("ulog-level"); + need_sess (sess); + sess->set_ulog_level (optaddr ("ulog-level")); + } + break; + + case opt_ulog_mode: + if (curr_board) + curr_board->set_ulog_mode (optstring ()); + else + { + defaults.ulog_mode = optstring (); + need_sess (sess); + sess->set_ulog_mode (optstring ()); + } + break; + + case opt_ulog_file: + need_sess (sess); + sess->add_ulog_file (optstring ()); + if (curr_board) + curr_board->set_ulog_file (optstring ()); + else + { + defaults.ulog_file = optstring (); + sess->set_ulog_file (optstring ()); + } break; } break; Index: sid/component/consoles/sid-io-stdio.txt =================================================================== RCS file: /cvs/src/src/sid/component/consoles/sid-io-stdio.txt,v retrieving revision 1.2 diff -c -p -r1.2 sid-io-stdio.txt *** sid/component/consoles/sid-io-stdio.txt 3 Aug 2001 01:30:17 -0000 1.2 --- sid/component/consoles/sid-io-stdio.txt 30 May 2003 20:23:25 -0000 *************** Functionality: *** 28,33 **** --- 28,39 ---- | output | When the stdout input pin is driven | | | with a value between 0 and 255, the | | | value is immediately written to | + | | output. If the filename attribute is | + | | set, the output is written to the file | + | | named by the attribute's value. If the | + | | filename attribute is set to "*", then | + | | output is written to stdout. The | + | | default behavior is to write to | | | stdout. | |--------+----------------------------------------| | input | When the poll pin is driven, the stdin | *************** Component Reference: *** 106,109 **** --- 112,119 ---- |--------------+--------+------+-------+------------|| |state-snapshot|- |opaque|- |state || | | |string| |save/restore|| + |--------------+--------+------+-------+------------|| + | | |valid | | || + |filename |- |file |- |output || + | | |name | | || +----------------------------------------------------+ Index: sid/component/consoles/sid-io-stdio.xml =================================================================== RCS file: /cvs/src/src/sid/component/consoles/sid-io-stdio.xml,v retrieving revision 1.1 diff -c -p -r1.1 sid-io-stdio.xml *** sid/component/consoles/sid-io-stdio.xml 3 Aug 2001 01:47:52 -0000 1.1 --- sid/component/consoles/sid-io-stdio.xml 30 May 2003 20:23:25 -0000 *************** *** 13,18 **** --- 13,19 ---- + This component performs input/output on the standard input/output. *************** *** 40,46 **** When the stdout input pin is driven with a value between 0 and ! 255, the value is immediately written to stdout. --- 41,51 ---- When the stdout input pin is driven with a value between 0 and ! 255, the value is immediately written to output. If the ! filename attribute ! is set, the output is written to the file named by the attribute's value. If ! the filename attribute is set to "*", then output is ! written to stdout. The default behavior is to write to stdout.