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][rfa] Dynamic Configuration of SID


Hi,

A customer of our showed some interest in dynamic configuration of SID simulations from the point of view of "warming up" the simulator in various situations. This generally means limiting high overhead functionality (tracing, performance analysis, etc.) to areas of the target application which are of greatest interest.

Attached are overviews of external and internal specs of how this could be applied to SID along with a patch which implements the spec.

Comments are appreciated and, as always, I'm looking for approval to commit this work.

Thanks,
Dave
Applying Simulator "Warmup" Techniques in SID
External Specification
==============================================
Simulating program execution using SID can be a useful way to collect
information about the behaviour and performance of an application. For most
existing ports, SID provides cycle counting, an interface for collecting data
for analysis using gprof as well as a variety of options for generating trace
output.

While simulation using these features is useful, it also requires the
simulator to perform extra overhead which can significantly slow down the
simulation. In addition, it is probable that only a portion of the application
being simulated is of interest for analysis. For example, when executing
applications written in C, the C runtime startup code is probably not of
interest.

It would be useful to enable detailed modelling for only the portions of the
application which are of interest. Thus the extra overhead of detailed
modelling would only be applied for a smaller portion of the simulation. The
remaining portion of the simulation would be run without this overhead, so
the simulation as a whole would finish more quickly.

In SID, the following options result in extra overhead for the simulator:

--trace-extract
--trace-semantics
--trace-disassemble
--trace-core
--ulog-level
--ulog-mode
--wrap
--verbose
--trace-counter
--final-insn-count
--gprof
--insn-count=N where N is a small integer

All of these options could be enabled/disabled on demand during the simulation
to provide information only about the parts of the application which are of
interest.

Proposed Interfaces For Controlled Modelling in SID
===================================================
In order for this technique to be useful for analyzing real applications and
algorithms, precise control is necessary. We propose a combination of a SID
command line options and a syscall instruction.

SID Command Line Options
------------------------
We propose the addition of new SID command line options:

--warmup

This option starts SID in "warmup" mode regardless of the specification of the
other options listed above. warmup mode means that all these options are set
to the values which provide maximum simulation speed.

As with most other SID options, if specified before the first --board, then
--warmup applies to all --boards, otherwise, it applies only to the previous
--board.

--profile-config=<profile-name>:<options>
  where <profile-name> is the name being assigned to this group of options
        <options> is one or more options from the list above

This option associates the given set of options with the given profile name.
This profile name may be referenced on a --profile-func option (see below) in
order to activate that set of options for a given function or functions. This
profile name may also be specified using a syscall instruction (see below)
to activate a set of options within a function.

This option may be specified more than once in order to define several
configuration profiles. The position of the option on the command line is
irrelevent. The named profile is available for use by any --board.

--profile-func=<functions>:<profile-name>
  where <functions> is a comma-separated list of function names
        <profile-name> is the name of a profile configuration specified
	on a --profile-config option.
        (see above)

This option automatically reconfigures SID with the specified options whenever
one of the listed functions is entered and restores the previous configuration
when the function exits. This can be used for gathering information about
the execution of specific functions within an application.

--profile-func may be specified more than once to provide different
configurations for different functions. As with most other SID options, if
specified before the first --board, then it applies to all --boards,
otherwise, it applies only to the previous --board.

***NOTE: This option will only work for ports in which the cpu component drives
cg-caller, cg-callee, cg-jump and cg-return pins on calls and branches.
Currently, no port does this.

--warmup-func=<functions>
  where <functions> is a comma-separated list of function names

  This option automatically returns SID to warmup mode whenever one of the
  listed functions is entered and restores the previous configuration when
  the function exits.

--warmup-func may be specified more than once. As with most other SID options,
if specified before the first --board, then it applies to all --boards,
otherwise, it applies only to the previous --board.

***NOTE: This option will only work for ports in which the cpu component drives
cg-caller, cg-callee, cg-jump and cg-return pins on calls and branches.
Currently, no port does this.

Syscall Instruction
-------------------
For finer control at the instruction level, we propose a system call.

A system call number which is curently not
in use would be selected. We propose the use of syscall number 0 since it is
likely that it can be specified on the system call instruction of all existing
ports.

The API for this system call would be:

On Entry:
  Argument 1: Configuration mode
      0 -- warmup: The above options are automatically set to the
           values which result in maximum simulation speed for the cpu
           making the call.
      1 -- set: Used to set specific configuration options.
           Argument 2 is a pointer to a nul terminated string containing the
	   name of a profile configuration specified by --profile-config.
	   The syscall dynamically reconfigures SID
           to reflect the options specified by the given profile configuration
	   for the cpu which executes the syscall.
      2 -- reset: Used to restore a previous configuration setting.
           Argument 2 is a configuration handle returned from a previous call
	   to this syscall insn by the cpu making the call. The configuration
	   is restored to the state represented by that handle.
On Exit:
  Return Value: The configuration handle of the previous configuration. This
      value may be used in a subsequent call to restore a previous
      configuration for the cpu making the call. If there is an error, the
      handle of the current configuration will be returned.

  Error code:
      0 of no error
      If mode was 1 (set) a non zero value indicates that the profile
        configuration name was not valid.
      If mode was 2 (reset) a non zero value indicates that the configuration
        handle was not valid.

This system call may be made in a function specified on a --profile-func option
(see above). If so, the configuration which existed prior to calling the
function will automatically be restored when the function exits.

System call access from C/C++
-----------------------------
The libgloss implementation for a given port may provide access to the system
call from C/C++ by implementing the following function:

  #define _SID_CONFIG_WARMUP 0
  #define _SID_CONFIG_SET 1
  #define _SID_CONFIG_RESET 2
  unsigned _Sid_config (unsigned mode, ...);

The arguments to _Sid_config correspond directly to the interface of the
system call instruction above:

  If 'mode' is _SID_CONFIG_WARMUP, then no further arguments are expected.

  If 'mode' is _SID_CONFIG_SET, then a second  argument of type
  'const char *' is expected to contain the name of a configuration profile
  specified on --profile-config and a third argument of type 'unsigned *' is
  expected for returning the error code.

  If mode is _SID_CONFIG_RESET, a second argument of type 'unsigned'
  is expected to contain the configuration handle and a third argument of type
  'unsigned *' is expected for returning the error code.

  The return value will be a handle for the previous configuration. If there
  are errors, then the handle of the current configuration will be returned.

If provided, the implementation of _Sid_config should simply make the
appropriate system call for the target.

Examples:
=========
NOTES:
------
o The examples below are for the xstormy16. Other ports will use different
  --board and --cpu flags and may use a different system call interface.

o The examples using --profile-func and --warmup-func depend upon the cpu
component of the port driving the cg-caller, cg-callee, cg-jump and cg-return
pins on calls and branches. Currently, no port does this.

o The examples using _Sid_config depend on the existence of the function
  Sid_config in the libgloss implementation for the port. Currently no ports
  implement this function. Similar examples could be constructed using 'asm'
  statements to make the system calls directly.

Example 1: Profile the entire simulation
----------------------------------------
  sid --gprof=gprof.out,cycles=1 --trace-disassemble --trace-counter \
      --board=basic --cpu=xstormy16 --memory-region=0x0,0x100000 --load=a.out

This example behaves as SID does today. It collects gprof data and dumps a
trace of the disassembly and cycle count for the entire simulation.

Example 2: Trace and Profile part of one function as specified on the command line
----------------------------------------------------------------------------------
  sid --warmup \
      --profile-config=myprofile:"--gprof=gprof.out,cycles=1 --trace-disassemble --trace-counter" \
      --board=basic --cpu=xstormy16 --memory-region=0x0,0x100000 --load=a.out

If function f in a.out looks as follows:

	.data
pname:	.ascii "myprofile"
	.text
	.p2align 1
	.globl f
	.type	f, @function
f:
	# enable profiling as specified by myprofile
	mov	r1,#1
	mov.w	r2,#pname
	.byte 0x01
	.byte 0x00

	....
	# code to be tested goes here
	....

	# Restore the simulation to warmup mode
	mov     r1,#0
	.byte 0x01
	.byte 0x00
	
	#return 0
	mov	r2, #0
	ret
   
This example will collect gprof data and dump a trace of the disassembly
and cycle count during the execution of the function f and then restore the
simulator to the previous state (warmup mode) before returning.

Example 2a: Trace and Profile part of one function as specified on the command line
-----------------------------------------------------------------------------------
This example is the same as example 2, except that it uses the 'reset' mode of the syscall
to restore the previous configuration after profiling.

  sid --warmup \
      --profile-config=myprofile:"--gprof=gprof.out,cycles=1 --trace-disassemble --trace-counter" \
      --board=basic --cpu=xstormy16 --memory-region=0x0,0x100000 --load=a.out

If function f in a.out looks as follows:

	.data
pname:	.ascii "myprofile"
	.text
	.p2align 1
	.globl f
	.type	f, @function
f:
	# enable profiling as specified by myprofile
	mov	r1,#1
	mov.w	r2,#pname
	.byte 0x01
	.byte 0x00
	# handle for previous configuration is in r2

	....
	# code to be tested goes here
	# must preserve r2
	....

	# Restore the simulation to the previous mode
	# r2 contains the handle of the previous configuration
	mov     r1,#2
	.byte 0x01
	.byte 0x00
	
	#return 0
	mov	r2, #0
	ret
   
Example 3: Collect gprof=<file>,cycles=1 data for one function and then
restore the previous configuration
-----------------------------------------------------------------------
  sid --warmup \
      --board=basic --cpu=xstormy16 --memory-region=0x0,0x100000 \
      --profile-func=test_function,myprofile \
      --profile-config=myprofile:"--gprof=gprof.out,cycles=1 --final-insn-count" \
      --load=a.out

  test.c:
  -------
	main ()
	{
	  non_profiled_function ();
	  test_function ();
	  another_non_profiled_function ();
        }
   
This example will collect gprof data during the execution of test_function and
then restore the simulator to warmup mode before returning. Note that no
source code changes are necessary in this example.

Example 4: Cache Priming
------------------------
It may be useful in some situations to run a function once without profiling
in order to prime the instruction cache and/or data cache before turning on
profiling:

  sid --warmup \
      --profile-config=myprofile:"--gprof=gprof.out,cycles=1 --final-insn-count" \
      --board=basic --cpu=xstormy16 --memory-region=0x0,0x100000 --load=a.out

  test.c:
  -------
	main ()
	{
          unsigned ix;
          const char *set_error;
          unsigned reset_error;

          /* warm up the test function */
	  test_function ();

          /* Reconfigure for profiling */
	  ix = _Sid_config (_SID_CONFIG_SET, "myprofile", & set_error);
	  test_function ();

          /* Restore the previous configuration */
	  _Sid_config (_SID_CONFIG_RESET, ix, & reset_error);
        }

Example 5: Excluding a function from profiling
----------------------------------------------
It may be useful to exclude one or more functions from profiling.
For example, one might like to exclude functions which set up the
state of the application being profiled. The example below profiles
'main' and all functions which it calls except for 'setup_function':

  sid --warmup \
      --profile-config=myprofile:"--gprof=gprof.out,cycles=1 --final-insn-count" \
      --profile-func=main:myprofile \
      --warmup-func=setup_function \
      --board=basic --cpu=xstormy16 --memory-region=0x0,0x100000 --load=a.out

  test.c:
  -------
	main ()
	{
	  int i;
	  for (i = 0; i < 100; ++i)
	  {
	    setup_function (i);
	    test_function ();
	  }
        }
Applying Simulator "Warmup" Techniques in SID
Internal Specification
=============================================
The behavior described in the document sid-warmup-external-spec.txt can be
realized in SID by implementing the following:

cfgroot_component
-----------------
o Add a mapping from configuration name to configuration spec.

o Add an attribute "dynamic-config". When set with a value of the form

    <name>:<spec>

  it adds the name/spec pair to the mapping. This corresponds to the
  command line option --profile-config.

o Add an attribute "lookup-dynamic-config". When set, assume the value is the
  name of a config in the mapping and look it up. If found make the spec
  available via the "found-dynamic-config" attribute.

dynamic_config component (new)
------------------------------
o One of these is allocated for each --board. It manages the configuration of
  that --board including:
  - configuration on demand via the configuration syscall
  - configuration on function entry/exit

o This component maintains a table of configurations which have been used by
  its --board. The index of each configuration in the table is its handle.

o This component maintains a mapping of function names to config spec names.
  This mapping is established by setting the profile-functions! attribute with
  strings of the form

    <function-name>[,<function-name]*:<config-name>

  The attribute may be set more than once and will accumulate pairs in the
  mapping. This corresponds to the command line option --profile-func.

o This component maintains a list of functions which should be run in
  warmup mode. This list is established by setting the warmup-functions!
  attribute with strings of the form

    <function-name>[,<function-name]*

  The attribute may be set more than once and will accumulate pairs in the
  mapping. This corresponds to the command line option --warmup-func.

o This component maintains a function call stack containing the handle of the
  configuration to be used for each function. The correct maintenance of this
  stack depends upon the port driving the cg-caller, cg-callee, cg-jump and
  cg-return pins on function calls, branches and returns. Without this,
  the stack will not be maintained and the --profile-func and --warmup-func
  options will have no effect.

o The configuration is changed by either:
  - setting the configure! attribute with the name of a configuration spec
    known to the cfgroot component.
  - driving the configure! pin with the handle of a configuration in the table.
  - Entering or returning to a function on the function call stack.

o This component maintains a list of configurable client components. When the
  step! pin is driven and the configuration has changed, the dynamic
  configurator sets the "configure!" attribute of each client with the spec of
  the new configuration. Each client is responsible for interpreting the spec
  and reconfiguring itself accordingly.

Individual Components
---------------------
Each component which may be reconfigured inherits from the
configurable_component mix-in base class. This provides each component with
the "configure!" attribute and a virtual method

    void configure (const string &spec);

The spec will be one of

	trace-extract=true|false
	trace-semantics=true|false
	trace-disassemble=true|false
	trace-core=true|false
	trace-counter=true|false
	ulog-level=N
	ulog-mode=greater|less|equal
	wrap=<component-name>[,<component-name>]*
	verbose=true|false
	final-insn-count=true|false
	gprof=<filename>[,N]
	insn-count=N

The implementation of 'configure' for each component should:

1) Call <base_class>::configure (spec)
2) Handle the given spec, if relevent for that component and ignore it
   otherwise.

Implementation Notes
--------------------
The current implementation provides support for the SID command line options
listed above. Below are some notes regarding the implementation

o No cpu currently drives the cg-caller, cg-callee, cg-jump and cg-return pins
  on function calls, branches and returns. This functionaility has been tested
  using an internal Red Hat port.

o In order to support detection of calls and returns to individual functions,
  the elf loader component now reads the symbol table of the executable and
  supports an interface for determining which function a given address is in.

  When the loader's "function?" pin is driven, the address is checked and the
  name of the function containing that address is made available via the
  loader's "current-function" attribute.

o Since the output filename for the --gprof option may be changed dynamically,
  the gprof component has been enhanced to maintain an array of statistics, one
  entry for each output file. Using dynamic configuration, statistics for
  different parts of the application may now be output to separate files.

o In order to solve timing issues, part of the gprof dynamic configuration
  is achieved by connecting/disconnecting pin connections between the cpu
  component and the gprof component. For this reason, the gprof component is
  not registered as a client of the dynamic configurator component. The
  gprof component's dynamic configuration is triggered from the cpu
  component's 'configure' method. The cpu component sets the gprof component's
  "configure!" attribute.
sid/main/dynamic/ChangeLog:
2005-08-04  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:

	2005-07-13  Dave Brolley  <brolley@redhat.com>

	* mepCfg.cxx (set_dynamic_config): New method of MepMemCfg.
	(MepCacheCfg::set_dynamic_config): Don't use the new-config pin
	or the dynamic-configurator attribute. Instead, relate the cache
	to the dynamic configurator using its client relation.
	(MepBoardCfg::write_config): Likewise for the insn_buffer, dmac,
	hw_engines and peripherals. Call set_dynamic_config for shared_main_mem.
	* mainDynamic.cxx (BoardConfig): New struct type.
	(main): Keep a vector of the boards in board_configs. Call
	set_start_config for each board after all the --wrap options have
	been seen. Call add_wrapped_component to identify each wrapped
	component to the session.
	* commonCfg.h (wrapped_components): New member of SessionCfg.
	(add_wrapped_component): New method of SessionCfg.
	(wrap_config): Likewise.
	* commonCfg.cxx (wrap_config): New method of SessionCfg.
	(profile_config): Use possible_wrap_name to obtain the component
	being wrapped so we can get its name.
	(GdbCfg::write_config): Don't connect the new-config pin or use the
	dynamic-configurator relation. Instead, use the dynamic configurator's
	client relation.
	(BoardCfg::write_config): Likewise. Relate the dynamic configurator
	to gloss.
	* baseCfg.cxx (wrap_component): Now returns AtomicCfg *.
	(possible_wrap_name): Likewise.
	(dynamic_config_for_wrapped_children): Don't connect the dynamic
	configurator's new-config pin to the components or relate the
	dynamic configurator to them. Rather, relate the components to the
	dynamic configurator using its 'client' relation.
	* baseCfg.h (wrap_component): Now returns AtomicCfg *.
	(possible_wrap_name): Likewise.

	2005-07-05  Dave Brolley  <brolley@redhat.com>

	* commonCfg.cxx (BoardCfg::write_load): Connect dynamic configurator's
	"reset" pin to output 2 of reset_net.
	(write_config): Set the "start-config" attribute of the dynamic
	configurator not gloss. Relate "main" to the dynamic configurator
	unconditionally. Connect the "config-error" pins of the dynamic
	configurator and gloss.

	2005-06-30  Dave Brolley  <brolley@redhat.com>

	* mainDynamic.cxx (try_add_gprof): Make sure an argument is specified
	after the comma.

	2005-06-06  Dave Brolley  <brolley@redhat.com>

	* mainDynamic.cxx (need_sess): Now takes 'verbose' argument. Use it
	to initialize sess->verbose. Update all callers.
	(main): Add " --model-busses" to board_start_config instead of
	" --model_busses" (typo).
	* commonCfg.h (need_core_probe): New member of SessionCfg.
	(BoardCfg::dynamic_configurator): Now public.
	* commonCfg.cxx (SessionCfg): Initialize need_core_probe.
	(profile_config): Set need_core_probe for --trace-core. Call
	use_tcl_bridge and possible_wrap_name for --wrap.
	(LoaderCfg): Don't set verbose? attribute here.
	(GlossCfg): Likewise.
	(GdbCfg::write_config): Connect the stub and the socket to the
	dynamic_configurator.
	(BoardCfg): Initialize core_probe and warmup_funcs. Connect the cpu's
	print-insn-summary pin to the shutdown sequence here.
	(BoardCfg::write_load): Connect the dynamic configurator's step! pin
	to the init-sequence's output 6. Set the core_probe's trace?
	attribute. Set the gloss and loader's verbose? attributes.
	(BoardCfg::write_config): Give the dynamic configurator its own
	subscription to sim-sched. Set the cpu's 'main' and core-probe
	relations. Connect gloss, core_probe, loader and all of the board's
	wrapped childred to the dynamic configurator. Check whether components
	are wrapped before connecting them to the dynamic configurator. Don't connect
	the cpu's print-insn-summary pin to the shutdown sequence here.
	* baseCfg.cxx (AtomicCfg): Initialize my_possibly_wrapped.
	(wrap_component): Set my_possibly_wrapped.
	(possible_wrap_name): New static method of AtomicCfg.
	(AtomicCfg::write_construct): Check my_possibly_wrapped. Set
	victim-trace? to false if only possibly wrapped.
	(dynamic_config_for_wrapped_children): New method of AggregateCfg.
	* baseCfg.h (possible_wrap_name): New static method of AtomicCfg.
	(possibly_wrapped): New method of AtomicCfg.
	(my_possibly_wrapped): New member of AtomicCfg.
	(dynamic_config_for_wrapped_children): New method of AggregateCfg.

	2005-05-29  Dave Brolley  <brolley@redhat.com>

	* mainDynamic.cxx (usage): Document --profile-config,--profile-func,
	--warmup-func and --warmup.
	(Defs): Initialize warmup, profile_func and start_config.
	(warmup,profile_func,warmup_func,start_config): New members of Defs.
	(need_sess): Call profile_config with "sid-internal-warmup:".
	(opt_warmup,opt_warmup_func,opt_profile_func,opt_profile_config): New
	enumerators.
	(long_options): Add --profile-config,--profile-func,
	--warmup-func and --warmup.
	(main): Accumulate start_config with reconfigurable options which occur
	before the first --board. For each board call set_start_config with
	the value of start_config concatenated with the additional reconfigurable
	options specified for that --board. Call set_warmup, add_warmup_func and
	add_profile_func for each board. Handle new option enums.
	* commonCfg.h (add_profile_config): New method of SessionCfg.
	(profile_config_error, profile_opt_value, profile_opt_int_value) 
	(profile_opt_gprof_value, match_profile_opt, profile_config): New
	methods of SessionCfg.
	(GprofCfg): New constructor.
	(write_load): New virtual override in BoardCfg.
	(add_profile_func, add_warmup_func, set_warmup, set_start_config): New
	methods of BoardCfg.
	(need_gprof): New member of BoardCfg.
	(start_config,warmup_funcs,profile_funcs): New members of BoardCfg.
	* commonCfg.cxx (SessionCfg): Initialize need_gprof.
	(add_profile_config): New method of SessionCfg.
	(profile_config_error, profile_opt_value, profile_opt_int_value) 
	(profile_opt_gprof_value, match_profile_opt, profile_config): New
	methods of SessionCfg.
	(GprofCfg): Always add a sunscription to sim_sched. Set the
	sim-sched-event attribute.
	(GprofCfg): New constructor.
	(BoardCfg): Initialize dynamic_configurator and start_config.
	(write_load): New virtual override in BoardCfg.
	(BoardCfg::write_config): Make connections and set attributes to allow
	for dynamic configuration.
	(add_profile_func, add_warmup_func, set_warmup, set_start_config): New
	methods of BoardCfg.

sid/include/ChangeLog:
2005-08-04  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:

	2005-07-13  Dave Brolley  <brolley@redhat.com>

	* sidcpuutil.h (num_cycles): New member of basic_cpu.
	(step_pin_handler): Call configure_gprof.
	(cg_profile): Call last_caller and last_callee.
	(cg_profile_jump): Call last_caller and last_callee.
	(configure_gprof): New method of basic_cpu.
	(unconfigure_gprof): New method of basic_cpu.
	(gprof_configured_p,configure_gprof_p,last_caller,last_callee)
	(pprof_spec): New members of basic_cpu.
	(configure): Call configure_gprof.
	(basic_cpu): Initialize gprof_configured_p, configure_gprof_p,
	last_caller and last_callee.
	* sidattrutil.h (configurable_component): Moved here ...
	* sidcomputil.h (configurable_component): ... from here.
	* sidbusutil.h (bus_arbitrator): Inherit from no_relation_component.

	2005-06-24  Dave Brolley  <brolley@redhat.com>

	* sidattrutil.h (fixed_attribute_map_with_logging_component): 
	Initialize buffer_output to false.

	2005-06-21  Dave Brolley  <brolley@redhat.com>

	* sidcpuutil.h (basic_cpu::configure): Call update_final_insn_count_p
	after processing "final-insn-count".

	2005-06-06  Dave Brolley  <brolley@redhat.com>

	* sidcpuutil.h (print_final_insn_count_p): New member of basic_cpu.
	(print_insn_summary): Check print_final_insn_count_p.
	(update_final_insn_count_p): New method of basic_cpu.
	(core_probe,main); New members of basic_cpu.
	(basic_cpu::configure): Handle insn-count, verbose, trace-core,
	trace-counter, trace-extract, trace-semantics and final-insn-count.
	(stream_state): Stream print_final_insn_count_p.
	(destream_state): Destream print_final_insn_count_p.
	(basic_cpu): Initialize core_probe and main. Initialize
	print_final_insn_count_p. Add final-insn-count? using
	add_attribute_notify. Add relations core-probe and main.
	* sidcomputil.h (configurable_component::configure_pin_handler): Now
	virtual.

	2005-05-29  Dave Brolley  <brolley@redhat.com>

	* sidcpuutil.h (basic_cpu): New inherits from configurable_component.
	(cg_jump_pin,cg_return_pin): New members of basic_cpu.
	(cg_profile_jump): New method of basic_cpu.
	(configure): New virtual override on basic_cpu.
	(basic_cpu): Initialize gprof. Add cg-return and cg-jump pins. Add
	gprof relation.
	* sidcomputil.h (configurable_component): New mix-in class for components.
	* sidattrutil.h (sidcomputil.h): #include it.
	(fixed_attribute_map_with_logging_component): Inherit from
	configurable_component.
	(configure): New virtual override in
	fixed_attribute_map_with_logging_component.

sid/component/tcl/ChangeLog:
2005-08-04  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:

	2005-07-13  Dave Brolley  <brolley@redhat.com>

	* compTcl.cxx (set_attribute_value): Handle the configure! attribute.
	(find_pin): Don't handle the configure! pin.
	(relate): Don't handle the dynamic-configurator relation.
	(unrelate): Likewise.
	(configure_pin_handler): Removed.

	2005-06-06  Dave Brolley  <brolley@redhat.com>

	* sid-api-trace.tcl (attribute_value): Handle component-type and victim
	attributes.
	* compTcl.cxx (tcl_component): component and configurable_component
	inherited virtually.
	(victim_name): New member of tcl_component.
	(set_attrinute_value): Handle victim-name attribute.
	(find_pin): Handle the "configure" pin specially.
	(relate): Handle the dynamic-configurator relation specially.
	(unrelate): Likewise.
	(configure_pin_handler,configure): New virtual overrides in
	tcl_component.

sid/component/profiling/ChangeLog:
2005-08-04  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:

	2005-07-13  Dave Brolley  <brolley@redhat.com>

	* gprof.cxx (gprof_component): Inherit virtually from
	fixed_attribute_map_component.

	2005-05-29  Dave Brolley  <brolley@redhat.com>

	* gprof.cxx: Keep a vector of statistics to allow switching from
	one output file to another dynamically.
	(sid::pin,sidutil::configurable_component)
	(sidutil::output_pin,sidutil::tokenize): Add using clauses.
	(profiling_components): Inherit virtually from fixed_pin_map_component
	and fixed_relation_map_component. Inherit from configurable_component.
	(statistics): New struct type.
	(stats,current_stats): New members of gprof_component.
	(set_nothing,value_min_get,value_max_get,value_count_get,limit_min_get)
	(limit_min_set,limit_max_get,limit_max_set,output_file_get)
	(output_file_set): New methods of gprof_component.
	(reset): Initialize stats vector.
	(store): Call store stats for each element of the stats vector.
	(configure): New virtual override in gprof_component.
	(gprof_component): Call reset. Add sim-sched-event attribute. Add
	sim-sched relation.

