X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Fpacket.cc;h=17e58859a1bfc72a08d7cae7d20709bd64e85b4d;hb=3535d746ab2adaef4c13fbf869ccc3a2e98279cd;hp=a16e590e3482dce9e176aa91e4e77efce2bf492a;hpb=9cf063eb8e0b9d4af40f0e8fe609f9135be899f5;p=gem5.git diff --git a/src/mem/packet.cc b/src/mem/packet.cc index a16e590e3..17e58859a 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -36,202 +36,229 @@ */ #include +#include +#include "base/cprintf.hh" #include "base/misc.hh" -#include "mem/packet.hh" #include "base/trace.hh" +#include "mem/packet.hh" + +using namespace std; -static const std::string ReadReqString("ReadReq"); -static const std::string WriteReqString("WriteReq"); -static const std::string WriteReqNoAckString("WriteReqNoAck|Writeback"); -static const std::string ReadRespString("ReadResp"); -static const std::string WriteRespString("WriteResp"); -static const std::string SoftPFReqString("SoftPFReq"); -static const std::string SoftPFRespString("SoftPFResp"); -static const std::string HardPFReqString("HardPFReq"); -static const std::string HardPFRespString("HardPFResp"); -static const std::string InvalidateReqString("InvalidateReq"); -static const std::string WriteInvalidateReqString("WriteInvalidateReq"); -static const std::string WriteInvalidateRespString("WriteInvalidateResp"); -static const std::string UpgradeReqString("UpgradeReq"); -static const std::string ReadExReqString("ReadExReq"); -static const std::string ReadExRespString("ReadExResp"); -static const std::string OtherCmdString(""); - -const std::string & -Packet::cmdString() const +// The one downside to bitsets is that static initializers can get ugly. +#define SET1(a1) (1 << (a1)) +#define SET2(a1, a2) (SET1(a1) | SET1(a2)) +#define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3)) +#define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4)) +#define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5)) +#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6)) + +const MemCmd::CommandInfo +MemCmd::commandInfo[] = { - switch (cmd) { - case ReadReq: return ReadReqString; - case WriteReq: return WriteReqString; - case WriteReqNoAck: return WriteReqNoAckString; - case ReadResp: return ReadRespString; - case WriteResp: return WriteRespString; - case SoftPFReq: return SoftPFReqString; - case SoftPFResp: return SoftPFRespString; - case HardPFReq: return HardPFReqString; - case HardPFResp: return HardPFRespString; - case InvalidateReq: return InvalidateReqString; - case WriteInvalidateReq:return WriteInvalidateReqString; - case WriteInvalidateResp:return WriteInvalidateRespString; - case UpgradeReq: return UpgradeReqString; - case ReadExReq: return ReadExReqString; - case ReadExResp: return ReadExRespString; - default: return OtherCmdString; - } -} + /* InvalidCmd */ + { 0, InvalidCmd, "InvalidCmd" }, + /* ReadReq */ + { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" }, + /* ReadResp */ + { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" }, + /* ReadRespWithInvalidate */ + { SET4(IsRead, IsResponse, HasData, IsInvalidate), + InvalidCmd, "ReadRespWithInvalidate" }, + /* WriteReq */ + { SET5(IsWrite, NeedsExclusive, IsRequest, NeedsResponse, HasData), + WriteResp, "WriteReq" }, + /* WriteResp */ + { SET3(IsWrite, NeedsExclusive, IsResponse), InvalidCmd, "WriteResp" }, + /* Writeback */ + { SET4(IsWrite, NeedsExclusive, IsRequest, HasData), + InvalidCmd, "Writeback" }, + /* SoftPFReq */ + { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse), + SoftPFResp, "SoftPFReq" }, + /* HardPFReq */ + { SET4(IsRead, IsRequest, IsHWPrefetch, NeedsResponse), + HardPFResp, "HardPFReq" }, + /* SoftPFResp */ + { SET4(IsRead, IsResponse, IsSWPrefetch, HasData), + InvalidCmd, "SoftPFResp" }, + /* HardPFResp */ + { SET4(IsRead, IsResponse, IsHWPrefetch, HasData), + InvalidCmd, "HardPFResp" }, + /* WriteInvalidateReq */ + { SET6(IsWrite, NeedsExclusive, IsInvalidate, + IsRequest, HasData, NeedsResponse), + WriteInvalidateResp, "WriteInvalidateReq" }, + /* WriteInvalidateResp */ + { SET3(IsWrite, NeedsExclusive, IsResponse), + InvalidCmd, "WriteInvalidateResp" }, + /* UpgradeReq */ + { SET4(IsInvalidate, NeedsExclusive, IsRequest, NeedsResponse), + UpgradeResp, "UpgradeReq" }, + /* UpgradeResp */ + { SET2(NeedsExclusive, IsResponse), + InvalidCmd, "UpgradeResp" }, + /* ReadExReq */ + { SET5(IsRead, NeedsExclusive, IsInvalidate, IsRequest, NeedsResponse), + ReadExResp, "ReadExReq" }, + /* ReadExResp */ + { SET4(IsRead, NeedsExclusive, IsResponse, HasData), + InvalidCmd, "ReadExResp" }, + /* LoadLockedReq: note that we use plain ReadResp as response, so that + * we can also use ReadRespWithInvalidate when needed */ + { SET4(IsRead, IsLocked, IsRequest, NeedsResponse), + ReadResp, "LoadLockedReq" }, + /* StoreCondReq */ + { SET6(IsWrite, NeedsExclusive, IsLocked, + IsRequest, NeedsResponse, HasData), + StoreCondResp, "StoreCondReq" }, + /* StoreCondResp */ + { SET4(IsWrite, NeedsExclusive, IsLocked, IsResponse), + InvalidCmd, "StoreCondResp" }, + /* SwapReq -- for Swap ldstub type operations */ + { SET6(IsRead, IsWrite, NeedsExclusive, IsRequest, HasData, NeedsResponse), + SwapResp, "SwapReq" }, + /* SwapResp -- for Swap ldstub type operations */ + { SET5(IsRead, IsWrite, NeedsExclusive, IsResponse, HasData), + InvalidCmd, "SwapResp" }, + /* IntReq -- for interrupts */ + { SET4(IsWrite, IsRequest, NeedsResponse, HasData), + MessageReq, "MessageReq" }, + /* IntResp -- for interrupts */ + { SET2(IsWrite, IsResponse), MessageResp, "MessageResp" }, + /* NetworkNackError -- nacked at network layer (not by protocol) */ + { SET2(IsResponse, IsError), InvalidCmd, "NetworkNackError" }, + /* InvalidDestError -- packet dest field invalid */ + { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" }, + /* BadAddressError -- memory address invalid */ + { SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" }, + /* PrintReq */ + { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" } +}; -const std::string & -Packet::cmdIdxToString(Packet::Command idx) +bool +Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) { - switch (idx) { - case ReadReq: return ReadReqString; - case WriteReq: return WriteReqString; - case WriteReqNoAck: return WriteReqNoAckString; - case ReadResp: return ReadRespString; - case WriteResp: return WriteRespString; - case SoftPFReq: return SoftPFReqString; - case SoftPFResp: return SoftPFRespString; - case HardPFReq: return HardPFReqString; - case HardPFResp: return HardPFRespString; - case InvalidateReq: return InvalidateReqString; - case WriteInvalidateReq:return WriteInvalidateReqString; - case WriteInvalidateResp:return WriteInvalidateRespString; - case UpgradeReq: return UpgradeReqString; - case ReadExReq: return ReadExReqString; - case ReadExResp: return ReadExRespString; - default: return OtherCmdString; + Addr func_start = getAddr(); + Addr func_end = getAddr() + getSize() - 1; + Addr val_start = addr; + Addr val_end = val_start + size - 1; + + if (func_start > val_end || val_start > func_end) { + // no intersection + return false; } + + // check print first since it doesn't require data + if (isPrint()) { + dynamic_cast(senderState)->printObj(obj); + return false; + } + + // if there's no data, there's no need to look further + if (!data) { + return false; + } + + // offset of functional request into supplied value (could be + // negative if partial overlap) + int offset = func_start - val_start; + + if (isRead()) { + if (func_start >= val_start && func_end <= val_end) { + allocate(); + memcpy(getPtr(), data + offset, getSize()); + makeResponse(); + return true; + } else { + // In this case the timing packet only partially satisfies + // the request, so we would need more information to make + // this work. Like bytes valid in the packet or + // something, so the request could continue and get this + // bit of possibly newer data along with the older data + // not written to yet. + panic("Memory value only partially satisfies the functional " + "request. Now what?"); + } + } else if (isWrite()) { + if (offset >= 0) { + memcpy(data + offset, getPtr(), + (min(func_end, val_end) - func_start) + 1); + } else { + // val_start > func_start + memcpy(data, getPtr() - offset, + (min(func_end, val_end) - val_start) + 1); + } + } else { + panic("Don't know how to handle command %s\n", cmdString()); + } + + // keep going with request by default + return false; } -/** delete the data pointed to in the data pointer. Ok to call to matter how - * data was allocted. */ void -Packet::deleteData() +Packet::print(ostream &o, const int verbosity, const string &prefix) const { - assert(staticData || dynamicData); - if (staticData) - return; - - if (arrayData) - delete [] data; - else - delete data; + ccprintf(o, "%s[%x:%x] %s\n", prefix, + getAddr(), getAddr() + getSize() - 1, cmdString()); } -/** If there isn't data in the packet, allocate some. */ -void -Packet::allocate() +Packet::PrintReqState::PrintReqState(ostream &_os, int _verbosity) + : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity) { - if (data) - return; - assert(!staticData); - dynamicData = true; - arrayData = true; - data = new uint8_t[getSize()]; + labelStack.push_back(LabelStackEntry("", curPrefixPtr)); } -/** Do the packet modify the same addresses. */ -bool -Packet::intersect(Packet *p) +Packet::PrintReqState::~PrintReqState() { - Addr s1 = getAddr(); - Addr e1 = getAddr() + getSize() - 1; - Addr s2 = p->getAddr(); - Addr e2 = p->getAddr() + p->getSize() - 1; - - return !(s1 > e2 || e1 < s2); + labelStack.pop_back(); + assert(labelStack.empty()); + delete curPrefixPtr; } -bool -fixPacket(Packet *func, Packet *timing) +Packet::PrintReqState:: +LabelStackEntry::LabelStackEntry(const string &_label, string *_prefix) + : label(_label), prefix(_prefix), labelPrinted(false) { - Addr funcStart = func->getAddr(); - Addr funcEnd = func->getAddr() + func->getSize() - 1; - Addr timingStart = timing->getAddr(); - Addr timingEnd = timing->getAddr() + timing->getSize() - 1; +} - assert(!(funcStart > timingEnd || timingStart < funcEnd)); +void +Packet::PrintReqState::pushLabel(const string &lbl, const string &prefix) +{ + labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr)); + curPrefixPtr = new string(*curPrefixPtr); + *curPrefixPtr += prefix; +} - if (DTRACE(FunctionalAccess)) { - DebugOut() << func; - DebugOut() << timing; - } +void +Packet::PrintReqState::popLabel() +{ + delete curPrefixPtr; + curPrefixPtr = labelStack.back().prefix; + labelStack.pop_back(); + assert(!labelStack.empty()); +} - // this packet can't solve our problem, continue on - if (!timing->hasData()) - return true; - - if (func->isRead()) { - if (funcStart >= timingStart && funcEnd <= timingEnd) { - func->allocate(); - memcpy(func->getPtr(), timing->getPtr() + - funcStart - timingStart, func->getSize()); - func->result = Packet::Success; - return false; - } else { - // In this case the timing packet only partially satisfies the - // requset, so we would need more information to make this work. - // Like bytes valid in the packet or something, so the request could - // continue and get this bit of possibly newer data along with the - // older data not written to yet. - panic("Timing packet only partially satisfies the functional" - "request. Now what?"); - } - } else if (func->isWrite()) { - if (funcStart >= timingStart) { - memcpy(timing->getPtr() + (funcStart - timingStart), - func->getPtr(), - funcStart - std::min(funcEnd, timingEnd)); - } else { // timingStart > funcStart - memcpy(timing->getPtr(), - func->getPtr() + (timingStart - funcStart), - timingStart - std::min(funcEnd, timingEnd)); +void +Packet::PrintReqState::printLabels() +{ + if (!labelStack.back().labelPrinted) { + LabelStack::iterator i = labelStack.begin(); + LabelStack::iterator end = labelStack.end(); + while (i != end) { + if (!i->labelPrinted) { + ccprintf(os, "%s%s\n", *(i->prefix), i->label); + i->labelPrinted = true; + } + i++; } - // we always want to keep going with a write - return true; - } else - panic("Don't know how to handle command type %#x\n", - func->cmdToIndex()); - + } } -std::ostream & -operator<<(std::ostream &o, const Packet &p) +void +Packet::PrintReqState::printObj(Printable *obj) { - - o << "[0x"; - o.setf(std::ios_base::hex, std::ios_base::showbase); - o << p.getAddr(); - o.unsetf(std::ios_base::hex| std::ios_base::showbase); - o << ":"; - o.setf(std::ios_base::hex, std::ios_base::showbase); - o << p.getAddr() + p.getSize() - 1 << "] "; - o.unsetf(std::ios_base::hex| std::ios_base::showbase); - - if (p.result == Packet::Success) - o << "Successful "; - if (p.result == Packet::BadAddress) - o << "BadAddress "; - if (p.result == Packet::Nacked) - o << "Nacked "; - if (p.result == Packet::Unknown) - o << "Inflight "; - - if (p.isRead()) - o << "Read "; - if (p.isWrite()) - o << "Read "; - if (p.isInvalidate()) - o << "Read "; - if (p.isRequest()) - o << "Request "; - if (p.isResponse()) - o << "Response "; - if (p.hasData()) - o << "w/Data "; - - o << std::endl; - return o; + printLabels(); + obj->print(os, verbosity, curPrefix()); } -