changed sendresult -> bool,tick,void as appropriate
first crack at io devices code made CpuRequest that derives from Request dev/io_device.cc: dev/io_device.hh: first crack at the classes for Pio and Dma devices dev/platform.hh: We are going to a system pointer to get info about the memory system mem/bus.hh: changed sendresult -> bool,tick,void as appropriate mem/port.hh: changed sendresult -> bool,tick,void as appropriate; removed the sendTiming(pkt,t) call since it is not really implementable in a generic fashion mem/request.hh: pulled items from Request into CpuRequest --HG-- extra : convert_revision : 6213cf2b66417fa023b80884d9e623e78f5aa891
This commit is contained in:
parent
a1033448ea
commit
4875b33467
6 changed files with 283 additions and 66 deletions
110
dev/io_device.cc
110
dev/io_device.cc
|
@ -27,25 +27,118 @@
|
|||
*/
|
||||
|
||||
#include "dev/io_device.hh"
|
||||
#include "mem/bus/base_interface.hh"
|
||||
#include "mem/bus/dma_interface.hh"
|
||||
#include "sim/builder.hh"
|
||||
|
||||
void
|
||||
PioPort::SendEvent::process()
|
||||
{
|
||||
if (port->sendTiming(packet) == Success)
|
||||
return;
|
||||
|
||||
port->transmitList.push_back(&packet);
|
||||
}
|
||||
|
||||
PioDevice::PioDevice(const std::string &name, Platform *p)
|
||||
: FunctionalMemory(name), platform(p), pioInterface(NULL), pioLatency(0)
|
||||
{}
|
||||
: SimObject(name), platform(p)
|
||||
{
|
||||
pioPort = new PioPort(this);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PioDevice::recvTiming(Packet &pkt)
|
||||
{
|
||||
device->recvAtomic(pkt);
|
||||
sendTiming(pkt, pkt.responseTime-pkt.requestTime);
|
||||
return Success;
|
||||
}
|
||||
|
||||
PioDevice::~PioDevice()
|
||||
{
|
||||
if (pioInterface)
|
||||
if (pioPort)
|
||||
delete pioInterface;
|
||||
}
|
||||
|
||||
DEFINE_SIM_OBJECT_CLASS_NAME("PioDevice", PioDevice)
|
||||
void
|
||||
DmaPort::sendDma(Packet &pkt)
|
||||
{
|
||||
device->platform->system->memoryMode()
|
||||
{
|
||||
case MemAtomic:
|
||||
}
|
||||
}
|
||||
|
||||
DmaDevice::DmaDevice(const std::string &name, Platform *p)
|
||||
: PioDevice(name, p), dmaInterface(NULL)
|
||||
{}
|
||||
: PioDevice(name, p)
|
||||
{
|
||||
dmaPort = new dmaPort(this);
|
||||
}
|
||||
|
||||
void
|
||||
DmaPort::dmaAction(Memory::Command cmd, DmaPort port, Addr addr, int size,
|
||||
Event *event, uint8_t *data = NULL)
|
||||
{
|
||||
|
||||
assert(event);
|
||||
|
||||
int prevSize = 0;
|
||||
Packet basePkt;
|
||||
Request baseReq;
|
||||
|
||||
basePkt.flags = 0;
|
||||
basePkt.coherence = NULL;
|
||||
basePkt.senderState = NULL;
|
||||
basePkt.src = 0;
|
||||
basePkt.dest = 0;
|
||||
basePkt.cmd = cmd;
|
||||
basePkt.result = Unknown;
|
||||
basePkt.request = NULL;
|
||||
baseReq.nicReq = true;
|
||||
baseReq.time = curTick;
|
||||
|
||||
completionEvent = event;
|
||||
|
||||
for (ChunkGenerator gen(addr, size, sendBlockSizeQuery()); !gen.done(); gen.next()) {
|
||||
Packet *pkt = new Packet(basePkt);
|
||||
Request *req = new Request(baseReq);
|
||||
pkt->addr = gen.addr();
|
||||
pkt->size = gen.size();
|
||||
pkt->req = req;
|
||||
pkt->req->paddr = pkt->addr;
|
||||
pkt->req->size = pkt->size;
|
||||
// Increment the data pointer on a write
|
||||
pkt->data = data ? data + prevSize : NULL ;
|
||||
prevSize = pkt->size;
|
||||
|
||||
sendDma(*pkt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DmaPort::sendDma(Packet &pkt)
|
||||
{
|
||||
// some kind of selction between access methods
|
||||
// more work is going to have to be done to make
|
||||
// switching actually work
|
||||
MemState state = device->platform->system->memState;
|
||||
|
||||
if (state == Timing) {
|
||||
if (sendTiming(pkt) == Failure)
|
||||
transmitList.push_back(&packet);
|
||||
} else if (state == Atomic) {
|
||||
sendAtomic(pkt);
|
||||
completionEvent->schedule(pkt.responseTime - pkt.requestTime);
|
||||
completionEvent == NULL;
|
||||
} else if (state == Functional) {
|
||||
sendFunctional(pkt);
|
||||
// Is this correct???
|
||||
completionEvent->schedule(pkt.responseTime - pkt.requestTime);
|
||||
completionEvent == NULL;
|
||||
} else
|
||||
panic("Unknown memory command state.");
|
||||
|
||||
}
|
||||
|
||||
DmaDevice::~DmaDevice()
|
||||
{
|
||||
|
@ -53,5 +146,4 @@ DmaDevice::~DmaDevice()
|
|||
delete dmaInterface;
|
||||
}
|
||||
|
||||
DEFINE_SIM_OBJECT_CLASS_NAME("DmaDevice", DmaDevice)
|
||||
|
||||
|
|
150
dev/io_device.hh
150
dev/io_device.hh
|
@ -29,34 +29,168 @@
|
|||
#ifndef __DEV_IO_DEVICE_HH__
|
||||
#define __DEV_IO_DEVICE_HH__
|
||||
|
||||
#include "mem/functional/functional.hh"
|
||||
#include "base/chunk_generator.hh"
|
||||
#include "mem/port.hh"
|
||||
#include "sim/eventq.hh"
|
||||
|
||||
class BaseInterface;
|
||||
class Bus;
|
||||
class HierParams;
|
||||
class Platform;
|
||||
template <class BusType> class DMAInterface;
|
||||
class PioDevice;
|
||||
|
||||
class PioDevice : public FunctionalMemory
|
||||
class PioPort : public Port
|
||||
{
|
||||
protected:
|
||||
PioDevice *device;
|
||||
|
||||
virtual bool recvTiming(Packet &pkt);
|
||||
|
||||
virtual Tick recvAtomic(Packet &pkt)
|
||||
{ return device->recvAtomic(pkt) };
|
||||
|
||||
virtual void recvFunctional(Packet &pkt)
|
||||
{ device->recvAtomic(pkt) };
|
||||
|
||||
virtual void recvAddressRangeQuery(std::list<Range<Addr> > &range_list,
|
||||
bool &owner)
|
||||
{ device->addressRanges(range_list, owner); }
|
||||
|
||||
void sendTiming(Packet &pkt, Tick time)
|
||||
{ new SendEvent(this, pkt, time); }
|
||||
|
||||
class SendEvent : public Event
|
||||
{
|
||||
PioPort *port;
|
||||
Packet packet;
|
||||
|
||||
SendEvent(PioPort *p, Packet &pkt, Tick t)
|
||||
: Event(&mainEventQueue), packet(pkt)
|
||||
{ schedule(curTick + t); }
|
||||
|
||||
virtual void process();
|
||||
|
||||
virtual const char *description()
|
||||
{ return "Future scheduled sendTiming event"; }
|
||||
|
||||
friend class PioPort;
|
||||
}
|
||||
|
||||
public:
|
||||
PioPort(PioDevice *dev)
|
||||
: device(dev)
|
||||
{ }
|
||||
|
||||
};
|
||||
|
||||
class DmaPort : public Port
|
||||
{
|
||||
protected:
|
||||
PioDevice *device;
|
||||
std::list<Packet*> transmitList;
|
||||
|
||||
|
||||
virtual bool recvTiming(Packet &pkt)
|
||||
{ completionEvent->schedule(curTick+1); completionEvent = NULL; }
|
||||
virtual Tick recvAtomic(Packet &pkt)
|
||||
{ panic("dma port shouldn't be used for pio access."); }
|
||||
virtual void recvFunctional(Packet &pkt)
|
||||
{ panic("dma port shouldn't be used for pio access."); }
|
||||
|
||||
virtual void recvStatusChange(Status status)
|
||||
{ ; }
|
||||
|
||||
virtual Packet *recvRetry()
|
||||
{ return transmitList.pop_front(); }
|
||||
|
||||
virtual void recvAddressRangeQuery(std::list<Range<Addr> > &range_list,
|
||||
bool &owner)
|
||||
{ range_list.clear(); owner = true; }
|
||||
|
||||
void dmaAction(Memory::Command cmd, DmaPort port, Addr addr, int size,
|
||||
Event *event, uint8_t *data = NULL);
|
||||
|
||||
void sendDma(Packet &pkt);
|
||||
|
||||
virtual Packet *recvRetry()
|
||||
{ return transmitList.pop_front(); }
|
||||
|
||||
class SendEvent : public Event
|
||||
{
|
||||
PioPort *port;
|
||||
Packet packet;
|
||||
|
||||
SendEvent(PioPort *p, Packet &pkt, Tick t)
|
||||
: Event(&mainEventQueue), packet(pkt)
|
||||
{ schedule(curTick + t); }
|
||||
|
||||
virtual void process();
|
||||
|
||||
virtual const char *description()
|
||||
{ return "Future scheduled sendTiming event"; }
|
||||
|
||||
friend class PioPort;
|
||||
}
|
||||
public:
|
||||
DmaPort(DmaDevice *dev)
|
||||
: device(dev)
|
||||
{ }
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
class PioDevice : public SimObject
|
||||
{
|
||||
protected:
|
||||
|
||||
Platform *platform;
|
||||
BaseInterface *pioInterface;
|
||||
Tick pioLatency;
|
||||
|
||||
PioPort *pioPort;
|
||||
|
||||
virtual void addressRanges(std::list<Range<Addr> > &range_list,
|
||||
bool &owner) = 0;
|
||||
|
||||
virtual read(Packet &pkt) = 0;
|
||||
|
||||
virtual write(Packet &pkt) = 0;
|
||||
|
||||
Tick recvAtomic(Packet &pkt)
|
||||
{ return pkt->cmd == Read ? this->read(pkt) : this->write(pkt); }
|
||||
|
||||
public:
|
||||
PioDevice(const std::string &name, Platform *p);
|
||||
|
||||
virtual ~PioDevice();
|
||||
|
||||
virtual Port *getPort(std::string if_name)
|
||||
{
|
||||
if (if_name == "pio")
|
||||
return pioPort;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
class DmaDevice : public PioDevice
|
||||
{
|
||||
protected:
|
||||
DMAInterface<Bus> *dmaInterface;
|
||||
DmaPort *dmaPort;
|
||||
|
||||
public:
|
||||
DmaDevice(const std::string &name, Platform *p);
|
||||
virtual ~DmaDevice();
|
||||
|
||||
virtual Port *getPort(std::string if_name)
|
||||
{
|
||||
if (if_name == "pio")
|
||||
return pioPort;
|
||||
else if (if_name = "dma")
|
||||
return dmaPort;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // __DEV_IO_DEVICE_HH__
|
||||
|
|
|
@ -41,6 +41,7 @@ class PciConfigAll;
|
|||
class IntrControl;
|
||||
class SimConsole;
|
||||
class Uart;
|
||||
class System;
|
||||
|
||||
class Platform : public SimObject
|
||||
{
|
||||
|
@ -54,6 +55,9 @@ class Platform : public SimObject
|
|||
/** Pointer to the UART, set by the uart */
|
||||
Uart *uart;
|
||||
|
||||
/** Pointer to the system for info about the memory system. */
|
||||
System *system;
|
||||
|
||||
public:
|
||||
Platform(const std::string &name, IntrControl *intctrl, PciConfigAll *pci);
|
||||
virtual ~Platform();
|
||||
|
|
12
mem/bus.hh
12
mem/bus.hh
|
@ -45,15 +45,15 @@ class Bus : public MemObject
|
|||
{
|
||||
/** Function called by the port when the bus is recieving a Timing
|
||||
transaction.*/
|
||||
SendResult recvTiming(Packet &pkt, int id);
|
||||
bool recvTiming(Packet &pkt, int id);
|
||||
|
||||
/** Function called by the port when the bus is recieving a Atomic
|
||||
transaction.*/
|
||||
SendResult recvAtomic(Packet &pkt, int id);
|
||||
Tick recvAtomic(Packet &pkt, int id);
|
||||
|
||||
/** Function called by the port when the bus is recieving a Functional
|
||||
transaction.*/
|
||||
SendResult recvFunctional(Packet &pkt, int id);
|
||||
void recvFunctional(Packet &pkt, int id);
|
||||
|
||||
/** Function called by the port when the bus is recieving a status change.*/
|
||||
void recvStatusChange(Port::Status status, int id);
|
||||
|
@ -79,17 +79,17 @@ class Bus : public MemObject
|
|||
|
||||
/** When reciving a timing request from the peer port (at id),
|
||||
pass it to the bus. */
|
||||
virtual SendResult recvTiming(Packet &pkt)
|
||||
virtual bool recvTiming(Packet &pkt)
|
||||
{ return bus->recvTiming(pkt, id); }
|
||||
|
||||
/** When reciving a Atomic requestfrom the peer port (at id),
|
||||
pass it to the bus. */
|
||||
virtual SendResult recvAtomic(Packet &pkt)
|
||||
virtual Tick recvAtomic(Packet &pkt)
|
||||
{ return bus->recvAtomic(pkt, id); }
|
||||
|
||||
/** When reciving a Functional requestfrom the peer port (at id),
|
||||
pass it to the bus. */
|
||||
virtual SendResult recvFunctional(Packet &pkt)
|
||||
virtual void recvFunctional(Packet &pkt)
|
||||
{ return bus->recvFunctional(pkt, id); }
|
||||
|
||||
/** When reciving a status changefrom the peer port (at id),
|
||||
|
|
32
mem/port.hh
32
mem/port.hh
|
@ -87,25 +87,13 @@ class Port
|
|||
protected:
|
||||
|
||||
/** Called to recive a timing call from the peer port. */
|
||||
virtual SendResult recvTiming(Packet &pkt) = 0;
|
||||
|
||||
/** Virtual function that can be used to handle scheduling an event
|
||||
to send the recvTiming at a given time. This is for direct
|
||||
connection without a interconnect. The bus will override
|
||||
this in it's port class because the bus does the timing.
|
||||
This is used to insert timing when an interconnect doesn't
|
||||
have it's own event queue.
|
||||
*/
|
||||
virtual SendResult recvTiming(Packet &pkt, Tick t)
|
||||
{
|
||||
// schedule event to call recvTiming(pkt) @ tick t
|
||||
}
|
||||
virtual bool recvTiming(Packet &pkt) = 0;
|
||||
|
||||
/** Called to recive a atomic call from the peer port. */
|
||||
virtual SendResult recvAtomic(Packet &pkt) = 0;
|
||||
virtual Tick recvAtomic(Packet &pkt) = 0;
|
||||
|
||||
/** Called to recive a functional call from the peer port. */
|
||||
virtual SendResult recvFunctional(Packet &pkt) = 0;
|
||||
virtual void recvFunctional(Packet &pkt) = 0;
|
||||
|
||||
/** Called to recieve a status change from the peer port. */
|
||||
virtual void recvStatusChange(Status status) = 0;
|
||||
|
@ -146,21 +134,13 @@ class Port
|
|||
case a cache has a higher priority request come in while waiting for
|
||||
the bus to arbitrate.
|
||||
*/
|
||||
SendResult sendTiming(Packet &pkt) { return peer->recvTiming(pkt); }
|
||||
|
||||
/** This function is identical to the sendTiming function, accept it
|
||||
provides a time when the recvTiming should be called. The
|
||||
peer->recvTimimng will schedule the event, if it's device handles the
|
||||
timing (bus) it will be overloaded by the bus type port to handle it
|
||||
properly.
|
||||
*/
|
||||
SendResult sendTiming(Packet &pkt, Tick t) { return peer->recvTiming(pkt, t); }
|
||||
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.
|
||||
*/
|
||||
SendResult sendAtomic(Packet &pkt)
|
||||
Tick sendAtomic(Packet &pkt)
|
||||
{ return peer->recvAtomic(pkt); }
|
||||
|
||||
/** Function called by the associated device to send a functional access,
|
||||
|
@ -168,7 +148,7 @@ class Port
|
|||
memory system, without affecting the current state of any block
|
||||
or moving the block.
|
||||
*/
|
||||
SendResult sendFunctional(Packet &pkt)
|
||||
void sendFunctional(Packet &pkt)
|
||||
{ return peer->recvFunctional(pkt); }
|
||||
|
||||
/** Called by the associated device to send a status change to the device
|
||||
|
|
|
@ -37,34 +37,41 @@
|
|||
class Request
|
||||
{
|
||||
|
||||
/** The virtual address of the request. */
|
||||
Addr vaddr;
|
||||
/** The physical address of the request. */
|
||||
Addr paddr;
|
||||
|
||||
/** whether this req came from the CPU or not */
|
||||
bool nic_req;
|
||||
|
||||
/** The address space ID. */
|
||||
int asid;
|
||||
/** The related execution context. */
|
||||
ExecContext *xc;
|
||||
/** whether this req came from the CPU or not **DO we need this??***/
|
||||
bool nicReq;
|
||||
|
||||
/** The size of the request. */
|
||||
int size;
|
||||
|
||||
/** The return value of store conditional. */
|
||||
uint64_t result;
|
||||
|
||||
/** The cpu number for statistics. */
|
||||
int cpu_num;
|
||||
/** The requesting thread id. */
|
||||
int thread_num;
|
||||
/** The time this request was started. Used to calculate latencies. */
|
||||
Tick time;
|
||||
|
||||
/** Destination address if this is a block copy. */
|
||||
Addr copyDest;
|
||||
};
|
||||
|
||||
class CpuRequest : public Request
|
||||
{
|
||||
/** The virtual address of the request. */
|
||||
Addr vaddr;
|
||||
|
||||
/** The address space ID. */
|
||||
int asid;
|
||||
|
||||
/** The return value of store conditional. */
|
||||
uint64_t scResult;
|
||||
|
||||
/** The cpu number for statistics. */
|
||||
int cpuNum;
|
||||
|
||||
/** The requesting thread id. */
|
||||
int threadNum;
|
||||
|
||||
/** program counter of initiating access; for tracing/debugging */
|
||||
Addr pc;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __MEM_REQUEST_HH__
|
||||
|
|
Loading…
Reference in a new issue