This is the mail archive of the sid@sourceware.org mailing list for the SID project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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
2006-05-11  Dave Brolley  <brolley@redhat.com>

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

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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]