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.
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;
}

View file

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

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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) {

View file

@ -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;
}

View file

@ -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;

View file

@ -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) {

View file

@ -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) ||

View file

@ -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());

View file

@ -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 ;

View file

@ -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;

View file

@ -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;

View file

@ -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>());

View file

@ -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)
{

View file

@ -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. */

View file

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

View file

@ -165,10 +165,11 @@ 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); }