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--