MEM: Separate queries for snooping and address ranges
This patch simplifies the address-range determination mechanism and also unifies the naming across ports and devices. It further splits the queries for determining if a port is snooping and what address ranges it responds to (aiming towards a separation of cache-maintenance ports and pure memory-mapped ports). Default behaviours are such that most ports do not have to define isSnooping, and master ports need not implement getAddrRanges.
This commit is contained in:
parent
142380a373
commit
07cf9d914b
54 changed files with 345 additions and 416 deletions
|
@ -353,25 +353,27 @@ X86ISA::Interrupts::recvResponse(PacketPtr pkt)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
X86ISA::Interrupts::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
X86ISA::Interrupts::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
AddrRangeList ranges;
|
||||
Range<Addr> range = RangeEx(x86LocalAPICAddress(initialApicId, 0),
|
||||
x86LocalAPICAddress(initialApicId, 0) +
|
||||
PageBytes);
|
||||
range_list.push_back(range);
|
||||
ranges.push_back(range);
|
||||
pioAddr = range.start;
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
X86ISA::Interrupts::getIntAddrRange(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
X86ISA::Interrupts::getIntAddrRange()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
|
||||
x86InterruptAddress(initialApicId, 0) +
|
||||
PhysAddrAPICRangeSize));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
|
||||
x86InterruptAddress(initialApicId, 0) +
|
||||
PhysAddrAPICRangeSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -217,8 +217,8 @@ class Interrupts : public BasicPioDevice, IntDev
|
|||
return entry.periodic;
|
||||
}
|
||||
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
void getIntAddrRange(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
AddrRangeList getIntAddrRange();
|
||||
|
||||
Port *getPort(const std::string &if_name, int idx = -1)
|
||||
{
|
||||
|
|
|
@ -154,17 +154,8 @@ Walker::WalkerPort::recvFunctional(PacketPtr pkt)
|
|||
}
|
||||
|
||||
void
|
||||
Walker::WalkerPort::recvStatusChange(Status status)
|
||||
Walker::WalkerPort::recvRangeChange()
|
||||
{
|
||||
if (status == RangeChange) {
|
||||
if (!snoopRangeSent) {
|
||||
snoopRangeSent = true;
|
||||
sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
panic("Unexpected recvStatusChange.\n");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -63,26 +63,18 @@ namespace X86ISA
|
|||
{
|
||||
public:
|
||||
WalkerPort(const std::string &_name, Walker * _walker) :
|
||||
Port(_name, _walker), walker(_walker),
|
||||
snoopRangeSent(false)
|
||||
Port(_name, _walker), walker(_walker)
|
||||
{}
|
||||
|
||||
protected:
|
||||
Walker * walker;
|
||||
|
||||
bool snoopRangeSent;
|
||||
|
||||
bool recvTiming(PacketPtr pkt);
|
||||
Tick recvAtomic(PacketPtr pkt);
|
||||
void recvFunctional(PacketPtr pkt);
|
||||
void recvStatusChange(Status status);
|
||||
void recvRangeChange();
|
||||
void recvRetry();
|
||||
void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
{
|
||||
resp.clear();
|
||||
snoop = true;
|
||||
}
|
||||
bool isSnooping() { return true; }
|
||||
};
|
||||
|
||||
friend class WalkerPort;
|
||||
|
|
|
@ -527,23 +527,6 @@ BaseCPU::CpuPort::recvFunctional(PacketPtr pkt)
|
|||
}
|
||||
|
||||
void
|
||||
BaseCPU::CpuPort::recvStatusChange(Status status)
|
||||
BaseCPU::CpuPort::recvRangeChange()
|
||||
{
|
||||
if (status == RangeChange) {
|
||||
if (!snoopRangeSent) {
|
||||
snoopRangeSent = true;
|
||||
sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
panic("BaseCPU doesn't expect recvStatusChange callback!");
|
||||
}
|
||||
|
||||
void
|
||||
BaseCPU::CpuPort::getDeviceAddressRanges(AddrRangeList& resp,
|
||||
bool& snoop)
|
||||
{
|
||||
resp.clear();
|
||||
snoop = false;
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ class BaseCPU : public MemObject
|
|||
* @param _name structural owner of this port
|
||||
*/
|
||||
CpuPort(const std::string& _name, MemObject* _owner) :
|
||||
Port(_name, _owner), snoopRangeSent(false)
|
||||
Port(_name, _owner)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
|
@ -139,22 +139,7 @@ class BaseCPU : public MemObject
|
|||
|
||||
void recvFunctional(PacketPtr pkt);
|
||||
|
||||
void recvStatusChange(Status status);
|
||||
|
||||
/**
|
||||
* Add CPU ports are master ports and do not respond to any
|
||||
* address ranges. Note that the LSQ snoops for specific ISAs
|
||||
* and thus has to override this method.
|
||||
*
|
||||
* @param resp list of ranges this port responds to
|
||||
* @param snoop indicating if the port snoops or not
|
||||
*/
|
||||
virtual void getDeviceAddressRanges(AddrRangeList& resp,
|
||||
bool& snoop);
|
||||
|
||||
private:
|
||||
|
||||
bool snoopRangeSent;
|
||||
void recvRangeChange();
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -82,17 +82,8 @@ CacheUnit::CachePort::recvFunctional(PacketPtr pkt)
|
|||
}
|
||||
|
||||
void
|
||||
CacheUnit::CachePort::recvStatusChange(Status status)
|
||||
CacheUnit::CachePort::recvRangeChange()
|
||||
{
|
||||
if (status == RangeChange) {
|
||||
if (!snoopRangeSent) {
|
||||
snoopRangeSent = true;
|
||||
sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
panic("CacheUnit::CachePort doesn't expect recvStatusChange callback!");
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -90,11 +90,9 @@ class CacheUnit : public Resource
|
|||
CachePort(CacheUnit *_cachePortUnit)
|
||||
: Port(_cachePortUnit->name() + "-cache-port",
|
||||
(MemObject*)_cachePortUnit->cpu),
|
||||
cachePortUnit(_cachePortUnit), snoopRangeSent(false)
|
||||
cachePortUnit(_cachePortUnit)
|
||||
{ }
|
||||
|
||||
bool snoopRangeSent;
|
||||
|
||||
protected:
|
||||
/** Atomic version of receive. Panics. */
|
||||
Tick recvAtomic(PacketPtr pkt);
|
||||
|
@ -102,13 +100,8 @@ class CacheUnit : public Resource
|
|||
/** Functional version of receive.*/
|
||||
void recvFunctional(PacketPtr pkt);
|
||||
|
||||
/** Receives status change. Other than range changing, panics. */
|
||||
void recvStatusChange(Status status);
|
||||
|
||||
/** Returns the address ranges of this device. */
|
||||
void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
{ resp.clear(); snoop = true; }
|
||||
/** Receives range changes. */
|
||||
void recvRangeChange();
|
||||
|
||||
/** Timing version of receive */
|
||||
bool recvTiming(PacketPtr pkt);
|
||||
|
|
|
@ -186,12 +186,10 @@ class FullO3CPU : public BaseO3CPU
|
|||
* As this CPU requires snooping to maintain the load store queue
|
||||
* change the behaviour from the base CPU port.
|
||||
*
|
||||
* @param resp list of ranges this port responds to
|
||||
* @param snoop indicating if the port snoops or not
|
||||
* @return true since we have to snoop
|
||||
*/
|
||||
virtual void getDeviceAddressRanges(AddrRangeList& resp,
|
||||
bool& snoop)
|
||||
{ resp.clear(); snoop = true; }
|
||||
virtual bool isSnooping()
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
class TickEvent : public Event
|
||||
|
|
|
@ -87,13 +87,8 @@ class FrontEnd
|
|||
/** Functional version of receive. Panics. */
|
||||
virtual void recvFunctional(PacketPtr pkt);
|
||||
|
||||
/** Receives status change. Other than range changing, panics. */
|
||||
virtual void recvStatusChange(Status status);
|
||||
|
||||
/** Returns the address ranges of this device. */
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
{ resp.clear(); snoop = true; }
|
||||
/** Receives range change. */
|
||||
virtual void recvRangeChange();
|
||||
|
||||
/** Timing version of receive. Handles setting fetch to the
|
||||
* proper status to start fetching. */
|
||||
|
|
|
@ -64,12 +64,8 @@ FrontEnd<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
|
|||
|
||||
template<class Impl>
|
||||
void
|
||||
FrontEnd<Impl>::IcachePort::recvStatusChange(Status status)
|
||||
FrontEnd<Impl>::IcachePort::recvRangeChange()
|
||||
{
|
||||
if (status == RangeChange)
|
||||
return;
|
||||
|
||||
panic("FrontEnd doesn't expect recvStatusChange callback!");
|
||||
}
|
||||
|
||||
template<class Impl>
|
||||
|
|
|
@ -256,11 +256,13 @@ class OzoneLWLSQ {
|
|||
|
||||
virtual void recvFunctional(PacketPtr pkt);
|
||||
|
||||
virtual void recvStatusChange(Status status);
|
||||
virtual void recvRangeChange();
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
{ resp.clear(); snoop = true; }
|
||||
/**
|
||||
* Is a snooper due to LSQ maintenance
|
||||
*/
|
||||
virtual bool isSnooping()
|
||||
{ return true; }
|
||||
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
|
||||
|
|
|
@ -77,12 +77,8 @@ OzoneLWLSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
|
|||
|
||||
template <class Impl>
|
||||
void
|
||||
OzoneLWLSQ<Impl>::DcachePort::recvStatusChange(Status status)
|
||||
OzoneLWLSQ<Impl>::DcachePort::recvRangeChange()
|
||||
{
|
||||
if (status == RangeChange)
|
||||
return;
|
||||
|
||||
panic("O3CPU doesn't expect recvStatusChange callback!");
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
|
|
|
@ -96,9 +96,7 @@ AtomicSimpleCPU::init()
|
|||
tcBase()->initMemProxies(tcBase());
|
||||
#endif
|
||||
if (hasPhysMemPort) {
|
||||
bool snoop = false;
|
||||
AddrRangeList pmAddrList;
|
||||
physmemPort.getPeerAddressRanges(pmAddrList, snoop);
|
||||
AddrRangeList pmAddrList = physmemPort.getPeer()->getAddrRanges();
|
||||
physMemAddr = *pmAddrList.begin();
|
||||
}
|
||||
// Atomic doesn't do MT right now, so contextId == threadId
|
||||
|
|
|
@ -84,17 +84,8 @@ MemTest::CpuPort::recvFunctional(PacketPtr pkt)
|
|||
}
|
||||
|
||||
void
|
||||
MemTest::CpuPort::recvStatusChange(Status status)
|
||||
MemTest::CpuPort::recvRangeChange()
|
||||
{
|
||||
if (status == RangeChange) {
|
||||
if (!snoopRangeSent) {
|
||||
snoopRangeSent = true;
|
||||
sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
panic("MemTest doesn't expect recvStatusChange callback!");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -149,9 +140,6 @@ MemTest::MemTest(const Params *p)
|
|||
atomic(p->atomic),
|
||||
suppress_func_warnings(p->suppress_func_warnings)
|
||||
{
|
||||
cachePort.snoopRangeSent = false;
|
||||
funcPort.snoopRangeSent = true;
|
||||
|
||||
id = TESTER_ALLOCATOR++;
|
||||
|
||||
// Needs to be masked off once we know the block size.
|
||||
|
|
|
@ -93,8 +93,6 @@ class MemTest : public MemObject
|
|||
: Port(_name, _memtest), memtest(_memtest)
|
||||
{ }
|
||||
|
||||
bool snoopRangeSent;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
|
@ -103,20 +101,14 @@ class MemTest : public MemObject
|
|||
|
||||
virtual void recvFunctional(PacketPtr pkt);
|
||||
|
||||
virtual void recvStatusChange(Status status);
|
||||
virtual void recvRangeChange();
|
||||
|
||||
virtual void recvRetry();
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
{ resp.clear(); snoop = false; }
|
||||
};
|
||||
|
||||
CpuPort cachePort;
|
||||
CpuPort funcPort;
|
||||
|
||||
bool snoopRangeSent;
|
||||
|
||||
class MemTestSenderState : public Packet::SenderState, public FastAlloc
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -81,17 +81,8 @@ NetworkTest::CpuPort::recvFunctional(PacketPtr pkt)
|
|||
}
|
||||
|
||||
void
|
||||
NetworkTest::CpuPort::recvStatusChange(Status status)
|
||||
NetworkTest::CpuPort::recvRangeChange()
|
||||
{
|
||||
if (status == RangeChange) {
|
||||
if (!snoopRangeSent) {
|
||||
snoopRangeSent = true;
|
||||
sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
panic("NetworkTest doesn't expect recvStatusChange callback!");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -124,8 +115,6 @@ NetworkTest::NetworkTest(const Params *p)
|
|||
injRate(p->inj_rate),
|
||||
precision(p->precision)
|
||||
{
|
||||
cachePort.snoopRangeSent = false;
|
||||
|
||||
// set up counters
|
||||
noResponseCycles = 0;
|
||||
schedule(tickEvent, 0);
|
||||
|
|
|
@ -89,8 +89,6 @@ class NetworkTest : public MemObject
|
|||
: Port(_name, _networktest), networktest(_networktest)
|
||||
{ }
|
||||
|
||||
bool snoopRangeSent;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
|
@ -99,19 +97,13 @@ class NetworkTest : public MemObject
|
|||
|
||||
virtual void recvFunctional(PacketPtr pkt);
|
||||
|
||||
virtual void recvStatusChange(Status status);
|
||||
virtual void recvRangeChange();
|
||||
|
||||
virtual void recvRetry();
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
{ resp.clear(); snoop = false; }
|
||||
};
|
||||
|
||||
CpuPort cachePort;
|
||||
|
||||
bool snoopRangeSent;
|
||||
|
||||
class NetworkTestSenderState : public Packet::SenderState, public FastAlloc
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -703,12 +703,13 @@ Gic::postInt(uint32_t cpu, Tick when)
|
|||
eventq->schedule(postIntEvent[cpu], when);
|
||||
}
|
||||
|
||||
void
|
||||
Gic::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
Gic::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(distAddr, DIST_SIZE));
|
||||
range_list.push_back(RangeSize(cpuAddr, CPU_SIZE));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(distAddr, DIST_SIZE));
|
||||
ranges.push_back(RangeSize(cpuAddr, CPU_SIZE));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ class Gic : public PioDevice
|
|||
/** Return the address ranges used by the Gic
|
||||
* This is the distributor address + all cpu addresses
|
||||
*/
|
||||
virtual void addressRanges(AddrRangeList &range_list);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
/** A PIO read to the device, immediately split up into
|
||||
* readDistributor() or readCpu()
|
||||
|
|
|
@ -735,11 +735,12 @@ Pl111::generateInterrupt()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::addressRanges(AddrRangeList& range_list)
|
||||
AddrRangeList
|
||||
Pl111::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(pioAddr, pioSize));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(pioAddr, pioSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
Pl111 *
|
||||
|
|
|
@ -325,10 +325,12 @@ class Pl111: public AmbaDmaDevice
|
|||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
/** return the address ranges that this device responds to.
|
||||
* @param range_list range list to populate with ranges
|
||||
/**
|
||||
* Determine the address ranges that this device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -85,7 +85,6 @@ class CopyEngine : public PciDev
|
|||
void init();
|
||||
|
||||
std::string name() { assert(ce); return ce->name() + csprintf("-chan%d", channelId); }
|
||||
virtual void addressRanges(AddrRangeList &range_list) { range_list.clear(); }
|
||||
virtual Tick read(PacketPtr pkt)
|
||||
{ panic("CopyEngineChannel has no I/O access\n");}
|
||||
virtual Tick write(PacketPtr pkt)
|
||||
|
|
|
@ -47,13 +47,10 @@ PioPort::recvAtomic(PacketPtr pkt)
|
|||
return pkt->isRead() ? device->read(pkt) : device->write(pkt);
|
||||
}
|
||||
|
||||
void
|
||||
PioPort::getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
|
||||
AddrRangeList
|
||||
PioPort::getAddrRanges()
|
||||
{
|
||||
snoop = false;
|
||||
device->addressRanges(resp);
|
||||
for (AddrRangeIter i = resp.begin(); i != resp.end(); i++)
|
||||
DPRINTF(BusAddrRanges, "Adding Range %#x-%#x\n", i->start, i->end);
|
||||
return device->getAddrRanges();
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,7 +69,7 @@ PioDevice::init()
|
|||
{
|
||||
if (!pioPort)
|
||||
panic("Pio port of %s not connected to anything!", name());
|
||||
pioPort->sendStatusChange(Port::RangeChange);
|
||||
pioPort->sendRangeChange();
|
||||
}
|
||||
|
||||
Port *
|
||||
|
@ -105,13 +102,14 @@ BasicPioDevice::BasicPioDevice(const Params *p)
|
|||
pioDelay(p->pio_latency)
|
||||
{}
|
||||
|
||||
void
|
||||
BasicPioDevice::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
BasicPioDevice::getAddrRanges()
|
||||
{
|
||||
assert(pioSize != 0);
|
||||
range_list.clear();
|
||||
AddrRangeList ranges;
|
||||
DPRINTF(BusAddrRanges, "registering range: %#x-%#x\n", pioAddr, pioSize);
|
||||
range_list.push_back(RangeSize(pioAddr, pioSize));
|
||||
ranges.push_back(RangeSize(pioAddr, pioSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
@ -121,7 +119,7 @@ DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff,
|
|||
pendingCount(0), actionInProgress(0), drainEvent(NULL),
|
||||
backoffTime(0), minBackoffDelay(min_backoff),
|
||||
maxBackoffDelay(max_backoff), inRetry(false), recvSnoops(recv_snoops),
|
||||
snoopRangeSent(false), backoffEvent(this)
|
||||
backoffEvent(this)
|
||||
{ }
|
||||
|
||||
bool
|
||||
|
|
|
@ -51,7 +51,7 @@ class System;
|
|||
* The PioPort class is a programmed i/o port that all devices that are
|
||||
* sensitive to an address range use. The port takes all the memory
|
||||
* access types and roles them into one read() and write() call that the device
|
||||
* must respond to. The device must also provide the addressRanges() function
|
||||
* must respond to. The device must also provide getAddrRanges() function
|
||||
* with which it returns the address ranges it is interested in.
|
||||
*/
|
||||
class PioPort : public SimpleTimingPort
|
||||
|
@ -62,8 +62,7 @@ class PioPort : public SimpleTimingPort
|
|||
|
||||
virtual Tick recvAtomic(PacketPtr pkt);
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
public:
|
||||
|
||||
|
@ -133,9 +132,6 @@ class DmaPort : public Port
|
|||
/** Port accesses a cache which requires snooping */
|
||||
bool recvSnoops;
|
||||
|
||||
/** Records snoop response so we only reply once to a status change */
|
||||
bool snoopRangeSent;
|
||||
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
virtual Tick recvAtomic(PacketPtr pkt)
|
||||
{
|
||||
|
@ -150,25 +146,16 @@ class DmaPort : public Port
|
|||
panic("dma port shouldn't be used for pio access.");
|
||||
}
|
||||
|
||||
virtual void recvStatusChange(Status status)
|
||||
virtual void recvRangeChange()
|
||||
{
|
||||
if (recvSnoops) {
|
||||
if (status == RangeChange) {
|
||||
if (!snoopRangeSent) {
|
||||
snoopRangeSent = true;
|
||||
sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
return;
|
||||
}
|
||||
panic("Unexpected recvStatusChange\n");
|
||||
}
|
||||
// DMA port is a master with a single slave so there is no choice and
|
||||
// thus no need to worry about any address changes
|
||||
}
|
||||
|
||||
virtual void recvRetry() ;
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
{ resp.clear(); snoop = recvSnoops; }
|
||||
virtual bool isSnooping()
|
||||
{ return recvSnoops; }
|
||||
|
||||
void queueDma(PacketPtr pkt, bool front = false);
|
||||
void sendDma();
|
||||
|
@ -192,7 +179,7 @@ class DmaPort : public Port
|
|||
/**
|
||||
* This device is the base class which all devices senstive to an address range
|
||||
* inherit from. There are three pure virtual functions which all devices must
|
||||
* implement addressRanges(), read(), and write(). The magic do choose which
|
||||
* implement getAddrRanges(), read(), and write(). The magic do choose which
|
||||
* mode we are in, etc is handled by the PioPort so the device doesn't have to
|
||||
* bother.
|
||||
*/
|
||||
|
@ -210,7 +197,13 @@ class PioDevice : public MemObject
|
|||
* that it sees. */
|
||||
PioPort *pioPort;
|
||||
|
||||
virtual void addressRanges(AddrRangeList &range_list) = 0;
|
||||
/**
|
||||
* Every PIO device is obliged to provide an implementation that
|
||||
* returns the address ranges the device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
virtual AddrRangeList getAddrRanges() = 0;
|
||||
|
||||
/** Pure virtual function that the device must implement. Called
|
||||
* when a read command is recieved by the port.
|
||||
|
@ -269,10 +262,12 @@ class BasicPioDevice : public PioDevice
|
|||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
/** return the address ranges that this device responds to.
|
||||
* @param range_list range list to populate with ranges
|
||||
/**
|
||||
* Determine the address ranges that this device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -86,11 +86,12 @@ PciConfigAll::write(PacketPtr pkt)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
PciConfigAll::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
PciConfigAll::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(pioAddr, params()->size));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(pioAddr, params()->size));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ class PciConfigAll : public PioDevice
|
|||
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
|
||||
private:
|
||||
Addr pioAddr;
|
||||
|
|
|
@ -72,13 +72,13 @@ PciDev::PciConfigPort::recvAtomic(PacketPtr pkt)
|
|||
return pkt->isRead() ? device->readConfig(pkt) : device->writeConfig(pkt);
|
||||
}
|
||||
|
||||
void
|
||||
PciDev::PciConfigPort::getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
AddrRangeList
|
||||
PciDev::PciConfigPort::getAddrRanges()
|
||||
{
|
||||
snoop = false;;
|
||||
AddrRangeList ranges;
|
||||
if (configAddr != ULL(-1))
|
||||
resp.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1));
|
||||
ranges.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
@ -152,7 +152,7 @@ PciDev::init()
|
|||
{
|
||||
if (!configPort)
|
||||
panic("pci config port not connected to anything!");
|
||||
configPort->sendStatusChange(Port::RangeChange);
|
||||
configPort->sendRangeChange();
|
||||
PioDevice::init();
|
||||
}
|
||||
|
||||
|
@ -207,14 +207,15 @@ PciDev::readConfig(PacketPtr pkt)
|
|||
|
||||
}
|
||||
|
||||
void
|
||||
PciDev::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
PciDev::getAddrRanges()
|
||||
{
|
||||
AddrRangeList ranges;
|
||||
int x = 0;
|
||||
range_list.clear();
|
||||
for (x = 0; x < 6; x++)
|
||||
if (BARAddrs[x] != 0)
|
||||
range_list.push_back(RangeSize(BARAddrs[x],BARSize[x]));
|
||||
ranges.push_back(RangeSize(BARAddrs[x],BARSize[x]));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
Tick
|
||||
|
@ -301,7 +302,7 @@ PciDev::writeConfig(PacketPtr pkt)
|
|||
BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ?
|
||||
platform->calcPciIOAddr(he_new_bar) :
|
||||
platform->calcPciMemAddr(he_new_bar);
|
||||
pioPort->sendStatusChange(Port::RangeChange);
|
||||
pioPort->sendRangeChange();
|
||||
}
|
||||
}
|
||||
config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) |
|
||||
|
@ -354,7 +355,7 @@ PciDev::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
|
||||
UNSERIALIZE_ARRAY(config.data,
|
||||
sizeof(config.data) / sizeof(config.data[0]));
|
||||
pioPort->sendStatusChange(Port::RangeChange);
|
||||
pioPort->sendRangeChange();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -65,8 +65,7 @@ class PciDev : public DmaDevice
|
|||
|
||||
virtual Tick recvAtomic(PacketPtr pkt);
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
Platform *platform;
|
||||
|
||||
|
@ -187,10 +186,12 @@ class PciDev : public DmaDevice
|
|||
interruptLine()
|
||||
{ return letoh(config.interruptLine); }
|
||||
|
||||
/** return the address ranges that this device responds to.
|
||||
* @params range_list range list to populate with ranges
|
||||
/**
|
||||
* Determine the address ranges that this device responds to.
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
|
||||
/**
|
||||
* Constructor for PCI Dev. This function copies data from the
|
||||
|
|
|
@ -1714,7 +1714,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
if (transmitTick)
|
||||
schedule(txEvent, curTick() + transmitTick);
|
||||
|
||||
pioPort->sendStatusChange(Port::RangeChange);
|
||||
pioPort->sendRangeChange();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -325,12 +325,13 @@ Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Iob::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
Iob::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(iobManAddr, iobManSize));
|
||||
range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(iobManAddr, iobManSize));
|
||||
ranges.push_back(RangeSize(iobJBusAddr, iobJBusSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ class Iob : public PioDevice
|
|||
bool receiveJBusInterrupt(int cpu_id, int source, uint64_t d0,
|
||||
uint64_t d1);
|
||||
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
|
|
@ -286,16 +286,14 @@ Uart8250::dataAvailable()
|
|||
|
||||
}
|
||||
|
||||
void
|
||||
Uart8250::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
Uart8250::getAddrRanges()
|
||||
{
|
||||
assert(pioSize != 0);
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(pioAddr, pioSize));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(pioAddr, pioSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Uart8250::serialize(ostream &os)
|
||||
{
|
||||
|
|
|
@ -100,7 +100,7 @@ class Uart8250 : public Uart
|
|||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
virtual void addressRanges(AddrRangeList &range_list);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
/**
|
||||
* Inform the uart that there is data available.
|
||||
|
|
|
@ -43,12 +43,13 @@ const uint8_t CommandAck = 0xfa;
|
|||
const uint8_t CommandNack = 0xfe;
|
||||
const uint8_t BatSuccessful = 0xaa;
|
||||
|
||||
void
|
||||
X86ISA::I8042::addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList
|
||||
X86ISA::I8042::getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(dataPort, 1));
|
||||
range_list.push_back(RangeSize(commandPort, 1));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(dataPort, 1));
|
||||
ranges.push_back(RangeSize(commandPort, 1));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -255,7 +255,7 @@ class I8042 : public BasicPioDevice
|
|||
commandByte.keyboardFullInt = 1;
|
||||
}
|
||||
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
AddrRangeList getAddrRanges();
|
||||
|
||||
Tick read(PacketPtr pkt);
|
||||
|
||||
|
|
|
@ -103,19 +103,21 @@ class I82094AA : public PioDevice, public IntDev
|
|||
Tick read(PacketPtr pkt);
|
||||
Tick write(PacketPtr pkt);
|
||||
|
||||
void addressRanges(AddrRangeList &range_list)
|
||||
AddrRangeList getAddrRanges()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeEx(pioAddr, pioAddr + 4));
|
||||
range_list.push_back(RangeEx(pioAddr + 16, pioAddr + 20));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeEx(pioAddr, pioAddr + 4));
|
||||
ranges.push_back(RangeEx(pioAddr + 16, pioAddr + 20));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
void getIntAddrRange(AddrRangeList &range_list)
|
||||
AddrRangeList getIntAddrRange()
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
|
||||
x86InterruptAddress(initialApicId, 0) +
|
||||
PhysAddrAPICRangeSize));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
|
||||
x86InterruptAddress(initialApicId, 0) +
|
||||
PhysAddrAPICRangeSize));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
void writeReg(uint8_t offset, uint32_t value);
|
||||
|
|
|
@ -54,7 +54,7 @@ X86ISA::IntDev::init()
|
|||
if (!intPort) {
|
||||
panic("Int port not connected to anything!");
|
||||
}
|
||||
intPort->sendStatusChange(Port::RangeChange);
|
||||
intPort->sendRangeChange();
|
||||
}
|
||||
|
||||
X86ISA::IntSourcePin *
|
||||
|
|
|
@ -63,10 +63,9 @@ class IntDev
|
|||
{
|
||||
}
|
||||
|
||||
void getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
|
||||
AddrRangeList getAddrRanges()
|
||||
{
|
||||
snoop = false;
|
||||
device->getIntAddrRange(resp);
|
||||
return device->getIntAddrRange();
|
||||
}
|
||||
|
||||
Tick recvMessage(PacketPtr pkt)
|
||||
|
@ -134,8 +133,8 @@ class IntDev
|
|||
return 0;
|
||||
}
|
||||
|
||||
virtual void
|
||||
getIntAddrRange(AddrRangeList &range_list)
|
||||
virtual AddrRangeList
|
||||
getIntAddrRange()
|
||||
{
|
||||
panic("intAddrRange not implemented.\n");
|
||||
}
|
||||
|
|
|
@ -57,14 +57,12 @@ BadAddrEvent::process(ThreadContext *tc)
|
|||
|
||||
uint64_t a0 = tc->readIntReg(16);
|
||||
|
||||
AddrRangeList resp;
|
||||
bool snoop;
|
||||
AddrRangeIter iter;
|
||||
bool found = false;
|
||||
|
||||
Port* dataPort = tc->getCpuPtr()->getPort("dcache_port");
|
||||
|
||||
dataPort->getPeerAddressRanges(resp, snoop);
|
||||
AddrRangeList resp = dataPort->getPeer()->getAddrRanges();
|
||||
for (iter = resp.begin(); iter != resp.end(); iter++) {
|
||||
if (*iter == (K0Seg2Phys(a0) & PAddrImplMask))
|
||||
found = true;
|
||||
|
|
|
@ -338,21 +338,19 @@ Bridge::BridgePort::recvFunctional(PacketPtr pkt)
|
|||
otherPort->sendFunctional(pkt);
|
||||
}
|
||||
|
||||
/** Function called by the port when the bus is receiving a status change.*/
|
||||
/** Function called by the port when the bridge is receiving a range change.*/
|
||||
void
|
||||
Bridge::BridgePort::recvStatusChange(Port::Status status)
|
||||
Bridge::BridgePort::recvRangeChange()
|
||||
{
|
||||
otherPort->sendStatusChange(status);
|
||||
otherPort->sendRangeChange();
|
||||
}
|
||||
|
||||
void
|
||||
Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
AddrRangeList
|
||||
Bridge::BridgePort::getAddrRanges()
|
||||
{
|
||||
otherPort->getPeerAddressRanges(resp, snoop);
|
||||
FilterRangeList(filterRanges, resp);
|
||||
// we don't allow snooping across bridges
|
||||
snoop = false;
|
||||
AddrRangeList ranges = otherPort->getPeer()->getAddrRanges();
|
||||
FilterRangeList(filterRanges, ranges);
|
||||
return ranges;
|
||||
}
|
||||
|
||||
Bridge *
|
||||
|
|
|
@ -178,14 +178,14 @@ class Bridge : public MemObject
|
|||
pass it to the bridge. */
|
||||
virtual void recvFunctional(PacketPtr pkt);
|
||||
|
||||
/** When receiving a status changefrom the peer port,
|
||||
pass it to the bridge. */
|
||||
virtual void recvStatusChange(Status status);
|
||||
/**
|
||||
* When receiving a range change, pass it through the bridge.
|
||||
*/
|
||||
virtual void recvRangeChange();
|
||||
|
||||
/** When receiving a address range request the peer port,
|
||||
pass it to the bridge. */
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
};
|
||||
|
||||
BridgePort portA, portB;
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2011 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -94,14 +106,21 @@ Bus::getPort(const std::string &if_name, int idx)
|
|||
return bp;
|
||||
}
|
||||
|
||||
/** Get the ranges of anyone other buses that we are connected to. */
|
||||
void
|
||||
Bus::init()
|
||||
{
|
||||
m5::hash_map<short,BusPort*>::iterator intIter;
|
||||
|
||||
for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
|
||||
intIter->second->sendStatusChange(Port::RangeChange);
|
||||
// iterate over our interfaces and determine which of our neighbours
|
||||
// are snooping and add them as snoopers
|
||||
for (intIter = interfaces.begin(); intIter != interfaces.end();
|
||||
intIter++) {
|
||||
if (intIter->second->getPeer()->isSnooping()) {
|
||||
DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n",
|
||||
intIter->second->getPeer()->name());
|
||||
snoopPorts.push_back(intIter->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Bus::BusFreeEvent::BusFreeEvent(Bus *_bus)
|
||||
|
@ -468,20 +487,16 @@ Bus::recvFunctional(PacketPtr pkt)
|
|||
}
|
||||
}
|
||||
|
||||
/** Function called by the port when the bus is receiving a status change.*/
|
||||
/** Function called by the port when the bus is receiving a range change.*/
|
||||
void
|
||||
Bus::recvStatusChange(Port::Status status, int id)
|
||||
Bus::recvRangeChange(int id)
|
||||
{
|
||||
AddrRangeList ranges;
|
||||
bool snoops;
|
||||
AddrRangeIter iter;
|
||||
|
||||
if (inRecvStatusChange.count(id))
|
||||
if (inRecvRangeChange.count(id))
|
||||
return;
|
||||
inRecvStatusChange.insert(id);
|
||||
|
||||
assert(status == Port::RangeChange &&
|
||||
"The other statuses need to be implemented.");
|
||||
inRecvRangeChange.insert(id);
|
||||
|
||||
DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
|
||||
|
||||
|
@ -490,8 +505,7 @@ Bus::recvStatusChange(Port::Status status, int id)
|
|||
defaultRange.clear();
|
||||
// Only try to update these ranges if the user set a default responder.
|
||||
if (useDefaultRange) {
|
||||
defaultPort->getPeerAddressRanges(ranges, snoops);
|
||||
assert(snoops == false);
|
||||
AddrRangeList ranges = defaultPort->getPeer()->getAddrRanges();
|
||||
for(iter = ranges.begin(); iter != ranges.end(); iter++) {
|
||||
defaultRange.push_back(*iter);
|
||||
DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n",
|
||||
|
@ -512,20 +526,7 @@ Bus::recvStatusChange(Port::Status status, int id)
|
|||
portIter++;
|
||||
}
|
||||
|
||||
for (SnoopIter s_iter = snoopPorts.begin();
|
||||
s_iter != snoopPorts.end(); ) {
|
||||
if ((*s_iter)->getId() == id)
|
||||
s_iter = snoopPorts.erase(s_iter);
|
||||
else
|
||||
s_iter++;
|
||||
}
|
||||
|
||||
port->getPeerAddressRanges(ranges, snoops);
|
||||
|
||||
if (snoops) {
|
||||
DPRINTF(BusAddrRanges, "Adding id %d to snoop list\n", id);
|
||||
snoopPorts.push_back(port);
|
||||
}
|
||||
ranges = port->getPeer()->getAddrRanges();
|
||||
|
||||
for (iter = ranges.begin(); iter != ranges.end(); iter++) {
|
||||
DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n",
|
||||
|
@ -546,24 +547,23 @@ Bus::recvStatusChange(Port::Status status, int id)
|
|||
|
||||
for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
|
||||
if (intIter->first != id && intIter->first != funcPortId)
|
||||
intIter->second->sendStatusChange(Port::RangeChange);
|
||||
intIter->second->sendRangeChange();
|
||||
|
||||
if (id != defaultId && defaultPort)
|
||||
defaultPort->sendStatusChange(Port::RangeChange);
|
||||
inRecvStatusChange.erase(id);
|
||||
defaultPort->sendRangeChange();
|
||||
inRecvRangeChange.erase(id);
|
||||
}
|
||||
|
||||
void
|
||||
Bus::addressRanges(AddrRangeList &resp, bool &snoop, int id)
|
||||
AddrRangeList
|
||||
Bus::getAddrRanges(int id)
|
||||
{
|
||||
resp.clear();
|
||||
snoop = false;
|
||||
AddrRangeList ranges;
|
||||
|
||||
DPRINTF(BusAddrRanges, "received address range request, returning:\n");
|
||||
|
||||
for (AddrRangeIter dflt_iter = defaultRange.begin();
|
||||
dflt_iter != defaultRange.end(); dflt_iter++) {
|
||||
resp.push_back(*dflt_iter);
|
||||
ranges.push_back(*dflt_iter);
|
||||
DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start,
|
||||
dflt_iter->end);
|
||||
}
|
||||
|
@ -586,12 +586,21 @@ Bus::addressRanges(AddrRangeList &resp, bool &snoop, int id)
|
|||
}
|
||||
}
|
||||
if (portIter->second != id && !subset) {
|
||||
resp.push_back(portIter->first);
|
||||
ranges.push_back(portIter->first);
|
||||
DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n",
|
||||
portIter->first.start, portIter->first.end);
|
||||
}
|
||||
}
|
||||
|
||||
return ranges;
|
||||
}
|
||||
|
||||
bool
|
||||
Bus::isSnooping(int id)
|
||||
{
|
||||
// in essence, answer the question if there are other snooping
|
||||
// ports rather than the port that is asking
|
||||
bool snoop = false;
|
||||
for (SnoopIter s_iter = snoopPorts.begin(); s_iter != snoopPorts.end();
|
||||
s_iter++) {
|
||||
if ((*s_iter)->getId() != id) {
|
||||
|
@ -599,6 +608,7 @@ Bus::addressRanges(AddrRangeList &resp, bool &snoop, int id)
|
|||
break;
|
||||
}
|
||||
}
|
||||
return snoop;
|
||||
}
|
||||
|
||||
unsigned
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2011 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -81,6 +93,15 @@ class Bus : public MemObject
|
|||
|
||||
int getId() { return id; }
|
||||
|
||||
/**
|
||||
* Determine if this port should be considered a snooper. This
|
||||
* is determined by the bus.
|
||||
*
|
||||
* @return a boolean that is true if this port is snooping
|
||||
*/
|
||||
virtual bool isSnooping()
|
||||
{ return bus->isSnooping(id); }
|
||||
|
||||
protected:
|
||||
|
||||
/** When reciving a timing request from the peer port (at id),
|
||||
|
@ -98,10 +119,10 @@ class Bus : public MemObject
|
|||
virtual void recvFunctional(PacketPtr pkt)
|
||||
{ pkt->setSrc(id); bus->recvFunctional(pkt); }
|
||||
|
||||
/** When reciving a status changefrom the peer port (at id),
|
||||
/** When reciving a range change from the peer port (at id),
|
||||
pass it to the bus. */
|
||||
virtual void recvStatusChange(Status status)
|
||||
{ bus->recvStatusChange(status, id); }
|
||||
virtual void recvRangeChange()
|
||||
{ bus->recvRangeChange(id); }
|
||||
|
||||
/** When reciving a retry from the peer port (at id),
|
||||
pass it to the bus. */
|
||||
|
@ -112,9 +133,8 @@ class Bus : public MemObject
|
|||
// downstream from this bus, yes? That is, the union of all
|
||||
// the 'owned' address ranges of all the other interfaces on
|
||||
// this bus...
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
{ bus->addressRanges(resp, snoop, id); }
|
||||
virtual AddrRangeList getAddrRanges()
|
||||
{ return bus->getAddrRanges(id); }
|
||||
|
||||
// Ask the bus to ask everyone on the bus what their block size is and
|
||||
// take the max of it. This might need to be changed a bit if we ever
|
||||
|
@ -174,8 +194,8 @@ class Bus : public MemObject
|
|||
* requests. */
|
||||
void recvRetry(int id);
|
||||
|
||||
/** Function called by the port when the bus is recieving a status change.*/
|
||||
void recvStatusChange(Port::Status status, int id);
|
||||
/** Function called by the port when the bus is recieving a range change.*/
|
||||
void recvRangeChange(int id);
|
||||
|
||||
/** Find which port connected to this bus (if any) should be given a packet
|
||||
* with this address.
|
||||
|
@ -238,12 +258,23 @@ class Bus : public MemObject
|
|||
portCache[0].valid = false;
|
||||
}
|
||||
|
||||
/** Process address range request.
|
||||
* @param resp addresses that we can respond to
|
||||
* @param snoop addresses that we would like to snoop
|
||||
* @param id ide of the busport that made the request.
|
||||
/**
|
||||
* Return the address ranges this port is responsible for.
|
||||
*
|
||||
* @param id id of the bus port that made the request
|
||||
*
|
||||
* @return a list of non-overlapping address ranges
|
||||
*/
|
||||
void addressRanges(AddrRangeList &resp, bool &snoop, int id);
|
||||
AddrRangeList getAddrRanges(int id);
|
||||
|
||||
/**
|
||||
* Determine if the bus port is snooping or not.
|
||||
*
|
||||
* @param id id of the bus port that made the request
|
||||
*
|
||||
* @return a boolean indicating if this port is snooping or not
|
||||
*/
|
||||
bool isSnooping(int id);
|
||||
|
||||
/** Calculate the timing parameters for the packet. Updates the
|
||||
* firstWordTime and finishTime fields of the packet object.
|
||||
|
@ -264,7 +295,7 @@ class Bus : public MemObject
|
|||
BusFreeEvent busIdle;
|
||||
|
||||
bool inRetry;
|
||||
std::set<int> inRecvStatusChange;
|
||||
std::set<int> inRecvRangeChange;
|
||||
|
||||
/** max number of bus ids we've handed out so far */
|
||||
short maxId;
|
||||
|
|
8
src/mem/cache/base.cc
vendored
8
src/mem/cache/base.cc
vendored
|
@ -70,11 +70,9 @@ BaseCache::BaseCache(const Params *p)
|
|||
}
|
||||
|
||||
void
|
||||
BaseCache::CachePort::recvStatusChange(Port::Status status)
|
||||
BaseCache::CachePort::recvRangeChange() const
|
||||
{
|
||||
if (status == Port::RangeChange) {
|
||||
otherPort->sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
otherPort->sendRangeChange();
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,7 +134,7 @@ BaseCache::init()
|
|||
{
|
||||
if (!cpuSidePort || !memSidePort)
|
||||
panic("Cache not hooked up on both sides\n");
|
||||
cpuSidePort->sendStatusChange(Port::RangeChange);
|
||||
cpuSidePort->sendRangeChange();
|
||||
}
|
||||
|
||||
|
||||
|
|
2
src/mem/cache/base.hh
vendored
2
src/mem/cache/base.hh
vendored
|
@ -105,7 +105,7 @@ class BaseCache : public MemObject
|
|||
CachePort(const std::string &_name, BaseCache *_cache,
|
||||
const std::string &_label);
|
||||
|
||||
virtual void recvStatusChange(Status status);
|
||||
virtual void recvRangeChange() const;
|
||||
|
||||
virtual unsigned deviceBlockSize() const;
|
||||
|
||||
|
|
6
src/mem/cache/cache.hh
vendored
6
src/mem/cache/cache.hh
vendored
|
@ -90,8 +90,7 @@ class Cache : public BaseCache
|
|||
return static_cast<Cache<TagStore> *>(cache);
|
||||
}
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
|
||||
|
@ -118,8 +117,7 @@ class Cache : public BaseCache
|
|||
|
||||
void processSendEvent();
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop);
|
||||
virtual bool isSnooping();
|
||||
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
|
||||
|
|
16
src/mem/cache/cache_impl.hh
vendored
16
src/mem/cache/cache_impl.hh
vendored
|
@ -1554,14 +1554,15 @@ Cache<TagStore>::nextMSHRReadyTime()
|
|||
///////////////
|
||||
|
||||
template<class TagStore>
|
||||
void
|
||||
AddrRangeList
|
||||
Cache<TagStore>::CpuSidePort::
|
||||
getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
|
||||
getAddrRanges()
|
||||
{
|
||||
// CPU side port doesn't snoop; it's a target only. It can
|
||||
// potentially respond to any address.
|
||||
snoop = false;
|
||||
resp.push_back(myCache()->getAddrRange());
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(myCache()->getAddrRange());
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1612,14 +1613,13 @@ CpuSidePort::CpuSidePort(const std::string &_name, Cache<TagStore> *_cache,
|
|||
///////////////
|
||||
|
||||
template<class TagStore>
|
||||
void
|
||||
Cache<TagStore>::MemSidePort::
|
||||
getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
|
||||
bool
|
||||
Cache<TagStore>::MemSidePort::isSnooping()
|
||||
{
|
||||
// Memory-side port always snoops, but never passes requests
|
||||
// through to targets on the cpu side (so we don't add anything to
|
||||
// the address range list).
|
||||
snoop = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ PhysicalMemory::init()
|
|||
|
||||
for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {
|
||||
if (*pi)
|
||||
(*pi)->sendStatusChange(Port::RangeChange);
|
||||
(*pi)->sendRangeChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -398,36 +398,30 @@ PhysicalMemory::getPort(const std::string &if_name, int idx)
|
|||
return port;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PhysicalMemory::recvStatusChange(Port::Status status)
|
||||
{
|
||||
}
|
||||
|
||||
PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
|
||||
PhysicalMemory *_memory)
|
||||
: SimpleTimingPort(_name, _memory), memory(_memory)
|
||||
{ }
|
||||
|
||||
void
|
||||
PhysicalMemory::MemoryPort::recvStatusChange(Port::Status status)
|
||||
PhysicalMemory::MemoryPort::recvRangeChange()
|
||||
{
|
||||
memory->recvStatusChange(status);
|
||||
// memory is a slave and thus should never have to worry about its
|
||||
// neighbours address ranges
|
||||
}
|
||||
|
||||
void
|
||||
PhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
AddrRangeList
|
||||
PhysicalMemory::MemoryPort::getAddrRanges()
|
||||
{
|
||||
memory->getAddressRanges(resp, snoop);
|
||||
return memory->getAddrRanges();
|
||||
}
|
||||
|
||||
void
|
||||
PhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop)
|
||||
AddrRangeList
|
||||
PhysicalMemory::getAddrRanges()
|
||||
{
|
||||
snoop = false;
|
||||
resp.clear();
|
||||
resp.push_back(RangeSize(start(), size()));
|
||||
AddrRangeList ranges;
|
||||
ranges.push_back(RangeSize(start(), size()));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
unsigned
|
||||
|
|
|
@ -65,10 +65,9 @@ class PhysicalMemory : public MemObject
|
|||
|
||||
virtual void recvFunctional(PacketPtr pkt);
|
||||
|
||||
virtual void recvStatusChange(Status status);
|
||||
virtual void recvRangeChange();
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop);
|
||||
virtual AddrRangeList getAddrRanges();
|
||||
|
||||
virtual unsigned deviceBlockSize() const;
|
||||
};
|
||||
|
@ -172,7 +171,7 @@ class PhysicalMemory : public MemObject
|
|||
|
||||
public:
|
||||
unsigned deviceBlockSize() const;
|
||||
void getAddressRanges(AddrRangeList &resp, bool &snoop);
|
||||
AddrRangeList getAddrRanges();
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||
void virtual init();
|
||||
unsigned int drain(Event *de);
|
||||
|
@ -181,7 +180,6 @@ class PhysicalMemory : public MemObject
|
|||
Tick doAtomicAccess(PacketPtr pkt);
|
||||
void doFunctionalAccess(PacketPtr pkt);
|
||||
virtual Tick calculateLatency(PacketPtr pkt);
|
||||
void recvStatusChange(Port::Status status);
|
||||
|
||||
public:
|
||||
virtual void serialize(std::ostream &os);
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2011 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -48,8 +60,7 @@
|
|||
#include "mem/packet.hh"
|
||||
#include "mem/request.hh"
|
||||
|
||||
/** This typedef is used to clean up the parameter list of
|
||||
* getDeviceAddressRanges() and getPeerAddressRanges(). It's declared
|
||||
/** This typedef is used to clean up getAddrRanges(). It's declared
|
||||
* outside the Port object since it's also used by some mem objects.
|
||||
* Eventually we should move this typedef to wherever Addr is
|
||||
* defined.
|
||||
|
@ -101,13 +112,6 @@ class Port
|
|||
|
||||
virtual ~Port();
|
||||
|
||||
// mey be better to use subclasses & RTTI?
|
||||
/** Holds the ports status. Currently just that a range recomputation needs
|
||||
* to be done. */
|
||||
enum Status {
|
||||
RangeChange
|
||||
};
|
||||
|
||||
void setName(const std::string &name)
|
||||
{ portName = name; }
|
||||
|
||||
|
@ -139,8 +143,8 @@ class Port
|
|||
/** Called to recive a functional call from the peer port. */
|
||||
virtual void recvFunctional(PacketPtr pkt) = 0;
|
||||
|
||||
/** Called to recieve a status change from the peer port. */
|
||||
virtual void recvStatusChange(Status status) = 0;
|
||||
/** Called to recieve an address range change from the peer port. */
|
||||
virtual void recvRangeChange() = 0;
|
||||
|
||||
/** Called by a peer port if the send was unsuccesful, and had to
|
||||
wait. This shouldn't be valid for response paths (IO Devices).
|
||||
|
@ -155,17 +159,31 @@ class Port
|
|||
*/
|
||||
virtual unsigned deviceBlockSize() const { return 0; }
|
||||
|
||||
/** The peer port is requesting us to reply with a list of the ranges we
|
||||
are responsible for.
|
||||
@param resp is a list of ranges responded to
|
||||
@param snoop is a list of ranges snooped
|
||||
*/
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
bool &snoop)
|
||||
{ panic("??"); }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get a list of the non-overlapping address ranges we are
|
||||
* responsible for. The default implementation returns an empty
|
||||
* list and thus no address ranges. Any slave port must override
|
||||
* this function and return a populated list with at least one
|
||||
* item.
|
||||
*
|
||||
* @return a list of ranges responded to
|
||||
*/
|
||||
virtual AddrRangeList getAddrRanges()
|
||||
{ AddrRangeList ranges; return ranges; }
|
||||
|
||||
/**
|
||||
* Determine if this port is snooping or not. The default
|
||||
* implementation returns false and thus tells the neighbour we
|
||||
* are not snooping. Any port that is to snoop (e.g. a cache
|
||||
* connected to a bus) has to override this function.
|
||||
*
|
||||
* @return true if the port should be considered a snooper
|
||||
*/
|
||||
virtual bool isSnooping()
|
||||
{ return false; }
|
||||
|
||||
/** Function called by associated memory device (cache, memory, iodevice)
|
||||
in order to send a timing request to the port. Simply calls the peer
|
||||
port receive function.
|
||||
|
@ -193,10 +211,11 @@ class Port
|
|||
void sendFunctional(PacketPtr pkt)
|
||||
{ return peer->recvFunctional(pkt); }
|
||||
|
||||
/** Called by the associated device to send a status change to the device
|
||||
connected to the peer interface.
|
||||
*/
|
||||
void sendStatusChange(Status status) {peer->recvStatusChange(status); }
|
||||
/**
|
||||
* Called by the associated device to send a status range to the
|
||||
* peer interface.
|
||||
*/
|
||||
void sendRangeChange() const { peer->recvRangeChange(); }
|
||||
|
||||
/** When a timing access doesn't return a success, some time later the
|
||||
Retry will be sent.
|
||||
|
@ -208,12 +227,6 @@ class Port
|
|||
*/
|
||||
unsigned peerBlockSize() const { return peer->deviceBlockSize(); }
|
||||
|
||||
/** Called by the associated device if it wishes to find out the address
|
||||
ranges connected to the peer ports devices.
|
||||
*/
|
||||
void getPeerAddressRanges(AddrRangeList &resp, bool &snoop)
|
||||
{ peer->getDeviceAddressRanges(resp, snoop); }
|
||||
|
||||
/** This function is a wrapper around sendFunctional()
|
||||
that breaks a larger, arbitrarily aligned access into
|
||||
appropriate chunks. The default implementation can use
|
||||
|
|
|
@ -671,9 +671,8 @@ RubyPort::PioPort::sendTiming(PacketPtr pkt)
|
|||
bool
|
||||
RubyPort::M5Port::isPhysMemAddress(Addr addr)
|
||||
{
|
||||
AddrRangeList physMemAddrList;
|
||||
bool snoop = false;
|
||||
ruby_port->physMemPort->getPeerAddressRanges(physMemAddrList, snoop);
|
||||
AddrRangeList physMemAddrList =
|
||||
ruby_port->physMemPort->getPeer()->getAddrRanges();
|
||||
for (AddrRangeIter iter = physMemAddrList.begin();
|
||||
iter != physMemAddrList.end();
|
||||
iter++) {
|
||||
|
|
|
@ -139,10 +139,13 @@ class SimpleTimingPort : public Port
|
|||
bool recvTiming(PacketPtr pkt);
|
||||
|
||||
/**
|
||||
* Simple ports generally don't care about any status
|
||||
* changes... can always override this in cases where that's not
|
||||
* true. */
|
||||
virtual void recvStatusChange(Status status) { }
|
||||
* Simple ports are generally used as slave ports (i.e. the
|
||||
* respond to requests) and thus do not expect to receive any
|
||||
* range changes (as the neighbouring port has a master role and
|
||||
* do not have any address ranges. A subclass can override the
|
||||
* default behaviuor if needed.
|
||||
*/
|
||||
virtual void recvRangeChange() { }
|
||||
|
||||
|
||||
public:
|
||||
|
|
|
@ -102,7 +102,13 @@ class System : public MemObject
|
|||
{ panic("SystemPort does not receive atomic!\n"); return 0; }
|
||||
void recvFunctional(PacketPtr pkt)
|
||||
{ panic("SystemPort does not receive functional!\n"); }
|
||||
void recvStatusChange(Status status) { }
|
||||
|
||||
/**
|
||||
* The system port is a master port connected to a single
|
||||
* slave and thus do not care about what ranges the slave
|
||||
* covers (as there is nothing to choose from).
|
||||
*/
|
||||
void recvRangeChange() { }
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue