eventq.cc revision 2632:1bb2f91485ea
1/*
2 * Copyright (c) 2000-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <assert.h>
30
31#include <iostream>
32#include <string>
33#include <vector>
34
35#include "cpu/smt.hh"
36#include "base/misc.hh"
37
38#include "sim/eventq.hh"
39#include "base/trace.hh"
40#include "sim/root.hh"
41
42using namespace std;
43
44//
45// Main Event Queue
46//
47// Events on this queue are processed at the *beginning* of each
48// cycle, before the pipeline simulation is performed.
49//
50EventQueue mainEventQueue("MainEventQueue");
51
52void
53EventQueue::insert(Event *event)
54{
55    if (head == NULL || event->when() < head->when() ||
56        (event->when() == head->when() &&
57         event->priority() <= head->priority())) {
58        event->next = head;
59        head = event;
60    } else {
61        Event *prev = head;
62        Event *curr = head->next;
63
64        while (curr) {
65            if (event->when() <= curr->when() &&
66                (event->when() < curr->when() ||
67                 event->priority() <= curr->priority()))
68                break;
69
70            prev = curr;
71            curr = curr->next;
72        }
73
74        event->next = curr;
75        prev->next = event;
76    }
77}
78
79void
80EventQueue::remove(Event *event)
81{
82    if (head == NULL)
83        return;
84
85    if (head == event){
86        head = event->next;
87        return;
88    }
89
90    Event *prev = head;
91    Event *curr = head->next;
92    while (curr && curr != event) {
93        prev = curr;
94        curr = curr->next;
95    }
96
97    if (curr == event)
98        prev->next = curr->next;
99}
100
101void
102EventQueue::serviceOne()
103{
104    Event *event = head;
105    event->clearFlags(Event::Scheduled);
106    head = event->next;
107
108    // handle action
109    if (!event->squashed())
110        event->process();
111    else
112        event->clearFlags(Event::Squashed);
113
114    if (event->getFlags(Event::AutoDelete) && !event->scheduled())
115        delete event;
116}
117
118
119void
120Event::serialize(std::ostream &os)
121{
122    SERIALIZE_SCALAR(_when);
123    SERIALIZE_SCALAR(_priority);
124    SERIALIZE_ENUM(_flags);
125}
126
127
128void
129Event::unserialize(Checkpoint *cp, const string &section)
130{
131    if (scheduled())
132        deschedule();
133
134    UNSERIALIZE_SCALAR(_when);
135    UNSERIALIZE_SCALAR(_priority);
136
137    // need to see if original event was in a scheduled, unsquashed
138    // state, but don't want to restore those flags in the current
139    // object itself (since they aren't immediately true)
140    UNSERIALIZE_ENUM(_flags);
141    bool wasScheduled = (_flags & Scheduled) && !(_flags & Squashed);
142    _flags &= ~(Squashed | Scheduled);
143
144    if (wasScheduled) {
145        DPRINTF(Config, "rescheduling at %d\n", _when);
146        schedule(_when);
147    }
148}
149
150void
151EventQueue::serialize(ostream &os)
152{
153    std::list<Event *> eventPtrs;
154
155    int numEvents = 0;
156    Event *event = head;
157    while (event) {
158        if (event->getFlags(Event::AutoSerialize)) {
159            eventPtrs.push_back(event);
160            paramOut(os, csprintf("event%d", numEvents++), event->name());
161        }
162        event = event->next;
163    }
164
165    SERIALIZE_SCALAR(numEvents);
166
167    for (std::list<Event *>::iterator it=eventPtrs.begin();
168         it != eventPtrs.end(); ++it) {
169        (*it)->nameOut(os);
170        (*it)->serialize(os);
171    }
172}
173
174void
175EventQueue::unserialize(Checkpoint *cp, const std::string &section)
176{
177    int numEvents;
178    UNSERIALIZE_SCALAR(numEvents);
179
180    std::string eventName;
181    for (int i = 0; i < numEvents; i++) {
182        // get the pointer value associated with the event
183        paramIn(cp, section, csprintf("event%d", i), eventName);
184
185        // create the event based on its pointer value
186        Serializable::create(cp, eventName);
187    }
188}
189
190void
191EventQueue::dump()
192{
193    cprintf("============================================================\n");
194    cprintf("EventQueue Dump  (cycle %d)\n", curTick);
195    cprintf("------------------------------------------------------------\n");
196
197    if (empty())
198        cprintf("<No Events>\n");
199    else {
200        Event *event = head;
201        while (event) {
202            event->dump();
203            event = event->next;
204        }
205    }
206
207    cprintf("============================================================\n");
208}
209
210extern "C"
211void
212dumpMainQueue()
213{
214    mainEventQueue.dump();
215}
216
217
218const char *
219Event::description()
220{
221    return "generic";
222}
223
224#if TRACING_ON
225void
226Event::trace(const char *action)
227{
228    // This DPRINTF is unconditional because calls to this function
229    // are protected by an 'if (DTRACE(Event))' in the inlined Event
230    // methods.
231    //
232    // This is just a default implementation for derived classes where
233    // it's not worth doing anything special.  If you want to put a
234    // more informative message in the trace, override this method on
235    // the particular subclass where you have the information that
236    // needs to be printed.
237    DPRINTFN("%s event %s @ %d\n", description(), action, when());
238}
239#endif
240
241void
242Event::dump()
243{
244    cprintf("Event  (%s)\n", description());
245    cprintf("Flags: %#x\n", _flags);
246#if TRACING_ON
247    cprintf("Created: %d\n", when_created);
248#endif
249    if (scheduled()) {
250#if TRACING_ON
251        cprintf("Scheduled at  %d\n", when_scheduled);
252#endif
253        cprintf("Scheduled for %d, priority %d\n", when(), _priority);
254    }
255    else {
256        cprintf("Not Scheduled\n");
257    }
258}
259