? 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_intset_attributes (buffer_output, ulog_level, ulog_mode);
+ return;
+ }
+ if (config.size () < 12)
+ return;
+ if (config.substr (0, 11) == "ulog-level=")
+ {
+ sid::host_int_4 level;
+ sid::component::status s = sidutil::parse_attribute (config.substr (11), level);
+ if (s == sid::component::ok)
+ ulog_level = level;
+ ulog_logger->set_attributes (buffer_output, ulog_level, ulog_mode);
+ return;
+ }
+ }
};
+
}
#endif // SIDATTRUTIL_H
Index: sid/include/sidcpuutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidcpuutil.h,v
retrieving revision 1.30
diff -c -p -r1.30 sidcpuutil.h
*** sid/include/sidcpuutil.h 10 May 2005 15:48:22 -0000 1.30
--- sid/include/sidcpuutil.h 4 Aug 2005 18:32:40 -0000
***************
*** 1,6 ****
// sidcpuutil.h - Elements common to CPU models. -*- C++ -*-
! // Copyright (C) 1999-2004 Red Hat.
// This file is part of SID and is licensed under the GPL.
// See the file COPYING.SID for conditions for redistribution.
--- 1,6 ----
// sidcpuutil.h - Elements common to CPU models. -*- C++ -*-
! // Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat.
// This file is part of SID and is licensed under the GPL.
// See the file COPYING.SID for conditions for redistribution.
*************** namespace sidutil
*** 105,111 ****
protected virtual fixed_accessor_map_component,
protected virtual fixed_attribute_map_component,
protected virtual fixed_relation_map_component,
! protected virtual fixed_bus_map_component
{
// custom memory allocators for poisioning freshly-allocated memory
public:
--- 105,112 ----
protected virtual fixed_accessor_map_component,
protected virtual fixed_attribute_map_component,
protected virtual fixed_relation_map_component,
! protected virtual fixed_bus_map_component,
! protected virtual configurable_component
{
// custom memory allocators for poisioning freshly-allocated memory
public:
*************** namespace sidutil
*** 206,214 ****
--- 207,218 ----
sid::host_int_8 total_insn_count;
mutable sid::host_int_8 total_latency;
sid::host_int_4 current_step_insn_count;
+ sid::host_int_4 num_cycles;
output_pin step_cycles_pin;
output_pin cg_caller_pin;
output_pin cg_callee_pin;
+ output_pin cg_jump_pin;
+ output_pin cg_return_pin;
// tracing
private:
*************** namespace sidutil
*** 257,262 ****
--- 261,267 ----
bool trace_semantics_p;
bool trace_counter_p;
bool final_insn_count_p;
+ bool print_final_insn_count_p;
bool enable_step_trap_p;
cpu_trace_stream trace_stream;
*************** namespace sidutil
*** 265,270 ****
--- 270,278 ----
recursion_record limit (& this->step_limit);
if (UNLIKELY(! limit.ok())) return;
+ if (UNLIKELY (! gprof_configured_p && configure_gprof_p))
+ configure_gprof ();
+
this->current_step_insn_count = 0;
this->yield_p = false;
*************** namespace sidutil
*** 283,292 ****
const sid::host_int_4 min_num_cycles = 1;
const sid::host_int_4 max_num_cycles = 0x7FFFFFFF;
sid::host_int_8 insn_cycles = num_insns + latency_to_cycles (latency);
! sid::host_int_4 num_cycles =
insn_cycles <= min_num_cycles ? min_num_cycles :
insn_cycles >= max_num_cycles ? max_num_cycles :
insn_cycles;
this->stepped (num_cycles);
}
void yield ()
--- 291,301 ----
const sid::host_int_4 min_num_cycles = 1;
const sid::host_int_4 max_num_cycles = 0x7FFFFFFF;
sid::host_int_8 insn_cycles = num_insns + latency_to_cycles (latency);
! num_cycles =
insn_cycles <= min_num_cycles ? min_num_cycles :
insn_cycles >= max_num_cycles ? max_num_cycles :
insn_cycles;
+
this->stepped (num_cycles);
}
void yield ()
*************** namespace sidutil
*** 300,307 ****
}
virtual void print_insn_summary (sid::host_int_4)
{
! std::cerr << "instruction count: " << this->total_insn_count << " "
! << "simulated cycles: " << this->total_latency + this->total_insn_count << std::endl;
}
virtual void stepped (sid::host_int_4 n)
{
--- 309,317 ----
}
virtual void print_insn_summary (sid::host_int_4)
{
! if (print_final_insn_count_p)
! std::cerr << "instruction count: " << this->total_insn_count << " "
! << "simulated cycles: " << this->total_latency + this->total_insn_count << std::endl;
}
virtual void stepped (sid::host_int_4 n)
{
*************** namespace sidutil
*** 309,314 ****
--- 319,326 ----
}
void cg_profile (sid::host_int_4 caller, sid::host_int_4 callee)
{
+ last_caller = caller;
+ last_callee = callee;
// The drive sequence is important: see sw-profile-gprof
this->cg_caller_pin.drive (caller);
this->cg_callee_pin.drive (callee);
*************** namespace sidutil
*** 324,329 ****
--- 336,347 ----
<< " ";
}
}
+ void cg_profile_jump (sid::host_int_4 caller, sid::host_int_4 callee)
+ {
+ last_caller = caller;
+ last_callee = callee;
+ this->cg_jump_pin.drive (callee);
+ }
public:
void set_total_latency (sid::host_int_8 latency) { this->total_latency = latency; }
*************** namespace sidutil
*** 381,386 ****
--- 399,410 ----
this->trace_result_p = (this->trace_semantics_p || this->trace_disass_p);
}
+ void
+ update_final_insn_count_p ()
+ {
+ if (this->final_insn_count_p)
+ this->print_final_insn_count_p = true;
+ }
// Reset the processor model to power-up state.
private:
*************** namespace sidutil
*** 426,432 ****
return static_cast(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")));