1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 sc_signal.h -- The sc_signal<T> primitive channel class. 23 24 Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 25 26 CHANGE LOG IS AT THE END OF THE FILE 27 *****************************************************************************/ 28 29#ifndef SC_SIGNAL_H 30#define SC_SIGNAL_H 31 32#include "sysc/communication/sc_port.h" 33#include "sysc/communication/sc_prim_channel.h" 34#include "sysc/communication/sc_signal_ifs.h" 35#include "sysc/communication/sc_writer_policy.h" 36#include "sysc/kernel/sc_event.h" 37#include "sysc/kernel/sc_process.h" 38#include "sysc/kernel/sc_simcontext.h" 39#include "sysc/datatypes/bit/sc_logic.h" 40#include "sysc/tracing/sc_trace.h" 41#include <typeinfo> 42 43namespace sc_core { 44 45// to avoid code bloat in sc_signal<T> 46 47extern void sc_deprecated_get_data_ref(); 48extern void sc_deprecated_get_new_value(); 49extern void sc_deprecated_trace(); 50extern sc_event * sc_lazy_kernel_event( sc_event**, const char* name ); 51 52inline 53bool 54sc_writer_policy_check_write::check_write( sc_object* target, bool ) 55{ 56 sc_object* writer_p = sc_get_curr_simcontext()->get_current_writer(); 57 if( SC_UNLIKELY_(m_writer_p == 0) ) { 58 m_writer_p = writer_p; 59 } else if( SC_UNLIKELY_(m_writer_p != writer_p && writer_p != 0) ) { 60 sc_signal_invalid_writer( target, m_writer_p, writer_p, m_check_delta ); 61 // error has been suppressed, ignore check as well 62 // return false; 63 } 64 return true; 65} 66 67// ---------------------------------------------------------------------------- 68// CLASS : sc_signal<T> 69// 70// The sc_signal<T> primitive channel class. 71// ---------------------------------------------------------------------------- 72 73template< class T, sc_writer_policy POL /* = SC_DEFAULT_WRITER_POLICY */ > 74class sc_signal 75 : public sc_signal_inout_if<T> 76 , public sc_prim_channel 77 , protected sc_writer_policy_check<POL> 78{ 79protected: 80 typedef sc_signal_inout_if<T> if_type; 81 typedef sc_signal<T,POL> this_type; 82 typedef sc_writer_policy_check<POL> policy_type; 83 84public: // constructors and destructor: 85 86 sc_signal() 87 : sc_prim_channel( sc_gen_unique_name( "signal" ) ), 88 m_change_event_p( 0 ), m_cur_val( T() ), 89 m_change_stamp( ~sc_dt::UINT64_ONE ), m_new_val( T() ) 90 {} 91 92 explicit sc_signal( const char* name_) 93 : sc_prim_channel( name_ ), 94 m_change_event_p( 0 ), m_cur_val( T() ), 95 m_change_stamp( ~sc_dt::UINT64_ONE ), m_new_val( T() ) 96 {} 97 98 sc_signal( const char* name_, const T& initial_value_ ) 99 : sc_prim_channel( name_ ) 100 , m_change_event_p( 0 ) 101 , m_cur_val( initial_value_ ) 102 , m_change_stamp( ~sc_dt::UINT64_ONE ) 103 , m_new_val( initial_value_ ) 104 {} 105 106 virtual ~sc_signal() 107 { 108 delete m_change_event_p; 109 } 110 111 112 // interface methods 113 114 virtual void register_port( sc_port_base&, const char* ); 115 116 virtual sc_writer_policy get_writer_policy() const 117 { return POL; } 118 119 // get the default event 120 virtual const sc_event& default_event() const 121 { return value_changed_event(); } 122 123 // get the value changed event 124 virtual const sc_event& value_changed_event() const 125 { 126 return *sc_lazy_kernel_event( &m_change_event_p 127 , "value_changed_event"); 128 } 129 130 131 // read the current value 132 virtual const T& read() const 133 { return m_cur_val; } 134 135 // get a reference to the current value (for tracing) 136 virtual const T& get_data_ref() const 137 { sc_deprecated_get_data_ref(); return m_cur_val; } 138 139 140 // was there an event? 141 virtual bool event() const 142 { return simcontext()->event_occurred(m_change_stamp); } 143 144 // write the new value 145 virtual void write( const T& ); 146 147 148 // other methods 149 150 operator const T& () const 151 { return read(); } 152 153 154 this_type& operator = ( const T& a ) 155 { write( a ); return *this; } 156 157 this_type& operator = ( const sc_signal_in_if<T>& a ) 158 { write( a.read() ); return *this; } 159 160 this_type& operator = ( const this_type& a ) 161 { write( a.read() ); return *this; } 162 163 164 const T& get_new_value() const 165 { sc_deprecated_get_new_value(); return m_new_val; } 166 167 168 void trace( sc_trace_file* tf ) const 169 { 170 sc_deprecated_trace(); 171# ifdef DEBUG_SYSTEMC 172 sc_trace( tf, read(), name() ); 173# else 174 if ( tf ) {} 175# endif 176 } 177 178 179 virtual void print( ::std::ostream& = ::std::cout ) const; 180 virtual void dump( ::std::ostream& = ::std::cout ) const; 181 182 virtual const char* kind() const 183 { return "sc_signal"; } 184 185protected: 186 187 virtual void update(); 188 void do_update(); 189 190protected: 191 192 mutable sc_event* m_change_event_p; 193 T m_cur_val; 194 sc_dt::uint64 m_change_stamp; // delta of last event 195 T m_new_val; 196 197private: 198 199 // disabled 200 sc_signal( const this_type& ); 201}; 202 203 204// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 205 206 207template< class T, sc_writer_policy POL > 208inline 209void 210sc_signal<T,POL>::register_port( sc_port_base& port_ 211 , const char* if_typename_ ) 212{ 213 214 bool is_output = std::string( if_typename_ ) == typeid(if_type).name(); 215 if( !policy_type::check_port( this, &port_, is_output ) ) 216 ((void)0); // fallback? error has been suppressed ... 217} 218 219 220// write the new value 221 222template< class T, sc_writer_policy POL > 223inline 224void 225sc_signal<T,POL>::write( const T& value_ ) 226{ 227 bool value_changed = !( m_cur_val == value_ ); 228 if ( !policy_type::check_write(this, value_changed) ) 229 return; 230 231 m_new_val = value_; 232 if( value_changed ) { 233 request_update(); 234 } 235} 236 237 238template< class T, sc_writer_policy POL > 239inline 240void 241sc_signal<T,POL>::print( ::std::ostream& os ) const 242{ 243 os << m_cur_val; 244} 245 246template< class T, sc_writer_policy POL > 247void 248sc_signal<T,POL>::dump( ::std::ostream& os ) const 249{ 250 os << " name = " << name() << ::std::endl; 251 os << " value = " << m_cur_val << ::std::endl; 252 os << "new value = " << m_new_val << ::std::endl; 253} 254 255 256template< class T, sc_writer_policy POL > 257void 258sc_signal<T,POL>::update() 259{ 260 policy_type::update(); 261 if( !( m_new_val == m_cur_val ) ) { 262 do_update(); 263 } 264} 265 266template< class T, sc_writer_policy POL > 267void 268sc_signal<T,POL>::do_update() 269{ 270 m_cur_val = m_new_val; 271 if ( m_change_event_p ) m_change_event_p->notify_next_delta(); 272 m_change_stamp = simcontext()->change_stamp(); 273} 274 275// ---------------------------------------------------------------------------- 276// CLASS : sc_signal<bool> 277// 278// Specialization of sc_signal<T> for type bool. 279// ---------------------------------------------------------------------------- 280 281class sc_reset; 282 283template< sc_writer_policy POL > 284class sc_signal<bool,POL> 285 : public sc_signal_inout_if<bool> 286 , public sc_prim_channel 287 , protected sc_writer_policy_check<POL> 288{ 289protected: 290 typedef sc_signal_inout_if<bool> if_type; 291 typedef sc_signal<bool,POL> this_type; 292 typedef sc_writer_policy_check<POL> policy_type; 293 294public: // constructors and destructor: 295 296 sc_signal() 297 : sc_prim_channel( sc_gen_unique_name( "signal" ) ), 298 m_change_event_p( 0 ), 299 m_cur_val( false ), 300 m_change_stamp( ~sc_dt::UINT64_ONE ), 301 m_negedge_event_p( 0 ), 302 m_new_val( false ), 303 m_posedge_event_p( 0 ), 304 m_reset_p( 0 ) 305 {} 306 307 explicit sc_signal( const char* name_ ) 308 : sc_prim_channel( name_ ), 309 m_change_event_p( 0 ), 310 m_cur_val( false ), 311 m_change_stamp( ~sc_dt::UINT64_ONE ), 312 m_negedge_event_p( 0 ), 313 m_new_val( false ), 314 m_posedge_event_p( 0 ), 315 m_reset_p( 0 ) 316 {} 317 318 sc_signal( const char* name_, bool initial_value_ ) 319 : sc_prim_channel( name_ ) 320 , m_change_event_p( 0 ) 321 , m_cur_val( initial_value_ ) 322 , m_change_stamp( ~sc_dt::UINT64_ONE ) 323 , m_negedge_event_p( 0 ) 324 , m_new_val( initial_value_ ) 325 , m_posedge_event_p( 0 ) 326 , m_reset_p( 0 ) 327 {} 328 329 virtual ~sc_signal(); 330 331 332 // interface methods 333 334 virtual void register_port( sc_port_base&, const char* ); 335 336 virtual sc_writer_policy get_writer_policy() const 337 { return POL; } 338 339 // get the default event 340 virtual const sc_event& default_event() const 341 { return value_changed_event(); } 342 343 // get the value changed event 344 virtual const sc_event& value_changed_event() const; 345 346 // get the positive edge event 347 virtual const sc_event& posedge_event() const; 348 349 // get the negative edge event 350 virtual const sc_event& negedge_event() const; 351 352 353 // read the current value 354 virtual const bool& read() const 355 { return m_cur_val; } 356 357 // get a reference to the current value (for tracing) 358 virtual const bool& get_data_ref() const 359 { sc_deprecated_get_data_ref(); return m_cur_val; } 360 361 362 // was there a value changed event? 363 virtual bool event() const 364 { return simcontext()->event_occurred(m_change_stamp); } 365 366 // was there a positive edge event? 367 virtual bool posedge() const 368 { return ( event() && m_cur_val ); } 369 370 // was there a negative edge event? 371 virtual bool negedge() const 372 { return ( event() && ! m_cur_val ); } 373 374 // write the new value 375 virtual void write( const bool& ); 376 377 // other methods 378 379 operator const bool& () const 380 { return read(); } 381 382 383 this_type& operator = ( const bool& a ) 384 { write( a ); return *this; } 385 386 this_type& operator = ( const sc_signal_in_if<bool>& a ) 387 { write( a.read() ); return *this; } 388 389 this_type& operator = ( const this_type& a ) 390 { write( a.read() ); return *this; } 391 392 393 const bool& get_new_value() const 394 { sc_deprecated_get_new_value(); return m_new_val; } 395 396 397 void trace( sc_trace_file* tf ) const 398 { 399 sc_deprecated_trace(); 400# ifdef DEBUG_SYSTEMC 401 sc_trace( tf, read(), name() ); 402# else 403 if ( tf ) {} 404# endif 405 } 406 407 408 virtual void print( ::std::ostream& = ::std::cout ) const; 409 virtual void dump( ::std::ostream& = ::std::cout ) const; 410 411 virtual const char* kind() const 412 { return "sc_signal"; } 413 414protected: 415 416 virtual void update(); 417 void do_update(); 418 419 virtual bool is_clock() const { return false; } 420 421protected: 422 mutable sc_event* m_change_event_p; // value change event if present. 423 bool m_cur_val; // current value of object. 424 sc_dt::uint64 m_change_stamp; // delta of last event 425 mutable sc_event* m_negedge_event_p; // negative edge event if present. 426 bool m_new_val; // next value of object. 427 mutable sc_event* m_posedge_event_p; // positive edge event if present. 428 mutable sc_reset* m_reset_p; // reset mechanism if present. 429 430private: 431 432 // reset creation 433 virtual sc_reset* is_reset() const; 434 435 // disabled 436 sc_signal( const this_type& ); 437}; 438 439 440// ---------------------------------------------------------------------------- 441// CLASS : sc_signal<sc_dt::sc_logic> 442// 443// Specialization of sc_signal<T> for type sc_dt::sc_logic. 444// ---------------------------------------------------------------------------- 445 446template< sc_writer_policy POL > 447class sc_signal<sc_dt::sc_logic,POL> 448 : public sc_signal_inout_if<sc_dt::sc_logic> 449 , public sc_prim_channel 450 , protected sc_writer_policy_check<POL> 451{ 452protected: 453 typedef sc_signal_inout_if<sc_dt::sc_logic> if_type; 454 typedef sc_signal<sc_dt::sc_logic,POL> this_type; 455 typedef sc_writer_policy_check<POL> policy_type; 456 457public: // constructors and destructor: 458 459 sc_signal() 460 : sc_prim_channel( sc_gen_unique_name( "signal" ) ), 461 m_change_event_p( 0 ), 462 m_cur_val(), 463 m_change_stamp( ~sc_dt::UINT64_ONE ), 464 m_negedge_event_p( 0 ), 465 m_new_val(), 466 m_posedge_event_p( 0 ) 467 {} 468 469 explicit sc_signal( const char* name_ ) 470 : sc_prim_channel( name_ ), 471 m_change_event_p( 0 ), 472 m_cur_val(), 473 m_change_stamp( ~sc_dt::UINT64_ONE ), 474 m_negedge_event_p( 0 ), 475 m_new_val(), 476 m_posedge_event_p( 0 ) 477 {} 478 479 sc_signal( const char* name_, sc_dt::sc_logic initial_value_ ) 480 : sc_prim_channel( name_ ) 481 , m_change_event_p( 0 ) 482 , m_cur_val( initial_value_ ) 483 , m_change_stamp( ~sc_dt::UINT64_ONE ) 484 , m_negedge_event_p( 0 ) 485 , m_new_val( initial_value_ ) 486 , m_posedge_event_p( 0 ) 487 {} 488 489 virtual ~sc_signal() 490 { 491 delete m_change_event_p; 492 delete m_negedge_event_p; 493 delete m_posedge_event_p; 494 } 495 496 497 // interface methods 498 499 virtual void register_port( sc_port_base&, const char* ); 500 501 virtual sc_writer_policy get_writer_policy() const 502 { return POL; } 503 504 // get the default event 505 virtual const sc_event& default_event() const 506 { return value_changed_event(); } 507 508 // get the value changed event 509 virtual const sc_event& value_changed_event() const; 510 511 // get the positive edge event 512 virtual const sc_event& posedge_event() const; 513 514 // get the negative edge event 515 virtual const sc_event& negedge_event() const; 516 517 518 // read the current value 519 virtual const sc_dt::sc_logic& read() const 520 { return m_cur_val; } 521 522 // get a reference to the current value (for tracing) 523 virtual const sc_dt::sc_logic& get_data_ref() const 524 { sc_deprecated_get_data_ref(); return m_cur_val; } 525 526 527 // was there an event? 528 virtual bool event() const 529 { return simcontext()->event_occurred(m_change_stamp); } 530 531 // was there a positive edge event? 532 virtual bool posedge() const 533 { return ( event() && m_cur_val == sc_dt::SC_LOGIC_1 ); } 534 535 // was there a negative edge event? 536 virtual bool negedge() const 537 { return ( event() && m_cur_val == sc_dt::SC_LOGIC_0 ); } 538 539 540 // write the new value 541 virtual void write( const sc_dt::sc_logic& ); 542 543 544 // other methods 545 546 operator const sc_dt::sc_logic& () const 547 { return read(); } 548 549 550 this_type& operator = ( const sc_dt::sc_logic& a ) 551 { write( a ); return *this; } 552 553 this_type& operator = ( const sc_signal_in_if<sc_dt::sc_logic>& a ) 554 { write( a.read() ); return *this; } 555 556 this_type& operator = (const this_type& a) 557 { write( a.read() ); return *this; } 558 559 560 const sc_dt::sc_logic& get_new_value() const 561 { sc_deprecated_get_new_value(); return m_new_val; } 562 563 564 void trace( sc_trace_file* tf ) const 565 { 566 sc_deprecated_trace(); 567# ifdef DEBUG_SYSTEMC 568 sc_trace( tf, read(), name() ); 569# else 570 if ( tf ) {} 571# endif 572 } 573 574 virtual void print( ::std::ostream& = ::std::cout ) const; 575 virtual void dump( ::std::ostream& = ::std::cout ) const; 576 577 virtual const char* kind() const 578 { return "sc_signal"; } 579 580protected: 581 582 virtual void update(); 583 void do_update(); 584 585protected: 586 587 mutable sc_event* m_change_event_p; // value change event if present. 588 sc_dt::sc_logic m_cur_val; // current value of object. 589 sc_dt::uint64 m_change_stamp; // delta of last event 590 mutable sc_event* m_negedge_event_p; // negative edge event if present. 591 sc_dt::sc_logic m_new_val; // next value of object. 592 mutable sc_event* m_posedge_event_p; // positive edge event if present. 593 594private: 595 596 // disabled 597 sc_signal( const this_type& ); 598}; 599 600// ---------------------------------------------------------------------------- 601 602template< typename T, sc_writer_policy POL > 603inline 604::std::ostream& 605operator << ( ::std::ostream& os, const sc_signal<T,POL>& a ) 606{ 607 return ( os << a.read() ); 608} 609 610 611 612} // namespace sc_core 613 614/***************************************************************************** 615 616 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 617 changes you are making here. 618 619 Name, Affiliation, Date: 620 Description of Modification: 621 622 *****************************************************************************/ 623//$Log: sc_signal.h,v $ 624//Revision 1.16 2011/08/26 20:45:42 acg 625// Andy Goodrich: moved the modification log to the end of the file to 626// eliminate source line number skew when check-ins are done. 627// 628//Revision 1.15 2011/08/15 16:43:24 acg 629// Torsten Maehne: changes to remove unused argument warnings. 630// 631//Revision 1.14 2011/06/25 17:08:38 acg 632// Andy Goodrich: Jerome Cornet's changes to use libtool to build the 633// library. 634// 635//Revision 1.13 2011/04/13 02:59:09 acg 636// Andy Goodrich: made events internal to signals into kernel events. 637// 638//Revision 1.12 2011/04/08 18:22:46 acg 639// Philipp A. Hartmann: use the context of the primitive channel to get 640// the change stamp value. 641// 642//Revision 1.11 2011/04/05 20:48:09 acg 643// Andy Goodrich: changes to make sure that event(), posedge() and negedge() 644// only return true if the clock has not moved. 645// 646//Revision 1.10 2011/04/05 07:10:55 acg 647// Andy Goodrich: added line that I dropped in sc_signal<sc_dt::sc_logic>. 648// 649//Revision 1.9 2011/04/05 06:15:18 acg 650// Philipp A. Hartmann: sc_writer_policy: ignore no-ops in delta check. 651// 652//Revision 1.8 2011/03/23 16:17:22 acg 653// Andy Goodrich: hide the sc_events that are kernel related. 654// 655//Revision 1.7 2011/03/06 15:55:08 acg 656// Andy Goodrich: Changes for named events. 657// 658//Revision 1.6 2011/02/18 20:23:45 acg 659// Andy Goodrich: Copyright update. 660// 661//Revision 1.5 2011/02/07 19:16:50 acg 662// Andy Goodrich: changes for handling multiple writers. 663// 664//Revision 1.4 2011/01/25 20:50:37 acg 665// Andy Goodrich: changes for IEEE 1666 2011. 666// 667//Revision 1.3 2010/12/07 19:50:37 acg 668// Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. 669// 670//Revision 1.1.1.1 2006/12/15 20:20:04 acg 671//SystemC 2.3 672// 673//Revision 1.14 2006/05/08 17:52:47 acg 674// Andy Goodrich: 675// (1) added David Long's forward declarations for friend functions, 676// methods, and operators to keep the Microsoft compiler happy. 677// (2) Added delta_count() method to sc_prim_channel for use by 678// sc_signal so that the friend declaration in sc_simcontext.h 679// can be for a non-templated class (i.e., sc_prim_channel.) 680// 681//Revision 1.12 2006/04/11 23:11:57 acg 682// Andy Goodrich: Changes for reset support that only includes 683// sc_cthread_process instances. 684// 685//Revision 1.11 2006/03/13 20:19:44 acg 686// Andy Goodrich: changed sc_event instances into pointers to sc_event instances 687// that are allocated as needed. This saves considerable storage for large 688// numbers of signals, etc. 689// 690//Revision 1.10 2006/01/26 21:00:50 acg 691// Andy Goodrich: conversion to use sc_event::notify(SC_ZERO_TIME) instead of 692// sc_event::notify_delayed() 693// 694//Revision 1.9 2006/01/24 20:45:41 acg 695//Andy Goodrich: converted notify_delayed() calls into notify_next_delta() calls 696//to eliminate deprecation warnings. notify_next_delta() is an implemenation- 697//dependent method of sc_event. It is simpler than notify_delayed(), and should 698//speed up simulation speeds. 699// 700//Revision 1.8 2006/01/19 19:18:25 acg 701//Andy Goodrich: eliminated check_writer in favor of inline code within the 702//write() method since we always execute the check_writer code even when 703//check writing is turned off. 704// 705//Revision 1.7 2006/01/19 00:30:57 acg 706//Andy Goodrich: Yet another implementation for disabling write checks on 707//signals. This version uses an environment variable, SC_SIGNAL_WRITE_CHECK, 708//that when set to DISABLE will turn off write checking. 709// 710//Revision 1.6 2006/01/18 21:42:26 acg 711//Andy Goodrich: Changes for check writer support, and tightening up sc_clock 712//port usage. 713// 714//Revision 1.5 2006/01/13 20:41:59 acg 715//Andy Goodrich: Changes to add port registration to the things that are 716//checked when SC_NO_WRITE_CHECK is not defined. 717// 718//Revision 1.4 2006/01/13 18:47:20 acg 719//Reversed sense of multiwriter signal check. It now defaults to ON unless the 720//user defines SC_NO_WRITE_CHEK before inclusion of the file. 721// 722//Revision 1.3 2006/01/03 23:18:26 acg 723//Changed copyright to include 2006. 724// 725//Revision 1.2 2005/12/20 21:58:18 acg 726//Removed Makefile.in, changed the event() methods to use sc_simcontext::event_occurred. 727// 728//Revision 1.1.1.1 2005/12/19 23:16:43 acg 729//First check in of SystemC 2.1 into its own archive. 730// 731//Revision 1.19 2005/09/15 23:01:51 acg 732//Added std:: prefix to appropriate methods and types to get around 733//issues with the Edison Front End. 734// 735//Revision 1.18 2005/06/10 22:43:55 acg 736//Added CVS change log annotation. 737// 738 739#endif 740 741// Taf! 742