00001 /***************************************************************************** 00002 00003 The following code is derived, directly or indirectly, from the SystemC 00004 source code Copyright (c) 1996-2008 by all Contributors. 00005 All Rights reserved. 00006 00007 The contents of this file are subject to the restrictions and limitations 00008 set forth in the SystemC Open Source License Version 3.0 (the "License"); 00009 You may not use this file except in compliance with such restrictions and 00010 limitations. You may obtain instructions on how to receive a copy of the 00011 License at http://www.systemc.org/. Software distributed by Contributors 00012 under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 00013 ANY KIND, either express or implied. See the License for the specific 00014 language governing rights and limitations under the License. 00015 00016 *****************************************************************************/ 00017 00018 #ifndef __TLM_QUANTUMKEEPER_H__ 00019 #define __TLM_QUANTUMKEEPER_H__ 00020 00021 #include "tlm_h/tlm_quantum/tlm_global_quantum.h" 00022 00023 namespace tlm_utils { 00024 00025 // 00026 // tlm_quantumkeeper class 00027 // 00028 // The tlm_quantumkeeper class is used to keep track of the local time in 00029 // an initiator (how much it has run ahead of the SystemC time), to 00030 // synchronize with SystemC time etc. 00031 // 00032 class tlm_quantumkeeper 00033 { 00034 public: 00035 // 00036 // Static setters/getters for the global quantum value. 00037 // 00038 // The global quantum is the maximum time an initiator can run ahead of 00039 // systemC time. All initiators will synchronize on timingpoints that are 00040 // multiples of the global quantum value. 00041 // 00042 static void set_global_quantum(const sc_core::sc_time& t) 00043 { 00044 tlm::tlm_global_quantum::instance().set(t); 00045 } 00046 00047 static const sc_core::sc_time& get_global_quantum() 00048 { 00049 return tlm::tlm_global_quantum::instance().get(); 00050 } 00051 00052 public: 00053 tlm_quantumkeeper() : 00054 m_next_sync_point(sc_core::SC_ZERO_TIME), 00055 m_local_time(sc_core::SC_ZERO_TIME) 00056 { 00057 } 00058 00059 virtual ‾tlm_quantumkeeper() {} 00060 00061 // 00062 // Increment the local time (the time the initiator is ahead of the 00063 // systemC time) After incrementing the local time an initiator should 00064 // check (with the need_sync method) if a sync is required. 00065 // 00066 virtual void inc(const sc_core::sc_time& t) 00067 { 00068 m_local_time += t; 00069 } 00070 00071 // 00072 // Sets the local time (the time the initiator is ahead of the 00073 // systemC time) After changing the local time an initiator should 00074 // check (with the need_sync method) if a sync is required. 00075 // 00076 virtual void set(const sc_core::sc_time& t) 00077 { 00078 m_local_time = t; 00079 } 00080 00081 // 00082 // Checks if a sync to systemC is required for this initiator. This will 00083 // be the case if the local time becomes greater than the local (current) 00084 // quantum value for this initiator. 00085 // 00086 virtual bool need_sync() const 00087 { 00088 return sc_core::sc_time_stamp() + m_local_time >= m_next_sync_point; 00089 } 00090 00091 // 00092 // Synchronize to systemC. This call will do a wait for the time the 00093 // initiator was running ahead of systemC time and reset the 00094 // tlm_quantumkeeper. 00095 // 00096 virtual void sync() 00097 { 00098 sc_core::wait(m_local_time); 00099 reset(); 00100 } 00101 00102 // 00103 // Resets the local time to SC_ZERO_TIME and computes the value of the 00104 // next local quantum. This method should be called by an initiator after 00105 // a wait because of a synchronization request by a target (TLM_ACCEPTED, 00106 // or TLM_UPDATED). 00107 // 00108 virtual void reset() 00109 { 00110 m_local_time = sc_core::SC_ZERO_TIME; 00111 m_next_sync_point = sc_core::sc_time_stamp() + compute_local_quantum(); 00112 } 00113 00114 // 00115 // Helper function to get the current systemC time, taken the local time 00116 // into account. The current systemC time is calculated as the time 00117 // returned by sc_time_stamp incremeneted with the time the initiator is 00118 // running ahead. 00119 // 00120 virtual sc_core::sc_time get_current_time() const 00121 { 00122 return sc_core::sc_time_stamp() + m_local_time; 00123 } 00124 00125 // 00126 // Helper functions to get the time the initiator is running ahead of 00127 // systenC (local time). This time should be passed to a target in the 00128 // nb_transport call 00129 // 00130 virtual sc_core::sc_time get_local_time() const 00131 { 00132 return m_local_time; 00133 } 00134 00135 protected: 00136 // 00137 // Calculate the next local quantum for this initiator. 00138 // 00139 // The method can be overloaded in a derived object if an initiator wants 00140 // to use another local quantum. This derived object should also take the 00141 // global quantum into account. It's local quantum should not be set to a 00142 // value that is larger than the quantum returned by the 00143 // compute_local_quantum of the tlm_global_quantum singleton. 00144 // 00145 virtual sc_core::sc_time compute_local_quantum() 00146 { 00147 return tlm::tlm_global_quantum::instance().compute_local_quantum(); 00148 } 00149 00150 protected: 00151 sc_core::sc_time m_next_sync_point; 00152 sc_core::sc_time m_local_time; 00153 }; 00154 00155 } // namespace tlm 00156 00157 #endif