clocked_object.hh revision 10236
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/**
589157Sandreas.hansson@arm.com * The ClockedObject class extends the SimObject with a clock and
599157Sandreas.hansson@arm.com * accessor functions to relate ticks to the cycles of the object.
609157Sandreas.hansson@arm.com */
619157Sandreas.hansson@arm.comclass ClockedObject : public SimObject
629157Sandreas.hansson@arm.com{
639157Sandreas.hansson@arm.com
649157Sandreas.hansson@arm.com  private:
659157Sandreas.hansson@arm.com
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    /**
759157Sandreas.hansson@arm.com     * Prevent inadvertent use of the copy constructor and assignment
769157Sandreas.hansson@arm.com     * operator by making them private.
779157Sandreas.hansson@arm.com     */
789157Sandreas.hansson@arm.com    ClockedObject(ClockedObject&);
799157Sandreas.hansson@arm.com    ClockedObject& operator=(ClockedObject&);
809157Sandreas.hansson@arm.com
819179Sandreas.hansson@arm.com    /**
8210236Sjthestness@gmail.com     *  Align cycle and tick to the next clock edge if not already done. When
8310236Sjthestness@gmail.com     *  complete, tick must be at least curTick().
849179Sandreas.hansson@arm.com     */
859179Sandreas.hansson@arm.com    void update() const
869179Sandreas.hansson@arm.com    {
879179Sandreas.hansson@arm.com        // both tick and cycle are up-to-date and we are done, note
889179Sandreas.hansson@arm.com        // that the >= is important as it captures cases where tick
899179Sandreas.hansson@arm.com        // has already passed curTick()
909179Sandreas.hansson@arm.com        if (tick >= curTick())
919179Sandreas.hansson@arm.com            return;
929179Sandreas.hansson@arm.com
939179Sandreas.hansson@arm.com        // optimise for the common case and see if the tick should be
949179Sandreas.hansson@arm.com        // advanced by a single clock period
959793Sakash.bagdia@arm.com        tick += clockPeriod();
969179Sandreas.hansson@arm.com        ++cycle;
979179Sandreas.hansson@arm.com
989179Sandreas.hansson@arm.com        // see if we are done at this point
999179Sandreas.hansson@arm.com        if (tick >= curTick())
1009179Sandreas.hansson@arm.com            return;
1019179Sandreas.hansson@arm.com
1029179Sandreas.hansson@arm.com        // if not, we have to recalculate the cycle and tick, we
1039179Sandreas.hansson@arm.com        // perform the calculations in terms of relative cycles to
1049179Sandreas.hansson@arm.com        // allow changes to the clock period in the future
1059793Sakash.bagdia@arm.com        Cycles elapsedCycles(divCeil(curTick() - tick, clockPeriod()));
1069179Sandreas.hansson@arm.com        cycle += elapsedCycles;
1079793Sakash.bagdia@arm.com        tick += elapsedCycles * clockPeriod();
1089179Sandreas.hansson@arm.com    }
1099179Sandreas.hansson@arm.com
1109793Sakash.bagdia@arm.com    /**
1119793Sakash.bagdia@arm.com     * The clock domain this clocked object belongs to
1129793Sakash.bagdia@arm.com     */
1139793Sakash.bagdia@arm.com    ClockDomain &clockDomain;
1149157Sandreas.hansson@arm.com
1159545Sandreas.hansson@arm.com  protected:
1169545Sandreas.hansson@arm.com
1179157Sandreas.hansson@arm.com    /**
1189793Sakash.bagdia@arm.com     * Create a clocked object and set the clock domain based on the
1199157Sandreas.hansson@arm.com     * parameters.
1209157Sandreas.hansson@arm.com     */
1219179Sandreas.hansson@arm.com    ClockedObject(const ClockedObjectParams* p) :
1229793Sakash.bagdia@arm.com        SimObject(p), tick(0), cycle(0), clockDomain(*p->clk_domain)
1239418Sandreas.hansson@arm.com    {
12410000Sclt67@cornell.edu        // Register with the clock domain, so that if the clock domain
12510000Sclt67@cornell.edu        // frequency changes, we can update this object's tick.
12610000Sclt67@cornell.edu        clockDomain.registerWithClockDomain(this);
1279418Sandreas.hansson@arm.com    }
1289157Sandreas.hansson@arm.com
1299157Sandreas.hansson@arm.com    /**
1309157Sandreas.hansson@arm.com     * Virtual destructor due to inheritance.
1319157Sandreas.hansson@arm.com     */
1329157Sandreas.hansson@arm.com    virtual ~ClockedObject() { }
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
2199550Sandreas.hansson@arm.com    inline Cycles ticksToCycles(Tick t) const
2209987Snilay@cs.wisc.edu    { return Cycles(divCeil(t, clockPeriod())); }
2219157Sandreas.hansson@arm.com
2229157Sandreas.hansson@arm.com};
2239157Sandreas.hansson@arm.com
2249157Sandreas.hansson@arm.com#endif //__SIM_CLOCKED_OBJECT_HH__
225