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