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.cpp -- 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 30#include "sysc/communication/sc_communication_ids.h" 31#include "sysc/utils/sc_utils_ids.h" 32#include "sysc/communication/sc_signal.h" 33#include "sysc/datatypes/int/sc_signed.h" 34#include "sysc/datatypes/int/sc_unsigned.h" 35#include "sysc/datatypes/bit/sc_lv_base.h" 36#include "sysc/kernel/sc_reset.h" 37 38#include <sstream> 39 40using sc_dt::sc_lv_base; 41using sc_dt::sc_signed; 42using sc_dt::sc_unsigned; 43using sc_dt::int64; 44using sc_dt::uint64; 45 46namespace sc_core { 47 48// to avoid code bloat in sc_signal<T> 49 50void 51sc_signal_invalid_writer( sc_object* target, sc_object* first_writer, 52 sc_object* second_writer, bool check_delta ) 53{ 54 if ( second_writer ) 55 { 56 std::stringstream msg; 57 58 msg 59 << "\n signal " 60 "`" << target->name() << "' " 61 "(" << target->kind() << ")" 62 << "\n first driver " 63 "`" << first_writer->name() << "' " 64 " (" << first_writer->kind() << ")" 65 << "\n second driver " 66 "`" << second_writer->name() << "' " 67 "(" << second_writer->kind() << ")"; 68 69 if( check_delta ) 70 { 71 msg << "\n first conflicting write in delta cycle " 72 << sc_delta_count(); 73 } 74 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, 75 msg.str().c_str() ); 76 } 77} 78 79bool 80sc_writer_policy_check_port:: 81 check_port( sc_object* target, sc_port_base * port_, bool is_output ) 82{ 83 if ( is_output && sc_get_curr_simcontext()->write_check() ) 84 { 85 // an out or inout port; only one can be connected 86 if( m_output != 0) { 87 sc_signal_invalid_writer( target, m_output, port_, false ); 88 return false; 89 } else { 90 m_output = port_; 91 } 92 } 93 return true; 94} 95 96void sc_deprecated_get_data_ref() 97{ 98 static bool warn_get_data_ref_deprecated=true; 99 if ( warn_get_data_ref_deprecated ) 100 { 101 warn_get_data_ref_deprecated=false; 102 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 103 "get_data_ref() is deprecated, use read() instead" ); 104 } 105} 106 107void sc_deprecated_get_new_value() 108{ 109 static bool warn_new_value=true; 110 if ( warn_new_value ) 111 { 112 warn_new_value=false; 113 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 114 "sc_signal<T>::get_new_value() is deprecated"); 115 } 116} 117 118void sc_deprecated_trace() 119{ 120 static bool warn_trace_deprecated=true; 121 if ( warn_trace_deprecated ) 122 { 123 warn_trace_deprecated=false; 124 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 125 "sc_signal<T>::trace() is deprecated"); 126 } 127} 128 129sc_event* 130sc_lazy_kernel_event( sc_event** ev, const char* name ) 131{ 132 if ( !*ev ) { 133 std::string kernel_name = SC_KERNEL_EVENT_PREFIX "_"; 134 kernel_name.append( name ); 135 *ev = new sc_event( kernel_name.c_str() ); 136 } 137 return *ev; 138 139} 140 141// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 142 143template< sc_writer_policy POL > 144void 145sc_signal<bool,POL>::register_port( sc_port_base& port_, 146 const char* if_typename_ ) 147{ 148 bool is_output = std::string( if_typename_ ) == typeid(if_type).name(); 149 if( !policy_type::check_port( this, &port_, is_output ) ) 150 ((void)0); // fallback? error has been suppressed ... 151} 152 153 154// write the new value 155 156template< sc_writer_policy POL > 157void 158sc_signal<bool,POL>::write( const bool& value_ ) 159{ 160 bool value_changed = !( m_cur_val == value_ ); 161 if ( !policy_type::check_write(this, value_changed) ) 162 return; 163 m_new_val = value_; 164 if( value_changed ) { 165 request_update(); 166 } 167} 168 169template< sc_writer_policy POL > 170inline 171void 172sc_signal<bool,POL>::print( ::std::ostream& os ) const 173{ 174 os << m_cur_val; 175} 176 177template< sc_writer_policy POL > 178void 179sc_signal<bool,POL>::dump( ::std::ostream& os ) const 180{ 181 os << " name = " << name() << ::std::endl; 182 os << " value = " << m_cur_val << ::std::endl; 183 os << "new value = " << m_new_val << ::std::endl; 184} 185 186 187template< sc_writer_policy POL > 188void 189sc_signal<bool,POL>::update() 190{ 191 policy_type::update(); 192 if( !( m_new_val == m_cur_val ) ) { 193 do_update(); 194 } 195} 196 197template< sc_writer_policy POL > 198void 199sc_signal<bool,POL>::do_update() 200{ 201 // order of execution below is important, the notify_processes() call 202 // must come after the update of m_cur_val for things to work properly! 203 204 m_cur_val = m_new_val; 205 206 if ( m_reset_p ) m_reset_p->notify_processes(); 207 208 if ( m_change_event_p ) m_change_event_p->notify_next_delta(); 209 210 sc_event* event_p = this->m_cur_val 211 ? m_posedge_event_p : m_negedge_event_p; 212 if ( event_p ) event_p->notify_next_delta(); 213 214 m_change_stamp = simcontext()->change_stamp(); 215} 216 217// (edge) event methods 218 219template< sc_writer_policy POL > 220const sc_event& 221sc_signal<bool,POL>::value_changed_event() const 222{ 223 return *sc_lazy_kernel_event(&m_change_event_p,"value_changed_event"); 224} 225 226template< sc_writer_policy POL > 227const sc_event& 228sc_signal<bool,POL>::posedge_event() const 229{ 230 return *sc_lazy_kernel_event(&m_posedge_event_p,"posedge_event"); 231} 232 233template< sc_writer_policy POL > 234const sc_event& 235sc_signal<bool,POL>::negedge_event() const 236{ 237 return *sc_lazy_kernel_event(&m_negedge_event_p,"negedge_event"); 238} 239 240 241// reset support: 242 243template< sc_writer_policy POL > 244sc_reset* 245sc_signal<bool,POL>::is_reset() const 246{ 247 sc_reset* result_p; 248 if ( !m_reset_p ) m_reset_p = new sc_reset( this ); 249 result_p = m_reset_p; 250 return result_p; 251} 252 253// destructor 254 255template< sc_writer_policy POL > 256sc_signal<bool,POL>::~sc_signal() 257{ 258 delete m_change_event_p; 259 delete m_negedge_event_p; 260 delete m_posedge_event_p; 261 delete m_reset_p; 262} 263 264// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 265 266template< sc_writer_policy POL > 267void 268sc_signal<sc_dt::sc_logic,POL>::register_port( sc_port_base& port_, 269 const char* if_typename_ ) 270{ 271 bool is_output = std::string( if_typename_ ) == typeid(if_type).name(); 272 if( !policy_type::check_port( this, &port_, is_output ) ) 273 ((void)0); // fallback? error has been suppressed ... 274} 275 276 277// write the new value 278 279template< sc_writer_policy POL > 280inline 281void 282sc_signal<sc_dt::sc_logic,POL>::write( const sc_dt::sc_logic& value_ ) 283{ 284 bool value_changed = !( m_cur_val == value_ ); 285 if ( !policy_type::check_write(this, value_changed) ) 286 return; 287 288 m_new_val = value_; 289 if( value_changed ) { 290 request_update(); 291 } 292} 293 294template< sc_writer_policy POL > 295inline 296void 297sc_signal<sc_dt::sc_logic,POL>::print( ::std::ostream& os ) const 298{ 299 os << m_cur_val; 300} 301 302template< sc_writer_policy POL > 303void 304sc_signal<sc_dt::sc_logic,POL>::dump( ::std::ostream& os ) const 305{ 306 os << " name = " << name() << ::std::endl; 307 os << " value = " << m_cur_val << ::std::endl; 308 os << "new value = " << m_new_val << ::std::endl; 309} 310 311 312template< sc_writer_policy POL > 313void 314sc_signal<sc_dt::sc_logic,POL>::update() 315{ 316 policy_type::update(); 317 if( !( m_new_val == m_cur_val ) ) { 318 do_update(); 319 } 320} 321 322template< sc_writer_policy POL > 323void 324sc_signal<sc_dt::sc_logic,POL>::do_update() 325{ 326 m_cur_val = m_new_val; 327 328 if ( m_change_event_p ) m_change_event_p->notify_next_delta(); 329 330 if( m_posedge_event_p && (this->m_cur_val == sc_dt::SC_LOGIC_1) ) { 331 m_posedge_event_p->notify_next_delta(); 332 } 333 else if( m_negedge_event_p && (this->m_cur_val == sc_dt::SC_LOGIC_0) ) { 334 m_negedge_event_p->notify_next_delta(); 335 } 336 337 m_change_stamp = simcontext()->change_stamp(); 338} 339 340// (edge) event methods 341 342template< sc_writer_policy POL > 343const sc_event& 344sc_signal<sc_dt::sc_logic,POL>::value_changed_event() const 345{ 346 return *sc_lazy_kernel_event(&m_change_event_p,"value_changed_event"); 347} 348 349template< sc_writer_policy POL > 350const sc_event& 351sc_signal<sc_dt::sc_logic,POL>::posedge_event() const 352{ 353 return *sc_lazy_kernel_event(&m_posedge_event_p,"posedge_event"); 354} 355 356template< sc_writer_policy POL > 357const sc_event& 358sc_signal<sc_dt::sc_logic,POL>::negedge_event() const 359{ 360 return *sc_lazy_kernel_event(&m_negedge_event_p,"negedge_event"); 361} 362 363 364// template instantiations for writer policies 365 366template class sc_signal<bool,SC_ONE_WRITER>; 367template class sc_signal<bool,SC_MANY_WRITERS>; 368template class sc_signal<bool,SC_UNCHECKED_WRITERS>; 369 370template class sc_signal<sc_dt::sc_logic,SC_ONE_WRITER>; 371template class sc_signal<sc_dt::sc_logic,SC_MANY_WRITERS>; 372template class sc_signal<sc_dt::sc_logic,SC_UNCHECKED_WRITERS>; 373 374} // namespace sc_core 375 376/* 377$Log: sc_signal.cpp,v $ 378Revision 1.9 2011/08/26 20:45:42 acg 379 Andy Goodrich: moved the modification log to the end of the file to 380 eliminate source line number skew when check-ins are done. 381 382Revision 1.8 2011/02/18 20:23:45 acg 383 Andy Goodrich: Copyright update. 384 385Revision 1.7 2011/02/18 20:08:14 acg 386 Philipp A. Hartmann: addition of include for sstream for MSVC. 387 388Revision 1.6 2011/01/25 20:50:37 acg 389 Andy Goodrich: changes for IEEE 1666 2011. 390 391Revision 1.5 2010/12/07 19:50:36 acg 392 Andy Goodrich: addition of writer policies, courtesy of Philipp Hartmann. 393 394Revision 1.3 2007/04/09 21:59:49 acg 395 Andy Goodrich: fixed multiple write notification bug where writes 396 done outside the simulator were being treated as multiple writes. 397 398Revision 1.2 2007/04/02 17:24:01 acg 399 Andy Goodrich: added check for null writer pointers in sc_signal invalid 400 writer method. 401 402Revision 1.1.1.1 2006/12/15 20:20:04 acg 403SystemC 2.3 404 405Revision 1.7 2006/04/11 23:11:57 acg 406 Andy Goodrich: Changes for reset support that only includes 407 sc_cthread_process instances. 408 409Revision 1.6 2006/03/13 20:19:44 acg 410 Andy Goodrich: changed sc_event instances into pointers to sc_event instances 411 that are allocated as needed. This saves considerable storage for large 412 numbers of signals, etc. 413 414Revision 1.5 2006/01/25 00:31:11 acg 415 Andy Goodrich: Changed over to use a standard message id of 416 SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. 417 418Revision 1.4 2006/01/24 20:46:32 acg 419Andy Goodrich: changes to eliminate use of deprecated features. For instance, 420using notify(SC_ZERO_TIME) in place of notify_delayed(). 421 422Revision 1.3 2006/01/18 21:42:26 acg 423Andy Goodrich: Changes for check writer support, and tightening up sc_clock 424port usage. 425 426Revision 1.2 2006/01/03 23:18:26 acg 427Changed copyright to include 2006. 428 429Revision 1.1.1.1 2005/12/19 23:16:43 acg 430First check in of SystemC 2.1 into its own archive. 431 432Revision 1.14 2005/09/15 23:01:51 acg 433Added std:: prefix to appropriate methods and types to get around 434issues with the Edison Front End. 435 436Revision 1.13 2005/05/08 19:04:06 acg 437Fix bug in concat_set(int64,off). Other changes from 2.1 examples usage. 438 439Revision 1.12 2005/04/04 00:15:51 acg 440Changes for directory name change to sys from systemc. 441Changes for sc_string going to std::string. 442Changes for sc_pvector going to std::vector. 443Changes for reference pools for bit and part selections. 444Changes for const sc_concatref support. 445 446Revision 1.10 2005/03/21 22:31:32 acg 447Changes to sc_core namespace. 448 449Revision 1.9 2004/09/27 21:02:54 acg 450Andy Goodrich - Forte Design Systems, Inc. 451 - Added a $Log comment so that CVS checkin comments will appear in 452 checked out source. 453 454*/ 455 456// Taf! 457