sc_signal.hh revision 13245:c666c5d4996b
16313Sgblack@eecs.umich.edu/* 26313Sgblack@eecs.umich.edu * Copyright 2018 Google, Inc. 36313Sgblack@eecs.umich.edu * 46313Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 56313Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 66313Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 76313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 86313Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 96313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 106313Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 116313Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 126313Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 136313Sgblack@eecs.umich.edu * this software without specific prior written permission. 146313Sgblack@eecs.umich.edu * 156313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 166313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 176313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 186313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 196313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 206313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 216313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 226313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 236313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 246313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 256313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 266313Sgblack@eecs.umich.edu * 276313Sgblack@eecs.umich.edu * Authors: Gabe Black 286313Sgblack@eecs.umich.edu */ 296313Sgblack@eecs.umich.edu 306313Sgblack@eecs.umich.edu#ifndef __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__ 316313Sgblack@eecs.umich.edu#define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__ 326313Sgblack@eecs.umich.edu 336313Sgblack@eecs.umich.edu#include <iostream> 348229Snate@binkert.org#include <string> 358229Snate@binkert.org#include <vector> 368229Snate@binkert.org 376335Sgblack@eecs.umich.edu#include "../core/sc_event.hh" 386313Sgblack@eecs.umich.edu#include "../core/sc_module.hh" // for sc_gen_unique_name 396335Sgblack@eecs.umich.edu#include "../core/sc_prim.hh" 406335Sgblack@eecs.umich.edu#include "../dt/bit/sc_logic.hh" 416335Sgblack@eecs.umich.edu#include "sc_signal_inout_if.hh" 426313Sgblack@eecs.umich.edu#include "warn_unimpl.hh" // for warn_unimpl 436313Sgblack@eecs.umich.edu 446335Sgblack@eecs.umich.edunamespace sc_core 456313Sgblack@eecs.umich.edu{ 466313Sgblack@eecs.umich.edu 476313Sgblack@eecs.umich.educlass sc_port_base; 487741Sgblack@eecs.umich.edu 497741Sgblack@eecs.umich.edutemplate <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER> 507741Sgblack@eecs.umich.educlass sc_signal : public sc_signal_inout_if<T>, 516335Sgblack@eecs.umich.edu public sc_prim_channel 527741Sgblack@eecs.umich.edu{ 537741Sgblack@eecs.umich.edu public: 547741Sgblack@eecs.umich.edu sc_signal() : sc_signal_inout_if<T>(), 557741Sgblack@eecs.umich.edu sc_prim_channel(sc_gen_unique_name("signal")), 567741Sgblack@eecs.umich.edu m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL) 577741Sgblack@eecs.umich.edu {} 587741Sgblack@eecs.umich.edu explicit sc_signal(const char *name) : 597741Sgblack@eecs.umich.edu sc_signal_inout_if<T>(), sc_prim_channel(name), 607741Sgblack@eecs.umich.edu m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL) 617741Sgblack@eecs.umich.edu {} 627741Sgblack@eecs.umich.edu explicit sc_signal(const char *name, const T &initial_value) : 636335Sgblack@eecs.umich.edu sc_signal_inout_if<T>(), sc_prim_channel(name), 646335Sgblack@eecs.umich.edu m_cur_val(initial_value), m_new_val(initial_value), _changeStamp(~0ULL) 657741Sgblack@eecs.umich.edu {} 667741Sgblack@eecs.umich.edu virtual ~sc_signal() {} 677741Sgblack@eecs.umich.edu 687741Sgblack@eecs.umich.edu virtual void 697741Sgblack@eecs.umich.edu register_port(sc_port_base &, const char *) 707741Sgblack@eecs.umich.edu { 717741Sgblack@eecs.umich.edu sc_channel_warn_unimpl(__PRETTY_FUNCTION__); 727741Sgblack@eecs.umich.edu } 737741Sgblack@eecs.umich.edu 746335Sgblack@eecs.umich.edu virtual const T &read() const { return m_cur_val; } 757741Sgblack@eecs.umich.edu operator const T&() const { return read(); } 767741Sgblack@eecs.umich.edu 777741Sgblack@eecs.umich.edu virtual sc_writer_policy 787741Sgblack@eecs.umich.edu get_writer_policy() const 797741Sgblack@eecs.umich.edu { 807741Sgblack@eecs.umich.edu return WRITER_POLICY; 817741Sgblack@eecs.umich.edu } 827741Sgblack@eecs.umich.edu virtual void 837741Sgblack@eecs.umich.edu write(const T &t) 847741Sgblack@eecs.umich.edu { 856335Sgblack@eecs.umich.edu m_new_val = t; 867741Sgblack@eecs.umich.edu bool changed = !(m_cur_val == m_new_val); 877741Sgblack@eecs.umich.edu //TODO check whether this write follows the write policy. 887741Sgblack@eecs.umich.edu if (changed) 897741Sgblack@eecs.umich.edu request_update(); 907741Sgblack@eecs.umich.edu } 917741Sgblack@eecs.umich.edu sc_signal<T, WRITER_POLICY> & 926335Sgblack@eecs.umich.edu operator = (const T &t) 937741Sgblack@eecs.umich.edu { 946335Sgblack@eecs.umich.edu write(t); 957741Sgblack@eecs.umich.edu return *this; 967741Sgblack@eecs.umich.edu } 976335Sgblack@eecs.umich.edu sc_signal<T, WRITER_POLICY> & 987741Sgblack@eecs.umich.edu operator = (const sc_signal<T, WRITER_POLICY> &s) 997741Sgblack@eecs.umich.edu { 1007741Sgblack@eecs.umich.edu write(s.read()); 1017741Sgblack@eecs.umich.edu return *this; 1027741Sgblack@eecs.umich.edu } 1036335Sgblack@eecs.umich.edu 1047741Sgblack@eecs.umich.edu virtual const sc_event & 1056335Sgblack@eecs.umich.edu default_event() const 1067741Sgblack@eecs.umich.edu { 1077741Sgblack@eecs.umich.edu return value_changed_event(); 1087741Sgblack@eecs.umich.edu } 1097741Sgblack@eecs.umich.edu virtual const sc_event & 1107741Sgblack@eecs.umich.edu value_changed_event() const 1117741Sgblack@eecs.umich.edu { 1127741Sgblack@eecs.umich.edu return _valueChangedEvent; 1137741Sgblack@eecs.umich.edu } 1146335Sgblack@eecs.umich.edu virtual bool 1157741Sgblack@eecs.umich.edu event() const 1167741Sgblack@eecs.umich.edu { 1176335Sgblack@eecs.umich.edu return _changeStamp == ::sc_gem5::getChangeStamp(); 1187741Sgblack@eecs.umich.edu } 1197741Sgblack@eecs.umich.edu 1206335Sgblack@eecs.umich.edu virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; } 1217741Sgblack@eecs.umich.edu virtual void 1227741Sgblack@eecs.umich.edu dump(std::ostream &os=std::cout) const 1236335Sgblack@eecs.umich.edu { 1247741Sgblack@eecs.umich.edu os << " name = " << name() << ::std::endl; 1257741Sgblack@eecs.umich.edu os << " value = " << m_cur_val << ::std::endl; 1267741Sgblack@eecs.umich.edu os << "new value = " << m_new_val << ::std::endl; 1277741Sgblack@eecs.umich.edu } 1287741Sgblack@eecs.umich.edu virtual const char *kind() const { return "sc_signal"; } 1296335Sgblack@eecs.umich.edu 1307741Sgblack@eecs.umich.edu protected: 1317741Sgblack@eecs.umich.edu virtual void 1327741Sgblack@eecs.umich.edu update() 1336335Sgblack@eecs.umich.edu { 1347741Sgblack@eecs.umich.edu if (m_new_val == m_cur_val) 1357741Sgblack@eecs.umich.edu return; 1367741Sgblack@eecs.umich.edu 1376335Sgblack@eecs.umich.edu m_cur_val = m_new_val; 1387741Sgblack@eecs.umich.edu _signalChange(); 1397741Sgblack@eecs.umich.edu _changeStamp = ::sc_gem5::getChangeStamp(); 1407741Sgblack@eecs.umich.edu _valueChangedEvent.notify(SC_ZERO_TIME); 1416335Sgblack@eecs.umich.edu } 1426337Sgblack@eecs.umich.edu 1437741Sgblack@eecs.umich.edu void 1447741Sgblack@eecs.umich.edu _signalChange() 1457741Sgblack@eecs.umich.edu { 1466337Sgblack@eecs.umich.edu _changeStamp = ::sc_gem5::getChangeStamp(); 1477741Sgblack@eecs.umich.edu _valueChangedEvent.notify(SC_ZERO_TIME); 1487741Sgblack@eecs.umich.edu } 1497741Sgblack@eecs.umich.edu 1506337Sgblack@eecs.umich.edu // These members which store the current and future value of the signal 1517741Sgblack@eecs.umich.edu // are not specified in the standard but are referred to directly by one 1527741Sgblack@eecs.umich.edu // of the tests. 1537741Sgblack@eecs.umich.edu T m_cur_val; 1547741Sgblack@eecs.umich.edu T m_new_val; 1557741Sgblack@eecs.umich.edu 1567741Sgblack@eecs.umich.edu private: 1577741Sgblack@eecs.umich.edu sc_event _valueChangedEvent; 1587741Sgblack@eecs.umich.edu uint64_t _changeStamp; 1597741Sgblack@eecs.umich.edu 1607741Sgblack@eecs.umich.edu // Disabled 1616337Sgblack@eecs.umich.edu sc_signal(const sc_signal<T, WRITER_POLICY> &) : 1627741Sgblack@eecs.umich.edu sc_signal_inout_if<T>(), sc_prim_channel("") 1637741Sgblack@eecs.umich.edu {} 1647741Sgblack@eecs.umich.edu}; 1657741Sgblack@eecs.umich.edu 1666337Sgblack@eecs.umich.edutemplate <class T, sc_writer_policy WRITER_POLICY> 1677741Sgblack@eecs.umich.eduinline std::ostream & 1686335Sgblack@eecs.umich.eduoperator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &s) 1697741Sgblack@eecs.umich.edu{ 1706335Sgblack@eecs.umich.edu os << s.read(); 1717741Sgblack@eecs.umich.edu return os; 1726335Sgblack@eecs.umich.edu} 1737741Sgblack@eecs.umich.edu 1747741Sgblack@eecs.umich.edutemplate <sc_writer_policy WRITER_POLICY> 1756335Sgblack@eecs.umich.educlass sc_signal<bool, WRITER_POLICY> : 1767741Sgblack@eecs.umich.edu public sc_signal_inout_if<bool>, public sc_prim_channel 1776335Sgblack@eecs.umich.edu{ 1787741Sgblack@eecs.umich.edu public: 1797741Sgblack@eecs.umich.edu sc_signal() : sc_signal_inout_if<bool>(), 1807741Sgblack@eecs.umich.edu sc_prim_channel(sc_gen_unique_name("signal")), 1816313Sgblack@eecs.umich.edu m_cur_val(bool()), m_new_val(bool()), 1827741Sgblack@eecs.umich.edu _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 1836313Sgblack@eecs.umich.edu {} 1847741Sgblack@eecs.umich.edu explicit sc_signal(const char *name) : 1857741Sgblack@eecs.umich.edu sc_signal_inout_if<bool>(), sc_prim_channel(name), 1866313Sgblack@eecs.umich.edu m_cur_val(bool()), m_new_val(bool()), 1877741Sgblack@eecs.umich.edu _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 1887741Sgblack@eecs.umich.edu {} 1897741Sgblack@eecs.umich.edu explicit sc_signal(const char *name, const bool &initial_value) : 1906313Sgblack@eecs.umich.edu sc_signal_inout_if<bool>(), sc_prim_channel(name), 1917741Sgblack@eecs.umich.edu m_cur_val(initial_value), m_new_val(initial_value), 1927741Sgblack@eecs.umich.edu _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 1937741Sgblack@eecs.umich.edu {} 1947741Sgblack@eecs.umich.edu virtual ~sc_signal() {} 1957741Sgblack@eecs.umich.edu 1967741Sgblack@eecs.umich.edu virtual void 1977741Sgblack@eecs.umich.edu register_port(sc_port_base &, const char *) 1987741Sgblack@eecs.umich.edu { 1996313Sgblack@eecs.umich.edu sc_channel_warn_unimpl(__PRETTY_FUNCTION__); 2007741Sgblack@eecs.umich.edu } 2017741Sgblack@eecs.umich.edu 2027741Sgblack@eecs.umich.edu virtual const bool &read() const { return m_cur_val; } 2037741Sgblack@eecs.umich.edu operator const bool &() const { return read(); } 2047741Sgblack@eecs.umich.edu 2056313Sgblack@eecs.umich.edu virtual sc_writer_policy 2067741Sgblack@eecs.umich.edu get_writer_policy() const 2077741Sgblack@eecs.umich.edu { 2087703Sgblack@eecs.umich.edu return WRITER_POLICY; 2097741Sgblack@eecs.umich.edu } 2107741Sgblack@eecs.umich.edu virtual void 2117741Sgblack@eecs.umich.edu write(const bool &b) 2127703Sgblack@eecs.umich.edu { 2137703Sgblack@eecs.umich.edu m_new_val = b; 2147741Sgblack@eecs.umich.edu bool changed = !(m_cur_val == m_new_val); 2157741Sgblack@eecs.umich.edu //TODO check whether this write follows the write policy. 2167741Sgblack@eecs.umich.edu if (changed) 2176313Sgblack@eecs.umich.edu request_update(); 2186313Sgblack@eecs.umich.edu } 2196313Sgblack@eecs.umich.edu sc_signal<bool, WRITER_POLICY> & 220 operator = (const bool &b) 221 { 222 write(b); 223 return *this; 224 } 225 sc_signal<bool, WRITER_POLICY> & 226 operator = (const sc_signal<bool, WRITER_POLICY> &s) 227 { 228 write(s.read()); 229 return *this; 230 } 231 232 virtual const sc_event & 233 default_event() const 234 { 235 return value_changed_event(); 236 } 237 238 virtual const sc_event & 239 value_changed_event() const 240 { 241 return _valueChangedEvent; 242 } 243 virtual const sc_event & 244 posedge_event() const 245 { 246 return _posedgeEvent; 247 } 248 virtual const sc_event & 249 negedge_event() const 250 { 251 return _negedgeEvent; 252 } 253 254 virtual bool 255 event() const 256 { 257 return _changeStamp == ::sc_gem5::getChangeStamp(); 258 } 259 virtual bool 260 posedge() const 261 { 262 return _posStamp == ::sc_gem5::getChangeStamp(); 263 } 264 virtual bool 265 negedge() const 266 { 267 return _negStamp == ::sc_gem5::getChangeStamp(); 268 } 269 270 virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; } 271 virtual void 272 dump(std::ostream &os=std::cout) const 273 { 274 os << " name = " << name() << ::std::endl; 275 os << " value = " << m_cur_val << ::std::endl; 276 os << "new value = " << m_new_val << ::std::endl; 277 } 278 virtual const char *kind() const { return "sc_signal"; } 279 280 protected: 281 virtual void 282 update() 283 { 284 if (m_new_val == m_cur_val) 285 return; 286 287 m_cur_val = m_new_val; 288 _signalChange(); 289 if (m_cur_val) { 290 _posStamp = ::sc_gem5::getChangeStamp(); 291 _posedgeEvent.notify(SC_ZERO_TIME); 292 } else { 293 _negStamp = ::sc_gem5::getChangeStamp(); 294 _negedgeEvent.notify(SC_ZERO_TIME); 295 } 296 } 297 298 void 299 _signalChange() 300 { 301 _changeStamp = ::sc_gem5::getChangeStamp(); 302 _valueChangedEvent.notify(SC_ZERO_TIME); 303 } 304 305 bool m_cur_val; 306 bool m_new_val; 307 308 private: 309 sc_event _valueChangedEvent; 310 sc_event _posedgeEvent; 311 sc_event _negedgeEvent; 312 313 uint64_t _changeStamp; 314 uint64_t _posStamp; 315 uint64_t _negStamp; 316 317 // Disabled 318 sc_signal(const sc_signal<bool, WRITER_POLICY> &) : 319 sc_signal_inout_if<bool>(), sc_prim_channel("") 320 {} 321}; 322 323template <sc_writer_policy WRITER_POLICY> 324class sc_signal<sc_dt::sc_logic, WRITER_POLICY> : 325 public sc_signal_inout_if<sc_dt::sc_logic>, public sc_prim_channel 326{ 327 public: 328 sc_signal() : sc_signal_inout_if<sc_dt::sc_logic>(), 329 sc_prim_channel(sc_gen_unique_name("signal")), 330 m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()), 331 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 332 {} 333 explicit sc_signal(const char *name) : 334 sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name), 335 m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()), 336 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 337 {} 338 explicit sc_signal(const char *name, 339 const sc_dt::sc_logic &initial_value) : 340 sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name), 341 m_cur_val(initial_value), m_new_val(initial_value), 342 _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL) 343 {} 344 virtual ~sc_signal() {} 345 346 virtual void 347 register_port(sc_port_base &, const char *) 348 { 349 sc_channel_warn_unimpl(__PRETTY_FUNCTION__); 350 } 351 352 virtual const sc_dt::sc_logic &read() const { return m_cur_val; } 353 operator const sc_dt::sc_logic &() const { return read(); } 354 355 virtual sc_writer_policy 356 get_writer_policy() const 357 { 358 return WRITER_POLICY; 359 } 360 virtual void 361 write(const sc_dt::sc_logic &l) 362 { 363 m_new_val = l; 364 bool changed = !(m_cur_val == m_new_val); 365 //TODO check whether this write follows the write policy. 366 if (changed) 367 request_update(); 368 } 369 sc_signal<sc_dt::sc_logic, WRITER_POLICY> & 370 operator = (const sc_dt::sc_logic &l) 371 { 372 write(l); 373 return *this; 374 } 375 sc_signal<sc_dt::sc_logic, WRITER_POLICY> & 376 operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &s) 377 { 378 write(s.read()); 379 return *this; 380 } 381 382 virtual const sc_event & 383 default_event() const 384 { 385 return value_changed_event(); 386 } 387 388 virtual const sc_event & 389 value_changed_event() const 390 { 391 return _valueChangedEvent; 392 } 393 virtual const sc_event & 394 posedge_event() const 395 { 396 return _posedgeEvent; 397 } 398 virtual const sc_event & 399 negedge_event() const 400 { 401 return _negedgeEvent; 402 } 403 404 virtual bool 405 event() const 406 { 407 return _changeStamp == ::sc_gem5::getChangeStamp(); 408 } 409 virtual bool 410 posedge() const 411 { 412 return _posStamp == ::sc_gem5::getChangeStamp(); 413 } 414 virtual bool 415 negedge() const 416 { 417 return _negStamp == ::sc_gem5::getChangeStamp(); 418 } 419 420 virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; } 421 virtual void 422 dump(std::ostream &os=std::cout) const 423 { 424 os << " name = " << name() << ::std::endl; 425 os << " value = " << m_cur_val << ::std::endl; 426 os << "new value = " << m_new_val << ::std::endl; 427 } 428 virtual const char *kind() const { return "sc_signal"; } 429 430 protected: 431 virtual void 432 update() 433 { 434 if (m_new_val == m_cur_val) 435 return; 436 437 m_cur_val = m_new_val; 438 _signalChange(); 439 if (m_cur_val == sc_dt::SC_LOGIC_1) { 440 _posStamp = ::sc_gem5::getChangeStamp(); 441 _posedgeEvent.notify(SC_ZERO_TIME); 442 } else if (m_cur_val == sc_dt::SC_LOGIC_0) { 443 _negStamp = ::sc_gem5::getChangeStamp(); 444 _negedgeEvent.notify(SC_ZERO_TIME); 445 } 446 } 447 448 void 449 _signalChange() 450 { 451 _changeStamp = ::sc_gem5::getChangeStamp(); 452 _valueChangedEvent.notify(SC_ZERO_TIME); 453 } 454 455 sc_dt::sc_logic m_cur_val; 456 sc_dt::sc_logic m_new_val; 457 458 private: 459 sc_event _valueChangedEvent; 460 sc_event _posedgeEvent; 461 sc_event _negedgeEvent; 462 463 uint64_t _changeStamp; 464 uint64_t _posStamp; 465 uint64_t _negStamp; 466 467 // Disabled 468 sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &) : 469 sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel("") 470 {} 471}; 472 473} // namespace sc_core 474 475#endif //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__ 476