sid/component/loader/ChangeLog:
2005-08-04  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:

	2005-07-13  Dave Brolley  <brolley@redhat.com>

	* compLoader.cxx (generic_loader): Inherit virtually from
	fixed_attribute_map_component. Inherit from no_relation_component.

	2005-06-06  Dave Brolley  <brolley@redhat.com>

	* elfload.c (readElfFile): Return and empty symbol table if none found.

	* compLoader.cxx: Add using cleause for
	sidutil::configurable_component.
	(generic_loader): fixed_pin_map_component and configurable_component
	inherited virtually.
	(configure): New virtual override in generic_loader.
	(check_function_pin_handler): Return the empty string if no function
	is associated with the given address.
	* sw-load-elf.xml: Add description of new interfaces.
	* sw-load-elf.txt: Regenerated.

	2005-05-29  Dave Brolley  <brolley@redhat.com>

	* elfload.h (StringTable, Symbol): New struct types.
	(readElfFile): New takes symbol_table argument.
	(SHT_SYMTAB, SHT_STRTAB, ELF32_ST_TYPE, STT_FUNC): New macros.
	* elfload.c (stringTables,stringTableCount,stringTableNum): New
	static variables.
	(newStringTable): New static function.
	(symbolTable,symbolCount,symbolNum): New static variables.
	(newSymbol): New static function.
	(readElfFile): New takes symbol_table argument. Build string tables and
	symbol table while reading the input file.
	* compLoader.cxx (elf_loader): New constructor.
	(load_it): Obtain symmol_table from readElfFile.
	(check_function_pin,symbol_table,current_function): New members
	of elf_loader.
	(check_function_pin_handler): New method of elf_loader.

sid/component/gloss/ChangeLog:
2005-08-04  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:

	2005-07-13  Dave Brolley  <brolley@redhat.com>

	* gloss.cxx (gloss32): Initialize dynamic_configurator. Add
	dynamic-configurator relation.
	* gloss.h (gloss32): Inherit virtually from
	fixed_attribute_map_component.
	(dynamic_configurator): New member of gloss32.

	2005-07-05  Dave Brolley  <brolley@redhat.com>

	* gloss.cxx (start_config): Removed from gloss32.
	(gloss32): Remove "start-config" attribute. Add "config-error"
	pin.
	(reset): Don't call sys_config_set.
	(sys_reconfig_set): Call set_error_result based on the value driven on
	config_error_pin.
	(sys_reconfig_reset): Likewise.
	* gloss.h (start_config): Removed from gloss32.
	(config_error_pin): New member of gloss32.

	2005-06-06  Dave Brolley  <brolley@redhat.com>

	* gloss.cxx (gloss32): Don't initialize dynamic_configurator.
	Don't add dynamic-configurator relation.
	(configure_pin): Renamed to sys_configure_pin.
	(configure): New virtual override in gloss32.
	(do_sys_reconfig): Print log messages to cerr and only when
	verbose_p.
	* gloss.h (gloss32): fixed_pin_map_component and configurable_component
	inherited virtually.
	(dynamic_configurator): Removed.
	(configure_pin): Renamed to sys_configure_pin.
	(configure): New virtual override in gloss32.

	2005-05-29  Dave Brolley  <brolley@redhat.com>

	* libgloss.h (SYS_reconfig): New enumerator.
	* gloss.h (main, dynamic_configurator): New members of gloss32.
	(configure_pin, config_result_pin, start_config): Likewise.
	(sys_reconfig_set): New method of gloss32.
	(sys_reconfig_reset, do_sys_reconfig): Likewise.
	* gloss.cxx (gloss32): Initialize main, dynamic_configurator and
	start_config. Add relations main, dynamic-configurator. Add
	configure pin. Add start-config addtribute. Add config-result
	pin.
	(reset): Call sys_reconfig_set with start_config if it's not
	empty.
	(syscall_trap): Handle SYS_reconfig.
	(sys_reconfig_set): New method of gloss32.
	(sys_reconfig_reset, do_sys_reconfig): Likewise.

sid/component/gdb/ChangeLog:
2005-08-04  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:

	2005-07-13  Dave Brolley  <brolley@redhat.com>

	* gdb.h (configurable_component): Inherit virtually from
	fixed_attribute_map_component.

	2005-06-06  Dave Brolley  <brolley@redhat.com>

	* gdb.cxx (configure): New virtual override in gdb.
	* gdb.h (configure): Likewise.
	(gdb): fixed_pin_map_component, fixed_relation_map_component and
	configurable_component inherited virtually.
	* sw-debug-gdb.xml: Add description of new interfaces.
	* sw-debug-gdb.txt: Regenerated.

sid/component/consoles/ChangeLog:
2005-08-04  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:

	2005-07-13  Dave Brolley  <brolley@redhat.com>

	* components.h (socketio): Inherit virtually from
	fixed_attribute_map_component. Inherit from no_relation_component.

	2005-06-06  Dave Brolley  <brolley@redhat.com>

	* components.h: Add using clause for sidutil::configurable_component.
	(socketio): fixed_pin_map_component and configurable_component inherited
	virtually. no_relation_component no longer inherited.
	(configure): New virtual override in socketio.
	* socketio.cxx (configure): Likewise.
	* sid-io-socket.xml: Add description of new interfaces.
	* sid-io-socket.txt: Regenerated.

sid/component/cgen-cpu/ChangeLog:
2005-08-04  Dave Brolley  <brolley@redhat.com>

	* Contribute the following changes:

	2005-07-13  Dave Brolley  <brolley@redhat.com>

	* cgen-cpu.h (notify_ret): Set last_caller and last_callee.

	2005-05-29  Dave Brolley  <brolley@redhat.com>

	* cgen-cpu.h (branch, done_insn, done_cti_insn, notify_ret): 
	New virtual overrides.
	(was_return): New member of cgen_bi_endian_cpu.

sid/component/cfgroot/ChangeLog:
2005-08-04  Dave Brolley  <brolley@redhat.com>

	* Contribute these changes:

	2005-07-13  Dave Brolley  <brolley@redhat.com>

	* compConfig.cxx (new_config_pin): Removed from
	dynamic_configurator_component.
	(clients): Added to dynamic_configurator_component.
	(dynamic_configurator_component): Remove new-config pin. Add
	clients as a multi relation.
	(step_pin_handler): Set the configure! attribute of each component
	related via the client relationship.
	(do_configure): Set config_names[0] and config_specs[0] if the
	handle is zero.
	* sid-control-dynamic-configurator.xml: Document the removal of the
	new-config pin and the addition of the clients relationship.
	* sid-control-dynamic-configurator.txt: Regenerated.

	2005-07-05  Dave Brolley  <brolley@redhat.com>

	* compConfig.cxx (reset_pin_handler): New method of
	dynamic_configurator_component.
	(set_start_config): Likewise.
	(reset): Likewise.
	(reset_pin): New member of dynamic_configurator_component.
	(config_error_pin): Likewise.
	(dynamic_configurator_component): Initialize current_config, prev_config
	and prev_user_config in the reset method. Add "start-config" attribute.
	Add "reset" and "config-error" pins.
	(configure): Check result of do_configure. Drive config_error_pin if not
	ok.
	(configure_pin_handler): Drive config_error_pin if the handle is not
	valid.
	* sid-control-dynamic-configurator.xml: Document the "config-error" and "reset"
	pins
	* sid-control-dynamic-configurator.txt: Regenerated.

	2005-06-21  Dave Brolley  <brolley@redhat.com>

	* compConfig.cxx (step_pin_handler): Always drive new_config_pin.

	2005-06-06  Dave Brolley  <brolley@redhat.com>

	* Makefile.am (pkgdata_DATA): Add sid-control-dynamic-configurator.txt.
	* Makefile.in: Regenerated.
	* compConfig.cxx (cfgroot_component::configure): Renamed to
	configure_file.
	(restore_config,set_syscall_config,check_config_change): New methods of
	dynamic_configurator_component.
	(in_function): Likewise.
	(prev_user_config): New member of dynamic_configurator_component.
	(dynamic_configurator_component): Prime the config_stack with a dummy
	entry.
	(add_warmup_functions): Tokenize based on ",".
	(add_profile_functions): Move on to the next spec on parse error.
	(dynamic_configurator_component::configure): Drive config_result_pin with
	prev_user_config. Call set_syscall_config and check_config_change.
	(do_configure): Don't drive the config_result_pin here. Don't drive the
	step_control_pin here. Duplicate the first stack entry for the first
	config in the dummy entry of the stack. Now takes a reference to a
	config handle.
	(configure_pin_handler): Drive the config_result_pin with prev_user_config.
	Call restore_config, sys_syscall_config and check_config_change.
	(function_callee_pin_handler): Always use sid-internal-warmup for _Sid_config.
	(function_return_pin_handler): Return if the loader can't identify the current
	function. Call restore_config and check_config_change.
	* sid-control-dynamic-configurator.txt: New file.
	* sid-control-dynamic-configurator.xml: New file.

	2005-05-29  Dave Brolley  <brolley@redhat.com>

	* compConfig.cxx (std::pair,sidutil::tokenize): Add using clause for these.
	(dynamic_config,lookup_dynamic_config): New methods of cfgroot_component.
	(dynamic_configs,found_dynamic_config): New members of cfgroot_component.
	(configure_line): Initialize num_invalid_chars.
	(cfgroot_component): Initialize dynamic_configs and found_dynamic_config.
	Add virtual attributes dynamic-config! and lookup-dynamic-config!. Add
	attribute found-dynamic-config.
	(dynamic_configurator_component): New class.
	(compConfigListTypes): Push back sid-control-dynamic-configurator.
	(compConfigCreate): Handle sid-control-dynamic-configurator.
	(compConfigDelete): Delete dynamic_configurator_component.

? sid/component/cfgroot/sid-control-dynamic-configurator.txt
? sid/component/cfgroot/sid-control-dynamic-configurator.xml
Index: sid/component/cfgroot/Makefile.am
===================================================================
RCS file: /cvs/src/src/sid/component/cfgroot/Makefile.am,v
retrieving revision 1.6
diff -c -p -r1.6 Makefile.am
*** sid/component/cfgroot/Makefile.am	29 Apr 2004 20:26:58 -0000	1.6
--- sid/component/cfgroot/Makefile.am	4 Aug 2005 18:32:38 -0000
*************** libconfig_la_LDFLAGS = -module -no-undef
*** 14,20 ****
  libconfig_la_LIBADD = @LIBLTDL@
  libconfig_la_DEPENDENCIES = @LIBLTDL@
  
! pkgdata_DATA = sid-control-cfgroot.txt
  
  DEJAGNUTESTS=badconf.exp
  check-local: all
--- 14,20 ----
  libconfig_la_LIBADD = @LIBLTDL@
  libconfig_la_DEPENDENCIES = @LIBLTDL@
  
! pkgdata_DATA = sid-control-cfgroot.txt sid-control-dynamic-configurator.txt
  
  DEJAGNUTESTS=badconf.exp
  check-local: all
Index: sid/component/cfgroot/compConfig.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/cfgroot/compConfig.cxx,v
retrieving revision 1.9
diff -c -p -r1.9 compConfig.cxx
*** sid/component/cfgroot/compConfig.cxx	29 Apr 2004 20:26:58 -0000	1.9
--- sid/component/cfgroot/compConfig.cxx	4 Aug 2005 18:32:38 -0000
***************
*** 1,7 ****
  // compConfig.cxx - The cfgroot component: configuration parsing, root
  // of component creation and management.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
--- 1,7 ----
  // compConfig.cxx - The cfgroot component: configuration parsing, root
  // of component creation and management.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 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.
  
***************
*** 38,43 ****
--- 38,44 ----
  #endif
  
  using std::map;
+ using std::pair;
  using std::vector;
  using std::string;
  using std::ostream;
*************** using sidutil::std_error_string;
*** 75,80 ****
--- 76,82 ----
  using sidutil::recursion_limited;
  using sidutil::recursion_record;
  using sidutil::find_sid_data_file;
+ using sidutil::tokenize;
  
  
  // This component reads a flat config file, and acts as a root
*************** protected:
*** 99,106 ****
    void stop (host_int_4); // stop top-level simulation loop
  
    // config-file! and config-line! virtual attribute handlers
!   component::status configure(const std::string&);
    component::status configure_line(const std::string&);
    string nothing ();
  
    // parser
--- 101,110 ----
    void stop (host_int_4); // stop top-level simulation loop
  
    // config-file! and config-line! virtual attribute handlers
!   component::status configure_file(const std::string&);
    component::status configure_line(const std::string&);
+   component::status dynamic_config(const std::string&);
+   component::status lookup_dynamic_config(const std::string&);
    string nothing ();
  
    // parser
*************** private:
*** 179,184 ****
--- 183,191 ----
    typedef map<string,component_library*> component_creator_map_t;
    component_creator_map_t component_creator_map;
  
+   // Dynamic configurations
+   map<string,string> dynamic_configs;
+   string found_dynamic_config;
  #ifndef NDEBUG
    void crash() { abort(); }
  #endif
*************** cfgroot_component::nothing()
*** 491,497 ****
  
  
  component::status
