[patch][commit] 64 bit support in gprof component

Dave Brolley <[email protected]>
Newsgroups gmane.comp.emulators.sid.devel
Message-ID <[email protected]>
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
sid-gprof.ChangeLog (text/plain, 934 B)
2006-05-11  Dave Brolley  <[email protected]>

	* 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.
sid-gprof.patch.txt (text/plain, 19.3 KB)
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<host_int_4,host_int_4> hitcount_map_t;
!     typedef map<pair<host_int_4,host_int_4>,host_int_4> cg_count_map_t;
      
      // statistics
      struct statistics
--- 95,102 ----
  			 protected no_bus_component,
  			 protected configurable_component
    {
!     typedef map<host_int_8,host_int_4> hitcount_map_t;
!     typedef map<pair<host_int_8,host_int_8>,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<gprof_component> accumulate_pin;
  
+     input_pin cg_caller_hi_pin;
      input_pin cg_caller_pin;
+     input_pin cg_callee_hi_pin;
      callback_pin<gprof_component> cg_callee_pin;
  
      callback_pin<gprof_component> 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 ----
      <defpin name="reset" direction="in" legalvalues="any" behaviors="resetting" />
      <defpin name="sample" direction="in" legalvalues="any" behaviors="data gathering" />
      <defpin name="cg-caller" direction="in" legalvalues="any" behaviors="data gathering" />
+     <defpin name="cg-caller-hi" direction="in" legalvalues="any" behaviors="data gathering" />
      <defpin name="cg-callee" direction="in" legalvalues="any" behaviors="data gathering" />
+     <defpin name="cg-callee-hi" direction="in" legalvalues="any" behaviors="data gathering" />
      <defpin name="store" direction="in" legalvalues="any" behaviors="profile generation" />
  
      <!-- attributes -->
***************
*** 17,29 ****
--- 19,35 ----
      <defattribute name="value-max" category="register" legalvalues="decimal string" behaviors="data gathering" />
      <defattribute name="limit-min" category="setting" legalvalues="decimal string" defaultvalue="0" behaviors="data gathering" />
      <defattribute name="limit-max" category="setting" legalvalues="decimal string" defaultvalue="infinity" behaviors="data gathering" />
+     <defattribute name="bucket-size" category="setting" legalvalues="integer" defaultvalue="1" behaviors="data gathering" />
+     <defattribute name="pc-size" category="setting" legalvalues="4 or 8" defaultvalue="4" behaviors="data gathering" />
      <defattribute name="value-attribute" category="setting" legalvalues="name" defaultvalue="'pc'" behaviors="data gathering" />
      <defattribute name="output-file" category="setting" legalvalues="file name" defaultvalue="'gmon.out'" behaviors="configuration" />
      <defattribute name="output-file-endianness" category="setting" legalvalues="0/1/2/little/big/unknown" defaultvalue="unknown" behaviors="configuration" />
      <defattribute name="reset" category="pin" behaviors="resetting" />
      <defattribute name="sample" category="pin" behaviors="data gathering" />
      <defattribute name="cg-caller" category="pin" behaviors="data gathering" />
+     <defattribute name="cg-caller-hi" category="pin" behaviors="data gathering" />
      <defattribute name="cg-callee" category="pin" behaviors="data gathering" />
+     <defattribute name="cg-callee-hi" category="pin" behaviors="data gathering" />
      <defattribute name="store" category="pin" behaviors="profile generation" />
  
  
***************
*** 50,56 ****
        This component needs to be configured with the <relation>target-component</relation>
        relation.  The first element in the relation will be used as the
        target of profiling.  The <attribute>value-attribute</attribute> setting contains the
!       name of the target component's attribute that will be collected.
        </p>
        <p>
        The <attribute>bucket-size</attribute> attribute configures the width of the
--- 56,63 ----
        This component needs to be configured with the <relation>target-component</relation>
        relation.  The first element in the relation will be used as the
        target of profiling.  The <attribute>value-attribute</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"
        </p>
        <p>
        The <attribute>bucket-size</attribute> attribute configures the width of the
***************
*** 58,63 ****
--- 65,74 ----
        any samples have been accumulated (if <attribute>value-count</attribute> is nonzero).
        </p>
        <p>
+       The <attribute>pc-size</attribute> attribute configures the width of the
+       program counter in bytes.  Valid values are 4 and 8.
+       </p>
+       <p>
        The <attribute>output-file</attribute> setting gives the name of the eventual profiling
        output file.  The <attribute>output-file-endianness</attribute> 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.
        </p>
!       <p>Alternately, if the <pin>cg-caller</pin> and then the <pin>cg-callee</pin>
        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.
        </p>
        <p>
        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.
        </p>
!       <p>Alternately, if the <pin>cg-caller</pin> and perhaps the <pin>cg-caller-hi</pin>
!       and then the <pin>cg-callee</pin> and perhaps the <pin>cg-callee-hi</pin>
        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 <pin>cg-caller-pin</pin> and
!       <pin>cg-callee-pin</pin> are used to provide 64 bit pc values and, if used,
!       must be driven before their counterparts.
        </p>
        <p>
        If a sample was collected, and falls between the
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.