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()
{
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();
// 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);
}
}
class CheckerCPU;
class ThreadContext;
class System;
-class Port;
namespace TheISA
{
};
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; }
/** 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; }
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);
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")
/*
+ * 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.
*
#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"
#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"
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)
{ }
_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),
{
cpu_params = params;
- resPool = new ResourcePool(this, params);
-
// Resize for Multithreading CPUs
thread.resize(numThreads);
}
}
- // 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);
resPool->init();
}
-Port*
-InOrderCPU::getPort(const std::string &if_name, int idx)
-{
- return resPool->getPort(if_name, idx);
-}
-
Fault
InOrderCPU::hwrei(ThreadID tid)
{
TheISA::TLB*
InOrderCPU::getITBPtr()
{
- CacheUnit *itb_res =
- dynamic_cast<CacheUnit*>(resPool->getResource(fetchPortIdx));
+ CacheUnit *itb_res = resPool->getInstUnit();
return itb_res->tlb();
}
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);
}
/*
+ * 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.
*
#include "sim/eventq.hh"
#include "sim/process.hh"
+class CacheUnit;
class ThreadContext;
class MemInterface;
class MemObject;
/* 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;
/** 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
{
CPUEventPri event_pri = InOrderCPU_Pri);
public:
+
+ /** Width (processing bandwidth) of each stage */
+ int stageWidth;
+
/** Interface between the CPU and CPU resources. */
ResourcePool *resPool;
/** 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];
}
};
+ 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. */
/** 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);
/** 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;
/** 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; }
/*
+ * 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.
*
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.
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));
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));
}
}
-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)
{
/*
+ * 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.
*
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.
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));
_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,
}
}
-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)
{
/*
+ * 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.
*
#ifndef __CPU_INORDER_RESOURCE_POOL_HH__
#define __CPU_INORDER_RESOURCE_POOL_HH__
-#include <list>
#include <string>
#include <vector>
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
+class CacheUnit;
class Event;
-class InOrderCPU;
-class Resource;
+class FetchUnit;
class ResourceEvent;
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 */
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;
}
#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;
}
-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();
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;
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;
};
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();
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);
protected:
/** Cache interface. */
- CachePort *cachePort;
+ Port *cachePort;
bool cachePortBlocked;
.prereq(miscRegfileWrites);
}
-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()
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.
*/
}
/** 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;
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);
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);
assert(retryTid != InvalidThreadID);
assert(fetchStatus[retryTid] == IcacheWaitRetry);
- if (cpu->getIcachePort()->sendTiming(retryPkt)) {
+ if (cpu->getInstPort().sendTiming(retryPkt)) {
fetchStatus[retryTid] = IcacheWaitResponse;
retryPkt = NULL;
retryTid = InvalidThreadID;
// Initialize the checker's dcache port here
#if USE_CHECKER
if (cpu->checker) {
- cpu->checker->setDcachePort(cpu->getDcachePort());
+ cpu->checker->setDcachePort(&cpu->getDataPort());
}
#endif
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());
}
}
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
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);
// forward declarations
class Checkpoint;
-class MemObject;
class Process;
class Processor;
class ThreadContext;
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()
{
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);
// (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);
}
AddrRangeIter iter;
bool found = false;
- Port* dataPort = tc->getCpuPtr()->getPort("dcache_port");
+ Port &dataPort = tc->getCpuPtr()->getDataPort();
- AddrRangeList resp = dataPort->getPeer()->getAddrRanges();
+ AddrRangeList resp = dataPort.getPeer()->getAddrRanges();
for (iter = resp.begin(); iter != resp.end(); iter++) {
if (*iter == (K0Seg2Phys(a0) & PAddrImplMask))
found = true;
using namespace TheISA;
FSTranslatingPortProxy::FSTranslatingPortProxy(ThreadContext *tc)
- : PortProxy(*(tc->getCpuPtr()->getPort("dcache_port"))), _tc(tc)
+ : PortProxy(tc->getCpuPtr()->getDataPort()), _tc(tc)
{
}