energy_ctrl.cc revision 10905
12SN/A/* 21762SN/A * Copyright (c) 2012-2014 ARM Limited 32SN/A * All rights reserved 42SN/A * 52SN/A * The license below extends only to copyright in the software and shall 62SN/A * not be construed as granting a license to any other intellectual 72SN/A * property including but not limited to intellectual property relating 82SN/A * to a hardware implementation of the functionality of the software 92SN/A * licensed hereunder. You may use the software subject to the license 102SN/A * terms below provided that you ensure that this notice is replicated 112SN/A * unmodified and in its entirety in all distributions of the software, 122SN/A * modified or unmodified, in source code or in binary form. 132SN/A * 142SN/A * Redistribution and use in source and binary forms, with or without 152SN/A * modification, are permitted provided that the following conditions are 162SN/A * met: redistributions of source code must retain the above copyright 172SN/A * notice, this list of conditions and the following disclaimer; 182SN/A * redistributions in binary form must reproduce the above copyright 192SN/A * notice, this list of conditions and the following disclaimer in the 202SN/A * documentation and/or other materials provided with the distribution; 212SN/A * neither the name of the copyright holders nor the names of its 222SN/A * contributors may be used to endorse or promote products derived from 232SN/A * this software without specific prior written permission. 242SN/A * 252SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272665Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282665Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292665Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302665Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 322SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 342SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 356712Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 366712Snate@binkert.org * 372SN/A * Authors: Vasileios Spiliopoulos 382SN/A * Akash Bagdia 393971Sgblack@eecs.umich.edu * Stephan Diestelhorst 4056SN/A */ 4156SN/A 421158SN/A#include "debug/EnergyCtrl.hh" 43146SN/A#include "dev/arm/energy_ctrl.hh" 441858SN/A#include "mem/packet.hh" 456658Snate@binkert.org#include "mem/packet_access.hh" 462680Sktlim@umich.edu#include "params/EnergyCtrl.hh" 472378SN/A#include "sim/dvfs_handler.hh" 482522SN/A 492401SN/AEnergyCtrl::EnergyCtrl(const Params *p) 505154Sgblack@eecs.umich.edu : BasicPioDevice(p, PIO_NUM_FIELDS * 4), // each field is 32 bit 514762Snate@binkert.org dvfsHandler(p->dvfs_handler), 525512SMichael.Adler@intel.com domainID(0), 53360SN/A domainIDIndexToRead(0), 544434Ssaidi@eecs.umich.edu perfLevelAck(0), 55695SN/A perfLevelToRead(0), 562093SN/A updateAckEvent(this) 572378SN/A{ 582SN/A fatal_if(!p->dvfs_handler, "EnergyCtrl: Needs a DVFSHandler for a " 592715Sstever@eecs.umich.edu "functioning system.\n"); 602715Sstever@eecs.umich.edu} 612715Sstever@eecs.umich.edu 622715Sstever@eecs.umich.eduTick 632715Sstever@eecs.umich.eduEnergyCtrl::read(PacketPtr pkt) 642715Sstever@eecs.umich.edu{ 652715Sstever@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 662715Sstever@eecs.umich.edu assert(pkt->getSize() == 4); 675335Shines@cs.fsu.edu 685335Shines@cs.fsu.edu Addr daddr = pkt->getAddr() - pioAddr; 694157Sgblack@eecs.umich.edu assert((daddr & 3) == 0); 704166Sgblack@eecs.umich.edu Registers reg = Registers(daddr / 4); 716691Stjones1@inf.ed.ac.uk 726691Stjones1@inf.ed.ac.uk if (!dvfsHandler->isEnabled()) { 732715Sstever@eecs.umich.edu // NB: Zero is a good response if the handler is disabled 742715Sstever@eecs.umich.edu pkt->set<uint32_t>(0); 752715Sstever@eecs.umich.edu warn_once("EnergyCtrl: Disabled handler, ignoring read from reg %i\n", 762715Sstever@eecs.umich.edu reg); 772715Sstever@eecs.umich.edu DPRINTF(EnergyCtrl, "dvfs handler disabled, return 0 for read from "\ 782SN/A "reg %i\n", reg); 792107SN/A pkt->makeAtomicResponse(); 802SN/A return pioDelay; 812SN/A } 822SN/A 832SN/A uint32_t result = 0; 842SN/A Tick period; 852SN/A double voltage; 861858SN/A 87360SN/A switch(reg) { 882SN/A case DVFS_HANDLER_STATUS: 892SN/A result = 1; 902SN/A DPRINTF(EnergyCtrl, "dvfs handler enabled\n"); 912SN/A break; 922SN/A case DVFS_NUM_DOMAINS: 935758Shsul@eecs.umich.edu result = dvfsHandler->numDomains(); 945771Shsul@eecs.umich.edu DPRINTF(EnergyCtrl, "reading number of domains %d\n", result); 955758Shsul@eecs.umich.edu break; 965758Shsul@eecs.umich.edu case DVFS_DOMAINID_AT_INDEX: 975758Shsul@eecs.umich.edu result = dvfsHandler->domainID(domainIDIndexToRead); 985758Shsul@eecs.umich.edu DPRINTF(EnergyCtrl, "reading domain id at index %d as %d\n", 995758Shsul@eecs.umich.edu domainIDIndexToRead, result); 1005771Shsul@eecs.umich.edu break; 1015771Shsul@eecs.umich.edu case DVFS_HANDLER_TRANS_LATENCY: 1025758Shsul@eecs.umich.edu // Return transition latency in nanoseconds 1035154Sgblack@eecs.umich.edu result = dvfsHandler->transLatency() / SimClock::Int::ns; 1045183Ssaidi@eecs.umich.edu DPRINTF(EnergyCtrl, "reading dvfs handler trans latency %d ns\n", 1055154Sgblack@eecs.umich.edu result); 1062SN/A break; 1075154Sgblack@eecs.umich.edu case DOMAIN_ID: 1085154Sgblack@eecs.umich.edu result = domainID; 1095514SMichael.Adler@intel.com DPRINTF(EnergyCtrl, "reading domain id:%d\n", result); 1105154Sgblack@eecs.umich.edu break; 1115154Sgblack@eecs.umich.edu case PERF_LEVEL: 1125154Sgblack@eecs.umich.edu result = dvfsHandler->perfLevel(domainID); 1135154Sgblack@eecs.umich.edu DPRINTF(EnergyCtrl, "reading domain %d perf level: %d\n", 1145154Sgblack@eecs.umich.edu domainID, result); 1155154Sgblack@eecs.umich.edu break; 1165154Sgblack@eecs.umich.edu case PERF_LEVEL_ACK: 1175154Sgblack@eecs.umich.edu result = perfLevelAck; 1185154Sgblack@eecs.umich.edu DPRINTF(EnergyCtrl, "reading ack:%d\n", result); 1195154Sgblack@eecs.umich.edu // Signal is set for a single read only 1205154Sgblack@eecs.umich.edu if (result == 1) 1215154Sgblack@eecs.umich.edu perfLevelAck = 0; 1225154Sgblack@eecs.umich.edu break; 1235154Sgblack@eecs.umich.edu case NUM_OF_PERF_LEVELS: 1245154Sgblack@eecs.umich.edu result = dvfsHandler->numPerfLevels(domainID); 1255154Sgblack@eecs.umich.edu DPRINTF(EnergyCtrl, "reading num of perf level:%d\n", result); 1265154Sgblack@eecs.umich.edu break; 1275154Sgblack@eecs.umich.edu case FREQ_AT_PERF_LEVEL: 1285154Sgblack@eecs.umich.edu period = dvfsHandler->clkPeriodAtPerfLevel(domainID, perfLevelToRead); 1295154Sgblack@eecs.umich.edu result = ticksTokHz(period); 1305514SMichael.Adler@intel.com DPRINTF(EnergyCtrl, "reading freq %d KHz at perf level: %d\n", 1315514SMichael.Adler@intel.com result, perfLevelToRead); 1325514SMichael.Adler@intel.com break; 1335514SMichael.Adler@intel.com case VOLT_AT_PERF_LEVEL: 1345514SMichael.Adler@intel.com voltage = dvfsHandler->voltageAtPerfLevel(domainID, perfLevelToRead); 1355514SMichael.Adler@intel.com result = toMicroVolt(voltage); 1365514SMichael.Adler@intel.com DPRINTF(EnergyCtrl, "reading voltage %d u-volt at perf level: %d\n", 1375514SMichael.Adler@intel.com result, perfLevelToRead); 1385514SMichael.Adler@intel.com break; 1395514SMichael.Adler@intel.com default: 1405154Sgblack@eecs.umich.edu panic("Tried to read EnergyCtrl at offset %#x / reg %i\n", daddr, 1414997Sgblack@eecs.umich.edu reg); 1422SN/A } 1435282Srstrong@cs.ucsd.edu pkt->set<uint32_t>(result); 1445282Srstrong@cs.ucsd.edu pkt->makeAtomicResponse(); 1455282Srstrong@cs.ucsd.edu return pioDelay; 1465282Srstrong@cs.ucsd.edu} 1475282Srstrong@cs.ucsd.edu 1485282Srstrong@cs.ucsd.eduTick 1495282Srstrong@cs.ucsd.eduEnergyCtrl::write(PacketPtr pkt) 1505282Srstrong@cs.ucsd.edu{ 1515282Srstrong@cs.ucsd.edu assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 1525282Srstrong@cs.ucsd.edu assert(pkt->getSize() == 4); 1535282Srstrong@cs.ucsd.edu 1545282Srstrong@cs.ucsd.edu uint32_t data; 1555282Srstrong@cs.ucsd.edu data = pkt->get<uint32_t>(); 1565282Srstrong@cs.ucsd.edu 1575282Srstrong@cs.ucsd.edu Addr daddr = pkt->getAddr() - pioAddr; 1585282Srstrong@cs.ucsd.edu assert((daddr & 3) == 0); 1595514SMichael.Adler@intel.com Registers reg = Registers(daddr / 4); 1605282Srstrong@cs.ucsd.edu 1615282Srstrong@cs.ucsd.edu if (!dvfsHandler->isEnabled()) { 1625282Srstrong@cs.ucsd.edu // Ignore writes to a disabled controller 1635282Srstrong@cs.ucsd.edu warn_once("EnergyCtrl: Disabled handler, ignoring write %u to "\ 1642SN/A "reg %i\n", data, reg); 1652SN/A DPRINTF(EnergyCtrl, "dvfs handler disabled, ignoring write %u to "\ 1662SN/A "reg %i\n", data, reg); 1675282Srstrong@cs.ucsd.edu pkt->makeAtomicResponse(); 1685282Srstrong@cs.ucsd.edu return pioDelay; 1692SN/A } 1702SN/A 1711450SN/A switch(reg) { 1721514SN/A case DVFS_DOMAINID_AT_INDEX: 1735184Sgblack@eecs.umich.edu domainIDIndexToRead = data; 1742SN/A DPRINTF(EnergyCtrl, "writing domain id index:%d\n", 1752SN/A domainIDIndexToRead); 1762SN/A break; 1772378SN/A case DOMAIN_ID: 1782SN/A // Extra check to ensure that a valid domain ID is being queried 1792SN/A if (dvfsHandler->validDomainID(data)) { 1802SN/A domainID = data; 181729SN/A DPRINTF(EnergyCtrl, "writing domain id:%d\n", domainID); 1822SN/A } else { 1832SN/A DPRINTF(EnergyCtrl, "invalid domain id:%d\n", domainID); 1842SN/A } 1852SN/A break; 1862SN/A case PERF_LEVEL: 1872SN/A if (dvfsHandler->perfLevel(domainID, data)) { 1882SN/A if (updateAckEvent.scheduled()) { 1892SN/A // The OS driver is trying to change the perf level while 1902SN/A // another change is in flight. This is fine, but only a 1912SN/A // single acknowledgment will be sent. 1922SN/A DPRINTF(EnergyCtrl, "descheduling previous pending ack "\ 1932SN/A "event\n"); 1942SN/A deschedule(updateAckEvent); 1952SN/A } 1962SN/A schedule(updateAckEvent, curTick() + dvfsHandler->transLatency()); 1972SN/A DPRINTF(EnergyCtrl, "writing domain %d perf level: %d\n", 1982SN/A domainID, data); 1992SN/A } else { 2002SN/A DPRINTF(EnergyCtrl, "invalid / ineffective perf level:%d for "\ 2012SN/A "domain:%d\n", data, domainID); 2022SN/A } 2032SN/A break; 2042SN/A case PERF_LEVEL_TO_READ: 2052SN/A perfLevelToRead = data; 2062SN/A DPRINTF(EnergyCtrl, "writing perf level to read opp at: %d\n", 2072SN/A data); 2082SN/A break; 2092SN/A default: 2105514SMichael.Adler@intel.com panic("Tried to write EnergyCtrl at offset %#x\n", daddr); 2112SN/A break; 2122SN/A } 2132SN/A 2142SN/A pkt->makeAtomicResponse(); 2152SN/A return pioDelay; 2162SN/A} 2172SN/A 2182SN/Avoid 2192SN/AEnergyCtrl::serialize(CheckpointOut &cp) const 2202SN/A{ 2215713Shsul@eecs.umich.edu SERIALIZE_SCALAR(domainID); 2225713Shsul@eecs.umich.edu SERIALIZE_SCALAR(domainIDIndexToRead); 2232SN/A SERIALIZE_SCALAR(perfLevelToRead); 2245713Shsul@eecs.umich.edu SERIALIZE_SCALAR(perfLevelAck); 2255713Shsul@eecs.umich.edu 2265713Shsul@eecs.umich.edu Tick next_event = updateAckEvent.scheduled() ? updateAckEvent.when() : 0; 2275713Shsul@eecs.umich.edu SERIALIZE_SCALAR(next_event); 2286029Ssteve.reinhardt@amd.com} 2295713Shsul@eecs.umich.edu 2305713Shsul@eecs.umich.eduvoid 2315713Shsul@eecs.umich.eduEnergyCtrl::unserialize(CheckpointIn &cp) 2325512SMichael.Adler@intel.com{ 2335713Shsul@eecs.umich.edu UNSERIALIZE_SCALAR(domainID); 2342SN/A UNSERIALIZE_SCALAR(domainIDIndexToRead); 2352SN/A UNSERIALIZE_SCALAR(perfLevelToRead); 2361395SN/A UNSERIALIZE_SCALAR(perfLevelAck); 2371395SN/A Tick next_event = 0; 2381395SN/A UNSERIALIZE_SCALAR(next_event); 2395713Shsul@eecs.umich.edu 2405713Shsul@eecs.umich.edu // restore scheduled events 2412378SN/A if (next_event != 0) { 2422680Sktlim@umich.edu schedule(updateAckEvent, next_event); 2435713Shsul@eecs.umich.edu } 2441395SN/A} 2451634SN/A 2462680Sktlim@umich.eduEnergyCtrl * EnergyCtrlParams::create() 2472462SN/A{ 2482519SN/A return new EnergyCtrl(this); 2492519SN/A} 2504434Ssaidi@eecs.umich.edu 2514434Ssaidi@eecs.umich.eduvoid 2522519SN/AEnergyCtrl::startup() 2532519SN/A{ 2541395SN/A if (!dvfsHandler->isEnabled()) { 2552SN/A warn("Existing EnergyCtrl, but no enabled DVFSHandler found.\n"); 2562SN/A } 2572SN/A} 2582SN/A 2592SN/Avoid 2602SN/AEnergyCtrl::init() 2612SN/A{ 2622SN/A BasicPioDevice::init(); 2635282Srstrong@cs.ucsd.edu} 2645282Srstrong@cs.ucsd.edu