panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n",
(uint32_t)asi, va);
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return tc->getCpuPtr()->cycles(1);
}
panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n",
(uint32_t)pkt->req->getAsi(), pkt->getAddr(), data);
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return tc->getCpuPtr()->cycles(1);
}
// Now do the timing access to see whether or not the instruction
// exists within the cache.
if (!icachePort->sendTiming(data_pkt)) {
- if (data_pkt->result == Packet::BadAddress) {
- fault = TheISA::genMachineCheckFault();
- delete mem_req;
- memReq[tid] = NULL;
- warn("Bad address!\n");
- }
assert(retryPkt == NULL);
assert(retryTid == -1);
DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
data_pkt->senderState = state;
if (!dcachePort->sendTiming(data_pkt)) {
- Packet::Result result = data_pkt->result;
-
// Delete state and data packet because a load retry
// initiates a pipeline restart; it does not retry.
delete state;
req = NULL;
- if (result == Packet::BadAddress) {
- return TheISA::genMachineCheckFault();
- }
-
// If the access didn't succeed, tell the LSQ by setting
// the retry thread id.
lsq->setRetryTid(lsqID);
}
if (!dcachePort->sendTiming(data_pkt)) {
- if (data_pkt->result == Packet::BadAddress) {
- panic("LSQ sent out a bad address for a completed store!");
- }
// Need to handle becoming blocked on a store.
DPRINTF(IEW, "D-Cache became blocked when writing [sn:%lli], will"
"retry later\n",
#endif
}
- if (pkt->result != Packet::Success) {
- DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n",
- storeWBIdx);
-
- DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
- storeQueue[storeWBIdx].inst->seqNum);
-
- //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
-
- //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size());
-
- // @todo: Increment stat here.
- } else {
- DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n",
- storeWBIdx);
-
- DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
- storeQueue[storeWBIdx].inst->seqNum);
- }
-
incrStIdx(storeWBIdx);
}
assert(retryPkt != NULL);
if (dcachePort->sendTiming(retryPkt)) {
- if (retryPkt->result == Packet::BadAddress) {
- panic("LSQ sent out a bad address for a completed store!");
- }
storePostSend(retryPkt);
retryPkt = NULL;
isStoreBlocked = false;
cpu->lockFlag = true;
}
- if (data_pkt->result != Packet::Success) {
- DPRINTF(OzoneLSQ, "OzoneLSQ: D-cache miss!\n");
- DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
- inst->seqNum);
- } else {
- DPRINTF(OzoneLSQ, "OzoneLSQ: D-cache hit!\n");
- DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
- inst->seqNum);
- }
-
return NoFault;
}
}
#endif
}
-
- if (pkt->result != Packet::Success) {
- DPRINTF(OzoneLSQ,"D-Cache Write Miss!\n");
-
- DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
- inst->seqNum);
-
- //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
-
- //DPRINTF(OzoneLWLSQ, "Added MSHR. count = %i\n",mshrSeqNums.size());
-
- // @todo: Increment stat here.
- } else {
- DPRINTF(OzoneLSQ,"D-Cache: Write Hit!\n");
-
- DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
- inst->seqNum);
- }
}
template <class Impl>
icachePort.snoopRangeSent = false;
dcachePort.snoopRangeSent = false;
- ifetch_req = new Request();
- ifetch_req->setThreadContext(p->cpu_id, 0); // Add thread ID if we add MT
- ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast);
- ifetch_pkt->dataStatic(&inst);
-
- data_read_req = new Request();
- data_read_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
- data_read_pkt = new Packet(data_read_req, MemCmd::ReadReq,
- Packet::Broadcast);
- data_read_pkt->dataStatic(&dataReg);
-
- data_write_req = new Request();
- data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
- data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq,
- Packet::Broadcast);
- data_swap_pkt = new Packet(data_write_req, MemCmd::SwapReq,
- Packet::Broadcast);
+ ifetch_req.setThreadContext(p->cpu_id, 0); // Add thread ID if we add MT
+ data_read_req.setThreadContext(p->cpu_id, 0); // Add thread ID here too
+ data_write_req.setThreadContext(p->cpu_id, 0); // Add thread ID here too
}
AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
{
// use the CPU's statically allocated read request and packet objects
- Request *req = data_read_req;
- PacketPtr pkt = data_read_pkt;
-
+ Request *req = &data_read_req;
req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
if (traceData) {
// Now do the access.
if (fault == NoFault) {
- pkt->reinitFromRequest();
+ Packet pkt = Packet(req, MemCmd::ReadReq, Packet::Broadcast);
+ pkt.dataStatic(&data);
if (req->isMmapedIpr())
- dcache_latency = TheISA::handleIprRead(thread->getTC(),pkt);
+ dcache_latency = TheISA::handleIprRead(thread->getTC(), &pkt);
else
- dcache_latency = dcachePort.sendAtomic(pkt);
+ dcache_latency = dcachePort.sendAtomic(&pkt);
dcache_access = true;
-#if !defined(NDEBUG)
- if (pkt->result != Packet::Success)
- panic("Unable to find responder for address pa = %#X va = %#X\n",
- pkt->req->getPaddr(), pkt->req->getVaddr());
-#endif
- data = pkt->get<T>();
+ assert(!pkt.isError());
if (req->isLocked()) {
TheISA::handleLockedRead(thread, req);
AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
{
// use the CPU's statically allocated write request and packet objects
- Request *req = data_write_req;
- PacketPtr pkt;
-
+ Request *req = &data_write_req;
req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
- if (req->isSwap())
- pkt = data_swap_pkt;
- else
- pkt = data_write_pkt;
-
if (traceData) {
traceData->setAddr(addr);
}
// Now do the access.
if (fault == NoFault) {
+ Packet pkt =
+ Packet(req, req->isSwap() ? MemCmd::SwapReq : MemCmd::WriteReq,
+ Packet::Broadcast);
+ pkt.dataStatic(&data);
+
bool do_access = true; // flag to suppress cache access
if (req->isLocked()) {
if (do_access) {
- pkt->reinitFromRequest();
- pkt->dataStatic(&data);
-
if (req->isMmapedIpr()) {
- dcache_latency = TheISA::handleIprWrite(thread->getTC(), pkt);
+ dcache_latency = TheISA::handleIprWrite(thread->getTC(), &pkt);
} else {
data = htog(data);
- dcache_latency = dcachePort.sendAtomic(pkt);
+ dcache_latency = dcachePort.sendAtomic(&pkt);
}
dcache_access = true;
-
-#if !defined(NDEBUG)
- if (pkt->result != Packet::Success)
- panic("Unable to find responder for address pa = %#X va = %#X\n",
- pkt->req->getPaddr(), pkt->req->getVaddr());
-#endif
+ assert(!pkt.isError());
}
if (req->isSwap()) {
assert(res);
- *res = pkt->get<T>();
+ *res = pkt.get<T>();
} else if (res) {
*res = req->getExtraData();
}
if (!curStaticInst || !curStaticInst->isDelayedCommit())
checkForInterrupts();
- Fault fault = setupFetchRequest(ifetch_req);
+ Fault fault = setupFetchRequest(&ifetch_req);
if (fault == NoFault) {
Tick icache_latency = 0;
//if(predecoder.needMoreBytes())
//{
icache_access = true;
- ifetch_pkt->reinitFromRequest();
+ Packet ifetch_pkt = Packet(&ifetch_req, MemCmd::ReadReq,
+ Packet::Broadcast);
+ ifetch_pkt.dataStatic(&inst);
- icache_latency = icachePort.sendAtomic(ifetch_pkt);
+ icache_latency = icachePort.sendAtomic(&ifetch_pkt);
// ifetch_req is initialized to read the instruction directly
// into the CPU object's inst field.
//}
};
DcachePort dcachePort;
- Request *ifetch_req;
- PacketPtr ifetch_pkt;
- Request *data_read_req;
- PacketPtr data_read_pkt;
- Request *data_write_req;
- PacketPtr data_write_pkt;
- PacketPtr data_swap_pkt;
+ Request ifetch_req;
+ Request data_read_req;
+ Request data_write_req;
bool dcache_access;
Tick dcache_latency;
// The predecoder
TheISA::Predecoder predecoder;
- // Static data storage
- TheISA::LargestRead dataReg;
-
StaticInstPtr curStaticInst;
StaticInstPtr curMacroStaticInst;
{
// received a response from the icache: execute the received
// instruction
- assert(pkt->result == Packet::Success);
+ assert(!pkt->isError());
assert(_status == IcacheWaitResponse);
_status = Running;
return true;
}
- else if (pkt->result == Packet::Nacked) {
+ else if (pkt->wasNacked()) {
assert(cpu->_status == IcacheWaitResponse);
pkt->reinitNacked();
if (!sendTiming(pkt)) {
{
// received a response from the dcache: complete the load or store
// instruction
- assert(pkt->result == Packet::Success);
+ assert(!pkt->isError());
assert(_status == DcacheWaitResponse);
_status = Running;
return true;
}
- else if (pkt->result == Packet::Nacked) {
+ else if (pkt->wasNacked()) {
assert(cpu->_status == DcacheWaitResponse);
pkt->reinitNacked();
if (!sendTiming(pkt)) {
* machine dependent address swizzle is required?
*/
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr daddr = pkt->getAddr() - pioAddr;
/* Old console code read in everyting as a 32bit int
* we now break that for better error checking.
*/
- pkt->result = Packet::BadAddress;
+ pkt->setBadAddress();
}
DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
pkt->get<uint32_t>());
pkt->get<uint64_t>());
break;
default:
- pkt->result = Packet::BadAddress;
+ pkt->setBadAddress();
}
- if (pkt->result == Packet::Unknown)
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
Tick
AlphaConsole::write(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr daddr = pkt->getAddr() - pioAddr;
panic("Unknown 64bit access, %#x\n", daddr);
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
{
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr regnum = (pkt->getAddr() - pioAddr) >> 6;
DPRINTF(Tsunami, "Tsunami CChip: read regnum=%#x size=%d data=%lld\n",
regnum, pkt->getSize(), pkt->get<uint64_t>());
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
panic("default in cchip read reached, accessing 0x%x\n");
} // swtich(regnum)
} // not BIG_TSUNAMI write
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
Tick
TsunamiIO::read(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr daddr = pkt->getAddr() - pioAddr;
} else {
panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize());
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
Tick
TsunamiIO::write(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr daddr = pkt->getAddr() - pioAddr;
panic("I/O Write - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>());
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
Tick
TsunamiPChip::read(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
pkt->allocate();
default:
panic("Default in PChip Read reached reading 0x%x\n", daddr);
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
Tick
TsunamiPChip::write(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr daddr = (pkt->getAddr() - pioAddr) >> 6;
} // uint64_t
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
pkt->set<uint32_t>(0);
};
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
panic("Write request to unknown register number: %#x\n", daddr);
};
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
default:
panic("invalid access size(?) for PCI configspace!\n");
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return configDelay;
}
bm_enabled = false;
break;
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return configDelay;
}
parseAddr(pkt->getAddr(), offset, channel, reg_type);
if (!io_enabled) {
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
offset, pkt->getSize(), pkt->get<uint32_t>());
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
parseAddr(pkt->getAddr(), offset, channel, reg_type);
if (!io_enabled) {
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
DPRINTF(IdeCtrl, "io not enabled\n");
return pioDelay;
}
switch (reg_type) {
case BMI_BLOCK:
if (!bm_enabled) {
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
offset, pkt->getSize(), pkt->get<uint32_t>());
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
bool
DmaPort::recvTiming(PacketPtr pkt)
{
-
-
- if (pkt->result == Packet::Nacked) {
+ if (pkt->wasNacked()) {
DPRINTF(DMA, "Received nacked Pkt %#x with State: %#x Addr: %#x\n",
pkt, pkt->senderState, pkt->getAddr());
Tick
IsaFake::read(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
if (params()->warnAccess != "")
warn("Device %s accessed by read to address %#x size=%d\n",
if (params()->retBadAddr) {
DPRINTF(Tsunami, "read to bad address va=%#x size=%d\n",
pkt->getAddr(), pkt->getSize());
- pkt->result = Packet::BadAddress;
+ pkt->setBadAddress();
} else {
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
DPRINTF(Tsunami, "read va=%#x size=%d\n",
default:
panic("invalid access size!\n");
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
}
return pioDelay;
}
if (params()->retBadAddr) {
DPRINTF(Tsunami, "write to bad address va=%#x size=%d \n",
pkt->getAddr(), pkt->getSize());
- pkt->result = Packet::BadAddress;
+ pkt->setBadAddress();
} else {
DPRINTF(Tsunami, "write - va=%#x size=%d \n",
pkt->getAddr(), pkt->getSize());
panic("invalid access size!\n");
}
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
}
return pioDelay;
}
ioEnable = false;
break;
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return configDelay;
}
// doesn't actually DEPEND upon their values
// MIB are just hardware stats keepers
pkt->set<uint32_t>(0);
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
} else if (daddr > 0x3FC)
panic("Something is messed up!\n");
DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
daddr, reg, reg);
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
} else {
panic("Invalid Request Size");
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
Tick
PciConfigAll::read(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
pkt->allocate();
default:
panic("invalid access size(?) for PCI configspace!\n");
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return params()->pio_delay;
}
Tick
PciConfigAll::write(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
panic("Attempting to write to config space on non-existant device\n");
M5_DUMMY_RETURN
}
Tick
PciDev::PciConfigPort::recvAtomic(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= configAddr &&
pkt->getAddr() < configAddr + PCI_CONFIG_SIZE);
return pkt->isRead() ? device->readConfig(pkt) : device->writeConfig(pkt);
default:
panic("invalid access size(?) for PCI configspace!\n");
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return configDelay;
}
default:
panic("invalid access size(?) for PCI configspace!\n");
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return configDelay;
}
Tick
DumbTOD::read(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
assert(pkt->getSize() == 8);
pkt->set(todTime);
todTime += 1000;
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
Tick
Iob::read(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
readIob(pkt);
else
panic("Invalid address reached Iob\n");
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
panic("Invalid address reached Iob\n");
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
uint32_t d32;
uint64_t d64;
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
accessAddr = pkt->getAddr() - pioAddr;
panic("Invalid access size\n");
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
uint32_t d32;
uint64_t d64;
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
accessAddr = pkt->getAddr() - pioAddr;
panic("Invalid access size\n");
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
Tick
Uart8250::read(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
assert(pkt->getSize() == 1);
/* uint32_t d32 = *data;
DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32);
*/
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
Uart8250::write(PacketPtr pkt)
{
- assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
assert(pkt->getSize() == 1);
panic("Tried to access a UART port that doesn't exist\n");
break;
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
return pioDelay;
}
otherPort->sendQueue.size(), otherPort->queuedRequests,
otherPort->outstandingResponses);
- if (pkt->isRequest() && otherPort->reqQueueFull() && pkt->result !=
- Packet::Nacked) {
+ if (pkt->isRequest() && otherPort->reqQueueFull() && !pkt->wasNacked()) {
DPRINTF(BusBridge, "Remote queue full, nacking\n");
nackRequest(pkt);
return true;
}
- if (pkt->needsResponse() && pkt->result != Packet::Nacked)
+ if (pkt->needsResponse() && !pkt->wasNacked())
if (respQueueFull()) {
DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n");
DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n",
Bridge::BridgePort::nackRequest(PacketPtr pkt)
{
// Nack the packet
- pkt->result = Packet::Nacked;
+ pkt->setNacked();
pkt->setDest(pkt->getSrc());
//put it on the list to send
void
Bridge::BridgePort::queueForSendTiming(PacketPtr pkt)
{
- if (pkt->isResponse() || pkt->result == Packet::Nacked) {
+ if (pkt->isResponse() || pkt->wasNacked()) {
// This is a response for a request we forwarded earlier. The
// corresponding PacketBuffer should be stored in the packet's
// senderState field.
// Check if this packet was expecting a response and it's a nacked
// packet, in which case we will never being seeing it
- if (buf->expectResponse && pkt->result == Packet::Nacked)
+ if (buf->expectResponse && pkt->wasNacked())
--outstandingResponses;
}
- if (pkt->isRequest() && pkt->result != Packet::Nacked) {
+ if (pkt->isRequest() && !pkt->wasNacked()) {
++queuedRequests;
}
// Ugly! @todo When multilevel coherence works this will be removed
if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite &&
- pkt->result != Packet::Nacked) {
+ !pkt->wasNacked()) {
PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq,
Packet::Broadcast);
funcPkt->dataStatic(pkt->getPtr<uint8_t>());
buf->origSrc, pkt->getDest(), pkt->getAddr());
bool wasReq = pkt->isRequest();
- bool wasNacked = pkt->result == Packet::Nacked;
+ bool wasNacked = pkt->wasNacked();
if (sendTiming(pkt)) {
// send successful
expectResponse(_pkt->needsResponse() && !nack)
{
- if (!pkt->isResponse() && !nack && pkt->result != Packet::Nacked)
+ if (!pkt->isResponse() && !nack && !pkt->wasNacked())
pkt->senderState = this;
}
Bus::recvTiming(PacketPtr pkt)
{
Port *port;
- DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s result %d\n",
- pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString(),
- pkt->result);
+ DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
BusPort *pktPort;
if (pkt->getSrc() == defaultId)
// id after each
int src_id = pkt->getSrc();
+ assert(pkt->isRequest()); // hasn't already been satisfied
+
for (SnoopIter s_iter = snoopPorts.begin();
s_iter != snoopPorts.end();
s_iter++) {
if (p != responder && p->getId() != src_id) {
p->sendFunctional(pkt);
}
- if (pkt->result == Packet::Success) {
+ if (pkt->isResponse()) {
break;
}
pkt->setSrc(src_id);
DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
assert(pkt->getDest() == Packet::Broadcast);
+ assert(pkt->isRequest());
// Variables for recording original command and snoop response (if
// any)... if a snooper respondes, we will need to restore
// original command so that additional snoops can take place
// properly
MemCmd orig_cmd = pkt->cmd;
- Packet::Result response_result = Packet::Unknown;
MemCmd response_cmd = MemCmd::InvalidCmd;
+ int orig_src = pkt->getSrc();
Port *target_port = findPort(pkt->getAddr(), pkt->getSrc());
assert(p != target_port);
if (p->getId() != pkt->getSrc()) {
p->sendAtomic(pkt);
- if (pkt->result != Packet::Unknown) {
+ if (pkt->isResponse()) {
// response from snoop agent
assert(pkt->cmd != orig_cmd);
assert(pkt->memInhibitAsserted());
- assert(pkt->isResponse());
// should only happen once
- assert(response_result == Packet::Unknown);
assert(response_cmd == MemCmd::InvalidCmd);
// save response state
- response_result = pkt->result;
response_cmd = pkt->cmd;
// restore original packet state for remaining snoopers
pkt->cmd = orig_cmd;
- pkt->result = Packet::Unknown;
+ pkt->setSrc(orig_src);
+ pkt->setDest(Packet::Broadcast);
}
}
}
Tick response_time = target_port->sendAtomic(pkt);
// if we got a response from a snooper, restore it here
- if (response_result != Packet::Unknown) {
- assert(response_cmd != MemCmd::InvalidCmd);
+ if (response_cmd != MemCmd::InvalidCmd) {
// no one else should have responded
- assert(pkt->result == Packet::Unknown);
+ assert(!pkt->isResponse());
assert(pkt->cmd == orig_cmd);
pkt->cmd = response_cmd;
- pkt->result = response_result;
}
// why do we have this packet field and the return value both???
Port* port = findPort(pkt->getAddr(), pkt->getSrc());
functionalSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
- // If the snooping found what we were looking for, we're done.
- if (pkt->result != Packet::Success && port) {
+ // If the snooping hasn't found what we were looking for, keep going.
+ if (!pkt->isResponse() && port) {
port->sendFunctional(pkt);
}
}
BaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt)
{
checkFunctional(pkt);
- if (pkt->result != Packet::Success)
+ if (!pkt->isResponse())
sendFunctional(pkt);
}
if (pkt->needsResponse()) {
pkt->makeAtomicResponse();
- pkt->result = Packet::Success;
}
return lat;
MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
assert(mshr);
- if (pkt->result == Packet::Nacked) {
+ if (pkt->wasNacked()) {
//pkt->reinitFromRequest();
warn("NACKs from devices not connected to the same bus "
"not implemented\n");
return;
}
- assert(pkt->result != Packet::BadAddress);
- assert(pkt->result == Packet::Success);
+ assert(!pkt->isError());
DPRINTF(Cache, "Handling response to %x\n", pkt->getAddr());
MSHRQueue *mq = mshr->queue;
Cache<TagStore>::CpuSidePort::recvFunctional(PacketPtr pkt)
{
checkFunctional(pkt);
- if (pkt->result != Packet::Success)
+ if (!pkt->isResponse())
myCache()->functionalAccess(pkt, cache->memSidePort);
}
// this needs to be fixed so that the cache updates the mshr and sends the
// packet back out on the link, but it probably won't happen so until this
// gets fixed, just panic when it does
- if (pkt->result == Packet::Nacked)
+ if (pkt->wasNacked())
panic("Need to implement cache resending nacked packets!\n");
if (pkt->isRequest() && blocked) {
Cache<TagStore>::MemSidePort::recvFunctional(PacketPtr pkt)
{
checkFunctional(pkt);
- if (pkt->result != Packet::Success)
+ if (!pkt->isResponse())
myCache()->functionalAccess(pkt, cache->cpuSidePort);
}
SwapResp, "SwapReq" },
/* SwapResp -- for Swap ldstub type operations */
{ SET5(IsRead, IsWrite, NeedsExclusive, IsResponse, HasData),
- InvalidCmd, "SwapResp" }
+ 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" }
};
if (func_start >= val_start && func_end <= val_end) {
allocate();
std::memcpy(getPtr<uint8_t>(), data + offset, getSize());
- result = Packet::Success;
+ makeResponse();
return true;
} else {
// In this case the timing packet only partially satisfies
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())
StoreCondResp,
SwapReq,
SwapResp,
+ // Error responses
+ // @TODO these should be classified as responses rather than
+ // requests; coding them as requests initially for backwards
+ // compatibility
+ NetworkNackError, // nacked at network layer (not by protocol)
+ InvalidDestError, // packet dest field invalid
+ BadAddressError, // memory address invalid
NUM_MEM_CMDS
};
IsHWPrefetch,
IsLocked, //!< Alpha/MIPS LL or SC access
HasData, //!< There is an associated payload
+ IsError, //!< Error response
NUM_COMMAND_ATTRIBUTES
};
bool isWrite() const { return testCmdAttrib(IsWrite); }
bool isRequest() const { return testCmdAttrib(IsRequest); }
bool isResponse() const { return testCmdAttrib(IsResponse); }
- bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
+ bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
bool needsResponse() const { return testCmdAttrib(NeedsResponse); }
bool isInvalidate() const { return testCmdAttrib(IsInvalidate); }
bool hasData() const { return testCmdAttrib(HasData); }
bool isReadWrite() const { return isRead() && isWrite(); }
bool isLocked() const { return testCmdAttrib(IsLocked); }
+ bool isError() const { return testCmdAttrib(IsError); }
const Command responseCommand() const {
return commandInfo[cmd].response;
typedef MemCmd::Command Command;
+ /** The command field of the packet. */
+ MemCmd cmd;
+
+ /** A pointer to the original request. */
+ RequestPtr req;
+
private:
/** A pointer to the data being transfered. It can be differnt
* sizes at each level of the heirarchy so it belongs in the
* (unlike * addr, size, and src). */
short dest;
+ /** The original value of the command field. Only valid when the
+ * current command field is an error condition; in that case, the
+ * previous contents of the command field are copied here. This
+ * field is *not* set on non-error responses.
+ */
+ MemCmd origCmd;
+
/** Are the 'addr' and 'size' fields valid? */
bool addrSizeValid;
/** Is the 'src' field valid? */
bool srcValid;
+ bool destValid;
- enum SnoopFlag {
+ enum Flag {
+ // Snoop flags
MemInhibit,
Shared,
- NUM_SNOOP_FLAGS
+ NUM_PACKET_FLAGS
};
- /** Coherence snoopFlags for snooping */
- std::bitset<NUM_SNOOP_FLAGS> snoopFlags;
+ /** Status flags */
+ std::bitset<NUM_PACKET_FLAGS> flags;
public:
* should be routed based on its address. */
static const short Broadcast = -1;
- /** A pointer to the original request. */
- RequestPtr req;
-
- /** A virtual base opaque structure used to hold coherence-related
- * state. A specific subclass would be derived from this to
- * carry state specific to a particular coherence protocol. */
- class CoherenceState : public FastAlloc {
- public:
- virtual ~CoherenceState() {}
- };
-
- /** This packet's coherence state. Caches should use
- * dynamic_cast<> to cast to the state appropriate for the
- * system's coherence protocol. */
- CoherenceState *coherence;
-
/** A virtual base opaque structure used to hold state associated
* with the packet but specific to the sending device (e.g., an
* MSHR). A pointer to this state is returned in the packet's
* to cast to the state appropriate to the sender. */
SenderState *senderState;
- public:
-
- /** The command field of the packet. */
- MemCmd cmd;
-
/** Return the string name of the cmd field (for debugging and
* tracing). */
const std::string &cmdString() const { return cmd.toString(); }
/** Return the index of this command. */
inline int cmdToIndex() const { return cmd.toInt(); }
- public:
-
bool isRead() const { return cmd.isRead(); }
bool isWrite() const { return cmd.isWrite(); }
bool isRequest() const { return cmd.isRequest(); }
bool isResponse() const { return cmd.isResponse(); }
- bool needsExclusive() const { return cmd.needsExclusive(); }
+ bool needsExclusive() const { return cmd.needsExclusive(); }
bool needsResponse() const { return cmd.needsResponse(); }
bool isInvalidate() const { return cmd.isInvalidate(); }
bool hasData() const { return cmd.hasData(); }
bool isReadWrite() const { return cmd.isReadWrite(); }
bool isLocked() const { return cmd.isLocked(); }
-
- void assertMemInhibit() { snoopFlags[MemInhibit] = true; }
- void assertShared() { snoopFlags[Shared] = true; }
- bool memInhibitAsserted() { return snoopFlags[MemInhibit]; }
- bool sharedAsserted() { return snoopFlags[Shared]; }
+ bool isError() const { return cmd.isError(); }
+
+ // Snoop flags
+ void assertMemInhibit() { flags[MemInhibit] = true; }
+ void assertShared() { flags[Shared] = true; }
+ bool memInhibitAsserted() { return flags[MemInhibit]; }
+ bool sharedAsserted() { return flags[Shared]; }
+
+ // Network error conditions... encapsulate them as methods since
+ // their encoding keeps changing (from result field to command
+ // field, etc.)
+ void setNacked() { origCmd = cmd; cmd = MemCmd::NetworkNackError; }
+ void setBadAddress() { origCmd = cmd; cmd = MemCmd::BadAddressError; }
+ bool wasNacked() { return cmd == MemCmd::NetworkNackError; }
+ bool hadBadAddress() { return cmd == MemCmd::BadAddressError; }
bool nic_pkt() { panic("Unimplemented"); M5_DUMMY_RETURN }
- /** Possible results of a packet's request. */
- enum Result
- {
- Success,
- BadAddress,
- Nacked,
- Unknown
- };
-
- /** The result of this packet's request. */
- Result result;
-
/** Accessor function that returns the source index of the packet. */
- short getSrc() const { assert(srcValid); return src; }
+ short getSrc() const { assert(srcValid); return src; }
void setSrc(short _src) { src = _src; srcValid = true; }
/** Reset source field, e.g. to retransmit packet on different bus. */
void clearSrc() { srcValid = false; }
/** Accessor function that returns the destination index of
the packet. */
- short getDest() const { return dest; }
- void setDest(short _dest) { dest = _dest; }
+ short getDest() const { assert(destValid); return dest; }
+ void setDest(short _dest) { dest = _dest; destValid = true; }
Addr getAddr() const { assert(addrSizeValid); return addr; }
- int getSize() const { assert(addrSizeValid); return size; }
+ int getSize() const { assert(addrSizeValid); return size; }
Addr getOffset(int blkSize) const { return addr & (Addr)(blkSize - 1); }
- void addrOverride(Addr newAddr) { assert(addrSizeValid); addr = newAddr; }
- void cmdOverride(MemCmd newCmd) { cmd = newCmd; }
-
/** Constructor. Note that a Request object must be constructed
* first, but the Requests's physical address and size fields
* need not be valid. The command and destination addresses
* must be supplied. */
Packet(Request *_req, MemCmd _cmd, short _dest)
- : data(NULL), staticData(false), dynamicData(false), arrayData(false),
+ : cmd(_cmd), req(_req),
+ data(NULL), staticData(false), dynamicData(false), arrayData(false),
addr(_req->paddr), size(_req->size), dest(_dest),
- addrSizeValid(_req->validPaddr), srcValid(false),
- snoopFlags(0),
- time(curTick),
- req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
- result(Unknown)
+ addrSizeValid(_req->validPaddr), srcValid(false), destValid(true),
+ flags(0), time(curTick), senderState(NULL)
{
}
* a request that is for a whole block, not the address from the req.
* this allows for overriding the size/addr of the req.*/
Packet(Request *_req, MemCmd _cmd, short _dest, int _blkSize)
- : data(NULL), staticData(false), dynamicData(false), arrayData(false),
+ : cmd(_cmd), req(_req),
+ data(NULL), staticData(false), dynamicData(false), arrayData(false),
addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize), dest(_dest),
- addrSizeValid(_req->validPaddr), srcValid(false),
- snoopFlags(0),
- time(curTick),
- req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
- result(Unknown)
+ addrSizeValid(_req->validPaddr), srcValid(false), destValid(true),
+ flags(0), time(curTick), senderState(NULL)
{
}
* dynamic data, user must guarantee that the new packet's
* lifetime is less than that of the original packet. */
Packet(Packet *origPkt)
- : data(NULL), staticData(false), dynamicData(false), arrayData(false),
+ : cmd(origPkt->cmd), req(origPkt->req),
+ data(NULL), staticData(false), dynamicData(false), arrayData(false),
addr(origPkt->addr), size(origPkt->size),
src(origPkt->src), dest(origPkt->dest),
- addrSizeValid(origPkt->addrSizeValid), srcValid(origPkt->srcValid),
- snoopFlags(origPkt->snoopFlags),
- time(curTick),
- req(origPkt->req), coherence(origPkt->coherence),
- senderState(origPkt->senderState), cmd(origPkt->cmd),
- result(origPkt->result)
+ addrSizeValid(origPkt->addrSizeValid),
+ srcValid(origPkt->srcValid), destValid(origPkt->destValid),
+ flags(origPkt->flags),
+ time(curTick), senderState(origPkt->senderState)
{
}
* multiple transactions. */
void reinitFromRequest() {
assert(req->validPaddr);
- snoopFlags = 0;
+ flags = 0;
addr = req->paddr;
size = req->size;
time = req->time;
addrSizeValid = true;
- result = Unknown;
if (dynamicData) {
deleteData();
dynamicData = false;
* destination fields are *not* modified, as is appropriate for
* atomic accesses.
*/
- void makeAtomicResponse()
+ void makeResponse()
{
assert(needsResponse());
assert(isRequest());
- assert(result == Unknown);
cmd = cmd.responseCommand();
- result = Success;
+ dest = src;
+ destValid = srcValid;
+ srcValid = false;
}
- /**
- * Perform the additional work required for timing responses above
- * and beyond atomic responses; i.e., change the destination to
- * point back to the requester and clear the source field.
- */
- void convertAtomicToTimingResponse()
+ void makeAtomicResponse()
{
- dest = getSrc();
- srcValid = false;
+ makeResponse();
}
- /**
- * Take a request packet and modify it in place to be suitable for
- * returning as a response to a timing request.
- */
void makeTimingResponse()
{
- makeAtomicResponse();
- convertAtomicToTimingResponse();
+ makeResponse();
}
/**
void
reinitNacked()
{
- assert(needsResponse() && result == Nacked);
- dest = Broadcast;
- result = Unknown;
+ assert(wasNacked());
+ cmd = origCmd;
+ assert(needsResponse());
+ setDest(Broadcast);
}
pkt->cmdString());
}
- pkt->result = Packet::Success;
+ pkt->makeAtomicResponse();
}
Port::blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd)
{
Request req;
- Packet pkt(&req, cmd, Packet::Broadcast);
for (ChunkGenerator gen(addr, size, peerBlockSize());
!gen.done(); gen.next()) {
req.setPhys(gen.addr(), gen.size(), 0);
- pkt.reinitFromRequest();
+ Packet pkt(&req, cmd, Packet::Broadcast);
pkt.dataStatic(p);
sendFunctional(&pkt);
p += gen.size();
checkFunctional(pkt);
// Just do an atomic access and throw away the returned latency
- if (pkt->result != Packet::Success)
+ if (!pkt->isResponse())
recvAtomic(pkt);
}
// correctly with the drain code, so that would need to be fixed
// if we ever added it back.
assert(pkt->isRequest());
- assert(pkt->result == Packet::Unknown);
if (pkt->memInhibitAsserted()) {
// snooper will supply based on copy of packet
// recvAtomic() should already have turned packet into
// atomic response
assert(pkt->isResponse());
- pkt->convertAtomicToTimingResponse();
schedSendTiming(pkt, curTick + latency);
} else {
delete pkt->req;
SimpleTimingPort::sendDeferredPacket()
{
assert(deferredPacketReady());
- bool success = sendTiming(transmitList.front().pkt);
+ // take packet off list here; if recvTiming() on the other side
+ // calls sendTiming() back on us (like SimpleTimingCpu does), then
+ // we get confused by having a non-active packet on transmitList
+ DeferredPacket dp = transmitList.front();
+ transmitList.pop_front();
+ bool success = sendTiming(dp.pkt);
if (success) {
- //send successful, remove packet
- transmitList.pop_front();
- if (!transmitList.empty()) {
+ if (!transmitList.empty() && !sendEvent->scheduled()) {
Tick time = transmitList.front().tick;
sendEvent->schedule(time <= curTick ? curTick+1 : time);
}
drainEvent->process();
drainEvent = NULL;
}
+ } else {
+ // Unsuccessful, need to put back on transmitList. Callee
+ // should not have messed with it (since it didn't accept that
+ // packet), so we can just push it back on the front.
+ assert(!sendEvent->scheduled());
+ transmitList.push_front(dp);
}
waitingOnRetry = !success;