sc_signal.hh revision 13142
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#include "warn_unimpl.hh" // for warn_unimpl 43 44namespace sc_core 45{ 46 47class sc_port_base; 48class sc_trace_file; 49 50// Nonstandard 51// Despite having a warning "FOR INTERNAL USE ONLY!" in all caps above this 52// class definition in the Accellera implementation, it appears in their 53// examples and test programs, and so we need to have it here as well. 54struct sc_trace_params 55{ 56 sc_trace_file *tf; 57 std::string name; 58 59 sc_trace_params(sc_trace_file *tf, const std::string &name) : 60 tf(tf), name(name) 61 {} 62}; 63typedef std::vector<sc_trace_params *> sc_trace_params_vec; 64 65template <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER> 66class sc_signal : public sc_signal_inout_if<T>, 67 public sc_prim_channel 68{ 69 public: 70 sc_signal() : sc_signal_inout_if<T>(), 71 sc_prim_channel(sc_gen_unique_name("signal")), 72 m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL) 73 {} 74 explicit sc_signal(const char *name) : 75 sc_signal_inout_if<T>(), sc_prim_channel(name), 76 m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL) 77 {} 78 explicit sc_signal(const char *name, const T &initial_value) : 79 sc_signal_inout_if<T>(), sc_prim_channel(name), 80 m_cur_val(initial_value), m_new_val(initial_value), _changeStamp(~0ULL) 81 {} 82 virtual ~sc_signal() {} 83 84 virtual void 85 register_port(sc_port_base &, const char *) 86 { 87 sc_channel_warn_unimpl(__PRETTY_FUNCTION__); 88 } 89 90 virtual const T &read() const { return m_cur_val; } 91 operator const T&() const { return read(); } 92 93 virtual sc_writer_policy 94 get_writer_policy() const 95 { 96 return WRITER_POLICY; 97 } 98 virtual void 99 write(const T &t) 100 { 101 m_new_val = t; 102 bool changed = !(m_cur_val == m_new_val); 103 //TODO check whether this write follows the write policy. 104 if (changed) 105 request_update(); 106 } 107 sc_signal<T, WRITER_POLICY> & 108 operator = (const T &t) 109 { 110 write(t); 111 return *this; 112 } 113 sc_signal<T, WRITER_POLICY> & 114 operator = (const sc_signal<T, WRITER_POLICY> &s) 115 { 116 write(s.read()); 117 return *this; 118 } 119 120 virtual const sc_event & 121 default_event() const 122 { 123 return value_changed_event(); 124 } 125 virtual const sc_event & 126 value_changed_event() const 127 { 128 return _valueChangedEvent; 129 } 130 virtual bool 131 event() const 132 { 133 return _changeStamp == ::sc_gem5::getChangeStamp(); 134 } 135 136 virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; } 137 virtual void 138 dump(std::ostream &os=std::cout) const 139 { 140 os << " name = " << name() << ::std::endl; 141 os << " value = " << m_cur_val << ::std::endl; 142 os << "new value = " << m_new_val << ::std::endl; 143 } 144 virtual const char *kind() const { return "sc_signal"; } 145 146 protected: 147 virtual void 148 update() 149 { 150 if (m_new_val == m_cur_val) 151 return; 152 153 m_cur_val = m_new_val; 154 _changeStamp = ::sc_gem5::getChangeStamp(); 155 _valueChangedEvent.notify(SC_ZERO_TIME); 156 } 157 158 // These members which store the current and future value of the signal 159 // are not specified in the standard but are referred to directly by one 160 // of the tests. 161 T m_cur_val; 162 T m_new_val; 163 164 private: 165 sc_event _valueChangedEvent; 166 uint64_t _changeStamp; 167 168 // Disabled 169 sc_signal(const sc_signal<T, WRITER_POLICY> &) : 170 sc_signal_inout_if<T>(), sc_prim_channel("") 171 {} 172}; 173 174template <class T, sc_writer_policy WRITER_POLICY> 175inline std::ostream & 176operator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &s) 177{ 178 os << s.read(); 179 return os; 180} 181 182template <sc_writer_policy WRITER_POLICY> 183class sc_signal<bool, WRITER_POLICY> : 184 public sc_signal_inout_if<bool>, public sc_prim_channel 185{ 186 public: 187 sc_signal() : sc_signal_inout_if<bool>(), 188 sc_prim_channel(sc_gen_unique_name("signal")), 189 m_cur_val(bool()), m_new_val(bool()), 190 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 191 {} 192 explicit sc_signal(const char *name) : 193 sc_signal_inout_if<bool>(), sc_prim_channel(name), 194 m_cur_val(bool()), m_new_val(bool()), 195 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 196 {} 197 explicit sc_signal(const char *name, const bool &initial_value) : 198 sc_signal_inout_if<bool>(), sc_prim_channel(name), 199 m_cur_val(initial_value), m_new_val(initial_value), 200 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 201 {} 202 virtual ~sc_signal() {} 203 204 virtual void 205 register_port(sc_port_base &, const char *) 206 { 207 sc_channel_warn_unimpl(__PRETTY_FUNCTION__); 208 } 209 210 virtual const bool &read() const { return m_cur_val; } 211 operator const bool &() const { return read(); } 212 213 virtual sc_writer_policy 214 get_writer_policy() const 215 { 216 return WRITER_POLICY; 217 } 218 virtual void 219 write(const bool &b) 220 { 221 m_new_val = b; 222 bool changed = !(m_cur_val == m_new_val); 223 //TODO check whether this write follows the write policy. 224 if (changed) 225 request_update(); 226 } 227 sc_signal<bool, WRITER_POLICY> & 228 operator = (const bool &b) 229 { 230 write(b); 231 return *this; 232 } 233 sc_signal<bool, WRITER_POLICY> & 234 operator = (const sc_signal<bool, WRITER_POLICY> &s) 235 { 236 write(s.read()); 237 return *this; 238 } 239 240 virtual const sc_event & 241 default_event() const 242 { 243 return value_changed_event(); 244 } 245 246 virtual const sc_event & 247 value_changed_event() const 248 { 249 return _valueChangedEvent; 250 } 251 virtual const sc_event & 252 posedge_event() const 253 { 254 return _posedgeEvent; 255 } 256 virtual const sc_event & 257 negedge_event() const 258 { 259 return _negedgeEvent; 260 } 261 262 virtual bool 263 event() const 264 { 265 return _changeStamp == ::sc_gem5::getChangeStamp(); 266 } 267 virtual bool 268 posedge() const 269 { 270 return _posStamp == ::sc_gem5::getChangeStamp(); 271 } 272 virtual bool 273 negedge() const 274 { 275 return _negStamp == ::sc_gem5::getChangeStamp(); 276 } 277 278 virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; } 279 virtual void 280 dump(std::ostream &os=std::cout) const 281 { 282 os << " name = " << name() << ::std::endl; 283 os << " value = " << m_cur_val << ::std::endl; 284 os << "new value = " << m_new_val << ::std::endl; 285 } 286 virtual const char *kind() const { return "sc_signal"; } 287 288 protected: 289 virtual void 290 update() 291 { 292 if (m_new_val == m_cur_val) 293 return; 294 295 m_cur_val = m_new_val; 296 uint64_t change_stamp = ::sc_gem5::getChangeStamp(); 297 _changeStamp = change_stamp; 298 _valueChangedEvent.notify(SC_ZERO_TIME); 299 if (m_cur_val) { 300 _posStamp = change_stamp; 301 _posedgeEvent.notify(SC_ZERO_TIME); 302 } else { 303 _negStamp = change_stamp; 304 _negedgeEvent.notify(SC_ZERO_TIME); 305 } 306 } 307 308 bool m_cur_val; 309 bool m_new_val; 310 311 private: 312 sc_event _valueChangedEvent; 313 sc_event _posedgeEvent; 314 sc_event _negedgeEvent; 315 316 uint64_t _changeStamp; 317 uint64_t _posStamp; 318 uint64_t _negStamp; 319 320 // Disabled 321 sc_signal(const sc_signal<bool, WRITER_POLICY> &) : 322 sc_signal_inout_if<bool>(), sc_prim_channel("") 323 {} 324}; 325 326template <sc_writer_policy WRITER_POLICY> 327class sc_signal<sc_dt::sc_logic, WRITER_POLICY> : 328 public sc_signal_inout_if<sc_dt::sc_logic>, public sc_prim_channel 329{ 330 public: 331 sc_signal() : sc_signal_inout_if<sc_dt::sc_logic>(), 332 sc_prim_channel(sc_gen_unique_name("signal")), 333 m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()), 334 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 335 {} 336 explicit sc_signal(const char *name) : 337 sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name), 338 m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()), 339 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 340 {} 341 explicit sc_signal(const char *name, 342 const sc_dt::sc_logic &initial_value) : 343 sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name), 344 m_cur_val(initial_value), m_new_val(initial_value), 345 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 346 {} 347 virtual ~sc_signal() {} 348 349 virtual void 350 register_port(sc_port_base &, const char *) 351 { 352 sc_channel_warn_unimpl(__PRETTY_FUNCTION__); 353 } 354 355 virtual const sc_dt::sc_logic &read() const { return m_cur_val; } 356 operator const sc_dt::sc_logic &() const { return read(); } 357 358 virtual sc_writer_policy 359 get_writer_policy() const 360 { 361 return WRITER_POLICY; 362 } 363 virtual void 364 write(const sc_dt::sc_logic &l) 365 { 366 m_new_val = l; 367 bool changed = !(m_cur_val == m_new_val); 368 //TODO check whether this write follows the write policy. 369 if (changed) 370 request_update(); 371 } 372 sc_signal<sc_dt::sc_logic, WRITER_POLICY> & 373 operator = (const sc_dt::sc_logic &l) 374 { 375 write(l); 376 return *this; 377 } 378 sc_signal<sc_dt::sc_logic, WRITER_POLICY> & 379 operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &s) 380 { 381 write(s.read()); 382 return *this; 383 } 384 385 virtual const sc_event & 386 default_event() const 387 { 388 return value_changed_event(); 389 } 390 391 virtual const sc_event & 392 value_changed_event() const 393 { 394 return _valueChangedEvent; 395 } 396 virtual const sc_event & 397 posedge_event() const 398 { 399 return _posedgeEvent; 400 } 401 virtual const sc_event & 402 negedge_event() const 403 { 404 return _negedgeEvent; 405 } 406 407 virtual bool 408 event() const 409 { 410 return _changeStamp == ::sc_gem5::getChangeStamp(); 411 } 412 virtual bool 413 posedge() const 414 { 415 return _posStamp == ::sc_gem5::getChangeStamp(); 416 } 417 virtual bool 418 negedge() const 419 { 420 return _negStamp == ::sc_gem5::getChangeStamp(); 421 } 422 423 virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; } 424 virtual void 425 dump(std::ostream &os=std::cout) const 426 { 427 os << " name = " << name() << ::std::endl; 428 os << " value = " << m_cur_val << ::std::endl; 429 os << "new value = " << m_new_val << ::std::endl; 430 } 431 virtual const char *kind() const { return "sc_signal"; } 432 433 protected: 434 virtual void 435 update() 436 { 437 if (m_new_val == m_cur_val) 438 return; 439 440 m_cur_val = m_new_val; 441 _valueChangedEvent.notify(SC_ZERO_TIME); 442 if (m_cur_val == sc_dt::SC_LOGIC_1) 443 _posedgeEvent.notify(SC_ZERO_TIME); 444 else if (m_cur_val == sc_dt::SC_LOGIC_0) 445 _negedgeEvent.notify(SC_ZERO_TIME); 446 } 447 448 sc_dt::sc_logic m_cur_val; 449 sc_dt::sc_logic m_new_val; 450 451 private: 452 sc_event _valueChangedEvent; 453 sc_event _posedgeEvent; 454 sc_event _negedgeEvent; 455 456 uint64_t _changeStamp; 457 uint64_t _posStamp; 458 uint64_t _negStamp; 459 460 // Disabled 461 sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &) : 462 sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel("") 463 {} 464}; 465 466} // namespace sc_core 467 468#endif //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__ 469