clocked_object.hh revision 10236
12789Sktlim@umich.edu/*
28733Sgeoffrey.blake@arm.com * Copyright (c) 2012-2013 ARM Limited
38733Sgeoffrey.blake@arm.com * Copyright (c) 2013 Cornell University
48733Sgeoffrey.blake@arm.com * All rights reserved
58733Sgeoffrey.blake@arm.com *
68733Sgeoffrey.blake@arm.com * The license below extends only to copyright in the software and shall
78733Sgeoffrey.blake@arm.com * not be construed as granting a license to any other intellectual
88733Sgeoffrey.blake@arm.com * property including but not limited to intellectual property relating
98733Sgeoffrey.blake@arm.com * to a hardware implementation of the functionality of the software
108733Sgeoffrey.blake@arm.com * licensed hereunder.  You may use the software subject to the license
118733Sgeoffrey.blake@arm.com * terms below provided that you ensure that this notice is replicated
128733Sgeoffrey.blake@arm.com * unmodified and in its entirety in all distributions of the software,
138733Sgeoffrey.blake@arm.com * modified or unmodified, in source code or in binary form.
142789Sktlim@umich.edu *
152789Sktlim@umich.edu * Redistribution and use in source and binary forms, with or without
162789Sktlim@umich.edu * modification, are permitted provided that the following conditions are
172789Sktlim@umich.edu * met: redistributions of source code must retain the above copyright
182789Sktlim@umich.edu * notice, this list of conditions and the following disclaimer;
192789Sktlim@umich.edu * redistributions in binary form must reproduce the above copyright
202789Sktlim@umich.edu * notice, this list of conditions and the following disclaimer in the
212789Sktlim@umich.edu * documentation and/or other materials provided with the distribution;
222789Sktlim@umich.edu * neither the name of the copyright holders nor the names of its
232789Sktlim@umich.edu * contributors may be used to endorse or promote products derived from
242789Sktlim@umich.edu * this software without specific prior written permission.
252789Sktlim@umich.edu *
262789Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
272789Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
282789Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
292789Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
302789Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
312789Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
322789Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
332789Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
342789Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
352789Sktlim@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
362789Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
372789Sktlim@umich.edu *
382789Sktlim@umich.edu * Authors: Andreas Hansson
392789Sktlim@umich.edu *          Christopher Torng
402789Sktlim@umich.edu */
418733Sgeoffrey.blake@arm.com
422789Sktlim@umich.edu/**
432789Sktlim@umich.edu * @file
442789Sktlim@umich.edu * ClockedObject declaration and implementation.
452789Sktlim@umich.edu */
462789Sktlim@umich.edu
478229Snate@binkert.org#ifndef __SIM_CLOCKED_OBJECT_HH__
482789Sktlim@umich.edu#define __SIM_CLOCKED_OBJECT_HH__
492789Sktlim@umich.edu
503348Sbinkertn@umich.edu#include "base/intmath.hh"
512789Sktlim@umich.edu#include "base/misc.hh"
528733Sgeoffrey.blake@arm.com#include "params/ClockedObject.hh"
538733Sgeoffrey.blake@arm.com#include "sim/core.hh"
542789Sktlim@umich.edu#include "sim/clock_domain.hh"
552789Sktlim@umich.edu#include "sim/sim_object.hh"
563565Sgblack@eecs.umich.edu
572789Sktlim@umich.edu/**
582789Sktlim@umich.edu * The ClockedObject class extends the SimObject with a clock and
592789Sktlim@umich.edu * accessor functions to relate ticks to the cycles of the object.
602789Sktlim@umich.edu */
618733Sgeoffrey.blake@arm.comclass ClockedObject : public SimObject
622789Sktlim@umich.edu{
632789Sktlim@umich.edu
642789Sktlim@umich.edu  private:
652789Sktlim@umich.edu
662789Sktlim@umich.edu    // the tick value of the next clock edge (>= curTick()) at the
672789Sktlim@umich.edu    // time of the last call to update()
682789Sktlim@umich.edu    mutable Tick tick;
692789Sktlim@umich.edu
702789Sktlim@umich.edu    // The cycle counter value corresponding to the current value of
712789Sktlim@umich.edu    // 'tick'
728733Sgeoffrey.blake@arm.com    mutable Cycles cycle;
738733Sgeoffrey.blake@arm.com
742789Sktlim@umich.edu    /**
752789Sktlim@umich.edu     * Prevent inadvertent use of the copy constructor and assignment
762789Sktlim@umich.edu     * operator by making them private.
772789Sktlim@umich.edu     */
782789Sktlim@umich.edu    ClockedObject(ClockedObject&);
792789Sktlim@umich.edu    ClockedObject& operator=(ClockedObject&);
802789Sktlim@umich.edu
812789Sktlim@umich.edu    /**
822789Sktlim@umich.edu     *  Align cycle and tick to the next clock edge if not already done. When
832789Sktlim@umich.edu     *  complete, tick must be at least curTick().
842789Sktlim@umich.edu     */
852789Sktlim@umich.edu    void update() const
862789Sktlim@umich.edu    {
878733Sgeoffrey.blake@arm.com        // both tick and cycle are up-to-date and we are done, note
882789Sktlim@umich.edu        // that the >= is important as it captures cases where tick
892789Sktlim@umich.edu        // has already passed curTick()
908733Sgeoffrey.blake@arm.com        if (tick >= curTick())
918733Sgeoffrey.blake@arm.com            return;
928733Sgeoffrey.blake@arm.com
933402Sktlim@umich.edu        // optimise for the common case and see if the tick should be
943402Sktlim@umich.edu        // advanced by a single clock period
953402Sktlim@umich.edu        tick += clockPeriod();
962789Sktlim@umich.edu        ++cycle;
972789Sktlim@umich.edu
988733Sgeoffrey.blake@arm.com        // see if we are done at this point
992789Sktlim@umich.edu        if (tick >= curTick())
1002789Sktlim@umich.edu            return;
1012789Sktlim@umich.edu
1022789Sktlim@umich.edu        // if not, we have to recalculate the cycle and tick, we
1032789Sktlim@umich.edu        // perform the calculations in terms of relative cycles to
1042789Sktlim@umich.edu        // allow changes to the clock period in the future
1052789Sktlim@umich.edu        Cycles elapsedCycles(divCeil(curTick() - tick, clockPeriod()));
1062789Sktlim@umich.edu        cycle += elapsedCycles;
1072789Sktlim@umich.edu        tick += elapsedCycles * clockPeriod();
1082789Sktlim@umich.edu    }
1092789Sktlim@umich.edu
1102789Sktlim@umich.edu    /**
1112789Sktlim@umich.edu     * The clock domain this clocked object belongs to
1122789Sktlim@umich.edu     */
1132789Sktlim@umich.edu    ClockDomain &clockDomain;
1142789Sktlim@umich.edu
1152789Sktlim@umich.edu  protected:
1162789Sktlim@umich.edu
1172789Sktlim@umich.edu    /**
1182789Sktlim@umich.edu     * Create a clocked object and set the clock domain based on the
1192789Sktlim@umich.edu     * parameters.
1202789Sktlim@umich.edu     */
1212789Sktlim@umich.edu    ClockedObject(const ClockedObjectParams* p) :
1222789Sktlim@umich.edu        SimObject(p), tick(0), cycle(0), clockDomain(*p->clk_domain)
1232789Sktlim@umich.edu    {
1242789Sktlim@umich.edu        // Register with the clock domain, so that if the clock domain
1252789Sktlim@umich.edu        // frequency changes, we can update this object's tick.
1262789Sktlim@umich.edu        clockDomain.registerWithClockDomain(this);
1272789Sktlim@umich.edu    }
1282789Sktlim@umich.edu
1292789Sktlim@umich.edu    /**
1302789Sktlim@umich.edu     * Virtual destructor due to inheritance.
1312789Sktlim@umich.edu     */
1322789Sktlim@umich.edu    virtual ~ClockedObject() { }
1332789Sktlim@umich.edu
1342789Sktlim@umich.edu    /**
1352789Sktlim@umich.edu     * Reset the object's clock using the current global tick value. Likely
1362789Sktlim@umich.edu     * to be used only when the global clock is reset. Currently, this done
1372789Sktlim@umich.edu     * only when Ruby is done warming up the memory system.
1382789Sktlim@umich.edu     */
1392789Sktlim@umich.edu    void resetClock() const
1402789Sktlim@umich.edu    {
1412789Sktlim@umich.edu        Cycles elapsedCycles(divCeil(curTick(), clockPeriod()));
1422789Sktlim@umich.edu        cycle = elapsedCycles;
1438733Sgeoffrey.blake@arm.com        tick = elapsedCycles * clockPeriod();
1442789Sktlim@umich.edu    }
1458733Sgeoffrey.blake@arm.com
1468733Sgeoffrey.blake@arm.com  public:
1478733Sgeoffrey.blake@arm.com
1488733Sgeoffrey.blake@arm.com    /**
1498733Sgeoffrey.blake@arm.com     * Update the tick to the current tick.
1508733Sgeoffrey.blake@arm.com     *
1518733Sgeoffrey.blake@arm.com     */
1522789Sktlim@umich.edu    inline void updateClockPeriod() const
1532789Sktlim@umich.edu    {
1548733Sgeoffrey.blake@arm.com        update();
1558733Sgeoffrey.blake@arm.com    }
1562789Sktlim@umich.edu
1578733Sgeoffrey.blake@arm.com    /**
1588733Sgeoffrey.blake@arm.com     * Determine the tick when a cycle begins, by default the current one, but
1598733Sgeoffrey.blake@arm.com     * the argument also enables the caller to determine a future cycle. When
1608733Sgeoffrey.blake@arm.com     * curTick() is on a clock edge, the number of cycles in the parameter is
1612789Sktlim@umich.edu     * added to curTick() to be returned. When curTick() is not aligned to a
1628733Sgeoffrey.blake@arm.com     * clock edge, the number of cycles in the parameter is added to the next
1638733Sgeoffrey.blake@arm.com     * clock edge.
1642789Sktlim@umich.edu     *
1658733Sgeoffrey.blake@arm.com     * @param cycles The number of cycles into the future
1668733Sgeoffrey.blake@arm.com     *
1678733Sgeoffrey.blake@arm.com     * @return The start tick when the requested clock edge occurs. Precisely,
1688733Sgeoffrey.blake@arm.com     * this tick can be
1698733Sgeoffrey.blake@arm.com     *     curTick() + [0, clockPeriod()) + clockPeriod() * cycles
1708733Sgeoffrey.blake@arm.com     */
1718733Sgeoffrey.blake@arm.com    inline Tick clockEdge(Cycles cycles = Cycles(0)) const
1728733Sgeoffrey.blake@arm.com    {
1738733Sgeoffrey.blake@arm.com        // align tick to the next clock edge
1748733Sgeoffrey.blake@arm.com        update();
1758733Sgeoffrey.blake@arm.com
1768733Sgeoffrey.blake@arm.com        // figure out when this future cycle is
1778733Sgeoffrey.blake@arm.com        return tick + clockPeriod() * cycles;
1788733Sgeoffrey.blake@arm.com    }
1798733Sgeoffrey.blake@arm.com
1808733Sgeoffrey.blake@arm.com    /**
1818733Sgeoffrey.blake@arm.com     * Determine the current cycle, corresponding to a tick aligned to
1828733Sgeoffrey.blake@arm.com     * a clock edge.
1838733Sgeoffrey.blake@arm.com     *
1848733Sgeoffrey.blake@arm.com     * @return When curTick() is on a clock edge, return the Cycle corresponding
1858733Sgeoffrey.blake@arm.com     * to that clock edge. When curTick() is not on a clock edge, return the
1868733Sgeoffrey.blake@arm.com     * Cycle corresponding to the next clock edge.
1878733Sgeoffrey.blake@arm.com     */
1888733Sgeoffrey.blake@arm.com    inline Cycles curCycle() const
1898733Sgeoffrey.blake@arm.com    {
1908733Sgeoffrey.blake@arm.com        // align cycle to the next clock edge.
1918733Sgeoffrey.blake@arm.com        update();
1928733Sgeoffrey.blake@arm.com
1938733Sgeoffrey.blake@arm.com        return cycle;
1948733Sgeoffrey.blake@arm.com    }
1958733Sgeoffrey.blake@arm.com
1968733Sgeoffrey.blake@arm.com    /**
1978733Sgeoffrey.blake@arm.com     * Based on the clock of the object, determine the start tick of the first
1988733Sgeoffrey.blake@arm.com     * cycle that is at least one cycle in the future. When curTick() is at the
1998733Sgeoffrey.blake@arm.com     * current cycle edge, this returns the next clock edge. When calling this
2008733Sgeoffrey.blake@arm.com     * during the middle of a cycle, this returns 2 clock edges in the future.
2018733Sgeoffrey.blake@arm.com     *
2028733Sgeoffrey.blake@arm.com     * @return The start tick of the first cycle that is at least one cycle in
2038733Sgeoffrey.blake@arm.com     * the future. Precisely, the returned tick can be in the range
2048733Sgeoffrey.blake@arm.com     *     curTick() + [clockPeriod(), 2 * clockPeriod())
2058733Sgeoffrey.blake@arm.com     */
2068733Sgeoffrey.blake@arm.com    Tick nextCycle() const
2078733Sgeoffrey.blake@arm.com    { return clockEdge(Cycles(1)); }
2088733Sgeoffrey.blake@arm.com
2098733Sgeoffrey.blake@arm.com    inline uint64_t frequency() const
2108733Sgeoffrey.blake@arm.com    {
2118733Sgeoffrey.blake@arm.com        return SimClock::Frequency / clockPeriod();
2128733Sgeoffrey.blake@arm.com    }
2138733Sgeoffrey.blake@arm.com
2148733Sgeoffrey.blake@arm.com    inline Tick clockPeriod() const
2158733Sgeoffrey.blake@arm.com    {
2168733Sgeoffrey.blake@arm.com        return clockDomain.clockPeriod();
2178733Sgeoffrey.blake@arm.com    }
2188733Sgeoffrey.blake@arm.com
2192789Sktlim@umich.edu    inline Cycles ticksToCycles(Tick t) const
2202789Sktlim@umich.edu    { return Cycles(divCeil(t, clockPeriod())); }
2218733Sgeoffrey.blake@arm.com
2228733Sgeoffrey.blake@arm.com};
2238733Sgeoffrey.blake@arm.com
2248733Sgeoffrey.blake@arm.com#endif //__SIM_CLOCKED_OBJECT_HH__
2258733Sgeoffrey.blake@arm.com