! cfgroot_component::configure(const std::string& name)
  {
    string last_config_file = this->config_file;
    this->config_file = name;
--- 498,504 ----
  
  
  component::status
! cfgroot_component::configure_file(const std::string& name)
  {
    string last_config_file = this->config_file;
    this->config_file = name;
*************** cfgroot_component::configure_line(const 
*** 529,534 ****
--- 536,542 ----
    this->config_file_history += this->config_file;
    unsigned last_line_num = this->line_num;
    this->line_num = 1;
+   num_invalid_chars = 0;
  
    string line_with_eol = line + "\n";
  
*************** cfgroot_component::configure_line(const 
*** 554,559 ****
--- 562,590 ----
  }
  
  
+ component::status
+ cfgroot_component::dynamic_config(const std::string& spec)
+ {
+   vector<string> parts = tokenize (spec, "|");
+   if (parts.size () != 2)
+     return component::bad_value;
+ 
+   dynamic_configs[parts[0]] = parts[1];
+   return component::ok;
+ }
+ 
+ 
+ component::status
+ cfgroot_component::lookup_dynamic_config(const std::string& name)
+ {
+   if (dynamic_configs.find (name) == dynamic_configs.end())
+     return component::not_found;
+ 
+   found_dynamic_config = name + "|" + dynamic_configs [name];
+   return component::ok;
+ }
+ 
+ 
  cfgroot_component::cfgroot_component():
    recursion_limited ("running", 1),
    running (false),
*************** cfgroot_component::cfgroot_component():
*** 564,570 ****
    stop_pin(this, & cfgroot_component::stop),
    verbose_p (false),
    autoprint_p (true),
!   persistent_p (false)
  {
    // suck in libtool preloaded symbols; must be called before lt_dlinit()
    LTDL_SET_PRELOADED_SYMBOLS ();
--- 595,603 ----
    stop_pin(this, & cfgroot_component::stop),
    verbose_p (false),
    autoprint_p (true),
!   persistent_p (false),
!   dynamic_configs (),
!   found_dynamic_config ("")
  {
    // suck in libtool preloaded symbols; must be called before lt_dlinit()
    LTDL_SET_PRELOADED_SYMBOLS ();
*************** cfgroot_component::cfgroot_component():
*** 609,619 ****
    add_attribute("stopping", & this->stopping_pin, "pin");
  
    add_attribute_virtual ("config-file!", this,
! 			 & cfgroot_component::configure,
  			 & cfgroot_component::nothing);
    add_attribute_virtual ("config-line!", this,
  			 & cfgroot_component::configure_line,
  			 & cfgroot_component::nothing);
    add_attribute_ro ("config-file-history", & this->config_file_history,
                      "register");
    add_attribute("verbose?", & this->verbose_p, "setting");
--- 642,659 ----
    add_attribute("stopping", & this->stopping_pin, "pin");
  
    add_attribute_virtual ("config-file!", this,
! 			 & cfgroot_component::configure_file,
  			 & cfgroot_component::nothing);
    add_attribute_virtual ("config-line!", this,
  			 & cfgroot_component::configure_line,
  			 & cfgroot_component::nothing);
+   add_attribute_virtual ("dynamic-config!", this,
+ 			 & cfgroot_component::dynamic_config,
+ 			 & cfgroot_component::nothing);
+   add_attribute_virtual ("lookup-dynamic-config!", this,
+ 			 & cfgroot_component::lookup_dynamic_config,
+ 			 & cfgroot_component::nothing);
+   add_attribute("found-dynamic-config", & this->found_dynamic_config, "result");
    add_attribute_ro ("config-file-history", & this->config_file_history,
                      "register");
    add_attribute("verbose?", & this->verbose_p, "setting");
*************** cfgroot_component::register_dso(const st
*** 739,745 ****
  
    // At last, try again looking within the executable
    if (dl_handle == 0)
!     dl_handle = lt_dlopen(NULL); // component library linked into executable
  
    if (dl_handle == 0)
      {
--- 779,787 ----
  
    // At last, try again looking within the executable
    if (dl_handle == 0)
!     {
!       dl_handle = lt_dlopen(NULL); // component library linked into executable
!     }
  
    if (dl_handle == 0)
      {
*************** cfgroot_component::inform_component_cata
*** 1172,1178 ****
      }
  }
  
- 
  ostream& 
  operator << (ostream& out, const cfgroot_component& it)
  {
--- 1214,1219 ----
*************** operator >> (istream& in, cfgroot_compon
*** 1202,1209 ****
--- 1243,1748 ----
  
    return in;
  }
+ 
  // -----------------------------------------------------------------------
+ // This component is used to dynamically configure the system.
+ //
+ class dynamic_configurator_component: public virtual component,
+ 					protected fixed_pin_map_component,
+ 					protected fixed_attribute_map_component,
+ 					protected no_bus_component,
+ 					protected no_accessor_component,
+ 					protected fixed_relation_map_component
+ {
+ public:
+   dynamic_configurator_component();
+   virtual ~dynamic_configurator_component() throw() {}
+ protected:
+   void reset_pin_handler(host_int_4 ignore);
+ 
+   component::status add_warmup_functions (const std::string&);
+   component::status add_profile_functions (const std::string&);
+   component::status set_start_config (const std::string&);
+ 
+   component::status configure (const std::string&);
+   component::status do_configure (const std::string &name, const std::string& config, unsigned &handle);
+   unsigned restore_config (unsigned handle);
+   unsigned set_syscall_config (unsigned);
+   void check_config_change (unsigned);
+ 
+   callback_pin<dynamic_configurator_component> reset_pin;
+   callback_pin<dynamic_configurator_component> step_pin;
+   output_pin step_control_pin;
+   callback_pin<dynamic_configurator_component> configure_pin;
+   callback_pin<dynamic_configurator_component> function_caller_pin;
+   callback_pin<dynamic_configurator_component> function_callee_pin;
+   callback_pin<dynamic_configurator_component> function_jump_pin;
+   callback_pin<dynamic_configurator_component> function_return_pin;
+   void step_pin_handler (host_int_4);
+   void configure_pin_handler (host_int_4 handle);
+   void function_caller_pin_handler (host_int_4 addr);
+   void function_callee_pin_handler (host_int_4 addr);
+   void function_jump_pin_handler (host_int_4 addr);
+   void function_return_pin_handler (host_int_4 addr);
+ 
+   output_pin config_result_pin;
+   output_pin config_error_pin;
+   output_pin function_address_pin;
+ 
+   unsigned current_config;
+   unsigned prev_config;
+   unsigned prev_user_config;
+   string get_current_config();
+   bool in_function (const string &name);
+ 
+   vector<string> config_names;
+   vector<string> config_specs;
+   map<string,string> function_configs;
+   vector< pair<string,unsigned> > config_stack;
+ 
+   component *loader;
+   component *main;
+   component_relation_t clients;
+ 
+ private:
+   string get_nothing () { return ""; }
+   component::status set_nothing (const string&) { return component::not_found; }
+   void reset ();
+ };
+ 
+ 
+ dynamic_configurator_component::dynamic_configurator_component ()
+   :
+   reset_pin(this, &dynamic_configurator_component::reset_pin_handler),
+   step_pin (this, &dynamic_configurator_component::step_pin_handler),
+   configure_pin (this, &dynamic_configurator_component::configure_pin_handler),
+   function_caller_pin (this, &dynamic_configurator_component::function_caller_pin_handler),
+   function_callee_pin (this, &dynamic_configurator_component::function_callee_pin_handler),
+   function_jump_pin (this, &dynamic_configurator_component::function_jump_pin_handler),
+   function_return_pin (this, &dynamic_configurator_component::function_return_pin_handler),
+   loader (0),
+   main (0)
+ {
+   add_attribute_virtual ("warmup-functions!", this,
+ 			 & dynamic_configurator_component::add_warmup_functions,
+ 			 & dynamic_configurator_component::get_nothing);
+   add_attribute_virtual ("profile-functions!", this,
+ 			 & dynamic_configurator_component::add_profile_functions,
+ 			 & dynamic_configurator_component::get_nothing);
+   add_attribute_virtual ("start-config", this,
+ 			 & dynamic_configurator_component::set_start_config,
+ 			 & dynamic_configurator_component::get_nothing);
+   add_attribute_virtual ("configure!", this,
+ 			 & dynamic_configurator_component::configure,
+ 			 & dynamic_configurator_component::get_nothing);
+   add_attribute_virtual ("current-config", this,
+ 			 & dynamic_configurator_component::get_current_config,
+ 			 & dynamic_configurator_component::set_nothing);
+   add_pin("reset", &this->reset_pin);
+   add_pin ("step!", &step_pin);
+   add_pin ("step-control", &step_control_pin);
+   add_pin ("configure!", &configure_pin);
+   add_pin ("config-result", &config_result_pin);
+   add_pin ("config-error", &config_error_pin);
+   add_pin ("function-caller!", &function_caller_pin);
+   add_pin ("function-callee!", &function_callee_pin);
+   add_pin ("function-jump!", &function_jump_pin);
+   add_pin ("function-return!", &function_return_pin);
+   add_pin ("function-address", &function_address_pin);
+ 
+   add_uni_relation("loader", &this->loader);
+   add_uni_relation("main", &this->main);
+   add_multi_relation ("client", &this->clients);
+ 
+   config_stack.push_back (pair<string,unsigned> ("<start>", 0));
+   config_names.push_back ("<start>");
+   config_specs.push_back ("");
+ 
+   reset ();
+ }
+ 
+ void
+ dynamic_configurator_component::reset_pin_handler(host_int_4)
+ {
+   reset();
+ }
+ 
+ void
+ dynamic_configurator_component::reset ()
+ {
+   current_config = 0;
+   prev_config = 0;
+   prev_user_config = 0;
+ 
+   while (config_stack.size () > 1)
+     config_stack.pop_back ();
+ 
+   assert (config_names.size () == config_specs.size ());
+   while (config_names.size () > 1)
+     {
+       config_names.pop_back ();
+       config_specs.pop_back ();
+     }
+ 
+   if (config_names[0] != "<start>")
+     {
+       component::status s = main->set_attribute_value ("lookup-dynamic-config!", config_names[0]);
+       if (s == component::ok)
+ 	{
+ 	  string spec = main->attribute_value ("found-dynamic-config");
+ 	  configure (spec);
+ 	}
+     }
+ }
+ 
+ // Set the starting configuration
+ component::status
+ dynamic_configurator_component::set_start_config (const std::string& name)
+ {
+   config_names[0] = name;
+   return component::ok;
+ }
+ 
+ // Add the given list of function names as functions to be simulated in warmup
+ // mode. FUNCS will be a comma-separated list of function names.
+ //
+ component::status
+ dynamic_configurator_component::add_warmup_functions (const std::string& funcs)
+ {
+   vector<string> parts = tokenize (funcs, ",");
+   unsigned size = parts.size ();
+   for (unsigned i = 0; i < size; ++i)
+     function_configs[parts[i]] = "sid-internal-warmup";
+ 
+   return component::ok;
+ }
+ 
+ // Process the given spec and assign the given profile name to
+ // the associated list of functions.
+ // SPEC will be a list of specs separatyed by '|'. Each spec
+ // will be a list of function names separated by commas followed
+ // by a colon and then the name of the profile to associated with
+ // thos functions.
+ //
+ component::status
+ dynamic_configurator_component::add_profile_functions (const std::string& specs)
+ {
+   component::status s = component::ok;
+   vector<string> parts = tokenize (specs, "|");
+   unsigned size = parts.size ();
+   for (unsigned i = 0; i < size; ++i)
+     {
+       vector<string> spec = tokenize (parts[i], ":");
+       if (spec.size () != 2)
+ 	{
+ 	  s = component::bad_value;
+ 	  continue;
+ 	}
+ 
+       const string &profile = spec[1];
+       vector<string> funcs = tokenize (spec[0], ",");
+       unsigned num_funcs = funcs.size ();
+       for (unsigned f = 0; f < num_funcs; ++f)
+ 	function_configs[funcs[f]] = profile;
+     }
+   return s;
+ }
+ 
+ // Drive the config-result pin if the configuration has changed
+ void
+ dynamic_configurator_component::step_pin_handler (host_int_4)
+ {
+   prev_config = current_config;
+ 
+   for (component_relation_t::const_iterator it = clients.begin ();
+        it != clients.end();
+        ++it)
+     (*it)->set_attribute_value ("configure!", config_specs[current_config]);
+ 
+   //  cout << "configured for " << config_names[current_config] + "|" + config_specs[current_config] << endl;
+ }
+ 
+ // Search for the named configuration in the list of previously used ones.
+ // If found, drive the config-result pin with the index of that config.
+ // Otherwise add the new config and drive the pin with the new index.
+ component::status
+ dynamic_configurator_component::configure (const std::string& spec)
+ {
+   vector<string> parts = tokenize (spec, "|");
+   if (parts.size () != 2)
+     return component::bad_value;
+ 
+   // Drive config-result pin with old config regardless of whether it changes.
+   config_result_pin.drive (prev_user_config);
+ 
+   unsigned new_handle;
+   component::status s = do_configure (parts[0], parts[1], new_handle);
+   if (s == component::ok)
+     {
+       new_handle = set_syscall_config (new_handle);
+       check_config_change (new_handle);
+       config_error_pin.drive (0);
+     }
+   else
+     config_error_pin.drive (1);
+ 
+   return s;
+ }
+ 
+ component::status
+ dynamic_configurator_component::do_configure (const std::string &name, const std::string& config, unsigned &new_handle)
+ {
+   // Identify and/or save the new configuration
+   unsigned size = config_names.size ();
+   unsigned handle;
+   for (handle = 0; handle < size; handle++)
+     {
+       if (config_names[handle] == name)
+ 	break;
+     }
+   if (handle >= size)
+     {
+       config_names.push_back (name);
+       config_specs.push_back (config);
+     }
+ 
+   // If this is the first configuration, then also set the
+   // default "<start>" config to this value.
+   if (handle == 0
+       || size == 1 && config_names[0] == "<start>")
+     {
+       config_names[0] = name;
+       config_specs[0] = config;
+     }
+ 
+   new_handle = handle;
+   return component::ok;
+ }
  
+ void
+ dynamic_configurator_component::configure_pin_handler (host_int_4 handle)
+ {
+   // Drive config-result pin with old config regardless of whether it changes.
+   config_result_pin.drive (prev_user_config);
+ 
+   host_int_4 orig_handle = handle;
+   handle = restore_config (handle);
+   config_error_pin.drive (handle != orig_handle);
+   handle = set_syscall_config (handle);
+   check_config_change (handle);
+ }
+ 
+ unsigned
+ dynamic_configurator_component::restore_config (host_int_4 handle)
+ {
+   if (handle >= config_specs.size ())
+     return current_config;
+ 
+   return handle;
+ }
+ 
+ unsigned
+ dynamic_configurator_component::set_syscall_config (unsigned handle)
+ {
+   // For a real syscall, there will be at least 2 entries on the stack.
+   unsigned size = config_stack.size ();
+   if (size <= 1)
+     return handle;
+ 
+   // If the current function is _Sid_config, then change the config
+   // of the function which called _Sid_config, otherwise change the
+   // config of the function on the top of the stack.
+   string top_func = config_stack.back ().first;
+   unsigned top_handle = config_stack.back ().second;
+   config_stack.pop_back ();
+ 
+   if (top_func == "_Sid_config")
+     {
+       assert (size > 2);
+       string next_func = config_stack.back ().first;
+       config_stack.pop_back ();
+       config_stack.push_back (pair<string,unsigned> (next_func, handle));
+       config_stack.push_back (pair<string,unsigned> (top_func, top_handle));
+       return top_handle;
+     }
+ 
+   config_stack.push_back (pair<string,unsigned> (top_func, handle));
+   return handle;
+ }
+ 
+ void
+ dynamic_configurator_component::check_config_change (unsigned handle)
+ {
+   if (handle != prev_user_config)
+     {
+       if (! in_function ("_Sid_config"))
+ 	prev_user_config = handle;
+     }
+ 
+   if (current_config != handle
+       && config_specs[current_config] != config_specs[handle])
+     {
+       current_config = handle;
+       step_control_pin.drive (1); // reconfigure during next cycle
+     }
+ }
+ 
+ void
+ dynamic_configurator_component::function_caller_pin_handler (host_int_4 addr)
+ {
+   if (! loader)
+     return;
+ 
+   // Drive the address on the function-address pin and read the
+   // resulting attribute value from the loader.
+   function_address_pin.drive (addr);
+   string function = loader->attribute_value("current-function");
+ 
+   // If there is no config on the stack, or it is for a different function,
+   // we must have jumped into this function. Treat it as if it was called.
+   if (config_stack.size() == 0 || config_stack.back ().first != function)
+     function_callee_pin_handler (addr);
+ }
+ 
+ void
+ dynamic_configurator_component::function_jump_pin_handler (host_int_4 addr)
+ {
+   if (! loader)
+     return;
+ 
+   // Drive the address on the function-address pin and read the
+   // resulting attribute value from the loader.
+   function_address_pin.drive (addr);
+   string function = loader->attribute_value("current-function");
+ 
+   // If the current function is on the stack, then assume we're
+   // returning to it, otherwise assume we're calling it.
+   for (vector < pair<string,unsigned> >::const_iterator it = config_stack.begin ();
+        it != config_stack.end ();
+        ++it)
+     {
+       if (it->first == function)
+ 	{
+ 	  function_return_pin_handler (addr);
+ 	  return;
+ 	}
+     }
+   function_callee_pin_handler (addr);
+ }
+ 
+ void
+ dynamic_configurator_component::function_callee_pin_handler (host_int_4 addr)
+ {
+   if (! loader)
+     return;
+ 
+   // Drive the address on the function-address pin and read the
+   // resulting attribute value from the loader.
+   function_address_pin.drive (addr);
+   string function = loader->attribute_value("current-function");
+   if (function.empty ())
+     return;
+ 
+   unsigned new_config = current_config;
+   // Make sure that the main component has been related to us.
+   if (main)
+     {
+       component::status s = component::not_found;
+       // If we are in a function called from _Sid_config, then
+       // use the config for _Sid_config (which will be sid-internal-warmup).
+       // Otherwise, look for the function name in function_configs. This mapping will provide
+       // the name of the config spec to be used. We can then use that to obtain
+       // the config handle. If there is no function associated with the given address
+       // or if there has been no config associated with that function, then use the
+       // current_config.
+       if (in_function ("_Sid_config"))
+ 	s = main->set_attribute_value ("lookup-dynamic-config!", "sid-internal-warmup");
+       else
+ 	{
+ 	  map<string,string>::const_iterator it = function_configs.find (function);
+ 	  if (it != function_configs.end())
+ 	    {
+ 	      // Set main's lookup-dynamic-config attribute with the name we're looking
+ 	      // for. main will then write the configuration string into its
+ 	      // found-config-profile attribute if it is found.
+ 	      s = main->set_attribute_value ("lookup-dynamic-config!", it->second);
+ 	    }
+ 	}
+       if (s == component::ok)
+ 	{
+ 	  // Get the config spec and configure using it. Don't use 'configure'
+ 	  // because we want that to be used for the syscall only.
+ 	  string spec = main->attribute_value ("found-dynamic-config");
+ 	  vector<string> parts = tokenize (spec, "|");
+ 	  assert (parts.size () == 2);
+ 	  do_configure (parts[0], parts[1], new_config);
+ 	}
+     }
+ 
+   // Push the function name and config name onto the stack
+   config_stack.push_back (pair<string,unsigned> (function, new_config));
+   check_config_change (new_config); // has been updated
+   //  cout << "called function '" << function << "' has config " << config_names[current_config] << "|" << config_specs[current_config] << endl;
+ }
+ 
+ void
+ dynamic_configurator_component::function_return_pin_handler (host_int_4 addr)
+ {
+   if (! loader)
+     return;
+ 
+   // Drive the address on the function-address pin and read the
+   // resulting attribute value from the loader.
+   function_address_pin.drive (addr);
+   string function = loader->attribute_value("current-function");
+   if (function.empty ())
+     return;
+ 
+   // Pop the function stack until the one we're returning to is on top
+   // or until we've reached the entry for the start.
+   assert (config_stack.size () >= 1);
+   if (config_stack.size () > 1)
+     {
+       config_stack.pop_back ();
+       while (config_stack.size () > 1)
+ 	{
+ 	  if (config_stack.back ().first == function)
+ 	    break;
+ 	  config_stack.pop_back ();
+ 	}
+     }
+ 
+   unsigned new_config = config_stack.back ().second;
+   function = config_stack.back ().first;
+ 
+   // Reconfigure to the saved configuration
+   new_config = restore_config (new_config);
+   check_config_change (new_config);
+ 
+   //  cout << "returned to '" << function << "' with config " << config_names[current_config] << "|" << config_specs[current_config] << endl;
+ }
+ 
+ bool
+ dynamic_configurator_component::in_function (const string &name)
+ {
+   vector< pair<string,unsigned> >::const_iterator it;
+   for (it = config_stack.begin (); it != config_stack.end (); ++it)
+     {
+       if (it->first == name)
+ 	return true;
+     }
+   return false;
+ }
+ 
+ string
+ dynamic_configurator_component::get_current_config()
+ {
+   if (current_config >= config_specs.size ())
+     return "";
+   return config_specs[current_config];
+ }
+ 
+ // -----------------------------------------------------------------------
  static
  vector<string>
  compConfigListTypes()
*************** compConfigListTypes()
*** 1211,1216 ****
--- 1750,1756 ----
    vector<string> types;
    // NB: correlate with type cfgroot_component ctor!
    types.push_back("sid-control-cfgroot");
+   types.push_back("sid-control-dynamic-configurator");
    return types;
  }
  
*************** compConfigCreate(const string& typeName)
*** 1221,1228 ****
  {
    if(typeName == "sid-control-cfgroot")
      return new cfgroot_component();
!   else
!     return 0;
  }
  
  
--- 1761,1769 ----
  {
    if(typeName == "sid-control-cfgroot")
      return new cfgroot_component();
!   if(typeName == "sid-control-dynamic-configurator")
!     return new dynamic_configurator_component();
!   return 0;
  }
  
  
*************** static
*** 1230,1236 ****
  void
  compConfigDelete(component* c)
  {
!   delete dynamic_cast<cfgroot_component*>(c);
  }
  
  
--- 1771,1780 ----
  void
  compConfigDelete(component* c)
  {
!   cfgroot_component* c1 = dynamic_cast<cfgroot_component*>(c);
!   if (c1) { delete c1; return; }
!   dynamic_configurator_component* c2 = dynamic_cast<dynamic_configurator_component*>(c);
!   if (c2) { delete c2; return; }
  }
  
  
Index: sid/component/cfgroot/sid-control-cfgroot.xml
===================================================================
RCS file: /cvs/src/src/sid/component/cfgroot/sid-control-cfgroot.xml,v
retrieving revision 1.2
diff -c -p -r1.2 sid-control-cfgroot.xml
*** sid/component/cfgroot/sid-control-cfgroot.xml	30 May 2002 15:23:59 -0000	1.2
--- sid/component/cfgroot/sid-control-cfgroot.xml	4 Aug 2005 18:32:38 -0000
***************
*** 27,40 ****
      <defattribute name="perform-activity" category="pin" behaviors="main loop" />
      <defattribute name="stop!" category="pin" behaviors="main loop" />
      <defattribute name="stopping" category="pin" behaviors="main loop" />
!     
      
      <!-- relationships -->
      <defrelationship name="component-catalog-informees" behaviors="simulation startup" />
      
    </defcomponent>
  
!   <synop>This component configures and executes a simulation run.
    </synop>
  
    <func>
--- 27,44 ----
      <defattribute name="perform-activity" category="pin" behaviors="main loop" />
      <defattribute name="stop!" category="pin" behaviors="main loop" />
      <defattribute name="stopping" category="pin" behaviors="main loop" />
!     <defattribute name="dynamic-config!"        default="config spec"   behaviors="configuration" />
!     <defattribute name="lookup-dynamic-config!" default="config name"   behaviors="configuration" />
!     <defattribute name="found-dynamic-config"   default="config string" behaviors="configuration" />
      
      <!-- relationships -->
      <defrelationship name="component-catalog-informees" behaviors="simulation startup" />
      
    </defcomponent>
  
!   <synop>This component configures and executes a simulation run. This component also
!     maintains a mapping of configuration names to configuration strings for use by the
!     sid-control-dynamic-configurator components associated with each board.
    </synop>
  
    <func>
*************** rel-name ::= string
*** 229,234 ****
--- 233,251 ----
        to a file, and the file's name supplied to the
        <attribute>config-file!</attribute> attribute.</p>
  
+       <p>
+       When the 
+ 	<attribute>dynamic-config!</attribute> attribute is written to, the value is
+       interpreted as a configuration spec of the form NAME:CONFIG_STRING[|NAME:CONFIG_STRING]*.
+       Each CONFIG_STRING is then associated with the given NAME.</p>
+ 
+       <p>
+       When the 
+ 	<attribute>lookup-dynamic-config!</attribute> attribute is written to, the value is
+       interpreted as a name previously associated with a config string via the 
+       <attribute>dynamic-config!</attribute> attribute.  The associated configuration
+       string is then made available via the <attribute>found-dynamic-config</attribute> attribute.</p>
+ 
      </behavior>
  
      <behavior name="startup">
Index: sid/component/cgen-cpu/cgen-cpu.h
===================================================================
RCS file: /cvs/src/src/sid/component/cgen-cpu/cgen-cpu.h,v
retrieving revision 1.14
diff -c -p -r1.14 cgen-cpu.h
*** sid/component/cgen-cpu/cgen-cpu.h	30 Jun 2005 20:27:23 -0000	1.14
--- sid/component/cgen-cpu/cgen-cpu.h	4 Aug 2005 18:32:38 -0000
***************
*** 1,6 ****
  // cgen-cpu.h  -*- C++ -*-
  
! // Copyright (C) 2000, 2001, 2002, 2003, 2004 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 ----
  // cgen-cpu.h  -*- C++ -*-
  
! // Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
*************** protected:
*** 82,87 ****
--- 82,114 ----
    void trace_counter (PCADDR pc);
  
  public:
+   // Called by semantic code to perform branches.
+   virtual void
+   branch (PCADDR new_pc, PCADDR& npc, sem_status& status)
+   {
+     branch_was_return = false;
+   }
+ 
+   // Called by the semantic code at the end of a non-cti insn.
+   // Make this a NOP; ordinary sequential PC stepping is done
+   // elsewhere.
+   virtual void done_insn (PCADDR npc, sem_status& status) {}
+      
+   // Called by the semantic code at the end of a cti insn.
+   virtual void
+   done_cti_insn (PCADDR npc, sem_status& status)
+   {
+     if (branch_was_return)
+       this->cg_return_pin.drive (npc);
+     branch_was_return = false;
+   }
+ 
+   virtual void notify_ret (sid::host_int_4 addr) { branch_was_return = true; last_caller = addr; last_callee = 0; }
+ 
+ protected:
+   bool branch_was_return;
+ 
+ public:
    cgen_bi_endian_cpu ();
    ~cgen_bi_endian_cpu () throw();
  
Index: sid/component/consoles/components.h
===================================================================
RCS file: /cvs/src/src/sid/component/consoles/components.h,v
retrieving revision 1.4
diff -c -p -r1.4 components.h
*** sid/component/consoles/components.h	10 Jun 2003 18:28:19 -0000	1.4
--- sid/component/consoles/components.h	4 Aug 2005 18:32:38 -0000
***************
*** 1,7 ****
  // file.cxx - Joint header file for nearby component classes.
  // -*- 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.
  
--- 1,7 ----
  // file.cxx - Joint header file for nearby component classes.
  // -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2003, 2005 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
*************** using sidutil::fixed_attribute_map_compo
*** 72,77 ****
--- 72,78 ----
  using sidutil::fixed_pin_map_component;
  using sidutil::no_accessor_component;
  using sidutil::no_relation_component;
+ using sidutil::configurable_component;
  using sidutil::output_pin;
  using sidutil::callback_pin;
  using sidutil::string2stream;
*************** private:
*** 146,155 ****
  
    class socketio: public virtual component,
  		  protected no_bus_component,
! 		  protected fixed_attribute_map_component,
! 		  protected fixed_pin_map_component,
  		  protected no_accessor_component,
  		  protected no_relation_component,
  		  protected recursion_limited
    {
    private:
--- 147,157 ----
  
    class socketio: public virtual component,
  		  protected no_bus_component,
! 		  protected virtual fixed_attribute_map_component,
! 		  protected virtual fixed_pin_map_component,
  		  protected no_accessor_component,
  		  protected no_relation_component,
+ 		  protected virtual configurable_component,
  		  protected recursion_limited
    {
    private:
*************** private:
*** 211,216 ****
--- 213,219 ----
      sid::component::status restore_state (const string& state)
        { return parse_attribute (state, *this); }
  
+     virtual void configure (const string &config);
  
    public:
      socketio (bool server_p);
Index: sid/component/consoles/sid-io-socket.xml
===================================================================
RCS file: /cvs/src/src/sid/component/consoles/sid-io-socket.xml,v
retrieving revision 1.1
diff -c -p -r1.1 sid-io-socket.xml
*** sid/component/consoles/sid-io-socket.xml	3 Aug 2001 01:47:52 -0000	1.1
--- sid/component/consoles/sid-io-socket.xml	4 Aug 2005 18:32:38 -0000
***************
*** 33,38 ****
--- 33,42 ----
      <defattribute name="fini" category="pin" legalvalues="numeric" behaviors="initialization" />
      <defattribute name="tx" category="pin" legalvalues="numeric" behaviors="pin i/o" />
      <defattribute name="rx" category="pin" legalvalues="numeric" behaviors="pin i/o" />
+     <defattribute name="configure!" category="setting" legalvalues="string" behaviors="configuration" />
+ 
+     <!-- relationships -->
+     <defrelationship name="dynamic-configurator"	behaviors="configuration" />
  
      <variants>
        <defcomponent name="sid-io-socket-client" type="concrete" />
***************
*** 159,164 ****
--- 163,177 ----
  
      </behavior>
  
+     <behavior name="configuration">
+       
+       <p>When the <attribute>configure!</attribute> is set, the new value is interpreted
+          as a configuration spec.  The spec is a colon-separated list of items, each of
+          which is passed in turn to the 'configure' method for interpretation and possible
+          action.</p>
+ 
+     </behavior>
+ 
      <convention name="functional" supported="true" />
      <convention name="save/restore" supported="false"/>
      <convention name="triggerpoints" supported="false"/>
Index: sid/component/consoles/socketio.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/consoles/socketio.cxx,v
retrieving revision 1.6
diff -c -p -r1.6 socketio.cxx
*** sid/component/consoles/socketio.cxx	22 Mar 2004 21:26:44 -0000	1.6
--- sid/component/consoles/socketio.cxx	4 Aug 2005 18:32:38 -0000
***************
*** 1,7 ****
  // socketio.cxx - A console that uses a socket to do its I/O.
  // -*- C++ -*-
  
! // Copyright (C) 1999-2002, 2004 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
--- 1,7 ----
  // socketio.cxx - A console that uses a socket to do its I/O.
  // -*- C++ -*-
  
! // Copyright (C) 1999-2002, 2004, 2005 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
*************** socketio::poll ()
*** 599,604 ****
--- 599,619 ----
    this->poll_transmit();
  }
  
+ void
+ socketio::configure (const string &config)
+ {
+   // Call up to the base class first
+   configurable_component::configure (config);
+ 
+   // Now handle relevent configuration for us.
+   if (config.size () <= 8)
+     return;
+   if (config.substr (0, 8) == "verbose=")
+     {
+       verbose_p = (config.substr (8) == "true");
+       return;
+     }
+ }
  
  ostream& 
  operator << (ostream& out, const socketio& it)
Index: sid/component/gdb/gdb.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/gdb/gdb.cxx,v
retrieving revision 1.14
diff -c -p -r1.14 gdb.cxx
*** sid/component/gdb/gdb.cxx	11 Aug 2004 20:59:05 -0000	1.14
--- sid/component/gdb/gdb.cxx	4 Aug 2005 18:32:38 -0000
***************
*** 1,6 ****
  // gdb.cxx - GDB stub implementation.  -*- C++ -*-
  
! // Copyright (C) 1999-2002, 2004 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 ----
  // gdb.cxx - GDB stub implementation.  -*- C++ -*-
  
! // Copyright (C) 1999-2002, 2004, 2005 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
*************** gdb::target_tx_handler (host_int_4 value
*** 1820,1825 ****
--- 1820,1843 ----
  }
  
  
+ void
+ gdb::configure (const string &config)
+ {
+   // Call up to the base class first
+   configurable_component::configure (config);
+ 
+   // Now handle relevent configuration for us.
+   if (config.size () <= 8)
+     return;
+   if (config.substr (0, 8) == "verbose=")
+     {
+       bool verbose_p = (config.substr (8) == "true");
+       trace_gdbserv = verbose_p;
+       trace_gdbsid = verbose_p;
+       return;
+     }
+ }
+ 
  
  gdb::~gdb() throw()
  {
Index: sid/component/gdb/gdb.h
===================================================================
RCS file: /cvs/src/src/sid/component/gdb/gdb.h,v
retrieving revision 1.9
diff -c -p -r1.9 gdb.h
*** sid/component/gdb/gdb.h	8 Jan 2003 03:05:59 -0000	1.9
--- sid/component/gdb/gdb.h	4 Aug 2005 18:32:38 -0000
***************
*** 1,6 ****
  // gdb.h - description.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 2002 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 ----
  // gdb.h - description.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 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.
  
*************** using sidutil::no_bus_component;
*** 54,59 ****
--- 54,60 ----
  using sidutil::no_accessor_component;
  using sidutil::fixed_relation_map_component;
  using sidutil::fixed_pin_map_component;
+ using sidutil::configurable_component;
  using sidutil::callback_pin;
  using sidutil::output_pin;
  using sidutil::input_pin;
*************** using sidutil::map_watchable_name;
*** 67,77 ****
  using sidutil::tokenize;
  
  class gdb: public virtual component,
! 	   public fixed_attribute_map_component,
! 	   public fixed_pin_map_component,
  	   public no_bus_component,
  	   public no_accessor_component,
! 	   public fixed_relation_map_component
  {
  public:
    gdb();
--- 68,79 ----
  using sidutil::tokenize;
  
  class gdb: public virtual component,
! 	   public virtual fixed_attribute_map_component,
! 	   public virtual fixed_pin_map_component,
  	   public no_bus_component,
  	   public no_accessor_component,
! 	   public virtual fixed_relation_map_component,
! 	   public virtual configurable_component
  {
  public:
    gdb();
*************** private:
*** 172,177 ****
--- 174,181 ----
    struct gdbserv* gdbserv;
    struct gdbserv_client* gdbserv_client;
  
+   virtual void configure (const string &config);
+ 
  public:
    // gdbserv_client<->gdb callback hooks
    void gdbsid_client_write (const unsigned char* ch, unsigned len);
Index: sid/component/gdb/sw-debug-gdb.xml
===================================================================
RCS file: /cvs/src/src/sid/component/gdb/sw-debug-gdb.xml,v
retrieving revision 1.2
diff -c -p -r1.2 sw-debug-gdb.xml
*** sid/component/gdb/sw-debug-gdb.xml	8 May 2002 19:15:31 -0000	1.2
--- sid/component/gdb/sw-debug-gdb.xml	4 Aug 2005 18:32:38 -0000
***************
*** 19,24 ****
--- 19,27 ----
      <defpin name="stop-target" direction="in" legalvalues="any" behaviors="execution"/>
      <defpin name="start-target" direction="in" legalvalues="any" behaviors="execution"/>
      <defpin name="deinit" direction="in" legalvalues="any" behaviors="deinitialization"/>
+     <!-- pins -->
+     <!-- relationships -->
+     <defrelationship name="dynamic-configurator"	behaviors="configuration" />
      <!-- attributes -->
      <defattribute name="trace-gdbserv?" legalvalues="boolean" defaultvalue="false" behaviors="setting"/>
      <defattribute name="trace-gdbsid?" legalvalues="boolean" defaultvalue="false" behaviors="setting"/>
***************
*** 31,36 ****
--- 34,40 ----
      <defattribute name="fallback-Z-sw-to-hw?" legalvalues="boolean" defaultvalue="true" behaviors="setting"/>
      <defattribute name="operating-mode?" legalvalues="boolean" defaultvalue="true" behaviors="setting"/>
      <defattribute name="connected?" legalvalues="boolean, read-only" defaultvalue="false" behaviors="execution"/>
+     <defattribute name="configure!" category="setting" legalvalues="string" behaviors="configuration" />
    </defcomponent>
    <synop>
      <p>
***************
*** 196,201 ****
--- 200,215 ----
  	for single stepping.
        </p>
      </behavior>
+ 
+     <behavior name="configuration">
+       
+       <p>When the <attribute>configure!</attribute> is set, the new value is interpreted
+          as a configuration spec.  The spec is a colon-separated list of items, each of
+          which is passed in turn to the 'configure' method for interpretation and possible
+          action.</p>
+ 
+     </behavior>
+ 
      <convention name="functional" supported="true">
      </convention>
      <convention name="save/restore" supported="false">
Index: sid/component/gloss/gloss.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/gloss/gloss.cxx,v
retrieving revision 1.19
diff -c -p -r1.19 gloss.cxx
*** sid/component/gloss/gloss.cxx	22 Nov 2002 20:34:59 -0000	1.19
--- sid/component/gloss/gloss.cxx	4 Aug 2005 18:32:39 -0000
***************
*** 1,6 ****
  // gloss.cxx - Gloss routines.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 2002 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 ----
  // gloss.cxx - Gloss routines.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 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.
  
*************** gloss32::gloss32() :
*** 41,47 ****
--- 41,49 ----
    trap_type_ipin(this, &gloss32::trap_pin_handler),
    rx_pin(this, &gloss32::rx_handler),
    cpu (0),
+   main (0),
    cpu_memory_bus (0),
+   dynamic_configurator (0),
    syscall_numbering_scheme("libgloss"),
    max_fds(32),
    verbose_p(false)
*************** gloss32::gloss32() :
*** 64,69 ****
--- 66,74 ----
    add_attribute_ro_value ("tk tty", string("hw-visual-tty"), "gui");
  
    add_uni_relation("cpu", &this->cpu);
+   add_uni_relation("main", &this->main);
+   add_uni_relation("dynamic-configurator", &this->dynamic_configurator);
+   add_pin ("configure", &this->sys_configure_pin);
  
    add_attribute_virtual("command-line", this,
  			&gloss32::get_command_line,
*************** gloss32::gloss32() :
*** 71,76 ****
--- 76,84 ----
  			"setting");
  
    add_attribute("syscall-numbering-scheme", &this->syscall_numbering_scheme, "setting");
+   add_pin ("config-result", &config_result_pin);
+   add_pin ("config-error", &config_error_pin);
+ 
    add_attribute("verbose?", &this->verbose_p, "setting");
    
    add_attribute("max-fds", &this->max_fds, "setting");
*************** gloss32::get_halfword (address32 addr, s
*** 341,347 ****
    if (! cpu_memory_bus)
      {
        if (verbose_p)
! 	cerr << "*** CPU memory bus not configure!" << endl;
        return false;
      }
  
--- 349,355 ----
    if (! cpu_memory_bus)
      {
        if (verbose_p)
! 	cerr << "*** CPU memory bus not configured!" << endl;
        return false;
      }
  
*************** gloss32::syscall_trap()
*** 790,795 ****
--- 798,806 ----
  
    switch (target_to_host_syscall(syscall))
      {
+     case libgloss::SYS_reconfig:
+       do_sys_reconfig();
+       break;
      case libgloss::SYS_read:
        do_sys_read();
        break;
*************** gloss32::do_nonstandard_target_syscalls 
*** 848,853 ****
--- 859,970 ----
  }
  
  void
+ gloss32::configure (const string &config)
+ {
+   // Call up to the base class first
+   configurable_component::configure (config);
+ 
+   // Now handle relevent configuration for us.
+   if (config.size () <= 8)
+     return;
+   if (config.substr (0, 8) == "verbose=")
+     {
+       verbose_p = (config.substr (8) == "true");
+       return;
+     }
+ }
+ 
+ void
+ gloss32::sys_reconfig_set (const string &profile_name)
+ {
+   // Make sure that the main component and the dynamic configurator component
+   // have been related to us.
+   if (! main)
+     {
+       set_error_result (1);
+       return;
+     }
+   if (! dynamic_configurator)
+     {
+       set_error_result (2);
+       return;
+     }
+ 
+   // Set main's lookup-dynamic-config attribute with the name we're looking
+   // for. main will then write the configuration string into its
+   // found-config-profile attribute if it is found.
+   component::status s = main->set_attribute_value ("lookup-dynamic-config!",
+ 						   profile_name);
+   if (s != component::ok)
+     {
+       set_error_result (3);
+       return;
+     }
+ 
+   // Pass the configuration string to the dynamic configurator for this board.
+   string config = main->attribute_value ("found-dynamic-config");
+   dynamic_configurator->set_attribute_value ("configure!", config);
+   if (s != component::ok)
+     {
+       set_error_result (4);
+       return;
+     }
+ 
+   host_int_4 result = config_result_pin.sense ();
+   set_int_result (result);
+   host_int_4 error = config_error_pin.sense ();
+   set_error_result (error);
+ }
+ 
+ void
+ gloss32::sys_reconfig_reset (int32 handle)
+ {
+   // Drive the configure! pin of the dynamic configurator
+   sys_configure_pin.drive (handle);
+ 
+   // If there is an error, then the config result will be zero, otherwise
+   // it will be a config handle.
+   host_int_4 result = config_result_pin.sense ();
+   set_int_result (result);
+   host_int_4 error = config_error_pin.sense ();
+   set_error_result (error);
+ }
+ 
+ void
+ gloss32::do_sys_reconfig ()
+ {
+   if (verbose_p)
+     cerr << "sys_reconfig: ";
+ 
+   int32 n, str_ptr, handle;
+   string profile_name;
+ 
+   get_int_argument(1, n);
+   switch (n)
+     {
+     case 0: // warmup ()
+       profile_name = "sid-internal-warmup";
+       if (verbose_p)
+ 	cerr << profile_name << endl;
+       sys_reconfig_set (profile_name);
+       break;
+     case 1: // set (name)
+       get_int_argument(2, str_ptr);
+       get_string(str_ptr, profile_name);
+       if (verbose_p)
+ 	cerr << "set " << profile_name << endl;
+       sys_reconfig_set (profile_name);
+       break;
+     case 2: // reset (handle)
+       get_int_argument(2, handle);
+       if (verbose_p)
+ 	cerr << "reset 0x" << ios::hex << handle << ios::dec << endl;
+       sys_reconfig_reset (handle);
+       break;
+     }
+ }
+ 
+ void
  gloss32::do_sys_argc ()
  {
    set_int_result (command_line.size ());
Index: sid/component/gloss/gloss.h
===================================================================
RCS file: /cvs/src/src/sid/component/gloss/gloss.h,v
retrieving revision 1.11
diff -c -p -r1.11 gloss.h
*** sid/component/gloss/gloss.h	5 Sep 2002 18:11:16 -0000	1.11
--- sid/component/gloss/gloss.h	4 Aug 2005 18:32:39 -0000
***************
*** 1,7 ****
  // gloss.h - Basic process emulation plus ROM monitor support.
  // -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 2002 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
--- 1,7 ----
  // gloss.h - Basic process emulation plus ROM monitor support.
  // -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 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.
  
*************** using sidutil::fixed_accessor_map_compon
*** 52,68 ****
  using sidutil::fixed_pin_map_component;
  using sidutil::no_bus_component;
  using sidutil::fixed_relation_map_component;
  using sidutil::callback_pin;
  using sidutil::output_pin;
  using sidutil::input_pin;
  
  
  class gloss32: public virtual component,
! 	       protected fixed_attribute_map_component,
  	       protected fixed_accessor_map_component,
! 	       protected fixed_pin_map_component,
  	       protected no_bus_component,
! 	       protected fixed_relation_map_component
  {
  public:
  
--- 52,70 ----
  using sidutil::fixed_pin_map_component;
  using sidutil::no_bus_component;
  using sidutil::fixed_relation_map_component;
+ using sidutil::configurable_component;
  using sidutil::callback_pin;
  using sidutil::output_pin;
  using sidutil::input_pin;
  
  
  class gloss32: public virtual component,
! 	       protected virtual fixed_attribute_map_component,
  	       protected fixed_accessor_map_component,
! 	       protected virtual fixed_pin_map_component,
  	       protected no_bus_component,
! 	       protected virtual fixed_relation_map_component,
! 	       protected configurable_component
  {
  public:
  
*************** protected:
*** 73,78 ****
--- 75,82 ----
  
    // The cpu we're connected to.
    component* cpu;
+   // The main SID component.
+   component* main;
    // Access to the cpu's memory.
    bus* cpu_memory_bus;
    // The endian of `cpu'.
*************** protected:
*** 150,157 ****
--- 154,171 ----
    virtual void syscall_trap();
    bool blocked_p; // signal that syscall blocked
  
+   // Dynamic configuration
+   component *dynamic_configurator;
+   void configure (const string &config);
+ 
    // syscall support
+   output_pin sys_configure_pin;
+   input_pin config_result_pin;
+   input_pin config_error_pin;
    int32 errnum;
+   void do_sys_reconfig();
+   void sys_reconfig_set (const string &profile_name);
+   void sys_reconfig_reset (int32 handle);
    void do_sys_exit();
    void do_sys_read();
    void do_sys_write();
Index: sid/component/gloss/libgloss.h
===================================================================
RCS file: /cvs/src/src/sid/component/gloss/libgloss.h,v
retrieving revision 1.5
diff -c -p -r1.5 libgloss.h
*** sid/component/gloss/libgloss.h	31 Jan 2002 23:03:53 -0000	1.5
--- sid/component/gloss/libgloss.h	4 Aug 2005 18:32:39 -0000
***************
*** 1,6 ****
  // libgloss.h - Interface details for libgloss.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 2002 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 ----
  // libgloss.h - Interface details for libgloss.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 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.
  
*************** public:
*** 19,24 ****
--- 19,25 ----
  
    enum libgloss_syscall
    {
+     SYS_reconfig = 0,
      SYS_exit = 1,
      SYS_open = 2, 
      SYS_close = 3, 
Index: sid/component/loader/compLoader.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/loader/compLoader.cxx,v
retrieving revision 1.10
diff -c -p -r1.10 compLoader.cxx
*** sid/component/loader/compLoader.cxx	12 May 2005 16:11:20 -0000	1.10
--- sid/component/loader/compLoader.cxx	4 Aug 2005 18:32:39 -0000
***************
*** 1,6 ****
  // compLoader.cxx - object file loader component.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2003, 2004 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 ----
  // compLoader.cxx - object file loader component.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2003, 2004, 2005 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
*************** using sidutil::fixed_attribute_map_compo
*** 50,55 ****
--- 50,56 ----
  using sidutil::fixed_pin_map_component;
  using sidutil::fixed_accessor_map_component;
  using sidutil::no_relation_component;
+ using sidutil::configurable_component;
  using sidutil::output_pin;
  using sidutil::callback_pin;
  using sidutil::string2stream;
*************** class loader_probe_bus: public sidutil::
*** 112,121 ****
  
  class generic_loader: public virtual component,
  		      protected fixed_bus_map_component,
! 		      protected fixed_attribute_map_component,
! 		      protected fixed_pin_map_component,
  		      protected fixed_accessor_map_component,
! 		      protected no_relation_component
  {
  private:
    callback_pin<generic_loader> doit_pin;
--- 113,123 ----
  
  class generic_loader: public virtual component,
  		      protected fixed_bus_map_component,
! 		      protected virtual fixed_attribute_map_component,
! 		      protected virtual fixed_pin_map_component,
  		      protected fixed_accessor_map_component,
! 		      protected no_relation_component,
! 		      protected virtual configurable_component
  {
  private:
    callback_pin<generic_loader> doit_pin;
*************** protected:
*** 164,169 ****
--- 166,173 ----
    sid::component::status restore_state(const string& state)
      { return parse_attribute(state, *this); }
  
+   virtual void configure (const string &config);
+ 
  public:
    generic_loader(): 
      doit_pin(this, & generic_loader::load_it), 
*************** public:
*** 196,201 ****
--- 200,221 ----
      
  };
  
+ void
+ generic_loader::configure (const string &config)
+ {
+   // Call up to the base class first
+   configurable_component::configure (config);
+ 
+   // Now handle relevent configuration for us.
+   if (config.size () < 12)
+     return;
+   if (config.substr (0, 8) == "verbose=")
+     {
+       verbose_p = (config.substr (8) == "true");
+       return;
+     }
+ }
+ 
  ostream& 
  operator << (ostream& out, const generic_loader& it)
  {
*************** operator >> (istream& in, generic_loader
*** 229,234 ****
--- 249,267 ----
  
  class elf_loader: public generic_loader
  {
+ public:
+   elf_loader ()
+     : generic_loader (),
+       symbol_table (0),
+       current_function (""),
+       check_function_pin (this, &elf_loader::check_function_pin_handler)
+     {
+       add_pin ("function?", &check_function_pin);
+       add_attribute ("current-function", & current_function);
+     }
+   ~elf_loader () throw () {}
+ 
+ private:
    // static pointer to active instance (XXX: concurrency?)
    static elf_loader* freeloader;
  
*************** class elf_loader: public generic_loader
*** 270,276 ****
        const struct TextSection *section_table;
        int success_p = readElfFile(& elf_loader::load_function,
  				  & entry_point, & little_endian_p,
! 				  & eflags, & section_table);
        probe_upstream.set_section_table (section_table);
        elf_loader::freeloader = 0;
  
--- 303,309 ----
        const struct TextSection *section_table;
        int success_p = readElfFile(& elf_loader::load_function,
  				  & entry_point, & little_endian_p,
! 				  & eflags, & section_table, & symbol_table);
        probe_upstream.set_section_table (section_table);
        elf_loader::freeloader = 0;
  
*************** class elf_loader: public generic_loader
*** 300,305 ****
--- 333,345 ----
        delete this->file;
        this->file = 0;
      }
+ 
+ protected:
+   callback_pin<elf_loader> check_function_pin;
+   void check_function_pin_handler (host_int_4 addr);
+ 
+   const struct Symbol *symbol_table;
+   string current_function;
  };
  
  // static variable
*************** elf_loader::load_function(host_int_8 des
*** 376,381 ****
--- 416,463 ----
    return bytes;
  }
  
+ void
+ elf_loader::check_function_pin_handler (host_int_4 addr)
+ {
+   // Find the function corresponding to the given address in the symbol
+   // table, if any, and set current_function to that name. If no function is
+   // found, set current_function to a string representing the address.
+   if (symbol_table)
+     {
+       unsigned closest = 0;
+       host_int_8 min_difference = ~(host_int_8)0;
+       unsigned ix;
+       for (ix = 0; symbol_table[ix].name; ++ix)
+ 	{
+ 	  // Don't consider unnamed symbols.
+ 	  if (! symbol_table[ix].name[0])
+ 	    continue;
+ 	  host_int_8 sym_addr = symbol_table[ix].addr;
+ 	  host_int_8 sym_size = symbol_table[ix].size;
+ 	  if (addr == sym_addr)
+ 	    break;
+ 	  if (addr > sym_addr && addr < (sym_addr + sym_size))
+ 	    break;
+ 	  if (addr - sym_addr < min_difference)
+ 	    {
+ 	      min_difference = addr - sym_addr;
+ 	      closest = ix;
+ 	    }
+ 	}
+       if (symbol_table[ix].name)
+ 	{
+ 	  current_function = symbol_table[ix].name;
+ 	  return;
+ 	}
+       if (closest != 0)
+ 	{
+ 	  current_function = symbol_table[closest].name;
+ 	  return;
+ 	}
+     }
+   current_function = "";
+ }
+ 
  // ----------------------------------------------------------------------------
  
  static
Index: sid/component/loader/elfload.c
===================================================================
RCS file: /cvs/src/src/sid/component/loader/elfload.c,v
retrieving revision 1.11
diff -c -p -r1.11 elfload.c
*** sid/component/loader/elfload.c	29 Jun 2004 19:10:39 -0000	1.11
--- sid/component/loader/elfload.c	4 Aug 2005 18:32:40 -0000
***************
*** 1,6 ****
  /* Simple ELF loader
   *
!  * Copyright (c) 1998, 2002, 2004 Red Hat
   *
   * The authors hereby grant permission to use, copy, modify, distribute,
   * and license this software and its documentation for any purpose, provided
--- 1,6 ----
  /* Simple ELF loader
   *
!  * Copyright (c) 1998, 2002, 2004, 2005 Red Hat
   *
   * The authors hereby grant permission to use, copy, modify, distribute,
   * and license this software and its documentation for any purpose, provided
*************** textSectionAddress (unsigned long long a
*** 59,65 ****
  {
    int i;
  
!   // Not a text section address if there is no table.
    if (! section_table)
      return 0;
  
--- 59,65 ----
  {
    int i;
  
!   /* Not a text section address if there is no table.  */
    if (! section_table)
      return 0;
  
*************** textSectionAddress (unsigned long long a
*** 74,79 ****
--- 74,109 ----
    return 0;
  }
  
+ /* A new string table table is created for each loader in the system.  */
+ static struct StringTable *stringTables;
+ static int stringTableCount;
+ static int stringTableNum;
+ 
+ static void
+ newStringTable (int index)
+ {
+   if (index >= stringTableNum)
+     {
+       stringTableNum = index + 10;
+       stringTables = xrealloc (stringTables, stringTableNum * sizeof (*stringTables));
+     }
+ }
+ 
+ /* A new symbol table is created for each loader in the system.  */
+ static struct Symbol *symbolTable;
+ static int symbolCount;
+ static int symbolNum;
+ 
+ static void
+ newSymbol (int index)
+ {
+   if (index >= symbolNum)
+     {
+       symbolNum = index + 10;
+       symbolTable = xrealloc (symbolTable, symbolNum * sizeof (*symbolTable));
+     }
+ }
+ 
  
  /* Read in an ELF file, using FUNC to read data from the stream.
     The result is a boolean indicating success.
*************** textSectionAddress (unsigned long long a
*** 83,96 ****
  
  int
  readElfFile (PFLOAD func, unsigned* entry_point, int* little_endian,
! 	     unsigned* e_flags, const struct TextSection **section_table)
  {
    unsigned char fileHeader [64];
    unsigned char psymHdr [56];
    unsigned char secHdr [64];
    unsigned long long psymOffset;
    int psymSize;
    int psymNum;
    int eFlags;
    unsigned long long secOffset;
    int secSize;
--- 113,131 ----
  
  int
  readElfFile (PFLOAD func, unsigned* entry_point, int* little_endian,
! 	     unsigned* e_flags, const struct TextSection **section_table,
! 	     const struct Symbol **symbol_table)
  {
    unsigned char fileHeader [64];
    unsigned char psymHdr [56];
    unsigned char secHdr [64];
+   unsigned char symTabEntry [16];
    unsigned long long psymOffset;
    int psymSize;
    int psymNum;
+   unsigned long long symbolTableOffset;
+   unsigned long long symbolTableSize;
+   unsigned long long symbolTableStringTableIx;
    int eFlags;
    unsigned long long secOffset;
    int secSize;
*************** readElfFile (PFLOAD func, unsigned* entr
*** 211,221 ****
    /* FIXME: admin part of program segment is loaded.  */
  
    /* Look in the section table in order to determine which sections contain
!      code and which contain data.  */
!   textSections = 0;
!   textSectionNum = 0;
!   textSectionCount = 0;
!   newTextSection (textSectionCount);
    if (sixtyfourbit) 
      {
        secOffset = fetchQuad (fileHeader+40, littleEndian);
--- 246,252 ----
    /* FIXME: admin part of program segment is loaded.  */
  
    /* Look in the section table in order to determine which sections contain
!      code, data, symbols and strings.  */
    if (sixtyfourbit) 
      {
        secOffset = fetchQuad (fileHeader+40, littleEndian);
*************** readElfFile (PFLOAD func, unsigned* entr
*** 228,233 ****
--- 259,271 ----
        secSize = fetchShort (fileHeader+46, littleEndian);
        secNum = fetchShort (fileHeader+48, littleEndian);
      }
+   textSections = 0;
+   textSectionNum = 0;
+   textSectionCount = 0;
+   stringTables = 0;
+   stringTableNum = 0;
+   stringTableCount = 0;
+   newTextSection (textSectionCount);
    for (x = 0; x < secNum; x++)
      {
        if (func (0, secHdr, secOffset, secSize, 0) != secSize)
*************** readElfFile (PFLOAD func, unsigned* entr
*** 249,255 ****
          }
        else
          {
! 	  if (fetchWord(secHdr+8, littleEndian) & SHF_EXECINSTR)
  	    {
  	      textSections[textSectionCount].lbound = 
  		fetchWord(secHdr+12, littleEndian);
--- 287,294 ----
          }
        else
          {
! 	  unsigned flags = fetchWord(secHdr+8, littleEndian);
! 	  if (flags & SHF_EXECINSTR)
  	    {
  	      textSections[textSectionCount].lbound = 
  		fetchWord(secHdr+12, littleEndian);
*************** readElfFile (PFLOAD func, unsigned* entr
*** 259,264 ****
--- 298,321 ----
  	      textSectionCount++;
  	      newTextSection (textSectionCount);
  	    }
+ 	  else if (fetchWord(secHdr+4, littleEndian) == SHT_STRTAB)
+ 	    {
+ 	      unsigned offset = fetchWord(secHdr+16, littleEndian);
+ 	      unsigned size = fetchWord(secHdr+20, littleEndian);
+ 	      char *strings = xmalloc (size);
+ 	      newStringTable (stringTableCount);
+ 	      stringTables[stringTableCount].ix = x;
+ 	      stringTables[stringTableCount].strings = strings;
+ 	      if (func (0, strings, offset, size, 0) != size)
+ 		return 0;
+ 	      ++stringTableCount;
+ 	    }
+ 	  else if (fetchWord(secHdr+4, littleEndian) == SHT_SYMTAB)
+ 	    {
+ 	      symbolTableOffset = fetchWord(secHdr+16, littleEndian);
+ 	      symbolTableSize = fetchWord(secHdr+20, littleEndian);
+ 	      symbolTableStringTableIx = fetchWord(secHdr+24, littleEndian);
+ 	    }
          }
        secOffset += secSize;
      }
*************** readElfFile (PFLOAD func, unsigned* entr
*** 267,275 ****
--- 324,372 ----
    textSections[textSectionCount].lbound = 0;
    textSections[textSectionCount].hbound = 0;
  
+   /* Can't look for functions in the symbol table until all the sections have been
+      examined, since the string table for the symbol table may follow the symbol
+      table itself.  Identify the correct string table first.  */
+   const char *strings = 0;
+   for (x = 0; x < stringTableCount; ++x)
+     {
+       if (stringTables[x].ix == symbolTableStringTableIx)
+ 	strings = stringTables[x].strings;
+     }
+ 
+   /* Now look for functions and record their addresses and lengths.  */
+   symbolTable = 0;
+   symbolCount = 0;
+   symbolNum = 0;
+   newSymbol (symbolCount);
+   if (strings)
+     {
+       for (x = 0; x < symbolTableSize; x += sizeof (symTabEntry))
+ 	{
+ 	  if (func (0, symTabEntry, symbolTableOffset + x, sizeof (symTabEntry), 0) != sizeof (symTabEntry))
+ 	    return 0;
+ 	  // TODO: Save only symbols representing functions
+ 	  // PROBLEM: Some don't have the STT_FUNC flag set
+ 	  symbolTable[symbolCount].name = strings + fetchWord(symTabEntry+0, littleEndian);
+ 	  symbolTable[symbolCount].addr = fetchWord(symTabEntry+4, littleEndian);
+ 	  symbolTable[symbolCount].size = fetchWord(symTabEntry+8, littleEndian);
+ #if 0
+ 	  printf ("found symbol %s at 0x%Lx for 0x%Lx\n",
+ 		  symbolTable[symbolCount].name,
+ 		  symbolTable[symbolCount].addr,
+ 		  symbolTable[symbolCount].size);
+ #endif
+ 	  symbolCount++;
+ 	  newSymbol (symbolCount);
+ 	}
+     }
+   // Terminate the symbol table.
+   symbolTable[symbolCount].name = 0;
+ 
    *entry_point = entryPoint;
    *little_endian = littleEndian;
    *section_table = textSections;
+   *symbol_table = symbolTable;
    *e_flags = eFlags;
  
    return 1;
Index: sid/component/loader/elfload.h
===================================================================
RCS file: /cvs/src/src/sid/component/loader/elfload.h,v
retrieving revision 1.5
diff -c -p -r1.5 elfload.h
*** sid/component/loader/elfload.h	29 Jun 2004 19:10:39 -0000	1.5
--- sid/component/loader/elfload.h	4 Aug 2005 18:32:40 -0000
***************
*** 1,6 ****
  /* Header for simple ELF loader
   *
!  * Copyright (c) 1998, 2004 Red Hat
   *
   * The authors hereby grant permission to use, copy, modify, distribute,
   * and license this software and its documentation for any purpose, provided
--- 1,6 ----
  /* Header for simple ELF loader
   *
!  * Copyright (c) 1998, 2004, 2005 Red Hat
   *
   * The authors hereby grant permission to use, copy, modify, distribute,
   * and license this software and its documentation for any purpose, provided
*************** struct TextSection
*** 32,37 ****
--- 32,50 ----
    unsigned long long hbound;
  };
  
+ struct StringTable
+ {
+   unsigned ix;
+   const char *strings;
+ };
+ 
+ struct Symbol
+ {
+   const char *name;
+   unsigned long long addr;
+   unsigned long long size;
+ };
+ 
  /* 
     PFLOAD represents a function that will read file data. 
     DEST or DEST2 is used as the destination address to be written with the
*************** typedef int (*PFLOAD)(unsigned long long
*** 48,54 ****
  extern int textSectionAddress(unsigned long long, const struct TextSection *);
  /* Load an ELF executable into memory. FUNC is used to actually read the
     file. */
! extern int readElfFile(PFLOAD func, unsigned*, int*, unsigned*, const struct TextSection **);
  
  #define EI_CLASS 4
  #define ELFCLASS64  2 /* 64 bit */
--- 61,67 ----
  extern int textSectionAddress(unsigned long long, const struct TextSection *);
  /* Load an ELF executable into memory. FUNC is used to actually read the
     file. */
! extern int readElfFile(PFLOAD func, unsigned*, int*, unsigned*, const struct TextSection **, const struct Symbol **);
  
  #define EI_CLASS 4
  #define ELFCLASS64  2 /* 64 bit */
*************** extern int readElfFile(PFLOAD func, unsi
*** 63,66 ****
--- 76,87 ----
  /* ELF section header flags */
  #define SHF_EXECINSTR	(1 << 2)	/* Executable machine instructions */
  
+ /* ELF section header types */
+ #define SHT_SYMTAB 2
+ #define SHT_STRTAB 3
+ 
+ /* ELF Symbol Table fields */
+ #define ELF32_ST_TYPE(i) ((i)&0xf)
+ #define STT_FUNC 2
+ 
  #endif
Index: sid/component/loader/sw-load-elf.xml
===================================================================
RCS file: /cvs/src/src/sid/component/loader/sw-load-elf.xml,v
retrieving revision 1.4
diff -c -p -r1.4 sw-load-elf.xml
*** sid/component/loader/sw-load-elf.xml	12 May 2005 16:11:20 -0000	1.4
--- sid/component/loader/sw-load-elf.xml	4 Aug 2005 18:32:40 -0000
***************
*** 4,9 ****
--- 4,14 ----
  <defcomplib lib="libloader.la" dlsym="loader_component_library">
    <defcomponent name="sw-load-elf" type="concrete">
  
+     <!-- relationships -->
+     <defrelationship name="dynamic-configurator"	behaviors="configuration" />
+ 
+     <!-- pins -->
+     <defpin name="function-address?"	direction="in"  legalvalues="address"	behaviors="configuration" />
      <defpin name="load!" direction="in" legalvalues="any" behaviors="loading"/>
      <defpin name="start-pc-set" direction="out" legalvalues="any" behaviors="loading"/>
      <defpin name="endian-set" direction="out" legalvalues="0/1/2" behaviors="loading"/>
***************
*** 14,19 ****
--- 19,25 ----
      <defattribute name="state-snapshot" legalvalues="opaque string" behaviors="save/restore"/>
      <defattribute name="file" category="setting" legalvalues="file name" defaultvalue='"/dev/null"' behaviors="configuration"/>
      <defattribute name="verbose?" category="setting" legalvalues="1/0" defaultvalue="0" behaviors="configuration"/>
+     <defattribute name="configure!" category="setting" legalvalues="string" behaviors="configuration" />
      
      <defbus name="probe-upstream" accesses="read/write" behaviors="error checking"/>
  
***************
*** 42,47 ****
--- 48,59 ----
        The "verbose?" attribute, when set, encourages this component to provide 
        informative messages to cout during loading.
        </p>
+ 
+       <p>When the <attribute>configure!</attribute> is set, the new value is interpreted
+          as a configuration spec.  The spec is a colon-separated list of items, each of
+          which is passed in turn to the 'configure' method for interpretation and possible
+          action.</p>
+ 
      </behavior>
  
      <behavior name="loading">
Index: sid/component/profiling/gprof.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/profiling/gprof.cxx,v
retrieving revision 1.11
diff -c -p -r1.11 gprof.cxx
*** sid/component/profiling/gprof.cxx	14 May 2003 14:59:52 -0000	1.11
--- sid/component/profiling/gprof.cxx	4 Aug 2005 18:32:40 -0000
***************
*** 1,6 ****
  // gprof.cxx - A component for generating gprof profile data.  -*- C++ -*-
  
! // Copyright (C) 1999-2002 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 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
*** 52,67 ****
--- 52,71 ----
    using sid::little_int_1;
    using sid::component;
    using sid::bus;
+   using sid::pin;
  
    using sidutil::fixed_pin_map_component;
    using sidutil::fixed_attribute_map_component;
    using sidutil::no_bus_component;
    using sidutil::no_accessor_component;
    using sidutil::fixed_relation_map_component;
+   using sidutil::configurable_component;
    using sidutil::input_pin;
+   using sidutil::output_pin;
    using sidutil::callback_pin;
    using sidutil::make_attribute;
    using sidutil::parse_attribute;
+   using sidutil::tokenize;
    using sidutil::std_error_string;
    using sidutil::endian;
    using sidutil::endian_unknown;
*************** namespace profiling_components
*** 84,110 ****
  // ----------------------------------------------------------------------------
  
    class gprof_component: public virtual component,
! 			 protected fixed_pin_map_component,
  			 protected no_accessor_component,
! 			 protected fixed_attribute_map_component,
! 			 protected fixed_relation_map_component,
! 			 protected no_bus_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
!     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 target_attribute;
      component* target_component;
  
-     string output_file;
      endian output_file_format;
  
      callback_pin<gprof_component> accumulate_pin;
--- 88,143 ----
  // ----------------------------------------------------------------------------
  
    class gprof_component: public virtual component,
! 			 protected virtual fixed_pin_map_component,
  			 protected no_accessor_component,
! 			 protected virtual fixed_attribute_map_component,
! 			 protected virtual fixed_relation_map_component,
! 			 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
!     {
!       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)
!         {
! 	  this->value_count = other.value_count;
! 	  this->value_min   = other.value_min;
! 	  this->value_max   = other.value_max;
! 	  this->limit_min   = other.limit_min;
! 	  this->limit_max   = other.limit_max;
! 	  this->bucket_size = other.bucket_size;
! 	  this->output_file = other.output_file;
! 	}
!     };
! 
!     vector<statistics> stats;
!     unsigned current_stats;
! 
!     component *sim_sched;
!     string sim_sched_event;
  
      string target_attribute;
      component* target_component;
  
      endian output_file_format;
  
      callback_pin<gprof_component> accumulate_pin;
*************** namespace profiling_components
*** 115,123 ****
      callback_pin<gprof_component> reset_pin;
      callback_pin<gprof_component> store_pin;
  
      string bucket_size_get()
        {
! 	return make_attribute (this->bucket_size);
        }
  
      component::status bucket_size_set(const string& str)
--- 148,206 ----
      callback_pin<gprof_component> reset_pin;
      callback_pin<gprof_component> store_pin;
  
+     component::status set_nothing (const string& str)
+       {
+ 	return component::bad_value;
+       }
+ 
+     string value_min_get()
+       {
+ 	return make_attribute (this->stats[current_stats].value_min);
+       }
+ 
+     string value_max_get()
+       {
+ 	return make_attribute (this->stats[current_stats].value_max);
+       }
+ 
+     string value_count_get()
+       {
+ 	return make_attribute (this->stats[current_stats].value_count);
+       }
+ 
+     string limit_min_get()
+       {
+ 	return make_attribute (this->stats[current_stats].limit_min);
+       }
+ 
+     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)
+ 	  this->stats[current_stats].limit_min = new_limit_min;
+ 	return s;
+       }
+ 
+     string limit_max_get()
+       {
+ 	return make_attribute (this->stats[current_stats].limit_max);
+       }
+ 
+     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)
+ 	  this->stats[current_stats].limit_max = new_limit_max;
+ 	return s;
+       }
+ 
      string bucket_size_get()
        {
! 	return make_attribute (this->stats[current_stats].bucket_size);
        }
  
      component::status bucket_size_set(const string& str)
*************** namespace profiling_components
*** 129,136 ****
  	if (s != component::ok) return s;
  
  	// Reject change if we already have samples 
! 	if ((this->value_count != 0) &&
! 	    (this->bucket_size != new_bucket_size))
  	  {
  	    cerr << "sw-profile-gprof: invalid time to change bucket size" << endl;
  	    return component::bad_value;
--- 212,219 ----
  	if (s != component::ok) return s;
  
  	// Reject change if we already have samples 
! 	if ((this->stats[current_stats].value_count != 0) &&
! 	    (this->stats[current_stats].bucket_size != new_bucket_size))
  	  {
  	    cerr << "sw-profile-gprof: invalid time to change bucket size" << endl;
  	    return component::bad_value;
*************** namespace profiling_components
*** 143,153 ****
  	    return component::bad_value;
  	  }
  
! 	this->bucket_size = new_bucket_size;
  	return component::ok;
        }
  
  
      void accumulate (host_int_4)
        {
  	if (! this->target_component) return;
--- 226,247 ----
  	    return component::bad_value;
  	  }
  
! 	this->stats[current_stats].bucket_size = new_bucket_size;
  	return component::ok;
        }
  
  
+     string output_file_get()
+       {
+ 	return this->stats[current_stats].output_file;
+       }
+ 
+     component::status output_file_set(const string& str)
+       {
+ 	this->stats[current_stats].output_file = str;
+ 	return component::ok;
+       }
+ 
      void accumulate (host_int_4)
        {
  	if (! this->target_component) return;
*************** namespace profiling_components
*** 156,173 ****
  	host_int_4 value;
  	component::status s = parse_attribute (value_str, value);
  	if (s != component::ok) return;
! 
  	// Reject out-of-bounds samples
! 	if (value < this->limit_min || value > this->limit_max) return;
  
! 	value_count ++;
  
! 	assert (this->bucket_size != 0);
! 	host_int_4 quantized = (value / this->bucket_size) * this->bucket_size;
  
! 	if (quantized < this->value_min) this->value_min = quantized;
! 	if (quantized > this->value_max) this->value_max = quantized;
! 	this->value_hitcount_map [quantized] ++;
        }
  
      void accumulate_call (host_int_4 selfpc)
--- 250,267 ----
  	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;
  
! 	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)
*************** namespace profiling_components
*** 175,205 ****
  	host_int_4 callerpc = this->cg_caller_pin.sense();
  
  	// Reject out-of-bounds samples
! 	if (selfpc < this->limit_min || selfpc > this->limit_max) return;
! 	if (callerpc < this->limit_min || callerpc > this->limit_max) return;
  
! 	value_count ++;
  
! 	assert (this->bucket_size != 0);
! 	host_int_4 c_quantized = (callerpc / this->bucket_size) * this->bucket_size;
! 	host_int_4 s_quantized = (selfpc / this->bucket_size) * this->bucket_size;
  
! 	if (c_quantized < this->value_min) this->value_min = c_quantized;
! 	if (s_quantized < this->value_min) this->value_min = s_quantized;
! 	if (c_quantized > this->value_max) this->value_max = c_quantized;
! 	if (s_quantized > this->value_max) this->value_max = s_quantized;
  
! 	this->cg_count_map [make_pair(c_quantized,s_quantized)] ++;
        }
  
  
      void reset (host_int_4)
        {
! 	this->cg_count_map.clear ();
! 	this->value_hitcount_map.clear ();
! 	this->value_min = ~0;
! 	this->value_max = 0;
! 	value_count = 0;
        }
  
  
--- 269,303 ----
  	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;
! 	if (callerpc < this->stats[current_stats].limit_min || callerpc > this->stats[current_stats].limit_max) return;
  
! 	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;
! 	if (c_quantized > this->stats[current_stats].value_max) this->stats[current_stats].value_max = c_quantized;
! 	if (s_quantized > this->stats[current_stats].value_max) this->stats[current_stats].value_max = s_quantized;
  
! 	this->stats[current_stats].cg_count_map [make_pair(c_quantized,s_quantized)] ++;
        }
  
  
      void reset (host_int_4)
        {
! 	statistics new_stats;
! 	if (! stats.empty ())
! 	  {
! 	    new_stats.bucket_size = stats[0].bucket_size;
! 	    new_stats.output_file = stats[0].output_file;
! 	  }
! 	stats.clear ();
! 	stats.push_back (new_stats);
! 	current_stats = 0;
        }
  
  
*************** namespace profiling_components
*** 257,268 ****
  	    return;
  	  }
  
! 	ofstream of (this->output_file.c_str (),
                       ios::out | ios::trunc | ios::binary);
  	if (! of.good())
  	  {
  	    cerr << "sw-profile-gprof: Error opening "
! 		 << this->output_file << ":" << std_error_string();
  	    return;
  	  }
  
--- 355,377 ----
  	    return;
  	  }
  
! 	for (vector<statistics>::iterator it = stats.begin ();
! 	     it != stats.end ();
! 	     ++it)
! 	  store_stats (*it);
!       }
! 
!     void store_stats (statistics &stats)
!       {
! 	if (stats.output_file.empty ())
! 	  stats.output_file = "gmon.out";
! 
! 	ofstream of (stats.output_file.c_str (),
                       ios::out | ios::trunc | ios::binary);
  	if (! of.good())
  	  {
  	    cerr << "sw-profile-gprof: Error opening "
! 		 << stats.output_file << ":" << std_error_string();
  	    return;
  	  }
  
*************** namespace profiling_components
*** 275,281 ****
  	put_bytes (of, host_int_4(0), 4);      // gmon_hdr.spare
  	put_bytes (of, host_int_4(0), 4);      // gmon_hdr.spare
  
! 	if (! this->value_hitcount_map.empty())
  	  {
  	    // We may have to loop and dump out several adjacent histogram
  	    // tables, because histogram bucket count overflow.  The
--- 384,390 ----
  	put_bytes (of, host_int_4(0), 4);      // gmon_hdr.spare
  	put_bytes (of, host_int_4(0), 4);      // gmon_hdr.spare
  
! 	if (! stats.value_hitcount_map.empty())
  	  {
  	    // We may have to loop and dump out several adjacent histogram
  	    // tables, because histogram bucket count overflow.  The
*************** namespace profiling_components
*** 284,301 ****
  	    // histogram tables.  We copy the histogram table here, since
  	    // its counters will be decremented by up to 2**16-1 per
  	    // iteration.
! 	    hitcount_map_t value_hitcount_map_copy = this->value_hitcount_map;
  	    while (true)
  	      {
  		// write a new histogram record
  		// GMON_Record_Tag
  		put_bytes (of, host_int_1(0), 1);      // GMON_TAG_TIME_HIST
  		// gmon_hist_hdr
! 		put_bytes (of, this->value_min, 4);    // gmon_hist_hdr.low_pc
! 		host_int_4 uprounded_value_max = this->value_max + this->bucket_size;
  		put_bytes (of, uprounded_value_max, 4); // gmon_hist_hdr.high_pc
! 		assert (this->bucket_size != 0);
! 		host_int_4 num_buckets = 1 + (this->value_max - this->value_min) / this->bucket_size;
  		put_bytes (of, num_buckets, 4);        // gmon_hist_hdr.hist_size
  		put_bytes (of, host_int_4(1), 4);      // gmon_hist_hdr.prof_rate
  		put_bytes (of, "tick", 15);            // gmon_hist_hdr.dimen
--- 393,410 ----
  	    // histogram tables.  We copy the histogram table here, since
  	    // its counters will be decremented by up to 2**16-1 per
  	    // iteration.
! 	    hitcount_map_t value_hitcount_map_copy = stats.value_hitcount_map;
  	    while (true)
  	      {
  		// write a new histogram record
  		// 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
  		put_bytes (of, host_int_4(1), 4);      // gmon_hist_hdr.prof_rate
  		put_bytes (of, "tick", 15);            // gmon_hist_hdr.dimen
*************** namespace profiling_components
*** 303,311 ****
  		
  		// Dump out histogram counts
  		bool overflow = false;
! 		for (host_int_4 bucket = this->value_min;
! 		     bucket <= this->value_max;
! 		     bucket += this->bucket_size)
  		  {
  		    const host_int_4 max_count = 65535;
  		    host_int_4 count = 0;
--- 412,420 ----
  		
  		// Dump out histogram counts
  		bool overflow = false;
! 		for (host_int_4 bucket = stats.value_min;
! 		     bucket <= stats.value_max;
! 		     bucket += stats.bucket_size)
  		  {
  		    const host_int_4 max_count = 65535;
  		    host_int_4 count = 0;
*************** namespace profiling_components
*** 337,344 ****
  	  } // (emitting hash table?)
  
  	// Now spit out the call graph stastics.
! 	cg_count_map_t::const_iterator ci = this->cg_count_map.begin();
! 	while (ci != this->cg_count_map.end())
  	  {
  	    // write a new histogram record
  	    // GMON_Record_Tag
--- 446,453 ----
  	  } // (emitting hash table?)
  
  	// Now spit out the call graph stastics.
! 	cg_count_map_t::const_iterator ci = stats.cg_count_map.begin();
! 	while (ci != stats.cg_count_map.end())
  	  {
  	    // write a new histogram record
  	    // GMON_Record_Tag
*************** namespace profiling_components
*** 355,380 ****
  	of.close ();
        }
  
  
    public:
      gprof_component ():
!       value_count (0),
!       value_min (~0),
!       value_max (0),
!       limit_min (0),
!       limit_max (~0),
!       bucket_size (1), // != 0
        target_attribute ("pc"),
        target_component (0),
-       output_file ("gmon.out"),
        output_file_format (endian_unknown),
        accumulate_pin (this, & gprof_component::accumulate),
        cg_callee_pin (this, & gprof_component::accumulate_call),
        reset_pin (this, & gprof_component::reset),
!       store_pin (this, & gprof_component::store)
        {
  	add_pin ("sample", & this->accumulate_pin);
  	add_attribute ("sample", & this->accumulate_pin, "pin");
  	add_pin ("cg-caller", & this->cg_caller_pin);
  	add_attribute ("cg-caller", & this->cg_caller_pin, "pin");
  	add_pin ("cg-callee", & this->cg_callee_pin);
--- 464,555 ----
  	of.close ();
        }
  
+     void configure (const string &config)
+       {
+ 	// Call up to the base classes first
+ 	configurable_component::configure (config);
+ 
+ 	// Now handle relevent configuration for us.
+ 	if (config.size () < 6)
+ 	  return;
+ 	if (config.substr (0, 6) == "gprof=")
+ 	  {
+ 	    // If a filename has been specified, then see if we need to switch files.
+ 	    if (config.size () > 6)
+ 	      {
+ 		vector<string> parts = tokenize (config.substr (6), ",");
+ 
+ 		// Special case: Default stats have not yet been assigned an
+ 		// output file and no data has been collected yet. Simply
+ 		// assign this file name.
+ 		if (current_stats == 0 && stats[0].value_count == 0
+ 		    && stats[0].output_file.empty ())
+ 		  stats[0].output_file = parts[0];
+ 		else
+ 		  {
+ 		    unsigned size = stats.size ();
+ 		    unsigned i;
+ 		    for (i = 0; i < size; ++i)
+ 		      if (stats[i].output_file == parts[0])
+ 			break;
+ 		    // This is a new output file, so create new stats for it.
+ 		    if (i >= size)
+ 		      {
+ 			statistics new_stats;
+ 			new_stats.bucket_size = stats[0].bucket_size;
+ 			new_stats.output_file = parts[0];
+ 			stats.push_back (new_stats);
+ 		      }
+ 		    current_stats = i;
+ 		  }
+ 
+ 		// If cycles was specified, then we need to be subscribed to the
+ 		// target scheduler
+ 		if (! sim_sched)
+ 		  return;
+ 		if (parts.size () == 2)
+ 		  {
+ 		    host_int_4 cycles;
+ 		    component::status s = parse_attribute (parts[1], cycles);
+ 		    if (s == component::ok)
+ 		      {
+ 			sim_sched->connect_pin (sim_sched_event + "-event", & accumulate_pin);
+ 			sim_sched->set_attribute_value (sim_sched_event + "-regular", "true");
+ 			sim_sched->set_attribute_value (sim_sched_event + "-time", make_attribute (cycles));
+ 			return;
+ 		      }
+ 		  }
+ 	      }
+ 	    // No gprof config or cycles was not specified. We will not be triggered by the
+ 	    // target scheduler.
+ 	    if (sim_sched)
+ 	      {
+ 		sim_sched->disconnect_pin (sim_sched_event + "-event", & accumulate_pin);
+ 		sim_sched->set_attribute_value (sim_sched_event + "-regular", "false");
+ 	      }
+ 	    return;
+ 	  }
+       }
  
    public:
      gprof_component ():
!       sim_sched (0),
!       sim_sched_event ("0"),
        target_attribute ("pc"),
        target_component (0),
        output_file_format (endian_unknown),
        accumulate_pin (this, & gprof_component::accumulate),
        cg_callee_pin (this, & gprof_component::accumulate_call),
        reset_pin (this, & gprof_component::reset),
!       store_pin (this, & gprof_component::store),
!       current_stats (0)
        {
+ 	// Reset before adding attributes etc.
+ 	reset (1);
+ 
  	add_pin ("sample", & this->accumulate_pin);
  	add_attribute ("sample", & this->accumulate_pin, "pin");
+ 	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-callee", & this->cg_callee_pin);
*************** namespace profiling_components
*** 387,401 ****
  			       & gprof_component::bucket_size_get,
  			       & gprof_component::bucket_size_set,
  			       "setting");
! 	add_attribute_ro ("value-min", & this->value_min, "register");
! 	add_attribute_ro ("value-max", & this->value_max, "register");
! 	add_attribute_ro ("value-count", & this->value_count, "register");
! 	add_attribute ("limit-min", & this->limit_min, "setting");
! 	add_attribute ("limit-max", & this->limit_max, "setting");
  	add_attribute ("value-attribute", & this->target_attribute, "setting");
! 	add_attribute ("output-file", & this->output_file, "setting");
  	add_attribute ("output-file-endianness", & this->output_file_format, "setting");
  	add_uni_relation ("target-component", & this->target_component);
        }
      ~gprof_component () throw () { }
    };
--- 562,595 ----
  			       & gprof_component::bucket_size_get,
  			       & gprof_component::bucket_size_set,
  			       "setting");
! 	add_attribute_virtual ("value-min", this,
! 			       & gprof_component::value_min_get,
! 			       & gprof_component::set_nothing, // ro
! 			       "setting");
! 	add_attribute_virtual ("value-max", this,
! 			       & gprof_component::value_max_get,
! 			       & gprof_component::set_nothing, // ro
! 			       "setting");
! 	add_attribute_virtual ("value-count", this,
! 			       & gprof_component::value_count_get,
! 			       & gprof_component::set_nothing, // ro
! 			       "setting");
! 	add_attribute_virtual ("limit-min", this,
! 			       & gprof_component::limit_min_get,
! 			       & gprof_component::limit_min_set,
! 			       "setting");
! 	add_attribute_virtual ("limit-max", this,
! 			       & gprof_component::limit_max_get,
! 			       & gprof_component::limit_max_set,
! 			       "setting");
  	add_attribute ("value-attribute", & this->target_attribute, "setting");
! 	add_attribute_virtual ("output-file", this,
! 			       & gprof_component::output_file_get,
! 			       & gprof_component::output_file_set,
! 			       "setting");
  	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);
        }
      ~gprof_component () throw () { }
    };
Index: sid/component/tcl/compTcl.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/tcl/compTcl.cxx,v
retrieving revision 1.6
diff -c -p -r1.6 compTcl.cxx
*** sid/component/tcl/compTcl.cxx	12 Jul 2001 11:37:32 -0000	1.6
--- sid/component/tcl/compTcl.cxx	4 Aug 2005 18:32:40 -0000
***************
*** 1,6 ****
  // compTcl.cxx - Tcl bridge component.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001 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 ----
  // compTcl.cxx - Tcl bridge component.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 2005 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
*************** namespace tcl_api_component
*** 86,91 ****
--- 86,92 ----
    using sid::big_int_4;
    using sid::big_int_8;
  
+   using sidutil::configurable_component;
    using sidutil::callback_pin;
    using sidutil::output_pin;
    using sidutil::make_attribute;
*************** namespace tcl_api_component
*** 99,105 ****
  
  #ifndef DISABLE_THIS_COMPONENT
  
- 
    // -----------------------------------------------------------------
  
    // forward decl
--- 100,105 ----
*************** namespace tcl_api_component
*** 168,174 ****
    // NB: the constructor may throw an exception if the embedded tcl interpreter
    // fails to "boot".
  
!   class tcl_component: public component
    {
    protected:
      // the interpreter itself 
--- 168,176 ----
    // NB: the constructor may throw an exception if the embedded tcl interpreter
    // fails to "boot".
  
!   class tcl_component
!     : virtual public component,
!       public configurable_component
    {
    protected:
      // the interpreter itself 
*************** namespace tcl_api_component
*** 187,192 ****
--- 189,195 ----
      // tables for mapping enumerations
      bijection<string,sid::bus::status> bus_status_lut;
      bijection<string,sid::component::status> component_status_lut;
+     string victim_name;
  
      // callback functions
      void event_pin_driven (host_int_4);
*************** namespace tcl_api_component
*** 214,220 ****
        event_pin (this, & tcl_component::event_pin_driven),
        component_lut ("sid-component#"),
        bus_lut ("sid-bus#"),
!       pin_lut ("sid-pin#")
        {
  	this->interp = Tcl_CreateInterp ();
  	if (this->interp == 0)
--- 217,224 ----
        event_pin (this, & tcl_component::event_pin_driven),
        component_lut ("sid-component#"),
        bus_lut ("sid-bus#"),
!       pin_lut ("sid-pin#"),
!       victim_name ("")
        {
  	this->interp = Tcl_CreateInterp ();
  	if (this->interp == 0)
*************** namespace tcl_api_component
*** 333,340 ****
--- 337,358 ----
  	    bool ok = call_void (value);
  	    return ok ? component::ok : component::bad_value;
  	  }
+ 	else if (name == "victim-name")
+ 	  {
+ 	    victim_name = value;
+ 	    return component::ok;
+ 	  }
  	else
  	  {
+ 	    // Handle the configure! attribute before passing the request on to the victim
+ 	    // Only the sid-api-trace-component is configurable
+ 	    if (name == "configure!")
+ 	      {
+ 		string comp_type = attribute_value ("component-type");
+ 		if (comp_type == "sid-api-trace")
+ 		  configurable_component::set_attribute_value (name, value);
+ 	      }
+ 
  	    string result = call_scalar ("set_attribute_value "
  					+ quote (name) + " "
  					+ quote (value));
*************** namespace tcl_api_component
*** 359,366 ****
  	if (name == "!event")
  	  return & this->event_pin;
  	else
! 	  return (decode_pin_handle (call_scalar ("find_pin "
! 						+ quote (name))));
        }
  
      component::status
--- 377,387 ----
  	if (name == "!event")
  	  return & this->event_pin;
  	else
! 	  {
! 	    pin *p = decode_pin_handle (call_scalar ("find_pin " 
! 						      + quote (name)));
! 	    return p;
! 	  }
        }
  
      component::status
*************** namespace tcl_api_component
*** 485,491 ****
        {
  	string cmd = "relate " + quote (rel) + " " + quote (encode_component_handle (comp));
  	string result = call_scalar (cmd);
! 	return (decode_component_status (result));
        }
  
  
--- 506,513 ----
        {
  	string cmd = "relate " + quote (rel) + " " + quote (encode_component_handle (comp));
  	string result = call_scalar (cmd);
! 	component::status s = decode_component_status (result);
! 	return s;
        }
  
  
*************** namespace tcl_api_component
*** 495,501 ****
        {
  	string cmd = "unrelate " + quote (rel) + " " + quote (encode_component_handle (comp));
  	string result = call_scalar (cmd);
! 	return (decode_component_status (result));
        }
  
  
--- 517,524 ----
        {
  	string cmd = "unrelate " + quote (rel) + " " + quote (encode_component_handle (comp));
  	string result = call_scalar (cmd);
! 	component::status s = decode_component_status (result);
! 	return s;
        }
  
  
*************** namespace tcl_api_component
*** 515,520 ****
--- 538,546 ----
  	  }
  	return comps;
        }
+ 
+   protected:
+     virtual void configure (const string &config);
    };
  
  
*************** tcl_component::event_pin_driven (host_in
*** 2038,2043 ****
--- 2064,2107 ----
    this->event_control_pin.drive (value);
  }
  
+ void
+ tcl_component::configure (const string &config)
+ {
+   // Only the sid-api-trace-component is configurable
+   string comp_type = attribute_value ("component-type");
+   if (comp_type != "sid-api-trace")
+     return;
+ 
+   // Call up to the base class
+   configurable_component::configure (config);
+ 
+   // Now handle relevent configuration for us.
+   if (config.size () < 5)
+     return;
+   if (config.substr (0, 5) == "wrap=")
+     {
+       if (! victim_name.empty () && config.size () > 5)
+ 	{
+ 	  // Get the list of wrapped components.
+ 	  vector<string> components = tokenize (config.substr (5), ",");
+ 	  // If the name of our victim is in the list, then set up to
+ 	  // 'wrap' that component
+ 	  for (vector<string>::const_iterator it = components.begin ();
+ 	       it != components.end ();
+ 	       ++it)
+ 	    {
+ 	      if (*it + "-traced" == victim_name)
+ 		{
+ 		  set_attribute_value ("victim-trace?", "1");
+ 		  return;
+ 		}
+ 	    }
+ 	}
+       // --wrap disabled, or no victim to wrap
+       set_attribute_value ("victim-trace?", "0");
+       return;
+     }
+ }
  
  
  #ifdef HAVE_TK_H
Index: sid/component/tcl/sid-api-trace.tcl
===================================================================
RCS file: /cvs/src/src/sid/component/tcl/sid-api-trace.tcl,v
retrieving revision 1.1
diff -c -p -r1.1 sid-api-trace.tcl
*** sid/component/tcl/sid-api-trace.tcl	7 Dec 2000 19:30:57 -0000	1.1
--- sid/component/tcl/sid-api-trace.tcl	4 Aug 2005 18:32:40 -0000
***************
*** 1,4 ****
! # Copyright (C) 2000 Red Hat
  #
  # This is a component that forwards almost all sid requests to another
  # component.  Further, it interjects proxy pin/bus objects between the
--- 1,4 ----
! # Copyright (C) 2000, 2005 Red Hat
  #
  # This is a component that forwards almost all sid requests to another
  # component.  Further, it interjects proxy pin/bus objects between the
*************** proc attribute_names_in_category {cat} {
*** 98,103 ****
--- 98,105 ----
  
  proc attribute_value {attr} {
      global victim
+     if {$attr == "component-type"} then { return "sid-api-trace" }
+     if {$attr == "victim"} then { return "$victim" }
      return [sidtrace [list sid::component::attribute_value $victim $attr]]
  }
  
Index: sid/include/sidattrutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidattrutil.h,v
retrieving revision 1.7
diff -c -p -r1.7 sidattrutil.h
*** sid/include/sidattrutil.h	10 May 2005 15:48:22 -0000	1.7
--- sid/include/sidattrutil.h	4 Aug 2005 18:32:40 -0000
***************
*** 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.
  
--- 2,8 ----
  // mappings between application objects and their string
  // representations.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2003, 2005 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
***************
*** 10,15 ****
--- 10,16 ----
  #define SIDATTRUTIL_H
  
  #include <sidconfig.h>
+ #include <sidcomputil.h>
  #include <sidpinutil.h>
  #include "sidtypes.h"
  
*************** make_attribute (const sid::any_int<IntTy
*** 1017,1033 ****
        }
    };
  
    // A mix-in for classes with user logging.
    class fixed_attribute_map_with_logging_component
    : public virtual fixed_attribute_map_component,
!     public virtual fixed_pin_map_component
    {
    protected:
      fixed_attribute_map_with_logging_component () :
        ulog_level (0),
        ulog_mode ("less"),
        ulog_out_pin (),
!       buffer_output (true)
        {
  	add_attribute ("buffer-output", &buffer_output, "setting");
  	add_attribute ("ulog-level", &ulog_level, "setting");
--- 1018,1068 ----
        }
    };
  
+   // A configurable_component maintains a relationship with a
+   // sid-control-dynamic-configurator component and reconfigures itself
+   // when its configure! attribute is set.
+   class configurable_component:
+     public virtual fixed_attribute_map_component
+   {
+   public:
+     configurable_component ()
+       {
+ 	add_attribute_virtual ("configure!", this,
+ 			       & configurable_component::dynamic_config,
+ 			       & configurable_component::nothing);
+       }
+     ~configurable_component() throw() {}
+ 
+     // Dynamic reconfiguration support
+   private:
+     std::string configurable_component::nothing() { return ""; }
+   protected:
+     virtual component::status
+     dynamic_config(const std::string& spec)
+       {
+ 	// Call the configure method to handle each configuration item.
+ 	std::vector<std::string> parts = sidutil::tokenize (spec, ":");
+ 	unsigned size = parts.size ();
+ 	for (unsigned i = 0; i < size; ++i)
+ 	  configure (parts[i]);
+ 	return component::ok;
+       }
+ 
+     virtual void configure (const std::string &config) {}
+   };
+ 
    // A mix-in for classes with user logging.
    class fixed_attribute_map_with_logging_component
    : public virtual fixed_attribute_map_component,
!     public virtual fixed_pin_map_component,
!     public virtual configurable_component
    {
    protected:
      fixed_attribute_map_with_logging_component () :
        ulog_level (0),
        ulog_mode ("less"),
        ulog_out_pin (),
!       buffer_output (false)
        {
  	add_attribute ("buffer-output", &buffer_output, "setting");
  	add_attribute ("ulog-level", &ulog_level, "setting");
*************** make_attribute (const sid::any_int<IntTy
*** 1038,1044 ****
      ~fixed_attribute_map_with_logging_component () throw()
        {
  	// Output any saved messages.
- 	// output_saved_messages ();
  	ulog_logger->output_saved_messages ();
        }
  
--- 1073,1078 ----
*************** make_attribute (const sid::any_int<IntTy
*** 1062,1068 ****
--- 1096,1132 ----
      sidutil::output_pin ulog_out_pin;
      bool buffer_output;
      sidutil::logger *ulog_logger;
+ 
+ protected:
+     // Dynamic configuration support
+     virtual void configure (const string &config)
+       {
+ 	// Call up to the base class
+ 	configurable_component::configure (config);
+ 
+ 	// Handle items specific to this component
+ 	if (config.size () < 11)
+ 	  return;
+ 	if (config.substr (0, 10) == "ulog-mode=")
+ 	  {
+ 	    ulog_mode = config.substr (10);
+ 	    ulog_logger->set_attributes (buffer_output, ulog_level, ulog_mode);
+ 	    return;
+ 	  }
+ 	if (config.size () < 12)
+ 	  return;
+ 	if (config.substr (0, 11) == "ulog-level=")
+ 	  {
+ 	    sid::host_int_4 level;
+ 	    sid::component::status s = sidutil::parse_attribute (config.substr (11), level);
+ 	    if (s == sid::component::ok)
+ 	      ulog_level = level;
+ 	    ulog_logger->set_attributes (buffer_output, ulog_level, ulog_mode);
+ 	    return;
+ 	  }
+       }
    };
+ 
  }
  
  #endif // SIDATTRUTIL_H
Index: sid/include/sidcpuutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidcpuutil.h,v
retrieving revision 1.30
diff -c -p -r1.30 sidcpuutil.h
*** sid/include/sidcpuutil.h	10 May 2005 15:48:22 -0000	1.30
--- sid/include/sidcpuutil.h	4 Aug 2005 18:32:40 -0000
***************
*** 1,6 ****
  // sidcpuutil.h - Elements common to CPU models.  -*- C++ -*-
  
! // Copyright (C) 1999-2004 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 ----
  // sidcpuutil.h - Elements common to CPU models.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
*************** namespace sidutil
*** 105,111 ****
  		   protected virtual fixed_accessor_map_component,
  		   protected virtual fixed_attribute_map_component,
  		   protected virtual fixed_relation_map_component,
! 		   protected virtual fixed_bus_map_component
    {
      // custom memory allocators for poisioning freshly-allocated memory
    public:
--- 105,112 ----
  		   protected virtual fixed_accessor_map_component,
  		   protected virtual fixed_attribute_map_component,
  		   protected virtual fixed_relation_map_component,
! 		   protected virtual fixed_bus_map_component,
! 		   protected virtual configurable_component
    {
      // custom memory allocators for poisioning freshly-allocated memory
    public:
*************** namespace sidutil
*** 206,214 ****
--- 207,218 ----
      sid::host_int_8 total_insn_count;
      mutable sid::host_int_8 total_latency;
      sid::host_int_4 current_step_insn_count;
+     sid::host_int_4 num_cycles;
      output_pin step_cycles_pin;
      output_pin cg_caller_pin;
      output_pin cg_callee_pin;
+     output_pin cg_jump_pin;
+     output_pin cg_return_pin;
     
      // tracing
    private:
*************** namespace sidutil
*** 257,262 ****
--- 261,267 ----
      bool trace_semantics_p;
      bool trace_counter_p;
      bool final_insn_count_p;
+     bool print_final_insn_count_p;
      bool enable_step_trap_p;
      cpu_trace_stream trace_stream;
  
*************** namespace sidutil
*** 265,270 ****
--- 270,278 ----
  	recursion_record limit (& this->step_limit);
  	if (UNLIKELY(! limit.ok())) return;
  
+ 	if (UNLIKELY (! gprof_configured_p && configure_gprof_p))
+ 	  configure_gprof ();
+ 
  	this->current_step_insn_count = 0;
  	this->yield_p = false;
  
*************** namespace sidutil
*** 283,292 ****
  	const sid::host_int_4 min_num_cycles = 1;
  	const sid::host_int_4 max_num_cycles = 0x7FFFFFFF;
  	sid::host_int_8 insn_cycles = num_insns + latency_to_cycles (latency);
! 	sid::host_int_4 num_cycles =
  	  insn_cycles <= min_num_cycles ? min_num_cycles :
  	  insn_cycles >= max_num_cycles ? max_num_cycles :
  	  insn_cycles;
  	this->stepped (num_cycles);
        }
      void yield ()
--- 291,301 ----
  	const sid::host_int_4 min_num_cycles = 1;
  	const sid::host_int_4 max_num_cycles = 0x7FFFFFFF;
  	sid::host_int_8 insn_cycles = num_insns + latency_to_cycles (latency);
! 	num_cycles =
  	  insn_cycles <= min_num_cycles ? min_num_cycles :
  	  insn_cycles >= max_num_cycles ? max_num_cycles :
  	  insn_cycles;
+ 
  	this->stepped (num_cycles);
        }
      void yield ()
*************** namespace sidutil
*** 300,307 ****
        }
      virtual void print_insn_summary (sid::host_int_4)
        {
! 	std::cerr << "instruction count: " << this->total_insn_count << "  "
! 		  << "simulated cycles: " << this->total_latency + this->total_insn_count << std::endl;
        }
      virtual void stepped (sid::host_int_4 n)
        {
--- 309,317 ----
        }
      virtual void print_insn_summary (sid::host_int_4)
        {
! 	if (print_final_insn_count_p)
! 	  std::cerr << "instruction count: " << this->total_insn_count << "  "
! 		    << "simulated cycles: " << this->total_latency + this->total_insn_count << std::endl;
        }
      virtual void stepped (sid::host_int_4 n)
        {
*************** namespace sidutil
*** 309,314 ****
--- 319,326 ----
        }
      void cg_profile (sid::host_int_4 caller, sid::host_int_4 callee)
      {
+       last_caller = caller;
+       last_callee = callee;
        // The drive sequence is important: see sw-profile-gprof
        this->cg_caller_pin.drive (caller);
        this->cg_callee_pin.drive (callee);
*************** namespace sidutil
*** 324,329 ****
--- 336,347 ----
  	                     << "  ";
  	}
      }
+     void cg_profile_jump (sid::host_int_4 caller, sid::host_int_4 callee)
+     {
+       last_caller = caller;
+       last_callee = callee;
+       this->cg_jump_pin.drive (callee);
+     }
  
    public:
      void set_total_latency (sid::host_int_8 latency) { this->total_latency = latency; }
*************** namespace sidutil
*** 381,386 ****
--- 399,410 ----
        this->trace_result_p = (this->trace_semantics_p || this->trace_disass_p);
      }
  
+     void
+     update_final_insn_count_p ()
+     {
+       if (this->final_insn_count_p)
+ 	this->print_final_insn_count_p = true;
+     }
  
      // Reset the processor model to power-up state.
    private:
*************** namespace sidutil
*** 426,432 ****
  	return static_cast<cpu_trap_disposition>(trap_disposition_pin.sense ());
        }
  
!     
      // state save/restore: Override these in derived classes, but
      // include a call up to this base implementation.
    protected:
--- 450,615 ----
  	return static_cast<cpu_trap_disposition>(trap_disposition_pin.sense ());
        }
  
!     void unconfigure_gprof (sid::host_int_4 num_cycles)
!       {
! 	assert (gprof);
! 	// First sample the address of the branch which caused
! 	// the reconfig for the given number of cycles.
! 	sid::pin *p;
! 	if (num_cycles && last_caller)
! 	  {
! 	    p = gprof->find_pin ("sample");
! 	    if (p)
! 	      {
! 		std::string save_pc = this->attribute_value ("pc");
! 		if (! save_pc.empty ())
! 		  {
! 		    sid::component::status s = this->set_attribute_value ("pc", make_numeric_attribute (last_caller));
! 		    if (s == sid::component::ok)
! 		      do
! 			{
! 			  p->driven (1);
! 			  --num_cycles;
! 			} while (num_cycles);
! 		    this->set_attribute_value ("pc", save_pc);
! 		  }
! 	      }
! 	  }
! 
! 	// Then get gprof to reconfigure itself.
! 	gprof->set_attribute_value ("configure!", gprof_spec);
! 
! 	// Then disconnect the call graph notification pins.
! 	assert (! configure_gprof_p);
! 	assert (gprof_configured_p);
! 	p = gprof->find_pin ("cg-caller");
! 	if (p) cg_caller_pin.disconnect (p); 
! 	p = gprof->find_pin ("cg-callee");
! 	if (p) cg_callee_pin.disconnect (p); 
! 	gprof_configured_p = false;
!       }
! 
!     void configure_gprof ()
!       {
! 	// First get gprof to reconfigure itself.
! 	assert (gprof);
! 	gprof->set_attribute_value ("configure!", gprof_spec);
! 
! 	// Then connect the call graph notification pins.
! 	assert (configure_gprof_p);
! 	assert (! gprof_configured_p);
! 	sid::pin *p = gprof->find_pin ("cg-caller");
! 	if (p)
! 	  {
! 	    cg_caller_pin.connect (p); 
! 	    if (last_caller && last_callee)
! 	      p->driven (last_caller);
! 	  }
! 	p = gprof->find_pin ("cg-callee");
! 	if (p) {
! 	  cg_callee_pin.connect (p); 
! 	  if (last_caller && last_callee)
! 	    p->driven (last_callee); 
! 	}
! 	gprof_configured_p = true;
!       }
! 
!     // ------------------------------------------------------------------------
!     // dynamic configuration
!   protected:
!     component *gprof;
!     component *core_probe;
!     component *main;
!     bool gprof_configured_p;
!     bool configure_gprof_p;
!     sid::host_int_4 last_caller;
!     sid::host_int_4 last_callee;
!     string gprof_spec;
! 
!     virtual void configure (const string &config)
!       {
! 	// Call up to the base class
! 	configurable_component::configure (config);
! 
! 	// Handle configuration specific to this component
! 	if (config.size () < 6)
! 	  return;
! 	if (config.substr (0, 6) == "gprof=")
! 	  {
! 	    if (! gprof)
! 	      return; // nothing to configure
! 	    gprof_spec = config;
! 	    // Set a flag to configure the gprof component the next time
! 	    // our step! pin is driven....
! 	    configure_gprof_p = (config.size () > 6);
! 	    // ... unless we are unconfiguring the gprof, in which
! 	    // case do it now.
! 	    if (gprof_configured_p && ! configure_gprof_p)
! 	      unconfigure_gprof (num_cycles);
! 	    return;
! 	  }
! 	if (config.size () <= 11)
! 	  return;
! 	if (config.substr (0, 11) == "insn-count=")
! 	  {
! 	    sid::host_int_4 n;
! 	    sid::component::status s = parse_attribute (config.substr (11), n);
! 	    if (s == sid::component::ok)
! 	      step_insn_count = n;
! 	    return;
! 	  }
! 	if (config.substr (0, 8) == "verbose=")
! 	  {
! 	    if (main)
! 	      main->set_attribute_value ("verbose?", config.substr (8));
! 	    return;
! 	  }
! 	if (config.size () < 15)
! 	  return;
! 	if (config.substr (0, 11) == "trace-core=")
! 	  {
! 	    if (core_probe)
! 	      core_probe->set_attribute_value ("trace?", config.substr (11));
! 	    return;
! 	  }
! 	if (config.size () < 18)
! 	  return;
! 	if (config.substr (0, 14) == "trace-counter=")
! 	  {
! 	    trace_counter_p = (config.substr (14) == "true");
! 	    return;
! 	  }
! 	if (config.substr (0, 14) == "trace-extract=")
! 	  {
! 	    trace_extract_p = (config.substr (14) == "true");
! 	    return;
! 	  }
! 	if (config.size () < 20)
! 	  return;
! 	if (config.substr (0, 16) == "trace-semantics=")
! 	  {
! 	    trace_semantics_p = (config.substr (16) == "true");
! 	    update_trace_result_p ();
! 	    return;
! 	  }
! 	if (config.size () < 21)
! 	  return;
! 	if (config.substr (0, 17) == "final-insn-count=")
! 	  {
! 	    final_insn_count_p = (config.substr (17) == "true");
! 	    update_final_insn_count_p ();
! 	    return;
! 	  }
! 	if (config.size () < 22)
! 	  return;
! 	if (config.substr (0, 18) == "trace-disassemble=")
! 	  {
! 	    trace_disass_p = (config.substr (18) == "true");
! 	    update_trace_result_p ();
! 	    return;
! 	  }
!       }
! 
      // state save/restore: Override these in derived classes, but
      // include a call up to this base implementation.
    protected:
*************** namespace sidutil
*** 444,449 ****
--- 627,633 ----
  	  << " " << this->trace_semantics_p
  	  << " " << this->trace_counter_p
  	  << " " << this->final_insn_count_p
+ 	  << " " << this->print_final_insn_count_p
  	  // pins
  	  << " " << this->step_cycles_pin
  	  << " " << this->trap_type_pin
*************** namespace sidutil
*** 469,474 ****
--- 653,659 ----
  	  >> this->trace_semantics_p
  	  >> this->trace_counter_p
  	  >> this->final_insn_count_p
+ 	  >> this->print_final_insn_count_p
  	  // pins
  	  >> this->step_cycles_pin
  	  >> this->trap_type_pin
*************** public:
*** 567,573 ****
        debugger_bus (& this->data_bus),
        trace_stream (),
        trace_filename ("-"), // standard output
!       trace_pin (this, & basic_cpu::trace_pin_handler)
        {
  	// buses
  	this->data_bus = 0;
--- 752,765 ----
        debugger_bus (& this->data_bus),
        trace_stream (),
        trace_filename ("-"), // standard output
!       trace_pin (this, & basic_cpu::trace_pin_handler),
!       gprof (0),
!       gprof_configured_p (false),
!       configure_gprof_p (false),
!       last_caller (0),
!       last_callee (0),
!       core_probe (0),
!       main (0)
        {
  	// buses
  	this->data_bus = 0;
*************** public:
*** 587,592 ****
--- 779,786 ----
  	add_pin ("start-pc-set!", & this->pc_set_pin);
  	add_pin ("cg-caller", & this->cg_caller_pin);
  	add_pin ("cg-callee", & this->cg_callee_pin);
+ 	add_pin ("cg-return", & this->cg_return_pin);
+ 	add_pin ("cg-jump", & this->cg_jump_pin);
  	add_pin ("print-insn-summary!", & this->print_insn_summary_pin);
  	add_pin ("endian-set!", & this->endian_set_pin);
  	add_pin ("eflags-set!", & this->eflags_set_pin);
*************** public:
*** 625,631 ****
  	this->trace_counter_p = false;
  	add_attribute ("trace-counter?", & this->trace_counter_p, "setting");
  	this->final_insn_count_p = false;
! 	add_attribute ("final-insn-count?", & this->final_insn_count_p, "setting");
        }
  
      virtual ~basic_cpu() throw() {}
--- 819,833 ----
  	this->trace_counter_p = false;
  	add_attribute ("trace-counter?", & this->trace_counter_p, "setting");
  	this->final_insn_count_p = false;
! 	this->print_final_insn_count_p = false;
! 	add_attribute_notify ("final-insn-count?", & this->final_insn_count_p, this,
! 			      & basic_cpu::update_final_insn_count_p,
! 			      "setting");
! 
! 	// For dynamic configuration
! 	add_uni_relation("gprof", &this->gprof);
! 	add_uni_relation("core-probe", &this->core_probe);
! 	add_uni_relation("main", &this->main);
        }
  
      virtual ~basic_cpu() throw() {}
Index: sid/main/dynamic/baseCfg.cxx
===================================================================
RCS file: /cvs/src/src/sid/main/dynamic/baseCfg.cxx,v
retrieving revision 1.3
diff -c -p -r1.3 baseCfg.cxx
*** sid/main/dynamic/baseCfg.cxx	31 Jan 2003 16:48:03 -0000	1.3
--- sid/main/dynamic/baseCfg.cxx	4 Aug 2005 18:32:40 -0000
*************** map<string, AtomicCfg *> AtomicCfg_impl:
*** 229,235 ****
  AtomicCfg::AtomicCfg (const string name, const string complib, 
  		      const string compsym, const string comptype) :
    ComponentCfg (name),
!   wrapped (false),
    my_complib (complib),
    my_compsym (compsym),
    my_comptype (comptype)
--- 229,236 ----
  AtomicCfg::AtomicCfg (const string name, const string complib, 
  		      const string compsym, const string comptype) :
    ComponentCfg (name),
!   my_wrapped (false),
!   my_possibly_wrapped (false),
    my_complib (complib),
    my_compsym (compsym),
    my_comptype (comptype)
*************** void AtomicCfg::add_prefix (const string
*** 245,257 ****
  
  AtomicCfg::~AtomicCfg() {}
  
! bool AtomicCfg::wrap_component (const string name)
  {
    if (AtomicCfg_impl::atomic_names.find (name) == 
        AtomicCfg_impl::atomic_names.end ())
!     return false;
!   AtomicCfg_impl::atomic_names[name]->wrapped = true;
!   return true;
  }
  
  void AtomicCfg::reset_load_map () 
--- 246,272 ----
  
  AtomicCfg::~AtomicCfg() {}
  
! AtomicCfg *AtomicCfg::wrap_component (const string name)
  {
    if (AtomicCfg_impl::atomic_names.find (name) == 
        AtomicCfg_impl::atomic_names.end ())
!     return 0;
!   AtomicCfg *comp = AtomicCfg_impl::atomic_names[name];
!   comp->my_wrapped = true;
!   comp->my_possibly_wrapped = false;
!   return comp;
! }
! 
! AtomicCfg *
! AtomicCfg::possible_wrap_name (const string &name)
! {
!   if (AtomicCfg_impl::atomic_names.find (name) == 
!       AtomicCfg_impl::atomic_names.end ())
!     return 0;
!   AtomicCfg *comp = AtomicCfg_impl::atomic_names[name];
!   if (! comp->my_wrapped)
!     comp->my_possibly_wrapped = true;
!   return comp;
  }
  
  void AtomicCfg::reset_load_map () 
*************** void AtomicCfg::write_construct (Writer 
*** 276,286 ****
  {
    if (my_comptype == "")
      return;
!   if (wrapped)
      {
        w.write_line ("new sid-api-trace " + my_name);
        w.write_line ("new " + my_comptype + " " + my_name + "-traced");      
        w.write_line ("relate " + my_name + " victim " + my_name + "-traced");      
      }
    else
      w.write_line ("new " + my_comptype + " " + my_name);
--- 291,304 ----
  {
    if (my_comptype == "")
      return;
!   if (my_wrapped || my_possibly_wrapped)
      {
        w.write_line ("new sid-api-trace " + my_name);
        w.write_line ("new " + my_comptype + " " + my_name + "-traced");      
        w.write_line ("relate " + my_name + " victim " + my_name + "-traced");      
+       w.write_line ("set " + my_name + " victim-name " + my_name + "-traced");      
+       if (my_possibly_wrapped)
+ 	w.write_line ("set " + my_name + " victim-trace? 0");      
      }
    else
      w.write_line ("new " + my_comptype + " " + my_name);
*************** const ResolvedName AggregateCfg::resolve
*** 375,380 ****
--- 393,425 ----
  }
  
  
+ void AggregateCfg::dynamic_config_for_wrapped_children (AtomicCfg *dynamic_configurator, Writer &w)
+ {
+   assert (dynamic_configurator);
+   for (vector<ComponentCfg *>::const_iterator i = a_impl->my_children.begin();
+        i != a_impl->my_children.end(); ++i)
+     {
+       if (*i == dynamic_configurator)
+ 	continue;
+       AtomicCfg *a = dynamic_cast<AtomicCfg *>(*i);
+       if (a)
+ 	{
+ 	  if (a->possibly_wrapped ())
+ 	    {
+ 	      Relation (dynamic_configurator, "client", a).write_to (w);
+ 	    }
+ 	  continue;
+ 	}
+       AggregateCfg *ag = dynamic_cast<AggregateCfg *>(*i);
+       if (ag)
+ 	{
+ 	  ag->dynamic_config_for_wrapped_children (dynamic_configurator, w);
+ 	  continue;
+ 	}
+       assert (false);
+     }
+ }
+ 
  
  Connection::Connection (ComponentCfg *src, const string srcport, 
  			ComponentCfg *dst, const string dstport,
Index: sid/main/dynamic/baseCfg.h
===================================================================
RCS file: /cvs/src/src/sid/main/dynamic/baseCfg.h,v
retrieving revision 1.1
diff -c -p -r1.1 baseCfg.h
*** sid/main/dynamic/baseCfg.h	9 Jan 2003 04:22:50 -0000	1.1
--- sid/main/dynamic/baseCfg.h	4 Aug 2005 18:32:40 -0000
*************** virtual public ComponentCfg
*** 99,108 ****
    virtual void write_load (Writer &w);
    virtual void write_construct (Writer &w);
    static void reset_load_map ();
!   static bool wrap_component (const string name);
    string comp_type () const { return my_comptype; }
   protected:
!   bool wrapped;
    string my_complib;
    string my_compsym;
    string my_comptype;
--- 99,112 ----
    virtual void write_load (Writer &w);
    virtual void write_construct (Writer &w);
    static void reset_load_map ();
!   static AtomicCfg *wrap_component (const string name);
!   static AtomicCfg *possible_wrap_name (const string &comp_name);
    string comp_type () const { return my_comptype; }
+   bool wrapped () const { return my_wrapped; }
+   bool possibly_wrapped () const { return my_wrapped || my_possibly_wrapped; }
   protected:
!   bool my_wrapped;
!   bool my_possibly_wrapped;
    string my_complib;
    string my_compsym;
    string my_comptype;
*************** virtual public ComponentCfg
*** 120,125 ****
--- 124,130 ----
    virtual void write_config (Writer &w);
    void add_child (ComponentCfg *c);
    virtual const ResolvedName resolve(const role r, const string name);
+   void dynamic_config_for_wrapped_children (AtomicCfg *dynamic_configurator, Writer &w);
   protected:
    AggregateCfg_impl *a_impl;
  };
Index: sid/main/dynamic/commonCfg.cxx
===================================================================
RCS file: /cvs/src/src/sid/main/dynamic/commonCfg.cxx,v
retrieving revision 1.9
diff -c -p -r1.9 commonCfg.cxx
*** sid/main/dynamic/commonCfg.cxx	10 May 2005 15:51:08 -0000	1.9
--- sid/main/dynamic/commonCfg.cxx	4 Aug 2005 18:32:40 -0000
*************** SessionCfg::SessionCfg (const string nam
*** 573,578 ****
--- 573,580 ----
      loader (NULL),
      verbose (false),
      use_stdio (true),
+     need_gprof (false),
+     need_core_probe (false),
      board_count (0),
      gdb_count (0)
  {
*************** SessionCfg::add_ulog_file (const string 
*** 615,620 ****
--- 617,628 ----
    add_child (ulog);
  }
  
+ void
+ SessionCfg::add_profile_config (const string &name, const string &options)
+ {
+   set (main_obj, "dynamic-config!", name + "|" + options);
+ }
+ 
  void SessionCfg::set_loader (LoaderCfg *l)
  {
    if (loader)
*************** void SessionCfg::use_tcl_bridge ()
*** 701,706 ****
--- 709,886 ----
    init_seq->add_output (7, tcl_bridge, "!event");
  }
  
+ string
+ SessionCfg::wrap_config ()
+ {
+   string spec;
+   for (vector<AtomicCfg *>::const_iterator it = wrapped_components.begin ();
+        it != wrapped_components.end ();
+        ++it)
+     spec += " --wrap=" + (*it)->get_name ();
+   return spec;
+ }
+ 
+ // Process the argument to --profile-config which will
+ // be a subset of the allowable SID command line options
+ // which can be dynamically changed.
+ //
+ void
+ SessionCfg::profile_config_error (const string &spec)
+ {
+   cerr << "error: invalid argument to --profile-config: " << spec << endl;
+   exit (8);
+ }
+ 
+ string
+ SessionCfg::profile_opt_value (const string& opt, const vector<string>& opt_parts, unsigned max_parts)
+ {
+   unsigned size = opt_parts.size ();
+   if (size > max_parts)
+     profile_config_error (opt); // doesn't return
+ 
+   if (max_parts == 1)
+     return "true";
+ 
+   return opt_parts[1];
+ }
+ 
+ string
+ SessionCfg::profile_opt_int_value (const string& opt, const vector<string>& opt_parts)
+ {
+   unsigned size = opt_parts.size ();
+   if (size != 2)
+     profile_config_error (opt); // doesn't return
+ 
+   unsigned n;
+   sid::component::status s = sidutil::parse_attribute (opt_parts[1], n);
+   if (s != sid::component::ok)
+     profile_config_error (opt); // doesn't return
+ 
+   return opt_parts[1];
+ }
+ 
+ string
+ SessionCfg::profile_opt_gprof_value (const string& opt, const vector<string>& opt_parts)
+ {
+   unsigned size = opt_parts.size ();
+   if (size < 2 || size > 3)
+     profile_config_error (opt); // doesn't return
+ 
+   vector<string> sub_parts = sidutil::tokenize (opt_parts[1], ",");
+   string value = sub_parts[0];
+   if (size == 3)
+     {
+       if (sub_parts.size () != 2 || sub_parts[1] != "cycles")
+ 	profile_config_error (opt); // doesn't return
+ 
+       unsigned n;
+       sid::component::status s = sidutil::parse_attribute (opt_parts[2], n);
+       if (s != sid::component::ok)
+ 	profile_config_error (opt); // doesn't return
+ 
+       value += "," + opt_parts[2];
+     }
+ 
+   need_gprof = true;
+   return value;
+ }
+ 
+ bool
+ SessionCfg::match_profile_opt (const string &opt, const string& want, unsigned min_size)
+ {
+   unsigned opt_size = opt.size ();
+   unsigned want_size = want.size ();
+   if (opt_size < min_size || opt_size > want_size)
+     return false;
+   return opt == want.substr (0, opt_size);
+ }
+ 
+ void 
+ SessionCfg::profile_config (const string &spec)
+ {
+   // Extract the name of the config profile
+   vector<string> parts = sidutil::tokenize (spec, ":");
+   if (parts.size () != 2)
+     profile_config_error (spec);
+   string name = parts[0];
+ 
+   // Initialize the candidate options to their default values.
+   string trace_extract = "false";
+   string trace_semantics = "false";
+   string trace_disassemble = "false";
+   string trace_core = "false";
+   string trace_counter = "false";
+   string ulog_level = "0";
+   string ulog_mode = "less";
+   string wrap = "";
+   string verbose = "false";
+   string final_insn_count = "false";
+   string gprof = "";
+   string insn_count = "10000";
+ 
+   // Now examine the spec and reset those which are specified.
+   vector<string>opts = sidutil::tokenize (parts[1], " ");
+   int size = opts.size ();
+   for (int i = 0; i < size; ++i)
+     {
+       const string opt = opts[i];
+       vector<string> opt_parts = sidutil::tokenize (opt, "=");
+       const string opt_name = opt_parts[0];
+ 
+       if (match_profile_opt (opt_name, "--trace-extract", 9))
+ 	trace_extract = profile_opt_value (opt, opt_parts, 1);
+       else if (match_profile_opt (opt_name, "--trace-semantics", 9))
+ 	trace_semantics = profile_opt_value (opt, opt_parts, 1);
+       else if (match_profile_opt (opt_name, "--trace-disassemble", 9))
+ 	trace_disassemble = profile_opt_value (opt, opt_parts, 1);
+       else if (match_profile_opt (opt_name, "--trace-core", 11))
+ 	{
+ 	  trace_core = profile_opt_value (opt, opt_parts, 1);
+ 	  need_core_probe = true;
+ 	}
+       else if (match_profile_opt (opt_name, "--trace-counter", 11))
+ 	trace_counter = profile_opt_value (opt, opt_parts, 1);
+       else if (match_profile_opt (opt_name, "--ulog-level=", 8))
+ 	ulog_level = profile_opt_int_value (opt, opt_parts);
+       else if (match_profile_opt (opt_name, "--ulog-mode=", 8))
+ 	ulog_mode = profile_opt_value (opt, opt_parts, 2);
+       else if (match_profile_opt (opt_name, "--verbose", 3))
+ 	verbose = profile_opt_value (opt, opt_parts, 1);
+       else if (match_profile_opt (opt_name, "--wrap=", 3))
+ 	{
+ 	  string comp_name = profile_opt_value (opt, opt_parts, 2);
+ 	  use_tcl_bridge ();
+ 	  AtomicCfg *comp = AtomicCfg::possible_wrap_name (comp_name);
+ 	  if (! wrap.empty ()) wrap += ",";
+ 	  if (comp)
+ 	    wrap += comp->get_name ();
+ 	  else
+ 	    wrap += comp_name;
+ 	}
+       else if (match_profile_opt (opt_name, "--final-insn-count", 3))
+ 	final_insn_count = profile_opt_value (opt, opt_parts, 1);
+       else if (match_profile_opt (opt_name, "--gprof=", 3))
+ 	gprof = profile_opt_gprof_value (opt, opt_parts);
+       else if (match_profile_opt (opt_name, "--insn-count=", 3))
+ 	insn_count = profile_opt_int_value (opt, opt_parts);
+     }
+ 
+   // Now contruct a string representing the complete configuration
+   add_profile_config (name,
+ 		      "trace-extract="     + trace_extract     + ":" +
+ 		      "trace-semantics="   + trace_semantics   + ":" +
+ 		      "trace-disassemble=" + trace_disassemble + ":" +
+ 		      "trace-core="        + trace_core        + ":" +
+ 		      "trace-counter="     + trace_counter     + ":" +
+ 		      "ulog-level="        + ulog_level        + ":" +
+ 		      "ulog-mode="         + ulog_mode         + ":" +
+ 		      "wrap="              + wrap              + ":" +
+ 		      "verbose="           + verbose           + ":" +
+ 		      "final-insn-count="  + final_insn_count  + ":" +
+ 		      "gprof="             + gprof             + ":" +
+ 		      "insn-count="        + insn_count);
+ }
+ 
  void SessionCfg::write_config (Writer &w)
  {
    AggregateCfg::write_config (w);
*************** LoaderCfg::LoaderCfg (const string name,
*** 733,739 ****
  {
    assert (sess);
    set (this, "file", "a.out");
-   set (this, "verbose?", sess->verbose ? "true" : "false");
    conn_pin (this, "error", sess->main_obj, "stop!");
    sess->init_seq->add_output (1, this, "load!");
  }
--- 913,918 ----
*************** GlossCfg::GlossCfg (const string name, 
*** 778,784 ****
    conn_pin (this, "trap", cpu, "trap", both);
    conn_pin (this, "trap-code", cpu, "trap-code", dst_to_src);
    conn_bus (this, "target-memory", mem, mem_bus_name);
-   set (this, "verbose?", sess->verbose ? "true" : "false");
    assert (sess->init_seq);
    sess->init_seq->add_output (2, this, "reset");
  }
--- 957,962 ----
*************** GlossCfg::GlossCfg (const string name, 
*** 796,807 ****
    relate (this, "cpu", cpu);
    conn_pin (this, "trap", cpu, "trap", both);
    conn_pin (this, "trap-code", cpu, "trap-code", dst_to_src);
-   set (this, "verbose?", sess->verbose ? "true" : "false");
    assert (sess->init_seq);
    sess->init_seq->add_output (2, this, "reset");
  }
  
- 
  // GprofCfg
  GprofCfg::~GprofCfg() {}
  GprofCfg::GprofCfg (const string name, 
--- 974,983 ----
*************** GprofCfg::GprofCfg (const string name, 
*** 817,826 ****
  {
    assert (cpu);
    assert (sess);
    if (type == simulated_cycles)
      {
-       assert (sess->sim_sched);
-       int slot = sess->sim_sched->add_subscription (this, "sample");
        sess->sim_sched->set_regular (slot, true);
        sess->sim_sched->set_time (slot, interval);
      }
--- 993,1005 ----
  {
    assert (cpu);
    assert (sess);
+   // Add a subscription to the target scheduler. Even if it's not
+   // used now, it could be used due to dynamic configuration.
+   assert (sess->sim_sched);
+   int slot = sess->sim_sched->add_subscription (this, "sample");
+ 
    if (type == simulated_cycles)
      {
        sess->sim_sched->set_regular (slot, true);
        sess->sim_sched->set_time (slot, interval);
      }
*************** GprofCfg::GprofCfg (const string name, 
*** 837,842 ****
--- 1016,1045 ----
    set (this, "value-attribute", "pc");
    set (this, "bucket-size", "4"); // bytes-per-bucket
    set (this, "output-file", filename);
+   set (this, "sim-sched-event", sidutil::make_attribute (slot));
+ }
+ 
+ // Create a gprof component but don't activate it
+ GprofCfg::GprofCfg (const string name,
+ 		    CpuCfg *cpu, 
+ 		    SessionCfg *sess) :
+   ComponentCfg (name),
+   AtomicCfg ( name, "libprof.la", 
+ 	      "prof_component_library",
+ 	      "sw-profile-gprof")
+ {
+   assert (cpu);
+   assert (sess);
+   // Add a subscription to the target scheduler. Even if it's not
+   // used now, it could be used due to dynamic configuration.
+   assert (sess->sim_sched);
+   int slot = sess->sim_sched->add_subscription (this, "sample");
+ 
+   sess->shutdown_seq->add_output (7, this, "store");
+   relate (this, "target-component", cpu);
+   set (this, "value-attribute", "pc");
+   set (this, "bucket-size", "4"); // bytes-per-bucket
+   set (this, "sim-sched-event", sidutil::make_attribute (slot));
  }
  
  
*************** void GdbCfg::write_config (Writer &w)
*** 914,919 ****
--- 1117,1135 ----
        Setting (stub, "trace-gdbserv?", "true").write_to (w); 
        Setting (sock, "verbose?", "true").write_to (w); 
      }
+ 
+   // the stub and socket need to be connected to the dynamic_configurator.
+   if (board->dynamic_configurator)
+     {
+       if (! stub->possibly_wrapped ())
+ 	{
+ 	  Relation (board->dynamic_configurator, "client", stub).write_to (w);
+ 	}
+       if (! sock->possibly_wrapped ())
+ 	{
+ 	  Relation (board->dynamic_configurator, "client", sock).write_to (w);
+ 	}
+     }
  }
  
  
*************** BoardCfg::BoardCfg (const string name, 
*** 938,944 ****
    main_mapper (NULL),
    icache (NULL),
    dcache (NULL),
!   loader (NULL)
  {
    assert (sess);
    cpu = new CpuCfg ("cpu", default_cpu_variant, sess);
--- 1154,1164 ----
    main_mapper (NULL),
    icache (NULL),
    dcache (NULL),
!   loader (NULL),
!   core_probe (0),
!   dynamic_configurator (NULL),
!   start_config (""),
!   warmup_funcs ("_Sid_config")
  {
    assert (sess);
    cpu = new CpuCfg ("cpu", default_cpu_variant, sess);
*************** BoardCfg::BoardCfg (const string name, 
*** 958,963 ****
--- 1178,1186 ----
        cpu->set_imem (main_mapper, "access-port");
        cpu->set_dmem (main_mapper, "access-port");
      }
+  
+   sess->shutdown_seq->add_output (0, cpu, "print-insn-summary!");
+ 
    add_child (cpu);
    add_child (main_mapper);
    add_child (cache_flush_net);
*************** void BoardCfg::set_loader (LoaderCfg *l)
*** 997,1005 ****
--- 1220,1268 ----
    add_child (l);
  }
  
+ void BoardCfg::write_load (Writer &w)
+ {
+   if (gloss)
+     {
+       // Create a dynamic reconfigurator to be used by this gloss
+       dynamic_configurator = new AtomicCfg ("dynamic-config", "libconfig.la", 
+ 					    "config_component_library",
+ 					    "sid-control-dynamic-configurator");
+       sess->init_seq->add_output (6, dynamic_configurator, "step!");
+       sess->reset_net->add_output (2, dynamic_configurator, "reset");
+       sess->sim_sched->add_subscription (dynamic_configurator, "step!", "step-control");
+       add_child (dynamic_configurator);
+ 
+       // If we may need a gprof for dynamic configuration but don't have
+       // one yet, then create a disabled one.
+       if (! gprof && sess->need_gprof)
+ 	{
+ 	  gprof = new GprofCfg ("gprof", cpu, sess);
+ 	  add_child (gprof);
+ 	}
+ 
+       // If we may need a core_probe for dynamic configuration but don't have
+       // one yet, then create a disabled one.
+       if (! core_probe && sess->need_core_probe)
+ 	{
+ 	  trace_core ();
+ 	  core_probe->set (core_probe, "trace?", "false");
+ 	}
+ 
+       if (sess->verbose)
+ 	set (gloss, "verbose?", "true");
+     }
+   if (loader)
+     if (sess->verbose)
+       set (loader, "verbose?", "true");
+ 
+   AggregateCfg::write_load (w);
+ }
+ 
  void BoardCfg::write_config (Writer &w)
  {
    AggregateCfg::write_config (w);
+ 
    if (gloss)
      {      
        if (gdb)
*************** void BoardCfg::write_config (Writer &w)
*** 1024,1029 ****
--- 1287,1354 ----
  	  PinConnection (gloss, "process-signal", sess->main_obj, "stop!").write_to(w);
  	  PinConnection (gloss, "process-signal", sess->yield_net, "input").write_to(w);
  	}
+ 
+       // Set up for dynamic configuration
+       assert (dynamic_configurator);
+       Relation (dynamic_configurator, "main", sess->main_obj).write_to (w);
+       PinConnection (dynamic_configurator, "step-control", cpu, "yield").write_to (w);
+       Relation (gloss, "main", sess->main_obj).write_to (w);
+       Relation (gloss, "dynamic-configurator", dynamic_configurator).write_to (w);
+       PinConnection (gloss, "configure", dynamic_configurator, "configure!").write_to (w);
+       PinConnection (dynamic_configurator, "config-result", gloss, "config-result").write_to (w);
+       PinConnection (dynamic_configurator, "config-error", gloss, "config-error").write_to (w);
+ 
+       // Set the starting configuration
+       if (start_config.empty ())
+ 	start_config = "sid-internal-warmup";
+       Setting (dynamic_configurator, "start-config", start_config).write_to (w);
+ 
+       // Connect the new-config pin of the dynamic configurator to
+       // the components of this board which need to know when the
+       // configuration changes.
+       assert (cpu);
+       Relation (cpu, "main", sess->main_obj).write_to (w);
+       if (! cpu->possibly_wrapped ())
+ 	{
+ 	  Relation (dynamic_configurator, "client", cpu).write_to (w);
+ 	}
+       if (gprof)
+       	{
+ 	  // gprof's configure! attribute will be set by the cpu.
+ 	  Relation (gprof, "sim-sched", sess->sim_sched).write_to (w);
+ 	  Relation (cpu, "gprof", gprof).write_to (w);
+       	}
+       if (! gloss->possibly_wrapped ())
+ 	{
+ 	  Relation (dynamic_configurator, "client", gloss).write_to (w);
+ 	}
+       if (core_probe)
+ 	Relation (cpu, "core-probe", core_probe).write_to (w);
+ 
+       // Connect the new-config pin of the dynamic configurator to any wrapped child components
+       dynamic_config_for_wrapped_children (dynamic_configurator, w);
+ 
+       // Make the connections which enable the dynamic configurator to change configs on function
+       // call and return.
+       if (loader)
+ 	{
+ 	  if (! loader->possibly_wrapped ())
+ 	    {
+ 	      Relation (dynamic_configurator, "client", loader).write_to (w);
+ 	    }
+ 	  PinConnection (cpu, "cg-caller", dynamic_configurator, "function-caller!").write_to (w);
+ 	  PinConnection (cpu, "cg-callee", dynamic_configurator, "function-callee!").write_to (w);
+ 	  PinConnection (cpu, "cg-jump", dynamic_configurator, "function-jump!").write_to (w);
+ 	  PinConnection (cpu, "cg-return", dynamic_configurator, "function-return!").write_to (w);
+ 	  Relation (dynamic_configurator, "loader", loader).write_to (w);
+ 	  PinConnection (dynamic_configurator, "function-address", loader, "function?").write_to (w);
+ 	}
+ 
+       // Initialize the warmup functions and profile functions.
+       assert (! warmup_funcs.empty ());
+       Setting (dynamic_configurator, "warmup-functions!", warmup_funcs).write_to (w);
+       if (! profile_funcs.empty ())
+ 	Setting (dynamic_configurator, "profile-functions!", profile_funcs.substr (1)).write_to (w); // Skip the initial delimeter.
      }
    else
      {
*************** void BoardCfg::final_insn_count ()
*** 1113,1119 ****
  {
    assert (cpu);
    assert (sess->shutdown_seq);
-   sess->shutdown_seq->add_output (0, cpu, "print-insn-summary!");
    cpu->set (cpu, "final-insn-count?", "true");
  }
  
--- 1438,1443 ----
*************** void BoardCfg::trace_core ()
*** 1208,1210 ****
--- 1532,1564 ----
    core_probe->conn_bus (core_probe, "downstream", main_mapper, "access-port", false);
    core_probe->set (core_probe, "trace?", "true");
  }
+ 
+ void BoardCfg::add_profile_func (const string &spec)
+ {
+   if (! spec.empty ())
+     profile_funcs += "|" + spec;
+ }
+ 
+ void BoardCfg::add_warmup_func (const string &funcs)
+ {
+   if (! funcs.empty ())
+     warmup_funcs += "," + funcs;
+ }
+ 
+ void BoardCfg::set_warmup (bool w)
+ {
+   if (w)
+     start_config = "sid-internal-warmup";
+ }
+ 
+ void BoardCfg::set_start_config (const string &config)
+ {
+   if (! start_config.empty ())
+     return;
+ 
+   if (! config.empty ())
+     {
+       start_config = "sid-internal-start-" + get_name ();
+       sess->profile_config (start_config + ":" + config.substr (1));  // get past leading comma
+     }
+ }
Index: sid/main/dynamic/commonCfg.h
===================================================================
RCS file: /cvs/src/src/sid/main/dynamic/commonCfg.h,v
retrieving revision 1.7
diff -c -p -r1.7 commonCfg.h
*** sid/main/dynamic/commonCfg.h	10 May 2005 15:51:08 -0000	1.7
--- sid/main/dynamic/commonCfg.h	4 Aug 2005 18:32:40 -0000
*************** struct SessionCfg :
*** 235,245 ****
--- 235,260 ----
    AtomicCfg *tcl_bridge;
    bool verbose;
    bool use_stdio;
+   bool need_gprof;
+   bool need_core_probe;
    void add_ulog_file (const string filename);
+ 
    map<const string, AtomicCfg *> ulog_map;
    void add_gdb () { ++gdb_count; }
    void add_board (ComponentCfg *b) { ++board_count; add_child (b); }
    virtual void write_config (Writer &w);
+   // Support for dynamic configuration profiles
+   vector<AtomicCfg *> wrapped_components;
+   void add_wrapped_component (AtomicCfg *comp) { wrapped_components.push_back (comp); }
+   string wrap_config ();
+   void profile_config (const string &spec);
+ protected:
+   void add_profile_config (const string &name, const string &options);
+   void profile_config_error (const string &spec);
+   string profile_opt_value (const string& opt, const vector<string>& opt_parts, unsigned max_parts);
+   string profile_opt_int_value (const string& opt, const vector<string>& opt_parts);
+   string profile_opt_gprof_value (const string& opt, const vector<string>& opt_parts);
+   bool match_profile_opt (const string &opt, const string& want, unsigned min_size);
  private:
    sid::host_int_4 board_count;
    sid::host_int_4 gdb_count;
*************** public:
*** 303,308 ****
--- 318,326 ----
  	    SessionCfg *sess,
  	    gprof_type type,
              int interval);
+   GprofCfg (const string name, 
+ 	    CpuCfg *cpu, 
+ 	    SessionCfg *sess);
    virtual ~GprofCfg ();
  };
  
*************** public:
*** 356,361 ****
--- 374,384 ----
    virtual void trace_semantics ();
    virtual void trace_disassemble ();
    virtual void trace_core ();
+   virtual void set_warmup (bool w = true);
+   virtual void add_profile_func (const string &spec);
+   virtual void add_warmup_func (const string &funcs);
+   virtual void set_start_config (const string &config);
+   virtual void write_load (Writer &w);
    virtual void write_config (Writer &w);
  
    virtual ~BoardCfg ();
*************** public:
*** 365,370 ****
--- 388,394 ----
    CpuCfg *cpu;
    SessionCfg *sess;
    MapperCfg *main_mapper;
+   AtomicCfg *dynamic_configurator;
  
   protected:
    GdbCfg *gdb;
*************** public:
*** 374,379 ****
--- 398,407 ----
    AtomicCfg *icache;
    AtomicCfg *dcache;  
    LoaderCfg *loader;
+ 
+   string start_config;
+   string warmup_funcs;
+   string profile_funcs;
  };
  
  #endif // __commonCfg_h__
Index: sid/main/dynamic/mainDynamic.cxx
===================================================================
RCS file: /cvs/src/src/sid/main/dynamic/mainDynamic.cxx,v
retrieving revision 1.6
diff -c -p -r1.6 mainDynamic.cxx
*** sid/main/dynamic/mainDynamic.cxx	22 Mar 2004 21:28:55 -0000	1.6
--- sid/main/dynamic/mainDynamic.cxx	4 Aug 2005 18:32:41 -0000
***************
*** 1,6 ****
  // mainDynamic.cxx - high-tech mainline.  -*- C++ -*-
  
! // Copyright (C) 1999-2004 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 ----
  // mainDynamic.cxx - high-tech mainline.  -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
***************
*** 14,19 ****
--- 14,21 ----
  #include <getopt.h>
  
  
+ #include <string>
+ 
  // Stub functions to set breakpoints on
  static void sid_pre_configure () {}
  static void sid_post_configure () {}
*************** usage ()
*** 68,73 ****
--- 70,77 ----
    cout << "FILE names supplied without -f are done last, in sequence." << endl;
    cout << endl;
    cout << "--persistent          Run top-level loop indefinitely" << endl;
+   cout << "--profile-config=NAME,OPTIONS" << endl;
+   cout << "                      Specify options for a named profiling configuration" << endl;
    cout << "--rc                  Pass stop code as simulator exit rc" << endl;
    cout << "--save-temps=FILE     Write config to FILE, '-' for stdout." << endl;
    cout << "--wrap=COMPONENT      Turn on SID API tracing for COMPONENT" << endl;
*************** usage ()
*** 120,129 ****
--- 124,138 ----
         << "                         mmap         Memory map given file" << endl
         << "                         latency=r:w  Set read, write latencies [0:0]" << endl
         << "                         latency=rw   Set both latencies [0]" << endl;
+   cout << "--profile-func=FUNCTIONS:NAME" << endl;
+   cout << "                      Specify functions which use a given profiling configuration" << endl;
    cout << "--ulog-level=LEVEL    Set the logging level for the current board" << endl;
    cout << "--ulog-mode=less|match|equal" << endl
         << "                      Set the logging mode for the current board" << endl;
    cout << "--ulog-file=-|FILE    Set the log file name" << endl;
+   cout << "--warmup              Start the simulation in 'warm-up' mode" << endl;
+   cout << "--warmup-func=FUNCTIONS" << endl;
+   cout << "                      Specify functions to be simulated in 'warm-up' mode" << endl;
    cout << endl
         << " note: most board-specific options can be used in board-neutral position " << endl
         << " where they are interpreted as session-specific or default settings. " << endl;
*************** void try_add_gprof(const string optstrin
*** 416,423 ****
    type = instruction_count;	// default type value
    if (toks.size() > 1)		// if we have a type argument
      {
        vector<string> subtoks = sidutil::tokenize (toks[1], "=");
-       
        if (subtoks[0] == "cycles")	// If it is cycles
          {
            type = simulated_cycles;
--- 425,436 ----
    type = instruction_count;	// default type value
    if (toks.size() > 1)		// if we have a type argument
      {
+       if (toks[1].empty ())
+ 	{
+           cerr << "error: unknown sub-option to --gprof: " << optstring << endl;
+           exit (21);      
+ 	}
        vector<string> subtoks = sidutil::tokenize (toks[1], "=");
        if (subtoks[0] == "cycles")	// If it is cycles
          {
            type = simulated_cycles;
*************** struct Defs {
*** 468,473 ****
--- 481,490 ----
  	    ulog_level (0),
  	    ulog_mode ("less"),
  	    ulog_file ("-"),
+ 	    warmup (false),
+ 	    profile_func (""),
+ 	    warmup_func (""),
+ 	    start_config (""),
  	    step_insn_count ("10000")
    {}
    string cpu;
*************** struct Defs {
*** 481,497 ****
    sid::host_int_4 ulog_level;
    string ulog_mode;
    string ulog_file;
    string step_insn_count;
  };
    
  
! void need_sess (SessionCfg *&sess)
  {
    if (! sess)
!     sess = new SessionCfg ("");
  }
  
- 
  // main line
  int
  main(int argc, char* argv[])
--- 498,526 ----
    sid::host_int_4 ulog_level;
    string ulog_mode;
    string ulog_file;
+   bool warmup;
+   string profile_func;
+   string warmup_func;
+   string start_config;
    string step_insn_count;
  };
    
+ struct BoardConfig
+ {
+   BoardCfg *board;
+   string config;
+ };
  
! static void need_sess (SessionCfg *&sess, bool verbose)
  {
    if (! sess)
!     {
!       sess = new SessionCfg ("");
!       sess->profile_config ("sid-internal-warmup:");
!       sess->verbose = verbose;
!     }
  }
  
  // main line
  int
  main(int argc, char* argv[])
*************** main(int argc, char* argv[])
*** 504,509 ****
--- 533,539 ----
    string output_file ("");
    SessionCfg *sess = NULL;
    BoardCfg *curr_board = NULL;
+   vector<BoardConfig> board_configs;
    int nboards = 0;
  
    if (argc == 1)
*************** main(int argc, char* argv[])
*** 518,530 ****
  
    enum option_num { opt_help, opt_version, opt_save_temps, opt_wrap, 
  		    opt_verbose, opt_tksched, opt_enable_warnings,
! 		    opt_persistent, opt_rc, opt_no_run, opt_sidrtc, opt_sidcodec, 
  		    opt_tksm, opt_board, opt_cpu, opt_gdb, opt_gloss, opt_engine, 
  		    opt_insn_count, opt_load, opt_icache, opt_dcache, 
! 		    opt_memory_region, opt_trace_extract, opt_trace_semantics,
  		    opt_trace_disassemble, opt_trace_counter, opt_trace_core,
  		    opt_final_insn_count, opt_eb, opt_el, opt_gprof,
! 		    opt_ulog_level, opt_ulog_mode, opt_ulog_file };
  		    
    int curr_opt;
  
--- 548,563 ----
  
    enum option_num { opt_help, opt_version, opt_save_temps, opt_wrap, 
  		    opt_verbose, opt_tksched, opt_enable_warnings,
! 		    opt_persistent, opt_profile_config,
! 		    opt_rc, opt_no_run, opt_sidrtc, opt_sidcodec, 
  		    opt_tksm, opt_board, opt_cpu, opt_gdb, opt_gloss, opt_engine, 
  		    opt_insn_count, opt_load, opt_icache, opt_dcache, 
! 		    opt_memory_region, opt_profile_func,
! 		    opt_trace_extract, opt_trace_semantics,
  		    opt_trace_disassemble, opt_trace_counter, opt_trace_core,
  		    opt_final_insn_count, opt_eb, opt_el, opt_gprof,
! 		    opt_ulog_level, opt_ulog_mode, opt_ulog_file,
! 		    opt_warmup, opt_warmup_func };
  		    
    int curr_opt;
  
*************** main(int argc, char* argv[])
*** 543,548 ****
--- 576,582 ----
      {"tksched",         no_argument, & curr_opt, opt_tksched },
      {"enable-warnings", no_argument, & curr_opt, opt_enable_warnings },
      {"persistent",      no_argument, & curr_opt, opt_persistent },
+     {"profile-config",  required_argument, &curr_opt, opt_profile_config },
      {"rc",              no_argument, & curr_opt, opt_rc },
      {"tksm",            no_argument, & curr_opt, opt_tksm },
  
*************** main(int argc, char* argv[])
*** 561,566 ****
--- 595,601 ----
      {"dcache",            required_argument, & curr_opt, opt_dcache },
      {"memory-region",     required_argument, & curr_opt, opt_memory_region },
      {"gloss",             no_argument, & curr_opt, opt_gloss },
+     {"profile-func",      required_argument, &curr_opt, opt_profile_func },
      {"trace-extract",     no_argument, & curr_opt, opt_trace_extract },
      {"trace-semantics",   no_argument, & curr_opt, opt_trace_semantics },
      {"trace-disassemble", no_argument, & curr_opt, opt_trace_disassemble },
*************** main(int argc, char* argv[])
*** 572,580 ****
      {"ulog-level",        required_argument, &curr_opt, opt_ulog_level },
      {"ulog-mode",         required_argument, &curr_opt, opt_ulog_mode },
      {"ulog-file",         required_argument, &curr_opt, opt_ulog_file },
      { 0, 0, NULL, 0 }
   };
!   
    while (true)
      {
        int c = getopt_long (argc, argv, "+hvne:f:",
--- 607,619 ----
      {"ulog-level",        required_argument, &curr_opt, opt_ulog_level },
      {"ulog-mode",         required_argument, &curr_opt, opt_ulog_mode },
      {"ulog-file",         required_argument, &curr_opt, opt_ulog_file },
+     {"warmup",            no_argument, &curr_opt, opt_warmup },
+     {"warmup-func",       required_argument, &curr_opt, opt_warmup_func },
      { 0, 0, NULL, 0 }
   };
! 
!   string board_start_config = "";
!   string wrap_config = "";
    while (true)
      {
        int c = getopt_long (argc, argv, "+hvne:f:",
*************** main(int argc, char* argv[])
*** 615,623 ****
  
  	    case opt_board:
  	      {
! 		need_sess (sess);
  		if (curr_board)
! 		  sess->add_board (curr_board);
  		curr_board = NULL;
  		string new_board_type = optstring();
  		string new_board_name (new_board_type + "-" + 
--- 654,670 ----
  
  	    case opt_board:
  	      {
! 		need_sess (sess, verbose_p);
  		if (curr_board)
! 		  {
! 		    sess->add_board (curr_board);
! 		    if (! defaults.warmup)
! 		      {
! 			BoardConfig bc = { curr_board, defaults.start_config + board_start_config };
! 			board_configs.push_back (bc);
! 		      }
! 		    board_start_config = "";
! 		  }
  		curr_board = NULL;
  		string new_board_type = optstring();
  		string new_board_name (new_board_type + "-" + 
*************** main(int argc, char* argv[])
*** 648,653 ****
--- 695,703 ----
  			curr_board->set_ulog_level (defaults.ulog_level);
  			curr_board->set_ulog_mode (defaults.ulog_mode);
  			curr_board->set_ulog_file (defaults.ulog_file);
+ 			curr_board->set_warmup (defaults.warmup);
+ 			curr_board->add_warmup_func (defaults.warmup_func);
+ 			curr_board->add_profile_func (defaults.profile_func);
  			if (defaults.step_insn_count != "10000")
  			  curr_board->set_step_insn_count(defaults.step_insn_count);
  			break;
*************** main(int argc, char* argv[])
*** 676,686 ****
--- 726,738 ----
  	      verbose_p = true;
  	      if (sess)
  		sess->verbose = true;
+ 	      defaults.start_config += " --verbose";
  	      break;
  	     
  	    case opt_gprof:
  	      option_requires_board (curr_board, "gprof");
  	      try_add_gprof(optstring(), curr_board);
+ 	      board_start_config += " --gprof=" + optstring();
  	      break;
  
  	    case opt_gdb:
*************** main(int argc, char* argv[])
*** 695,701 ****
  	      break;
  
  	    case opt_load:
! 	      need_sess (sess);
  	      try_load_file (optstring(), curr_board, sess);
  	      break;
  	      
--- 747,753 ----
  	      break;
  
  	    case opt_load:
! 	      need_sess (sess, verbose_p);
  	      try_load_file (optstring(), curr_board, sess);
  	      break;
  	      
*************** main(int argc, char* argv[])
*** 708,751 ****
  	      
  	    case opt_trace_extract:
  	      if (curr_board)
! 		curr_board->trace_extract();
  	      else
! 		defaults.trace_extract = true;
  	      break;
  
  	    case opt_trace_semantics:
  	      if (curr_board)
! 		curr_board->trace_semantics();
  	      else
! 		defaults.trace_semantics = true;
  	      break;
  
  	    case opt_trace_disassemble:
  	      if (curr_board)
! 		curr_board->trace_disassemble();
  	      else
! 		defaults.trace_disassemble = true;
  	      break;
  
  	    case opt_trace_counter:
  	      if (curr_board)
! 		curr_board->trace_counter();
  	      else
! 		defaults.trace_counter = true;
  	      break;
  
  	    case opt_final_insn_count:
  	      if (curr_board)
! 		curr_board->final_insn_count();
  	      else
! 		defaults.final_insn_count = true;
  	      break;
  
  	    case opt_trace_core:
  	      if (curr_board)
! 		curr_board->trace_core();
  	      else
! 		defaults.trace_core = true;
  	      break;
  
  	    case opt_enable_warnings:
--- 760,839 ----
  	      
  	    case opt_trace_extract:
  	      if (curr_board)
! 		{
! 		  board_start_config += " --trace-extract";
! 		  curr_board->trace_extract();
! 		}
  	      else
! 		{
! 		  defaults.trace_extract = true;
! 		  defaults.start_config += " --trace-extract";
! 		}
  	      break;
  
  	    case opt_trace_semantics:
  	      if (curr_board)
! 		{
! 		  board_start_config += " --trace-semantics";
! 		  curr_board->trace_semantics();
! 		}
  	      else
! 		{
! 		  defaults.trace_semantics = true;
! 		  defaults.start_config += " --trace-semantics";
! 		}
  	      break;
  
  	    case opt_trace_disassemble:
  	      if (curr_board)
! 		{
! 		  curr_board->trace_disassemble();
! 		  board_start_config += " --trace-disassemble";
! 		}
  	      else
! 		{
! 		  defaults.trace_disassemble = true;
! 		  defaults.start_config += " --trace-disassemble";
! 		}
  	      break;
  
  	    case opt_trace_counter:
  	      if (curr_board)
! 		{
! 		  curr_board->trace_counter();
! 		  board_start_config += " --trace-counter";
! 		}
  	      else
! 		{
! 		  defaults.trace_counter = true;
! 		  defaults.start_config += " --trace-counter";
! 		}
  	      break;
  
  	    case opt_final_insn_count:
  	      if (curr_board)
! 		{
! 		  curr_board->final_insn_count();
! 		  board_start_config += " --final-insn-count";
! 		}
  	      else
! 		{
! 		  defaults.final_insn_count = true;
! 		  defaults.start_config += " --final-insn-count";
! 		}
  	      break;
  
  	    case opt_trace_core:
  	      if (curr_board)
! 		{
! 		  curr_board->trace_core();
! 		  board_start_config += " --trace-core";
! 		}
  	      else
! 		{
! 		  defaults.trace_core = true;
! 		  defaults.start_config += " --trace-core";
! 		}
  	      break;
  
  	    case opt_enable_warnings:
*************** main(int argc, char* argv[])
*** 760,779 ****
  		string c (optstring());
  		if (sess)
  		  sess->use_tcl_bridge ();
! 		if (! AtomicCfg::wrap_component (c))
  		  {
  		    cerr << "error: no component named '" << c << "' to wrap" << endl;
  		    exit (9);
  		  }
  	      }
  	      break;
  
  	      
  	    case opt_insn_count:
  	      if (curr_board)
! 		curr_board->set_step_insn_count(optstring());
  	      else
! 		defaults.step_insn_count = optstring();
  	      break;
  
  	    case opt_persistent:
--- 848,875 ----
  		string c (optstring());
  		if (sess)
  		  sess->use_tcl_bridge ();
! 		AtomicCfg *comp = AtomicCfg::wrap_component (c);
! 		if (! comp)
  		  {
  		    cerr << "error: no component named '" << c << "' to wrap" << endl;
  		    exit (9);
  		  }
+ 		sess->add_wrapped_component (comp);
  	      }
  	      break;
  
  	      
  	    case opt_insn_count:
  	      if (curr_board)
! 		{
! 		  curr_board->set_step_insn_count(optstring());
! 		  board_start_config += " --insn-count=" + optstring();
! 		}
  	      else
! 		{
! 		  defaults.step_insn_count = optstring();
! 		  defaults.start_config += " --insn-count=" + optstring();
! 		}
  	      break;
  
  	    case opt_persistent:
*************** main(int argc, char* argv[])
*** 805,811 ****
  	      break;
  
  	    case opt_memory_region:
! 	      need_sess (sess);
  	      try_add_memory (optstring(), curr_board, sess);
  	      break;
  
--- 901,907 ----
  	      break;
  
  	    case opt_memory_region:
! 	      need_sess (sess, verbose_p);
  	      try_add_memory (optstring(), curr_board, sess);
  	      break;
  
*************** main(int argc, char* argv[])
*** 835,862 ****
  
  	    case opt_ulog_level:
  	      if (curr_board)
! 		curr_board->set_ulog_level (optaddr ("ulog-level"));
  	      else
  		{
  		  defaults.ulog_level = optaddr ("ulog-level");
! 		  need_sess (sess);
  		  sess->set_ulog_level (optaddr ("ulog-level"));
  		}
  	      break;
  
  	    case opt_ulog_mode:
  	      if (curr_board)
! 		curr_board->set_ulog_mode (optstring ());
  	      else
  		{
  		  defaults.ulog_mode = optstring ();
! 		  need_sess (sess);
  		  sess->set_ulog_mode (optstring ());
  		}
  	      break;
  
  	    case opt_ulog_file:
! 	      need_sess (sess);
  	      sess->add_ulog_file (optstring ());
  	      if (curr_board)
  		curr_board->set_ulog_file (optstring ());
--- 931,966 ----
  
  	    case opt_ulog_level:
  	      if (curr_board)
! 		{
! 		  curr_board->set_ulog_level (optaddr ("ulog-level"));
! 		  board_start_config += " --ulog-level=" + optstring();
! 		}
  	      else
  		{
  		  defaults.ulog_level = optaddr ("ulog-level");
! 		  defaults.start_config += " --ulog-level=" + optstring();
! 		  need_sess (sess, verbose_p);
  		  sess->set_ulog_level (optaddr ("ulog-level"));
  		}
  	      break;
  
  	    case opt_ulog_mode:
  	      if (curr_board)
! 		{
! 		  curr_board->set_ulog_mode (optstring ());
! 		  board_start_config += " --ulog-mode=" + optstring();
! 		}
  	      else
  		{
  		  defaults.ulog_mode = optstring ();
! 		  defaults.start_config += " --ulog-mode=" + optstring();
! 		  need_sess (sess, verbose_p);
  		  sess->set_ulog_mode (optstring ());
  		}
  	      break;
  
  	    case opt_ulog_file:
! 	      need_sess (sess, verbose_p);
  	      sess->add_ulog_file (optstring ());
  	      if (curr_board)
  		curr_board->set_ulog_file (optstring ());
*************** main(int argc, char* argv[])
*** 866,874 ****
  		  sess->set_ulog_file (optstring ());
  		}
  	      break;
  	    }
  	  break;
! 	  
  
  	case '?':
  	default:
--- 970,1012 ----
  		  sess->set_ulog_file (optstring ());
  		}
  	      break;
+ 
+ 	    case opt_warmup:
+ 	      if (curr_board)
+ 		curr_board->set_warmup (true);
+ 	      else
+ 		defaults.warmup = true;
+ 	      break;
+ 
+ 	    case opt_warmup_func:
+ 	      if (curr_board)
+ 		curr_board->add_warmup_func (optstring ());
+ 	      else
+ 		{
+ 		  if (! defaults.warmup_func.empty ())
+ 		    defaults.warmup_func += ",";
+ 		  defaults.warmup_func += optstring ();
+ 		}
+ 	      break;
+ 
+ 	    case opt_profile_func:
+ 	      if (curr_board)
+ 		curr_board->add_profile_func (optstring ());
+ 	      else
+ 		{
+ 		  if (! defaults.profile_func.empty ())
+ 		    defaults.profile_func += "|";
+ 		  defaults.profile_func += optstring ();
+ 		}
+ 	      break;
+ 
+ 	    case opt_profile_config:
+ 	      need_sess (sess, verbose_p);
+ 	      sess->profile_config (optstring ());
+ 	      break;
  	    }
  	  break;
! 
  
  	case '?':
  	default:
*************** main(int argc, char* argv[])
*** 878,884 ****
      }
  
    if (sess && curr_board)
!     sess->add_board (curr_board);
  
    if (persistent_p)
      config_items.push_back (make_pair (false, string("set main persistent? true")));
--- 1016,1035 ----
      }
  
    if (sess && curr_board)
!     {
!       sess->add_board (curr_board);
!       if (! defaults.warmup)
! 	{
! 	  BoardConfig bc = { curr_board, defaults.start_config + board_start_config };
! 	  board_configs.push_back (bc);
! 
! 	  string wrap_config = sess->wrap_config ();
! 	  for (vector<BoardConfig>::const_iterator it = board_configs.begin ();
! 	       it != board_configs.end ();
! 	       ++it)
! 	    it->board->set_start_config (it->config + wrap_config);
! 	}
!     }
  
    if (persistent_p)
      config_items.push_back (make_pair (false, string("set main persistent? true")));
<?xml version="1.0" ?>
<!DOCTYPE defcomplib SYSTEM "http://sources.redhat.com/sid/component.dtd";>

<defcomplib lib="internal" dlsym="config_component_library">
  <defcomponent name="sid-control-dynamic-configurator" type="concrete">

    <!-- pins -->
    <defpin name="reset"		direction="in"  legalvalues="any"			behaviors="initialization" />
    <defpin name="step!"		direction="in"  legalvalues="any"			behaviors="running" />
    <defpin name="step-control"		direction="out" legalvalues="1"			behaviors="running" />
    <defpin name="configure!"		direction="in"  legalvalues="configuration handle"	behaviors="configuration" />
    <defpin name="config-result"	direction="out" legalvalues="configuration handle"	behaviors="configuration" />
    <defpin name="config-error"	        direction="out" legalvalues="error code"	behaviors="configuration" />
    <defpin name="function-caller!"	direction="in"  legalvalues="address"		behaviors="configuration" />
    <defpin name="function-callee!"	direction="in"  legalvalues="address"		behaviors="configuration" />
    <defpin name="function-jump!"	direction="in"  legalvalues="address"		behaviors="configuration" />
    <defpin name="function-return!"	direction="in"  legalvalues="address"		behaviors="configuration" />
    <defpin name="function-address"	direction="out" legalvalues="address"		behaviors="configuration" />

    
    <!-- attributes -->
    <defattribute name ="warmup-functions!"	default="function list" behaviors="configuration" />
    <defattribute name ="profile-functions!"	default="config spec"   behaviors="configuration" />
    <defattribute name ="configure!"		default="config name"   behaviors="configuration" />
    <defattribute name ="current-config"	default="config string" behaviors="configuration" />
    
    <!-- relationships -->
    <defrelationship name="client"	behaviors="configuration" />
    <defrelationship name="loader"	behaviors="configuration" />
    <defrelationship name="main"	behaviors="configuration" />
    
  </defcomponent>

  <synop>This component manages configuration profiles for a board.
  </synop>

  <func>
    <modelling>
      <p>
      This component manages dynamic configuration of a board based upon the setting of an
      attribute, the driving of an input pin and entry/exit to/from functions.  The selected
      configurations are made available to other components in the system which then reconfigure
      themselves accordingly.</p>

      <p>This component does not correspond to hardware.</p>
    </modelling>

    <behavior name="configuration">

      <p>
      When the <attribute>configure!</attribute> attribute is written to, the value is
      interpreted as the name of a configuration spec.  The corresponding configuration
      string is then obtained from the configuration root component by setting its
      <attribute>lookup-dynamic-config!</attribute> attribute and then, if successful,
      reading its <attribute>found-dynamic-config</attribute> attribute.  A numeric handle
      is assigned to this configuration. The handle of the previous configuration is driven
      on the <pin>config-result</pin> pin. If an error occurs, a non-zero
      value will be driven on the <pin>config-error</pin> pin.</p>

      <p>
      When the <pin>configure!</pin> pin is driven, the value is interpreted as
      the handle of a configuration which was previously driven on the <pin>config-result</pin>
      pin. This configuration is then selected and the handle of the previous configuration is
      driven on the <pin>config-result</pin>. If an error occurs, a non-zero
      value will be driven on the <pin>config-error</pin> pin.</p>

      <p>
      When the <attribute>profile-functions!</attribute> attribute is written to, the value is
      interpreted as a specification of the form FUNCTION_NAME[,FUNCTION_NAME]*:CONFIG_NAME,
      where FUNCTION_NAME is the name of a function in the target software and CONFIG_NAME is
      the name of a configuration specified to the configuration root component via its
      <attribute>dynamic-config</attribute> attribute. The listed functions are then associated
      with the named configuration.  The <pin>function-caller!</pin>, <pin>function-callee!</pin>,
      <pin>function-jump!</pin> and <pin>function-return!</pin> pins should be driven by the cpu
      component as the target software executes.  The values driven on these pins are interpreted as
      memory addresses containing executable code. The addresses are driven on the <pin>function-address</pin>,
      which should be connected to the <pin>function?</pin> pin of the board's loader component. The name
      of the corresponding function is then obtained from the loader's <attribute>current-function</attribute>
      attribute. If the named function is associated with a configuration, that configuration is then
      selected.</p>

      <p>
      When the <attribute>warmup-functions!</attribute> attribute is written to, the value is
      interpreted as a comma-separated list of function names in the target software.  The listed
      functions are then associated with the configuration named sid-internal-warmup.  When one of
      the listed functions is entered (see <attribute>profile-fuinctions!</attribute> above), this
      configuration is selected.  The special function _Sid_config should be specified as a
      warmup function and it does not restore the previous configuration when returning to the function
      which called it.</p>

    </behavior>

    <behavior name="initialization">

      <p>
      When the <pin>reset</pin> pin is driven, the configuration identified by the
      <attribute>start-config</attribute> attribute is selected.</p>

    </behavior>

    <behavior name="running">

      <p>
      When the <pin>step!</pin> is driven, and the currently selected configuration has changed since the previous
      time the <pin>step!</pin> was driven, the specifiction of the currently selected configuration is passed
      on the <pin>new-config</pin> and the string representing the current configuration is made available
      to each component related via the <relationship>client</relationship> by setting their
      <attribute>configure!</attribute> attributes. Each client is then responsible for interpreting the
      specification and configuring themselves accordingly.
      </p> 

      <p>
      When a new configuration is selected, using one of the methods above, the <pin>step-control</pin> is
      driven with the value 1.</p>

    </behavior>

    <convention name="supervisory" supported="true"/>
    <convention name="save/restore" supported="false">state is minimal.</convention>
    <convention name="triggerpoints" supported="false"/>
    <convention name="recursion-inhibit" supported="false"/>
    <convention name="categories" supported="false"/>

  </func>
  <env>
  </env>

  
</defcomplib>
       sid-control-dynamic-configurator (internal :: config_component_library)

Synopsis:

   This component manages configuration profiles for a board.

     ----------------------------------------------------------------------

Functionality:

  Modelling:

   This component manages dynamic configuration of a board based upon the
   setting of an attribute, the driving of an input pin and entry/exit
   to/from functions. The selected configurations are made available to other
   components in the system which then reconfigure themselves accordingly.

   This component does not correspond to hardware.

   +-------------------------------------------------------------+
   |                          Behaviors                          |
   |-------------------------------------------------------------|
   |configuration|When the configure! attribute is written to,   |
   |             |the value is interpreted as the name of a      |
   |             |configuration spec. The corresponding          |
   |             |configuration string is then obtained from the |
   |             |configuration root component by setting its    |
   |             |lookup-dynamic-config! attribute and then, if  |
   |             |successful, reading its found-dynamic-config   |
   |             |attribute. A numeric handle is assigned to this|
   |             |configuration. The handle of the previous      |
   |             |configuration is driven and its value is driven|
   |             |on the config-result pin.                      |
   |             |                                               |
   |             |When the configure! pin is driven, the value is|
   |             |interpreted as the handle of a configuration   |
   |             |which was previously driven on the             |
   |             |config-result pin. This configuration is then  |
   |             |selected and the handle of the previous        |
   |             |configuration is driven on the config-result   |
   |             |                                               |
   |             |When the profile-functions! attribute is       |
   |             |written to, the value is interpreted as a      |
   |             |specification of the form                      |
   |             |FUNCTION_NAME[,FUNCTION_NAME]*:CONFIG_NAME,    |
   |             |where FUNCTION_NAME is the name of a function  |
   |             |in the target software and CONFIG_NAME is the  |
   |             |name of a configuration specified to the       |
   |             |configuration root component via its           |
   |             |dynamic-config attribute. The listed functions |
   |             |are then associated with the named             |
   |             |configuration. The function-caller!,           |
   |             |function-callee!, function-jump! and           |
   |             |function-return! pins should be driven by the  |
   |             |cpu component as the target software executes. |
   |             |The values driven on these pins are interpreted|
   |             |as memory addresses containing executable code.|
   |             |The addresses are driven on the                |
   |             |function-address, which should be connected to |
   |             |the function? pin of the board's loader        |
   |             |component. The name of the corresponding       |
   |             |function is then obtained from the loader's    |
   |             |current-function attribute. If the named       |
   |             |function is associated with a configuration,   |
   |             |that configuration is then selected.           |
   |             |                                               |
   |             |When the warmup-functions! attribute is written|
   |             |to, the value is interpreted as a              |
   |             |comma-separated list of function names in the  |
   |             |target software. The listed functions are then |
   |             |associated with the configuration named        |
   |             |sid-internal-warmup. When one of the listed    |
   |             |functions is entered (see profile-fuinctions!  |
   |             |above), this configuration is selected. The    |
   |             |special function _Sid_config should be         |
   |             |specified as a warmup function and it does not |
   |             |restore the previous configuration when        |
   |             |returning to the function which called it.     |
   |-------------+-----------------------------------------------|
   |      running|When the step! is driven, and the currently    |
   |             |selected configuration has changed since the   |
   |             |previous time the step! was driven, the handle |
   |             |of the currently selected configuration is     |
   |             |driven on the new-config and the string        |
   |             |representing the current configuration is made |
   |             |available via the current-config attribute.    |
   |             |                                               |
   |             |When a new configuration is selected, using one|
   |             |of the methods above, the step-control is      |
   |             |driven with the value 1.                       |
   +-------------------------------------------------------------+

   +-------------------------------------------------+
   |                 SID Conventions                 |
   |-------------------------------------------------|
   |           supervisory | supported        | -    |
   |-----------------------+------------------+------|
   |          save/restore | not supported    | -    |
   |-----------------------+------------------+------|
   |         triggerpoints | not supported    | -    |
   |-----------------------+------------------+------|
   |     recursion-inhibit | not supported    | -    |
   |-----------------------+------------------+------|
   |            categories | not supported    | -    |
   +-------------------------------------------------+

     ----------------------------------------------------------------------

Environment:

     ----------------------------------------------------------------------

Component Reference:

  Component: sid-control-dynamic-configurator

   +--------------------------------------------------------------+
   |                             pins                             |
   |--------------------------------------------------------------|
   |      name      |direction|     legalvalues     |  behaviors  |
   |----------------+---------+---------------------+-------------|
   |step!           |in       |any                  |running      |
   |----------------+---------+---------------------+-------------|
   |step-control    |out      |1                    |running      |
   |----------------+---------+---------------------+-------------|
   |configure!      |in       |configuration handle |configuration|
   |----------------+---------+---------------------+-------------|
   |new-config      |out      |configuration handle |configuration|
   |----------------+---------+---------------------+-------------|
   |config-result   |out      |configuration handle |configuration|
   |----------------+---------+---------------------+-------------|
   |function-caller!|in       |address              |configuration|
   |----------------+---------+---------------------+-------------|
   |function-callee!|in       |address              |configuration|
   |----------------+---------+---------------------+-------------|
   |function-jump!  |in       |address              |configuration|
   |----------------+---------+---------------------+-------------|
   |function-return!|in       |address              |configuration|
   |----------------+---------+---------------------+-------------|
   |function-address|out      |address              |configuration|
   +--------------------------------------------------------------+

   +-------------------------------------------------------------------+
   |                            attributes                             |
   |-------------------------------------------------------------------|
   |        name        | category | legal  | default |   behaviors   ||
   |                    |          | values |  value  |               ||
   |--------------------+----------+--------+---------+---------------||
   |warmup-functions!   |-         |-       |-        |configuration  ||
   |--------------------+----------+--------+---------+---------------||
   |profile-functions!  |-         |-       |-        |configuration  ||
   |--------------------+----------+--------+---------+---------------||
   |configure!          |-         |-       |-        |configuration  ||
   |--------------------+----------+--------+---------+---------------||
   |current-config      |-         |-       |-        |configuration  ||
   +-------------------------------------------------------------------+

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