00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #include "sysc/kernel/sc_simcontext.h"
00075 #include "sysc/kernel/sc_module.h"
00076 #include "sysc/kernel/sc_method_process.h"
00077 #include "sysc/kernel/sc_thread_process.h"
00078 #include "sysc/communication/sc_communication_ids.h"
00079 #include "sysc/utils/sc_utils_ids.h"
00080 #include "sysc/communication/sc_event_finder.h"
00081 #include "sysc/communication/sc_port.h"
00082 #include "sysc/communication/sc_signal_ifs.h"
00083
00084 namespace sc_core {
00085
00086
00087
00088
00089
00090 struct sc_bind_elem
00091 {
00092
00093 sc_bind_elem();
00094 explicit sc_bind_elem( sc_interface* interface_ );
00095 explicit sc_bind_elem( sc_port_base* parent_ );
00096
00097 sc_interface* iface;
00098 sc_port_base* parent;
00099 };
00100
00101
00102
00103
00104
00105
00106 sc_bind_elem::sc_bind_elem()
00107 : iface( 0 ),
00108 parent( 0 )
00109 {}
00110
00111 sc_bind_elem::sc_bind_elem( sc_interface* interface_ )
00112 : iface( interface_ ),
00113 parent( 0 )
00114 {}
00115
00116 sc_bind_elem::sc_bind_elem( sc_port_base* parent_ )
00117 : iface( 0 ),
00118 parent( parent_ )
00119 {}
00120
00121
00122
00123
00124
00125
00126 struct sc_bind_ef
00127 {
00128
00129 sc_bind_ef( sc_process_b* , sc_event_finder* );
00130
00131
00132 ~sc_bind_ef();
00133
00134 sc_process_b* handle;
00135 sc_event_finder* event_finder;
00136 };
00137
00138
00139
00140
00141
00142
00143 sc_bind_ef::sc_bind_ef( sc_process_b* handle_,
00144 sc_event_finder* event_finder_ )
00145 : handle( handle_ ),
00146 event_finder( event_finder_ )
00147 {}
00148
00149
00150
00151
00152 sc_bind_ef::~sc_bind_ef()
00153 {
00154 }
00155
00156
00157
00158
00159
00160
00161 struct sc_bind_info
00162 {
00163
00164 explicit sc_bind_info( int max_size_,
00165 sc_port_policy policy_=SC_ONE_OR_MORE_BOUND );
00166
00167
00168 ~sc_bind_info();
00169
00170 int max_size() const;
00171 sc_port_policy policy() const;
00172 int size() const;
00173
00174 int m_max_size;
00175 sc_port_policy m_policy;
00176 std::vector<sc_bind_elem*> vec;
00177 bool has_parent;
00178 int last_add;
00179 bool is_leaf;
00180 bool complete;
00181
00182 std::vector<sc_bind_ef*> thread_vec;
00183 std::vector<sc_bind_ef*> method_vec;
00184 };
00185
00186
00187
00188
00189
00190
00191 sc_bind_info::sc_bind_info( int max_size_, sc_port_policy policy_ )
00192 : m_max_size( max_size_ ),
00193 m_policy( policy_ ),
00194 has_parent( false ),
00195 last_add( -1 ),
00196 is_leaf( true ),
00197 complete( false )
00198 {}
00199
00200
00201
00202
00203 sc_bind_info::~sc_bind_info()
00204 {
00205 for( int i = size() - 1; i >= 0; -- i ) {
00206 delete vec[i];
00207 }
00208 }
00209
00210
00211 int
00212 sc_bind_info::max_size() const
00213 {
00214 return m_max_size ? m_max_size : vec.size();
00215 }
00216
00217 sc_port_policy
00218 sc_bind_info::policy() const
00219 {
00220 return m_policy;
00221 }
00222
00223 int
00224 sc_bind_info::size() const
00225 {
00226 return vec.size();
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 void sc_port_base::add_static_event(
00242 sc_method_handle process_p, const sc_event& event ) const
00243 {
00244 process_p->add_static_event( event );
00245 }
00246
00247 void sc_port_base::add_static_event(
00248 sc_thread_handle process_p, const sc_event& event ) const
00249 {
00250 process_p->add_static_event( event );
00251 }
00252
00253
00254
00255
00256 void
00257 sc_port_base::report_error( const char* id, const char* add_msg ) const
00258 {
00259 char msg[BUFSIZ];
00260 if( add_msg != 0 ) {
00261 std::sprintf( msg, "%s: port '%s' (%s)", add_msg, name(), kind() );
00262 } else {
00263 std::sprintf( msg, "port '%s' (%s)", name(), kind() );
00264 }
00265 SC_REPORT_ERROR( id, msg );
00266 }
00267
00268
00269
00270
00271 sc_port_base::sc_port_base(
00272 int max_size_, sc_port_policy policy
00273 ) :
00274 sc_object( sc_gen_unique_name( "port" ) ),
00275 m_bind_info( new sc_bind_info( max_size_, policy ) )
00276 {
00277 simcontext()->get_port_registry()->insert( this );
00278 }
00279
00280 sc_port_base::sc_port_base(
00281 const char* name_, int max_size_, sc_port_policy policy
00282 ) :
00283 sc_object( name_ ),
00284 m_bind_info( new sc_bind_info( max_size_, policy ) )
00285 {
00286 simcontext()->get_port_registry()->insert( this );
00287 }
00288
00289
00290
00291
00292 sc_port_base::~sc_port_base()
00293 {
00294 simcontext()->get_port_registry()->remove( this );
00295 if( m_bind_info != 0 ) {
00296 delete m_bind_info;
00297 }
00298 }
00299
00300
00301
00302
00303 void
00304 sc_port_base::bind( sc_interface& interface_ )
00305 {
00306 if( m_bind_info == 0 ) {
00307
00308 report_error( SC_ID_BIND_IF_TO_PORT_, "simulation running" );
00309 }
00310
00311 m_bind_info->vec.push_back( new sc_bind_elem( &interface_ ) );
00312
00313 if( ! m_bind_info->has_parent ) {
00314
00315 add_interface( &interface_ );
00316 m_bind_info->last_add ++;
00317 }
00318 }
00319
00320
00321
00322
00323 void
00324 sc_port_base::bind( this_type& parent_ )
00325 {
00326 if( m_bind_info == 0 ) {
00327
00328 report_error( SC_ID_BIND_PORT_TO_PORT_, "simulation running" );
00329 }
00330
00331 if( &parent_ == this ) {
00332 report_error( SC_ID_BIND_PORT_TO_PORT_, "same port" );
00333 }
00334
00335
00336 #if 0
00337 for( int i = m_bind_info->size() - 1; i >= 0; -- i ) {
00338 if( &parent_ == m_bind_info->vec[i]->parent ) {
00339 report_error( SC_ID_BIND_PORT_TO_PORT_, "already bound" );
00340 }
00341 }
00342 #endif //
00343
00344 m_bind_info->vec.push_back( new sc_bind_elem( &parent_ ) );
00345 m_bind_info->has_parent = true;
00346 parent_.m_bind_info->is_leaf = false;
00347 }
00348
00349
00350
00351 void sc_port_base::before_end_of_elaboration()
00352 {}
00353
00354
00355
00356 void
00357 sc_port_base::end_of_elaboration()
00358 {}
00359
00360
00361
00362 void sc_port_base::start_of_simulation()
00363 {}
00364
00365
00366
00367 void sc_port_base::end_of_simulation()
00368 {}
00369
00370
00371
00372
00373 int
00374 sc_port_base::pbind( sc_interface& interface_ )
00375 {
00376 if( m_bind_info == 0 ) {
00377
00378 report_error( SC_ID_BIND_IF_TO_PORT_, "simulation running" );
00379 }
00380
00381 if( m_bind_info->size() != 0 ) {
00382
00383 return 1;
00384 }
00385
00386 return vbind( interface_ );
00387 }
00388
00389 int
00390 sc_port_base::pbind( sc_port_base& parent_ )
00391 {
00392 if( m_bind_info == 0 ) {
00393
00394 report_error( SC_ID_BIND_PORT_TO_PORT_, "simulation running" );
00395 }
00396
00397 if( m_bind_info->size() != 0 ) {
00398
00399 return 1;
00400 }
00401
00402 return vbind( parent_ );
00403 }
00404
00405
00406
00407
00408 void
00409 sc_port_base::make_sensitive( sc_thread_handle handle_,
00410 sc_event_finder* event_finder_ ) const
00411 {
00412 assert( m_bind_info != 0 );
00413 m_bind_info->thread_vec.push_back(
00414 new sc_bind_ef( (sc_process_b*)handle_, event_finder_ ) );
00415 }
00416
00417 void
00418 sc_port_base::make_sensitive( sc_method_handle handle_,
00419 sc_event_finder* event_finder_ ) const
00420 {
00421 assert( m_bind_info != 0 );
00422 m_bind_info->method_vec.push_back(
00423 new sc_bind_ef( (sc_process_b*)handle_, event_finder_ ) );
00424 }
00425
00426
00427
00428
00429 int
00430 sc_port_base::first_parent()
00431 {
00432 for( int i = 0; i < m_bind_info->size(); ++ i ) {
00433 if( m_bind_info->vec[i]->parent != 0 ) {
00434 return i;
00435 }
00436 }
00437 return -1;
00438 }
00439
00440 void
00441 sc_port_base::insert_parent( int i )
00442 {
00443 std::vector<sc_bind_elem*>& vec = m_bind_info->vec;
00444
00445 this_type* parent = vec[i]->parent;
00446
00447
00448
00449
00450
00451
00452
00453 vec[i]->parent = 0;
00454 if ( parent->m_bind_info->vec.size() == 0 ) return;
00455
00456 vec[i]->iface = parent->m_bind_info->vec[0]->iface;
00457 int n = parent->m_bind_info->size() - 1;
00458 if( n > 0 ) {
00459
00460 for( int k = 0; k < n; ++ k ) {
00461 vec.push_back( new sc_bind_elem() );
00462 }
00463
00464 for( int k = m_bind_info->size() - n - 1; k > i; -- k ) {
00465 vec[k + n]->iface = vec[k]->iface;
00466 vec[k + n]->parent = vec[k]->parent;
00467 }
00468
00469 for( int k = i + 1; k <= i + n; ++ k ) {
00470 vec[k]->iface = parent->m_bind_info->vec[k - i]->iface;
00471 vec[k]->parent = 0;
00472 }
00473 }
00474 }
00475
00476
00477
00478
00479 void
00480 sc_port_base::complete_binding()
00481 {
00482 char msg_buffer[128];
00483
00484
00485
00486 assert( m_bind_info != 0 );
00487 if( m_bind_info->complete ) {
00488 return;
00489 }
00490
00491
00492
00493 int i = first_parent();
00494 while( i >= 0 ) {
00495 m_bind_info->vec[i]->parent->complete_binding();
00496 insert_parent( i );
00497 i = first_parent();
00498 }
00499
00500
00501
00502 int size;
00503 for( int j = 0; j < m_bind_info->size(); ++ j ) {
00504 sc_interface* iface = m_bind_info->vec[j]->iface;
00505
00506
00507 if ( iface == 0 ) continue;
00508
00509
00510 if( j > m_bind_info->last_add ) {
00511 add_interface( iface );
00512 }
00513
00514
00515 if( m_bind_info->is_leaf ) {
00516 iface->register_port( *this, if_typename() );
00517 }
00518
00519
00520 size = m_bind_info->method_vec.size();
00521 for( int k = 0; k < size; ++ k ) {
00522 sc_bind_ef* p = m_bind_info->method_vec[k];
00523 const sc_event& event = ( p->event_finder != 0 )
00524 ? p->event_finder->find_event(iface)
00525 : iface->default_event();
00526 p->handle->add_static_event( event );
00527 }
00528
00529
00530 size = m_bind_info->thread_vec.size();
00531 for( int k = 0; k < size; ++ k ) {
00532 sc_bind_ef* p = m_bind_info->thread_vec[k];
00533 const sc_event& event = ( p->event_finder != 0 )
00534 ? p->event_finder->find_event(iface)
00535 : iface->default_event();
00536 p->handle->add_static_event( event );
00537 }
00538
00539 }
00540
00541
00542
00543
00544
00545 int actual_binds = interface_count();
00546
00547 if ( actual_binds > m_bind_info->max_size() )
00548 {
00549 sprintf(msg_buffer, "%d binds exceeds maximum of %d allowed",
00550 actual_binds, m_bind_info->max_size() );
00551 report_error( SC_ID_COMPLETE_BINDING_, msg_buffer );
00552 }
00553 switch ( m_bind_info->policy() )
00554 {
00555 case SC_ONE_OR_MORE_BOUND:
00556 if ( actual_binds < 1 ) {
00557 report_error( SC_ID_COMPLETE_BINDING_, "port not bound" );
00558 }
00559 break;
00560 case SC_ALL_BOUND:
00561 if ( actual_binds < m_bind_info->max_size() || actual_binds < 1 ) {
00562 sprintf(msg_buffer, "%d actual binds is less than required %d",
00563 actual_binds, m_bind_info->max_size() );
00564 report_error( SC_ID_COMPLETE_BINDING_, msg_buffer );
00565 }
00566 break;
00567 default:
00568 break;
00569 }
00570
00571
00572
00573
00574 size = m_bind_info->method_vec.size();
00575 for( int k = 0; k < size; ++ k ) {
00576 delete m_bind_info->method_vec[k];
00577 }
00578 m_bind_info->method_vec.resize(0);
00579
00580 size = m_bind_info->thread_vec.size();
00581 for( int k = 0; k < size; ++ k ) {
00582 delete m_bind_info->thread_vec[k];
00583 }
00584 m_bind_info->thread_vec.resize(0);
00585
00586 m_bind_info->complete = true;
00587 }
00588 void
00589 sc_port_base::construction_done()
00590 {
00591 before_end_of_elaboration();
00592 }
00593
00594 void
00595 sc_port_base::elaboration_done()
00596 {
00597 assert( m_bind_info != 0 && m_bind_info->complete );
00598 delete m_bind_info;
00599 m_bind_info = 0;
00600
00601 end_of_elaboration();
00602 }
00603
00604 void
00605 sc_port_base::start_simulation()
00606 {
00607 start_of_simulation();
00608 }
00609
00610 void
00611 sc_port_base::simulation_done()
00612 {
00613 end_of_simulation();
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624 void
00625 sc_port_registry::insert( sc_port_base* port_ )
00626 {
00627 if( sc_is_running() ) {
00628 port_->report_error( SC_ID_INSERT_PORT_, "simulation running" );
00629 }
00630
00631 #if defined(DEBUG_SYSTEMC)
00632
00633 for( int i = size() - 1; i >= 0; -- i ) {
00634 if( port_ == m_port_vec[i] ) {
00635 port_->report_error( SC_ID_INSERT_PORT_, "port already inserted" );
00636 }
00637 }
00638 #endif
00639
00640
00641 sc_module* curr_module = m_simc->hierarchy_curr();
00642 if( curr_module == 0 ) {
00643 port_->report_error( SC_ID_PORT_OUTSIDE_MODULE_ );
00644 }
00645 curr_module->append_port( port_ );
00646
00647
00648 m_port_vec.push_back( port_ );
00649 }
00650
00651 void
00652 sc_port_registry::remove( sc_port_base* port_ )
00653 {
00654 int i;
00655 for( i = size() - 1; i >= 0; -- i ) {
00656 if( port_ == m_port_vec[i] ) {
00657 break;
00658 }
00659 }
00660 if( i == -1 ) {
00661 port_->report_error( SC_ID_REMOVE_PORT_, "port not registered" );
00662 }
00663
00664
00665 m_port_vec[i] = m_port_vec[size() - 1];
00666 m_port_vec.resize(size()-1);
00667 }
00668
00669
00670
00671
00672 sc_port_registry::sc_port_registry( sc_simcontext& simc_ )
00673 : m_simc( &simc_ )
00674 {
00675 }
00676
00677
00678
00679
00680 sc_port_registry::~sc_port_registry()
00681 {
00682 }
00683
00684
00685
00686 void
00687 sc_port_registry::construction_done()
00688 {
00689 for( int i = size() - 1; i >= 0; -- i ) {
00690 m_port_vec[i]->construction_done();
00691 }
00692 }
00693
00694
00695
00696 void
00697 sc_port_registry::complete_binding()
00698 {
00699 for( int i = size() - 1; i >= 0; -- i ) {
00700 m_port_vec[i]->complete_binding();
00701 }
00702 }
00703
00704
00705
00706
00707 void
00708 sc_port_registry::elaboration_done()
00709 {
00710 complete_binding();
00711
00712 for( int i = size() - 1; i >= 0; -- i ) {
00713 m_port_vec[i]->elaboration_done();
00714 }
00715 }
00716
00717
00718
00719 void
00720 sc_port_registry::start_simulation()
00721 {
00722 for( int i = size() - 1; i >= 0; -- i ) {
00723 m_port_vec[i]->start_simulation();
00724 }
00725 }
00726
00727
00728
00729 void
00730 sc_port_registry::simulation_done()
00731 {
00732 for( int i = size() - 1; i >= 0; -- i ) {
00733 m_port_vec[i]->simulation_done();
00734 }
00735 }
00736
00737
00738
00739 void
00740 sc_port_registry::replace_port( sc_port_registry* registry )
00741 {
00742 }
00743
00744 void sc_warn_port_constructor()
00745 {
00746 static bool warn_port_constructor=true;
00747 if ( warn_port_constructor )
00748 {
00749 warn_port_constructor = false;
00750 SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
00751 "interface and/or port binding in port constructors is deprecated"
00752 );
00753 }
00754 }
00755
00756 }
00757
00758