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:
parent
0e5db091e9
commit
91e3aa6295
|
@ -250,10 +250,9 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
|||
|
||||
// Now do the access.
|
||||
if (fault == NoFault) {
|
||||
data_read_pkt->reset();
|
||||
data_read_pkt->reinitFromRequest();
|
||||
|
||||
dcache_complete = dcachePort.sendAtomic(data_read_pkt);
|
||||
dcache_latency = dcachePort.sendAtomic(data_read_pkt);
|
||||
dcache_access = true;
|
||||
|
||||
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.
|
||||
if (fault == NoFault) {
|
||||
data_write_pkt->reset();
|
||||
data = htog(data);
|
||||
data_write_pkt->dataStatic(&data);
|
||||
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;
|
||||
|
||||
assert(data_write_pkt->result == Packet::Success);
|
||||
|
@ -411,11 +409,12 @@ AtomicSimpleCPU::tick()
|
|||
checkForInterrupts();
|
||||
|
||||
ifetch_req->resetMin();
|
||||
ifetch_pkt->reset();
|
||||
Fault fault = setupFetchPacket(ifetch_pkt);
|
||||
Fault fault = setupFetchRequest(ifetch_req);
|
||||
|
||||
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
|
||||
// into the CPU object's inst field.
|
||||
|
||||
|
@ -430,9 +429,9 @@ AtomicSimpleCPU::tick()
|
|||
// cycle time. If not, the next tick event may get
|
||||
// scheduled at a non-integer multiple of the CPU
|
||||
// cycle time.
|
||||
Tick icache_stall = icache_complete - curTick - cycles(1);
|
||||
Tick icache_stall = icache_latency - cycles(1);
|
||||
Tick dcache_stall =
|
||||
dcache_access ? dcache_complete - curTick - cycles(1) : 0;
|
||||
dcache_access ? dcache_latency - cycles(1) : 0;
|
||||
latency += icache_stall + dcache_stall;
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
|
|||
Packet *data_write_pkt;
|
||||
|
||||
bool dcache_access;
|
||||
Tick dcache_complete;
|
||||
Tick dcache_latency;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -351,29 +351,21 @@ BaseSimpleCPU::checkForInterrupts()
|
|||
|
||||
|
||||
Fault
|
||||
BaseSimpleCPU::setupFetchPacket(Packet *ifetch_pkt)
|
||||
BaseSimpleCPU::setupFetchRequest(Request *req)
|
||||
{
|
||||
// Try to fetch an instruction
|
||||
|
||||
// set up memory request for instruction fetch
|
||||
|
||||
DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",cpuXC->readPC(),
|
||||
cpuXC->readNextPC(),cpuXC->readNextNPC());
|
||||
|
||||
Request *ifetch_req = ifetch_pkt->req;
|
||||
ifetch_req->setVaddr(cpuXC->readPC() & ~3);
|
||||
ifetch_req->setTime(curTick);
|
||||
req->setVaddr(cpuXC->readPC() & ~3);
|
||||
req->setTime(curTick);
|
||||
#if FULL_SYSTEM
|
||||
ifetch_req->setFlags((cpuXC->readPC() & 1) ? PHYSICAL : 0);
|
||||
req->setFlags((cpuXC->readPC() & 1) ? PHYSICAL : 0);
|
||||
#else
|
||||
ifetch_req->setFlags(0);
|
||||
req->setFlags(0);
|
||||
#endif
|
||||
|
||||
Fault fault = cpuXC->translateInstReq(ifetch_req);
|
||||
|
||||
if (fault == NoFault) {
|
||||
ifetch_pkt->reinitFromRequest();
|
||||
}
|
||||
Fault fault = cpuXC->translateInstReq(req);
|
||||
|
||||
return fault;
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ class BaseSimpleCPU : public BaseCPU
|
|||
StaticInstPtr curStaticInst;
|
||||
|
||||
void checkForInterrupts();
|
||||
Fault setupFetchPacket(Packet *ifetch_pkt);
|
||||
Fault setupFetchRequest(Request *req);
|
||||
void preExecute();
|
||||
void postExecute();
|
||||
void advancePC(Fault fault);
|
||||
|
|
|
@ -342,11 +342,11 @@ TimingSimpleCPU::fetch()
|
|||
|
||||
Request *ifetch_req = new Request(true);
|
||||
ifetch_req->setSize(sizeof(MachInst));
|
||||
Fault fault = setupFetchRequest(ifetch_req);
|
||||
|
||||
ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
|
||||
ifetch_pkt->dataStatic(&inst);
|
||||
|
||||
Fault fault = setupFetchPacket(ifetch_pkt);
|
||||
if (fault == NoFault) {
|
||||
if (!icachePort.sendTiming(ifetch_pkt)) {
|
||||
// Need to wait for retry
|
||||
|
|
|
@ -98,7 +98,6 @@ AlphaConsole::read(Packet *pkt)
|
|||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
pkt->time += pioDelay;
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
pkt->allocate();
|
||||
|
@ -191,8 +190,6 @@ AlphaConsole::read(Packet *pkt)
|
|||
Tick
|
||||
AlphaConsole::write(Packet *pkt)
|
||||
{
|
||||
pkt->time += pioDelay;
|
||||
|
||||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
|
|
@ -430,7 +430,6 @@ IdeController::read(Packet *pkt)
|
|||
IdeRegType reg_type;
|
||||
int disk;
|
||||
|
||||
pkt->time += pioDelay;
|
||||
pkt->allocate();
|
||||
if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
|
||||
panic("Bad IDE read size: %d\n", pkt->getSize());
|
||||
|
@ -518,8 +517,6 @@ IdeController::write(Packet *pkt)
|
|||
int disk;
|
||||
uint8_t oldVal, newVal;
|
||||
|
||||
pkt->time += pioDelay;
|
||||
|
||||
parseAddr(pkt->getAddr(), offset, channel, reg_type);
|
||||
|
||||
if (!io_enabled) {
|
||||
|
|
|
@ -80,10 +80,10 @@ PioPort::SendEvent::process()
|
|||
bool
|
||||
PioPort::recvTiming(Packet *pkt)
|
||||
{
|
||||
device->recvAtomic(pkt);
|
||||
Tick latency = device->recvAtomic(pkt);
|
||||
// turn packet around to go back to requester
|
||||
pkt->makeTimingResponse();
|
||||
sendTiming(pkt, pkt->time - pkt->req->getTime());
|
||||
sendTiming(pkt, latency);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,8 +54,6 @@ IsaFake::read(Packet *pkt)
|
|||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
pkt->time += pioDelay;
|
||||
|
||||
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
|
||||
|
||||
switch (pkt->getSize()) {
|
||||
|
@ -80,7 +78,6 @@ IsaFake::read(Packet *pkt)
|
|||
Tick
|
||||
IsaFake::write(Packet *pkt)
|
||||
{
|
||||
pkt->time += pioDelay;
|
||||
DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize());
|
||||
pkt->result = Packet::Success;
|
||||
return pioDelay;
|
||||
|
|
|
@ -492,7 +492,6 @@ NSGigE::read(Packet *pkt)
|
|||
{
|
||||
assert(ioEnable);
|
||||
|
||||
pkt->time += pioDelay;
|
||||
pkt->allocate();
|
||||
|
||||
//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",
|
||||
daddr, pkt->getAddr(), pkt->getSize());
|
||||
|
||||
pkt->time += pioDelay;
|
||||
|
||||
if (daddr > LAST && daddr <= RESERVED) {
|
||||
panic("Accessing reserved register");
|
||||
} else if (daddr > RESERVED && daddr <= 0x3FC) {
|
||||
|
|
|
@ -99,7 +99,6 @@ PciConfigAll::read(Packet *pkt)
|
|||
int func = (daddr >> 8) & 0x7;
|
||||
int reg = daddr & 0xFF;
|
||||
|
||||
pkt->time += pioDelay;
|
||||
pkt->allocate();
|
||||
|
||||
DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt->getAddr(), daddr,
|
||||
|
@ -134,8 +133,6 @@ PciConfigAll::read(Packet *pkt)
|
|||
Tick
|
||||
PciConfigAll::write(Packet *pkt)
|
||||
{
|
||||
pkt->time += pioDelay;
|
||||
|
||||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == sizeof(uint8_t) || pkt->getSize() == sizeof(uint16_t) ||
|
||||
|
|
|
@ -322,7 +322,6 @@ Device::read(Packet *pkt)
|
|||
Addr index = daddr >> Regs::VirtualShift;
|
||||
Addr raddr = daddr & Regs::VirtualMask;
|
||||
|
||||
pkt->time += pioDelay;
|
||||
pkt->allocate();
|
||||
|
||||
if (!regValid(raddr))
|
||||
|
@ -410,8 +409,6 @@ Device::write(Packet *pkt)
|
|||
Addr index = daddr >> Regs::VirtualShift;
|
||||
Addr raddr = daddr & Regs::VirtualMask;
|
||||
|
||||
pkt->time += pioDelay;
|
||||
|
||||
if (!regValid(raddr))
|
||||
panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
|
||||
cpu, daddr, pkt->getAddr(), pkt->getSize());
|
||||
|
|
|
@ -76,7 +76,6 @@ TsunamiCChip::read(Packet *pkt)
|
|||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
pkt->time += pioDelay;
|
||||
Addr regnum = (pkt->getAddr() - pioAddr) >> 6;
|
||||
Addr daddr = (pkt->getAddr() - pioAddr);
|
||||
|
||||
|
@ -182,9 +181,6 @@ TsunamiCChip::read(Packet *pkt)
|
|||
Tick
|
||||
TsunamiCChip::write(Packet *pkt)
|
||||
{
|
||||
pkt->time += pioDelay;
|
||||
|
||||
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
Addr regnum = (pkt->getAddr() - pioAddr) >> 6 ;
|
||||
|
|
|
@ -447,7 +447,6 @@ TsunamiIO::read(Packet *pkt)
|
|||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
pkt->time += pioDelay;
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(),
|
||||
|
@ -511,8 +510,6 @@ TsunamiIO::read(Packet *pkt)
|
|||
Tick
|
||||
TsunamiIO::write(Packet *pkt)
|
||||
{
|
||||
pkt->time += pioDelay;
|
||||
|
||||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
|
|
@ -70,8 +70,6 @@ TsunamiPChip::read(Packet *pkt)
|
|||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
|
||||
pkt->time += pioDelay;
|
||||
pkt->allocate();
|
||||
Addr daddr = (pkt->getAddr() - pioAddr) >> 6;;
|
||||
assert(pkt->getSize() == sizeof(uint64_t));
|
||||
|
@ -151,8 +149,6 @@ TsunamiPChip::read(Packet *pkt)
|
|||
Tick
|
||||
TsunamiPChip::write(Packet *pkt)
|
||||
{
|
||||
pkt->time += pioDelay;
|
||||
|
||||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
Addr daddr = (pkt->getAddr() - pioAddr) >> 6;
|
||||
|
|
|
@ -114,7 +114,6 @@ Uart8250::read(Packet *pkt)
|
|||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 1);
|
||||
|
||||
pkt->time += pioDelay;
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
pkt->allocate();
|
||||
|
||||
|
@ -198,7 +197,6 @@ Uart8250::write(Packet *pkt)
|
|||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
assert(pkt->getSize() == 1);
|
||||
|
||||
pkt->time += pioDelay;
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
DPRINTF(Uart, " write register %#x value %#x\n", daddr, pkt->get<uint8_t>());
|
||||
|
|
|
@ -97,20 +97,6 @@ Packet::intersect(Packet *p)
|
|||
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
|
||||
fixPacket(Packet *func, Packet *timing)
|
||||
{
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Declaration of the Packet Class, a packet is a transaction occuring
|
||||
* between a single level of the memory heirarchy (ie L1->L2).
|
||||
* Declaration of the Packet class.
|
||||
*/
|
||||
|
||||
#ifndef __MEM_PACKET_HH__
|
||||
|
@ -44,81 +43,98 @@ typedef Packet* PacketPtr;
|
|||
typedef uint8_t* PacketDataPtr;
|
||||
|
||||
/**
|
||||
* A Packet is the structure to handle requests between two levels
|
||||
* of the memory system. The Request is a global object that trancends
|
||||
* all of the memory heirarchy, but at each levels interface a packet
|
||||
* is created to transfer data/requests. For example, a request would
|
||||
* be used to initiate a request to go to memory/IOdevices, as the request
|
||||
* 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.
|
||||
* A Packet is used to encapsulate a transfer between two objects in
|
||||
* the memory system (e.g., the L1 and L2 cache). (In contrast, a
|
||||
* single Request travels all the way from the requester to the
|
||||
* ultimate destination and back, possibly being conveyed by several
|
||||
* different Packets along the way.)
|
||||
*/
|
||||
class Packet
|
||||
{
|
||||
private:
|
||||
/** A pointer to the data being transfered. It can be differnt sizes
|
||||
at each level of the heirarchy so it belongs in the packet,
|
||||
not request. This may or may not be populated when a responder recieves
|
||||
the packet. If not populated it memory should be allocated.
|
||||
/** A pointer to the data being transfered. It can be differnt
|
||||
* sizes at each level of the heirarchy so it belongs in the
|
||||
* packet, not request. This may or may not be populated when a
|
||||
* responder recieves the packet. If not populated it memory
|
||||
* should be allocated.
|
||||
*/
|
||||
PacketDataPtr data;
|
||||
|
||||
/** Is the data pointer set to a value that shouldn't be freed when the
|
||||
* packet is destroyed? */
|
||||
/** Is the data pointer set to a value that shouldn't be freed
|
||||
* when the packet is destroyed? */
|
||||
bool staticData;
|
||||
/** The data pointer points to a value that should be freed when the packet
|
||||
* is destroyed. */
|
||||
/** The data pointer points to a value that should be freed when
|
||||
* the packet is destroyed. */
|
||||
bool dynamicData;
|
||||
/** the data pointer points to an array (thus delete [] ) needs to be called
|
||||
* on it rather than simply delete.*/
|
||||
/** the data pointer points to an array (thus delete [] ) needs to
|
||||
* be called on it rather than simply delete.*/
|
||||
bool arrayData;
|
||||
|
||||
|
||||
/** The address of the request, could be virtual or physical (depending on
|
||||
cache configurations). */
|
||||
/** The address of the request. This address could be virtual or
|
||||
* physical, depending on the system configuration. */
|
||||
Addr addr;
|
||||
|
||||
/** Indicates the size of the request. */
|
||||
/** The size of the request or transfer. */
|
||||
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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Is the 'addr' field valid? */
|
||||
bool addrValid;
|
||||
/** Is the 'size' field valid? */
|
||||
bool sizeValid;
|
||||
/** Is the 'src' field valid? */
|
||||
bool srcValid;
|
||||
|
||||
public:
|
||||
|
||||
/** The special destination address indicating that the packet
|
||||
* should be routed based on its address. */
|
||||
static const short Broadcast = -1;
|
||||
|
||||
/** A pointer to the overall request. */
|
||||
/** 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:
|
||||
virtual ~CoherenceState() {}
|
||||
};
|
||||
|
||||
/** A virtual base opaque structure used to hold
|
||||
coherence status messages. */
|
||||
CoherenceState *coherence; // virtual base opaque,
|
||||
// assert(dynamic_cast<Foo>) etc.
|
||||
/** 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
|
||||
* 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 {
|
||||
public:
|
||||
virtual ~SenderState() {}
|
||||
};
|
||||
|
||||
/** A virtual base opaque structure used to hold the senders state. */
|
||||
SenderState *senderState; // virtual base opaque,
|
||||
// assert(dynamic_cast<Foo>) etc.
|
||||
/** This packet's sender state. Devices should use dynamic_cast<>
|
||||
* to cast to the state appropriate to the sender. */
|
||||
SenderState *senderState;
|
||||
|
||||
private:
|
||||
/** List of command attributes. */
|
||||
|
@ -144,9 +160,11 @@ class Packet
|
|||
WriteResp = IsWrite | IsResponse
|
||||
};
|
||||
|
||||
/** Return the string name of the cmd field (for debugging and
|
||||
* tracing). */
|
||||
const std::string &cmdString() const;
|
||||
|
||||
/** The command of the transaction. */
|
||||
/** The command field of the packet. */
|
||||
Command cmd;
|
||||
|
||||
bool isRead() { return (cmd & IsRead) != 0; }
|
||||
|
@ -154,20 +172,7 @@ class Packet
|
|||
bool isResponse() { return (cmd & IsResponse) != 0; }
|
||||
bool needsResponse() { return (cmd & NeedsResponse) != 0; }
|
||||
|
||||
void makeTimingResponse() {
|
||||
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. */
|
||||
/** Possible results of a packet's request. */
|
||||
enum Result
|
||||
{
|
||||
Success,
|
||||
|
@ -175,7 +180,7 @@ class Packet
|
|||
Unknown
|
||||
};
|
||||
|
||||
/** The result of the packet transaction. */
|
||||
/** The result of this packet's request. */
|
||||
Result result;
|
||||
|
||||
/** Accessor function that returns the source index of the packet. */
|
||||
|
@ -193,27 +198,56 @@ class Packet
|
|||
int getSize() const { assert(sizeValid); return size; }
|
||||
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)
|
||||
: data(NULL), staticData(false), dynamicData(false), arrayData(false),
|
||||
addr(_req->paddr), size(_req->size), dest(_dest),
|
||||
addrValid(_req->validPaddr), sizeValid(_req->validSize),
|
||||
srcValid(false),
|
||||
req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
|
||||
time(curTick), result(Unknown)
|
||||
result(Unknown)
|
||||
{
|
||||
}
|
||||
|
||||
/** Destructor. */
|
||||
~Packet()
|
||||
{ deleteData(); }
|
||||
|
||||
|
||||
/** Minimally reset a packet so something like simple cpu can reuse it. */
|
||||
void reset();
|
||||
|
||||
/** Reinitialize packet address and size from the associated
|
||||
* Request object, and reset other fields that may have been
|
||||
* modified by a previous transaction. Typically called when a
|
||||
* statically allocated Request/Packet pair is reused for
|
||||
* multiple transactions. */
|
||||
void reinitFromRequest() {
|
||||
if (req->validPaddr) setAddr(req->paddr);
|
||||
if (req->validSize) setSize(req->size);
|
||||
assert(req->validPaddr);
|
||||
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. */
|
||||
|
|
|
@ -139,8 +139,7 @@ Tick
|
|||
PhysicalMemory::doAtomicAccess(Packet *pkt)
|
||||
{
|
||||
doFunctionalAccess(pkt);
|
||||
pkt->time = curTick + lat;
|
||||
return curTick + lat;
|
||||
return lat;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -165,9 +165,10 @@ class Port
|
|||
*/
|
||||
bool sendTiming(Packet *pkt) { return peer->recvTiming(pkt); }
|
||||
|
||||
/** Function called by the associated device to send an atomic access,
|
||||
an access in which the data is moved and the state is updated in one
|
||||
cycle, without interleaving with other memory accesses.
|
||||
/** Function called by the associated device to send an atomic
|
||||
* access, an access in which the data is moved and the state is
|
||||
* updated in one cycle, without interleaving with other memory
|
||||
* accesses. Returns estimated latency of access.
|
||||
*/
|
||||
Tick sendAtomic(Packet *pkt)
|
||||
{ return peer->recvAtomic(pkt); }
|
||||
|
|
Loading…
Reference in a new issue