mshr.cc (7636:59b6a1b5bb0c) mshr.cc (7667:aa8fd8f6a495)
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * Copyright (c) 2010 Advanced Micro Devices, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright

--- 75 unchanged lines hidden (view full) ---

84 mshr->downstreamPending = true;
85 }
86 }
87
88 push_back(Target(pkt, readyTime, order, source, markPending));
89}
90
91
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * Copyright (c) 2010 Advanced Micro Devices, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright

--- 75 unchanged lines hidden (view full) ---

84 mshr->downstreamPending = true;
85 }
86 }
87
88 push_back(Target(pkt, readyTime, order, source, markPending));
89}
90
91
92static void
93replaceUpgrade(PacketPtr pkt)
94{
95 if (pkt->cmd == MemCmd::UpgradeReq) {
96 pkt->cmd = MemCmd::ReadExReq;
97 DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
98 } else if (pkt->cmd == MemCmd::SCUpgradeReq) {
99 pkt->cmd = MemCmd::SCUpgradeFailReq;
100 DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n");
101 }
102}
103
104
92void
93MSHR::TargetList::replaceUpgrades()
94{
95 if (!hasUpgrade)
96 return;
97
98 Iterator end_i = end();
99 for (Iterator i = begin(); i != end_i; ++i) {
105void
106MSHR::TargetList::replaceUpgrades()
107{
108 if (!hasUpgrade)
109 return;
110
111 Iterator end_i = end();
112 for (Iterator i = begin(); i != end_i; ++i) {
100 if (i->pkt->cmd == MemCmd::UpgradeReq) {
101 i->pkt->cmd = MemCmd::ReadExReq;
102 DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
103 } else if (i->pkt->cmd == MemCmd::SCUpgradeReq) {
104 i->pkt->cmd = MemCmd::SCUpgradeFailReq;
105 DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n");
106 }
113 replaceUpgrade(i->pkt);
107 }
108
109 hasUpgrade = false;
110}
111
112
113void
114MSHR::TargetList::clearDownstreamPending()

--- 60 unchanged lines hidden (view full) ---

175 ntargets = 1;
176 assert(targets->isReset());
177 // Don't know of a case where we would allocate a new MSHR for a
178 // snoop (mem-side request), so set source according to request here
179 Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
180 Target::FromPrefetcher : Target::FromCPU;
181 targets->add(target, whenReady, _order, source, true);
182 assert(deferredTargets->isReset());
114 }
115
116 hasUpgrade = false;
117}
118
119
120void
121MSHR::TargetList::clearDownstreamPending()

--- 60 unchanged lines hidden (view full) ---

