? 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")));