diff options
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/base.cc | 35 | ||||
-rw-r--r-- | src/cpu/base.hh | 35 | ||||
-rw-r--r-- | src/cpu/base_dyn_inst.hh | 2 | ||||
-rw-r--r-- | src/cpu/inorder/InOrderCPU.py | 3 | ||||
-rw-r--r-- | src/cpu/inorder/cpu.cc | 91 | ||||
-rw-r--r-- | src/cpu/inorder/cpu.hh | 78 | ||||
-rw-r--r-- | src/cpu/inorder/resource.hh | 6 | ||||
-rw-r--r-- | src/cpu/inorder/resource_pool.9stage.cc | 61 | ||||
-rw-r--r-- | src/cpu/inorder/resource_pool.cc | 86 | ||||
-rw-r--r-- | src/cpu/inorder/resource_pool.hh | 48 | ||||
-rw-r--r-- | src/cpu/inorder/resources/cache_unit.cc | 76 | ||||
-rw-r--r-- | src/cpu/inorder/resources/cache_unit.hh | 38 | ||||
-rw-r--r-- | src/cpu/o3/cpu.cc | 12 | ||||
-rw-r--r-- | src/cpu/o3/cpu.hh | 7 | ||||
-rw-r--r-- | src/cpu/o3/fetch_impl.hh | 8 | ||||
-rw-r--r-- | src/cpu/o3/iew_impl.hh | 2 | ||||
-rw-r--r-- | src/cpu/o3/lsq_impl.hh | 2 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 10 | ||||
-rw-r--r-- | src/cpu/simple/atomic.hh | 12 | ||||
-rw-r--r-- | src/cpu/simple/base.hh | 1 | ||||
-rw-r--r-- | src/cpu/simple/timing.cc | 11 | ||||
-rw-r--r-- | src/cpu/simple/timing.hh | 10 | ||||
-rw-r--r-- | src/cpu/thread_state.cc | 2 |
23 files changed, 305 insertions, 331 deletions
diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 276995da2..86edf62cf 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -296,6 +296,21 @@ BaseCPU::regStats() threadContexts[0]->regStats(name()); } +Port * +BaseCPU::getPort(const string &if_name, int idx) +{ + // Get the right port based on name. This applies to all the + // subclasses of the base CPU and relies on their implementation + // of getDataPort and getInstPort. In all cases there methods + // return a CpuPort pointer. + if (if_name == "dcache_port") + return &getDataPort(); + else if (if_name == "icache_port") + return &getInstPort(); + else + panic("CPU %s has no port named %s\n", name(), if_name); +} + Tick BaseCPU::nextCycle() { @@ -363,8 +378,8 @@ BaseCPU::switchOut() void BaseCPU::takeOverFrom(BaseCPU *oldCPU) { - Port *ic = getPort("icache_port"); - Port *dc = getPort("dcache_port"); + CpuPort &ic = getInstPort(); + CpuPort &dc = getDataPort(); assert(threadContexts.size() == oldCPU->threadContexts.size()); _cpuId = oldCPU->cpuId(); @@ -453,16 +468,16 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) // Connect new CPU to old CPU's memory only if new CPU isn't // connected to anything. Also connect old CPU's memory to new // CPU. - if (!ic->isConnected()) { - Port *peer = oldCPU->getPort("icache_port")->getPeer(); - ic->setPeer(peer); - peer->setPeer(ic); + if (!ic.isConnected()) { + Port *peer = oldCPU->getInstPort().getPeer(); + ic.setPeer(peer); + peer->setPeer(&ic); } - if (!dc->isConnected()) { - Port *peer = oldCPU->getPort("dcache_port")->getPeer(); - dc->setPeer(peer); - peer->setPeer(dc); + if (!dc.isConnected()) { + Port *peer = oldCPU->getDataPort().getPeer(); + dc.setPeer(peer); + peer->setPeer(&dc); } } diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 74c1a8762..8728a6e07 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -63,7 +63,6 @@ class BranchPred; class CheckerCPU; class ThreadContext; class System; -class Port; namespace TheISA { @@ -147,6 +146,23 @@ class BaseCPU : public MemObject }; public: + + /** + * Purely virtual method that returns a reference to the data + * port. All subclasses must implement this method. + * + * @return a reference to the data port + */ + virtual CpuPort &getDataPort() = 0; + + /** + * Purely virtual method that returns a reference to the instruction + * port. All subclasses must implement this method. + * + * @return a reference to the instruction port + */ + virtual CpuPort &getInstPort() = 0; + /** Reads this CPU's ID. */ int cpuId() { return _cpuId; } @@ -155,6 +171,23 @@ class BaseCPU : public MemObject /** Reads this CPU's unique instruction requestor ID */ MasterID instMasterId() { return _instMasterId; } + /** + * Get a port on this MemObject. This method is virtual to allow + * the subclasses of the BaseCPU to override it. All CPUs have a + * data and instruction port, but the Atomic CPU (in its current + * form) adds a port directly connected to the memory and has to + * override getPort. + * + * This method uses getDataPort and getInstPort to resolve the two + * ports. + * + * @param if_name the port name + * @param idx ignored index + * + * @return a pointer to the port with the given name + */ + virtual Port *getPort(const std::string &if_name, int idx = -1); + // Tick currentTick; inline Tick frequency() const { return SimClock::Frequency / clock; } inline Tick ticks(int numCycles) const { return clock * numCycles; } diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 882d5ba41..134725f70 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -975,7 +975,7 @@ BaseDynInst<Impl>::splitRequest(RequestPtr req, RequestPtr &sreqLow, RequestPtr &sreqHigh) { // Check to see if the request crosses the next level block boundary. - unsigned block_size = cpu->getDcachePort()->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 --git a/src/cpu/inorder/InOrderCPU.py b/src/cpu/inorder/InOrderCPU.py index 40af48b19..2dcd51d45 100644 --- a/src/cpu/inorder/InOrderCPU.py +++ b/src/cpu/inorder/InOrderCPU.py @@ -42,9 +42,6 @@ class InOrderCPU(BaseCPU): cachePorts = Param.Unsigned(2, "Cache Ports") stageWidth = Param.Unsigned(4, "Stage width") - fetchMemPort = Param.String("icache_port" , "Name of Memory Port to get instructions from") - dataMemPort = Param.String("dcache_port" , "Name of Memory Port to get data from") - fetchBuffSize = Param.Unsigned(4, "Fetch Buffer Size (Number of Cache Blocks Stored)") memBlockSize = Param.Unsigned(64, "Memory Block Size") diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 51d3cbe2f..84f5e3850 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2012 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2007 MIPS Technologies, Inc. * All rights reserved. * @@ -34,6 +46,7 @@ #include "arch/utility.hh" #include "base/bigint.hh" #include "config/the_isa.hh" +#include "cpu/inorder/resources/cache_unit.hh" #include "cpu/inorder/resources/resource_list.hh" #include "cpu/inorder/cpu.hh" #include "cpu/inorder/first_stage.hh" @@ -50,10 +63,11 @@ #include "cpu/thread_context.hh" #include "debug/Activity.hh" #include "debug/InOrderCPU.hh" +#include "debug/InOrderCachePort.hh" #include "debug/Interrupt.hh" +#include "debug/Quiesce.hh" #include "debug/RefCount.hh" #include "debug/SkedCache.hh" -#include "debug/Quiesce.hh" #include "params/InOrderCPU.hh" #include "sim/full_system.hh" #include "sim/process.hh" @@ -68,6 +82,34 @@ using namespace std; using namespace TheISA; using namespace ThePipeline; +InOrderCPU::CachePort::CachePort(CacheUnit *_cacheUnit) : + CpuPort(_cacheUnit->name() + "-cache-port", _cacheUnit->cpu), + cacheUnit(_cacheUnit) +{ } + +bool +InOrderCPU::CachePort::recvTiming(Packet *pkt) +{ + if (pkt->isError()) + DPRINTF(InOrderCachePort, "Got error packet back for address: %x\n", + pkt->getAddr()); + else if (pkt->isResponse()) + cacheUnit->processCacheCompletion(pkt); + else { + //@note: depending on consistency model, update here + DPRINTF(InOrderCachePort, "Received snoop pkt %x,Ignoring\n", + pkt->getAddr()); + } + + return true; +} + +void +InOrderCPU::CachePort::recvRetry() +{ + cacheUnit->recvRetry(); +} + InOrderCPU::TickEvent::TickEvent(InOrderCPU *c) : Event(CPU_Tick_Pri), cpu(c) { } @@ -191,7 +233,10 @@ InOrderCPU::InOrderCPU(Params *params) _status(Idle), tickEvent(this), stageWidth(params->stageWidth), + resPool(new ResourcePool(this, params)), timeBuffer(2 , 2), + dataPort(resPool->getDataUnit()), + instPort(resPool->getInstUnit()), removeInstsThisCycle(false), activityRec(params->name, NumStages, 10, params->activity), system(params->system), @@ -207,8 +252,6 @@ InOrderCPU::InOrderCPU(Params *params) { cpu_params = params; - resPool = new ResourcePool(this, params); - // Resize for Multithreading CPUs thread.resize(numThreads); @@ -240,17 +283,6 @@ InOrderCPU::InOrderCPU(Params *params) } } - // Bind the fetch & data ports from the resource pool. - fetchPortIdx = resPool->getPortIdx(params->fetchMemPort); - if (fetchPortIdx == 0) { - fatal("Unable to find port to fetch instructions from.\n"); - } - - dataPortIdx = resPool->getPortIdx(params->dataMemPort); - if (dataPortIdx == 0) { - fatal("Unable to find port for data.\n"); - } - for (ThreadID tid = 0; tid < numThreads; ++tid) { pc[tid].set(0); lastCommittedPC[tid].set(0); @@ -775,12 +807,6 @@ InOrderCPU::init() resPool->init(); } -Port* -InOrderCPU::getPort(const std::string &if_name, int idx) -{ - return resPool->getPort(if_name, idx); -} - Fault InOrderCPU::hwrei(ThreadID tid) { @@ -1735,8 +1761,7 @@ InOrderCPU::syscall(int64_t callnum, ThreadID tid) TheISA::TLB* InOrderCPU::getITBPtr() { - CacheUnit *itb_res = - dynamic_cast<CacheUnit*>(resPool->getResource(fetchPortIdx)); + CacheUnit *itb_res = resPool->getInstUnit(); return itb_res->tlb(); } @@ -1744,38 +1769,26 @@ InOrderCPU::getITBPtr() TheISA::TLB* InOrderCPU::getDTBPtr() { - CacheUnit *dtb_res = - dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx)); - return dtb_res->tlb(); + return resPool->getDataUnit()->tlb(); } Decoder * InOrderCPU::getDecoderPtr() { - FetchUnit *fetch_res = - dynamic_cast<FetchUnit*>(resPool->getResource(fetchPortIdx)); - return &fetch_res->decoder; + return &resPool->getInstUnit()->decoder; } Fault InOrderCPU::read(DynInstPtr inst, Addr addr, uint8_t *data, unsigned size, unsigned flags) { - //@TODO: Generalize name "CacheUnit" to "MemUnit" just in case - // you want to run w/out caches? - CacheUnit *cache_res = - dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx)); - - return cache_res->read(inst, addr, data, size, flags); + return resPool->getDataUnit()->read(inst, addr, data, size, flags); } Fault InOrderCPU::write(DynInstPtr inst, uint8_t *data, unsigned size, Addr addr, unsigned flags, uint64_t *write_res) { - //@TODO: Generalize name "CacheUnit" to "MemUnit" just in case - // you want to run w/out caches? - CacheUnit *cache_res = - dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx)); - return cache_res->write(inst, data, size, addr, flags, write_res); + return resPool->getDataUnit()->write(inst, data, size, addr, flags, + write_res); } diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 5e336fd5a..d8fe5c057 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2012 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2007 MIPS Technologies, Inc. * All rights reserved. * @@ -61,6 +73,7 @@ #include "sim/eventq.hh" #include "sim/process.hh" +class CacheUnit; class ThreadContext; class MemInterface; class MemObject; @@ -96,6 +109,12 @@ class InOrderCPU : public BaseCPU /* 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; @@ -132,6 +151,31 @@ class InOrderCPU : public BaseCPU /** Overall CPU status. */ Status _status; private: + + /** + * CachePort class for the in-order CPU, interacting with a + * specific CacheUnit in the pipeline. + */ + class CachePort : public CpuPort + { + + private: + /** Pointer to cache unit */ + CacheUnit *cacheUnit; + + public: + /** Default constructor. */ + CachePort(CacheUnit *_cacheUnit); + + protected: + + /** Timing version of receive */ + bool recvTiming(PacketPtr pkt); + + /** Handles doing a retry of a failed timing request. */ + void recvRetry(); + }; + /** Define TickEvent for the CPU */ class TickEvent : public Event { @@ -244,6 +288,10 @@ class InOrderCPU : public BaseCPU CPUEventPri event_pri = InOrderCPU_Pri); public: + + /** Width (processing bandwidth) of each stage */ + int stageWidth; + /** Interface between the CPU and CPU resources. */ ResourcePool *resPool; @@ -257,22 +305,9 @@ class InOrderCPU : public BaseCPU /** Used by resources to signify a denied access to a resource. */ ResourceRequest *dummyReq[ThePipeline::MaxThreads]; - /** Identifies the resource id that identifies a fetch - * access unit. - */ - unsigned fetchPortIdx; - - /** Identifies the resource id that identifies a data - * access unit. - */ - unsigned dataPortIdx; - /** The Pipeline Stages for the CPU */ PipelineStage *pipelineStage[ThePipeline::NumStages]; - /** Width (processing bandwidth) of each stage */ - int stageWidth; - /** Program Counters */ TheISA::PCState pc[ThePipeline::MaxThreads]; @@ -396,6 +431,14 @@ class InOrderCPU : public BaseCPU } }; + private: + + /** Data port. Note that it has to appear after the resPool. */ + CachePort dataPort; + + /** Instruction port. Note that it has to appear after the resPool. */ + CachePort instPort; + public: /** Registers statistics. */ @@ -409,9 +452,6 @@ class InOrderCPU : public BaseCPU /** Initialize the CPU */ void init(); - /** Get a Memory Port */ - Port* getPort(const std::string &if_name, int idx = 0); - /** HW return from error interrupt. */ Fault hwrei(ThreadID tid); @@ -811,12 +851,6 @@ class InOrderCPU : public BaseCPU /** Pointers to all of the threads in the CPU. */ std::vector<Thread *> thread; - /** Pointer to the icache interface. */ - MemInterface *icacheInterface; - - /** Pointer to the dcache interface. */ - MemInterface *dcacheInterface; - /** Whether or not the CPU should defer its registration. */ bool deferRegistration; diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh index 972925d94..8822a3620 100644 --- a/src/cpu/inorder/resource.hh +++ b/src/cpu/inorder/resource.hh @@ -70,12 +70,6 @@ class Resource { /** Return name of this resource */ virtual std::string name(); - /** Define this function if resource, has a port to connect to an outside - * simulation object. - */ - virtual Port* getPort(const std::string &if_name, int idx) - { return NULL; } - /** Return ID for this resource */ int getId() { return id; } diff --git a/src/cpu/inorder/resource_pool.9stage.cc b/src/cpu/inorder/resource_pool.9stage.cc index e0a00ee0f..d231aafba 100644 --- a/src/cpu/inorder/resource_pool.9stage.cc +++ b/src/cpu/inorder/resource_pool.9stage.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2012 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2007 MIPS Technologies, Inc. * All rights reserved. * @@ -39,7 +51,7 @@ using namespace std; using namespace ThePipeline; ResourcePool::ResourcePool(InOrderCPU *_cpu, InOrderCPUParams *params) - : cpu(_cpu) + : cpu(_cpu), instUnit(NULL), dataUnit(NULL) { //@todo: use this function to instantiate the resources in resource pool. This will help in the //auto-generation of this pipeline model. @@ -53,9 +65,13 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, InOrderCPUParams *params) resources.push_back(new TLBUnit("itlb", ITLB, StageWidth, 0, _cpu, params)); - memObjects.push_back(ICache); - resources.push_back(new CacheUnit("icache_port", ICache, - StageWidth * MaxThreads, 0, _cpu, params)); + + // Keep track of the instruction fetch unit so we can easily + // provide a pointer to it in the CPU. + instUnit = new FetchUnit("icache_port", ICache, + StageWidth * MaxThreads, 0, _cpu, + params); + resources.push_back(instUnit); resources.push_back(new DecodeUnit("decode_unit", Decode, StageWidth, 0, _cpu, params)); @@ -84,9 +100,12 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, InOrderCPUParams *params) resources.push_back(new TLBUnit("dtlb", DTLB, StageWidth, 0, _cpu, params)); - memObjects.push_back(DCache); - resources.push_back(new CacheUnit("dcache_port", DCache, - StageWidth * MaxThreads, 0, _cpu, params)); + // Keep track of the data load/store unit so we can easily provide + // a pointer to it in the CPU. + dataUnit = new CacheUnit("dcache_port", DCache, + StageWidth * MaxThreads, 0, _cpu, + params); + resources.push_back(dataUnit); resources.push_back(new GraduationUnit("graduation_unit", Grad, StageWidth * MaxThreads, 0, _cpu, params)); @@ -119,34 +138,6 @@ ResourcePool::regStats() } } -Port * -ResourcePool::getPort(const std::string &if_name, int idx) -{ - for (int i = 0; i < memObjects.size(); i++) { - int obj_idx = memObjects[i]; - Port *port = resources[obj_idx]->getPort(if_name, idx); - if (port != NULL) { - return port; - } - } - - return NULL; -} - -unsigned -ResourcePool::getPortIdx(const std::string &port_name) -{ - for (int i = 0; i < memObjects.size(); i++) { - unsigned obj_idx = memObjects[i]; - Port *port = resources[obj_idx]->getPort(port_name, obj_idx); - if (port != NULL) { - return obj_idx; - } - } - - return 0; -} - ResReqPtr ResourcePool::request(int res_idx, DynInstPtr inst) { diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc index 50d667ea7..4c01165b8 100644 --- a/src/cpu/inorder/resource_pool.cc +++ b/src/cpu/inorder/resource_pool.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2012 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2007 MIPS Technologies, Inc. * All rights reserved. * @@ -40,7 +52,7 @@ using namespace std; using namespace ThePipeline; ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params) - : cpu(_cpu) + : cpu(_cpu), instUnit(NULL), dataUnit(NULL) { //@todo: use this function to instantiate the resources in resource pool. //This will help in the auto-generation of this pipeline model. @@ -54,10 +66,12 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params) resources.push_back(new FetchSeqUnit("fetch_seq_unit", FetchSeq, stage_width * 2, 0, _cpu, params)); - memObjects.push_back(ICache); - resources.push_back(new FetchUnit("icache_port", ICache, - stage_width * 2 + MaxThreads, 0, _cpu, - params)); + // Keep track of the instruction fetch unit so we can easily + // provide a pointer to it in the CPU. + instUnit = new FetchUnit("icache_port", ICache, + stage_width * 2 + MaxThreads, 0, _cpu, + params); + resources.push_back(instUnit); resources.push_back(new DecodeUnit("decode_unit", Decode, stage_width, 0, _cpu, params)); @@ -84,10 +98,12 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params) _cpu, params)); - memObjects.push_back(DCache); - resources.push_back(new CacheUnit("dcache_port", DCache, - stage_width * 2 + MaxThreads, 0, _cpu, - params)); + // Keep track of the data load/store unit so we can easily provide + // a pointer to it in the CPU. + dataUnit = new CacheUnit("dcache_port", DCache, + stage_width * 2 + MaxThreads, 0, _cpu, + params); + resources.push_back(dataUnit); gradObjects.push_back(BPred); resources.push_back(new GraduationUnit("graduation_unit", Grad, @@ -151,58 +167,6 @@ ResourcePool::regStats() } } -Port * -ResourcePool::getPort(const std::string &if_name, int idx) -{ - DPRINTF(Resource, "Binding %s in Resource Pool.\n", if_name); - - for (int i = 0; i < memObjects.size(); i++) { - int obj_idx = memObjects[i]; - Port *port = resources[obj_idx]->getPort(if_name, idx); - if (port != NULL) { - DPRINTF(Resource, "%s set to resource %s(#%i) in Resource Pool.\n", - if_name, resources[obj_idx]->name(), obj_idx); - return port; - } - } - - return NULL; -} - -unsigned -ResourcePool::getPortIdx(const std::string &port_name) -{ - DPRINTF(Resource, "Finding Port Idx for %s.\n", port_name); - - for (int i = 0; i < memObjects.size(); i++) { - unsigned obj_idx = memObjects[i]; - Port *port = resources[obj_idx]->getPort(port_name, obj_idx); - if (port != NULL) { - DPRINTF(Resource, "Returning Port Idx %i for %s.\n", obj_idx, - port_name); - return obj_idx; - } - } - - return 0; -} - -unsigned -ResourcePool::getResIdx(const std::string &res_name) -{ - DPRINTF(Resource, "Finding Resource Idx for %s.\n", res_name); - - int num_resources = resources.size(); - - for (int idx = 0; idx < num_resources; idx++) { - if (resources[idx]->name() == res_name) - return idx; - } - - panic("Can't find resource idx for: %s\n", res_name); - return 0; -} - unsigned ResourcePool::getResIdx(const ThePipeline::ResourceId &res_id) { diff --git a/src/cpu/inorder/resource_pool.hh b/src/cpu/inorder/resource_pool.hh index 4f05494c4..9e0952236 100644 --- a/src/cpu/inorder/resource_pool.hh +++ b/src/cpu/inorder/resource_pool.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2012 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2007 MIPS Technologies, Inc. * All rights reserved. * @@ -32,7 +44,6 @@ #ifndef __CPU_INORDER_RESOURCE_POOL_HH__ #define __CPU_INORDER_RESOURCE_POOL_HH__ -#include <list> #include <string> #include <vector> @@ -46,9 +57,9 @@ #include "sim/eventq.hh" #include "sim/sim_object.hh" +class CacheUnit; class Event; -class InOrderCPU; -class Resource; +class FetchUnit; class ResourceEvent; class ResourcePool { @@ -142,14 +153,7 @@ class ResourcePool { /** Register Statistics in All Resources */ void regStats(); - /** Returns a specific port. */ - Port* getPort(const std::string &if_name, int idx); - - /** Returns a specific port. */ - unsigned getPortIdx(const std::string &port_name); - /** Returns a specific resource. */ - unsigned getResIdx(const std::string &res_name); unsigned getResIdx(const ThePipeline::ResourceId &res_id); /** Returns a pointer to a resource */ @@ -215,11 +219,29 @@ class ResourcePool { DynInstPtr dummyInst[ThePipeline::MaxThreads]; + /** + * Get a pointer to the (always present) instruction fetch unit. + * + * @return the instruction unit + */ + FetchUnit *getInstUnit() const { return instUnit; } + + /** + * Get a pointer to the (always present) data load/store unit. + * + * @return the data cache unit + */ + CacheUnit *getDataUnit() const { return dataUnit; } + private: - std::vector<Resource *> resources; - /** Resources that interface with memory objects */ - std::vector<int> memObjects; + /** The instruction fetch unit. */ + FetchUnit *instUnit; + + /** The data load/store unit. */ + CacheUnit *dataUnit; + + std::vector<Resource *> resources; /** Resources that need to be updated on an inst. graduation */ std::vector<int> gradObjects; diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 33bd9e619..10046f7f2 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -67,62 +67,23 @@ printMemData(uint8_t *data, unsigned size) } #endif -Tick -CacheUnit::CachePort::recvAtomic(PacketPtr pkt) -{ - panic("%s doesn't expect recvAtomic callback!", cachePortUnit->name()); - return curTick(); -} - -void -CacheUnit::CachePort::recvFunctional(PacketPtr pkt) -{ - DPRINTF(InOrderCachePort, "Doesn't update state on a recvFunctional." - "Ignoring packet for %x.\n", pkt->getAddr()); -} - -void -CacheUnit::CachePort::recvRangeChange() -{ -} - -bool -CacheUnit::CachePort::recvTiming(Packet *pkt) -{ - if (pkt->isError()) - DPRINTF(InOrderCachePort, "Got error packet back for address: %x\n", - pkt->getAddr()); - else if (pkt->isResponse()) - cachePortUnit->processCacheCompletion(pkt); - else { - //@note: depending on consistency model, update here - DPRINTF(InOrderCachePort, "Received snoop pkt %x,Ignoring\n", pkt->getAddr()); - } - - return true; -} - -void -CacheUnit::CachePort::recvRetry() -{ - cachePortUnit->recvRetry(); -} - CacheUnit::CacheUnit(string res_name, int res_id, int res_width, int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) : Resource(res_name, res_id, res_width, res_latency, _cpu), - cachePortBlocked(false) + cachePort(NULL), cachePortBlocked(false) { - cachePort = new CachePort(this); - // Hard-Code Selection For Now - if (res_name == "icache_port") + if (res_id == ICache) _tlb = params->itb; - else if (res_name == "dcache_port") + else if (res_id == DCache) _tlb = params->dtb; else fatal("Unrecognized TLB name passed by user"); + // Note that the CPU port is not yet instantiated (as it is done + // after the resource pool), we delay setting the cachePort + // pointer until init(). + for (int i=0; i < MaxThreads; i++) { tlbBlocked[i] = false; tlbBlockSeqNum[i] = 0; @@ -136,23 +97,22 @@ CacheUnit::tlb() } -Port * -CacheUnit::getPort(const string &if_name, int idx) -{ - if (if_name == resName) - return cachePort; - else - return NULL; -} - void CacheUnit::init() { + // Get the appropriate port from the CPU based on the resource name. + if (id == ICache) { + cachePort = &cpu->getInstPort(); + } else if (id == DCache) { + cachePort = &cpu->getDataPort(); + } + assert(cachePort != NULL); + for (int i = 0; i < width; i++) { reqs[i] = new CacheRequest(this); } - cacheBlkSize = this->cachePort->peerBlockSize(); + cacheBlkSize = cachePort->peerBlockSize(); cacheBlkMask = cacheBlkSize - 1; initSlots(); @@ -446,7 +406,7 @@ CacheUnit::read(DynInstPtr inst, Addr addr, assert(cache_req && "Can't Find Instruction for Read!"); // The block size of our peer - unsigned blockSize = this->cachePort->peerBlockSize(); + unsigned blockSize = cacheBlkSize; //The size of the data we're trying to read. int fullSize = size; @@ -541,7 +501,7 @@ CacheUnit::write(DynInstPtr inst, uint8_t *data, unsigned size, assert(cache_req && "Can't Find Instruction for Write!"); // The block size of our peer - unsigned blockSize = this->cachePort->peerBlockSize(); + unsigned blockSize = cacheBlkSize; //The size of the data we're trying to write. int fullSize = size; diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh index 416cb76d1..d9f98e42c 100644 --- a/src/cpu/inorder/resources/cache_unit.hh +++ b/src/cpu/inorder/resources/cache_unit.hh @@ -73,39 +73,6 @@ class CacheUnit : public Resource }; public: - /** CachePort class for the Cache Unit. Handles doing the - * communication with the cache/memory. - */ - class CachePort : public Port - { - protected: - /** Pointer to cache port unit */ - CacheUnit *cachePortUnit; - - public: - /** Default constructor. */ - CachePort(CacheUnit *_cachePortUnit) - : Port(_cachePortUnit->name() + "-cache-port", - (MemObject*)_cachePortUnit->cpu), - cachePortUnit(_cachePortUnit) - { } - - protected: - /** Atomic version of receive. Panics. */ - Tick recvAtomic(PacketPtr pkt); - - /** Functional version of receive.*/ - void recvFunctional(PacketPtr pkt); - - /** Receives range changes. */ - void recvRangeChange(); - - /** Timing version of receive */ - bool recvTiming(PacketPtr pkt); - - /** Handles doing a retry of a failed fetch. */ - void recvRetry(); - }; void init(); @@ -149,9 +116,6 @@ class CacheUnit : public Resource void trap(Fault fault, ThreadID tid, DynInstPtr inst); void recvRetry(); - - /** Returns a specific port. */ - Port *getPort(const std::string &if_name, int idx); Fault read(DynInstPtr inst, Addr addr, uint8_t *data, unsigned size, unsigned flags); @@ -175,7 +139,7 @@ class CacheUnit : public Resource protected: /** Cache interface. */ - CachePort *cachePort; + Port *cachePort; bool cachePortBlocked; diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 82f17adc9..7f24ee988 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -578,18 +578,6 @@ FullO3CPU<Impl>::regStats() } template <class Impl> -Port * -FullO3CPU<Impl>::getPort(const std::string &if_name, int idx) -{ - if (if_name == "dcache_port") - return &dcachePort; - else if (if_name == "icache_port") - return &icachePort; - else - panic("No Such Port\n"); -} - -template <class Impl> void FullO3CPU<Impl>::tick() { diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 1c713097a..f48c0f0f2 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -361,9 +361,6 @@ class FullO3CPU : public BaseO3CPU this->dtb->demapPage(vaddr, asn); } - /** Returns a specific port. */ - Port *getPort(const std::string &if_name, int idx); - /** Ticks CPU, calling tick() on each stage, and checking the overall * activity to see if the CPU should deschedule itself. */ @@ -781,10 +778,10 @@ class FullO3CPU : public BaseO3CPU } /** Used by the fetch unit to get a hold of the instruction port. */ - Port* getIcachePort() { return &icachePort; } + virtual CpuPort &getInstPort() { return icachePort; } /** Get the dcache port (used to find block size for translations). */ - Port* getDcachePort() { return &dcachePort; } + virtual CpuPort &getDataPort() { return dcachePort; } Addr lockAddr; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 3dca6e8ba..1271ea481 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -335,10 +335,10 @@ template<class Impl> void DefaultFetch<Impl>::setIcache() { - assert(cpu->getIcachePort()->isConnected()); + assert(cpu->getInstPort().isConnected()); // Size of cache block. - cacheBlkSize = cpu->getIcachePort()->peerBlockSize(); + cacheBlkSize = cpu->getInstPort().peerBlockSize(); // Create mask to get rid of offset bits. cacheBlkMask = (cacheBlkSize - 1); @@ -623,7 +623,7 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req) fetchedCacheLines++; // Access the cache. - if (!cpu->getIcachePort()->sendTiming(data_pkt)) { + if (!cpu->getInstPort().sendTiming(data_pkt)) { assert(retryPkt == NULL); assert(retryTid == InvalidThreadID); DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); @@ -1358,7 +1358,7 @@ DefaultFetch<Impl>::recvRetry() assert(retryTid != InvalidThreadID); assert(fetchStatus[retryTid] == IcacheWaitRetry); - if (cpu->getIcachePort()->sendTiming(retryPkt)) { + if (cpu->getInstPort().sendTiming(retryPkt)) { fetchStatus[retryTid] = IcacheWaitResponse; retryPkt = NULL; retryTid = InvalidThreadID; diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index 97b41ad9f..209ad317b 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -302,7 +302,7 @@ DefaultIEW<Impl>::initStage() // Initialize the checker's dcache port here #if USE_CHECKER if (cpu->checker) { - cpu->checker->setDcachePort(cpu->getDcachePort()); + cpu->checker->setDcachePort(&cpu->getDataPort()); } #endif diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index f1642be9c..02758f212 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -111,7 +111,7 @@ LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) for (ThreadID tid = 0; tid < numThreads; tid++) { thread[tid].init(cpu, iew_ptr, params, this, maxLQEntries, maxSQEntries, tid); - thread[tid].setDcachePort(cpu_ptr->getDcachePort()); + thread[tid].setDcachePort(&cpu_ptr->getDataPort()); } } diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 4b243e862..cc2c3576f 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -68,16 +68,12 @@ AtomicSimpleCPU::TickEvent::description() const Port * AtomicSimpleCPU::getPort(const string &if_name, int idx) { - if (if_name == "dcache_port") - return &dcachePort; - else if (if_name == "icache_port") - return &icachePort; - else if (if_name == "physmem_port") { + if (if_name == "physmem_port") { hasPhysMemPort = true; return &physmemPort; + } else { + return BaseCPU::getPort(if_name, idx); } - else - panic("No Such Port\n"); } void diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index f677ed49b..8a1c9000f 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -101,8 +101,20 @@ class AtomicSimpleCPU : public BaseSimpleCPU Range<Addr> physMemAddr; + 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: + /** + * Override the getPort of the BaseCPU so that we can provide a pointer + * to the physmemPort, unique to the Atomic CPU. + */ virtual Port *getPort(const std::string &if_name, int idx = -1); virtual void serialize(std::ostream &os); diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 4c02e2eb0..4b73a4519 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -67,7 +67,6 @@ // forward declarations class Checkpoint; -class MemObject; class Process; class Processor; class ThreadContext; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index d71a96580..3d1fe081d 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -60,17 +60,6 @@ using namespace std; using namespace TheISA; -Port * -TimingSimpleCPU::getPort(const std::string &if_name, int idx) -{ - if (if_name == "dcache_port") - return &dcachePort; - else if (if_name == "icache_port") - return &icachePort; - else - panic("No Such Port\n"); -} - void TimingSimpleCPU::init() { diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index ed91524cf..e0c5c89f7 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -231,9 +231,15 @@ class TimingSimpleCPU : public BaseSimpleCPU Tick previousTick; - public: + protected: + + /** Return a reference to the data port. */ + virtual CpuPort &getDataPort() { return dcachePort; } - virtual Port *getPort(const std::string &if_name, int idx = -1); + /** Return a reference to the instruction port. */ + virtual CpuPort &getInstPort() { return icachePort; } + + public: virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 86e552afb..33c0d719c 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -106,7 +106,7 @@ ThreadState::initMemProxies(ThreadContext *tc) // (i.e. due to restoring from a checkpoint and later switching // in. if (physProxy == NULL) - physProxy = new PortProxy(*baseCpu->getPort("dcache_port")); + physProxy = new PortProxy(baseCpu->getDataPort()); if (virtProxy == NULL) virtProxy = new FSTranslatingPortProxy(tc); } |