cache.cc (12715:0c8b4f376378) | cache.cc (12719:68a20fbd07a6) |
---|---|
1/* 2 * Copyright (c) 2010-2018 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 --- 1308 unchanged lines hidden (view full) --- 1317 1318 // Reset the bus additional time as it is now accounted for 1319 pkt->headerDelay = pkt->payloadDelay = 0; 1320 1321 cpuSidePort->schedTimingResp(pkt, completion_time, true); 1322} 1323 1324void | 1/* 2 * Copyright (c) 2010-2018 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 --- 1308 unchanged lines hidden (view full) --- 1317 1318 // Reset the bus additional time as it is now accounted for 1319 pkt->headerDelay = pkt->payloadDelay = 0; 1320 1321 cpuSidePort->schedTimingResp(pkt, completion_time, true); 1322} 1323 1324void |
1325Cache::recvTimingResp(PacketPtr pkt) | 1325Cache::serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, CacheBlk *blk, 1326 PacketList &writebacks) |
1326{ | 1327{ |
1327 assert(pkt->isResponse()); 1328 1329 // all header delay should be paid for by the crossbar, unless 1330 // this is a prefetch response from above 1331 panic_if(pkt->headerDelay != 0 && pkt->cmd != MemCmd::HardPFResp, 1332 "%s saw a non-zero packet delay\n", name()); 1333 1334 bool is_error = pkt->isError(); 1335 1336 if (is_error) { 1337 DPRINTF(Cache, "%s: Cache received %s with error\n", __func__, 1338 pkt->print()); 1339 } 1340 1341 DPRINTF(Cache, "%s: Handling response %s\n", __func__, 1342 pkt->print()); 1343 1344 // if this is a write, we should be looking at an uncacheable 1345 // write 1346 if (pkt->isWrite()) { 1347 assert(pkt->req->isUncacheable()); 1348 handleUncacheableWriteResp(pkt); 1349 return; 1350 } 1351 1352 // we have dealt with any (uncacheable) writes above, from here on 1353 // we know we are dealing with an MSHR due to a miss or a prefetch 1354 MSHR *mshr = dynamic_cast<MSHR*>(pkt->popSenderState()); 1355 assert(mshr); 1356 1357 if (mshr == noTargetMSHR) { 1358 // we always clear at least one target 1359 clearBlocked(Blocked_NoTargets); 1360 noTargetMSHR = nullptr; 1361 } 1362 1363 // Initial target is used just for stats | |
1364 MSHR::Target *initial_tgt = mshr->getTarget(); | 1328 MSHR::Target *initial_tgt = mshr->getTarget(); |
1365 int stats_cmd_idx = initial_tgt->pkt->cmdToIndex(); 1366 Tick miss_latency = curTick() - initial_tgt->recvTime; | 1329 // First offset for critical word first calculations 1330 const int initial_offset = initial_tgt->pkt->getOffset(blkSize); |
1367 | 1331 |
1368 if (pkt->req->isUncacheable()) { 1369 assert(pkt->req->masterId() < system->maxMasters()); 1370 mshr_uncacheable_lat[stats_cmd_idx][pkt->req->masterId()] += 1371 miss_latency; 1372 } else { 1373 assert(pkt->req->masterId() < system->maxMasters()); 1374 mshr_miss_latency[stats_cmd_idx][pkt->req->masterId()] += 1375 miss_latency; 1376 } 1377 1378 bool wasFull = mshrQueue.isFull(); 1379 1380 PacketList writebacks; 1381 1382 Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay; 1383 | 1332 const bool is_error = pkt->isError(); |
1384 bool is_fill = !mshr->isForward && 1385 (pkt->isRead() || pkt->cmd == MemCmd::UpgradeResp); | 1333 bool is_fill = !mshr->isForward && 1334 (pkt->isRead() || pkt->cmd == MemCmd::UpgradeResp); |
1386 1387 CacheBlk *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure()); 1388 const bool valid_blk = blk && blk->isValid(); 1389 // If the response indicates that there are no sharers and we 1390 // either had the block already or the response is filling we can 1391 // promote our copy to writable 1392 if (!pkt->hasSharers() && 1393 (is_fill || (valid_blk && !pkt->req->isCacheInvalidate()))) { 1394 mshr->promoteWritable(); 1395 } 1396 1397 if (is_fill && !is_error) { 1398 DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n", 1399 pkt->getAddr()); 1400 1401 blk = handleFill(pkt, blk, writebacks, mshr->allocOnFill()); 1402 assert(blk != nullptr); 1403 } 1404 | |
1405 // allow invalidation responses originating from write-line 1406 // requests to be discarded 1407 bool is_invalidate = pkt->isInvalidate(); 1408 | 1335 // allow invalidation responses originating from write-line 1336 // requests to be discarded 1337 bool is_invalidate = pkt->isInvalidate(); 1338 |
1409 // The block was marked as not readable while there was a pending 1410 // cache maintenance operation, restore its flag. 1411 if (pkt->isClean() && !is_invalidate && valid_blk) { 1412 blk->status |= BlkReadable; 1413 } 1414 1415 // First offset for critical word first calculations 1416 int initial_offset = initial_tgt->pkt->getOffset(blkSize); 1417 | |
1418 MSHR::TargetList targets = mshr->extractServiceableTargets(pkt); 1419 for (auto &target: targets) { 1420 Packet *tgt_pkt = target.pkt; 1421 switch (target.source) { 1422 case MSHR::Target::FromCPU: 1423 Tick completion_time; 1424 // Here we charge on completion_time the delay of the xbar if the 1425 // packet comes from it, charged on headerDelay. --- 19 unchanged lines hidden (view full) --- 1445 if (tgt_pkt->cmd == MemCmd::WriteLineReq) { 1446 assert(!is_error); 1447 // we got the block in a writable state, so promote 1448 // any deferred targets if possible 1449 mshr->promoteWritable(); 1450 // NB: we use the original packet here and not the response! 1451 blk = handleFill(tgt_pkt, blk, writebacks, 1452 targets.allocOnFill); | 1339 MSHR::TargetList targets = mshr->extractServiceableTargets(pkt); 1340 for (auto &target: targets) { 1341 Packet *tgt_pkt = target.pkt; 1342 switch (target.source) { 1343 case MSHR::Target::FromCPU: 1344 Tick completion_time; 1345 // Here we charge on completion_time the delay of the xbar if the 1346 // packet comes from it, charged on headerDelay. --- 19 unchanged lines hidden (view full) --- 1366 if (tgt_pkt->cmd == MemCmd::WriteLineReq) { 1367 assert(!is_error); 1368 // we got the block in a writable state, so promote 1369 // any deferred targets if possible 1370 mshr->promoteWritable(); 1371 // NB: we use the original packet here and not the response! 1372 blk = handleFill(tgt_pkt, blk, writebacks, 1373 targets.allocOnFill); |
1453 assert(blk != nullptr); | 1374 assert(blk); |
1454 1455 // treat as a fill, and discard the invalidation 1456 // response 1457 is_fill = true; 1458 is_invalidate = false; 1459 } 1460 1461 if (is_fill) { --- 112 unchanged lines hidden (view full) --- 1574 // should not invalidate the block, so check if the 1575 // invalidation should be discarded 1576 if (is_invalidate || mshr->hasPostInvalidate()) { 1577 invalidateBlock(blk); 1578 } else if (mshr->hasPostDowngrade()) { 1579 blk->status &= ~BlkWritable; 1580 } 1581 } | 1375 1376 // treat as a fill, and discard the invalidation 1377 // response 1378 is_fill = true; 1379 is_invalidate = false; 1380 } 1381 1382 if (is_fill) { --- 112 unchanged lines hidden (view full) --- 1495 // should not invalidate the block, so check if the 1496 // invalidation should be discarded 1497 if (is_invalidate || mshr->hasPostInvalidate()) { 1498 invalidateBlock(blk); 1499 } else if (mshr->hasPostDowngrade()) { 1500 blk->status &= ~BlkWritable; 1501 } 1502 } |
1503} |
|
1582 | 1504 |
1505void 1506Cache::recvTimingResp(PacketPtr pkt) 1507{ 1508 assert(pkt->isResponse()); 1509 1510 // all header delay should be paid for by the crossbar, unless 1511 // this is a prefetch response from above 1512 panic_if(pkt->headerDelay != 0 && pkt->cmd != MemCmd::HardPFResp, 1513 "%s saw a non-zero packet delay\n", name()); 1514 1515 const bool is_error = pkt->isError(); 1516 1517 if (is_error) { 1518 DPRINTF(Cache, "%s: Cache received %s with error\n", __func__, 1519 pkt->print()); 1520 } 1521 1522 DPRINTF(Cache, "%s: Handling response %s\n", __func__, 1523 pkt->print()); 1524 1525 // if this is a write, we should be looking at an uncacheable 1526 // write 1527 if (pkt->isWrite()) { 1528 assert(pkt->req->isUncacheable()); 1529 handleUncacheableWriteResp(pkt); 1530 return; 1531 } 1532 1533 // we have dealt with any (uncacheable) writes above, from here on 1534 // we know we are dealing with an MSHR due to a miss or a prefetch 1535 MSHR *mshr = dynamic_cast<MSHR*>(pkt->popSenderState()); 1536 assert(mshr); 1537 1538 if (mshr == noTargetMSHR) { 1539 // we always clear at least one target 1540 clearBlocked(Blocked_NoTargets); 1541 noTargetMSHR = nullptr; 1542 } 1543 1544 // Initial target is used just for stats 1545 MSHR::Target *initial_tgt = mshr->getTarget(); 1546 int stats_cmd_idx = initial_tgt->pkt->cmdToIndex(); 1547 Tick miss_latency = curTick() - initial_tgt->recvTime; 1548 1549 if (pkt->req->isUncacheable()) { 1550 assert(pkt->req->masterId() < system->maxMasters()); 1551 mshr_uncacheable_lat[stats_cmd_idx][pkt->req->masterId()] += 1552 miss_latency; 1553 } else { 1554 assert(pkt->req->masterId() < system->maxMasters()); 1555 mshr_miss_latency[stats_cmd_idx][pkt->req->masterId()] += 1556 miss_latency; 1557 } 1558 1559 PacketList writebacks; 1560 1561 bool is_fill = !mshr->isForward && 1562 (pkt->isRead() || pkt->cmd == MemCmd::UpgradeResp); 1563 1564 CacheBlk *blk = tags->findBlock(pkt->getAddr(), pkt->isSecure()); 1565 1566 if (is_fill && !is_error) { 1567 DPRINTF(Cache, "Block for addr %#llx being updated in Cache\n", 1568 pkt->getAddr()); 1569 1570 blk = handleFill(pkt, blk, writebacks, mshr->allocOnFill()); 1571 assert(blk != nullptr); 1572 } 1573 1574 if (blk && blk->isValid() && pkt->isClean() && !pkt->isInvalidate()) { 1575 // The block was marked not readable while there was a pending 1576 // cache maintenance operation, restore its flag. 1577 blk->status |= BlkReadable; 1578 } 1579 1580 if (blk && blk->isWritable() && !pkt->req->isCacheInvalidate()) { 1581 // If at this point the referenced block is writable and the 1582 // response is not a cache invalidate, we promote targets that 1583 // were deferred as we couldn't guarrantee a writable copy 1584 mshr->promoteWritable(); 1585 } 1586 1587 serviceMSHRTargets(mshr, pkt, blk, writebacks); 1588 |
|
1583 if (mshr->promoteDeferredTargets()) { 1584 // avoid later read getting stale data while write miss is 1585 // outstanding.. see comment in timingAccess() 1586 if (blk) { 1587 blk->status &= ~BlkReadable; 1588 } 1589 mshrQueue.markPending(mshr); 1590 schedMemSideSendEvent(clockEdge() + pkt->payloadDelay); 1591 } else { | 1589 if (mshr->promoteDeferredTargets()) { 1590 // avoid later read getting stale data while write miss is 1591 // outstanding.. see comment in timingAccess() 1592 if (blk) { 1593 blk->status &= ~BlkReadable; 1594 } 1595 mshrQueue.markPending(mshr); 1596 schedMemSideSendEvent(clockEdge() + pkt->payloadDelay); 1597 } else { |
1598 // while we deallocate an mshr from the queue we still have to 1599 // check the isFull condition before and after as we might 1600 // have been using the reserved entries already 1601 const bool was_full = mshrQueue.isFull(); |
|
1592 mshrQueue.deallocate(mshr); | 1602 mshrQueue.deallocate(mshr); |
1593 if (wasFull && !mshrQueue.isFull()) { | 1603 if (was_full && !mshrQueue.isFull()) { |
1594 clearBlocked(Blocked_NoMSHRs); 1595 } 1596 1597 // Request the bus for a prefetch if this deallocation freed enough 1598 // MSHRs for a prefetch to take place 1599 if (prefetcher && mshrQueue.canPrefetch()) { 1600 Tick next_pf_time = std::max(prefetcher->nextPrefetchReadyTime(), 1601 clockEdge()); 1602 if (next_pf_time != MaxTick) 1603 schedMemSideSendEvent(next_pf_time); 1604 } 1605 } | 1604 clearBlocked(Blocked_NoMSHRs); 1605 } 1606 1607 // Request the bus for a prefetch if this deallocation freed enough 1608 // MSHRs for a prefetch to take place 1609 if (prefetcher && mshrQueue.canPrefetch()) { 1610 Tick next_pf_time = std::max(prefetcher->nextPrefetchReadyTime(), 1611 clockEdge()); 1612 if (next_pf_time != MaxTick) 1613 schedMemSideSendEvent(next_pf_time); 1614 } 1615 } |
1606 // reset the xbar additional timinig as it is now accounted for 1607 pkt->headerDelay = pkt->payloadDelay = 0; | |
1608 1609 // if we used temp block, check to see if its valid and then clear it out 1610 if (blk == tempBlock && tempBlock->isValid()) { 1611 PacketPtr wb_pkt = tempBlock->isDirty() || writebackClean ? 1612 writebackBlk(blk) : cleanEvictBlk(blk); 1613 writebacks.push_back(wb_pkt); 1614 invalidateBlock(tempBlock); 1615 } 1616 | 1616 1617 // if we used temp block, check to see if its valid and then clear it out 1618 if (blk == tempBlock && tempBlock->isValid()) { 1619 PacketPtr wb_pkt = tempBlock->isDirty() || writebackClean ? 1620 writebackBlk(blk) : cleanEvictBlk(blk); 1621 writebacks.push_back(wb_pkt); 1622 invalidateBlock(tempBlock); 1623 } 1624 |
1625 const Tick forward_time = clockEdge(forwardLatency) + pkt->headerDelay; |
|
1617 // copy writebacks to write buffer 1618 doWritebacks(writebacks, forward_time); 1619 1620 DPRINTF(CacheVerbose, "%s: Leaving with %s\n", __func__, pkt->print()); 1621 delete pkt; 1622} 1623 1624PacketPtr --- 1235 unchanged lines hidden --- | 1626 // copy writebacks to write buffer 1627 doWritebacks(writebacks, forward_time); 1628 1629 DPRINTF(CacheVerbose, "%s: Leaving with %s\n", __func__, pkt->print()); 1630 delete pkt; 1631} 1632 1633PacketPtr --- 1235 unchanged lines hidden --- |