[patch][commit] Prioritization of Scheduler Events

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[patch][commit] Prioritization of Scheduler Events

Dave Brolley-2
Hi,

While looking into some bugs with the recent dynamic configuration work,
it became apparent that it would be necessary to have some control over
when the dynamic configurator component's step! pin was drive in
relation to the scheduling of other components. In particular, it is
desirable that the dynamic configurator be stepped (if necessary) first,
before other components scheduled at the same time are stepped. In this
way, all components are stepped under the same configuration.

After some experimentation with sequence components, it occurred to me
that this could be easily accomplished if the events scheduled at a
given time could be prioritized, so that they are dispatched in a
predictable order.

I've committed an implementation which adds a new attribute, N-priority,
to each output of the generic_scheduler component which is analogous to
the existing N-event and N-control pins and the N-time and N-regular
attributes. N-priority is assigned an integral value with the default
being zero. The higher the value, the higher the priority of that
output. When multiple events are scheduled at the same time, they are
dispatched in priority order.

There is no change for existing ports since all outputs will be assigned
a priority of zero.

Also included in this patch is a change to assign the gprof component a
priority of 1. In this way it will always take a sample before the cpu
is driven.

The dynamic configurator component is assigned a priority of 2, so that
the entire system is configured (if necessary) before any other
components are stepped.

Note that there is no change to the number of events being dispatched.
Simply a prioritization.

Let me know if there are any problems or concerns.

Dave

Dave


sid/component/cfgroot/ChangeLog:
2005-08-23  Dave Brolley  <[hidden email]>

        * compConfig.cxx (reset): Drive step_control_pin.
        (get_current_config): Removed.
        * sid-control-dynamic-configurator.xml: Correct description of interface.
        * sid-control-dynamic-configurator.txt: Regenerated.

sid/component/profiling/ChangeLog:
2005-08-23  Dave Brolley  <[hidden email]>

        * gprof.cxx (configure): Don't reset the N-regular attribute of the
        scheduler. Call accumulate when configuring for cycles=N.

sid/component/sched/ChangeLog:
2005-08-23  Dave Brolley  <[hidden email]>

        * compSched.cxx (scheduling_event): Constructors now take
        a 'priority' argument.
        (operator <): Consider priority of events.
        (yield): Likewise.
        (next_event): Likewise.
        (schedule_irregular): Now takes a 'priority' argument. Used when
        creating scheduling events.
        (schedule_regular): Likewise.
        (refill_regular_events_table): Consider priority of events.
        (operator <<): Stream priority.
        (operator >>): Destream priority.
        (class scheduler_client): Add 'priority' member.
        (set_time): Pass priority of the client to the scheduler.
        (client_num_update): Handle N-priority attribute.
        * sid-sched.xml: Describe the N-priority attribute.
        * sid-sched.txt: Regenerated.

sid/include/ChangeLog:
2005-08-23  Dave Brolley  <[hidden email]>

        * sidcpuutil.h (step_pin_handler): Don't call configure_gprof here.
        (unconfigure_gprof): Check gprof_configured_p.
        (configure_gprof): Check gprof_configured_p.
        (configure_gprof_p): Removed.
        (gprof_spec): Removed.
        (configure): Call configure_gprof here.

sid/main/dynamic/ChangeLog:
2005-08-23  Dave Brolley  <[hidden email]>

        * mainDynamic.cxx (try_add_gprof): Initialize interval.
        * commonCfg.cxx (set_priority): New method of SchedCfg.
        (GprofCfg): Always call set_time, set_regular and set_priority.
        (BoardCfg::write_load): Don't connect init-seq to the dynamic
        configurator's step! pin. Call set_priority.
        * commonCfg.h (set_priority): New method of SchedCfg.
        (config_priority,gprof_priority,default_priority): New constants in
        SchedCfg.


Index: sid/component/cfgroot/compConfig.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/cfgroot/compConfig.cxx,v
retrieving revision 1.10
diff -c -p -r1.10 compConfig.cxx
*** sid/component/cfgroot/compConfig.cxx 19 Aug 2005 19:39:07 -0000 1.10
--- sid/component/cfgroot/compConfig.cxx 23 Aug 2005 20:58:30 -0000
*************** dynamic_configurator_component::reset ()
*** 1389,1394 ****
--- 1389,1396 ----
   configure (spec);
  }
      }
+
+   step_control_pin.drive (1); // reconfigure during next cycle
  }
 
  // Set the starting configuration
