diff options
Diffstat (limited to 'src/systemc/ext/tlm_utils/tlm_quantumkeeper.h')
-rw-r--r-- | src/systemc/ext/tlm_utils/tlm_quantumkeeper.h | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/src/systemc/ext/tlm_utils/tlm_quantumkeeper.h b/src/systemc/ext/tlm_utils/tlm_quantumkeeper.h new file mode 100644 index 000000000..ed211665f --- /dev/null +++ b/src/systemc/ext/tlm_utils/tlm_quantumkeeper.h @@ -0,0 +1,172 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// 20-Mar-2009 John Aynsley Add set_and_sync() method + + +#ifndef __TLM_QUANTUMKEEPER_H__ +#define __TLM_QUANTUMKEEPER_H__ + +#include "tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h" + +namespace tlm_utils { + + // + // tlm_quantumkeeper class + // + // The tlm_quantumkeeper class is used to keep track of the local time in + // an initiator (how much it has run ahead of the SystemC time), to + // synchronize with SystemC time etc. + // + class tlm_quantumkeeper + { + public: + // + // Static setters/getters for the global quantum value. + // + // The global quantum is the maximum time an initiator can run ahead of + // systemC time. All initiators will synchronize on timingpoints that are + // multiples of the global quantum value. + // + static void set_global_quantum(const sc_core::sc_time& t) + { + tlm::tlm_global_quantum::instance().set(t); + } + + static const sc_core::sc_time& get_global_quantum() + { + return tlm::tlm_global_quantum::instance().get(); + } + + public: + tlm_quantumkeeper() : + m_next_sync_point(sc_core::SC_ZERO_TIME), + m_local_time(sc_core::SC_ZERO_TIME) + { + } + + virtual ~tlm_quantumkeeper() {} + + // + // Increment the local time (the time the initiator is ahead of the + // systemC time) After incrementing the local time an initiator should + // check (with the need_sync method) if a sync is required. + // + virtual void inc(const sc_core::sc_time& t) + { + m_local_time += t; + } + + // + // Sets the local time (the time the initiator is ahead of the + // systemC time) After changing the local time an initiator should + // check (with the need_sync method) if a sync is required. + // + virtual void set(const sc_core::sc_time& t) + { + m_local_time = t; + } + + // + // Checks if a sync to systemC is required for this initiator. This will + // be the case if the local time becomes greater than the local (current) + // quantum value for this initiator. + // + virtual bool need_sync() const + { + return sc_core::sc_time_stamp() + m_local_time >= m_next_sync_point; + } + + // + // Synchronize to systemC. This call will do a wait for the time the + // initiator was running ahead of systemC time and reset the + // tlm_quantumkeeper. + // + virtual void sync() + { + sc_core::wait(m_local_time); + reset(); + } + + // + // Non-virtual convenience method to set the local time and sync only if needed + // + void set_and_sync(const sc_core::sc_time& t) + { + set(t); + if (need_sync()) + sync(); + } + + // + // Resets the local time to SC_ZERO_TIME and computes the value of the + // next local quantum. This method should be called by an initiator after + // a wait because of a synchronization request by a target (TLM_ACCEPTED, + // or TLM_UPDATED). + // + virtual void reset() + { + m_local_time = sc_core::SC_ZERO_TIME; + m_next_sync_point = sc_core::sc_time_stamp() + compute_local_quantum(); + } + + // + // Helper function to get the current systemC time, taken the local time + // into account. The current systemC time is calculated as the time + // returned by sc_time_stamp incremeneted with the time the initiator is + // running ahead. + // + virtual sc_core::sc_time get_current_time() const + { + return sc_core::sc_time_stamp() + m_local_time; + } + + // + // Helper functions to get the time the initiator is running ahead of + // systenC (local time). This time should be passed to a target in the + // nb_transport call + // + virtual sc_core::sc_time get_local_time() const + { + return m_local_time; + } + + protected: + // + // Calculate the next local quantum for this initiator. + // + // The method can be overloaded in a derived object if an initiator wants + // to use another local quantum. This derived object should also take the + // global quantum into account. It's local quantum should not be set to a + // value that is larger than the quantum returned by the + // compute_local_quantum of the tlm_global_quantum singleton. + // + virtual sc_core::sc_time compute_local_quantum() + { + return tlm::tlm_global_quantum::instance().compute_local_quantum(); + } + + protected: + sc_core::sc_time m_next_sync_point; + sc_core::sc_time m_local_time; + }; + +} // namespace tlm + +#endif |