eventq.cc revision 5501
12SN/A/*
21762SN/A * Copyright (c) 2000-2005 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt
292665Ssaidi@eecs.umich.edu *          Nathan Binkert
302665Ssaidi@eecs.umich.edu *          Steve Raasch
312SN/A */
322SN/A
335501Snate@binkert.org#include <cassert>
342SN/A#include <iostream>
352SN/A#include <string>
362SN/A#include <vector>
372SN/A
385501Snate@binkert.org#include "base/misc.hh"
395501Snate@binkert.org#include "base/trace.hh"
401717SN/A#include "cpu/smt.hh"
415501Snate@binkert.org#include "sim/core.hh"
4256SN/A#include "sim/eventq.hh"
432SN/A
442SN/Ausing namespace std;
452SN/A
462SN/A//
472SN/A// Main Event Queue
482SN/A//
492SN/A// Events on this queue are processed at the *beginning* of each
502SN/A// cycle, before the pipeline simulation is performed.
512SN/A//
52221SN/AEventQueue mainEventQueue("MainEventQueue");
532SN/A
544017Sstever@eecs.umich.edu#ifndef NDEBUG
554016Sstever@eecs.umich.eduCounter Event::instanceCounter = 0;
564017Sstever@eecs.umich.edu#endif
574016Sstever@eecs.umich.edu
582SN/Avoid
592SN/AEventQueue::insert(Event *event)
602SN/A{
612SN/A    if (head == NULL || event->when() < head->when() ||
622SN/A        (event->when() == head->when() &&
632SN/A         event->priority() <= head->priority())) {
642SN/A        event->next = head;
652SN/A        head = event;
662SN/A    } else {
672SN/A        Event *prev = head;
682SN/A        Event *curr = head->next;
692SN/A
702SN/A        while (curr) {
712SN/A            if (event->when() <= curr->when() &&
722SN/A                (event->when() < curr->when() ||
732SN/A                 event->priority() <= curr->priority()))
742SN/A                break;
752SN/A
762SN/A            prev = curr;
772SN/A            curr = curr->next;
782SN/A        }
792SN/A
802SN/A        event->next = curr;
812SN/A        prev->next = event;
822SN/A    }
832SN/A}
842SN/A
852SN/Avoid
862SN/AEventQueue::remove(Event *event)
872SN/A{
882SN/A    if (head == NULL)
892SN/A        return;
902SN/A
912SN/A    if (head == event){
922SN/A        head = event->next;
932SN/A        return;
942SN/A    }
952SN/A
962SN/A    Event *prev = head;
972SN/A    Event *curr = head->next;
982SN/A    while (curr && curr != event) {
992SN/A        prev = curr;
1002SN/A        curr = curr->next;
1012SN/A    }
1022SN/A
1032SN/A    if (curr == event)
1042SN/A        prev->next = curr->next;
1052SN/A}
1062SN/A
1072667Sstever@eecs.umich.eduEvent *
1082SN/AEventQueue::serviceOne()
1092SN/A{
1102SN/A    Event *event = head;
1112SN/A    event->clearFlags(Event::Scheduled);
1122SN/A    head = event->next;
1132SN/A
1142SN/A    // handle action
1152667Sstever@eecs.umich.edu    if (!event->squashed()) {
1162SN/A        event->process();
1172667Sstever@eecs.umich.edu        if (event->isExitEvent()) {
1182667Sstever@eecs.umich.edu            assert(!event->getFlags(Event::AutoDelete)); // would be silly
1192667Sstever@eecs.umich.edu            return event;
1202667Sstever@eecs.umich.edu        }
1212667Sstever@eecs.umich.edu    } else {
1222SN/A        event->clearFlags(Event::Squashed);
1232667Sstever@eecs.umich.edu    }
1242SN/A
125294SN/A    if (event->getFlags(Event::AutoDelete) && !event->scheduled())
1262SN/A        delete event;
1272667Sstever@eecs.umich.edu
1282667Sstever@eecs.umich.edu    return NULL;
1292SN/A}
1302SN/A
131224SN/A
132224SN/Avoid
133224SN/AEvent::serialize(std::ostream &os)
134224SN/A{
135224SN/A    SERIALIZE_SCALAR(_when);
136224SN/A    SERIALIZE_SCALAR(_priority);
137224SN/A    SERIALIZE_ENUM(_flags);
138224SN/A}
139224SN/A
140224SN/A
141224SN/Avoid
142237SN/AEvent::unserialize(Checkpoint *cp, const string &section)
143224SN/A{
144224SN/A    if (scheduled())
145224SN/A        deschedule();
146224SN/A
147224SN/A    UNSERIALIZE_SCALAR(_when);
148224SN/A    UNSERIALIZE_SCALAR(_priority);
149224SN/A
150224SN/A    // need to see if original event was in a scheduled, unsquashed
151224SN/A    // state, but don't want to restore those flags in the current
152224SN/A    // object itself (since they aren't immediately true)
153224SN/A    UNSERIALIZE_ENUM(_flags);
154224SN/A    bool wasScheduled = (_flags & Scheduled) && !(_flags & Squashed);
155224SN/A    _flags &= ~(Squashed | Scheduled);
156224SN/A
157224SN/A    if (wasScheduled) {
158224SN/A        DPRINTF(Config, "rescheduling at %d\n", _when);
159224SN/A        schedule(_when);
160224SN/A    }
161224SN/A}
162224SN/A
1632SN/Avoid
164217SN/AEventQueue::serialize(ostream &os)
1652SN/A{
166265SN/A    std::list<Event *> eventPtrs;
167237SN/A
168237SN/A    int numEvents = 0;
1692SN/A    Event *event = head;
1702SN/A    while (event) {
171237SN/A        if (event->getFlags(Event::AutoSerialize)) {
172265SN/A            eventPtrs.push_back(event);
173270SN/A            paramOut(os, csprintf("event%d", numEvents++), event->name());
174237SN/A        }
1752SN/A        event = event->next;
1762SN/A    }
177237SN/A
178265SN/A    SERIALIZE_SCALAR(numEvents);
179265SN/A
180265SN/A    for (std::list<Event *>::iterator it=eventPtrs.begin();
181265SN/A         it != eventPtrs.end(); ++it) {
182265SN/A        (*it)->nameOut(os);
183265SN/A        (*it)->serialize(os);
184265SN/A    }
1852SN/A}
1862SN/A
187237SN/Avoid
188237SN/AEventQueue::unserialize(Checkpoint *cp, const std::string &section)
189237SN/A{
190265SN/A    int numEvents;
191265SN/A    UNSERIALIZE_SCALAR(numEvents);
192265SN/A
193270SN/A    std::string eventName;
194265SN/A    for (int i = 0; i < numEvents; i++) {
195265SN/A        // get the pointer value associated with the event
196270SN/A        paramIn(cp, section, csprintf("event%d", i), eventName);
197265SN/A
198265SN/A        // create the event based on its pointer value
199395SN/A        Serializable::create(cp, eventName);
200237SN/A    }
201237SN/A}
202237SN/A
2032SN/Avoid
2045501Snate@binkert.orgEventQueue::dump() const
2052SN/A{
2062SN/A    cprintf("============================================================\n");
2072SN/A    cprintf("EventQueue Dump  (cycle %d)\n", curTick);
2082SN/A    cprintf("------------------------------------------------------------\n");
2092SN/A
2102SN/A    if (empty())
2112SN/A        cprintf("<No Events>\n");
2122SN/A    else {
2132SN/A        Event *event = head;
2142SN/A        while (event) {
2152SN/A            event->dump();
2162SN/A            event = event->next;
2172SN/A        }
2182SN/A    }
2192SN/A
2202SN/A    cprintf("============================================================\n");
2212SN/A}
2222SN/A
2231019SN/Avoid
2241019SN/AdumpMainQueue()
2251019SN/A{
2261019SN/A    mainEventQueue.dump();
2271019SN/A}
2281019SN/A
2292SN/A
2302SN/Aconst char *
2315336Shines@cs.fsu.eduEvent::description() const
2322SN/A{
2332SN/A    return "generic";
2342SN/A}
2352SN/A
2362SN/Avoid
2372SN/AEvent::trace(const char *action)
2382SN/A{
2392SN/A    // This DPRINTF is unconditional because calls to this function
2402SN/A    // are protected by an 'if (DTRACE(Event))' in the inlined Event
2412SN/A    // methods.
2422SN/A    //
2432SN/A    // This is just a default implementation for derived classes where
2442SN/A    // it's not worth doing anything special.  If you want to put a
2452SN/A    // more informative message in the trace, override this method on
2462SN/A    // the particular subclass where you have the information that
2472SN/A    // needs to be printed.
2482SN/A    DPRINTFN("%s event %s @ %d\n", description(), action, when());
2492SN/A}
2502SN/A
2512SN/Avoid
2525501Snate@binkert.orgEvent::dump() const
2532SN/A{
2545501Snate@binkert.org    cprintf("Event %s (%s)\n", name(), description());
2551019SN/A    cprintf("Flags: %#x\n", _flags);
2565501Snate@binkert.org#ifdef EVENTQ_DEBUG
2575501Snate@binkert.org    cprintf("Created: %d\n", whenCreated);
2582SN/A#endif
2592SN/A    if (scheduled()) {
2605501Snate@binkert.org#ifdef EVENTQ_DEBUG
2615501Snate@binkert.org        cprintf("Scheduled at  %d\n", whenScheduled);
2622SN/A#endif
2631019SN/A        cprintf("Scheduled for %d, priority %d\n", when(), _priority);
2645501Snate@binkert.org    } else {
2651019SN/A        cprintf("Not Scheduled\n");
2662SN/A    }
2672SN/A}
268