From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path:
Received: (qmail 23365 invoked by alias); 11 May 2006 17:04:10 -0000
Received: (qmail 23354 invoked by uid 22791); 11 May 2006 17:04:07 -0000
X-Spam-Check-By: sourceware.org
Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 11 May 2006 17:03:56 +0000
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k4BH3sKs009996 for ; Thu, 11 May 2006 13:03:54 -0400
Received: from pobox.toronto.redhat.com (pobox.toronto.redhat.com [172.16.14.4]) by int-mx1.corp.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k4BH3s63024332 for ; Thu, 11 May 2006 13:03:54 -0400
Received: from [172.16.14.227] (IDENT:+nHGMUbdtLvLTHrGv54m7nFhV/geB30s@topaz.toronto.redhat.com [172.16.14.227]) by pobox.toronto.redhat.com (8.12.8/8.12.8) with ESMTP id k4BH3rAc022128 for ; Thu, 11 May 2006 13:03:53 -0400
Message-ID: <44636E79.7030004@redhat.com>
Date: Thu, 11 May 2006 17:04:00 -0000
From: Dave Brolley
User-Agent: Mozilla Thunderbird 1.0.2 (X11/20050317)
MIME-Version: 1.0
To: sid@sources.redhat.com
Subject: [patch][commit] 64 bit support in gprof component
Content-Type: multipart/mixed; boundary="------------070600080006060801070403"
X-IsSubscribed: yes
Mailing-List: contact sid-help@sourceware.org; run by ezmlm
Precedence: bulk
List-Subscribe:
List-Archive:
List-Post:
List-Help: ,
Sender: sid-owner@sourceware.org
X-SW-Source: 2006-q2/txt/msg00027.txt.bz2
This is a multi-part message in MIME format.
--------------070600080006060801070403
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Content-length: 1203
Hi,
I've committed the attached patch which adds 64 bit capability to the
gprof component.
Internally this was simply done by changing host_int_4 to host_int_8
where appropriate and writing the correct data size to the output as
necessary.
In the component interface, the following were added:
cg-caller-hi pin: Driven with the high order 32 bits of the pc, if necessary
cg-callee-hi pin: Driven with the high order 32 bits of the pc, if necessary
pc-size attribute: Specifies the size, in bytes of the pc. Valid values
are 4 and 8
Normally, an attribute of the target component named by value-attribute
is polled to obtain the current pc.
If pc-size is 8, then in addition to this attribute, an additional
attribute suffixed by "-hi" is polled. For example, if the value of
value-attribute is "current-pc", then the target attribute named
current-pc-hi will also be polled. If there is no such attribute then a
value of zero will be assumed.
cg-caller-hi and cg-callee-hi are primed with a value of zero and
pc-size is primed with a value of 4, so behavior for ports which don't
use these remains unchanged.
This has been tested on an internal port which required this support.
Dave
--------------070600080006060801070403
Content-Type: text/plain;
name="sid-gprof.ChangeLog"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="sid-gprof.ChangeLog"
Content-length: 934
2006-05-11 Dave Brolley
* gprof.cxx (hitcount_map_t): PC now host_int_8.
(cg_count_map_t): Likewise.
(statistics): value_min,value_max,limit_min,limit_max likewise.
New member, pc_size.
(statistics::operator=): Copy pc_size.
(cg_caller_hi_pin): New pin.
(cg_callee_hi_pin): New pin.
(limit_min_set): Handle 64 bits.
(limit_max_set): Handle 64 bits.
(pc_size_get): New method.
(pc_size_set): New method.
(accumulate): Use target_attribute + "-hi" to obtain 64 bit pc. Handle
64 bits throughout.
(accumulate_call): Use {caller,callee}_hi pin to obtain 64 bit pc. Handle
64 bits throughout.
(store_stats): Handle 32 or 64 bit pc.
(gprof_component): Add cg-caller_hi and cg-callee-hi pins. Add pc-size
attribute. Initialize value on cg-caller-hi and cg-callee-hi to zero.
* sw-profile-gprof.xml: Document cg-caller-hi, cg-callee-hi,
bucket-size, pc-size.
* sw-profile-gprof.txt: Regenerated.
--------------070600080006060801070403
Content-Type: text/plain;
name="sid-gprof.patch.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="sid-gprof.patch.txt"
Content-length: 19740
Index: sid/component/profiling/gprof.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/profiling/gprof.cxx,v
retrieving revision 1.14
diff -c -p -r1.14 gprof.cxx
*** sid/component/profiling/gprof.cxx 1 Mar 2006 21:07:02 -0000 1.14
--- sid/component/profiling/gprof.cxx 11 May 2006 16:00:35 -0000
***************
*** 1,6 ****
// gprof.cxx - A component for generating gprof profile data. -*- C++ -*-
! // Copyright (C) 1999-2002, 2005 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 ----
// gprof.cxx - A component for generating gprof profile data. -*- C++ -*-
! // Copyright (C) 1999-2002, 2005, 2006 Red Hat.
// This file is part of SID and is licensed under the GPL.
// See the file COPYING.SID for conditions for redistribution.
*************** namespace profiling_components
*** 95,102 ****
protected no_bus_component,
protected configurable_component
{
! typedef map hitcount_map_t;
! typedef map,host_int_4> cg_count_map_t;
// statistics
struct statistics
--- 95,102 ----
protected no_bus_component,
protected configurable_component
{
! typedef map hitcount_map_t;
! typedef map,host_int_4> cg_count_map_t;
// statistics
struct statistics
*************** namespace profiling_components
*** 104,120 ****
hitcount_map_t value_hitcount_map;
cg_count_map_t cg_count_map;
host_int_4 value_count;
! host_int_4 value_min, value_max;
! host_int_4 limit_min, limit_max;
host_int_4 bucket_size;
string output_file;
statistics () :
value_count (0),
! value_min (~0),
value_max (0),
limit_min (0),
! limit_max (~0),
bucket_size (1), // != 0
output_file ("")
{ }
const statistics &operator= (const statistics &other)
--- 104,122 ----
hitcount_map_t value_hitcount_map;
cg_count_map_t cg_count_map;
host_int_4 value_count;
! host_int_8 value_min, value_max;
! host_int_8 limit_min, limit_max;
host_int_4 bucket_size;
+ host_int_4 pc_size;
string output_file;
statistics () :
value_count (0),
! value_min (~(host_int_8)0),
value_max (0),
limit_min (0),
! limit_max (~(host_int_8)0),
bucket_size (1), // != 0
+ pc_size (4), // default
output_file ("")
{ }
const statistics &operator= (const statistics &other)
*************** namespace profiling_components
*** 125,130 ****
--- 127,133 ----
this->limit_min = other.limit_min;
this->limit_max = other.limit_max;
this->bucket_size = other.bucket_size;
+ this->pc_size = other.pc_size;
this->output_file = other.output_file;
}
};
*************** namespace profiling_components
*** 142,148 ****
--- 145,153 ----
callback_pin accumulate_pin;
+ input_pin cg_caller_hi_pin;
input_pin cg_caller_pin;
+ input_pin cg_callee_hi_pin;
callback_pin cg_callee_pin;
callback_pin reset_pin;
*************** namespace profiling_components
*** 175,181 ****
component::status limit_min_set(const string& str)
{
! host_int_4 new_limit_min;
component::status s = parse_attribute (str, new_limit_min);
// Reject malformed input
if (s == component::ok)
--- 180,186 ----
component::status limit_min_set(const string& str)
{
! host_int_8 new_limit_min;
component::status s = parse_attribute (str, new_limit_min);
// Reject malformed input
if (s == component::ok)
*************** namespace profiling_components
*** 190,196 ****
component::status limit_max_set(const string& str)
{
! host_int_4 new_limit_max;
component::status s = parse_attribute (str, new_limit_max);
// Reject malformed input
if (s == component::ok)
--- 195,201 ----
component::status limit_max_set(const string& str)
{
! host_int_8 new_limit_max;
component::status s = parse_attribute (str, new_limit_max);
// Reject malformed input
if (s == component::ok)
*************** namespace profiling_components
*** 231,236 ****
--- 236,266 ----
}
+ string pc_size_get()
+ {
+ return make_attribute (this->stats[current_stats].pc_size);
+ }
+
+ component::status pc_size_set(const string& str)
+ {
+ host_int_4 new_pc_size;
+ component::status s = parse_attribute (str, new_pc_size);
+
+ // Reject malformed input
+ if (s != component::ok) return s;
+
+ // Reject invalid sizes
+ if (new_pc_size != 4 && new_pc_size != 8)
+ {
+ cerr << "sw-profile-gprof: invalid pc size." << endl;
+ return component::bad_value;
+ }
+
+ this->stats[current_stats].pc_size = new_pc_size;
+ return component::ok;
+ }
+
+
string output_file_get()
{
return this->stats[current_stats].output_file;
*************** namespace profiling_components
*** 247,255 ****
if (! this->target_component) return;
string value_str = this->target_component->attribute_value (this->target_attribute);
! host_int_4 value;
component::status s = parse_attribute (value_str, value);
if (s != component::ok) return;
// std::cout << "sampled at 0x" << std::hex << value << std::dec << " for " << stats[current_stats].output_file << endl;
// Reject out-of-bounds samples
if (value < this->stats[current_stats].limit_min || value > this->stats[current_stats].limit_max) return;
--- 277,294 ----
if (! this->target_component) return;
string value_str = this->target_component->attribute_value (this->target_attribute);
! host_int_8 value;
component::status s = parse_attribute (value_str, value);
if (s != component::ok) return;
+
+ value_str = this->target_component->attribute_value (this->target_attribute + "-hi");
+ host_int_8 value_hi;
+ s = parse_attribute (value_str, value_hi);
+ if (s != component::ok)
+ value_hi = 0;
+
+ value = (value_hi << 32) | (value & 0xffffffff);
+
// std::cout << "sampled at 0x" << std::hex << value << std::dec << " for " << stats[current_stats].output_file << endl;
// Reject out-of-bounds samples
if (value < this->stats[current_stats].limit_min || value > this->stats[current_stats].limit_max) return;
*************** namespace profiling_components
*** 257,272 ****
stats[current_stats].value_count ++;
assert (this->stats[current_stats].bucket_size != 0);
! host_int_4 quantized = (value / this->stats[current_stats].bucket_size) * this->stats[current_stats].bucket_size;
if (quantized < this->stats[current_stats].value_min) this->stats[current_stats].value_min = quantized;
if (quantized > this->stats[current_stats].value_max) this->stats[current_stats].value_max = quantized;
this->stats[current_stats].value_hitcount_map [quantized] ++;
}
! void accumulate_call (host_int_4 selfpc)
{
! host_int_4 callerpc = this->cg_caller_pin.sense();
// Reject out-of-bounds samples
if (selfpc < this->stats[current_stats].limit_min || selfpc > this->stats[current_stats].limit_max) return;
--- 296,312 ----
stats[current_stats].value_count ++;
assert (this->stats[current_stats].bucket_size != 0);
! host_int_8 quantized = (value / this->stats[current_stats].bucket_size) * this->stats[current_stats].bucket_size;
if (quantized < this->stats[current_stats].value_min) this->stats[current_stats].value_min = quantized;
if (quantized > this->stats[current_stats].value_max) this->stats[current_stats].value_max = quantized;
this->stats[current_stats].value_hitcount_map [quantized] ++;
}
! void accumulate_call (host_int_4 selfpc_low)
{
! host_int_8 selfpc = (((host_int_8)this->cg_callee_hi_pin.sense ()) << 32) | (selfpc_low & 0xffffffff);
! host_int_8 callerpc = (((host_int_8)this->cg_caller_hi_pin.sense ()) << 32) | (this->cg_caller_pin.sense () & 0xffffffff);
// Reject out-of-bounds samples
if (selfpc < this->stats[current_stats].limit_min || selfpc > this->stats[current_stats].limit_max) return;
*************** namespace profiling_components
*** 275,282 ****
stats[current_stats].value_count ++;
assert (this->stats[current_stats].bucket_size != 0);
! host_int_4 c_quantized = (callerpc / this->stats[current_stats].bucket_size) * this->stats[current_stats].bucket_size;
! host_int_4 s_quantized = (selfpc / this->stats[current_stats].bucket_size) * this->stats[current_stats].bucket_size;
if (c_quantized < this->stats[current_stats].value_min) this->stats[current_stats].value_min = c_quantized;
if (s_quantized < this->stats[current_stats].value_min) this->stats[current_stats].value_min = s_quantized;
--- 315,322 ----
stats[current_stats].value_count ++;
assert (this->stats[current_stats].bucket_size != 0);
! host_int_8 c_quantized = (callerpc / this->stats[current_stats].bucket_size) * this->stats[current_stats].bucket_size;
! host_int_8 s_quantized = (selfpc / this->stats[current_stats].bucket_size) * this->stats[current_stats].bucket_size;
if (c_quantized < this->stats[current_stats].value_min) this->stats[current_stats].value_min = c_quantized;
if (s_quantized < this->stats[current_stats].value_min) this->stats[current_stats].value_min = s_quantized;
*************** namespace profiling_components
*** 400,408 ****
// GMON_Record_Tag
put_bytes (of, host_int_1(0), 1); // GMON_TAG_TIME_HIST
// gmon_hist_hdr
! put_bytes (of, stats.value_min, 4); // gmon_hist_hdr.low_pc
! host_int_4 uprounded_value_max = stats.value_max + stats.bucket_size;
! put_bytes (of, uprounded_value_max, 4); // gmon_hist_hdr.high_pc
assert (stats.bucket_size != 0);
host_int_4 num_buckets = 1 + (stats.value_max - stats.value_min) / stats.bucket_size;
put_bytes (of, num_buckets, 4); // gmon_hist_hdr.hist_size
--- 440,457 ----
// GMON_Record_Tag
put_bytes (of, host_int_1(0), 1); // GMON_TAG_TIME_HIST
// gmon_hist_hdr
! if (stats.pc_size == 4) // 4 byte pc
! {
! put_bytes (of, (host_int_4)stats.value_min, stats.pc_size); // gmon_hist_hdr.low_pc
! host_int_4 uprounded_value_max = stats.value_max + stats.bucket_size;
! put_bytes (of, uprounded_value_max, stats.pc_size); // gmon_hist_hdr.high_pc
! }
! else // 8 byte pc
! {
! put_bytes (of, stats.value_min, stats.pc_size); // gmon_hist_hdr.low_pc
! host_int_8 uprounded_value_max = stats.value_max + stats.bucket_size;
! put_bytes (of, uprounded_value_max, stats.pc_size); // gmon_hist_hdr.high_pc
! }
assert (stats.bucket_size != 0);
host_int_4 num_buckets = 1 + (stats.value_max - stats.value_min) / stats.bucket_size;
put_bytes (of, num_buckets, 4); // gmon_hist_hdr.hist_size
*************** namespace profiling_components
*** 412,418 ****
// Dump out histogram counts
bool overflow = false;
! for (host_int_4 bucket = stats.value_min;
bucket <= stats.value_max;
bucket += stats.bucket_size)
{
--- 461,467 ----
// Dump out histogram counts
bool overflow = false;
! for (host_int_8 bucket = stats.value_min;
bucket <= stats.value_max;
bucket += stats.bucket_size)
{
*************** namespace profiling_components
*** 454,461 ****
put_bytes (of, host_int_1(1), 1); // GMON_TAG_CG_ARC
// gmon_hist_hdr
! put_bytes (of, ci->first.first, 4); // cg caller
! put_bytes (of, ci->first.second, 4); // cg self
put_bytes (of, ci->second, 4); // cg count
ci ++;
--- 503,518 ----
put_bytes (of, host_int_1(1), 1); // GMON_TAG_CG_ARC
// gmon_hist_hdr
! if (stats.pc_size == 4) // 4 byte pc
! {
! put_bytes (of, (host_int_4)(ci->first.first), 4); // cg caller
! put_bytes (of, (host_int_4)(ci->first.second), 4); // cg self
! }
! else // 8 byte pc
! {
! put_bytes (of, ci->first.first, 8); // cg caller
! put_bytes (of, ci->first.second, 8); // cg self
! }
put_bytes (of, ci->second, 4); // cg count
ci ++;
*************** namespace profiling_components
*** 551,562 ****
--- 608,627 ----
add_attribute ("sim-sched-event", & this->sim_sched_event, "setting");
add_pin ("cg-caller", & this->cg_caller_pin);
add_attribute ("cg-caller", & this->cg_caller_pin, "pin");
+ add_pin ("cg-caller-hi", & this->cg_caller_hi_pin);
+ add_attribute ("cg-caller-hi", & this->cg_caller_hi_pin, "pin");
add_pin ("cg-callee", & this->cg_callee_pin);
add_attribute ("cg-callee", & this->cg_callee_pin, "pin");
+ add_pin ("cg-callee-hi", & this->cg_callee_hi_pin);
+ add_attribute ("cg-callee-hi", & this->cg_callee_hi_pin, "pin");
add_pin ("reset", & this->reset_pin);
add_attribute ("reset", & this->reset_pin, "pin");
add_pin ("store", & this->store_pin);
add_attribute ("store", & this->store_pin, "pin");
+ add_attribute_virtual ("pc-size", this,
+ & gprof_component::pc_size_get,
+ & gprof_component::pc_size_set,
+ "setting");
add_attribute_virtual ("bucket-size", this,
& gprof_component::bucket_size_get,
& gprof_component::bucket_size_set,
*************** namespace profiling_components
*** 589,594 ****
--- 654,662 ----
add_attribute ("output-file-endianness", & this->output_file_format, "setting");
add_uni_relation ("target-component", & this->target_component);
add_uni_relation ("sim-sched", & this->sim_sched);
+
+ cg_caller_hi_pin.driven (0);
+ cg_callee_hi_pin.driven (0);
}
~gprof_component () throw () { }
};
Index: sid/component/profiling/sw-profile-gprof.xml
===================================================================
RCS file: /cvs/src/src/sid/component/profiling/sw-profile-gprof.xml,v
retrieving revision 1.3
diff -c -p -r1.3 sw-profile-gprof.xml
*** sid/component/profiling/sw-profile-gprof.xml 11 Nov 2002 22:28:29 -0000 1.3
--- sid/component/profiling/sw-profile-gprof.xml 11 May 2006 16:00:35 -0000
***************
*** 8,14 ****
--- 8,16 ----
+
+
***************
*** 17,29 ****
--- 19,35 ----
+
+
+
+
***************
*** 50,56 ****
This component needs to be configured with the target-component
relation. The first element in the relation will be used as the
target of profiling. The value-attribute setting contains the
! name of the target component's attribute that will be collected.
The bucket-size attribute configures the width of the
--- 56,63 ----
This component needs to be configured with the target-component
relation. The first element in the relation will be used as the
target of profiling. The value-attribute setting contains the
! name of the target component's attribute that will be collected. If pc-size is 64, then
! the target component should also have an attribute with the same name suffixed by "-hi"
The bucket-size attribute configures the width of the
***************
*** 58,63 ****
--- 65,74 ----
any samples have been accumulated (if value-count is nonzero).
+ The pc-size attribute configures the width of the
+ program counter in bytes. Valid values are 4 and 8.
+
+
The output-file setting gives the name of the eventual profiling
output file. The output-file-endianness setting determines the
endianness of the gprof formatted output.
***************
*** 75,84 ****
If the target component is unset, or its target attribute does
not result in a valid numeric string, no sample is accumulated.
! Alternately, if the cg-caller and then the cg-callee
pins are driven, the values driven are interpreted as the caller and the
callee PC addresses of a subroutine call event. These events are recorded
! in a dynamic call graph.
If a sample was collected, and falls between the
--- 86,98 ----
If the target component is unset, or its target attribute does
not result in a valid numeric string, no sample is accumulated.
! Alternately, if the cg-caller and perhaps the cg-caller-hi
! and then the cg-callee and perhaps the cg-callee-hi
pins are driven, the values driven are interpreted as the caller and the
callee PC addresses of a subroutine call event. These events are recorded
! in a dynamic call graph. The -hi versions of the cg-caller-pin and
! cg-callee-pin are used to provide 64 bit pc values and, if used,
! must be driven before their counterparts.
If a sample was collected, and falls between the
--------------070600080006060801070403--