Index: sid/component/profiling/gprof.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/profiling/gprof.cxx,v
retrieving revision 1.12
diff -c -p -r1.12 gprof.cxx
*** sid/component/profiling/gprof.cxx 19 Aug 2005 19:46:00 -0000 1.12
--- sid/component/profiling/gprof.cxx 23 Aug 2005 20:58:30 -0000
*************** namespace profiling_components
*** 514,521 ****
     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;
       }
   }
--- 514,523 ----
     if (s == component::ok)
       {
  sim_sched->connect_pin (sim_sched_event + "-event", & accumulate_pin);
  sim_sched->set_attribute_value (sim_sched_event + "-time", make_attribute (cycles));
+ // Take a sample now to make up for the one which just got cancelled when
+ // N-time was set.
+ accumulate (1);
  return;
       }
   }
*************** namespace profiling_components
*** 523,532 ****
     // 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;
   }
        }
--- 525,531 ----
     // 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);
     return;
   }
        }
Index: sid/component/sched/compSched.cxx
===================================================================
RCS file: /cvs/src/src/sid/component/sched/compSched.cxx,v
retrieving revision 1.12
diff -c -p -r1.12 compSched.cxx
*** sid/component/sched/compSched.cxx 12 Feb 2005 16:25:47 -0000 1.12
--- sid/component/sched/compSched.cxx 23 Aug 2005 20:58:31 -0000
***************
*** 1,9 ****
  // compSched.cxx - the scheduler component.  -*- C++ -*-
 
! // Copyright (C) 1999-2003 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
-
  #include "config.h"
 
  #include <sidcomp.h>
--- 1,8 ----
  // compSched.cxx - the scheduler component.  -*- C++ -*-
 
! // Copyright (C) 1999-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.
  #include "config.h"
 
  #include <sidcomp.h>
*************** namespace scheduler_component
*** 129,140 ****
      tick_t      when;
      tick_t      interval;
      output_pin* what;
 
!     scheduling_event(): when(0), interval(0), what(0) {}
!     scheduling_event(tick_t when, output_pin* what):
!       when(when), interval(0), what(what) {}
!     scheduling_event(tick_t when, tick_t interval, output_pin* what):
!       when(when), interval(interval), what(what) {}
    };
 
    // Define a comparison function for heaps of scheduling events.  It
--- 128,140 ----
      tick_t      when;
      tick_t      interval;
      output_pin* what;
+     host_int_4  priority;
 
!     scheduling_event(): when(0), interval(0), what(0), priority (0) {}
!     scheduling_event(tick_t when, output_pin* what, host_int_4 priority):
!       when(when), interval(0), what(what), priority(priority) {}
!     scheduling_event(tick_t when, tick_t interval, output_pin* what, host_int_4 priority):
!       when(when), interval(interval), what(what), priority(priority) {}
    };
 
    // Define a comparison function for heaps of scheduling events.  It
*************** namespace scheduler_component
*** 142,148 ****
    inline bool
    operator < (const scheduling_event& a, const scheduling_event& b)
  {
!   return a.when > b.when;
  }
 
 
--- 142,148 ----
    inline bool
    operator < (const scheduling_event& a, const scheduling_event& b)
  {
!   return (a.when > b.when) || ((a.when == b.when) && (a.priority < b.priority));
  }
 
 
*************** operator >> (istream& i, exact_host_time
*** 603,609 ****
   }
 
  tick_t yield_until;
! if (   (rnext && irnext && (rnext->when < irnext->when))
     || (rnext && !irnext))
   yield_until = rnext->when;
  else if (irnext)
--- 603,611 ----
   }
 
  tick_t yield_until;
! if ((rnext && irnext
!     && ((rnext->when < irnext->when)
! || (rnext->when == irnext->when && rnext->priority > irnext->priority)))
     || (rnext && !irnext))
   yield_until = rnext->when;
  else if (irnext)
*************** operator >> (istream& i, exact_host_time
*** 674,680 ****
     rnext = & * this->regular_table_iter;
   }
 
! if (   (rnext && irnext && (rnext->when < irnext->when))
     || (rnext && !irnext))
   {
     return make_pair(rnext,true);
--- 676,684 ----
     rnext = & * this->regular_table_iter;
   }
 
