gem5  v21.1.0.2
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 #include "sim/serialize.hh"
47 
48 namespace gem5
49 {
50 
52  : BasicPioDevice(p, PIO_NUM_FIELDS * 4), // each field is 32 bit
53  dvfsHandler(p.dvfs_handler),
54  domainID(0),
55  domainIDIndexToRead(0),
56  perfLevelAck(0),
57  perfLevelToRead(0),
58  updateAckEvent([this]{ updatePLAck(); }, name())
59 {
60  fatal_if(!p.dvfs_handler, "EnergyCtrl: Needs a DVFSHandler for a "
61  "functioning system.\n");
62 }
63 
64 Tick
66 {
67  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
68  assert(pkt->getSize() == 4);
69 
70  Addr daddr = pkt->getAddr() - pioAddr;
71  assert((daddr & 3) == 0);
72  Registers reg = Registers(daddr / 4);
73 
74  if (!dvfsHandler->isEnabled()) {
75  // NB: Zero is a good response if the handler is disabled
76  pkt->setLE<uint32_t>(0);
77  warn_once("EnergyCtrl: Disabled handler, ignoring read from reg %i\n",
78  reg);
79  DPRINTF(EnergyCtrl, "dvfs handler disabled, return 0 for read from "\
80  "reg %i\n", reg);
81  pkt->makeAtomicResponse();
82  return pioDelay;
83  }
84 
85  uint32_t result = 0;
86  Tick period;
87  double voltage;
88 
89  switch(reg) {
91  result = 1;
92  DPRINTF(EnergyCtrl, "dvfs handler enabled\n");
93  break;
94  case DVFS_NUM_DOMAINS:
95  result = dvfsHandler->numDomains();
96  DPRINTF(EnergyCtrl, "reading number of domains %d\n", result);
97  break;
100  DPRINTF(EnergyCtrl, "reading domain id at index %d as %d\n",
101  domainIDIndexToRead, result);
102  break;
104  // Return transition latency in nanoseconds
106  DPRINTF(EnergyCtrl, "reading dvfs handler trans latency %d ns\n",
107  result);
108  break;
109  case DOMAIN_ID:
110  result = domainID;
111  DPRINTF(EnergyCtrl, "reading domain id:%d\n", result);
112  break;
113  case PERF_LEVEL:
114  result = dvfsHandler->perfLevel(domainID);
115  DPRINTF(EnergyCtrl, "reading domain %d perf level: %d\n",
116  domainID, result);
117  break;
118  case PERF_LEVEL_ACK:
119  result = perfLevelAck;
120  DPRINTF(EnergyCtrl, "reading ack:%d\n", result);
121  // Signal is set for a single read only
122  if (result == 1)
123  perfLevelAck = 0;
124  break;
125  case NUM_OF_PERF_LEVELS:
127  DPRINTF(EnergyCtrl, "reading num of perf level:%d\n", result);
128  break;
129  case FREQ_AT_PERF_LEVEL:
131  result = ticksTokHz(period);
132  DPRINTF(EnergyCtrl, "reading freq %d KHz at perf level: %d\n",
133  result, perfLevelToRead);
134  break;
135  case VOLT_AT_PERF_LEVEL:
137  result = toMicroVolt(voltage);
138  DPRINTF(EnergyCtrl, "reading voltage %d u-volt at perf level: %d\n",
139  result, perfLevelToRead);
140  break;
141  default:
142  panic("Tried to read EnergyCtrl at offset %#x / reg %i\n", daddr,
143  reg);
144  }
145  pkt->setLE<uint32_t>(result);
146  pkt->makeAtomicResponse();
147  return pioDelay;
148 }
149 
150 Tick
152 {
153  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
154  assert(pkt->getSize() == 4);
155 
156  uint32_t data;
157  data = pkt->getLE<uint32_t>();
158 
159  Addr daddr = pkt->getAddr() - pioAddr;
160  assert((daddr & 3) == 0);
161  Registers reg = Registers(daddr / 4);
162 
163  if (!dvfsHandler->isEnabled()) {
164  // Ignore writes to a disabled controller
165  warn_once("EnergyCtrl: Disabled handler, ignoring write %u to "\
166  "reg %i\n", data, reg);
167  DPRINTF(EnergyCtrl, "dvfs handler disabled, ignoring write %u to "\
168  "reg %i\n", data, reg);
169  pkt->makeAtomicResponse();
170  return pioDelay;
171  }
172 
173  switch(reg) {
176  DPRINTF(EnergyCtrl, "writing domain id index:%d\n",
178  break;
179  case DOMAIN_ID:
180  // Extra check to ensure that a valid domain ID is being queried
182  domainID = data;
183  DPRINTF(EnergyCtrl, "writing domain id:%d\n", domainID);
184  } else {
185  DPRINTF(EnergyCtrl, "invalid domain id:%d\n", domainID);
186  }
187  break;
188  case PERF_LEVEL:
190  if (updateAckEvent.scheduled()) {
191  // The OS driver is trying to change the perf level while
192  // another change is in flight. This is fine, but only a
193  // single acknowledgment will be sent.
194  DPRINTF(EnergyCtrl, "descheduling previous pending ack "\
195  "event\n");
197  }
199  DPRINTF(EnergyCtrl, "writing domain %d perf level: %d\n",
200  domainID, data);
201  } else {
202  DPRINTF(EnergyCtrl, "invalid / ineffective perf level:%d for "\
203  "domain:%d\n", data, domainID);
204  }
205  break;
206  case PERF_LEVEL_TO_READ:
208  DPRINTF(EnergyCtrl, "writing perf level to read opp at: %d\n",
209  data);
210  break;
211  default:
212  panic("Tried to write EnergyCtrl at offset %#x\n", daddr);
213  break;
214  }
215 
216  pkt->makeAtomicResponse();
217  return pioDelay;
218 }
219 
220 void
222 {
227 
228  Tick next_event = updateAckEvent.scheduled() ? updateAckEvent.when() : 0;
229  SERIALIZE_SCALAR(next_event);
230 }
231 
232 void
234 {
239  Tick next_event = 0;
240  UNSERIALIZE_SCALAR(next_event);
241 
242  // restore scheduled events
243  if (next_event != 0) {
244  schedule(updateAckEvent, next_event);
245  }
246 }
247 
248 void
250 {
251  if (!dvfsHandler->isEnabled()) {
252  warn("Existing EnergyCtrl, but no enabled DVFSHandler found.\n");
253  }
254 }
255 
256 void
258 {
260 }
261 
262 } // namespace gem5
gem5::EnergyCtrl::PERF_LEVEL
@ PERF_LEVEL
Definition: energy_ctrl.hh:110
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::EnergyCtrl::read
Tick read(PacketPtr pkt) override
Read command sent to the device.
Definition: energy_ctrl.cc:65
gem5::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:165
gem5::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:173
gem5::Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:508
gem5::EnergyCtrl::toMicroVolt
static uint32_t toMicroVolt(double voltage)
Definition: energy_ctrl.hh:173
gem5::BasicPioDevice::pioAddr
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:151
gem5::EnergyCtrl::dvfsHandler
DVFSHandler * dvfsHandler
Definition: energy_ctrl.hh:142
warn
#define warn(...)
Definition: logging.hh:245
gem5::EnergyCtrl::VOLT_AT_PERF_LEVEL
@ VOLT_AT_PERF_LEVEL
Definition: energy_ctrl.hh:115
data
const char data[]
Definition: circlebuf.test.cc:48
serialize.hh
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
warn_once
#define warn_once(...)
Definition: logging.hh:249
gem5::EnergyCtrl::DVFS_HANDLER_STATUS
@ DVFS_HANDLER_STATUS
Definition: energy_ctrl.hh:105
gem5::CheckpointIn
Definition: serialize.hh:68
gem5::EnergyCtrl::EnergyCtrl
EnergyCtrl(const Params &p)
Definition: energy_ctrl.cc:51
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
gem5::EnergyCtrl::Params
EnergyCtrlParams Params
Definition: energy_ctrl.hh:119
gem5::EnergyCtrl::PERF_LEVEL_TO_READ
@ PERF_LEVEL_TO_READ
Definition: energy_ctrl.hh:113
gem5::EnergyCtrl
Definition: energy_ctrl.hh:64
gem5::Packet::makeAtomicResponse
void makeAtomicResponse()
Definition: packet.hh:1043
gem5::DVFSHandler::numPerfLevels
PerfLevel numPerfLevels(PerfLevel domain_id) const
Get the total number of available performance levels.
Definition: dvfs_handler.hh:168
gem5::EnergyCtrl::FREQ_AT_PERF_LEVEL
@ FREQ_AT_PERF_LEVEL
Definition: energy_ctrl.hh:114
packet.hh
gem5::EnergyCtrl::DVFS_NUM_DOMAINS
@ DVFS_NUM_DOMAINS
Definition: energy_ctrl.hh:106
gem5::PioDevice::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: io_device.cc:59
gem5::EnergyCtrl::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: energy_ctrl.cc:221
gem5::DVFSHandler::validDomainID
bool validDomainID(DomainID domain_id) const
Check whether a domain ID is known to the handler or not.
Definition: dvfs_handler.cc:105
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:283
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::DVFSHandler::transLatency
Tick transLatency() const
Get transition latency to switch between performance levels.
Definition: dvfs_handler.hh:106
gem5::Clocked::voltage
double voltage() const
Definition: clocked_object.hh:219
gem5::BasicPioDevice::pioDelay
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:157
gem5::EnergyCtrl::DVFS_DOMAINID_AT_INDEX
@ DVFS_DOMAINID_AT_INDEX
Definition: energy_ctrl.hh:107
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::EnergyCtrl::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: energy_ctrl.cc:233
gem5::EnergyCtrl::updateAckEvent
EventFunctionWrapper updateAckEvent
Definition: energy_ctrl.hh:185
name
const std::string & name()
Definition: trace.cc:49
gem5::EnergyCtrl::startup
void startup() override
startup() is the final initialization call before simulation.
Definition: energy_ctrl.cc:249
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
energy_ctrl.hh
packet_access.hh
gem5::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:154
gem5::EnergyCtrl::ticksTokHz
static uint32_t ticksTokHz(Tick period)
Definition: energy_ctrl.hh:169
gem5::EnergyCtrl::DOMAIN_ID
@ DOMAIN_ID
Definition: energy_ctrl.hh:109
gem5::EventManager::deschedule
void deschedule(Event &event)
Definition: eventq.hh:1028
gem5::EnergyCtrl::DVFS_HANDLER_TRANS_LATENCY
@ DVFS_HANDLER_TRANS_LATENCY
Definition: energy_ctrl.hh:108
gem5::X86ISA::reg
Bitfield< 5, 3 > reg
Definition: types.hh:92
gem5::EnergyCtrl::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: energy_ctrl.cc:257
gem5::EnergyCtrl::updatePLAck
void updatePLAck()
Update the acknowledgment that is read back by the software to confirm newly requested performance le...
Definition: energy_ctrl.hh:181
gem5::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:148
gem5::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:94
dvfs_handler.hh
gem5::EnergyCtrl::write
Tick write(PacketPtr pkt) override
Write command sent to the device.
Definition: energy_ctrl.cc:151
gem5::Packet::getLE
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Definition: packet_access.hh:78
gem5::BasicPioDevice::pioSize
Addr pioSize
Size that the device's address range.
Definition: io_device.hh:154
gem5::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:178
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
trace.hh
gem5::Packet::setLE
void setLE(T v)
Set the value in the data pointer to v as little endian.
Definition: packet_access.hh:108
gem5::EnergyCtrl::perfLevelToRead
uint32_t perfLevelToRead
Definition: energy_ctrl.hh:167
gem5::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:138
gem5::DVFSHandler::numDomains
uint32_t numDomains() const
Get the number of domains assigned to this DVFS handler.
Definition: dvfs_handler.hh:87
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:781
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:225
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::BasicPioDevice
Definition: io_device.hh:147
gem5::DVFSHandler::perfLevel
bool perfLevel(DomainID domain_id, PerfLevel perf_level)
Set a new performance level for the specified domain.
Definition: dvfs_handler.cc:118
gem5::EnergyCtrl::PERF_LEVEL_ACK
@ PERF_LEVEL_ACK
Definition: energy_ctrl.hh:111
gem5::EnergyCtrl::Registers
Registers
Definition: energy_ctrl.hh:103
gem5::EnergyCtrl::NUM_OF_PERF_LEVELS
@ NUM_OF_PERF_LEVELS
Definition: energy_ctrl.hh:112
gem5::Packet::getSize
unsigned getSize() const
Definition: packet.hh:791
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:177
gem5::sim_clock::as_int::ns
Tick ns
nanosecond
Definition: core.cc:71

Generated on Tue Sep 21 2021 12:25:09 for gem5 by doxygen 1.8.17