misc: Replaced master/slave terminology
[gem5.git] / src / learning_gem5 / part2 / simple_cache.hh
1 /*
2 * Copyright (c) 2017 Jason Lowe-Power
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
29 #ifndef __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__
30 #define __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__
31
32 #include <unordered_map>
33
34 #include "base/statistics.hh"
35 #include "mem/port.hh"
36 #include "params/SimpleCache.hh"
37 #include "sim/clocked_object.hh"
38
39 /**
40 * A very simple cache object. Has a fully-associative data store with random
41 * replacement.
42 * This cache is fully blocking (not non-blocking). Only a single request can
43 * be outstanding at a time.
44 * This cache is a writeback cache.
45 */
46 class SimpleCache : public ClockedObject
47 {
48 private:
49
50 /**
51 * Port on the CPU-side that receives requests.
52 * Mostly just forwards requests to the cache (owner)
53 */
54 class CPUSidePort : public ResponsePort
55 {
56 private:
57 /// Since this is a vector port, need to know what number this one is
58 int id;
59
60 /// The object that owns this object (SimpleCache)
61 SimpleCache *owner;
62
63 /// True if the port needs to send a retry req.
64 bool needRetry;
65
66 /// If we tried to send a packet and it was blocked, store it here
67 PacketPtr blockedPacket;
68
69 public:
70 /**
71 * Constructor. Just calls the superclass constructor.
72 */
73 CPUSidePort(const std::string& name, int id, SimpleCache *owner) :
74 ResponsePort(name, owner), id(id), owner(owner), needRetry(false),
75 blockedPacket(nullptr)
76 { }
77
78 /**
79 * Send a packet across this port. This is called by the owner and
80 * all of the flow control is hanled in this function.
81 * This is a convenience function for the SimpleCache to send pkts.
82 *
83 * @param packet to send.
84 */
85 void sendPacket(PacketPtr pkt);
86
87 /**
88 * Get a list of the non-overlapping address ranges the owner is
89 * responsible for. All response ports must override this function
90 * and return a populated list with at least one item.
91 *
92 * @return a list of ranges responded to
93 */
94 AddrRangeList getAddrRanges() const override;
95
96 /**
97 * Send a retry to the peer port only if it is needed. This is called
98 * from the SimpleCache whenever it is unblocked.
99 */
100 void trySendRetry();
101
102 protected:
103 /**
104 * Receive an atomic request packet from the request port.
105 * No need to implement in this simple cache.
106 */
107 Tick recvAtomic(PacketPtr pkt) override
108 { panic("recvAtomic unimpl."); }
109
110 /**
111 * Receive a functional request packet from the request port.
112 * Performs a "debug" access updating/reading the data in place.
113 *
114 * @param packet the requestor sent.
115 */
116 void recvFunctional(PacketPtr pkt) override;
117
118 /**
119 * Receive a timing request from the request port.
120 *
121 * @param the packet that the requestor sent
122 * @return whether this object can consume to packet. If false, we
123 * will call sendRetry() when we can try to receive this
124 * request again.
125 */
126 bool recvTimingReq(PacketPtr pkt) override;
127
128 /**
129 * Called by the request port if sendTimingResp was called on this
130 * response port (causing recvTimingResp to be called on the request
131 * port) and was unsuccessful.
132 */
133 void recvRespRetry() override;
134 };
135
136 /**
137 * Port on the memory-side that receives responses.
138 * Mostly just forwards requests to the cache (owner)
139 */
140 class MemSidePort : public RequestPort
141 {
142 private:
143 /// The object that owns this object (SimpleCache)
144 SimpleCache *owner;
145
146 /// If we tried to send a packet and it was blocked, store it here
147 PacketPtr blockedPacket;
148
149 public:
150 /**
151 * Constructor. Just calls the superclass constructor.
152 */
153 MemSidePort(const std::string& name, SimpleCache *owner) :
154 RequestPort(name, owner), owner(owner), blockedPacket(nullptr)
155 { }
156
157 /**
158 * Send a packet across this port. This is called by the owner and
159 * all of the flow control is hanled in this function.
160 * This is a convenience function for the SimpleCache to send pkts.
161 *
162 * @param packet to send.
163 */
164 void sendPacket(PacketPtr pkt);
165
166 protected:
167 /**
168 * Receive a timing response from the response port.
169 */
170 bool recvTimingResp(PacketPtr pkt) override;
171
172 /**
173 * Called by the response port if sendTimingReq was called on this
174 * request port (causing recvTimingReq to be called on the response
175 * port) and was unsuccesful.
176 */
177 void recvReqRetry() override;
178
179 /**
180 * Called to receive an address range change from the peer response
181 * port. The default implementation ignores the change and does
182 * nothing. Override this function in a derived class if the owner
183 * needs to be aware of the address ranges, e.g. in an
184 * interconnect component like a bus.
185 */
186 void recvRangeChange() override;
187 };
188
189 /**
190 * Handle the request from the CPU side. Called from the CPU port
191 * on a timing request.
192 *
193 * @param requesting packet
194 * @param id of the port to send the response
195 * @return true if we can handle the request this cycle, false if the
196 * requestor needs to retry later
197 */
198 bool handleRequest(PacketPtr pkt, int port_id);
199
200 /**
201 * Handle the respone from the memory side. Called from the memory port
202 * on a timing response.
203 *
204 * @param responding packet
205 * @return true if we can handle the response this cycle, false if the
206 * responder needs to retry later
207 */
208 bool handleResponse(PacketPtr pkt);
209
210 /**
211 * Send the packet to the CPU side.
212 * This function assumes the pkt is already a response packet and forwards
213 * it to the correct port. This function also unblocks this object and
214 * cleans up the whole request.
215 *
216 * @param the packet to send to the cpu side
217 */
218 void sendResponse(PacketPtr pkt);
219
220 /**
221 * Handle a packet functionally. Update the data on a write and get the
222 * data on a read. Called from CPU port on a recv functional.
223 *
224 * @param packet to functionally handle
225 */
226 void handleFunctional(PacketPtr pkt);
227
228 /**
229 * Access the cache for a timing access. This is called after the cache
230 * access latency has already elapsed.
231 */
232 void accessTiming(PacketPtr pkt);
233
234 /**
235 * This is where we actually update / read from the cache. This function
236 * is executed on both timing and functional accesses.
237 *
238 * @return true if a hit, false otherwise
239 */
240 bool accessFunctional(PacketPtr pkt);
241
242 /**
243 * Insert a block into the cache. If there is no room left in the cache,
244 * then this function evicts a random entry t make room for the new block.
245 *
246 * @param packet with the data (and address) to insert into the cache
247 */
248 void insert(PacketPtr pkt);
249
250 /**
251 * Return the address ranges this cache is responsible for. Just use the
252 * same as the next upper level of the hierarchy.
253 *
254 * @return the address ranges this cache is responsible for
255 */
256 AddrRangeList getAddrRanges() const;
257
258 /**
259 * Tell the CPU side to ask for our memory ranges.
260 */
261 void sendRangeChange() const;
262
263 /// Latency to check the cache. Number of cycles for both hit and miss
264 const Cycles latency;
265
266 /// The block size for the cache
267 const unsigned blockSize;
268
269 /// Number of blocks in the cache (size of cache / block size)
270 const unsigned capacity;
271
272 /// Instantiation of the CPU-side port
273 std::vector<CPUSidePort> cpuPorts;
274
275 /// Instantiation of the memory-side port
276 MemSidePort memPort;
277
278 /// True if this cache is currently blocked waiting for a response.
279 bool blocked;
280
281 /// Packet that we are currently handling. Used for upgrading to larger
282 /// cache line sizes
283 PacketPtr originalPacket;
284
285 /// The port to send the response when we recieve it back
286 int waitingPortId;
287
288 /// For tracking the miss latency
289 Tick missTime;
290
291 /// An incredibly simple cache storage. Maps block addresses to data
292 std::unordered_map<Addr, uint8_t*> cacheStore;
293
294 /// Cache statistics
295 protected:
296 struct SimpleCacheStats : public Stats::Group
297 {
298 SimpleCacheStats(Stats::Group *parent);
299 Stats::Scalar hits;
300 Stats::Scalar misses;
301 Stats::Histogram missLatency;
302 Stats::Formula hitRatio;
303 } stats;
304
305 public:
306
307 /** constructor
308 */
309 SimpleCache(SimpleCacheParams *params);
310
311 /**
312 * Get a port with a given name and index. This is used at
313 * binding time and returns a reference to a protocol-agnostic
314 * port.
315 *
316 * @param if_name Port name
317 * @param idx Index in the case of a VectorPort
318 *
319 * @return A reference to the given port
320 */
321 Port &getPort(const std::string &if_name,
322 PortID idx=InvalidPortID) override;
323
324 };
325
326
327 #endif // __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__