! if ((rnext && irnext
!     && ((rnext->when < irnext->when)
! || (rnext->when == irnext->when && rnext->priority > irnext->priority)))
     || (rnext && !irnext))
   {
     return make_pair(rnext,true);
*************** operator >> (istream& i, exact_host_time
*** 789,795 ****
 
      // Schedule an irregular event.
      void
!     schedule_irregular(tick_t delta, output_pin* what)
        {
  // cerr << "schedule_irregular when=" << when << endl;
 
--- 793,799 ----
 
      // Schedule an irregular event.
      void
!     schedule_irregular(tick_t delta, output_pin* what, host_int_4 priority)
        {
  // cerr << "schedule_irregular when=" << when << endl;
 
*************** operator >> (istream& i, exact_host_time
*** 798,826 ****
  this->get_now(now);
  tick_t when = now + delta;
 
! this->irregular_events.push_back(scheduling_event(when, what));
  push_heap(this->irregular_events.begin(), this->irregular_events.end());
        }
 
 
      // Schedule a regular event, starting "when"
      void
!     schedule_regular(tick_t when, tick_t interval, output_pin* what)
        {
  // cerr << "schedule_regular when=" << when << " interval=" << interval << endl;
! this->regular_events.push_back (scheduling_event(when, interval, what));
  this->refill_regular_events_table();
        }
      // Schedule a regular event starting "now"
      void
!     schedule_regular(tick_t interval, output_pin* what)
        {
  // cerr << "scheduler_regular interval=" << interval << endl;
 
  // infer "now" as starting time
  tick_t now;
  this->get_now(now);
! this->schedule_regular (now, interval, what);
        }
 
 
--- 802,830 ----
  this->get_now(now);
  tick_t when = now + delta;
 
! this->irregular_events.push_back(scheduling_event(when, what, priority));
  push_heap(this->irregular_events.begin(), this->irregular_events.end());
        }
 
 
      // Schedule a regular event, starting "when"
      void
!     schedule_regular(tick_t when, tick_t interval, output_pin* what, host_int_4 priority)
        {
  // cerr << "schedule_regular when=" << when << " interval=" << interval << endl;
! this->regular_events.push_back (scheduling_event(when, interval, what, priority));
  this->refill_regular_events_table();
        }
      // Schedule a regular event starting "now"
      void
!     schedule_regular(tick_t interval, output_pin* what, host_int_4 priority)
        {
  // cerr << "scheduler_regular interval=" << interval << endl;
 
  // infer "now" as starting time
  tick_t now;
  this->get_now(now);
! this->schedule_regular (now, interval, what, priority);
        }
 
 
*************** generic_scheduler<Timekeeper>::refill_re
*** 935,946 ****
  {
   if (next_tick_time[reg] > next_tick_time[k])
     reg = k;
  }
 
        slot->when = next_tick_time[reg];
        slot->interval = 0; // initialize unused field
        slot->what = this->regular_events[reg].what;
!       // cerr << " slot: when=" << slot->when << " what=" << slot->what << endl;
 
        next_tick_time[reg] += this->regular_events[reg].interval;
      }
--- 939,954 ----
  {
   if (next_tick_time[reg] > next_tick_time[k])
     reg = k;
+  else if (next_tick_time[reg] == next_tick_time[k]
+   && this->regular_events[reg].priority < this->regular_events[k].priority)
+    reg = k;
  }
 
        slot->when = next_tick_time[reg];
        slot->interval = 0; // initialize unused field
        slot->what = this->regular_events[reg].what;
!       slot->priority = this->regular_events[reg].priority;
!       // cerr << " slot: when=" << slot->when << " what=" << slot->what << " priority=" << slot->priority << endl;
 
        next_tick_time[reg] += this->regular_events[reg].interval;
      }
*************** operator << (ostream& o, const generic_s
*** 975,981 ****
        string name;
        bool ok = it.pin_state_map.find(e->what, name);
        assert (ok);
!       o << "  " << e->when << " " << e->interval << " " << name << endl;
      }
 
    o << it.regular_events.size() << endl;
--- 983,989 ----
        string name;
        bool ok = it.pin_state_map.find(e->what, name);
        assert (ok);
!       o << "  " << e->when << " " << e->priority << " " << e->interval << " " << name << endl;
      }
 
    o << it.regular_events.size() << endl;
*************** operator << (ostream& o, const generic_s
*** 988,994 ****
        string name;
        bool ok = it.pin_state_map.find(e->what, name);
        assert (ok);
!       o << "  " << e->when << " " << e->interval << " " << name << endl;
      }
 
    return o;
--- 996,1002 ----
        string name;
        bool ok = it.pin_state_map.find(e->what, name);
        assert (ok);
!       o << "  " << e->when << " " << e->priority << " " << e->interval << " " << name << endl;
      }
 
    return o;
