clocked_object.hh revision 11524:3101ce98c55c
15625Sgblack@eecs.umich.edu/*
25625Sgblack@eecs.umich.edu * Copyright (c) 2012-2013, 2015-2016 ARM Limited
35625Sgblack@eecs.umich.edu * Copyright (c) 2013 Cornell University
45625Sgblack@eecs.umich.edu * All rights reserved
57087Snate@binkert.org *
67087Snate@binkert.org * The license below extends only to copyright in the software and shall
77087Snate@binkert.org * not be construed as granting a license to any other intellectual
87087Snate@binkert.org * property including but not limited to intellectual property relating
97087Snate@binkert.org * to a hardware implementation of the functionality of the software
107087Snate@binkert.org * licensed hereunder.  You may use the software subject to the license
117087Snate@binkert.org * terms below provided that you ensure that this notice is replicated
127087Snate@binkert.org * unmodified and in its entirety in all distributions of the software,
135625Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
147087Snate@binkert.org *
157087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
167087Snate@binkert.org * modification, are permitted provided that the following conditions are
177087Snate@binkert.org * met: redistributions of source code must retain the above copyright
187087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
197087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
207087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
217087Snate@binkert.org * documentation and/or other materials provided with the distribution;
225625Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
237087Snate@binkert.org * contributors may be used to endorse or promote products derived from
245625Sgblack@eecs.umich.edu * this software without specific prior written permission.
255625Sgblack@eecs.umich.edu *
265625Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
275625Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
285625Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
295625Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
305625Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
315625Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
325625Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
335625Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
345625Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
355625Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
365625Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
375625Sgblack@eecs.umich.edu *
385625Sgblack@eecs.umich.edu * Authors: Andreas Hansson
395625Sgblack@eecs.umich.edu *          Christopher Torng
405625Sgblack@eecs.umich.edu *          Akash Bagdia
415625Sgblack@eecs.umich.edu *          David Guillen Fandos
425625Sgblack@eecs.umich.edu */
435625Sgblack@eecs.umich.edu
445625Sgblack@eecs.umich.edu/**
455625Sgblack@eecs.umich.edu * @file
465625Sgblack@eecs.umich.edu * ClockedObject declaration and implementation.
475625Sgblack@eecs.umich.edu */
485625Sgblack@eecs.umich.edu
495625Sgblack@eecs.umich.edu#ifndef __SIM_CLOCKED_OBJECT_HH__
505625Sgblack@eecs.umich.edu#define __SIM_CLOCKED_OBJECT_HH__
515625Sgblack@eecs.umich.edu
528229Snate@binkert.org#include "base/callback.hh"
535625Sgblack@eecs.umich.edu#include "base/intmath.hh"
548706Sandreas.hansson@arm.com#include "base/misc.hh"
555625Sgblack@eecs.umich.edu#include "enums/PwrState.hh"
565625Sgblack@eecs.umich.edu#include "params/ClockedObject.hh"
578737Skoansin.tan@gmail.com#include "sim/core.hh"
588737Skoansin.tan@gmail.com#include "sim/clock_domain.hh"
595625Sgblack@eecs.umich.edu#include "sim/sim_object.hh"
605625Sgblack@eecs.umich.edu
618737Skoansin.tan@gmail.com/**
628737Skoansin.tan@gmail.com * Helper class for objects that need to be clocked. Clocked objects
635625Sgblack@eecs.umich.edu * typically inherit from this class. Objects that need SimObject
645625Sgblack@eecs.umich.edu * functionality as well should inherit from ClockedObject.
658737Skoansin.tan@gmail.com */
668737Skoansin.tan@gmail.comclass Clocked
678737Skoansin.tan@gmail.com{
688737Skoansin.tan@gmail.com
698737Skoansin.tan@gmail.com  private:
705625Sgblack@eecs.umich.edu    // the tick value of the next clock edge (>= curTick()) at the
715625Sgblack@eecs.umich.edu    // time of the last call to update()
728737Skoansin.tan@gmail.com    mutable Tick tick;
738737Skoansin.tan@gmail.com
748737Skoansin.tan@gmail.com    // The cycle counter value corresponding to the current value of
755625Sgblack@eecs.umich.edu    // 'tick'
765625Sgblack@eecs.umich.edu    mutable Cycles cycle;
775625Sgblack@eecs.umich.edu
785625Sgblack@eecs.umich.edu    /**
795625Sgblack@eecs.umich.edu     *  Align cycle and tick to the next clock edge if not already done. When
805625Sgblack@eecs.umich.edu     *  complete, tick must be at least curTick().
815625Sgblack@eecs.umich.edu     */
825625Sgblack@eecs.umich.edu    void update() const
835625Sgblack@eecs.umich.edu    {
845625Sgblack@eecs.umich.edu        // both tick and cycle are up-to-date and we are done, note
855625Sgblack@eecs.umich.edu        // that the >= is important as it captures cases where tick
865625Sgblack@eecs.umich.edu        // has already passed curTick()
875625Sgblack@eecs.umich.edu        if (tick >= curTick())
885625Sgblack@eecs.umich.edu            return;
895625Sgblack@eecs.umich.edu
905625Sgblack@eecs.umich.edu        // optimise for the common case and see if the tick should be
915625Sgblack@eecs.umich.edu        // advanced by a single clock period
925625Sgblack@eecs.umich.edu        tick += clockPeriod();
935625Sgblack@eecs.umich.edu        ++cycle;
945625Sgblack@eecs.umich.edu
955625Sgblack@eecs.umich.edu        // see if we are done at this point
968706Sandreas.hansson@arm.com        if (tick >= curTick())
975625Sgblack@eecs.umich.edu            return;
985625Sgblack@eecs.umich.edu
995625Sgblack@eecs.umich.edu        // if not, we have to recalculate the cycle and tick, we
1005625Sgblack@eecs.umich.edu        // perform the calculations in terms of relative cycles to
1015625Sgblack@eecs.umich.edu        // allow changes to the clock period in the future
1025625Sgblack@eecs.umich.edu        Cycles elapsedCycles(divCeil(curTick() - tick, clockPeriod()));
1035625Sgblack@eecs.umich.edu        cycle += elapsedCycles;
1045625Sgblack@eecs.umich.edu        tick += elapsedCycles * clockPeriod();
1055625Sgblack@eecs.umich.edu    }
1065625Sgblack@eecs.umich.edu
1075625Sgblack@eecs.umich.edu    /**
1085625Sgblack@eecs.umich.edu     * The clock domain this clocked object belongs to
1095625Sgblack@eecs.umich.edu     */
1105625Sgblack@eecs.umich.edu    ClockDomain &clockDomain;
1115625Sgblack@eecs.umich.edu
1125625Sgblack@eecs.umich.edu  protected:
1135625Sgblack@eecs.umich.edu
1145625Sgblack@eecs.umich.edu    /**
1155625Sgblack@eecs.umich.edu     * Create a clocked object and set the clock domain based on the
1165625Sgblack@eecs.umich.edu     * parameters.
1175625Sgblack@eecs.umich.edu     */
1185625Sgblack@eecs.umich.edu    Clocked(ClockDomain &clk_domain)
1195625Sgblack@eecs.umich.edu        : tick(0), cycle(0), clockDomain(clk_domain)
1208706Sandreas.hansson@arm.com    {
1215625Sgblack@eecs.umich.edu        // Register with the clock domain, so that if the clock domain
1225625Sgblack@eecs.umich.edu        // frequency changes, we can update this object's tick.
1235625Sgblack@eecs.umich.edu        clockDomain.registerWithClockDomain(this);
1245625Sgblack@eecs.umich.edu    }
1255625Sgblack@eecs.umich.edu
1265625Sgblack@eecs.umich.edu    Clocked(Clocked &) = delete;
1275625Sgblack@eecs.umich.edu    Clocked &operator=(Clocked &) = delete;
1285625Sgblack@eecs.umich.edu
1295625Sgblack@eecs.umich.edu    /**
1305625Sgblack@eecs.umich.edu     * Virtual destructor due to inheritance.
1315625Sgblack@eecs.umich.edu     */
1325625Sgblack@eecs.umich.edu    virtual ~Clocked() { }
1335625Sgblack@eecs.umich.edu
1345625Sgblack@eecs.umich.edu    /**
1358706Sandreas.hansson@arm.com     * Reset the object's clock using the current global tick value. Likely
1365625Sgblack@eecs.umich.edu     * to be used only when the global clock is reset. Currently, this done
1375625Sgblack@eecs.umich.edu     * only when Ruby is done warming up the memory system.
1385625Sgblack@eecs.umich.edu     */
1395625Sgblack@eecs.umich.edu    void resetClock() const
1405625Sgblack@eecs.umich.edu    {
1415625Sgblack@eecs.umich.edu        Cycles elapsedCycles(divCeil(curTick(), clockPeriod()));
1425625Sgblack@eecs.umich.edu        cycle = elapsedCycles;
1435625Sgblack@eecs.umich.edu        tick = elapsedCycles * clockPeriod();
1445625Sgblack@eecs.umich.edu    }
1455625Sgblack@eecs.umich.edu
1465625Sgblack@eecs.umich.edu  public:
1475625Sgblack@eecs.umich.edu
1485625Sgblack@eecs.umich.edu    /**
1495625Sgblack@eecs.umich.edu     * Update the tick to the current tick.
1505625Sgblack@eecs.umich.edu     *
1515625Sgblack@eecs.umich.edu     */
1525625Sgblack@eecs.umich.edu    inline void updateClockPeriod() const
1535625Sgblack@eecs.umich.edu    {
1545625Sgblack@eecs.umich.edu        update();
1555625Sgblack@eecs.umich.edu    }
1565625Sgblack@eecs.umich.edu
1575625Sgblack@eecs.umich.edu    /**
1588706Sandreas.hansson@arm.com     * Determine the tick when a cycle begins, by default the current one, but
1595625Sgblack@eecs.umich.edu     * the argument also enables the caller to determine a future cycle. When
1605625Sgblack@eecs.umich.edu     * curTick() is on a clock edge, the number of cycles in the parameter is
1615625Sgblack@eecs.umich.edu     * added to curTick() to be returned. When curTick() is not aligned to a
1625625Sgblack@eecs.umich.edu     * clock edge, the number of cycles in the parameter is added to the next
1635625Sgblack@eecs.umich.edu     * clock edge.
1645625Sgblack@eecs.umich.edu     *
1655625Sgblack@eecs.umich.edu     * @param cycles The number of cycles into the future
1665625Sgblack@eecs.umich.edu     *
1675625Sgblack@eecs.umich.edu     * @return The start tick when the requested clock edge occurs. Precisely,
1685625Sgblack@eecs.umich.edu     * this tick can be
1695625Sgblack@eecs.umich.edu     *     curTick() + [0, clockPeriod()) + clockPeriod() * cycles
1705625Sgblack@eecs.umich.edu     */
1715625Sgblack@eecs.umich.edu    inline Tick clockEdge(Cycles cycles = Cycles(0)) const
1725625Sgblack@eecs.umich.edu    {
1735625Sgblack@eecs.umich.edu        // align tick to the next clock edge
1745625Sgblack@eecs.umich.edu        update();
1758706Sandreas.hansson@arm.com
1765625Sgblack@eecs.umich.edu        // figure out when this future cycle is
1775625Sgblack@eecs.umich.edu        return tick + clockPeriod() * cycles;
1785625Sgblack@eecs.umich.edu    }
1795625Sgblack@eecs.umich.edu
1805625Sgblack@eecs.umich.edu    /**
1815625Sgblack@eecs.umich.edu     * Determine the current cycle, corresponding to a tick aligned to
1825625Sgblack@eecs.umich.edu     * a clock edge.
1835625Sgblack@eecs.umich.edu     *
1845625Sgblack@eecs.umich.edu     * @return When curTick() is on a clock edge, return the Cycle corresponding
1855625Sgblack@eecs.umich.edu     * to that clock edge. When curTick() is not on a clock edge, return the
1865625Sgblack@eecs.umich.edu     * Cycle corresponding to the next clock edge.
1875625Sgblack@eecs.umich.edu     */
1885625Sgblack@eecs.umich.edu    inline Cycles curCycle() const
1898706Sandreas.hansson@arm.com    {
1905625Sgblack@eecs.umich.edu        // align cycle to the next clock edge.
1915625Sgblack@eecs.umich.edu        update();
1925625Sgblack@eecs.umich.edu
1935625Sgblack@eecs.umich.edu        return cycle;
1945625Sgblack@eecs.umich.edu    }
1955625Sgblack@eecs.umich.edu
1965625Sgblack@eecs.umich.edu    /**
1975625Sgblack@eecs.umich.edu     * Based on the clock of the object, determine the start tick of the first
1985625Sgblack@eecs.umich.edu     * cycle that is at least one cycle in the future. When curTick() is at the
1995625Sgblack@eecs.umich.edu     * current cycle edge, this returns the next clock edge. When calling this
2005625Sgblack@eecs.umich.edu     * during the middle of a cycle, this returns 2 clock edges in the future.
2015625Sgblack@eecs.umich.edu     *
2025625Sgblack@eecs.umich.edu     * @return The start tick of the first cycle that is at least one cycle in
2035625Sgblack@eecs.umich.edu     * the future. Precisely, the returned tick can be in the range
2045625Sgblack@eecs.umich.edu     *     curTick() + [clockPeriod(), 2 * clockPeriod())
2058706Sandreas.hansson@arm.com     */
2065625Sgblack@eecs.umich.edu    Tick nextCycle() const
2075625Sgblack@eecs.umich.edu    { return clockEdge(Cycles(1)); }
2085625Sgblack@eecs.umich.edu
2095625Sgblack@eecs.umich.edu    inline uint64_t frequency() const
2105625Sgblack@eecs.umich.edu    {
2115625Sgblack@eecs.umich.edu        return SimClock::Frequency / clockPeriod();
2125625Sgblack@eecs.umich.edu    }
2135625Sgblack@eecs.umich.edu
2145625Sgblack@eecs.umich.edu    inline Tick clockPeriod() const
2155625Sgblack@eecs.umich.edu    {
2165625Sgblack@eecs.umich.edu        return clockDomain.clockPeriod();
2175625Sgblack@eecs.umich.edu    }
2185625Sgblack@eecs.umich.edu
2195625Sgblack@eecs.umich.edu    inline double voltage() const
2205625Sgblack@eecs.umich.edu    {
2215625Sgblack@eecs.umich.edu        return clockDomain.voltage();
2225625Sgblack@eecs.umich.edu    }
2235625Sgblack@eecs.umich.edu
2248706Sandreas.hansson@arm.com    inline Cycles ticksToCycles(Tick t) const
2255625Sgblack@eecs.umich.edu    { return Cycles(divCeil(t, clockPeriod())); }
2265625Sgblack@eecs.umich.edu
2275625Sgblack@eecs.umich.edu    inline Tick cyclesToTicks(Cycles c) const
2285625Sgblack@eecs.umich.edu    { return clockPeriod() * c; }
2295625Sgblack@eecs.umich.edu};
2305625Sgblack@eecs.umich.edu
2315625Sgblack@eecs.umich.edu/**
2325625Sgblack@eecs.umich.edu * The ClockedObject class extends the SimObject with a clock and
2335625Sgblack@eecs.umich.edu * accessor functions to relate ticks to the cycles of the object.
2345625Sgblack@eecs.umich.edu */
2355625Sgblack@eecs.umich.educlass ClockedObject
2365625Sgblack@eecs.umich.edu    : public SimObject, public Clocked
2375625Sgblack@eecs.umich.edu{
2385625Sgblack@eecs.umich.edu  public:
2395625Sgblack@eecs.umich.edu    ClockedObject(const ClockedObjectParams *p)
2405625Sgblack@eecs.umich.edu        : SimObject(p), Clocked(*p->clk_domain),
2415625Sgblack@eecs.umich.edu        _currPwrState(p->default_p_state),
2425625Sgblack@eecs.umich.edu        prvEvalTick(0)
2435625Sgblack@eecs.umich.edu    { }
2445625Sgblack@eecs.umich.edu
2455625Sgblack@eecs.umich.edu    /** Parameters of ClockedObject */
2465625Sgblack@eecs.umich.edu    typedef ClockedObjectParams Params;
2475625Sgblack@eecs.umich.edu    const Params* params() const
2485625Sgblack@eecs.umich.edu    { return reinterpret_cast<const Params*>(_params); }
2495625Sgblack@eecs.umich.edu
2505625Sgblack@eecs.umich.edu    void serialize(CheckpointOut &cp) const override;
2515625Sgblack@eecs.umich.edu    void unserialize(CheckpointIn &cp) override;
2525625Sgblack@eecs.umich.edu
2535625Sgblack@eecs.umich.edu    inline Enums::PwrState pwrState() const
2545625Sgblack@eecs.umich.edu    { return _currPwrState; }
2555625Sgblack@eecs.umich.edu
2565625Sgblack@eecs.umich.edu    inline std::string pwrStateName() const
2575625Sgblack@eecs.umich.edu    { return Enums::PwrStateStrings[_currPwrState]; }
2585625Sgblack@eecs.umich.edu
2595625Sgblack@eecs.umich.edu    /** Returns the percentage residency for each power state */
2605625Sgblack@eecs.umich.edu    std::vector<double> pwrStateWeights() const;
2615625Sgblack@eecs.umich.edu
2625625Sgblack@eecs.umich.edu    /**
2635625Sgblack@eecs.umich.edu     * Record stats values like state residency by computing the time
2645625Sgblack@eecs.umich.edu     * difference from previous update. Also, updates the previous evaluation
2655625Sgblack@eecs.umich.edu     * tick once all stats are recorded.
2665625Sgblack@eecs.umich.edu     * Usually called on power state change and stats dump callback.
2675625Sgblack@eecs.umich.edu     */
2685625Sgblack@eecs.umich.edu    void computeStats();
2695625Sgblack@eecs.umich.edu
2705625Sgblack@eecs.umich.edu    void pwrState(Enums::PwrState);
2715625Sgblack@eecs.umich.edu    void regStats();
2728706Sandreas.hansson@arm.com
2735625Sgblack@eecs.umich.edu  protected:
2745625Sgblack@eecs.umich.edu
2755625Sgblack@eecs.umich.edu    /** To keep track of the current power state */
2765625Sgblack@eecs.umich.edu    Enums::PwrState _currPwrState;
2775625Sgblack@eecs.umich.edu
2785625Sgblack@eecs.umich.edu    Tick prvEvalTick;
2795625Sgblack@eecs.umich.edu
2805625Sgblack@eecs.umich.edu    Stats::Scalar numPwrStateTransitions;
2815625Sgblack@eecs.umich.edu    Stats::Distribution pwrStateClkGateDist;
2825625Sgblack@eecs.umich.edu    Stats::Vector pwrStateResidencyTicks;
2835625Sgblack@eecs.umich.edu
2845625Sgblack@eecs.umich.edu};
2855625Sgblack@eecs.umich.edu
2865625Sgblack@eecs.umich.educlass ClockedObjectDumpCallback : public Callback
2878706Sandreas.hansson@arm.com{
2885625Sgblack@eecs.umich.edu    ClockedObject *co;
2895625Sgblack@eecs.umich.edu  public:
2905625Sgblack@eecs.umich.edu    ClockedObjectDumpCallback(ClockedObject *co_t) : co(co_t) {}
2915625Sgblack@eecs.umich.edu    virtual void process() { co->computeStats(); };
2925625Sgblack@eecs.umich.edu};
2935625Sgblack@eecs.umich.edu
2945625Sgblack@eecs.umich.edu#endif //__SIM_CLOCKED_OBJECT_HH__
2955625Sgblack@eecs.umich.edu