182 ntargets = 1;
183 assert(targets->isReset());
184 // Don't know of a case where we would allocate a new MSHR for a
185 // snoop (mem-side request), so set source according to request here
186 Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
187 Target::FromPrefetcher : Target::FromCPU;
188 targets->add(target, whenReady, _order, source, true);
189 assert(deferredTargets->isReset());
183 pendingInvalidate = false;
184 pendingShared = false;
185 data = NULL;
186}
187
188
189void
190MSHR::clearDownstreamPending()
191{
192 assert(downstreamPending);
193 downstreamPending = false;
194 // recursively clear flag on any MSHRs we will be forwarding
195 // responses to
196 targets->clearDownstreamPending();
197}
198
199bool
190 data = NULL;
191}
192
193
194void
195MSHR::clearDownstreamPending()
196{
197 assert(downstreamPending);
198 downstreamPending = false;
199 // recursively clear flag on any MSHRs we will be forwarding
200 // responses to
201 targets->clearDownstreamPending();
202}
203
204bool
200MSHR::markInService()
205MSHR::markInService(PacketPtr pkt)
201{
202 assert(!inService);
203 if (isForwardNoResponse()) {
204 // we just forwarded the request packet & don't expect a
205 // response, so get rid of it
206 assert(getNumTargets() == 1);
207 popTarget();
208 return true;
209 }
210 inService = true;
206{
207 assert(!inService);
208 if (isForwardNoResponse()) {
209 // we just forwarded the request packet & don't expect a
210 // response, so get rid of it
211 assert(getNumTargets() == 1);
212 popTarget();
213 return true;
214 }
215 inService = true;
216 pendingDirty = (targets->needsExclusive ||
217 (!pkt->sharedAsserted() && pkt->memInhibitAsserted()));
218 postInvalidate = postDowngrade = false;
219
211 if (!downstreamPending) {
212 // let upstream caches know that the request has made it to a
213 // level where it's going to get a response
214 targets->clearDownstreamPending();
215 }
216 return false;
217}
218
219
220void
221MSHR::deallocate()
222{
223 assert(targets->empty());
224 targets->resetFlags();
225 assert(deferredTargets->isReset());
226 assert(ntargets == 0);
227 inService = false;
220 if (!downstreamPending) {
221 // let upstream caches know that the request has made it to a
222 // level where it's going to get a response
223 targets->clearDownstreamPending();
224 }
225 return false;
226}
227
228
229void
230MSHR::deallocate()
231{
232 assert(targets->empty());
233 targets->resetFlags();
234 assert(deferredTargets->isReset());
235 assert(ntargets == 0);
236 inService = false;
228 //allocIter = NULL;
229 //readyIter = NULL;
230}
231
232/*
233 * Adds a target to an MSHR
234 */
235void
236MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
237{
238 // if there's a request already in service for this MSHR, we will
239 // have to defer the new target until after the response if any of
240 // the following are true:
241 // - there are other targets already deferred
242 // - there's a pending invalidate to be applied after the response
243 // comes back (but before this target is processed)
237}
238
239/*
240 * Adds a target to an MSHR
241 */
242void
243MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
244{
245 // if there's a request already in service for this MSHR, we will
246 // have to defer the new target until after the response if any of
247 // the following are true:
248 // - there are other targets already deferred
249 // - there's a pending invalidate to be applied after the response
250 // comes back (but before this target is processed)
244 // - the outstanding request is for a non-exclusive block and this
245 // target requires an exclusive block
251 // - this target requires an exclusive block and either we're not
252 // getting an exclusive block back or we have already snooped
253 // another read request that will downgrade our exclusive block
254 // to shared
246
247 // assume we'd never issue a prefetch when we've got an
248 // outstanding miss
249 assert(pkt->cmd != MemCmd::HardPFReq);
250
251 if (inService &&
255
256 // assume we'd never issue a prefetch when we've got an
257 // outstanding miss
258 assert(pkt->cmd != MemCmd::HardPFReq);
259
260 if (inService &&
252 (!deferredTargets->empty() || pendingInvalidate ||
253 (!targets->needsExclusive && pkt->needsExclusive()))) {
261 (!deferredTargets->empty() || hasPostInvalidate() ||
262 (pkt->needsExclusive() &&
263 (!isPendingDirty() || hasPostDowngrade() || isForward)))) {
254 // need to put on deferred list
264 // need to put on deferred list
265 if (hasPostInvalidate())
266 replaceUpgrade(pkt);
255 deferredTargets->add(pkt, whenReady, _order, Target::FromCPU, true);
256 } else {
257 // No request outstanding, or still OK to append to
258 // outstanding request: append to regular target list. Only
259 // mark pending if current request hasn't been issued yet
260 // (isn't in service).
261 targets->add(pkt, whenReady, _order, Target::FromCPU, !inService);
262 }

--- 23 unchanged lines hidden (view full) ---

286 deferredTargets->replaceUpgrades();
287 }
288
289 return false;
290 }
291
292 // From here on down, the request issued by this MSHR logically
293 // precedes the request we're snooping.
267 deferredTargets->add(pkt, whenReady, _order, Target::FromCPU, true);
268 } else {
269 // No request outstanding, or still OK to append to
270 // outstanding request: append to regular target list. Only
271 // mark pending if current request hasn't been issued yet
272 // (isn't in service).
273 targets->add(pkt, whenReady, _order, Target::FromCPU, !inService);
274 }