*************** operator >> (istream& i, generic_schedul
*** 1024,1031 ****
        for(unsigned t=0; t<num_irregular_events; t++)
  {
   clock_t when, interval;
   string name;
!  i >> when >> interval >> name;
   // make base time absolute
   when += delta;
   // find new pin
--- 1032,1040 ----
        for(unsigned t=0; t<num_irregular_events; t++)
  {
   clock_t when, interval;
+  host_int_4 priority;
   string name;
!  i >> when >> priority >> interval >> name;
   // make base time absolute
   when += delta;
   // find new pin
*************** operator >> (istream& i, generic_schedul
*** 1033,1039 ****
   bool ok = it.pin_state_map.find(name, pin);
   assert (ok);
   // add it
!  it.irregular_events.push_back(scheduling_event(when, interval, pin));
  }
 
        // Clear regular events table
--- 1042,1048 ----
   bool ok = it.pin_state_map.find(name, pin);
   assert (ok);
   // add it
!  it.irregular_events.push_back(scheduling_event(when, interval, pin, priority));
  }
 
        // Clear regular events table
*************** operator >> (istream& i, generic_schedul
*** 1045,1052 ****
        for(unsigned t=0; t<num_regular_events; t++)
  {
   clock_t when, interval;
   string name;
!  i >> when >> interval >> name;
   // make base time absolute
   when += delta;
   // find new pin
--- 1054,1062 ----
        for(unsigned t=0; t<num_regular_events; t++)
  {
   clock_t when, interval;
+  host_int_4 priority;
   string name;
!  i >> when >> priority >> interval >> name;
   // make base time absolute
   when += delta;
   // find new pin
*************** operator >> (istream& i, generic_schedul
*** 1054,1060 ****
   bool ok = it.pin_state_map.find(name, pin);
   assert (ok);
   // add it
!  it.regular_events.push_back(scheduling_event(when, interval, pin));
  }
 
        // get scheduler ready for operation with new data
--- 1064,1070 ----
   bool ok = it.pin_state_map.find(name, pin);
   assert (ok);
   // add it
!  it.regular_events.push_back(scheduling_event(when, interval, pin, priority));
  }
 
        // get scheduler ready for operation with new data
*************** public:
*** 1083,1088 ****
--- 1093,1099 ----
    host_int_2 scale_mul, scale_div;  // time-to-ticks conversion factor
    tick_t time;       // time of next event (irregular) or interval (regular)
    bool regular_p;    // regular (vs irregular) event source
+   host_int_4 priority; // priority of client
    string name;       // "pretty" name, for use in scheduler GUI
 
    // These are public members for direct pin map twiddlers
*************** private:
*** 1103,1120 ****
        // silently prevent division-by-zero
        if (this->scale_div == 0)
  this->scale_div = 1;
-       tick_t sched_time = t * this->scale_mul / this->scale_div;
 
        if (LIKELY(t != 0))
  {
   // round up away from zero
   if (sched_time == 0)
     sched_time = 1;
 
   if (this->regular_p)
!    this->comp->sched.schedule_regular (sched_time, & this->event_pin);
   else
!    this->comp->sched.schedule_irregular (sched_time, & this->event_pin);
  }
      }
 
--- 1114,1131 ----
        // silently prevent division-by-zero
        if (this->scale_div == 0)
  this->scale_div = 1;
 
        if (LIKELY(t != 0))
  {
   // round up away from zero
+  tick_t sched_time = t * this->scale_mul / this->scale_div;
   if (sched_time == 0)
     sched_time = 1;
 
   if (this->regular_p)
!    this->comp->sched.schedule_regular (sched_time, & this->event_pin, this->priority);
   else
!    this->comp->sched.schedule_irregular (sched_time, & this->event_pin, this->priority);
  }
      }
 
*************** public:
*** 1140,1145 ****
--- 1151,1157 ----
      scale_div (1),
      time (0),
      regular_p (true),
+     priority (0),
      event_pin (),
      control_pin(this, & scheduler_client::set_control),
      comp(comp)
*************** operator << (ostream& o, const scheduler
*** 1236,1242 ****
  << it.clients[j]->time << " "
  << it.clients[j]->scale_mul << " "
  << it.clients[j]->scale_div << " "
! << it.clients[j]->regular_p << endl;
        its.add_pin_mapping((make_numeric_attribute(j) + "-event"),
   & it.clients[j]->event_pin);
      }
--- 1248,1256 ----
  << it.clients[j]->time << " "
  << it.clients[j]->scale_mul << " "
  << it.clients[j]->scale_div << " "
! << it.clients[j]->regular_p << " "
! << it.clients[j]->priority << " "
! << endl;
        its.add_pin_mapping((make_numeric_attribute(j) + "-event"),
   & it.clients[j]->event_pin);
      }
*************** operator >> (istream& i, scheduler_compo
*** 1282,1288 ****
   i >> it.clients[j]->time
     >> it.clients[j]->scale_mul
     >> it.clients[j]->scale_div
!    >> it.clients[j]->regular_p;
 
   it.sched.add_pin_mapping((make_numeric_attribute(j) + "-event"),
    & it.clients[j]->event_pin);
--- 1296,1303 ----
   i >> it.clients[j]->time
     >> it.clients[j]->scale_mul
     >> it.clients[j]->scale_div
!    >> it.clients[j]->regular_p
!    >> it.clients[j]->priority;
 
   it.sched.add_pin_mapping((make_numeric_attribute(j) + "-event"),
    & it.clients[j]->event_pin);
*************** scheduler_component<Scheduler>::client_n
*** 1522,1527 ****
--- 1537,1543 ----
        string num = sidutil::make_numeric_attribute(n);
        this->remove_attribute (num + "-regular?");
        this->remove_attribute (num + "-time");
+       this->remove_attribute (num + "-priority");
        this->remove_attribute (num + "-scale");
        this->remove_attribute (num + "-name");
        this->remove_attribute (num + "-event");
*************** scheduler_component<Scheduler>::client_n
*** 1549,1554 ****
--- 1565,1574 ----
   & c->time, c,
   & client_t::reset_events,
   "setting");
+       this->add_attribute_notify (num + "-priority",
+  & c->priority, c,
+  & client_t::reset_events,
+  "setting");
        this->add_attribute_virtual (num + "-scale",
    c, & client_t::get_scale_attr, & client_t::set_scale_attr,
    "setting");
Index: sid/component/sched/sid-sched.txt
===================================================================
RCS file: /cvs/src/src/sid/component/sched/sid-sched.txt,v
retrieving revision 1.7
diff -c -p -r1.7 sid-sched.txt
*** sid/component/sched/sid-sched.txt 21 Oct 2003 21:36:29 -0000 1.7
--- sid/component/sched/sid-sched.txt 23 Aug 2005 20:58:31 -0000
*************** Functionality:
*** 95,118 ****
     |               |                                 |
     |               | Each subscription is defined by |
     |               | an index, a                     |
!    |               | regular-vs-irregular flag, and  |
!    |               | a time quantity. The index is a |
!    |               | number between 0 and            |
!    |               | num-clients -1, and is          |
     |               | represented as N in the         |
     |               | pin/attribute list templates in |
     |               | this document. The              |
     |               | regular-vs-irregular flag is    |
     |               | accessible as the N-regular?    |
!    |               | attribute. The time quantity is |
!    |               | accessible as the N-time        |
!    |               | attribute. If the value is      |
!    |               | zero, it is interpreted as a    |
!    |               | request to cancel all pending   |
!    |               | events for this subscription.   |
!    |               | Otherwise, the value is taken   |
!    |               | to be a delta until the time of |
!    |               | the requested event.            |
     |               |                                 |
     |               | You can also set these controls |
     |               | by driving encoded values into  |
--- 95,122 ----
     |               |                                 |
     |               | Each subscription is defined by |
     |               | an index, a                     |
!    |               | regular-vs-irregular flag, a    |
!    |               | priority and a time quantity.   |
!    |               | The index is a number between 0 |
!    |               | and num-clients -1, and is      |
     |               | represented as N in the         |
     |               | pin/attribute list templates in |
     |               | this document. The              |
     |               | regular-vs-irregular flag is    |
     |               | accessible as the N-regular?    |
!    |               | attribute. The priority is      |
!    |               | accessible as the N-priority    |
!    |               | attribute. Higher values        |
!    |               | indicate higher priority. The   |
!    |               | time quantity is accessible as  |
!    |               | the N-time attribute. If the    |
!    |               | value is zero, it is            |
!    |               | interpreted as a request to     |
!    |               | cancel all pending events for   |
!    |               | this subscription. Otherwise,   |
!    |               | the value is taken to be a      |
!    |               | delta until the time of the     |
!    |               | requested event.                |
     |               |                                 |
     |               | You can also set these controls |
     |               | by driving encoded values into  |
*************** Functionality:
*** 181,186 ****
--- 185,198 ----
     |               | This loop may be aborted early  |
     |               | if the yield input pin is       |
     |               | driven.                         |
+    |               |                                 |
+    |               | If more than one event is       |
+    |               | scheduled at the same time.     |
+    |               | Events will be dispatched in    |
+    |               | priority order. Events with     |
+    |               | higher priority will be         |
+    |               | dispatched before events with   |
+    |               | lower priority.                 |
     +-------------------------------------------------+
 
     +-------------------------------------------------+
*************** Component Reference:
*** 291,296 ****
--- 303,310 ----
  |---------------------------+----------+----------+-----------+---------------||
  |N-time                     |setting   |numeric   |'0'        |subscription   ||
  |---------------------------+----------+----------+-----------+---------------||
+ |N-priority                 |setting   |numeric   |'0'        |subscription   ||
+ |---------------------------+----------+----------+-----------+---------------||
  |N-scale                    |setting   |numeric   |'1'        |subscription   ||
  |                           |          |fraction  |           |               ||
  |---------------------------+----------+----------+-----------+---------------||
Index: sid/component/sched/sid-sched.xml
===================================================================
RCS file: /cvs/src/src/sid/component/sched/sid-sched.xml,v
retrieving revision 1.6
diff -c -p -r1.6 sid-sched.xml
*** sid/component/sched/sid-sched.xml 21 Oct 2003 21:36:29 -0000 1.6
--- sid/component/sched/sid-sched.xml 23 Aug 2005 20:58:31 -0000
***************
*** 22,27 ****
--- 22,28 ----
      <defattribute name="N-name" category="setting" behaviors="configuration" />
      <defattribute name="N-regular?" category="setting" legalvalues="boolean" defaultvalue="'0'" behaviors="subscription" />
      <defattribute name="N-time" category="setting" legalvalues="numeric" defaultvalue="'0'" behaviors="subscription" />
+     <defattribute name="N-priority" category="setting" legalvalues="numeric" defaultvalue="'0'" behaviors="subscription" />
      <defattribute name="N-scale" category="setting" legalvalues="numeric fraction" defaultvalue="'1'" behaviors="subscription" />
      <defattribute name="N-event" category="pin" behaviors="advancing" />
      <defattribute name="N-control" category="pin" behaviors="subscription" />
***************
*** 110,120 ****
        </p>
 
        <p> Each subscription is defined by an index, a
!       regular-vs-irregular flag, and a time quantity.  The index is a
        number between 0 and <attribute>num-clients</attribute> -1, and is represented as <tt>N</tt>
        in the pin/attribute list templates in this document.  The
        regular-vs-irregular flag is accessible as the <attribute>N-regular?</attribute>
!       attribute.  The time quantity is accessible as the <attribute>N-time</attribute>
        attribute.  If the value is zero, it is interpreted as a request
        to cancel all pending events for this subscription.  Otherwise,
        the value is taken to be a delta until the <attribute>time</attribute> of the
--- 111,123 ----
        </p>
 
        <p> Each subscription is defined by an index, a
!       regular-vs-irregular flag, a priority and a time quantity.  The index is a
        number between 0 and <attribute>num-clients</attribute> -1, and is represented as <tt>N</tt>
        in the pin/attribute list templates in this document.  The
        regular-vs-irregular flag is accessible as the <attribute>N-regular?</attribute>
!       attribute.  The priority is accessible as the <attribute>N-priority</attribute>
!       attribute. Higher values indicate higher priority.
!       The time quantity is accessible as the <attribute>N-time</attribute>
        attribute.  If the value is zero, it is interpreted as a request
        to cancel all pending events for this subscription.  Otherwise,
        the value is taken to be a delta until the <attribute>time</attribute> of the
***************
*** 166,171 ****
--- 169,179 ----
        the <pin>yield</pin> input pin is driven.
        </p>
 
+       <p> If more than one event is scheduled at the same time. Events will be dispatched in
+       priority order. Events with higher priority will be dispatched before events with lower
+       priority.
+       </p>
+
      </behavior>
 
      <convention name="functional" supported="true" />
Index: sid/include/sidcpuutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidcpuutil.h,v
retrieving revision 1.31
diff -c -p -r1.31 sidcpuutil.h
*** sid/include/sidcpuutil.h 19 Aug 2005 19:47:44 -0000 1.31
--- sid/include/sidcpuutil.h 23 Aug 2005 20:58:31 -0000
*************** namespace sidutil
*** 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;
 
--- 270,275 ----
*************** namespace sidutil
*** 450,503 ****
  return static_cast<cpu_trap_disposition>(trap_disposition_pin.sense ());
        }
 
