X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Fpacket.cc;h=551ccd8be69f9f74e7a49b503ce4c5a48215fbb6;hb=078bdc86617e096d545b253f359ab27d5b3fdced;hp=e05783ca9cd5edb5b0feb049fb709cce6ea75b77;hpb=1088f0c4ac3999fc3c363cc51daef4cfb360a2bd;p=gem5.git diff --git a/src/mem/packet.cc b/src/mem/packet.cc index e05783ca9..551ccd8be 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 ARM Limited + * Copyright (c) 2011-2019 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -50,14 +50,16 @@ #include "mem/packet.hh" +#include #include #include +#include +#include #include "base/cprintf.hh" #include "base/logging.hh" #include "base/trace.hh" - -using namespace std; +#include "mem/packet_access.hh" // The one downside to bitsets is that static initializers can get ugly. #define SET1(a1) (1 << (a1)) @@ -95,11 +97,17 @@ MemCmd::commandInfo[] = * dirty. */ { SET5(IsWrite, IsRequest, IsEviction, HasData, FromCache), InvalidCmd, "WritebackClean" }, + /* WriteClean - This allows a cache to write a dirty block to a memory + below without evicting its copy. */ + { SET4(IsWrite, IsRequest, HasData, FromCache), InvalidCmd, "WriteClean" }, /* CleanEvict */ { SET3(IsRequest, IsEviction, FromCache), InvalidCmd, "CleanEvict" }, /* SoftPFReq */ { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse), SoftPFResp, "SoftPFReq" }, + /* SoftPFExReq */ + { SET6(IsRead, NeedsWritable, IsInvalidate, IsRequest, + IsSWPrefetch, NeedsResponse), SoftPFResp, "SoftPFExReq" }, /* HardPFReq */ { SET5(IsRead, IsRequest, IsHWPrefetch, NeedsResponse, FromCache), HardPFResp, "HardPFReq" }, @@ -172,15 +180,30 @@ MemCmd::commandInfo[] = /* SwapResp -- for Swap ldstub type operations */ { SET4(IsRead, IsWrite, IsResponse, HasData), InvalidCmd, "SwapResp" }, - /* IntReq -- for interrupts */ - { SET4(IsWrite, IsRequest, NeedsResponse, HasData), - MessageResp, "MessageReq" }, - /* IntResp -- for interrupts */ - { SET2(IsWrite, IsResponse), InvalidCmd, "MessageResp" }, + { 0, InvalidCmd, "Deprecated_MessageReq" }, + { 0, InvalidCmd, "Deprecated_MessageResp" }, /* MemFenceReq -- for synchronization requests */ {SET2(IsRequest, NeedsResponse), MemFenceResp, "MemFenceReq"}, /* MemFenceResp -- for synchronization responses */ {SET1(IsResponse), InvalidCmd, "MemFenceResp"}, + /* Cache Clean Request -- Update with the latest data all existing + copies of the block down to the point indicated by the + request */ + { SET4(IsRequest, IsClean, NeedsResponse, FromCache), + CleanSharedResp, "CleanSharedReq" }, + /* Cache Clean Response - Indicates that all caches up to the + specified point of reference have a up-to-date copy of the + cache block or no copy at all */ + { SET2(IsResponse, IsClean), InvalidCmd, "CleanSharedResp" }, + /* Cache Clean and Invalidate Request -- Invalidate all existing + copies down to the point indicated by the request */ + { SET5(IsRequest, IsInvalidate, IsClean, NeedsResponse, FromCache), + CleanInvalidResp, "CleanInvalidReq" }, + /* Cache Clean and Invalidate Respose -- Indicates that no cache + above the specified point holds the block and that the block + was written to a memory below the specified point. */ + { SET3(IsResponse, IsInvalidate, IsClean), + InvalidCmd, "CleanInvalidResp" }, /* InvalidDestError -- packet dest field invalid */ { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" }, /* BadAddressError -- memory address invalid */ @@ -201,14 +224,20 @@ MemCmd::commandInfo[] = InvalidCmd, "InvalidateResp" } }; +AddrRange +Packet::getAddrRange() const +{ + return RangeSize(getAddr(), getSize()); +} + bool -Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size, +Packet::trySatisfyFunctional(Printable *obj, Addr addr, bool is_secure, int size, uint8_t *_data) { - Addr func_start = getAddr(); - Addr func_end = getAddr() + getSize() - 1; - Addr val_start = addr; - Addr val_end = val_start + size - 1; + const Addr func_start = getAddr(); + const Addr func_end = getAddr() + getSize() - 1; + const Addr val_start = addr; + const Addr val_end = val_start + size - 1; if (is_secure != _isSecure || func_start > val_end || val_start > func_end) { @@ -229,94 +258,45 @@ Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size, return false; } - // offset of functional request into supplied value (could be - // negative if partial overlap) - int offset = func_start - val_start; + const Addr val_offset = func_start > val_start ? + func_start - val_start : 0; + const Addr func_offset = func_start < val_start ? + val_start - func_start : 0; + const Addr overlap_size = std::min(val_end, func_end)+1 - + std::max(val_start, func_start); if (isRead()) { - if (func_start >= val_start && func_end <= val_end) { - memcpy(getPtr(), _data + offset, getSize()); - if (bytesValid.empty()) - bytesValid.resize(getSize(), true); - // complete overlap, and as the current packet is a read - // we are done - return true; - } else { - // Offsets and sizes to copy in case of partial overlap - int func_offset; - int val_offset; - int overlap_size; - - // calculate offsets and copy sizes for the two byte arrays - if (val_start < func_start && val_end <= func_end) { - // the one we are checking against starts before and - // ends before or the same - val_offset = func_start - val_start; - func_offset = 0; - overlap_size = val_end - func_start; - } else if (val_start >= func_start && val_end > func_end) { - // the one we are checking against starts after or the - // same, and ends after - val_offset = 0; - func_offset = val_start - func_start; - overlap_size = func_end - val_start; - } else if (val_start >= func_start && val_end <= func_end) { - // the one we are checking against is completely - // subsumed in the current packet, possibly starting - // and ending at the same address - val_offset = 0; - func_offset = val_start - func_start; - overlap_size = size; - } else if (val_start < func_start && val_end > func_end) { - // the current packet is completely subsumed in the - // one we are checking against - val_offset = func_start - val_start; - func_offset = 0; - overlap_size = func_end - func_start; - } else { - panic("Missed a case for checkFunctional with " - " %s 0x%x size %d, against 0x%x size %d\n", - cmdString(), getAddr(), getSize(), addr, size); - } + std::memcpy(getPtr() + func_offset, + _data + val_offset, + overlap_size); - // copy partial data into the packet's data array - uint8_t *dest = getPtr() + func_offset; - uint8_t *src = _data + val_offset; - memcpy(dest, src, overlap_size); + // initialise the tracking of valid bytes if we have not + // used it already + if (bytesValid.empty()) + bytesValid.resize(getSize(), false); - // initialise the tracking of valid bytes if we have not - // used it already - if (bytesValid.empty()) - bytesValid.resize(getSize(), false); + // track if we are done filling the functional access + bool all_bytes_valid = true; - // track if we are done filling the functional access - bool all_bytes_valid = true; + int i = 0; - int i = 0; + // check up to func_offset + for (; all_bytes_valid && i < func_offset; ++i) + all_bytes_valid &= bytesValid[i]; - // check up to func_offset - for (; all_bytes_valid && i < func_offset; ++i) - all_bytes_valid &= bytesValid[i]; + // update the valid bytes + for (i = func_offset; i < func_offset + overlap_size; ++i) + bytesValid[i] = true; - // update the valid bytes - for (i = func_offset; i < func_offset + overlap_size; ++i) - bytesValid[i] = true; + // check the bit after the update we just made + for (; all_bytes_valid && i < getSize(); ++i) + all_bytes_valid &= bytesValid[i]; - // check the bit after the update we just made - for (; all_bytes_valid && i < getSize(); ++i) - all_bytes_valid &= bytesValid[i]; - - return all_bytes_valid; - } + return all_bytes_valid; } else if (isWrite()) { - if (offset >= 0) { - memcpy(_data + offset, getConstPtr(), - (min(func_end, val_end) - func_start) + 1); - } else { - // val_start > func_start - memcpy(_data, getConstPtr() - offset, - (min(func_end, val_end) - val_start) + 1); - } + std::memcpy(_data + val_offset, + getConstPtr() + func_offset, + overlap_size); } else { panic("Don't know how to handle command %s\n", cmdString()); } @@ -325,6 +305,16 @@ Packet::checkFunctional(Printable *obj, Addr addr, bool is_secure, int size, return false; } +void +Packet::copyResponderFlags(const PacketPtr pkt) +{ + assert(isRequest()); + // If we have already found a responder, no other cache should + // commit to responding + assert(!pkt->cacheResponding() || !cacheResponding()); + flags.set(pkt->flags & RESPONDER_FLAGS); +} + void Packet::pushSenderState(Packet::SenderState *sender_state) { @@ -343,26 +333,94 @@ Packet::popSenderState() return sender_state; } +uint64_t +Packet::getUintX(ByteOrder endian) const +{ + switch(getSize()) { + case 1: + return (uint64_t)get(endian); + case 2: + return (uint64_t)get(endian); + case 4: + return (uint64_t)get(endian); + case 8: + return (uint64_t)get(endian); + default: + panic("%i isn't a supported word size.\n", getSize()); + } +} + +void +Packet::setUintX(uint64_t w, ByteOrder endian) +{ + switch(getSize()) { + case 1: + set((uint8_t)w, endian); + break; + case 2: + set((uint16_t)w, endian); + break; + case 4: + set((uint32_t)w, endian); + break; + case 8: + set((uint64_t)w, endian); + break; + default: + panic("%i isn't a supported word size.\n", getSize()); + } + +} + void -Packet::print(ostream &o, const int verbosity, const string &prefix) const +Packet::print(std::ostream &o, const int verbosity, + const std::string &prefix) const { - ccprintf(o, "%s%s [%x:%x]%s%s%s%s", prefix, cmdString(), + ccprintf(o, "%s%s [%x:%x]%s%s%s%s%s%s", prefix, cmdString(), getAddr(), getAddr() + getSize() - 1, req->isSecure() ? " (s)" : "", req->isInstFetch() ? " IF" : "", req->isUncacheable() ? " UC" : "", - isExpressSnoop() ? " ES" : ""); + isExpressSnoop() ? " ES" : "", + req->isToPOC() ? " PoC" : "", + req->isToPOU() ? " PoU" : ""); } std::string Packet::print() const { - ostringstream str; + std::ostringstream str; print(str); return str.str(); } -Packet::PrintReqState::PrintReqState(ostream &_os, int _verbosity) - : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity) +bool +Packet::matchBlockAddr(const Addr addr, const bool is_secure, + const int blk_size) const +{ + return (getBlockAddr(blk_size) == addr) && (isSecure() == is_secure); +} + +bool +Packet::matchBlockAddr(const PacketPtr pkt, const int blk_size) const +{ + return matchBlockAddr(pkt->getBlockAddr(blk_size), pkt->isSecure(), + blk_size); +} + +bool +Packet::matchAddr(const Addr addr, const bool is_secure) const +{ + return (getAddr() == addr) && (isSecure() == is_secure); +} + +bool +Packet::matchAddr(const PacketPtr pkt) const +{ + return matchAddr(pkt->getAddr(), pkt->isSecure()); +} + +Packet::PrintReqState::PrintReqState(std::ostream &_os, int _verbosity) + : curPrefixPtr(new std::string("")), os(_os), verbosity(_verbosity) { labelStack.push_back(LabelStackEntry("", curPrefixPtr)); } @@ -375,16 +433,18 @@ Packet::PrintReqState::~PrintReqState() } Packet::PrintReqState:: -LabelStackEntry::LabelStackEntry(const string &_label, string *_prefix) +LabelStackEntry::LabelStackEntry(const std::string &_label, + std::string *_prefix) : label(_label), prefix(_prefix), labelPrinted(false) { } void -Packet::PrintReqState::pushLabel(const string &lbl, const string &prefix) +Packet::PrintReqState::pushLabel(const std::string &lbl, + const std::string &prefix) { labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr)); - curPrefixPtr = new string(*curPrefixPtr); + curPrefixPtr = new std::string(*curPrefixPtr); *curPrefixPtr += prefix; }