process.hh revision 12962
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_PROCESS_HH__ 31#define __SYSTEMC_CORE_PROCESS_HH__ 32 33#include <functional> 34#include <vector> 35 36#include "base/fiber.hh" 37#include "sim/eventq.hh" 38#include "systemc/core/bindinfo.hh" 39#include "systemc/core/list.hh" 40#include "systemc/core/object.hh" 41#include "systemc/ext/core/sc_event.hh" 42#include "systemc/ext/core/sc_interface.hh" 43#include "systemc/ext/core/sc_module.hh" 44#include "systemc/ext/core/sc_port.hh" 45#include "systemc/ext/core/sc_process_handle.hh" 46 47namespace sc_gem5 48{ 49 50class Sensitivity 51{ 52 protected: 53 Process *process; 54 55 public: 56 Sensitivity(Process *p) : process(p) {} 57 virtual ~Sensitivity() {} 58 59 virtual void notifyWork(Event *e); 60 void notify(Event *e); 61 void notify() { notify(nullptr); } 62 63 const std::string name(); 64}; 65 66class SensitivityTimeout : virtual public Sensitivity 67{ 68 private: 69 void timeout(); 70 EventWrapper<SensitivityTimeout, 71 &SensitivityTimeout::timeout> timeoutEvent; 72 ::sc_core::sc_time time; 73 74 public: 75 SensitivityTimeout(Process *p, ::sc_core::sc_time t); 76 ~SensitivityTimeout(); 77}; 78 79class SensitivityEvent : virtual public Sensitivity 80{ 81 private: 82 const ::sc_core::sc_event *event; 83 84 public: 85 SensitivityEvent(Process *p, const ::sc_core::sc_event *e); 86 ~SensitivityEvent(); 87}; 88 89//XXX This sensitivity can't be reused. To reset it, it has to be deleted and 90//recreated. That works for dynamic sensitivities, but not for static. 91//Fortunately processes can't be statically sensitive to sc_event_and_lists. 92class SensitivityEventAndList : virtual public Sensitivity 93{ 94 private: 95 const ::sc_core::sc_event_and_list *list; 96 int count; 97 98 public: 99 SensitivityEventAndList( 100 Process *p, const ::sc_core::sc_event_and_list *list); 101 ~SensitivityEventAndList(); 102 103 void notifyWork(Event *e) override; 104}; 105 106class SensitivityEventOrList : virtual public Sensitivity 107{ 108 private: 109 const ::sc_core::sc_event_or_list *list; 110 111 public: 112 SensitivityEventOrList( 113 Process *p, const ::sc_core::sc_event_or_list *list); 114 ~SensitivityEventOrList(); 115}; 116 117// Combined sensitivities. These trigger when any of their parts do. 118 119class SensitivityTimeoutAndEvent : 120 public SensitivityTimeout, public SensitivityEvent 121{ 122 public: 123 SensitivityTimeoutAndEvent( 124 Process *p, ::sc_core::sc_time t, const ::sc_core::sc_event *e) : 125 Sensitivity(p), SensitivityTimeout(p, t), SensitivityEvent(p, e) 126 {} 127}; 128 129class SensitivityTimeoutAndEventAndList : 130 public SensitivityTimeout, public SensitivityEventAndList 131{ 132 public: 133 SensitivityTimeoutAndEventAndList( 134 Process *p, ::sc_core::sc_time t, 135 const ::sc_core::sc_event_and_list *eal) : 136 Sensitivity(p), SensitivityTimeout(p, t), 137 SensitivityEventAndList(p, eal) 138 {} 139}; 140 141class SensitivityTimeoutAndEventOrList : 142 public SensitivityTimeout, public SensitivityEventOrList 143{ 144 public: 145 SensitivityTimeoutAndEventOrList( 146 Process *p, ::sc_core::sc_time t, 147 const ::sc_core::sc_event_or_list *eol) : 148 Sensitivity(p), SensitivityTimeout(p, t), 149 SensitivityEventOrList(p, eol) 150 {} 151}; 152 153typedef std::vector<Sensitivity *> Sensitivities; 154 155 156/* 157 * Pending sensitivities. These are records of sensitivities to install later, 158 * once all the information to configure them is available. 159 */ 160 161class PendingSensitivity 162{ 163 protected: 164 Process *process; 165 166 public: 167 virtual void finalize(Sensitivities &s) = 0; 168 PendingSensitivity(Process *p) : process(p) {} 169 virtual ~PendingSensitivity() {} 170}; 171 172class PendingSensitivityEvent : public PendingSensitivity 173{ 174 private: 175 const sc_core::sc_event *event; 176 177 public: 178 PendingSensitivityEvent(Process *p, const sc_core::sc_event *e) : 179 PendingSensitivity(p), event(e) {} 180 181 void 182 finalize(Sensitivities &s) override 183 { 184 s.push_back(new SensitivityEvent(process, event)); 185 } 186}; 187 188class PendingSensitivityInterface : public PendingSensitivity 189{ 190 private: 191 const sc_core::sc_interface *interface; 192 193 public: 194 PendingSensitivityInterface(Process *p, const sc_core::sc_interface *i) : 195 PendingSensitivity(p), interface(i) 196 {} 197 198 void 199 finalize(Sensitivities &s) override 200 { 201 s.push_back(new SensitivityEvent(process, 202 &interface->default_event())); 203 } 204}; 205 206class PendingSensitivityPort : public PendingSensitivity 207{ 208 private: 209 const sc_core::sc_port_base *port; 210 211 public: 212 PendingSensitivityPort(Process *p, const sc_core::sc_port_base *pb) : 213 PendingSensitivity(p), port(pb) 214 {} 215 216 void 217 finalize(Sensitivities &s) override 218 { 219 for (int i = 0; i < port->size(); i++) { 220 const ::sc_core::sc_event *e = 221 &port->_gem5BindInfo[i]->interface->default_event(); 222 s.push_back(new SensitivityEvent(process, e)); 223 } 224 } 225}; 226 227class PendingSensitivityFinder : public PendingSensitivity 228{ 229 private: 230 const sc_core::sc_event_finder *finder; 231 232 public: 233 PendingSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) : 234 PendingSensitivity(p), finder(f) 235 {} 236 237 void 238 finalize(Sensitivities &s) override 239 { 240 s.push_back(new SensitivityEvent(process, &finder->find_event())); 241 } 242}; 243 244typedef std::vector<PendingSensitivity *> PendingSensitivities; 245 246 247class Process : public ::sc_core::sc_object, public ListNode 248{ 249 public: 250 virtual ::sc_core::sc_curr_proc_kind procKind() const = 0; 251 bool needsStart() const { return _needsStart; } 252 bool dynamic() const { return _dynamic; } 253 bool isUnwinding() const { return _isUnwinding; } 254 bool terminated() const { return _terminated; } 255 256 void forEachKid(const std::function<void(Process *)> &work); 257 258 bool suspended() const { return _suspended; } 259 bool disabled() const { return _disabled; } 260 261 void suspend(bool inc_kids); 262 void resume(bool inc_kids); 263 void disable(bool inc_kids); 264 void enable(bool inc_kids); 265 266 void kill(bool inc_kids); 267 void reset(bool inc_kids); 268 virtual void throw_it(ExceptionWrapperBase &exc, bool inc_kids); 269 270 void injectException(ExceptionWrapperBase &exc); 271 ExceptionWrapperBase *excWrapper; 272 273 void syncResetOn(bool inc_kids); 274 void syncResetOff(bool inc_kids); 275 276 void incref() { refCount++; } 277 void decref() { refCount--; } 278 279 const ::sc_core::sc_event &resetEvent() { return _resetEvent; } 280 const ::sc_core::sc_event &terminatedEvent() { return _terminatedEvent; } 281 282 // This should only be called before initialization. 283 void dontInitialize(); 284 285 void setStackSize(size_t size) { stackSize = size; } 286 287 void finalize(); 288 289 void run(); 290 291 void addStatic(PendingSensitivity *); 292 void setDynamic(Sensitivity *); 293 294 void satisfySensitivity(Sensitivity *); 295 296 void ready(); 297 298 virtual Fiber *fiber() { return Fiber::primaryFiber(); } 299 300 static Process *newest() { return _newest; } 301 302 protected: 303 Process(const char *name, ProcessFuncWrapper *func, bool _dynamic, 304 bool needs_start); 305 306 static Process *_newest; 307 308 virtual ~Process() 309 { 310 delete func; 311 for (auto s: staticSensitivities) 312 delete s; 313 } 314 315 ::sc_core::sc_event _resetEvent; 316 ::sc_core::sc_event _terminatedEvent; 317 318 ProcessFuncWrapper *func; 319 sc_core::sc_curr_proc_kind _procKind; 320 bool _needsStart; 321 bool _dynamic; 322 bool _isUnwinding; 323 bool _terminated; 324 325 bool _suspended; 326 bool _suspendedReady; 327 bool _disabled; 328 329 bool _syncReset; 330 331 int refCount; 332 333 size_t stackSize; 334 335 Sensitivities staticSensitivities; 336 PendingSensitivities pendingStaticSensitivities; 337 338 Sensitivity *dynamicSensitivity; 339}; 340 341inline void 342Sensitivity::notifyWork(Event *e) 343{ 344 process->satisfySensitivity(this); 345} 346 347inline void 348Sensitivity::notify(Event *e) 349{ 350 if (!process->disabled()) 351 notifyWork(e); 352} 353 354inline const std::string 355Sensitivity::name() 356{ 357 return std::string(process->name()) + ".timeout"; 358} 359 360} // namespace sc_gem5 361 362#endif //__SYSTEMC_CORE_PROCESS_HH__ 363