mem-ruby: Update stats style
[gem5.git] / src / mem / ruby / structures / CacheMemory.hh
1 /*
2 * Copyright (c) 2020 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood
15 * Copyright (c) 2013 Advanced Micro Devices, Inc.
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 #ifndef __MEM_RUBY_STRUCTURES_CACHEMEMORY_HH__
43 #define __MEM_RUBY_STRUCTURES_CACHEMEMORY_HH__
44
45 #include <string>
46 #include <unordered_map>
47 #include <vector>
48
49 #include "base/statistics.hh"
50 #include "mem/cache/replacement_policies/base.hh"
51 #include "mem/cache/replacement_policies/replaceable_entry.hh"
52 #include "mem/ruby/common/DataBlock.hh"
53 #include "mem/ruby/protocol/CacheRequestType.hh"
54 #include "mem/ruby/protocol/CacheResourceType.hh"
55 #include "mem/ruby/protocol/RubyRequest.hh"
56 #include "mem/ruby/slicc_interface/AbstractCacheEntry.hh"
57 #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
58 #include "mem/ruby/structures/BankedArray.hh"
59 #include "mem/ruby/system/CacheRecorder.hh"
60 #include "params/RubyCache.hh"
61 #include "sim/sim_object.hh"
62
63 class CacheMemory : public SimObject
64 {
65 public:
66 typedef RubyCacheParams Params;
67 typedef std::shared_ptr<ReplacementPolicy::ReplacementData> ReplData;
68 CacheMemory(const Params &p);
69 ~CacheMemory();
70
71 void init();
72
73 // Public Methods
74 // perform a cache access and see if we hit or not. Return true on a hit.
75 bool tryCacheAccess(Addr address, RubyRequestType type,
76 DataBlock*& data_ptr);
77
78 // similar to above, but doesn't require full access check
79 bool testCacheAccess(Addr address, RubyRequestType type,
80 DataBlock*& data_ptr);
81
82 // tests to see if an address is present in the cache
83 bool isTagPresent(Addr address) const;
84
85 // Returns true if there is:
86 // a) a tag match on this address or there is
87 // b) an unused line in the same cache "way"
88 bool cacheAvail(Addr address) const;
89
90 // Returns a NULL entry that acts as a placeholder for invalid lines
91 AbstractCacheEntry*
92 getNullEntry() const
93 {
94 return nullptr;
95 }
96
97 // find an unused entry and sets the tag appropriate for the address
98 AbstractCacheEntry* allocate(Addr address, AbstractCacheEntry* new_entry);
99 void allocateVoid(Addr address, AbstractCacheEntry* new_entry)
100 {
101 allocate(address, new_entry);
102 }
103
104 // Explicitly free up this address
105 void deallocate(Addr address);
106
107 // Returns with the physical address of the conflicting cache line
108 Addr cacheProbe(Addr address) const;
109
110 // looks an address up in the cache
111 AbstractCacheEntry* lookup(Addr address);
112 const AbstractCacheEntry* lookup(Addr address) const;
113
114 Cycles getTagLatency() const { return tagArray.getLatency(); }
115 Cycles getDataLatency() const { return dataArray.getLatency(); }
116
117 bool isBlockInvalid(int64_t cache_set, int64_t loc);
118 bool isBlockNotBusy(int64_t cache_set, int64_t loc);
119
120 // Hook for checkpointing the contents of the cache
121 void recordCacheContents(int cntrl, CacheRecorder* tr) const;
122
123 // Set this address to most recently used
124 void setMRU(Addr address);
125 void setMRU(Addr addr, int occupancy);
126 void setMRU(AbstractCacheEntry* entry);
127 int getReplacementWeight(int64_t set, int64_t loc);
128
129 // Functions for locking and unlocking cache lines corresponding to the
130 // provided address. These are required for supporting atomic memory
131 // accesses. These are to be used when only the address of the cache entry
132 // is available. In case the entry itself is available. use the functions
133 // provided by the AbstractCacheEntry class.
134 void setLocked (Addr addr, int context);
135 void clearLocked (Addr addr);
136 void clearLockedAll (int context);
137 bool isLocked (Addr addr, int context);
138
139 // Print cache contents
140 void print(std::ostream& out) const;
141 void printData(std::ostream& out) const;
142
143 bool checkResourceAvailable(CacheResourceType res, Addr addr);
144 void recordRequestType(CacheRequestType requestType, Addr addr);
145
146 // hardware transactional memory
147 void htmAbortTransaction();
148 void htmCommitTransaction();
149
150 public:
151 struct CacheMemoryStats : public Stats::Group
152 {
153 CacheMemoryStats(Stats::Group *parent);
154
155 Stats::Scalar numDataArrayReads;
156 Stats::Scalar numDataArrayWrites;
157 Stats::Scalar numTagArrayReads;
158 Stats::Scalar numTagArrayWrites;
159
160 Stats::Scalar numTagArrayStalls;
161 Stats::Scalar numDataArrayStalls;
162
163 // hardware transactional memory
164 Stats::Histogram htmTransCommitReadSet;
165 Stats::Histogram htmTransCommitWriteSet;
166 Stats::Histogram htmTransAbortReadSet;
167 Stats::Histogram htmTransAbortWriteSet;
168 };
169
170 int getCacheSize() const { return m_cache_size; }
171 int getCacheAssoc() const { return m_cache_assoc; }
172 int getNumBlocks() const { return m_cache_num_sets * m_cache_assoc; }
173 Addr getAddressAtIdx(int idx) const;
174
175 private:
176 // convert a Address to its location in the cache
177 int64_t addressToCacheSet(Addr address) const;
178
179 // Given a cache tag: returns the index of the tag in a set.
180 // returns -1 if the tag is not found.
181 int findTagInSet(int64_t line, Addr tag) const;
182 int findTagInSetIgnorePermissions(int64_t cacheSet, Addr tag) const;
183
184 // Private copy constructor and assignment operator
185 CacheMemory(const CacheMemory& obj);
186 CacheMemory& operator=(const CacheMemory& obj);
187
188 private:
189 // Data Members (m_prefix)
190 bool m_is_instruction_only_cache;
191
192 // The first index is the # of cache lines.
193 // The second index is the the amount associativity.
194 std::unordered_map<Addr, int> m_tag_index;
195 std::vector<std::vector<AbstractCacheEntry*> > m_cache;
196
197 /** We use the replacement policies from the Classic memory system. */
198 ReplacementPolicy::Base *m_replacementPolicy_ptr;
199
200 BankedArray dataArray;
201 BankedArray tagArray;
202
203 int m_cache_size;
204 int m_cache_num_sets;
205 int m_cache_num_set_bits;
206 int m_cache_assoc;
207 int m_start_index_bit;
208 bool m_resource_stalls;
209 int m_block_size;
210
211 /**
212 * We store all the ReplacementData in a 2-dimensional array. By doing
213 * this, we can use all replacement policies from Classic system. Ruby
214 * cache will deallocate cache entry every time we evict the cache block
215 * so we cannot store the ReplacementData inside the cache entry.
216 * Instantiate ReplacementData for multiple times will break replacement
217 * policy like TreePLRU.
218 */
219 std::vector<std::vector<ReplData> > replacement_data;
220
221 /**
222 * Set to true when using WeightedLRU replacement policy, otherwise, set to
223 * false.
224 */
225 bool m_use_occupancy;
226
227 public:
228 CacheMemoryStats cacheMemoryStats;
229 Stats::Scalar m_demand_hits;
230 Stats::Scalar m_demand_misses;
231 Stats::Formula m_demand_accesses;
232
233 Stats::Scalar m_sw_prefetches;
234 Stats::Scalar m_hw_prefetches;
235 Stats::Formula m_prefetches;
236
237 Stats::Vector m_accessModeType;
238 };
239
240 std::ostream& operator<<(std::ostream& out, const CacheMemory& obj);
241
242 #endif // __MEM_RUBY_STRUCTURES_CACHEMEMORY_HH__