gem5  v20.1.0.0
energy_ctrl.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2014 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include "dev/arm/energy_ctrl.hh"
39 
40 #include "base/trace.hh"
41 #include "debug/EnergyCtrl.hh"
42 #include "mem/packet.hh"
43 #include "mem/packet_access.hh"
44 #include "params/EnergyCtrl.hh"
45 #include "sim/dvfs_handler.hh"
46 
48  : BasicPioDevice(p, PIO_NUM_FIELDS * 4), // each field is 32 bit
49  dvfsHandler(p->dvfs_handler),
50  domainID(0),
51  domainIDIndexToRead(0),
52  perfLevelAck(0),
53  perfLevelToRead(0),
54  updateAckEvent([this]{ updatePLAck(); }, name())
55 {
56  fatal_if(!p->dvfs_handler, "EnergyCtrl: Needs a DVFSHandler for a "
57  "functioning system.\n");
58 }
59 
60 Tick
62 {
63  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
64  assert(pkt->getSize() == 4);
65 
66  Addr daddr = pkt->getAddr() - pioAddr;
67  assert((daddr & 3) == 0);
68  Registers reg = Registers(daddr / 4);
69 
70  if (!dvfsHandler->isEnabled()) {
71  // NB: Zero is a good response if the handler is disabled
72  pkt->setLE<uint32_t>(0);
73  warn_once("EnergyCtrl: Disabled handler, ignoring read from reg %i\n",
74  reg);
75  DPRINTF(EnergyCtrl, "dvfs handler disabled, return 0 for read from "\
76  "reg %i\n", reg);
77  pkt->makeAtomicResponse();
78  return pioDelay;
79  }
80 
81  uint32_t result = 0;
82  Tick period;
83  double voltage;
84 
85  switch(reg) {
87  result = 1;
88  DPRINTF(EnergyCtrl, "dvfs handler enabled\n");
89  break;
90  case DVFS_NUM_DOMAINS:
91  result = dvfsHandler->numDomains();
92  DPRINTF(EnergyCtrl, "reading number of domains %d\n", result);
93  break;
96  DPRINTF(EnergyCtrl, "reading domain id at index %d as %d\n",
97  domainIDIndexToRead, result);
98  break;
100  // Return transition latency in nanoseconds
102  DPRINTF(EnergyCtrl, "reading dvfs handler trans latency %d ns\n",
103  result);
104  break;
105  case DOMAIN_ID:
106  result = domainID;
107  DPRINTF(EnergyCtrl, "reading domain id:%d\n", result);
108  break;
109  case PERF_LEVEL:
110  result = dvfsHandler->perfLevel(domainID);
111  DPRINTF(EnergyCtrl, "reading domain %d perf level: %d\n",
112  domainID, result);
113  break;
114  case PERF_LEVEL_ACK:
115  result = perfLevelAck;
116  DPRINTF(EnergyCtrl, "reading ack:%d\n", result);
117  // Signal is set for a single read only
118  if (result == 1)
119  perfLevelAck = 0;
120  break;
121  case NUM_OF_PERF_LEVELS:
123  DPRINTF(EnergyCtrl, "reading num of perf level:%d\n", result);
124  break;
125  case FREQ_AT_PERF_LEVEL:
127  result = ticksTokHz(period);
128  DPRINTF(EnergyCtrl, "reading freq %d KHz at perf level: %d\n",
129  result, perfLevelToRead);
130  break;
131  case VOLT_AT_PERF_LEVEL:
133  result = toMicroVolt(voltage);
134  DPRINTF(EnergyCtrl, "reading voltage %d u-volt at perf level: %d\n",
135  result, perfLevelToRead);
136  break;
137  default:
138  panic("Tried to read EnergyCtrl at offset %#x / reg %i\n", daddr,
139  reg);
140  }
141  pkt->setLE<uint32_t>(result);
142  pkt->makeAtomicResponse();
143  return pioDelay;
144 }
145 
146 Tick
148 {
149  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
150  assert(pkt->getSize() == 4);
151 
152  uint32_t data;
153  data = pkt->getLE<uint32_t>();
154 
155  Addr daddr = pkt->getAddr() - pioAddr;
156  assert((daddr & 3) == 0);
157  Registers reg = Registers(daddr / 4);
158 
159  if (!dvfsHandler->isEnabled()) {
160  // Ignore writes to a disabled controller
161  warn_once("EnergyCtrl: Disabled handler, ignoring write %u to "\
162  "reg %i\n", data, reg);
163  DPRINTF(EnergyCtrl, "dvfs handler disabled, ignoring write %u to "\
164  "reg %i\n", data, reg);
165  pkt->makeAtomicResponse();
166  return pioDelay;
167  }
168 
169  switch(reg) {
172  DPRINTF(EnergyCtrl, "writing domain id index:%d\n",
174  break;
175  case DOMAIN_ID:
176  // Extra check to ensure that a valid domain ID is being queried
178  domainID = data;
179  DPRINTF(EnergyCtrl, "writing domain id:%d\n", domainID);
180  } else {
181  DPRINTF(EnergyCtrl, "invalid domain id:%d\n", domainID);
182  }
183  break;
184  case PERF_LEVEL:
186  if (updateAckEvent.scheduled()) {
187  // The OS driver is trying to change the perf level while
188  // another change is in flight. This is fine, but only a
189  // single acknowledgment will be sent.
190  DPRINTF(EnergyCtrl, "descheduling previous pending ack "\
191  "event\n");
193  }
195  DPRINTF(EnergyCtrl, "writing domain %d perf level: %d\n",
196  domainID, data);
197  } else {
198  DPRINTF(EnergyCtrl, "invalid / ineffective perf level:%d for "\
199  "domain:%d\n", data, domainID);
200  }
201  break;
202  case PERF_LEVEL_TO_READ:
204  DPRINTF(EnergyCtrl, "writing perf level to read opp at: %d\n",
205  data);
206  break;
207  default:
208  panic("Tried to write EnergyCtrl at offset %#x\n", daddr);
209  break;
210  }
211 
212  pkt->makeAtomicResponse();
213  return pioDelay;
214 }
215 
216 void
218 {
223 
224  Tick next_event = updateAckEvent.scheduled() ? updateAckEvent.when() : 0;
225  SERIALIZE_SCALAR(next_event);
226 }
227 
228 void
230 {
235  Tick next_event = 0;
236  UNSERIALIZE_SCALAR(next_event);
237 
238  // restore scheduled events
239  if (next_event != 0) {
240  schedule(updateAckEvent, next_event);
241  }
242 }
243 
244 EnergyCtrl * EnergyCtrlParams::create()
245 {
246  return new EnergyCtrl(this);
247 }
248 
249 void
251 {
252  if (!dvfsHandler->isEnabled()) {
253  warn("Existing EnergyCtrl, but no enabled DVFSHandler found.\n");
254  }
255 }
256 
257 void
259 {
261 }
EnergyCtrl::FREQ_AT_PERF_LEVEL
@ FREQ_AT_PERF_LEVEL
Definition: energy_ctrl.hh:110
Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:460
Packet::makeAtomicResponse
void makeAtomicResponse()
Definition: packet.hh:1016
BasicPioDevice::pioAddr
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:154
SimClock::Int::ns
Tick ns
nanosecond
Definition: core.cc:65
warn
#define warn(...)
Definition: logging.hh:239
EnergyCtrl::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: energy_ctrl.cc:258
DVFSHandler::numPerfLevels
PerfLevel numPerfLevels(PerfLevel domain_id) const
Get the total number of available performance levels.
Definition: dvfs_handler.hh:161
data
const char data[]
Definition: circlebuf.test.cc:42
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:797
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
PioDevice::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: io_device.cc:56
warn_once
#define warn_once(...)
Definition: logging.hh:243
EnergyCtrl::perfLevelToRead
uint32_t perfLevelToRead
Definition: energy_ctrl.hh:163
EnergyCtrl::DVFS_NUM_DOMAINS
@ DVFS_NUM_DOMAINS
Definition: energy_ctrl.hh:102
Clocked::voltage
double voltage() const
Definition: clocked_object.hh:216
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
EnergyCtrl::DVFS_HANDLER_STATUS
@ DVFS_HANDLER_STATUS
Definition: energy_ctrl.hh:101
DVFSHandler::voltageAtPerfLevel
double voltageAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
Read the voltage of the specified domain at the specified performance level.
Definition: dvfs_handler.cc:172
EnergyCtrl::ticksTokHz
static uint32_t ticksTokHz(Tick period)
Definition: energy_ctrl.hh:165
EventManager::deschedule
void deschedule(Event &event)
Definition: eventq.hh:1014
Packet::getSize
unsigned getSize() const
Definition: packet.hh:764
EnergyCtrl::read
Tick read(PacketPtr pkt) override
Read command sent to the device.
Definition: energy_ctrl.cc:61
DVFSHandler::validDomainID
bool validDomainID(DomainID domain_id) const
Check whether a domain ID is known to the handler or not.
Definition: dvfs_handler.cc:104
EnergyCtrl::DOMAIN_ID
@ DOMAIN_ID
Definition: energy_ctrl.hh:105
DVFSHandler::isEnabled
bool isEnabled() const
Check enable status of the DVFS handler, when the handler is disabled, no request should be sent to t...
Definition: dvfs_handler.hh:171
Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:503
X86ISA::reg
Bitfield< 5, 3 > reg
Definition: types.hh:87
DVFSHandler::clkPeriodAtPerfLevel
Tick clkPeriodAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
Read the clock period of the specified domain at the specified performance level.
Definition: dvfs_handler.hh:131
packet.hh
EnergyCtrl::PERF_LEVEL
@ PERF_LEVEL
Definition: energy_ctrl.hh:106
EnergyCtrl::updateAckEvent
EventFunctionWrapper updateAckEvent
Definition: energy_ctrl.hh:181
cp
Definition: cprintf.cc:40
EnergyCtrl::startup
void startup() override
startup() is the final initialization call before simulation.
Definition: energy_ctrl.cc:250
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1005
EnergyCtrl::PERF_LEVEL_TO_READ
@ PERF_LEVEL_TO_READ
Definition: energy_ctrl.hh:109
EnergyCtrl::Params
EnergyCtrlParams Params
Definition: energy_ctrl.hh:115
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
DVFSHandler::numDomains
uint32_t numDomains() const
Get the number of domains assigned to this DVFS handler.
Definition: dvfs_handler.hh:80
DVFSHandler::domainID
DomainID domainID(uint32_t index) const
Get the n-th domain ID, from the domains managed by this handler.
Definition: dvfs_handler.cc:93
EnergyCtrl::NUM_OF_PERF_LEVELS
@ NUM_OF_PERF_LEVELS
Definition: energy_ctrl.hh:108
EnergyCtrl::updatePLAck
void updatePLAck()
Update the acknowledgment that is read back by the software to confirm newly requested performance le...
Definition: energy_ctrl.hh:177
EnergyCtrl
Definition: energy_ctrl.hh:61
BasicPioDevice::pioSize
Addr pioSize
Size that the device's address range.
Definition: io_device.hh:157
EnergyCtrl::perfLevelAck
uint32_t perfLevelAck
Acknowledgment (PERF_LEVEL_ACK) RO register, software polls this register to read back the status of ...
Definition: energy_ctrl.hh:161
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
DVFSHandler::transLatency
Tick transLatency() const
Get transition latency to switch between performance levels.
Definition: dvfs_handler.hh:99
name
const std::string & name()
Definition: trace.cc:50
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:790
energy_ctrl.hh
packet_access.hh
EnergyCtrl::toMicroVolt
static uint32_t toMicroVolt(double voltage)
Definition: energy_ctrl.hh:169
Packet::getLE
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Definition: packet_access.hh:75
EnergyCtrl::Registers
Registers
Definition: energy_ctrl.hh:100
EnergyCtrl::write
Tick write(PacketPtr pkt) override
Write command sent to the device.
Definition: energy_ctrl.cc:147
dvfs_handler.hh
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
BasicPioDevice
Definition: io_device.hh:150
EnergyCtrl::DVFS_HANDLER_TRANS_LATENCY
@ DVFS_HANDLER_TRANS_LATENCY
Definition: energy_ctrl.hh:104
EnergyCtrl::domainIDIndexToRead
uint32_t domainIDIndexToRead
Index for getting the domain ID from the domain ID list available with the DVFS handler.
Definition: energy_ctrl.hh:150
BasicPioDevice::pioDelay
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:160
Packet::setLE
void setLE(T v)
Set the value in the data pointer to v as little endian.
Definition: packet_access.hh:105
CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:63
trace.hh
EnergyCtrl::domainID
uint32_t domainID
Cluster ID (DOMAIN_ID) R/W register, programmed to ID of the domain for which the set/get performance...
Definition: energy_ctrl.hh:144
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:219
CheckpointIn
Definition: serialize.hh:67
EnergyCtrl::VOLT_AT_PERF_LEVEL
@ VOLT_AT_PERF_LEVEL
Definition: energy_ctrl.hh:111
EnergyCtrl::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: energy_ctrl.cc:217
EnergyCtrl::PERF_LEVEL_ACK
@ PERF_LEVEL_ACK
Definition: energy_ctrl.hh:107
EnergyCtrl::dvfsHandler
DVFSHandler * dvfsHandler
Definition: energy_ctrl.hh:138
EnergyCtrl::DVFS_DOMAINID_AT_INDEX
@ DVFS_DOMAINID_AT_INDEX
Definition: energy_ctrl.hh:103
EnergyCtrl::EnergyCtrl
EnergyCtrl(const Params *p)
Definition: energy_ctrl.cc:47
DVFSHandler::perfLevel
bool perfLevel(DomainID domain_id, PerfLevel perf_level)
Set a new performance level for the specified domain.
Definition: dvfs_handler.cc:117
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
EnergyCtrl::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: energy_ctrl.cc:229
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45

Generated on Wed Sep 30 2020 14:02:10 for gem5 by doxygen 1.8.17