MEM: Move port creation to the memory object(s) construction
This patch moves all port creation from the getPort method to be consistently done in the MemObject's constructor. This is possible thanks to the Swig interface passing the length of the vector ports. Previously there was a mix of: 1) creating the ports as members (at object construction time) and using getPort for the name resolution, or 2) dynamically creating the ports in the getPort call. This is now uniform. Furthermore, objects that would not be complete without a port have these ports as members rather than having pointers to dynamically allocated ports. This patch also enables an elaboration-time enumeration of all the ports in the system which can be used to determine the masterId.
This commit is contained in:
@@ -45,13 +45,14 @@
|
||||
#include "debug/Checkpoint.hh"
|
||||
#include "debug/TLB.hh"
|
||||
#include "debug/TLBVerbose.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace ArmISA;
|
||||
|
||||
TableWalker::TableWalker(const Params *p)
|
||||
: MemObject(p), port(NULL), tlb(NULL), currState(NULL), pending(false),
|
||||
: MemObject(p), port(this, params()->sys, params()->min_backoff,
|
||||
params()->max_backoff, true),
|
||||
tlb(NULL), currState(NULL), pending(false),
|
||||
masterId(p->sys->getMasterId(name())),
|
||||
doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this)
|
||||
{
|
||||
@@ -94,13 +95,7 @@ Port*
|
||||
TableWalker::getPort(const std::string &if_name, int idx)
|
||||
{
|
||||
if (if_name == "port") {
|
||||
if (port != NULL)
|
||||
return port;
|
||||
System *sys = params()->sys;
|
||||
Tick minb = params()->min_backoff;
|
||||
Tick maxb = params()->max_backoff;
|
||||
port = new DmaPort(this, sys, minb, maxb, true);
|
||||
return port;
|
||||
return &port;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -225,24 +220,24 @@ TableWalker::processWalk()
|
||||
}
|
||||
|
||||
if (currState->timing) {
|
||||
port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
|
||||
&doL1DescEvent, (uint8_t*)&currState->l1Desc.data,
|
||||
currState->tc->getCpuPtr()->ticks(1), flag);
|
||||
port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
|
||||
&doL1DescEvent, (uint8_t*)&currState->l1Desc.data,
|
||||
currState->tc->getCpuPtr()->ticks(1), flag);
|
||||
DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
|
||||
stateQueueL1.size());
|
||||
stateQueueL1.push_back(currState);
|
||||
currState = NULL;
|
||||
} else if (!currState->functional) {
|
||||
port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
|
||||
NULL, (uint8_t*)&currState->l1Desc.data,
|
||||
currState->tc->getCpuPtr()->ticks(1), flag);
|
||||
port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
|
||||
NULL, (uint8_t*)&currState->l1Desc.data,
|
||||
currState->tc->getCpuPtr()->ticks(1), flag);
|
||||
doL1Descriptor();
|
||||
f = currState->fault;
|
||||
} else {
|
||||
RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag, masterId);
|
||||
PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
|
||||
pkt->dataStatic((uint8_t*)&currState->l1Desc.data);
|
||||
port->sendFunctional(pkt);
|
||||
port.sendFunctional(pkt);
|
||||
doL1Descriptor();
|
||||
delete req;
|
||||
delete pkt;
|
||||
@@ -574,11 +569,11 @@ TableWalker::doL1Descriptor()
|
||||
|
||||
if (currState->timing) {
|
||||
currState->delayed = true;
|
||||
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
||||
port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
||||
&doL2DescEvent, (uint8_t*)&currState->l2Desc.data,
|
||||
currState->tc->getCpuPtr()->ticks(1));
|
||||
} else if (!currState->functional) {
|
||||
port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
||||
port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
||||
NULL, (uint8_t*)&currState->l2Desc.data,
|
||||
currState->tc->getCpuPtr()->ticks(1));
|
||||
doL2Descriptor();
|
||||
@@ -586,7 +581,7 @@ TableWalker::doL1Descriptor()
|
||||
RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0, masterId);
|
||||
PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
|
||||
pkt->dataStatic((uint8_t*)&currState->l2Desc.data);
|
||||
port->sendFunctional(pkt);
|
||||
port.sendFunctional(pkt);
|
||||
doL2Descriptor();
|
||||
delete req;
|
||||
delete pkt;
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
#include "arch/arm/miscregs.hh"
|
||||
#include "arch/arm/tlb.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "mem/mem_object.hh"
|
||||
#include "mem/request.hh"
|
||||
#include "params/ArmTableWalker.hh"
|
||||
@@ -328,7 +329,7 @@ class TableWalker : public MemObject
|
||||
|
||||
|
||||
/** Port to issue translation requests from */
|
||||
DmaPort *port;
|
||||
DmaPort port;
|
||||
|
||||
/** TLB that is initiating these table walks */
|
||||
TLB *tlb;
|
||||
|
||||
@@ -554,7 +554,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
|
||||
break;
|
||||
}
|
||||
pendingIPIs += apics.size();
|
||||
intPort->sendMessage(apics, message, timing);
|
||||
intPort.sendMessage(apics, message, timing);
|
||||
newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
|
||||
}
|
||||
break;
|
||||
@@ -612,7 +612,8 @@ X86ISA::Interrupts::Interrupts(Params * p) :
|
||||
pendingInit(false), initVector(0),
|
||||
pendingStartup(false), startupVector(0),
|
||||
startedUp(false), pendingUnmaskableInt(false),
|
||||
pendingIPIs(0), cpu(NULL)
|
||||
pendingIPIs(0), cpu(NULL),
|
||||
intSlavePort(name() + ".int_slave", this, this, latency)
|
||||
{
|
||||
pioSize = PageBytes;
|
||||
memset(regs, 0, sizeof(regs));
|
||||
|
||||
@@ -188,6 +188,9 @@ class Interrupts : public BasicPioDevice, IntDev
|
||||
|
||||
int initialApicId;
|
||||
|
||||
// Port for receiving interrupts
|
||||
IntPort intSlavePort;
|
||||
|
||||
public:
|
||||
|
||||
int getInitialApicId() { return initialApicId; }
|
||||
@@ -242,10 +245,9 @@ class Interrupts : public BasicPioDevice, IntDev
|
||||
// Python class we also need two ports even if they are
|
||||
// identical
|
||||
if (if_name == "int_master") {
|
||||
return intPort;
|
||||
return &intPort;
|
||||
} else if (if_name == "int_slave") {
|
||||
// memory leak...but will be removed in the next patch
|
||||
return new IntPort(name() + ".int_slave", this, this, latency);
|
||||
return &intSlavePort;
|
||||
}
|
||||
return BasicPioDevice::getPort(if_name, idx);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009-2010 Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
@@ -40,6 +52,12 @@ RubyDirectedTester::RubyDirectedTester(const Params *p)
|
||||
{
|
||||
m_requests_completed = 0;
|
||||
|
||||
// create the ports
|
||||
for (int i = 0; i < p->port_cpuPort_connection_count; ++i) {
|
||||
ports.push_back(new CpuPort(csprintf("%s-port%d", name(), i),
|
||||
this, i));
|
||||
}
|
||||
|
||||
// add the check start event to the event queue
|
||||
schedule(directedStartEvent, 1);
|
||||
}
|
||||
@@ -61,21 +79,15 @@ Port *
|
||||
RubyDirectedTester::getPort(const std::string &if_name, int idx)
|
||||
{
|
||||
if (if_name != "cpuPort") {
|
||||
panic("RubyDirectedTester::getPort: unknown port %s requested", if_name);
|
||||
panic("RubyDirectedTester::getPort: unknown port %s requested",
|
||||
if_name);
|
||||
}
|
||||
|
||||
if (idx >= (int)ports.size()) {
|
||||
ports.resize(idx + 1);
|
||||
if (idx >= static_cast<int>(ports.size())) {
|
||||
panic("RubyDirectedTester::getPort: unknown index %d requested\n", idx);
|
||||
}
|
||||
|
||||
if (ports[idx] != NULL) {
|
||||
panic("RubyDirectedTester::getPort: port %d already assigned", idx);
|
||||
}
|
||||
|
||||
CpuPort *port = new CpuPort(csprintf("%s-port%d", name(), idx), this, idx);
|
||||
|
||||
ports[idx] = port;
|
||||
return port;
|
||||
return ports[idx];
|
||||
}
|
||||
|
||||
Tick
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 Advanced Micro Devices, Inc.
|
||||
* All rights reserved.
|
||||
@@ -48,6 +60,12 @@ RubyTester::RubyTester(const Params *p)
|
||||
{
|
||||
m_checks_completed = 0;
|
||||
|
||||
// create the ports
|
||||
for (int i = 0; i < p->port_cpuPort_connection_count; ++i) {
|
||||
ports.push_back(new CpuPort(csprintf("%s-port%d", name(), i),
|
||||
this, i));
|
||||
}
|
||||
|
||||
// add the check start event to the event queue
|
||||
schedule(checkStartEvent, 1);
|
||||
}
|
||||
@@ -78,21 +96,14 @@ Port *
|
||||
RubyTester::getPort(const std::string &if_name, int idx)
|
||||
{
|
||||
if (if_name != "cpuPort") {
|
||||
panic("RubyTester::getPort: unknown port %s requested", if_name);
|
||||
panic("RubyTester::getPort: unknown port %s requested\n", if_name);
|
||||
}
|
||||
|
||||
if (idx >= (int)ports.size()) {
|
||||
ports.resize(idx + 1);
|
||||
if (idx >= static_cast<int>(ports.size())) {
|
||||
panic("RubyTester::getPort: unknown index %d requested\n", idx);
|
||||
}
|
||||
|
||||
if (ports[idx] != NULL) {
|
||||
panic("RubyTester::getPort: port %d already assigned", idx);
|
||||
}
|
||||
|
||||
CpuPort *port = new CpuPort(csprintf("%s-port%d", name(), idx), this, idx);
|
||||
|
||||
ports[idx] = port;
|
||||
return port;
|
||||
return ports[idx];
|
||||
}
|
||||
|
||||
Tick
|
||||
|
||||
@@ -284,7 +284,8 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
|
||||
baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
|
||||
pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
|
||||
|
||||
pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t));
|
||||
pioPort.readBlob(pteAddr, (uint8_t*)&pteEntry,
|
||||
sizeof(uint64_t));
|
||||
|
||||
dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
|
||||
|
||||
|
||||
@@ -460,9 +460,9 @@ Pl111::fillFifo()
|
||||
// will be uncacheable as well. If we have uncacheable and cacheable
|
||||
// requests in the memory system for the same address it won't be
|
||||
// pleased
|
||||
dmaPort->dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize,
|
||||
&dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer, 0,
|
||||
Request::UNCACHEABLE);
|
||||
dmaPort.dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize,
|
||||
&dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer,
|
||||
0, Request::UNCACHEABLE);
|
||||
curAddr += dmaSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,9 @@ CopyEngine::CopyEngine(const Params *p)
|
||||
|
||||
|
||||
CopyEngine::CopyEngineChannel::CopyEngineChannel(CopyEngine *_ce, int cid)
|
||||
: cePort(NULL), ce(_ce), channelId(cid), busy(false), underReset(false),
|
||||
: cePort(_ce, _ce->sys, _ce->params()->min_backoff_delay,
|
||||
_ce->params()->max_backoff_delay),
|
||||
ce(_ce), channelId(cid), busy(false), underReset(false),
|
||||
refreshNext(false), latBeforeBegin(ce->params()->latBeforeBegin),
|
||||
latAfterCompletion(ce->params()->latAfterCompletion),
|
||||
completionDataReg(0), nextState(Idle), drainEvent(NULL),
|
||||
@@ -106,7 +108,6 @@ CopyEngine::CopyEngineChannel::~CopyEngineChannel()
|
||||
{
|
||||
delete curDmaDesc;
|
||||
delete [] copyBuffer;
|
||||
delete cePort;
|
||||
}
|
||||
|
||||
Port *
|
||||
@@ -123,10 +124,7 @@ CopyEngine::getPort(const std::string &if_name, int idx)
|
||||
Port *
|
||||
CopyEngine::CopyEngineChannel::getPort()
|
||||
{
|
||||
assert(cePort == NULL);
|
||||
cePort = new DmaPort(ce, ce->sys, ce->params()->min_backoff_delay,
|
||||
ce->params()->max_backoff_delay);
|
||||
return cePort;
|
||||
return &cePort;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -451,9 +449,9 @@ CopyEngine::CopyEngineChannel::fetchDescriptor(Addr address)
|
||||
DPRINTF(DMACopyEngine, "dmaAction: %#x, %d bytes, to addr %#x\n",
|
||||
ce->platform->pciToDma(address), sizeof(DmaDesc), curDmaDesc);
|
||||
|
||||
cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address),
|
||||
sizeof(DmaDesc), &fetchCompleteEvent, (uint8_t*)curDmaDesc,
|
||||
latBeforeBegin);
|
||||
cePort.dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address),
|
||||
sizeof(DmaDesc), &fetchCompleteEvent,
|
||||
(uint8_t*)curDmaDesc, latBeforeBegin);
|
||||
lastDescriptorAddr = address;
|
||||
}
|
||||
|
||||
@@ -495,8 +493,8 @@ CopyEngine::CopyEngineChannel::readCopyBytes()
|
||||
DPRINTF(DMACopyEngine, "Reading %d bytes from buffer to memory location %#x(%#x)\n",
|
||||
curDmaDesc->len, curDmaDesc->dest,
|
||||
ce->platform->pciToDma(curDmaDesc->src));
|
||||
cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(curDmaDesc->src),
|
||||
curDmaDesc->len, &readCompleteEvent, copyBuffer, 0);
|
||||
cePort.dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(curDmaDesc->src),
|
||||
curDmaDesc->len, &readCompleteEvent, copyBuffer, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -517,8 +515,8 @@ CopyEngine::CopyEngineChannel::writeCopyBytes()
|
||||
curDmaDesc->len, curDmaDesc->dest,
|
||||
ce->platform->pciToDma(curDmaDesc->dest));
|
||||
|
||||
cePort->dmaAction(MemCmd::WriteReq, ce->platform->pciToDma(curDmaDesc->dest),
|
||||
curDmaDesc->len, &writeCompleteEvent, copyBuffer, 0);
|
||||
cePort.dmaAction(MemCmd::WriteReq, ce->platform->pciToDma(curDmaDesc->dest),
|
||||
curDmaDesc->len, &writeCompleteEvent, copyBuffer, 0);
|
||||
|
||||
ce->bytesCopied[channelId] += curDmaDesc->len;
|
||||
ce->copiesProcessed[channelId]++;
|
||||
@@ -586,9 +584,10 @@ CopyEngine::CopyEngineChannel::writeCompletionStatus()
|
||||
completionDataReg, cr.completionAddr,
|
||||
ce->platform->pciToDma(cr.completionAddr));
|
||||
|
||||
cePort->dmaAction(MemCmd::WriteReq, ce->platform->pciToDma(cr.completionAddr),
|
||||
sizeof(completionDataReg), &statusCompleteEvent,
|
||||
(uint8_t*)&completionDataReg, latAfterCompletion);
|
||||
cePort.dmaAction(MemCmd::WriteReq,
|
||||
ce->platform->pciToDma(cr.completionAddr),
|
||||
sizeof(completionDataReg), &statusCompleteEvent,
|
||||
(uint8_t*)&completionDataReg, latAfterCompletion);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -604,9 +603,10 @@ CopyEngine::CopyEngineChannel::fetchNextAddr(Addr address)
|
||||
anBegin("FetchNextAddr");
|
||||
DPRINTF(DMACopyEngine, "Fetching next address...\n");
|
||||
busy = true;
|
||||
cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address +
|
||||
offsetof(DmaDesc, next)), sizeof(Addr), &addrCompleteEvent,
|
||||
(uint8_t*)curDmaDesc + offsetof(DmaDesc, next), 0);
|
||||
cePort.dmaAction(MemCmd::ReadReq,
|
||||
ce->platform->pciToDma(address + offsetof(DmaDesc, next)),
|
||||
sizeof(Addr), &addrCompleteEvent,
|
||||
(uint8_t*)curDmaDesc + offsetof(DmaDesc, next), 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -648,7 +648,7 @@ CopyEngine::CopyEngineChannel::drain(Event *de)
|
||||
if (nextState == Idle || ce->getState() != SimObject::Running)
|
||||
return 0;
|
||||
unsigned int count = 1;
|
||||
count += cePort->drain(de);
|
||||
count += cePort.drain(de);
|
||||
|
||||
DPRINTF(DMACopyEngine, "unable to drain, returning %d\n", count);
|
||||
drainEvent = de;
|
||||
@@ -659,7 +659,7 @@ unsigned int
|
||||
CopyEngine::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de);
|
||||
count = pioPort.drain(de) + dmaPort.drain(de) + configPort.drain(de);
|
||||
for (int x = 0;x < chan.size(); x++)
|
||||
count += chan[x]->drain(de);
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ class CopyEngine : public PciDev
|
||||
class CopyEngineChannel
|
||||
{
|
||||
private:
|
||||
DmaPort *cePort;
|
||||
DmaPort cePort;
|
||||
CopyEngine *ce;
|
||||
CopyEngineReg::ChanRegs cr;
|
||||
int channelId;
|
||||
|
||||
@@ -2051,7 +2051,7 @@ unsigned int
|
||||
IGbE::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort->drain(de) + dmaPort->drain(de);
|
||||
count = pioPort.drain(de) + dmaPort.drain(de);
|
||||
if (rxDescCache.hasOutstandingEvents() ||
|
||||
txDescCache.hasOutstandingEvents()) {
|
||||
count++;
|
||||
|
||||
@@ -55,33 +55,28 @@ PioPort::getAddrRanges()
|
||||
|
||||
|
||||
PioDevice::PioDevice(const Params *p)
|
||||
: MemObject(p), sys(p->system), pioPort(NULL)
|
||||
: MemObject(p), sys(p->system), pioPort(this, sys)
|
||||
{}
|
||||
|
||||
PioDevice::~PioDevice()
|
||||
{
|
||||
if (pioPort)
|
||||
delete pioPort;
|
||||
}
|
||||
|
||||
void
|
||||
PioDevice::init()
|
||||
{
|
||||
if (!pioPort)
|
||||
if (!pioPort.isConnected())
|
||||
panic("Pio port of %s not connected to anything!", name());
|
||||
pioPort->sendRangeChange();
|
||||
pioPort.sendRangeChange();
|
||||
}
|
||||
|
||||
Port *
|
||||
PioDevice::getPort(const std::string &if_name, int idx)
|
||||
{
|
||||
if (if_name == "pio") {
|
||||
if (pioPort != NULL)
|
||||
fatal("%s: pio port already connected to %s",
|
||||
name(), pioPort->getPeer()->name());
|
||||
pioPort = new PioPort(this, sys);
|
||||
return pioPort;
|
||||
return &pioPort;
|
||||
}
|
||||
panic("PioDevice %s has no port named %s\n", name(), if_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -89,7 +84,7 @@ unsigned int
|
||||
PioDevice::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort->drain(de);
|
||||
count = pioPort.drain(de);
|
||||
if (count)
|
||||
changeState(Draining);
|
||||
else
|
||||
@@ -185,14 +180,23 @@ DmaPort::recvTiming(PacketPtr pkt)
|
||||
}
|
||||
|
||||
DmaDevice::DmaDevice(const Params *p)
|
||||
: PioDevice(p), dmaPort(NULL)
|
||||
: PioDevice(p), dmaPort(this, sys, params()->min_backoff_delay,
|
||||
params()->max_backoff_delay)
|
||||
{ }
|
||||
|
||||
void
|
||||
DmaDevice::init()
|
||||
{
|
||||
if (!dmaPort.isConnected())
|
||||
panic("DMA port of %s not connected to anything!", name());
|
||||
PioDevice::init();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
DmaDevice::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort->drain(de) + dmaPort->drain(de);
|
||||
count = pioPort.drain(de) + dmaPort.drain(de);
|
||||
if (count)
|
||||
changeState(Draining);
|
||||
else
|
||||
@@ -362,8 +366,6 @@ DmaPort::sendDma()
|
||||
|
||||
DmaDevice::~DmaDevice()
|
||||
{
|
||||
if (dmaPort)
|
||||
delete dmaPort;
|
||||
}
|
||||
|
||||
|
||||
@@ -371,12 +373,7 @@ Port *
|
||||
DmaDevice::getPort(const std::string &if_name, int idx)
|
||||
{
|
||||
if (if_name == "dma") {
|
||||
if (dmaPort != NULL)
|
||||
fatal("%s: dma port already connected to %s",
|
||||
name(), dmaPort->getPeer()->name());
|
||||
dmaPort = new DmaPort(this, sys, params()->min_backoff_delay,
|
||||
params()->max_backoff_delay);
|
||||
return dmaPort;
|
||||
return &dmaPort;
|
||||
}
|
||||
return PioDevice::getPort(if_name, idx);
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ class PioDevice : public MemObject
|
||||
|
||||
/** The pioPort that handles the requests for us and provides us requests
|
||||
* that it sees. */
|
||||
PioPort *pioPort;
|
||||
PioPort pioPort;
|
||||
|
||||
/**
|
||||
* Every PIO device is obliged to provide an implementation that
|
||||
@@ -271,7 +271,7 @@ class BasicPioDevice : public PioDevice
|
||||
class DmaDevice : public PioDevice
|
||||
{
|
||||
protected:
|
||||
DmaPort *dmaPort;
|
||||
DmaPort dmaPort;
|
||||
|
||||
public:
|
||||
typedef DmaDeviceParams Params;
|
||||
@@ -284,21 +284,25 @@ class DmaDevice : public PioDevice
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
|
||||
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0)
|
||||
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data,
|
||||
Tick delay = 0)
|
||||
{
|
||||
dmaPort->dmaAction(MemCmd::WriteReq, addr, size, event, data, delay);
|
||||
dmaPort.dmaAction(MemCmd::WriteReq, addr, size, event, data, delay);
|
||||
}
|
||||
|
||||
void dmaRead(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0)
|
||||
void dmaRead(Addr addr, int size, Event *event, uint8_t *data,
|
||||
Tick delay = 0)
|
||||
{
|
||||
dmaPort->dmaAction(MemCmd::ReadReq, addr, size, event, data, delay);
|
||||
dmaPort.dmaAction(MemCmd::ReadReq, addr, size, event, data, delay);
|
||||
}
|
||||
|
||||
bool dmaPending() { return dmaPort->dmaPending(); }
|
||||
bool dmaPending() { return dmaPort.dmaPending(); }
|
||||
|
||||
virtual void init();
|
||||
|
||||
virtual unsigned int drain(Event *de);
|
||||
|
||||
unsigned cacheBlockSize() const { return dmaPort->cacheBlockSize(); }
|
||||
unsigned cacheBlockSize() const { return dmaPort.cacheBlockSize(); }
|
||||
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||
|
||||
|
||||
@@ -283,7 +283,8 @@ MaltaPChip::translatePciToDma(Addr busAddr)
|
||||
baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
|
||||
pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
|
||||
|
||||
pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t));
|
||||
pioPort.readBlob(pteAddr, (uint8_t*)&pteEntry,
|
||||
sizeof(uint64_t));
|
||||
|
||||
dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
|
||||
|
||||
|
||||
@@ -82,7 +82,9 @@ PciDev::PciConfigPort::getAddrRanges()
|
||||
|
||||
PciDev::PciDev(const Params *p)
|
||||
: DmaDevice(p), platform(p->platform), pioDelay(p->pio_latency),
|
||||
configDelay(p->config_latency), configPort(NULL)
|
||||
configDelay(p->config_latency),
|
||||
configPort(this, params()->pci_bus, params()->pci_dev,
|
||||
params()->pci_func, params()->platform)
|
||||
{
|
||||
config.vendor = htole(p->VendorID);
|
||||
config.device = htole(p->DeviceID);
|
||||
@@ -148,17 +150,17 @@ PciDev::PciDev(const Params *p)
|
||||
void
|
||||
PciDev::init()
|
||||
{
|
||||
if (!configPort && !configPort->isConnected())
|
||||
if (!configPort.isConnected())
|
||||
panic("PCI config port on %s not connected to anything!\n", name());
|
||||
configPort->sendRangeChange();
|
||||
PioDevice::init();
|
||||
configPort.sendRangeChange();
|
||||
DmaDevice::init();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PciDev::drain(Event *de)
|
||||
{
|
||||
unsigned int count;
|
||||
count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de);
|
||||
count = pioPort.drain(de) + dmaPort.drain(de) + configPort.drain(de);
|
||||
if (count)
|
||||
changeState(Draining);
|
||||
else
|
||||
@@ -300,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->sendRangeChange();
|
||||
pioPort.sendRangeChange();
|
||||
}
|
||||
}
|
||||
config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) |
|
||||
@@ -353,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->sendRangeChange();
|
||||
pioPort.sendRangeChange();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ class PciDev : public DmaDevice
|
||||
Platform *platform;
|
||||
Tick pioDelay;
|
||||
Tick configDelay;
|
||||
PciConfigPort *configPort;
|
||||
PciConfigPort configPort;
|
||||
|
||||
/**
|
||||
* Write to the PCI config space data that is stored locally. This may be
|
||||
@@ -221,12 +221,7 @@ class PciDev : public DmaDevice
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1)
|
||||
{
|
||||
if (if_name == "config") {
|
||||
if (configPort != NULL)
|
||||
panic("pciconfig port already connected to.");
|
||||
configPort = new PciConfigPort(this, params()->pci_bus,
|
||||
params()->pci_dev, params()->pci_func,
|
||||
params()->platform);
|
||||
return configPort;
|
||||
return &configPort;
|
||||
}
|
||||
return DmaDevice::getPort(if_name, idx);
|
||||
}
|
||||
|
||||
@@ -1714,7 +1714,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
if (transmitTick)
|
||||
schedule(txEvent, curTick() + transmitTick);
|
||||
|
||||
pioPort->sendRangeChange();
|
||||
pioPort.sendRangeChange();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -222,8 +222,8 @@ X86ISA::I82094AA::signalInterrupt(int line)
|
||||
apics.push_back(selected);
|
||||
}
|
||||
}
|
||||
intPort->sendMessage(apics, message,
|
||||
sys->getMemoryMode() == Enums::timing);
|
||||
intPort.sendMessage(apics, message,
|
||||
sys->getMemoryMode() == Enums::timing);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ class I82094AA : public PioDevice, public IntDev
|
||||
Port *getPort(const std::string &if_name, int idx = -1)
|
||||
{
|
||||
if (if_name == "int_master")
|
||||
return intPort;
|
||||
return &intPort;
|
||||
return PioDevice::getPort(if_name, idx);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,10 +51,10 @@ X86ISA::IntDev::IntPort::sendMessage(ApicList apics,
|
||||
void
|
||||
X86ISA::IntDev::init()
|
||||
{
|
||||
if (!intPort) {
|
||||
if (!intPort.isConnected()) {
|
||||
panic("Int port not connected to anything!");
|
||||
}
|
||||
intPort->sendRangeChange();
|
||||
intPort.sendRangeChange();
|
||||
}
|
||||
|
||||
X86ISA::IntSourcePin *
|
||||
|
||||
@@ -84,17 +84,12 @@ class IntDev
|
||||
TriggerIntMessage message, bool timing);
|
||||
};
|
||||
|
||||
IntPort * intPort;
|
||||
IntPort intPort;
|
||||
|
||||
public:
|
||||
IntDev(MemObject * parent, Tick latency = 0)
|
||||
IntDev(MemObject * parent, Tick latency = 0) :
|
||||
intPort(parent->name() + ".int_master", parent, this, latency)
|
||||
{
|
||||
if (parent != NULL) {
|
||||
intPort = new IntPort(parent->name() + ".int_master",
|
||||
parent, this, latency);
|
||||
} else {
|
||||
intPort = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~IntDev()
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
Bridge::BridgeSlavePort::BridgeSlavePort(const std::string &_name,
|
||||
Bridge* _bridge,
|
||||
BridgeMasterPort* _masterPort,
|
||||
BridgeMasterPort& _masterPort,
|
||||
int _delay, int _nack_delay,
|
||||
int _resp_limit,
|
||||
std::vector<Range<Addr> > _ranges)
|
||||
@@ -63,24 +63,25 @@ Bridge::BridgeSlavePort::BridgeSlavePort(const std::string &_name,
|
||||
delay(_delay), nackDelay(_nack_delay),
|
||||
ranges(_ranges.begin(), _ranges.end()),
|
||||
outstandingResponses(0), inRetry(false),
|
||||
respQueueLimit(_resp_limit), sendEvent(this)
|
||||
respQueueLimit(_resp_limit), sendEvent(*this)
|
||||
{
|
||||
}
|
||||
|
||||
Bridge::BridgeMasterPort::BridgeMasterPort(const std::string &_name,
|
||||
Bridge* _bridge,
|
||||
BridgeSlavePort* _slavePort,
|
||||
BridgeSlavePort& _slavePort,
|
||||
int _delay, int _req_limit)
|
||||
: Port(_name, _bridge), bridge(_bridge), slavePort(_slavePort),
|
||||
delay(_delay), inRetry(false), reqQueueLimit(_req_limit), sendEvent(this)
|
||||
delay(_delay), inRetry(false), reqQueueLimit(_req_limit),
|
||||
sendEvent(*this)
|
||||
{
|
||||
}
|
||||
|
||||
Bridge::Bridge(Params *p)
|
||||
: MemObject(p),
|
||||
slavePort(p->name + "-slave", this, &masterPort, p->delay,
|
||||
slavePort(p->name + "-slave", this, masterPort, p->delay,
|
||||
p->nack_delay, p->resp_size, p->ranges),
|
||||
masterPort(p->name + "-master", this, &slavePort, p->delay, p->req_size),
|
||||
masterPort(p->name + "-master", this, slavePort, p->delay, p->req_size),
|
||||
ackWrites(p->write_ack), _params(p)
|
||||
{
|
||||
if (ackWrites)
|
||||
@@ -90,19 +91,14 @@ Bridge::Bridge(Params *p)
|
||||
Port*
|
||||
Bridge::getPort(const std::string &if_name, int idx)
|
||||
{
|
||||
Port* port;
|
||||
|
||||
if (if_name == "slave")
|
||||
port = &slavePort;
|
||||
return &slavePort;
|
||||
else if (if_name == "master")
|
||||
port = &masterPort;
|
||||
else
|
||||
return &masterPort;
|
||||
else {
|
||||
panic("Bridge %s has no port named %s\n", name(), if_name);
|
||||
return NULL;
|
||||
|
||||
if (port->getPeer() != NULL)
|
||||
panic("bridge side %s already connected to %s.",
|
||||
if_name, port->getPeer()->name());
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +144,7 @@ Bridge::BridgeMasterPort::recvTiming(PacketPtr pkt)
|
||||
|
||||
DPRINTF(BusBridge, "Request queue size: %d\n", requestQueue.size());
|
||||
|
||||
slavePort->queueForSendTiming(pkt);
|
||||
slavePort.queueForSendTiming(pkt);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -165,7 +161,7 @@ Bridge::BridgeSlavePort::recvTiming(PacketPtr pkt)
|
||||
DPRINTF(BusBridge, "Response queue size: %d outresp: %d\n",
|
||||
responseQueue.size(), outstandingResponses);
|
||||
|
||||
if (masterPort->reqQueueFull()) {
|
||||
if (masterPort.reqQueueFull()) {
|
||||
DPRINTF(BusBridge, "Request queue full, nacking\n");
|
||||
nackRequest(pkt);
|
||||
return true;
|
||||
@@ -187,7 +183,7 @@ Bridge::BridgeSlavePort::recvTiming(PacketPtr pkt)
|
||||
}
|
||||
}
|
||||
|
||||
masterPort->queueForSendTiming(pkt);
|
||||
masterPort.queueForSendTiming(pkt);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -422,7 +418,7 @@ Bridge::BridgeMasterPort::recvAtomic(PacketPtr pkt)
|
||||
Tick
|
||||
Bridge::BridgeSlavePort::recvAtomic(PacketPtr pkt)
|
||||
{
|
||||
return delay + masterPort->sendAtomic(pkt);
|
||||
return delay + masterPort.sendAtomic(pkt);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -450,14 +446,14 @@ Bridge::BridgeSlavePort::recvFunctional(PacketPtr pkt)
|
||||
}
|
||||
|
||||
// also check the master port's request queue
|
||||
if (masterPort->checkFunctional(pkt)) {
|
||||
if (masterPort.checkFunctional(pkt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pkt->popLabel();
|
||||
|
||||
// fall through if pkt still not satisfied
|
||||
masterPort->sendFunctional(pkt);
|
||||
masterPort.sendFunctional(pkt);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -131,10 +131,10 @@ class Bridge : public MemObject
|
||||
Bridge *bridge;
|
||||
|
||||
/**
|
||||
* Pointer to the master port on the other side of the bridge
|
||||
* Master port on the other side of the bridge
|
||||
* (connected to the other bus).
|
||||
*/
|
||||
BridgeMasterPort* masterPort;
|
||||
BridgeMasterPort& masterPort;
|
||||
|
||||
/** Minimum request delay though this bridge. */
|
||||
Tick delay;
|
||||
@@ -189,11 +189,11 @@ class Bridge : public MemObject
|
||||
*/
|
||||
class SendEvent : public Event
|
||||
{
|
||||
BridgeSlavePort *port;
|
||||
BridgeSlavePort& port;
|
||||
|
||||
public:
|
||||
SendEvent(BridgeSlavePort *p) : port(p) {}
|
||||
virtual void process() { port->trySend(); }
|
||||
SendEvent(BridgeSlavePort& p) : port(p) {}
|
||||
virtual void process() { port.trySend(); }
|
||||
virtual const char *description() const { return "bridge send"; }
|
||||
};
|
||||
|
||||
@@ -214,7 +214,7 @@ class Bridge : public MemObject
|
||||
* @param _ranges a number of address ranges to forward
|
||||
*/
|
||||
BridgeSlavePort(const std::string &_name, Bridge *_bridge,
|
||||
BridgeMasterPort* _masterPort, int _delay,
|
||||
BridgeMasterPort& _masterPort, int _delay,
|
||||
int _nack_delay, int _resp_limit,
|
||||
std::vector<Range<Addr> > _ranges);
|
||||
|
||||
@@ -272,7 +272,7 @@ class Bridge : public MemObject
|
||||
* Pointer to the slave port on the other side of the bridge
|
||||
* (connected to the other bus).
|
||||
*/
|
||||
BridgeSlavePort* slavePort;
|
||||
BridgeSlavePort& slavePort;
|
||||
|
||||
/** Minimum delay though this bridge. */
|
||||
Tick delay;
|
||||
@@ -303,11 +303,11 @@ class Bridge : public MemObject
|
||||
*/
|
||||
class SendEvent : public Event
|
||||
{
|
||||
BridgeMasterPort *port;
|
||||
BridgeMasterPort& port;
|
||||
|
||||
public:
|
||||
SendEvent(BridgeMasterPort *p) : port(p) {}
|
||||
virtual void process() { port->trySend(); }
|
||||
SendEvent(BridgeMasterPort& p) : port(p) {}
|
||||
virtual void process() { port.trySend(); }
|
||||
virtual const char *description() const { return "bridge send"; }
|
||||
};
|
||||
|
||||
@@ -326,7 +326,7 @@ class Bridge : public MemObject
|
||||
* @param _req_limit the size of the request queue
|
||||
*/
|
||||
BridgeMasterPort(const std::string &_name, Bridge *_bridge,
|
||||
BridgeSlavePort* _slavePort, int _delay,
|
||||
BridgeSlavePort& _slavePort, int _delay,
|
||||
int _req_limit);
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,6 +57,7 @@ Bus::Bus(const BusParams *p)
|
||||
: MemObject(p), busId(p->bus_id), clock(p->clock),
|
||||
headerCycles(p->header_cycles), width(p->width), tickNextIdle(0),
|
||||
drainEvent(NULL), busIdle(this), inRetry(false),
|
||||
nbrMasterPorts(p->port_master_connection_count),
|
||||
defaultPortId(INVALID_PORT_ID), useDefaultRange(p->use_default_range),
|
||||
defaultBlockSize(p->block_size),
|
||||
cachedBlockSize(0), cachedBlockSizeValid(false)
|
||||
@@ -68,27 +69,55 @@ Bus::Bus(const BusParams *p)
|
||||
fatal("Bus clock period must be positive\n");
|
||||
if (headerCycles <= 0)
|
||||
fatal("Number of header cycles must be positive\n");
|
||||
|
||||
// create the ports based on the size of the master and slave
|
||||
// vector ports, and the presence of the default master
|
||||
|
||||
// id used to index into interfaces which is a flat vector of all
|
||||
// ports
|
||||
int id = 0;
|
||||
for (int i = 0; i < p->port_master_connection_count; ++i) {
|
||||
std::string portName = csprintf("%s-p%d", name(), id);
|
||||
interfaces.push_back(new BusPort(portName, this, id));
|
||||
++id;
|
||||
}
|
||||
|
||||
// note that the first slave port is now stored on index
|
||||
// nbrMasterPorts in the vector
|
||||
for (int i = 0; i < p->port_slave_connection_count; ++i) {
|
||||
std::string portName = csprintf("%s-p%d", name(), id);
|
||||
interfaces.push_back(new BusPort(portName, this, id));
|
||||
++id;
|
||||
}
|
||||
|
||||
// see if we have a default master connected and if so add the
|
||||
// port at the end
|
||||
if (p->port_default_connection_count) {
|
||||
defaultPortId = id;
|
||||
std::string portName = csprintf("%s-default", name());
|
||||
interfaces.push_back(new BusPort(portName, this, id));
|
||||
++id;
|
||||
}
|
||||
|
||||
clearPortCache();
|
||||
}
|
||||
|
||||
Port *
|
||||
Bus::getPort(const std::string &if_name, int idx)
|
||||
{
|
||||
std::string portName;
|
||||
int id = interfaces.size();
|
||||
if (if_name == "default") {
|
||||
if (defaultPortId == INVALID_PORT_ID) {
|
||||
defaultPortId = id;
|
||||
portName = csprintf("%s-default", name());
|
||||
} else
|
||||
fatal("Default port already set on %s\n", name());
|
||||
if (if_name == "master") {
|
||||
// the master index translates directly to the interfaces
|
||||
// vector as they are stored first
|
||||
return interfaces[idx];
|
||||
} else if (if_name == "slave") {
|
||||
// the slaves are stored after the masters and we must thus
|
||||
// offset the slave index with the number of master ports
|
||||
return interfaces[nbrMasterPorts + idx];
|
||||
} else if (if_name == "default") {
|
||||
return interfaces[defaultPortId];
|
||||
} else {
|
||||
portName = csprintf("%s-p%d", name(), id);
|
||||
panic("No port %s %d on bus %s\n", if_name, idx, name());
|
||||
}
|
||||
BusPort *bp = new BusPort(portName, this, id);
|
||||
interfaces.push_back(bp);
|
||||
cachedBlockSizeValid = false;
|
||||
return bp;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -287,6 +287,11 @@ class Bus : public MemObject
|
||||
bool inRetry;
|
||||
std::set<int> inRecvRangeChange;
|
||||
|
||||
// keep track of the number of master ports (not counting the
|
||||
// default master) since we need this as an offset into the
|
||||
// interfaces vector
|
||||
unsigned int nbrMasterPorts;
|
||||
|
||||
/** An ordered vector of pointers to the peer port interfaces
|
||||
connected to this bus.*/
|
||||
std::vector<BusPort*> interfaces;
|
||||
|
||||
@@ -76,6 +76,12 @@ PhysicalMemory::PhysicalMemory(const Params *p)
|
||||
if (size() % TheISA::PageBytes != 0)
|
||||
panic("Memory Size not divisible by page size\n");
|
||||
|
||||
// create the appropriate number of ports
|
||||
for (int i = 0; i < p->port_port_connection_count; ++i) {
|
||||
ports.push_back(new MemoryPort(csprintf("%s-port%d", name(), i),
|
||||
this));
|
||||
}
|
||||
|
||||
if (params()->null)
|
||||
return;
|
||||
|
||||
@@ -109,13 +115,12 @@ PhysicalMemory::PhysicalMemory(const Params *p)
|
||||
void
|
||||
PhysicalMemory::init()
|
||||
{
|
||||
if (ports.size() == 0) {
|
||||
if (ports.empty()) {
|
||||
fatal("PhysicalMemory object %s is unconnected!", name());
|
||||
}
|
||||
|
||||
for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {
|
||||
if (*pi)
|
||||
(*pi)->sendRangeChange();
|
||||
(*pi)->sendRangeChange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,22 +443,14 @@ Port *
|
||||
PhysicalMemory::getPort(const std::string &if_name, int idx)
|
||||
{
|
||||
if (if_name != "port") {
|
||||
panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
|
||||
panic("PhysicalMemory::getPort: unknown port %s requested\n", if_name);
|
||||
}
|
||||
|
||||
if (idx >= (int)ports.size()) {
|
||||
ports.resize(idx + 1);
|
||||
if (idx >= static_cast<int>(ports.size())) {
|
||||
panic("PhysicalMemory::getPort: unknown index %d requested\n", idx);
|
||||
}
|
||||
|
||||
if (ports[idx] != NULL) {
|
||||
panic("PhysicalMemory::getPort: port %d already assigned", idx);
|
||||
}
|
||||
|
||||
MemoryPort *port =
|
||||
new MemoryPort(csprintf("%s-port%d", name(), idx), this);
|
||||
|
||||
ports[idx] = port;
|
||||
return port;
|
||||
return ports[idx];
|
||||
}
|
||||
|
||||
PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
|
||||
|
||||
@@ -35,7 +35,8 @@
|
||||
#include "mem/ruby/system/RubyPort.hh"
|
||||
|
||||
RubyPort::RubyPort(const Params *p)
|
||||
: MemObject(p)
|
||||
: MemObject(p), pio_port(csprintf("%s-pio-port", name()), this),
|
||||
physMemPort(csprintf("%s-physMemPort", name()), this)
|
||||
{
|
||||
m_version = p->version;
|
||||
assert(m_version != -1);
|
||||
@@ -46,8 +47,6 @@ RubyPort::RubyPort(const Params *p)
|
||||
m_mandatory_q_ptr = NULL;
|
||||
|
||||
m_request_cnt = 0;
|
||||
pio_port = NULL;
|
||||
physMemPort = NULL;
|
||||
|
||||
m_usingRubyTester = p->using_ruby_tester;
|
||||
access_phys_mem = p->access_phys_mem;
|
||||
@@ -87,21 +86,11 @@ RubyPort::getPort(const std::string &if_name, int idx)
|
||||
}
|
||||
|
||||
if (if_name == "pio_port") {
|
||||
// ensure there is only one pio port
|
||||
assert(pio_port == NULL);
|
||||
|
||||
pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx), this);
|
||||
|
||||
return pio_port;
|
||||
return &pio_port;
|
||||
}
|
||||
|
||||
if (if_name == "physMemPort") {
|
||||
// RubyPort should only have one port to physical memory
|
||||
assert (physMemPort == NULL);
|
||||
|
||||
physMemPort = new PioPort(csprintf("%s-physMemPort", name()), this);
|
||||
|
||||
return physMemPort;
|
||||
return &physMemPort;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -194,12 +183,12 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
|
||||
// Check for pio requests and directly send them to the dedicated
|
||||
// pio port.
|
||||
if (!isPhysMemAddress(pkt->getAddr())) {
|
||||
assert(ruby_port->pio_port != NULL);
|
||||
assert(ruby_port->pio_port.isConnected());
|
||||
DPRINTF(RubyPort,
|
||||
"Request for address 0x%#x is assumed to be a pio request\n",
|
||||
pkt->getAddr());
|
||||
|
||||
return ruby_port->pio_port->sendTiming(pkt);
|
||||
return ruby_port->pio_port.sendTiming(pkt);
|
||||
}
|
||||
|
||||
assert(Address(pkt->getAddr()).getOffset() + pkt->getSize() <=
|
||||
@@ -426,7 +415,7 @@ RubyPort::M5Port::recvFunctional(PacketPtr pkt)
|
||||
// Check for pio requests and directly send them to the dedicated
|
||||
// pio port.
|
||||
if (!isPhysMemAddress(pkt->getAddr())) {
|
||||
assert(ruby_port->pio_port != NULL);
|
||||
assert(ruby_port->pio_port.isConnected());
|
||||
DPRINTF(RubyPort, "Request for address 0x%#x is a pio request\n",
|
||||
pkt->getAddr());
|
||||
panic("RubyPort::PioPort::recvFunctional() not implemented!\n");
|
||||
@@ -461,7 +450,7 @@ RubyPort::M5Port::recvFunctional(PacketPtr pkt)
|
||||
// The following command performs the real functional access.
|
||||
// This line should be removed once Ruby supplies the official version
|
||||
// of data.
|
||||
ruby_port->physMemPort->sendFunctional(pkt);
|
||||
ruby_port->physMemPort.sendFunctional(pkt);
|
||||
}
|
||||
|
||||
// turn packet around to go back to requester if response expected
|
||||
@@ -554,12 +543,12 @@ RubyPort::getDrainCount(Event *de)
|
||||
// event should have been descheduled.
|
||||
assert(isDeadlockEventScheduled() == false);
|
||||
|
||||
if (pio_port != NULL) {
|
||||
count += pio_port->drain(de);
|
||||
if (pio_port.isConnected()) {
|
||||
count += pio_port.drain(de);
|
||||
DPRINTF(Config, "count after pio check %d\n", count);
|
||||
}
|
||||
if (physMemPort != NULL) {
|
||||
count += physMemPort->drain(de);
|
||||
if (physMemPort.isConnected()) {
|
||||
count += physMemPort.drain(de);
|
||||
DPRINTF(Config, "count after physmem check %d\n", count);
|
||||
}
|
||||
|
||||
@@ -640,7 +629,7 @@ RubyPort::M5Port::hitCallback(PacketPtr pkt)
|
||||
DPRINTF(RubyPort, "Hit callback needs response %d\n", needsResponse);
|
||||
|
||||
if (accessPhysMem) {
|
||||
ruby_port->physMemPort->sendAtomic(pkt);
|
||||
ruby_port->physMemPort.sendAtomic(pkt);
|
||||
} else if (needsResponse) {
|
||||
pkt->makeResponse();
|
||||
}
|
||||
@@ -675,7 +664,7 @@ bool
|
||||
RubyPort::M5Port::isPhysMemAddress(Addr addr)
|
||||
{
|
||||
AddrRangeList physMemAddrList =
|
||||
ruby_port->physMemPort->getPeer()->getAddrRanges();
|
||||
ruby_port->physMemPort.getPeer()->getAddrRanges();
|
||||
for (AddrRangeIter iter = physMemAddrList.begin();
|
||||
iter != physMemAddrList.end();
|
||||
iter++) {
|
||||
|
||||
@@ -137,7 +137,7 @@ class RubyPort : public MemObject
|
||||
int m_version;
|
||||
AbstractController* m_controller;
|
||||
MessageBuffer* m_mandatory_q_ptr;
|
||||
PioPort* pio_port;
|
||||
PioPort pio_port;
|
||||
bool m_usingRubyTester;
|
||||
|
||||
private:
|
||||
@@ -155,7 +155,7 @@ class RubyPort : public MemObject
|
||||
uint16_t m_port_id;
|
||||
uint64_t m_request_cnt;
|
||||
|
||||
PioPort* physMemPort;
|
||||
PioPort physMemPort;
|
||||
|
||||
/*! Vector of CPU Port attached to this Ruby port. */
|
||||
typedef std::vector<M5Port*>::iterator CpuPortIter;
|
||||
|
||||
Reference in New Issue
Block a user