#include <iostream>
#include <cstring>
+#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))
{ 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" },
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),
SwapResp, "SwapReq" },
/* SwapResp -- for Swap ldstub type operations */
{ SET5(IsRead, IsWrite, NeedsExclusive, IsResponse, HasData),
- InvalidCmd, "SwapResp" }
+ 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" }
};
-
-/** 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
-fixDelayedResponsePacket(PacketPtr func, PacketPtr timing)
-{
- bool result;
-
- if (timing->isRead() || timing->isWrite()) {
- // Ugly hack to deal with the fact that we queue the requests
- // and don't convert them to responses until we issue them on
- // the bus. I tried to avoid this by converting packets to
- // responses right away, but this breaks during snoops where a
- // responder may do the conversion before other caches have
- // done the snoop. Would work if we copied the packet instead
- // of just hanging on to a pointer.
- MemCmd oldCmd = timing->cmd;
- timing->cmd = timing->cmd.responseCommand();
- result = fixPacket(func, timing);
- timing->cmd = oldCmd;
- }
- else {
- //Don't toggle if it isn't a read/write response
- result = fixPacket(func, timing);
- }
-
- return result;
-}
-
-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;
return false;
}
+ // check print first since it doesn't require data
+ if (isPrint()) {
+ dynamic_cast<PrintReqState*>(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();
- std::memcpy(getPtr<uint8_t>(), data + offset, getSize());
- result = Packet::Success;
+ memcpy(getPtr<uint8_t>(), data + offset, getSize());
+ makeResponse();
return true;
} else {
// In this case the timing packet only partially satisfies
}
} else if (isWrite()) {
if (offset >= 0) {
- std::memcpy(data + offset, getPtr<uint8_t>(),
- (std::min(func_end, val_end) - func_start) + 1);
- } else { // val_start > func_start
- std::memcpy(data, getPtr<uint8_t>() - offset,
- (std::min(func_end, val_end) - val_start) + 1);
+ memcpy(data + offset, getPtr<uint8_t>(),
+ (min(func_end, val_end) - func_start) + 1);
+ } else {
+ // val_start > func_start
+ memcpy(data, getPtr<uint8_t>() - 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));
+}
-std::ostream &
-operator<<(std::ostream &o, const Packet &p)
+Packet::PrintReqState::~PrintReqState()
{
+ labelStack.pop_back();
+ assert(labelStack.empty());
+ delete curPrefixPtr;
+}
- 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);
+Packet::PrintReqState::
+LabelStackEntry::LabelStackEntry(const string &_label, string *_prefix)
+ : label(_label), prefix(_prefix), labelPrinted(false)
+{
+}
- 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 ";
+void
+Packet::PrintReqState::pushLabel(const string &lbl, const string &prefix)
+{
+ labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr));
+ curPrefixPtr = new string(*curPrefixPtr);
+ *curPrefixPtr += prefix;
+}
- 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 ";
+void
+Packet::PrintReqState::popLabel()
+{
+ delete curPrefixPtr;
+ curPrefixPtr = labelStack.back().prefix;
+ labelStack.pop_back();
+ assert(!labelStack.empty());
+}
- 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());
+}