tracer = Param.InstTracer(default_tracer, "Instruction tracer")
- _cached_ports = []
+ icache_port = Port("Instruction Port")
+ dcache_port = Port("Data Port")
+ _cached_ports = ['icache_port', 'dcache_port']
+
if buildEnv['TARGET_ISA'] in ['x86', 'arm'] and buildEnv['FULL_SYSTEM']:
- _cached_ports = ["itb.walker.port", "dtb.walker.port"]
+ _cached_ports += ["itb.walker.port", "dtb.walker.port"]
_uncached_ports = []
if buildEnv['TARGET_ISA'] == 'x86' and buildEnv['FULL_SYSTEM']:
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* Copyright (c) 2011 Regents of the University of California
* All rights reserved.
functionEntryTick = curTick();
}
}
+
+bool
+BaseCPU::CpuPort::recvTiming(PacketPtr pkt)
+{
+ panic("BaseCPU doesn't expect recvTiming callback!");
+ return true;
+}
+
+void
+BaseCPU::CpuPort::recvRetry()
+{
+ panic("BaseCPU doesn't expect recvRetry callback!");
+}
+
+Tick
+BaseCPU::CpuPort::recvAtomic(PacketPtr pkt)
+{
+ panic("BaseCPU doesn't expect recvAtomic callback!");
+ return curTick();
+}
+
+void
+BaseCPU::CpuPort::recvFunctional(PacketPtr pkt)
+{
+ // No internal storage to update (in the general case). In the
+ // long term this should never be called, but that assumed a split
+ // into master/slave and request/response.
+}
+
+void
+BaseCPU::CpuPort::recvStatusChange(Status status)
+{
+ if (status == RangeChange) {
+ if (!snoopRangeSent) {
+ snoopRangeSent = true;
+ sendStatusChange(Port::RangeChange);
+ }
+ return;
+ }
+
+ panic("BaseCPU doesn't expect recvStatusChange callback!");
+}
+
+void
+BaseCPU::CpuPort::getDeviceAddressRanges(AddrRangeList& resp,
+ bool& snoop)
+{
+ resp.clear();
+ snoop = false;
+}
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* Copyright (c) 2011 Regents of the University of California
* All rights reserved.
// therefore no setCpuId() method is provided
int _cpuId;
+ /**
+ * Define a base class for the CPU ports (instruction and data)
+ * that is refined in the subclasses. This class handles the
+ * common cases, i.e. the functional accesses and the status
+ * changes and address range queries. The default behaviour for
+ * both atomic and timing access is to panic and the corresponding
+ * subclasses have to override these methods.
+ */
+ class CpuPort : public Port
+ {
+ public:
+
+ /**
+ * Create a CPU port with a name and a structural owner.
+ *
+ * @param _name port name including the owner
+ * @param _name structural owner of this port
+ */
+ CpuPort(const std::string& _name, MemObject* _owner) :
+ Port(_name, _owner), snoopRangeSent(false)
+ { }
+
+ protected:
+
+ virtual bool recvTiming(PacketPtr pkt);
+
+ virtual Tick recvAtomic(PacketPtr pkt);
+
+ virtual void recvRetry();
+
+ void recvFunctional(PacketPtr pkt);
+
+ void recvStatusChange(Status status);
+
+ /**
+ * Add CPU ports are master ports and do not respond to any
+ * address ranges. Note that the LSQ snoops for specific ISAs
+ * and thus has to override this method.
+ *
+ * @param resp list of ranges this port responds to
+ * @param snoop indicating if the port snoops or not
+ */
+ virtual void getDeviceAddressRanges(AddrRangeList& resp,
+ bool& snoop);
+
+ private:
+
+ bool snoopRangeSent;
+
+ };
+
public:
/** Reads this CPU's ID. */
int cpuId() { return _cpuId; }
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")
- icache_port = Port("Instruction Port")
- dcache_port = Port("Data Port")
- _cached_ports = ['icache_port', 'dcache_port']
fetchBuffSize = Param.Unsigned(4, "Fetch Buffer Size (Number of Cache Blocks Stored)")
memBlockSize = Param.Unsigned(64, "Memory Block Size")
checker.dtb = Parent.dtb
cachePorts = Param.Unsigned(200, "Cache Ports")
- icache_port = Port("Instruction Port")
- dcache_port = Port("Data Port")
- _cached_ports = BaseCPU._cached_ports + ['icache_port', 'dcache_port']
decodeToFetchDelay = Param.Unsigned(1, "Decode to fetch delay")
renameToFetchDelay = Param.Unsigned(1 ,"Rename to fetch delay")
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* Copyright (c) 2011 Regents of the University of California
* All rights reserved.
BaseCPU::regStats();
}
+template<class Impl>
+bool
+FullO3CPU<Impl>::IcachePort::recvTiming(PacketPtr pkt)
+{
+ DPRINTF(O3CPU, "Fetch unit received timing\n");
+ if (pkt->isResponse()) {
+ // We shouldn't ever get a block in ownership state
+ assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted()));
+
+ fetch->processCacheCompletion(pkt);
+ }
+ //else Snooped a coherence request, just return
+ return true;
+}
+
+template<class Impl>
+void
+FullO3CPU<Impl>::IcachePort::recvRetry()
+{
+ fetch->recvRetry();
+}
+
+template <class Impl>
+bool
+FullO3CPU<Impl>::DcachePort::recvTiming(PacketPtr pkt)
+{
+ return lsq->recvTiming(pkt);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::DcachePort::recvRetry()
+{
+ lsq->recvRetry();
+}
+
template <class Impl>
FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
: Event(CPU_Tick_Pri), cpu(c)
TheISA::NumMiscRegs * numThreads,
TheISA::ZeroReg),
+ icachePort(&fetch, this),
+ dcachePort(&iew.ldstQueue, this),
+
timeBuffer(params->backComSize, params->forwardComSize),
fetchQueue(params->backComSize, params->forwardComSize),
decodeQueue(params->backComSize, params->forwardComSize),
if (params->checker) {
BaseCPU *temp_checker = params->checker;
checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
+ checker->setIcachePort(&icachePort);
#if FULL_SYSTEM
checker->setSystem(params->system);
#endif
FullO3CPU<Impl>::getPort(const std::string &if_name, int idx)
{
if (if_name == "dcache_port")
- return iew.getDcachePort();
+ return &dcachePort;
else if (if_name == "icache_port")
- return fetch.getIcachePort();
+ return &icachePort;
else
panic("No Such Port\n");
}
for (ThreadID tid = 0; tid < numThreads; ++tid)
thread[tid]->inSyscall = true;
+ // this CPU could still be unconnected if we are restoring from a
+ // checkpoint and this CPU is to be switched in, thus we can only
+ // do this here if the instruction port is actually connected, if
+ // not we have to do it as part of takeOverFrom
+ if (icachePort.isConnected())
+ fetch.setIcache();
+
#if FULL_SYSTEM
for (ThreadID tid = 0; tid < numThreads; tid++) {
ThreadContext *src_tc = threadContexts[tid];
activityRec.reset();
- BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort());
+ BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
fetch.takeOverFrom();
decode.takeOverFrom();
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* Copyright (c) 2011 Regents of the University of California
* All rights reserved.
Status _threadStatus[Impl::MaxThreads];
private:
+
+ /**
+ * IcachePort class for instruction fetch.
+ */
+ class IcachePort : public CpuPort
+ {
+ protected:
+ /** Pointer to fetch. */
+ DefaultFetch<Impl> *fetch;
+
+ public:
+ /** Default constructor. */
+ IcachePort(DefaultFetch<Impl> *_fetch, FullO3CPU<Impl>* _cpu)
+ : CpuPort(_fetch->name() + "-iport", _cpu), fetch(_fetch)
+ { }
+
+ protected:
+
+ /** Timing version of receive. Handles setting fetch to the
+ * proper status to start fetching. */
+ virtual bool recvTiming(PacketPtr pkt);
+
+ /** Handles doing a retry of a failed fetch. */
+ virtual void recvRetry();
+ };
+
+ /**
+ * DcachePort class for the load/store queue.
+ */
+ class DcachePort : public CpuPort
+ {
+ protected:
+
+ /** Pointer to LSQ. */
+ LSQ<Impl> *lsq;
+
+ public:
+ /** Default constructor. */
+ DcachePort(LSQ<Impl> *_lsq, FullO3CPU<Impl>* _cpu)
+ : CpuPort(_lsq->name() + "-dport", _cpu), lsq(_lsq)
+ { }
+
+ protected:
+
+ /** Timing version of receive. Handles writing back and
+ * completing the load or store that has returned from
+ * memory. */
+ virtual bool recvTiming(PacketPtr pkt);
+
+ /** Handles doing a retry of the previous send. */
+ virtual void recvRetry();
+
+ /**
+ * As this CPU requires snooping to maintain the load store queue
+ * change the behaviour from the base CPU port.
+ *
+ * @param resp list of ranges this port responds to
+ * @param snoop indicating if the port snoops or not
+ */
+ virtual void getDeviceAddressRanges(AddrRangeList& resp,
+ bool& snoop)
+ { resp.clear(); snoop = true; }
+ };
+
class TickEvent : public Event
{
private:
TheISA::ISA isa[Impl::MaxThreads];
+ /** Instruction port. Note that it has to appear after the fetch stage. */
+ IcachePort icachePort;
+
+ /** Data port. Note that it has to appear after the iew stages */
+ DcachePort dcachePort;
+
public:
/** Enum to give each stage a specific index, so when calling
* activateStage() or deactivateStage(), they can specify which stage
data, store_idx);
}
+ /** Used by the fetch unit to get a hold of the instruction port. */
+ Port* getIcachePort() { return &icachePort; }
+
/** Get the dcache port (used to find block size for translations). */
- Port *getDcachePort() { return this->iew.ldstQueue.getDcachePort(); }
+ Port* getDcachePort() { return &dcachePort; }
Addr lockAddr;
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
typedef TheISA::MachInst MachInst;
typedef TheISA::ExtMachInst ExtMachInst;
- /** IcachePort class for DefaultFetch. Handles doing the
- * communication with the cache/memory.
- */
- class IcachePort : public Port
- {
- protected:
- /** Pointer to fetch. */
- DefaultFetch<Impl> *fetch;
-
- public:
- /** Default constructor. */
- IcachePort(DefaultFetch<Impl> *_fetch)
- : Port(_fetch->name() + "-iport", _fetch->cpu), fetch(_fetch)
- { }
-
- bool snoopRangeSent;
-
- virtual void setPeer(Port *port);
-
- protected:
- /** Atomic version of receive. Panics. */
- virtual Tick recvAtomic(PacketPtr pkt);
-
- /** Functional version of receive. Panics. */
- virtual void recvFunctional(PacketPtr pkt);
-
- /** Receives status change. Other than range changing, panics. */
- virtual void recvStatusChange(Status status);
-
- /** Returns the address ranges of this device. */
- virtual void getDeviceAddressRanges(AddrRangeList &resp,
- bool &snoop)
- { resp.clear(); snoop = true; }
-
- /** Timing version of receive. Handles setting fetch to the
- * proper status to start fetching. */
- virtual bool recvTiming(PacketPtr pkt);
-
- /** Handles doing a retry of a failed fetch. */
- virtual void recvRetry();
- };
-
class FetchTranslation : public BaseTLB::Translation
{
protected:
/** Registers statistics. */
void regStats();
- /** Returns the icache port. */
- Port *getIcachePort() { return icachePort; }
-
/** Sets the main backwards communication time buffer pointer. */
void setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer);
/** Tells the fetch stage that the Icache is set. */
void setIcache();
+ /** Handles retrying the fetch access. */
+ void recvRetry();
+
/** Processes cache completion event. */
void processCacheCompletion(PacketPtr pkt);
StaticInstPtr curMacroop, TheISA::PCState thisPC,
TheISA::PCState nextPC, bool trace);
- /** Handles retrying the fetch access. */
- void recvRetry();
-
/** Returns the appropriate thread to fetch, given the fetch policy. */
ThreadID getFetchingThread(FetchPriority &fetch_priority);
/** Wire used to write any information heading to decode. */
typename TimeBuffer<FetchStruct>::wire toDecode;
- /** Icache interface. */
- IcachePort *icachePort;
-
/** BPredUnit. */
BPredUnit branchPred;
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
using namespace std;
-template<class Impl>
-void
-DefaultFetch<Impl>::IcachePort::setPeer(Port *port)
-{
- Port::setPeer(port);
-
- fetch->setIcache();
-}
-
-template<class Impl>
-Tick
-DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt)
-{
- panic("DefaultFetch doesn't expect recvAtomic callback!");
- return curTick();
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
-{
- DPRINTF(Fetch, "DefaultFetch doesn't update its state from a "
- "functional call.\n");
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::IcachePort::recvStatusChange(Status status)
-{
- if (status == RangeChange) {
- if (!snoopRangeSent) {
- snoopRangeSent = true;
- sendStatusChange(Port::RangeChange);
- }
- return;
- }
-
- panic("DefaultFetch doesn't expect recvStatusChange callback!");
-}
-
-template<class Impl>
-bool
-DefaultFetch<Impl>::IcachePort::recvTiming(PacketPtr pkt)
-{
- DPRINTF(Fetch, "Received timing\n");
- if (pkt->isResponse()) {
- // We shouldn't ever get a block in ownership state
- assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted()));
-
- fetch->processCacheCompletion(pkt);
- }
- //else Snooped a coherence request, just return
- return true;
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::IcachePort::recvRetry()
-{
- fetch->recvRetry();
-}
-
template<class Impl>
DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params)
: cpu(_cpu),
// Get the size of an instruction.
instSize = sizeof(TheISA::MachInst);
-
- // Name is finally available, so create the port.
- icachePort = new IcachePort(this);
-
- icachePort->snoopRangeSent = false;
-
-#if USE_CHECKER
- if (cpu->checker) {
- cpu->checker->setIcachePort(icachePort);
- }
-#endif
}
template <class Impl>
void
DefaultFetch<Impl>::setIcache()
{
+ assert(cpu->getIcachePort()->isConnected());
+
// Size of cache block.
- cacheBlkSize = icachePort->peerBlockSize();
+ cacheBlkSize = cpu->getIcachePort()->peerBlockSize();
// Create mask to get rid of offset bits.
cacheBlkMask = (cacheBlkSize - 1);
void
DefaultFetch<Impl>::takeOverFrom()
{
+ // the instruction port is now connected so we can get the block
+ // size
+ setIcache();
+
// Reset all state
for (ThreadID i = 0; i < Impl::MaxThreads; ++i) {
stalls[i].decode = 0;
fetchedCacheLines++;
// Access the cache.
- if (!icachePort->sendTiming(data_pkt)) {
+ if (!cpu->getIcachePort()->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 (icachePort->sendTiming(retryPkt)) {
+ if (cpu->getIcachePort()->sendTiming(retryPkt)) {
fetchStatus[retryTid] = IcacheWaitResponse;
retryPkt = NULL;
retryTid = InvalidThreadID;
/** Initializes stage; sends back the number of free IQ and LSQ entries. */
void initStage();
- /** Returns the dcache port. */
- Port *getDcachePort() { return ldstQueue.getDcachePort(); }
-
/** Sets main time buffer used for backwards communication. */
void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
/*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
/** Registers statistics of each LSQ unit. */
void regStats();
- /** Returns dcache port.
- * @todo: Dcache port needs to be moved up to this level for SMT
- * to work. For now it just returns the port from one of the
- * threads.
- */
- Port *getDcachePort() { return &dcachePort; }
-
/** Sets the pointer to the list of active threads. */
void setActiveThreads(std::list<ThreadID> *at_ptr);
/** Switches out the LSQ. */
Fault write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
uint8_t *data, int store_idx);
+ /**
+ * Retry the previous send that failed.
+ */
+ void recvRetry();
+
+ /**
+ * Handles writing back and completing the load or store that has
+ * returned from memory.
+ *
+ * @param pkt Response packet from the memory sub-system
+ */
+ bool recvTiming(PacketPtr pkt);
+
/** The CPU pointer. */
O3CPU *cpu;
/** The IEW stage pointer. */
IEW *iewStage;
- /** DcachePort class for this LSQ. Handles doing the
- * communication with the cache/memory.
- */
- class DcachePort : public Port
- {
- protected:
- /** Pointer to LSQ. */
- LSQ *lsq;
-
- public:
- /** Default constructor. */
- DcachePort(LSQ *_lsq)
- : Port(_lsq->name() + "-dport", _lsq->cpu), lsq(_lsq)
- { }
-
- bool snoopRangeSent;
-
- protected:
- /** Atomic version of receive. Panics. */
- virtual Tick recvAtomic(PacketPtr pkt);
-
- /** Functional version of receive. Panics. */
- virtual void recvFunctional(PacketPtr pkt);
-
- /** Receives status change. Other than range changing, panics. */
- virtual void recvStatusChange(Status status);
-
- /** Returns the address ranges of this device. */
- virtual void getDeviceAddressRanges(AddrRangeList &resp,
- bool &snoop)
- { resp.clear(); snoop = true; }
-
- /** Timing version of receive. Handles writing back and
- * completing the load or store that has returned from
- * memory. */
- virtual bool recvTiming(PacketPtr pkt);
-
- /** Handles doing a retry of the previous send. */
- virtual void recvRetry();
- };
-
- /** D-cache port. */
- DcachePort dcachePort;
-
protected:
/** The LSQ policy for SMT mode. */
LSQPolicy lsqPolicy;
/*
+ * Copyright (c) 2011 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) 2005-2006 The Regents of The University of Michigan
* All rights reserved.
*
using namespace std;
-template <class Impl>
-Tick
-LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
-{
- panic("O3CPU model does not work with atomic mode!");
- return curTick();
-}
-
-template <class Impl>
-void
-LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
-{
- DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional.\n");
-}
-
-template <class Impl>
-void
-LSQ<Impl>::DcachePort::recvStatusChange(Status status)
-{
- if (status == RangeChange) {
- if (!snoopRangeSent) {
- snoopRangeSent = true;
- sendStatusChange(Port::RangeChange);
- }
- return;
- }
- panic("O3CPU doesn't expect recvStatusChange callback!");
-}
-
-template <class Impl>
-bool
-LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
-{
- if (pkt->isError())
- DPRINTF(LSQ, "Got error packet back for address: %#X\n", pkt->getAddr());
- if (pkt->isResponse()) {
- lsq->thread[pkt->req->threadId()].completeDataAccess(pkt);
- } else {
- DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(),
- pkt->cmdString());
-
- // must be a snoop
- if (pkt->isInvalidate()) {
- DPRINTF(LSQ, "received invalidation for addr:%#x\n", pkt->getAddr());
- for (ThreadID tid = 0; tid < lsq->numThreads; tid++) {
- lsq->thread[tid].checkSnoop(pkt);
- }
- }
- // to provide stronger consistency model
- }
- return true;
-}
-
-template <class Impl>
-void
-LSQ<Impl>::DcachePort::recvRetry()
-{
- if (lsq->retryTid == -1)
- {
- //Squashed, so drop it
- return;
- }
- int curr_retry_tid = lsq->retryTid;
- // Speculatively clear the retry Tid. This will get set again if
- // the LSQUnit was unable to complete its access.
- lsq->retryTid = -1;
- lsq->thread[curr_retry_tid].recvRetry();
-}
-
template <class Impl>
LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
- : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this),
+ : cpu(cpu_ptr), iewStage(iew_ptr),
LQEntries(params->LQEntries),
SQEntries(params->SQEntries),
numThreads(params->numThreads),
retryTid(-1)
{
- dcachePort.snoopRangeSent = false;
-
//**********************************************/
//************ Handle SMT Parameters ***********/
//**********************************************/
for (ThreadID tid = 0; tid < numThreads; tid++) {
thread[tid].init(cpu, iew_ptr, params, this,
maxLQEntries, maxSQEntries, tid);
- thread[tid].setDcachePort(&dcachePort);
+ thread[tid].setDcachePort(cpu_ptr->getDcachePort());
}
}
return false;
}
+template <class Impl>
+void
+LSQ<Impl>::recvRetry()
+{
+ if (retryTid == InvalidThreadID)
+ {
+ //Squashed, so drop it
+ return;
+ }
+ int curr_retry_tid = retryTid;
+ // Speculatively clear the retry Tid. This will get set again if
+ // the LSQUnit was unable to complete its access.
+ retryTid = -1;
+ thread[curr_retry_tid].recvRetry();
+}
+
+template <class Impl>
+bool
+LSQ<Impl>::recvTiming(PacketPtr pkt)
+{
+ if (pkt->isError())
+ DPRINTF(LSQ, "Got error packet back for address: %#X\n",
+ pkt->getAddr());
+ if (pkt->isResponse()) {
+ thread[pkt->req->threadId()].completeDataAccess(pkt);
+ } else {
+ DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(),
+ pkt->cmdString());
+
+ // must be a snoop
+ if (pkt->isInvalidate()) {
+ DPRINTF(LSQ, "received invalidation for addr:%#x\n",
+ pkt->getAddr());
+ for (ThreadID tid = 0; tid < numThreads; tid++) {
+ thread[tid].checkSnoop(pkt);
+ }
+ }
+ // to provide stronger consistency model
+ }
+ return true;
+}
+
template<class Impl>
int
LSQ<Impl>::getCount()
width = Param.Int(1, "CPU width")
simulate_data_stalls = Param.Bool(False, "Simulate dcache stall cycles")
simulate_inst_stalls = Param.Bool(False, "Simulate icache stall cycles")
- icache_port = Port("Instruction Port")
- dcache_port = Port("Data Port")
physmem_port = Port("Physical Memory Port")
- _cached_ports = BaseSimpleCPU._cached_ports + \
- ['icache_port', 'dcache_port']
class TimingSimpleCPU(BaseSimpleCPU):
type = 'TimingSimpleCPU'
- icache_port = Port("Instruction Port")
- dcache_port = Port("Data Port")
- _cached_ports = BaseSimpleCPU._cached_ports + ['icache_port', 'dcache_port']
data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too
}
-bool
-AtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt)
-{
- panic("AtomicSimpleCPU doesn't expect recvTiming callback!");
- return true;
-}
-
-Tick
-AtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt)
-{
- //Snooping a coherence request, just return
- return 0;
-}
-
-void
-AtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt)
-{
- //No internal storage to update, just return
- return;
-}
-
-void
-AtomicSimpleCPU::CpuPort::recvStatusChange(Status status)
-{
- if (status == RangeChange) {
- if (!snoopRangeSent) {
- snoopRangeSent = true;
- sendStatusChange(Port::RangeChange);
- }
- return;
- }
-
- panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
-}
-
-void
-AtomicSimpleCPU::CpuPort::recvRetry()
-{
- panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
-}
-
AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p)
: BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false),
simulate_data_stalls(p->simulate_data_stalls),
physmemPort(name() + "-iport", this), hasPhysMemPort(false)
{
_status = Idle;
-
- icachePort.snoopRangeSent = false;
- dcachePort.snoopRangeSent = false;
-
}
// main simulation loop (one cycle)
void tick();
- class CpuPort : public Port
+ /**
+ * An AtomicCPUPort overrides the default behaviour of the
+ * recvAtomic and ignores the packet instead of panicking.
+ */
+ class AtomicCPUPort : public CpuPort
{
+
public:
- CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu)
- : Port(_name, _cpu), cpu(_cpu)
+ AtomicCPUPort(const std::string &_name, BaseCPU* _cpu)
+ : CpuPort(_name, _cpu)
{ }
- bool snoopRangeSent;
-
protected:
- AtomicSimpleCPU *cpu;
-
- virtual bool recvTiming(PacketPtr pkt);
-
- virtual Tick recvAtomic(PacketPtr pkt);
-
- virtual void recvFunctional(PacketPtr pkt);
-
- virtual void recvStatusChange(Status status);
-
- virtual void recvRetry();
-
- virtual void getDeviceAddressRanges(AddrRangeList &resp,
- bool &snoop)
- { resp.clear(); snoop = true; }
+ virtual Tick recvAtomic(PacketPtr pkt)
+ {
+ // Snooping a coherence request, just return
+ return 0;
+ }
};
- CpuPort icachePort;
- CpuPort dcachePort;
+ AtomicCPUPort icachePort;
+ AtomicCPUPort dcachePort;
CpuPort physmemPort;
bool hasPhysMemPort;
#endif
}
-Tick
-TimingSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt)
-{
- panic("TimingSimpleCPU doesn't expect recvAtomic callback!");
- return curTick();
-}
-
void
-TimingSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt)
-{
- //No internal storage to update, jusst return
- return;
-}
-
-void
-TimingSimpleCPU::CpuPort::recvStatusChange(Status status)
-{
- if (status == RangeChange) {
- if (!snoopRangeSent) {
- snoopRangeSent = true;
- sendStatusChange(Port::RangeChange);
- }
- return;
- }
-
- panic("TimingSimpleCPU doesn't expect recvStatusChange callback!");
-}
-
-
-void
-TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
+TimingSimpleCPU::TimingCPUPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
{
pkt = _pkt;
cpu->schedule(this, t);
}
TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
- : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this, p->clock),
- dcachePort(this, p->clock), fetchEvent(this)
+ : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this),
+ dcachePort(this), fetchEvent(this)
{
_status = Idle;
- icachePort.snoopRangeSent = false;
- dcachePort.snoopRangeSent = false;
-
ifetch_pkt = dcache_pkt = NULL;
drainEvent = NULL;
previousTick = 0;
// This function always implicitly uses dcache_pkt.
bool handleWritePacket();
- class CpuPort : public Port
+ /**
+ * A TimingCPUPort overrides the default behaviour of the
+ * recvTiming and recvRetry and implements events for the
+ * scheduling of handling of incoming packets in the following
+ * cycle.
+ */
+ class TimingCPUPort : public CpuPort
{
- protected:
- TimingSimpleCPU *cpu;
- Tick lat;
-
public:
- CpuPort(const std::string &_name, TimingSimpleCPU *_cpu, Tick _lat)
- : Port(_name, _cpu), cpu(_cpu), lat(_lat), retryEvent(this)
+ TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu)
+ : CpuPort(_name, _cpu), cpu(_cpu), retryEvent(this)
{ }
- bool snoopRangeSent;
-
protected:
- virtual Tick recvAtomic(PacketPtr pkt);
-
- virtual void recvFunctional(PacketPtr pkt);
-
- virtual void recvStatusChange(Status status);
-
- virtual void getDeviceAddressRanges(AddrRangeList &resp,
- bool &snoop)
- { resp.clear(); snoop = false; }
+ TimingSimpleCPU* cpu;
struct TickEvent : public Event
{
TimingSimpleCPU *cpu;
CpuPort *port;
- TickEvent(TimingSimpleCPU *_cpu) : cpu(_cpu) {}
+ TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {}
const char *description() const { return "Timing CPU tick"; }
void schedule(PacketPtr _pkt, Tick t);
};
EventWrapper<Port, &Port::sendRetry> retryEvent;
};
- class IcachePort : public CpuPort
+ class IcachePort : public TimingCPUPort
{
public:
- IcachePort(TimingSimpleCPU *_cpu, Tick _lat)
- : CpuPort(_cpu->name() + "-iport", _cpu, _lat), tickEvent(_cpu)
+ IcachePort(TimingSimpleCPU *_cpu)
+ : TimingCPUPort(_cpu->name() + "-iport", _cpu),
+ tickEvent(_cpu)
{ }
protected:
};
- class DcachePort : public CpuPort
+ class DcachePort : public TimingCPUPort
{
public:
- DcachePort(TimingSimpleCPU *_cpu, Tick _lat)
- : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu)
+ DcachePort(TimingSimpleCPU *_cpu)
+ : TimingCPUPort(_cpu->name() + "-dport", _cpu), tickEvent(_cpu)
{ }
protected: