Minor further cleanup & commenting of Packet class.

src/cpu/simple/atomic.cc:
    Make common ifetch setup based on Request rather than Packet.
    Packet::reset() no longer a separate function.
    sendAtomic() returns latency, not absolute tick.
src/cpu/simple/atomic.hh:
    sendAtomic returns latency, not absolute tick.
src/cpu/simple/base.cc:
src/cpu/simple/base.hh:
src/cpu/simple/timing.cc:
    Make common ifetch setup based on Request rather than Packet.
src/dev/alpha_console.cc:
src/dev/ide_ctrl.cc:
src/dev/io_device.cc:
src/dev/isa_fake.cc:
src/dev/ns_gige.cc:
src/dev/pciconfigall.cc:
src/dev/sinic.cc:
src/dev/tsunami_cchip.cc:
src/dev/tsunami_io.cc:
src/dev/tsunami_pchip.cc:
src/dev/uart8250.cc:
src/mem/physical.cc:
    Get rid of redundant Packet time field.
src/mem/packet.cc:
    Eliminate reset() method.
src/mem/packet.hh:
    Fold reset() function into reinitFromRequest()... it was
    only ever called together with that function.
    Get rid of redundant time field.
    Cleanup/add comments.
src/mem/port.hh:
    Document in comment that sendAtomic returns latency, not absolute tick.

--HG--
extra : convert_revision : 0252f1a294043ca3ed58f437232ad24fc0733e0c
This commit is contained in:
Steve Reinhardt 2006-05-30 22:30:42 -04:00
parent 0e5db091e9
commit 91e3aa6295
20 changed files with 120 additions and 140 deletions

View file

