1/* 2 * Copyright 2018 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution; 11 * neither the name of the copyright holders nor the names of its 12 * contributors may be used to endorse or promote products derived from 13 * this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Authors: Gabe Black 28 */ 29 30#ifndef __SYSTEMC_CORE_SCHEDULER_HH__ 31#define __SYSTEMC_CORE_SCHEDULER_HH__ 32
| 1/* 2 * Copyright 2018 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution; 11 * neither the name of the copyright holders nor the names of its 12 * contributors may be used to endorse or promote products derived from 13 * this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Authors: Gabe Black 28 */ 29 30#ifndef __SYSTEMC_CORE_SCHEDULER_HH__ 31#define __SYSTEMC_CORE_SCHEDULER_HH__ 32
|
| 33#include "sim/eventq.hh" 34#include "systemc/core/channel.hh"
|
33#include "systemc/core/list.hh" 34#include "systemc/core/process.hh" 35 36namespace sc_gem5 37{ 38 39typedef NodeList<Process> ProcessList;
| 35#include "systemc/core/list.hh" 36#include "systemc/core/process.hh" 37 38namespace sc_gem5 39{ 40 41typedef NodeList<Process> ProcessList;
|
| 42typedef NodeList<Channel> ChannelList;
|
40
| 43
|
| 44/* 45 * The scheduler supports three different mechanisms, the initialization phase, 46 * delta cycles, and timed notifications. 47 * 48 * INITIALIZATION PHASE 49 * 50 * The initialization phase has three parts: 51 * 1. Run requested channel updates. 52 * 2. Make processes which need to initialize runnable (methods and threads 53 * which didn't have dont_initialize called on them). 54 * 3. Process delta notifications. 55 * 56 * First, the Kernel SimObject calls the update() method during its startup() 57 * callback which handles the requested channel updates. The Kernel also 58 * schedules an event to be run at time 0 with a slightly elevated priority 59 * so that it happens before any "normal" event. 60 * 61 * When that t0 event happens, it calls the schedulers initToReady method 62 * which performs step 2 above. That indirectly causes the scheduler's 63 * readyEvent to be scheduled with slightly lowered priority, ensuring it 64 * happens after any "normal" event. 65 * 66 * Because delta notifications are scheduled at the standard priority, all 67 * of those events will happen next, performing step 3 above. Once they finish, 68 * if the readyEvent was scheduled above, there shouldn't be any higher 69 * priority events in front of it. When it runs, it will start the first 70 * evaluate phase of the first delta cycle. 71 * 72 * DELTA CYCLE 73 * 74 * A delta cycle has three phases within it. 75 * 1. The evaluate phase where runnable processes are allowed to run. 76 * 2. The update phase where requested channel updates hapen. 77 * 3. The delta notification phase where delta notifications happen. 78 * 79 * The readyEvent runs the first two steps of the delta cycle. It first goes 80 * through the list of runnable processes and executes them until the set is 81 * empty, and then immediately runs the update phase. Since these are all part 82 * of the same event, there's no chance for other events to intervene and 83 * break the required order above. 84 * 85 * During the update phase above, the spec forbids any action which would make 86 * a process runnable. That means that once the update phase finishes, the set 87 * of runnable processes will be empty. There may, however, have been some 88 * delta notifications/timeouts which will have been scheduled during either 89 * the evaluate or update phase above. Because those are scheduled at the 90 * normal priority, they will now happen together until there aren't any 91 * delta events left. 92 * 93 * If any processes became runnable during the delta notification phase, the 94 * readyEvent will have been scheduled and will have been waiting patiently 95 * behind the delta notification events. That will now run, effectively 96 * starting the next delta cycle. 97 * 98 * TIMED NOTIFICATION PHASE 99 * 100 * If no processes became runnable, the event queue will continue to process 101 * events until it comes across a timed notification, aka a notification 102 * scheduled to happen in the future. Like delta notification events, those 103 * will all happen together since the readyEvent priority is lower, 104 * potentially marking new processes as ready. Once these events finish, the 105 * readyEvent may run, starting the next delta cycle. 106 */ 107
|
41class Scheduler 42{ 43 public: 44 Scheduler(); 45
| 108class Scheduler 109{ 110 public: 111 Scheduler(); 112
|
| 113 const std::string name() const { return "systemc_scheduler"; } 114
|
46 uint64_t numCycles() { return _numCycles; } 47 Process *current() { return _current; } 48
| 115 uint64_t numCycles() { return _numCycles; } 116 Process *current() { return _current; } 117
|
49 // Run the initialization phase. 50 void initialize();
| 118 // Mark processes that need to be initialized as ready. 119 void initToReady();
|
51
| 120
|
52 // Run delta cycles until time needs to advance. 53 void runCycles(); 54
| |
55 // Put a process on the list of processes to be initialized. 56 void init(Process *p) { initList.pushLast(p); } 57 58 // Run the next process, if there is one. 59 void yield(); 60 61 // Put a process on the ready list.
| 121 // Put a process on the list of processes to be initialized. 122 void init(Process *p) { initList.pushLast(p); } 123 124 // Run the next process, if there is one. 125 void yield(); 126 127 // Put a process on the ready list.
|
62 void 63 ready(Process *p) 64 { 65 // Clump methods together to minimize context switching. 66 if (p->procKind() == ::sc_core::SC_METHOD_PROC_) 67 readyList.pushFirst(p); 68 else 69 readyList.pushLast(p); 70 }
| 128 void ready(Process *p);
|
71
| 129
|
| 130 // Schedule an update for a given channel. 131 void requestUpdate(Channel *c); 132
|
72 // Run the given process immediately, preempting whatever may be running. 73 void 74 runNow(Process *p) 75 { 76 // If a process is running, schedule it/us to run again. 77 if (_current) 78 readyList.pushFirst(_current); 79 // Schedule p to run first. 80 readyList.pushFirst(p); 81 yield(); 82 } 83
| 133 // Run the given process immediately, preempting whatever may be running. 134 void 135 runNow(Process *p) 136 { 137 // If a process is running, schedule it/us to run again. 138 if (_current) 139 readyList.pushFirst(_current); 140 // Schedule p to run first. 141 readyList.pushFirst(p); 142 yield(); 143 } 144
|
| 145 // Set an event queue for scheduling events. 146 void setEventQueue(EventQueue *_eq) { eq = _eq; } 147 148 // Retrieve the event queue. 149 EventQueue &eventQueue() const { return *eq; } 150 151 // Run scheduled channel updates. 152 void update(); 153
|
84 private:
| 154 private:
|
| 155 EventQueue *eq; 156 157 void runReady(); 158 EventWrapper<Scheduler, &Scheduler::runReady> readyEvent; 159 void scheduleReadyEvent(); 160
|
85 uint64_t _numCycles; 86 87 Process *_current; 88 89 ProcessList initList; 90 ProcessList readyList; 91
| 161 uint64_t _numCycles; 162 163 Process *_current; 164 165 ProcessList initList; 166 ProcessList readyList; 167
|
92 void evaluate(); 93 void update(); 94 void delta();
| 168 ChannelList updateList;
|
95}; 96 97extern Scheduler scheduler; 98 99} // namespace sc_gem5 100 101#endif // __SYSTEMC_CORE_SCHEDULER_H__
| 169}; 170 171extern Scheduler scheduler; 172 173} // namespace sc_gem5 174 175#endif // __SYSTEMC_CORE_SCHEDULER_H__
|