spatio_temporal_memory_streaming.cc revision 13786:860c780d9f30
113277Sgabeblack@google.com/**
213277Sgabeblack@google.com * Copyright (c) 2019 Metempsy Technology Consulting
313277Sgabeblack@google.com * All rights reserved.
413277Sgabeblack@google.com *
513277Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
613277Sgabeblack@google.com * modification, are permitted provided that the following conditions are
713277Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
813277Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
913277Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1013277Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1113277Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1213277Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1313277Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1413277Sgabeblack@google.com * this software without specific prior written permission.
1513277Sgabeblack@google.com *
1613277Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1713277Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1813277Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1913277Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2013277Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2113277Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2213277Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2313277Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2413277Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2513277Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2613277Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2713277Sgabeblack@google.com *
2813277Sgabeblack@google.com * Authors: Javier Bueno
2913277Sgabeblack@google.com */
3013277Sgabeblack@google.com
3113277Sgabeblack@google.com#include "mem/cache/prefetch/spatio_temporal_memory_streaming.hh"
3213277Sgabeblack@google.com
3313324Sgabeblack@google.com#include "debug/HWPrefetch.hh"
3413277Sgabeblack@google.com#include "mem/cache/prefetch/associative_set_impl.hh"
3513277Sgabeblack@google.com#include "params/STeMSPrefetcher.hh"
3613277Sgabeblack@google.com
3713277Sgabeblack@google.comSTeMSPrefetcher::STeMSPrefetcher(const STeMSPrefetcherParams *p)
3813277Sgabeblack@google.com  : QueuedPrefetcher(p), spatialRegionSize(p->spatial_region_size),
3913277Sgabeblack@google.com    spatialRegionSizeBits(floorLog2(p->spatial_region_size)),
4013277Sgabeblack@google.com    reconstructionEntries(p->reconstruction_entries),
4113277Sgabeblack@google.com    activeGenerationTable(p->active_generation_table_assoc,
4213277Sgabeblack@google.com                          p->active_generation_table_entries,
4313277Sgabeblack@google.com                          p->active_generation_table_indexing_policy,
4413277Sgabeblack@google.com                          p->active_generation_table_replacement_policy,
4513277Sgabeblack@google.com                          ActiveGenerationTableEntry(
4613277Sgabeblack@google.com                              spatialRegionSize / blkSize)),
4713277Sgabeblack@google.com    patternSequenceTable(p->pattern_sequence_table_assoc,
4813277Sgabeblack@google.com                         p->pattern_sequence_table_entries,
4913277Sgabeblack@google.com                         p->pattern_sequence_table_indexing_policy,
5013277Sgabeblack@google.com                         p->pattern_sequence_table_replacement_policy,
5113277Sgabeblack@google.com                         ActiveGenerationTableEntry(
5213277Sgabeblack@google.com                             spatialRegionSize / blkSize)),
5313277Sgabeblack@google.com    rmob(p->region_miss_order_buffer_entries), rmobHead(0)
5413277Sgabeblack@google.com{
5513277Sgabeblack@google.com    fatal_if(!isPowerOf2(spatialRegionSize),
5613277Sgabeblack@google.com        "The spatial region size must be a power of 2.");
5713277Sgabeblack@google.com}
5813277Sgabeblack@google.com
5913277Sgabeblack@google.comvoid
6013277Sgabeblack@google.comSTeMSPrefetcher::checkForActiveGenerationsEnd() {
6113277Sgabeblack@google.com    // This prefetcher operates attached to the L1 and it observes all
6213277Sgabeblack@google.com    // accesses, this guarantees that no evictions are missed
6313277Sgabeblack@google.com
6413277Sgabeblack@google.com    // Iterate over all entries, if any recorded cacheline has been evicted,
6513277Sgabeblack@google.com    // the generation finishes, move the entry to the PST
6613277Sgabeblack@google.com    for (auto &agt_entry : activeGenerationTable) {
6713277Sgabeblack@google.com        if (agt_entry.isValid()) {
6813277Sgabeblack@google.com            bool generation_ended = false;
6913277Sgabeblack@google.com            bool sr_is_secure = agt_entry.isSecure();
7013277Sgabeblack@google.com            for (auto &seq_entry : agt_entry.sequence) {
7113277Sgabeblack@google.com                if (seq_entry.counter > 0) {
7213495Sgabeblack@google.com                    Addr cache_addr =
7313495Sgabeblack@google.com                        agt_entry.paddress + seq_entry.offset * blkSize;
7413495Sgabeblack@google.com                    if (!inCache(cache_addr, sr_is_secure) &&
7513495Sgabeblack@google.com                            !inMissQueue(cache_addr, sr_is_secure)) {
7613495Sgabeblack@google.com                        generation_ended = true;
7713495Sgabeblack@google.com                        break;
7813495Sgabeblack@google.com                    }
7913495Sgabeblack@google.com                }
8013495Sgabeblack@google.com            }
8113495Sgabeblack@google.com            if (generation_ended) {
8213495Sgabeblack@google.com                // PST is indexed using the PC (secure bit is unused)
8313495Sgabeblack@google.com                ActiveGenerationTableEntry *pst_entry =
8413495Sgabeblack@google.com                    patternSequenceTable.findEntry(agt_entry.pc,
8513495Sgabeblack@google.com                                                   false /*unused*/);
8613277Sgabeblack@google.com                if (pst_entry == nullptr) {
8713277Sgabeblack@google.com                    // Tipically an entry will not exist
8813277Sgabeblack@google.com                    pst_entry = patternSequenceTable.findVictim(agt_entry.pc);
8913277Sgabeblack@google.com                    assert(pst_entry != nullptr);
9013277Sgabeblack@google.com                    patternSequenceTable.insertEntry(agt_entry.pc,
9113277Sgabeblack@google.com                            false /*unused*/, pst_entry);
9213277Sgabeblack@google.com                } else {
9313277Sgabeblack@google.com                    patternSequenceTable.accessEntry(pst_entry);
9413277Sgabeblack@google.com                }
9513278Sgabeblack@google.com                // If the entry existed, this will update the values, if not,
9613277Sgabeblack@google.com                // this also sets the values of the entry
9713277Sgabeblack@google.com                pst_entry->update(agt_entry);
9813277Sgabeblack@google.com                // Free the AGT entry
9913277Sgabeblack@google.com                agt_entry.setInvalid();
10013277Sgabeblack@google.com            }
10113277Sgabeblack@google.com        }
10213277Sgabeblack@google.com    }
10313324Sgabeblack@google.com}
10413277Sgabeblack@google.com
10513277Sgabeblack@google.comvoid
10613277Sgabeblack@google.comSTeMSPrefetcher::addToRMOB(Addr sr_addr, Addr pst_addr, unsigned int delta)
10713277Sgabeblack@google.com{
10813277Sgabeblack@google.com    RegionMissOrderBufferEntry &rmob_entry = rmob[rmobHead];
10913277Sgabeblack@google.com    rmobHead = (rmobHead + 1) % rmob.size();
11013277Sgabeblack@google.com
11113277Sgabeblack@google.com    rmob_entry.srAddress = sr_addr;
11213277Sgabeblack@google.com    rmob_entry.pstAddress = pst_addr;
11313277Sgabeblack@google.com    rmob_entry.delta = delta;
11413277Sgabeblack@google.com    rmob_entry.valid = true;
11513277Sgabeblack@google.com}
11613277Sgabeblack@google.com
11713277Sgabeblack@google.comvoid
11813277Sgabeblack@google.comSTeMSPrefetcher::calculatePrefetch(const PrefetchInfo &pfi,
11913277Sgabeblack@google.com                                   std::vector<AddrPriority> &addresses)
12013277Sgabeblack@google.com{
12113277Sgabeblack@google.com    if (!pfi.hasPC()) {
12213277Sgabeblack@google.com        DPRINTF(HWPrefetch, "Ignoring request with no PC.\n");
12313277Sgabeblack@google.com        return;
12413277Sgabeblack@google.com    }
12513277Sgabeblack@google.com
12613277Sgabeblack@google.com    Addr pc = pfi.getPC();
12713277Sgabeblack@google.com    bool is_secure = pfi.isSecure();
12813277Sgabeblack@google.com    // Spatial region address
12913277Sgabeblack@google.com    Addr sr_addr = pfi.getAddr() / spatialRegionSize;
13013277Sgabeblack@google.com    Addr paddr = pfi.getPaddr();
13113277Sgabeblack@google.com
13213277Sgabeblack@google.com    // Offset in cachelines within the spatial region
13313277Sgabeblack@google.com    Addr sr_offset = (pfi.getAddr() % spatialRegionSize) / blkSize;
13413277Sgabeblack@google.com
13513277Sgabeblack@google.com    // Check if any active generation has ended
13613277Sgabeblack@google.com    checkForActiveGenerationsEnd();
13713277Sgabeblack@google.com
13813277Sgabeblack@google.com    ActiveGenerationTableEntry *agt_entry =
13913277Sgabeblack@google.com        activeGenerationTable.findEntry(sr_addr, is_secure);
14013277Sgabeblack@google.com    if (agt_entry != nullptr) {
14113277Sgabeblack@google.com        // found an entry in the AGT, entry is currently being recorded,
14213277Sgabeblack@google.com        // add the offset
14313277Sgabeblack@google.com        activeGenerationTable.accessEntry(agt_entry);
14413277Sgabeblack@google.com        agt_entry->addOffset(sr_offset);
14513277Sgabeblack@google.com        lastTriggerCounter += 1;
14613277Sgabeblack@google.com    } else {
14713277Sgabeblack@google.com        // Not found, this is the first access (Trigger access)
14813277Sgabeblack@google.com
14913277Sgabeblack@google.com        // Add entry to RMOB
15013277Sgabeblack@google.com        Addr pst_addr = (pc << spatialRegionSizeBits) + sr_offset;
15113277Sgabeblack@google.com        addToRMOB(sr_addr, pst_addr, lastTriggerCounter);
15213277Sgabeblack@google.com        // Reset last trigger counter
15313277Sgabeblack@google.com        lastTriggerCounter = 0;
15413277Sgabeblack@google.com
15513277Sgabeblack@google.com        // allocate a new AGT entry
15613277Sgabeblack@google.com        agt_entry = activeGenerationTable.findVictim(sr_addr);
15713277Sgabeblack@google.com        assert(agt_entry != nullptr);
15813277Sgabeblack@google.com        activeGenerationTable.insertEntry(sr_addr, is_secure, agt_entry);
15913277Sgabeblack@google.com        agt_entry->pc = pc;
16013277Sgabeblack@google.com        agt_entry->paddress = paddr;
16113277Sgabeblack@google.com        agt_entry->addOffset(sr_offset);
16213277Sgabeblack@google.com    }
16313277Sgabeblack@google.com    // increase the seq Counter for other entries
16413277Sgabeblack@google.com    for (auto &agt_e : activeGenerationTable) {
16513277Sgabeblack@google.com        if (agt_e.isValid() && agt_entry != &agt_e) {
16613277Sgabeblack@google.com            agt_e.seqCounter += 1;
16713277Sgabeblack@google.com        }
16813277Sgabeblack@google.com    }
16913277Sgabeblack@google.com
17013277Sgabeblack@google.com    // Prefetch generation: if this is a miss, search for the most recent
17113277Sgabeblack@google.com    // entry in the RMOB, and reconstruct the registered access sequence
17213277Sgabeblack@google.com    if (pfi.isCacheMiss()) {
17313277Sgabeblack@google.com        for (unsigned int idx = (rmobHead - 1) % rmob.size();
17413277Sgabeblack@google.com             idx != rmobHead && rmob[idx].valid;
17513277Sgabeblack@google.com             idx = (idx - 1) % rmob.size())
17613277Sgabeblack@google.com        {
17713277Sgabeblack@google.com            if (rmob[idx].srAddress == sr_addr) {
17813277Sgabeblack@google.com                // reconstruct the access sequence
17913277Sgabeblack@google.com                reconstructSequence(idx, addresses);
18013277Sgabeblack@google.com                break;
18113277Sgabeblack@google.com            }
18213288Sgabeblack@google.com        }
18313277Sgabeblack@google.com    }
18413277Sgabeblack@google.com}
18513277Sgabeblack@google.com
18613277Sgabeblack@google.comvoid
18713277Sgabeblack@google.comSTeMSPrefetcher::reconstructSequence(unsigned int rmob_idx,
18813277Sgabeblack@google.com    std::vector<AddrPriority> &addresses)
18913288Sgabeblack@google.com{
19013288Sgabeblack@google.com    std::vector<Addr> reconstruction(reconstructionEntries, MaxAddr);
19113288Sgabeblack@google.com    unsigned int idx = 0;
19213288Sgabeblack@google.com    // process rmob entries from rmob_idx (most recent with
19313288Sgabeblack@google.com    // address = sr_addr) to the last one (rmobHead)
19413288Sgabeblack@google.com    for (int i = rmob_idx;
19513288Sgabeblack@google.com         i != rmobHead && idx < reconstructionEntries;
19613288Sgabeblack@google.com         i = (i + 1) % rmob.size())
19713288Sgabeblack@google.com    {
19813288Sgabeblack@google.com        reconstruction[idx] = rmob[i].srAddress * spatialRegionSize;
19913288Sgabeblack@google.com        unsigned int next_i = (i + 1) % rmob.size();
20013288Sgabeblack@google.com        idx += rmob[next_i].delta + 1;
20113288Sgabeblack@google.com    }
20213277Sgabeblack@google.com    // Now query the PST with the PC of each RMOB entry
203    idx = 0;
204    for (int i = rmob_idx;
205         i != rmobHead && idx < reconstructionEntries;
206         i = (i + 1) % rmob.size())
207    {
208        ActiveGenerationTableEntry *pst_entry =
209            patternSequenceTable.findEntry(rmob[i].pstAddress,
210                                           false /* unused */);
211        if (pst_entry != nullptr) {
212            patternSequenceTable.accessEntry(pst_entry);
213            for (auto &seq_entry : pst_entry->sequence) {
214                if (seq_entry.counter > 1) {
215                    // 3-bit counter: high enough confidence with a
216                    // value greater than 1
217                    Addr rec_addr = rmob[i].srAddress * spatialRegionSize +
218                        seq_entry.offset;
219                    unsigned ridx = idx + seq_entry.delta;
220                    // Try to use the corresponding position, if it has been
221                    // already used, look the surrounding positions
222                    if (ridx < reconstructionEntries &&
223                        reconstruction[ridx] == MaxAddr) {
224                        reconstruction[ridx] = rec_addr;
225                    } else if ((ridx + 1) < reconstructionEntries &&
226                        reconstruction[ridx + 1] == MaxAddr) {
227                        reconstruction[ridx + 1] = rec_addr;
228                    } else if ((ridx + 2) < reconstructionEntries &&
229                        reconstruction[ridx + 2] == MaxAddr) {
230                        reconstruction[ridx + 2] = rec_addr;
231                    } else if ((ridx > 0) &&
232                        ((ridx - 1) < reconstructionEntries) &&
233                        reconstruction[ridx - 1] == MaxAddr) {
234                        reconstruction[ridx - 1] = rec_addr;
235                    } else if ((ridx > 1) &&
236                        ((ridx - 2) < reconstructionEntries) &&
237                        reconstruction[ridx - 2] == MaxAddr) {
238                        reconstruction[ridx - 2] = rec_addr;
239                    }
240                }
241            }
242        }
243        unsigned int next_i = (i + 1) % rmob.size();
244        idx += rmob[next_i].delta + 1;
245    }
246    for (Addr pf_addr : reconstruction) {
247        if (pf_addr != MaxAddr) {
248            addresses.push_back(AddrPriority(pf_addr, 0));
249        }
250    }
251}
252
253STeMSPrefetcher *
254STeMSPrefetcherParams::create()
255{
256   return new STeMSPrefetcher(this);
257}
258