sc_reset.cpp revision 12027
13914Ssaidi@eecs.umich.edu/***************************************************************************** 23914Ssaidi@eecs.umich.edu 33914Ssaidi@eecs.umich.edu Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 43914Ssaidi@eecs.umich.edu more contributor license agreements. See the NOTICE file distributed 53914Ssaidi@eecs.umich.edu with this work for additional information regarding copyright ownership. 63914Ssaidi@eecs.umich.edu Accellera licenses this file to you under the Apache License, Version 2.0 73914Ssaidi@eecs.umich.edu (the "License"); you may not use this file except in compliance with the 83914Ssaidi@eecs.umich.edu License. You may obtain a copy of the License at 93914Ssaidi@eecs.umich.edu 103914Ssaidi@eecs.umich.edu http://www.apache.org/licenses/LICENSE-2.0 113914Ssaidi@eecs.umich.edu 123914Ssaidi@eecs.umich.edu Unless required by applicable law or agreed to in writing, software 133914Ssaidi@eecs.umich.edu distributed under the License is distributed on an "AS IS" BASIS, 143914Ssaidi@eecs.umich.edu WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 153914Ssaidi@eecs.umich.edu implied. See the License for the specific language governing 163914Ssaidi@eecs.umich.edu permissions and limitations under the License. 173914Ssaidi@eecs.umich.edu 183914Ssaidi@eecs.umich.edu *****************************************************************************/ 193914Ssaidi@eecs.umich.edu 203914Ssaidi@eecs.umich.edu/***************************************************************************** 213914Ssaidi@eecs.umich.edu 223914Ssaidi@eecs.umich.edu sc_reset.cpp -- Support for reset. 233914Ssaidi@eecs.umich.edu 243914Ssaidi@eecs.umich.edu Original Author: Andy Goodrich, Forte Design Systems 253914Ssaidi@eecs.umich.edu 263914Ssaidi@eecs.umich.edu CHANGE LOG AT THE END OF THE FILE 273914Ssaidi@eecs.umich.edu *****************************************************************************/ 283914Ssaidi@eecs.umich.edu 293914Ssaidi@eecs.umich.edu 303914Ssaidi@eecs.umich.edu#include "sysc/kernel/sc_simcontext.h" 313914Ssaidi@eecs.umich.edu#include "sysc/kernel/sc_reset.h" 323914Ssaidi@eecs.umich.edu#include "sysc/kernel/sc_process_handle.h" 333914Ssaidi@eecs.umich.edu#include "sysc/communication/sc_signal.h" 343914Ssaidi@eecs.umich.edu#include "sysc/communication/sc_signal_ports.h" 353914Ssaidi@eecs.umich.edu 363914Ssaidi@eecs.umich.edu 373914Ssaidi@eecs.umich.edu// THE SYSTEMC PROOF OF CONCEPT SIMULATOR RESET SIGNAL IMPLEMENTATION: 383914Ssaidi@eecs.umich.edu// 393914Ssaidi@eecs.umich.edu// (1) An instance of the sc_reset class is attached to each sc_signal<bool> 404762Snate@binkert.org// that is used as a reset signal. 413914Ssaidi@eecs.umich.edu// 426658Snate@binkert.org// (2) Each process that is senstive to a reset signal will be registered in the 433914Ssaidi@eecs.umich.edu// sc_reset class attached to that reset signal. 443914Ssaidi@eecs.umich.edu// 453914Ssaidi@eecs.umich.edu// (3) When a change in the value of a reset signal occurs it invokes the 463914Ssaidi@eecs.umich.edu// notify_processes() method of its sc_reset object instance. The 473914Ssaidi@eecs.umich.edu// notify_processes() method will call the reset_changed() method of each 483914Ssaidi@eecs.umich.edu// process that is registered with it to inform the process that 493914Ssaidi@eecs.umich.edu// state of the reset signal has changed. 503914Ssaidi@eecs.umich.edu// 513914Ssaidi@eecs.umich.edu// (4) A process may have multiple reset signals, so counters are kept for the 524762Snate@binkert.org// number of active asynchronous, and synchronous, reset signals that are 539808Sstever@gmail.com// active. Those counters are incremented and decremented in the process' 543914Ssaidi@eecs.umich.edu// reset_changed() method. 554762Snate@binkert.org// 5610531Sandreas.hansson@arm.com// (5) When a process' semantics() method is called the current reset state is 573943Sbinkertn@umich.edu// checked, and a reset sequence is initiated if the process is in reset. 583914Ssaidi@eecs.umich.edu// This will occur every time an SC_METHOD is dispatched. SC_CTHREAD and 593914Ssaidi@eecs.umich.edu// and SC_THREAD instances, only go through the semantics() method they 603914Ssaidi@eecs.umich.edu// initially start up. So the reset check is duplicated in the suspend_me() 613914Ssaidi@eecs.umich.edu// method, the tail of which will execute each time the thread is 623914Ssaidi@eecs.umich.edu// dispatched. 633914Ssaidi@eecs.umich.edu 643914Ssaidi@eecs.umich.edunamespace sc_core { 653914Ssaidi@eecs.umich.edu 663914Ssaidi@eecs.umich.educlass sc_reset_finder; 673914Ssaidi@eecs.umich.edustatic sc_reset_finder* reset_finder_q=0; // Q of reset finders to reconcile. 683914Ssaidi@eecs.umich.edu 693914Ssaidi@eecs.umich.edu//============================================================================== 703914Ssaidi@eecs.umich.edu// sc_reset_finder - place holder class for a port reset signal until it is 714870Sstever@eecs.umich.edu// bound and an interface class is available. When the port 723914Ssaidi@eecs.umich.edu// has been bound the information in this class will be used 733914Ssaidi@eecs.umich.edu// to initialize its sc_reset object instance. 743914Ssaidi@eecs.umich.edu//============================================================================== 753914Ssaidi@eecs.umich.educlass sc_reset_finder { 763914Ssaidi@eecs.umich.edu friend class sc_reset; 773914Ssaidi@eecs.umich.edu public: 783914Ssaidi@eecs.umich.edu sc_reset_finder( bool async, const sc_in<bool>* port_p, bool level, 793914Ssaidi@eecs.umich.edu sc_process_b* target_p); 803914Ssaidi@eecs.umich.edu sc_reset_finder( bool async, const sc_inout<bool>* port_p, bool level, 813990Ssaidi@eecs.umich.edu sc_process_b* target_p); 8210905Sandreas.sandberg@arm.com sc_reset_finder( bool async, const sc_out<bool>* port_p, bool level, 833990Ssaidi@eecs.umich.edu sc_process_b* target_p); 843990Ssaidi@eecs.umich.edu 853990Ssaidi@eecs.umich.edu protected: 863990Ssaidi@eecs.umich.edu bool m_async; // True if asynchronous reset. 873990Ssaidi@eecs.umich.edu bool m_level; // Level for reset. 8810905Sandreas.sandberg@arm.com sc_reset_finder* m_next_p; // Next reset finder in list. 893990Ssaidi@eecs.umich.edu const sc_in<bool>* m_in_p; // Port for which reset is needed. 903990Ssaidi@eecs.umich.edu const sc_inout<bool>* m_inout_p; // Port for which reset is needed. 913990Ssaidi@eecs.umich.edu const sc_out<bool>* m_out_p; // Port for which reset is needed. 923990Ssaidi@eecs.umich.edu sc_process_b* m_target_p; // Process to reset. 934762Snate@binkert.org 944762Snate@binkert.org private: // disabled 953914Ssaidi@eecs.umich.edu sc_reset_finder( const sc_reset_finder& ); 964762Snate@binkert.org const sc_reset_finder& operator = ( const sc_reset_finder& ); 973914Ssaidi@eecs.umich.edu}; 98 99inline sc_reset_finder::sc_reset_finder( 100 bool async, const sc_in<bool>* port_p, bool level, sc_process_b* target_p) : 101 m_async(async), m_level(level), m_next_p(0), m_in_p(port_p), m_inout_p(0), 102 m_out_p(0), m_target_p(target_p) 103{ 104 m_next_p = reset_finder_q; 105 reset_finder_q = this; 106} 107 108inline sc_reset_finder::sc_reset_finder( 109 bool async, const sc_inout<bool>* port_p, bool level, sc_process_b* target_p 110) : 111 m_async(async), m_level(level), m_next_p(0), m_in_p(0), m_inout_p(port_p), 112 m_out_p(0), m_target_p(target_p) 113{ 114 m_next_p = reset_finder_q; 115 reset_finder_q = this; 116} 117 118inline sc_reset_finder::sc_reset_finder( 119 bool async, const sc_out<bool>* port_p, bool level, sc_process_b* target_p 120) : 121 m_async(async), m_level(level), m_next_p(0), m_in_p(0), m_inout_p(0), 122 m_out_p(port_p), m_target_p(target_p) 123{ 124 m_next_p = reset_finder_q; 125 reset_finder_q = this; 126} 127 128 129//------------------------------------------------------------------------------ 130//"sc_reset::notify_processes" 131// 132// Notify processes that there is a change in the reset signal value. 133//------------------------------------------------------------------------------ 134void sc_reset::notify_processes() 135{ 136 bool active; // true if reset is active. 137 sc_reset_target* entry_p; // reset entry processing. 138 std::vector<sc_reset_target>::size_type process_i; // index of process resetting. 139 std::vector<sc_reset_target>::size_type process_n; // # of processes to reset. 140 bool value; // value of our signal. 141 142 value = m_iface_p->read(); 143 process_n = m_targets.size(); 144 for ( process_i = 0; process_i < process_n; process_i++ ) 145 { 146 entry_p = &m_targets[process_i]; 147 active = ( entry_p->m_level == value ); 148 entry_p->m_process_p->reset_changed( entry_p->m_async, active ); 149 } 150} 151 152 153//------------------------------------------------------------------------------ 154//"sc_reset::reconcile_resets" 155// 156// This static method processes the sc_reset_finders to establish the actual 157// reset connections. 158// 159// Notes: 160// (1) If reset is asserted we tell the process that it is in reset. 161//------------------------------------------------------------------------------ 162void sc_reset::reconcile_resets() 163{ 164 const sc_signal_in_if<bool>* iface_p; // Interface to reset signal. 165 sc_reset_finder* next_p; // Next finder to process. 166 sc_reset_finder* now_p; // Finder currently processing. 167 sc_reset_target reset_target; // Target's reset entry. 168 sc_reset* reset_p; // Reset object to use. 169 170 for ( now_p = reset_finder_q; now_p; now_p = next_p ) 171 { 172 next_p = now_p->m_next_p; 173 if ( now_p->m_in_p ) 174 { 175 iface_p = DCAST<const sc_signal_in_if<bool>*>( 176 now_p->m_in_p->get_interface()); 177 } 178 else if ( now_p->m_inout_p ) 179 { 180 iface_p = DCAST<const sc_signal_in_if<bool>*>( 181 now_p->m_inout_p->get_interface()); 182 } 183 else 184 { 185 iface_p = DCAST<const sc_signal_in_if<bool>*>( 186 now_p->m_out_p->get_interface()); 187 } 188 assert( iface_p != 0 ); 189 reset_p = iface_p->is_reset(); 190 now_p->m_target_p->m_resets.push_back(reset_p); 191 reset_target.m_async = now_p->m_async; 192 reset_target.m_level = now_p->m_level; 193 reset_target.m_process_p = now_p->m_target_p; 194 reset_p->m_targets.push_back(reset_target); 195 if ( iface_p->read() == now_p->m_level ) // see note 1 above 196 now_p->m_target_p->initially_in_reset( now_p->m_async ); 197 delete now_p; 198 } 199} 200 201 202//------------------------------------------------------------------------------ 203//"sc_reset::remove_process" 204// 205// This method removes the supplied process from the list of processes that 206// should be notified when there is a change in the value of the reset signal. 207// 208// Arguments: 209// process_p -> process to be removed. 210//------------------------------------------------------------------------------ 211void sc_reset::remove_process( sc_process_b* process_p ) 212{ 213 int process_i; // Index of process resetting. 214 int process_n; // # of processes to reset. 215 216 process_n = m_targets.size(); 217 for ( process_i = 0; process_i < process_n; ) 218 { 219 if ( m_targets[process_i].m_process_p == process_p ) 220 { 221 m_targets[process_i] = m_targets[process_n-1]; 222 process_n--; 223 m_targets.resize(process_n); 224 } 225 else 226 { 227 process_i++; 228 } 229 } 230} 231 232//------------------------------------------------------------------------------ 233//"sc_reset::reset_signal_is - ports" 234// 235// These overloads of the reset_signal_is() method will register the active 236// process with the sc_reset object instance associated with the supplied port. 237// If the port does not yet have a pointer to its sc_signal<bool> instance it 238// will create an sc_reset_finder class object instance that will be used 239// to set the process' reset information when the port has been bound. 240// 241// Arguments: 242// async = true if the reset signal is asynchronous, false if not. 243// port = port for sc_signal<bool> that will provide the reset signal. 244// level = level at which reset is active, either true or false. 245//------------------------------------------------------------------------------ 246void sc_reset::reset_signal_is( bool async, const sc_in<bool>& port, bool level) 247{ 248 const sc_signal_in_if<bool>* iface_p; 249 sc_process_b* process_p; 250 251 process_p = (sc_process_b*)sc_get_current_process_handle(); 252 assert( process_p ); 253 process_p->m_has_reset_signal = true; 254 switch ( process_p->proc_kind() ) 255 { 256 case SC_THREAD_PROC_: 257 case SC_METHOD_PROC_: 258 case SC_CTHREAD_PROC_: 259 iface_p = DCAST<const sc_signal_in_if<bool>*>(port.get_interface()); 260 if ( iface_p ) 261 reset_signal_is( async, *iface_p, level ); 262 else 263 new sc_reset_finder( async, &port, level, process_p ); 264 break; 265 default: 266 SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); 267 break; 268 } 269} 270 271void sc_reset::reset_signal_is( 272 bool async, const sc_inout<bool>& port, bool level ) 273{ 274 const sc_signal_in_if<bool>* iface_p; 275 sc_process_b* process_p; 276 277 process_p = (sc_process_b*)sc_get_current_process_handle(); 278 assert( process_p ); 279 process_p->m_has_reset_signal = true; 280 switch ( process_p->proc_kind() ) 281 { 282 case SC_THREAD_PROC_: 283 case SC_METHOD_PROC_: 284 case SC_CTHREAD_PROC_: 285 iface_p = DCAST<const sc_signal_in_if<bool>*>(port.get_interface()); 286 if ( iface_p ) 287 reset_signal_is( async, *iface_p, level ); 288 else 289 new sc_reset_finder( async, &port, level, process_p ); 290 break; 291 default: 292 SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); 293 break; 294 } 295} 296 297void sc_reset::reset_signal_is( 298 bool async, const sc_out<bool>& port, bool level ) 299{ 300 const sc_signal_in_if<bool>* iface_p; 301 sc_process_b* process_p; 302 303 process_p = (sc_process_b*)sc_get_current_process_handle(); 304 assert( process_p ); 305 process_p->m_has_reset_signal = true; 306 switch ( process_p->proc_kind() ) 307 { 308 case SC_THREAD_PROC_: 309 case SC_METHOD_PROC_: 310 case SC_CTHREAD_PROC_: 311 iface_p = DCAST<const sc_signal_in_if<bool>*>(port.get_interface()); 312 if ( iface_p ) 313 reset_signal_is( async, *iface_p, level ); 314 else 315 new sc_reset_finder( async, &port, level, process_p ); 316 break; 317 default: 318 SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); 319 break; 320 } 321} 322 323//------------------------------------------------------------------------------ 324//"sc_reset::reset_signal_is" 325// 326// This static method will register the active process instance as being 327// reset by the sc_signal<bool> whose interface has been supplied. If no 328// sc_reset object instance has been attached to the sc_signal<bool> yet, it 329// will be created and attached. The active process instance is pushed into 330// the list of processes that the sc_reset object instance should notify if 331// the value of the reset signal changes. 332// 333// Arguments: 334// async = true if the reset signal is asynchronous, false if not. 335// iface = interface for the reset signal. 336// level = is the level at which reset is active, either true or false. 337// Notes: 338// (1) If reset is asserted we tell the process that it is in reset 339// initially. 340//------------------------------------------------------------------------------ 341void sc_reset::reset_signal_is( 342 bool async, const sc_signal_in_if<bool>& iface, bool level ) 343{ 344 sc_process_b* process_p; // process adding reset for. 345 sc_reset_target reset_target; // entry to build for the process. 346 sc_reset* reset_p; // reset object. 347 348 process_p = sc_process_b::last_created_process_base(); 349 assert( process_p ); 350 process_p->m_has_reset_signal = true; 351 switch ( process_p->proc_kind() ) 352 { 353 case SC_METHOD_PROC_: 354 case SC_CTHREAD_PROC_: 355 case SC_THREAD_PROC_: 356 reset_p = iface.is_reset(); 357 process_p->m_resets.push_back(reset_p); 358 reset_target.m_async = async; 359 reset_target.m_level = level; 360 reset_target.m_process_p = process_p; 361 reset_p->m_targets.push_back(reset_target); 362 if ( iface.read() == level ) process_p->initially_in_reset( async ); 363 break; 364 default: 365 SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); 366 break; 367 } 368} 369 370} // namespace sc_core 371 372// $Log: sc_reset.cpp,v $ 373// Revision 1.16 2011/08/26 20:46:10 acg 374// Andy Goodrich: moved the modification log to the end of the file to 375// eliminate source line number skew when check-ins are done. 376// 377// Revision 1.15 2011/08/24 22:05:51 acg 378// Torsten Maehne: initialization changes to remove warnings. 379// 380// Revision 1.14 2011/04/08 22:37:34 acg 381// Andy Goodrich: documentation of the reset mechanism and additional 382// documentation of methods. Removal of check for SC_METHODs in 383// sc_reset_signal_is() that should not have been there. 384// 385// Revision 1.13 2011/03/20 15:13:01 acg 386// Andy Goodrich: set the reset flag for async_reset_signal_is to catch 387// the suspend() corner case. 388// 389// Revision 1.12 2011/03/20 13:43:23 acg 390// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. 391// 392// Revision 1.11 2011/03/06 19:57:11 acg 393// Andy Goodrich: refinements for the illegal suspend - synchronous reset 394// interaction. 395// 396// Revision 1.10 2011/02/18 20:27:14 acg 397// Andy Goodrich: Updated Copyrights. 398// 399// Revision 1.9 2011/02/13 21:47:37 acg 400// Andy Goodrich: update copyright notice. 401// 402// Revision 1.8 2011/02/01 21:08:26 acg 403// Andy Goodrich: new multiple reset support. 404// 405// Revision 1.7 2011/01/06 18:04:38 acg 406// Andy Goodrich: removed commented out code. 407// 408// Revision 1.6 2010/12/07 20:09:13 acg 409// Andy Goodrich: removed sc_signal overloads since already have sc_signal_in_if overloads. 410// 411// Revision 1.5 2010/11/20 17:10:56 acg 412// Andy Goodrich: reset processing changes for new IEEE 1666 standard. 413// 414// Revision 1.4 2009/05/22 16:06:29 acg 415// Andy Goodrich: process control updates. 416// 417// Revision 1.3 2009/03/12 22:59:58 acg 418// Andy Goodrich: updates for 2.4 stuff. 419// 420// Revision 1.2 2008/05/22 17:06:26 acg 421// Andy Goodrich: updated copyright notice to include 2008. 422// 423// Revision 1.1.1.1 2006/12/15 20:20:05 acg 424// SystemC 2.3 425// 426// Revision 1.7 2006/12/02 20:58:19 acg 427// Andy Goodrich: updates from 2.2 for IEEE 1666 support. 428// 429// Revision 1.5 2006/04/11 23:13:21 acg 430// Andy Goodrich: Changes for reduced reset support that only includes 431// sc_cthread, but has preliminary hooks for expanding to method and thread 432// processes also. 433// 434// Revision 1.4 2006/01/24 20:49:05 acg 435// Andy Goodrich: changes to remove the use of deprecated features within the 436// simulator, and to issue warning messages when deprecated features are used. 437// 438// Revision 1.3 2006/01/13 18:44:30 acg 439// Added $Log to record CVS changes into the source. 440// 441