From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8115 invoked by alias); 5 Aug 2005 19:36:12 -0000 Mailing-List: contact sid-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: sid-owner@sources.redhat.com Received: (qmail 7722 invoked by uid 22791); 5 Aug 2005 19:34:47 -0000 Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Fri, 05 Aug 2005 19:34:47 +0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.11/8.12.11) with ESMTP id j75JYj9O002218 for ; Fri, 5 Aug 2005 15:34:45 -0400 Received: from pobox.toronto.redhat.com (pobox.toronto.redhat.com [172.16.14.4]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id j75JYfV18021 for ; Fri, 5 Aug 2005 15:34:41 -0400 Received: from [172.16.14.227] (IDENT:aSJ/mol46PzEF17CsAWSb7bWmedI1enj@topaz.toronto.redhat.com [172.16.14.227]) by pobox.toronto.redhat.com (8.12.8/8.12.8) with ESMTP id j75JYd1M032097 for ; Fri, 5 Aug 2005 15:34:39 -0400 Message-ID: <42F3BF4F.1090709@redhat.com> Date: Fri, 05 Aug 2005 19:36:00 -0000 From: Dave Brolley User-Agent: Mozilla Thunderbird 1.0.2 (X11/20050317) MIME-Version: 1.0 To: sid@sources.redhat.com Subject: [patch][rfa] Dynamic Configuration of SID Content-Type: multipart/mixed; boundary="------------010804080709050905080504" X-SW-Source: 2005-q3/txt/msg00017.txt.bz2 This is a multi-part message in MIME format. --------------010804080709050905080504 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 572 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 --------------010804080709050905080504 Content-Type: text/plain; name="sid-warmup-external-spec.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sid-warmup-external-spec.txt" Content-length: 13343 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=: where is the name being assigned to this group of 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=: where is a comma-separated list of function names 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= where 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=,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 (); } } --------------010804080709050905080504 Content-Type: text/plain; name="sid-warmup-internal-spec.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sid-warmup-internal-spec.txt" Content-length: 5338 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 : 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 [, 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 [,[,]* verbose=true|false final-insn-count=true|false gprof=[,N] insn-count=N The implementation of 'configure' for each component should: 1) Call ::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. --------------010804080709050905080504 Content-Type: text/plain; name="sid-warmup.ChangeLog" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sid-warmup.ChangeLog" Content-length: 20330 sid/main/dynamic/ChangeLog: 2005-08-04 Dave Brolley * Contribute the following changes: 2005-07-13 Dave Brolley * 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 * 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 * mainDynamic.cxx (try_add_gprof): Make sure an argument is specified after the comma. 2005-06-06 Dave Brolley * 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 * 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 * Contribute the following changes: 2005-07-13 Dave Brolley * 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 * sidattrutil.h (fixed_attribute_map_with_logging_component): Initialize buffer_output to false. 2005-06-21 Dave Brolley * sidcpuutil.h (basic_cpu::configure): Call update_final_insn_count_p after processing "final-insn-count". 2005-06-06 Dave Brolley * 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 * 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 * Contribute the following changes: 2005-07-13 Dave Brolley * 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 * 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 * Contribute the following changes: 2005-07-13 Dave Brolley * gprof.cxx (gprof_component): Inherit virtually from fixed_attribute_map_component. 2005-05-29 Dave Brolley * 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 * Contribute the following changes: 2005-07-13 Dave Brolley * compLoader.cxx (generic_loader): Inherit virtually from fixed_attribute_map_component. Inherit from no_relation_component. 2005-06-06 Dave Brolley * 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 * 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 * Contribute the following changes: 2005-07-13 Dave Brolley * 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 * 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 * 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 * 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 * Contribute the following changes: 2005-07-13 Dave Brolley * gdb.h (configurable_component): Inherit virtually from fixed_attribute_map_component. 2005-06-06 Dave Brolley * 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 * Contribute the following changes: 2005-07-13 Dave Brolley * components.h (socketio): Inherit virtually from fixed_attribute_map_component. Inherit from no_relation_component. 2005-06-06 Dave Brolley * 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 * Contribute the following changes: 2005-07-13 Dave Brolley * cgen-cpu.h (notify_ret): Set last_caller and last_callee. 2005-05-29 Dave Brolley * 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 * Contribute these changes: 2005-07-13 Dave Brolley * 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 * 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 * compConfig.cxx (step_pin_handler): Always drive new_config_pin. 2005-06-06 Dave Brolley * 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 * 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. --------------010804080709050905080504 Content-Type: text/plain; name="sid-warmup.patch.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sid-warmup.patch.txt" Content-length: 164447 ? 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 component_creator_map_t; component_creator_map_t component_creator_map; + // Dynamic configurations + map 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 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 reset_pin; + callback_pin step_pin; + output_pin step_control_pin; + callback_pin configure_pin; + callback_pin function_caller_pin; + callback_pin function_callee_pin; + callback_pin function_jump_pin; + callback_pin 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 config_names; + vector config_specs; + map function_configs; + vector< pair > 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 ("", 0)); + config_names.push_back (""); + 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] != "") + { + 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 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 parts = tokenize (specs, "|"); + unsigned size = parts.size (); + for (unsigned i = 0; i < size; ++i) + { + vector spec = tokenize (parts[i], ":"); + if (spec.size () != 2) + { + s = component::bad_value; + continue; + } + + const string &profile = spec[1]; + vector 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 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 "" config to this value. + if (handle == 0 + || size == 1 && config_names[0] == "") + { + 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 (next_func, handle)); + config_stack.push_back (pair (top_func, top_handle)); + return top_handle; + } + + config_stack.push_back (pair (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 >::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::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 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 (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 >::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 compConfigListTypes() *************** compConfigListTypes() *** 1211,1216 **** --- 1750,1756 ---- vector 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(c); } --- 1771,1780 ---- void compConfigDelete(component* c) { ! cfgroot_component* c1 = dynamic_cast(c); ! if (c1) { delete c1; return; } ! dynamic_configurator_component* c2 = dynamic_cast(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 **** ! ! This component configures and executes a simulation run. --- 27,44 ---- ! ! ! ! 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. *************** rel-name ::= string *** 229,234 **** --- 233,251 ---- to a file, and the file's name supplied to the config-file! attribute.

+

+ When the + dynamic-config! 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.

+ +

+ When the + lookup-dynamic-config! attribute is written to, the value is + interpreted as a name previously associated with a config string via the + dynamic-config! attribute. The associated configuration + string is then made available via the found-dynamic-config attribute.

+ 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 ---- + + + + *************** *** 159,164 **** --- 163,177 ---- + + +

When the configure! 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.

+ +
+ 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 ---- + + + *************** *** 31,36 **** --- 34,40 ---- +

*************** *** 196,201 **** --- 200,215 ---- for single stepping.

+ + + +

When the configure! 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.

+ +
+ 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 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 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 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 ---- + + + + + *************** *** 14,19 **** --- 19,25 ---- + *************** *** 42,47 **** --- 48,59 ---- The "verbose?" attribute, when set, encourages this component to provide informative messages to cout during loading.

+ +

When the configure! 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.

+ 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 hitcount_map_t; typedef map,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 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 hitcount_map_t; typedef map,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 stats; ! unsigned current_stats; ! ! component *sim_sched; ! string sim_sched_event; string target_attribute; component* target_component; endian output_file_format; callback_pin accumulate_pin; *************** namespace profiling_components *** 115,123 **** callback_pin reset_pin; callback_pin store_pin; string bucket_size_get() { ! return make_attribute (this->bucket_size); } component::status bucket_size_set(const string& str) --- 148,206 ---- callback_pin reset_pin; callback_pin 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::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 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 bus_status_lut; bijection 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 components = tokenize (config.substr (5), ","); + // If the name of our victim is in the list, then set up to + // 'wrap' that component + for (vector::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 + #include #include #include "sidtypes.h" *************** make_attribute (const sid::any_int 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_intoutput_saved_messages (); } --- 1073,1078 ---- *************** make_attribute (const sid::any_inttotal_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(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(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 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::const_iterator i = a_impl->my_children.begin(); + i != a_impl->my_children.end(); ++i) + { + if (*i == dynamic_configurator) + continue; + AtomicCfg *a = dynamic_cast(*i); + if (a) + { + if (a->possibly_wrapped ()) + { + Relation (dynamic_configurator, "client", a).write_to (w); + } + continue; + } + AggregateCfg *ag = dynamic_cast(*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::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& 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& 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& opt_parts) + { + unsigned size = opt_parts.size (); + if (size < 2 || size > 3) + profile_config_error (opt); // doesn't return + + vector 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 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. + vectoropts = sidutil::tokenize (parts[1], " "); + int size = opts.size (); + for (int i = 0; i < size; ++i) + { + const string opt = opts[i]; + vector 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 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 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& opt_parts, unsigned max_parts); + string profile_opt_int_value (const string& opt, const vector& opt_parts); + string profile_opt_gprof_value (const string& opt, const vector& 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 + #include + // 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 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 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 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::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"))); --------------010804080709050905080504 Content-Type: text/xml; name="sid-control-dynamic-configurator.xml" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sid-control-dynamic-configurator.xml" Content-length: 6936 This component manages configuration profiles for a board.

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.

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 on the config-result pin. If an error occurs, a non-zero value will be driven on the config-error 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. If an error occurs, a non-zero value will be driven on the config-error pin.

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.

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

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

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

state is minimal.
--------------010804080709050905080504 Content-Type: text/plain; name="sid-control-dynamic-configurator.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sid-control-dynamic-configurator.txt" Content-length: 9113 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 || +-------------------------------------------------------------------+ --------------010804080709050905080504--