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