clocked_object.hh revision 11527
19157Sandreas.hansson@arm.com/*
211524Sdavid.guillen@arm.com * Copyright (c) 2012-2013, 2015-2016 ARM Limited
310000Sclt67@cornell.edu * Copyright (c) 2013 Cornell University
49157Sandreas.hansson@arm.com * All rights reserved
59157Sandreas.hansson@arm.com *
69157Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
79157Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
89157Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
99157Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
109157Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
119157Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
129157Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
139157Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
149157Sandreas.hansson@arm.com *
159157Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
169157Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
179157Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
189157Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
199157Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
209157Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
219157Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
229157Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
239157Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
249157Sandreas.hansson@arm.com * this software without specific prior written permission.
259157Sandreas.hansson@arm.com *
269157Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
279157Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
289157Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
299157Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
309157Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
319157Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
329157Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
339157Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
349157Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
359157Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
369157Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
379157Sandreas.hansson@arm.com *
389157Sandreas.hansson@arm.com * Authors: Andreas Hansson
3910000Sclt67@cornell.edu *          Christopher Torng
4011524Sdavid.guillen@arm.com *          Akash Bagdia
4111524Sdavid.guillen@arm.com *          David Guillen Fandos
429157Sandreas.hansson@arm.com */
439157Sandreas.hansson@arm.com
449157Sandreas.hansson@arm.com/**
459157Sandreas.hansson@arm.com * @file
469157Sandreas.hansson@arm.com * ClockedObject declaration and implementation.
479157Sandreas.hansson@arm.com */
489157Sandreas.hansson@arm.com
499157Sandreas.hansson@arm.com#ifndef __SIM_CLOCKED_OBJECT_HH__
509157Sandreas.hansson@arm.com#define __SIM_CLOCKED_OBJECT_HH__
519157Sandreas.hansson@arm.com
5211524Sdavid.guillen@arm.com#include "base/callback.hh"
539157Sandreas.hansson@arm.com#include "base/intmath.hh"
549418Sandreas.hansson@arm.com#include "base/misc.hh"
5511524Sdavid.guillen@arm.com#include "enums/PwrState.hh"
569157Sandreas.hansson@arm.com#include "params/ClockedObject.hh"
579356Snilay@cs.wisc.edu#include "sim/core.hh"
589793Sakash.bagdia@arm.com#include "sim/clock_domain.hh"
599157Sandreas.hansson@arm.com#include "sim/sim_object.hh"
609157Sandreas.hansson@arm.com
619157Sandreas.hansson@arm.com/**
6211009Sandreas.sandberg@arm.com * Helper class for objects that need to be clocked. Clocked objects
6311009Sandreas.sandberg@arm.com * typically inherit from this class. Objects that need SimObject
6411009Sandreas.sandberg@arm.com * functionality as well should inherit from ClockedObject.
659157Sandreas.hansson@arm.com */
6611009Sandreas.sandberg@arm.comclass Clocked
679157Sandreas.hansson@arm.com{
689157Sandreas.hansson@arm.com
699157Sandreas.hansson@arm.com  private:
709179Sandreas.hansson@arm.com    // the tick value of the next clock edge (>= curTick()) at the
719179Sandreas.hansson@arm.com    // time of the last call to update()
729179Sandreas.hansson@arm.com    mutable Tick tick;
739179Sandreas.hansson@arm.com
749179Sandreas.hansson@arm.com    // The cycle counter value corresponding to the current value of
759179Sandreas.hansson@arm.com    // 'tick'
769180Sandreas.hansson@arm.com    mutable Cycles cycle;
779179Sandreas.hansson@arm.com
789157Sandreas.hansson@arm.com    /**
7910236Sjthestness@gmail.com     *  Align cycle and tick to the next clock edge if not already done. When
8010236Sjthestness@gmail.com     *  complete, tick must be at least curTick().
819179Sandreas.hansson@arm.com     */
829179Sandreas.hansson@arm.com    void update() const
839179Sandreas.hansson@arm.com    {
849179Sandreas.hansson@arm.com        // both tick and cycle are up-to-date and we are done, note
859179Sandreas.hansson@arm.com        // that the >= is important as it captures cases where tick
869179Sandreas.hansson@arm.com        // has already passed curTick()
879179Sandreas.hansson@arm.com        if (tick >= curTick())
889179Sandreas.hansson@arm.com            return;
899179Sandreas.hansson@arm.com
909179Sandreas.hansson@arm.com        // optimise for the common case and see if the tick should be
919179Sandreas.hansson@arm.com        // advanced by a single clock period
929793Sakash.bagdia@arm.com        tick += clockPeriod();
939179Sandreas.hansson@arm.com        ++cycle;
949179Sandreas.hansson@arm.com
959179Sandreas.hansson@arm.com        // see if we are done at this point
969179Sandreas.hansson@arm.com        if (tick >= curTick())
979179Sandreas.hansson@arm.com            return;
989179Sandreas.hansson@arm.com
999179Sandreas.hansson@arm.com        // if not, we have to recalculate the cycle and tick, we
1009179Sandreas.hansson@arm.com        // perform the calculations in terms of relative cycles to
1019179Sandreas.hansson@arm.com        // allow changes to the clock period in the future
1029793Sakash.bagdia@arm.com        Cycles elapsedCycles(divCeil(curTick() - tick, clockPeriod()));
1039179Sandreas.hansson@arm.com        cycle += elapsedCycles;
1049793Sakash.bagdia@arm.com        tick += elapsedCycles * clockPeriod();
1059179Sandreas.hansson@arm.com    }
1069179Sandreas.hansson@arm.com
1079793Sakash.bagdia@arm.com    /**
1089793Sakash.bagdia@arm.com     * The clock domain this clocked object belongs to
1099793Sakash.bagdia@arm.com     */
1109793Sakash.bagdia@arm.com    ClockDomain &clockDomain;
1119157Sandreas.hansson@arm.com
1129545Sandreas.hansson@arm.com  protected:
1139545Sandreas.hansson@arm.com
1149157Sandreas.hansson@arm.com    /**
1159793Sakash.bagdia@arm.com     * Create a clocked object and set the clock domain based on the
1169157Sandreas.hansson@arm.com     * parameters.
1179157Sandreas.hansson@arm.com     */
11811009Sandreas.sandberg@arm.com    Clocked(ClockDomain &clk_domain)
11911009Sandreas.sandberg@arm.com        : tick(0), cycle(0), clockDomain(clk_domain)
1209418Sandreas.hansson@arm.com    {
12110000Sclt67@cornell.edu        // Register with the clock domain, so that if the clock domain
12210000Sclt67@cornell.edu        // frequency changes, we can update this object's tick.
12310000Sclt67@cornell.edu        clockDomain.registerWithClockDomain(this);
1249418Sandreas.hansson@arm.com    }
1259157Sandreas.hansson@arm.com
12611009Sandreas.sandberg@arm.com    Clocked(Clocked &) = delete;
12711009Sandreas.sandberg@arm.com    Clocked &operator=(Clocked &) = delete;
12811009Sandreas.sandberg@arm.com
1299157Sandreas.hansson@arm.com    /**
1309157Sandreas.hansson@arm.com     * Virtual destructor due to inheritance.
1319157Sandreas.hansson@arm.com     */
13211009Sandreas.sandberg@arm.com    virtual ~Clocked() { }
1339157Sandreas.hansson@arm.com
1349296Snilay@cs.wisc.edu    /**
1359296Snilay@cs.wisc.edu     * Reset the object's clock using the current global tick value. Likely
1369296Snilay@cs.wisc.edu     * to be used only when the global clock is reset. Currently, this done
1379296Snilay@cs.wisc.edu     * only when Ruby is done warming up the memory system.
1389296Snilay@cs.wisc.edu     */
1399296Snilay@cs.wisc.edu    void resetClock() const
1409296Snilay@cs.wisc.edu    {
1419793Sakash.bagdia@arm.com        Cycles elapsedCycles(divCeil(curTick(), clockPeriod()));
1429296Snilay@cs.wisc.edu        cycle = elapsedCycles;
1439793Sakash.bagdia@arm.com        tick = elapsedCycles * clockPeriod();
1449296Snilay@cs.wisc.edu    }
1459296Snilay@cs.wisc.edu
1469157Sandreas.hansson@arm.com  public:
1479157Sandreas.hansson@arm.com
1489157Sandreas.hansson@arm.com    /**
14910000Sclt67@cornell.edu     * Update the tick to the current tick.
15010000Sclt67@cornell.edu     *
15110000Sclt67@cornell.edu     */
15210000Sclt67@cornell.edu    inline void updateClockPeriod() const
15310000Sclt67@cornell.edu    {
15410000Sclt67@cornell.edu        update();
15510000Sclt67@cornell.edu    }
15610000Sclt67@cornell.edu
15710000Sclt67@cornell.edu    /**
15810236Sjthestness@gmail.com     * Determine the tick when a cycle begins, by default the current one, but
15910236Sjthestness@gmail.com     * the argument also enables the caller to determine a future cycle. When
16010236Sjthestness@gmail.com     * curTick() is on a clock edge, the number of cycles in the parameter is
16110236Sjthestness@gmail.com     * added to curTick() to be returned. When curTick() is not aligned to a
16210236Sjthestness@gmail.com     * clock edge, the number of cycles in the parameter is added to the next
16310236Sjthestness@gmail.com     * clock edge.
1649179Sandreas.hansson@arm.com     *
1659179Sandreas.hansson@arm.com     * @param cycles The number of cycles into the future
1669179Sandreas.hansson@arm.com     *
16710236Sjthestness@gmail.com     * @return The start tick when the requested clock edge occurs. Precisely,
16810236Sjthestness@gmail.com     * this tick can be
16910236Sjthestness@gmail.com     *     curTick() + [0, clockPeriod()) + clockPeriod() * cycles
1709179Sandreas.hansson@arm.com     */
1719180Sandreas.hansson@arm.com    inline Tick clockEdge(Cycles cycles = Cycles(0)) const
1729179Sandreas.hansson@arm.com    {
1739179Sandreas.hansson@arm.com        // align tick to the next clock edge
1749179Sandreas.hansson@arm.com        update();
1759179Sandreas.hansson@arm.com
1769179Sandreas.hansson@arm.com        // figure out when this future cycle is
1779793Sakash.bagdia@arm.com        return tick + clockPeriod() * cycles;
1789179Sandreas.hansson@arm.com    }
1799179Sandreas.hansson@arm.com
1809179Sandreas.hansson@arm.com    /**
1819179Sandreas.hansson@arm.com     * Determine the current cycle, corresponding to a tick aligned to
1829179Sandreas.hansson@arm.com     * a clock edge.
1839179Sandreas.hansson@arm.com     *
18410236Sjthestness@gmail.com     * @return When curTick() is on a clock edge, return the Cycle corresponding
18510236Sjthestness@gmail.com     * to that clock edge. When curTick() is not on a clock edge, return the
18610236Sjthestness@gmail.com     * Cycle corresponding to the next clock edge.
1879179Sandreas.hansson@arm.com     */
1889180Sandreas.hansson@arm.com    inline Cycles curCycle() const
1899179Sandreas.hansson@arm.com    {
1909179Sandreas.hansson@arm.com        // align cycle to the next clock edge.
1919179Sandreas.hansson@arm.com        update();
1929179Sandreas.hansson@arm.com
1939179Sandreas.hansson@arm.com        return cycle;
1949179Sandreas.hansson@arm.com    }
1959179Sandreas.hansson@arm.com
1969179Sandreas.hansson@arm.com    /**
19710236Sjthestness@gmail.com     * Based on the clock of the object, determine the start tick of the first
19810236Sjthestness@gmail.com     * cycle that is at least one cycle in the future. When curTick() is at the
19910236Sjthestness@gmail.com     * current cycle edge, this returns the next clock edge. When calling this
20010236Sjthestness@gmail.com     * during the middle of a cycle, this returns 2 clock edges in the future.
2019157Sandreas.hansson@arm.com     *
20210236Sjthestness@gmail.com     * @return The start tick of the first cycle that is at least one cycle in
20310236Sjthestness@gmail.com     * the future. Precisely, the returned tick can be in the range
20410236Sjthestness@gmail.com     *     curTick() + [clockPeriod(), 2 * clockPeriod())
2059157Sandreas.hansson@arm.com     */
2069157Sandreas.hansson@arm.com    Tick nextCycle() const
2079648Sdam.sunwoo@arm.com    { return clockEdge(Cycles(1)); }
2089157Sandreas.hansson@arm.com
2099793Sakash.bagdia@arm.com    inline uint64_t frequency() const
2109793Sakash.bagdia@arm.com    {
2119793Sakash.bagdia@arm.com        return SimClock::Frequency / clockPeriod();
2129793Sakash.bagdia@arm.com    }
2139157Sandreas.hansson@arm.com
2149793Sakash.bagdia@arm.com    inline Tick clockPeriod() const
2159793Sakash.bagdia@arm.com    {
2169793Sakash.bagdia@arm.com        return clockDomain.clockPeriod();
2179793Sakash.bagdia@arm.com    }
2189157Sandreas.hansson@arm.com
21911366Sdavid.guillen@arm.com    inline double voltage() const
22011366Sdavid.guillen@arm.com    {
22111366Sdavid.guillen@arm.com        return clockDomain.voltage();
22211366Sdavid.guillen@arm.com    }
22311366Sdavid.guillen@arm.com
2249550Sandreas.hansson@arm.com    inline Cycles ticksToCycles(Tick t) const
2259987Snilay@cs.wisc.edu    { return Cycles(divCeil(t, clockPeriod())); }
2269157Sandreas.hansson@arm.com
22711018Snilay@cs.wisc.edu    inline Tick cyclesToTicks(Cycles c) const
22811018Snilay@cs.wisc.edu    { return clockPeriod() * c; }
2299157Sandreas.hansson@arm.com};
2309157Sandreas.hansson@arm.com
23111009Sandreas.sandberg@arm.com/**
23211009Sandreas.sandberg@arm.com * The ClockedObject class extends the SimObject with a clock and
23311009Sandreas.sandberg@arm.com * accessor functions to relate ticks to the cycles of the object.
23411009Sandreas.sandberg@arm.com */
23511009Sandreas.sandberg@arm.comclass ClockedObject
23611009Sandreas.sandberg@arm.com    : public SimObject, public Clocked
23711009Sandreas.sandberg@arm.com{
23811009Sandreas.sandberg@arm.com  public:
23911527Sdavid.guillen@arm.com    ClockedObject(const ClockedObjectParams *p);
24011524Sdavid.guillen@arm.com
24111524Sdavid.guillen@arm.com    /** Parameters of ClockedObject */
24211524Sdavid.guillen@arm.com    typedef ClockedObjectParams Params;
24311524Sdavid.guillen@arm.com    const Params* params() const
24411524Sdavid.guillen@arm.com    { return reinterpret_cast<const Params*>(_params); }
24511524Sdavid.guillen@arm.com
24611524Sdavid.guillen@arm.com    void serialize(CheckpointOut &cp) const override;
24711524Sdavid.guillen@arm.com    void unserialize(CheckpointIn &cp) override;
24811524Sdavid.guillen@arm.com
24911524Sdavid.guillen@arm.com    inline Enums::PwrState pwrState() const
25011524Sdavid.guillen@arm.com    { return _currPwrState; }
25111524Sdavid.guillen@arm.com
25211524Sdavid.guillen@arm.com    inline std::string pwrStateName() const
25311524Sdavid.guillen@arm.com    { return Enums::PwrStateStrings[_currPwrState]; }
25411524Sdavid.guillen@arm.com
25511524Sdavid.guillen@arm.com    /** Returns the percentage residency for each power state */
25611524Sdavid.guillen@arm.com    std::vector<double> pwrStateWeights() const;
25711524Sdavid.guillen@arm.com
25811524Sdavid.guillen@arm.com    /**
25911524Sdavid.guillen@arm.com     * Record stats values like state residency by computing the time
26011524Sdavid.guillen@arm.com     * difference from previous update. Also, updates the previous evaluation
26111524Sdavid.guillen@arm.com     * tick once all stats are recorded.
26211524Sdavid.guillen@arm.com     * Usually called on power state change and stats dump callback.
26311524Sdavid.guillen@arm.com     */
26411524Sdavid.guillen@arm.com    void computeStats();
26511524Sdavid.guillen@arm.com
26611524Sdavid.guillen@arm.com    void pwrState(Enums::PwrState);
26711524Sdavid.guillen@arm.com    void regStats();
26811524Sdavid.guillen@arm.com
26911524Sdavid.guillen@arm.com  protected:
27011524Sdavid.guillen@arm.com
27111524Sdavid.guillen@arm.com    /** To keep track of the current power state */
27211524Sdavid.guillen@arm.com    Enums::PwrState _currPwrState;
27311524Sdavid.guillen@arm.com
27411524Sdavid.guillen@arm.com    Tick prvEvalTick;
27511524Sdavid.guillen@arm.com
27611524Sdavid.guillen@arm.com    Stats::Scalar numPwrStateTransitions;
27711524Sdavid.guillen@arm.com    Stats::Distribution pwrStateClkGateDist;
27811524Sdavid.guillen@arm.com    Stats::Vector pwrStateResidencyTicks;
27911524Sdavid.guillen@arm.com
28011524Sdavid.guillen@arm.com};
28111524Sdavid.guillen@arm.com
28211524Sdavid.guillen@arm.comclass ClockedObjectDumpCallback : public Callback
28311524Sdavid.guillen@arm.com{
28411524Sdavid.guillen@arm.com    ClockedObject *co;
28511524Sdavid.guillen@arm.com  public:
28611524Sdavid.guillen@arm.com    ClockedObjectDumpCallback(ClockedObject *co_t) : co(co_t) {}
28711524Sdavid.guillen@arm.com    virtual void process() { co->computeStats(); };
28811009Sandreas.sandberg@arm.com};
28911009Sandreas.sandberg@arm.com
2909157Sandreas.hansson@arm.com#endif //__SIM_CLOCKED_OBJECT_HH__
291