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::serviceMSHRTargets(MSHR *mshr, const PacketPtr pkt, CacheBlk *blk, 1326 PacketList &writebacks) |
1327{ |
1328 MSHR::Target *initial_tgt = mshr->getTarget(); |
1329 // First offset for critical word first calculations 1330 const int initial_offset = initial_tgt->pkt->getOffset(blkSize); |
1331 |
1332 const bool is_error = pkt->isError(); |
1333 bool is_fill = !mshr->isForward && 1334 (pkt->isRead() || pkt->cmd == MemCmd::UpgradeResp); |
1335 // allow invalidation responses originating from write-line 1336 // requests to be discarded 1337 bool is_invalidate = pkt->isInvalidate(); 1338 |
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); |
1374 assert(blk); |
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} |
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 |
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(); |
1602 mshrQueue.deallocate(mshr); |
1603 if (was_full && !mshrQueue.isFull()) { |
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 } |
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; |
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 --- |