diff -r b8abb27c5a88 -r 11e228ae7ed4 src/arch/arm/table_walker.hh --- a/src/arch/arm/table_walker.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/arch/arm/table_walker.hh Tue Jul 17 19:06:02 2012 +0100 @@ -262,10 +262,10 @@ protected: /** - * A snooping DMA port that currently does nothing besides - * extending the DMA port to accept snoops without complaining. + * A snooping DMA handler that currently does nothing besides + * extending the DMA handler to accept snoops without complaining. */ - class SnoopingDmaPort : public DmaPort + class SnoopingDmaHandler : public DmaHandler { protected: @@ -284,12 +284,12 @@ public: /** - * A snooping DMA port merely calls the construtor of the DMA - * port. + * A snooping DMA handler merely calls the construtor of + * the DMA handler. */ - SnoopingDmaPort(MemObject *dev, System *s, Tick min_backoff, - Tick max_backoff) : - DmaPort(dev, s, min_backoff, max_backoff) + SnoopingDmaHandler(MemObject *dev, System *s, Tick min_backoff, + Tick max_backoff) : + DmaHandler(dev, s, min_backoff, max_backoff) { } }; @@ -362,7 +362,8 @@ /** Port to issue translation requests from */ - SnoopingDmaPort port; + SnoopingDmaHandler handler; + DmaPort port; /** TLB that is initiating these table walks */ TLB *tlb; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/arch/arm/table_walker.cc --- a/src/arch/arm/table_walker.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/arch/arm/table_walker.cc Tue Jul 17 19:06:02 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -50,8 +50,10 @@ using namespace ArmISA; TableWalker::TableWalker(const Params *p) - : MemObject(p), port(this, params()->sys, params()->min_backoff, - params()->max_backoff), + : MemObject(p), + handler(this, params()->sys, params()->min_backoff, + params()->max_backoff), + port(this->name() + "-tablewalker-port", this, handler), tlb(NULL), currState(NULL), pending(false), masterId(p->sys->getMasterId(name())), doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this) @@ -220,24 +222,24 @@ } if (currState->timing) { - port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), - &doL1DescEvent, (uint8_t*)&currState->l1Desc.data, - currState->tc->getCpuPtr()->ticks(1), flag); + port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), + &doL1DescEvent, (uint8_t*)&currState->l1Desc.data, + currState->tc->getCpuPtr()->ticks(1), flag); DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", stateQueueL1.size()); stateQueueL1.push_back(currState); currState = NULL; } else if (!currState->functional) { - port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), - NULL, (uint8_t*)&currState->l1Desc.data, - currState->tc->getCpuPtr()->ticks(1), flag); + port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), + NULL, (uint8_t*)&currState->l1Desc.data, + currState->tc->getCpuPtr()->ticks(1), flag); doL1Descriptor(); f = currState->fault; } else { RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag, masterId); PacketPtr pkt = new Packet(req, MemCmd::ReadReq); pkt->dataStatic((uint8_t*)&currState->l1Desc.data); - port.sendFunctional(pkt); + port->sendFunctional(pkt); doL1Descriptor(); delete req; delete pkt; @@ -569,20 +571,20 @@ if (currState->timing) { currState->delayed = true; - port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), - &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, - currState->tc->getCpuPtr()->ticks(1)); + port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), + &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, + currState->tc->getCpuPtr()->ticks(1)); } else if (!currState->functional) { - port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), - NULL, (uint8_t*)&currState->l2Desc.data, - currState->tc->getCpuPtr()->ticks(1)); + port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), + NULL, (uint8_t*)&currState->l2Desc.data, + currState->tc->getCpuPtr()->ticks(1)); doL2Descriptor(); } else { RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0, masterId); PacketPtr pkt = new Packet(req, MemCmd::ReadReq); pkt->dataStatic((uint8_t*)&currState->l2Desc.data); - port.sendFunctional(pkt); + port->sendFunctional(pkt); doL2Descriptor(); delete req; delete pkt; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/arch/x86/interrupts.hh --- a/src/arch/x86/interrupts.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/arch/x86/interrupts.hh Tue Jul 17 19:06:02 2012 +0100 @@ -189,7 +189,8 @@ int initialApicId; // Port for receiving interrupts - IntSlavePort intSlavePort; + IntSlaveHandler intSlaveHandler; + SlavePort intSlavePort; public: diff -r b8abb27c5a88 -r 11e228ae7ed4 src/arch/x86/interrupts.cc --- a/src/arch/x86/interrupts.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/arch/x86/interrupts.cc Tue Jul 17 19:06:02 2012 +0100 @@ -319,7 +319,7 @@ IntDev::init(); // the slave port has a range so inform the connected master - intSlavePort.sendRangeChange(); + intSlavePort->sendRangeChange(); } @@ -569,7 +569,7 @@ break; } pendingIPIs += apics.size(); - intMasterPort.sendMessage(apics, message, timing); + intMasterPort->sendMessage(apics, message, timing); newVal = regs[APIC_INTERRUPT_COMMAND_LOW]; } break; @@ -628,7 +628,8 @@ pendingStartup(false), startupVector(0), startedUp(false), pendingUnmaskableInt(false), pendingIPIs(0), cpu(NULL), - intSlavePort(name() + ".int_slave", this, this, latency) + intSlaveHandler(this, this, latency), + intSlavePort(name() + ".int_slave", this, intSlaveHandler) { pioSize = PageBytes; memset(regs, 0, sizeof(regs)); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/arch/x86/pagetable_walker.hh --- a/src/arch/x86/pagetable_walker.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/arch/x86/pagetable_walker.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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) 2007 The Hewlett-Packard Development Company * All rights reserved. * @@ -59,11 +71,11 @@ { protected: // Port for accessing memory - class WalkerPort : public MasterPort + class WalkerHandler : public MasterInterface { public: - WalkerPort(const std::string &_name, Walker * _walker) : - MasterPort(_name, _walker), walker(_walker) + WalkerHandler(Walker * _walker) : + walker(_walker) {} protected: @@ -81,8 +93,8 @@ bool isSnooping() const { return true; } }; - friend class WalkerPort; - WalkerPort port; + WalkerHandler handler; + MasterPort port; // State to track each walk of the page table class WalkerState @@ -199,7 +211,8 @@ } Walker(const Params *params) : - MemObject(params), port(name() + ".port", this), + MemObject(params), handler(this), + port(name() + ".port", this, handler), funcState(this, NULL, NULL, true), tlb(NULL), sys(params->system), masterId(sys->getMasterId(name())) { diff -r b8abb27c5a88 -r 11e228ae7ed4 src/arch/x86/pagetable_walker.cc --- a/src/arch/x86/pagetable_walker.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/arch/x86/pagetable_walker.cc Tue Jul 17 19:06:02 2012 +0100 @@ -114,7 +114,7 @@ } bool -Walker::WalkerPort::recvTimingResp(PacketPtr pkt) +Walker::WalkerHandler::recvTimingResp(PacketPtr pkt) { return walker->recvTimingResp(pkt); } @@ -150,7 +150,7 @@ } void -Walker::WalkerPort::recvRetry() +Walker::WalkerHandler::recvRetry() { walker->recvRetry(); } @@ -170,7 +170,7 @@ bool Walker::sendTiming(WalkerState* sendingState, PacketPtr pkt) { pkt->senderState = new WalkerSenderState(sendingState, pkt->senderState); - return port.sendTimingReq(pkt); + return port->sendTimingReq(pkt); } BaseMasterPort & @@ -207,14 +207,14 @@ sendPackets(); } else { do { - walker->port.sendAtomic(read); + walker->port->sendAtomic(read); PacketPtr write = NULL; fault = stepWalk(write); assert(fault == NoFault || read == NULL); state = nextState; nextState = Ready; if (write) - walker->port.sendAtomic(write); + walker->port->sendAtomic(write); } while(read); state = Ready; nextState = Waiting; @@ -231,7 +231,7 @@ setupWalk(addr); do { - walker->port.sendFunctional(read); + walker->port->sendFunctional(read); // On a functional access (page table lookup), writes should // not happen so this pointer is ignored after stepWalk PacketPtr write = NULL; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/base.hh --- a/src/cpu/base.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/base.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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 @@ -105,26 +105,15 @@ MasterID _dataMasterId; /** - * Define a base class for the CPU ports (instruction and data) + * Define a base handler for the CPU ports (instruction and data) * that is refined in the subclasses. This class handles the * common cases, i.e. the functional accesses and the status * changes and address range queries. The default behaviour for * both atomic and timing access is to panic and the corresponding * subclasses have to override these methods. */ - class CpuPort : public MasterPort + class CpuHandler : public MasterInterface { - public: - - /** - * Create a CPU port with a name and a structural owner. - * - * @param _name port name including the owner - * @param _name structural owner of this port - */ - CpuPort(const std::string& _name, MemObject* _owner) : - MasterPort(_name, _owner) - { } protected: @@ -136,23 +125,24 @@ }; + MasterPort icachePort; + MasterPort dcachePort; + public: /** - * Purely virtual method that returns a reference to the data - * port. All subclasses must implement this method. + * Get the data port of the CPU. * * @return a reference to the data port */ - virtual CpuPort &getDataPort() = 0; + MasterPort &getDataPort() { return dcachePort; } /** - * Purely virtual method that returns a reference to the instruction - * port. All subclasses must implement this method. + * Get the instruction port of the CPU. * * @return a reference to the instruction port */ - virtual CpuPort &getInstPort() = 0; + MasterPort &getInstPort() { return icachePort; } /** Reads this CPU's ID. */ int cpuId() { return _cpuId; } @@ -288,7 +278,21 @@ typedef BaseCPUParams Params; const Params *params() const { return reinterpret_cast(_params); } - BaseCPU(Params *params, bool is_checker = false); + + /** + * Construct a BaseCPU based on the parameters, and with a + * specific handler for the instruction and data port, passed from + * the subclass that is calling this constructor. All the + * different CPUs rely on the instruction and data port of the + * BaseCPU, but have different handlers to reflect their + * differences in behaviour. + * + * @param params Parameter from the Python specification + * @param instHandler Handler for the instruction port + * @param dataHandler Handler for the data port + */ + BaseCPU(Params *params, CpuHandler &instHandler, + CpuHandler &dataHandler, bool is_checker = false); virtual ~BaseCPU(); virtual void init(); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/base.cc --- a/src/cpu/base.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/base.cc Tue Jul 17 19:06:02 2012 +0100 @@ -114,10 +114,13 @@ return "CPU Progress"; } -BaseCPU::BaseCPU(Params *p, bool is_checker) +BaseCPU::BaseCPU(Params *p, CpuHandler &instHandler, + CpuHandler &dataHandler, bool is_checker) : MemObject(p), clock(p->clock), instCnt(0), _cpuId(p->cpu_id), _instMasterId(p->system->getMasterId(name() + ".inst")), _dataMasterId(p->system->getMasterId(name() + ".data")), + icachePort(name() + ".icache_port", this, instHandler), + dcachePort(name() + ".dcache_port", this, dataHandler), interrupts(p->interrupts), numThreads(p->numThreads), system(p->system), phase(p->phase) @@ -537,20 +540,20 @@ } bool -BaseCPU::CpuPort::recvTimingResp(PacketPtr pkt) +BaseCPU::CpuHandler::recvTimingResp(PacketPtr pkt) { panic("BaseCPU doesn't expect recvTiming!\n"); return true; } void -BaseCPU::CpuPort::recvRetry() +BaseCPU::CpuHandler::recvRetry() { panic("BaseCPU doesn't expect recvRetry!\n"); } void -BaseCPU::CpuPort::recvFunctionalSnoop(PacketPtr pkt) +BaseCPU::CpuHandler::recvFunctionalSnoop(PacketPtr pkt) { // No internal storage to update (in the general case). A CPU with // internal storage, e.g. an LSQ that should be part of the diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/base_dyn_inst.hh --- a/src/cpu/base_dyn_inst.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/base_dyn_inst.hh Tue Jul 17 19:06:02 2012 +0100 @@ -976,7 +976,7 @@ RequestPtr &sreqHigh) { // Check to see if the request crosses the next level block boundary. - unsigned block_size = cpu->getDataPort().peerBlockSize(); + unsigned block_size = cpu->getDataPort()->peerBlockSize(); Addr addr = req->getVaddr(); Addr split_addr = roundDown(addr + req->getSize() - 1, block_size); assert(split_addr <= addr || split_addr - addr < block_size); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/checker/cpu.hh --- a/src/cpu/checker/cpu.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/checker/cpu.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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 @@ -111,25 +111,19 @@ System *systemPtr; - void setIcachePort(CpuPort *icache_port); + void setIcachePort(MasterPort *icache_port); - CpuPort *icachePort; + MasterPort *icachePort; - void setDcachePort(CpuPort *dcache_port); + // Instantiate a default handler to pass to the BaseCPU + CpuHandler instHandler; - CpuPort *dcachePort; + void setDcachePort(MasterPort *dcache_port); - CpuPort &getDataPort() - { - panic("Not supported on checker!"); - return *dcachePort; - } + // Instantiate a default handler to pass to the BaseCPU + CpuHandler dataHandler; - CpuPort &getInstPort() - { - panic("Not supported on checker!"); - return *icachePort; - } + MasterPort *dcachePort; public: // Primary thread being run. diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/checker/cpu.cc --- a/src/cpu/checker/cpu.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/checker/cpu.cc Tue Jul 17 19:06:02 2012 +0100 @@ -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 @@ -65,7 +65,7 @@ } CheckerCPU::CheckerCPU(Params *p) - : BaseCPU(p, true), thread(NULL), tc(NULL) + : BaseCPU(p, instHandler, dataHandler, true), thread(NULL), tc(NULL) { memReq = NULL; curStaticInst = NULL; @@ -115,13 +115,13 @@ } void -CheckerCPU::setIcachePort(CpuPort *icache_port) +CheckerCPU::setIcachePort(MasterPort *icache_port) { icachePort = icache_port; } void -CheckerCPU::setDcachePort(CpuPort *dcache_port) +CheckerCPU::setDcachePort(MasterPort *dcache_port) { dcachePort = dcache_port; } @@ -140,7 +140,7 @@ CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags) { Fault fault = NoFault; - unsigned blockSize = dcachePort->peerBlockSize(); + unsigned blockSize = (*dcachePort)->peerBlockSize(); int fullSize = size; Addr secondAddr = roundDown(addr + size - 1, blockSize); bool checked_flags = false; @@ -178,7 +178,7 @@ if (!(memReq->isUncacheable() || memReq->isMmappedIpr())) { // Access memory to see if we have the same data - dcachePort->sendFunctional(pkt); + (*dcachePort)->sendFunctional(pkt); } else { // Assume the data is correct if it's an uncached access memcpy(data, unverifiedMemData, size); @@ -234,7 +234,7 @@ bool flags_match = true; Addr pAddr = 0x0; - unsigned blockSize = dcachePort->peerBlockSize(); + unsigned blockSize = (*dcachePort)->peerBlockSize(); int fullSize = size; Addr secondAddr = roundDown(addr + size - 1, blockSize); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/checker/cpu_impl.hh --- a/src/cpu/checker/cpu_impl.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/checker/cpu_impl.hh Tue Jul 17 19:06:02 2012 +0100 @@ -286,7 +286,7 @@ PacketPtr pkt = new Packet(memReq, MemCmd::ReadReq); pkt->dataStatic(&machInst); - icachePort->sendFunctional(pkt); + (*icachePort)->sendFunctional(pkt); machInst = gtoh(machInst); delete memReq; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/inorder/cpu.hh --- a/src/cpu/inorder/cpu.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/inorder/cpu.hh Tue Jul 17 19:06:02 2012 +0100 @@ -108,12 +108,6 @@ InOrderCPU(Params *params); /* Destructor */ ~InOrderCPU(); - - /** Return a reference to the data port. */ - virtual CpuPort &getDataPort() { return dataPort; } - - /** Return a reference to the instruction port. */ - virtual CpuPort &getInstPort() { return instPort; } /** CPU ID */ int cpu_id; @@ -153,10 +147,10 @@ private: /** - * CachePort class for the in-order CPU, interacting with a + * CacheHandler class for the in-order CPU, interacting with a * specific CacheUnit in the pipeline. */ - class CachePort : public CpuPort + class CacheHandler : public CpuHandler { private: @@ -165,7 +159,7 @@ public: /** Default constructor. */ - CachePort(CacheUnit *_cacheUnit, const std::string& name); + CacheHandler(CacheUnit *_cacheUnit); protected: @@ -437,10 +431,10 @@ private: /** Data port. Note that it has to appear after the resPool. */ - CachePort dataPort; + CacheHandler dataHandler; /** Instruction port. Note that it has to appear after the resPool. */ - CachePort instPort; + CacheHandler instHandler; public: diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/inorder/cpu.cc --- a/src/cpu/inorder/cpu.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/inorder/cpu.cc Tue Jul 17 19:06:02 2012 +0100 @@ -82,14 +82,12 @@ using namespace TheISA; using namespace ThePipeline; -InOrderCPU::CachePort::CachePort(CacheUnit *_cacheUnit, - const std::string& name) : - CpuPort(_cacheUnit->name() + name, _cacheUnit->cpu), +InOrderCPU::CacheHandler::CacheHandler(CacheUnit *_cacheUnit) : cacheUnit(_cacheUnit) { } bool -InOrderCPU::CachePort::recvTimingResp(Packet *pkt) +InOrderCPU::CacheHandler::recvTimingResp(Packet *pkt) { if (pkt->isError()) DPRINTF(InOrderCachePort, "Got error packet back for address: %x\n", @@ -101,7 +99,7 @@ } void -InOrderCPU::CachePort::recvRetry() +InOrderCPU::CacheHandler::recvRetry() { cacheUnit->recvRetry(); } @@ -223,7 +221,7 @@ } InOrderCPU::InOrderCPU(Params *params) - : BaseCPU(params), + : BaseCPU(params, instHandler, dataHandler), cpu_id(params->cpu_id), coreType("default"), _status(Idle), @@ -231,8 +229,8 @@ stageWidth(params->stageWidth), resPool(new ResourcePool(this, params)), timeBuffer(2 , 2), - dataPort(resPool->getDataUnit(), ".dcache_port"), - instPort(resPool->getInstUnit(), ".icache_port"), + dataHandler(resPool->getDataUnit()), + instHandler(resPool->getInstUnit()), removeInstsThisCycle(false), activityRec(params->name, NumStages, 10, params->activity), system(params->system), diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/inorder/resources/cache_unit.cc --- a/src/cpu/inorder/resources/cache_unit.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/inorder/resources/cache_unit.cc Tue Jul 17 19:06:02 2012 +0100 @@ -111,7 +111,7 @@ reqs[i] = new CacheRequest(this); } - cacheBlkSize = cachePort->peerBlockSize(); + cacheBlkSize = (*cachePort)->peerBlockSize(); cacheBlkMask = cacheBlkSize - 1; initSlots(); @@ -872,7 +872,7 @@ tid, inst->seqNum, cache_req->dataPkt->getAddr()); if (do_access) { - if (!cachePort->sendTimingReq(cache_req->dataPkt)) { + if (!(*cachePort)->sendTimingReq(cache_req->dataPkt)) { DPRINTF(InOrderCachePort, "[tid:%i] [sn:%i] cannot access cache, because port " "is blocked. now waiting to retry request\n", tid, diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/o3/cpu.hh --- a/src/cpu/o3/cpu.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/o3/cpu.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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 @@ -83,7 +83,8 @@ { //Stuff that's pretty ISA independent will go here. public: - BaseO3CPU(BaseCPUParams *params); + BaseO3CPU(BaseCPUParams *params, CpuHandler &instHandler, + CpuHandler &dataHandler); void regStats(); }; @@ -130,9 +131,9 @@ private: /** - * IcachePort class for instruction fetch. + * IcacheHandler class for instruction fetch. */ - class IcachePort : public CpuPort + class IcacheHandler : public CpuHandler { protected: /** Pointer to fetch. */ @@ -140,9 +141,7 @@ public: /** Default constructor. */ - IcachePort(DefaultFetch *_fetch, FullO3CPU* _cpu) - : CpuPort(_cpu->name() + ".icache_port", _cpu), fetch(_fetch) - { } + IcacheHandler(DefaultFetch* _fetch) : fetch(_fetch) { } protected: @@ -156,9 +155,9 @@ }; /** - * DcachePort class for the load/store queue. + * DcacheHandler class for the load/store queue. */ - class DcachePort : public CpuPort + class DcacheHandler : public CpuHandler { protected: @@ -167,9 +166,7 @@ public: /** Default constructor. */ - DcachePort(LSQ *_lsq, FullO3CPU* _cpu) - : CpuPort(_cpu->name() + ".dcache_port", _cpu), lsq(_lsq) - { } + DcacheHandler(LSQ *_lsq) : lsq(_lsq) { } protected: @@ -635,11 +632,13 @@ TheISA::ISA isa[Impl::MaxThreads]; - /** Instruction port. Note that it has to appear after the fetch stage. */ - IcachePort icachePort; + /** Instruction port handler. Note that it has to appear after the + * fetch stage. */ + IcacheHandler icacheHandler; - /** Data port. Note that it has to appear after the iew stages */ - DcachePort dcachePort; + /** Data port handler. Note that it has to appear after the iew + * stages */ + DcacheHandler dcacheHandler; public: /** Enum to give each stage a specific index, so when calling @@ -775,12 +774,6 @@ data, store_idx); } - /** Used by the fetch unit to get a hold of the instruction port. */ - virtual CpuPort &getInstPort() { return icachePort; } - - /** Get the dcache port (used to find block size for translations). */ - virtual CpuPort &getDataPort() { return dcachePort; } - Addr lockAddr; /** Temporary fix for the lock flag, works in the UP case. */ diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/o3/cpu.cc --- a/src/cpu/o3/cpu.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/o3/cpu.cc Tue Jul 17 19:06:02 2012 +0100 @@ -74,8 +74,9 @@ using namespace TheISA; using namespace std; -BaseO3CPU::BaseO3CPU(BaseCPUParams *params) - : BaseCPU(params) +BaseO3CPU::BaseO3CPU(BaseCPUParams *params, CpuHandler &instHandler, + CpuHandler &dataHandler) + : BaseCPU(params, instHandler, dataHandler) { } @@ -87,7 +88,7 @@ template bool -FullO3CPU::IcachePort::recvTimingResp(PacketPtr pkt) +FullO3CPU::IcacheHandler::recvTimingResp(PacketPtr pkt) { DPRINTF(O3CPU, "Fetch unit received timing\n"); // We shouldn't ever get a block in ownership state @@ -99,28 +100,28 @@ template void -FullO3CPU::IcachePort::recvRetry() +FullO3CPU::IcacheHandler::recvRetry() { fetch->recvRetry(); } template bool -FullO3CPU::DcachePort::recvTimingResp(PacketPtr pkt) +FullO3CPU::DcacheHandler::recvTimingResp(PacketPtr pkt) { return lsq->recvTimingResp(pkt); } template void -FullO3CPU::DcachePort::recvTimingSnoopReq(PacketPtr pkt) +FullO3CPU::DcacheHandler::recvTimingSnoopReq(PacketPtr pkt) { lsq->recvTimingSnoopReq(pkt); } template void -FullO3CPU::DcachePort::recvRetry() +FullO3CPU::DcacheHandler::recvRetry() { lsq->recvRetry(); } @@ -208,7 +209,7 @@ template FullO3CPU::FullO3CPU(DerivO3CPUParams *params) - : BaseO3CPU(params), + : BaseO3CPU(params, icacheHandler, dcacheHandler), itb(params->itb), dtb(params->dtb), tickEvent(this), @@ -240,8 +241,8 @@ TheISA::NumMiscRegs * numThreads, TheISA::ZeroReg), - icachePort(&fetch, this), - dcachePort(&iew.ldstQueue, this), + icacheHandler(&fetch), + dcacheHandler(&iew.ldstQueue), timeBuffer(params->backComSize, params->forwardComSize), fetchQueue(params->backComSize, params->forwardComSize), diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/o3/fetch_impl.hh --- a/src/cpu/o3/fetch_impl.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/o3/fetch_impl.hh Tue Jul 17 19:06:02 2012 +0100 @@ -339,7 +339,7 @@ assert(cpu->getInstPort().isConnected()); // Size of cache block. - cacheBlkSize = cpu->getInstPort().peerBlockSize(); + cacheBlkSize = cpu->getInstPort()->peerBlockSize(); // Create mask to get rid of offset bits. cacheBlkMask = (cacheBlkSize - 1); @@ -623,7 +623,7 @@ fetchedCacheLines++; // Access the cache. - if (!cpu->getInstPort().sendTimingReq(data_pkt)) { + if (!cpu->getInstPort()->sendTimingReq(data_pkt)) { assert(retryPkt == NULL); assert(retryTid == InvalidThreadID); DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); @@ -1356,7 +1356,7 @@ assert(retryTid != InvalidThreadID); assert(fetchStatus[retryTid] == IcacheWaitRetry); - if (cpu->getInstPort().sendTimingReq(retryPkt)) { + if (cpu->getInstPort()->sendTimingReq(retryPkt)) { fetchStatus[retryTid] = IcacheWaitResponse; retryPkt = NULL; retryTid = InvalidThreadID; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/o3/lsq_impl.hh --- a/src/cpu/o3/lsq_impl.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/o3/lsq_impl.hh Tue Jul 17 19:06:02 2012 +0100 @@ -111,7 +111,6 @@ for (ThreadID tid = 0; tid < numThreads; tid++) { thread[tid].init(cpu, iew_ptr, params, this, maxLQEntries, maxSQEntries, tid); - thread[tid].setDcachePort(&cpu_ptr->getDataPort()); } } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/o3/lsq_unit.hh --- a/src/cpu/o3/lsq_unit.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/o3/lsq_unit.hh Tue Jul 17 19:06:02 2012 +0100 @@ -88,9 +88,6 @@ /** Registers statistics. */ void regStats(); - /** Sets the pointer to the dcache port. */ - void setDcachePort(MasterPort *dcache_port); - /** Switches out LSQ unit. */ void switchOut(); @@ -799,7 +796,7 @@ state->mainPkt = data_pkt; } - if (!dcachePort->sendTimingReq(fst_data_pkt)) { + if (!(*dcachePort)->sendTimingReq(fst_data_pkt)) { // Delete state and data packet because a load retry // initiates a pipeline restart; it does not retry. delete state; @@ -828,7 +825,7 @@ // The first packet will return in completeDataAccess and be // handled there. ++usedPorts; - if (!dcachePort->sendTimingReq(snd_data_pkt)) { + if (!(*dcachePort)->sendTimingReq(snd_data_pkt)) { // The main packet will be deleted in completeDataAccess. delete snd_data_pkt->req; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/o3/lsq_unit_impl.hh --- a/src/cpu/o3/lsq_unit_impl.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/o3/lsq_unit_impl.hh Tue Jul 17 19:06:02 2012 +0100 @@ -174,6 +174,8 @@ usedPorts = 0; cachePorts = params->cachePorts; + dcachePort = &cpu->getDataPort(); + retryPkt = NULL; memDepViolator = NULL; @@ -239,13 +241,6 @@ template void -LSQUnit::setDcachePort(MasterPort *dcache_port) -{ - dcachePort = dcache_port; -} - -template -void LSQUnit::clearLQ() { loadQueue.clear(); @@ -447,7 +442,7 @@ if (!cacheBlockMask) { assert(dcachePort); - Addr bs = dcachePort->peerBlockSize(); + Addr bs = (*dcachePort)->peerBlockSize(); // Make sure we actually got a size assert(bs != 0); @@ -1180,7 +1175,7 @@ bool LSQUnit::sendStore(PacketPtr data_pkt) { - if (!dcachePort->sendTimingReq(data_pkt)) { + if (!(*dcachePort)->sendTimingReq(data_pkt)) { // Need to handle becoming blocked on a store. isStoreBlocked = true; ++lsqCacheBlocked; @@ -1203,7 +1198,7 @@ LSQSenderState *state = dynamic_cast(retryPkt->senderState); - if (dcachePort->sendTimingReq(retryPkt)) { + if ((*dcachePort)->sendTimingReq(retryPkt)) { // Don't finish the store unless this is the last packet. if (!TheISA::HasUnalignedMemAcc || !state->pktToSend || state->pendingPacket == retryPkt) { diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/simple/atomic.hh --- a/src/cpu/simple/atomic.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/simple/atomic.hh Tue Jul 17 19:06:02 2012 +0100 @@ -80,15 +80,9 @@ * An AtomicCPUPort overrides the default behaviour of the * recvAtomic and ignores the packet instead of panicking. */ - class AtomicCPUPort : public CpuPort + class AtomicCPUHandler : public CpuHandler { - public: - - AtomicCPUPort(const std::string &_name, BaseCPU* _cpu) - : CpuPort(_name, _cpu) - { } - protected: virtual Tick recvAtomicSnoop(PacketPtr pkt) @@ -99,8 +93,8 @@ }; - AtomicCPUPort icachePort; - AtomicCPUPort dcachePort; + AtomicCPUHandler icacheHandler; + AtomicCPUHandler dcacheHandler; bool fastmem; Request ifetch_req; @@ -110,14 +104,6 @@ bool dcache_access; Tick dcache_latency; - protected: - - /** Return a reference to the data port. */ - virtual CpuPort &getDataPort() { return dcachePort; } - - /** Return a reference to the instruction port. */ - virtual CpuPort &getInstPort() { return icachePort; } - public: virtual void serialize(std::ostream &os); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/simple/atomic.cc --- a/src/cpu/simple/atomic.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/simple/atomic.cc Tue Jul 17 19:06:02 2012 +0100 @@ -102,11 +102,10 @@ } AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) - : BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false), + : BaseSimpleCPU(p, icacheHandler, dcacheHandler), tickEvent(this), + width(p->width), locked(false), simulate_data_stalls(p->simulate_data_stalls), simulate_inst_stalls(p->simulate_inst_stalls), - icachePort(name() + ".icache_port", this), - dcachePort(name() + ".dcache_port", this), fastmem(p->fastmem) { _status = Idle; @@ -251,7 +250,7 @@ } //The block size of our peer. - unsigned blockSize = dcachePort.peerBlockSize(); + unsigned blockSize = dcachePort->peerBlockSize(); //The size of the data we're trying to read. int fullSize = size; @@ -283,7 +282,7 @@ if (fastmem && system->isMemAddr(pkt.getAddr())) system->getPhysMem().access(&pkt); else - dcache_latency += dcachePort.sendAtomic(&pkt); + dcache_latency += dcachePort->sendAtomic(&pkt); } dcache_access = true; @@ -339,7 +338,7 @@ } //The block size of our peer. - unsigned blockSize = dcachePort.peerBlockSize(); + unsigned blockSize = dcachePort->peerBlockSize(); //The size of the data we're trying to read. int fullSize = size; @@ -385,7 +384,7 @@ if (fastmem && system->isMemAddr(pkt.getAddr())) system->getPhysMem().access(&pkt); else - dcache_latency += dcachePort.sendAtomic(&pkt); + dcache_latency += dcachePort->sendAtomic(&pkt); } dcache_access = true; assert(!pkt.isError()); @@ -480,7 +479,7 @@ if (fastmem && system->isMemAddr(ifetch_pkt.getAddr())) system->getPhysMem().access(&ifetch_pkt); else - icache_latency = icachePort.sendAtomic(&ifetch_pkt); + icache_latency = icachePort->sendAtomic(&ifetch_pkt); assert(!ifetch_pkt.isError()); @@ -544,7 +543,7 @@ void AtomicSimpleCPU::printAddr(Addr a) { - dcachePort.printAddr(a); + dcachePort->printAddr(a); } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/simple/base.hh --- a/src/cpu/simple/base.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/simple/base.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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 @@ -109,7 +109,8 @@ }; public: - BaseSimpleCPU(BaseSimpleCPUParams *params); + BaseSimpleCPU(BaseSimpleCPUParams *params, CpuHandler &instHandler, + CpuHandler &dataHandler); virtual ~BaseSimpleCPU(); public: diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/simple/base.cc --- a/src/cpu/simple/base.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/simple/base.cc Tue Jul 17 19:06:02 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011 ARM Limited + * Copyright (c) 2010-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -84,8 +84,12 @@ using namespace std; using namespace TheISA; -BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p) - : BaseCPU(p), traceData(NULL), thread(NULL) + +BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p, + CpuHandler &instHandler, + CpuHandler &dataHandler) + : BaseCPU(p, instHandler, dataHandler), traceData(NULL), + thread(NULL) { if (FullSystem) thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/simple/timing.hh --- a/src/cpu/simple/timing.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/simple/timing.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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. * @@ -138,17 +150,17 @@ bool handleWritePacket(); /** - * A TimingCPUPort overrides the default behaviour of the - * recvTiming and recvRetry and implements events for the + * A TimingCPUHandler overrides the default handler behaviour of + * the recvTiming and recvRetry and implements events for the * scheduling of handling of incoming packets in the following * cycle. */ - class TimingCPUPort : public CpuPort + class TimingCPUHandler : public CpuHandler { public: - TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu) - : CpuPort(_name, _cpu), cpu(_cpu), retryEvent(this) + TimingCPUHandler(TimingSimpleCPU* _cpu) : + cpu(_cpu), retryEvent(this) { } protected: @@ -170,16 +182,15 @@ void schedule(PacketPtr _pkt, Tick t); }; - EventWrapper retryEvent; + EventWrapper retryEvent; }; - class IcachePort : public TimingCPUPort + class IcacheHandler : public TimingCPUHandler { public: - IcachePort(TimingSimpleCPU *_cpu) - : TimingCPUPort(_cpu->name() + ".icache_port", _cpu), - tickEvent(_cpu) + IcacheHandler(TimingSimpleCPU *_cpu) + : TimingCPUHandler(_cpu), tickEvent(_cpu) { } protected: @@ -201,13 +212,12 @@ }; - class DcachePort : public TimingCPUPort + class DcacheHandler : public TimingCPUHandler { public: - DcachePort(TimingSimpleCPU *_cpu) - : TimingCPUPort(_cpu->name() + ".dcache_port", _cpu), - tickEvent(_cpu) + DcacheHandler(TimingSimpleCPU *_cpu) + : TimingCPUHandler(_cpu), tickEvent(_cpu) { } protected: @@ -228,22 +238,14 @@ }; - IcachePort icachePort; - DcachePort dcachePort; + IcacheHandler icacheHandler; + DcacheHandler dcacheHandler; PacketPtr ifetch_pkt; PacketPtr dcache_pkt; Tick previousTick; - protected: - - /** Return a reference to the data port. */ - virtual CpuPort &getDataPort() { return dcachePort; } - - /** Return a reference to the instruction port. */ - virtual CpuPort &getInstPort() { return icachePort; } - public: virtual void serialize(std::ostream &os); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/simple/timing.cc --- a/src/cpu/simple/timing.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/simple/timing.cc Tue Jul 17 19:06:02 2012 +0100 @@ -78,15 +78,16 @@ } void -TimingSimpleCPU::TimingCPUPort::TickEvent::schedule(PacketPtr _pkt, Tick t) +TimingSimpleCPU::TimingCPUHandler::TickEvent::schedule(PacketPtr _pkt, Tick t) { pkt = _pkt; cpu->schedule(this, t); } TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) - : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this), - dcachePort(this), fetchEvent(this) + : BaseSimpleCPU(p, icacheHandler, dcacheHandler), + fetchTranslation(this), icacheHandler(this), dcacheHandler(this), + fetchEvent(this) { _status = Idle; @@ -234,7 +235,7 @@ new IprEvent(pkt, this, nextCycle(curTick() + delay)); _status = DcacheWaitResponse; dcache_pkt = NULL; - } else if (!dcachePort.sendTimingReq(pkt)) { + } else if (!dcachePort->sendTimingReq(pkt)) { _status = DcacheRetry; dcache_pkt = pkt; } else { @@ -399,7 +400,7 @@ const int asid = 0; const ThreadID tid = 0; const Addr pc = thread->instAddr(); - unsigned block_size = dcachePort.peerBlockSize(); + unsigned block_size = dcachePort->peerBlockSize(); BaseTLB::Mode mode = BaseTLB::Read; if (traceData) { @@ -449,7 +450,7 @@ new IprEvent(dcache_pkt, this, nextCycle(curTick() + delay)); _status = DcacheWaitResponse; dcache_pkt = NULL; - } else if (!dcachePort.sendTimingReq(dcache_pkt)) { + } else if (!dcachePort->sendTimingReq(dcache_pkt)) { _status = DcacheRetry; } else { _status = DcacheWaitResponse; @@ -469,7 +470,7 @@ const int asid = 0; const ThreadID tid = 0; const Addr pc = thread->instAddr(); - unsigned block_size = dcachePort.peerBlockSize(); + unsigned block_size = dcachePort->peerBlockSize(); BaseTLB::Mode mode = BaseTLB::Write; if (traceData) { @@ -581,7 +582,7 @@ ifetch_pkt->dataStatic(&inst); DPRINTF(SimpleCPU, " -- pkt addr: %#x\n", ifetch_pkt->getAddr()); - if (!icachePort.sendTimingReq(ifetch_pkt)) { + if (!icachePort->sendTimingReq(ifetch_pkt)) { // Need to wait for retry _status = IcacheRetry; } else { @@ -709,13 +710,13 @@ } void -TimingSimpleCPU::IcachePort::ITickEvent::process() +TimingSimpleCPU::IcacheHandler::ITickEvent::process() { cpu->completeIfetch(pkt); } bool -TimingSimpleCPU::IcachePort::recvTimingResp(PacketPtr pkt) +TimingSimpleCPU::IcacheHandler::recvTimingResp(PacketPtr pkt) { if (!pkt->wasNacked()) { DPRINTF(SimpleCPU, "Received timing response %#x\n", pkt->getAddr()); @@ -741,7 +742,7 @@ } void -TimingSimpleCPU::IcachePort::recvRetry() +TimingSimpleCPU::IcacheHandler::recvRetry() { // we shouldn't get a retry unless we have a packet that we're // waiting to transmit @@ -835,7 +836,7 @@ } bool -TimingSimpleCPU::DcachePort::recvTimingResp(PacketPtr pkt) +TimingSimpleCPU::DcacheHandler::recvTimingResp(PacketPtr pkt) { if (!pkt->wasNacked()) { // delay processing of returned data until next CPU clock edge @@ -870,13 +871,13 @@ } void -TimingSimpleCPU::DcachePort::DTickEvent::process() +TimingSimpleCPU::DcacheHandler::DTickEvent::process() { cpu->completeDataAccess(pkt); } void -TimingSimpleCPU::DcachePort::recvRetry() +TimingSimpleCPU::DcacheHandler::recvRetry() { // we shouldn't get a retry unless we have a packet that we're // waiting to transmit @@ -942,7 +943,7 @@ void TimingSimpleCPU::printAddr(Addr a) { - dcachePort.printAddr(a); + dcachePort->printAddr(a); } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/directedtest/InvalidateGenerator.cc --- a/src/cpu/testers/directedtest/InvalidateGenerator.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/directedtest/InvalidateGenerator.cc Tue Jul 17 19:06:02 2012 +0100 @@ -80,7 +80,7 @@ *dummyData = 0; pkt->dataDynamic(dummyData); - if (port->sendTimingReq(pkt)) { + if ((*port)->sendTimingReq(pkt)) { DPRINTF(DirectedTest, "initiating request - successful\n"); if (m_status == InvalidateGeneratorStatus_Load_Waiting) { m_status = InvalidateGeneratorStatus_Load_Pending; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/directedtest/RubyDirectedTester.hh --- a/src/cpu/testers/directedtest/RubyDirectedTester.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/directedtest/RubyDirectedTester.hh Tue Jul 17 19:06:02 2012 +0100 @@ -47,15 +47,14 @@ class RubyDirectedTester : public MemObject { public: - class CpuPort : public MasterPort + class CpuHandler : public MasterInterface { private: RubyDirectedTester *tester; public: - CpuPort(const std::string &_name, RubyDirectedTester *_tester, - PortID _id) - : MasterPort(_name, _tester, _id), tester(_tester) + CpuHandler(RubyDirectedTester *_tester) + : tester(_tester) {} protected: diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/directedtest/RubyDirectedTester.cc --- a/src/cpu/testers/directedtest/RubyDirectedTester.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/directedtest/RubyDirectedTester.cc Tue Jul 17 19:06:02 2012 +0100 @@ -54,8 +54,9 @@ // create the ports for (int i = 0; i < p->port_cpuPort_connection_count; ++i) { - ports.push_back(new CpuPort(csprintf("%s-port%d", name(), i), - this, i)); + CpuHandler* ph = new CpuHandler(this); + ports.push_back(new MasterPort(csprintf("%s-port%d", name(), i), + this, *ph, i)); } // add the check start event to the event queue @@ -91,9 +92,9 @@ } bool -RubyDirectedTester::CpuPort::recvTimingResp(PacketPtr pkt) +RubyDirectedTester::CpuHandler::recvTimingResp(PacketPtr pkt) { - tester->hitCallback(id, pkt->getAddr()); + tester->hitCallback(port->getId(), pkt->getAddr()); // // Now that the tester has completed, delete the packet, then return diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/directedtest/SeriesRequestGenerator.cc --- a/src/cpu/testers/directedtest/SeriesRequestGenerator.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/directedtest/SeriesRequestGenerator.cc Tue Jul 17 19:06:02 2012 +0100 @@ -70,7 +70,7 @@ *dummyData = 0; pkt->dataDynamic(dummyData); - if (port->sendTimingReq(pkt)) { + if ((*port)->sendTimingReq(pkt)) { DPRINTF(DirectedTest, "initiating request - successful\n"); m_status = SeriesRequestGeneratorStatus_Request_Pending; return true; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/memtest/memtest.hh --- a/src/cpu/testers/memtest/memtest.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/memtest/memtest.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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. * @@ -84,14 +96,14 @@ TickEvent tickEvent; - class CpuPort : public MasterPort + class CpuHandler : public MasterInterface { MemTest *memtest; public: - CpuPort(const std::string &_name, MemTest *_memtest) - : MasterPort(_name, _memtest), memtest(_memtest) + CpuHandler(const std::string& _name, MemTest* _obj) : + memtest(_obj) { } protected: @@ -107,8 +119,10 @@ virtual void recvRetry(); }; - CpuPort cachePort; - CpuPort funcPort; + CpuHandler cacheHandler; + CpuHandler funcHandler; + MasterPort cachePort; + MasterPort funcPort; PortProxy funcProxy; class MemTestSenderState : public Packet::SenderState diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/memtest/memtest.cc --- a/src/cpu/testers/memtest/memtest.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/memtest/memtest.cc Tue Jul 17 19:06:02 2012 +0100 @@ -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. * @@ -53,14 +65,14 @@ int TESTER_ALLOCATOR=0; bool -MemTest::CpuPort::recvTimingResp(PacketPtr pkt) +MemTest::CpuHandler::recvTimingResp(PacketPtr pkt) { memtest->completeRequest(pkt); return true; } void -MemTest::CpuPort::recvRetry() +MemTest::CpuHandler::recvRetry() { memtest->doRetry(); } @@ -68,10 +80,10 @@ void MemTest::sendPkt(PacketPtr pkt) { if (atomic) { - cachePort.sendAtomic(pkt); + cachePort->sendAtomic(pkt); completeRequest(pkt); } - else if (!cachePort.sendTimingReq(pkt)) { + else if (!cachePort->sendTimingReq(pkt)) { DPRINTF(MemTest, "accessRetry setting to true\n"); // @@ -93,8 +105,10 @@ MemTest::MemTest(const Params *p) : MemObject(p), tickEvent(this), - cachePort("test", this), - funcPort("functional", this), + cacheHandler("test-handler", this), + funcHandler("functional-handler", this), + cachePort("test", this, cacheHandler), + funcPort("functional", this, funcHandler), funcProxy(funcPort), retryPkt(NULL), // mainMem(main_mem), @@ -146,7 +160,7 @@ MemTest::init() { // By the time init() is called, the ports should be hooked up. - blockSize = cachePort.peerBlockSize(); + blockSize = cachePort->peerBlockSize(); blockAddrMask = blockSize - 1; traceBlockAddr = blockAddr(traceBlockAddr); @@ -335,7 +349,7 @@ if (do_functional) { assert(pkt->needsResponse()); pkt->setSuppressFuncError(); - cachePort.sendFunctional(pkt); + cachePort->sendFunctional(pkt); completeRequest(pkt); } else { sendPkt(pkt); @@ -367,7 +381,7 @@ if (do_functional) { pkt->setSuppressFuncError(); - cachePort.sendFunctional(pkt); + cachePort->sendFunctional(pkt); completeRequest(pkt); } else { sendPkt(pkt); @@ -378,7 +392,7 @@ void MemTest::doRetry() { - if (cachePort.sendTimingReq(retryPkt)) { + if (cachePort->sendTimingReq(retryPkt)) { DPRINTF(MemTest, "accessRetry setting to false\n"); accessRetry = false; retryPkt = NULL; @@ -389,7 +403,7 @@ void MemTest::printAddr(Addr a) { - cachePort.printAddr(a); + cachePort->printAddr(a); } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/networktest/networktest.hh --- a/src/cpu/testers/networktest/networktest.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/networktest/networktest.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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. * All rights reserved. * @@ -79,14 +91,14 @@ TickEvent tickEvent; - class CpuPort : public MasterPort + class CpuHandler : public MasterInterface { NetworkTest *networktest; public: - CpuPort(const std::string &_name, NetworkTest *_networktest) - : MasterPort(_name, _networktest), networktest(_networktest) + CpuHandler(NetworkTest *_networktest) + : networktest(_networktest) { } protected: @@ -96,7 +108,8 @@ virtual void recvRetry(); }; - CpuPort cachePort; + CpuHandler cacheHandler; + MasterPort cachePort; class NetworkTestSenderState : public Packet::SenderState { diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/networktest/networktest.cc --- a/src/cpu/testers/networktest/networktest.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/networktest/networktest.cc Tue Jul 17 19:06:02 2012 +0100 @@ -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. * All rights reserved. * @@ -51,14 +63,14 @@ int TESTER_NETWORK=0; bool -NetworkTest::CpuPort::recvTimingResp(PacketPtr pkt) +NetworkTest::CpuHandler::recvTimingResp(PacketPtr pkt) { networktest->completeRequest(pkt); return true; } void -NetworkTest::CpuPort::recvRetry() +NetworkTest::CpuHandler::recvRetry() { networktest->doRetry(); } @@ -66,7 +78,7 @@ void NetworkTest::sendPkt(PacketPtr pkt) { - if (!cachePort.sendTimingReq(pkt)) { + if (!cachePort->sendTimingReq(pkt)) { retryPkt = pkt; // RubyPort will retry sending } numPacketsSent++; @@ -75,7 +87,8 @@ NetworkTest::NetworkTest(const Params *p) : MemObject(p), tickEvent(this), - cachePort("network-test", this), + cacheHandler(this), + cachePort("test", this, cacheHandler), retryPkt(NULL), size(p->memory_size), blockSizeBits(p->block_offset), @@ -268,7 +281,7 @@ void NetworkTest::doRetry() { - if (cachePort.sendTimingReq(retryPkt)) { + if (cachePort->sendTimingReq(retryPkt)) { retryPkt = NULL; } } @@ -276,7 +289,7 @@ void NetworkTest::printAddr(Addr a) { - cachePort.printAddr(a); + cachePort->printAddr(a); } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/rubytest/Check.cc --- a/src/cpu/testers/rubytest/Check.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/rubytest/Check.cc Tue Jul 17 19:06:02 2012 +0100 @@ -114,7 +114,7 @@ pkt->senderState = new SenderState(m_address, req->getSize(), pkt->senderState); - if (port->sendTimingReq(pkt)) { + if ((*port)->sendTimingReq(pkt)) { DPRINTF(RubyTest, "successfully initiated prefetch.\n"); } else { // If the packet did not issue, must delete @@ -154,7 +154,7 @@ pkt->senderState = new SenderState(m_address, req->getSize(), pkt->senderState); - if (port->sendTimingReq(pkt)) { + if ((*port)->sendTimingReq(pkt)) { DPRINTF(RubyTest, "initiating Flush - successful\n"); } } @@ -201,7 +201,7 @@ pkt->senderState = new SenderState(writeAddr, req->getSize(), pkt->senderState); - if (port->sendTimingReq(pkt)) { + if ((*port)->sendTimingReq(pkt)) { DPRINTF(RubyTest, "initiating action - successful\n"); DPRINTF(RubyTest, "status before action update: %s\n", (TesterStatus_to_string(m_status)).c_str()); @@ -253,7 +253,7 @@ pkt->senderState = new SenderState(m_address, req->getSize(), pkt->senderState); - if (port->sendTimingReq(pkt)) { + if ((*port)->sendTimingReq(pkt)) { DPRINTF(RubyTest, "initiating check - successful\n"); DPRINTF(RubyTest, "status before check update: %s\n", TesterStatus_to_string(m_status).c_str()); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/rubytest/RubyTester.hh --- a/src/cpu/testers/rubytest/RubyTester.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/rubytest/RubyTester.hh Tue Jul 17 19:06:02 2012 +0100 @@ -45,7 +45,7 @@ class RubyTester : public MemObject { public: - class CpuPort : public MasterPort + class CpuHandler : public MasterInterface { private: RubyTester *tester; @@ -57,8 +57,8 @@ // RubyPorts that support both types of requests, separate InstOnly // and DataOnly CpuPorts will map to that RubyPort - CpuPort(const std::string &_name, RubyTester *_tester, PortID _id) - : MasterPort(_name, _tester, _id), tester(_tester) + CpuHandler(RubyTester *_tester) + : tester(_tester) {} protected: diff -r b8abb27c5a88 -r 11e228ae7ed4 src/cpu/testers/rubytest/RubyTester.cc --- a/src/cpu/testers/rubytest/RubyTester.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/cpu/testers/rubytest/RubyTester.cc Tue Jul 17 19:06:02 2012 +0100 @@ -74,12 +74,14 @@ // then the data ports are added to the readPort vector // for (int i = 0; i < p->port_cpuInstPort_connection_count; ++i) { - readPorts.push_back(new CpuPort(csprintf("%s-instPort%d", name(), i), - this, i)); + CpuHandler* ph = new CpuHandler(this); + readPorts.push_back(new MasterPort(csprintf("%s-instPort%d", name(), i), + this, *ph, i)); } for (int i = 0; i < p->port_cpuDataPort_connection_count; ++i) { - CpuPort *port = new CpuPort(csprintf("%s-dataPort%d", name(), i), - this, i); + CpuHandler* ph = new CpuHandler(this); + MasterPort *port = new MasterPort(csprintf("%s-dataPort%d", name(), i), + this, *ph, i); readPorts.push_back(port); writePorts.push_back(port); } @@ -145,7 +147,7 @@ } bool -RubyTester::CpuPort::recvTimingResp(PacketPtr pkt) +RubyTester::CpuHandler::recvTimingResp(PacketPtr pkt) { // retrieve the subblock and call hitCallback RubyTester::SenderState* senderState = @@ -156,7 +158,7 @@ // pop the sender state from the packet pkt->senderState = senderState->saved; - tester->hitCallback(id, subblock); + tester->hitCallback(port->getId(), subblock); // Now that the tester has completed, delete the senderState // (includes sublock) and the packet, then return diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/arm/pl111.cc --- a/src/dev/arm/pl111.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/arm/pl111.cc Tue Jul 17 19:06:02 2012 +0100 @@ -465,9 +465,9 @@ // will be uncacheable as well. If we have uncacheable and cacheable // requests in the memory system for the same address it won't be // pleased - dmaPort.dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize, - &dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer, - 0, Request::UNCACHEABLE); + dmaPort->dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize, + &dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer, + 0, Request::UNCACHEABLE); curAddr += dmaSize; } } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/copy_engine.hh --- a/src/dev/copy_engine.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/copy_engine.hh Tue Jul 17 19:06:02 2012 +0100 @@ -61,6 +61,7 @@ class CopyEngineChannel { private: + DmaHandler ceHandler; DmaPort cePort; CopyEngine *ce; CopyEngineReg::ChanRegs cr; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/copy_engine.cc --- a/src/dev/copy_engine.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/copy_engine.cc Tue Jul 17 19:06:02 2012 +0100 @@ -77,8 +77,10 @@ CopyEngine::CopyEngineChannel::CopyEngineChannel(CopyEngine *_ce, int cid) - : cePort(_ce, _ce->sys, _ce->params()->min_backoff_delay, - _ce->params()->max_backoff_delay), + : ceHandler(_ce, _ce->sys, + _ce->params()->min_backoff_delay, + _ce->params()->max_backoff_delay), + cePort(_ce->name() + "-dma", _ce, ceHandler), ce(_ce), channelId(cid), busy(false), underReset(false), refreshNext(false), latBeforeBegin(ce->params()->latBeforeBegin), latAfterCompletion(ce->params()->latAfterCompletion), @@ -454,9 +456,9 @@ DPRINTF(DMACopyEngine, "dmaAction: %#x, %d bytes, to addr %#x\n", ce->platform->pciToDma(address), sizeof(DmaDesc), curDmaDesc); - cePort.dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address), - sizeof(DmaDesc), &fetchCompleteEvent, - (uint8_t*)curDmaDesc, latBeforeBegin); + cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(address), + sizeof(DmaDesc), &fetchCompleteEvent, + (uint8_t*)curDmaDesc, latBeforeBegin); lastDescriptorAddr = address; } @@ -498,8 +500,8 @@ DPRINTF(DMACopyEngine, "Reading %d bytes from buffer to memory location %#x(%#x)\n", curDmaDesc->len, curDmaDesc->dest, ce->platform->pciToDma(curDmaDesc->src)); - cePort.dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(curDmaDesc->src), - curDmaDesc->len, &readCompleteEvent, copyBuffer, 0); + cePort->dmaAction(MemCmd::ReadReq, ce->platform->pciToDma(curDmaDesc->src), + curDmaDesc->len, &readCompleteEvent, copyBuffer, 0); } void @@ -520,8 +522,9 @@ curDmaDesc->len, curDmaDesc->dest, ce->platform->pciToDma(curDmaDesc->dest)); - cePort.dmaAction(MemCmd::WriteReq, ce->platform->pciToDma(curDmaDesc->dest), - curDmaDesc->len, &writeCompleteEvent, copyBuffer, 0); + cePort->dmaAction(MemCmd::WriteReq, + ce->platform->pciToDma(curDmaDesc->dest), + curDmaDesc->len, &writeCompleteEvent, copyBuffer, 0); ce->bytesCopied[channelId] += curDmaDesc->len; ce->copiesProcessed[channelId]++; @@ -589,10 +592,10 @@ completionDataReg, cr.completionAddr, ce->platform->pciToDma(cr.completionAddr)); - cePort.dmaAction(MemCmd::WriteReq, - ce->platform->pciToDma(cr.completionAddr), - sizeof(completionDataReg), &statusCompleteEvent, - (uint8_t*)&completionDataReg, latAfterCompletion); + cePort->dmaAction(MemCmd::WriteReq, + ce->platform->pciToDma(cr.completionAddr), + sizeof(completionDataReg), &statusCompleteEvent, + (uint8_t*)&completionDataReg, latAfterCompletion); } void @@ -608,10 +611,10 @@ anBegin("FetchNextAddr"); DPRINTF(DMACopyEngine, "Fetching next address...\n"); busy = true; - cePort.dmaAction(MemCmd::ReadReq, - ce->platform->pciToDma(address + offsetof(DmaDesc, next)), - sizeof(Addr), &addrCompleteEvent, - (uint8_t*)curDmaDesc + offsetof(DmaDesc, next), 0); + cePort->dmaAction(MemCmd::ReadReq, + ce->platform->pciToDma(address + offsetof(DmaDesc, next)), + sizeof(Addr), &addrCompleteEvent, + (uint8_t*)curDmaDesc + offsetof(DmaDesc, next), 0); } void @@ -653,7 +656,7 @@ if (nextState == Idle || ce->getState() != SimObject::Running) return 0; unsigned int count = 1; - count += cePort.drain(de); + count += cePort->drain(de); DPRINTF(DMACopyEngine, "unable to drain, returning %d\n", count); drainEvent = de; @@ -664,7 +667,7 @@ CopyEngine::drain(Event *de) { unsigned int count; - count = pioPort.drain(de) + dmaPort.drain(de) + configPort.drain(de); + count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de); for (int x = 0;x < chan.size(); x++) count += chan[x]->drain(de); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/dma_device.hh --- a/src/dev/dma_device.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/dma_device.hh Tue Jul 17 19:06:02 2012 +0100 @@ -47,7 +47,7 @@ #include "dev/io_device.hh" #include "params/DmaDevice.hh" -class DmaPort : public MasterPort +class DmaHandler : public MasterInterface { protected: struct DmaReqState : public Packet::SenderState @@ -112,23 +112,31 @@ void sendDma(); /** event to give us a kick every time we backoff time is reached. */ - EventWrapper backoffEvent; + EventWrapper backoffEvent; public: - DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff); + DmaHandler(MemObject *dev, System *s, Tick min_backoff, + Tick max_backoff); void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, uint8_t *data, Tick delay, Request::Flags flag = 0); bool dmaPending() { return pendingCount > 0; } - unsigned cacheBlockSize() const { return peerBlockSize(); } unsigned int drain(Event *de); }; +/** + * Type definition for a DmaPort which is a master port exposing the + * DmaHandler interface. This is used in numerous places and this + * declared in the global namespace. + */ +typedef IfaceMasterPort DmaPort; + class DmaDevice : public PioDevice { protected: + DmaHandler dmaHandler; DmaPort dmaPort; public: @@ -145,27 +153,27 @@ void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0) { - dmaPort.dmaAction(MemCmd::WriteReq, addr, size, event, data, delay); + dmaPort->dmaAction(MemCmd::WriteReq, addr, size, event, data, + delay); } void dmaRead(Addr addr, int size, Event *event, uint8_t *data, Tick delay = 0) { - dmaPort.dmaAction(MemCmd::ReadReq, addr, size, event, data, delay); + dmaPort->dmaAction(MemCmd::ReadReq, addr, size, event, data, + delay); } - bool dmaPending() { return dmaPort.dmaPending(); } + bool dmaPending() { return dmaPort->dmaPending(); } virtual void init(); virtual unsigned int drain(Event *de); - unsigned cacheBlockSize() const { return dmaPort.cacheBlockSize(); } + unsigned cacheBlockSize() const { return dmaPort->peerBlockSize(); } virtual BaseMasterPort &getMasterPort(const std::string &if_name, PortID idx = InvalidPortID); - - friend class DmaPort; }; #endif // __DEV_DMA_DEVICE_HH__ diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/dma_device.cc --- a/src/dev/dma_device.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/dma_device.cc Tue Jul 17 19:06:02 2012 +0100 @@ -46,8 +46,9 @@ #include "dev/dma_device.hh" #include "sim/system.hh" -DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff) - : MasterPort(dev->name() + ".dma", dev), device(dev), sys(s), +DmaHandler::DmaHandler(MemObject *dev, System *s, Tick min_backoff, + Tick max_backoff) + : device(dev), sys(s), masterId(s->getMasterId(dev->name())), pendingCount(0), actionInProgress(0), drainEvent(NULL), backoffTime(0), minBackoffDelay(min_backoff), @@ -56,7 +57,7 @@ { } bool -DmaPort::recvTimingResp(PacketPtr pkt) +DmaHandler::recvTimingResp(PacketPtr pkt) { if (pkt->wasNacked()) { DPRINTF(DMA, "Received nacked %s addr %#x\n", @@ -115,8 +116,9 @@ } DmaDevice::DmaDevice(const Params *p) - : PioDevice(p), dmaPort(this, sys, params()->min_backoff_delay, - params()->max_backoff_delay) + : PioDevice(p), dmaHandler(this, sys, params()->min_backoff_delay, + params()->max_backoff_delay), + dmaPort(this->name() + ".dma", this, dmaHandler) { } void @@ -131,7 +133,7 @@ DmaDevice::drain(Event *de) { unsigned int count; - count = pioPort.drain(de) + dmaPort.drain(de); + count = pioPort->drain(de) + dmaPort->drain(de); if (count) changeState(Draining); else @@ -140,7 +142,7 @@ } unsigned int -DmaPort::drain(Event *de) +DmaHandler::drain(Event *de) { if (pendingCount == 0) return 0; @@ -149,7 +151,7 @@ } void -DmaPort::recvRetry() +DmaHandler::recvRetry() { assert(transmitList.size()); bool result = true; @@ -179,8 +181,9 @@ } void -DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event, - uint8_t *data, Tick delay, Request::Flags flag) +DmaHandler::dmaAction(Packet::Command cmd, Addr addr, int size, + Event *event, uint8_t *data, Tick delay, + Request::Flags flag) { assert(device->getState() == SimObject::Running); @@ -210,7 +213,7 @@ } void -DmaPort::queueDma(PacketPtr pkt, bool front) +DmaHandler::queueDma(PacketPtr pkt, bool front) { if (front) @@ -221,7 +224,7 @@ } void -DmaPort::sendDma() +DmaHandler::sendDma() { // some kind of selction between access methods // more work is going to have to be done to make diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/i8254xGBe.cc --- a/src/dev/i8254xGBe.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/i8254xGBe.cc Tue Jul 17 19:06:02 2012 +0100 @@ -2058,7 +2058,7 @@ IGbE::drain(Event *de) { unsigned int count; - count = pioPort.drain(de) + dmaPort.drain(de); + count = pioPort->drain(de) + dmaPort->drain(de); if (rxDescCache.hasOutstandingEvents() || txDescCache.hasOutstandingEvents()) { count++; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/io_device.hh --- a/src/dev/io_device.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/io_device.hh Tue Jul 17 19:06:02 2012 +0100 @@ -59,7 +59,7 @@ * must respond to. The device must also provide getAddrRanges() function * with which it returns the address ranges it is interested in. */ -class PioPort : public SimpleTimingPort +class PioHandler : public SimpleTimingHandler { protected: /** The device that this port serves. */ @@ -71,7 +71,7 @@ public: - PioPort(PioDevice *dev); + PioHandler(PioDevice *dev); }; /** @@ -88,7 +88,8 @@ /** The pioPort that handles the requests for us and provides us requests * that it sees. */ - PioPort pioPort; + PioHandler pioHandler; + QueuedSlavePort pioPort; /** * Every PIO device is obliged to provide an implementation that @@ -130,7 +131,7 @@ virtual BaseSlavePort &getSlavePort(const std::string &if_name, PortID idx = InvalidPortID); - friend class PioPort; + friend class PioHandler; }; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/io_device.cc --- a/src/dev/io_device.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/io_device.cc Tue Jul 17 19:06:02 2012 +0100 @@ -46,25 +46,26 @@ #include "dev/io_device.hh" #include "sim/system.hh" -PioPort::PioPort(PioDevice *dev) - : SimpleTimingPort(dev->name() + ".pio", dev), device(dev) +PioHandler::PioHandler(PioDevice *dev) + : SimpleTimingHandler(dev), device(dev) { } Tick -PioPort::recvAtomic(PacketPtr pkt) +PioHandler::recvAtomic(PacketPtr pkt) { return pkt->isRead() ? device->read(pkt) : device->write(pkt); } AddrRangeList -PioPort::getAddrRanges() const +PioHandler::getAddrRanges() const { return device->getAddrRanges(); } PioDevice::PioDevice(const Params *p) - : MemObject(p), sys(p->system), pioPort(this) + : MemObject(p), sys(p->system), pioHandler(this), + pioPort(this->name() + ".pio", this, pioHandler) {} PioDevice::~PioDevice() @@ -76,7 +77,7 @@ { if (!pioPort.isConnected()) panic("Pio port of %s not connected to anything!", name()); - pioPort.sendRangeChange(); + pioPort->sendRangeChange(); } BaseSlavePort & @@ -92,14 +93,13 @@ PioDevice::drain(Event *de) { unsigned int count; - count = pioPort.drain(de); + count = pioPort->drain(de); if (count) changeState(Draining); else changeState(Drained); return count; } - BasicPioDevice::BasicPioDevice(const Params *p) : PioDevice(p), pioAddr(p->pio_addr), pioSize(0), pioDelay(p->pio_latency) diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/pcidev.hh --- a/src/dev/pcidev.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/pcidev.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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) 2004-2005 The Regents of The University of Michigan * All rights reserved. * @@ -58,7 +70,7 @@ */ class PciDev : public DmaDevice { - class PciConfigPort : public SimpleTimingPort + class PciConfigHandler : public SimpleTimingHandler { protected: PciDev *device; @@ -76,8 +88,8 @@ Addr configAddr; public: - PciConfigPort(PciDev *dev, int busid, int devid, int funcid, - Platform *p); + PciConfigHandler(PciDev *dev, int busid, int devid, int funcid, + Platform *p); }; public: @@ -151,7 +163,8 @@ Platform *platform; Tick pioDelay; Tick configDelay; - PciConfigPort configPort; + PciConfigHandler configHandler; + QueuedSlavePort configPort; /** * Write to the PCI config space data that is stored locally. This may be diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/pcidev.cc --- a/src/dev/pcidev.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/pcidev.cc Tue Jul 17 19:06:02 2012 +0100 @@ -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) 2004-2005 The Regents of The University of Michigan * All rights reserved. * @@ -52,18 +64,16 @@ #include "sim/byteswap.hh" #include "sim/core.hh" - -PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid, - int funcid, Platform *p) - : SimpleTimingPort(dev->name() + "-pciconf", dev), device(dev), +PciDev::PciConfigHandler::PciConfigHandler(PciDev *dev, int busid, int devid, + int funcid, Platform *p) + : SimpleTimingHandler(dev), device(dev), platform(p), busId(busid), deviceId(devid), functionId(funcid) { configAddr = platform->calcPciConfigAddr(busId, deviceId, functionId); } - Tick -PciDev::PciConfigPort::recvAtomic(PacketPtr pkt) +PciDev::PciConfigHandler::recvAtomic(PacketPtr pkt) { assert(pkt->getAddr() >= configAddr && pkt->getAddr() < configAddr + PCI_CONFIG_SIZE); @@ -71,7 +81,7 @@ } AddrRangeList -PciDev::PciConfigPort::getAddrRanges() const +PciDev::PciConfigHandler::getAddrRanges() const { AddrRangeList ranges; if (configAddr != ULL(-1)) @@ -83,8 +93,9 @@ PciDev::PciDev(const Params *p) : DmaDevice(p), platform(p->platform), pioDelay(p->pio_latency), configDelay(p->config_latency), - configPort(this, params()->pci_bus, params()->pci_dev, - params()->pci_func, params()->platform) + configHandler(this, params()->pci_bus, params()->pci_dev, + params()->pci_func, params()->platform), + configPort(this->name() + "-config", this, configHandler) { config.vendor = htole(p->VendorID); config.device = htole(p->DeviceID); @@ -152,7 +163,7 @@ { if (!configPort.isConnected()) panic("PCI config port on %s not connected to anything!\n", name()); - configPort.sendRangeChange(); + configPort->sendRangeChange(); DmaDevice::init(); } @@ -160,7 +171,7 @@ PciDev::drain(Event *de) { unsigned int count; - count = pioPort.drain(de) + dmaPort.drain(de) + configPort.drain(de); + count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de); if (count) changeState(Draining); else @@ -302,7 +313,7 @@ BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ? platform->calcPciIOAddr(he_new_bar) : platform->calcPciMemAddr(he_new_bar); - pioPort.sendRangeChange(); + pioPort->sendRangeChange(); } } config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) | @@ -355,7 +366,6 @@ UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); UNSERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0])); - pioPort.sendRangeChange(); + pioPort->sendRangeChange(); } - diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/sinic.cc --- a/src/dev/sinic.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/sinic.cc Tue Jul 17 19:06:02 2012 +0100 @@ -1714,7 +1714,7 @@ if (transmitTick) schedule(txEvent, curTick() + transmitTick); - pioPort.sendRangeChange(); + pioPort->sendRangeChange(); } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/x86/i82094aa.cc --- a/src/dev/x86/i82094aa.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/x86/i82094aa.cc Tue Jul 17 19:06:02 2012 +0100 @@ -222,8 +222,8 @@ apics.push_back(selected); } } - intMasterPort.sendMessage(apics, message, - sys->getMemoryMode() == Enums::timing); + intMasterPort->sendMessage(apics, message, + sys->getMemoryMode() == Enums::timing); } } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/x86/intdev.hh --- a/src/dev/x86/intdev.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/x86/intdev.hh Tue Jul 17 19:06:02 2012 +0100 @@ -63,14 +63,13 @@ class IntDev { protected: - class IntSlavePort : public MessageSlavePort + class IntSlaveHandler : public MessageSlaveHandler { IntDev * device; Tick latency; public: - IntSlavePort(const std::string& _name, MemObject* _parent, - IntDev* dev, Tick _latency) : - MessageSlavePort(_name, _parent), device(dev), latency(_latency) + IntSlaveHandler(MemObject* _parent, IntDev* dev, Tick _latency) : + MessageSlaveHandler(_parent), device(dev), latency(_latency) { } @@ -85,14 +84,13 @@ } }; - class IntMasterPort : public MessageMasterPort + class IntMasterHandler : public MessageMasterHandler { IntDev* device; Tick latency; public: - IntMasterPort(const std::string& _name, MemObject* _parent, - IntDev* dev, Tick _latency) : - MessageMasterPort(_name, _parent), device(dev), latency(_latency) + IntMasterHandler(MemObject* _parent, IntDev* dev, Tick _latency) : + MessageMasterHandler(_parent), device(dev), latency(_latency) { } @@ -107,11 +105,13 @@ TriggerIntMessage message, bool timing); }; - IntMasterPort intMasterPort; + IntMasterHandler intMasterHandler; + IfaceMasterPort intMasterPort; public: IntDev(MemObject * parent, Tick latency = 0) : - intMasterPort(parent->name() + ".int_master", parent, this, latency) + intMasterHandler(parent, this, latency), + intMasterPort(parent->name() + ".int_master", parent, intMasterHandler) { } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/dev/x86/intdev.cc --- a/src/dev/x86/intdev.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/dev/x86/intdev.cc Tue Jul 17 19:06:02 2012 +0100 @@ -43,9 +43,9 @@ #include "dev/x86/intdev.hh" void -X86ISA::IntDev::IntMasterPort::sendMessage(ApicList apics, - TriggerIntMessage message, - bool timing) +X86ISA::IntDev::IntMasterHandler::sendMessage(ApicList apics, + TriggerIntMessage message, + bool timing) { ApicList::iterator apicIt; for (apicIt = apics.begin(); apicIt != apics.end(); apicIt++) { diff -r b8abb27c5a88 -r 11e228ae7ed4 src/kern/tru64/tru64_events.cc --- a/src/kern/tru64/tru64_events.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/kern/tru64/tru64_events.cc Tue Jul 17 19:06:02 2012 +0100 @@ -63,7 +63,7 @@ MasterPort &dataPort = tc->getCpuPtr()->getDataPort(); // get the address ranges of the connected slave port - AddrRangeList resp = dataPort.getAddrRanges(); + AddrRangeList resp = dataPort->getAddrRanges(); for (iter = resp.begin(); iter != resp.end(); iter++) { if (*iter == (K0Seg2Phys(a0) & PAddrImplMask)) found = true; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/SConscript --- a/src/mem/SConscript Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/SConscript Tue Jul 17 19:06:02 2012 +0100 @@ -44,6 +44,7 @@ Source('noncoherent_bus.cc') Source('packet.cc') Source('port.cc') +Source('port_interface.cc') Source('packet_queue.cc') Source('tport.cc') Source('port_proxy.cc') diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/bridge.hh --- a/src/mem/bridge.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/bridge.hh Tue Jul 17 19:06:02 2012 +0100 @@ -143,8 +143,14 @@ { } }; - // Forward declaration to allow the slave port to have a pointer - class BridgeMasterPort; + // Forward declaration to allow the slave handler to have a pointer + class BridgeMasterHandler; + + /** + * Convenience type definition of a master port with a bridge + * master handler interface. + */ + typedef IfaceMasterPort BridgeMasterPort; /** * The port on the side that receives requests and sends @@ -152,7 +158,8 @@ * is responsible for. The slave port also has a buffer for the * responses not yet sent. */ - class BridgeSlavePort : public SlavePort + + class BridgeSlaveHandler : public SlaveInterface { private: @@ -214,14 +221,14 @@ void trySend(); /** Send event for the response queue. */ - EventWrapper sendEvent; + EventWrapper sendEvent; public: /** - * Constructor for the BridgeSlavePort. + * Constructor for the BridgeSlaveHandler. * - * @param _name the port name including the owner * @param _bridge the structural owner * @param _masterPort the master port on the other side of the bridge * @param _delay the delay from seeing a response to sending it @@ -229,10 +236,10 @@ * @param _resp_limit the size of the response queue * @param _ranges a number of address ranges to forward */ - BridgeSlavePort(const std::string &_name, Bridge *_bridge, - BridgeMasterPort& _masterPort, int _delay, - int _nack_delay, int _resp_limit, - std::vector > _ranges); + BridgeSlaveHandler(Bridge *_bridge, + BridgeMasterPort& _masterPort, + int _delay, int _nack_delay, int _resp_limit, + std::vector > _ranges); /** * Queue a response packet to be sent out later and also schedule @@ -265,13 +272,18 @@ virtual AddrRangeList getAddrRanges() const; }; + /** + * Convenience type definition of a slave port with a bridge + * slave handler interface. + */ + typedef IfaceSlavePort BridgeSlavePort; /** * Port on the side that forwards requests and receives * responses. The master port has a buffer for the requests not * yet sent. */ - class BridgeMasterPort : public MasterPort + class BridgeMasterHandler : public MasterInterface { private: @@ -309,22 +321,22 @@ void trySend(); /** Send event for the request queue. */ - EventWrapper sendEvent; + EventWrapper sendEvent; public: /** - * Constructor for the BridgeMasterPort. + * Constructor for the BridgeMasterHandler. * - * @param _name the port name including the owner * @param _bridge the structural owner * @param _slavePort the slave port on the other side of the bridge * @param _delay the delay from seeing a request to sending it * @param _req_limit the size of the request queue */ - BridgeMasterPort(const std::string &_name, Bridge *_bridge, - BridgeSlavePort& _slavePort, int _delay, - int _req_limit); + BridgeMasterHandler(Bridge* _bridge, + BridgeSlavePort& _slavePort, + int _delay, int _req_limit); /** * Is this side blocked from accepting new request packets. @@ -362,10 +374,11 @@ virtual void recvRetry(); }; - /** Slave port of the bridge. */ + /** Slave/master port and handler of the bridge. */ + BridgeSlaveHandler slaveHandler; + BridgeMasterHandler masterHandler; + BridgeSlavePort slavePort; - - /** Master port of the bridge. */ BridgeMasterPort masterPort; /** If this bridge should acknowledge writes. */ diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/bridge.cc --- a/src/mem/bridge.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/bridge.cc Tue Jul 17 19:06:02 2012 +0100 @@ -53,13 +53,13 @@ #include "mem/bridge.hh" #include "params/Bridge.hh" -Bridge::BridgeSlavePort::BridgeSlavePort(const std::string &_name, - Bridge* _bridge, - BridgeMasterPort& _masterPort, - int _delay, int _nack_delay, - int _resp_limit, - std::vector > _ranges) - : SlavePort(_name, _bridge), bridge(_bridge), masterPort(_masterPort), +Bridge::BridgeSlaveHandler::BridgeSlaveHandler( + Bridge* _bridge, + BridgeMasterPort& _masterPort, + int _delay, int _nack_delay, int _resp_limit, + std::vector > _ranges) + : bridge(_bridge), + masterPort(_masterPort), delay(_delay), nackDelay(_nack_delay), ranges(_ranges.begin(), _ranges.end()), outstandingResponses(0), inRetry(false), @@ -67,11 +67,12 @@ { } -Bridge::BridgeMasterPort::BridgeMasterPort(const std::string &_name, - Bridge* _bridge, - BridgeSlavePort& _slavePort, - int _delay, int _req_limit) - : MasterPort(_name, _bridge), bridge(_bridge), slavePort(_slavePort), +Bridge::BridgeMasterHandler::BridgeMasterHandler( + Bridge* _bridge, + BridgeSlavePort& _slavePort, + int _delay, int _req_limit) + : bridge(_bridge), + slavePort(_slavePort), delay(_delay), inRetry(false), reqQueueLimit(_req_limit), sendEvent(*this) { @@ -79,9 +80,11 @@ Bridge::Bridge(Params *p) : MemObject(p), - slavePort(p->name + ".slave", this, masterPort, p->delay, - p->nack_delay, p->resp_size, p->ranges), - masterPort(p->name + ".master", this, slavePort, p->delay, p->req_size), + slaveHandler(this, masterPort, p->delay, + p->nack_delay, p->resp_size, p->ranges), + masterHandler(this, slavePort, p->delay, p->req_size), + slavePort(p->name + ".slave", this, slaveHandler), + masterPort(p->name + ".master", this, masterHandler), ackWrites(p->write_ack), _params(p) { if (ackWrites) @@ -115,29 +118,29 @@ if (!slavePort.isConnected() || !masterPort.isConnected()) fatal("Both ports of bus bridge are not connected to a bus.\n"); - if (slavePort.peerBlockSize() != masterPort.peerBlockSize()) + if (slavePort->peerBlockSize() != masterPort->peerBlockSize()) fatal("Slave port size %d, master port size %d \n " \ "Busses don't have the same block size... Not supported.\n", - slavePort.peerBlockSize(), masterPort.peerBlockSize()); + slavePort->peerBlockSize(), masterPort->peerBlockSize()); // notify the master side of our address ranges - slavePort.sendRangeChange(); + slavePort->sendRangeChange(); } bool -Bridge::BridgeSlavePort::respQueueFull() +Bridge::BridgeSlaveHandler::respQueueFull() { return outstandingResponses == respQueueLimit; } bool -Bridge::BridgeMasterPort::reqQueueFull() +Bridge::BridgeMasterHandler::reqQueueFull() { return requestQueue.size() == reqQueueLimit; } bool -Bridge::BridgeMasterPort::recvTimingResp(PacketPtr pkt) +Bridge::BridgeMasterHandler::recvTimingResp(PacketPtr pkt) { // all checks are done when the request is accepted on the slave // side, so we are guaranteed to have space for the response @@ -146,13 +149,13 @@ DPRINTF(BusBridge, "Request queue size: %d\n", requestQueue.size()); - slavePort.queueForSendTiming(pkt); + slavePort->queueForSendTiming(pkt); return true; } bool -Bridge::BridgeSlavePort::recvTimingReq(PacketPtr pkt) +Bridge::BridgeSlaveHandler::recvTimingReq(PacketPtr pkt) { DPRINTF(BusBridge, "recvTiming: request %s addr 0x%x\n", pkt->cmdString(), pkt->getAddr()); @@ -160,7 +163,7 @@ DPRINTF(BusBridge, "Response queue size: %d outresp: %d\n", responseQueue.size(), outstandingResponses); - if (masterPort.reqQueueFull()) { + if (masterPort->reqQueueFull()) { DPRINTF(BusBridge, "Request queue full, nacking\n"); nackRequest(pkt); return true; @@ -182,13 +185,13 @@ } } - masterPort.queueForSendTiming(pkt); + masterPort->queueForSendTiming(pkt); return true; } void -Bridge::BridgeSlavePort::nackRequest(PacketPtr pkt) +Bridge::BridgeSlaveHandler::nackRequest(PacketPtr pkt) { // Nack the packet pkt->makeTimingResponse(); @@ -239,7 +242,7 @@ } void -Bridge::BridgeMasterPort::queueForSendTiming(PacketPtr pkt) +Bridge::BridgeMasterHandler::queueForSendTiming(PacketPtr pkt) { Tick readyTime = curTick() + delay; @@ -268,7 +271,7 @@ void -Bridge::BridgeSlavePort::queueForSendTiming(PacketPtr pkt) +Bridge::BridgeSlaveHandler::queueForSendTiming(PacketPtr pkt) { // This is a response for a request we forwarded earlier. The // corresponding request state should be stored in the packet's @@ -298,7 +301,7 @@ } void -Bridge::BridgeMasterPort::trySend() +Bridge::BridgeMasterHandler::trySend() { assert(!requestQueue.empty()); @@ -330,7 +333,7 @@ } void -Bridge::BridgeSlavePort::trySend() +Bridge::BridgeSlaveHandler::trySend() { assert(!responseQueue.empty()); @@ -372,7 +375,7 @@ } void -Bridge::BridgeMasterPort::recvRetry() +Bridge::BridgeMasterHandler::recvRetry() { inRetry = false; Tick nextReady = requestQueue.front().ready; @@ -383,7 +386,7 @@ } void -Bridge::BridgeSlavePort::recvRetry() +Bridge::BridgeSlaveHandler::recvRetry() { inRetry = false; Tick nextReady = responseQueue.front().ready; @@ -394,13 +397,13 @@ } Tick -Bridge::BridgeSlavePort::recvAtomic(PacketPtr pkt) +Bridge::BridgeSlaveHandler::recvAtomic(PacketPtr pkt) { - return delay + masterPort.sendAtomic(pkt); + return delay + masterPort->sendAtomic(pkt); } void -Bridge::BridgeSlavePort::recvFunctional(PacketPtr pkt) +Bridge::BridgeSlaveHandler::recvFunctional(PacketPtr pkt) { std::list::iterator i; @@ -415,18 +418,18 @@ } // also check the master port's request queue - if (masterPort.checkFunctional(pkt)) { + if (masterPort->checkFunctional(pkt)) { return; } pkt->popLabel(); // fall through if pkt still not satisfied - masterPort.sendFunctional(pkt); + masterPort->sendFunctional(pkt); } bool -Bridge::BridgeMasterPort::checkFunctional(PacketPtr pkt) +Bridge::BridgeMasterHandler::checkFunctional(PacketPtr pkt) { bool found = false; std::list::iterator i = requestQueue.begin(); @@ -443,7 +446,7 @@ } AddrRangeList -Bridge::BridgeSlavePort::getAddrRanges() const +Bridge::BridgeSlaveHandler::getAddrRanges() const { return ranges; } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/bus.cc --- a/src/mem/bus.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/bus.cc Tue Jul 17 19:06:02 2012 +0100 @@ -270,7 +270,7 @@ // note that we might have blocked on the receiving port being // busy (rather than the bus itself) and now call retry before the // destination called retry on the bus - retryList.front()->sendRetry(); + (*retryList.front())->sendRetry(); // If the bus is still in the retry state, sendTiming wasn't // called in zero time (e.g. the cache does this) @@ -371,7 +371,7 @@ if (useDefaultRange) { // get the address ranges of the connected slave port AddrRangeList ranges = - masterPorts[master_port_id]->getAddrRanges(); + (*masterPorts[master_port_id])->getAddrRanges(); for(iter = ranges.begin(); iter != ranges.end(); iter++) { defaultRange.push_back(*iter); DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", @@ -393,7 +393,7 @@ } // get the address ranges of the connected slave port - ranges = port->getAddrRanges(); + ranges = (*port)->getAddrRanges(); for (iter = ranges.begin(); iter != ranges.end(); iter++) { DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", @@ -413,7 +413,7 @@ // has changed for (SlavePortConstIter p = slavePorts.begin(); p != slavePorts.end(); ++p) - (*p)->sendRangeChange(); + (**p)->sendRangeChange(); inRecvRangeChange.erase(master_port_id); } @@ -469,14 +469,14 @@ for (MasterPortConstIter m = masterPorts.begin(); m != masterPorts.end(); ++m) { - unsigned tmp_bs = (*m)->peerBlockSize(); + unsigned tmp_bs = (**m)->peerBlockSize(); if (tmp_bs > max_bs) max_bs = tmp_bs; } for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end(); ++s) { - unsigned tmp_bs = (*s)->peerBlockSize(); + unsigned tmp_bs = (**s)->peerBlockSize(); if (tmp_bs > max_bs) max_bs = tmp_bs; } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/cache/base.hh --- a/src/mem/cache/base.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/cache/base.hh Tue Jul 17 19:06:02 2012 +0100 @@ -118,7 +118,7 @@ * and the sendDeferredPacket of the timing port is modified to * consider both the transmit list and the requests from the MSHR. */ - class CacheMasterPort : public QueuedMasterPort + class CacheMasterHandler : public QueuedMasterHandler { public: @@ -147,9 +147,8 @@ protected: - CacheMasterPort(const std::string &_name, BaseCache *_cache, - MasterPacketQueue &_queue) : - QueuedMasterPort(_name, _cache, _queue) + CacheMasterHandler(MasterPacketQueue &_queue) : + QueuedMasterHandler(_queue) { } /** @@ -168,7 +167,7 @@ * incoming requests. If blocked, the port will issue a retry once * unblocked. */ - class CacheSlavePort : public QueuedSlavePort + class CacheSlaveHandler : public QueuedSlaveHandler { public: @@ -192,24 +191,28 @@ protected: - CacheSlavePort(const std::string &_name, BaseCache *_cache, - const std::string &_label); + CacheSlaveHandler(BaseCache *_cache, const std::string &_label); /** A normal packet queue used to store responses. */ SlavePacketQueue queue; + BaseCache* cache; + bool blocked; bool mustSendRetry; private: - EventWrapper sendRetryEvent; + EventWrapper sendRetryEvent; }; - CacheSlavePort *cpuSidePort; - CacheMasterPort *memSidePort; + CacheSlaveHandler &cpuSideHandler; + CacheMasterHandler &memSideHandler; + IfaceSlavePort cpuSidePort; + IfaceMasterPort memSidePort; protected: @@ -439,8 +442,9 @@ public: typedef BaseCacheParams Params; - BaseCache(const Params *p); - ~BaseCache() {} + BaseCache(const Params *p, CacheSlaveHandler &_cpuSideHandler, + CacheMasterHandler &_memSideHandler); + virtual ~BaseCache(); virtual void init(); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/cache/base.cc --- a/src/mem/cache/base.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/cache/base.cc Tue Jul 17 19:06:02 2012 +0100 @@ -54,16 +54,21 @@ using namespace std; -BaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name, - BaseCache *_cache, - const std::string &_label) - : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label), - blocked(false), mustSendRetry(false), sendRetryEvent(this) +BaseCache::CacheSlaveHandler::CacheSlaveHandler( + BaseCache *_cache, const std::string &_label) + : QueuedSlaveHandler(queue), + queue(*_cache, *this, _label), + cache(_cache), blocked(false), mustSendRetry(false), sendRetryEvent(this) { } -BaseCache::BaseCache(const Params *p) +BaseCache::BaseCache(const Params *p, CacheSlaveHandler &_cpuSideHandler, + CacheMasterHandler &_memSideHandler) : MemObject(p), + cpuSideHandler(_cpuSideHandler), + memSideHandler(_memSideHandler), + cpuSidePort(p->name + "-cpu_side", this, cpuSideHandler), + memSidePort(p->name + "-mem_side", this, memSideHandler), mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs), writeBuffer("write buffer", p->write_buffers, p->mshrs+1000, MSHRQueue_WriteBuffer), @@ -81,8 +86,12 @@ { } +BaseCache::~BaseCache() +{ +} + void -BaseCache::CacheSlavePort::setBlocked() +BaseCache::CacheSlaveHandler::setBlocked() { assert(!blocked); DPRINTF(CachePort, "Cache port %s blocking new requests\n", name()); @@ -90,7 +99,7 @@ } void -BaseCache::CacheSlavePort::clearBlocked() +BaseCache::CacheSlaveHandler::clearBlocked() { assert(blocked); DPRINTF(CachePort, "Cache port %s accepting new requests\n", name()); @@ -99,7 +108,7 @@ DPRINTF(CachePort, "Cache port %s sending retry\n", name()); mustSendRetry = false; // @TODO: need to find a better time (next bus cycle?) - owner.schedule(sendRetryEvent, curTick() + 1); + cache->schedule(sendRetryEvent, curTick() + 1); } } @@ -107,7 +116,7 @@ void BaseCache::init() { - if (!cpuSidePort->isConnected() || !memSidePort->isConnected()) + if (!cpuSidePort.isConnected() || !memSidePort.isConnected()) fatal("Cache ports on %s are not connected\n", name()); cpuSidePort->sendRangeChange(); } @@ -116,7 +125,7 @@ BaseCache::getMasterPort(const std::string &if_name, PortID idx) { if (if_name == "mem_side") { - return *memSidePort; + return memSidePort; } else { return MemObject::getMasterPort(if_name, idx); } @@ -126,7 +135,7 @@ BaseCache::getSlavePort(const std::string &if_name, PortID idx) { if (if_name == "cpu_side") { - return *cpuSidePort; + return cpuSidePort; } else { return MemObject::getSlavePort(if_name, idx); } @@ -709,7 +718,8 @@ .desc("average overall mshr uncacheable latency") .flags(total | nozero | nonan) ; - overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable; + overallAvgMshrUncacheableLatency = + overallMshrUncacheableLatency / overallMshrUncacheable; for (int i = 0; i < system->maxMasters(); i++) { overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i)); } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/cache/cache.hh --- a/src/mem/cache/cache.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/cache/cache.hh Tue Jul 17 19:06:02 2012 +0100 @@ -81,13 +81,8 @@ * The CPU-side port extends the base cache slave port with access * functions for functional, atomic and timing requests. */ - class CpuSidePort : public CacheSlavePort + class CpuSideHandler : public CacheSlaveHandler { - private: - - // a pointer to our specific cache implementation - Cache *cache; - protected: virtual bool recvTimingSnoopResp(PacketPtr pkt); @@ -105,8 +100,12 @@ public: - CpuSidePort(const std::string &_name, Cache *_cache, - const std::string &_label); + CpuSideHandler(Cache *_cache, const std::string &_label); + + private: + + // a pointer to our specific cache implementation + Cache *cache; }; @@ -125,9 +124,9 @@ public: - MemSidePacketQueue(Cache &cache, MasterPort &port, + MemSidePacketQueue(Cache &cache, MasterInterface &interface, const std::string &label) : - MasterPacketQueue(cache, port, label), cache(cache) { } + MasterPacketQueue(cache, interface, label), cache(cache) { } /** * Override the normal sendDeferredPacket and do not only @@ -142,16 +141,8 @@ * The memory-side port extends the base cache master port with * access functions for functional, atomic and timing snoops. */ - class MemSidePort : public CacheMasterPort + class MemSideHandler : public CacheMasterHandler { - private: - - /** The cache-specific queue. */ - MemSidePacketQueue _queue; - - // a pointer to our specific cache implementation - Cache *cache; - protected: virtual void recvTimingSnoopReq(PacketPtr pkt); @@ -167,10 +158,22 @@ public: - MemSidePort(const std::string &_name, Cache *_cache, - const std::string &_label); + MemSideHandler(Cache *_cache, const std::string &_label); + + private: + + /** The cache-specific queue. */ + MemSidePacketQueue _queue; + + // a pointer to our specific cache implementation + Cache *cache; + }; + /** Instances of our two port handler. */ + CpuSideHandler cpuSideHandler; + MemSideHandler memSideHandler; + /** Tag and data Storage */ TagStore *tags; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/cache/cache_impl.hh --- a/src/mem/cache/cache_impl.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/cache/cache_impl.hh Tue Jul 17 19:06:02 2012 +0100 @@ -63,7 +63,9 @@ template Cache::Cache(const Params *p, TagStore *tags) - : BaseCache(p), + : BaseCache(p, cpuSideHandler, memSideHandler), + cpuSideHandler(this, "CpuSidePort"), + memSideHandler(this, "MemSidePort"), tags(tags), prefetcher(p->prefetcher), doFastWrites(true), @@ -72,11 +74,6 @@ tempBlock = new BlkType(); tempBlock->data = new uint8_t[blkSize]; - cpuSidePort = new CpuSidePort(p->name + ".cpu_side", this, - "CpuSidePort"); - memSidePort = new MemSidePort(p->name + ".mem_side", this, - "MemSidePort"); - tags->setCache(this); if (prefetcher) prefetcher->setCache(this); @@ -1347,7 +1344,7 @@ template bool -Cache::CpuSidePort::recvTimingSnoopResp(PacketPtr pkt) +Cache::CpuSideHandler::recvTimingSnoopResp(PacketPtr pkt) { // Express snoop responses from master to slave, e.g., from L1 to L2 cache->timingAccess(pkt); @@ -1588,14 +1585,14 @@ template AddrRangeList -Cache::CpuSidePort::getAddrRanges() const +Cache::CpuSideHandler::getAddrRanges() const { return cache->getAddrRanges(); } template bool -Cache::CpuSidePort::recvTimingReq(PacketPtr pkt) +Cache::CpuSideHandler::recvTimingReq(PacketPtr pkt) { // always let inhibited requests through even if blocked if (!pkt->memInhibitAsserted() && blocked) { @@ -1610,7 +1607,7 @@ template Tick -Cache::CpuSidePort::recvAtomic(PacketPtr pkt) +Cache::CpuSideHandler::recvAtomic(PacketPtr pkt) { // atomic request return cache->atomicAccess(pkt); @@ -1618,7 +1615,7 @@ template void -Cache::CpuSidePort::recvFunctional(PacketPtr pkt) +Cache::CpuSideHandler::recvFunctional(PacketPtr pkt) { // functional request cache->functionalAccess(pkt, true); @@ -1626,9 +1623,10 @@ template Cache:: -CpuSidePort::CpuSidePort(const std::string &_name, Cache *_cache, - const std::string &_label) - : BaseCache::CacheSlavePort(_name, _cache, _label), cache(_cache) +CpuSideHandler::CpuSideHandler(Cache *_cache, + const std::string &_label) + : BaseCache::CacheSlaveHandler(_cache, _label), + cache(_cache) { } @@ -1640,7 +1638,7 @@ template bool -Cache::MemSidePort::recvTimingResp(PacketPtr pkt) +Cache::MemSideHandler::recvTimingResp(PacketPtr pkt) { // this needs to be fixed so that the cache updates the mshr and sends the // packet back out on the link, but it probably won't happen so until this @@ -1655,7 +1653,7 @@ // Express snooping requests to memside port template void -Cache::MemSidePort::recvTimingSnoopReq(PacketPtr pkt) +Cache::MemSideHandler::recvTimingSnoopReq(PacketPtr pkt) { // handle snooping requests cache->snoopTiming(pkt); @@ -1663,7 +1661,7 @@ template Tick -Cache::MemSidePort::recvAtomicSnoop(PacketPtr pkt) +Cache::MemSideHandler::recvAtomicSnoop(PacketPtr pkt) { // atomic snoop return cache->snoopAtomic(pkt); @@ -1671,7 +1669,7 @@ template void -Cache::MemSidePort::recvFunctionalSnoop(PacketPtr pkt) +Cache::MemSideHandler::recvFunctionalSnoop(PacketPtr pkt) { // functional snoop (note that in contrast to atomic we don't have // a specific functionalSnoop method, as they have the same @@ -1698,7 +1696,7 @@ } else { MSHR *mshr = dynamic_cast(pkt->senderState); - waitingOnRetry = !masterPort.sendTimingReq(pkt); + waitingOnRetry = !masterInterface.sendTimingReq(pkt); if (waitingOnRetry) { DPRINTF(CachePort, "now waiting on a retry\n"); @@ -1729,9 +1727,9 @@ template Cache:: -MemSidePort::MemSidePort(const std::string &_name, Cache *_cache, - const std::string &_label) - : BaseCache::CacheMasterPort(_name, _cache, _queue), +MemSideHandler::MemSideHandler(Cache *_cache, + const std::string &_label) + : BaseCache::CacheMasterHandler(_queue), _queue(*_cache, *this, _label), cache(_cache) { } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/coherent_bus.hh --- a/src/mem/coherent_bus.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/coherent_bus.hh Tue Jul 17 19:06:02 2012 +0100 @@ -82,7 +82,7 @@ * instantiated for each of the master ports connecting to the * bus. */ - class CoherentBusSlavePort : public SlavePort + class CoherentBusSlaveHandler : public SlaveInterface { private: @@ -92,9 +92,8 @@ public: - CoherentBusSlavePort(const std::string &_name, - CoherentBus &_bus, PortID _id) - : SlavePort(_name, &_bus, _id), bus(_bus) + CoherentBusSlaveHandler(CoherentBus &_bus) + : bus(_bus) { } protected: @@ -103,25 +102,25 @@ * When receiving a timing request, pass it to the bus. */ virtual bool recvTimingReq(PacketPtr pkt) - { return bus.recvTimingReq(pkt, id); } + { return bus.recvTimingReq(pkt, port->getId()); } /** * When receiving a timing snoop response, pass it to the bus. */ virtual bool recvTimingSnoopResp(PacketPtr pkt) - { return bus.recvTimingSnoopResp(pkt, id); } + { return bus.recvTimingSnoopResp(pkt, port->getId()); } /** * When receiving an atomic request, pass it to the bus. */ virtual Tick recvAtomic(PacketPtr pkt) - { return bus.recvAtomic(pkt, id); } + { return bus.recvAtomic(pkt, port->getId()); } /** * When receiving a functional request, pass it to the bus. */ virtual void recvFunctional(PacketPtr pkt) - { bus.recvFunctional(pkt, id); } + { bus.recvFunctional(pkt, port->getId()); } /** * When receiving a retry, pass it to the bus. @@ -148,7 +147,7 @@ * instantiated for each of the slave interfaces connecting to the * bus. */ - class CoherentBusMasterPort : public MasterPort + class CoherentBusMasterHandler : public MasterInterface { private: /** A reference to the bus to which this port belongs. */ @@ -156,9 +155,8 @@ public: - CoherentBusMasterPort(const std::string &_name, - CoherentBus &_bus, PortID _id) - : MasterPort(_name, &_bus, _id), bus(_bus) + CoherentBusMasterHandler(CoherentBus &_bus) + : bus(_bus) { } protected: @@ -176,30 +174,30 @@ * When receiving a timing response, pass it to the bus. */ virtual bool recvTimingResp(PacketPtr pkt) - { return bus.recvTimingResp(pkt, id); } + { return bus.recvTimingResp(pkt, port->getId()); } /** * When receiving a timing snoop request, pass it to the bus. */ virtual void recvTimingSnoopReq(PacketPtr pkt) - { return bus.recvTimingSnoopReq(pkt, id); } + { return bus.recvTimingSnoopReq(pkt, port->getId()); } /** * When receiving an atomic snoop request, pass it to the bus. */ virtual Tick recvAtomicSnoop(PacketPtr pkt) - { return bus.recvAtomicSnoop(pkt, id); } + { return bus.recvAtomicSnoop(pkt, port->getId()); } /** * When receiving a functional snoop request, pass it to the bus. */ virtual void recvFunctionalSnoop(PacketPtr pkt) - { bus.recvFunctionalSnoop(pkt, id); } + { bus.recvFunctionalSnoop(pkt, port->getId()); } /** When reciving a range change from the peer port (at id), pass it to the bus. */ virtual void recvRangeChange() - { bus.recvRangeChange(id); } + { bus.recvRangeChange(port->getId()); } /** When reciving a retry from the peer port (at id), pass it to the bus. */ diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/coherent_bus.cc --- a/src/mem/coherent_bus.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/coherent_bus.cc Tue Jul 17 19:06:02 2012 +0100 @@ -63,7 +63,9 @@ // are enumerated starting from zero for (int i = 0; i < p->port_master_connection_count; ++i) { std::string portName = csprintf("%s.master[%d]", name(), i); - MasterPort* bp = new CoherentBusMasterPort(portName, *this, i); + CoherentBusMasterHandler* bh = + new CoherentBusMasterHandler(*this); + MasterPort* bp = new MasterPort(portName, this, *bh, i); masterPorts.push_back(bp); } @@ -72,15 +74,18 @@ if (p->port_default_connection_count) { defaultPortID = masterPorts.size(); std::string portName = name() + ".default"; - MasterPort* bp = new CoherentBusMasterPort(portName, *this, - defaultPortID); + CoherentBusMasterHandler* bh = + new CoherentBusMasterHandler(*this); + MasterPort* bp = new MasterPort(portName, this, *bh, defaultPortID); masterPorts.push_back(bp); } // create the slave ports, once again starting at zero for (int i = 0; i < p->port_slave_connection_count; ++i) { std::string portName = csprintf("%s.slave[%d]", name(), i); - SlavePort* bp = new CoherentBusSlavePort(portName, *this, i); + CoherentBusSlaveHandler* bh = + new CoherentBusSlaveHandler(*this); + SlavePort* bp = new SlavePort(portName, this, *bh, i); slavePorts.push_back(bp); } @@ -95,7 +100,7 @@ for (SlavePortConstIter p = slavePorts.begin(); p != slavePorts.end(); ++p) { // check if the connected master port is snooping - if ((*p)->isSnooping()) { + if ((**p)->isSnooping()) { DPRINTF(BusAddrRanges, "Adding snooping master %s\n", (*p)->getMasterPort().name()); snoopPorts.push_back(*p); @@ -158,7 +163,7 @@ // since it is a normal request, determine the destination // based on the address and attempt to send the packet - bool success = masterPorts[findPort(pkt->getAddr())]->sendTimingReq(pkt); + bool success = (*masterPorts[findPort(pkt->getAddr())])->sendTimingReq(pkt); // if this is an express snoop, we are done at this point if (is_express_snoop) { @@ -217,7 +222,8 @@ // send the packet to the destination through one of our slave // ports, as determined by the destination field - bool success M5_VAR_USED = slavePorts[pkt->getDest()]->sendTimingResp(pkt); + bool success M5_VAR_USED = + (*slavePorts[pkt->getDest()])->sendTimingResp(pkt); // currently it is illegal to block responses... can lead to // deadlock @@ -286,7 +292,8 @@ // this is a snoop response to a snoop request we // forwarded, e.g. coming from the L1 and going to the L2 // this should be forwarded as a snoop response - bool success M5_VAR_USED = masterPorts[dest]->sendTimingSnoopResp(pkt); + bool success M5_VAR_USED = + (*masterPorts[dest])->sendTimingSnoopResp(pkt); assert(success); } else { // we got a snoop response on one of our slave ports, @@ -304,7 +311,7 @@ // as a normal response, it should go back to a master // through one of our slave ports - bool success M5_VAR_USED = slavePorts[dest]->sendTimingResp(pkt); + bool success M5_VAR_USED = (*slavePorts[dest])->sendTimingResp(pkt); // currently it is illegal to block responses... can lead // to deadlock @@ -329,7 +336,7 @@ if (exclude_slave_port_id == InvalidPortID || p->getId() != exclude_slave_port_id) { // cache is not allowed to refuse snoop - p->sendTimingSnoopReq(pkt); + (*p)->sendTimingSnoopReq(pkt); } } } @@ -367,7 +374,7 @@ PortID dest_id = findPort(pkt->getAddr()); // forward the request to the appropriate destination - Tick response_latency = masterPorts[dest_id]->sendAtomic(pkt); + Tick response_latency = (*masterPorts[dest_id])->sendAtomic(pkt); // if we got a response from a snooper, restore it here if (snoop_response_cmd != MemCmd::InvalidCmd) { @@ -419,7 +426,7 @@ // from if (exclude_slave_port_id == InvalidPortID || p->getId() != exclude_slave_port_id) { - Tick latency = p->sendAtomicSnoop(pkt); + Tick latency = (*p)->sendAtomicSnoop(pkt); // in contrast to a functional access, we have to keep on // going as all snoopers must be updated even if we get a // response @@ -465,7 +472,7 @@ if (!pkt->isResponse()) { PortID dest_id = findPort(pkt->getAddr()); - masterPorts[dest_id]->sendFunctional(pkt); + (*masterPorts[dest_id])->sendFunctional(pkt); } } @@ -495,7 +502,7 @@ // from if (exclude_slave_port_id == InvalidPortID || p->getId() != exclude_slave_port_id) - p->sendFunctionalSnoop(pkt); + (*p)->sendFunctionalSnoop(pkt); // if we get a response we are done if (pkt->isResponse()) { diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/comm_monitor.hh --- a/src/mem/comm_monitor.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/comm_monitor.hh Tue Jul 17 19:06:02 2012 +0100 @@ -128,13 +128,13 @@ * send function of the slave port is called. Besides this, these * functions can also perform actions for capturing statistics. */ - class MonitorMasterPort : public MasterPort + class MonitorMasterHandler : public MasterInterface { public: - MonitorMasterPort(const std::string& _name, CommMonitor& _mon) - : MasterPort(_name, &_mon), mon(_mon) + MonitorMasterHandler(CommMonitor& _mon) + : mon(_mon) { } protected: @@ -186,7 +186,8 @@ }; /** Instance of master port, facing the memory side */ - MonitorMasterPort masterPort; + MonitorMasterHandler masterHandler; + MasterPort masterPort; /** * This is the slave port of the communication monitor. All recv @@ -194,13 +195,13 @@ * send function of the master port is called. Besides this, these * functions can also perform actions for capturing statistics. */ - class MonitorSlavePort : public SlavePort + class MonitorSlaveHandler : public SlaveInterface { public: - MonitorSlavePort(const std::string& _name, CommMonitor& _mon) - : SlavePort(_name, &_mon), mon(_mon) + MonitorSlaveHandler(CommMonitor& _mon) + : mon(_mon) { } protected: @@ -247,7 +248,8 @@ }; /** Instance of slave port, i.e. on the CPU side */ - MonitorSlavePort slavePort; + MonitorSlaveHandler slaveHandler; + SlavePort slavePort; void recvFunctional(PacketPtr pkt); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/comm_monitor.cc --- a/src/mem/comm_monitor.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/comm_monitor.cc Tue Jul 17 19:06:02 2012 +0100 @@ -44,8 +44,10 @@ CommMonitor::CommMonitor(Params* params) : MemObject(params), - masterPort(name() + "-master", *this), - slavePort(name() + "-slave", *this), + masterHandler(*this), + masterPort(name() + "-master", this, masterHandler), + slaveHandler(*this), + slavePort(name() + "-slave", this, slaveHandler), samplePeriodicEvent(this), samplePeriodTicks(params->sample_period), readAddrMask(params->read_addr_mask), @@ -97,25 +99,25 @@ void CommMonitor::recvFunctional(PacketPtr pkt) { - masterPort.sendFunctional(pkt); + masterPort->sendFunctional(pkt); } void CommMonitor::recvFunctionalSnoop(PacketPtr pkt) { - slavePort.sendFunctionalSnoop(pkt); + slavePort->sendFunctionalSnoop(pkt); } Tick CommMonitor::recvAtomic(PacketPtr pkt) { - return masterPort.sendAtomic(pkt); + return masterPort->sendAtomic(pkt); } Tick CommMonitor::recvAtomicSnoop(PacketPtr pkt) { - return slavePort.sendAtomicSnoop(pkt); + return slavePort->sendAtomicSnoop(pkt); } bool @@ -145,7 +147,7 @@ // Attempt to send the packet (always succeeds for inhibited // packets) - bool successful = masterPort.sendTimingReq(pkt); + bool successful = masterPort->sendTimingReq(pkt); // If not successful, restore the sender state if (!successful && needsResponse && !stats.disableLatencyHists) { @@ -262,7 +264,7 @@ } // Attempt to send the packet - bool successful = slavePort.sendTimingResp(pkt); + bool successful = slavePort->sendTimingResp(pkt); if (!stats.disableLatencyHists) { // If packet successfully send, sample value of latency, @@ -316,57 +318,57 @@ void CommMonitor::recvTimingSnoopReq(PacketPtr pkt) { - slavePort.sendTimingSnoopReq(pkt); + slavePort->sendTimingSnoopReq(pkt); } bool CommMonitor::recvTimingSnoopResp(PacketPtr pkt) { - return masterPort.sendTimingSnoopResp(pkt); + return masterPort->sendTimingSnoopResp(pkt); } bool CommMonitor::isSnooping() const { // check if the connected master port is snooping - return slavePort.isSnooping(); + return slavePort->isSnooping(); } unsigned CommMonitor::deviceBlockSizeMaster() { - return slavePort.peerBlockSize(); + return slavePort->peerBlockSize(); } unsigned CommMonitor::deviceBlockSizeSlave() { - return masterPort.peerBlockSize(); + return masterPort->peerBlockSize(); } AddrRangeList CommMonitor::getAddrRanges() const { // get the address ranges of the connected slave port - return masterPort.getAddrRanges(); + return masterPort->getAddrRanges(); } void CommMonitor::recvRetryMaster() { - slavePort.sendRetry(); + slavePort->sendRetry(); } void CommMonitor::recvRetrySlave() { - masterPort.sendRetry(); + masterPort->sendRetry(); } void CommMonitor::recvRangeChange() { - slavePort.sendRangeChange(); + slavePort->sendRangeChange(); } void diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/fs_translating_port_proxy.hh --- a/src/mem/fs_translating_port_proxy.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/fs_translating_port_proxy.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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 @@ -78,7 +78,7 @@ FSTranslatingPortProxy(ThreadContext* tc); - FSTranslatingPortProxy(MasterPort &port); + FSTranslatingPortProxy(MasterInterface &_iface); virtual ~FSTranslatingPortProxy(); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/fs_translating_port_proxy.cc --- a/src/mem/fs_translating_port_proxy.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/fs_translating_port_proxy.cc Tue Jul 17 19:06:02 2012 +0100 @@ -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 @@ -58,8 +58,8 @@ { } -FSTranslatingPortProxy::FSTranslatingPortProxy(MasterPort &port) - : PortProxy(port), _tc(NULL) +FSTranslatingPortProxy::FSTranslatingPortProxy(MasterInterface &_iface) + : PortProxy(_iface), _tc(NULL) { } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/mport.hh --- a/src/mem/mport.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/mport.hh Tue Jul 17 19:06:02 2012 +0100 @@ -53,15 +53,12 @@ * the underpinnings of SimpleTimingPort, but it tweaks some of the external * functions. */ -class MessageSlavePort : public SimpleTimingPort +class MessageSlaveHandler : public SimpleTimingHandler { public: - MessageSlavePort(const std::string &name, MemObject *owner) : - SimpleTimingPort(name, owner) - {} - - virtual ~MessageSlavePort() + MessageSlaveHandler(MemObject *owner) : + SimpleTimingHandler(owner) {} protected: @@ -71,16 +68,13 @@ virtual Tick recvMessage(PacketPtr pkt) = 0; }; -class MessageMasterPort : public QueuedMasterPort +class MessageMasterHandler : public QueuedMasterHandler { public: - MessageMasterPort(const std::string &name, MemObject *owner) : - QueuedMasterPort(name, owner, queue), queue(*owner, *this) - {} - - virtual ~MessageMasterPort() - {} + MessageMasterHandler(MemObject *owner) : + QueuedMasterHandler(queue), queue(*owner, *this) + { } bool recvTimingResp(PacketPtr pkt) { recvResponse(pkt); return true; } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/mport.cc --- a/src/mem/mport.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/mport.cc Tue Jul 17 19:06:02 2012 +0100 @@ -43,12 +43,12 @@ #include "mem/mport.hh" Tick -MessageSlavePort::recvAtomic(PacketPtr pkt) +MessageSlaveHandler::recvAtomic(PacketPtr pkt) { if (pkt->cmd == MemCmd::MessageReq) { return recvMessage(pkt); } else { panic("%s received unexpected atomic command %s from %s.\n", - name(), pkt->cmd.toString(), getMasterPort().name()); + name(), pkt->cmd.toString(), port->name()); } } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/noncoherent_bus.hh --- a/src/mem/noncoherent_bus.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/noncoherent_bus.hh Tue Jul 17 19:06:02 2012 +0100 @@ -84,7 +84,7 @@ * be instantiated for each of the master ports connecting to the * bus. */ - class NoncoherentBusSlavePort : public SlavePort + class NoncoherentBusSlaveHandler : public SlaveInterface { private: @@ -93,9 +93,8 @@ public: - NoncoherentBusSlavePort(const std::string &_name, - NoncoherentBus &_bus, PortID _id) - : SlavePort(_name, &_bus, _id), bus(_bus) + NoncoherentBusSlaveHandler(NoncoherentBus &_bus) + : bus(_bus) { } protected: @@ -104,19 +103,19 @@ * When receiving a timing request, pass it to the bus. */ virtual bool recvTimingReq(PacketPtr pkt) - { return bus.recvTimingReq(pkt, id); } + { return bus.recvTimingReq(pkt, port->getId()); } /** * When receiving an atomic request, pass it to the bus. */ virtual Tick recvAtomic(PacketPtr pkt) - { return bus.recvAtomic(pkt, id); } + { return bus.recvAtomic(pkt, port->getId()); } /** * When receiving a functional request, pass it to the bus. */ virtual void recvFunctional(PacketPtr pkt) - { bus.recvFunctional(pkt, id); } + { bus.recvFunctional(pkt, port->getId()); } /** * When receiving a retry, pass it to the bus. @@ -143,7 +142,7 @@ * instantiated for each of the slave ports connecting to the * bus. */ - class NoncoherentBusMasterPort : public MasterPort + class NoncoherentBusMasterHandler : public MasterInterface { private: @@ -152,9 +151,8 @@ public: - NoncoherentBusMasterPort(const std::string &_name, - NoncoherentBus &_bus, PortID _id) - : MasterPort(_name, &_bus, _id), bus(_bus) + NoncoherentBusMasterHandler(NoncoherentBus &_bus) + : bus(_bus) { } protected: @@ -163,12 +161,12 @@ * When receiving a timing response, pass it to the bus. */ virtual bool recvTimingResp(PacketPtr pkt) - { return bus.recvTimingResp(pkt, id); } + { return bus.recvTimingResp(pkt, port->getId()); } /** When reciving a range change from the peer port (at id), pass it to the bus. */ virtual void recvRangeChange() - { bus.recvRangeChange(id); } + { bus.recvRangeChange(port->getId()); } /** When reciving a retry from the peer port (at id), pass it to the bus. */ diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/noncoherent_bus.cc --- a/src/mem/noncoherent_bus.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/noncoherent_bus.cc Tue Jul 17 19:06:02 2012 +0100 @@ -63,7 +63,9 @@ // are enumerated starting from zero for (int i = 0; i < p->port_master_connection_count; ++i) { std::string portName = csprintf("%s.master[%d]", name(), i); - MasterPort* bp = new NoncoherentBusMasterPort(portName, *this, i); + NoncoherentBusMasterHandler* bh = + new NoncoherentBusMasterHandler(*this); + MasterPort* bp = new MasterPort(portName, this, *bh, i); masterPorts.push_back(bp); } @@ -72,15 +74,18 @@ if (p->port_default_connection_count) { defaultPortID = masterPorts.size(); std::string portName = name() + ".default"; - MasterPort* bp = new NoncoherentBusMasterPort(portName, *this, - defaultPortID); + NoncoherentBusMasterHandler* bh = + new NoncoherentBusMasterHandler(*this); + MasterPort* bp = new MasterPort(portName, this, *bh, defaultPortID); masterPorts.push_back(bp); } // create the slave ports, once again starting at zero for (int i = 0; i < p->port_slave_connection_count; ++i) { std::string portName = csprintf("%s.slave[%d]", name(), i); - SlavePort* bp = new NoncoherentBusSlavePort(portName, *this, i); + NoncoherentBusSlaveHandler* bh = + new NoncoherentBusSlaveHandler(*this); + SlavePort* bp = new SlavePort(portName, this, *bh, i); slavePorts.push_back(bp); } @@ -115,7 +120,7 @@ // since it is a normal request, determine the destination // based on the address and attempt to send the packet - bool success = masterPorts[findPort(pkt->getAddr())]->sendTimingReq(pkt); + bool success = (*masterPorts[findPort(pkt->getAddr())])->sendTimingReq(pkt); if (!success) { // inhibited packets should never be forced to retry @@ -156,7 +161,8 @@ // send the packet to the destination through one of our slave // ports, as determined by the destination field - bool success M5_VAR_USED = slavePorts[pkt->getDest()]->sendTimingResp(pkt); + bool success M5_VAR_USED = + (*slavePorts[pkt->getDest()])->sendTimingResp(pkt); // currently it is illegal to block responses... can lead to // deadlock @@ -187,7 +193,7 @@ PortID dest_id = findPort(pkt->getAddr()); // forward the request to the appropriate destination - Tick response_latency = masterPorts[dest_id]->sendAtomic(pkt); + Tick response_latency = (*masterPorts[dest_id])->sendAtomic(pkt); pkt->finishTime = curTick() + response_latency; return response_latency; @@ -208,7 +214,7 @@ PortID dest_id = findPort(pkt->getAddr()); // forward the request to the appropriate destination - masterPorts[dest_id]->sendFunctional(pkt); + (*masterPorts[dest_id])->sendFunctional(pkt); } unsigned int diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/packet_queue.hh --- a/src/mem/packet_queue.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/packet_queue.hh Tue Jul 17 19:06:02 2012 +0100 @@ -39,6 +39,7 @@ * * Authors: Ali Saidi * Andreas Hansson + * William Wang */ #ifndef __MEM_PACKET_QUEUE_HH__ @@ -221,7 +222,7 @@ protected: - MasterPort& masterPort; + MasterInterface& masterInterface; public: @@ -231,16 +232,16 @@ * request packets. * * @param _em Event manager used for scheduling this queue - * @param _masterPort Master port used to send the packets + * @param _masterInterface Master interface used to send the packets * @param _label Label to push on the label stack for print request packets */ - MasterPacketQueue(EventManager& _em, MasterPort& _masterPort, + MasterPacketQueue(EventManager& _em, MasterInterface& _masterInterface, const std::string _label = "MasterPacketQueue"); virtual ~MasterPacketQueue() { } const std::string name() const - { return masterPort.name() + "-" + label; } + { return masterInterface.name() + "-" + label; } bool sendTiming(PacketPtr pkt, bool send_as_snoop); }; @@ -250,7 +251,7 @@ protected: - SlavePort& slavePort; + SlaveInterface& slaveInterface; public: @@ -260,16 +261,16 @@ * request packets. * * @param _em Event manager used for scheduling this queue - * @param _slavePort Slave port used to send the packets + * @param _slaveInterface Slave interface used to send the packets * @param _label Label to push on the label stack for print request packets */ - SlavePacketQueue(EventManager& _em, SlavePort& _slavePort, + SlavePacketQueue(EventManager& _em, SlaveInterface& _slaveInterface, const std::string _label = "SlavePacketQueue"); virtual ~SlavePacketQueue() { } const std::string name() const - { return slavePort.name() + "-" + label; } + { return slaveInterface.name() + "-" + label; } bool sendTiming(PacketPtr pkt, bool send_as_snoop); diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/packet_queue.cc --- a/src/mem/packet_queue.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/packet_queue.cc Tue Jul 17 19:06:02 2012 +0100 @@ -205,9 +205,10 @@ return 1; } -MasterPacketQueue::MasterPacketQueue(EventManager& _em, MasterPort& _masterPort, +MasterPacketQueue::MasterPacketQueue(EventManager& _em, + MasterInterface& _masterInterface, const std::string _label) - : PacketQueue(_em, _label), masterPort(_masterPort) + : PacketQueue(_em, _label), masterInterface(_masterInterface) { } @@ -216,14 +217,15 @@ { // attempt to send the packet and return according to the outcome if (!send_as_snoop) - return masterPort.sendTimingReq(pkt); + return masterInterface.sendTimingReq(pkt); else - return masterPort.sendTimingSnoopResp(pkt); + return masterInterface.sendTimingSnoopResp(pkt); } -SlavePacketQueue::SlavePacketQueue(EventManager& _em, SlavePort& _slavePort, +SlavePacketQueue::SlavePacketQueue(EventManager& _em, + SlaveInterface& _slaveInterface, const std::string _label) - : PacketQueue(_em, _label), slavePort(_slavePort) + : PacketQueue(_em, _label), slaveInterface(_slaveInterface) { } @@ -232,5 +234,5 @@ { // we should never have queued snoop requests assert(!send_as_snoop); - return slavePort.sendTimingResp(pkt); + return slaveInterface.sendTimingResp(pkt); } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/port.hh --- a/src/mem/port.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/port.hh Tue Jul 17 19:06:02 2012 +0100 @@ -44,34 +44,56 @@ /** * @file - * Port Object Declaration. + * Port declaration, including protocol-agnostic BaseMasterPort and + * BaseSlavePort, as well as the interface-specific MasterPort and + * SlavePort. */ #ifndef __MEM_PORT_HH__ #define __MEM_PORT_HH__ -#include - -#include "base/range.hh" -#include "mem/packet.hh" - -/** - * 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. - */ - -typedef std::list > AddrRangeList; -typedef std::list >::iterator AddrRangeIter; -typedef std::list >::const_iterator AddrRangeConstIter; +#include "mem/port_interface.hh" class MemObject; /** * 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. Each port has a name, an owner, and an identifier. + * opposite role. Each port has a name, an owner, and an + * identifier. The port itself dictates how things are connected and + * governs the physical topology of the system. On top of this, the + * port interfaces (implemented by handlers) are responsible for the + * transport functions, e.g. send/recv for functional, atomic and + * timing, and also for functions like querying of address ranges and + * block size. + * + * To enable any arbitrary specialisation of the interfaces, the + * protcol-agnostic base ports have bind functions that call a virtual + * bind function on the interface base class. It is then up to the + * specific implementation to overload this function and verify the + * compatibility. Thus, the ports pass the binding responsibility to + * the interface. + * + * The separation of the port and the interface is done in a similar + * manner to TLM-2.0, with the interface of the port being accessible + * by overloading the pointer operator. Although this might seem like + * C++ abuse, it makes for a far-less verbose way of accessing the + * interface compared to e.g. a member function. + * + * As can be seen e.g. in the CPU, the separation of the port and the + * interface also enable the BaseCPU to declare the instPort and + * dataPort, and then leave it up to the specific CPU model to provide + * the interface handlers. Thus, the atomic, timing, inorder and O3 + * CPU can all implement their own independent handlers, and merely + * pass them on to the BaseCPU. A similar approach is used in the + * cache. + * + * An additional benefit of this separation is that the module itself + * can implement the interface. This is done in the SimpleMemory, + * where the port handler was a trivial class that only added a level + * of indirection. Instead of having this handler, the port is now + * assigned the SimpleMemory itself as the handler, and the + * SimpleMemory is both a MemObject and a SlaveInterface. */ class Port { @@ -130,7 +152,7 @@ protected: - BaseSlavePort* _baseSlavePort; + BaseSlavePort* _slavePort; BaseMasterPort(const std::string& name, MemObject* owner, PortID id = InvalidPortID); @@ -138,8 +160,21 @@ public: + /** + * Bind this master port to a slave port. It is the responsibility + * of the master to also ensure that the slave is bound to the + * master. Moreover, the master must also bind the interface of + * the port. + * + * This method is virtual as the protocol specific port also is + * responsible for the binding of the interfaces. + * + * @param slave_port the slave port to bind to + */ virtual void bind(BaseSlavePort& slave_port) = 0; + BaseSlavePort& getSlavePort() const; + bool isConnected() const; }; @@ -153,7 +188,7 @@ protected: - BaseMasterPort* _baseMasterPort; + BaseMasterPort* _masterPort; BaseSlavePort(const std::string& name, MemObject* owner, PortID id = InvalidPortID); @@ -161,306 +196,140 @@ public: + void bind(BaseMasterPort& master_port); + BaseMasterPort& getMasterPort() const; + + virtual BaseSlaveInterface& getInterface() = 0; + bool isConnected() const; }; /** Forward declaration */ -class SlavePort; +template +class IfaceSlavePort; /** - * A MasterPort is a specialisation of a BaseMasterPort, which - * implements the default protocol for the three different level of - * transport functions. In addition to the basic functionality of - * sending packets, it also has functions to receive range changes or - * determine if the port is snooping or not. + * An IfaceMasterPort is a specialisation of a BaseMasterPort, which + * implements a specific interface. Each port now has two template + * parameters, one for the exposed interface of the port itself + * (i.e. the sending and receiving functionality) and one for the + * interface required from the peer port (the receiving end of the + * port's own sending interface). For example, for a conventional + * master port, this would now be IfaceMasterPort, where the parameters can be left out as they are + * the default values. This corresponds to a port on which we can use + * the MasterInterface, and bind to a peer port with a SlaveInterface. */ -class MasterPort : public BaseMasterPort +template +class IfaceMasterPort : public BaseMasterPort { - friend class SlavePort; - private: - SlavePort* _slavePort; + MASTER_IF& _masterInterface; public: - MasterPort(const std::string& name, MemObject* owner, - PortID id = InvalidPortID); - virtual ~MasterPort(); - - void bind(BaseSlavePort& slave_port); - - /** - * Send an atomic request packet, where the data is moved and the - * state is updated in zero time, without interleaving with other - * memory accesses. - * - * @param pkt Packet to send. - * - * @return Estimated latency of access. - */ - Tick sendAtomic(PacketPtr pkt); - - /** - * Send a functional request packet, where the data is instantly - * updated everywhere in the memory system, without affecting the - * current state of any block or moving the block. - * - * @param pkt Packet to send. - */ - void sendFunctional(PacketPtr pkt); - - /** - * Attempt to send a timing request to the slave port by calling - * its corresponding 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 - * sendTimingReq. - * - * @param pkt Packet to send. - * - * @return If the send was succesful or not. - */ - bool sendTimingReq(PacketPtr pkt); - - /** - * Attempt to send a timing snoop response packet to the slave - * port by calling its corresponding 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 sendTimingSnoopResp. - * - * @param pkt Packet to send. - */ - bool sendTimingSnoopResp(PacketPtr pkt); - - /** - * Send a retry to the slave port that previously attempted a - * sendTimingResp to this master port and failed. - */ - void sendRetry(); - - /** - * 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; - - /** - * Get the address ranges of the connected slave port. - */ - AddrRangeList getAddrRanges() const; - - /** Inject a PrintReq for the given address to print the state of - * that address throughout the memory system. For debugging. - */ - void printAddr(Addr a); - - protected: - - /** - * Receive an atomic snoop request packet from the slave port. - */ - virtual Tick recvAtomicSnoop(PacketPtr pkt) + IfaceMasterPort(const std::string& name, MemObject* owner, + MASTER_IF& interface, PortID id = InvalidPortID) + : BaseMasterPort(name, owner, id), + _masterInterface(interface) { - panic("%s was not expecting an atomic snoop request\n", name()); - return 0; + // enable the interface to also track the port that owns it + _masterInterface.setMasterPort(this); } - /** - * Receive a functional snoop request packet from the slave port. - */ - virtual void recvFunctionalSnoop(PacketPtr pkt) + virtual ~IfaceMasterPort() { } + + void bind(BaseSlavePort& slave_port) { - panic("%s was not expecting a functional snoop request\n", name()); + // bind on the level of the base ports + _slavePort = &slave_port; + + // also attempt to bind the interface + _masterInterface.bind(slave_port.getInterface()); + + // the slave port also keeps track of the master port + slave_port.bind(*this); } - /** - * Receive a timing response from the slave port. - */ - virtual bool recvTimingResp(PacketPtr pkt) = 0; - - /** - * Receive a timing snoop request from the slave port. - */ - virtual void recvTimingSnoopReq(PacketPtr pkt) + inline MASTER_IF* operator->() { - panic("%s was not expecting a timing snoop request\n", name()); + return &_masterInterface; } - /** - * Called by the slave port if sendTimingReq or - * sendTimingSnoopResp was called on this master port (causing - * recvTimingReq and recvTimingSnoopResp to be called on the - * slave port) and was unsuccesful. - */ - virtual void recvRetry() = 0; + inline const MASTER_IF* operator->() const + { + return &_masterInterface; + } - /** - * Called to receive an address range change from the peer slave - * port. the default implementation ignored the change and does - * nothing. Override this function in a derived class if the owner - * needs to be aware of he laesddress ranges, e.g. in an - * interconnect component like a bus. - */ - virtual void recvRangeChange() { } + operator MASTER_IF&() { return _masterInterface; } }; /** - * 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. + * Convenience typedef for a master port with the default template + * parameters. This is sufficient in most typical cases, where no + * additional functionality is required from the ports. In the case of + * e.g. a DMA port, additional sending functions like dmaAction + * require the port to expose a DMA-specific interface, which extends + * the MasterInterface. This is implemented in a DmaHandler, which + * inherits from the MasterInterface, and besides implementing + * e.g. recvTimingResp also adds the desired DMA functions. By using a + * IfaceMasterPort we get a master port with the + * desired DMA interface (which still binds to a SlaveInterface). */ -class SlavePort : public BaseSlavePort +typedef IfaceMasterPort<> MasterPort; + +/** + * An IfaceSlavePort is a specialisation of a slave port with a + * specific port interface. + */ +template +class IfaceSlavePort : public BaseSlavePort { - friend class MasterPort; - private: - MasterPort* _masterPort; + SLAVE_IF& _slaveInterface; public: - SlavePort(const std::string& name, MemObject* owner, - PortID id = InvalidPortID); - virtual ~SlavePort(); - - void bind(MasterPort& master_port); - - /** - * Send an atomic snoop request packet, where the data is moved - * and the state is updated in zero time, without interleaving - * with other memory accesses. - * - * @param pkt Snoop packet to send. - * - * @return Estimated latency of access. - */ - Tick sendAtomicSnoop(PacketPtr pkt); - - /** - * Send a functional snoop request packet, where the data is - * instantly updated everywhere in the memory system, without - * affecting the current state of any block or moving the block. - * - * @param pkt Snoop packet to send. - */ - void sendFunctionalSnoop(PacketPtr pkt); - - /** - * Attempt to send a timing response to the master port by calling - * its corresponding 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 - * sendTimingResp. - * - * @param pkt Packet to send. - * - * @return If the send was succesful or not. - */ - bool sendTimingResp(PacketPtr pkt); - - /** - * Attempt to send a timing snoop request packet to the master port - * by calling its corresponding receive function. Snoop requests - * always succeed and hence no return value is needed. - * - * @param pkt Packet to send. - */ - void sendTimingSnoopReq(PacketPtr pkt); - - /** - * Send a retry to the master port that previously attempted a - * sendTimingReq or sendTimingSnoopResp to this slave port and - * failed. - */ - void sendRetry(); - - /** - * 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; - - /** - * Find out if the peer master port is snooping or not. - * - * @return true if the peer master port is snooping - */ - bool isSnooping() const { return _masterPort->isSnooping(); } - - /** - * 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() const = 0; - - protected: - - /** - * Receive an atomic request packet from the master port. - */ - virtual Tick recvAtomic(PacketPtr pkt) = 0; - - /** - * Receive a functional request packet from the master port. - */ - virtual void recvFunctional(PacketPtr pkt) = 0; - - /** - * Receive a timing request from the master port. - */ - virtual bool recvTimingReq(PacketPtr pkt) = 0; - - /** - * Receive a timing snoop response from the master port. - */ - virtual bool recvTimingSnoopResp(PacketPtr pkt) + IfaceSlavePort(const std::string& name, MemObject* owner, + SLAVE_IF& interface, PortID id = InvalidPortID) + : BaseSlavePort(name, owner, id), + _slaveInterface(interface) { - panic("%s was not expecting a timing snoop response\n", name()); + // enable the interface to also track the port that owns it + _slaveInterface.setSlavePort(this); } - /** - * Called by the master port if sendTimingResp was called on this - * slave port (causing recvTimingResp to be called on the master - * port) and was unsuccesful. - */ - virtual void recvRetry() = 0; + virtual ~IfaceSlavePort() { } + + inline SLAVE_IF* operator->() + { + return &_slaveInterface; + } + + inline const SLAVE_IF* operator->() const + { + return &_slaveInterface; + } + + BaseSlaveInterface& getInterface() + { + return _slaveInterface; + } }; +/** + * Convenience typedef for a slave port with the default template + * parameters. + */ +typedef IfaceSlavePort<> SlavePort; + #endif //__MEM_PORT_HH__ diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/port.cc --- a/src/mem/port.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/port.cc Tue Jul 17 19:06:02 2012 +0100 @@ -44,7 +44,7 @@ /** * @file - * Port object definitions. + * Port object implementation. */ #include "base/trace.hh" #include "mem/mem_object.hh" @@ -61,7 +61,7 @@ BaseMasterPort::BaseMasterPort(const std::string& name, MemObject* owner, PortID _id) - : Port(name, *owner, _id), _baseSlavePort(NULL) + : Port(name, *owner, _id), _slavePort(NULL) { } @@ -72,22 +72,22 @@ BaseSlavePort& BaseMasterPort::getSlavePort() const { - if(_baseSlavePort == NULL) + if(_slavePort == NULL) panic("Cannot getSlavePort on master port %s that is not connected\n", name()); - return *_baseSlavePort; + return *_slavePort; } bool BaseMasterPort::isConnected() const { - return _baseSlavePort != NULL; + return _slavePort != NULL; } BaseSlavePort::BaseSlavePort(const std::string& name, MemObject* owner, PortID _id) - : Port(name, *owner, _id), _baseMasterPort(NULL) + : Port(name, *owner, _id), _masterPort(NULL) { } @@ -95,168 +95,25 @@ { } +void +BaseSlavePort::bind(BaseMasterPort& master_port) +{ + _masterPort = &master_port; +} + + BaseMasterPort& BaseSlavePort::getMasterPort() const { - if(_baseMasterPort == NULL) + if(_masterPort == NULL) panic("Cannot getMasterPort on slave port %s that is not connected\n", name()); - return *_baseMasterPort; + return *_masterPort; } bool BaseSlavePort::isConnected() const { - return _baseMasterPort != NULL; + return _masterPort != NULL; } - -/** - * Master port - */ -MasterPort::MasterPort(const std::string& name, MemObject* owner, PortID _id) - : BaseMasterPort(name, owner, _id), _slavePort(NULL) -{ -} - -MasterPort::~MasterPort() -{ -} - -void -MasterPort::bind(BaseSlavePort& slave_port) -{ - // bind on the level of the base ports - _baseSlavePort = &slave_port; - - // also attempt to base the slave to the appropriate type - SlavePort* cast_slave_port = dynamic_cast(&slave_port); - - // if this port is compatible, then proceed with the binding - if (cast_slave_port != NULL) { - // master port keeps track of the slave port - _slavePort = cast_slave_port; - - // slave port also keeps track of master port - _slavePort->bind(*this); - } else { - fatal("Master port %s cannot bind to %s\n", name(), - slave_port.name()); - } -} - -unsigned -MasterPort::peerBlockSize() const -{ - return _slavePort->deviceBlockSize(); -} - -AddrRangeList -MasterPort::getAddrRanges() const -{ - return _slavePort->getAddrRanges(); -} - -Tick -MasterPort::sendAtomic(PacketPtr pkt) -{ - assert(pkt->isRequest()); - return _slavePort->recvAtomic(pkt); -} - -void -MasterPort::sendFunctional(PacketPtr pkt) -{ - assert(pkt->isRequest()); - return _slavePort->recvFunctional(pkt); -} - -bool -MasterPort::sendTimingReq(PacketPtr pkt) -{ - assert(pkt->isRequest()); - return _slavePort->recvTimingReq(pkt); -} - -bool -MasterPort::sendTimingSnoopResp(PacketPtr pkt) -{ - assert(pkt->isResponse()); - return _slavePort->recvTimingSnoopResp(pkt); -} - -void -MasterPort::sendRetry() -{ - _slavePort->recvRetry(); -} - -void -MasterPort::printAddr(Addr a) -{ - Request req(a, 1, 0, Request::funcMasterId); - Packet pkt(&req, MemCmd::PrintReq); - Packet::PrintReqState prs(std::cerr); - pkt.senderState = &prs; - - sendFunctional(&pkt); -} - -/** - * Slave port - */ -SlavePort::SlavePort(const std::string& name, MemObject* owner, PortID id) - : BaseSlavePort(name, owner, id), _masterPort(NULL) -{ -} - -SlavePort::~SlavePort() -{ -} - -void -SlavePort::bind(MasterPort& master_port) -{ - _baseMasterPort = &master_port; - _masterPort = &master_port; -} - -unsigned -SlavePort::peerBlockSize() const -{ - return _masterPort->deviceBlockSize(); -} - -Tick -SlavePort::sendAtomicSnoop(PacketPtr pkt) -{ - assert(pkt->isRequest()); - return _masterPort->recvAtomicSnoop(pkt); -} - -void -SlavePort::sendFunctionalSnoop(PacketPtr pkt) -{ - assert(pkt->isRequest()); - return _masterPort->recvFunctionalSnoop(pkt); -} - -bool -SlavePort::sendTimingResp(PacketPtr pkt) -{ - assert(pkt->isResponse()); - return _masterPort->recvTimingResp(pkt); -} - -void -SlavePort::sendTimingSnoopReq(PacketPtr pkt) -{ - assert(pkt->isRequest()); - _masterPort->recvTimingSnoopReq(pkt); -} - -void -SlavePort::sendRetry() -{ - _masterPort->recvRetry(); -} diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/port_interface.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/port_interface.hh Tue Jul 17 19:06:02 2012 +0100 @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2011-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. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Ron Dreslinski + * Andreas Hansson + * William Wang + */ + +/** + * @file + * Port interface declaration. + */ + +#ifndef __MEM_PORT_INTERFACE_HH__ +#define __MEM_PORT_INTERFACE_HH__ + +#include + +#include "base/range.hh" +#include "mem/packet.hh" + +/** + * This typedef is used to clean up getAddrRanges(). It's declared + * outside the interfaces since it's also used by some mem objects. + * Eventually we should move this typedef to wherever Addr is + * defined. + */ + +typedef std::list > AddrRangeList; +typedef std::list >::iterator AddrRangeIter; +typedef std::list >::const_iterator AddrRangeConstIter; + +/** + * A base slave interface gives the ports a way to bind a master and + * slave interface without having any knowledge of protocol-specific + * interfaces. + */ +class BaseSlaveInterface +{ + public: + + BaseSlaveInterface() { } + + virtual ~BaseSlaveInterface() { } +}; + +/** + * A base master interface serves to give the ports a way to bind the + * interfaces without having to k nowanything about any + * protocol-specific interface. + */ +class BaseMasterInterface +{ + public: + + BaseMasterInterface() { } + + virtual ~BaseMasterInterface() { } + + /** + * Bind this master interface to a slave interface. This method is + * purely virtual and will be implemented by the final master + * interface that will also check the compatibility of the slave + * interface. + * + * @param slave_if Slave interface to bind to + */ + virtual void bind(BaseSlaveInterface& slave_if) = 0; +}; + +/** + * Forward declaration to avoid circular dependencies. + */ +class Port; +class BaseMasterPort; +class BaseSlavePort; +class SlaveInterface; + +/** + * A master port interface implements the default classic interface + * protocol of a master port. + */ +class MasterInterface : public BaseMasterInterface +{ + + friend class SlaveInterface; + + protected: + + /** + * A pointer to the peer slave interface. Just like ports, + * interfaces always come in pairs. + */ + SlaveInterface* slaveInterface; + + /** + * The port which owns this interface, always a master port, but + * we do not need the type information as it is only used for the + * name. + */ + Port* port; + + public: + + /** + * Create a master interface, initially without a peer and without + * association to a port. + */ + MasterInterface() : slaveInterface(NULL), port(NULL) { } + + virtual ~MasterInterface() { } + + /** + * Set the peer slave interface. + */ + void bind(BaseSlaveInterface& slave_if); + + /** + * Set the master port . + */ + void setMasterPort(BaseMasterPort* master_port); + + /** + * Get the interface name. + */ + std::string name() const; + + /** + * Send an atomic request packet, where the data is moved and the + * state is updated in zero time, without interleaving with other + * memory accesses. + * + * @param pkt Packet to send. + * + * @return Estimated latency of access. + */ + Tick sendAtomic(PacketPtr pkt); + + /** + * Send a functional request packet, where the data is instantly + * updated everywhere in the memory system, without affecting the + * current state of any block or moving the block. + * + * @param pkt Packet to send. + */ + void sendFunctional(PacketPtr pkt); + + /** + * Attempt to send a timing request to the slave interface by + * calling its corresponding 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 + * sendTimingReq. + * + * @param pkt Packet to send. + * + * @return If the send was succesful or not. + */ + bool sendTimingReq(PacketPtr pkt); + + /** + * Attempt to send a timing snoop response packet to the slave + * interface by calling its corresponding 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 sendTimingSnoopResp. + * + * @param pkt Packet to send. + */ + bool sendTimingSnoopResp(PacketPtr pkt); + + /** + * Send a retry to the slave interface that previously attempted a + * sendTimingResp to this master interface and failed. + */ + void sendRetry(); + + /** + * Determine if this master interface is snooping or not. The + * default implementation returns false and thus tells the + * neighbour we are not snooping. Any master 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; } + + /** + * Determine the block size of the owner of this interface. + */ + virtual unsigned deviceBlockSize() const { return 0; } + + /** + * Retrieve the blocksize of peer slave interface. + */ + unsigned peerBlockSize() const; + + /** + * Get the address ranges of the connected slave interface. + */ + AddrRangeList getAddrRanges() const; + + /** Inject a PrintReq for the given address to print the state of + * that address throughout the memory system. For debugging. + */ + void printAddr(Addr a); + + protected: + + /** + * Receive an atomic snoop request packet from the slave interface. + */ + virtual Tick recvAtomicSnoop(PacketPtr pkt) + { + panic("%s was not expecting an atomic snoop request\n", name()); + return 0; + } + + /** + * Receive a functional snoop request packet from the slave interface. + */ + virtual void recvFunctionalSnoop(PacketPtr pkt) + { + panic("%s was not expecting a functional snoop request\n", name()); + } + + /** + * Receive a timing response from the slave interface. + */ + virtual bool recvTimingResp(PacketPtr pkt) = 0; + + /** + * Receive a timing snoop request from the slave interface. + */ + virtual void recvTimingSnoopReq(PacketPtr pkt) + { + panic("%s was not expecting a timing snoop request\n", name()); + } + + /** + * Called by the slave interface if sendTimingReq or + * sendTimingSnoopResp was called on this master interface + * (causing recvTimingReq and recvTimingSnoopResp to be called on + * the slave port) and was unsuccesful. + */ + virtual void recvRetry() = 0; + + /** + * Called to receive an address range change from the peer slave + * interface. The default implementation ignores the change and + * does nothing. Override this function in a derived class if the + * owner needs to be aware of the address ranges, e.g. in an + * interconnect component like a bus. + */ + virtual void recvRangeChange() { } +}; + +/** + * A slave port interface implements the default base interface + * protocol of a slave port. + */ +class SlaveInterface : public BaseSlaveInterface +{ + + friend class MasterInterface; + + protected: + + /** + * A pointer to the peer master interface. + */ + MasterInterface* masterInterface; + + /** + * The slave port which owns this interface. + */ + Port* port; + + public: + + /** + * Create a slave interface, initially without a peer and without + * association to a port. + */ + SlaveInterface() : masterInterface(NULL), port(NULL) { } + + virtual ~SlaveInterface() { } + + /** + * Set the peer master interface. + */ + void bind(MasterInterface& master_if) + { masterInterface = &master_if; } + + /** + * Set the slave port. + */ + void setSlavePort(BaseSlavePort* slave_port); + + /** + * Get the interface name. + */ + std::string name() const; + + /** + * Send an atomic snoop request packet, where the data is moved + * and the state is updated in zero time, without interleaving + * with other memory accesses. + * + * @param pkt Snoop packet to send. + * + * @return Estimated latency of access. + */ + Tick sendAtomicSnoop(PacketPtr pkt); + + /** + * Send a functional snoop request packet, where the data is + * instantly updated everywhere in the memory system, without + * affecting the current state of any block or moving the block. + * + * @param pkt Snoop packet to send. + */ + void sendFunctionalSnoop(PacketPtr pkt); + + /** + * Attempt to send a timing response to the master interface by + * calling its corresponding 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 + * sendTimingResp. + * + * @param pkt Packet to send. + * + * @return If the send was succesful or not. + */ + bool sendTimingResp(PacketPtr pkt); + + /** + * Attempt to send a timing snoop request packet to the master + * interface by calling its corresponding receive function. Snoop + * requests always succeed and hence no return value is needed. + * + * @param pkt Packet to send. + */ + void sendTimingSnoopReq(PacketPtr pkt); + + /** + * Send a retry to the master interface that previously attempted + * a sendTimingReq or sendTimingSnoopResp to this slave port and + * failed. + */ + void sendRetry(); + + /** + * Determine the block size of the owner of this interface. + */ + virtual unsigned deviceBlockSize() const { return 0; } + + /** + * Retrieve the blocksize of peer slave interface. + */ + unsigned peerBlockSize() const; + + /** + * Find out if the peer master interface is snooping or not. + * + * @return true if the peer master interface is snooping + */ + bool isSnooping() const { return masterInterface->isSnooping(); } + + /** + * Called by the owner to send a range change + */ + void sendRangeChange() const { masterInterface->recvRangeChange(); } + + /** + * Get a list of the non-overlapping address ranges the owner is + * responsible for. All slave interfaces must override this + * function and return a populated list with at least one item. + * + * @return a list of ranges responded to + */ + virtual AddrRangeList getAddrRanges() const = 0; + + protected: + + /** + * Receive an atomic request packet from the master interface. + */ + virtual Tick recvAtomic(PacketPtr pkt) = 0; + + /** + * Receive a functional request packet from the master interface. + */ + virtual void recvFunctional(PacketPtr pkt) = 0; + + /** + * Receive a timing request from the master interface. + */ + virtual bool recvTimingReq(PacketPtr pkt) = 0; + + /** + * Receive a timing snoop response from the master interface. + */ + virtual bool recvTimingSnoopResp(PacketPtr pkt) + { + panic("%s was not expecting a timing snoop response\n", name()); + } + + /** + * Called by the master port if sendTimingResp was called on this + * slave interface (causing recvTimingResp to be called on the + * master interface) and was unsuccesful. + */ + virtual void recvRetry() = 0; + +}; + +#endif //__MEM_PORT_INTERFACE_HH__ diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/port_interface.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/port_interface.cc Tue Jul 17 19:06:02 2012 +0100 @@ -0,0 +1,195 @@ +/* + * 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. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Andreas Hansson + * William Wang + */ + +/** + * @file + * Port interface implementation. + */ + +#include "mem/port.hh" +#include "mem/port_interface.hh" + +unsigned +MasterInterface::peerBlockSize() const +{ + return slaveInterface->deviceBlockSize(); +} + +AddrRangeList +MasterInterface::getAddrRanges() const +{ + return slaveInterface->getAddrRanges(); +} + +void +MasterInterface::bind(BaseSlaveInterface& slave_if) +{ + // attempt to bind the slave interface after casting to the + // appropriate type + slaveInterface = dynamic_cast(&slave_if); + if (slaveInterface == NULL) + fatal("Cannot bind incompatible slave interface\n"); + + // also let the slave interface point back to the master interface + slaveInterface->bind(*this); +} + +void +MasterInterface::setMasterPort(BaseMasterPort* master_port) +{ + // we throw away the type information here as we only use the port + // for the name, still we check that it is a master port when + // passing the pointer + assert(master_port != NULL); + port = master_port; +} + +std::string +MasterInterface::name() const +{ + // append interface to the port name + return port->name() + "-interface"; +} + +Tick +MasterInterface::sendAtomic(PacketPtr pkt) +{ + assert(pkt->isRequest()); + return slaveInterface->recvAtomic(pkt); +} + +void +MasterInterface::sendFunctional(PacketPtr pkt) +{ + assert(pkt->isRequest()); + return slaveInterface->recvFunctional(pkt); +} + +bool +MasterInterface::sendTimingReq(PacketPtr pkt) +{ + assert(pkt->isRequest()); + return slaveInterface->recvTimingReq(pkt); +} + +bool +MasterInterface::sendTimingSnoopResp(PacketPtr pkt) +{ + assert(pkt->isResponse()); + return slaveInterface->recvTimingSnoopResp(pkt); +} + +void +MasterInterface::sendRetry() +{ + slaveInterface->recvRetry(); +} + +void +MasterInterface::printAddr(Addr a) +{ + Request req(a, 1, 0, Request::funcMasterId); + Packet pkt(&req, MemCmd::PrintReq); + Packet::PrintReqState prs(std::cerr); + pkt.senderState = &prs; + + sendFunctional(&pkt); +} + +unsigned +SlaveInterface::peerBlockSize() const +{ + return masterInterface->deviceBlockSize(); +} + +void +SlaveInterface::setSlavePort(BaseSlavePort* slave_port) +{ + // we throw away the type information here as we only use the port + // for the name, still we check that it is a slave port when + // passing the pointer + assert(slave_port != NULL); + port = slave_port; +} + +std::string +SlaveInterface::name() const +{ + // append interface to the port name + return port->name() + "-interface"; +} + +Tick +SlaveInterface::sendAtomicSnoop(PacketPtr pkt) +{ + assert(pkt->isRequest()); + return masterInterface->recvAtomicSnoop(pkt); +} + +void +SlaveInterface::sendFunctionalSnoop(PacketPtr pkt) +{ + assert(pkt->isRequest()); + return masterInterface->recvFunctionalSnoop(pkt); +} + +bool +SlaveInterface::sendTimingResp(PacketPtr pkt) +{ + assert(pkt->isResponse()); + return masterInterface->recvTimingResp(pkt); +} + +void +SlaveInterface::sendTimingSnoopReq(PacketPtr pkt) +{ + assert(pkt->isRequest()); + masterInterface->recvTimingSnoopReq(pkt); +} + +void +SlaveInterface::sendRetry() +{ + masterInterface->recvRetry(); +} diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/port_proxy.hh --- a/src/mem/port_proxy.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/port_proxy.hh Tue Jul 17 19:06:02 2012 +0100 @@ -85,13 +85,13 @@ { private: - /** The actual physical port used by this proxy. */ - MasterPort &_port; + /** The actual interface used by this proxy. */ + MasterInterface &_iface; void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd) const; public: - PortProxy(MasterPort &port) : _port(port) { } + PortProxy(MasterInterface &iface) : _iface(iface) { } virtual ~PortProxy() { } /** diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/port_proxy.cc --- a/src/mem/port_proxy.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/port_proxy.cc Tue Jul 17 19:06:02 2012 +0100 @@ -45,12 +45,12 @@ { Request req; - for (ChunkGenerator gen(addr, size, _port.peerBlockSize()); + for (ChunkGenerator gen(addr, size, _iface.peerBlockSize()); !gen.done(); gen.next()) { req.setPhys(gen.addr(), gen.size(), 0, Request::funcMasterId); Packet pkt(&req, cmd); pkt.dataStatic(p); - _port.sendFunctional(&pkt); + _iface.sendFunctional(&pkt); p += gen.size(); } } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/qport.hh --- a/src/mem/qport.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/qport.hh Tue Jul 17 19:06:02 2012 +0100 @@ -42,21 +42,22 @@ /** * @file - * Declaration of the queued port. + * Declaration of the queued handlers and ports. */ #include "mem/packet_queue.hh" #include "mem/port.hh" /** - * A queued port is a port that has an infinite queue for outgoing - * packets and thus decouples the module that wants to send + * A queued handler is a handler that has an infinite queue for + * outgoing packets and thus decouples the module that wants to send * request/responses from the flow control (retry mechanism) of the - * port. A queued port can be used by both a master and a slave. The - * queue is a parameter to allow tailoring of the queue implementation - * (used in the cache). + * port. A queued handler can be used by both a master and a slave, + * with a class for each option. The queue is a parameter to allow + * tailoring of the queue implementation (used in the cache). */ -class QueuedSlavePort : public SlavePort + +class QueuedSlaveHandler : public SlaveInterface { protected: @@ -71,25 +72,22 @@ 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. + * Create a QueuedSlaveHandler with 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. */ - QueuedSlavePort(const std::string& name, MemObject* owner, - SlavePacketQueue &queue) : - SlavePort(name, owner), queue(queue) + QueuedSlaveHandler(SlavePacketQueue &queue) : queue(queue) { } - virtual ~QueuedSlavePort() { } + virtual ~QueuedSlaveHandler() { } /** 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. + * Hook for draining the queue. * * @param de an event which is used to signal back to the caller * @returns a number indicating how many times process will be called @@ -97,7 +95,12 @@ unsigned int drain(Event *de) { return queue.drain(de); } }; -class QueuedMasterPort : public MasterPort +/** + * Convenience type definition for a queued slave port. + */ +typedef IfaceSlavePort QueuedSlavePort; + +class QueuedMasterHandler : public MasterInterface { protected: @@ -112,25 +115,22 @@ 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. + * Create a QueuedMasterHandler with 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. */ - QueuedMasterPort(const std::string& name, MemObject* owner, - MasterPacketQueue &queue) : - MasterPort(name, owner), queue(queue) + QueuedMasterHandler(MasterPacketQueue &queue) : queue(queue) { } - virtual ~QueuedMasterPort() { } + virtual ~QueuedMasterHandler() { } /** 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. + * Hook for draining the queue. * * @param de an event which is used to signal back to the caller * @returns a number indicating how many times process will be called @@ -138,4 +138,9 @@ unsigned int drain(Event *de) { return queue.drain(de); } }; +/** + * Convenience type definition for a queued master port. + */ +typedef IfaceMasterPort QueuedMasterPort; + #endif // __MEM_QPORT_HH__ diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/ruby/system/RubyPort.hh --- a/src/mem/ruby/system/RubyPort.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/ruby/system/RubyPort.hh Tue Jul 17 19:06:02 2012 +0100 @@ -58,7 +58,7 @@ class RubyPort : public MemObject { public: - class M5Port : public QueuedSlavePort + class M5Handler : public QueuedSlaveHandler { private: @@ -69,8 +69,8 @@ bool access_phys_mem; public: - M5Port(const std::string &_name, RubyPort *_port, - RubySystem*_system, bool _access_phys_mem); + M5Handler(RubyPort *_port, RubySystem*_system, + bool _access_phys_mem); bool sendNextCycle(PacketPtr pkt, bool send_as_snoop = false); void hitCallback(PacketPtr pkt); void evictionCallback(const Address& address); @@ -94,9 +94,11 @@ bool doFunctionalWrite(PacketPtr pkt); }; - friend class M5Port; + typedef IfaceSlavePort M5Port; - class PioPort : public QueuedMasterPort + friend class M5Handler; + + class PioHandler : public QueuedMasterHandler { private: @@ -105,22 +107,23 @@ RubyPort *ruby_port; public: - PioPort(const std::string &_name, RubyPort *_port); + PioHandler(RubyPort *_port); bool sendNextCycle(PacketPtr pkt); protected: virtual bool recvTimingResp(PacketPtr pkt); }; - friend class PioPort; + typedef IfaceMasterPort PioPort; struct SenderState : public Packet::SenderState { - M5Port* port; + M5Handler& handler; Packet::SenderState *saved; - SenderState(M5Port* _port, Packet::SenderState *sender_state = NULL) - : port(_port), saved(sender_state) + SenderState(M5Handler& _handler, + Packet::SenderState *sender_state = NULL) + : handler(_handler), saved(sender_state) {} }; @@ -157,15 +160,16 @@ int m_version; AbstractController* m_controller; MessageBuffer* m_mandatory_q_ptr; + PioHandler pio_port_handler; PioPort pio_port; bool m_usingRubyTester; private: - void addToRetryList(M5Port * port) + void addToRetryList(M5Handler * handler) { - if (!port->onRetryList()) { - port->onRetryList(true); - retryList.push_back(port); + if (!handler->onRetryList()) { + handler->onRetryList(true); + retryList.push_back(handler); waitingOnSequencer = true; } } @@ -189,7 +193,7 @@ // Based on similar code in the M5 bus. Stores pointers to those ports // that should be called when the Sequencer becomes available after a stall. // - std::list retryList; + std::list retryList; bool waitingOnSequencer; bool access_phys_mem; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/ruby/system/RubyPort.cc --- a/src/mem/ruby/system/RubyPort.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/ruby/system/RubyPort.cc Tue Jul 17 19:06:02 2012 +0100 @@ -50,7 +50,8 @@ RubyPort::RubyPort(const Params *p) : MemObject(p), m_version(p->version), m_controller(NULL), m_mandatory_q_ptr(NULL), - pio_port(csprintf("%s-pio-port", name()), this), + pio_port_handler(this), + pio_port(csprintf("%s-pio-port", name()), this, pio_port_handler), m_usingRubyTester(p->using_ruby_tester), m_request_cnt(0), drainEvent(NULL), ruby_system(p->ruby_system), system(p->system), waitingOnSequencer(false), access_phys_mem(p->access_phys_mem) @@ -59,14 +60,17 @@ // create the slave ports based on the number of connected ports for (size_t i = 0; i < p->port_slave_connection_count; ++i) { + M5Handler* slaveHandler = + new M5Handler(this, ruby_system, access_phys_mem); slave_ports.push_back(new M5Port(csprintf("%s-slave%d", name(), i), - this, ruby_system, access_phys_mem)); + this, *slaveHandler)); } // create the master ports based on the number of connected ports for (size_t i = 0; i < p->port_master_connection_count; ++i) { + PioHandler* masterHandler = new PioHandler(this); master_ports.push_back(new PioPort(csprintf("%s-master%d", name(), i), - this)); + this, *masterHandler)); } } @@ -115,25 +119,23 @@ } } -RubyPort::PioPort::PioPort(const std::string &_name, - RubyPort *_port) - : QueuedMasterPort(_name, _port, queue), queue(*_port, *this), +RubyPort::PioHandler::PioHandler(RubyPort *_port) + : QueuedMasterHandler(queue), queue(*_port, *this), ruby_port(_port) { - 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) - : QueuedSlavePort(_name, _port, queue), queue(*_port, *this), +RubyPort::M5Handler::M5Handler(RubyPort *_port, + RubySystem *_system, + bool _access_phys_mem) + : QueuedSlaveHandler(queue), queue(*_port, *this), ruby_port(_port), ruby_system(_system), _onRetryList(false), access_phys_mem(_access_phys_mem) { - DPRINTF(RubyPort, "creating slave port on ruby sequencer %s\n", _name); } Tick -RubyPort::M5Port::recvAtomic(PacketPtr pkt) +RubyPort::M5Handler::recvAtomic(PacketPtr pkt) { panic("RubyPort::M5Port::recvAtomic() not implemented!\n"); return 0; @@ -141,7 +143,7 @@ bool -RubyPort::PioPort::recvTimingResp(PacketPtr pkt) +RubyPort::PioHandler::recvTimingResp(PacketPtr pkt) { // In FS mode, ruby memory will receive pio responses from devices // and it must forward these responses back to the particular CPU. @@ -150,20 +152,19 @@ // First we must retrieve the request port from the sender State RubyPort::SenderState *senderState = safe_cast(pkt->senderState); - M5Port *port = senderState->port; - assert(port != NULL); + M5Handler &handler = senderState->handler; // pop the sender state from the packet pkt->senderState = senderState->saved; delete senderState; - port->sendTimingResp(pkt); + handler.sendTimingResp(pkt); return true; } bool -RubyPort::M5Port::recvTimingReq(PacketPtr pkt) +RubyPort::M5Handler::recvTimingReq(PacketPtr pkt) { DPRINTF(RubyPort, "Timing access caught for address %#x\n", pkt->getAddr()); @@ -185,7 +186,7 @@ // Save the port in the sender state object to be used later to // route the response - pkt->senderState = new SenderState(this, pkt->senderState); + pkt->senderState = new SenderState(*this, pkt->senderState); // Check for pio requests and directly send them to the dedicated // pio port. @@ -195,7 +196,7 @@ "Request for address 0x%#x is assumed to be a pio request\n", pkt->getAddr()); - return ruby_port->pio_port.sendNextCycle(pkt); + return ruby_port->pio_port->sendNextCycle(pkt); } assert(Address(pkt->getAddr()).getOffset() + pkt->getSize() <= @@ -231,7 +232,7 @@ } bool -RubyPort::M5Port::doFunctionalRead(PacketPtr pkt) +RubyPort::M5Handler::doFunctionalRead(PacketPtr pkt) { Address address(pkt->getAddr()); Address line_address(address); @@ -334,7 +335,7 @@ } bool -RubyPort::M5Port::doFunctionalWrite(PacketPtr pkt) +RubyPort::M5Handler::doFunctionalWrite(PacketPtr pkt) { Address addr(pkt->getAddr()); Address line_addr = line_address(addr); @@ -414,7 +415,7 @@ } void -RubyPort::M5Port::recvFunctional(PacketPtr pkt) +RubyPort::M5Handler::recvFunctional(PacketPtr pkt) { DPRINTF(RubyPort, "Functional access caught for address %#x\n", pkt->getAddr()); @@ -479,14 +480,13 @@ // Retrieve the request port from the sender State RubyPort::SenderState *senderState = safe_cast(pkt->senderState); - M5Port *port = senderState->port; - assert(port != NULL); + M5Handler &handler = senderState->handler; // pop the sender state from the packet pkt->senderState = senderState->saved; delete senderState; - port->hitCallback(pkt); + handler.hitCallback(pkt); // // If we had to stall the M5Ports, wake them up because the sequencer @@ -500,12 +500,12 @@ // list. Therefore we want to clear the retryList before calling // sendRetry. // - std::list curRetryList(retryList); + std::list curRetryList(retryList); retryList.clear(); waitingOnSequencer = false; - for (std::list::iterator i = curRetryList.begin(); + for (std::list::iterator i = curRetryList.begin(); i != curRetryList.end(); ++i) { DPRINTF(RubyPort, "Sequencer may now be free. SendRetry to port %s\n", @@ -551,18 +551,18 @@ assert(isDeadlockEventScheduled() == false); if (pio_port.isConnected()) { - count += pio_port.drain(de); + count += pio_port->drain(de); DPRINTF(Config, "count after pio check %d\n", count); } for (CpuPortIter p = slave_ports.begin(); p != slave_ports.end(); ++p) { - count += (*p)->drain(de); + count += (**p)->drain(de); DPRINTF(Config, "count after slave port check %d\n", count); } for (std::vector::iterator p = master_ports.begin(); p != master_ports.end(); ++p) { - count += (*p)->drain(de); + count += (**p)->drain(de); DPRINTF(Config, "count after master port check %d\n", count); } @@ -593,7 +593,7 @@ } void -RubyPort::M5Port::hitCallback(PacketPtr pkt) +RubyPort::M5Handler::hitCallback(PacketPtr pkt) { bool needsResponse = pkt->needsResponse(); @@ -652,7 +652,7 @@ } bool -RubyPort::M5Port::sendNextCycle(PacketPtr pkt, bool send_as_snoop) +RubyPort::M5Handler::sendNextCycle(PacketPtr pkt, bool send_as_snoop) { //minimum latency, must be > 0 queue.schedSendTiming(pkt, curTick() + (1 * g_eventQueue_ptr->getClock()), @@ -661,7 +661,7 @@ } bool -RubyPort::PioPort::sendNextCycle(PacketPtr pkt) +RubyPort::PioHandler::sendNextCycle(PacketPtr pkt) { //minimum latency, must be > 0 queue.schedSendTiming(pkt, curTick() + (1 * g_eventQueue_ptr->getClock())); @@ -669,7 +669,7 @@ } AddrRangeList -RubyPort::M5Port::getAddrRanges() const +RubyPort::M5Handler::getAddrRanges() const { // at the moment the assumption is that the master does not care AddrRangeList ranges; @@ -677,13 +677,13 @@ } bool -RubyPort::M5Port::isPhysMemAddress(Addr addr) +RubyPort::M5Handler::isPhysMemAddress(Addr addr) { return ruby_port->system->isMemAddr(addr); } unsigned -RubyPort::M5Port::deviceBlockSize() const +RubyPort::M5Handler::deviceBlockSize() const { return (unsigned) RubySystem::getBlockSizeBytes(); } @@ -696,10 +696,10 @@ Request req(address.getAddress(), 0, 0, Request::funcMasterId); for (CpuPortIter p = slave_ports.begin(); p != slave_ports.end(); ++p) { // check if the connected master port is snooping - if ((*p)->isSnooping()) { + if ((**p)->isSnooping()) { Packet *pkt = new Packet(&req, MemCmd::InvalidationReq); // send as a snoop request - (*p)->sendTimingSnoopReq(pkt); + (**p)->sendTimingSnoopReq(pkt); } } } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/se_translating_port_proxy.hh --- a/src/mem/se_translating_port_proxy.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/se_translating_port_proxy.hh Tue Jul 17 19:06:02 2012 +0100 @@ -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 @@ -80,7 +80,8 @@ AllocType allocating; public: - SETranslatingPortProxy(MasterPort& port, Process* p, AllocType alloc); + SETranslatingPortProxy(MasterInterface& _iface, Process* p, + AllocType alloc); virtual ~SETranslatingPortProxy(); bool tryReadBlob(Addr addr, uint8_t *p, int size) const; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/se_translating_port_proxy.cc --- a/src/mem/se_translating_port_proxy.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/se_translating_port_proxy.cc Tue Jul 17 19:06:02 2012 +0100 @@ -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 @@ -53,9 +53,10 @@ using namespace TheISA; -SETranslatingPortProxy::SETranslatingPortProxy(MasterPort& port, Process *p, +SETranslatingPortProxy::SETranslatingPortProxy(MasterInterface& iface, + Process *p, AllocType alloc) - : PortProxy(port), pTable(p->pTable), process(p), + : PortProxy(iface), pTable(p->pTable), process(p), allocating(alloc) { } diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/simple_mem.hh --- a/src/mem/simple_mem.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/simple_mem.hh Tue Jul 17 19:06:02 2012 +0100 @@ -56,33 +56,16 @@ /** * The simple memory is a basic single-ported memory controller with * an infinite throughput and a fixed latency, potentially with a - * variance added to it. It uses a SimpleTimingPort to implement the - * timing accesses. + * variance added to it. It extends SimpleTimingHandler to implement + * the timing accesses and thus avoids having an explicit port + * interface handler. */ -class SimpleMemory : public AbstractMemory +class SimpleMemory : public AbstractMemory, public SimpleTimingHandler { private: - class MemoryPort : public SimpleTimingPort - { - SimpleMemory& memory; - - public: - - MemoryPort(const std::string& _name, SimpleMemory& _memory); - - protected: - - virtual Tick recvAtomic(PacketPtr pkt); - - virtual void recvFunctional(PacketPtr pkt); - - virtual AddrRangeList getAddrRanges() const; - - }; - - MemoryPort port; + QueuedSlavePort port; Tick lat; Tick lat_var; @@ -107,8 +90,10 @@ protected: - Tick doAtomicAccess(PacketPtr pkt); - void doFunctionalAccess(PacketPtr pkt); + Tick recvAtomic(PacketPtr pkt); + void recvFunctional(PacketPtr pkt); + AddrRangeList getAddrRanges() const; + virtual Tick calculateLatency(PacketPtr pkt); }; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/simple_mem.cc --- a/src/mem/simple_mem.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/simple_mem.cc Tue Jul 17 19:06:02 2012 +0100 @@ -48,8 +48,9 @@ using namespace std; SimpleMemory::SimpleMemory(const Params* p) : - AbstractMemory(p), - port(name() + ".port", *this), lat(p->latency), lat_var(p->latency_var) + AbstractMemory(p), SimpleTimingHandler(this), + port(SimObject::name() + ".port", this, *this), + lat(p->latency), lat_var(p->latency_var) { } @@ -59,7 +60,7 @@ // allow unconnected memories as this is used in several ruby // systems at the moment if (port.isConnected()) { - port.sendRangeChange(); + port->sendRangeChange(); } } @@ -77,16 +78,25 @@ } Tick -SimpleMemory::doAtomicAccess(PacketPtr pkt) +SimpleMemory::recvAtomic(PacketPtr pkt) { access(pkt); return calculateLatency(pkt); } void -SimpleMemory::doFunctionalAccess(PacketPtr pkt) +SimpleMemory::recvFunctional(PacketPtr pkt) { - functionalAccess(pkt); + pkt->pushLabel(SimpleTimingHandler::name()); + + if (!queue.checkFunctional(pkt)) { + // Default implementation of SimpleTimingPort::recvFunctional() + // calls recvAtomic() and throws away the latency; we can save a + // little here by just not calculating the latency. + functionalAccess(pkt); + } + + pkt->popLabel(); } BaseSlavePort & @@ -102,7 +112,7 @@ unsigned int SimpleMemory::drain(Event *de) { - int count = port.drain(de); + int count = port->drain(de); if (count) changeState(Draining); @@ -111,40 +121,14 @@ return count; } -SimpleMemory::MemoryPort::MemoryPort(const std::string& _name, - SimpleMemory& _memory) - : SimpleTimingPort(_name, &_memory), memory(_memory) -{ } - AddrRangeList -SimpleMemory::MemoryPort::getAddrRanges() const +SimpleMemory::getAddrRanges() const { AddrRangeList ranges; - ranges.push_back(memory.getAddrRange()); + ranges.push_back(getAddrRange()); return ranges; } -Tick -SimpleMemory::MemoryPort::recvAtomic(PacketPtr pkt) -{ - return memory.doAtomicAccess(pkt); -} - -void -SimpleMemory::MemoryPort::recvFunctional(PacketPtr pkt) -{ - pkt->pushLabel(memory.name()); - - if (!queue.checkFunctional(pkt)) { - // Default implementation of SimpleTimingPort::recvFunctional() - // calls recvAtomic() and throws away the latency; we can save a - // little here by just not calculating the latency. - memory.doFunctionalAccess(pkt); - } - - pkt->popLabel(); -} - SimpleMemory* SimpleMemoryParams::create() { diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/tport.hh --- a/src/mem/tport.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/tport.hh Tue Jul 17 19:06:02 2012 +0100 @@ -39,6 +39,7 @@ * * Authors: Ali Saidi * Andreas Hansson + * William Wang */ #ifndef __MEM_TPORT_HH__ @@ -47,17 +48,18 @@ /** * @file * - * Declaration of SimpleTimingPort. + * Declaration of SimpleTimingHandler. */ #include "mem/qport.hh" /** - * The simple timing port uses a queued port to implement + * The simple timing handler uses a queued slave handler to implement * recvFunctional and recvTimingReq through recvAtomic. It is always a * slave port. */ -class SimpleTimingPort : public QueuedSlavePort + +class SimpleTimingHandler : public QueuedSlaveHandler { private: @@ -91,19 +93,16 @@ public: /** - * Create a new SimpleTimingPort that relies on a packet queue to - * hold responses, and implements recvTimingReq and recvFunctional - * through calls to recvAtomic. Once a request arrives, it is - * passed to recvAtomic, and in the case of a timing access any - * response is scheduled to be sent after the delay of the atomic - * operation. + * Create a new SimpleTimingHandler that relies on a packet queue + * to hold responses, and implements recvTimingReq and + * recvFunctional through calls to recvAtomic. Once a request + * arrives, it is passed to recvAtomic, and in the case of a + * timing access any response is scheduled to be sent after the + * delay of the atomic operation. * - * @param name port name * @param owner structural owner */ - SimpleTimingPort(const std::string& name, MemObject* owner); - - virtual ~SimpleTimingPort() { } + SimpleTimingHandler(MemObject* _owner); }; diff -r b8abb27c5a88 -r 11e228ae7ed4 src/mem/tport.cc --- a/src/mem/tport.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/mem/tport.cc Tue Jul 17 19:06:02 2012 +0100 @@ -44,14 +44,13 @@ #include "mem/mem_object.hh" #include "mem/tport.hh" -SimpleTimingPort::SimpleTimingPort(const std::string& _name, - MemObject* _owner) : - QueuedSlavePort(_name, _owner, queueImpl), queueImpl(*_owner, *this) +SimpleTimingHandler::SimpleTimingHandler(MemObject* _owner) : + QueuedSlaveHandler(queueImpl), queueImpl(*_owner, *this) { } void -SimpleTimingPort::recvFunctional(PacketPtr pkt) +SimpleTimingHandler::recvFunctional(PacketPtr pkt) { if (!queue.checkFunctional(pkt)) { // do an atomic access and throw away the returned latency @@ -60,7 +59,7 @@ } bool -SimpleTimingPort::recvTimingReq(PacketPtr pkt) +SimpleTimingHandler::recvTimingReq(PacketPtr pkt) { /// @todo temporary hack to deal with memory corruption issue until /// 4-phase transactions are complete. Remove me later diff -r b8abb27c5a88 -r 11e228ae7ed4 src/sim/system.hh --- a/src/sim/system.hh Tue Jul 17 19:05:10 2012 +0100 +++ b/src/sim/system.hh Tue Jul 17 19:06:02 2012 +0100 @@ -78,23 +78,18 @@ * master for debug access and for non-structural entities that do * not have a port of their own. */ - class SystemPort : public MasterPort + class SystemHandler : public MasterInterface { - public: + protected: - /** - * Create a system port with a name and an owner. - */ - SystemPort(const std::string &_name, MemObject *_owner) - : MasterPort(_name, _owner) - { } bool recvTimingResp(PacketPtr pkt) { panic("SystemPort does not receive timing!\n"); return false; } void recvRetry() { panic("SystemPort does not expect retry!\n"); } }; - SystemPort _systemPort; + SystemHandler _systemHandler; + MasterPort _systemPort; public: diff -r b8abb27c5a88 -r 11e228ae7ed4 src/sim/system.cc --- a/src/sim/system.cc Tue Jul 17 19:05:10 2012 +0100 +++ b/src/sim/system.cc Tue Jul 17 19:06:02 2012 +0100 @@ -72,7 +72,8 @@ int System::numSystemsRunning = 0; System::System(Params *p) - : MemObject(p), _systemPort("system_port", this), + : MemObject(p), + _systemPort("system_port", this, _systemHandler), _numContexts(0), pagePtr(0), init_param(p->init_param),