/** * Copyright (c) 2018 Metempsy Technology Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Javier Bueno */ #include "mem/cache/prefetch/delta_correlating_prediction_tables.hh" #include "debug/HWPrefetch.hh" #include "mem/cache/prefetch/associative_set_impl.hh" #include "params/DCPTPrefetcher.hh" #include "params/DeltaCorrelatingPredictionTables.hh" DeltaCorrelatingPredictionTables::DeltaCorrelatingPredictionTables( DeltaCorrelatingPredictionTablesParams *p) : SimObject(p), deltaBits(p->delta_bits), deltaMaskBits(p->delta_mask_bits), table(p->table_assoc, p->table_entries, p->table_indexing_policy, p->table_replacement_policy, DCPTEntry(p->deltas_per_entry)) { } void DeltaCorrelatingPredictionTables::DCPTEntry::reset() { for (auto &delta : deltas) { delta = 0; } lastAddress = 0; deltaPointer = 0; } void DeltaCorrelatingPredictionTables::DCPTEntry::addAddress(Addr address, unsigned int delta_bits) { if ((address - lastAddress) != 0) { Addr delta = address - lastAddress; // Account for the sign bit Addr max_positive_delta = (1 << (delta_bits-1)) - 1; if (address > lastAddress) { // check positive delta overflow if (delta > max_positive_delta) { delta = 0; } } else { // check negative delta overflow if (lastAddress - address > (max_positive_delta + 1)) { delta = 0; } } deltas[deltaPointer] = delta; deltaPointer = (deltaPointer + 1) % deltas.size(); lastAddress = address; } } void DeltaCorrelatingPredictionTables::DCPTEntry::getCandidates( std::vector &pfs, unsigned int mask) const { // most recent index unsigned int last = (deltaPointer - 1) % deltas.size(); // second most recent index unsigned int last_prev = (deltaPointer - 2) % deltas.size(); int delta_0 = deltas[last_prev]; int delta_1 = deltas[last]; // a delta 0 means that it overflowed, we can not match it if (delta_0 == 0 || delta_1 == 0) { return; } // Try to find the two most recent deltas in a previous position on the // delta circular array, if found, start issuing prefetches using the // remaining deltas (adding each delta to the last Addr to generate the // prefetched address. // oldest index int idx_0 = deltaPointer + 1; // second oldest index int idx_1 = deltaPointer + 2; for (int i = 0; i < deltas.size() - 2; i += 1) { int this_delta_0 = deltas[(idx_0 + i) % deltas.size()]; int this_delta_1 = deltas[(idx_1 + i) % deltas.size()]; if ((this_delta_0 >> mask) == (delta_0 >> mask) && (this_delta_1 >> mask) == (delta_1 >> mask)) { Addr addr = lastAddress; // Pattern found, issue prefetches with the remaining deltas after // this pair i += 2; // skip the matching pair do { int pf_delta = deltas[(idx_0 + i) % deltas.size()]; addr += pf_delta; pfs.push_back(QueuedPrefetcher::AddrPriority(addr, 0)); i += 1; } while (i < deltas.size() - 2); } } } void DeltaCorrelatingPredictionTables::calculatePrefetch( const BasePrefetcher::PrefetchInfo &pfi, std::vector &addresses) { if (!pfi.hasPC()) { DPRINTF(HWPrefetch, "Ignoring request with no PC.\n"); return; } Addr address = pfi.getAddr(); Addr pc = pfi.getPC(); // Look up table entry, is_secure is unused in findEntry because we // index using the pc DCPTEntry *entry = table.findEntry(pc, false /* unused */); if (entry != nullptr) { entry->addAddress(address, deltaBits); //Delta correlating entry->getCandidates(addresses, deltaMaskBits); } else { entry = table.findVictim(pc); table.insertEntry(pc, false /* unused */, entry); entry->lastAddress = address; } } DeltaCorrelatingPredictionTables * DeltaCorrelatingPredictionTablesParams::create() { return new DeltaCorrelatingPredictionTables(this); } DCPTPrefetcher::DCPTPrefetcher(const DCPTPrefetcherParams *p) : QueuedPrefetcher(p), dcpt(*p->dcpt) { } void DCPTPrefetcher::calculatePrefetch(const PrefetchInfo &pfi, std::vector &addresses) { dcpt.calculatePrefetch(pfi, addresses); } DCPTPrefetcher* DCPTPrefetcherParams::create() { return new DCPTPrefetcher(this); }