*/
#include <iostream>
-
+#include <cstring>
#include "base/misc.hh"
#include "base/trace.hh"
#include "mem/packet.hh"
-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("<other>");
-
-const std::string &
-Packet::cmdString() const
-{
- 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;
- }
-}
+// 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 std::string &
-Packet::cmdIdxToString(Packet::Command idx)
+const MemCmd::CommandInfo
+MemCmd::commandInfo[] =
{
- 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;
- }
-}
+ /* InvalidCmd */
+ { 0, InvalidCmd, "InvalidCmd" },
+ /* ReadReq */
+ { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" },
+ /* ReadResp */
+ { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" },
+ /* 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 */
+ { SET4(IsWrite, NeedsExclusive, IsInvalidate, IsResponse),
+ InvalidCmd, "WriteInvalidateResp" },
+ /* UpgradeReq */
+ { SET4(IsInvalidate, NeedsExclusive, IsRequest, NeedsResponse),
+ UpgradeResp, "UpgradeReq" },
+ /* UpgradeResp */
+ { SET3(IsInvalidate, NeedsExclusive, IsResponse),
+ InvalidCmd, "UpgradeResp" },
+ /* ReadExReq */
+ { SET5(IsRead, NeedsExclusive, IsInvalidate, IsRequest, NeedsResponse),
+ ReadExResp, "ReadExReq" },
+ /* ReadExResp */
+ { SET5(IsRead, NeedsExclusive, IsInvalidate, IsResponse, HasData),
+ InvalidCmd, "ReadExResp" },
+ /* LoadLockedReq */
+ { SET4(IsRead, IsLocked, IsRequest, NeedsResponse),
+ LoadLockedResp, "LoadLockedReq" },
+ /* LoadLockedResp */
+ { SET4(IsRead, IsLocked, IsResponse, HasData),
+ InvalidCmd, "LoadLockedResp" },
+ /* 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" },
+ /* NetworkNackError -- nacked at network layer (not by protocol) */
+ { SET2(IsRequest, IsError), InvalidCmd, "NetworkNackError" },
+ /* InvalidDestError -- packet dest field invalid */
+ { SET2(IsRequest, IsError), InvalidCmd, "InvalidDestError" },
+ /* BadAddressError -- memory address invalid */
+ { SET2(IsRequest, IsError), InvalidCmd, "BadAddressError" }
+};
+
/** delete the data pointed to in the data pointer. Ok to call to matter how
* data was allocted. */
return !(s1 > e2 || e1 < s2);
}
+
bool
-fixPacket(PacketPtr func, PacketPtr timing)
+Packet::checkFunctional(Addr addr, int size, uint8_t *data)
{
- 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));
-
- if (DTRACE(FunctionalAccess)) {
- DebugOut() << func;
- DebugOut() << timing;
+ 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;
}
- // 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<uint8_t>(), timing->getPtr<uint8_t>() +
- funcStart - timingStart, func->getSize());
- func->result = Packet::Success;
- 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());
+ makeResponse();
+ return true;
} 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?");
+ // 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 (func->isWrite()) {
- if (funcStart >= timingStart) {
- memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart),
- func->getPtr<uint8_t>(),
- std::min(funcEnd, timingEnd) - funcStart);
- } else { // timingStart > funcStart
- memcpy(timing->getPtr<uint8_t>(),
- func->getPtr<uint8_t>() + (timingStart - funcStart),
- std::min(funcEnd, timingEnd) - timingStart);
+ } 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);
}
// we always want to keep going with a write
- return true;
+ return false;
} else
- panic("Don't know how to handle command type %#x\n",
- func->cmdToIndex());
-
+ panic("Don't know how to handle command %s\n", cmdString());
}
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 ";
+ o << "Write ";
if (p.isInvalidate())
- o << "Read ";
+ o << "Invalidate ";
if (p.isRequest())
o << "Request ";
if (p.isResponse())