summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/base.cc35
-rw-r--r--src/cpu/base.hh35
-rw-r--r--src/cpu/base_dyn_inst.hh2
-rw-r--r--src/cpu/inorder/InOrderCPU.py3
-rw-r--r--src/cpu/inorder/cpu.cc91
-rw-r--r--src/cpu/inorder/cpu.hh78
-rw-r--r--src/cpu/inorder/resource.hh6
-rw-r--r--src/cpu/inorder/resource_pool.9stage.cc61
-rw-r--r--src/cpu/inorder/resource_pool.cc86
-rw-r--r--src/cpu/inorder/resource_pool.hh48
-rw-r--r--src/cpu/inorder/resources/cache_unit.cc76
-rw-r--r--src/cpu/inorder/resources/cache_unit.hh38
-rw-r--r--src/cpu/o3/cpu.cc12
-rw-r--r--src/cpu/o3/cpu.hh7
-rw-r--r--src/cpu/o3/fetch_impl.hh8
-rw-r--r--src/cpu/o3/iew_impl.hh2
-rw-r--r--src/cpu/o3/lsq_impl.hh2
-rw-r--r--src/cpu/simple/atomic.cc10
-rw-r--r--src/cpu/simple/atomic.hh12
-rw-r--r--src/cpu/simple/base.hh1
-rw-r--r--src/cpu/simple/timing.cc11
-rw-r--r--src/cpu/simple/timing.hh10
-rw-r--r--src/cpu/thread_state.cc2
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 &section);
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);
}