This is the mail archive of the
sid@sources.redhat.com
mailing list for the SID project.
[patch][rfa] ulog enhancements. C++ issues
- From: Dave Brolley <brolley at redhat dot com>
- To: sid at sources dot redhat dot com
- Date: Tue, 21 Oct 2003 17:01:17 -0400
- Subject: [patch][rfa] ulog enhancements. C++ issues
- Organization: Red Hat Canada, Ltd
Hi,
This patch fixes some problems with the ulog support and also abstracts
it into a separate utility class "logger" so that a component can have
specialized loggers in addition to the generic ulog support logger.
This patch also addresses some C++ language issues needed for
compilation with recent releases of gcc.
Dave
2003-10-07 Dave Brolley <brolley@redhat.com>
For Stan Cox <scox@redhat.com>
* sidmiscutil.h (logger): New class.
* sidattrutil.h (fixed_attribute_map_with_logging_component): Convert
to use logger.
2003-10-07 Dave Brolley <brolley@redhat.com>
* sidattrutil.h (SID_LOG_PERSISTENT_BUFFER): New macro.
(SID_LOG_TRANSIENT_MALLOC_BUFFER): New macro.
(buffer_output): New member of
fixed_attribute_map_with_logging_component.
(fixed_attribute_with_logging_component): Add buffer-output attribute.
Use SID_LOG_PERSISTENT_BUFFER.
(~fixed_attribute_with_logging_component): Use
SID_LOG_PERSISTENT_BUFFER.
(log): Buffer output based on buffer_output. Use
SID_LOG_TRANSIENT_MALLOC_BUFFER.
* sidcpuutil.h (get_total_latency): New method of basic_cpu.
2003-10-07 Dave Brolley <brolley@redhat.com>
* sidattrutil.h (log): Don't use STDCTYPE for vsnprint or vasprintf.
2003-10-07 Dave Brolley <brolley@redhat.com>
For Stan Cox <scox@redhat.com>
* sidmiscutil.h (bijection::find): Add typename.
* sidbusutil.h (ro_value_control_register): New ValueType typedef.
(control_register_bus::word_write, control_register_bus::word_read):
Add typename
2003-10-07 Dave Brolley <brolley@redhat.com>
* sidattrutil.h (iostream): #include it.
(log): Use std::cerr and std::endl.
2003-10-07 Dave Brolley <brolley@redhat.com>
* sidattrutil.h (fixed_attribute_map_with_logging_component):
Initialize saved_messages and saved_levels.
(~fixed_attribute_map_with_logging_component): Output saved messages.
Delete buffer if necessary.
(log): Save message for later if output pin not connected. Otherwise
output saved messages before the new message. Use vsnprintf or
vasprintf if possible.
(check_level): New member of fixed_attribute_map_with_logging_component.
(output_saved_messages): Ditto.
Index: sid/include/sidattrutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidattrutil.h,v
retrieving revision 1.5
diff -c -p -r1.5 sidattrutil.h
*** sid/include/sidattrutil.h 20 Jun 2003 21:29:13 -0000 1.5
--- sid/include/sidattrutil.h 21 Oct 2003 20:21:46 -0000
***************
*** 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.
--- 2,8 ----
// mappings between application objects and their string
// representations. -*- 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.
***************
*** 43,48 ****
--- 43,49 ----
#endif
#include <cassert>
+ #include <sidmiscutil.h>
namespace sidutil
*************** make_attribute (const sid::any_int<IntTy
*** 687,693 ****
operator () (const std::string& s) const
{
// XXX: improve?
! return hash<const char*> () (s.c_str ());
}
};
#endif
--- 688,694 ----
operator () (const std::string& s) const
{
// XXX: improve?
! return std::hash<const char*> () (s.c_str ());
}
};
#endif
*************** make_attribute (const sid::any_int<IntTy
*** 699,705 ****
private:
// use hash table for this, if available
#ifdef HAVE_HASHING
! typedef hash_map<std::string,attribute_coder_base*,hash_string> attribute_map_t;
#else
typedef std::map<std::string,attribute_coder_base*> attribute_map_t;
#endif
--- 700,706 ----
private:
// use hash table for this, if available
#ifdef HAVE_HASHING
! typedef std::hash_map<std::string,attribute_coder_base*,hash_string> attribute_map_t;
#else
typedef std::map<std::string,attribute_coder_base*> attribute_map_t;
#endif
*************** make_attribute (const sid::any_int<IntTy
*** 1037,1042 ****
--- 1038,1044 ----
add_attribute ("ulog-level", &ulog_level, "setting");
add_attribute ("ulog-mode", &ulog_mode, "setting");
add_pin ("ulog-out", & ulog_out_pin);
+ ulog_logger = new logger (& ulog_out_pin, buffer_output, ulog_level, ulog_mode);
#if SID_LOG_PERSISTENT_BUFFER
buffer = new char[buffer_size];
#endif
*************** make_attribute (const sid::any_int<IntTy
*** 1044,1125 ****
~fixed_attribute_map_with_logging_component () throw()
{
// Output any saved messages.
! output_saved_messages ();
#if SID_LOG_PERSISTENT_BUFFER
delete [] buffer;
#endif
}
! virtual void log (sid::host_int_4 level, const char *fmt, ...)
{
! if (! buffer_output)
! {
! // 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 = 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 = 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 (buffer_output)
! {
! 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 SID_LOG_TRANSIENT_MALLOC_BUFFER
! 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 ()
--- 1046,1072 ----
~fixed_attribute_map_with_logging_component () throw()
{
// Output any saved messages.
! // output_saved_messages ();
! ulog_logger->output_saved_messages ();
#if SID_LOG_PERSISTENT_BUFFER
delete [] buffer;
#endif
}
! void log (sid::host_int_4 level, const char *fmt, ...)
{
! va_list ap;
! va_start (ap, fmt);
! // In case values changed
! ulog_logger->set_attributes (buffer_output, ulog_level, ulog_mode);
! ulog_logger->log (level, fmt, ap);
! va_end (ap);
}
private:
bool check_level (sid::host_int_4 level)
{
! ulog_logger->check_level (level);
}
void output_saved_messages ()
*************** private:
*** 1141,1146 ****
--- 1088,1094 ----
std::string ulog_mode;
sidutil::output_pin ulog_out_pin;
bool buffer_output;
+ sidutil::logger *ulog_logger;
char *buffer;
long buffer_size;
std::vector<std::string> saved_messages;
Index: sid/include/sidcpuutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidcpuutil.h,v
retrieving revision 1.26
diff -c -p -r1.26 sidcpuutil.h
*** sid/include/sidcpuutil.h 29 Aug 2003 19:27:05 -0000 1.26
--- sid/include/sidcpuutil.h 21 Oct 2003 20:21:46 -0000
*************** namespace sidutil
*** 234,240 ****
--- 234,244 ----
else
*this << std::endl;
}
+ private:
bool cout_p;
+
+ template <typename T> friend
+ basic_cpu::cpu_trace_stream& operator<< (basic_cpu::cpu_trace_stream& s, T t);
};
template <typename T> friend
Index: sid/include/sidmiscutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidmiscutil.h,v
retrieving revision 1.6
diff -c -p -r1.6 sidmiscutil.h
*** sid/include/sidmiscutil.h 22 Nov 2002 20:35:00 -0000 1.6
--- sid/include/sidmiscutil.h 21 Oct 2003 20:21:46 -0000
***************
*** 8,15 ****
--- 8,17 ----
#define SIDMISCUTIL_H
#include <sidconfig.h>
+ #include <sidpinutil.h>
#include <string>
+ #include <iostream>
#include <fstream>
#include <vector>
#include <map>
***************
*** 20,26 ****
--- 22,40 ----
#ifdef __CYGWIN__
#include <sys/cygwin.h>
#endif
+ // XXX: kludge for compatibility both with old & new libstdc++
+ #if STD_CCTYPE
+ #define STDCTYPE(func) std::func
+ #else
+ #define STDCTYPE(func) func
+ #endif
+
+ #include <limits.h>
+ #include <stdio.h>
+ #include <stdarg.h>
+ using std::string;
+ using std::vector;
namespace sidutil
{
*************** namespace sidutil
*** 376,381 ****
--- 390,534 ----
return file;
}
+ class logger
+ {
+ #define SID_LOG_PERSISTENT_BUFFER (HAVE_VSNPRINTF || ! HAVE_VASPRINTF)
+ #define SID_LOG_TRANSIENT_MALLOC_BUFFER (! SID_LOG_PERSISTENT_BUFFER)
+ public:
+ logger (sidutil::output_pin *p_ulog_out_pin,
+ bool p_buffer_output,
+ sid::host_int_4 p_ulog_level,
+ std::string p_ulog_mode) :
+ ulog_level (p_ulog_level),
+ ulog_mode (p_ulog_mode),
+ buffer_output (p_buffer_output),
+ buffer_size (4096), // big enough for now
+ saved_messages (),
+ saved_levels ()
+ {
+ ulog_out_pin = p_ulog_out_pin;
+ #if SID_LOG_PERSISTENT_BUFFER
+ buffer = new char[buffer_size];
+ #endif
+ }
+ ~logger () throw()
+ {
+ // Output any saved messages.
+ output_saved_messages ();
+ #if SID_LOG_PERSISTENT_BUFFER
+ delete [] buffer;
+ #endif
+ }
+
+ void set_attributes (bool p_buffer_output,
+ sid::host_int_4 p_ulog_level,
+ std::string p_ulog_mode)
+ {
+ buffer_output = p_buffer_output;
+ ulog_level = p_ulog_level;
+ ulog_mode = p_ulog_mode;
+ }
+
+ virtual void log (sid::host_int_4 level, const char *fmt, va_list ap)
+ {
+ if (! buffer_output)
+ {
+ // 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 (;;)
+ {
+ #if HAVE_VSNPRINTF
+ length = vsnprintf (buffer, buffer_size, fmt, ap);
+ if (length < buffer_size)
+ break;
+ delete [] buffer;
+ buffer_size = length + 256;
+ buffer = new char[buffer_size];
+ #elif HAVE_VASPRINTF
+ length = vasprintf (&buffer, fmt, ap);
+ break;
+ #else
+ length = STDCTYPE(vsprintf) (buffer, fmt, 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 (buffer_output)
+ {
+ 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 SID_LOG_TRANSIENT_MALLOC_BUFFER
+ free (buffer);
+ #endif
+ }
+
+ public:
+ 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;
+ }
+
+ public:
+ 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 ());
+ }
+ }
+
+ private:
+ sid::host_int_4 ulog_level;
+ std::string ulog_mode;
+ sidutil::output_pin *ulog_out_pin;
+ bool buffer_output;
+ char *buffer;
+ long buffer_size;
+ std::vector<std::string> saved_messages;
+ std::vector<sid::host_int_4> saved_levels;
+ #undef SID_LOG_PERSISTENT_BUFFER
+ #undef SID_LOG_TRANSIENT_MALLOC_BUFFER
+ public:
+ void delete_saved_messages ()
+ {
+ saved_messages.erase (saved_messages.end ());
+ }
+ };
}