--- 23 unchanged lines hidden (view full) ---

298 deferredTargets->replaceUpgrades();
299 }
300
301 return false;
302 }
303
304 // From here on down, the request issued by this MSHR logically
305 // precedes the request we're snooping.
294
295 if (pkt->needsExclusive()) {
296 // snooped request still precedes the re-request we'll have to
297 // issue for deferred targets, if any...
298 deferredTargets->replaceUpgrades();
299 }
300
306 if (pkt->needsExclusive()) {
307 // snooped request still precedes the re-request we'll have to
308 // issue for deferred targets, if any...
309 deferredTargets->replaceUpgrades();
310 }
311
301 if (pendingInvalidate) {
312 if (hasPostInvalidate()) {
302 // a prior snoop has already appended an invalidation, so
303 // logically we don't have the block anymore; no need for
304 // further snooping.
305 return true;
306 }
307
313 // a prior snoop has already appended an invalidation, so
314 // logically we don't have the block anymore; no need for
315 // further snooping.
316 return true;
317 }
318
308 if (targets->needsExclusive || pkt->needsExclusive()) {
309 // actual target device (typ. PhysicalMemory) will delete the
310 // packet on reception, so we need to save a copy here
319 if (isPendingDirty() || pkt->isInvalidate()) {
320 // We need to save and replay the packet in two cases:
321 // 1. We're awaiting an exclusive copy, so ownership is pending,
322 // and we need to respond after we receive data.
323 // 2. It's an invalidation (e.g., UpgradeReq), and we need
324 // to forward the snoop up the hierarchy after the current
325 // transaction completes.
326
327 // Actual target device (typ. PhysicalMemory) will delete the
328 // packet on reception, so we need to save a copy here.
311 PacketPtr cp_pkt = new Packet(pkt, true);
312 targets->add(cp_pkt, curTick, _order, Target::FromSnoop,
313 downstreamPending && targets->needsExclusive);
314 ++ntargets;
315
329 PacketPtr cp_pkt = new Packet(pkt, true);
330 targets->add(cp_pkt, curTick, _order, Target::FromSnoop,
331 downstreamPending && targets->needsExclusive);
332 ++ntargets;
333
316 if (targets->needsExclusive) {
317 // We're awaiting an exclusive copy, so ownership is pending.
318 // It's up to us to respond once the data arrives.
334 if (isPendingDirty()) {
319 pkt->assertMemInhibit();
320 pkt->setSupplyExclusive();
335 pkt->assertMemInhibit();
336 pkt->setSupplyExclusive();
321 } else {
322 // Someone else may respond before we get around to
323 // processing this snoop, which means the copied request
324 // pointer will no longer be valid
325 cp_pkt->req = NULL;
326 }
327
328 if (pkt->needsExclusive()) {
329 // This transaction will take away our pending copy
337 }
338
339 if (pkt->needsExclusive()) {
340 // This transaction will take away our pending copy
330 pendingInvalidate = true;
341 postInvalidate = true;
331 }
342 }
332 } else {
333 // Read to a read: no conflict, so no need to record as
334 // target, but make sure neither reader thinks he's getting an
335 // exclusive copy
336 pendingShared = true;
343 }
344
345 if (!pkt->needsExclusive()) {
346 // This transaction will get a read-shared copy, downgrading
347 // our copy if we had an exclusive one
348 postDowngrade = true;
337 pkt->assertShared();
338 }
339
340 return true;
341}
342
343
344bool

--- 9 unchanged lines hidden (view full) ---

354 targets = deferredTargets;
355 deferredTargets = tmp;
356
357 assert(targets->size() == ntargets);
358
359 // clear deferredTargets flags
360 deferredTargets->resetFlags();
361
349 pkt->assertShared();
350 }
351
352 return true;
353}
354
355
356bool

