X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Fpacket.cc;h=17e58859a1bfc72a08d7cae7d20709bd64e85b4d;hb=3535d746ab2adaef4c13fbf869ccc3a2e98279cd;hp=8de02f533735d7176bf13dba905b3d1bb4ca027f;hpb=d10a843723009ddee79cdbf94a46704df1e5cee6;p=gem5.git diff --git a/src/mem/packet.cc b/src/mem/packet.cc index 8de02f533..17e58859a 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -37,10 +37,13 @@ #include #include +#include "base/cprintf.hh" #include "base/misc.hh" #include "base/trace.hh" #include "mem/packet.hh" +using namespace std; + // 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)) @@ -58,6 +61,9 @@ MemCmd::commandInfo[] = { 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" }, @@ -83,26 +89,24 @@ MemCmd::commandInfo[] = IsRequest, HasData, NeedsResponse), WriteInvalidateResp, "WriteInvalidateReq" }, /* WriteInvalidateResp */ - { SET4(IsWrite, NeedsExclusive, IsInvalidate, IsResponse), + { SET3(IsWrite, NeedsExclusive, IsResponse), InvalidCmd, "WriteInvalidateResp" }, /* UpgradeReq */ { SET4(IsInvalidate, NeedsExclusive, IsRequest, NeedsResponse), UpgradeResp, "UpgradeReq" }, /* UpgradeResp */ - { SET3(IsInvalidate, NeedsExclusive, IsResponse), + { SET2(NeedsExclusive, IsResponse), InvalidCmd, "UpgradeResp" }, /* ReadExReq */ { SET5(IsRead, NeedsExclusive, IsInvalidate, IsRequest, NeedsResponse), ReadExResp, "ReadExReq" }, /* ReadExResp */ - { SET5(IsRead, NeedsExclusive, IsInvalidate, IsResponse, HasData), + { SET4(IsRead, NeedsExclusive, IsResponse, HasData), InvalidCmd, "ReadExResp" }, - /* LoadLockedReq */ + /* 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" }, - /* LoadLockedResp */ - { SET4(IsRead, IsLocked, IsResponse, HasData), - InvalidCmd, "LoadLockedResp" }, /* StoreCondReq */ { SET6(IsWrite, NeedsExclusive, IsLocked, IsRequest, NeedsResponse, HasData), @@ -116,57 +120,23 @@ MemCmd::commandInfo[] = /* 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(IsRequest, IsError), InvalidCmd, "NetworkNackError" }, + { SET2(IsResponse, IsError), InvalidCmd, "NetworkNackError" }, /* InvalidDestError -- packet dest field invalid */ - { SET2(IsRequest, IsError), InvalidCmd, "InvalidDestError" }, + { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" }, /* BadAddressError -- memory address invalid */ - { SET2(IsRequest, IsError), InvalidCmd, "BadAddressError" } + { SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" }, + /* PrintReq */ + { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" } }; - -/** delete the data pointed to in the data pointer. Ok to call to matter how - * data was allocted. */ -void -Packet::deleteData() -{ - assert(staticData || dynamicData); - if (staticData) - return; - - if (arrayData) - delete [] data; - else - delete data; -} - -/** If there isn't data in the packet, allocate some. */ -void -Packet::allocate() -{ - if (data) - return; - assert(!staticData); - dynamicData = true; - arrayData = true; - data = new uint8_t[getSize()]; -} - -/** Do the packet modify the same addresses. */ -bool -Packet::intersect(PacketPtr p) -{ - Addr s1 = getAddr(); - Addr e1 = getAddr() + getSize() - 1; - Addr s2 = p->getAddr(); - Addr e2 = p->getAddr() + p->getSize() - 1; - - return !(s1 > e2 || e1 < s2); -} - - bool -Packet::checkFunctional(Addr addr, int size, uint8_t *data) +Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data) { Addr func_start = getAddr(); Addr func_end = getAddr() + getSize() - 1; @@ -178,6 +148,17 @@ Packet::checkFunctional(Addr addr, int size, uint8_t *data) 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; @@ -185,7 +166,7 @@ Packet::checkFunctional(Addr addr, int size, uint8_t *data) if (isRead()) { if (func_start >= val_start && func_end <= val_end) { allocate(); - std::memcpy(getPtr(), data + offset, getSize()); + memcpy(getPtr(), data + offset, getSize()); makeResponse(); return true; } else { @@ -200,46 +181,84 @@ Packet::checkFunctional(Addr addr, int size, uint8_t *data) } } else if (isWrite()) { if (offset >= 0) { - std::memcpy(data + offset, getPtr(), - (std::min(func_end, val_end) - func_start) + 1); - } else { // val_start > func_start - std::memcpy(data, getPtr() - offset, - (std::min(func_end, val_end) - val_start) + 1); + 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); } - // we always want to keep going with a write - return false; - } else + } else { panic("Don't know how to handle command %s\n", cmdString()); + } + + // keep going with request by default + return false; } +void +Packet::print(ostream &o, const int verbosity, const string &prefix) const +{ + ccprintf(o, "%s[%x:%x] %s\n", prefix, + getAddr(), getAddr() + getSize() - 1, cmdString()); +} + +Packet::PrintReqState::PrintReqState(ostream &_os, int _verbosity) + : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity) +{ + labelStack.push_back(LabelStackEntry("", curPrefixPtr)); +} + +Packet::PrintReqState::~PrintReqState() +{ + labelStack.pop_back(); + assert(labelStack.empty()); + delete curPrefixPtr; +} + +Packet::PrintReqState:: +LabelStackEntry::LabelStackEntry(const string &_label, string *_prefix) + : label(_label), prefix(_prefix), labelPrinted(false) +{ +} + +void +Packet::PrintReqState::pushLabel(const string &lbl, const string &prefix) +{ + labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr)); + curPrefixPtr = new string(*curPrefixPtr); + *curPrefixPtr += prefix; +} -std::ostream & -operator<<(std::ostream &o, const Packet &p) +void +Packet::PrintReqState::popLabel() { + delete curPrefixPtr; + curPrefixPtr = labelStack.back().prefix; + labelStack.pop_back(); + assert(!labelStack.empty()); +} - 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.isRead()) - o << "Read "; - if (p.isWrite()) - o << "Write "; - if (p.isInvalidate()) - o << "Invalidate "; - if (p.isRequest()) - o << "Request "; - if (p.isResponse()) - o << "Response "; - if (p.hasData()) - o << "w/Data "; - - o << std::endl; - return o; +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++; + } + } } + +void +Packet::PrintReqState::printObj(Printable *obj) +{ + printLabels(); + obj->print(os, verbosity, curPrefix()); +}