113511Sgabeblack@google.com/*****************************************************************************
213511Sgabeblack@google.com
313511Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
413511Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
513511Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
613511Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
713511Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
813511Sgabeblack@google.com  License.  You may obtain a copy of the License at
913511Sgabeblack@google.com
1013511Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1113511Sgabeblack@google.com
1213511Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1313511Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1413511Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1513511Sgabeblack@google.com  implied.  See the License for the specific language governing
1613511Sgabeblack@google.com  permissions and limitations under the License.
1713511Sgabeblack@google.com
1813511Sgabeblack@google.com *****************************************************************************/
1913511Sgabeblack@google.com
2013513Sgabeblack@google.com#ifndef __SYSTEMC_EXT_TLM_UTILS_TLM_QUANTUMKEEPER_H__
2113513Sgabeblack@google.com#define __SYSTEMC_EXT_TLM_UTILS_TLM_QUANTUMKEEPER_H__
2213511Sgabeblack@google.com
2313586Sgabeblack@google.com#include "../core/sc_time.hh"
2413511Sgabeblack@google.com
2513513Sgabeblack@google.comnamespace tlm_utils
2613513Sgabeblack@google.com{
2713511Sgabeblack@google.com
2813513Sgabeblack@google.com// tlm_quantumkeeper class
2913513Sgabeblack@google.com//
3013513Sgabeblack@google.com// The tlm_quantumkeeper class is used to keep track of the local time in
3113513Sgabeblack@google.com// an initiator (how much it has run ahead of the SystemC time), to
3213513Sgabeblack@google.com// synchronize with SystemC time etc.
3313513Sgabeblack@google.comclass tlm_quantumkeeper
3413513Sgabeblack@google.com{
3513511Sgabeblack@google.com  public:
3613511Sgabeblack@google.com    //
3713511Sgabeblack@google.com    // Static setters/getters for the global quantum value.
3813511Sgabeblack@google.com    //
3913511Sgabeblack@google.com    // The global quantum is the maximum time an initiator can run ahead of
4013513Sgabeblack@google.com    // SystemC time. All initiators will synchronize on timing points that are
4113511Sgabeblack@google.com    // multiples of the global quantum value.
4213511Sgabeblack@google.com    //
4313513Sgabeblack@google.com    static void
4413513Sgabeblack@google.com    set_global_quantum(const sc_core::sc_time &t)
4513511Sgabeblack@google.com    {
4613513Sgabeblack@google.com        tlm::tlm_global_quantum::instance().set(t);
4713511Sgabeblack@google.com    }
4813511Sgabeblack@google.com
4913513Sgabeblack@google.com    static const sc_core::sc_time &
5013513Sgabeblack@google.com    get_global_quantum()
5113511Sgabeblack@google.com    {
5213513Sgabeblack@google.com        return tlm::tlm_global_quantum::instance().get();
5313511Sgabeblack@google.com    }
5413511Sgabeblack@google.com
5513511Sgabeblack@google.com  public:
5613513Sgabeblack@google.com    tlm_quantumkeeper() : m_next_sync_point(sc_core::SC_ZERO_TIME),
5713513Sgabeblack@google.com                          m_local_time(sc_core::SC_ZERO_TIME)
5813513Sgabeblack@google.com    {}
5913511Sgabeblack@google.com
6013511Sgabeblack@google.com    virtual ~tlm_quantumkeeper() {}
6113511Sgabeblack@google.com
6213511Sgabeblack@google.com    // Increment the local time (the time the initiator is ahead of the
6313511Sgabeblack@google.com    // systemC time) After incrementing the local time an initiator should
6413511Sgabeblack@google.com    // check (with the need_sync method) if a sync is required.
6513513Sgabeblack@google.com    virtual void inc(const sc_core::sc_time &t) { m_local_time += t; }
6613511Sgabeblack@google.com
6713511Sgabeblack@google.com    // Sets the local time (the time the initiator is ahead of the
6813511Sgabeblack@google.com    // systemC time) After changing the local time an initiator should
6913511Sgabeblack@google.com    // check (with the need_sync method) if a sync is required.
7013513Sgabeblack@google.com    virtual void set(const sc_core::sc_time &t) { m_local_time = t; }
7113511Sgabeblack@google.com
7213511Sgabeblack@google.com    // Checks if a sync to systemC is required for this initiator. This will
7313511Sgabeblack@google.com    // be the case if the local time becomes greater than the local (current)
7413511Sgabeblack@google.com    // quantum value for this initiator.
7513513Sgabeblack@google.com    virtual bool
7613513Sgabeblack@google.com    need_sync() const
7713511Sgabeblack@google.com    {
7813513Sgabeblack@google.com        return sc_core::sc_time_stamp() + m_local_time >= m_next_sync_point;
7913511Sgabeblack@google.com    }
8013511Sgabeblack@google.com
8113511Sgabeblack@google.com    // Synchronize to systemC. This call will do a wait for the time the
8213511Sgabeblack@google.com    // initiator was running ahead of systemC time and reset the
8313511Sgabeblack@google.com    // tlm_quantumkeeper.
8413513Sgabeblack@google.com    virtual void
8513513Sgabeblack@google.com    sync()
8613511Sgabeblack@google.com    {
8713513Sgabeblack@google.com        sc_core::wait(m_local_time);
8813513Sgabeblack@google.com        reset();
8913511Sgabeblack@google.com    }
9013511Sgabeblack@google.com
9113513Sgabeblack@google.com    // Non-virtual convenience method to set the local time and sync only if
9213513Sgabeblack@google.com    // needed
9313513Sgabeblack@google.com    void
9413513Sgabeblack@google.com    set_and_sync(const sc_core::sc_time &t)
9513511Sgabeblack@google.com    {
9613513Sgabeblack@google.com        set(t);
9713513Sgabeblack@google.com        if (need_sync())
9813513Sgabeblack@google.com            sync();
9913511Sgabeblack@google.com    }
10013511Sgabeblack@google.com
10113511Sgabeblack@google.com    // Resets the local time to SC_ZERO_TIME and computes the value of the
10213511Sgabeblack@google.com    // next local quantum. This method should be called by an initiator after
10313511Sgabeblack@google.com    // a wait because of a synchronization request by a target (TLM_ACCEPTED,
10413511Sgabeblack@google.com    // or TLM_UPDATED).
10513513Sgabeblack@google.com    virtual void
10613513Sgabeblack@google.com    reset()
10713511Sgabeblack@google.com    {
10813513Sgabeblack@google.com        m_local_time = sc_core::SC_ZERO_TIME;
10913513Sgabeblack@google.com        m_next_sync_point = sc_core::sc_time_stamp() + compute_local_quantum();
11013511Sgabeblack@google.com    }
11113511Sgabeblack@google.com
11213511Sgabeblack@google.com    // Helper function to get the current systemC time, taken the local time
11313511Sgabeblack@google.com    // into account. The current systemC time is calculated as the time
11413511Sgabeblack@google.com    // returned by sc_time_stamp incremeneted with the time the initiator is
11513511Sgabeblack@google.com    // running ahead.
11613513Sgabeblack@google.com    virtual sc_core::sc_time
11713513Sgabeblack@google.com    get_current_time() const
11813511Sgabeblack@google.com    {
11913513Sgabeblack@google.com        return sc_core::sc_time_stamp() + m_local_time;
12013511Sgabeblack@google.com    }
12113511Sgabeblack@google.com
12213511Sgabeblack@google.com    // Helper functions to get the time the initiator is running ahead of
12313511Sgabeblack@google.com    // systenC (local time). This time should be passed to a target in the
12413511Sgabeblack@google.com    // nb_transport call
12513513Sgabeblack@google.com    virtual sc_core::sc_time
12613513Sgabeblack@google.com    get_local_time() const
12713511Sgabeblack@google.com    {
12813513Sgabeblack@google.com        return m_local_time;
12913511Sgabeblack@google.com    }
13013511Sgabeblack@google.com
13113511Sgabeblack@google.com  protected:
13213511Sgabeblack@google.com    // Calculate the next local quantum for this initiator.
13313511Sgabeblack@google.com    //
13413511Sgabeblack@google.com    // The method can be overloaded in a derived object if an initiator wants
13513511Sgabeblack@google.com    // to use another local quantum. This derived object should also take the
13613511Sgabeblack@google.com    // global quantum into account. It's local quantum should not be set to a
13713511Sgabeblack@google.com    // value that is larger than the quantum returned by the
13813511Sgabeblack@google.com    // compute_local_quantum of the tlm_global_quantum singleton.
13913513Sgabeblack@google.com    virtual sc_core::sc_time
14013513Sgabeblack@google.com    compute_local_quantum()
14113511Sgabeblack@google.com    {
14213513Sgabeblack@google.com        return tlm::tlm_global_quantum::instance().compute_local_quantum();
14313511Sgabeblack@google.com    }
14413511Sgabeblack@google.com
14513511Sgabeblack@google.com  protected:
14613511Sgabeblack@google.com    sc_core::sc_time m_next_sync_point;
14713511Sgabeblack@google.com    sc_core::sc_time m_local_time;
14813513Sgabeblack@google.com};
14913511Sgabeblack@google.com
15013513Sgabeblack@google.com} // namespace tlm_utils
15113511Sgabeblack@google.com
15213513Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_UTILS_TLM_QUANTUMKEEPER_H__ */
153