clocked_object.hh revision 11018
19157Sandreas.hansson@arm.com/*
29793Sakash.bagdia@arm.com * Copyright (c) 2012-2013 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
409157Sandreas.hansson@arm.com */
419157Sandreas.hansson@arm.com
429157Sandreas.hansson@arm.com/**
439157Sandreas.hansson@arm.com * @file
449157Sandreas.hansson@arm.com * ClockedObject declaration and implementation.
459157Sandreas.hansson@arm.com */
469157Sandreas.hansson@arm.com
479157Sandreas.hansson@arm.com#ifndef __SIM_CLOCKED_OBJECT_HH__
489157Sandreas.hansson@arm.com#define __SIM_CLOCKED_OBJECT_HH__
499157Sandreas.hansson@arm.com
509157Sandreas.hansson@arm.com#include "base/intmath.hh"
519418Sandreas.hansson@arm.com#include "base/misc.hh"
529157Sandreas.hansson@arm.com#include "params/ClockedObject.hh"
539356Snilay@cs.wisc.edu#include "sim/core.hh"
549793Sakash.bagdia@arm.com#include "sim/clock_domain.hh"
559157Sandreas.hansson@arm.com#include "sim/sim_object.hh"
569157Sandreas.hansson@arm.com
579157Sandreas.hansson@arm.com/**
5811009Sandreas.sandberg@arm.com * Helper class for objects that need to be clocked. Clocked objects
5911009Sandreas.sandberg@arm.com * typically inherit from this class. Objects that need SimObject
6011009Sandreas.sandberg@arm.com * functionality as well should inherit from ClockedObject.
619157Sandreas.hansson@arm.com */
6211009Sandreas.sandberg@arm.comclass Clocked
639157Sandreas.hansson@arm.com{
649157Sandreas.hansson@arm.com
659157Sandreas.hansson@arm.com  private:
669179Sandreas.hansson@arm.com    // the tick value of the next clock edge (>= curTick()) at the
679179Sandreas.hansson@arm.com    // time of the last call to update()
689179Sandreas.hansson@arm.com    mutable Tick tick;
699179Sandreas.hansson@arm.com
709179Sandreas.hansson@arm.com    // The cycle counter value corresponding to the current value of
719179Sandreas.hansson@arm.com    // 'tick'
729180Sandreas.hansson@arm.com    mutable Cycles cycle;
739179Sandreas.hansson@arm.com
749157Sandreas.hansson@arm.com    /**
7510236Sjthestness@gmail.com     *  Align cycle and tick to the next clock edge if not already done. When
7610236Sjthestness@gmail.com     *  complete, tick must be at least curTick().
779179Sandreas.hansson@arm.com     */
789179Sandreas.hansson@arm.com    void update() const
799179Sandreas.hansson@arm.com    {
809179Sandreas.hansson@arm.com        // both tick and cycle are up-to-date and we are done, note
819179Sandreas.hansson@arm.com        // that the >= is important as it captures cases where tick
829179Sandreas.hansson@arm.com        // has already passed curTick()
839179Sandreas.hansson@arm.com        if (tick >= curTick())
849179Sandreas.hansson@arm.com            return;
859179Sandreas.hansson@arm.com
869179Sandreas.hansson@arm.com        // optimise for the common case and see if the tick should be
879179Sandreas.hansson@arm.com        // advanced by a single clock period
889793Sakash.bagdia@arm.com        tick += clockPeriod();
899179Sandreas.hansson@arm.com        ++cycle;
909179Sandreas.hansson@arm.com
919179Sandreas.hansson@arm.com        // see if we are done at this point
929179Sandreas.hansson@arm.com        if (tick >= curTick())
939179Sandreas.hansson@arm.com            return;
949179Sandreas.hansson@arm.com
959179Sandreas.hansson@arm.com        // if not, we have to recalculate the cycle and tick, we
969179Sandreas.hansson@arm.com        // perform the calculations in terms of relative cycles to
979179Sandreas.hansson@arm.com        // allow changes to the clock period in the future
989793Sakash.bagdia@arm.com        Cycles elapsedCycles(divCeil(curTick() - tick, clockPeriod()));
999179Sandreas.hansson@arm.com        cycle += elapsedCycles;
1009793Sakash.bagdia@arm.com        tick += elapsedCycles * clockPeriod();
1019179Sandreas.hansson@arm.com    }
1029179Sandreas.hansson@arm.com
1039793Sakash.bagdia@arm.com    /**
1049793Sakash.bagdia@arm.com     * The clock domain this clocked object belongs to
1059793Sakash.bagdia@arm.com     */
1069793Sakash.bagdia@arm.com    ClockDomain &clockDomain;
1079157Sandreas.hansson@arm.com
1089545Sandreas.hansson@arm.com  protected:
1099545Sandreas.hansson@arm.com
1109157Sandreas.hansson@arm.com    /**
1119793Sakash.bagdia@arm.com     * Create a clocked object and set the clock domain based on the
1129157Sandreas.hansson@arm.com     * parameters.
1139157Sandreas.hansson@arm.com     */
11411009Sandreas.sandberg@arm.com    Clocked(ClockDomain &clk_domain)
11511009Sandreas.sandberg@arm.com        : tick(0), cycle(0), clockDomain(clk_domain)
1169418Sandreas.hansson@arm.com    {
11710000Sclt67@cornell.edu        // Register with the clock domain, so that if the clock domain
11810000Sclt67@cornell.edu        // frequency changes, we can update this object's tick.
11910000Sclt67@cornell.edu        clockDomain.registerWithClockDomain(this);
1209418Sandreas.hansson@arm.com    }
1219157Sandreas.hansson@arm.com
12211009Sandreas.sandberg@arm.com    Clocked(Clocked &) = delete;
12311009Sandreas.sandberg@arm.com    Clocked &operator=(Clocked &) = delete;
12411009Sandreas.sandberg@arm.com
1259157Sandreas.hansson@arm.com    /**
1269157Sandreas.hansson@arm.com     * Virtual destructor due to inheritance.
1279157Sandreas.hansson@arm.com     */
12811009Sandreas.sandberg@arm.com    virtual ~Clocked() { }
1299157Sandreas.hansson@arm.com
1309296Snilay@cs.wisc.edu    /**
1319296Snilay@cs.wisc.edu     * Reset the object's clock using the current global tick value. Likely
1329296Snilay@cs.wisc.edu     * to be used only when the global clock is reset. Currently, this done
1339296Snilay@cs.wisc.edu     * only when Ruby is done warming up the memory system.
1349296Snilay@cs.wisc.edu     */
1359296Snilay@cs.wisc.edu    void resetClock() const
1369296Snilay@cs.wisc.edu    {
1379793Sakash.bagdia@arm.com        Cycles elapsedCycles(divCeil(curTick(), clockPeriod()));
1389296Snilay@cs.wisc.edu        cycle = elapsedCycles;
1399793Sakash.bagdia@arm.com        tick = elapsedCycles * clockPeriod();
1409296Snilay@cs.wisc.edu    }
1419296Snilay@cs.wisc.edu
1429157Sandreas.hansson@arm.com  public:
1439157Sandreas.hansson@arm.com
1449157Sandreas.hansson@arm.com    /**
14510000Sclt67@cornell.edu     * Update the tick to the current tick.
14610000Sclt67@cornell.edu     *
14710000Sclt67@cornell.edu     */
14810000Sclt67@cornell.edu    inline void updateClockPeriod() const
14910000Sclt67@cornell.edu    {
15010000Sclt67@cornell.edu        update();
15110000Sclt67@cornell.edu    }
15210000Sclt67@cornell.edu
15310000Sclt67@cornell.edu    /**
15410236Sjthestness@gmail.com     * Determine the tick when a cycle begins, by default the current one, but
15510236Sjthestness@gmail.com     * the argument also enables the caller to determine a future cycle. When
15610236Sjthestness@gmail.com     * curTick() is on a clock edge, the number of cycles in the parameter is
15710236Sjthestness@gmail.com     * added to curTick() to be returned. When curTick() is not aligned to a
15810236Sjthestness@gmail.com     * clock edge, the number of cycles in the parameter is added to the next
15910236Sjthestness@gmail.com     * clock edge.
1609179Sandreas.hansson@arm.com     *
1619179Sandreas.hansson@arm.com     * @param cycles The number of cycles into the future
1629179Sandreas.hansson@arm.com     *
16310236Sjthestness@gmail.com     * @return The start tick when the requested clock edge occurs. Precisely,
16410236Sjthestness@gmail.com     * this tick can be
16510236Sjthestness@gmail.com     *     curTick() + [0, clockPeriod()) + clockPeriod() * cycles
1669179Sandreas.hansson@arm.com     */
1679180Sandreas.hansson@arm.com    inline Tick clockEdge(Cycles cycles = Cycles(0)) const
1689179Sandreas.hansson@arm.com    {
1699179Sandreas.hansson@arm.com        // align tick to the next clock edge
1709179Sandreas.hansson@arm.com        update();
1719179Sandreas.hansson@arm.com
1729179Sandreas.hansson@arm.com        // figure out when this future cycle is
1739793Sakash.bagdia@arm.com        return tick + clockPeriod() * cycles;
1749179Sandreas.hansson@arm.com    }
1759179Sandreas.hansson@arm.com
1769179Sandreas.hansson@arm.com    /**
1779179Sandreas.hansson@arm.com     * Determine the current cycle, corresponding to a tick aligned to
1789179Sandreas.hansson@arm.com     * a clock edge.
1799179Sandreas.hansson@arm.com     *
18010236Sjthestness@gmail.com     * @return When curTick() is on a clock edge, return the Cycle corresponding
18110236Sjthestness@gmail.com     * to that clock edge. When curTick() is not on a clock edge, return the
18210236Sjthestness@gmail.com     * Cycle corresponding to the next clock edge.
1839179Sandreas.hansson@arm.com     */
1849180Sandreas.hansson@arm.com    inline Cycles curCycle() const
1859179Sandreas.hansson@arm.com    {
1869179Sandreas.hansson@arm.com        // align cycle to the next clock edge.
1879179Sandreas.hansson@arm.com        update();
1889179Sandreas.hansson@arm.com
1899179Sandreas.hansson@arm.com        return cycle;
1909179Sandreas.hansson@arm.com    }
1919179Sandreas.hansson@arm.com
1929179Sandreas.hansson@arm.com    /**
19310236Sjthestness@gmail.com     * Based on the clock of the object, determine the start tick of the first
19410236Sjthestness@gmail.com     * cycle that is at least one cycle in the future. When curTick() is at the
19510236Sjthestness@gmail.com     * current cycle edge, this returns the next clock edge. When calling this
19610236Sjthestness@gmail.com     * during the middle of a cycle, this returns 2 clock edges in the future.
1979157Sandreas.hansson@arm.com     *
19810236Sjthestness@gmail.com     * @return The start tick of the first cycle that is at least one cycle in
19910236Sjthestness@gmail.com     * the future. Precisely, the returned tick can be in the range
20010236Sjthestness@gmail.com     *     curTick() + [clockPeriod(), 2 * clockPeriod())
2019157Sandreas.hansson@arm.com     */
2029157Sandreas.hansson@arm.com    Tick nextCycle() const
2039648Sdam.sunwoo@arm.com    { return clockEdge(Cycles(1)); }
2049157Sandreas.hansson@arm.com
2059793Sakash.bagdia@arm.com    inline uint64_t frequency() const
2069793Sakash.bagdia@arm.com    {
2079793Sakash.bagdia@arm.com        return SimClock::Frequency / clockPeriod();
2089793Sakash.bagdia@arm.com    }
2099157Sandreas.hansson@arm.com
2109793Sakash.bagdia@arm.com    inline Tick clockPeriod() const
2119793Sakash.bagdia@arm.com    {
2129793Sakash.bagdia@arm.com        return clockDomain.clockPeriod();
2139793Sakash.bagdia@arm.com    }
2149157Sandreas.hansson@arm.com
2159550Sandreas.hansson@arm.com    inline Cycles ticksToCycles(Tick t) const
2169987Snilay@cs.wisc.edu    { return Cycles(divCeil(t, clockPeriod())); }
2179157Sandreas.hansson@arm.com
21811018Snilay@cs.wisc.edu    inline Tick cyclesToTicks(Cycles c) const
21911018Snilay@cs.wisc.edu    { 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 */
22611009Sandreas.sandberg@arm.comclass ClockedObject
22711009Sandreas.sandberg@arm.com    : public SimObject, public Clocked
22811009Sandreas.sandberg@arm.com{
22911009Sandreas.sandberg@arm.com  public:
23011009Sandreas.sandberg@arm.com    ClockedObject(const ClockedObjectParams *p)
23111009Sandreas.sandberg@arm.com        : SimObject(p), Clocked(*p->clk_domain) { }
23211009Sandreas.sandberg@arm.com};
23311009Sandreas.sandberg@arm.com
2349157Sandreas.hansson@arm.com#endif //__SIM_CLOCKED_OBJECT_HH__
235