pmu.cc revision 10461
111988Sandreas.sandberg@arm.com/* 28839Sandreas.hansson@arm.com * Copyright (c) 2011-2014 ARM Limited 38839Sandreas.hansson@arm.com * All rights reserved 48839Sandreas.hansson@arm.com * 58839Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68839Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78839Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88839Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98839Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108839Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118839Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128839Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 133101Sstever@eecs.umich.edu * 148579Ssteve.reinhardt@amd.com * Redistribution and use in source and binary forms, with or without 153101Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are 163101Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright 173101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 183101Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 193101Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 203101Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution; 213101Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its 223101Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from 233101Sstever@eecs.umich.edu * this software without specific prior written permission. 243101Sstever@eecs.umich.edu * 253101Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 263101Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 273101Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 283101Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 293101Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 303101Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 313101Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 323101Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 333101Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 343101Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 353101Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 363101Sstever@eecs.umich.edu * 373101Sstever@eecs.umich.edu * Authors: Dam Sunwoo 383101Sstever@eecs.umich.edu * Matt Horsnell 393101Sstever@eecs.umich.edu * Andreas Sandberg 403101Sstever@eecs.umich.edu */ 413101Sstever@eecs.umich.edu 427778Sgblack@eecs.umich.edu#include "arch/arm/pmu.hh" 438839Sandreas.hansson@arm.com 443101Sstever@eecs.umich.edu#include "base/trace.hh" 453101Sstever@eecs.umich.edu#include "cpu/base.hh" 463101Sstever@eecs.umich.edu#include "debug/Checkpoint.hh" 473101Sstever@eecs.umich.edu#include "debug/PMUVerbose.hh" 483101Sstever@eecs.umich.edu#include "dev/arm/base_gic.hh" 493101Sstever@eecs.umich.edu#include "dev/arm/realview.hh" 503101Sstever@eecs.umich.edu#include "params/ArmPMU.hh" 513101Sstever@eecs.umich.edu 523101Sstever@eecs.umich.edunamespace ArmISA { 533101Sstever@eecs.umich.edu 543101Sstever@eecs.umich.educonst MiscReg PMU::reg_pmcr_wr_mask = 0x39; 553101Sstever@eecs.umich.edu 563101Sstever@eecs.umich.eduPMU::PMU(const ArmPMUParams *p) 573101Sstever@eecs.umich.edu : SimObject(p), BaseISADevice(), 583101Sstever@eecs.umich.edu reg_pmcnten(0), reg_pmcr(0), 593101Sstever@eecs.umich.edu reg_pmselr(0), reg_pminten(0), reg_pmovsr(0), 603101Sstever@eecs.umich.edu reg_pmceid(0), 613101Sstever@eecs.umich.edu clock_remainder(0), 6212563Sgabeblack@google.com counters(p->eventCounters), 6312563Sgabeblack@google.com reg_pmcr_conf(0), 643885Sbinkertn@umich.edu pmuInterrupt(p->pmuInterrupt), 653885Sbinkertn@umich.edu platform(p->platform) 664762Snate@binkert.org{ 673885Sbinkertn@umich.edu DPRINTF(PMUVerbose, "Initializing the PMU.\n"); 683885Sbinkertn@umich.edu 697528Ssteve.reinhardt@amd.com if (p->eventCounters > 31) { 703885Sbinkertn@umich.edu fatal("The PMU can only accept 31 counters, %d counters requested.\n", 714380Sbinkertn@umich.edu p->eventCounters); 724167Sbinkertn@umich.edu } 733102Sstever@eecs.umich.edu 743101Sstever@eecs.umich.edu /* Setup the performance counter ID registers */ 754762Snate@binkert.org reg_pmcr_conf.imp = 0x41; // ARM Ltd. 764762Snate@binkert.org reg_pmcr_conf.idcode = 0x00; 774762Snate@binkert.org reg_pmcr_conf.n = p->eventCounters; 784762Snate@binkert.org 794762Snate@binkert.org // Setup the hard-coded cycle counter, which is equivalent to 804762Snate@binkert.org // architected counter event type 0x11. 814762Snate@binkert.org cycleCounter.eventId = 0x11; 824762Snate@binkert.org} 834762Snate@binkert.org 845033Smilesck@eecs.umich.eduPMU::~PMU() 855033Smilesck@eecs.umich.edu{ 865033Smilesck@eecs.umich.edu} 875033Smilesck@eecs.umich.edu 885033Smilesck@eecs.umich.eduvoid 895033Smilesck@eecs.umich.eduPMU::addEventProbe(unsigned int id, SimObject *obj, const char *probe_name) 905033Smilesck@eecs.umich.edu{ 915033Smilesck@eecs.umich.edu DPRINTF(PMUVerbose, "PMU: Adding event type '0x%x' as probe %s:%s\n", 925033Smilesck@eecs.umich.edu id, obj->name(), probe_name); 935033Smilesck@eecs.umich.edu pmuEventTypes.insert(std::make_pair(id, EventType(obj, probe_name))); 943101Sstever@eecs.umich.edu 953101Sstever@eecs.umich.edu // Flag the event as available in the PMCEID register if it is an 963101Sstever@eecs.umich.edu // architected event. 975033Smilesck@eecs.umich.edu if (id < 0x40) 9810267SGeoffrey.Blake@arm.com reg_pmceid |= (1 << id); 998596Ssteve.reinhardt@amd.com} 1008596Ssteve.reinhardt@amd.com 1018596Ssteve.reinhardt@amd.comvoid 1028596Ssteve.reinhardt@amd.comPMU::drainResume() 1037673Snate@binkert.org{ 1047673Snate@binkert.org // Re-attach enabled counters after a resume in case they changed. 1057673Snate@binkert.org updateAllCounters(); 1067673Snate@binkert.org} 10711988Sandreas.sandberg@arm.com 10811988Sandreas.sandberg@arm.comvoid 10911988Sandreas.sandberg@arm.comPMU::setMiscReg(int misc_reg, MiscReg val) 11011988Sandreas.sandberg@arm.com{ 1113101Sstever@eecs.umich.edu DPRINTF(PMUVerbose, "setMiscReg(%s, 0x%x)\n", 1123101Sstever@eecs.umich.edu miscRegName[unflattenMiscReg(misc_reg)], val); 1133101Sstever@eecs.umich.edu 1143101Sstever@eecs.umich.edu switch (unflattenMiscReg(misc_reg)) { 1153101Sstever@eecs.umich.edu case MISCREG_PMCR_EL0: 11610380SAndrew.Bardsley@arm.com case MISCREG_PMCR: 11710380SAndrew.Bardsley@arm.com setControlReg(val); 11810380SAndrew.Bardsley@arm.com return; 11910380SAndrew.Bardsley@arm.com 12010380SAndrew.Bardsley@arm.com case MISCREG_PMCNTENSET_EL0: 12110380SAndrew.Bardsley@arm.com case MISCREG_PMCNTENSET: 12210458Sandreas.hansson@arm.com reg_pmcnten |= val; 12310458Sandreas.hansson@arm.com updateAllCounters(); 12410458Sandreas.hansson@arm.com return; 12510458Sandreas.hansson@arm.com 12610458Sandreas.hansson@arm.com case MISCREG_PMCNTENCLR_EL0: 12710458Sandreas.hansson@arm.com case MISCREG_PMCNTENCLR: 12810458Sandreas.hansson@arm.com reg_pmcnten &= ~val; 12910458Sandreas.hansson@arm.com updateAllCounters(); 13010458Sandreas.hansson@arm.com return; 13110458Sandreas.hansson@arm.com 13210458Sandreas.hansson@arm.com case MISCREG_PMOVSCLR_EL0: 13310458Sandreas.hansson@arm.com case MISCREG_PMOVSR: 1343101Sstever@eecs.umich.edu reg_pmovsr &= ~val; 1353101Sstever@eecs.umich.edu return; 1363101Sstever@eecs.umich.edu 1373101Sstever@eecs.umich.edu case MISCREG_PMSWINC_EL0: 1383101Sstever@eecs.umich.edu case MISCREG_PMSWINC: 13910267SGeoffrey.Blake@arm.com for (int i = 0; i < counters.size(); ++i) { 14010267SGeoffrey.Blake@arm.com CounterState &ctr(getCounter(i)); 14110267SGeoffrey.Blake@arm.com if (ctr.enabled && (val & (1 << i))) 14210267SGeoffrey.Blake@arm.com ++ctr.value; 1433101Sstever@eecs.umich.edu } 1443101Sstever@eecs.umich.edu break; 1453101Sstever@eecs.umich.edu 1463101Sstever@eecs.umich.edu case MISCREG_PMCCNTR_EL0: 1473101Sstever@eecs.umich.edu case MISCREG_PMCCNTR: 1483101Sstever@eecs.umich.edu cycleCounter.value = val; 1493101Sstever@eecs.umich.edu return; 1503101Sstever@eecs.umich.edu 1513101Sstever@eecs.umich.edu case MISCREG_PMSELR_EL0: 1523101Sstever@eecs.umich.edu case MISCREG_PMSELR: 1533101Sstever@eecs.umich.edu reg_pmselr = val; 1543101Sstever@eecs.umich.edu return; 1553101Sstever@eecs.umich.edu 1563101Sstever@eecs.umich.edu case MISCREG_PMCEID0_EL0: 1573101Sstever@eecs.umich.edu case MISCREG_PMCEID0: 1583101Sstever@eecs.umich.edu case MISCREG_PMCEID1_EL0: 1593101Sstever@eecs.umich.edu case MISCREG_PMCEID1: 1603101Sstever@eecs.umich.edu // Ignore writes 1613101Sstever@eecs.umich.edu return; 1623101Sstever@eecs.umich.edu 1633101Sstever@eecs.umich.edu case MISCREG_PMEVTYPER0_EL0...MISCREG_PMEVTYPER5_EL0: 1643101Sstever@eecs.umich.edu setCounterTypeRegister(misc_reg - MISCREG_PMEVCNTR0_EL0, val); 1653101Sstever@eecs.umich.edu return; 1663101Sstever@eecs.umich.edu 1673101Sstever@eecs.umich.edu case MISCREG_PMCCFILTR: 1683101Sstever@eecs.umich.edu case MISCREG_PMCCFILTR_EL0: 1693101Sstever@eecs.umich.edu DPRINTF(PMUVerbose, "Setting PMCCFILTR: 0x%x\n", val); 1703101Sstever@eecs.umich.edu setCounterTypeRegister(PMCCNTR, val); 1713101Sstever@eecs.umich.edu return; 1723101Sstever@eecs.umich.edu 1733101Sstever@eecs.umich.edu case MISCREG_PMXEVTYPER_PMCCFILTR: 1743101Sstever@eecs.umich.edu case MISCREG_PMXEVTYPER_EL0: 1753101Sstever@eecs.umich.edu case MISCREG_PMXEVTYPER: 1763101Sstever@eecs.umich.edu DPRINTF(PMUVerbose, "Setting counter type: " 1773101Sstever@eecs.umich.edu "[PMSELR: 0x%x, PMSELER.sel: 0x%x, EVTYPER: 0x%x]\n", 1785033Smilesck@eecs.umich.edu reg_pmselr, reg_pmselr.sel, val); 1796656Snate@binkert.org setCounterTypeRegister(reg_pmselr.sel, val); 1805033Smilesck@eecs.umich.edu return; 1815033Smilesck@eecs.umich.edu 1825033Smilesck@eecs.umich.edu case MISCREG_PMEVCNTR0_EL0...MISCREG_PMEVCNTR5_EL0: 1833101Sstever@eecs.umich.edu setCounterValue(misc_reg - MISCREG_PMEVCNTR0_EL0, val); 1843101Sstever@eecs.umich.edu return; 1853101Sstever@eecs.umich.edu 18610267SGeoffrey.Blake@arm.com case MISCREG_PMXEVCNTR_EL0: 18710267SGeoffrey.Blake@arm.com case MISCREG_PMXEVCNTR: 18810267SGeoffrey.Blake@arm.com setCounterValue(reg_pmselr.sel, val); 18910267SGeoffrey.Blake@arm.com return; 19010267SGeoffrey.Blake@arm.com 19110267SGeoffrey.Blake@arm.com case MISCREG_PMUSERENR_EL0: 19210267SGeoffrey.Blake@arm.com case MISCREG_PMUSERENR: 19310267SGeoffrey.Blake@arm.com // TODO 19410267SGeoffrey.Blake@arm.com break; 19510267SGeoffrey.Blake@arm.com 19610267SGeoffrey.Blake@arm.com case MISCREG_PMINTENSET_EL1: 19710267SGeoffrey.Blake@arm.com case MISCREG_PMINTENSET: 19810267SGeoffrey.Blake@arm.com reg_pminten |= val; 1993101Sstever@eecs.umich.edu return; 2003101Sstever@eecs.umich.edu 2013101Sstever@eecs.umich.edu case MISCREG_PMINTENCLR_EL1: 2023101Sstever@eecs.umich.edu case MISCREG_PMINTENCLR: 2033101Sstever@eecs.umich.edu reg_pminten &= ~val; 2043101Sstever@eecs.umich.edu return; 2053101Sstever@eecs.umich.edu 2063101Sstever@eecs.umich.edu case MISCREG_PMOVSSET_EL0: 2073101Sstever@eecs.umich.edu case MISCREG_PMOVSSET: 2083101Sstever@eecs.umich.edu reg_pmovsr |= val; 2093102Sstever@eecs.umich.edu return; 2103101Sstever@eecs.umich.edu 2113101Sstever@eecs.umich.edu default: 2123101Sstever@eecs.umich.edu panic("Unexpected PMU register: %i\n", miscRegName[misc_reg]); 21310267SGeoffrey.Blake@arm.com } 21410267SGeoffrey.Blake@arm.com 21510267SGeoffrey.Blake@arm.com warn("Not doing anything for write to miscreg %s\n", 21610267SGeoffrey.Blake@arm.com miscRegName[misc_reg]); 21710267SGeoffrey.Blake@arm.com} 21810267SGeoffrey.Blake@arm.com 21910267SGeoffrey.Blake@arm.comMiscReg 2207673Snate@binkert.orgPMU::readMiscReg(int misc_reg) 2218607Sgblack@eecs.umich.edu{ 2227673Snate@binkert.org MiscReg val(readMiscRegInt(misc_reg)); 2233101Sstever@eecs.umich.edu DPRINTF(PMUVerbose, "readMiscReg(%s): 0x%x\n", 22411988Sandreas.sandberg@arm.com miscRegName[unflattenMiscReg(misc_reg)], val); 22511988Sandreas.sandberg@arm.com return val; 22611988Sandreas.sandberg@arm.com} 2277673Snate@binkert.org 2287673Snate@binkert.orgMiscReg 2293101Sstever@eecs.umich.eduPMU::readMiscRegInt(int misc_reg) 2303101Sstever@eecs.umich.edu{ 2313101Sstever@eecs.umich.edu misc_reg = unflattenMiscReg(misc_reg); 2323101Sstever@eecs.umich.edu switch (misc_reg) { 2333101Sstever@eecs.umich.edu case MISCREG_PMCR_EL0: 2343101Sstever@eecs.umich.edu case MISCREG_PMCR: 2355033Smilesck@eecs.umich.edu return reg_pmcr_conf | (reg_pmcr & reg_pmcr_wr_mask); 2365475Snate@binkert.org 2375475Snate@binkert.org case MISCREG_PMCNTENSET_EL0: 2385475Snate@binkert.org case MISCREG_PMCNTENCLR_EL0: 2395475Snate@binkert.org case MISCREG_PMCNTENSET: 24010380SAndrew.Bardsley@arm.com case MISCREG_PMCNTENCLR: 24110380SAndrew.Bardsley@arm.com return reg_pmcnten; 24210380SAndrew.Bardsley@arm.com 2433101Sstever@eecs.umich.edu case MISCREG_PMOVSCLR_EL0: 2443101Sstever@eecs.umich.edu case MISCREG_PMOVSSET_EL0: 2453101Sstever@eecs.umich.edu case MISCREG_PMOVSR: // Overflow Status Register 2464762Snate@binkert.org case MISCREG_PMOVSSET: 2474762Snate@binkert.org return reg_pmovsr; 2484762Snate@binkert.org 2493101Sstever@eecs.umich.edu case MISCREG_PMSWINC_EL0: 25012050Snikos.nikoleris@arm.com case MISCREG_PMSWINC: // Software Increment Register (RAZ) 25112050Snikos.nikoleris@arm.com return 0; 25212050Snikos.nikoleris@arm.com 2538459SAli.Saidi@ARM.com case MISCREG_PMSELR: 2548459SAli.Saidi@ARM.com return reg_pmselr; 25512050Snikos.nikoleris@arm.com 2563101Sstever@eecs.umich.edu case MISCREG_PMCEID0_EL0: 2577528Ssteve.reinhardt@amd.com case MISCREG_PMCEID0: // Common Event ID register 2587528Ssteve.reinhardt@amd.com return reg_pmceid & 0xFFFFFFFF; 2597528Ssteve.reinhardt@amd.com 2607528Ssteve.reinhardt@amd.com case MISCREG_PMCEID1_EL0: 2617528Ssteve.reinhardt@amd.com case MISCREG_PMCEID1: // Common Event ID register 2627528Ssteve.reinhardt@amd.com return (reg_pmceid >> 32) & 0xFFFFFFFF; 2633101Sstever@eecs.umich.edu 2647528Ssteve.reinhardt@amd.com case MISCREG_PMCCNTR_EL0: 2657528Ssteve.reinhardt@amd.com return cycleCounter.value; 2667528Ssteve.reinhardt@amd.com 2677528Ssteve.reinhardt@amd.com case MISCREG_PMCCNTR: 2687528Ssteve.reinhardt@amd.com return cycleCounter.value & 0xFFFFFFFF; 2697528Ssteve.reinhardt@amd.com 2707528Ssteve.reinhardt@amd.com case MISCREG_PMEVTYPER0_EL0...MISCREG_PMEVTYPER5_EL0: 2717528Ssteve.reinhardt@amd.com return getCounterTypeRegister(misc_reg - MISCREG_PMEVTYPER0_EL0); 2727528Ssteve.reinhardt@amd.com 2737528Ssteve.reinhardt@amd.com case MISCREG_PMCCFILTR: 2748321Ssteve.reinhardt@amd.com case MISCREG_PMCCFILTR_EL0: 27512194Sgabeblack@google.com return getCounterTypeRegister(PMCCNTR); 2767528Ssteve.reinhardt@amd.com 2777528Ssteve.reinhardt@amd.com case MISCREG_PMXEVTYPER_PMCCFILTR: 2787528Ssteve.reinhardt@amd.com case MISCREG_PMXEVTYPER_EL0: 2797528Ssteve.reinhardt@amd.com case MISCREG_PMXEVTYPER: 2807528Ssteve.reinhardt@amd.com return getCounterTypeRegister(reg_pmselr.sel); 2817528Ssteve.reinhardt@amd.com 2827528Ssteve.reinhardt@amd.com case MISCREG_PMEVCNTR0_EL0...MISCREG_PMEVCNTR5_EL0: 2837528Ssteve.reinhardt@amd.com return getCounterValue(misc_reg - MISCREG_PMEVCNTR0_EL0) & 0xFFFFFFFF; 2847528Ssteve.reinhardt@amd.com 2857528Ssteve.reinhardt@amd.com case MISCREG_PMXEVCNTR_EL0: 2867528Ssteve.reinhardt@amd.com case MISCREG_PMXEVCNTR: 2877528Ssteve.reinhardt@amd.com return getCounterValue(reg_pmselr.sel) & 0xFFFFFFFF; 2887528Ssteve.reinhardt@amd.com 2893101Sstever@eecs.umich.edu case MISCREG_PMUSERENR_EL0: 2908664SAli.Saidi@ARM.com case MISCREG_PMUSERENR: 2918664SAli.Saidi@ARM.com // TODO 2928664SAli.Saidi@ARM.com return 0; 2938664SAli.Saidi@ARM.com 2948664SAli.Saidi@ARM.com case MISCREG_PMINTENSET_EL1: 2958664SAli.Saidi@ARM.com case MISCREG_PMINTENCLR_EL1: 2969953Sgeoffrey.blake@arm.com case MISCREG_PMINTENSET: 2979953Sgeoffrey.blake@arm.com case MISCREG_PMINTENCLR: 2989953Sgeoffrey.blake@arm.com return reg_pminten; 2999953Sgeoffrey.blake@arm.com 3009953Sgeoffrey.blake@arm.com default: 3019953Sgeoffrey.blake@arm.com panic("Unexpected PMU register: %i\n", miscRegName[misc_reg]); 3029953Sgeoffrey.blake@arm.com } 3039953Sgeoffrey.blake@arm.com 3049953Sgeoffrey.blake@arm.com warn("Not doing anything for read from miscreg %s\n", 3059953Sgeoffrey.blake@arm.com miscRegName[misc_reg]); 3069953Sgeoffrey.blake@arm.com return 0; 3079953Sgeoffrey.blake@arm.com} 3089953Sgeoffrey.blake@arm.com 30910267SGeoffrey.Blake@arm.comvoid 31010267SGeoffrey.Blake@arm.comPMU::setControlReg(PMCR_t val) 31110267SGeoffrey.Blake@arm.com{ 31210267SGeoffrey.Blake@arm.com DPRINTF(PMUVerbose, "Set Control Reg 0x%08x.\n", val); 31310267SGeoffrey.Blake@arm.com 31410267SGeoffrey.Blake@arm.com if (val.p) { 31510267SGeoffrey.Blake@arm.com DPRINTF(PMUVerbose, "PMU reset all events to zero.\n"); 31612563Sgabeblack@google.com resetEventCounts(); 31710267SGeoffrey.Blake@arm.com } 31810267SGeoffrey.Blake@arm.com 31910267SGeoffrey.Blake@arm.com if (val.c) { 32010267SGeoffrey.Blake@arm.com DPRINTF(PMUVerbose, "PMU reset cycle counter to zero.\n"); 32110267SGeoffrey.Blake@arm.com cycleCounter.value = 0; 32210267SGeoffrey.Blake@arm.com } 32310267SGeoffrey.Blake@arm.com 32410267SGeoffrey.Blake@arm.com // Reset the clock remainder if divide by 64-mode is toggled. 32510267SGeoffrey.Blake@arm.com if (reg_pmcr.d != val.d) 32610267SGeoffrey.Blake@arm.com clock_remainder = 0; 32710267SGeoffrey.Blake@arm.com 32810267SGeoffrey.Blake@arm.com reg_pmcr = val & reg_pmcr_wr_mask; 3293101Sstever@eecs.umich.edu updateAllCounters(); 3303101Sstever@eecs.umich.edu} 3313101Sstever@eecs.umich.edu 3323101Sstever@eecs.umich.eduvoid 3333101Sstever@eecs.umich.eduPMU::updateAllCounters() 3343101Sstever@eecs.umich.edu{ 3353101Sstever@eecs.umich.edu const bool global_enable(reg_pmcr.e); 33610364SGeoffrey.Blake@arm.com 33710364SGeoffrey.Blake@arm.com for (int i = 0; i < counters.size(); ++i) { 33810364SGeoffrey.Blake@arm.com CounterState &ctr(counters[i]); 33910364SGeoffrey.Blake@arm.com const bool enable(global_enable && (reg_pmcnten & (1 << i))); 3403101Sstever@eecs.umich.edu if (ctr.enabled != enable) { 3414762Snate@binkert.org ctr.enabled = enable; 3424762Snate@binkert.org updateCounter(i, ctr); 3434762Snate@binkert.org } 3444762Snate@binkert.org } 3457528Ssteve.reinhardt@amd.com 3464762Snate@binkert.org const bool ccntr_enable(global_enable && (reg_pmcnten & (1 << PMCCNTR))); 3474762Snate@binkert.org if (cycleCounter.enabled != ccntr_enable) { 3484762Snate@binkert.org cycleCounter.enabled = ccntr_enable; 34910267SGeoffrey.Blake@arm.com updateCounter(PMCCNTR, cycleCounter); 35010267SGeoffrey.Blake@arm.com } 35110267SGeoffrey.Blake@arm.com} 35210267SGeoffrey.Blake@arm.com 35310267SGeoffrey.Blake@arm.comvoid 35410267SGeoffrey.Blake@arm.comPMU::handleEvent(CounterId id, uint64_t delta) 35510267SGeoffrey.Blake@arm.com{ 35610267SGeoffrey.Blake@arm.com CounterState &ctr(getCounter(id)); 35710267SGeoffrey.Blake@arm.com const bool overflowed(reg_pmovsr & (1 << id)); 35810267SGeoffrey.Blake@arm.com 35910267SGeoffrey.Blake@arm.com // Handle the "count every 64 cycles" mode 36010267SGeoffrey.Blake@arm.com if (id == PMCCNTR && reg_pmcr.d) { 36110267SGeoffrey.Blake@arm.com clock_remainder += delta; 36210267SGeoffrey.Blake@arm.com delta = (clock_remainder >> 6); 36310267SGeoffrey.Blake@arm.com clock_remainder &= 63; 36410267SGeoffrey.Blake@arm.com } 36510267SGeoffrey.Blake@arm.com 36610267SGeoffrey.Blake@arm.com // Add delta and handle (new) overflows 36710267SGeoffrey.Blake@arm.com if (ctr.add(delta) && !overflowed) { 36810267SGeoffrey.Blake@arm.com DPRINTF(PMUVerbose, "PMU counter '%i' overflowed.\n", id); 36910267SGeoffrey.Blake@arm.com reg_pmovsr |= (1 << id); 37010267SGeoffrey.Blake@arm.com // Deliver a PMU interrupt if interrupt delivery is enabled 37110267SGeoffrey.Blake@arm.com // for this counter. 37210267SGeoffrey.Blake@arm.com if (reg_pminten & (1 << id)) 37310267SGeoffrey.Blake@arm.com raiseInterrupt(); 37410267SGeoffrey.Blake@arm.com } 37510364SGeoffrey.Blake@arm.com} 37610364SGeoffrey.Blake@arm.com 37710267SGeoffrey.Blake@arm.comvoid 37810267SGeoffrey.Blake@arm.comPMU::updateCounter(CounterId id, CounterState &ctr) 37910267SGeoffrey.Blake@arm.com{ 38010267SGeoffrey.Blake@arm.com if (!ctr.enabled) { 38110267SGeoffrey.Blake@arm.com if (!ctr.listeners.empty()) { 38210267SGeoffrey.Blake@arm.com DPRINTF(PMUVerbose, "updateCounter(%i): Disabling counter\n", id); 3837673Snate@binkert.org ctr.listeners.clear(); 3847673Snate@binkert.org } 3857673Snate@binkert.org } else { 3863101Sstever@eecs.umich.edu DPRINTF(PMUVerbose, "updateCounter(%i): Enable event id 0x%x\n", 38711988Sandreas.sandberg@arm.com id, ctr.eventId); 38811988Sandreas.sandberg@arm.com 38911988Sandreas.sandberg@arm.com // Attach all probes belonging to this event 39011988Sandreas.sandberg@arm.com auto range(pmuEventTypes.equal_range(ctr.eventId)); 3917673Snate@binkert.org for (auto it = range.first; it != range.second; ++it) { 3927673Snate@binkert.org const EventType &et(it->second); 3933101Sstever@eecs.umich.edu 3943101Sstever@eecs.umich.edu DPRINTF(PMUVerbose, "\tProbe: %s:%s\n", et.obj->name(), et.name); 3953101Sstever@eecs.umich.edu ctr.listeners.emplace_back(et.create(*this, id)); 3963101Sstever@eecs.umich.edu } 3973101Sstever@eecs.umich.edu 3983101Sstever@eecs.umich.edu /* The SW_INCR event type is a special case which doesn't need 3993101Sstever@eecs.umich.edu * any probes since it is controlled by software and the PMU 4003101Sstever@eecs.umich.edu * itself. 4013101Sstever@eecs.umich.edu */ 4023101Sstever@eecs.umich.edu if (ctr.listeners.empty() && ctr.eventId != ARCH_EVENT_SW_INCR) { 4033101Sstever@eecs.umich.edu warn("Can't enable PMU counter of type '0x%x': " 4043101Sstever@eecs.umich.edu "No such event type.\n", ctr.eventId); 4053101Sstever@eecs.umich.edu } 4063101Sstever@eecs.umich.edu } 4073101Sstever@eecs.umich.edu} 4085033Smilesck@eecs.umich.edu 4095033Smilesck@eecs.umich.edu 4103101Sstever@eecs.umich.eduvoid 4113101Sstever@eecs.umich.eduPMU::resetEventCounts() 4123101Sstever@eecs.umich.edu{ 4133101Sstever@eecs.umich.edu for (CounterState &ctr : counters) 4143101Sstever@eecs.umich.edu ctr.value = 0; 4153101Sstever@eecs.umich.edu} 4163101Sstever@eecs.umich.edu 4173101Sstever@eecs.umich.eduvoid 4183101Sstever@eecs.umich.eduPMU::setCounterValue(CounterId id, uint64_t val) 4193101Sstever@eecs.umich.edu{ 4203101Sstever@eecs.umich.edu if (!isValidCounter(id)) { 4213101Sstever@eecs.umich.edu warn_once("Can't change counter value: Counter %i does not exist.\n", 4223101Sstever@eecs.umich.edu id); 4233101Sstever@eecs.umich.edu return; 4243101Sstever@eecs.umich.edu } 4253101Sstever@eecs.umich.edu 4263101Sstever@eecs.umich.edu CounterState &ctr(getCounter(id)); 4273101Sstever@eecs.umich.edu ctr.value = val; 4283101Sstever@eecs.umich.edu} 4293101Sstever@eecs.umich.edu 4303101Sstever@eecs.umich.eduPMU::PMEVTYPER_t 4313101Sstever@eecs.umich.eduPMU::getCounterTypeRegister(CounterId id) const 4323101Sstever@eecs.umich.edu{ 4333101Sstever@eecs.umich.edu if (!isValidCounter(id)) 4343101Sstever@eecs.umich.edu return 0; 43510267SGeoffrey.Blake@arm.com 4367673Snate@binkert.org const CounterState &cs(getCounter(id)); 4377673Snate@binkert.org PMEVTYPER_t type(0); 4387673Snate@binkert.org 4397673Snate@binkert.org // TODO: Re-create filtering settings from counter state 4407673Snate@binkert.org type.evtCount = cs.eventId; 44110267SGeoffrey.Blake@arm.com 44210267SGeoffrey.Blake@arm.com return type; 44310267SGeoffrey.Blake@arm.com} 44410267SGeoffrey.Blake@arm.com 44510458Sandreas.hansson@arm.comvoid 44610458Sandreas.hansson@arm.comPMU::setCounterTypeRegister(CounterId id, PMEVTYPER_t val) 44710458Sandreas.hansson@arm.com{ 44810458Sandreas.hansson@arm.com DPRINTF(PMUVerbose, "Set Event [%d] = 0x%08x\n", id, val); 44910458Sandreas.hansson@arm.com if (!isValidCounter(id)) { 4504762Snate@binkert.org warn_once("Can't change counter type: Counter %i does not exist.\n", 4514762Snate@binkert.org id); 4523101Sstever@eecs.umich.edu return; 4533101Sstever@eecs.umich.edu } 4543101Sstever@eecs.umich.edu 4553101Sstever@eecs.umich.edu CounterState &ctr(getCounter(id)); 4563101Sstever@eecs.umich.edu // TODO: Handle filtering (both for general purpose counters and 4573101Sstever@eecs.umich.edu // the cycle counter) 4583101Sstever@eecs.umich.edu 4593101Sstever@eecs.umich.edu // If PMCCNTR Register, do not change event type. PMCCNTR can count 4603101Sstever@eecs.umich.edu // processor cycles only. 4613101Sstever@eecs.umich.edu if (id != PMCCNTR) { 4623101Sstever@eecs.umich.edu ctr.eventId = val.evtCount; 4633714Sstever@eecs.umich.edu updateCounter(reg_pmselr.sel, ctr); 4643714Sstever@eecs.umich.edu } 4653714Sstever@eecs.umich.edu} 4663714Sstever@eecs.umich.edu 4673714Sstever@eecs.umich.eduvoid 4683714Sstever@eecs.umich.eduPMU::raiseInterrupt() 4693101Sstever@eecs.umich.edu{ 4703101Sstever@eecs.umich.edu RealView *rv(dynamic_cast<RealView *>(platform)); 4713101Sstever@eecs.umich.edu if (!rv || !rv->gic) { 4723101Sstever@eecs.umich.edu warn_once("ARM PMU: GIC missing, can't raise interrupt.\n"); 4733101Sstever@eecs.umich.edu return; 4743101Sstever@eecs.umich.edu } 4753101Sstever@eecs.umich.edu 4763101Sstever@eecs.umich.edu DPRINTF(PMUVerbose, "Delivering PMU interrupt.\n"); 4773101Sstever@eecs.umich.edu rv->gic->sendInt(pmuInterrupt); 4783101Sstever@eecs.umich.edu} 4793101Sstever@eecs.umich.edu 4803101Sstever@eecs.umich.eduvoid 4813101Sstever@eecs.umich.eduPMU::serialize(std::ostream &os) 4823101Sstever@eecs.umich.edu{ 4833101Sstever@eecs.umich.edu DPRINTF(Checkpoint, "Serializing Arm PMU\n"); 4843101Sstever@eecs.umich.edu 4853101Sstever@eecs.umich.edu SERIALIZE_SCALAR(reg_pmcr); 4863101Sstever@eecs.umich.edu SERIALIZE_SCALAR(reg_pmcnten); 4873101Sstever@eecs.umich.edu SERIALIZE_SCALAR(reg_pmselr); 4883101Sstever@eecs.umich.edu SERIALIZE_SCALAR(reg_pminten); 4893101Sstever@eecs.umich.edu SERIALIZE_SCALAR(reg_pmovsr); 4903101Sstever@eecs.umich.edu SERIALIZE_SCALAR(reg_pmceid); 4913101Sstever@eecs.umich.edu SERIALIZE_SCALAR(clock_remainder); 4923101Sstever@eecs.umich.edu 49310380SAndrew.Bardsley@arm.com for (size_t i = 0; i < counters.size(); ++i) { 49410380SAndrew.Bardsley@arm.com nameOut(os, csprintf("%s.counters.%i", name(), i)); 49510380SAndrew.Bardsley@arm.com counters[i].serialize(os); 49610458Sandreas.hansson@arm.com } 49710458Sandreas.hansson@arm.com 49810458Sandreas.hansson@arm.com nameOut(os, csprintf("%s.cycleCounter", name())); 49910458Sandreas.hansson@arm.com cycleCounter.serialize(os); 50010458Sandreas.hansson@arm.com} 50110458Sandreas.hansson@arm.com 50210458Sandreas.hansson@arm.comvoid 50310458Sandreas.hansson@arm.comPMU::unserialize(Checkpoint *cp, const std::string §ion) 50410458Sandreas.hansson@arm.com{ 50510458Sandreas.hansson@arm.com DPRINTF(Checkpoint, "Unserializing Arm PMU\n"); 50610458Sandreas.hansson@arm.com 50710458Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(reg_pmcr); 50810458Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(reg_pmcnten); 5093101Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(reg_pmselr); 5105033Smilesck@eecs.umich.edu UNSERIALIZE_SCALAR(reg_pminten); 5113101Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(reg_pmovsr); 5123101Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(reg_pmceid); 5133101Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(clock_remainder); 5143101Sstever@eecs.umich.edu 5153101Sstever@eecs.umich.edu for (size_t i = 0; i < counters.size(); ++i) 5163101Sstever@eecs.umich.edu counters[i].unserialize(cp, csprintf("%s.counters.%i", section, i)); 5173101Sstever@eecs.umich.edu 5183101Sstever@eecs.umich.edu cycleCounter.unserialize(cp, csprintf("%s.cycleCounter", section)); 5193101Sstever@eecs.umich.edu} 5203101Sstever@eecs.umich.edu 5213101Sstever@eecs.umich.eduvoid 5223101Sstever@eecs.umich.eduPMU::CounterState::serialize(std::ostream &os) 5235822Ssaidi@eecs.umich.edu{ 5245822Ssaidi@eecs.umich.edu SERIALIZE_SCALAR(eventId); 5253101Sstever@eecs.umich.edu SERIALIZE_SCALAR(value); 5263101Sstever@eecs.umich.edu SERIALIZE_SCALAR(enabled); 5273101Sstever@eecs.umich.edu SERIALIZE_SCALAR(overflow64); 5283101Sstever@eecs.umich.edu} 5293101Sstever@eecs.umich.edu 5303101Sstever@eecs.umich.eduvoid 5313101Sstever@eecs.umich.eduPMU::CounterState::unserialize(Checkpoint *cp, const std::string §ion) 5323101Sstever@eecs.umich.edu{ 5333101Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(eventId); 5343101Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(value); 5353101Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(enabled); 5363101Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(overflow64); 5373101Sstever@eecs.umich.edu} 53810267SGeoffrey.Blake@arm.com 5393101Sstever@eecs.umich.edubool 5403101Sstever@eecs.umich.eduPMU::CounterState::add(uint64_t delta) 5413101Sstever@eecs.umich.edu{ 5423101Sstever@eecs.umich.edu const uint64_t msb(1ULL << (overflow64 ? 63 : 31)); 5433101Sstever@eecs.umich.edu const uint64_t old_value(value); 5443101Sstever@eecs.umich.edu 5453101Sstever@eecs.umich.edu assert(delta > 0); 5463101Sstever@eecs.umich.edu 5473102Sstever@eecs.umich.edu value += delta; 5483714Sstever@eecs.umich.edu 5493101Sstever@eecs.umich.edu // Overflow if the msb goes from 1 to 0 5503714Sstever@eecs.umich.edu return (old_value & msb) && !(value & msb); 5513714Sstever@eecs.umich.edu} 5523714Sstever@eecs.umich.edu 5533101Sstever@eecs.umich.edu} // namespace ArmISA 5543101Sstever@eecs.umich.edu 55510267SGeoffrey.Blake@arm.comArmISA::PMU * 55610267SGeoffrey.Blake@arm.comArmPMUParams::create() 55710267SGeoffrey.Blake@arm.com{ 55810267SGeoffrey.Blake@arm.com return new ArmISA::PMU(this); 5597673Snate@binkert.org} 5607673Snate@binkert.org