114039Sstacze01@arm.com/* 214039Sstacze01@arm.com * Copyright (c) 2014, 2018-2019 ARM Limited 314039Sstacze01@arm.com * All rights reserved 414039Sstacze01@arm.com * 514039Sstacze01@arm.com * The license below extends only to copyright in the software and shall 614039Sstacze01@arm.com * not be construed as granting a license to any other intellectual 714039Sstacze01@arm.com * property including but not limited to intellectual property relating 814039Sstacze01@arm.com * to a hardware implementation of the functionality of the software 914039Sstacze01@arm.com * licensed hereunder. You may use the software subject to the license 1014039Sstacze01@arm.com * terms below provided that you ensure that this notice is replicated 1114039Sstacze01@arm.com * unmodified and in its entirety in all distributions of the software, 1214039Sstacze01@arm.com * modified or unmodified, in source code or in binary form. 1314039Sstacze01@arm.com * 1414039Sstacze01@arm.com * Redistribution and use in source and binary forms, with or without 1514039Sstacze01@arm.com * modification, are permitted provided that the following conditions are 1614039Sstacze01@arm.com * met: redistributions of source code must retain the above copyright 1714039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer; 1814039Sstacze01@arm.com * redistributions in binary form must reproduce the above copyright 1914039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer in the 2014039Sstacze01@arm.com * documentation and/or other materials provided with the distribution; 2114039Sstacze01@arm.com * neither the name of the copyright holders nor the names of its 2214039Sstacze01@arm.com * contributors may be used to endorse or promote products derived from 2314039Sstacze01@arm.com * this software without specific prior written permission. 2414039Sstacze01@arm.com * 2514039Sstacze01@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2614039Sstacze01@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2714039Sstacze01@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2814039Sstacze01@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2914039Sstacze01@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3014039Sstacze01@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3114039Sstacze01@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3214039Sstacze01@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3314039Sstacze01@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3414039Sstacze01@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3514039Sstacze01@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3614039Sstacze01@arm.com * 3714039Sstacze01@arm.com * Authors: Stan Czerniawski 3814039Sstacze01@arm.com * Damian Richardson 3914039Sstacze01@arm.com */ 4014039Sstacze01@arm.com 4114039Sstacze01@arm.com#include "dev/arm/smmu_v3_caches.hh" 4214039Sstacze01@arm.com 4314039Sstacze01@arm.com#include <numeric> 4414039Sstacze01@arm.com 4514039Sstacze01@arm.com#include "base/bitfield.hh" 4614039Sstacze01@arm.com#include "base/intmath.hh" 4714039Sstacze01@arm.com#include "base/logging.hh" 4814039Sstacze01@arm.com#include "sim/stats.hh" 4914039Sstacze01@arm.com 5014039Sstacze01@arm.com 5114039Sstacze01@arm.com// taken from hex expansion of pi 5214039Sstacze01@arm.com#define SMMUTLB_SEED 0xEA752DFE 5314039Sstacze01@arm.com#define ARMARCHTLB_SEED 0x8B021FA1 5414039Sstacze01@arm.com#define IPACACHE_SEED 0xE5A0CC0F 5514039Sstacze01@arm.com#define CONFIGCACHE_SEED 0xB56F74E8 5614039Sstacze01@arm.com#define WALKCACHE_SEED 0x18ACF3D6 5714039Sstacze01@arm.com 5814039Sstacze01@arm.com/* 5914039Sstacze01@arm.com * BaseCache 6014039Sstacze01@arm.com * 6114039Sstacze01@arm.com * TODO: move more code into this base class to reduce duplication. 6214039Sstacze01@arm.com */ 6314039Sstacze01@arm.com 6414039Sstacze01@arm.comSMMUv3BaseCache::SMMUv3BaseCache(const std::string &policy_name, uint32_t seed) : 6514039Sstacze01@arm.com replacementPolicy(decodePolicyName(policy_name)), 6614039Sstacze01@arm.com nextToReplace(0), 6714039Sstacze01@arm.com random(seed), 6814039Sstacze01@arm.com useStamp(0) 6914039Sstacze01@arm.com{} 7014039Sstacze01@arm.com 7114039Sstacze01@arm.comint 7214039Sstacze01@arm.comSMMUv3BaseCache::decodePolicyName(const std::string &policy_name) 7314039Sstacze01@arm.com{ 7414039Sstacze01@arm.com if (policy_name == "rr") { 7514039Sstacze01@arm.com return SMMU_CACHE_REPL_ROUND_ROBIN; 7614039Sstacze01@arm.com } else if (policy_name == "rand") { 7714039Sstacze01@arm.com return SMMU_CACHE_REPL_RANDOM; 7814039Sstacze01@arm.com } else if (policy_name == "lru") { 7914039Sstacze01@arm.com return SMMU_CACHE_REPL_LRU; 8014039Sstacze01@arm.com } else { 8114039Sstacze01@arm.com panic("Unknown cache replacement policy '%s'\n", policy_name); 8214039Sstacze01@arm.com } 8314039Sstacze01@arm.com} 8414039Sstacze01@arm.com 8514039Sstacze01@arm.comvoid 8614039Sstacze01@arm.comSMMUv3BaseCache::regStats(const std::string &name) 8714039Sstacze01@arm.com{ 8814039Sstacze01@arm.com using namespace Stats; 8914039Sstacze01@arm.com 9014039Sstacze01@arm.com 9114039Sstacze01@arm.com averageLookups 9214039Sstacze01@arm.com .name(name + ".averageLookups") 9314039Sstacze01@arm.com .desc("Average number lookups per second") 9414039Sstacze01@arm.com .flags(pdf); 9514039Sstacze01@arm.com 9614039Sstacze01@arm.com totalLookups 9714039Sstacze01@arm.com .name(name + ".totalLookups") 9814039Sstacze01@arm.com .desc("Total number of lookups") 9914039Sstacze01@arm.com .flags(pdf); 10014039Sstacze01@arm.com 10114039Sstacze01@arm.com averageLookups = totalLookups / simSeconds; 10214039Sstacze01@arm.com 10314039Sstacze01@arm.com 10414039Sstacze01@arm.com averageMisses 10514039Sstacze01@arm.com .name(name + ".averageMisses") 10614039Sstacze01@arm.com .desc("Average number misses per second") 10714039Sstacze01@arm.com .flags(pdf); 10814039Sstacze01@arm.com 10914039Sstacze01@arm.com totalMisses 11014039Sstacze01@arm.com .name(name + ".totalMisses") 11114039Sstacze01@arm.com .desc("Total number of misses") 11214039Sstacze01@arm.com .flags(pdf); 11314039Sstacze01@arm.com 11414039Sstacze01@arm.com averageMisses = totalMisses / simSeconds; 11514039Sstacze01@arm.com 11614039Sstacze01@arm.com 11714039Sstacze01@arm.com averageUpdates 11814039Sstacze01@arm.com .name(name + ".averageUpdates") 11914039Sstacze01@arm.com .desc("Average number updates per second") 12014039Sstacze01@arm.com .flags(pdf); 12114039Sstacze01@arm.com 12214039Sstacze01@arm.com totalUpdates 12314039Sstacze01@arm.com .name(name + ".totalUpdates") 12414039Sstacze01@arm.com .desc("Total number of updates") 12514039Sstacze01@arm.com .flags(pdf); 12614039Sstacze01@arm.com 12714039Sstacze01@arm.com averageUpdates = totalUpdates / simSeconds; 12814039Sstacze01@arm.com 12914039Sstacze01@arm.com 13014039Sstacze01@arm.com averageHitRate 13114039Sstacze01@arm.com .name(name + ".averageHitRate") 13214039Sstacze01@arm.com .desc("Average hit rate") 13314039Sstacze01@arm.com .flags(pdf); 13414039Sstacze01@arm.com 13514039Sstacze01@arm.com averageHitRate = (totalLookups - totalMisses) / totalLookups; 13614039Sstacze01@arm.com 13714039Sstacze01@arm.com insertions 13814039Sstacze01@arm.com .name(name + ".insertions") 13914039Sstacze01@arm.com .desc("Number of insertions (not replacements)") 14014039Sstacze01@arm.com .flags(pdf); 14114039Sstacze01@arm.com} 14214039Sstacze01@arm.com 14314039Sstacze01@arm.com 14414039Sstacze01@arm.com 14514039Sstacze01@arm.com/* 14614039Sstacze01@arm.com * SMMUTLB 14714039Sstacze01@arm.com */ 14814039Sstacze01@arm.com 14914039Sstacze01@arm.comSMMUTLB::SMMUTLB(unsigned numEntries, unsigned _associativity, 15014039Sstacze01@arm.com const std::string &policy) 15114039Sstacze01@arm.com: 15214039Sstacze01@arm.com SMMUv3BaseCache(policy, SMMUTLB_SEED), 15314039Sstacze01@arm.com associativity(_associativity) 15414039Sstacze01@arm.com{ 15514039Sstacze01@arm.com if (associativity == 0) 15614039Sstacze01@arm.com associativity = numEntries; // fully associative 15714039Sstacze01@arm.com 15814039Sstacze01@arm.com if (numEntries == 0) 15914039Sstacze01@arm.com fatal("SMMUTLB must have at least one entry\n"); 16014039Sstacze01@arm.com 16114039Sstacze01@arm.com if (associativity > numEntries) 16214039Sstacze01@arm.com fatal("SMMUTLB associativity cannot be higher than " 16314039Sstacze01@arm.com "its number of entries\n"); 16414039Sstacze01@arm.com 16514039Sstacze01@arm.com unsigned num_sets = numEntries / associativity; 16614039Sstacze01@arm.com 16714039Sstacze01@arm.com if (num_sets*associativity != numEntries) 16814039Sstacze01@arm.com fatal("Number of SMMUTLB entries must be divisible " 16914039Sstacze01@arm.com "by its associativity\n"); 17014039Sstacze01@arm.com 17114039Sstacze01@arm.com Entry e; 17214039Sstacze01@arm.com e.valid = false; 17314039Sstacze01@arm.com 17414039Sstacze01@arm.com Set set(associativity, e); 17514039Sstacze01@arm.com sets.resize(num_sets, set); 17614039Sstacze01@arm.com} 17714039Sstacze01@arm.com 17814039Sstacze01@arm.comconst SMMUTLB::Entry* 17914039Sstacze01@arm.comSMMUTLB::lookup(uint32_t sid, uint32_t ssid, 18014039Sstacze01@arm.com Addr va, bool updStats) 18114039Sstacze01@arm.com{ 18214039Sstacze01@arm.com const Entry *result = NULL; 18314039Sstacze01@arm.com 18414039Sstacze01@arm.com Set &set = sets[pickSetIdx(va)]; 18514039Sstacze01@arm.com 18614039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 18714039Sstacze01@arm.com const Entry &e = set[i]; 18814039Sstacze01@arm.com 18914039Sstacze01@arm.com if (e.valid && (e.va & e.vaMask) == (va & e.vaMask) && 19014039Sstacze01@arm.com e.sid==sid && e.ssid==ssid) 19114039Sstacze01@arm.com { 19214039Sstacze01@arm.com if (result != NULL) 19314039Sstacze01@arm.com panic("SMMUTLB: duplicate entry found!\n"); 19414039Sstacze01@arm.com 19514039Sstacze01@arm.com result = &e; 19614039Sstacze01@arm.com break; 19714039Sstacze01@arm.com } 19814039Sstacze01@arm.com } 19914039Sstacze01@arm.com 20014039Sstacze01@arm.com if (updStats) { 20114039Sstacze01@arm.com if (result) 20214039Sstacze01@arm.com result->lastUsed = useStamp++; 20314039Sstacze01@arm.com 20414039Sstacze01@arm.com totalLookups++; 20514039Sstacze01@arm.com if (result == NULL) 20614039Sstacze01@arm.com totalMisses++; 20714039Sstacze01@arm.com } 20814039Sstacze01@arm.com 20914039Sstacze01@arm.com return result; 21014039Sstacze01@arm.com} 21114039Sstacze01@arm.com 21214039Sstacze01@arm.comconst SMMUTLB::Entry* 21314039Sstacze01@arm.comSMMUTLB::lookupAnyVA(uint32_t sid, uint32_t ssid, bool updStats) 21414039Sstacze01@arm.com{ 21514039Sstacze01@arm.com const Entry *result = NULL; 21614039Sstacze01@arm.com 21714039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 21814039Sstacze01@arm.com Set &set = sets[s]; 21914039Sstacze01@arm.com 22014039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 22114039Sstacze01@arm.com const Entry &e = set[i]; 22214039Sstacze01@arm.com 22314039Sstacze01@arm.com if (e.valid && e.sid==sid && e.ssid==ssid) { 22414039Sstacze01@arm.com result = &e; 22514039Sstacze01@arm.com break; 22614039Sstacze01@arm.com } 22714039Sstacze01@arm.com } 22814039Sstacze01@arm.com } 22914039Sstacze01@arm.com 23014039Sstacze01@arm.com if (updStats) { 23114039Sstacze01@arm.com totalLookups++; 23214039Sstacze01@arm.com if (result == NULL) 23314039Sstacze01@arm.com totalMisses++; 23414039Sstacze01@arm.com } 23514039Sstacze01@arm.com 23614039Sstacze01@arm.com return result; 23714039Sstacze01@arm.com} 23814039Sstacze01@arm.com 23914039Sstacze01@arm.comvoid 24014039Sstacze01@arm.comSMMUTLB::store(const Entry &incoming, AllocPolicy alloc) 24114039Sstacze01@arm.com{ 24214039Sstacze01@arm.com if (!incoming.valid) 24314039Sstacze01@arm.com panic("Tried to store an invalid entry\n"); 24414039Sstacze01@arm.com 24514039Sstacze01@arm.com incoming.lastUsed = 0; 24614039Sstacze01@arm.com 24714039Sstacze01@arm.com const Entry *existing = 24814039Sstacze01@arm.com lookup(incoming.sid, incoming.ssid, incoming.va, false); 24914039Sstacze01@arm.com 25014039Sstacze01@arm.com if (existing) { 25114039Sstacze01@arm.com *const_cast<Entry *> (existing) = incoming; 25214039Sstacze01@arm.com } else { 25314039Sstacze01@arm.com Set &set = sets[pickSetIdx(incoming.va)]; 25414039Sstacze01@arm.com set[pickEntryIdxToReplace(set, alloc)] = incoming; 25514039Sstacze01@arm.com } 25614039Sstacze01@arm.com 25714039Sstacze01@arm.com totalUpdates++; 25814039Sstacze01@arm.com} 25914039Sstacze01@arm.com 26014039Sstacze01@arm.comvoid 26114132Sgiacomo.travaglini@arm.comSMMUTLB::invalidateSSID(uint32_t sid, uint32_t ssid) 26214132Sgiacomo.travaglini@arm.com{ 26314132Sgiacomo.travaglini@arm.com Set &set = sets[pickSetIdx(sid, ssid)]; 26414132Sgiacomo.travaglini@arm.com 26514132Sgiacomo.travaglini@arm.com for (size_t i = 0; i < set.size(); i++) { 26614132Sgiacomo.travaglini@arm.com Entry &e = set[i]; 26714132Sgiacomo.travaglini@arm.com 26814132Sgiacomo.travaglini@arm.com if (e.sid == sid && e.ssid == ssid) 26914132Sgiacomo.travaglini@arm.com e.valid = false; 27014132Sgiacomo.travaglini@arm.com } 27114132Sgiacomo.travaglini@arm.com} 27214132Sgiacomo.travaglini@arm.com 27314132Sgiacomo.travaglini@arm.comvoid 27414132Sgiacomo.travaglini@arm.comSMMUTLB::invalidateSID(uint32_t sid) 27514132Sgiacomo.travaglini@arm.com{ 27614132Sgiacomo.travaglini@arm.com for (size_t s = 0; s < sets.size(); s++) { 27714132Sgiacomo.travaglini@arm.com Set &set = sets[s]; 27814132Sgiacomo.travaglini@arm.com 27914132Sgiacomo.travaglini@arm.com for (size_t i = 0; i < set.size(); i++) { 28014132Sgiacomo.travaglini@arm.com Entry &e = set[i]; 28114132Sgiacomo.travaglini@arm.com 28214132Sgiacomo.travaglini@arm.com if (e.sid == sid) 28314132Sgiacomo.travaglini@arm.com e.valid = false; 28414132Sgiacomo.travaglini@arm.com } 28514132Sgiacomo.travaglini@arm.com } 28614132Sgiacomo.travaglini@arm.com} 28714132Sgiacomo.travaglini@arm.com 28814132Sgiacomo.travaglini@arm.comvoid 28914039Sstacze01@arm.comSMMUTLB::invalidateVA(Addr va, uint16_t asid, uint16_t vmid) 29014039Sstacze01@arm.com{ 29114039Sstacze01@arm.com Set &set = sets[pickSetIdx(va)]; 29214039Sstacze01@arm.com 29314039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 29414039Sstacze01@arm.com Entry &e = set[i]; 29514039Sstacze01@arm.com 29614039Sstacze01@arm.com if ((e.va & e.vaMask) == (va & e.vaMask) && 29714039Sstacze01@arm.com e.asid==asid && e.vmid==vmid) 29814039Sstacze01@arm.com { 29914039Sstacze01@arm.com e.valid = false; 30014039Sstacze01@arm.com } 30114039Sstacze01@arm.com } 30214039Sstacze01@arm.com} 30314039Sstacze01@arm.com 30414039Sstacze01@arm.comvoid 30514039Sstacze01@arm.comSMMUTLB::invalidateVAA(Addr va, uint16_t vmid) 30614039Sstacze01@arm.com{ 30714039Sstacze01@arm.com Set &set = sets[pickSetIdx(va)]; 30814039Sstacze01@arm.com 30914039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 31014039Sstacze01@arm.com Entry &e = set[i]; 31114039Sstacze01@arm.com 31214039Sstacze01@arm.com if ((e.va & e.vaMask) == (va & e.vaMask) && e.vmid==vmid) 31314039Sstacze01@arm.com e.valid = false; 31414039Sstacze01@arm.com } 31514039Sstacze01@arm.com} 31614039Sstacze01@arm.com 31714039Sstacze01@arm.comvoid 31814039Sstacze01@arm.comSMMUTLB::invalidateASID(uint16_t asid, uint16_t vmid) 31914039Sstacze01@arm.com{ 32014039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 32114039Sstacze01@arm.com Set &set = sets[s]; 32214039Sstacze01@arm.com 32314039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 32414039Sstacze01@arm.com Entry &e = set[i]; 32514039Sstacze01@arm.com 32614039Sstacze01@arm.com if (e.asid==asid && e.vmid==vmid) 32714039Sstacze01@arm.com e.valid = false; 32814039Sstacze01@arm.com } 32914039Sstacze01@arm.com } 33014039Sstacze01@arm.com} 33114039Sstacze01@arm.com 33214039Sstacze01@arm.comvoid 33314039Sstacze01@arm.comSMMUTLB::invalidateVMID(uint16_t vmid) 33414039Sstacze01@arm.com{ 33514039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 33614039Sstacze01@arm.com Set &set = sets[s]; 33714039Sstacze01@arm.com 33814039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 33914039Sstacze01@arm.com Entry &e = set[i]; 34014039Sstacze01@arm.com 34114039Sstacze01@arm.com if (e.vmid == vmid) 34214039Sstacze01@arm.com e.valid = false; 34314039Sstacze01@arm.com } 34414039Sstacze01@arm.com } 34514039Sstacze01@arm.com} 34614039Sstacze01@arm.com 34714039Sstacze01@arm.comvoid 34814039Sstacze01@arm.comSMMUTLB::invalidateAll() 34914039Sstacze01@arm.com{ 35014039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 35114039Sstacze01@arm.com Set &set = sets[s]; 35214039Sstacze01@arm.com 35314039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) 35414039Sstacze01@arm.com set[i].valid = false; 35514039Sstacze01@arm.com } 35614039Sstacze01@arm.com} 35714039Sstacze01@arm.com 35814039Sstacze01@arm.comsize_t 35914039Sstacze01@arm.comSMMUTLB::pickSetIdx(Addr va) const 36014039Sstacze01@arm.com{ 36114039Sstacze01@arm.com return (va >> 12) % sets.size(); 36214039Sstacze01@arm.com} 36314039Sstacze01@arm.com 36414039Sstacze01@arm.comsize_t 36514132Sgiacomo.travaglini@arm.comSMMUTLB::pickSetIdx(uint32_t sid, uint32_t ssid) const 36614132Sgiacomo.travaglini@arm.com{ 36714132Sgiacomo.travaglini@arm.com return (sid^ssid) % sets.size(); 36814132Sgiacomo.travaglini@arm.com} 36914132Sgiacomo.travaglini@arm.com 37014132Sgiacomo.travaglini@arm.comsize_t 37114039Sstacze01@arm.comSMMUTLB::pickEntryIdxToReplace(const Set &set, AllocPolicy alloc) 37214039Sstacze01@arm.com{ 37314039Sstacze01@arm.com if (alloc == ALLOC_LAST_WAY) 37414039Sstacze01@arm.com return associativity - 1; 37514039Sstacze01@arm.com 37614039Sstacze01@arm.com uint32_t lru_tick = UINT32_MAX; 37714039Sstacze01@arm.com size_t lru_idx = 0; 37814039Sstacze01@arm.com size_t max_idx = 37914039Sstacze01@arm.com alloc==ALLOC_ANY_BUT_LAST_WAY ? 38014039Sstacze01@arm.com set.size()-1 : set.size(); 38114039Sstacze01@arm.com 38214039Sstacze01@arm.com for (size_t i = 0; i < max_idx; i++) { 38314039Sstacze01@arm.com if (!set[i].valid) { 38414039Sstacze01@arm.com insertions++; 38514039Sstacze01@arm.com return i; 38614039Sstacze01@arm.com } 38714039Sstacze01@arm.com 38814039Sstacze01@arm.com if (set[i].lastUsed < lru_tick) { 38914039Sstacze01@arm.com lru_idx = i; 39014039Sstacze01@arm.com lru_tick = set[i].lastUsed; 39114039Sstacze01@arm.com } 39214039Sstacze01@arm.com } 39314039Sstacze01@arm.com 39414039Sstacze01@arm.com switch (replacementPolicy) { 39514039Sstacze01@arm.com case SMMU_CACHE_REPL_ROUND_ROBIN: 39614039Sstacze01@arm.com switch (alloc) { 39714039Sstacze01@arm.com case ALLOC_ANY_WAY: 39814039Sstacze01@arm.com return nextToReplace = ((nextToReplace+1) % associativity); 39914039Sstacze01@arm.com case ALLOC_ANY_BUT_LAST_WAY: 40014039Sstacze01@arm.com return nextToReplace = ((nextToReplace+1) % (associativity-1)); 40114039Sstacze01@arm.com default: 40214039Sstacze01@arm.com panic("Unknown allocation mode %d\n", alloc); 40314039Sstacze01@arm.com } 40414039Sstacze01@arm.com 40514039Sstacze01@arm.com case SMMU_CACHE_REPL_RANDOM: 40614039Sstacze01@arm.com switch (alloc) { 40714039Sstacze01@arm.com case ALLOC_ANY_WAY: 40814039Sstacze01@arm.com return random.random<size_t>(0, associativity-1); 40914039Sstacze01@arm.com case ALLOC_ANY_BUT_LAST_WAY: 41014039Sstacze01@arm.com return random.random<size_t>(0, associativity-2); 41114039Sstacze01@arm.com default: 41214039Sstacze01@arm.com panic("Unknown allocation mode %d\n", alloc); 41314039Sstacze01@arm.com } 41414039Sstacze01@arm.com 41514039Sstacze01@arm.com case SMMU_CACHE_REPL_LRU: 41614039Sstacze01@arm.com return lru_idx; 41714039Sstacze01@arm.com 41814039Sstacze01@arm.com default: 41914039Sstacze01@arm.com panic("Unknown replacement policy %d\n", replacementPolicy); 42014039Sstacze01@arm.com } 42114039Sstacze01@arm.com} 42214039Sstacze01@arm.com 42314039Sstacze01@arm.com 42414039Sstacze01@arm.com 42514039Sstacze01@arm.com/* 42614039Sstacze01@arm.com * ARMArchTLB 42714039Sstacze01@arm.com */ 42814039Sstacze01@arm.com 42914039Sstacze01@arm.comARMArchTLB::ARMArchTLB(unsigned numEntries, unsigned _associativity, 43014039Sstacze01@arm.com const std::string &policy) 43114039Sstacze01@arm.com: 43214039Sstacze01@arm.com SMMUv3BaseCache(policy, ARMARCHTLB_SEED), 43314039Sstacze01@arm.com associativity(_associativity) 43414039Sstacze01@arm.com{ 43514039Sstacze01@arm.com if (associativity == 0) 43614039Sstacze01@arm.com associativity = numEntries; // fully associative 43714039Sstacze01@arm.com 43814039Sstacze01@arm.com if (numEntries == 0) 43914039Sstacze01@arm.com fatal("ARMArchTLB must have at least one entry\n"); 44014039Sstacze01@arm.com 44114039Sstacze01@arm.com if (associativity > numEntries) 44214039Sstacze01@arm.com fatal("ARMArchTLB associativity cannot be higher than " 44314039Sstacze01@arm.com "its number of entries\n"); 44414039Sstacze01@arm.com 44514039Sstacze01@arm.com unsigned num_sets = numEntries / associativity; 44614039Sstacze01@arm.com 44714039Sstacze01@arm.com if (num_sets*associativity != numEntries) 44814039Sstacze01@arm.com fatal("Number of ARMArchTLB entries must be divisible " 44914039Sstacze01@arm.com "by its associativity\n"); 45014039Sstacze01@arm.com 45114039Sstacze01@arm.com Entry e; 45214039Sstacze01@arm.com e.valid = false; 45314039Sstacze01@arm.com 45414039Sstacze01@arm.com Set set(associativity, e); 45514039Sstacze01@arm.com sets.resize(num_sets, set); 45614039Sstacze01@arm.com} 45714039Sstacze01@arm.com 45814039Sstacze01@arm.comconst ARMArchTLB::Entry * 45914039Sstacze01@arm.comARMArchTLB::lookup(Addr va, uint16_t asid, uint16_t vmid, bool updStats) 46014039Sstacze01@arm.com{ 46114039Sstacze01@arm.com const Entry *result = NULL; 46214039Sstacze01@arm.com 46314039Sstacze01@arm.com Set &set = sets[pickSetIdx(va, asid, vmid)]; 46414039Sstacze01@arm.com 46514039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 46614039Sstacze01@arm.com const Entry &e = set[i]; 46714039Sstacze01@arm.com 46814039Sstacze01@arm.com if (e.valid && (e.va & e.vaMask) == (va & e.vaMask) && 46914039Sstacze01@arm.com e.asid==asid && e.vmid==vmid) 47014039Sstacze01@arm.com { 47114039Sstacze01@arm.com if (result != NULL) 47214039Sstacze01@arm.com panic("ARMArchTLB: duplicate entry found!\n"); 47314039Sstacze01@arm.com 47414039Sstacze01@arm.com result = &e; 47514039Sstacze01@arm.com break; 47614039Sstacze01@arm.com } 47714039Sstacze01@arm.com } 47814039Sstacze01@arm.com 47914039Sstacze01@arm.com if (updStats) { 48014039Sstacze01@arm.com if (result) 48114039Sstacze01@arm.com result->lastUsed = useStamp++; 48214039Sstacze01@arm.com 48314039Sstacze01@arm.com totalLookups++; 48414039Sstacze01@arm.com if (result == NULL) 48514039Sstacze01@arm.com totalMisses++; 48614039Sstacze01@arm.com } 48714039Sstacze01@arm.com 48814039Sstacze01@arm.com return result; 48914039Sstacze01@arm.com} 49014039Sstacze01@arm.com 49114039Sstacze01@arm.comvoid 49214039Sstacze01@arm.comARMArchTLB::store(const Entry &incoming) 49314039Sstacze01@arm.com{ 49414039Sstacze01@arm.com if (!incoming.valid) 49514039Sstacze01@arm.com panic("Tried to store an invalid entry\n"); 49614039Sstacze01@arm.com 49714039Sstacze01@arm.com incoming.lastUsed = 0; 49814039Sstacze01@arm.com 49914039Sstacze01@arm.com const Entry *existing = 50014039Sstacze01@arm.com lookup(incoming.va, incoming.asid, incoming.vmid, false); 50114039Sstacze01@arm.com 50214039Sstacze01@arm.com if (existing) { 50314039Sstacze01@arm.com *const_cast<Entry *> (existing) = incoming; 50414039Sstacze01@arm.com } else { 50514039Sstacze01@arm.com Set &set = sets[pickSetIdx(incoming.va, incoming.asid, incoming.vmid)]; 50614039Sstacze01@arm.com set[pickEntryIdxToReplace(set)] = incoming; 50714039Sstacze01@arm.com } 50814039Sstacze01@arm.com 50914039Sstacze01@arm.com totalUpdates++; 51014039Sstacze01@arm.com} 51114039Sstacze01@arm.com 51214039Sstacze01@arm.comvoid 51314039Sstacze01@arm.comARMArchTLB::invalidateVA(Addr va, uint16_t asid, uint16_t vmid) 51414039Sstacze01@arm.com{ 51514039Sstacze01@arm.com Set &set = sets[pickSetIdx(va, asid, vmid)]; 51614039Sstacze01@arm.com 51714039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 51814039Sstacze01@arm.com Entry &e = set[i]; 51914039Sstacze01@arm.com 52014039Sstacze01@arm.com if ((e.va & e.vaMask) == (va & e.vaMask) && 52114039Sstacze01@arm.com e.asid==asid && e.vmid==vmid) 52214039Sstacze01@arm.com { 52314039Sstacze01@arm.com e.valid = false; 52414039Sstacze01@arm.com } 52514039Sstacze01@arm.com } 52614039Sstacze01@arm.com} 52714039Sstacze01@arm.com 52814039Sstacze01@arm.comvoid 52914039Sstacze01@arm.comARMArchTLB::invalidateVAA(Addr va, uint16_t vmid) 53014039Sstacze01@arm.com{ 53114039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 53214039Sstacze01@arm.com Set &set = sets[s]; 53314039Sstacze01@arm.com 53414039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 53514039Sstacze01@arm.com Entry &e = set[i]; 53614039Sstacze01@arm.com 53714039Sstacze01@arm.com if ((e.va & e.vaMask) == (va & e.vaMask) && e.vmid==vmid) 53814039Sstacze01@arm.com e.valid = false; 53914039Sstacze01@arm.com } 54014039Sstacze01@arm.com } 54114039Sstacze01@arm.com} 54214039Sstacze01@arm.com 54314039Sstacze01@arm.comvoid 54414039Sstacze01@arm.comARMArchTLB::invalidateASID(uint16_t asid, uint16_t vmid) 54514039Sstacze01@arm.com{ 54614039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 54714039Sstacze01@arm.com Set &set = sets[s]; 54814039Sstacze01@arm.com 54914039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 55014039Sstacze01@arm.com Entry &e = set[i]; 55114039Sstacze01@arm.com 55214039Sstacze01@arm.com if (e.asid==asid && e.vmid==vmid) 55314039Sstacze01@arm.com e.valid = false; 55414039Sstacze01@arm.com } 55514039Sstacze01@arm.com } 55614039Sstacze01@arm.com} 55714039Sstacze01@arm.com 55814039Sstacze01@arm.comvoid 55914039Sstacze01@arm.comARMArchTLB::invalidateVMID(uint16_t vmid) 56014039Sstacze01@arm.com{ 56114039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 56214039Sstacze01@arm.com Set &set = sets[s]; 56314039Sstacze01@arm.com 56414039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 56514039Sstacze01@arm.com Entry &e = set[i]; 56614039Sstacze01@arm.com 56714039Sstacze01@arm.com if (e.vmid == vmid) 56814039Sstacze01@arm.com e.valid = false; 56914039Sstacze01@arm.com } 57014039Sstacze01@arm.com } 57114039Sstacze01@arm.com} 57214039Sstacze01@arm.com 57314039Sstacze01@arm.comvoid 57414039Sstacze01@arm.comARMArchTLB::invalidateAll() 57514039Sstacze01@arm.com{ 57614039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 57714039Sstacze01@arm.com Set &set = sets[s]; 57814039Sstacze01@arm.com 57914039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) 58014039Sstacze01@arm.com set[i].valid = false; 58114039Sstacze01@arm.com } 58214039Sstacze01@arm.com} 58314039Sstacze01@arm.com 58414039Sstacze01@arm.comsize_t 58514039Sstacze01@arm.comARMArchTLB::pickSetIdx(Addr va, uint16_t asid, uint16_t vmid) const 58614039Sstacze01@arm.com{ 58714039Sstacze01@arm.com return ((va >> 12) ^ asid ^ vmid) % sets.size(); 58814039Sstacze01@arm.com} 58914039Sstacze01@arm.com 59014039Sstacze01@arm.comsize_t 59114039Sstacze01@arm.comARMArchTLB::pickEntryIdxToReplace(const Set &set) 59214039Sstacze01@arm.com{ 59314039Sstacze01@arm.com size_t lru_idx = 0; 59414039Sstacze01@arm.com uint32_t lru_tick = UINT32_MAX; 59514039Sstacze01@arm.com 59614039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 59714039Sstacze01@arm.com if (!set[i].valid) { 59814039Sstacze01@arm.com insertions++; 59914039Sstacze01@arm.com return i; 60014039Sstacze01@arm.com } 60114039Sstacze01@arm.com 60214039Sstacze01@arm.com if (set[i].lastUsed < lru_tick) { 60314039Sstacze01@arm.com lru_idx = i; 60414039Sstacze01@arm.com lru_tick = set[i].lastUsed; 60514039Sstacze01@arm.com } 60614039Sstacze01@arm.com } 60714039Sstacze01@arm.com 60814039Sstacze01@arm.com switch (replacementPolicy) { 60914039Sstacze01@arm.com case SMMU_CACHE_REPL_ROUND_ROBIN: 61014039Sstacze01@arm.com return nextToReplace = ((nextToReplace+1) % associativity); 61114039Sstacze01@arm.com 61214039Sstacze01@arm.com case SMMU_CACHE_REPL_RANDOM: 61314039Sstacze01@arm.com return random.random<size_t>(0, associativity-1); 61414039Sstacze01@arm.com 61514039Sstacze01@arm.com case SMMU_CACHE_REPL_LRU: 61614039Sstacze01@arm.com return lru_idx; 61714039Sstacze01@arm.com 61814039Sstacze01@arm.com default: 61914039Sstacze01@arm.com panic("Unknown replacement policy %d\n", replacementPolicy); 62014039Sstacze01@arm.com } 62114039Sstacze01@arm.com 62214039Sstacze01@arm.com} 62314039Sstacze01@arm.com 62414039Sstacze01@arm.com/* 62514039Sstacze01@arm.com * IPACache 62614039Sstacze01@arm.com */ 62714039Sstacze01@arm.com 62814039Sstacze01@arm.comIPACache::IPACache(unsigned numEntries, unsigned _associativity, 62914039Sstacze01@arm.com const std::string &policy) 63014039Sstacze01@arm.com: 63114039Sstacze01@arm.com SMMUv3BaseCache(policy, IPACACHE_SEED), 63214039Sstacze01@arm.com associativity(_associativity) 63314039Sstacze01@arm.com{ 63414039Sstacze01@arm.com if (associativity == 0) 63514039Sstacze01@arm.com associativity = numEntries; // fully associative 63614039Sstacze01@arm.com 63714039Sstacze01@arm.com if (numEntries == 0) 63814039Sstacze01@arm.com fatal("IPACache must have at least one entry\n"); 63914039Sstacze01@arm.com 64014039Sstacze01@arm.com if (associativity > numEntries) 64114039Sstacze01@arm.com fatal("IPACache associativity cannot be higher than " 64214039Sstacze01@arm.com "its number of entries\n"); 64314039Sstacze01@arm.com 64414039Sstacze01@arm.com unsigned num_sets = numEntries / associativity; 64514039Sstacze01@arm.com 64614039Sstacze01@arm.com if (num_sets*associativity != numEntries) 64714039Sstacze01@arm.com fatal("Number of IPACache entries must be divisible " 64814039Sstacze01@arm.com "by its associativity\n"); 64914039Sstacze01@arm.com 65014039Sstacze01@arm.com Entry e; 65114039Sstacze01@arm.com e.valid = false; 65214039Sstacze01@arm.com 65314039Sstacze01@arm.com Set set(associativity, e); 65414039Sstacze01@arm.com sets.resize(num_sets, set); 65514039Sstacze01@arm.com} 65614039Sstacze01@arm.com 65714039Sstacze01@arm.comconst IPACache::Entry* 65814039Sstacze01@arm.comIPACache::lookup(Addr ipa, uint16_t vmid, bool updStats) 65914039Sstacze01@arm.com{ 66014039Sstacze01@arm.com const Entry *result = NULL; 66114039Sstacze01@arm.com 66214039Sstacze01@arm.com Set &set = sets[pickSetIdx(ipa, vmid)]; 66314039Sstacze01@arm.com 66414039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 66514039Sstacze01@arm.com const Entry &e = set[i]; 66614039Sstacze01@arm.com 66714039Sstacze01@arm.com if (e.valid && (e.ipa & e.ipaMask) == (ipa & e.ipaMask) && 66814039Sstacze01@arm.com e.vmid==vmid) 66914039Sstacze01@arm.com { 67014039Sstacze01@arm.com if (result != NULL) 67114039Sstacze01@arm.com panic("IPACache: duplicate entry found!\n"); 67214039Sstacze01@arm.com 67314039Sstacze01@arm.com result = &e; 67414039Sstacze01@arm.com break; 67514039Sstacze01@arm.com } 67614039Sstacze01@arm.com } 67714039Sstacze01@arm.com 67814039Sstacze01@arm.com if (updStats) { 67914039Sstacze01@arm.com if (result) 68014039Sstacze01@arm.com result->lastUsed = useStamp++; 68114039Sstacze01@arm.com 68214039Sstacze01@arm.com totalLookups++; 68314039Sstacze01@arm.com if (result == NULL) 68414039Sstacze01@arm.com totalMisses++; 68514039Sstacze01@arm.com } 68614039Sstacze01@arm.com 68714039Sstacze01@arm.com return result; 68814039Sstacze01@arm.com} 68914039Sstacze01@arm.com 69014039Sstacze01@arm.comvoid 69114039Sstacze01@arm.comIPACache::store(const Entry &incoming) 69214039Sstacze01@arm.com{ 69314039Sstacze01@arm.com if (!incoming.valid) 69414039Sstacze01@arm.com panic("Tried to store an invalid entry\n"); 69514039Sstacze01@arm.com 69614039Sstacze01@arm.com incoming.lastUsed = 0; 69714039Sstacze01@arm.com 69814039Sstacze01@arm.com const Entry *existing = lookup(incoming.ipa, incoming.vmid, false); 69914039Sstacze01@arm.com 70014039Sstacze01@arm.com if (existing) { 70114039Sstacze01@arm.com *const_cast<Entry *> (existing) = incoming; 70214039Sstacze01@arm.com } else { 70314039Sstacze01@arm.com Set &set = sets[pickSetIdx(incoming.ipa, incoming.vmid)]; 70414039Sstacze01@arm.com set[pickEntryIdxToReplace(set)] = incoming; 70514039Sstacze01@arm.com } 70614039Sstacze01@arm.com 70714039Sstacze01@arm.com totalUpdates++; 70814039Sstacze01@arm.com} 70914039Sstacze01@arm.com 71014039Sstacze01@arm.comvoid 71114039Sstacze01@arm.comIPACache::invalidateIPA(Addr ipa, uint16_t vmid) 71214039Sstacze01@arm.com{ 71314039Sstacze01@arm.com Set &set = sets[pickSetIdx(ipa, vmid)]; 71414039Sstacze01@arm.com 71514039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 71614039Sstacze01@arm.com Entry &e = set[i]; 71714039Sstacze01@arm.com 71814039Sstacze01@arm.com if ((e.ipa & e.ipaMask) == (ipa & e.ipaMask) && e.vmid==vmid) 71914039Sstacze01@arm.com e.valid = false; 72014039Sstacze01@arm.com } 72114039Sstacze01@arm.com} 72214039Sstacze01@arm.com 72314039Sstacze01@arm.comvoid 72414039Sstacze01@arm.comIPACache::invalidateIPAA(Addr ipa) 72514039Sstacze01@arm.com{ 72614039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 72714039Sstacze01@arm.com Set &set = sets[s]; 72814039Sstacze01@arm.com 72914039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 73014039Sstacze01@arm.com Entry &e = set[i]; 73114039Sstacze01@arm.com 73214039Sstacze01@arm.com if ((e.ipa & e.ipaMask) == (ipa & e.ipaMask)) 73314039Sstacze01@arm.com e.valid = false; 73414039Sstacze01@arm.com } 73514039Sstacze01@arm.com } 73614039Sstacze01@arm.com} 73714039Sstacze01@arm.com 73814039Sstacze01@arm.comvoid 73914039Sstacze01@arm.comIPACache::invalidateVMID(uint16_t vmid) 74014039Sstacze01@arm.com{ 74114039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 74214039Sstacze01@arm.com Set &set = sets[s]; 74314039Sstacze01@arm.com 74414039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 74514039Sstacze01@arm.com Entry &e = set[i]; 74614039Sstacze01@arm.com 74714039Sstacze01@arm.com if (e.vmid == vmid) 74814039Sstacze01@arm.com e.valid = false; 74914039Sstacze01@arm.com } 75014039Sstacze01@arm.com } 75114039Sstacze01@arm.com} 75214039Sstacze01@arm.com 75314039Sstacze01@arm.comvoid 75414039Sstacze01@arm.comIPACache::invalidateAll() 75514039Sstacze01@arm.com{ 75614039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 75714039Sstacze01@arm.com Set &set = sets[s]; 75814039Sstacze01@arm.com 75914039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) 76014039Sstacze01@arm.com set[i].valid = false; 76114039Sstacze01@arm.com } 76214039Sstacze01@arm.com} 76314039Sstacze01@arm.com 76414039Sstacze01@arm.comsize_t 76514039Sstacze01@arm.comIPACache::pickSetIdx(Addr va, uint16_t vmid) const 76614039Sstacze01@arm.com{ 76714039Sstacze01@arm.com return ((va >> 12) ^ vmid) % sets.size(); 76814039Sstacze01@arm.com} 76914039Sstacze01@arm.com 77014039Sstacze01@arm.comsize_t 77114039Sstacze01@arm.comIPACache::pickEntryIdxToReplace(const Set &set) 77214039Sstacze01@arm.com{ 77314039Sstacze01@arm.com size_t lru_idx = 0; 77414039Sstacze01@arm.com uint32_t lru_tick = UINT32_MAX; 77514039Sstacze01@arm.com 77614039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 77714039Sstacze01@arm.com if (!set[i].valid) { 77814039Sstacze01@arm.com insertions++; 77914039Sstacze01@arm.com return i; 78014039Sstacze01@arm.com } 78114039Sstacze01@arm.com 78214039Sstacze01@arm.com if (set[i].lastUsed < lru_tick) { 78314039Sstacze01@arm.com lru_idx = i; 78414039Sstacze01@arm.com lru_tick = set[i].lastUsed; 78514039Sstacze01@arm.com } 78614039Sstacze01@arm.com } 78714039Sstacze01@arm.com 78814039Sstacze01@arm.com switch (replacementPolicy) { 78914039Sstacze01@arm.com case SMMU_CACHE_REPL_ROUND_ROBIN: 79014039Sstacze01@arm.com return nextToReplace = ((nextToReplace+1) % associativity); 79114039Sstacze01@arm.com 79214039Sstacze01@arm.com case SMMU_CACHE_REPL_RANDOM: 79314039Sstacze01@arm.com return random.random<size_t>(0, associativity-1); 79414039Sstacze01@arm.com 79514039Sstacze01@arm.com case SMMU_CACHE_REPL_LRU: 79614039Sstacze01@arm.com return lru_idx; 79714039Sstacze01@arm.com 79814039Sstacze01@arm.com default: 79914039Sstacze01@arm.com panic("Unknown replacement policy %d\n", replacementPolicy); 80014039Sstacze01@arm.com } 80114039Sstacze01@arm.com 80214039Sstacze01@arm.com} 80314039Sstacze01@arm.com 80414039Sstacze01@arm.com/* 80514039Sstacze01@arm.com * ConfigCache 80614039Sstacze01@arm.com */ 80714039Sstacze01@arm.com 80814039Sstacze01@arm.comConfigCache::ConfigCache(unsigned numEntries, unsigned _associativity, 80914039Sstacze01@arm.com const std::string &policy) 81014039Sstacze01@arm.com: 81114039Sstacze01@arm.com SMMUv3BaseCache(policy, CONFIGCACHE_SEED), 81214039Sstacze01@arm.com associativity(_associativity) 81314039Sstacze01@arm.com{ 81414039Sstacze01@arm.com if (associativity == 0) 81514039Sstacze01@arm.com associativity = numEntries; // fully associative 81614039Sstacze01@arm.com 81714039Sstacze01@arm.com if (numEntries == 0) 81814039Sstacze01@arm.com fatal("ConfigCache must have at least one entry\n"); 81914039Sstacze01@arm.com 82014039Sstacze01@arm.com if (associativity > numEntries) 82114039Sstacze01@arm.com fatal("ConfigCache associativity cannot be higher than " 82214039Sstacze01@arm.com "its number of entries\n"); 82314039Sstacze01@arm.com 82414039Sstacze01@arm.com unsigned num_sets = numEntries / associativity; 82514039Sstacze01@arm.com 82614039Sstacze01@arm.com if (num_sets*associativity != numEntries) 82714039Sstacze01@arm.com fatal("Number of ConfigCache entries must be divisible " 82814039Sstacze01@arm.com "by its associativity\n"); 82914039Sstacze01@arm.com 83014039Sstacze01@arm.com Entry e; 83114039Sstacze01@arm.com e.valid = false; 83214039Sstacze01@arm.com 83314039Sstacze01@arm.com Set set(associativity, e); 83414039Sstacze01@arm.com sets.resize(num_sets, set); 83514039Sstacze01@arm.com} 83614039Sstacze01@arm.com 83714039Sstacze01@arm.comconst ConfigCache::Entry * 83814039Sstacze01@arm.comConfigCache::lookup(uint32_t sid, uint32_t ssid, bool updStats) 83914039Sstacze01@arm.com{ 84014039Sstacze01@arm.com const Entry *result = NULL; 84114039Sstacze01@arm.com 84214039Sstacze01@arm.com Set &set = sets[pickSetIdx(sid, ssid)]; 84314039Sstacze01@arm.com 84414039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 84514039Sstacze01@arm.com const Entry &e = set[i]; 84614039Sstacze01@arm.com 84714039Sstacze01@arm.com if (e.valid && e.sid==sid && e.ssid==ssid) 84814039Sstacze01@arm.com { 84914039Sstacze01@arm.com if (result != NULL) 85014039Sstacze01@arm.com panic("ConfigCache: duplicate entry found!\n"); 85114039Sstacze01@arm.com 85214039Sstacze01@arm.com result = &e; 85314039Sstacze01@arm.com break; 85414039Sstacze01@arm.com } 85514039Sstacze01@arm.com } 85614039Sstacze01@arm.com 85714039Sstacze01@arm.com if (updStats) { 85814039Sstacze01@arm.com if (result) 85914039Sstacze01@arm.com result->lastUsed = useStamp++; 86014039Sstacze01@arm.com 86114039Sstacze01@arm.com totalLookups++; 86214039Sstacze01@arm.com if (result == NULL) 86314039Sstacze01@arm.com totalMisses++; 86414039Sstacze01@arm.com } 86514039Sstacze01@arm.com 86614039Sstacze01@arm.com return result; 86714039Sstacze01@arm.com} 86814039Sstacze01@arm.com 86914039Sstacze01@arm.comvoid 87014039Sstacze01@arm.comConfigCache::store(const Entry &incoming) 87114039Sstacze01@arm.com{ 87214039Sstacze01@arm.com if (!incoming.valid) 87314039Sstacze01@arm.com panic("Tried to store an invalid entry\n"); 87414039Sstacze01@arm.com 87514039Sstacze01@arm.com incoming.lastUsed = 0; 87614039Sstacze01@arm.com 87714039Sstacze01@arm.com const Entry *existing = lookup(incoming.sid, incoming.ssid, false); 87814039Sstacze01@arm.com 87914039Sstacze01@arm.com if (existing) { 88014039Sstacze01@arm.com *const_cast<Entry *> (existing) = incoming; 88114039Sstacze01@arm.com } else { 88214039Sstacze01@arm.com Set &set = sets[pickSetIdx(incoming.sid, incoming.ssid)]; 88314039Sstacze01@arm.com set[pickEntryIdxToReplace(set)] = incoming; 88414039Sstacze01@arm.com } 88514039Sstacze01@arm.com 88614039Sstacze01@arm.com totalUpdates++; 88714039Sstacze01@arm.com} 88814039Sstacze01@arm.com 88914039Sstacze01@arm.comvoid 89014039Sstacze01@arm.comConfigCache::invalidateSSID(uint32_t sid, uint32_t ssid) 89114039Sstacze01@arm.com{ 89214039Sstacze01@arm.com Set &set = sets[pickSetIdx(sid, ssid)]; 89314039Sstacze01@arm.com 89414039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 89514039Sstacze01@arm.com Entry &e = set[i]; 89614039Sstacze01@arm.com 89714039Sstacze01@arm.com if (e.sid==sid && e.ssid==ssid) 89814039Sstacze01@arm.com e.valid = false; 89914039Sstacze01@arm.com } 90014039Sstacze01@arm.com} 90114039Sstacze01@arm.com 90214039Sstacze01@arm.comvoid 90314039Sstacze01@arm.comConfigCache::invalidateSID(uint32_t sid) 90414039Sstacze01@arm.com{ 90514039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 90614039Sstacze01@arm.com Set &set = sets[s]; 90714039Sstacze01@arm.com 90814039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 90914039Sstacze01@arm.com Entry &e = set[i]; 91014039Sstacze01@arm.com 91114039Sstacze01@arm.com if (e.sid == sid) 91214039Sstacze01@arm.com e.valid = false; 91314039Sstacze01@arm.com } 91414039Sstacze01@arm.com } 91514039Sstacze01@arm.com} 91614039Sstacze01@arm.com 91714039Sstacze01@arm.comvoid 91814039Sstacze01@arm.comConfigCache::invalidateAll() 91914039Sstacze01@arm.com{ 92014039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 92114039Sstacze01@arm.com Set &set = sets[s]; 92214039Sstacze01@arm.com 92314039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) 92414039Sstacze01@arm.com set[i].valid = false; 92514039Sstacze01@arm.com } 92614039Sstacze01@arm.com} 92714039Sstacze01@arm.com 92814039Sstacze01@arm.comsize_t 92914039Sstacze01@arm.comConfigCache::pickSetIdx(uint32_t sid, uint32_t ssid) const 93014039Sstacze01@arm.com{ 93114039Sstacze01@arm.com return (sid^ssid) % sets.size(); 93214039Sstacze01@arm.com} 93314039Sstacze01@arm.com 93414039Sstacze01@arm.comsize_t 93514039Sstacze01@arm.comConfigCache::pickEntryIdxToReplace(const Set &set) 93614039Sstacze01@arm.com{ 93714039Sstacze01@arm.com size_t lru_idx = 0; 93814039Sstacze01@arm.com uint32_t lru_tick = UINT32_MAX; 93914039Sstacze01@arm.com 94014039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 94114039Sstacze01@arm.com if (!set[i].valid) { 94214039Sstacze01@arm.com insertions++; 94314039Sstacze01@arm.com return i; 94414039Sstacze01@arm.com } 94514039Sstacze01@arm.com 94614039Sstacze01@arm.com if (set[i].lastUsed < lru_tick) { 94714039Sstacze01@arm.com lru_idx = i; 94814039Sstacze01@arm.com lru_tick = set[i].lastUsed; 94914039Sstacze01@arm.com } 95014039Sstacze01@arm.com } 95114039Sstacze01@arm.com 95214039Sstacze01@arm.com switch (replacementPolicy) { 95314039Sstacze01@arm.com case SMMU_CACHE_REPL_ROUND_ROBIN: 95414039Sstacze01@arm.com return nextToReplace = ((nextToReplace+1) % associativity); 95514039Sstacze01@arm.com 95614039Sstacze01@arm.com case SMMU_CACHE_REPL_RANDOM: 95714039Sstacze01@arm.com return random.random<size_t>(0, associativity-1); 95814039Sstacze01@arm.com 95914039Sstacze01@arm.com case SMMU_CACHE_REPL_LRU: 96014039Sstacze01@arm.com return lru_idx; 96114039Sstacze01@arm.com 96214039Sstacze01@arm.com default: 96314039Sstacze01@arm.com panic("Unknown replacement policy %d\n", replacementPolicy); 96414039Sstacze01@arm.com } 96514039Sstacze01@arm.com 96614039Sstacze01@arm.com} 96714039Sstacze01@arm.com 96814039Sstacze01@arm.com/* 96914039Sstacze01@arm.com * WalkCache 97014039Sstacze01@arm.com */ 97114039Sstacze01@arm.com 97214039Sstacze01@arm.comWalkCache::WalkCache(const std::array<unsigned, 2*WALK_CACHE_LEVELS> &_sizes, 97314039Sstacze01@arm.com unsigned _associativity, const std::string &policy) : 97414039Sstacze01@arm.com SMMUv3BaseCache(policy, WALKCACHE_SEED), 97514039Sstacze01@arm.com associativity(_associativity), 97614039Sstacze01@arm.com sizes() 97714039Sstacze01@arm.com{ 97814039Sstacze01@arm.com unsigned numEntries = std::accumulate(&_sizes[0], 97914039Sstacze01@arm.com &_sizes[2*WALK_CACHE_LEVELS], 0); 98014039Sstacze01@arm.com 98114039Sstacze01@arm.com if (associativity == 0) 98214039Sstacze01@arm.com associativity = numEntries; // fully associative 98314039Sstacze01@arm.com 98414039Sstacze01@arm.com if (numEntries == 0) 98514039Sstacze01@arm.com fatal("WalkCache must have at least one entry\n"); 98614039Sstacze01@arm.com 98714039Sstacze01@arm.com for (size_t i = 0; i < 2*WALK_CACHE_LEVELS; i++){ 98814039Sstacze01@arm.com if (_sizes[i] % associativity != 0) 98914039Sstacze01@arm.com fatal("Number of WalkCache entries at each level must be " 99014039Sstacze01@arm.com "divisible by WalkCache associativity\n"); 99114039Sstacze01@arm.com 99214039Sstacze01@arm.com sizes[i] = _sizes[i] / associativity; 99314039Sstacze01@arm.com offsets[i] = i==0 ? 0 : offsets[i-1] + sizes[i-1]; 99414039Sstacze01@arm.com } 99514039Sstacze01@arm.com 99614039Sstacze01@arm.com if (associativity > numEntries) 99714039Sstacze01@arm.com fatal("WalkCache associativity cannot be higher than " 99814039Sstacze01@arm.com "its number of entries\n"); 99914039Sstacze01@arm.com 100014039Sstacze01@arm.com unsigned num_sets = numEntries / associativity; 100114039Sstacze01@arm.com 100214039Sstacze01@arm.com if (num_sets*associativity != numEntries) 100314039Sstacze01@arm.com fatal("Number of WalkCache entries must be divisible " 100414039Sstacze01@arm.com "by its associativity\n"); 100514039Sstacze01@arm.com 100614039Sstacze01@arm.com Entry e; 100714039Sstacze01@arm.com e.valid = false; 100814039Sstacze01@arm.com 100914039Sstacze01@arm.com Set set(associativity, e); 101014039Sstacze01@arm.com sets.resize(num_sets, set); 101114039Sstacze01@arm.com} 101214039Sstacze01@arm.com 101314039Sstacze01@arm.comconst WalkCache::Entry* 101414039Sstacze01@arm.comWalkCache::lookup(Addr va, Addr vaMask, 101514039Sstacze01@arm.com uint16_t asid, uint16_t vmid, 101614039Sstacze01@arm.com unsigned stage, unsigned level, 101714039Sstacze01@arm.com bool updStats) 101814039Sstacze01@arm.com{ 101914039Sstacze01@arm.com const Entry *result = NULL; 102014039Sstacze01@arm.com 102114039Sstacze01@arm.com Set &set = sets[pickSetIdx(va, vaMask, stage, level)]; 102214039Sstacze01@arm.com 102314039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 102414039Sstacze01@arm.com const Entry &e = set[i]; 102514039Sstacze01@arm.com 102614039Sstacze01@arm.com if (e.valid && (e.va & e.vaMask) == (va & e.vaMask) && 102714039Sstacze01@arm.com e.asid==asid && e.vmid==vmid && e.stage==stage && e.level==level) 102814039Sstacze01@arm.com { 102914039Sstacze01@arm.com if (result != NULL) 103014039Sstacze01@arm.com panic("WalkCache: duplicate entry found!\n"); 103114039Sstacze01@arm.com 103214039Sstacze01@arm.com result = &e; 103314039Sstacze01@arm.com break; 103414039Sstacze01@arm.com } 103514039Sstacze01@arm.com } 103614039Sstacze01@arm.com 103714039Sstacze01@arm.com if (updStats) { 103814039Sstacze01@arm.com if (result) 103914039Sstacze01@arm.com result->lastUsed = useStamp++; 104014039Sstacze01@arm.com 104114039Sstacze01@arm.com totalLookups++; 104214039Sstacze01@arm.com if (result == NULL) 104314039Sstacze01@arm.com totalMisses++; 104414039Sstacze01@arm.com 104514039Sstacze01@arm.com lookupsByStageLevel[stage-1][level]++; 104614039Sstacze01@arm.com totalLookupsByStageLevel[stage-1][level]++; 104714039Sstacze01@arm.com if (result == NULL) { 104814039Sstacze01@arm.com missesByStageLevel[stage-1][level]++; 104914039Sstacze01@arm.com totalMissesByStageLevel[stage-1][level]++; 105014039Sstacze01@arm.com } 105114039Sstacze01@arm.com } 105214039Sstacze01@arm.com 105314039Sstacze01@arm.com return result; 105414039Sstacze01@arm.com} 105514039Sstacze01@arm.com 105614039Sstacze01@arm.comvoid 105714039Sstacze01@arm.comWalkCache::store(const Entry &incoming) 105814039Sstacze01@arm.com{ 105914039Sstacze01@arm.com if (!incoming.valid) 106014039Sstacze01@arm.com panic("Tried to store an invalid entry\n"); 106114039Sstacze01@arm.com 106214039Sstacze01@arm.com assert(incoming.stage==1 || incoming.stage==2); 106314039Sstacze01@arm.com assert(incoming.level<=WALK_CACHE_LEVELS); 106414039Sstacze01@arm.com 106514039Sstacze01@arm.com incoming.lastUsed = 0; 106614039Sstacze01@arm.com 106714039Sstacze01@arm.com const Entry *existing = lookup(incoming.va, incoming.vaMask, 106814039Sstacze01@arm.com incoming.asid, incoming.vmid, 106914039Sstacze01@arm.com incoming.stage, incoming.level, false); 107014039Sstacze01@arm.com 107114039Sstacze01@arm.com if (existing) { 107214039Sstacze01@arm.com *const_cast<Entry *> (existing) = incoming; 107314039Sstacze01@arm.com } else { 107414039Sstacze01@arm.com Set &set = sets[pickSetIdx(incoming.va, incoming.vaMask, 107514039Sstacze01@arm.com incoming.stage, incoming.level)]; 107614039Sstacze01@arm.com set[pickEntryIdxToReplace(set, incoming.stage, incoming.level)] = 107714039Sstacze01@arm.com incoming; 107814039Sstacze01@arm.com } 107914039Sstacze01@arm.com 108014039Sstacze01@arm.com totalUpdates++; 108114039Sstacze01@arm.com updatesByStageLevel[incoming.stage-1][incoming.level]++; 108214039Sstacze01@arm.com totalUpdatesByStageLevel[incoming.stage-1][incoming.level]++; 108314039Sstacze01@arm.com} 108414039Sstacze01@arm.com 108514039Sstacze01@arm.comvoid 108614221Sadrian.herrera@arm.comWalkCache::invalidateVA(Addr va, uint16_t asid, uint16_t vmid, 108714221Sadrian.herrera@arm.com const bool leaf_only) 108814039Sstacze01@arm.com{ 108914221Sadrian.herrera@arm.com for (size_t s = 0; s < sets.size(); s++) { 109014221Sadrian.herrera@arm.com Set &set = sets[s]; 109114221Sadrian.herrera@arm.com 109214221Sadrian.herrera@arm.com for (size_t i = 0; i < set.size(); i++) { 109314221Sadrian.herrera@arm.com Entry &e = set[i]; 109414221Sadrian.herrera@arm.com 109514221Sadrian.herrera@arm.com if ((!leaf_only || e.leaf) && (e.va & e.vaMask) == (va & e.vaMask) 109614221Sadrian.herrera@arm.com && e.asid == asid && e.vmid == vmid) 109714221Sadrian.herrera@arm.com { 109814221Sadrian.herrera@arm.com e.valid = false; 109914221Sadrian.herrera@arm.com } 110014221Sadrian.herrera@arm.com } 110114221Sadrian.herrera@arm.com } 110214039Sstacze01@arm.com} 110314039Sstacze01@arm.com 110414039Sstacze01@arm.comvoid 110514221Sadrian.herrera@arm.comWalkCache::invalidateVAA(Addr va, uint16_t vmid, const bool leaf_only) 110614039Sstacze01@arm.com{ 110714221Sadrian.herrera@arm.com for (size_t s = 0; s < sets.size(); s++) { 110814221Sadrian.herrera@arm.com Set &set = sets[s]; 110914221Sadrian.herrera@arm.com 111014221Sadrian.herrera@arm.com for (size_t i = 0; i < set.size(); i++) { 111114221Sadrian.herrera@arm.com Entry &e = set[i]; 111214221Sadrian.herrera@arm.com 111314221Sadrian.herrera@arm.com if ((!leaf_only || e.leaf) && (e.va & e.vaMask) == (va & e.vaMask) 111414221Sadrian.herrera@arm.com && e.vmid == vmid) 111514221Sadrian.herrera@arm.com { 111614221Sadrian.herrera@arm.com e.valid = false; 111714221Sadrian.herrera@arm.com } 111814221Sadrian.herrera@arm.com } 111914221Sadrian.herrera@arm.com } 112014039Sstacze01@arm.com} 112114039Sstacze01@arm.com 112214039Sstacze01@arm.comvoid 112314039Sstacze01@arm.comWalkCache::invalidateASID(uint16_t asid, uint16_t vmid) 112414039Sstacze01@arm.com{ 112514222Sjan-peter.larsson@arm.com for (size_t s = 0; s < sets.size(); s++) { 112614222Sjan-peter.larsson@arm.com Set &set = sets[s]; 112714222Sjan-peter.larsson@arm.com 112814222Sjan-peter.larsson@arm.com for (size_t i = 0; i < set.size(); i++) { 112914222Sjan-peter.larsson@arm.com Entry &e = set[i]; 113014222Sjan-peter.larsson@arm.com 113114222Sjan-peter.larsson@arm.com if (e.asid==asid && e.vmid==vmid) 113214222Sjan-peter.larsson@arm.com e.valid = false; 113314222Sjan-peter.larsson@arm.com } 113414222Sjan-peter.larsson@arm.com } 113514039Sstacze01@arm.com} 113614039Sstacze01@arm.com 113714039Sstacze01@arm.comvoid 113814039Sstacze01@arm.comWalkCache::invalidateVMID(uint16_t vmid) 113914039Sstacze01@arm.com{ 114014039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 114114039Sstacze01@arm.com Set &set = sets[s]; 114214039Sstacze01@arm.com 114314039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 114414039Sstacze01@arm.com Entry &e = set[i]; 114514039Sstacze01@arm.com 114614039Sstacze01@arm.com if (e.vmid == vmid) 114714039Sstacze01@arm.com e.valid = false; 114814039Sstacze01@arm.com } 114914039Sstacze01@arm.com } 115014039Sstacze01@arm.com} 115114039Sstacze01@arm.com 115214039Sstacze01@arm.comvoid 115314039Sstacze01@arm.comWalkCache::invalidateAll() 115414039Sstacze01@arm.com{ 115514039Sstacze01@arm.com for (size_t s = 0; s < sets.size(); s++) { 115614039Sstacze01@arm.com Set &set = sets[s]; 115714039Sstacze01@arm.com 115814039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) 115914039Sstacze01@arm.com set[i].valid = false; 116014039Sstacze01@arm.com } 116114039Sstacze01@arm.com} 116214039Sstacze01@arm.com 116314039Sstacze01@arm.comsize_t 116414039Sstacze01@arm.comWalkCache::pickSetIdx(Addr va, Addr vaMask, 116514039Sstacze01@arm.com unsigned stage, unsigned level) const 116614039Sstacze01@arm.com{ 116714039Sstacze01@arm.com (void) stage; 116814039Sstacze01@arm.com 116914039Sstacze01@arm.com int size, offset; 117014039Sstacze01@arm.com 117114039Sstacze01@arm.com switch (stage) { 117214039Sstacze01@arm.com case 1: 117314039Sstacze01@arm.com assert (level<=3); 117414039Sstacze01@arm.com size = sizes[0*WALK_CACHE_LEVELS + level]; 117514039Sstacze01@arm.com offset = offsets[0*WALK_CACHE_LEVELS + level]; 117614039Sstacze01@arm.com break; 117714039Sstacze01@arm.com 117814039Sstacze01@arm.com case 2: 117914039Sstacze01@arm.com assert (level<=3); 118014039Sstacze01@arm.com size = sizes[1*WALK_CACHE_LEVELS + level]; 118114039Sstacze01@arm.com offset = offsets[1*WALK_CACHE_LEVELS + level]; 118214039Sstacze01@arm.com break; 118314039Sstacze01@arm.com 118414039Sstacze01@arm.com default: 118514039Sstacze01@arm.com panic("bad stage"); 118614039Sstacze01@arm.com } 118714039Sstacze01@arm.com 118814039Sstacze01@arm.com return ((va >> findLsbSet(vaMask)) % size) + offset; 118914039Sstacze01@arm.com} 119014039Sstacze01@arm.com 119114039Sstacze01@arm.comsize_t 119214039Sstacze01@arm.comWalkCache::pickEntryIdxToReplace(const Set &set, 119314039Sstacze01@arm.com unsigned stage, unsigned level) 119414039Sstacze01@arm.com{ 119514039Sstacze01@arm.com size_t lru_idx = 0; 119614039Sstacze01@arm.com uint32_t lru_tick = UINT32_MAX; 119714039Sstacze01@arm.com 119814039Sstacze01@arm.com for (size_t i = 0; i < set.size(); i++) { 119914039Sstacze01@arm.com if (!set[i].valid) { 120014039Sstacze01@arm.com insertions++; 120114039Sstacze01@arm.com insertionsByStageLevel[stage-1][level]++; 120214039Sstacze01@arm.com return i; 120314039Sstacze01@arm.com } 120414039Sstacze01@arm.com 120514039Sstacze01@arm.com if (set[i].lastUsed < lru_tick) { 120614039Sstacze01@arm.com lru_idx = i; 120714039Sstacze01@arm.com lru_tick = set[i].lastUsed; 120814039Sstacze01@arm.com } 120914039Sstacze01@arm.com } 121014039Sstacze01@arm.com 121114039Sstacze01@arm.com switch (replacementPolicy) { 121214039Sstacze01@arm.com case SMMU_CACHE_REPL_ROUND_ROBIN: 121314039Sstacze01@arm.com return nextToReplace = ((nextToReplace+1) % associativity); 121414039Sstacze01@arm.com 121514039Sstacze01@arm.com case SMMU_CACHE_REPL_RANDOM: 121614039Sstacze01@arm.com return random.random<size_t>(0, associativity-1); 121714039Sstacze01@arm.com 121814039Sstacze01@arm.com case SMMU_CACHE_REPL_LRU: 121914039Sstacze01@arm.com return lru_idx; 122014039Sstacze01@arm.com 122114039Sstacze01@arm.com default: 122214039Sstacze01@arm.com panic("Unknown replacement policy %d\n", replacementPolicy); 122314039Sstacze01@arm.com } 122414039Sstacze01@arm.com 122514039Sstacze01@arm.com} 122614039Sstacze01@arm.com 122714039Sstacze01@arm.comvoid 122814039Sstacze01@arm.comWalkCache::regStats(const std::string &name) 122914039Sstacze01@arm.com{ 123014039Sstacze01@arm.com using namespace Stats; 123114039Sstacze01@arm.com 123214039Sstacze01@arm.com SMMUv3BaseCache::regStats(name); 123314039Sstacze01@arm.com 123414039Sstacze01@arm.com for (int s = 0; s < 2; s++) { 123514039Sstacze01@arm.com for (int l = 0; l < WALK_CACHE_LEVELS; l++) { 123614039Sstacze01@arm.com averageLookupsByStageLevel[s][l] 123714039Sstacze01@arm.com .name(csprintf("%s.averageLookupsS%dL%d", name, s+1, l)) 123814039Sstacze01@arm.com .desc("Average number lookups per second") 123914039Sstacze01@arm.com .flags(pdf); 124014039Sstacze01@arm.com 124114039Sstacze01@arm.com totalLookupsByStageLevel[s][l] 124214039Sstacze01@arm.com .name(csprintf("%s.totalLookupsS%dL%d", name, s+1, l)) 124314039Sstacze01@arm.com .desc("Total number of lookups") 124414039Sstacze01@arm.com .flags(pdf); 124514039Sstacze01@arm.com 124614039Sstacze01@arm.com averageLookupsByStageLevel[s][l] = 124714039Sstacze01@arm.com totalLookupsByStageLevel[s][l] / simSeconds; 124814039Sstacze01@arm.com 124914039Sstacze01@arm.com 125014039Sstacze01@arm.com averageMissesByStageLevel[s][l] 125114039Sstacze01@arm.com .name(csprintf("%s.averageMissesS%dL%d", name, s+1, l)) 125214039Sstacze01@arm.com .desc("Average number misses per second") 125314039Sstacze01@arm.com .flags(pdf); 125414039Sstacze01@arm.com 125514039Sstacze01@arm.com totalMissesByStageLevel[s][l] 125614039Sstacze01@arm.com .name(csprintf("%s.totalMissesS%dL%d", name, s+1, l)) 125714039Sstacze01@arm.com .desc("Total number of misses") 125814039Sstacze01@arm.com .flags(pdf); 125914039Sstacze01@arm.com 126014039Sstacze01@arm.com averageMissesByStageLevel[s][l] = 126114039Sstacze01@arm.com totalMissesByStageLevel[s][l] / simSeconds; 126214039Sstacze01@arm.com 126314039Sstacze01@arm.com 126414039Sstacze01@arm.com averageUpdatesByStageLevel[s][l] 126514039Sstacze01@arm.com .name(csprintf("%s.averageUpdatesS%dL%d", name, s+1, l)) 126614039Sstacze01@arm.com .desc("Average number updates per second") 126714039Sstacze01@arm.com .flags(pdf); 126814039Sstacze01@arm.com 126914039Sstacze01@arm.com totalUpdatesByStageLevel[s][l] 127014039Sstacze01@arm.com .name(csprintf("%s.totalUpdatesS%dL%d", name, s+1, l)) 127114039Sstacze01@arm.com .desc("Total number of updates") 127214039Sstacze01@arm.com .flags(pdf); 127314039Sstacze01@arm.com 127414039Sstacze01@arm.com averageUpdatesByStageLevel[s][l] = 127514039Sstacze01@arm.com totalUpdatesByStageLevel[s][l] / simSeconds; 127614039Sstacze01@arm.com 127714039Sstacze01@arm.com 127814039Sstacze01@arm.com averageHitRateByStageLevel[s][l] 127914039Sstacze01@arm.com .name(csprintf("%s.averageHitRateS%dL%d", name, s+1, l)) 128014039Sstacze01@arm.com .desc("Average hit rate") 128114039Sstacze01@arm.com .flags(pdf); 128214039Sstacze01@arm.com 128314039Sstacze01@arm.com averageHitRateByStageLevel[s][l] = 128414039Sstacze01@arm.com (totalLookupsByStageLevel[s][l] - 128514039Sstacze01@arm.com totalMissesByStageLevel[s][l]) 128614039Sstacze01@arm.com / totalLookupsByStageLevel[s][l]; 128714039Sstacze01@arm.com 128814039Sstacze01@arm.com insertionsByStageLevel[s][l] 128914039Sstacze01@arm.com .name(csprintf("%s.insertionsS%dL%d", name, s+1, l)) 129014039Sstacze01@arm.com .desc("Number of insertions (not replacements)") 129114039Sstacze01@arm.com .flags(pdf); 129214039Sstacze01@arm.com } 129314039Sstacze01@arm.com } 129414039Sstacze01@arm.com} 1295