--- 9 unchanged lines hidden (view full) ---

366 targets = deferredTargets;
367 deferredTargets = tmp;
368
369 assert(targets->size() == ntargets);
370
371 // clear deferredTargets flags
372 deferredTargets->resetFlags();
373
362 pendingInvalidate = false;
363 pendingShared = false;
364 order = targets->front().order;
365 readyTime = std::max(curTick, targets->front().readyTime);
366
367 return true;
368}
369
370
371void
372MSHR::handleFill(Packet *pkt, CacheBlk *blk)
373{
374 order = targets->front().order;
375 readyTime = std::max(curTick, targets->front().readyTime);
376
377 return true;
378}
379
380
381void
382MSHR::handleFill(Packet *pkt, CacheBlk *blk)
383{
374 if (pendingShared) {
375 // we snooped another read while this read was in
376 // service... assert shared line on its behalf
377 pkt->assertShared();
378 }
379
380 if (!pkt->sharedAsserted() && !pendingInvalidate
384 if (!pkt->sharedAsserted()
385 && !(hasPostInvalidate() || hasPostDowngrade())
381 && deferredTargets->needsExclusive) {
382 // We got an exclusive response, but we have deferred targets
383 // which are waiting to request an exclusive copy (not because
384 // of a pending invalidate). This can happen if the original
385 // request was for a read-only (non-exclusive) block, but we
386 // got an exclusive copy anyway because of the E part of the
387 // MOESI/MESI protocol. Since we got the exclusive copy
388 // there's no need to defer the targets, so move them up to

--- 33 unchanged lines hidden (view full) ---

422 ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n",
423 prefix, addr, addr+size-1,
424 isForward ? "Forward" : "",
425 isForwardNoResponse() ? "ForwNoResp" : "",
426 needsExclusive() ? "Excl" : "",
427 _isUncacheable ? "Unc" : "",
428 inService ? "InSvc" : "",
429 downstreamPending ? "DwnPend" : "",
386 && deferredTargets->needsExclusive) {
387 // We got an exclusive response, but we have deferred targets
388 // which are waiting to request an exclusive copy (not because
389 // of a pending invalidate). This can happen if the original
390 // request was for a read-only (non-exclusive) block, but we
391 // got an exclusive copy anyway because of the E part of the
392 // MOESI/MESI protocol. Since we got the exclusive copy
393 // there's no need to defer the targets, so move them up to

--- 33 unchanged lines hidden (view full) ---

427 ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n",
428 prefix, addr, addr+size-1,
429 isForward ? "Forward" : "",
430 isForwardNoResponse() ? "ForwNoResp" : "",
431 needsExclusive() ? "Excl" : "",
432 _isUncacheable ? "Unc" : "",
433 inService ? "InSvc" : "",
434 downstreamPending ? "DwnPend" : "",
430 pendingInvalidate ? "PendInv" : "",
431 pendingShared ? "PendShared" : "");
435 hasPostInvalidate() ? "PostInv" : "",
436 hasPostDowngrade() ? "PostDowngr" : "");
432
433 ccprintf(os, "%s Targets:\n", prefix);
434 targets->print(os, verbosity, prefix + " ");
435 if (!deferredTargets->empty()) {
436 ccprintf(os, "%s Deferred Targets:\n", prefix);
437 deferredTargets->print(os, verbosity, prefix + " ");
438 }
439}
440
441MSHR::~MSHR()
442{
443}
437
438 ccprintf(os, "%s Targets:\n", prefix);
439 targets->print(os, verbosity, prefix + " ");
440 if (!deferredTargets->empty()) {
441 ccprintf(os, "%s Deferred Targets:\n", prefix);
442 deferredTargets->print(os, verbosity, prefix + " ");
443 }
444}
445
446MSHR::~MSHR()
447{
448}