clocked_object.hh revision 14162
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"
5411524Sdavid.guillen@arm.com#include "enums/PwrState.hh"
559157Sandreas.hansson@arm.com#include "params/ClockedObject.hh"
569356Snilay@cs.wisc.edu#include "sim/core.hh"
579793Sakash.bagdia@arm.com#include "sim/clock_domain.hh"
589157Sandreas.hansson@arm.com#include "sim/sim_object.hh"
599157Sandreas.hansson@arm.com
609157Sandreas.hansson@arm.com/**
6111009Sandreas.sandberg@arm.com * Helper class for objects that need to be clocked. Clocked objects
6211009Sandreas.sandberg@arm.com * typically inherit from this class. Objects that need SimObject
6311009Sandreas.sandberg@arm.com * functionality as well should inherit from ClockedObject.
649157Sandreas.hansson@arm.com */
6511009Sandreas.sandberg@arm.comclass Clocked
669157Sandreas.hansson@arm.com{
679157Sandreas.hansson@arm.com
689157Sandreas.hansson@arm.com  private:
699179Sandreas.hansson@arm.com    // the tick value of the next clock edge (>= curTick()) at the
709179Sandreas.hansson@arm.com    // time of the last call to update()
719179Sandreas.hansson@arm.com    mutable Tick tick;
729179Sandreas.hansson@arm.com
739179Sandreas.hansson@arm.com    // The cycle counter value corresponding to the current value of
749179Sandreas.hansson@arm.com    // 'tick'
759180Sandreas.hansson@arm.com    mutable Cycles cycle;
769179Sandreas.hansson@arm.com
779157Sandreas.hansson@arm.com    /**
7810236Sjthestness@gmail.com     *  Align cycle and tick to the next clock edge if not already done. When
7910236Sjthestness@gmail.com     *  complete, tick must be at least curTick().
809179Sandreas.hansson@arm.com     */
8114162Sgabeblack@google.com    void
8214162Sgabeblack@google.com    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     */
13914162Sgabeblack@google.com    void
14014162Sgabeblack@google.com    resetClock() const
1419296Snilay@cs.wisc.edu    {
1429793Sakash.bagdia@arm.com        Cycles elapsedCycles(divCeil(curTick(), clockPeriod()));
1439296Snilay@cs.wisc.edu        cycle = elapsedCycles;
1449793Sakash.bagdia@arm.com        tick = elapsedCycles * clockPeriod();
1459296Snilay@cs.wisc.edu    }
1469296Snilay@cs.wisc.edu
1479157Sandreas.hansson@arm.com  public:
1489157Sandreas.hansson@arm.com
1499157Sandreas.hansson@arm.com    /**
15010000Sclt67@cornell.edu     * Update the tick to the current tick.
15110000Sclt67@cornell.edu     */
15214162Sgabeblack@google.com    void updateClockPeriod() const { update(); }
15310000Sclt67@cornell.edu
15410000Sclt67@cornell.edu    /**
15510236Sjthestness@gmail.com     * Determine the tick when a cycle begins, by default the current one, but
15610236Sjthestness@gmail.com     * the argument also enables the caller to determine a future cycle. When
15710236Sjthestness@gmail.com     * curTick() is on a clock edge, the number of cycles in the parameter is
15810236Sjthestness@gmail.com     * added to curTick() to be returned. When curTick() is not aligned to a
15910236Sjthestness@gmail.com     * clock edge, the number of cycles in the parameter is added to the next
16010236Sjthestness@gmail.com     * clock edge.
1619179Sandreas.hansson@arm.com     *
1629179Sandreas.hansson@arm.com     * @param cycles The number of cycles into the future
1639179Sandreas.hansson@arm.com     *
16410236Sjthestness@gmail.com     * @return The start tick when the requested clock edge occurs. Precisely,
16510236Sjthestness@gmail.com     * this tick can be
16610236Sjthestness@gmail.com     *     curTick() + [0, clockPeriod()) + clockPeriod() * cycles
1679179Sandreas.hansson@arm.com     */
16814162Sgabeblack@google.com    Tick
16914162Sgabeblack@google.com    clockEdge(Cycles cycles=Cycles(0)) const
1709179Sandreas.hansson@arm.com    {
1719179Sandreas.hansson@arm.com        // align tick to the next clock edge
1729179Sandreas.hansson@arm.com        update();
1739179Sandreas.hansson@arm.com
1749179Sandreas.hansson@arm.com        // figure out when this future cycle is
1759793Sakash.bagdia@arm.com        return tick + clockPeriod() * cycles;
1769179Sandreas.hansson@arm.com    }
1779179Sandreas.hansson@arm.com
1789179Sandreas.hansson@arm.com    /**
1799179Sandreas.hansson@arm.com     * Determine the current cycle, corresponding to a tick aligned to
1809179Sandreas.hansson@arm.com     * a clock edge.
1819179Sandreas.hansson@arm.com     *
18210236Sjthestness@gmail.com     * @return When curTick() is on a clock edge, return the Cycle corresponding
18310236Sjthestness@gmail.com     * to that clock edge. When curTick() is not on a clock edge, return the
18410236Sjthestness@gmail.com     * Cycle corresponding to the next clock edge.
1859179Sandreas.hansson@arm.com     */
18614162Sgabeblack@google.com    Cycles
18714162Sgabeblack@google.com    curCycle() const
1889179Sandreas.hansson@arm.com    {
1899179Sandreas.hansson@arm.com        // align cycle to the next clock edge.
1909179Sandreas.hansson@arm.com        update();
1919179Sandreas.hansson@arm.com
1929179Sandreas.hansson@arm.com        return cycle;
1939179Sandreas.hansson@arm.com    }
1949179Sandreas.hansson@arm.com
1959179Sandreas.hansson@arm.com    /**
19610236Sjthestness@gmail.com     * Based on the clock of the object, determine the start tick of the first
19710236Sjthestness@gmail.com     * cycle that is at least one cycle in the future. When curTick() is at the
19810236Sjthestness@gmail.com     * current cycle edge, this returns the next clock edge. When calling this
19910236Sjthestness@gmail.com     * during the middle of a cycle, this returns 2 clock edges in the future.
2009157Sandreas.hansson@arm.com     *
20110236Sjthestness@gmail.com     * @return The start tick of the first cycle that is at least one cycle in
20210236Sjthestness@gmail.com     * the future. Precisely, the returned tick can be in the range
20310236Sjthestness@gmail.com     *     curTick() + [clockPeriod(), 2 * clockPeriod())
2049157Sandreas.hansson@arm.com     */
20514162Sgabeblack@google.com    Tick nextCycle() const { return clockEdge(Cycles(1)); }
2069157Sandreas.hansson@arm.com
20714162Sgabeblack@google.com    uint64_t frequency() const { return SimClock::Frequency / clockPeriod(); }
20814162Sgabeblack@google.com
20914162Sgabeblack@google.com    Tick clockPeriod() const { return clockDomain.clockPeriod(); }
21014162Sgabeblack@google.com
21114162Sgabeblack@google.com    double voltage() const { return clockDomain.voltage(); }
21214162Sgabeblack@google.com
21314162Sgabeblack@google.com    Cycles
21414162Sgabeblack@google.com    ticksToCycles(Tick t) const
2159793Sakash.bagdia@arm.com    {
21614162Sgabeblack@google.com        return Cycles(divCeil(t, clockPeriod()));
2179793Sakash.bagdia@arm.com    }
2189157Sandreas.hansson@arm.com
21914162Sgabeblack@google.com    Tick cyclesToTicks(Cycles c) const { return clockPeriod() * c; }
2209157Sandreas.hansson@arm.com};
2219157Sandreas.hansson@arm.com
22211009Sandreas.sandberg@arm.com/**
22311009Sandreas.sandberg@arm.com * The ClockedObject class extends the SimObject with a clock and
22411009Sandreas.sandberg@arm.com * accessor functions to relate ticks to the cycles of the object.
22511009Sandreas.sandberg@arm.com */
22614162Sgabeblack@google.comclass ClockedObject : public SimObject, public Clocked
22711009Sandreas.sandberg@arm.com{
22811009Sandreas.sandberg@arm.com  public:
22911527Sdavid.guillen@arm.com    ClockedObject(const ClockedObjectParams *p);
23011524Sdavid.guillen@arm.com
23111524Sdavid.guillen@arm.com    /** Parameters of ClockedObject */
23211524Sdavid.guillen@arm.com    typedef ClockedObjectParams Params;
23314162Sgabeblack@google.com    const Params *
23414162Sgabeblack@google.com    params() const
23514162Sgabeblack@google.com    {
23614162Sgabeblack@google.com        return reinterpret_cast<const Params*>(_params);
23714162Sgabeblack@google.com    }
23811524Sdavid.guillen@arm.com
23911524Sdavid.guillen@arm.com    void serialize(CheckpointOut &cp) const override;
24011524Sdavid.guillen@arm.com    void unserialize(CheckpointIn &cp) override;
24111524Sdavid.guillen@arm.com
24214162Sgabeblack@google.com    Enums::PwrState pwrState() const { return _currPwrState; }
24311524Sdavid.guillen@arm.com
24414162Sgabeblack@google.com    std::string
24514162Sgabeblack@google.com    pwrStateName() const
24614162Sgabeblack@google.com    {
24714162Sgabeblack@google.com        return Enums::PwrStateStrings[_currPwrState];
24814162Sgabeblack@google.com    }
24911524Sdavid.guillen@arm.com
25011524Sdavid.guillen@arm.com    /** Returns the percentage residency for each power state */
25111524Sdavid.guillen@arm.com    std::vector<double> pwrStateWeights() const;
25211524Sdavid.guillen@arm.com
25311524Sdavid.guillen@arm.com    /**
25411524Sdavid.guillen@arm.com     * Record stats values like state residency by computing the time
25511524Sdavid.guillen@arm.com     * difference from previous update. Also, updates the previous evaluation
25611524Sdavid.guillen@arm.com     * tick once all stats are recorded.
25711524Sdavid.guillen@arm.com     * Usually called on power state change and stats dump callback.
25811524Sdavid.guillen@arm.com     */
25911524Sdavid.guillen@arm.com    void computeStats();
26011524Sdavid.guillen@arm.com
26111524Sdavid.guillen@arm.com    void pwrState(Enums::PwrState);
26211532Sandreas.hansson@arm.com    void regStats() override;
26311524Sdavid.guillen@arm.com
26411524Sdavid.guillen@arm.com  protected:
26511524Sdavid.guillen@arm.com
26611524Sdavid.guillen@arm.com    /** To keep track of the current power state */
26711524Sdavid.guillen@arm.com    Enums::PwrState _currPwrState;
26811524Sdavid.guillen@arm.com
26911524Sdavid.guillen@arm.com    Tick prvEvalTick;
27011524Sdavid.guillen@arm.com
27111524Sdavid.guillen@arm.com    Stats::Scalar numPwrStateTransitions;
27211524Sdavid.guillen@arm.com    Stats::Distribution pwrStateClkGateDist;
27311524Sdavid.guillen@arm.com    Stats::Vector pwrStateResidencyTicks;
27411524Sdavid.guillen@arm.com
27511524Sdavid.guillen@arm.com};
27611524Sdavid.guillen@arm.com
27711524Sdavid.guillen@arm.comclass ClockedObjectDumpCallback : public Callback
27811524Sdavid.guillen@arm.com{
27911524Sdavid.guillen@arm.com    ClockedObject *co;
28011524Sdavid.guillen@arm.com  public:
28111524Sdavid.guillen@arm.com    ClockedObjectDumpCallback(ClockedObject *co_t) : co(co_t) {}
28211524Sdavid.guillen@arm.com    virtual void process() { co->computeStats(); };
28311009Sandreas.sandberg@arm.com};
28411009Sandreas.sandberg@arm.com
2859157Sandreas.hansson@arm.com#endif //__SIM_CLOCKED_OBJECT_HH__
286