/*
- * Copyright (c) 2013 ARM Limited
+ * Copyright (c) 2013-2014 ARM Limited
+ * Copyright (c) 2013 Cornell University
* All rights reserved
*
* The license below extends only to copyright in the software and shall
*
* Authors: Vasileios Spiliopoulos
* Akash Bagdia
+ * Christopher Torng
+ * Stephan Diestelhorst
*/
/**
#ifndef __SIM_CLOCK_DOMAIN_HH__
#define __SIM_CLOCK_DOMAIN_HH__
+#include <algorithm>
+
#include "base/statistics.hh"
#include "params/ClockDomain.hh"
#include "params/DerivedClockDomain.hh"
* Forward declaration
*/
class DerivedClockDomain;
+class VoltageDomain;
+class Clocked;
/**
* The ClockDomain provides clock to group of clocked objects bundled
- * under the same clock domain. The clock domains provide support for
+ * under the same clock domain. The clock domains, in turn, are
+ * grouped into voltage domains. The clock domains provide support for
* a hierarchial structure with source and derived domains.
*/
class ClockDomain : public SimObject
{
+ private:
+
+ /**
+ * Stat to report clock period of clock domain
+ */
+ Stats::Value currentClock;
+
protected:
/**
*/
Tick _clockPeriod;
+ /**
+ * Voltage domain this clock domain belongs to
+ */
+ VoltageDomain *_voltageDomain;
+
/**
* Pointers to potential derived clock domains so we can propagate
* changes.
*/
std::vector<DerivedClockDomain*> children;
+ /**
+ * Pointers to members of this clock domain, so that when the clock
+ * period changes, we can update each member's tick.
+ */
+ std::vector<Clocked *> members;
+
public:
typedef ClockDomainParams Params;
- ClockDomain(const Params *p) : SimObject(p), _clockPeriod(0) {}
+ ClockDomain(const Params *p, VoltageDomain *voltage_domain) :
+ SimObject(p),
+ _clockPeriod(0),
+ _voltageDomain(voltage_domain) {}
+
+ void regStats();
/**
* Get the clock period.
*
* @return Clock period in ticks
*/
- inline Tick clockPeriod() const { return _clockPeriod; }
+ Tick clockPeriod() const { return _clockPeriod; }
+
+ /**
+ * Register a Clocked object with this ClockDomain.
+ *
+ * @param Clocked to add as a member
+ */
+ void registerWithClockDomain(Clocked *c)
+ {
+ assert(c != NULL);
+ assert(std::find(members.begin(), members.end(), c) == members.end());
+ members.push_back(c);
+ }
+
+ /**
+ * Get the voltage domain.
+ *
+ * @return Voltage domain this clock domain belongs to
+ */
+ inline VoltageDomain *voltageDomain() const { return _voltageDomain; }
+
+
+ /**
+ * Get the current voltage this clock domain operates at.
+ *
+ * @return Voltage applied to the clock domain
+ */
+ double voltage() const;
/**
* Add a derived domain.
/**
* The source clock domains provides the notion of a clock domain that is
* connected to a tunable clock source. It maintains the clock period and
- * provides methods for setting/getting the clock.
+ * provides methods for setting/getting the clock and configuration parameters
+ * for clock domain that handler is going to manage. This includes frequency
+ * values at various performance levels, domain id, and current performance
+ * level. Note that a performance level as requested by the software corresponds
+ * to one of the frequency operational points the domain can operate at.
*/
class SrcClockDomain : public ClockDomain
{
*/
void clockPeriod(Tick clock_period);
+ // Explicitly import the otherwise hidden clockPeriod
+ using ClockDomain::clockPeriod;
+
+ typedef int32_t DomainID;
+ static const DomainID emptyDomainID = -1;
+
+ /**
+ * @return the domainID of the domain
+ */
+ uint32_t domainID() const { return _domainID; }
+
+ typedef uint32_t PerfLevel;
+ /**
+ * Checks whether the performance level requested exists in the current
+ * domain configuration
+ *
+ * @param the target performance level of the domain
+ *
+ * @return validity status of the given performance level
+ */
+ bool validPerfLevel(PerfLevel perf_level) const {
+ return perf_level < numPerfLevels();
+ }
+
+ /**
+ * Sets the current performance level of the domain
+ *
+ * @param perf_level the target performance level
+ */
+ void perfLevel(PerfLevel perf_level);
+
+ /**
+ * @return the current performance level of the domain
+ */
+ PerfLevel perfLevel() const { return _perfLevel; }
+
+ /**
+ * Get the number of available performance levels for this clock domain.
+ *
+ * @return Number of perf levels configured for this domain.
+ */
+ PerfLevel numPerfLevels() const {return freqOpPoints.size();}
+
+ /**
+ * @returns the clock period (expressed in ticks) for the current
+ * performance level
+ */
+ Tick clkPeriodAtPerfLevel() const { return freqOpPoints[perfLevel()]; }
+
+ Tick clkPeriodAtPerfLevel(PerfLevel perf_level) const
+ {
+ assert(validPerfLevel(perf_level));
+ return freqOpPoints[perf_level];
+ }
+
+ void startup() override;
+
+ void serialize(CheckpointOut &cp) const override;
+ void unserialize(CheckpointIn &cp) override;
+
+ private:
+ /**
+ * List of possible frequency operational points, should be in
+ * descending order
+ * An empty list corresponds to default frequency specified for its
+ * clock domain, overall implying NO DVFS
+ */
+ const std::vector<Tick> freqOpPoints;
+
+ /**
+ * Software recognizable id number for the domain, should be unique for
+ * each domain
+ */
+ const uint32_t _domainID;
+
+ /**
+ * Current performance level the domain is set to.
+ * The performance level corresponds to one selected frequency (and related
+ * voltage) from the supplied list of frequencies, with perfLevel = 0 being
+ * the fastest performance state.
+ */
+ PerfLevel _perfLevel;
};
/**