!     void unconfigure_gprof (sid::host_int_4 num_cycles)
        {
  assert (gprof);
- // First sample the address of the branch which caused
- // the reconfig for the given number of cycles.
  sid::pin *p;
! if (num_cycles && last_caller)
   {
!    p = gprof->find_pin ("sample");
!    if (p)
       {
! std::string save_pc = this->attribute_value ("pc");
! if (! save_pc.empty ())
   {
!    sid::component::status s = this->set_attribute_value ("pc", make_numeric_attribute (last_caller));
!    if (s == sid::component::ok)
!      do
! {
!  p->driven (1);
!  --num_cycles;
! } while (num_cycles);
!    this->set_attribute_value ("pc", save_pc);
   }
       }
   }
!
! // Then get gprof to reconfigure itself.
! gprof->set_attribute_value ("configure!", gprof_spec);
 
  // Then disconnect the call graph notification pins.
- assert (! configure_gprof_p);
- assert (gprof_configured_p);
  p = gprof->find_pin ("cg-caller");
  if (p) cg_caller_pin.disconnect (p);
  p = gprof->find_pin ("cg-callee");
! if (p) cg_callee_pin.disconnect (p);
  gprof_configured_p = false;
        }
 
      void configure_gprof ()
        {
! // First get gprof to reconfigure itself.
! assert (gprof);
! gprof->set_attribute_value ("configure!", gprof_spec);
 
! // Then connect the call graph notification pins.
! assert (configure_gprof_p);
! assert (! gprof_configured_p);
  sid::pin *p = gprof->find_pin ("cg-caller");
  if (p)
   {
--- 447,502 ----
  return static_cast<cpu_trap_disposition>(trap_disposition_pin.sense ());
        }
 
!     void unconfigure_gprof (const string &gprof_spec, sid::host_int_4 num_cycles)
        {
+ if (! gprof_configured_p)
+  return;
+
  assert (gprof);
  sid::pin *p;
!
! #if 0 // can't happen?
! // If 'cycles' was specified on the --gprof option, then
! // first, sample the address of the branch which caused
! // the reconfig for the given number of cycles.
! if (num_cycles && last_caller && gprof_spec.size () > 6)
   {
!    vector<string> parts = tokenize (gprof_spec.substr (6), ",");
!    if (parts.size () > 1)
       {
! 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)
!  for (int i = 0; i < num_cycles; ++i)
!    p->driven (1);
! this->set_attribute_value ("pc", save_pc);
!      }
   }
       }
   }
