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 // 20-Mar-2009 John Aynsley Add set_and_sync() method 00019 00020 00021 #ifndef __TLM_QUANTUMKEEPER_H__ 00022 #define __TLM_QUANTUMKEEPER_H__ 00023 00024 #include "tlm_h/tlm_quantum/tlm_global_quantum.h" 00025 00026 namespace tlm_utils { 00027 00028 // 00029 // tlm_quantumkeeper class 00030 // 00031 // The tlm_quantumkeeper class is used to keep track of the local time in 00032 // an initiator (how much it has run ahead of the SystemC time), to 00033 // synchronize with SystemC time etc. 00034 // 00035 class tlm_quantumkeeper 00036 { 00037 public: 00038 // 00039 // Static setters/getters for the global quantum value. 00040 // 00041 // The global quantum is the maximum time an initiator can run ahead of 00042 // systemC time. All initiators will synchronize on timingpoints that are 00043 // multiples of the global quantum value. 00044 // 00045 static void set_global_quantum(const sc_core::sc_time& t) 00046 { 00047 tlm::tlm_global_quantum::instance().set(t); 00048 } 00049 00050 static const sc_core::sc_time& get_global_quantum() 00051 { 00052 return tlm::tlm_global_quantum::instance().get(); 00053 } 00054 00055 public: 00056 tlm_quantumkeeper() : 00057 m_next_sync_point(sc_core::SC_ZERO_TIME), 00058 m_local_time(sc_core::SC_ZERO_TIME) 00059 { 00060 } 00061 00062 virtual ~tlm_quantumkeeper() {} 00063 00064 // 00065 // Increment the local time (the time the initiator is ahead of the 00066 // systemC time) After incrementing the local time an initiator should 00067 // check (with the need_sync method) if a sync is required. 00068 // 00069 virtual void inc(const sc_core::sc_time& t) 00070 { 00071 m_local_time += t; 00072 } 00073 00074 // 00075 // Sets the local time (the time the initiator is ahead of the 00076 // systemC time) After changing the local time an initiator should 00077 // check (with the need_sync method) if a sync is required. 00078 // 00079 virtual void set(const sc_core::sc_time& t) 00080 { 00081 m_local_time = t; 00082 } 00083 00084 // 00085 // Checks if a sync to systemC is required for this initiator. This will 00086 // be the case if the local time becomes greater than the local (current) 00087 // quantum value for this initiator. 00088 // 00089 virtual bool need_sync() const 00090 { 00091 return sc_core::sc_time_stamp() + m_local_time >= m_next_sync_point; 00092 } 00093 00094 // 00095 // Synchronize to systemC. This call will do a wait for the time the 00096 // initiator was running ahead of systemC time and reset the 00097 // tlm_quantumkeeper. 00098 // 00099 virtual void sync() 00100 { 00101 sc_core::wait(m_local_time); 00102 reset(); 00103 } 00104 00105 // 00106 // Non-virtual convenience method to set the local time and sync only if needed 00107 // 00108 void set_and_sync(const sc_core::sc_time& t) 00109 { 00110 set(t); 00111 if (need_sync()) 00112 sync(); 00113 } 00114 00115 // 00116 // Resets the local time to SC_ZERO_TIME and computes the value of the 00117 // next local quantum. This method should be called by an initiator after 00118 // a wait because of a synchronization request by a target (TLM_ACCEPTED, 00119 // or TLM_UPDATED). 00120 // 00121 virtual void reset() 00122 { 00123 m_local_time = sc_core::SC_ZERO_TIME; 00124 m_next_sync_point = sc_core::sc_time_stamp() + compute_local_quantum(); 00125 } 00126 00127 // 00128 // Helper function to get the current systemC time, taken the local time 00129 // into account. The current systemC time is calculated as the time 00130 // returned by sc_time_stamp incremeneted with the time the initiator is 00131 // running ahead. 00132 // 00133 virtual sc_core::sc_time get_current_time() const 00134 { 00135 return sc_core::sc_time_stamp() + m_local_time; 00136 } 00137 00138 // 00139 // Helper functions to get the time the initiator is running ahead of 00140 // systenC (local time). This time should be passed to a target in the 00141 // nb_transport call 00142 // 00143 virtual sc_core::sc_time get_local_time() const 00144 { 00145 return m_local_time; 00146 } 00147 00148 protected: 00149 // 00150 // Calculate the next local quantum for this initiator. 00151 // 00152 // The method can be overloaded in a derived object if an initiator wants 00153 // to use another local quantum. This derived object should also take the 00154 // global quantum into account. It's local quantum should not be set to a 00155 // value that is larger than the quantum returned by the 00156 // compute_local_quantum of the tlm_global_quantum singleton. 00157 // 00158 virtual sc_core::sc_time compute_local_quantum() 00159 { 00160 return tlm::tlm_global_quantum::instance().compute_local_quantum(); 00161 } 00162 00163 protected: 00164 sc_core::sc_time m_next_sync_point; 00165 sc_core::sc_time m_local_time; 00166 }; 00167 00168 } // namespace tlm 00169 00170 #endif