diff -r 8eed4047889b -r 48f97059228b src/arch/arm/table_walker.hh --- a/src/arch/arm/table_walker.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/arch/arm/table_walker.hh Thu Mar 22 16:41:45 2012 +0000 @@ -358,7 +358,8 @@ virtual unsigned int drain(Event *de); virtual void resume(); - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort& getMasterPort(const std::string &if_name, + int idx = -1); Fault walk(RequestPtr req, ThreadContext *tc, uint8_t cid, TLB::Mode mode, TLB::Translation *_trans, bool timing, bool functional = false); diff -r 8eed4047889b -r 48f97059228b src/arch/arm/table_walker.cc --- a/src/arch/arm/table_walker.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/arch/arm/table_walker.cc Thu Mar 22 16:41:45 2012 +0000 @@ -91,13 +91,13 @@ } } -Port* -TableWalker::getPort(const std::string &if_name, int idx) +MasterPort& +TableWalker::getMasterPort(const std::string &if_name, int idx) { if (if_name == "port") { - return &port; + return port; } - return NULL; + return MemObject::getMasterPort(if_name, idx); } Fault diff -r 8eed4047889b -r 48f97059228b src/arch/arm/tlb.hh --- a/src/arch/arm/tlb.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/arch/arm/tlb.hh Thu Mar 22 16:41:45 2012 +0000 @@ -214,8 +214,17 @@ void regStats(); - // Get the port from the table walker and return it - virtual Port *getPort(); + /** + * Get the table walker master port. This is used for migrating + * port connections during a CPU takeOverFrom() call. For + * architectures that do not have a table walker, NULL is + * returned, hence the use of a pointer rather than a + * reference. For ARM this method will always return a valid port + * pointer. + * + * @return A pointer to the walker master port + */ + virtual MasterPort* getMasterPort(); // Caching misc register values here. // Writing to misc registers needs to invalidate them. diff -r 8eed4047889b -r 48f97059228b src/arch/arm/tlb.cc --- a/src/arch/arm/tlb.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/arch/arm/tlb.cc Thu Mar 22 16:41:45 2012 +0000 @@ -722,10 +722,10 @@ return fault; } -Port* -TLB::getPort() +MasterPort* +TLB::getMasterPort() { - return tableWalker->getPort("port"); + return &tableWalker->getMasterPort("port"); } diff -r 8eed4047889b -r 48f97059228b src/arch/x86/interrupts.hh --- a/src/arch/x86/interrupts.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/arch/x86/interrupts.hh Thu Mar 22 16:41:45 2012 +0000 @@ -189,7 +189,7 @@ int initialApicId; // Port for receiving interrupts - IntPort intSlavePort; + IntSlavePort intSlavePort; public: @@ -239,17 +239,20 @@ AddrRangeList getAddrRanges(); AddrRangeList getIntAddrRange(); - Port *getPort(const std::string &if_name, int idx = -1) + MasterPort &getMasterPort(const std::string &if_name, int idx = -1) { - // a bit of an odd one since there is now two ports in the - // Python class we also need two ports even if they are - // identical if (if_name == "int_master") { - return &intPort; - } else if (if_name == "int_slave") { - return &intSlavePort; + return intMasterPort; } - return BasicPioDevice::getPort(if_name, idx); + return BasicPioDevice::getMasterPort(if_name, idx); + } + + SlavePort &getSlavePort(const std::string &if_name, int idx = -1) + { + if (if_name == "int_slave") { + return intSlavePort; + } + return BasicPioDevice::getSlavePort(if_name, idx); } /* diff -r 8eed4047889b -r 48f97059228b src/arch/x86/interrupts.cc --- a/src/arch/x86/interrupts.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/arch/x86/interrupts.cc Thu Mar 22 16:41:45 2012 +0000 @@ -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) 2008 The Hewlett-Packard Development Company * All rights reserved. * @@ -304,6 +316,9 @@ // BasicPioDevice::init(); IntDev::init(); + + // the slave port has a range so inform the connected master + intSlavePort.sendRangeChange(); } @@ -554,7 +569,7 @@ break; } pendingIPIs += apics.size(); - intPort.sendMessage(apics, message, timing); + intMasterPort.sendMessage(apics, message, timing); newVal = regs[APIC_INTERRUPT_COMMAND_LOW]; } break; diff -r 8eed4047889b -r 48f97059228b src/arch/x86/pagetable_walker.hh --- a/src/arch/x86/pagetable_walker.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/arch/x86/pagetable_walker.hh Thu Mar 22 16:41:45 2012 +0000 @@ -60,11 +60,11 @@ { protected: // Port for accessing memory - class WalkerPort : public Port + class WalkerPort : public MasterPort { public: WalkerPort(const std::string &_name, Walker * _walker) : - Port(_name, _walker), walker(_walker) + MasterPort(_name, _walker), walker(_walker) {} protected: @@ -73,9 +73,8 @@ bool recvTiming(PacketPtr pkt); Tick recvAtomic(PacketPtr pkt); void recvFunctional(PacketPtr pkt); - void recvRangeChange(); void recvRetry(); - bool isSnooping() { return true; } + bool isSnooping() const { return true; } }; friend class WalkerPort; @@ -166,7 +165,7 @@ RequestPtr req, BaseTLB::Mode mode); Fault startFunctional(ThreadContext * _tc, Addr &addr, Addr &pageSize, BaseTLB::Mode mode); - Port *getPort(const std::string &if_name, int idx = -1); + MasterPort &getMasterPort(const std::string &if_name, int idx = -1); protected: // The TLB we're supposed to load. diff -r 8eed4047889b -r 48f97059228b src/arch/x86/pagetable_walker.cc --- a/src/arch/x86/pagetable_walker.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/arch/x86/pagetable_walker.cc Thu Mar 22 16:41:45 2012 +0000 @@ -154,11 +154,6 @@ } void -Walker::WalkerPort::recvRangeChange() -{ -} - -void Walker::WalkerPort::recvRetry() { walker->recvRetry(); @@ -182,13 +177,13 @@ return port.sendTiming(pkt); } -Port * -Walker::getPort(const std::string &if_name, int idx) +MasterPort & +Walker::getMasterPort(const std::string &if_name, int idx) { if (if_name == "port") - return &port; + return port; else - panic("No page table walker port named %s!\n", if_name); + return MemObject::getMasterPort(if_name, idx); } void diff -r 8eed4047889b -r 48f97059228b src/arch/x86/tlb.hh --- a/src/arch/x86/tlb.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/arch/x86/tlb.hh Thu Mar 22 16:41:45 2012 +0000 @@ -125,7 +125,17 @@ virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); - virtual Port * getPort(); + /** + * Get the table walker master port. This is used for + * migrating port connections during a CPU takeOverFrom() + * call. For architectures that do not have a table walker, + * NULL is returned, hence the use of a pointer rather than a + * reference. For X86 this method will always return a valid + * port pointer. + * + * @return A pointer to the walker master port + */ + virtual MasterPort *getMasterPort(); }; } diff -r 8eed4047889b -r 48f97059228b src/arch/x86/tlb.cc --- a/src/arch/x86/tlb.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/arch/x86/tlb.cc Thu Mar 22 16:41:45 2012 +0000 @@ -428,10 +428,10 @@ { } -Port * -TLB::getPort() +MasterPort * +TLB::getMasterPort() { - return walker->getPort("port"); + return &walker->getMasterPort("port"); } } // namespace X86ISA diff -r 8eed4047889b -r 48f97059228b src/cpu/base.hh --- a/src/cpu/base.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/base.hh Thu Mar 22 16:41:45 2012 +0000 @@ -117,7 +117,7 @@ * both atomic and timing access is to panic and the corresponding * subclasses have to override these methods. */ - class CpuPort : public Port + class CpuPort : public MasterPort { public: @@ -128,7 +128,7 @@ * @param _name structural owner of this port */ CpuPort(const std::string& _name, MemObject* _owner) : - Port(_name, _owner) + MasterPort(_name, _owner) { } protected: @@ -141,8 +141,6 @@ void recvFunctional(PacketPtr pkt); - void recvRangeChange(); - }; public: @@ -172,11 +170,11 @@ MasterID instMasterId() { return _instMasterId; } /** - * Get a port on this MemObject. This method is virtual to allow + * Get a master port on this MemObject. This method is virtual to allow * the subclasses of the BaseCPU to override it. All CPUs have a * data and instruction port, but the Atomic CPU (in its current * form) adds a port directly connected to the memory and has to - * override getPort. + * override getMasterPort. * * This method uses getDataPort and getInstPort to resolve the two * ports. @@ -184,9 +182,10 @@ * @param if_name the port name * @param idx ignored index * - * @return a pointer to the port with the given name + * @return a reference to the port with the given name */ - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort &getMasterPort(const std::string &if_name, + int idx = -1); // Tick currentTick; inline Tick frequency() const { return SimClock::Frequency / clock; } diff -r 8eed4047889b -r 48f97059228b src/cpu/base.cc --- a/src/cpu/base.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/base.cc Thu Mar 22 16:41:45 2012 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -299,19 +299,19 @@ threadContexts[0]->regStats(name()); } -Port * -BaseCPU::getPort(const string &if_name, int idx) +MasterPort & +BaseCPU::getMasterPort(const string &if_name, int idx) { // Get the right port based on name. This applies to all the // subclasses of the base CPU and relies on their implementation // of getDataPort and getInstPort. In all cases there methods // return a CpuPort pointer. if (if_name == "dcache_port") - return &getDataPort(); + return getDataPort(); else if (if_name == "icache_port") - return &getInstPort(); + return getInstPort(); else - panic("CPU %s has no port named %s\n", name(), if_name); + return MemObject::getMasterPort(if_name, idx); } Tick @@ -381,8 +381,6 @@ void BaseCPU::takeOverFrom(BaseCPU *oldCPU) { - CpuPort &ic = getInstPort(); - CpuPort &dc = getDataPort(); assert(threadContexts.size() == oldCPU->threadContexts.size()); _cpuId = oldCPU->cpuId(); @@ -407,24 +405,21 @@ ThreadContext::compare(oldTC, newTC); */ - Port *old_itb_port, *old_dtb_port, *new_itb_port, *new_dtb_port; - old_itb_port = oldTC->getITBPtr()->getPort(); - old_dtb_port = oldTC->getDTBPtr()->getPort(); - new_itb_port = newTC->getITBPtr()->getPort(); - new_dtb_port = newTC->getDTBPtr()->getPort(); + MasterPort *old_itb_port = oldTC->getITBPtr()->getMasterPort(); + MasterPort *old_dtb_port = oldTC->getDTBPtr()->getMasterPort(); + MasterPort *new_itb_port = newTC->getITBPtr()->getMasterPort(); + MasterPort *new_dtb_port = newTC->getDTBPtr()->getMasterPort(); // Move over any table walker ports if they exist if (new_itb_port && !new_itb_port->isConnected()) { assert(old_itb_port); - Port *peer = old_itb_port->getPeer();; - new_itb_port->setPeer(peer); - peer->setPeer(new_itb_port); + SlavePort &slavePort = old_itb_port->getSlavePort(); + new_itb_port->bind(slavePort); } if (new_dtb_port && !new_dtb_port->isConnected()) { assert(old_dtb_port); - Port *peer = old_dtb_port->getPeer();; - new_dtb_port->setPeer(peer); - peer->setPeer(new_dtb_port); + SlavePort &slavePort = old_dtb_port->getSlavePort(); + new_dtb_port->bind(slavePort); } // Checker whether or not we have to transfer CheckerCPU @@ -432,26 +427,25 @@ CheckerCPU *oldChecker = oldTC->getCheckerCpuPtr(); CheckerCPU *newChecker = newTC->getCheckerCpuPtr(); if (oldChecker && newChecker) { - Port *old_checker_itb_port, *old_checker_dtb_port; - Port *new_checker_itb_port, *new_checker_dtb_port; - - old_checker_itb_port = oldChecker->getITBPtr()->getPort(); - old_checker_dtb_port = oldChecker->getDTBPtr()->getPort(); - new_checker_itb_port = newChecker->getITBPtr()->getPort(); - new_checker_dtb_port = newChecker->getDTBPtr()->getPort(); + MasterPort *old_checker_itb_port = + oldChecker->getITBPtr()->getMasterPort(); + MasterPort *old_checker_dtb_port = + oldChecker->getDTBPtr()->getMasterPort(); + MasterPort *new_checker_itb_port = + newChecker->getITBPtr()->getMasterPort(); + MasterPort *new_checker_dtb_port = + newChecker->getDTBPtr()->getMasterPort(); // Move over any table walker ports if they exist for checker if (new_checker_itb_port && !new_checker_itb_port->isConnected()) { assert(old_checker_itb_port); - Port *peer = old_checker_itb_port->getPeer();; - new_checker_itb_port->setPeer(peer); - peer->setPeer(new_checker_itb_port); + SlavePort &slavePort = old_checker_itb_port->getSlavePort();; + new_checker_itb_port->bind(slavePort); } if (new_checker_dtb_port && !new_checker_dtb_port->isConnected()) { assert(old_checker_dtb_port); - Port *peer = old_checker_dtb_port->getPeer();; - new_checker_dtb_port->setPeer(peer); - peer->setPeer(new_checker_dtb_port); + SlavePort &slavePort = old_checker_dtb_port->getSlavePort();; + new_checker_dtb_port->bind(slavePort); } } } @@ -470,16 +464,12 @@ // Connect new CPU to old CPU's memory only if new CPU isn't // connected to anything. Also connect old CPU's memory to new // CPU. - if (!ic.isConnected()) { - Port *peer = oldCPU->getInstPort().getPeer(); - ic.setPeer(peer); - peer->setPeer(&ic); + if (!getInstPort().isConnected()) { + getInstPort().bind(oldCPU->getInstPort().getSlavePort()); } - if (!dc.isConnected()) { - Port *peer = oldCPU->getDataPort().getPeer(); - dc.setPeer(peer); - peer->setPeer(&dc); + if (!getDataPort().isConnected()) { + getDataPort().bind(oldCPU->getDataPort().getSlavePort()); } } @@ -568,8 +558,3 @@ // long term this should never be called, but that assumed a split // into master/slave and request/response. } - -void -BaseCPU::CpuPort::recvRangeChange() -{ -} diff -r 8eed4047889b -r 48f97059228b src/cpu/checker/cpu.hh --- a/src/cpu/checker/cpu.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/checker/cpu.hh Thu Mar 22 16:41:45 2012 +0000 @@ -132,12 +132,6 @@ return *icachePort; } - virtual Port *getPort(const std::string &name, int idx) - { - panic("Not supported on checker!"); - return NULL; - } - public: // Primary thread being run. SimpleThread *thread; diff -r 8eed4047889b -r 48f97059228b src/cpu/inorder/resources/cache_unit.hh --- a/src/cpu/inorder/resources/cache_unit.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/inorder/resources/cache_unit.hh Thu Mar 22 16:41:45 2012 +0000 @@ -139,7 +139,7 @@ protected: /** Cache interface. */ - Port *cachePort; + MasterPort *cachePort; bool cachePortBlocked; diff -r 8eed4047889b -r 48f97059228b src/cpu/o3/cpu.hh --- a/src/cpu/o3/cpu.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/o3/cpu.hh Thu Mar 22 16:41:45 2012 +0000 @@ -186,8 +186,7 @@ * * @return true since we have to snoop */ - virtual bool isSnooping() - { return true; } + virtual bool isSnooping() const { return true; } }; class TickEvent : public Event diff -r 8eed4047889b -r 48f97059228b src/cpu/o3/lsq_unit.hh --- a/src/cpu/o3/lsq_unit.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/o3/lsq_unit.hh Thu Mar 22 16:41:45 2012 +0000 @@ -90,7 +90,7 @@ void regStats(); /** Sets the pointer to the dcache port. */ - void setDcachePort(Port *dcache_port); + void setDcachePort(MasterPort *dcache_port); /** Switches out LSQ unit. */ void switchOut(); @@ -268,7 +268,7 @@ LSQ *lsq; /** Pointer to the dcache port. Used only for sending. */ - Port *dcachePort; + MasterPort *dcachePort; /** Derived class to hold any sender state the LSQ needs. */ class LSQSenderState : public Packet::SenderState, public FastAlloc diff -r 8eed4047889b -r 48f97059228b src/cpu/o3/lsq_unit_impl.hh --- a/src/cpu/o3/lsq_unit_impl.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/o3/lsq_unit_impl.hh Thu Mar 22 16:41:45 2012 +0000 @@ -239,7 +239,7 @@ template void -LSQUnit::setDcachePort(Port *dcache_port) +LSQUnit::setDcachePort(MasterPort *dcache_port) { dcachePort = dcache_port; } diff -r 8eed4047889b -r 48f97059228b src/cpu/ozone/OzoneCPU.py --- a/src/cpu/ozone/OzoneCPU.py Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/ozone/OzoneCPU.py Thu Mar 22 16:41:45 2012 +0000 @@ -36,9 +36,6 @@ numThreads = Param.Unsigned("number of HW thread contexts") - icache_port = Port("Instruction Port") - dcache_port = Port("Data Port") - width = Param.Unsigned("Width") frontEndWidth = Param.Unsigned("Front end width") frontEndLatency = Param.Unsigned("Front end latency") diff -r 8eed4047889b -r 48f97059228b src/cpu/ozone/cpu.hh --- a/src/cpu/ozone/cpu.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/ozone/cpu.hh Thu Mar 22 16:41:45 2012 +0000 @@ -316,8 +316,6 @@ System *system; PhysicalMemory *physmem; - virtual Port *getPort(const std::string &name, int idx); - FrontEnd *frontEnd; BackEnd *backEnd; diff -r 8eed4047889b -r 48f97059228b src/cpu/ozone/cpu_impl.hh --- a/src/cpu/ozone/cpu_impl.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/ozone/cpu_impl.hh Thu Mar 22 16:41:45 2012 +0000 @@ -391,18 +391,6 @@ } template -Port * -OzoneCPU::getPort(const std::string &if_name, int idx) -{ - if (if_name == "dcache_port") - return backEnd->getDcachePort(); - else if (if_name == "icache_port") - return frontEnd->getIcachePort(); - else - panic("No Such Port\n"); -} - -template void OzoneCPU::serialize(std::ostream &os) { diff -r 8eed4047889b -r 48f97059228b src/cpu/ozone/front_end.hh --- a/src/cpu/ozone/front_end.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/ozone/front_end.hh Thu Mar 22 16:41:45 2012 +0000 @@ -68,7 +68,7 @@ /** IcachePort class. Handles doing the communication with the * cache/memory. */ - class IcachePort : public Port + class IcachePort : public MasterPort { protected: /** Pointer to FE. */ @@ -87,9 +87,6 @@ /** Functional version of receive. Panics. */ virtual void recvFunctional(PacketPtr pkt); - /** Receives range change. */ - virtual void recvRangeChange(); - /** Timing version of receive. Handles setting fetch to the * proper status to start fetching. */ virtual bool recvTiming(PacketPtr pkt); diff -r 8eed4047889b -r 48f97059228b src/cpu/ozone/front_end_impl.hh --- a/src/cpu/ozone/front_end_impl.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/ozone/front_end_impl.hh Thu Mar 22 16:41:45 2012 +0000 @@ -59,12 +59,6 @@ } template -void -FrontEnd::IcachePort::recvRangeChange() -{ -} - -template bool FrontEnd::IcachePort::recvTiming(PacketPtr pkt) { diff -r 8eed4047889b -r 48f97059228b src/cpu/ozone/lw_lsq.hh --- a/src/cpu/ozone/lw_lsq.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/ozone/lw_lsq.hh Thu Mar 22 16:41:45 2012 +0000 @@ -240,7 +240,7 @@ /** Pointer to the back-end stage. */ BackEnd *be; - class DcachePort : public Port + class DcachePort : public MasterPort { protected: OzoneLWLSQ *lsq; @@ -255,13 +255,10 @@ virtual void recvFunctional(PacketPtr pkt); - virtual void recvRangeChange(); - /** * Is a snooper due to LSQ maintenance */ - virtual bool isSnooping() - { return true; } + virtual bool isSnooping() const { return true; } virtual bool recvTiming(PacketPtr pkt); diff -r 8eed4047889b -r 48f97059228b src/cpu/ozone/lw_lsq_impl.hh --- a/src/cpu/ozone/lw_lsq_impl.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/ozone/lw_lsq_impl.hh Thu Mar 22 16:41:45 2012 +0000 @@ -75,12 +75,6 @@ } template -void -OzoneLWLSQ::DcachePort::recvRangeChange() -{ -} - -template bool OzoneLWLSQ::DcachePort::recvTiming(PacketPtr pkt) { diff -r 8eed4047889b -r 48f97059228b src/cpu/simple/atomic.hh --- a/src/cpu/simple/atomic.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/simple/atomic.hh Thu Mar 22 16:41:45 2012 +0000 @@ -112,10 +112,11 @@ public: /** - * Override the getPort of the BaseCPU so that we can provide a pointer - * to the physmemPort, unique to the Atomic CPU. + * Override the getMasterPort of the BaseCPU so that we can + * provide the physmemPort, unique to the Atomic CPU. */ - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort &getMasterPort(const std::string &if_name, + int idx = -1); virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); diff -r 8eed4047889b -r 48f97059228b src/cpu/simple/atomic.cc --- a/src/cpu/simple/atomic.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/simple/atomic.cc Thu Mar 22 16:41:45 2012 +0000 @@ -65,14 +65,14 @@ return "AtomicSimpleCPU tick"; } -Port * -AtomicSimpleCPU::getPort(const string &if_name, int idx) +MasterPort & +AtomicSimpleCPU::getMasterPort(const string &if_name, int idx) { if (if_name == "physmem_port") { hasPhysMemPort = true; - return &physmemPort; + return physmemPort; } else { - return BaseCPU::getPort(if_name, idx); + return BaseCPU::getMasterPort(if_name, idx); } } @@ -93,7 +93,7 @@ tcBase()->initMemProxies(tcBase()); if (hasPhysMemPort) { - AddrRangeList pmAddrList = physmemPort.getPeer()->getAddrRanges(); + AddrRangeList pmAddrList = physmemPort.getSlavePort().getAddrRanges(); physMemAddr = *pmAddrList.begin(); } // Atomic doesn't do MT right now, so contextId == threadId diff -r 8eed4047889b -r 48f97059228b src/cpu/testers/directedtest/RubyDirectedTester.hh --- a/src/cpu/testers/directedtest/RubyDirectedTester.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/testers/directedtest/RubyDirectedTester.hh Thu Mar 22 16:41:45 2012 +0000 @@ -47,7 +47,7 @@ class RubyDirectedTester : public MemObject { public: - class CpuPort : public Port + class CpuPort : public MasterPort { private: RubyDirectedTester *tester; @@ -55,25 +55,27 @@ public: CpuPort(const std::string &_name, RubyDirectedTester *_tester, uint32_t _idx) - : Port(_name, _tester), tester(_tester), idx(_idx) + : MasterPort(_name, _tester), tester(_tester), idx(_idx) {} uint32_t idx; protected: virtual bool recvTiming(PacketPtr pkt); + virtual void recvRetry() + { panic("%s does not expect a retry\n", name()); } virtual Tick recvAtomic(PacketPtr pkt); virtual void recvFunctional(PacketPtr pkt) { } - virtual void recvRangeChange() { } }; typedef RubyDirectedTesterParams Params; RubyDirectedTester(const Params *p); ~RubyDirectedTester(); - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort &getMasterPort(const std::string &if_name, + int idx = -1); - Port* getCpuPort(int idx); + MasterPort* getCpuPort(int idx); virtual void init(); diff -r 8eed4047889b -r 48f97059228b src/cpu/testers/directedtest/RubyDirectedTester.cc --- a/src/cpu/testers/directedtest/RubyDirectedTester.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/testers/directedtest/RubyDirectedTester.cc Thu Mar 22 16:41:45 2012 +0000 @@ -75,19 +75,19 @@ generator->setDirectedTester(this); } -Port * -RubyDirectedTester::getPort(const std::string &if_name, int idx) +MasterPort & +RubyDirectedTester::getMasterPort(const std::string &if_name, int idx) { if (if_name != "cpuPort") { - panic("RubyDirectedTester::getPort: unknown port %s requested", - if_name); + // pass it along to our super class + return MemObject::getMasterPort(if_name, idx); + } else { + if (idx >= static_cast(ports.size())) { + panic("RubyDirectedTester::getMasterPort: unknown index %d\n", idx); + } + + return *ports[idx]; } - - if (idx >= static_cast(ports.size())) { - panic("RubyDirectedTester::getPort: unknown index %d requested\n", idx); - } - - return ports[idx]; } Tick @@ -110,7 +110,7 @@ return true; } -Port* +MasterPort* RubyDirectedTester::getCpuPort(int idx) { assert(idx >= 0 && idx < ports.size()); diff -r 8eed4047889b -r 48f97059228b src/cpu/testers/memtest/memtest.hh --- a/src/cpu/testers/memtest/memtest.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/testers/memtest/memtest.hh Thu Mar 22 16:41:45 2012 +0000 @@ -62,7 +62,8 @@ // main simulation loop (one cycle) void tick(); - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort &getMasterPort(const std::string &if_name, + int idx = -1); /** * Print state of address in memory system via PrintReq (for @@ -84,14 +85,14 @@ TickEvent tickEvent; - class CpuPort : public Port + class CpuPort : public MasterPort { MemTest *memtest; public: CpuPort(const std::string &_name, MemTest *_memtest) - : Port(_name, _memtest), memtest(_memtest) + : MasterPort(_name, _memtest), memtest(_memtest) { } protected: @@ -102,8 +103,6 @@ virtual void recvFunctional(PacketPtr pkt); - virtual void recvRangeChange(); - virtual void recvRetry(); }; diff -r 8eed4047889b -r 48f97059228b src/cpu/testers/memtest/memtest.cc --- a/src/cpu/testers/memtest/memtest.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/testers/memtest/memtest.cc Thu Mar 22 16:41:45 2012 +0000 @@ -85,11 +85,6 @@ } void -MemTest::CpuPort::recvRangeChange() -{ -} - -void MemTest::CpuPort::recvRetry() { memtest->doRetry(); @@ -161,15 +156,15 @@ dmaOutstanding = false; } -Port * -MemTest::getPort(const std::string &if_name, int idx) +MasterPort & +MemTest::getMasterPort(const std::string &if_name, int idx) { if (if_name == "functional") - return &funcPort; + return funcPort; else if (if_name == "test") - return &cachePort; + return cachePort; else - panic("No Such Port\n"); + return MemObject::getMasterPort(if_name, idx); } void diff -r 8eed4047889b -r 48f97059228b src/cpu/testers/networktest/networktest.hh --- a/src/cpu/testers/networktest/networktest.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/testers/networktest/networktest.hh Thu Mar 22 16:41:45 2012 +0000 @@ -57,7 +57,8 @@ // main simulation loop (one cycle) void tick(); - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort &getMasterPort(const std::string &if_name, + int idx = -1); /** * Print state of address in memory system via PrintReq (for @@ -79,14 +80,14 @@ TickEvent tickEvent; - class CpuPort : public Port + class CpuPort : public MasterPort { NetworkTest *networktest; public: CpuPort(const std::string &_name, NetworkTest *_networktest) - : Port(_name, _networktest), networktest(_networktest) + : MasterPort(_name, _networktest), networktest(_networktest) { } protected: @@ -97,8 +98,6 @@ virtual void recvFunctional(PacketPtr pkt); - virtual void recvRangeChange(); - virtual void recvRetry(); }; diff -r 8eed4047889b -r 48f97059228b src/cpu/testers/networktest/networktest.cc --- a/src/cpu/testers/networktest/networktest.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/testers/networktest/networktest.cc Thu Mar 22 16:41:45 2012 +0000 @@ -82,11 +82,6 @@ } void -NetworkTest::CpuPort::recvRangeChange() -{ -} - -void NetworkTest::CpuPort::recvRetry() { networktest->doRetry(); @@ -126,13 +121,13 @@ name(), id); } -Port * -NetworkTest::getPort(const std::string &if_name, int idx) +MasterPort & +NetworkTest::getMasterPort(const std::string &if_name, int idx) { if (if_name == "test") - return &cachePort; + return cachePort; else - panic("No Such Port\n"); + return MemObject::getMasterPort(if_name, idx); } void diff -r 8eed4047889b -r 48f97059228b src/cpu/testers/rubytest/RubyTester.hh --- a/src/cpu/testers/rubytest/RubyTester.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/testers/rubytest/RubyTester.hh Thu Mar 22 16:41:45 2012 +0000 @@ -45,23 +45,24 @@ class RubyTester : public MemObject { public: - class CpuPort : public Port + class CpuPort : public MasterPort { private: RubyTester *tester; public: CpuPort(const std::string &_name, RubyTester *_tester, int _idx) - : Port(_name, _tester), tester(_tester), idx(_idx) + : MasterPort(_name, _tester), tester(_tester), idx(_idx) {} int idx; protected: virtual bool recvTiming(PacketPtr pkt); + virtual void recvRetry() + { panic("%s does not expect a retry\n", name()); } virtual Tick recvAtomic(PacketPtr pkt); virtual void recvFunctional(PacketPtr pkt) { } - virtual void recvRangeChange() { } }; struct SenderState : public Packet::SenderState @@ -86,9 +87,10 @@ RubyTester(const Params *p); ~RubyTester(); - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort &getMasterPort(const std::string &if_name, + int idx = -1); - Port* getCpuPort(int idx); + MasterPort* getCpuPort(int idx); virtual void init(); diff -r 8eed4047889b -r 48f97059228b src/cpu/testers/rubytest/RubyTester.cc --- a/src/cpu/testers/rubytest/RubyTester.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/cpu/testers/rubytest/RubyTester.cc Thu Mar 22 16:41:45 2012 +0000 @@ -92,18 +92,19 @@ m_checkTable_ptr = new CheckTable(m_num_cpu_sequencers, this); } -Port * -RubyTester::getPort(const std::string &if_name, int idx) +MasterPort & +RubyTester::getMasterPort(const std::string &if_name, int idx) { if (if_name != "cpuPort") { - panic("RubyTester::getPort: unknown port %s requested\n", if_name); + // pass it along to our super class + return MemObject::getMasterPort(if_name, idx); + } else { + if (idx >= static_cast(ports.size())) { + panic("RubyTester::getMasterPort: unknown index %d\n", idx); + } + + return *ports[idx]; } - - if (idx >= static_cast(ports.size())) { - panic("RubyTester::getPort: unknown index %d requested\n", idx); - } - - return ports[idx]; } Tick @@ -135,7 +136,7 @@ return true; } -Port* +MasterPort* RubyTester::getCpuPort(int idx) { assert(idx >= 0 && idx < ports.size()); diff -r 8eed4047889b -r 48f97059228b src/dev/copy_engine.hh --- a/src/dev/copy_engine.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/dev/copy_engine.hh Thu Mar 22 16:41:45 2012 +0000 @@ -94,7 +94,7 @@ public: CopyEngineChannel(CopyEngine *_ce, int cid); virtual ~CopyEngineChannel(); - Port *getPort(); + MasterPort &getMasterPort(); std::string name() { assert(ce); return ce->name() + csprintf("-chan%d", channelId); } virtual Tick read(PacketPtr pkt) @@ -196,7 +196,8 @@ void regStats(); - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort &getMasterPort(const std::string &if_name, + int idx = -1); virtual Tick read(PacketPtr pkt); virtual Tick write(PacketPtr pkt); diff -r 8eed4047889b -r 48f97059228b src/dev/copy_engine.cc --- a/src/dev/copy_engine.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/dev/copy_engine.cc Thu Mar 22 16:41:45 2012 +0000 @@ -110,21 +110,26 @@ delete [] copyBuffer; } -Port * -CopyEngine::getPort(const std::string &if_name, int idx) +MasterPort & +CopyEngine::getMasterPort(const std::string &if_name, int idx) { - if (if_name == "dma") { - if (idx < chan.size()) - return chan[idx]->getPort(); + if (if_name != "dma") { + // pass it along to our super class + return PciDev::getMasterPort(if_name, idx); + } else { + if (idx >= static_cast(chan.size())) { + panic("CopyEngine::getMasterPort: unknown index %d\n", idx); + } + + return chan[idx]->getMasterPort(); } - return PciDev::getPort(if_name, idx); } -Port * -CopyEngine::CopyEngineChannel::getPort() +MasterPort & +CopyEngine::CopyEngineChannel::getMasterPort() { - return &cePort; + return cePort; } void diff -r 8eed4047889b -r 48f97059228b src/dev/io_device.hh --- a/src/dev/io_device.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/dev/io_device.hh Thu Mar 22 16:41:45 2012 +0000 @@ -69,7 +69,7 @@ }; -class DmaPort : public Port +class DmaPort : public MasterPort { protected: struct DmaReqState : public Packet::SenderState, public FastAlloc @@ -148,16 +148,9 @@ panic("dma port shouldn't be used for pio access."); } - virtual void recvRangeChange() - { - // 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 bool isSnooping() - { return recvSnoops; } + virtual bool isSnooping() const { return recvSnoops; } void queueDma(PacketPtr pkt, bool front = false); void sendDma(); @@ -231,7 +224,7 @@ virtual unsigned int drain(Event *de); - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1); friend class PioPort; @@ -304,7 +297,8 @@ unsigned cacheBlockSize() const { return dmaPort.cacheBlockSize(); } - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort &getMasterPort(const std::string &if_name, + int idx = -1); friend class DmaPort; }; diff -r 8eed4047889b -r 48f97059228b src/dev/io_device.cc --- a/src/dev/io_device.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/dev/io_device.cc Thu Mar 22 16:41:45 2012 +0000 @@ -71,14 +71,13 @@ pioPort.sendRangeChange(); } -Port * -PioDevice::getPort(const std::string &if_name, int idx) +SlavePort & +PioDevice::getSlavePort(const std::string &if_name, int idx) { if (if_name == "pio") { - return &pioPort; + return pioPort; } - panic("PioDevice %s has no port named %s\n", name(), if_name); - return NULL; + return MemObject::getSlavePort(if_name, idx); } unsigned int @@ -111,7 +110,7 @@ DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff, bool recv_snoops) - : Port(dev->name() + "-dmaport", dev), device(dev), sys(s), + : MasterPort(dev->name() + "-dmaport", dev), device(dev), sys(s), masterId(s->getMasterId(dev->name())), pendingCount(0), actionInProgress(0), drainEvent(NULL), backoffTime(0), minBackoffDelay(min_backoff), @@ -370,12 +369,12 @@ } -Port * -DmaDevice::getPort(const std::string &if_name, int idx) +MasterPort & +DmaDevice::getMasterPort(const std::string &if_name, int idx) { if (if_name == "dma") { - return &dmaPort; + return dmaPort; } - return PioDevice::getPort(if_name, idx); + return PioDevice::getMasterPort(if_name, idx); } diff -r 8eed4047889b -r 48f97059228b src/dev/pcidev.hh --- a/src/dev/pcidev.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/dev/pcidev.hh Thu Mar 22 16:41:45 2012 +0000 @@ -218,12 +218,12 @@ virtual unsigned int drain(Event *de); - virtual Port *getPort(const std::string &if_name, int idx = -1) + virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1) { if (if_name == "config") { - return &configPort; + return configPort; } - return DmaDevice::getPort(if_name, idx); + return DmaDevice::getSlavePort(if_name, idx); } }; diff -r 8eed4047889b -r 48f97059228b src/dev/x86/i82094aa.hh --- a/src/dev/x86/i82094aa.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/dev/x86/i82094aa.hh Thu Mar 22 16:41:45 2012 +0000 @@ -121,11 +121,11 @@ void writeReg(uint8_t offset, uint32_t value); uint32_t readReg(uint8_t offset); - Port *getPort(const std::string &if_name, int idx = -1) + MasterPort &getMasterPort(const std::string &if_name, int idx = -1) { if (if_name == "int_master") - return &intPort; - return PioDevice::getPort(if_name, idx); + return intMasterPort; + return PioDevice::getMasterPort(if_name, idx); } void signalInterrupt(int line); diff -r 8eed4047889b -r 48f97059228b src/dev/x86/i82094aa.cc --- a/src/dev/x86/i82094aa.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/dev/x86/i82094aa.cc Thu Mar 22 16:41:45 2012 +0000 @@ -222,8 +222,8 @@ apics.push_back(selected); } } - intPort.sendMessage(apics, message, - sys->getMemoryMode() == Enums::timing); + intMasterPort.sendMessage(apics, message, + sys->getMemoryMode() == Enums::timing); } } diff -r 8eed4047889b -r 48f97059228b src/dev/x86/intdev.hh --- a/src/dev/x86/intdev.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/dev/x86/intdev.hh Thu Mar 22 16:41:45 2012 +0000 @@ -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) 2008 The Regents of The University of Michigan * All rights reserved. * @@ -51,15 +63,14 @@ class IntDev { protected: - class IntPort : public MessagePort + class IntSlavePort : public MessageSlavePort { IntDev * device; Tick latency; - Addr intAddr; public: - IntPort(const std::string &_name, MemObject * _parent, - IntDev *dev, Tick _latency) : - MessagePort(_name, _parent), device(dev), latency(_latency) + IntSlavePort(const std::string& _name, MemObject* _parent, + IntDev* dev, Tick _latency) : + MessageSlavePort(_name, _parent), device(dev), latency(_latency) { } @@ -72,6 +83,18 @@ { return device->recvMessage(pkt); } + }; + + class IntMasterPort : public MessageMasterPort + { + IntDev* device; + Tick latency; + public: + IntMasterPort(const std::string& _name, MemObject* _parent, + IntDev* dev, Tick _latency) : + MessageMasterPort(_name, _parent), device(dev), latency(_latency) + { + } Tick recvResponse(PacketPtr pkt) { @@ -84,11 +107,11 @@ TriggerIntMessage message, bool timing); }; - IntPort intPort; + IntMasterPort intMasterPort; public: IntDev(MemObject * parent, Tick latency = 0) : - intPort(parent->name() + ".int_master", parent, this, latency) + intMasterPort(parent->name() + ".int_master", parent, this, latency) { } diff -r 8eed4047889b -r 48f97059228b src/dev/x86/intdev.cc --- a/src/dev/x86/intdev.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/dev/x86/intdev.cc Thu Mar 22 16:41:45 2012 +0000 @@ -43,8 +43,9 @@ #include "dev/x86/intdev.hh" void -X86ISA::IntDev::IntPort::sendMessage(ApicList apics, TriggerIntMessage message, - bool timing) +X86ISA::IntDev::IntMasterPort::sendMessage(ApicList apics, + TriggerIntMessage message, + bool timing) { ApicList::iterator apicIt; for (apicIt = apics.begin(); apicIt != apics.end(); apicIt++) { @@ -67,10 +68,9 @@ void X86ISA::IntDev::init() { - if (!intPort.isConnected()) { + if (!intMasterPort.isConnected()) { panic("Int port not connected to anything!"); } - intPort.sendRangeChange(); } X86ISA::IntSourcePin * diff -r 8eed4047889b -r 48f97059228b src/kern/tru64/tru64_events.cc --- a/src/kern/tru64/tru64_events.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/kern/tru64/tru64_events.cc Thu Mar 22 16:41:45 2012 +0000 @@ -60,9 +60,9 @@ AddrRangeIter iter; bool found = false; - Port &dataPort = tc->getCpuPtr()->getDataPort(); + MasterPort &dataPort = tc->getCpuPtr()->getDataPort(); - AddrRangeList resp = dataPort.getPeer()->getAddrRanges(); + AddrRangeList resp = dataPort.getSlavePort().getAddrRanges(); for (iter = resp.begin(); iter != resp.end(); iter++) { if (*iter == (K0Seg2Phys(a0) & PAddrImplMask)) found = true; diff -r 8eed4047889b -r 48f97059228b src/mem/bridge.hh --- a/src/mem/bridge.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/bridge.hh Thu Mar 22 16:41:45 2012 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -122,7 +122,7 @@ * is responsible for. The slave port also has a buffer for the * responses not yet sent. */ - class BridgeSlavePort : public Port + class BridgeSlavePort : public SlavePort { private: @@ -244,11 +244,6 @@ pass it to the bridge. */ virtual void recvFunctional(PacketPtr pkt); - /** - * When receiving a range change on the slave side do nothing. - */ - virtual void recvRangeChange(); - /** When receiving a address range request the peer port, pass it to the bridge. */ virtual AddrRangeList getAddrRanges(); @@ -260,7 +255,7 @@ * responses. The master port has a buffer for the requests not * yet sent. */ - class BridgeMasterPort : public Port + class BridgeMasterPort : public MasterPort { private: @@ -371,11 +366,6 @@ /** When receiving a Functional request from the peer port, pass it to the bridge. */ virtual void recvFunctional(PacketPtr pkt); - - /** - * When receiving a range change, pass it through the bridge. - */ - virtual void recvRangeChange(); }; /** Slave port of the bridge. */ @@ -396,8 +386,9 @@ public: const Params *params() const { return _params; } - /** A function used to return the port associated with this bus object. */ - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort& getMasterPort(const std::string& if_name, + int idx = -1); + virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1); virtual void init(); diff -r 8eed4047889b -r 48f97059228b src/mem/bridge.cc --- a/src/mem/bridge.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/bridge.cc Thu Mar 22 16:41:45 2012 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -59,7 +59,7 @@ int _delay, int _nack_delay, int _resp_limit, std::vector > _ranges) - : Port(_name, _bridge), bridge(_bridge), masterPort(_masterPort), + : SlavePort(_name, _bridge), bridge(_bridge), masterPort(_masterPort), delay(_delay), nackDelay(_nack_delay), ranges(_ranges.begin(), _ranges.end()), outstandingResponses(0), inRetry(false), @@ -71,7 +71,7 @@ Bridge* _bridge, BridgeSlavePort& _slavePort, int _delay, int _req_limit) - : Port(_name, _bridge), bridge(_bridge), slavePort(_slavePort), + : MasterPort(_name, _bridge), bridge(_bridge), slavePort(_slavePort), delay(_delay), inRetry(false), reqQueueLimit(_req_limit), sendEvent(*this) { @@ -88,20 +88,26 @@ panic("No support for acknowledging writes\n"); } -Port* -Bridge::getPort(const std::string &if_name, int idx) +MasterPort& +Bridge::getMasterPort(const std::string &if_name, int idx) +{ + if (if_name == "master") + return masterPort; + else + // pass it along to our super class + return MemObject::getMasterPort(if_name, idx); +} + +SlavePort& +Bridge::getSlavePort(const std::string &if_name, int idx) { if (if_name == "slave") - return &slavePort; - else if (if_name == "master") - return &masterPort; - else { - panic("Bridge %s has no port named %s\n", name(), if_name); - return NULL; - } + return slavePort; + else + // pass it along to our super class + return MemObject::getSlavePort(if_name, idx); } - void Bridge::init() { @@ -473,19 +479,6 @@ return found; } -/** Function called by the port when the bridge is receiving a range change.*/ -void -Bridge::BridgeMasterPort::recvRangeChange() -{ - // no need to forward as the bridge has a fixed set of ranges -} - -void -Bridge::BridgeSlavePort::recvRangeChange() -{ - // is a slave port so do nothing -} - AddrRangeList Bridge::BridgeSlavePort::getAddrRanges() { diff -r 8eed4047889b -r 48f97059228b src/mem/bus.hh --- a/src/mem/bus.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/bus.hh Thu Mar 22 16:41:45 2012 +0000 @@ -40,6 +40,7 @@ * Authors: Ron Dreslinski * Ali Saidi * Andreas Hansson + * William Wang */ /** @@ -65,21 +66,85 @@ class Bus : public MemObject { - /** Declaration of the buses port type, one will be instantiated for each - of the interfaces connecting to the bus. */ - class BusPort : public Port + /** + * Declaration of the bus slave port type, one will be + * instantiated for each of the master interfaces connecting to + * the bus. + */ + class BusSlavePort : public SlavePort { + private: /** A pointer to the bus to which this port belongs. */ Bus *bus; - /** A id to keep track of the intercafe ID this port is connected to. */ + /** A id to keep track of the interface ID of this port. */ int id; public: - /** Constructor for the BusPort.*/ - BusPort(const std::string &_name, Bus *_bus, int _id) - : Port(_name, _bus), bus(_bus), id(_id) + /** Constructor for the BusSlavePort.*/ + BusSlavePort(const std::string &_name, Bus *_bus, int _id) + : SlavePort(_name, _bus), bus(_bus), id(_id) + { } + + int getId() const { return id; } + + protected: + + /** When reciving a timing request from the peer port (at id), + pass it to the bus. */ + virtual bool recvTiming(PacketPtr pkt) + { pkt->setSrc(id); return bus->recvTiming(pkt); } + + /** When reciving a Atomic requestfrom the peer port (at id), + pass it to the bus. */ + virtual Tick recvAtomic(PacketPtr pkt) + { pkt->setSrc(id); return bus->recvAtomic(pkt); } + + /** When reciving a Functional requestfrom the peer port (at id), + pass it to the bus. */ + virtual void recvFunctional(PacketPtr pkt) + { pkt->setSrc(id); bus->recvFunctional(pkt); } + + /** When reciving a retry from the peer port (at id), + pass it to the bus. */ + virtual void recvRetry() + { bus->recvRetry(id); } + + // This should return all the 'owned' addresses that are + // downstream from this bus, yes? That is, the union of all + // the 'owned' address ranges of all the other interfaces on + // this bus... + 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 + // support multiple block sizes. + virtual unsigned deviceBlockSize() const + { return bus->findBlockSize(id); } + + }; + + /** + * Declaration of the bus master port type, one will be + * instantiated for each of the slave interfaces connecting to the + * bus. + */ + class BusMasterPort : public MasterPort + { + private: + /** A pointer to the bus to which this port belongs. */ + Bus *bus; + + /** A id to keep track of the interface ID of this port. */ + int id; + + public: + + /** Constructor for the BusMasterPort.*/ + BusMasterPort(const std::string &_name, Bus *_bus, int _id) + : MasterPort(_name, _bus), bus(_bus), id(_id) { } int getId() const { return id; } @@ -90,7 +155,7 @@ * * @return a boolean that is true if this port is snooping */ - virtual bool isSnooping() + virtual bool isSnooping() const { return bus->isSnooping(id); } protected: @@ -120,13 +185,6 @@ virtual void recvRetry() { bus->recvRetry(id); } - // This should return all the 'owned' addresses that are - // downstream from this bus, yes? That is, the union of all - // the 'owned' address ranges of all the other interfaces on - // this bus... - 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 // support multiple block sizes. @@ -151,8 +209,8 @@ AddrRangeList defaultRange; - typedef std::vector::iterator SnoopIter; - std::vector snoopPorts; + typedef std::vector::iterator SnoopIter; + std::vector snoopPorts; /** Function called by the port when the bus is recieving a Timing transaction.*/ @@ -250,7 +308,7 @@ * * @return a boolean indicating if this port is snooping or not */ - bool isSnooping(int id); + bool isSnooping(int id) const; /** Calculate the timing parameters for the packet. Updates the * firstWordTime and finishTime fields of the packet object. @@ -292,9 +350,9 @@ // interfaces vector unsigned int nbrMasterPorts; - /** An ordered vector of pointers to the peer port interfaces - connected to this bus.*/ - std::vector interfaces; + /** The master and slave ports of the bus */ + std::vector slavePorts; + std::vector masterPorts; /** An array of pointers to ports that retry should be called on because the * original send failed for whatever reason.*/ @@ -338,7 +396,8 @@ public: /** A function used to return the port associated with this bus object. */ - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual MasterPort& getMasterPort(const std::string& if_name, int idx = -1); + virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1); virtual void init(); virtual void startup(); diff -r 8eed4047889b -r 48f97059228b src/mem/bus.cc --- a/src/mem/bus.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/bus.cc Thu Mar 22 16:41:45 2012 +0000 @@ -39,6 +39,7 @@ * * Authors: Ali Saidi * Andreas Hansson + * William Wang */ /** @@ -72,12 +73,14 @@ // 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 + // id used to index into master and slave ports, that currently + // has holes to be able to use the id to index into either 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)); + BusMasterPort* bp = new BusMasterPort(portName, this, id); + masterPorts.push_back(bp); + slavePorts.push_back(NULL); ++id; } @@ -86,7 +89,9 @@ if (p->port_default_connection_count) { defaultPortId = id; std::string portName = csprintf("%s-default", name()); - interfaces.push_back(new BusPort(portName, this, id)); + BusMasterPort* bp = new BusMasterPort(portName, this, id); + masterPorts.push_back(bp); + slavePorts.push_back(NULL); ++id; // this is an additional master port ++nbrMasterPorts; @@ -96,44 +101,55 @@ // 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)); + BusSlavePort* bp = new BusSlavePort(portName, this, id); + masterPorts.push_back(NULL); + slavePorts.push_back(bp); ++id; } clearPortCache(); } -Port * -Bus::getPort(const std::string &if_name, int idx) +MasterPort & +Bus::getMasterPort(const std::string &if_name, int idx) { 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]; + return *masterPorts[idx]; } else if (if_name == "default") { - return interfaces[defaultPortId]; + return *masterPorts[defaultPortId]; } else { - panic("No port %s %d on bus %s\n", if_name, idx, name()); + return MemObject::getMasterPort(if_name, idx); + } +} + +SlavePort & +Bus::getSlavePort(const std::string &if_name, int idx) +{ + if (if_name == "slave") { + return *slavePorts[nbrMasterPorts + idx]; + } else { + return MemObject::getSlavePort(if_name, idx); } } void Bus::init() { - std::vector::iterator intIter; + std::vector::iterator intIter; // iterate over our interfaces and determine which of our neighbours // are snooping and add them as snoopers - for (intIter = interfaces.begin(); intIter != interfaces.end(); + for (intIter = slavePorts.begin(); intIter != slavePorts.end(); intIter++) { - if ((*intIter)->getPeer()->isSnooping()) { - DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n", - (*intIter)->getPeer()->name()); - snoopPorts.push_back(*intIter); + // since there are holes in the vector, check for NULL + if (*intIter != NULL) { + if ((*intIter)->getMasterPort().isSnooping()) { + DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n", + (*intIter)->getMasterPort().name()); + snoopPorts.push_back(*intIter); + } } } } @@ -194,7 +210,9 @@ // get the source id and port Packet::NodeID src_id = pkt->getSrc(); - BusPort *src_port = interfaces[src_id]; + // determine the source port based on the id + Port *src_port = slavePorts[src_id] ? + (Port*) slavePorts[src_id] : (Port*) masterPorts[src_id]; // If the bus is busy, or other devices are in line ahead of the current // one, put this device on the retry list. @@ -218,14 +236,14 @@ int dest_id; Port *dest_port; - if (dest == Packet::Broadcast) { + if (pkt->isRequest()) { // the packet is a memory-mapped request and should be broadcasted to // our snoopers - assert(pkt->isRequest()); + assert(dest == Packet::Broadcast); SnoopIter s_end = snoopPorts.end(); for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { - BusPort *p = *s_iter; + BusSlavePort *p = *s_iter; // we got this request from a snooping master // (corresponding to our own slave port that is also in // snoopPorts) and should not send it back to where it @@ -241,16 +259,28 @@ // determine the destination based on the address and forward // through the corresponding master port dest_id = findPort(pkt->getAddr()); - dest_port = interfaces[dest_id]; + dest_port = masterPorts[dest_id]; } else { // the packet is a response, and it should always go back to // the port determined by the destination field dest_id = dest; assert(dest_id != src_id); // catch infinite loops - assert(dest_id < interfaces.size()); - dest_port = interfaces[dest_id]; + dest_port = slavePorts[dest_id] ? + (Port*) slavePorts[dest_id] : (Port*) masterPorts[dest_id]; + + // a normal response from the memory system (i.e. from a + // connected slave) should always go back to the master + // that issued it through one of our slave ports, however + // if this is a snoop response it could go either way, for + // example, it could be coming from a slave port + // connecting an L1 with a coherent master and another L1 + // coherent master (one of our slave ports), or coming + // from the L1 and going to the L2 slave port (through one + // of our master ports) } + assert(dest_port != NULL); + // if this is a snoop from a slave (corresponding to our own // master), i.e. the memory side of the bus, then do not send it // back to where it came from @@ -318,8 +348,6 @@ // send a retry to the port at the head of the retry list inRetry = true; - DPRINTF(Bus, "Sending a retry to %s\n", - retryList.front()->getPeer()->name()); // note that we might have blocked on the receiving port being // busy (rather than the bus itself) and now call retry before the @@ -427,7 +455,7 @@ SnoopIter s_end = snoopPorts.end(); for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { - BusPort *p = *s_iter; + BusSlavePort *p = *s_iter; // we could have gotten this request from a snooping master // (corresponding to our own slave port that is also in // snoopPorts) and should not send it back to where it came @@ -464,7 +492,7 @@ // master), i.e. the memory side of the bus, then do not send it // back to where it came from if (dest_id != src_id) { - response_latency = interfaces[dest_id]->sendAtomic(pkt); + response_latency = masterPorts[dest_id]->sendAtomic(pkt); } // if we got a response from a snooper, restore it here @@ -504,7 +532,7 @@ SnoopIter s_end = snoopPorts.end(); for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { - BusPort *p = *s_iter; + BusSlavePort *p = *s_iter; // we could have gotten this request from a snooping master // (corresponding to our own slave port that is also in // snoopPorts) and should not send it back to where it came @@ -528,7 +556,7 @@ // master), i.e. the memory side of the bus, then do not send // it back to where it came from, if (dest_id != src_id) { - interfaces[dest_id]->sendFunctional(pkt); + masterPorts[dest_id]->sendFunctional(pkt); } } } @@ -551,7 +579,8 @@ defaultRange.clear(); // Only try to update these ranges if the user set a default responder. if (useDefaultRange) { - AddrRangeList ranges = interfaces[id]->getPeer()->getAddrRanges(); + AddrRangeList ranges = + masterPorts[id]->getSlavePort().getAddrRanges(); for(iter = ranges.begin(); iter != ranges.end(); iter++) { defaultRange.push_back(*iter); DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", @@ -560,8 +589,8 @@ } } else { - assert(id < interfaces.size() && id >= 0); - BusPort *port = interfaces[id]; + assert(id < masterPorts.size() && id >= 0); + BusMasterPort *port = masterPorts[id]; // Clean out any previously existent ids for (PortIter portIter = portMap.begin(); @@ -572,7 +601,7 @@ portIter++; } - ranges = port->getPeer()->getAddrRanges(); + ranges = port->getSlavePort().getAddrRanges(); for (iter = ranges.begin(); iter != ranges.end(); iter++) { DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", @@ -580,8 +609,8 @@ if (portMap.insert(*iter, id) == portMap.end()) { int conflict_id = portMap.find(*iter)->second; fatal("%s has two ports with same range:\n\t%s\n\t%s\n", - name(), interfaces[id]->getPeer()->name(), - interfaces[conflict_id]->getPeer()->name()); + name(), masterPorts[id]->getSlavePort().name(), + masterPorts[conflict_id]->getSlavePort().name()); } } } @@ -589,10 +618,10 @@ // tell all our peers that our address range has changed. // Don't tell the device that caused this change, it already knows - std::vector::const_iterator intIter; + std::vector::const_iterator intIter; - for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) - if ((*intIter)->getId() != id) + for (intIter = slavePorts.begin(); intIter != slavePorts.end(); intIter++) + if (*intIter != NULL && (*intIter)->getId() != id) (*intIter)->sendRangeChange(); inRecvRangeChange.erase(id); @@ -640,7 +669,7 @@ } bool -Bus::isSnooping(int id) +Bus::isSnooping(int id) const { // in essence, answer the question if there are snooping ports return !snoopPorts.empty(); @@ -656,7 +685,7 @@ PortIter p_end = portMap.end(); for (PortIter p_iter = portMap.begin(); p_iter != p_end; p_iter++) { - unsigned tmp_bs = interfaces[p_iter->second]->peerBlockSize(); + unsigned tmp_bs = masterPorts[p_iter->second]->peerBlockSize(); if (tmp_bs > max_bs) max_bs = tmp_bs; } diff -r 8eed4047889b -r 48f97059228b src/mem/cache/base.hh --- a/src/mem/cache/base.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/cache/base.hh Thu Mar 22 16:41:45 2012 +0000 @@ -118,7 +118,7 @@ * and the sendDeferredPacket of the timing port is modified to * consider both the transmit list and the requests from the MSHR. */ - class CacheMasterPort : public QueuedPort + class CacheMasterPort : public QueuedMasterPort { public: @@ -149,7 +149,7 @@ CacheMasterPort(const std::string &_name, BaseCache *_cache, PacketQueue &_queue) : - QueuedPort(_name, _cache, _queue) + QueuedMasterPort(_name, _cache, _queue) { } /** @@ -157,7 +157,7 @@ * * @return always true */ - virtual bool isSnooping() { return true; } + virtual bool isSnooping() const { return true; } }; /** @@ -168,7 +168,7 @@ * incoming requests. If blocked, the port will issue a retry once * unblocked. */ - class CacheSlavePort : public QueuedPort + class CacheSlavePort : public QueuedSlavePort { public: @@ -444,6 +444,9 @@ virtual void init(); + virtual MasterPort &getMasterPort(const std::string &if_name, int idx = -1); + virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1); + /** * Query block size of a cache. * @return The block size diff -r 8eed4047889b -r 48f97059228b src/mem/cache/base.cc --- a/src/mem/cache/base.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/cache/base.cc Thu Mar 22 16:41:45 2012 +0000 @@ -57,7 +57,7 @@ BaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name, BaseCache *_cache, const std::string &_label) - : QueuedPort(_name, _cache, queue), queue(*_cache, *this, _label), + : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label), blocked(false), mustSendRetry(false), sendRetryEvent(this) { } @@ -99,7 +99,7 @@ DPRINTF(CachePort, "Cache port %s sending retry\n", name()); mustSendRetry = false; // @TODO: need to find a better time (next bus cycle?) - owner->schedule(sendRetryEvent, curTick() + 1); + owner.schedule(sendRetryEvent, curTick() + 1); } } @@ -108,10 +108,29 @@ BaseCache::init() { if (!cpuSidePort->isConnected() || !memSidePort->isConnected()) - panic("Cache %s not hooked up on both sides\n", name()); + fatal("Cache ports on %s are not connected\n", name()); cpuSidePort->sendRangeChange(); } +MasterPort & +BaseCache::getMasterPort(const std::string &if_name, int idx) +{ + if (if_name == "mem_side") { + return *memSidePort; + } else { + return MemObject::getMasterPort(if_name, idx); + } +} + +SlavePort & +BaseCache::getSlavePort(const std::string &if_name, int idx) +{ + if (if_name == "cpu_side") { + return *cpuSidePort; + } else { + return MemObject::getSlavePort(if_name, idx); + } +} void BaseCache::regStats() diff -r 8eed4047889b -r 48f97059228b src/mem/cache/builder.cc --- a/src/mem/cache/builder.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/cache/builder.cc Thu Mar 22 16:41:45 2012 +0000 @@ -40,7 +40,6 @@ #include "mem/cache/base.hh" #include "mem/cache/cache.hh" #include "mem/config/cache.hh" -#include "mem/bus.hh" #include "params/BaseCache.hh" // Tag Templates diff -r 8eed4047889b -r 48f97059228b src/mem/cache/cache.hh --- a/src/mem/cache/cache.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/cache/cache.hh Thu Mar 22 16:41:45 2012 +0000 @@ -249,8 +249,6 @@ /** Instantiates a basic cache object. */ Cache(const Params *p, TagStore *tags); - virtual Port *getPort(const std::string &if_name, int idx = -1); - void regStats(); /** diff -r 8eed4047889b -r 48f97059228b src/mem/cache/cache_impl.hh --- a/src/mem/cache/cache_impl.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/cache/cache_impl.hh Thu Mar 22 16:41:45 2012 +0000 @@ -92,19 +92,6 @@ } template -Port * -Cache::getPort(const std::string &if_name, int idx) -{ - if (if_name == "cpu_side") { - return cpuSidePort; - } else if (if_name == "mem_side") { - return memSidePort; - } else { - panic("Port name %s unrecognized\n", if_name); - } -} - -template void Cache::cmpAndSwap(BlkType *blk, PacketPtr pkt) { @@ -795,7 +782,7 @@ // continues towards the memory side if (fromCpuSide) { memSidePort->sendFunctional(pkt); - } else if (forwardSnoops) { + } else if (forwardSnoops && cpuSidePort->getMasterPort().isSnooping()) { // if it came from the memory side, it must be a snoop request // and we should only forward it if we are forwarding snoops cpuSidePort->sendFunctional(pkt); diff -r 8eed4047889b -r 48f97059228b src/mem/fs_translating_port_proxy.hh --- a/src/mem/fs_translating_port_proxy.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/fs_translating_port_proxy.hh Thu Mar 22 16:41:45 2012 +0000 @@ -78,7 +78,7 @@ FSTranslatingPortProxy(ThreadContext* tc); - FSTranslatingPortProxy(Port &port); + FSTranslatingPortProxy(MasterPort &port); virtual ~FSTranslatingPortProxy(); diff -r 8eed4047889b -r 48f97059228b src/mem/fs_translating_port_proxy.cc --- a/src/mem/fs_translating_port_proxy.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/fs_translating_port_proxy.cc Thu Mar 22 16:41:45 2012 +0000 @@ -58,7 +58,7 @@ { } -FSTranslatingPortProxy::FSTranslatingPortProxy(Port &port) +FSTranslatingPortProxy::FSTranslatingPortProxy(MasterPort &port) : PortProxy(port), _tc(NULL) { } diff -r 8eed4047889b -r 48f97059228b src/mem/mem_object.hh --- a/src/mem/mem_object.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/mem_object.hh Thu Mar 22 16:41:45 2012 +0000 @@ -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) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -26,11 +38,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Ron Dreslinski + * Andreas Hansson */ /** * @file - * Base Memory Object declaration. + * MemObject declaration. */ #ifndef __MEM_MEM_OBJECT_HH__ @@ -41,8 +54,8 @@ #include "sim/sim_object.hh" /** - * The base MemoryObject class, allows for an accesor function to a - * simobj that returns the Port. + * The MemObject class extends the SimObject with accessor functions + * to get its master and slave ports. */ class MemObject : public SimObject { @@ -53,9 +66,27 @@ MemObject(const Params *params); - public: - /** Additional function to return the Port of a memory object. */ - virtual Port *getPort(const std::string &if_name, int idx = -1) = 0; + /** + * Get a master port with a given name and index. + * + * @param if_name Port name + * @param idx Index in the case of a VectorPort + * + * @return A reference to the given port + */ + virtual MasterPort& getMasterPort(const std::string& if_name, + int idx = -1); + + /** + * Get a slave port with a given name and index. + * + * @param if_name Port name + * @param idx Index in the case of a VectorPort + * + * @return A reference to the given port + */ + virtual SlavePort& getSlavePort(const std::string& if_name, + int idx = -1); }; #endif //__MEM_MEM_OBJECT_HH__ diff -r 8eed4047889b -r 48f97059228b src/mem/mem_object.cc --- a/src/mem/mem_object.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/mem_object.cc Thu Mar 22 16:41:45 2012 +0000 @@ -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) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -26,6 +38,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Steve Reinhardt + * Andreas Hansson */ #include "mem/mem_object.hh" @@ -34,3 +47,15 @@ : SimObject(params) { } + +MasterPort& +MemObject::getMasterPort(const std::string& if_name, int idx) +{ + fatal("%s does not have any master port named %s\n", name(), if_name); +} + +SlavePort& +MemObject::getSlavePort(const std::string& if_name, int idx) +{ + fatal("%s does not have any slave port named %s\n", name(), if_name); +} diff -r 8eed4047889b -r 48f97059228b src/mem/mport.hh --- a/src/mem/mport.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/mport.hh Thu Mar 22 16:41:45 2012 +0000 @@ -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) 2008 The Regents of The University of Michigan * All rights reserved. * @@ -41,15 +53,15 @@ * the underpinnings of SimpleTimingPort, but it tweaks some of the external * functions. */ -class MessagePort : public SimpleTimingPort +class MessageSlavePort : public SimpleTimingPort { public: - MessagePort(const std::string &name, MemObject *owner) : + MessageSlavePort(const std::string &name, MemObject *owner) : SimpleTimingPort(name, owner) {} - virtual ~MessagePort() + virtual ~MessageSlavePort() {} protected: @@ -57,6 +69,29 @@ Tick recvAtomic(PacketPtr pkt); virtual Tick recvMessage(PacketPtr pkt) = 0; +}; + +class MessageMasterPort : public QueuedMasterPort +{ + public: + + MessageMasterPort(const std::string &name, MemObject *owner) : + QueuedMasterPort(name, owner, queue), queue(*owner, *this) + {} + + virtual ~MessageMasterPort() + {} + + void recvFunctional(PacketPtr pkt) { assert(false); } + + Tick recvAtomic(PacketPtr pkt); + + bool recvTiming(PacketPtr pkt) { recvAtomic(pkt); return true; } + + protected: + + /** A packet queue for outgoing packets. */ + PacketQueue queue; // Accept and ignore responses. virtual Tick recvResponse(PacketPtr pkt) diff -r 8eed4047889b -r 48f97059228b src/mem/mport.cc --- a/src/mem/mport.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/mport.cc Thu Mar 22 16:41:45 2012 +0000 @@ -43,17 +43,26 @@ #include "mem/mport.hh" Tick -MessagePort::recvAtomic(PacketPtr pkt) +MessageSlavePort::recvAtomic(PacketPtr pkt) { if (pkt->cmd == MemCmd::MessageReq) { return recvMessage(pkt); - } else if (pkt->cmd == MemCmd::MessageResp) { + } else { + panic("%s received unexpected atomic command %s from %s.\n", + name(), pkt->cmd.toString(), getMasterPort().name()); + } +} + +Tick +MessageMasterPort::recvAtomic(PacketPtr pkt) +{ + if (pkt->cmd == MemCmd::MessageResp) { // normally we would never see responses in recvAtomic, but // since the timing port uses recvAtomic to implement - // recvTiming we have to deal with both cases + // recvTiming we have to deal with them here return recvResponse(pkt); } else { panic("%s received unexpected atomic command %s from %s.\n", - name(), pkt->cmd.toString(), getPeer()->name()); + name(), pkt->cmd.toString(), getSlavePort().name()); } } diff -r 8eed4047889b -r 48f97059228b src/mem/physical.hh --- a/src/mem/physical.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/physical.hh Thu Mar 22 16:41:45 2012 +0000 @@ -67,8 +67,6 @@ virtual void recvFunctional(PacketPtr pkt); - virtual void recvRangeChange(); - virtual AddrRangeList getAddrRanges(); virtual unsigned deviceBlockSize() const; @@ -196,7 +194,7 @@ public: unsigned deviceBlockSize() const; AddrRangeList getAddrRanges(); - virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1); void virtual init(); unsigned int drain(Event *de); diff -r 8eed4047889b -r 48f97059228b src/mem/physical.cc --- a/src/mem/physical.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/physical.cc Thu Mar 22 16:41:45 2012 +0000 @@ -439,18 +439,18 @@ } -Port * -PhysicalMemory::getPort(const std::string &if_name, int idx) +SlavePort & +PhysicalMemory::getSlavePort(const std::string &if_name, int idx) { if (if_name != "port") { - panic("PhysicalMemory::getPort: unknown port %s requested\n", if_name); + return MemObject::getSlavePort(if_name, idx); + } else { + if (idx >= static_cast(ports.size())) { + fatal("PhysicalMemory::getSlavePort: unknown index %d\n", idx); + } + + return *ports[idx]; } - - if (idx >= static_cast(ports.size())) { - panic("PhysicalMemory::getPort: unknown index %d requested\n", idx); - } - - return ports[idx]; } PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, @@ -458,13 +458,6 @@ : SimpleTimingPort(_name, _memory), memory(_memory) { } -void -PhysicalMemory::MemoryPort::recvRangeChange() -{ - // memory is a slave and thus should never have to worry about its - // neighbours address ranges -} - AddrRangeList PhysicalMemory::MemoryPort::getAddrRanges() { diff -r 8eed4047889b -r 48f97059228b src/mem/port.hh --- a/src/mem/port.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/port.hh Thu Mar 22 16:41:45 2012 +0000 @@ -39,15 +39,12 @@ * * Authors: Ron Dreslinski * Andreas Hansson + * William Wang */ /** * @file - * Port Object Declaration. Ports are used to interface memory objects to - * each other. They will always come in pairs, and we refer to the other - * port object as the peer. These are used to make the design more - * modular so that a specific interface between every type of objcet doesn't - * have to be created. + * Port Object Declaration. */ #ifndef __MEM_PORT_HH__ @@ -58,7 +55,8 @@ #include "base/range.hh" #include "mem/packet.hh" -/** This typedef is used to clean up getAddrRanges(). 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. @@ -70,62 +68,47 @@ class MemObject; /** - * Ports are used to interface memory objects to - * each other. They will always come in pairs, and we refer to the other - * port object as the peer. These are used to make the design more - * modular so that a specific interface between every type of objcet doesn't - * have to be created. + * Ports are used to interface memory objects to each other. A port is + * either a master or a slave and the connected peer is always of the + * opposite role. * - * Recv accesor functions are being called from the peer interface. - * Send accessor functions are being called from the device the port is - * associated with, and it will call the peer recv. accessor function. + * Each port has a name and an owner, and enables three basic types of + * accesses to the peer port: sendFunctional, sendAtomic and + * sendTiming. */ class Port { + + private: + + /** Descriptive name (for DPRINTF output) */ + std::string portName; + protected: - /** Descriptive name (for DPRINTF output) */ - mutable std::string portName; - /** A pointer to the peer port. Ports always come in pairs, that way they - can use a standardized interface to communicate between different - memory objects. */ - Port *peer; + /** A pointer to the peer port. */ + Port* peer; - /** A pointer to the MemObject that owns this port. This may not be set. */ - MemObject *owner; + /** A reference to the MemObject that owns this port. */ + MemObject& owner; + + /** + * Abstract base class for ports + * + * @param _name Port name including the owners name + * @param _owner The MemObject that is the structural owner of this port + */ + Port(const std::string& _name, MemObject& _owner); + + /** + * Virtual destructor due to inheritance. + */ + virtual ~Port(); public: - /** - * Constructor. - * - * @param _name Port name for DPRINTF output. Should include name - * of memory system object to which the port belongs. - * @param _owner Pointer to the MemObject that owns this port. - * Will not necessarily be set. - */ - Port(const std::string &_name, MemObject *_owner); /** Return port name (for DPRINTF). */ - const std::string &name() const { return portName; } - - virtual ~Port(); - - void setName(const std::string &name) - { portName = name; } - - /** Function to set the pointer for the peer port. */ - virtual void setPeer(Port *port); - - /** Function to get the pointer to the peer port. */ - Port *getPeer() { return peer; } - - /** Function to set the owner of this port. */ - void setOwner(MemObject *_owner); - - /** Function to return the owner of this port. */ - MemObject *getOwner() { return owner; } - - bool isConnected() { return peer != NULL; } + const std::string name() const { return portName; } protected: @@ -141,89 +124,109 @@ /** Called to recive a functional call from the peer port. */ virtual void recvFunctional(PacketPtr pkt) = 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). - so it is set to panic if it isn't already defined. - */ - virtual void recvRetry() { panic("??"); } - - /** Called by a peer port in order to determine the block size of the - device connected to this port. It sometimes doesn't make sense for - this function to be called, so it just returns 0. Anytthing that is - concerned with the size should just ignore that. - */ - virtual unsigned deviceBlockSize() const { return 0; } + /** + * Called by a peer port if sendTiming was unsuccesful, and had to + * wait. + */ + virtual void recvRetry() = 0; 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. + * Attempt to send a timing packet to the peer port by calling its + * receive function. If the send does not succeed, as indicated by + * the return value, then the sender must wait for a recvRetry at + * which point it can re-issue a sendTiming. * - * @return a list of ranges responded to - */ - virtual AddrRangeList getAddrRanges() - { AddrRangeList ranges; return ranges; } + * @param pkt Packet to send. + * + * @return If the send was succesful or not. + */ + bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); } /** - * Determine if this port is snooping or not. The default + * Send a retry to a peer port that previously attempted a sendTiming + * which was unsuccessful. + */ + void sendRetry() { return peer->recvRetry(); } + + /** + * Send an atomic packet, where the data is moved and the state + * is updated in zero time, without interleaving with other + * memory accesses. + * + * @param pkt Packet to send. + * + * @return Estimated latency of access. + */ + Tick sendAtomic(PacketPtr pkt) { return peer->recvAtomic(pkt); } + + /** + * Send a functional packet, where the data is instantly updated + * everywhere in the memory system, without affecting the current + * state of any block or moving the block. + * + * @param pkt Packet to send. + */ + void sendFunctional(PacketPtr pkt) { return peer->recvFunctional(pkt); } + +}; + +/** Forward declaration */ +class SlavePort; + +/** + * A MasterPort is a specialisation of a port. In addition to the + * basic functionality of sending packets to its slave peer, it also + * has functions specific to a master, e.g. to receive range changes + * or determine if the port is snooping or not. + */ +class MasterPort : public Port +{ + + private: + + SlavePort* _slavePort; + + public: + + MasterPort(const std::string& name, MemObject* owner); + virtual ~MasterPort(); + + void bind(SlavePort& slave_port); + SlavePort& getSlavePort() const; + bool isConnected() const; + + /** + * Called to receive an address range change from the peer slave + * port. the default implementation ignored the change and does + * nothing. Override this function in a derived class if the owner + * needs to be aware of he laesddress ranges, e.g. in an + * interconnect component like a bus. + */ + virtual void recvRangeChange() { } + + /** + * Determine if this master 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. + * are not snooping. Any master port that wants to receive snoop + * requests (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. - @return This function returns if the send was succesful in it's - recieve. If it was a failure, then the port will wait for a recvRetry - at which point it can possibly issue a successful sendTiming. This is used in - case a cache has a higher priority request come in while waiting for - the bus to arbitrate. - */ - bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); } - - /** Function called by the associated device to send an atomic - * access, an access in which the data is moved and the state is - * updated in one cycle, without interleaving with other memory - * accesses. Returns estimated latency of access. - */ - Tick sendAtomic(PacketPtr pkt) - { return peer->recvAtomic(pkt); } - - /** Function called by the associated device to send a functional access, - an access in which the data is instantly updated everywhere in the - memory system, without affecting the current state of any block or - moving the block. - */ - void sendFunctional(PacketPtr pkt) - { return peer->recvFunctional(pkt); } + virtual bool isSnooping() const { return false; } /** - * Called by the associated device to send a status range to the - * peer interface. + * Called by a peer port in order to determine the block size of + * the owner of this port. */ - void sendRangeChange() const { peer->recvRangeChange(); } - - /** When a timing access doesn't return a success, some time later the - Retry will be sent. - */ - void sendRetry() { return peer->recvRetry(); } + virtual unsigned deviceBlockSize() const { return 0; } /** Called by the associated device if it wishes to find out the blocksize of the device on attached to the peer port. */ - unsigned peerBlockSize() const { return peer->deviceBlockSize(); } + unsigned peerBlockSize() const; /** Inject a PrintReq for the given address to print the state of * that address throughout the memory system. For debugging. @@ -231,4 +234,52 @@ void printAddr(Addr a); }; +/** + * A SlavePort is a specialisation of a port. In addition to the + * basic functionality of sending packets to its master peer, it also + * has functions specific to a slave, e.g. to send range changes + * and get the address ranges that the port responds to. + */ +class SlavePort : public Port +{ + + private: + + MasterPort* _masterPort; + + public: + + SlavePort(const std::string& name, MemObject* owner); + virtual ~SlavePort(); + + void bind(MasterPort& master_port); + MasterPort& getMasterPort() const; + bool isConnected() const; + + /** + * Called by a peer port in order to determine the block size of + * the owner of this port. + */ + virtual unsigned deviceBlockSize() const { return 0; } + + /** Called by the associated device if it wishes to find out the blocksize + of the device on attached to the peer port. + */ + unsigned peerBlockSize() const; + + /** + * Called by the owner to send a range change + */ + void sendRangeChange() const { _masterPort->recvRangeChange(); } + + /** + * Get a list of the non-overlapping address ranges the owner is + * responsible for. All slave ports must override this function + * and return a populated list with at least one item. + * + * @return a list of ranges responded to + */ + virtual AddrRangeList getAddrRanges() = 0; +}; + #endif //__MEM_PORT_HH__ diff -r 8eed4047889b -r 48f97059228b src/mem/port.cc --- a/src/mem/port.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/port.cc Thu Mar 22 16:41:45 2012 +0000 @@ -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) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -26,6 +38,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Steve Reinhardt + * Andreas Hansson + * William Wang */ /** @@ -33,11 +47,10 @@ * Port object definitions. */ #include "base/trace.hh" -#include "debug/Config.hh" #include "mem/mem_object.hh" #include "mem/port.hh" -Port::Port(const std::string &_name, MemObject *_owner) +Port::Port(const std::string &_name, MemObject& _owner) : portName(_name), peer(NULL), owner(_owner) { } @@ -46,22 +59,53 @@ { } -void -Port::setPeer(Port *port) +/** + * Master port + */ +MasterPort::MasterPort(const std::string& name, MemObject* owner) + : Port(name, *owner), _slavePort(NULL) { - DPRINTF(Config, "setting peer to %s\n", port->name()); +} - peer = port; +MasterPort::~MasterPort() +{ +} + +SlavePort& +MasterPort::getSlavePort() const +{ + if(_slavePort == NULL) + panic("Cannot getSlavePort on master port %s that is not connected\n", + name()); + + return *_slavePort; } void -Port::setOwner(MemObject *_owner) +MasterPort::bind(SlavePort& slave_port) { - owner = _owner; + // master port keeps track of the slave port + _slavePort = &slave_port; + peer = &slave_port; + + // slave port also keeps track of master port + _slavePort->bind(*this); } -void -Port::printAddr(Addr a) +bool +MasterPort::isConnected() const +{ + return _slavePort != NULL; +} + +unsigned +MasterPort::peerBlockSize() const +{ + return _slavePort->deviceBlockSize(); +} + + void +MasterPort::printAddr(Addr a) { Request req(a, 1, 0, Request::funcMasterId); Packet pkt(&req, MemCmd::PrintReq, Packet::Broadcast); @@ -70,3 +114,44 @@ sendFunctional(&pkt); } + +/** + * Slave port + */ +SlavePort::SlavePort(const std::string& name, MemObject* owner) + : Port(name, *owner), _masterPort(NULL) +{ +} + +SlavePort::~SlavePort() +{ +} + +void +SlavePort::bind(MasterPort& master_port) +{ + _masterPort = &master_port; + peer = &master_port; +} + +MasterPort& +SlavePort::getMasterPort() const +{ + if (_masterPort == NULL) + panic("Cannot getMasterPort on slave port %s that is not connected\n", + name()); + + return *_masterPort; +} + +unsigned +SlavePort::peerBlockSize() const +{ + return _masterPort->deviceBlockSize(); +} + +bool +SlavePort::isConnected() const +{ + return _masterPort != NULL; +} diff -r 8eed4047889b -r 48f97059228b src/mem/port_proxy.hh --- a/src/mem/port_proxy.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/port_proxy.hh Thu Mar 22 16:41:45 2012 +0000 @@ -86,12 +86,12 @@ private: /** The actual physical port used by this proxy. */ - Port &_port; + MasterPort &_port; void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd) const; public: - PortProxy(Port &port) : _port(port) { } + PortProxy(MasterPort &port) : _port(port) { } virtual ~PortProxy() { } /** diff -r 8eed4047889b -r 48f97059228b src/mem/qport.hh --- a/src/mem/qport.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/qport.hh Thu Mar 22 16:41:45 2012 +0000 @@ -56,7 +56,7 @@ * queue is a parameter to allow tailoring of the queue implementation * (used in the cache). */ -class QueuedPort : public Port +class QueuedSlavePort : public SlavePort { protected: @@ -68,7 +68,46 @@ * packet again. */ virtual void recvRetry() { queue.retry(); } - virtual void recvRangeChange() { } + public: + + /** + * Create a QueuedPort with a given name, owner, and a supplied + * implementation of a packet queue. The external definition of + * the queue enables e.g. the cache to implement a specific queue + * behaviuor in a subclass, and provide the latter to the + * QueuePort constructor. + */ + QueuedSlavePort(const std::string& name, MemObject* owner, + PacketQueue &queue) : + SlavePort(name, owner), queue(queue) + { } + + virtual ~QueuedSlavePort() { } + + /** Check the list of buffered packets against the supplied + * functional request. */ + bool checkFunctional(PacketPtr pkt) { return queue.checkFunctional(pkt); } + + /** + * Hook for draining the queued port. + * + * @param de an event which is used to signal back to the caller + * @returns a number indicating how many times process will be called + */ + unsigned int drain(Event *de) { return queue.drain(de); } +}; + +class QueuedMasterPort : public MasterPort +{ + + protected: + + /** Packet queue used to store outgoing requests and responses. */ + PacketQueue &queue; + + /** This function is notification that the device should attempt to send a + * packet again. */ + virtual void recvRetry() { queue.retry(); } public: @@ -79,11 +118,12 @@ * behaviuor in a subclass, and provide the latter to the * QueuePort constructor. */ - QueuedPort(const std::string& name, MemObject* owner, PacketQueue &queue) : - Port(name, owner), queue(queue) + QueuedMasterPort(const std::string& name, MemObject* owner, + PacketQueue &queue) : + MasterPort(name, owner), queue(queue) { } - virtual ~QueuedPort() { } + virtual ~QueuedMasterPort() { } /** Check the list of buffered packets against the supplied * functional request. */ diff -r 8eed4047889b -r 48f97059228b src/mem/ruby/system/RubyPort.hh --- a/src/mem/ruby/system/RubyPort.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/ruby/system/RubyPort.hh Thu Mar 22 16:41:45 2012 +0000 @@ -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) 2009 Advanced Micro Devices, Inc. * Copyright (c) 2011 Mark D. Hill and David A. Wood * All rights reserved. @@ -46,7 +58,7 @@ class RubyPort : public MemObject { public: - class M5Port : public QueuedPort + class M5Port : public QueuedSlavePort { private: @@ -74,6 +86,7 @@ virtual bool recvTiming(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt); virtual void recvFunctional(PacketPtr pkt); + virtual AddrRangeList getAddrRanges(); private: bool isPhysMemAddress(Addr addr); @@ -83,7 +96,7 @@ friend class M5Port; - class PioPort : public QueuedPort + class PioPort : public QueuedMasterPort { private: @@ -119,7 +132,8 @@ void init(); - Port *getPort(const std::string &if_name, int idx); + MasterPort &getMasterPort(const std::string &if_name, int idx); + SlavePort &getSlavePort(const std::string &if_name, int idx); virtual RequestStatus makeRequest(PacketPtr pkt) = 0; virtual int outstandingCount() const = 0; @@ -163,9 +177,10 @@ PioPort physMemPort; - /*! Vector of CPU Port attached to this Ruby port. */ + /** Vector of M5 Ports attached to this Ruby port. */ typedef std::vector::iterator CpuPortIter; - std::vector cpu_ports; + std::vector slave_ports; + std::vector master_ports; Event *drainEvent; diff -r 8eed4047889b -r 48f97059228b src/mem/ruby/system/RubyPort.cc --- a/src/mem/ruby/system/RubyPort.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/ruby/system/RubyPort.cc Thu Mar 22 16:41:45 2012 +0000 @@ -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) 2009 Advanced Micro Devices, Inc. * Copyright (c) 2011 Mark D. Hill and David A. Wood * All rights reserved. @@ -35,26 +47,27 @@ #include "mem/ruby/system/RubyPort.hh" RubyPort::RubyPort(const Params *p) - : MemObject(p), pio_port(csprintf("%s-pio-port", name()), this), - physMemPort(csprintf("%s-physMemPort", name()), this) + : MemObject(p), m_version(p->version), m_controller(NULL), + m_mandatory_q_ptr(NULL), + pio_port(csprintf("%s-pio-port", name()), this), + m_usingRubyTester(p->using_ruby_tester), m_request_cnt(0), + physMemPort(csprintf("%s-physMemPort", name()), this), + drainEvent(NULL), physmem(p->physmem), ruby_system(p->ruby_system), + waitingOnSequencer(false), access_phys_mem(p->access_phys_mem) { - m_version = p->version; assert(m_version != -1); - physmem = p->physmem; + // create the slave ports based on the number of connected ports + for (size_t i = 0; i < p->port_slave_connection_count; ++i) { + slave_ports.push_back(new M5Port(csprintf("%s-slave%d", name(), i), + this, ruby_system, access_phys_mem)); + } - m_controller = NULL; - m_mandatory_q_ptr = NULL; - - m_request_cnt = 0; - - m_usingRubyTester = p->using_ruby_tester; - access_phys_mem = p->access_phys_mem; - - drainEvent = NULL; - - ruby_system = p->ruby_system; - waitingOnSequencer = false; + // create the master ports based on the number of connected ports + for (size_t i = 0; i < p->port_master_connection_count; ++i) { + master_ports.push_back(new PioPort(csprintf("%s-master%d", name(), i), + this)); + } } void @@ -64,52 +77,63 @@ m_mandatory_q_ptr = m_controller->getMandatoryQueue(); } -Port * -RubyPort::getPort(const std::string &if_name, int idx) +MasterPort & +RubyPort::getMasterPort(const std::string &if_name, int idx) { - // used by the CPUs to connect the caches to the interconnect, and - // for the x86 case also the interrupt master - if (if_name == "slave") { - M5Port* cpuPort = new M5Port(csprintf("%s-slave%d", name(), idx), - this, ruby_system, access_phys_mem); - cpu_ports.push_back(cpuPort); - return cpuPort; + if (if_name == "pio_port") { + return pio_port; + } + + if (if_name == "physMemPort") { + return physMemPort; } // used by the x86 CPUs to connect the interrupt PIO and interrupt slave // port - if (if_name == "master") { - PioPort* masterPort = new PioPort(csprintf("%s-master%d", name(), idx), - this); + if (if_name != "master") { + // pass it along to our super class + return MemObject::getMasterPort(if_name, idx); + } else { + if (idx >= static_cast(master_ports.size())) { + panic("RubyPort::getMasterPort: unknown index %d\n", idx); + } - return masterPort; + return *master_ports[idx]; } +} - if (if_name == "pio_port") { - return &pio_port; +SlavePort & +RubyPort::getSlavePort(const std::string &if_name, int idx) +{ + // used by the CPUs to connect the caches to the interconnect, and + // for the x86 case also the interrupt master + if (if_name != "slave") { + // pass it along to our super class + return MemObject::getSlavePort(if_name, idx); + } else { + if (idx >= static_cast(slave_ports.size())) { + panic("RubyPort::getSlavePort: unknown index %d\n", idx); + } + + return *slave_ports[idx]; } - - if (if_name == "physMemPort") { - return &physMemPort; - } - - return NULL; } RubyPort::PioPort::PioPort(const std::string &_name, RubyPort *_port) - : QueuedPort(_name, _port, queue), queue(*_port, *this), ruby_port(_port) + : QueuedMasterPort(_name, _port, queue), queue(*_port, *this), + ruby_port(_port) { - DPRINTF(RubyPort, "creating port to ruby sequencer to cpu %s\n", _name); + DPRINTF(RubyPort, "creating master port on ruby sequencer %s\n", _name); } RubyPort::M5Port::M5Port(const std::string &_name, RubyPort *_port, RubySystem *_system, bool _access_phys_mem) - : QueuedPort(_name, _port, queue), queue(*_port, *this), + : QueuedSlavePort(_name, _port, queue), queue(*_port, *this), ruby_port(_port), ruby_system(_system), _onRetryList(false), access_phys_mem(_access_phys_mem) { - DPRINTF(RubyPort, "creating port from ruby sequcner to cpu %s\n", _name); + DPRINTF(RubyPort, "creating slave port on ruby sequencer %s\n", _name); } Tick @@ -549,11 +573,15 @@ DPRINTF(Config, "count after physmem check %d\n", count); } - for (CpuPortIter p_iter = cpu_ports.begin(); p_iter != cpu_ports.end(); - p_iter++) { - M5Port* cpu_port = *p_iter; - count += cpu_port->drain(de); - DPRINTF(Config, "count after cpu port check %d\n", count); + for (CpuPortIter p = slave_ports.begin(); p != slave_ports.end(); ++p) { + count += (*p)->drain(de); + DPRINTF(Config, "count after slave port check %d\n", count); + } + + for (std::vector::iterator p = master_ports.begin(); + p != master_ports.end(); ++p) { + count += (*p)->drain(de); + DPRINTF(Config, "count after master port check %d\n", count); } DPRINTF(Config, "final count %d\n", count); @@ -657,11 +685,19 @@ return true; } +AddrRangeList +RubyPort::M5Port::getAddrRanges() +{ + // at the moment the assumption is that the master does not care + AddrRangeList ranges; + return ranges; +} + bool RubyPort::M5Port::isPhysMemAddress(Addr addr) { AddrRangeList physMemAddrList = - ruby_port->physMemPort.getPeer()->getAddrRanges(); + ruby_port->physMemPort.getSlavePort().getAddrRanges(); for (AddrRangeIter iter = physMemAddrList.begin(); iter != physMemAddrList.end(); iter++) { @@ -684,9 +720,12 @@ RubyPort::ruby_eviction_callback(const Address& address) { DPRINTF(RubyPort, "Sending invalidations.\n"); + // should this really be using funcMasterId? Request req(address.getAddress(), 0, 0, Request::funcMasterId); - for (CpuPortIter it = cpu_ports.begin(); it != cpu_ports.end(); it++) { - Packet *pkt = new Packet(&req, MemCmd::InvalidationReq, -1); - (*it)->sendNextCycle(pkt); + for (CpuPortIter p = slave_ports.begin(); p != slave_ports.end(); ++p) { + if ((*p)->getMasterPort().isSnooping()) { + Packet *pkt = new Packet(&req, MemCmd::InvalidationReq, -1); + (*p)->sendNextCycle(pkt); + } } } diff -r 8eed4047889b -r 48f97059228b src/mem/se_translating_port_proxy.hh --- a/src/mem/se_translating_port_proxy.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/se_translating_port_proxy.hh Thu Mar 22 16:41:45 2012 +0000 @@ -80,7 +80,7 @@ AllocType allocating; public: - SETranslatingPortProxy(Port& port, Process* p, AllocType alloc); + SETranslatingPortProxy(MasterPort& port, Process* p, AllocType alloc); virtual ~SETranslatingPortProxy(); bool tryReadBlob(Addr addr, uint8_t *p, int size) const; diff -r 8eed4047889b -r 48f97059228b src/mem/se_translating_port_proxy.cc --- a/src/mem/se_translating_port_proxy.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/se_translating_port_proxy.cc Thu Mar 22 16:41:45 2012 +0000 @@ -53,7 +53,7 @@ using namespace TheISA; -SETranslatingPortProxy::SETranslatingPortProxy(Port& port, Process *p, +SETranslatingPortProxy::SETranslatingPortProxy(MasterPort& port, Process *p, AllocType alloc) : PortProxy(port), pTable(p->pTable), process(p), allocating(alloc) diff -r 8eed4047889b -r 48f97059228b src/mem/tport.hh --- a/src/mem/tport.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/tport.hh Thu Mar 22 16:41:45 2012 +0000 @@ -57,7 +57,7 @@ * recvFunctional and recvTiming through recvAtomic. It is always a * slave port. */ -class SimpleTimingPort : public QueuedPort +class SimpleTimingPort : public QueuedSlavePort { protected: diff -r 8eed4047889b -r 48f97059228b src/mem/tport.cc --- a/src/mem/tport.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/mem/tport.cc Thu Mar 22 16:41:45 2012 +0000 @@ -46,7 +46,7 @@ SimpleTimingPort::SimpleTimingPort(const std::string& _name, MemObject* _owner) : - QueuedPort(_name, _owner, queue), queue(*_owner, *this) + QueuedSlavePort(_name, _owner, queue), queue(*_owner, *this) { } @@ -63,6 +63,9 @@ bool SimpleTimingPort::recvTiming(PacketPtr pkt) { + // the port is a slave and should hence only get timing requests + assert(pkt->isRequest()); + if (pkt->memInhibitAsserted()) { // snooper will supply based on copy of packet // still target's responsibility to delete packet diff -r 8eed4047889b -r 48f97059228b src/python/swig/pyobject.cc --- a/src/python/swig/pyobject.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/python/swig/pyobject.cc Thu Mar 22 16:41:45 2012 +0000 @@ -44,24 +44,6 @@ using namespace std; -/** - * Look up a MemObject port. Helper function for connectPorts(). - */ -Port * -lookupPort(SimObject *so, const std::string &name, int i) -{ - MemObject *mo = dynamic_cast(so); - if (mo == NULL) { - warn("error casting SimObject %s to MemObject", so->name()); - return NULL; - } - - Port *p = mo->getPort(name, i); - if (p == NULL) - warn("error looking up port %s on object %s", name, so->name()); - return p; -} - EtherInt * lookupEthPort(SimObject *so, const std::string &name, int i) { @@ -83,6 +65,7 @@ /** * Connect the described MemObject ports. Called from Python via SWIG. * The indices i1 & i2 will be -1 for regular ports, >= 0 for vector ports. + * SimObject1 is the master, and SimObject2 is the slave */ int connectPorts(SimObject *o1, const std::string &name1, int i1, @@ -109,16 +92,20 @@ } } } - Port *p1 = lookupPort(o1, name1, i1); - Port *p2 = lookupPort(o2, name2, i2); + MemObject *mo1, *mo2; + mo1 = dynamic_cast(o1); + mo2 = dynamic_cast(o2); - if (p1 == NULL || p2 == NULL) { - warn("connectPorts: port lookup error"); - return 0; + if(mo1 == NULL || mo2 == NULL) { + panic ("Error casting SimObjects %s and %s to MemObject", o1->name(), + o2->name()); } - p1->setPeer(p2); - p2->setPeer(p1); + // generic master/slave port connection + MasterPort& masterPort = mo1->getMasterPort(name1, i1); + SlavePort& slavePort = mo2->getSlavePort(name2, i2); + + masterPort.bind(slavePort); return 1; } diff -r 8eed4047889b -r 48f97059228b src/sim/system.hh --- a/src/sim/system.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/sim/system.hh Thu Mar 22 16:41:45 2012 +0000 @@ -78,7 +78,7 @@ * master for debug access and for non-structural entities that do * not have a port of their own. */ - class SystemPort : public Port + class SystemPort : public MasterPort { public: @@ -86,22 +86,16 @@ * Create a system port with a name and an owner. */ SystemPort(const std::string &_name, MemObject *_owner) - : Port(_name, _owner) + : MasterPort(_name, _owner) { } bool recvTiming(PacketPtr pkt) { panic("SystemPort does not receive timing!\n"); return false; } + void recvRetry() + { panic("SystemPort does not expect retry!\n"); } Tick recvAtomic(PacketPtr pkt) { panic("SystemPort does not receive atomic!\n"); return 0; } void recvFunctional(PacketPtr pkt) { panic("SystemPort does not receive functional!\n"); } - - /** - * 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() { } - }; SystemPort _systemPort; @@ -122,12 +116,12 @@ * * @return a reference to the system port we own */ - Port& getSystemPort() { return _systemPort; } + MasterPort& getSystemPort() { return _systemPort; } /** * Additional function to return the Port of a memory object. */ - Port *getPort(const std::string &if_name, int idx = -1); + MasterPort& getMasterPort(const std::string &if_name, int idx = -1); static const char *MemoryModeStrings[3]; diff -r 8eed4047889b -r 48f97059228b src/sim/system.cc --- a/src/sim/system.cc Thu Mar 22 16:41:39 2012 +0000 +++ b/src/sim/system.cc Thu Mar 22 16:41:45 2012 +0000 @@ -174,11 +174,11 @@ panic("System port on %s is not connected.\n", name()); } -Port* -System::getPort(const std::string &if_name, int idx) +MasterPort& +System::getMasterPort(const std::string &if_name, int idx) { // no need to distinguish at the moment (besides checking) - return &_systemPort; + return _systemPort; } void diff -r 8eed4047889b -r 48f97059228b src/sim/tlb.hh --- a/src/sim/tlb.hh Thu Mar 22 16:41:39 2012 +0000 +++ b/src/sim/tlb.hh Thu Mar 22 16:41:45 2012 +0000 @@ -49,8 +49,7 @@ #include "sim/sim_object.hh" class ThreadContext; -class Packet; -class Port; +class MasterPort; class BaseTLB : public SimObject { @@ -65,10 +64,16 @@ public: virtual void demapPage(Addr vaddr, uint64_t asn) = 0; - /** Get any port that the TLB or hardware table walker needs. - * This is used for migrating port connections during a takeOverFrom() - * call. */ - virtual Port* getPort() { return NULL; } + /** + * Get the table walker master port if present. This is used for + * migrating port connections during a CPU takeOverFrom() + * call. For architectures that do not have a table walker, NULL + * is returned, hence the use of a pointer rather than a + * reference. + * + * @return A pointer to the walker master port or NULL if not present + */ + virtual MasterPort* getMasterPort() { return NULL; } class Translation {