! #endif
 
  // Then disconnect the call graph notification pins.
  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 ()
        {
! if (gprof_configured_p)
!  return;
 
! // Connect the call graph notification pins.
! assert (gprof);
  sid::pin *p = gprof->find_pin ("cg-caller");
  if (p)
   {
*************** namespace sidutil
*** 511,516 ****
--- 510,516 ----
   if (last_caller && last_callee)
     p->driven (last_callee);
  }
+
  gprof_configured_p = true;
        }
 
*************** namespace sidutil
*** 520,530 ****
      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)
        {
--- 520,528 ----
      component *gprof;
      component *core_probe;
      component *main;
      sid::host_int_4 last_caller;
      sid::host_int_4 last_callee;
!     bool gprof_configured_p;
 
      virtual void configure (const string &config)
        {
*************** namespace sidutil
*** 538,551 ****
   {
     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)
--- 536,548 ----
   {
     if (! gprof)
       return; // nothing to configure
!    // First get gprof to configure itself
!    gprof->set_attribute_value ("configure!", config);
!    // Now do our own configuration
!    if (config.size () > 6)
!      configure_gprof ();
!    else
!      unconfigure_gprof (config, num_cycles);
     return;
   }
  if (config.size () <= 11)
*************** public:
*** 754,763 ****
        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)
        {
--- 751,759 ----
        trace_filename ("-"), // standard output
        trace_pin (this, & basic_cpu::trace_pin_handler),
        gprof (0),
        last_caller (0),
        last_callee (0),
+       gprof_configured_p (false),
        core_probe (0),
        main (0)
        {
Index: sid/main/dynamic/commonCfg.cxx
===================================================================
RCS file: /cvs/src/src/sid/main/dynamic/commonCfg.cxx,v
retrieving revision 1.10
diff -c -p -r1.10 commonCfg.cxx
*** sid/main/dynamic/commonCfg.cxx 19 Aug 2005 19:48:45 -0000 1.10
--- sid/main/dynamic/commonCfg.cxx 23 Aug 2005 20:58:31 -0000
*************** void SchedCfg::set_time (int n, int tv)
*** 439,444 ****
--- 439,451 ----
    set (this, s + "-time", ts);
  }
 
+ void SchedCfg::set_priority (int n, int pv)
+ {
+   string s = sidutil::make_attribute (n);
+   string ps = sidutil::make_attribute (pv);
+   set (this, s + "-priority", ps);
+ }
+
  void SchedCfg::write_config (Writer &w)
  {
    Setting (this, "num-clients", sidutil::make_attribute (n)).write_to (w);
*************** GprofCfg::GprofCfg (const string name,
*** 997,1014 ****
    // 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);
!     }
!   else // default to instruction_count
      {
        string ev = sidutil::make_attribute (cpu->get_subscription_number());
        ev += "-event";
        conn_pin (sess->sim_sched, ev, this, "sample");
      }
    sess->shutdown_seq->add_output (7, this, "store");
    relate (this, "target-component", cpu);
    conn_pin (cpu, "cg-caller", this, "cg-caller");
--- 1004,1021 ----
    // used now, it could be used due to dynamic configuration.
    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);
+   sess->sim_sched->set_priority (slot, SchedCfg::gprof_priority);
 
!   if (type != simulated_cycles)
      {
+       // default to instruction_count
        string ev = sidutil::make_attribute (cpu->get_subscription_number());
        ev += "-event";
        conn_pin (sess->sim_sched, ev, this, "sample");
      }
+
    sess->shutdown_seq->add_output (7, this, "store");
    relate (this, "target-component", cpu);
    conn_pin (cpu, "cg-caller", this, "cg-caller");
*************** GprofCfg::GprofCfg (const string name,
*** 1034,1039 ****
--- 1041,1049 ----
    // used now, it could be used due to dynamic configuration.
    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, 1);
+   sess->sim_sched->set_priority (slot, SchedCfg::gprof_priority);
 
    sess->shutdown_seq->add_output (7, this, "store");
    relate (this, "target-component", cpu);
*************** void BoardCfg::write_load (Writer &w)
*** 1228,1236 ****
        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
--- 1238,1246 ----
        dynamic_configurator = new AtomicCfg ("dynamic-config", "libconfig.la",
     "config_component_library",
     "sid-control-dynamic-configurator");
        sess->reset_net->add_output (2, dynamic_configurator, "reset");
!       int slot = sess->sim_sched->add_subscription (dynamic_configurator, "step!", "step-control");
!       sess->sim_sched->set_priority (slot, SchedCfg::config_priority);
        add_child (dynamic_configurator);
 
        // If we may need a gprof for dynamic configuration but don't have
Index: sid/main/dynamic/commonCfg.h
===================================================================
RCS file: /cvs/src/src/sid/main/dynamic/commonCfg.h,v
retrieving revision 1.8
diff -c -p -r1.8 commonCfg.h
*** sid/main/dynamic/commonCfg.h 19 Aug 2005 19:48:45 -0000 1.8
--- sid/main/dynamic/commonCfg.h 23 Aug 2005 20:58:38 -0000
*************** public:
*** 109,115 ****
--- 109,121 ----
  string time_low);
    void set_regular (int n, bool v);
    void set_time (int n, int tv);
+   void set_priority (int n, int pv);
    virtual void write_config (Writer &w);
+
+   static const int config_priority  = 2;
+   static const int gprof_priority   = 1;
+   static const int default_priority = 0;
+
  protected:
    int n;
  };
Index: sid/main/dynamic/mainDynamic.cxx
===================================================================
RCS file: /cvs/src/src/sid/main/dynamic/mainDynamic.cxx,v
retrieving revision 1.7
diff -c -p -r1.7 mainDynamic.cxx
*** sid/main/dynamic/mainDynamic.cxx 19 Aug 2005 19:48:45 -0000 1.7
--- sid/main/dynamic/mainDynamic.cxx 23 Aug 2005 20:58:38 -0000
*************** void try_add_gprof(const string optstrin
*** 419,425 ****
  {
    gprof_type type;
    string interval_string;
!   int interval;
    vector<string> toks = sidutil::tokenize (optstring, ",");
 
    type = instruction_count; // default type value
--- 419,425 ----
  {
    gprof_type type;
    string interval_string;
!   int interval = 1;
    vector<string> toks = sidutil::tokenize (optstring, ",");
 
    type = instruction_count; // default type value