tlm_quantumkeeper.h revision 13586
17087Snate@binkert.org/*****************************************************************************
210959Sdavid.hashe@amd.com
37087Snate@binkert.org  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
47087Snate@binkert.org  more contributor license agreements.  See the NOTICE file distributed
57087Snate@binkert.org  with this work for additional information regarding copyright ownership.
67087Snate@binkert.org  Accellera licenses this file to you under the Apache License, Version 2.0
77087Snate@binkert.org  (the "License"); you may not use this file except in compliance with the
87087Snate@binkert.org  License.  You may obtain a copy of the License at
97087Snate@binkert.org
107087Snate@binkert.org    http://www.apache.org/licenses/LICENSE-2.0
117087Snate@binkert.org
127087Snate@binkert.org  Unless required by applicable law or agreed to in writing, software
137087Snate@binkert.org  distributed under the License is distributed on an "AS IS" BASIS,
145331Sgblack@eecs.umich.edu  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
155331Sgblack@eecs.umich.edu  implied.  See the License for the specific language governing
165331Sgblack@eecs.umich.edu  permissions and limitations under the License.
175331Sgblack@eecs.umich.edu
185331Sgblack@eecs.umich.edu *****************************************************************************/
195331Sgblack@eecs.umich.edu
205331Sgblack@eecs.umich.edu#ifndef __SYSTEMC_EXT_TLM_UTILS_TLM_QUANTUMKEEPER_H__
215331Sgblack@eecs.umich.edu#define __SYSTEMC_EXT_TLM_UTILS_TLM_QUANTUMKEEPER_H__
225331Sgblack@eecs.umich.edu
235331Sgblack@eecs.umich.edu#include "../core/sc_time.hh"
245331Sgblack@eecs.umich.edu
255331Sgblack@eecs.umich.edunamespace tlm_utils
265331Sgblack@eecs.umich.edu{
275331Sgblack@eecs.umich.edu
285331Sgblack@eecs.umich.edu// tlm_quantumkeeper class
295331Sgblack@eecs.umich.edu//
305331Sgblack@eecs.umich.edu// The tlm_quantumkeeper class is used to keep track of the local time in
315331Sgblack@eecs.umich.edu// an initiator (how much it has run ahead of the SystemC time), to
325331Sgblack@eecs.umich.edu// synchronize with SystemC time etc.
335331Sgblack@eecs.umich.educlass tlm_quantumkeeper
345331Sgblack@eecs.umich.edu{
355331Sgblack@eecs.umich.edu  public:
365331Sgblack@eecs.umich.edu    //
375331Sgblack@eecs.umich.edu    // Static setters/getters for the global quantum value.
385331Sgblack@eecs.umich.edu    //
395331Sgblack@eecs.umich.edu    // The global quantum is the maximum time an initiator can run ahead of
405331Sgblack@eecs.umich.edu    // SystemC time. All initiators will synchronize on timing points that are
415331Sgblack@eecs.umich.edu    // multiples of the global quantum value.
424276Sgblack@eecs.umich.edu    //
434276Sgblack@eecs.umich.edu    static void
444276Sgblack@eecs.umich.edu    set_global_quantum(const sc_core::sc_time &t)
454276Sgblack@eecs.umich.edu    {
4610593Sgabeblack@google.com        tlm::tlm_global_quantum::instance().set(t);
4710593Sgabeblack@google.com    }
4810593Sgabeblack@google.com
4910593Sgabeblack@google.com    static const sc_core::sc_time &
5010593Sgabeblack@google.com    get_global_quantum()
5110593Sgabeblack@google.com    {
5210593Sgabeblack@google.com        return tlm::tlm_global_quantum::instance().get();
5310593Sgabeblack@google.com    }
5410593Sgabeblack@google.com
5510593Sgabeblack@google.com  public:
5610593Sgabeblack@google.com    tlm_quantumkeeper() : m_next_sync_point(sc_core::SC_ZERO_TIME),
5710593Sgabeblack@google.com                          m_local_time(sc_core::SC_ZERO_TIME)
5810593Sgabeblack@google.com    {}
5910593Sgabeblack@google.com
6010593Sgabeblack@google.com    virtual ~tlm_quantumkeeper() {}
6110593Sgabeblack@google.com
6210593Sgabeblack@google.com    // Increment the local time (the time the initiator is ahead of the
6310593Sgabeblack@google.com    // systemC time) After incrementing the local time an initiator should
6410593Sgabeblack@google.com    // check (with the need_sync method) if a sync is required.
6510593Sgabeblack@google.com    virtual void inc(const sc_core::sc_time &t) { m_local_time += t; }
6610593Sgabeblack@google.com
6710593Sgabeblack@google.com    // Sets the local time (the time the initiator is ahead of the
6810593Sgabeblack@google.com    // systemC time) After changing the local time an initiator should
6910593Sgabeblack@google.com    // check (with the need_sync method) if a sync is required.
7010593Sgabeblack@google.com    virtual void set(const sc_core::sc_time &t) { m_local_time = t; }
715238Sgblack@eecs.umich.edu
7210593Sgabeblack@google.com    // Checks if a sync to systemC is required for this initiator. This will
7310593Sgabeblack@google.com    // be the case if the local time becomes greater than the local (current)
7410593Sgabeblack@google.com    // quantum value for this initiator.
7510593Sgabeblack@google.com    virtual bool
7610593Sgabeblack@google.com    need_sync() const
7710593Sgabeblack@google.com    {
7810593Sgabeblack@google.com        return sc_core::sc_time_stamp() + m_local_time >= m_next_sync_point;
7910593Sgabeblack@google.com    }
8010593Sgabeblack@google.com
8110593Sgabeblack@google.com    // Synchronize to systemC. This call will do a wait for the time the
8210593Sgabeblack@google.com    // initiator was running ahead of systemC time and reset the
8310593Sgabeblack@google.com    // tlm_quantumkeeper.
8410593Sgabeblack@google.com    virtual void
8510593Sgabeblack@google.com    sync()
8610593Sgabeblack@google.com    {
8710593Sgabeblack@google.com        sc_core::wait(m_local_time);
8810593Sgabeblack@google.com        reset();
896611Sgblack@eecs.umich.edu    }
9010593Sgabeblack@google.com
9110593Sgabeblack@google.com    // Non-virtual convenience method to set the local time and sync only if
9210593Sgabeblack@google.com    // needed
9310593Sgabeblack@google.com    void
9410593Sgabeblack@google.com    set_and_sync(const sc_core::sc_time &t)
9510593Sgabeblack@google.com    {
966611Sgblack@eecs.umich.edu        set(t);
9710593Sgabeblack@google.com        if (need_sync())
9810593Sgabeblack@google.com            sync();
9910593Sgabeblack@google.com    }
10010593Sgabeblack@google.com
10110593Sgabeblack@google.com    // Resets the local time to SC_ZERO_TIME and computes the value of the
10210593Sgabeblack@google.com    // next local quantum. This method should be called by an initiator after
10310593Sgabeblack@google.com    // a wait because of a synchronization request by a target (TLM_ACCEPTED,
1046611Sgblack@eecs.umich.edu    // or TLM_UPDATED).
1056611Sgblack@eecs.umich.edu    virtual void
10610593Sgabeblack@google.com    reset()
10710593Sgabeblack@google.com    {
10810593Sgabeblack@google.com        m_local_time = sc_core::SC_ZERO_TIME;
10910593Sgabeblack@google.com        m_next_sync_point = sc_core::sc_time_stamp() + compute_local_quantum();
11010593Sgabeblack@google.com    }
11110593Sgabeblack@google.com
11210593Sgabeblack@google.com    // Helper function to get the current systemC time, taken the local time
11310593Sgabeblack@google.com    // into account. The current systemC time is calculated as the time
11410593Sgabeblack@google.com    // returned by sc_time_stamp incremeneted with the time the initiator is
11510593Sgabeblack@google.com    // running ahead.
11610593Sgabeblack@google.com    virtual sc_core::sc_time
11710593Sgabeblack@google.com    get_current_time() const
11810593Sgabeblack@google.com    {
11910593Sgabeblack@google.com        return sc_core::sc_time_stamp() + m_local_time;
12010593Sgabeblack@google.com    }
12110593Sgabeblack@google.com
12210593Sgabeblack@google.com    // Helper functions to get the time the initiator is running ahead of
12310593Sgabeblack@google.com    // systenC (local time). This time should be passed to a target in the
12410593Sgabeblack@google.com    // nb_transport call
1255292Sgblack@eecs.umich.edu    virtual sc_core::sc_time
1266611Sgblack@eecs.umich.edu    get_local_time() const
1275238Sgblack@eecs.umich.edu    {
12810593Sgabeblack@google.com        return m_local_time;
12910593Sgabeblack@google.com    }
13010593Sgabeblack@google.com
13110593Sgabeblack@google.com  protected:
13210593Sgabeblack@google.com    // Calculate the next local quantum for this initiator.
13310593Sgabeblack@google.com    //
13410593Sgabeblack@google.com    // The method can be overloaded in a derived object if an initiator wants
13510593Sgabeblack@google.com    // to use another local quantum. This derived object should also take the
13610593Sgabeblack@google.com    // global quantum into account. It's local quantum should not be set to a
1375789Sgblack@eecs.umich.edu    // value that is larger than the quantum returned by the
1385789Sgblack@eecs.umich.edu    // compute_local_quantum of the tlm_global_quantum singleton.
13910593Sgabeblack@google.com    virtual sc_core::sc_time
1405908Sgblack@eecs.umich.edu    compute_local_quantum()
1414276Sgblack@eecs.umich.edu    {
14210593Sgabeblack@google.com        return tlm::tlm_global_quantum::instance().compute_local_quantum();
14310593Sgabeblack@google.com    }
14410593Sgabeblack@google.com
14510593Sgabeblack@google.com  protected:
14610593Sgabeblack@google.com    sc_core::sc_time m_next_sync_point;
14710593Sgabeblack@google.com    sc_core::sc_time m_local_time;
14810593Sgabeblack@google.com};
14910593Sgabeblack@google.com
15010593Sgabeblack@google.com} // namespace tlm_utils
15110593Sgabeblack@google.com
15210593Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_UTILS_TLM_QUANTUMKEEPER_H__ */
15310593Sgabeblack@google.com