diff options
Diffstat (limited to 'src')
75 files changed, 1031 insertions, 653 deletions
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index 8bffe68f8..73a691cff 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -91,13 +91,13 @@ TableWalker::resume() } } -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 --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh index b5099bb27..a6ff2585b 100644 --- a/src/arch/arm/table_walker.hh +++ b/src/arch/arm/table_walker.hh @@ -358,7 +358,8 @@ class TableWalker : public MemObject 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 --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index 0b003e9fb..f9b2e6fe7 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -722,10 +722,10 @@ TLB::translateTiming(RequestPtr req, ThreadContext *tc, return fault; } -Port* -TLB::getPort() +MasterPort* +TLB::getMasterPort() { - return tableWalker->getPort("port"); + return &tableWalker->getMasterPort("port"); } diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh index daf59f01d..a20957f6a 100644 --- a/src/arch/arm/tlb.hh +++ b/src/arch/arm/tlb.hh @@ -214,8 +214,17 @@ class TLB : public BaseTLB 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 --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 6a9f07af2..a422a4758 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -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 @@ X86ISA::Interrupts::init() // BasicPioDevice::init(); IntDev::init(); + + // the slave port has a range so inform the connected master + intSlavePort.sendRangeChange(); } @@ -554,7 +569,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) break; } pendingIPIs += apics.size(); - intPort.sendMessage(apics, message, timing); + intMasterPort.sendMessage(apics, message, timing); newVal = regs[APIC_INTERRUPT_COMMAND_LOW]; } break; diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index abf3040bd..328e7159d 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -189,7 +189,7 @@ class Interrupts : public BasicPioDevice, IntDev int initialApicId; // Port for receiving interrupts - IntPort intSlavePort; + IntSlavePort intSlavePort; public: @@ -239,17 +239,20 @@ class Interrupts : public BasicPioDevice, IntDev 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 --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc index f29531cd5..87505f4df 100644 --- a/src/arch/x86/pagetable_walker.cc +++ b/src/arch/x86/pagetable_walker.cc @@ -154,11 +154,6 @@ Walker::WalkerPort::recvFunctional(PacketPtr pkt) } void -Walker::WalkerPort::recvRangeChange() -{ -} - -void Walker::WalkerPort::recvRetry() { walker->recvRetry(); @@ -182,13 +177,13 @@ bool Walker::sendTiming(WalkerState* sendingState, PacketPtr pkt) 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 --git a/src/arch/x86/pagetable_walker.hh b/src/arch/x86/pagetable_walker.hh index 90f075280..bf7a9e615 100644 --- a/src/arch/x86/pagetable_walker.hh +++ b/src/arch/x86/pagetable_walker.hh @@ -60,11 +60,11 @@ namespace X86ISA { 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 @@ namespace X86ISA 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 @@ namespace X86ISA 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 --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 10ef217e1..89561f851 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -428,10 +428,10 @@ TLB::unserialize(Checkpoint *cp, const std::string §ion) { } -Port * -TLB::getPort() +MasterPort * +TLB::getMasterPort() { - return walker->getPort("port"); + return &walker->getMasterPort("port"); } } // namespace X86ISA diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh index 078b8b8d6..bcadda762 100644 --- a/src/arch/x86/tlb.hh +++ b/src/arch/x86/tlb.hh @@ -125,7 +125,17 @@ namespace X86ISA 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 --git a/src/cpu/base.cc b/src/cpu/base.cc index 5d5f704db..d01dcbef3 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -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 @@ BaseCPU::regStats() 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 @@ BaseCPU::switchOut() void BaseCPU::takeOverFrom(BaseCPU *oldCPU) { - CpuPort &ic = getInstPort(); - CpuPort &dc = getDataPort(); assert(threadContexts.size() == oldCPU->threadContexts.size()); _cpuId = oldCPU->cpuId(); @@ -407,24 +405,21 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) 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 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) 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 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) // 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 @@ BaseCPU::CpuPort::recvFunctional(PacketPtr pkt) // long term this should never be called, but that assumed a split // into master/slave and request/response. } - -void -BaseCPU::CpuPort::recvRangeChange() -{ -} diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 149d26aa3..145b014aa 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -117,7 +117,7 @@ class BaseCPU : public MemObject * 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 @@ class BaseCPU : public MemObject * @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 @@ class BaseCPU : public MemObject void recvFunctional(PacketPtr pkt); - void recvRangeChange(); - }; public: @@ -172,11 +170,11 @@ class BaseCPU : public MemObject 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 @@ class BaseCPU : public MemObject * @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 --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index afc453f87..d816578ae 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -132,12 +132,6 @@ class CheckerCPU : public BaseCPU 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 --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh index d9f98e42c..3f3ef12e6 100644 --- a/src/cpu/inorder/resources/cache_unit.hh +++ b/src/cpu/inorder/resources/cache_unit.hh @@ -139,7 +139,7 @@ class CacheUnit : public Resource protected: /** Cache interface. */ - Port *cachePort; + MasterPort *cachePort; bool cachePortBlocked; diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 42e9f01f9..493730458 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -186,8 +186,7 @@ class FullO3CPU : public BaseO3CPU * * @return true since we have to snoop */ - virtual bool isSnooping() - { return true; } + virtual bool isSnooping() const { return true; } }; class TickEvent : public Event diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 702606d39..44898eb38 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -90,7 +90,7 @@ class LSQUnit { 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 @@ class LSQUnit { 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 --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index d0a630f6d..2de349242 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -239,7 +239,7 @@ LSQUnit<Impl>::regStats() template<class Impl> void -LSQUnit<Impl>::setDcachePort(Port *dcache_port) +LSQUnit<Impl>::setDcachePort(MasterPort *dcache_port) { dcachePort = dcache_port; } diff --git a/src/cpu/ozone/OzoneCPU.py b/src/cpu/ozone/OzoneCPU.py index d50d8d715..b4f37220c 100644 --- a/src/cpu/ozone/OzoneCPU.py +++ b/src/cpu/ozone/OzoneCPU.py @@ -36,9 +36,6 @@ class DerivOzoneCPU(BaseCPU): 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 --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index d2b90bff3..1bd2ee25b 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -316,8 +316,6 @@ class OzoneCPU : public BaseCPU System *system; PhysicalMemory *physmem; - virtual Port *getPort(const std::string &name, int idx); - FrontEnd *frontEnd; BackEnd *backEnd; diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index b111d4425..3a32c07c6 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -391,18 +391,6 @@ OzoneCPU<Impl>::init() } template <class Impl> -Port * -OzoneCPU<Impl>::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 <class Impl> void OzoneCPU<Impl>::serialize(std::ostream &os) { diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh index 41b86aab8..6c63bf8d9 100644 --- a/src/cpu/ozone/front_end.hh +++ b/src/cpu/ozone/front_end.hh @@ -68,7 +68,7 @@ class FrontEnd /** 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 @@ class FrontEnd /** 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 --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 2c9c70872..12aa0a321 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -59,12 +59,6 @@ FrontEnd<Impl>::IcachePort::recvFunctional(PacketPtr pkt) } template<class Impl> -void -FrontEnd<Impl>::IcachePort::recvRangeChange() -{ -} - -template<class Impl> bool FrontEnd<Impl>::IcachePort::recvTiming(PacketPtr pkt) { diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index 809725c0d..a581b242f 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -240,7 +240,7 @@ class OzoneLWLSQ { /** Pointer to the back-end stage. */ BackEnd *be; - class DcachePort : public Port + class DcachePort : public MasterPort { protected: OzoneLWLSQ *lsq; @@ -255,13 +255,10 @@ class OzoneLWLSQ { 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 --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index 82d0b4e8b..c0c6d7276 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -75,12 +75,6 @@ OzoneLWLSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) } template <class Impl> -void -OzoneLWLSQ<Impl>::DcachePort::recvRangeChange() -{ -} - -template <class Impl> bool OzoneLWLSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) { diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index e5b3bd67d..d7ad07a5e 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -65,14 +65,14 @@ AtomicSimpleCPU::TickEvent::description() const 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); } } @@ -94,7 +94,7 @@ AtomicSimpleCPU::init() } 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 --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 8a1c9000f..126cd3765 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -112,10 +112,11 @@ class AtomicSimpleCPU : public BaseSimpleCPU 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 --git a/src/cpu/testers/directedtest/RubyDirectedTester.cc b/src/cpu/testers/directedtest/RubyDirectedTester.cc index 4518066eb..bfdd28e08 100644 --- a/src/cpu/testers/directedtest/RubyDirectedTester.cc +++ b/src/cpu/testers/directedtest/RubyDirectedTester.cc @@ -75,19 +75,19 @@ RubyDirectedTester::init() 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<int>(ports.size())) { + panic("RubyDirectedTester::getMasterPort: unknown index %d\n", idx); + } - if (idx >= static_cast<int>(ports.size())) { - panic("RubyDirectedTester::getPort: unknown index %d requested\n", idx); + return *ports[idx]; } - - return ports[idx]; } Tick @@ -110,7 +110,7 @@ RubyDirectedTester::CpuPort::recvTiming(PacketPtr pkt) return true; } -Port* +MasterPort* RubyDirectedTester::getCpuPort(int idx) { assert(idx >= 0 && idx < ports.size()); diff --git a/src/cpu/testers/directedtest/RubyDirectedTester.hh b/src/cpu/testers/directedtest/RubyDirectedTester.hh index cd0632976..cb207ff80 100644 --- a/src/cpu/testers/directedtest/RubyDirectedTester.hh +++ b/src/cpu/testers/directedtest/RubyDirectedTester.hh @@ -47,7 +47,7 @@ class DirectedGenerator; class RubyDirectedTester : public MemObject { public: - class CpuPort : public Port + class CpuPort : public MasterPort { private: RubyDirectedTester *tester; @@ -55,25 +55,27 @@ class RubyDirectedTester : public MemObject 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 --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc index dffaa71ed..07cdf73a6 100644 --- a/src/cpu/testers/memtest/memtest.cc +++ b/src/cpu/testers/memtest/memtest.cc @@ -85,11 +85,6 @@ MemTest::CpuPort::recvFunctional(PacketPtr pkt) } void -MemTest::CpuPort::recvRangeChange() -{ -} - -void MemTest::CpuPort::recvRetry() { memtest->doRetry(); @@ -161,15 +156,15 @@ MemTest::MemTest(const Params *p) 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 --git a/src/cpu/testers/memtest/memtest.hh b/src/cpu/testers/memtest/memtest.hh index c56a37574..d179fa530 100644 --- a/src/cpu/testers/memtest/memtest.hh +++ b/src/cpu/testers/memtest/memtest.hh @@ -62,7 +62,8 @@ class MemTest : public MemObject // 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 @@ class MemTest : public MemObject 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 @@ class MemTest : public MemObject virtual void recvFunctional(PacketPtr pkt); - virtual void recvRangeChange(); - virtual void recvRetry(); }; diff --git a/src/cpu/testers/networktest/networktest.cc b/src/cpu/testers/networktest/networktest.cc index 3fe153c4e..01f247707 100644 --- a/src/cpu/testers/networktest/networktest.cc +++ b/src/cpu/testers/networktest/networktest.cc @@ -82,11 +82,6 @@ NetworkTest::CpuPort::recvFunctional(PacketPtr pkt) } void -NetworkTest::CpuPort::recvRangeChange() -{ -} - -void NetworkTest::CpuPort::recvRetry() { networktest->doRetry(); @@ -126,13 +121,13 @@ NetworkTest::NetworkTest(const Params *p) 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 --git a/src/cpu/testers/networktest/networktest.hh b/src/cpu/testers/networktest/networktest.hh index de67d41a0..21984f45d 100644 --- a/src/cpu/testers/networktest/networktest.hh +++ b/src/cpu/testers/networktest/networktest.hh @@ -57,7 +57,8 @@ class NetworkTest : public MemObject // 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 @@ class NetworkTest : public MemObject 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 @@ class NetworkTest : public MemObject virtual void recvFunctional(PacketPtr pkt); - virtual void recvRangeChange(); - virtual void recvRetry(); }; diff --git a/src/cpu/testers/rubytest/RubyTester.cc b/src/cpu/testers/rubytest/RubyTester.cc index 70ee40aed..e1942cf61 100644 --- a/src/cpu/testers/rubytest/RubyTester.cc +++ b/src/cpu/testers/rubytest/RubyTester.cc @@ -92,18 +92,19 @@ RubyTester::init() 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<int>(ports.size())) { + panic("RubyTester::getMasterPort: unknown index %d\n", idx); + } - if (idx >= static_cast<int>(ports.size())) { - panic("RubyTester::getPort: unknown index %d requested\n", idx); + return *ports[idx]; } - - return ports[idx]; } Tick @@ -135,7 +136,7 @@ RubyTester::CpuPort::recvTiming(PacketPtr pkt) return true; } -Port* +MasterPort* RubyTester::getCpuPort(int idx) { assert(idx >= 0 && idx < ports.size()); diff --git a/src/cpu/testers/rubytest/RubyTester.hh b/src/cpu/testers/rubytest/RubyTester.hh index e8cf4c874..b24dddd83 100644 --- a/src/cpu/testers/rubytest/RubyTester.hh +++ b/src/cpu/testers/rubytest/RubyTester.hh @@ -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 @@ class RubyTester : public MemObject 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 --git a/src/dev/copy_engine.cc b/src/dev/copy_engine.cc index 7b17a86a3..809649718 100644 --- a/src/dev/copy_engine.cc +++ b/src/dev/copy_engine.cc @@ -110,21 +110,26 @@ CopyEngine::CopyEngineChannel::~CopyEngineChannel() 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<int>(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 --git a/src/dev/copy_engine.hh b/src/dev/copy_engine.hh index aa0bf0896..28fc6315c 100644 --- a/src/dev/copy_engine.hh +++ b/src/dev/copy_engine.hh @@ -94,7 +94,7 @@ class CopyEngine : public PciDev 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 @@ class CopyEngine : public PciDev 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 --git a/src/dev/io_device.cc b/src/dev/io_device.cc index f7b8db09d..2937c66b1 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -71,14 +71,13 @@ PioDevice::init() 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 @@ BasicPioDevice::getAddrRanges() 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 @@ DmaDevice::~DmaDevice() } -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 --git a/src/dev/io_device.hh b/src/dev/io_device.hh index 400263957..9bb2c3d87 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -69,7 +69,7 @@ class PioPort : public SimpleTimingPort }; -class DmaPort : public Port +class DmaPort : public MasterPort { protected: struct DmaReqState : public Packet::SenderState, public FastAlloc @@ -148,16 +148,9 @@ class DmaPort : public Port 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 @@ class PioDevice : public MemObject 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 @@ class DmaDevice : public PioDevice 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 --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh index 07089fd0e..435188342 100644 --- a/src/dev/pcidev.hh +++ b/src/dev/pcidev.hh @@ -218,12 +218,12 @@ class PciDev : public DmaDevice 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 --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index 3d7454dfd..54824c778 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -222,8 +222,8 @@ X86ISA::I82094AA::signalInterrupt(int line) apics.push_back(selected); } } - intPort.sendMessage(apics, message, - sys->getMemoryMode() == Enums::timing); + intMasterPort.sendMessage(apics, message, + sys->getMemoryMode() == Enums::timing); } } diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index f0837cc27..d3eedea7b 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -121,11 +121,11 @@ class I82094AA : public PioDevice, public IntDev 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 --git a/src/dev/x86/intdev.cc b/src/dev/x86/intdev.cc index 0d038b93d..8580ae943 100644 --- a/src/dev/x86/intdev.cc +++ b/src/dev/x86/intdev.cc @@ -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 @@ X86ISA::IntDev::IntPort::sendMessage(ApicList apics, TriggerIntMessage message, void X86ISA::IntDev::init() { - if (!intPort.isConnected()) { + if (!intMasterPort.isConnected()) { panic("Int port not connected to anything!"); } - intPort.sendRangeChange(); } X86ISA::IntSourcePin * diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh index 5549df637..bbdd98b24 100644 --- a/src/dev/x86/intdev.hh +++ b/src/dev/x86/intdev.hh @@ -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 @@ typedef std::list<int> ApicList; 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 @@ class IntDev { 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 @@ class IntDev 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 --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc index 357665184..89f2990b9 100644 --- a/src/kern/tru64/tru64_events.cc +++ b/src/kern/tru64/tru64_events.cc @@ -60,9 +60,9 @@ BadAddrEvent::process(ThreadContext *tc) 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 --git a/src/mem/bridge.cc b/src/mem/bridge.cc index 0733b6ea8..ebb37e792 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -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 @@ Bridge::BridgeSlavePort::BridgeSlavePort(const std::string &_name, int _delay, int _nack_delay, int _resp_limit, std::vector<Range<Addr> > _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::BridgeMasterPort::BridgeMasterPort(const std::string &_name, 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,19 +88,25 @@ Bridge::Bridge(Params *p) 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 == "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; - } + 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 + // pass it along to our super class + return MemObject::getSlavePort(if_name, idx); +} void Bridge::init() @@ -473,19 +479,6 @@ Bridge::BridgeMasterPort::checkFunctional(PacketPtr pkt) 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 --git a/src/mem/bridge.hh b/src/mem/bridge.hh index 3e0040514..e7dbc0a28 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -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 @@ class Bridge : public MemObject * 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 @@ class Bridge : public MemObject 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 @@ class Bridge : public MemObject * 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 @@ class Bridge : public MemObject /** 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 @@ class Bridge : public MemObject 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 --git a/src/mem/bus.cc b/src/mem/bus.cc index 0c0e3c3e2..c89455f02 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -39,6 +39,7 @@ * * Authors: Ali Saidi * Andreas Hansson + * William Wang */ /** @@ -72,12 +73,14 @@ Bus::Bus(const BusParams *p) // 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 @@ Bus::Bus(const BusParams *p) 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 @@ Bus::Bus(const BusParams *p) // 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<BusPort*>::iterator intIter; + std::vector<BusSlavePort*>::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 @@ Bus::recvTiming(PacketPtr pkt) // 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 @@ Bus::recvTiming(PacketPtr pkt) 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 @@ Bus::recvTiming(PacketPtr pkt) // 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 @@ Bus::retryWaiting() // 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 @@ Bus::recvAtomic(PacketPtr pkt) 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 @@ Bus::recvAtomic(PacketPtr pkt) // 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 @@ Bus::recvFunctional(PacketPtr pkt) 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 @@ Bus::recvFunctional(PacketPtr pkt) // 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 @@ Bus::recvRangeChange(int id) 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 @@ Bus::recvRangeChange(int id) } } 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 @@ Bus::recvRangeChange(int id) 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 @@ Bus::recvRangeChange(int id) 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 @@ Bus::recvRangeChange(int id) // tell all our peers that our address range has changed. // Don't tell the device that caused this change, it already knows - std::vector<BusPort*>::const_iterator intIter; + std::vector<BusSlavePort*>::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 @@ Bus::getAddrRanges(int id) } 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 @@ Bus::findBlockSize(int id) 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 --git a/src/mem/bus.hh b/src/mem/bus.hh index 4ea92308a..e79e9df9e 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -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 interface ID of this port. */ + int id; + + public: + + /** 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 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 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 @@ class Bus : public MemObject * * @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 @@ class Bus : public MemObject 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 @@ class Bus : public MemObject AddrRangeList defaultRange; - typedef std::vector<BusPort*>::iterator SnoopIter; - std::vector<BusPort*> snoopPorts; + typedef std::vector<BusSlavePort*>::iterator SnoopIter; + std::vector<BusSlavePort*> snoopPorts; /** Function called by the port when the bus is recieving a Timing transaction.*/ @@ -250,7 +308,7 @@ class Bus : public MemObject * * @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 @@ class Bus : public MemObject // interfaces vector unsigned int nbrMasterPorts; - /** An ordered vector of pointers to the peer port interfaces - connected to this bus.*/ - std::vector<BusPort*> interfaces; + /** The master and slave ports of the bus */ + std::vector<BusSlavePort*> slavePorts; + std::vector<BusMasterPort*> 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 @@ class Bus : public MemObject 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 --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc index a2cb59a76..4ae6376db 100644 --- a/src/mem/cache/base.cc +++ b/src/mem/cache/base.cc @@ -57,7 +57,7 @@ using namespace std; 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 @@ BaseCache::CacheSlavePort::clearBlocked() 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 @@ void 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 --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index c13d27d42..47cbaf7a0 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -118,7 +118,7 @@ class BaseCache : public MemObject * 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 @@ class BaseCache : public MemObject CacheMasterPort(const std::string &_name, BaseCache *_cache, PacketQueue &_queue) : - QueuedPort(_name, _cache, _queue) + QueuedMasterPort(_name, _cache, _queue) { } /** @@ -157,7 +157,7 @@ class BaseCache : public MemObject * * @return always true */ - virtual bool isSnooping() { return true; } + virtual bool isSnooping() const { return true; } }; /** @@ -168,7 +168,7 @@ class BaseCache : public MemObject * 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 @@ class BaseCache : public MemObject 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 --git a/src/mem/cache/builder.cc b/src/mem/cache/builder.cc index cc206b784..ca8c378fb 100644 --- a/src/mem/cache/builder.cc +++ b/src/mem/cache/builder.cc @@ -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 --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 782749aab..e745529a7 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -249,8 +249,6 @@ class Cache : public BaseCache /** 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 --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 2463071de..3525e0777 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -92,19 +92,6 @@ Cache<TagStore>::regStats() } template<class TagStore> -Port * -Cache<TagStore>::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<class TagStore> void Cache<TagStore>::cmpAndSwap(BlkType *blk, PacketPtr pkt) { @@ -795,7 +782,7 @@ Cache<TagStore>::functionalAccess(PacketPtr pkt, bool fromCpuSide) // 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 --git a/src/mem/fs_translating_port_proxy.cc b/src/mem/fs_translating_port_proxy.cc index 2e9a0fa00..bf0c076c6 100644 --- a/src/mem/fs_translating_port_proxy.cc +++ b/src/mem/fs_translating_port_proxy.cc @@ -58,7 +58,7 @@ FSTranslatingPortProxy::FSTranslatingPortProxy(ThreadContext *tc) { } -FSTranslatingPortProxy::FSTranslatingPortProxy(Port &port) +FSTranslatingPortProxy::FSTranslatingPortProxy(MasterPort &port) : PortProxy(port), _tc(NULL) { } diff --git a/src/mem/fs_translating_port_proxy.hh b/src/mem/fs_translating_port_proxy.hh index 2217a46aa..c022f3d09 100644 --- a/src/mem/fs_translating_port_proxy.hh +++ b/src/mem/fs_translating_port_proxy.hh @@ -78,7 +78,7 @@ class FSTranslatingPortProxy : public PortProxy FSTranslatingPortProxy(ThreadContext* tc); - FSTranslatingPortProxy(Port &port); + FSTranslatingPortProxy(MasterPort &port); virtual ~FSTranslatingPortProxy(); diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc index 111d3718c..ce8badbe7 100644 --- a/src/mem/mem_object.cc +++ b/src/mem/mem_object.cc @@ -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 @@ MemObject::MemObject(const Params *params) : 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 --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh index 5865fc935..d8e6bdcb0 100644 --- a/src/mem/mem_object.hh +++ b/src/mem/mem_object.hh @@ -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 @@ class MemObject : public SimObject 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 --git a/src/mem/mport.cc b/src/mem/mport.cc index 2c57030b1..9af394d27 100644 --- a/src/mem/mport.cc +++ b/src/mem/mport.cc @@ -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 --git a/src/mem/mport.hh b/src/mem/mport.hh index 7f167c227..664acc559 100644 --- a/src/mem/mport.hh +++ b/src/mem/mport.hh @@ -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 @@ class MessagePort : public SimpleTimingPort 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 --git a/src/mem/physical.cc b/src/mem/physical.cc index f11fbb947..9c953e562 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -439,18 +439,18 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt) } -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<int>(ports.size())) { + fatal("PhysicalMemory::getSlavePort: unknown index %d\n", idx); + } - if (idx >= static_cast<int>(ports.size())) { - panic("PhysicalMemory::getPort: unknown index %d requested\n", idx); + return *ports[idx]; } - - return ports[idx]; } PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, @@ -458,13 +458,6 @@ PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, : 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 --git a/src/mem/physical.hh b/src/mem/physical.hh index b447237c7..452ac3fc0 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -67,8 +67,6 @@ class PhysicalMemory : public MemObject virtual void recvFunctional(PacketPtr pkt); - virtual void recvRangeChange(); - virtual AddrRangeList getAddrRanges(); virtual unsigned deviceBlockSize() const; @@ -196,7 +194,7 @@ class PhysicalMemory : public MemObject 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 --git a/src/mem/port.cc b/src/mem/port.cc index 8edca16f7..3305541c7 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -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 @@ Port::~Port() { } -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() +{ } -void -Port::setOwner(MemObject *_owner) +SlavePort& +MasterPort::getSlavePort() const { - owner = _owner; + if(_slavePort == NULL) + panic("Cannot getSlavePort on master port %s that is not connected\n", + name()); + + return *_slavePort; } void -Port::printAddr(Addr a) +MasterPort::bind(SlavePort& slave_port) +{ + // 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); +} + +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 @@ Port::printAddr(Addr a) 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 --git a/src/mem/port.hh b/src/mem/port.hh index fef0c839d..80bb3b085 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -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 @@ typedef std::list<Range<Addr> >::iterator AddrRangeIter; 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 { - protected: + + private: + /** Descriptive name (for DPRINTF output) */ - mutable std::string portName; + 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; + protected: - /** A pointer to the MemObject that owns this port. This may not be set. */ - MemObject *owner; + /** A pointer to the peer port. */ + Port* peer; + + /** A reference to the MemObject that owns this port. */ + MemObject& owner; - public: /** - * Constructor. + * Abstract base class for ports * - * @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. + * @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); - - /** Return port name (for DPRINTF). */ - const std::string &name() const { return portName; } + Port(const std::string& _name, MemObject& _owner); + /** + * Virtual destructor due to inheritance. + */ 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; } + public: - bool isConnected() { return peer != NULL; } + /** Return port name (for DPRINTF). */ + const std::string name() const { return portName; } protected: @@ -141,89 +124,109 @@ class Port /** 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 sendTiming was unsuccesful, and had to + * wait. + */ + virtual void recvRetry() = 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("??"); } + public: - /** 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. + /** + * 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. + * + * @param pkt Packet to send. + * + * @return If the send was succesful or not. */ - virtual unsigned deviceBlockSize() const { return 0; } + bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); } - public: + /** + * Send a retry to a peer port that previously attempted a sendTiming + * which was unsuccessful. + */ + void sendRetry() { return peer->recvRetry(); } /** - * 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. + * Send an atomic packet, where the data is moved and the state + * is updated in zero time, without interleaving with other + * memory accesses. * - * @return a list of ranges responded to + * @param pkt Packet to send. + * + * @return Estimated latency of access. */ - virtual AddrRangeList getAddrRanges() - { AddrRangeList ranges; return ranges; } + Tick sendAtomic(PacketPtr pkt) { return peer->recvAtomic(pkt); } /** - * Determine if this port is snooping or not. The default - * implementation returns false and thus tells the neighbour we - * are not snooping. Any port that is to snoop (e.g. a cache - * connected to a bus) has to override this function. + * 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. * - * @return true if the port should be considered a snooper + * @param pkt Packet to send. */ - 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); } + void sendFunctional(PacketPtr pkt) { return peer->recvFunctional(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); } +/** 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 by the associated device to send a status range to the - * peer interface. + * 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. */ - void sendRangeChange() const { peer->recvRangeChange(); } + virtual void recvRangeChange() { } - /** When a timing access doesn't return a success, some time later the - Retry will be sent. - */ - void sendRetry() { return peer->recvRetry(); } + /** + * Determine if this master port is snooping or not. The default + * implementation returns false and thus tells the neighbour we + * 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() const { return false; } + + /** + * 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 { 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 @@ class Port 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 --git a/src/mem/port_proxy.hh b/src/mem/port_proxy.hh index b2b27312e..4600cd407 100644 --- a/src/mem/port_proxy.hh +++ b/src/mem/port_proxy.hh @@ -86,12 +86,12 @@ class PortProxy 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 --git a/src/mem/qport.hh b/src/mem/qport.hh index 39612d22f..6ee71a572 100644 --- a/src/mem/qport.hh +++ b/src/mem/qport.hh @@ -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 @@ class QueuedPort : public Port * 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 @@ class QueuedPort : public Port * 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 --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index aca6604c6..1769c51fd 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -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; - - 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; + // 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)); + } - 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 @@ RubyPort::init() 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<int>(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<int>(slave_ports.size())) { + panic("RubyPort::getSlavePort: unknown index %d\n", idx); + } - if (if_name == "physMemPort") { - return &physMemPort; + return *slave_ports[idx]; } - - 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 @@ RubyPort::getDrainCount(Event *de) 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<PioPort*>::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 @@ RubyPort::PioPort::sendNextCycle(PacketPtr pkt) 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 @@ void 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 --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh index bef291d63..d97f6e69e 100644 --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -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 AbstractController; class RubyPort : public MemObject { public: - class M5Port : public QueuedPort + class M5Port : public QueuedSlavePort { private: @@ -74,6 +86,7 @@ class RubyPort : public MemObject 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 @@ class RubyPort : public MemObject friend class M5Port; - class PioPort : public QueuedPort + class PioPort : public QueuedMasterPort { private: @@ -119,7 +132,8 @@ class RubyPort : public MemObject 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 @@ class RubyPort : public MemObject PioPort physMemPort; - /*! Vector of CPU Port attached to this Ruby port. */ + /** Vector of M5 Ports attached to this Ruby port. */ typedef std::vector<M5Port*>::iterator CpuPortIter; - std::vector<M5Port*> cpu_ports; + std::vector<M5Port*> slave_ports; + std::vector<PioPort*> master_ports; Event *drainEvent; diff --git a/src/mem/se_translating_port_proxy.cc b/src/mem/se_translating_port_proxy.cc index 2ab130744..72466655c 100644 --- a/src/mem/se_translating_port_proxy.cc +++ b/src/mem/se_translating_port_proxy.cc @@ -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 --git a/src/mem/se_translating_port_proxy.hh b/src/mem/se_translating_port_proxy.hh index 31874e6b8..c0e522611 100644 --- a/src/mem/se_translating_port_proxy.hh +++ b/src/mem/se_translating_port_proxy.hh @@ -80,7 +80,7 @@ class SETranslatingPortProxy : public PortProxy 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 --git a/src/mem/tport.cc b/src/mem/tport.cc index bf3d59a8f..db2c72bbc 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -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 @@ SimpleTimingPort::recvFunctional(PacketPtr pkt) 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 --git a/src/mem/tport.hh b/src/mem/tport.hh index c77166386..91706fbe9 100644 --- a/src/mem/tport.hh +++ b/src/mem/tport.hh @@ -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 --git a/src/python/swig/pyobject.cc b/src/python/swig/pyobject.cc index 3478310b1..05698e794 100644 --- a/src/python/swig/pyobject.cc +++ b/src/python/swig/pyobject.cc @@ -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<MemObject *>(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 @@ lookupEthPort(SimObject *so, const std::string &name, int i) /** * 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 @@ connectPorts(SimObject *o1, const std::string &name1, int i1, } } } - Port *p1 = lookupPort(o1, name1, i1); - Port *p2 = lookupPort(o2, name2, i2); + MemObject *mo1, *mo2; + mo1 = dynamic_cast<MemObject*>(o1); + mo2 = dynamic_cast<MemObject*>(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 --git a/src/sim/system.cc b/src/sim/system.cc index 4601d2d52..2c5d4e44b 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -174,11 +174,11 @@ System::init() 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 --git a/src/sim/system.hh b/src/sim/system.hh index dd122161d..d5e45fa0d 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -78,7 +78,7 @@ class System : public MemObject * 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 @@ class System : public MemObject * 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 @@ class System : public MemObject * * @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 --git a/src/sim/tlb.hh b/src/sim/tlb.hh index 253f12072..379cdd343 100644 --- a/src/sim/tlb.hh +++ b/src/sim/tlb.hh @@ -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 @@ class BaseTLB : public SimObject 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 { |