irregular_stream_buffer.cc revision 13669:24ef552b4d6d
1/** 2 * Copyright (c) 2018 Metempsy Technology Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Javier Bueno 29 */ 30 31#include "mem/cache/prefetch/irregular_stream_buffer.hh" 32 33#include "debug/HWPrefetch.hh" 34#include "mem/cache/prefetch/associative_set_impl.hh" 35#include "params/IrregularStreamBufferPrefetcher.hh" 36 37IrregularStreamBufferPrefetcher::IrregularStreamBufferPrefetcher( 38 const IrregularStreamBufferPrefetcherParams *p) 39 : QueuedPrefetcher(p), maxCounterValue(p->max_counter_value), 40 chunkSize(p->chunk_size), 41 prefetchCandidatesPerEntry(p->prefetch_candidates_per_entry), 42 degree(p->degree), 43 trainingUnit(p->training_unit_assoc, p->training_unit_entries, 44 p->training_unit_indexing_policy, 45 p->training_unit_replacement_policy), 46 psAddressMappingCache(p->address_map_cache_assoc, 47 p->address_map_cache_entries, 48 p->ps_address_map_cache_indexing_policy, 49 p->ps_address_map_cache_replacement_policy, 50 AddressMappingEntry(prefetchCandidatesPerEntry)), 51 spAddressMappingCache(p->address_map_cache_assoc, 52 p->address_map_cache_entries, 53 p->sp_address_map_cache_indexing_policy, 54 p->sp_address_map_cache_replacement_policy, 55 AddressMappingEntry(prefetchCandidatesPerEntry)), 56 structuralAddressCounter(0) 57{ 58 assert(isPowerOf2(prefetchCandidatesPerEntry)); 59} 60 61void 62IrregularStreamBufferPrefetcher::calculatePrefetch(const PrefetchInfo &pfi, 63 std::vector<AddrPriority> &addresses) 64{ 65 // This prefetcher requires a PC 66 if (!pfi.hasPC()) { 67 return; 68 } 69 bool is_secure = pfi.isSecure(); 70 Addr pc = pfi.getPC(); 71 Addr addr = blockIndex(pfi.getAddr()); 72 73 // Training, if the entry exists, then we found a correlation between 74 // the entry lastAddress (named as correlated_addr_A) and the address of 75 // the current access (named as correlated_addr_B) 76 TrainingUnitEntry *entry = trainingUnit.findEntry(pc, is_secure); 77 bool correlated_addr_found = false; 78 Addr correlated_addr_A = 0; 79 Addr correlated_addr_B = 0; 80 if (entry != nullptr && entry->lastAddressSecure == is_secure) { 81 trainingUnit.accessEntry(entry); 82 correlated_addr_found = true; 83 correlated_addr_A = entry->lastAddress; 84 correlated_addr_B = addr; 85 } else { 86 entry = trainingUnit.findVictim(pc); 87 assert(entry != nullptr); 88 89 trainingUnit.insertEntry(pc, is_secure, entry); 90 } 91 // Update the entry 92 entry->lastAddress = addr; 93 entry->lastAddressSecure = is_secure; 94 95 if (correlated_addr_found) { 96 // If a correlation was found, update the Physical-to-Structural 97 // table accordingly 98 AddressMapping &mapping_A = getPSMapping(correlated_addr_A, is_secure); 99 AddressMapping &mapping_B = getPSMapping(correlated_addr_B, is_secure); 100 if (mapping_A.counter > 0 && mapping_B.counter > 0) { 101 // Entry for A and B 102 if (mapping_B.address == (mapping_A.address + 1)) { 103 if (mapping_B.counter < maxCounterValue) { 104 mapping_B.counter += 1; 105 } 106 } else { 107 if (mapping_B.counter == 1) { 108 // counter would hit 0, reassign address 109 mapping_B.counter = 1; 110 mapping_B.address = mapping_A.address + 1; 111 addStructuralToPhysicalEntry(mapping_B.address, is_secure, 112 correlated_addr_B); 113 } else { 114 mapping_B.counter -= 1; 115 } 116 } 117 } else { 118 if (mapping_A.counter == 0) { 119 // if A is not valid, generate a new structural address 120 mapping_A.counter = 1; 121 mapping_A.address = structuralAddressCounter; 122 structuralAddressCounter += chunkSize; 123 addStructuralToPhysicalEntry(mapping_A.address, 124 is_secure, correlated_addr_A); 125 } 126 mapping_B.counter = 1; 127 mapping_B.address = mapping_A.address + 1; 128 // update SP-AMC 129 addStructuralToPhysicalEntry(mapping_B.address, is_secure, 130 correlated_addr_B); 131 } 132 } 133 134 // Use the PS mapping to predict future accesses using the current address 135 // - Look for the structured address 136 // - if it exists, use it to generate prefetches for the subsequent 137 // addresses in ascending order, as many as indicated by the degree 138 // (given the structured address S, prefetch S+1, S+2, .. up to S+degree) 139 Addr amc_address = addr / prefetchCandidatesPerEntry; 140 Addr map_index = addr % prefetchCandidatesPerEntry; 141 AddressMappingEntry *ps_am = psAddressMappingCache.findEntry(amc_address, 142 is_secure); 143 if (ps_am != nullptr) { 144 AddressMapping &mapping = ps_am->mappings[map_index]; 145 if (mapping.counter > 0) { 146 Addr sp_address = mapping.address / prefetchCandidatesPerEntry; 147 Addr sp_index = mapping.address % prefetchCandidatesPerEntry; 148 AddressMappingEntry *sp_am = 149 spAddressMappingCache.findEntry(sp_address, is_secure); 150 assert(sp_am != nullptr); 151 for (unsigned d = 1; 152 d <= degree && (sp_index + d) < prefetchCandidatesPerEntry; 153 d += 1) 154 { 155 AddressMapping &spm = sp_am->mappings[sp_index + d]; 156 //generate prefetch 157 if (spm.counter > 0) { 158 Addr pf_addr = spm.address << lBlkSize; 159 addresses.push_back(AddrPriority(pf_addr, 0)); 160 } 161 } 162 } 163 } 164} 165 166IrregularStreamBufferPrefetcher::AddressMapping& 167IrregularStreamBufferPrefetcher::getPSMapping(Addr paddr, bool is_secure) 168{ 169 Addr amc_address = paddr / prefetchCandidatesPerEntry; 170 Addr map_index = paddr % prefetchCandidatesPerEntry; 171 AddressMappingEntry *ps_entry = 172 psAddressMappingCache.findEntry(amc_address, is_secure); 173 if (ps_entry != nullptr) { 174 // A PS-AMC line already exists 175 psAddressMappingCache.accessEntry(ps_entry); 176 } else { 177 ps_entry = psAddressMappingCache.findVictim(amc_address); 178 assert(ps_entry != nullptr); 179 180 psAddressMappingCache.insertEntry(amc_address, is_secure, ps_entry); 181 } 182 return ps_entry->mappings[map_index]; 183} 184 185void 186IrregularStreamBufferPrefetcher::addStructuralToPhysicalEntry( 187 Addr structural_address, bool is_secure, Addr physical_address) 188{ 189 Addr amc_address = structural_address / prefetchCandidatesPerEntry; 190 Addr map_index = structural_address % prefetchCandidatesPerEntry; 191 AddressMappingEntry *sp_entry = 192 spAddressMappingCache.findEntry(amc_address, is_secure); 193 if (sp_entry != nullptr) { 194 spAddressMappingCache.accessEntry(sp_entry); 195 } else { 196 sp_entry = spAddressMappingCache.findVictim(amc_address); 197 assert(sp_entry != nullptr); 198 199 spAddressMappingCache.insertEntry(amc_address, is_secure, sp_entry); 200 } 201 AddressMapping &mapping = sp_entry->mappings[map_index]; 202 mapping.address = physical_address; 203 mapping.counter = 1; 204} 205 206IrregularStreamBufferPrefetcher* 207IrregularStreamBufferPrefetcherParams::create() 208{ 209 return new IrregularStreamBufferPrefetcher(this); 210} 211