sc_signal.hh revision 13303
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_EXT_CHANNEL_SC_SIGNAL_HH__ 31#define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__ 32 33#include <iostream> 34#include <string> 35#include <vector> 36 37#include "../core/sc_event.hh" 38#include "../core/sc_module.hh" // for sc_gen_unique_name 39#include "../core/sc_prim.hh" 40#include "../dt/bit/sc_logic.hh" 41#include "sc_signal_inout_if.hh" 42 43namespace sc_core 44{ 45 46class sc_port_base; 47 48} // namespace sc_core 49 50namespace sc_gem5 51{ 52 53class Process; 54class Reset; 55 56class ScSignalBase : public sc_core::sc_prim_channel 57{ 58 public: 59 virtual const char *kind() const { return "sc_signal"; } 60 61 protected: 62 ScSignalBase(const char *_name); 63 virtual ~ScSignalBase(); 64 65 const sc_core::sc_event &defaultEvent() const; 66 const sc_core::sc_event &valueChangedEvent() const; 67 68 bool event() const; 69 70 void _signalChange(); 71 72 virtual sc_core::sc_writer_policy get_writer_policy() const = 0; 73 74 InternalScEvent _valueChangedEvent; 75 uint64_t _changeStamp; 76 sc_core::sc_port_base *_gem5WriterPort; 77}; 78 79class ScSignalBaseBinary : public ScSignalBase 80{ 81 protected: 82 ScSignalBaseBinary(const char *_name); 83 84 mutable std::vector<sc_gem5::Reset *> _resets; 85 void _signalReset(sc_gem5::Reset *reset); 86 void _signalReset(); 87 88 const sc_core::sc_event &posedgeEvent() const; 89 const sc_core::sc_event &negedgeEvent() const; 90 91 bool posedge() const; 92 bool negedge() const; 93 94 InternalScEvent _posedgeEvent; 95 InternalScEvent _negedgeEvent; 96 97 uint64_t _posStamp; 98 uint64_t _negStamp; 99}; 100 101template <class T> 102class ScSignalBasePicker : public ScSignalBase 103{ 104 protected: 105 ScSignalBasePicker(const char *_name) : ScSignalBase(_name) {} 106}; 107 108template <> 109class ScSignalBasePicker<bool> : public ScSignalBaseBinary 110{ 111 protected: 112 ScSignalBasePicker(const char *_name) : ScSignalBaseBinary(_name) {} 113}; 114 115template <> 116class ScSignalBasePicker<sc_dt::sc_logic> : public ScSignalBaseBinary 117{ 118 protected: 119 ScSignalBasePicker(const char *_name) : ScSignalBaseBinary(_name) {} 120}; 121 122template <sc_core::sc_writer_policy WRITER_POLICY> 123class WriteChecker; 124 125template <> 126class WriteChecker<sc_core::SC_ONE_WRITER> 127{ 128 public: 129 WriteChecker(ScSignalBase *_sig); 130 131 void checkPort(sc_core::sc_port_base &port, 132 std::string iface_type_name, std::string out_name); 133 void checkWriter(); 134 135 private: 136 ScSignalBase *sig; 137 sc_core::sc_port_base *firstPort; 138 Process *proc; 139 uint64_t writeStamp; 140}; 141 142template <> 143class WriteChecker<sc_core::SC_MANY_WRITERS> 144{ 145 public: 146 WriteChecker(ScSignalBase *_sig); 147 148 void checkPort(sc_core::sc_port_base &port, 149 std::string iface_type_name, std::string out_name); 150 void checkWriter(); 151 152 private: 153 ScSignalBase *sig; 154 Process *proc; 155 uint64_t writeStamp; 156}; 157 158template <class T, sc_core::sc_writer_policy WRITER_POLICY> 159class ScSignalBaseT : 160 public ScSignalBasePicker<T>, public sc_core::sc_signal_inout_if<T> 161{ 162 public: 163 ScSignalBaseT(const char *_name) : 164 ScSignalBasePicker<T>(_name), m_cur_val(T()), m_new_val(T()), 165 _checker(this) 166 {} 167 ScSignalBaseT(const char *_name, const T &initial_value) : 168 ScSignalBasePicker<T>(_name), m_cur_val(initial_value), 169 m_new_val(initial_value), _checker(this) 170 {} 171 virtual ~ScSignalBaseT() {} 172 173 virtual void 174 register_port(sc_core::sc_port_base &port, const char *iface_type_name) 175 { 176# if !defined(SC_NO_WRITE_CHECK) 177 { 178 _checker.checkPort(port, iface_type_name, 179 typeid(sc_core::sc_signal_inout_if<T>).name()); 180 } 181# endif 182 } 183 184 virtual const T &read() const { return m_cur_val; } 185 operator const T&() const { return read(); } 186 187 virtual void 188 write(const T &t) 189 { 190# if !defined(SC_NO_WRITE_CHECK) 191 { 192 _checker.checkWriter(); 193 } 194# endif 195 m_new_val = t; 196 bool changed = !(m_cur_val == m_new_val); 197 if (changed) 198 this->request_update(); 199 } 200 201 virtual const sc_core::sc_event & 202 default_event() const 203 { 204 return ScSignalBase::defaultEvent(); 205 } 206 207 virtual const sc_core::sc_event & 208 value_changed_event() const 209 { 210 return ScSignalBase::valueChangedEvent(); 211 } 212 213 virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; } 214 virtual void 215 dump(std::ostream &os=std::cout) const 216 { 217 os << " name = " << this->name() << ::std::endl; 218 os << " value = " << m_cur_val << ::std::endl; 219 os << "new value = " << m_new_val << ::std::endl; 220 } 221 222 virtual bool event() const { return ScSignalBase::event(); } 223 224 virtual sc_core::sc_writer_policy 225 get_writer_policy() const 226 { 227 return WRITER_POLICY; 228 } 229 230 protected: 231 // These members which store the current and future value of the signal 232 // are not specified in the standard but are referred to directly by one 233 // of the tests. 234 T m_cur_val; 235 T m_new_val; 236 237 WriteChecker<WRITER_POLICY> _checker; 238}; 239 240template <typename T, sc_core::sc_writer_policy WRITER_POLICY> 241class ScSignalBinary : public ScSignalBaseT<T, WRITER_POLICY> 242{ 243 public: 244 ScSignalBinary(const char *_name) : ScSignalBaseT<T, WRITER_POLICY>(_name) 245 {} 246 ScSignalBinary(const char *_name, const T& initial_value) : 247 ScSignalBaseT<T, WRITER_POLICY>(_name, initial_value) 248 {} 249 250 const sc_core::sc_event & 251 posedge_event() const 252 { 253 return ScSignalBaseBinary::posedgeEvent(); 254 } 255 const sc_core::sc_event & 256 negedge_event() const 257 { 258 return ScSignalBaseBinary::negedgeEvent(); 259 } 260 261 bool posedge() const { return ScSignalBaseBinary::posedge(); } 262 bool negedge() const { return ScSignalBaseBinary::negedge(); } 263}; 264 265} // namespace sc_gem5 266 267namespace sc_core 268{ 269 270template <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER> 271class sc_signal : public sc_gem5::ScSignalBaseT<T, WRITER_POLICY> 272{ 273 public: 274 sc_signal() : sc_gem5::ScSignalBaseT<T, WRITER_POLICY>( 275 sc_gen_unique_name("signal")) 276 {} 277 explicit sc_signal(const char *name) : 278 sc_gem5::ScSignalBaseT<T, WRITER_POLICY>(name) 279 {} 280 explicit sc_signal(const char *name, const T &initial_value) : 281 sc_gem5::ScSignalBaseT<T, WRITER_POLICY>(name, initial_value) 282 {} 283 virtual ~sc_signal() {} 284 285 sc_signal<T, WRITER_POLICY> & 286 operator = (const T &t) 287 { 288 this->write(t); 289 return *this; 290 } 291 sc_signal<T, WRITER_POLICY> & 292 operator = (const sc_signal<T, WRITER_POLICY> &s) 293 { 294 this->write(s.read()); 295 return *this; 296 } 297 298 protected: 299 virtual void 300 update() 301 { 302 if (this->m_new_val == this->m_cur_val) 303 return; 304 305 this->m_cur_val = this->m_new_val; 306 this->_signalChange(); 307 } 308 309 private: 310 // Disabled 311 sc_signal(const sc_signal<T, WRITER_POLICY> &); 312}; 313 314template <class T, sc_writer_policy WRITER_POLICY> 315inline std::ostream & 316operator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &s) 317{ 318 os << s.read(); 319 return os; 320} 321 322template <sc_writer_policy WRITER_POLICY> 323class sc_signal<bool, WRITER_POLICY> : 324 public sc_gem5::ScSignalBinary<bool, WRITER_POLICY> 325{ 326 public: 327 sc_signal() : 328 sc_gem5::ScSignalBinary<bool, WRITER_POLICY>( 329 sc_gen_unique_name("signal")) 330 {} 331 explicit sc_signal(const char *name) : 332 sc_gem5::ScSignalBinary<bool, WRITER_POLICY>(name) 333 {} 334 explicit sc_signal(const char *name, const bool &initial_value) : 335 sc_gem5::ScSignalBinary<bool, WRITER_POLICY>(name, initial_value) 336 {} 337 virtual ~sc_signal() {} 338 339 sc_signal<bool, WRITER_POLICY> & 340 operator = (const bool &b) 341 { 342 this->write(b); 343 return *this; 344 } 345 sc_signal<bool, WRITER_POLICY> & 346 operator = (const sc_signal<bool, WRITER_POLICY> &s) 347 { 348 this->write(s.read()); 349 return *this; 350 } 351 352 protected: 353 virtual void 354 update() 355 { 356 if (this->m_new_val == this->m_cur_val) 357 return; 358 359 this->m_cur_val = this->m_new_val; 360 this->_signalReset(); 361 this->_signalChange(); 362 if (this->m_cur_val) { 363 this->_posStamp = ::sc_gem5::getChangeStamp(); 364 this->_posedgeEvent.notify(SC_ZERO_TIME); 365 } else { 366 this->_negStamp = ::sc_gem5::getChangeStamp(); 367 this->_negedgeEvent.notify(SC_ZERO_TIME); 368 } 369 } 370 371 private: 372 bool 373 _addReset(sc_gem5::Reset *reset) const 374 { 375 this->_resets.push_back(reset); 376 return true; 377 } 378 379 // Disabled 380 sc_signal(const sc_signal<bool, WRITER_POLICY> &); 381}; 382 383template <sc_writer_policy WRITER_POLICY> 384class sc_signal<sc_dt::sc_logic, WRITER_POLICY> : 385 public sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY> 386{ 387 public: 388 sc_signal() : 389 sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>( 390 sc_gen_unique_name("signal")) 391 {} 392 explicit sc_signal(const char *name) : 393 sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>(name) 394 {} 395 explicit sc_signal(const char *name, 396 const sc_dt::sc_logic &initial_value) : 397 sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>( 398 name, initial_value) 399 {} 400 virtual ~sc_signal() {} 401 402 sc_signal<sc_dt::sc_logic, WRITER_POLICY> & 403 operator = (const sc_dt::sc_logic &l) 404 { 405 this->write(l); 406 return *this; 407 } 408 sc_signal<sc_dt::sc_logic, WRITER_POLICY> & 409 operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &s) 410 { 411 this->write(s.read()); 412 return *this; 413 } 414 415 protected: 416 virtual void 417 update() 418 { 419 if (this->m_new_val == this->m_cur_val) 420 return; 421 422 this->m_cur_val = this->m_new_val; 423 this->_signalChange(); 424 if (this->m_cur_val == sc_dt::SC_LOGIC_1) { 425 this->_posStamp = ::sc_gem5::getChangeStamp(); 426 this->_posedgeEvent.notify(SC_ZERO_TIME); 427 } else if (this->m_cur_val == sc_dt::SC_LOGIC_0) { 428 this->_negStamp = ::sc_gem5::getChangeStamp(); 429 this->_negedgeEvent.notify(SC_ZERO_TIME); 430 } 431 } 432 433 private: 434 // Disabled 435 sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &); 436}; 437 438} // namespace sc_core 439 440#endif //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__ 441