@ -250,10 +250,9 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
// Now do the access. // Now do the access.
if (fault == NoFault) { if (fault == NoFault) {
data_read_pkt->reset();
data_read_pkt->reinitFromRequest(); data_read_pkt->reinitFromRequest();
dcache_complete = dcachePort.sendAtomic(data_read_pkt); dcache_latency = dcachePort.sendAtomic(data_read_pkt);
dcache_access = true; dcache_access = true;
assert(data_read_pkt->result == Packet::Success); assert(data_read_pkt->result == Packet::Success);
@ -329,12 +328,11 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
// Now do the access. // Now do the access.
if (fault == NoFault) { if (fault == NoFault) {
data_write_pkt->reset();
data = htog(data); data = htog(data);
data_write_pkt->dataStatic(&data);
data_write_pkt->reinitFromRequest(); data_write_pkt->reinitFromRequest();
data_write_pkt->dataStatic(&data);
dcache_complete = dcachePort.sendAtomic(data_write_pkt); dcache_latency = dcachePort.sendAtomic(data_write_pkt);
dcache_access = true; dcache_access = true;
assert(data_write_pkt->result == Packet::Success); assert(data_write_pkt->result == Packet::Success);
@ -411,11 +409,12 @@ AtomicSimpleCPU::tick()
checkForInterrupts(); checkForInterrupts();
ifetch_req->resetMin(); ifetch_req->resetMin();
ifetch_pkt->reset(); Fault fault = setupFetchRequest(ifetch_req);
Fault fault = setupFetchPacket(ifetch_pkt);
if (fault == NoFault) { if (fault == NoFault) {
Tick icache_complete = icachePort.sendAtomic(ifetch_pkt); ifetch_pkt->reinitFromRequest();
Tick icache_latency = icachePort.sendAtomic(ifetch_pkt);
// ifetch_req is initialized to read the instruction directly // ifetch_req is initialized to read the instruction directly
// into the CPU object's inst field. // into the CPU object's inst field.
@ -430,9 +429,9 @@ AtomicSimpleCPU::tick()
// cycle time. If not, the next tick event may get // cycle time. If not, the next tick event may get
// scheduled at a non-integer multiple of the CPU // scheduled at a non-integer multiple of the CPU
// cycle time. // cycle time.
Tick icache_stall = icache_complete - curTick - cycles(1); Tick icache_stall = icache_latency - cycles(1);
Tick dcache_stall = Tick dcache_stall =
dcache_access ? dcache_complete - curTick - cycles(1) : 0; dcache_access ? dcache_latency - cycles(1) : 0;
latency += icache_stall + dcache_stall; latency += icache_stall + dcache_stall;
} }

View file

@ -116,7 +116,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
Packet *data_write_pkt; Packet *data_write_pkt;
bool dcache_access; bool dcache_access;
Tick dcache_complete; Tick dcache_latency;
public: public:

View file

@ -351,29 +351,21 @@ BaseSimpleCPU::checkForInterrupts()
Fault Fault
BaseSimpleCPU::setupFetchPacket(Packet *ifetch_pkt) BaseSimpleCPU::setupFetchRequest(Request *req)
{ {
// Try to fetch an instruction
// set up memory request for instruction fetch // set up memory request for instruction fetch
DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",cpuXC->readPC(), DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",cpuXC->readPC(),
cpuXC->readNextPC(),cpuXC->readNextNPC()); cpuXC->readNextPC(),cpuXC->readNextNPC());
Request *ifetch_req = ifetch_pkt->req; req->setVaddr(cpuXC->readPC() & ~3);
ifetch_req->setVaddr(cpuXC->readPC() & ~3); req->setTime(curTick);
ifetch_req->setTime(curTick);
#if FULL_SYSTEM #if FULL_SYSTEM
ifetch_req->setFlags((cpuXC->readPC() & 1) ? PHYSICAL : 0); req->setFlags((cpuXC->readPC() & 1) ? PHYSICAL : 0);
#else #else
ifetch_req->setFlags(0); req->setFlags(0);
#endif #endif
Fault fault = cpuXC->translateInstReq(ifetch_req); Fault fault = cpuXC->translateInstReq(req);
if (fault == NoFault) {
ifetch_pkt->reinitFromRequest();
}
return fault; return fault;
} }

View file

@ -129,7 +129,7 @@ class BaseSimpleCPU : public BaseCPU
StaticInstPtr curStaticInst; StaticInstPtr curStaticInst;
void checkForInterrupts(); void checkForInterrupts();
Fault setupFetchPacket(Packet *ifetch_pkt); Fault setupFetchRequest(Request *req);
void preExecute(); void preExecute();
void postExecute(); void postExecute();
void advancePC(Fault fault); void advancePC(Fault fault);

View file

@ -342,11 +342,11 @@ TimingSimpleCPU::fetch()
Request *ifetch_req = new Request(true); Request *ifetch_req = new Request(true);
ifetch_req->setSize(sizeof(MachInst)); ifetch_req->setSize(sizeof(MachInst));
Fault fault = setupFetchRequest(ifetch_req);
ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
ifetch_pkt->dataStatic(&inst); ifetch_pkt->dataStatic(&inst);
Fault fault = setupFetchPacket(ifetch_pkt);
if (fault == NoFault) { if (fault == NoFault) {
if (!icachePort.sendTiming(ifetch_pkt)) { if (!icachePort.sendTiming(ifetch_pkt)) {
// Need to wait for retry // Need to wait for retry

View file

@ -98,7 +98,6 @@ AlphaConsole::read(Packet *pkt)
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
pkt->time += pioDelay;
Addr daddr = pkt->getAddr() - pioAddr; Addr daddr = pkt->getAddr() - pioAddr;
pkt->allocate(); pkt->allocate();
@ -191,8 +190,6 @@ AlphaConsole::read(Packet *pkt)
Tick Tick
AlphaConsole::write(Packet *pkt) AlphaConsole::write(Packet *pkt)
{ {
pkt->time += pioDelay;
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr daddr = pkt->getAddr() - pioAddr; Addr daddr = pkt->getAddr() - pioAddr;

View file

@ -430,7 +430,6 @@ IdeController::read(Packet *pkt)
IdeRegType reg_type; IdeRegType reg_type;
int disk; int disk;
pkt->time += pioDelay;
pkt->allocate(); pkt->allocate();
if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4) if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
panic("Bad IDE read size: %d\n", pkt->getSize()); panic("Bad IDE read size: %d\n", pkt->getSize());
@ -518,8 +517,6 @@ IdeController::write(Packet *pkt)
int disk; int disk;
uint8_t oldVal, newVal; uint8_t oldVal, newVal;
pkt->time += pioDelay;
parseAddr(pkt->getAddr(), offset, channel, reg_type); parseAddr(pkt->getAddr(), offset, channel, reg_type);
if (!io_enabled) { if (!io_enabled) {

View file

@ -80,10 +80,10 @@ PioPort::SendEvent::process()
bool bool
PioPort::recvTiming(Packet *pkt) PioPort::recvTiming(Packet *pkt)
{ {
device->recvAtomic(pkt); Tick latency = device->recvAtomic(pkt);
// turn packet around to go back to requester // turn packet around to go back to requester
pkt->makeTimingResponse(); pkt->makeTimingResponse();
sendTiming(pkt, pkt->time - pkt->req->getTime()); sendTiming(pkt, latency);
return true; return true;
} }

View file

@ -54,8 +54,6 @@ IsaFake::read(Packet *pkt)
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
pkt->time += pioDelay;
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize()); DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
switch (pkt->getSize()) { switch (pkt->getSize()) {
@ -80,7 +78,6 @@ IsaFake::read(Packet *pkt)
Tick Tick
IsaFake::write(Packet *pkt) IsaFake::write(Packet *pkt)
{ {
pkt->time += pioDelay;
DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize()); DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize());
pkt->result = Packet::Success; pkt->result = Packet::Success;
return pioDelay; return pioDelay;

View file

@ -492,7 +492,6 @@ NSGigE::read(Packet *pkt)
{ {
assert(ioEnable); assert(ioEnable);
pkt->time += pioDelay;
pkt->allocate(); pkt->allocate();
//The mask is to give you only the offset into the device register file //The mask is to give you only the offset into the device register file
@ -728,8 +727,6 @@ NSGigE::write(Packet *pkt)
DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n", DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
daddr, pkt->getAddr(), pkt->getSize()); daddr, pkt->getAddr(), pkt->getSize());
pkt->time += pioDelay;
if (daddr > LAST && daddr <= RESERVED) { if (daddr > LAST && daddr <= RESERVED) {
panic("Accessing reserved register"); panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) { } else if (daddr > RESERVED && daddr <= 0x3FC) {

View file

@ -99,7 +99,6 @@ PciConfigAll::read(Packet *pkt)
int func = (daddr >> 8) & 0x7; int func = (daddr >> 8) & 0x7;
int reg = daddr & 0xFF; int reg = daddr & 0xFF;
pkt->time += pioDelay;
pkt->allocate(); pkt->allocate();
DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt->getAddr(), daddr, DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt->getAddr(), daddr,
@ -134,8 +133,6 @@ PciConfigAll::read(Packet *pkt)
Tick Tick
PciConfigAll::write(Packet *pkt) PciConfigAll::write(Packet *pkt)
{ {
pkt->time += pioDelay;
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
assert(pkt->getSize() == sizeof(uint8_t) || pkt->getSize() == sizeof(uint16_t) || assert(pkt->getSize() == sizeof(uint8_t) || pkt->getSize() == sizeof(uint16_t) ||

View file

@ -322,7 +322,6 @@ Device::read(Packet *pkt)
Addr index = daddr >> Regs::VirtualShift; Addr index = daddr >> Regs::VirtualShift;
Addr raddr = daddr & Regs::VirtualMask; Addr raddr = daddr & Regs::VirtualMask;
pkt->time += pioDelay;
pkt->allocate(); pkt->allocate();
if (!regValid(raddr)) if (!regValid(raddr))
@ -410,8 +409,6 @@ Device::write(Packet *pkt)
Addr index = daddr >> Regs::VirtualShift; Addr index = daddr >> Regs::VirtualShift;
Addr raddr = daddr & Regs::VirtualMask; Addr raddr = daddr & Regs::VirtualMask;
pkt->time += pioDelay;
if (!regValid(raddr)) if (!regValid(raddr))
panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d", panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
cpu, daddr, pkt->getAddr(), pkt->getSize()); cpu, daddr, pkt->getAddr(), pkt->getSize());

View file

@ -76,7 +76,6 @@ TsunamiCChip::read(Packet *pkt)
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
pkt->time += pioDelay;
Addr regnum = (pkt->getAddr() - pioAddr) >> 6; Addr regnum = (pkt->getAddr() - pioAddr) >> 6;
Addr daddr = (pkt->getAddr() - pioAddr); Addr daddr = (pkt->getAddr() - pioAddr);
@ -182,9 +181,6 @@ TsunamiCChip::read(Packet *pkt)
Tick Tick
TsunamiCChip::write(Packet *pkt) TsunamiCChip::write(Packet *pkt)
{ {
pkt->time += pioDelay;
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr daddr = pkt->getAddr() - pioAddr; Addr daddr = pkt->getAddr() - pioAddr;
Addr regnum = (pkt->getAddr() - pioAddr) >> 6 ; Addr regnum = (pkt->getAddr() - pioAddr) >> 6 ;

View file

@ -447,7 +447,6 @@ TsunamiIO::read(Packet *pkt)
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
pkt->time += pioDelay;
Addr daddr = pkt->getAddr() - pioAddr; Addr daddr = pkt->getAddr() - pioAddr;
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(), DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(),
@ -511,8 +510,6 @@ TsunamiIO::read(Packet *pkt)
Tick Tick
TsunamiIO::write(Packet *pkt) TsunamiIO::write(Packet *pkt)
{ {
pkt->time += pioDelay;
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr daddr = pkt->getAddr() - pioAddr; Addr daddr = pkt->getAddr() - pioAddr;

View file

@ -70,8 +70,6 @@ TsunamiPChip::read(Packet *pkt)
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
pkt->time += pioDelay;
pkt->allocate(); pkt->allocate();
Addr daddr = (pkt->getAddr() - pioAddr) >> 6;; Addr daddr = (pkt->getAddr() - pioAddr) >> 6;;
assert(pkt->getSize() == sizeof(uint64_t)); assert(pkt->getSize() == sizeof(uint64_t));
@ -151,8 +149,6 @@ TsunamiPChip::read(Packet *pkt)
Tick Tick
TsunamiPChip::write(Packet *pkt) TsunamiPChip::write(Packet *pkt)
{ {
pkt->time += pioDelay;
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr daddr = (pkt->getAddr() - pioAddr) >> 6; Addr daddr = (pkt->getAddr() - pioAddr) >> 6;

View file

@ -114,7 +114,6 @@ Uart8250::read(Packet *pkt)
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
assert(pkt->getSize() == 1); assert(pkt->getSize() == 1);
pkt->time += pioDelay;
Addr daddr = pkt->getAddr() - pioAddr; Addr daddr = pkt->getAddr() - pioAddr;
pkt->allocate(); pkt->allocate();
@ -198,7 +197,6 @@ Uart8250::write(Packet *pkt)
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
assert(pkt->getSize() == 1); assert(pkt->getSize() == 1);
pkt->time += pioDelay;
Addr daddr = pkt->getAddr() - pioAddr; Addr daddr = pkt->getAddr() - pioAddr;
DPRINTF(Uart, " write register %#x value %#x\n", daddr, pkt->get<uint8_t>()); DPRINTF(Uart, " write register %#x value %#x\n", daddr, pkt->get<uint8_t>());

View file

@ -97,20 +97,6 @@ Packet::intersect(Packet *p)
return false; return false;
} }
/** Minimally reset a packet so something like simple cpu can reuse it. */
void
Packet::reset()
{
result = Unknown;
if (dynamicData) {
deleteData();
dynamicData = false;
arrayData = false;
time = curTick;
}
}
bool bool
fixPacket(Packet *func, Packet *timing) fixPacket(Packet *func, Packet *timing)
{ {

View file

@ -28,8 +28,7 @@
/** /**
* @file * @file
* Declaration of the Packet Class, a packet is a transaction occuring * Declaration of the Packet class.
* between a single level of the memory heirarchy (ie L1->L2).
*/ */
#ifndef __MEM_PACKET_HH__ #ifndef __MEM_PACKET_HH__
@ -44,81 +43,98 @@ typedef Packet* PacketPtr;
typedef uint8_t* PacketDataPtr; typedef uint8_t* PacketDataPtr;
/** /**
* A Packet is the structure to handle requests between two levels * A Packet is used to encapsulate a transfer between two objects in
* of the memory system. The Request is a global object that trancends * the memory system (e.g., the L1 and L2 cache). (In contrast, a
* all of the memory heirarchy, but at each levels interface a packet * single Request travels all the way from the requester to the
* is created to transfer data/requests. For example, a request would * ultimate destination and back, possibly being conveyed by several
* be used to initiate a request to go to memory/IOdevices, as the request * different Packets along the way.)
* passes through the memory system several packets will be created. One
* will be created to go between the L1 and L2 caches and another to go to
* the next level and so forth.
*
* Packets are assumed to be returned in the case of a single response. If
* the transaction has no response, then the consumer will delete the packet.
*/ */
class Packet class Packet
{ {
private: private:
/** A pointer to the data being transfered. It can be differnt sizes /** A pointer to the data being transfered. It can be differnt
at each level of the heirarchy so it belongs in the packet, * sizes at each level of the heirarchy so it belongs in the
not request. This may or may not be populated when a responder recieves * packet, not request. This may or may not be populated when a
the packet. If not populated it memory should be allocated. * responder recieves the packet. If not populated it memory
* should be allocated.
*/ */
PacketDataPtr data; PacketDataPtr data;
/** Is the data pointer set to a value that shouldn't be freed when the /** Is the data pointer set to a value that shouldn't be freed
* packet is destroyed? */ * when the packet is destroyed? */
bool staticData; bool staticData;
/** The data pointer points to a value that should be freed when the packet /** The data pointer points to a value that should be freed when
* is destroyed. */ * the packet is destroyed. */
bool dynamicData; bool dynamicData;
/** the data pointer points to an array (thus delete [] ) needs to be called /** the data pointer points to an array (thus delete [] ) needs to
* on it rather than simply delete.*/ * be called on it rather than simply delete.*/
bool arrayData; bool arrayData;
/** The address of the request, could be virtual or physical (depending on /** The address of the request. This address could be virtual or
cache configurations). */ * physical, depending on the system configuration. */
Addr addr; Addr addr;
/** Indicates the size of the request. */ /** The size of the request or transfer. */
int size; int size;
/** A index of the source of the transaction. */ /** Device address (e.g., bus ID) of the source of the
* transaction. The source is not responsible for setting this
* field; it is set implicitly by the interconnect when the
* packet * is first sent. */
short src; short src;
/** A index to the destination of the transaction. */ /** Device address (e.g., bus ID) of the destination of the
* transaction. The special value Broadcast indicates that the
* packet should be routed based on its address. This field is
* initialized in the constructor and is thus always valid
* (unlike * addr, size, and src). */
short dest; short dest;
/** Is the 'addr' field valid? */
bool addrValid; bool addrValid;
/** Is the 'size' field valid? */
bool sizeValid; bool sizeValid;
/** Is the 'src' field valid? */
bool srcValid; bool srcValid;
public: public:
/** The special destination address indicating that the packet
* should be routed based on its address. */
static const short Broadcast = -1; static const short Broadcast = -1;
/** A pointer to the overall request. */ /** A pointer to the original request. */
RequestPtr req; 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 { class CoherenceState {
public: public:
virtual ~CoherenceState() {} virtual ~CoherenceState() {}
}; };
/** A virtual base opaque structure used to hold /** This packet's coherence state. Caches should use
coherence status messages. */ * dynamic_cast<> to cast to the state appropriate for the
CoherenceState *coherence; // virtual base opaque, * system's coherence protocol. */
// assert(dynamic_cast<Foo>) etc. 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
* response so that the sender can quickly look up the state
* needed to process it. A specific subclass would be derived
* from this to carry state specific to a particular sending
* device. */
class SenderState { class SenderState {
public: public:
virtual ~SenderState() {} virtual ~SenderState() {}
}; };
/** A virtual base opaque structure used to hold the senders state. */ /** This packet's sender state. Devices should use dynamic_cast<>
SenderState *senderState; // virtual base opaque, * to cast to the state appropriate to the sender. */
// assert(dynamic_cast<Foo>) etc. SenderState *senderState;
private: private:
/** List of command attributes. */ /** List of command attributes. */
@ -144,9 +160,11 @@ class Packet
WriteResp = IsWrite | IsResponse WriteResp = IsWrite | IsResponse
}; };
/** Return the string name of the cmd field (for debugging and
* tracing). */
const std::string &cmdString() const; const std::string &cmdString() const;
/** The command of the transaction. */ /** The command field of the packet. */
Command cmd; Command cmd;
bool isRead() { return (cmd & IsRead) != 0; } bool isRead() { return (cmd & IsRead) != 0; }
@ -154,20 +172,7 @@ class Packet
bool isResponse() { return (cmd & IsResponse) != 0; } bool isResponse() { return (cmd & IsResponse) != 0; }
bool needsResponse() { return (cmd & NeedsResponse) != 0; } bool needsResponse() { return (cmd & NeedsResponse) != 0; }
void makeTimingResponse() { /** Possible results of a packet's request. */
assert(needsResponse());
int icmd = (int)cmd;
icmd &= ~(IsRequest | NeedsResponse);
icmd |= IsResponse;
cmd = (Command)icmd;
dest = src;
srcValid = false;
}
/** The time this request was responded to. Used to calculate latencies. */
Tick time;
/** The result of a particular packets request. */
enum Result enum Result
{ {
Success, Success,
@ -175,7 +180,7 @@ class Packet
Unknown Unknown
}; };
/** The result of the packet transaction. */ /** The result of this packet's request. */
Result result; Result result;
/** Accessor function that returns the source index of the packet. */ /** Accessor function that returns the source index of the packet. */
@ -193,27 +198,56 @@ class Packet
int getSize() const { assert(sizeValid); return size; } int getSize() const { assert(sizeValid); return size; }
void setSize(int _size) { size = _size; sizeValid = true; } void setSize(int _size) { size = _size; sizeValid = true; }
/** 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, Command _cmd, short _dest) Packet(Request *_req, Command _cmd, short _dest)
: data(NULL), staticData(false), dynamicData(false), arrayData(false), : data(NULL), staticData(false), dynamicData(false), arrayData(false),
addr(_req->paddr), size(_req->size), dest(_dest), addr(_req->paddr), size(_req->size), dest(_dest),
addrValid(_req->validPaddr), sizeValid(_req->validSize), addrValid(_req->validPaddr), sizeValid(_req->validSize),
srcValid(false), srcValid(false),
req(_req), coherence(NULL), senderState(NULL), cmd(_cmd), req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
time(curTick), result(Unknown) result(Unknown)
{ {
} }
/** Destructor. */
~Packet() ~Packet()
{ deleteData(); } { deleteData(); }
/** Reinitialize packet address and size from the associated
/** Minimally reset a packet so something like simple cpu can reuse it. */ * Request object, and reset other fields that may have been
void reset(); * modified by a previous transaction. Typically called when a
* statically allocated Request/Packet pair is reused for
* multiple transactions. */
void reinitFromRequest() { void reinitFromRequest() {
if (req->validPaddr) setAddr(req->paddr); assert(req->validPaddr);
if (req->validSize) setSize(req->size); setAddr(req->paddr);
assert(req->validSize);
setSize(req->size);
result = Unknown;
if (dynamicData) {
deleteData();
dynamicData = false;
arrayData = false;
}
}
/** Take a request packet and modify it in place to be suitable
* for returning as a response to that request. Used for timing
* accesses only. For atomic and functional accesses, the
* request packet is always implicitly passed back *without*
* modifying the command or destination fields, so this function
* should not be called. */
void makeTimingResponse() {
assert(needsResponse());
int icmd = (int)cmd;
icmd &= ~(IsRequest | NeedsResponse);
icmd |= IsResponse;
cmd = (Command)icmd;
dest = src;
srcValid = false;
} }
/** Set the data pointer to the following value that should not be freed. */ /** Set the data pointer to the following value that should not be freed. */

View file

@ -139,8 +139,7 @@ Tick
PhysicalMemory::doAtomicAccess(Packet *pkt) PhysicalMemory::doAtomicAccess(Packet *pkt)
{ {
doFunctionalAccess(pkt); doFunctionalAccess(pkt);
pkt->time = curTick + lat; return lat;
return curTick + lat;
} }
void void

View file

@ -165,10 +165,11 @@ class Port
*/ */
bool sendTiming(Packet *pkt) { return peer->recvTiming(pkt); } bool sendTiming(Packet *pkt) { return peer->recvTiming(pkt); }
/** Function called by the associated device to send an atomic access, /** Function called by the associated device to send an atomic
an access in which the data is moved and the state is updated in one * access, an access in which the data is moved and the state is
cycle, without interleaving with other memory accesses. * updated in one cycle, without interleaving with other memory
*/ * accesses. Returns estimated latency of access.
*/
Tick sendAtomic(Packet *pkt) Tick sendAtomic(Packet *pkt)
{ return peer->recvAtomic(pkt); } { return peer->recvAtomic(pkt); }