Apply the gem5 namespace to the codebase. Some anonymous namespaces could theoretically be removed, but since this change's main goal was to keep conflicts at a minimum, it was decided not to modify much the general shape of the files. A few missing comments of the form "// namespace X" that occurred before the newly added "} // namespace gem5" have been added for consistency. std out should not be included in the gem5 namespace, so they weren't. ProtoMessage has not been included in the gem5 namespace, since I'm not familiar with how proto works. Regarding the SystemC files, although they belong to gem5, they actually perform integration between gem5 and SystemC; therefore, it deserved its own separate namespace. Files that are automatically generated have been included in the gem5 namespace. The .isa files currently are limited to a single namespace. This limitation should be later removed to make it easier to accomodate a better API. Regarding the files in util, gem5:: was prepended where suitable. Notice that this patch was tested as much as possible given that most of these were already not previously compiling. Change-Id: Ia53d404ec79c46edaa98f654e23bc3b0e179fe2d Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/46323 Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu> Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu> Reviewed-by: Matthew Poremba <matthew.poremba@amd.com> Tested-by: kokoro <noreply+kokoro@google.com>
255 lines
9.4 KiB
C++
255 lines
9.4 KiB
C++
/*
|
|
* Copyright (c) 2020-2021 ARM Limited
|
|
* All rights reserved
|
|
*
|
|
* The license below extends only to copyright in the software and shall
|
|
* not be construed as granting a license to any other intellectual
|
|
* property including but not limited to intellectual property relating
|
|
* to a hardware implementation of the functionality of the software
|
|
* licensed hereunder. You may use the software subject to the license
|
|
* terms below provided that you ensure that this notice is replicated
|
|
* unmodified and in its entirety in all distributions of the software,
|
|
* modified or unmodified, in source code or in binary form.
|
|
*
|
|
* Copyright (c) 1999-2012 Mark D. Hill and David A. Wood
|
|
* Copyright (c) 2013 Advanced Micro Devices, Inc.
|
|
* 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.
|
|
*/
|
|
|
|
#ifndef __MEM_RUBY_STRUCTURES_CACHEMEMORY_HH__
|
|
#define __MEM_RUBY_STRUCTURES_CACHEMEMORY_HH__
|
|
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include "base/statistics.hh"
|
|
#include "mem/cache/replacement_policies/base.hh"
|
|
#include "mem/cache/replacement_policies/replaceable_entry.hh"
|
|
#include "mem/ruby/common/DataBlock.hh"
|
|
#include "mem/ruby/protocol/CacheRequestType.hh"
|
|
#include "mem/ruby/protocol/CacheResourceType.hh"
|
|
#include "mem/ruby/protocol/RubyRequest.hh"
|
|
#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh"
|
|
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
|
|
#include "mem/ruby/structures/BankedArray.hh"
|
|
#include "mem/ruby/system/CacheRecorder.hh"
|
|
#include "params/RubyCache.hh"
|
|
#include "sim/sim_object.hh"
|
|
|
|
namespace gem5
|
|
{
|
|
|
|
class CacheMemory : public SimObject
|
|
{
|
|
public:
|
|
typedef RubyCacheParams Params;
|
|
typedef std::shared_ptr<replacement_policy::ReplacementData> ReplData;
|
|
CacheMemory(const Params &p);
|
|
~CacheMemory();
|
|
|
|
void init();
|
|
|
|
// Public Methods
|
|
// perform a cache access and see if we hit or not. Return true on a hit.
|
|
bool tryCacheAccess(Addr address, RubyRequestType type,
|
|
DataBlock*& data_ptr);
|
|
|
|
// similar to above, but doesn't require full access check
|
|
bool testCacheAccess(Addr address, RubyRequestType type,
|
|
DataBlock*& data_ptr);
|
|
|
|
// tests to see if an address is present in the cache
|
|
bool isTagPresent(Addr address) const;
|
|
|
|
// Returns true if there is:
|
|
// a) a tag match on this address or there is
|
|
// b) an unused line in the same cache "way"
|
|
bool cacheAvail(Addr address) const;
|
|
|
|
// Returns a NULL entry that acts as a placeholder for invalid lines
|
|
AbstractCacheEntry*
|
|
getNullEntry() const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
// find an unused entry and sets the tag appropriate for the address
|
|
AbstractCacheEntry* allocate(Addr address, AbstractCacheEntry* new_entry);
|
|
void allocateVoid(Addr address, AbstractCacheEntry* new_entry)
|
|
{
|
|
allocate(address, new_entry);
|
|
}
|
|
|
|
// Explicitly free up this address
|
|
void deallocate(Addr address);
|
|
|
|
// Returns with the physical address of the conflicting cache line
|
|
Addr cacheProbe(Addr address) const;
|
|
|
|
// looks an address up in the cache
|
|
AbstractCacheEntry* lookup(Addr address);
|
|
const AbstractCacheEntry* lookup(Addr address) const;
|
|
|
|
Cycles getTagLatency() const { return tagArray.getLatency(); }
|
|
Cycles getDataLatency() const { return dataArray.getLatency(); }
|
|
|
|
bool isBlockInvalid(int64_t cache_set, int64_t loc);
|
|
bool isBlockNotBusy(int64_t cache_set, int64_t loc);
|
|
|
|
// Hook for checkpointing the contents of the cache
|
|
void recordCacheContents(int cntrl, CacheRecorder* tr) const;
|
|
|
|
// Set this address to most recently used
|
|
void setMRU(Addr address);
|
|
void setMRU(Addr addr, int occupancy);
|
|
void setMRU(AbstractCacheEntry* entry);
|
|
int getReplacementWeight(int64_t set, int64_t loc);
|
|
|
|
// Functions for locking and unlocking cache lines corresponding to the
|
|
// provided address. These are required for supporting atomic memory
|
|
// accesses. These are to be used when only the address of the cache entry
|
|
// is available. In case the entry itself is available. use the functions
|
|
// provided by the AbstractCacheEntry class.
|
|
void setLocked (Addr addr, int context);
|
|
void clearLocked (Addr addr);
|
|
void clearLockedAll (int context);
|
|
bool isLocked (Addr addr, int context);
|
|
|
|
// Print cache contents
|
|
void print(std::ostream& out) const;
|
|
void printData(std::ostream& out) const;
|
|
|
|
bool checkResourceAvailable(CacheResourceType res, Addr addr);
|
|
void recordRequestType(CacheRequestType requestType, Addr addr);
|
|
|
|
// hardware transactional memory
|
|
void htmAbortTransaction();
|
|
void htmCommitTransaction();
|
|
|
|
public:
|
|
int getCacheSize() const { return m_cache_size; }
|
|
int getCacheAssoc() const { return m_cache_assoc; }
|
|
int getNumBlocks() const { return m_cache_num_sets * m_cache_assoc; }
|
|
Addr getAddressAtIdx(int idx) const;
|
|
|
|
private:
|
|
// convert a Address to its location in the cache
|
|
int64_t addressToCacheSet(Addr address) const;
|
|
|
|
// Given a cache tag: returns the index of the tag in a set.
|
|
// returns -1 if the tag is not found.
|
|
int findTagInSet(int64_t line, Addr tag) const;
|
|
int findTagInSetIgnorePermissions(int64_t cacheSet, Addr tag) const;
|
|
|
|
// Private copy constructor and assignment operator
|
|
CacheMemory(const CacheMemory& obj);
|
|
CacheMemory& operator=(const CacheMemory& obj);
|
|
|
|
private:
|
|
// Data Members (m_prefix)
|
|
bool m_is_instruction_only_cache;
|
|
|
|
// The first index is the # of cache lines.
|
|
// The second index is the the amount associativity.
|
|
std::unordered_map<Addr, int> m_tag_index;
|
|
std::vector<std::vector<AbstractCacheEntry*> > m_cache;
|
|
|
|
/** We use the replacement policies from the Classic memory system. */
|
|
replacement_policy::Base *m_replacementPolicy_ptr;
|
|
|
|
BankedArray dataArray;
|
|
BankedArray tagArray;
|
|
|
|
int m_cache_size;
|
|
int m_cache_num_sets;
|
|
int m_cache_num_set_bits;
|
|
int m_cache_assoc;
|
|
int m_start_index_bit;
|
|
bool m_resource_stalls;
|
|
int m_block_size;
|
|
|
|
/**
|
|
* We store all the ReplacementData in a 2-dimensional array. By doing
|
|
* this, we can use all replacement policies from Classic system. Ruby
|
|
* cache will deallocate cache entry every time we evict the cache block
|
|
* so we cannot store the ReplacementData inside the cache entry.
|
|
* Instantiate ReplacementData for multiple times will break replacement
|
|
* policy like TreePLRU.
|
|
*/
|
|
std::vector<std::vector<ReplData> > replacement_data;
|
|
|
|
/**
|
|
* Set to true when using WeightedLRU replacement policy, otherwise, set to
|
|
* false.
|
|
*/
|
|
bool m_use_occupancy;
|
|
|
|
private:
|
|
struct CacheMemoryStats : public statistics::Group
|
|
{
|
|
CacheMemoryStats(statistics::Group *parent);
|
|
|
|
statistics::Scalar numDataArrayReads;
|
|
statistics::Scalar numDataArrayWrites;
|
|
statistics::Scalar numTagArrayReads;
|
|
statistics::Scalar numTagArrayWrites;
|
|
|
|
statistics::Scalar numTagArrayStalls;
|
|
statistics::Scalar numDataArrayStalls;
|
|
|
|
// hardware transactional memory
|
|
statistics::Histogram htmTransCommitReadSet;
|
|
statistics::Histogram htmTransCommitWriteSet;
|
|
statistics::Histogram htmTransAbortReadSet;
|
|
statistics::Histogram htmTransAbortWriteSet;
|
|
|
|
statistics::Scalar m_demand_hits;
|
|
statistics::Scalar m_demand_misses;
|
|
statistics::Formula m_demand_accesses;
|
|
|
|
statistics::Scalar m_prefetch_hits;
|
|
statistics::Scalar m_prefetch_misses;
|
|
statistics::Formula m_prefetch_accesses;
|
|
|
|
statistics::Vector m_accessModeType;
|
|
} cacheMemoryStats;
|
|
|
|
public:
|
|
// These function increment the number of demand hits/misses by one
|
|
// each time they are called
|
|
void profileDemandHit();
|
|
void profileDemandMiss();
|
|
void profilePrefetchHit();
|
|
void profilePrefetchMiss();
|
|
};
|
|
|
|
std::ostream& operator<<(std::ostream& out, const CacheMemory& obj);
|
|
|
|
} // namespace gem5
|
|
|
|
#endif // __MEM_RUBY_STRUCTURES_CACHEMEMORY_HH__
|