clocked_object.hh revision 9648
19157Sandreas.hansson@arm.com/*
29157Sandreas.hansson@arm.com * Copyright (c) 2012 ARM Limited
39157Sandreas.hansson@arm.com * All rights reserved
49157Sandreas.hansson@arm.com *
59157Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
69157Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
79157Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
89157Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
99157Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
109157Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
119157Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
129157Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
139157Sandreas.hansson@arm.com *
149157Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
159157Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
169157Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
179157Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
189157Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
199157Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
209157Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
219157Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
229157Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
239157Sandreas.hansson@arm.com * this software without specific prior written permission.
249157Sandreas.hansson@arm.com *
259157Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
269157Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
279157Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
289157Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
299157Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
309157Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
319157Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
329157Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
339157Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
349157Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
359157Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
369157Sandreas.hansson@arm.com *
379157Sandreas.hansson@arm.com * Authors: Andreas Hansson
389157Sandreas.hansson@arm.com */
399157Sandreas.hansson@arm.com
409157Sandreas.hansson@arm.com/**
419157Sandreas.hansson@arm.com * @file
429157Sandreas.hansson@arm.com * ClockedObject declaration and implementation.
439157Sandreas.hansson@arm.com */
449157Sandreas.hansson@arm.com
459157Sandreas.hansson@arm.com#ifndef __SIM_CLOCKED_OBJECT_HH__
469157Sandreas.hansson@arm.com#define __SIM_CLOCKED_OBJECT_HH__
479157Sandreas.hansson@arm.com
489157Sandreas.hansson@arm.com#include "base/intmath.hh"
499418Sandreas.hansson@arm.com#include "base/misc.hh"
509157Sandreas.hansson@arm.com#include "params/ClockedObject.hh"
519356Snilay@cs.wisc.edu#include "sim/core.hh"
529157Sandreas.hansson@arm.com#include "sim/sim_object.hh"
539157Sandreas.hansson@arm.com
549157Sandreas.hansson@arm.com/**
559157Sandreas.hansson@arm.com * The ClockedObject class extends the SimObject with a clock and
569157Sandreas.hansson@arm.com * accessor functions to relate ticks to the cycles of the object.
579157Sandreas.hansson@arm.com */
589157Sandreas.hansson@arm.comclass ClockedObject : public SimObject
599157Sandreas.hansson@arm.com{
609157Sandreas.hansson@arm.com
619157Sandreas.hansson@arm.com  private:
629157Sandreas.hansson@arm.com
639179Sandreas.hansson@arm.com    // the tick value of the next clock edge (>= curTick()) at the
649179Sandreas.hansson@arm.com    // time of the last call to update()
659179Sandreas.hansson@arm.com    mutable Tick tick;
669179Sandreas.hansson@arm.com
679179Sandreas.hansson@arm.com    // The cycle counter value corresponding to the current value of
689179Sandreas.hansson@arm.com    // 'tick'
699180Sandreas.hansson@arm.com    mutable Cycles cycle;
709179Sandreas.hansson@arm.com
719157Sandreas.hansson@arm.com    /**
729157Sandreas.hansson@arm.com     * Prevent inadvertent use of the copy constructor and assignment
739157Sandreas.hansson@arm.com     * operator by making them private.
749157Sandreas.hansson@arm.com     */
759157Sandreas.hansson@arm.com    ClockedObject(ClockedObject&);
769157Sandreas.hansson@arm.com    ClockedObject& operator=(ClockedObject&);
779157Sandreas.hansson@arm.com
789179Sandreas.hansson@arm.com    /**
799179Sandreas.hansson@arm.com     *  Align cycle and tick to the next clock edge if not already done.
809179Sandreas.hansson@arm.com     */
819179Sandreas.hansson@arm.com    void update() const
829179Sandreas.hansson@arm.com    {
839179Sandreas.hansson@arm.com        // both tick and cycle are up-to-date and we are done, note
849179Sandreas.hansson@arm.com        // that the >= is important as it captures cases where tick
859179Sandreas.hansson@arm.com        // has already passed curTick()
869179Sandreas.hansson@arm.com        if (tick >= curTick())
879179Sandreas.hansson@arm.com            return;
889179Sandreas.hansson@arm.com
899179Sandreas.hansson@arm.com        // optimise for the common case and see if the tick should be
909179Sandreas.hansson@arm.com        // advanced by a single clock period
919179Sandreas.hansson@arm.com        tick += clock;
929179Sandreas.hansson@arm.com        ++cycle;
939179Sandreas.hansson@arm.com
949179Sandreas.hansson@arm.com        // see if we are done at this point
959179Sandreas.hansson@arm.com        if (tick >= curTick())
969179Sandreas.hansson@arm.com            return;
979179Sandreas.hansson@arm.com
989179Sandreas.hansson@arm.com        // if not, we have to recalculate the cycle and tick, we
999179Sandreas.hansson@arm.com        // perform the calculations in terms of relative cycles to
1009179Sandreas.hansson@arm.com        // allow changes to the clock period in the future
1019180Sandreas.hansson@arm.com        Cycles elapsedCycles(divCeil(curTick() - tick, clock));
1029179Sandreas.hansson@arm.com        cycle += elapsedCycles;
1039179Sandreas.hansson@arm.com        tick += elapsedCycles * clock;
1049179Sandreas.hansson@arm.com    }
1059179Sandreas.hansson@arm.com
1069157Sandreas.hansson@arm.com    // Clock period in ticks
1079157Sandreas.hansson@arm.com    Tick clock;
1089157Sandreas.hansson@arm.com
1099545Sandreas.hansson@arm.com  protected:
1109545Sandreas.hansson@arm.com
1119157Sandreas.hansson@arm.com    /**
1129157Sandreas.hansson@arm.com     * Create a clocked object and set the clock based on the
1139157Sandreas.hansson@arm.com     * parameters.
1149157Sandreas.hansson@arm.com     */
1159179Sandreas.hansson@arm.com    ClockedObject(const ClockedObjectParams* p) :
1169179Sandreas.hansson@arm.com        SimObject(p), tick(0), cycle(0), clock(p->clock)
1179418Sandreas.hansson@arm.com    {
1189418Sandreas.hansson@arm.com        if (clock == 0) {
1199418Sandreas.hansson@arm.com            fatal("%s has a clock period of zero\n", name());
1209418Sandreas.hansson@arm.com        }
1219418Sandreas.hansson@arm.com    }
1229157Sandreas.hansson@arm.com
1239157Sandreas.hansson@arm.com    /**
1249157Sandreas.hansson@arm.com     * Virtual destructor due to inheritance.
1259157Sandreas.hansson@arm.com     */
1269157Sandreas.hansson@arm.com    virtual ~ClockedObject() { }
1279157Sandreas.hansson@arm.com
1289296Snilay@cs.wisc.edu    /**
1299296Snilay@cs.wisc.edu     * Reset the object's clock using the current global tick value. Likely
1309296Snilay@cs.wisc.edu     * to be used only when the global clock is reset. Currently, this done
1319296Snilay@cs.wisc.edu     * only when Ruby is done warming up the memory system.
1329296Snilay@cs.wisc.edu     */
1339296Snilay@cs.wisc.edu    void resetClock() const
1349296Snilay@cs.wisc.edu    {
1359296Snilay@cs.wisc.edu        Cycles elapsedCycles(divCeil(curTick(), clock));
1369296Snilay@cs.wisc.edu        cycle = elapsedCycles;
1379296Snilay@cs.wisc.edu        tick = elapsedCycles * clock;
1389296Snilay@cs.wisc.edu    }
1399296Snilay@cs.wisc.edu
1409157Sandreas.hansson@arm.com  public:
1419157Sandreas.hansson@arm.com
1429157Sandreas.hansson@arm.com    /**
1439179Sandreas.hansson@arm.com     * Determine the tick when a cycle begins, by default the current
1449179Sandreas.hansson@arm.com     * one, but the argument also enables the caller to determine a
1459179Sandreas.hansson@arm.com     * future cycle.
1469179Sandreas.hansson@arm.com     *
1479179Sandreas.hansson@arm.com     * @param cycles The number of cycles into the future
1489179Sandreas.hansson@arm.com     *
1499179Sandreas.hansson@arm.com     * @return The tick when the clock edge occurs
1509179Sandreas.hansson@arm.com     */
1519180Sandreas.hansson@arm.com    inline Tick clockEdge(Cycles cycles = Cycles(0)) const
1529179Sandreas.hansson@arm.com    {
1539179Sandreas.hansson@arm.com        // align tick to the next clock edge
1549179Sandreas.hansson@arm.com        update();
1559179Sandreas.hansson@arm.com
1569179Sandreas.hansson@arm.com        // figure out when this future cycle is
1579180Sandreas.hansson@arm.com        return tick + clock * cycles;
1589179Sandreas.hansson@arm.com    }
1599179Sandreas.hansson@arm.com
1609179Sandreas.hansson@arm.com    /**
1619179Sandreas.hansson@arm.com     * Determine the current cycle, corresponding to a tick aligned to
1629179Sandreas.hansson@arm.com     * a clock edge.
1639179Sandreas.hansson@arm.com     *
1649180Sandreas.hansson@arm.com     * @return The current cycle count
1659179Sandreas.hansson@arm.com     */
1669180Sandreas.hansson@arm.com    inline Cycles curCycle() const
1679179Sandreas.hansson@arm.com    {
1689179Sandreas.hansson@arm.com        // align cycle to the next clock edge.
1699179Sandreas.hansson@arm.com        update();
1709179Sandreas.hansson@arm.com
1719179Sandreas.hansson@arm.com        return cycle;
1729179Sandreas.hansson@arm.com    }
1739179Sandreas.hansson@arm.com
1749179Sandreas.hansson@arm.com    /**
1759648Sdam.sunwoo@arm.com     * Based on the clock of the object, determine the tick when the next
1769648Sdam.sunwoo@arm.com     * cycle begins, in other words, return the next clock edge.
1779648Sdam.sunwoo@arm.com     * (This can never be the current tick.)
1789157Sandreas.hansson@arm.com     *
1799157Sandreas.hansson@arm.com     * @return The tick when the next cycle starts
1809157Sandreas.hansson@arm.com     */
1819157Sandreas.hansson@arm.com    Tick nextCycle() const
1829648Sdam.sunwoo@arm.com    { return clockEdge(Cycles(1)); }
1839157Sandreas.hansson@arm.com
1849180Sandreas.hansson@arm.com    inline uint64_t frequency() const { return SimClock::Frequency / clock; }
1859157Sandreas.hansson@arm.com
1869179Sandreas.hansson@arm.com    inline Tick clockPeriod() const { return clock; }
1879157Sandreas.hansson@arm.com
1889550Sandreas.hansson@arm.com    inline Cycles ticksToCycles(Tick t) const
1899550Sandreas.hansson@arm.com    { return Cycles(t / clock); }
1909157Sandreas.hansson@arm.com
1919157Sandreas.hansson@arm.com};
1929157Sandreas.hansson@arm.com
1939157Sandreas.hansson@arm.com#endif //__SIM_CLOCKED_OBJECT_HH__
194