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:
Andreas Hansson 2012-01-17 12:55:09 -06:00
parent 142380a373
commit 07cf9d914b
54 changed files with 345 additions and 416 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -325,10 +325,12 @@ class Pl111: public AmbaDmaDevice
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
/** 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

View file

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

View file

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

View file

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

View file

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

View file

@ -80,7 +80,7 @@ class PciConfigAll : public PioDevice
virtual Tick write(PacketPtr pkt);
void addressRanges(AddrRangeList &range_list);
AddrRangeList getAddrRanges();
private:
Addr pioAddr;

View file

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

View file

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

View file

@ -1714,7 +1714,7 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
if (transmitTick)
schedule(txEvent, curTick() + transmitTick);
pioPort->sendStatusChange(Port::RangeChange);
pioPort->sendRangeChange();
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -255,7 +255,7 @@ class I8042 : public BasicPioDevice
commandByte.keyboardFullInt = 1;
}
void addressRanges(AddrRangeList &range_list);
AddrRangeList getAddrRanges();
Tick read(PacketPtr pkt);

View file

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

View file

@ -54,7 +54,7 @@ X86ISA::IntDev::init()
if (!intPort) {
panic("Int port not connected to anything!");
}
intPort->sendStatusChange(Port::RangeChange);
intPort->sendRangeChange();
}
X86ISA::IntSourcePin *

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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