summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2006-07-11 13:43:30 -0400
committerKevin Lim <ktlim@umich.edu>2006-07-11 13:43:30 -0400
commit0b0cb2bca71acdab4a30acc639509030631f9dfd (patch)
treefee4bbd0c1bfb45b7abec14e944400852f90b468 /src
parentb55cda163ed1a29ee5e08cde36743047923ab475 (diff)
parent7078d8d1b42c1a158c854b3e07800f20aa695bfb (diff)
downloadgem5-0b0cb2bca71acdab4a30acc639509030631f9dfd.tar.xz
Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/newmem --HG-- extra : convert_revision : c565fd7cebaa4058ba510b3db50a9c76bf301228
Diffstat (limited to 'src')
-rw-r--r--src/arch/alpha/regfile.hh4
-rw-r--r--src/base/timebuf.hh5
-rw-r--r--src/cpu/SConscript7
-rw-r--r--src/cpu/base.cc4
-rw-r--r--src/cpu/base.hh5
-rw-r--r--src/cpu/checker/cpu.hh6
-rw-r--r--src/cpu/checker/thread_context.hh2
-rw-r--r--src/cpu/o3/alpha/cpu_builder.cc12
-rw-r--r--src/cpu/o3/alpha/thread_context.hh15
-rw-r--r--src/cpu/o3/commit.hh14
-rw-r--r--src/cpu/o3/commit_impl.hh30
-rw-r--r--src/cpu/o3/cpu.cc333
-rw-r--r--src/cpu/o3/cpu.hh61
-rw-r--r--src/cpu/o3/decode.hh2
-rw-r--r--src/cpu/o3/decode_impl.hh3
-rw-r--r--src/cpu/o3/fetch.hh5
-rw-r--r--src/cpu/o3/fetch_impl.hh28
-rw-r--r--src/cpu/o3/iew.hh5
-rw-r--r--src/cpu/o3/iew_impl.hh8
-rw-r--r--src/cpu/o3/lsq.hh7
-rw-r--r--src/cpu/o3/lsq_impl.hh3
-rw-r--r--src/cpu/o3/lsq_unit.hh5
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh4
-rwxr-xr-xsrc/cpu/o3/params.hh6
-rw-r--r--src/cpu/o3/regfile.hh4
-rw-r--r--src/cpu/o3/rename.hh2
-rw-r--r--src/cpu/o3/rename_impl.hh3
-rw-r--r--src/cpu/o3/rob.hh2
-rw-r--r--src/cpu/o3/rob_impl.hh14
-rwxr-xr-xsrc/cpu/o3/thread_context.hh2
-rwxr-xr-xsrc/cpu/o3/thread_context_impl.hh16
-rw-r--r--src/cpu/ozone/cpu.hh6
-rw-r--r--src/cpu/ozone/cpu_impl.hh18
-rw-r--r--src/cpu/ozone/front_end.hh2
-rw-r--r--src/cpu/ozone/front_end_impl.hh5
-rw-r--r--src/cpu/ozone/lw_back_end.hh4
-rw-r--r--src/cpu/ozone/lw_back_end_impl.hh12
-rw-r--r--src/cpu/ozone/lw_lsq.hh18
-rw-r--r--src/cpu/ozone/lw_lsq_impl.hh15
-rw-r--r--src/cpu/simple/atomic.cc22
-rw-r--r--src/cpu/simple/atomic.hh2
-rw-r--r--src/cpu/simple/timing.cc47
-rw-r--r--src/cpu/simple/timing.hh4
-rw-r--r--src/cpu/simple_thread.cc78
-rw-r--r--src/cpu/simple_thread.hh10
-rw-r--r--src/cpu/thread_context.hh4
-rw-r--r--src/cpu/thread_state.cc43
-rw-r--r--src/cpu/thread_state.hh6
-rw-r--r--src/dev/tsunami_pchip.hh2
-rw-r--r--src/mem/cache/base_cache.cc41
-rw-r--r--src/mem/cache/base_cache.hh40
-rw-r--r--src/mem/cache/cache.hh4
-rw-r--r--src/mem/cache/cache_impl.hh2
-rw-r--r--src/mem/cache/miss/miss_queue.cc8
-rw-r--r--src/mem/cache/miss/mshr.cc1
-rw-r--r--src/mem/packet.hh21
-rw-r--r--src/python/SConscript15
-rw-r--r--src/python/m5/__init__.py135
-rw-r--r--src/python/m5/attrdict.py61
-rw-r--r--src/python/m5/main.py307
-rw-r--r--src/python/m5/objects/O3CPU.py5
-rw-r--r--src/python/m5/objects/OzoneCPU.py3
-rw-r--r--src/sim/main.cc168
-rw-r--r--src/sim/pseudo_inst.cc1
-rw-r--r--src/sim/serialize.cc10
-rw-r--r--src/sim/serialize.hh6
-rw-r--r--src/sim/syscall_emul.hh1
67 files changed, 1131 insertions, 613 deletions
diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh
index 1025412cd..9ecad6f42 100644
--- a/src/arch/alpha/regfile.hh
+++ b/src/arch/alpha/regfile.hh
@@ -112,6 +112,10 @@ namespace AlphaISA
lock_flag = 0;
lock_addr = 0;
}
+
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
#if FULL_SYSTEM
protected:
typedef uint64_t InternalProcReg;
diff --git a/src/base/timebuf.hh b/src/base/timebuf.hh
index 160a97034..a484a3179 100644
--- a/src/base/timebuf.hh
+++ b/src/base/timebuf.hh
@@ -215,6 +215,11 @@ class TimeBuffer
{
return wire(this, 0);
}
+
+ int getSize()
+ {
+ return size;
+ }
};
#endif // __BASE_TIMEBUF_HH__
diff --git a/src/cpu/SConscript b/src/cpu/SConscript
index 1d0a015b0..bc4ec7923 100644
--- a/src/cpu/SConscript
+++ b/src/cpu/SConscript
@@ -188,9 +188,10 @@ if env['USE_CHECKER']:
if i in env['CPU_MODELS']:
checker_supports = True
if not checker_supports:
- print "Checker only supports CPU models %s, please " \
- "set USE_CHECKER=False or use one of those CPU models" \
- % CheckerSupportedCPUList
+ print "Checker only supports CPU models",
+ for i in CheckerSupportedCPUList:
+ print i,
+ print ", please set USE_CHECKER=False or use one of those CPU models"
Exit(1)
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index 0b9c80591..ce440aeff 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -59,11 +59,11 @@ int maxThreadsPerCPU = 1;
#if FULL_SYSTEM
BaseCPU::BaseCPU(Params *p)
- : SimObject(p->name), clock(p->clock), checkInterrupts(true),
+ : MemObject(p->name), clock(p->clock), checkInterrupts(true),
params(p), number_of_threads(p->numberOfThreads), system(p->system)
#else
BaseCPU::BaseCPU(Params *p)
- : SimObject(p->name), clock(p->clock), params(p),
+ : MemObject(p->name), clock(p->clock), params(p),
number_of_threads(p->numberOfThreads), system(p->system)
#endif
{
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
index 5256a411f..2be6e4e81 100644
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -37,15 +37,16 @@
#include "base/statistics.hh"
#include "config/full_system.hh"
#include "sim/eventq.hh"
-#include "sim/sim_object.hh"
+#include "mem/mem_object.hh"
#include "arch/isa_traits.hh"
class BranchPred;
class CheckerCPU;
class ThreadContext;
class System;
+class Port;
-class BaseCPU : public SimObject
+class BaseCPU : public MemObject
{
protected:
// CPU's clock period in terms of the number of ticks of curTime.
diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh
index b520e1be0..a508c56ba 100644
--- a/src/cpu/checker/cpu.hh
+++ b/src/cpu/checker/cpu.hh
@@ -127,6 +127,12 @@ class CheckerCPU : public BaseCPU
Port *dcachePort;
+ virtual Port *getPort(const std::string &name, int idx)
+ {
+ panic("Not supported on checker!");
+ return NULL;
+ }
+
public:
// Primary thread being run.
SimpleThread *thread;
diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh
index c0ac8f01d..c035e92ac 100644
--- a/src/cpu/checker/thread_context.hh
+++ b/src/cpu/checker/thread_context.hh
@@ -120,7 +120,7 @@ class CheckerThreadContext : public ThreadContext
void suspend() { actualTC->suspend(); }
/// Set the status to Unallocated.
- void deallocate() { actualTC->deallocate(); }
+ void deallocate(int delay = 0) { actualTC->deallocate(delay); }
/// Set the status to Halted.
void halt() { actualTC->halt(); }
diff --git a/src/cpu/o3/alpha/cpu_builder.cc b/src/cpu/o3/alpha/cpu_builder.cc
index d61eee4b1..5e767655d 100644
--- a/src/cpu/o3/alpha/cpu_builder.cc
+++ b/src/cpu/o3/alpha/cpu_builder.cc
@@ -102,7 +102,9 @@ Param<unsigned> renameToROBDelay;
Param<unsigned> commitWidth;
Param<unsigned> squashWidth;
Param<Tick> trapLatency;
-Param<Tick> fetchTrapLatency;
+
+Param<unsigned> backComSize;
+Param<unsigned> forwardComSize;
Param<std::string> predType;
Param<unsigned> localPredictorSize;
@@ -222,7 +224,9 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
INIT_PARAM(commitWidth, "Commit width"),
INIT_PARAM(squashWidth, "Squash width"),
INIT_PARAM_DFLT(trapLatency, "Number of cycles before the trap is handled", 6),
- INIT_PARAM_DFLT(fetchTrapLatency, "Number of cycles before the fetch trap is handled", 12),
+
+ INIT_PARAM(backComSize, "Time buffer size for backwards communication"),
+ INIT_PARAM(forwardComSize, "Time buffer size for forward communication"),
INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
INIT_PARAM(localPredictorSize, "Size of local predictor"),
@@ -350,7 +354,9 @@ CREATE_SIM_OBJECT(DerivO3CPU)
params->commitWidth = commitWidth;
params->squashWidth = squashWidth;
params->trapLatency = trapLatency;
- params->fetchTrapLatency = fetchTrapLatency;
+
+ params->backComSize = backComSize;
+ params->forwardComSize = forwardComSize;
params->predType = predType;
params->localPredictorSize = localPredictorSize;
diff --git a/src/cpu/o3/alpha/thread_context.hh b/src/cpu/o3/alpha/thread_context.hh
index 78b0ee788..ad52b0d2e 100644
--- a/src/cpu/o3/alpha/thread_context.hh
+++ b/src/cpu/o3/alpha/thread_context.hh
@@ -70,18 +70,19 @@ class AlphaTC : public O3ThreadContext<Impl>
{ panic("Not supported on Alpha!"); }
- // This function exits the thread context in the CPU and returns
- // 1 if the CPU has no more active threads (meaning it's OK to exit);
- // Used in syscall-emulation mode when a thread executes the 'exit'
- // syscall.
+ /** This function exits the thread context in the CPU and returns
+ * 1 if the CPU has no more active threads (meaning it's OK to exit);
+ * Used in syscall-emulation mode when a thread executes the 'exit'
+ * syscall.
+ */
virtual int exit()
{
- this->cpu->deallocateContext(this->thread->readTid());
+ this->deallocate();
// If there are still threads executing in the system
if (this->cpu->numActiveThreads())
- return 0;
+ return 0; // don't exit simulation
else
- return 1;
+ return 1; // exit simulation
}
};
diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh
index 49ff5cdad..956b6ec3e 100644
--- a/src/cpu/o3/commit.hh
+++ b/src/cpu/o3/commit.hh
@@ -162,10 +162,6 @@ class DefaultCommit
/** Sets the pointer to the queue coming from IEW. */
void setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr);
- void setFetchStage(Fetch *fetch_stage);
-
- Fetch *fetchStage;
-
/** Sets the pointer to the IEW stage. */
void setIEWStage(IEW *iew_stage);
@@ -188,7 +184,7 @@ class DefaultCommit
void initStage();
/** Initializes the draining of commit. */
- void drain();
+ bool drain();
/** Resumes execution after draining. */
void resume();
@@ -335,10 +331,6 @@ class DefaultCommit
/** Vector of all of the threads. */
std::vector<Thread *> thread;
- Fault fetchFault;
-
- int fetchTrapWait;
-
/** Records that commit has written to the time buffer this cycle. Used for
* the CPU to determine if it can deschedule itself if there is no activity.
*/
@@ -397,10 +389,6 @@ class DefaultCommit
*/
Tick trapLatency;
- Tick fetchTrapLatency;
-
- Tick fetchFaultTick;
-
/** The commit PC of each thread. Refers to the instruction that
* is currently being processed/committed.
*/
diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index 2eb05afac..904af1071 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -82,8 +82,7 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
numThreads(params->numberOfThreads),
drainPending(false),
switchedOut(false),
- trapLatency(params->trapLatency),
- fetchTrapLatency(params->fetchTrapLatency)
+ trapLatency(params->trapLatency)
{
_status = Active;
_nextStatus = Inactive;
@@ -123,9 +122,6 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
tcSquash[i] = false;
PC[i] = nextPC[i] = 0;
}
-
- fetchFaultTick = 0;
- fetchTrapWait = 0;
}
template <class Impl>
@@ -235,7 +231,6 @@ DefaultCommit<Impl>::setCPU(O3CPU *cpu_ptr)
cpu->activateStage(O3CPU::CommitIdx);
trapLatency = cpu->cycles(trapLatency);
- fetchTrapLatency = cpu->cycles(fetchTrapLatency);
}
template <class Impl>
@@ -294,13 +289,6 @@ DefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
template <class Impl>
void
-DefaultCommit<Impl>::setFetchStage(Fetch *fetch_stage)
-{
- fetchStage = fetch_stage;
-}
-
-template <class Impl>
-void
DefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
{
iewStage = iew_stage;
@@ -350,10 +338,18 @@ DefaultCommit<Impl>::initStage()
}
template <class Impl>
-void
+bool
DefaultCommit<Impl>::drain()
{
drainPending = true;
+
+ // If it's already drained, return true.
+ if (rob->isEmpty() && !iewStage->hasStoresToWB()) {
+ cpu->signalDrained();
+ return true;
+ }
+
+ return false;
}
template <class Impl>
@@ -369,6 +365,7 @@ template <class Impl>
void
DefaultCommit<Impl>::resume()
{
+ drainPending = false;
}
template <class Impl>
@@ -569,6 +566,9 @@ DefaultCommit<Impl>::tick()
return;
}
+ if ((*activeThreads).size() <= 0)
+ return;
+
list<unsigned>::iterator threads = (*activeThreads).begin();
// Check if any of the threads are done squashing. Change the
@@ -582,7 +582,7 @@ DefaultCommit<Impl>::tick()
commitStatus[tid] = Running;
} else {
DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
- "insts this cycle.\n", tid);
+ " insts this cycle.\n", tid);
rob->doSquash(tid);
toIEW->commitInfo[tid].robSquashing = true;
wroteToTimeBuffer = true;
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index b182d5ca7..7d2727401 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -115,6 +115,36 @@ FullO3CPU<Impl>::ActivateThreadEvent::description()
}
template <class Impl>
+FullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent()
+ : Event(&mainEventQueue, CPU_Tick_Pri)
+{
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num,
+ FullO3CPU<Impl> *thread_cpu)
+{
+ tid = thread_num;
+ cpu = thread_cpu;
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::DeallocateContextEvent::process()
+{
+ cpu->deactivateThread(tid);
+ cpu->removeThread(tid);
+}
+
+template <class Impl>
+const char *
+FullO3CPU<Impl>::DeallocateContextEvent::description()
+{
+ return "FullO3CPU \"Deallocate Context\" event";
+}
+
+template <class Impl>
FullO3CPU<Impl>::FullO3CPU(Params *params)
: BaseO3CPU(params),
tickEvent(this),
@@ -141,15 +171,14 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
TheISA::NumMiscRegs * number_of_threads,
TheISA::ZeroReg),
- // For now just have these time buffers be pretty big.
- // @todo: Make these time buffer sizes parameters or derived
- // from latencies
- timeBuffer(5, 5),
- fetchQueue(5, 5),
- decodeQueue(5, 5),
- renameQueue(5, 5),
- iewQueue(5, 5),
- activityRec(NumStages, 10, params->activity),
+ timeBuffer(params->backComSize, params->forwardComSize),
+ fetchQueue(params->backComSize, params->forwardComSize),
+ decodeQueue(params->backComSize, params->forwardComSize),
+ renameQueue(params->backComSize, params->forwardComSize),
+ iewQueue(params->backComSize, params->forwardComSize),
+ activityRec(NumStages,
+ params->backComSize + params->forwardComSize,
+ params->activity),
globalSeqNum(1),
@@ -214,7 +243,6 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
commit.setIEWQueue(&iewQueue);
commit.setRenameQueue(&renameQueue);
- commit.setFetchStage(&fetch);
commit.setIEWStage(&iew);
rename.setIEWStage(&iew);
rename.setCommitStage(&commit);
@@ -361,6 +389,18 @@ FullO3CPU<Impl>::fullCPURegStats()
}
template <class Impl>
+Port *
+FullO3CPU<Impl>::getPort(const std::string &if_name, int idx)
+{
+ if (if_name == "dcache_port")
+ return iew.getDcachePort();
+ else if (if_name == "icache_port")
+ return fetch.getIcachePort();
+ else
+ panic("No Such Port\n");
+}
+
+template <class Impl>
void
FullO3CPU<Impl>::tick()
{
@@ -400,7 +440,8 @@ FullO3CPU<Impl>::tick()
}
if (!tickEvent.scheduled()) {
- if (_status == SwitchedOut) {
+ if (_status == SwitchedOut ||
+ getState() == SimObject::DrainedTiming) {
// increment stat
lastRunningCycle = curTick;
} else if (!activityRec.active()) {
@@ -461,6 +502,118 @@ FullO3CPU<Impl>::init()
template <class Impl>
void
+FullO3CPU<Impl>::activateThread(unsigned tid)
+{
+ list<unsigned>::iterator isActive = find(
+ activeThreads.begin(), activeThreads.end(), tid);
+
+ if (isActive == activeThreads.end()) {
+ DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
+ tid);
+
+ activeThreads.push_back(tid);
+ }
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::deactivateThread(unsigned tid)
+{
+ //Remove From Active List, if Active
+ list<unsigned>::iterator thread_it =
+ find(activeThreads.begin(), activeThreads.end(), tid);
+
+ if (thread_it != activeThreads.end()) {
+ DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
+ tid);
+ activeThreads.erase(thread_it);
+ }
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::activateContext(int tid, int delay)
+{
+ // Needs to set each stage to running as well.
+ if (delay){
+ DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
+ "on cycle %d\n", tid, curTick + cycles(delay));
+ scheduleActivateThreadEvent(tid, delay);
+ } else {
+ activateThread(tid);
+ }
+
+ if(lastActivatedCycle < curTick) {
+ scheduleTickEvent(delay);
+
+ // Be sure to signal that there's some activity so the CPU doesn't
+ // deschedule itself.
+ activityRec.activity();
+ fetch.wakeFromQuiesce();
+
+ lastActivatedCycle = curTick;
+
+ _status = Running;
+ }
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::deallocateContext(int tid, int delay)
+{
+ // Schedule removal of thread data from CPU
+ if (delay){
+ DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate "
+ "on cycle %d\n", tid, curTick + cycles(delay));
+ scheduleDeallocateContextEvent(tid, delay);
+ } else {
+ deactivateThread(tid);
+ removeThread(tid);
+ }
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::suspendContext(int tid)
+{
+ DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
+ unscheduleTickEvent();
+ _status = Idle;
+/*
+ //Remove From Active List, if Active
+ list<unsigned>::iterator isActive = find(
+ activeThreads.begin(), activeThreads.end(), tid);
+
+ if (isActive != activeThreads.end()) {
+ DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
+ tid);
+ activeThreads.erase(isActive);
+ }
+*/
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::haltContext(int tid)
+{
+ DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid);
+/*
+ //Remove From Active List, if Active
+ list<unsigned>::iterator isActive = find(
+ activeThreads.begin(), activeThreads.end(), tid);
+
+ if (isActive != activeThreads.end()) {
+ DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
+ tid);
+ activeThreads.erase(isActive);
+
+ removeThread(tid);
+ }
+*/
+}
+
+template <class Impl>
+void
FullO3CPU<Impl>::insertThread(unsigned tid)
{
DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
@@ -511,7 +664,7 @@ template <class Impl>
void
FullO3CPU<Impl>::removeThread(unsigned tid)
{
- DPRINTF(O3CPU,"[tid:%i] Removing thread from CPU.");
+ DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid);
// Copy Thread Data From RegFile
// If thread is suspended, it might be re-allocated
@@ -537,6 +690,8 @@ FullO3CPU<Impl>::removeThread(unsigned tid)
fetch.squash(0,tid);
decode.squash(tid);
rename.squash(tid);
+ iew.squash(tid);
+ commit.rob->squash(commit.rob->readHeadInst(tid)->seqNum, tid);
assert(iew.ldstQueue.getCount(tid) == 0);
@@ -600,6 +755,7 @@ FullO3CPU<Impl>::activateWhenReady(int tid)
//blocks fetch
contextSwitch = true;
+ //@todo: dont always add to waitlist
//do waitlist
cpuWaitList.push_back(tid);
}
@@ -607,112 +763,50 @@ FullO3CPU<Impl>::activateWhenReady(int tid)
template <class Impl>
void
-FullO3CPU<Impl>::activateThread(unsigned int tid)
-{
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive == activeThreads.end()) {
- DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
- tid);
-
- activeThreads.push_back(tid);
+FullO3CPU<Impl>::serialize(std::ostream &os)
+{
+ SERIALIZE_ENUM(_status);
+ BaseCPU::serialize(os);
+ nameOut(os, csprintf("%s.tickEvent", name()));
+ tickEvent.serialize(os);
+
+ // Use SimpleThread's ability to checkpoint to make it easier to
+ // write out the registers. Also make this static so it doesn't
+ // get instantiated multiple times (causes a panic in statistics).
+ static SimpleThread temp;
+
+ for (int i = 0; i < thread.size(); i++) {
+ nameOut(os, csprintf("%s.xc.%i", name(), i));
+ temp.copyTC(thread[i]->getTC());
+ temp.serialize(os);
}
}
-
template <class Impl>
void
-FullO3CPU<Impl>::activateContext(int tid, int delay)
+FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
{
- // Needs to set each stage to running as well.
- if (delay){
- DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
- "on cycle %d\n", tid, curTick + cycles(delay));
- scheduleActivateThreadEvent(tid, delay);
- } else {
- activateThread(tid);
- }
-
- if(lastActivatedCycle < curTick) {
- scheduleTickEvent(delay);
-
- // Be sure to signal that there's some activity so the CPU doesn't
- // deschedule itself.
- activityRec.activity();
- fetch.wakeFromQuiesce();
+ UNSERIALIZE_ENUM(_status);
+ BaseCPU::unserialize(cp, section);
+ tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
- lastActivatedCycle = curTick;
+ // Use SimpleThread's ability to checkpoint to make it easier to
+ // read in the registers. Also make this static so it doesn't
+ // get instantiated multiple times (causes a panic in statistics).
+ static SimpleThread temp;
- _status = Running;
+ for (int i = 0; i < thread.size(); i++) {
+ temp.copyTC(thread[i]->getTC());
+ temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
+ thread[i]->getTC()->copyArchRegs(temp.getTC());
}
}
template <class Impl>
-void
-FullO3CPU<Impl>::suspendContext(int tid)
-{
- DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
- unscheduleTickEvent();
- _status = Idle;
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
- }
-*/
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::deallocateContext(int tid)
-{
- DPRINTF(O3CPU,"[tid:%i]: Deallocating Thread Context", tid);
-
- //Remove From Active List, if Active
- list<unsigned>::iterator thread_it =
- find(activeThreads.begin(), activeThreads.end(), tid);
-
- if (thread_it != activeThreads.end()) {
- DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(thread_it);
-
- removeThread(tid);
- }
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::haltContext(int tid)
-{
- DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid);
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
-
- removeThread(tid);
- }
-*/
-}
-
-template <class Impl>
bool
FullO3CPU<Impl>::drain(Event *drain_event)
{
drainCount = 0;
- drainEvent = drain_event;
fetch.drain();
decode.drain();
rename.drain();
@@ -720,28 +814,40 @@ FullO3CPU<Impl>::drain(Event *drain_event)
commit.drain();
// Wake the CPU and record activity so everything can drain out if
- // the CPU is currently idle.
- wakeCPU();
- activityRec.activity();
+ // the CPU was not able to immediately drain.
+ if (getState() != SimObject::DrainedTiming) {
+ // A bit of a hack...set the drainEvent after all the drain()
+ // calls have been made, that way if all of the stages drain
+ // immediately, the signalDrained() function knows not to call
+ // process on the drain event.
+ drainEvent = drain_event;
+
+ wakeCPU();
+ activityRec.activity();
- return false;
+ return false;
+ } else {
+ return true;
+ }
}
template <class Impl>
void
FullO3CPU<Impl>::resume()
{
- if (_status == SwitchedOut)
- return;
fetch.resume();
decode.resume();
rename.resume();
iew.resume();
commit.resume();
+ if (_status == SwitchedOut || _status == Idle)
+ return;
+
if (!tickEvent.scheduled())
tickEvent.schedule(curTick);
_status = Running;
+ changeState(SimObject::Timing);
}
template <class Impl>
@@ -751,8 +857,13 @@ FullO3CPU<Impl>::signalDrained()
if (++drainCount == NumStages) {
if (tickEvent.scheduled())
tickEvent.squash();
- _status = Drained;
- drainEvent->process();
+
+ changeState(SimObject::DrainedTiming);
+
+ if (drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
+ }
}
assert(drainCount <= 5);
}
@@ -781,7 +892,7 @@ void
FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
{
// Flush out any old data from the time buffers.
- for (int i = 0; i < 10; ++i) {
+ for (int i = 0; i < timeBuffer.getSize(); ++i) {
timeBuffer.advance();
fetchQueue.advance();
decodeQueue.advance();
diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh
index cf3747601..2fbd013ac 100644
--- a/src/cpu/o3/cpu.hh
+++ b/src/cpu/o3/cpu.hh
@@ -111,7 +111,6 @@ class FullO3CPU : public BaseO3CPU
Idle,
Halted,
Blocked,
- Drained,
SwitchedOut
};
@@ -200,6 +199,49 @@ class FullO3CPU : public BaseO3CPU
/** The tick event used for scheduling CPU ticks. */
ActivateThreadEvent activateThreadEvent[Impl::MaxThreads];
+ class DeallocateContextEvent : public Event
+ {
+ private:
+ /** Number of Thread to Activate */
+ int tid;
+
+ /** Pointer to the CPU. */
+ FullO3CPU<Impl> *cpu;
+
+ public:
+ /** Constructs the event. */
+ DeallocateContextEvent();
+
+ /** Initialize Event */
+ void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
+
+ /** Processes the event, calling activateThread() on the CPU. */
+ void process();
+
+ /** Returns the description of the event. */
+ const char *description();
+ };
+
+ /** Schedule cpu to deallocate thread context.*/
+ void scheduleDeallocateContextEvent(int tid, int delay)
+ {
+ // Schedule thread to activate, regardless of its current state.
+ if (deallocateContextEvent[tid].squashed())
+ deallocateContextEvent[tid].reschedule(curTick + cycles(delay));
+ else if (!deallocateContextEvent[tid].scheduled())
+ deallocateContextEvent[tid].schedule(curTick + cycles(delay));
+ }
+
+ /** Unschedule thread deallocation in CPU */
+ void unscheduleDeallocateContextEvent(int tid)
+ {
+ if (deallocateContextEvent[tid].scheduled())
+ deallocateContextEvent[tid].squash();
+ }
+
+ /** The tick event used for scheduling CPU ticks. */
+ DeallocateContextEvent deallocateContextEvent[Impl::MaxThreads];
+
public:
/** Constructs a CPU with the given parameters. */
FullO3CPU(Params *params);
@@ -209,6 +251,9 @@ class FullO3CPU : public BaseO3CPU
/** Registers statistics. */
void fullCPURegStats();
+ /** 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.
*/
@@ -222,7 +267,10 @@ class FullO3CPU : public BaseO3CPU
{ return activeThreads.size(); }
/** Add Thread to Active Threads List */
- void activateThread(unsigned int tid);
+ void activateThread(unsigned tid);
+
+ /** Remove Thread from Active Threads List */
+ void deactivateThread(unsigned tid);
/** Setup CPU to insert a thread's context */
void insertThread(unsigned tid);
@@ -250,7 +298,7 @@ class FullO3CPU : public BaseO3CPU
/** Remove Thread from Active Threads List &&
* Remove Thread Context from CPU.
*/
- void deallocateContext(int tid);
+ void deallocateContext(int tid, int delay = 1);
/** Remove Thread from Active Threads List &&
* Remove Thread Context from CPU.
@@ -266,6 +314,13 @@ class FullO3CPU : public BaseO3CPU
/** Update The Order In Which We Process Threads. */
void updateThreadPriority();
+ /** Serialize state. */
+ virtual void serialize(std::ostream &os);
+
+ /** Unserialize from a checkpoint. */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ public:
/** Executes a syscall on this cycle.
* ---------------------------------------
* Note: this is a virtual function. CPU-Specific
diff --git a/src/cpu/o3/decode.hh b/src/cpu/o3/decode.hh
index 1e96f1884..7f5ecbc26 100644
--- a/src/cpu/o3/decode.hh
+++ b/src/cpu/o3/decode.hh
@@ -110,7 +110,7 @@ class DefaultDecode
void setActiveThreads(std::list<unsigned> *at_ptr);
/** Drains the decode stage. */
- void drain();
+ bool drain();
/** Resumes execution after a drain. */
void resume() { }
diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh
index 71637883b..8b851c032 100644
--- a/src/cpu/o3/decode_impl.hh
+++ b/src/cpu/o3/decode_impl.hh
@@ -165,11 +165,12 @@ DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr)
}
template <class Impl>
-void
+bool
DefaultDecode<Impl>::drain()
{
// Decode is done draining at any time.
cpu->signalDrained();
+ return true;
}
template <class Impl>
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index 9611f0455..85654cebc 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -162,6 +162,9 @@ class DefaultFetch
/** Registers statistics. */
void regStats();
+ /** Returns the icache port. */
+ Port *getIcachePort() { return icachePort; }
+
/** Sets CPU pointer. */
void setCPU(O3CPU *cpu_ptr);
@@ -181,7 +184,7 @@ class DefaultFetch
void processCacheCompletion(PacketPtr pkt);
/** Begins the drain of the fetch stage. */
- void drain();
+ bool drain();
/** Resumes execution after a drain. */
void resume();
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 500b5304e..de883b5ba 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -280,10 +280,6 @@ DefaultFetch<Impl>::setCPU(O3CPU *cpu_ptr)
// Name is finally available, so create the port.
icachePort = new IcachePort(this);
- Port *mem_dport = mem->getPort("");
- icachePort->setPeer(mem_dport);
- mem_dport->setPeer(icachePort);
-
#if USE_CHECKER
if (cpu->checker) {
cpu->checker->setIcachePort(icachePort);
@@ -354,22 +350,23 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
// to return.
if (fetchStatus[tid] != IcacheWaitResponse ||
pkt->req != memReq[tid] ||
- isSwitchedOut() ||
- drainPending) {
+ isSwitchedOut()) {
++fetchIcacheSquashes;
delete pkt->req;
delete pkt;
return;
}
- // Wake up the CPU (if it went to sleep and was waiting on this completion
- // event).
- cpu->wakeCPU();
+ if (!drainPending) {
+ // Wake up the CPU (if it went to sleep and was waiting on
+ // this completion event).
+ cpu->wakeCPU();
- DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n",
- tid);
+ DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n",
+ tid);
- switchToActive();
+ switchToActive();
+ }
// Only switch to IcacheAccessComplete if we're not stalled as well.
if (checkStall(tid)) {
@@ -385,12 +382,13 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
}
template <class Impl>
-void
+bool
DefaultFetch<Impl>::drain()
{
// Fetch is ready to drain at any time.
cpu->signalDrained();
drainPending = true;
+ return true;
}
template <class Impl>
@@ -508,7 +506,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
unsigned flags = 0;
#endif // FULL_SYSTEM
- if (cacheBlocked || (interruptPending && flags == 0) || drainPending) {
+ if (cacheBlocked || (interruptPending && flags == 0)) {
// Hold off fetch from getting new instructions when:
// Cache is blocked, or
// while an interrupt is pending and we're not in PAL mode, or
@@ -908,7 +906,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
//////////////////////////////////////////
int tid = getFetchingThread(fetchPolicy);
- if (tid == -1) {
+ if (tid == -1 || drainPending) {
DPRINTF(Fetch,"There are no more threads available to fetch from.\n");
// Breaks looping condition in tick()
diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh
index 774b6dcbd..fb9afde54 100644
--- a/src/cpu/o3/iew.hh
+++ b/src/cpu/o3/iew.hh
@@ -125,6 +125,9 @@ class DefaultIEW
/** Initializes stage; sends back the number of free IQ and LSQ entries. */
void initStage();
+ /** Returns the dcache port. */
+ Port *getDcachePort() { return ldstQueue.getDcachePort(); }
+
/** Sets CPU pointer for IEW, IQ, and LSQ. */
void setCPU(O3CPU *cpu_ptr);
@@ -144,7 +147,7 @@ class DefaultIEW
void setScoreboard(Scoreboard *sb_ptr);
/** Drains IEW stage. */
- void drain();
+ bool drain();
/** Resumes execution after a drain. */
void resume();
diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
index c3aa748ae..684ae2295 100644
--- a/src/cpu/o3/iew_impl.hh
+++ b/src/cpu/o3/iew_impl.hh
@@ -42,8 +42,7 @@ using namespace std;
template<class Impl>
DefaultIEW<Impl>::DefaultIEW(Params *params)
- : // @todo: Make this into a parameter.
- issueToExecQueue(5, 5),
+ : issueToExecQueue(params->backComSize, params->forwardComSize),
instQueue(params),
ldstQueue(params),
fuPool(params->fuPool),
@@ -354,11 +353,12 @@ DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
}
template <class Impl>
-void
+bool
DefaultIEW<Impl>::drain()
{
// IEW is ready to drain at any time.
cpu->signalDrained();
+ return true;
}
template <class Impl>
@@ -412,7 +412,7 @@ DefaultIEW<Impl>::takeOverFrom()
updateLSQNextCycle = false;
// @todo: Fix hardcoded number
- for (int i = 0; i < 6; ++i) {
+ for (int i = 0; i < issueToExecQueue.getSize(); ++i) {
issueToExecQueue.advance();
}
}
diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh
index 89791fec9..d5890950f 100644
--- a/src/cpu/o3/lsq.hh
+++ b/src/cpu/o3/lsq.hh
@@ -65,6 +65,13 @@ class LSQ {
/** 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 thread[0].getDcachePort(); }
+
/** Sets the pointer to the list of active threads. */
void setActiveThreads(std::list<unsigned> *at_ptr);
/** Sets the CPU pointer. */
diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh
index 5173f8be1..89fd1a71d 100644
--- a/src/cpu/o3/lsq_impl.hh
+++ b/src/cpu/o3/lsq_impl.hh
@@ -502,6 +502,9 @@ LSQ<Impl>::hasStoresToWB()
{
list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ if ((*activeThreads).empty())
+ return false;
+
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
if (!hasStoresToWB(tid))
diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh
index 74b8fe5bb..4d7a8350b 100644
--- a/src/cpu/o3/lsq_unit.hh
+++ b/src/cpu/o3/lsq_unit.hh
@@ -77,6 +77,11 @@ class LSQUnit {
/** Returns the name of the LSQ unit. */
std::string name() const;
+ /** Returns the dcache port.
+ * @todo: Remove this once the port moves up to the LSQ level.
+ */
+ Port *getDcachePort() { return dcachePort; }
+
/** Registers statistics. */
void regStats();
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index bb3da7eec..8e951534f 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -182,10 +182,6 @@ LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr)
cpu = cpu_ptr;
dcachePort = new DcachePort(cpu, this);
- Port *mem_dport = mem->getPort("");
- dcachePort->setPeer(mem_dport);
- mem_dport->setPeer(dcachePort);
-
#if USE_CHECKER
if (cpu->checker) {
cpu->checker->setDcachePort(dcachePort);
diff --git a/src/cpu/o3/params.hh b/src/cpu/o3/params.hh
index ed53fa97a..1c234bcd7 100755
--- a/src/cpu/o3/params.hh
+++ b/src/cpu/o3/params.hh
@@ -115,6 +115,12 @@ class O3Params : public BaseO3CPU::Params
Tick fetchTrapLatency;
//
+ // Timebuffer sizes
+ //
+ unsigned backComSize;
+ unsigned forwardComSize;
+
+ //
// Branch predictor (BP, BTB, RAS)
//
std::string predType;
diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh
index 6972f055f..b6677b4b1 100644
--- a/src/cpu/o3/regfile.hh
+++ b/src/cpu/o3/regfile.hh
@@ -86,10 +86,6 @@ class PhysRegFile
//The duplication is unfortunate but it's better than having
//different ways to access certain registers.
- //Add these in later when everything else is in place
-// void serialize(std::ostream &os);
-// void unserialize(Checkpoint *cp, const std::string &section);
-
/** Reads an integer register. */
uint64_t readIntReg(PhysRegIndex reg_idx)
{
diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh
index 538dd9bb4..034087feb 100644
--- a/src/cpu/o3/rename.hh
+++ b/src/cpu/o3/rename.hh
@@ -158,7 +158,7 @@ class DefaultRename
void setScoreboard(Scoreboard *_scoreboard);
/** Drains the rename stage. */
- void drain();
+ bool drain();
/** Resumes execution after a drain. */
void resume() { }
diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh
index fddbae3db..805a72808 100644
--- a/src/cpu/o3/rename_impl.hh
+++ b/src/cpu/o3/rename_impl.hh
@@ -257,11 +257,12 @@ DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
}
template <class Impl>
-void
+bool
DefaultRename<Impl>::drain()
{
// Rename is ready to switch out at any time.
cpu->signalDrained();
+ return true;
}
template <class Impl>
diff --git a/src/cpu/o3/rob.hh b/src/cpu/o3/rob.hh
index 6f8080ef4..7cd5a5143 100644
--- a/src/cpu/o3/rob.hh
+++ b/src/cpu/o3/rob.hh
@@ -308,7 +308,7 @@ class ROB
private:
/** The sequence number of the squashed instruction. */
- InstSeqNum squashedSeqNum;
+ InstSeqNum squashedSeqNum[Impl::MaxThreads];
/** Is the ROB done squashing. */
bool doneSquashing[Impl::MaxThreads];
diff --git a/src/cpu/o3/rob_impl.hh b/src/cpu/o3/rob_impl.hh
index d9978b17f..1b9f666b8 100644
--- a/src/cpu/o3/rob_impl.hh
+++ b/src/cpu/o3/rob_impl.hh
@@ -41,10 +41,10 @@ ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
: numEntries(_numEntries),
squashWidth(_squashWidth),
numInstsInROB(0),
- squashedSeqNum(0),
numThreads(_numThreads)
{
for (int tid=0; tid < numThreads; tid++) {
+ squashedSeqNum[tid] = 0;
doneSquashing[tid] = true;
threadEntries[tid] = 0;
}
@@ -352,11 +352,11 @@ void
ROB<Impl>::doSquash(unsigned tid)
{
DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n",
- tid, squashedSeqNum);
+ tid, squashedSeqNum[tid]);
assert(squashIt[tid] != instList[tid].end());
- if ((*squashIt[tid])->seqNum < squashedSeqNum) {
+ if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) {
DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
tid);
@@ -371,7 +371,7 @@ ROB<Impl>::doSquash(unsigned tid)
for (int numSquashed = 0;
numSquashed < squashWidth &&
squashIt[tid] != instList[tid].end() &&
- (*squashIt[tid])->seqNum > squashedSeqNum;
+ (*squashIt[tid])->seqNum > squashedSeqNum[tid];
++numSquashed)
{
DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
@@ -408,7 +408,7 @@ ROB<Impl>::doSquash(unsigned tid)
// Check if ROB is done squashing.
- if ((*squashIt[tid])->seqNum <= squashedSeqNum) {
+ if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) {
DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
tid);
@@ -520,7 +520,7 @@ ROB<Impl>::squash(InstSeqNum squash_num,unsigned tid)
doneSquashing[tid] = false;
- squashedSeqNum = squash_num;
+ squashedSeqNum[tid] = squash_num;
if (!instList[tid].empty()) {
InstIt tail_thread = instList[tid].end();
@@ -544,6 +544,7 @@ ROB<Impl>::readHeadInst()
}
}
*/
+
template <class Impl>
typename Impl::DynInstPtr
ROB<Impl>::readHeadInst(unsigned tid)
@@ -558,6 +559,7 @@ ROB<Impl>::readHeadInst(unsigned tid)
return dummyInst;
}
}
+
/*
template <class Impl>
uint64_t
diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh
index d097ee63e..df8d1a6d8 100755
--- a/src/cpu/o3/thread_context.hh
+++ b/src/cpu/o3/thread_context.hh
@@ -112,7 +112,7 @@ class O3ThreadContext : public ThreadContext
virtual void suspend();
/** Set the status to Unallocated. */
- virtual void deallocate();
+ virtual void deallocate(int delay = 0);
/** Set the status to Halted. */
virtual void halt();
diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh
index cfb71f623..bf8cbf850 100755
--- a/src/cpu/o3/thread_context_impl.hh
+++ b/src/cpu/o3/thread_context_impl.hh
@@ -115,7 +115,8 @@ template <class Impl>
void
O3ThreadContext<Impl>::activate(int delay)
{
- DPRINTF(O3CPU, "Calling activate on AlphaTC\n");
+ DPRINTF(O3CPU, "Calling activate on Thread Context %d\n",
+ getThreadNum());
if (thread->status() == ThreadContext::Active)
return;
@@ -139,7 +140,8 @@ template <class Impl>
void
O3ThreadContext<Impl>::suspend()
{
- DPRINTF(O3CPU, "Calling suspend on AlphaTC\n");
+ DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n",
+ getThreadNum());
if (thread->status() == ThreadContext::Suspended)
return;
@@ -163,22 +165,24 @@ O3ThreadContext<Impl>::suspend()
template <class Impl>
void
-O3ThreadContext<Impl>::deallocate()
+O3ThreadContext<Impl>::deallocate(int delay)
{
- DPRINTF(O3CPU, "Calling deallocate on AlphaTC\n");
+ DPRINTF(O3CPU, "Calling deallocate on Thread Context %d\n",
+ getThreadNum());
if (thread->status() == ThreadContext::Unallocated)
return;
thread->setStatus(ThreadContext::Unallocated);
- cpu->deallocateContext(thread->readTid());
+ cpu->deallocateContext(thread->readTid(), delay);
}
template <class Impl>
void
O3ThreadContext<Impl>::halt()
{
- DPRINTF(O3CPU, "Calling halt on AlphaTC\n");
+ DPRINTF(O3CPU, "Calling halt on Thread Context %d\n",
+ getThreadNum());
if (thread->status() == ThreadContext::Halted)
return;
diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh
index 8993781ea..e411c12bd 100644
--- a/src/cpu/ozone/cpu.hh
+++ b/src/cpu/ozone/cpu.hh
@@ -150,7 +150,7 @@ class OzoneCPU : public BaseCPU
void suspend();
/// Set the status to Unallocated.
- void deallocate();
+ void deallocate(int delay = 0);
/// Set the status to Halted.
void halt();
@@ -372,6 +372,8 @@ class OzoneCPU : public BaseCPU
PhysicalMemory *physmem;
#endif
+ virtual Port *getPort(const std::string &name, int idx);
+
MemObject *mem;
FrontEnd *frontEnd;
@@ -383,7 +385,7 @@ class OzoneCPU : public BaseCPU
virtual void activateContext(int thread_num, int delay);
virtual void suspendContext(int thread_num);
- virtual void deallocateContext(int thread_num);
+ virtual void deallocateContext(int thread_num, int delay);
virtual void haltContext(int thread_num);
// statistics
diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh
index ccb1c8418..f58b81990 100644
--- a/src/cpu/ozone/cpu_impl.hh
+++ b/src/cpu/ozone/cpu_impl.hh
@@ -335,7 +335,7 @@ OzoneCPU<Impl>::suspendContext(int thread_num)
template <class Impl>
void
-OzoneCPU<Impl>::deallocateContext(int thread_num)
+OzoneCPU<Impl>::deallocateContext(int thread_num, int delay)
{
// for now, these are equivalent
suspendContext(thread_num);
@@ -419,6 +419,18 @@ OzoneCPU<Impl>::init()
}
template <class Impl>
+Port *
+OzoneCPU<Impl>::getPort(const std::string &if_name, int idx)
+{
+ if (if_name == "dcache_port")
+ return backEnd->getDcachePort();
+ else if (if_name == "icache_port")
+ return frontEnd->getIcachePort();
+ else
+ panic("No Such Port\n");
+}
+
+template <class Impl>
void
OzoneCPU<Impl>::serialize(std::ostream &os)
{
@@ -780,9 +792,9 @@ OzoneCPU<Impl>::OzoneTC::suspend()
/// Set the status to Unallocated.
template <class Impl>
void
-OzoneCPU<Impl>::OzoneTC::deallocate()
+OzoneCPU<Impl>::OzoneTC::deallocate(int delay)
{
- cpu->deallocateContext(thread->readTid());
+ cpu->deallocateContext(thread->readTid(), delay);
}
/// Set the status to Halted.
diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh
index 181609098..3ed3c4d18 100644
--- a/src/cpu/ozone/front_end.hh
+++ b/src/cpu/ozone/front_end.hh
@@ -119,6 +119,8 @@ class FrontEnd
void regStats();
+ Port *getIcachePort() { return &icachePort; }
+
void tick();
Fault fetchCacheLine();
void processInst(DynInstPtr &inst);
diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh
index 40042489d..9da937320 100644
--- a/src/cpu/ozone/front_end_impl.hh
+++ b/src/cpu/ozone/front_end_impl.hh
@@ -36,6 +36,7 @@
#include "cpu/thread_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/ozone/front_end.hh"
+#include "mem/mem_object.hh"
#include "mem/packet.hh"
#include "mem/request.hh"
@@ -138,10 +139,6 @@ FrontEnd<Impl>::setCPU(CPUType *cpu_ptr)
icachePort.setName(this->name() + "-iport");
- Port *mem_dport = mem->getPort("");
- icachePort.setPeer(mem_dport);
- mem_dport->setPeer(&icachePort);
-
#if USE_CHECKER
if (cpu->checker) {
cpu->checker->setIcachePort(&icachePort);
diff --git a/src/cpu/ozone/lw_back_end.hh b/src/cpu/ozone/lw_back_end.hh
index bb3ef3a72..d836ceebd 100644
--- a/src/cpu/ozone/lw_back_end.hh
+++ b/src/cpu/ozone/lw_back_end.hh
@@ -51,6 +51,8 @@ class ThreadContext;
template <class Impl>
class OzoneThreadState;
+class Port;
+
template <class Impl>
class LWBackEnd
{
@@ -114,6 +116,8 @@ class LWBackEnd
void setCommBuffer(TimeBuffer<CommStruct> *_comm);
+ Port *getDcachePort() { return LSQ.getDcachePort(); }
+
void tick();
void squash();
void generateTCEvent() { tcSquash = true; }
diff --git a/src/cpu/ozone/lw_back_end_impl.hh b/src/cpu/ozone/lw_back_end_impl.hh
index a73d3ee6e..a4f1d805e 100644
--- a/src/cpu/ozone/lw_back_end_impl.hh
+++ b/src/cpu/ozone/lw_back_end_impl.hh
@@ -142,7 +142,7 @@ LWBackEnd<Impl>::replayMemInst(DynInstPtr &inst)
template <class Impl>
LWBackEnd<Impl>::LWBackEnd(Params *params)
: d2i(5, 5), i2e(5, 5), e2c(5, 5), numInstsToWB(5, 5),
- trapSquash(false), tcSquash(false), LSQ(params),
+ trapSquash(false), tcSquash(false),
width(params->backEndWidth), exactFullStall(true)
{
numROBEntries = params->numROBEntries;
@@ -557,6 +557,7 @@ LWBackEnd<Impl>::checkInterrupts()
}
}
}
+#endif
template <class Impl>
void
@@ -580,7 +581,6 @@ LWBackEnd<Impl>::handleFault(Fault &fault, Tick latency)
// Generate trap squash event.
generateTrapEvent(latency);
}
-#endif
template <class Impl>
void
@@ -602,6 +602,7 @@ LWBackEnd<Impl>::tick()
#if FULL_SYSTEM
checkInterrupts();
+#endif
if (trapSquash) {
assert(!tcSquash);
@@ -609,7 +610,6 @@ LWBackEnd<Impl>::tick()
} else if (tcSquash) {
squashFromTC();
}
-#endif
if (dispatchStatus != Blocked) {
dispatchInsts();
@@ -1137,13 +1137,9 @@ LWBackEnd<Impl>::commitInst(int inst_num)
thread->setInst(
static_cast<TheISA::MachInst>(inst->staticInst->machInst));
-#if FULL_SYSTEM
+
handleFault(inst_fault);
return false;
-#else // !FULL_SYSTEM
- panic("fault (%d) detected @ PC %08p", inst_fault,
- inst->PC);
-#endif // FULL_SYSTEM
}
int freed_regs = 0;
diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh
index c749e3aee..2eb09d01a 100644
--- a/src/cpu/ozone/lw_lsq.hh
+++ b/src/cpu/ozone/lw_lsq.hh
@@ -91,8 +91,7 @@ class OzoneLWLSQ {
void setBE(BackEnd *be_ptr)
{ be = be_ptr; }
- /** Sets the page table pointer. */
-// void setPageTable(PageTable *pt_ptr);
+ Port *getDcachePort() { return &dcachePort; }
/** Ticks the LSQ unit, which in this case only resets the number of
* used cache ports.
@@ -241,13 +240,11 @@ class OzoneLWLSQ {
class DcachePort : public Port
{
protected:
- OzoneCPU *cpu;
-
OzoneLWLSQ *lsq;
public:
- DcachePort(OzoneCPU *_cpu, OzoneLWLSQ *_lsq)
- : Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq)
+ DcachePort(OzoneLWLSQ *_lsq)
+ : lsq(_lsq)
{ }
protected:
@@ -266,11 +263,8 @@ class OzoneLWLSQ {
virtual void recvRetry();
};
- /** Pointer to the D-cache. */
- DcachePort *dcachePort;
-
- /** Pointer to the page table. */
-// PageTable *pTable;
+ /** D-cache port. */
+ DcachePort dcachePort;
public:
struct SQEntry {
@@ -639,7 +633,7 @@ OzoneLWLSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
data_pkt->senderState = state;
// if we have a cache, do cache access too
- if (!dcachePort->sendTiming(data_pkt)) {
+ if (!dcachePort.sendTiming(data_pkt)) {
// There's an older load that's already going to squash.
if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum)
return NoFault;
diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh
index a65a2a4d3..88e9c218f 100644
--- a/src/cpu/ozone/lw_lsq_impl.hh
+++ b/src/cpu/ozone/lw_lsq_impl.hh
@@ -131,8 +131,9 @@ OzoneLWLSQ<Impl>::completeDataAccess(PacketPtr pkt)
template <class Impl>
OzoneLWLSQ<Impl>::OzoneLWLSQ()
- : switchedOut(false), loads(0), stores(0), storesToWB(0), stalled(false),
- isStoreBlocked(false), isLoadBlocked(false), loadBlockedHandled(false)
+ : switchedOut(false), dcachePort(this), loads(0), stores(0),
+ storesToWB(0), stalled(false), isStoreBlocked(false),
+ isLoadBlocked(false), loadBlockedHandled(false)
{
}
@@ -175,15 +176,11 @@ void
OzoneLWLSQ<Impl>::setCPU(OzoneCPU *cpu_ptr)
{
cpu = cpu_ptr;
- dcachePort = new DcachePort(cpu, this);
-
- Port *mem_dport = mem->getPort("");
- dcachePort->setPeer(mem_dport);
- mem_dport->setPeer(dcachePort);
+ dcachePort.setName(this->name() + "-dport");
#if USE_CHECKER
if (cpu->checker) {
- cpu->checker->setDcachePort(dcachePort);
+ cpu->checker->setDcachePort(&dcachePort);
}
#endif
}
@@ -614,7 +611,7 @@ OzoneLWLSQ<Impl>::writebackStores()
state->noWB = true;
}
- if (!dcachePort->sendTiming(data_pkt)) {
+ if (!dcachePort.sendTiming(data_pkt)) {
// Need to handle becoming blocked on a store.
isStoreBlocked = true;
assert(retryPkt == NULL);
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index b7202cbbb..12bfdeb9b 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -55,18 +55,28 @@ AtomicSimpleCPU::TickEvent::description()
return "AtomicSimpleCPU tick event";
}
+Port *
+AtomicSimpleCPU::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
AtomicSimpleCPU::init()
{
//Create Memory Ports (conect them up)
- Port *mem_dport = mem->getPort("");
- dcachePort.setPeer(mem_dport);
- mem_dport->setPeer(&dcachePort);
+// Port *mem_dport = mem->getPort("");
+// dcachePort.setPeer(mem_dport);
+// mem_dport->setPeer(&dcachePort);
- Port *mem_iport = mem->getPort("");
- icachePort.setPeer(mem_iport);
- mem_iport->setPeer(&icachePort);
+// Port *mem_iport = mem->getPort("");
+// icachePort.setPeer(mem_iport);
+// mem_iport->setPeer(&icachePort);
BaseCPU::init();
#if FULL_SYSTEM
diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh
index 951a8da06..179b4a721 100644
--- a/src/cpu/simple/atomic.hh
+++ b/src/cpu/simple/atomic.hh
@@ -122,6 +122,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU
public:
+ virtual Port *getPort(const std::string &if_name, int idx = -1);
+
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index ad04c8d3b..e55301c6b 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -37,19 +37,20 @@
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()
{
- //Create Memory Ports (conect them up)
- Port *mem_dport = mem->getPort("");
- dcachePort.setPeer(mem_dport);
- mem_dport->setPeer(&dcachePort);
-
- Port *mem_iport = mem->getPort("");
- icachePort.setPeer(mem_iport);
- mem_iport->setPeer(&icachePort);
-
BaseCPU::init();
#if FULL_SYSTEM
for (int i = 0; i < threadContexts.size(); ++i) {
@@ -89,6 +90,7 @@ TimingSimpleCPU::TimingSimpleCPU(Params *p)
_status = Idle;
ifetch_pkt = dcache_pkt = NULL;
drainEvent = NULL;
+ fetchEvent = NULL;
state = SimObject::Timing;
}
@@ -118,11 +120,11 @@ TimingSimpleCPU::drain(Event *drain_event)
// an access to complete.
if (status() == Idle || status() == Running || status() == SwitchedOut) {
changeState(SimObject::DrainedTiming);
- return false;
+ return true;
} else {
changeState(SimObject::Draining);
drainEvent = drain_event;
- return true;
+ return false;
}
}
@@ -130,9 +132,15 @@ void
TimingSimpleCPU::resume()
{
if (_status != SwitchedOut && _status != Idle) {
- Event *e =
- new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, true);
- e->schedule(curTick);
+ // Delete the old event if it existed.
+ if (fetchEvent) {
+ assert(!fetchEvent->scheduled());
+ delete fetchEvent;
+ }
+
+ fetchEvent =
+ new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false);
+ fetchEvent->schedule(curTick);
}
}
@@ -147,6 +155,11 @@ TimingSimpleCPU::switchOut()
{
assert(status() == Running || status() == Idle);
_status = SwitchedOut;
+
+ // If we've been scheduled to resume but are then told to switch out,
+ // we'll need to cancel it.
+ if (fetchEvent && fetchEvent->scheduled())
+ fetchEvent->deschedule();
}
@@ -178,9 +191,9 @@ TimingSimpleCPU::activateContext(int thread_num, int delay)
notIdleFraction++;
_status = Running;
// kick things off by initiating the fetch of the next instruction
- Event *e =
- new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, true);
- e->schedule(curTick + cycles(delay));
+ fetchEvent =
+ new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false);
+ fetchEvent->schedule(curTick + cycles(delay));
}
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index c360e553e..0a3f91e6c 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -66,6 +66,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
Event *drainEvent;
+ Event *fetchEvent;
+
private:
class CpuPort : public Port
@@ -130,6 +132,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
public:
+ virtual Port *getPort(const std::string &if_name, int idx = -1);
+
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc
index db28b23e8..af1db2ff2 100644
--- a/src/cpu/simple_thread.cc
+++ b/src/cpu/simple_thread.cc
@@ -123,15 +123,19 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num,
tc = new ProxyThreadContext<SimpleThread>(this);
}
-SimpleThread::SimpleThread(RegFile *regFile)
- : ThreadState(-1, -1, NULL, -1, NULL), cpu(NULL)
+#endif
+
+SimpleThread::SimpleThread()
+#if FULL_SYSTEM
+ : ThreadState(-1, -1)
+#else
+ : ThreadState(-1, -1, NULL, -1, NULL)
+#endif
{
- regs = *regFile;
tc = new ProxyThreadContext<SimpleThread>(this);
+ regs.clear();
}
-#endif
-
SimpleThread::~SimpleThread()
{
delete tc;
@@ -147,13 +151,8 @@ SimpleThread::takeOverFrom(ThreadContext *oldContext)
assert(process == oldContext->getProcessPtr());
#endif
- // copy over functional state
- _status = oldContext->status();
- copyArchRegs(oldContext);
- cpuId = oldContext->readCpuId();
-#if !FULL_SYSTEM
- funcExeInst = oldContext->readFuncExeInst();
-#else
+ copyState(oldContext);
+#if FULL_SYSTEM
EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
if (quiesce) {
// Point the quiesce event's TC at this TC so that it wakes up
@@ -171,42 +170,49 @@ SimpleThread::takeOverFrom(ThreadContext *oldContext)
}
void
-SimpleThread::serialize(ostream &os)
+SimpleThread::copyTC(ThreadContext *context)
{
- SERIALIZE_ENUM(_status);
- regs.serialize(os);
- // thread_num and cpu_id are deterministic from the config
- SERIALIZE_SCALAR(funcExeInst);
- SERIALIZE_SCALAR(inst);
+ copyState(context);
#if FULL_SYSTEM
- Tick quiesceEndTick = 0;
- if (quiesceEvent->scheduled())
- quiesceEndTick = quiesceEvent->when();
- SERIALIZE_SCALAR(quiesceEndTick);
- if (kernelStats)
- kernelStats->serialize(os);
+ EndQuiesceEvent *quiesce = context->getQuiesceEvent();
+ if (quiesce) {
+ quiesceEvent = quiesce;
+ }
+ Kernel::Statistics *stats = context->getKernelStats();
+ if (stats) {
+ kernelStats = stats;
+ }
#endif
}
+void
+SimpleThread::copyState(ThreadContext *oldContext)
+{
+ // copy over functional state
+ _status = oldContext->status();
+ copyArchRegs(oldContext);
+ cpuId = oldContext->readCpuId();
+#if !FULL_SYSTEM
+ funcExeInst = oldContext->readFuncExeInst();
+#endif
+}
+
+void
+SimpleThread::serialize(ostream &os)
+{
+ ThreadState::serialize(os);
+ regs.serialize(os);
+ // thread_num and cpu_id are deterministic from the config
+}
+
void
SimpleThread::unserialize(Checkpoint *cp, const std::string &section)
{
- UNSERIALIZE_ENUM(_status);
+ ThreadState::unserialize(cp, section);
regs.unserialize(cp, section);
// thread_num and cpu_id are deterministic from the config
- UNSERIALIZE_SCALAR(funcExeInst);
- UNSERIALIZE_SCALAR(inst);
-
-#if FULL_SYSTEM
- Tick quiesceEndTick;
- UNSERIALIZE_SCALAR(quiesceEndTick);
- if (quiesceEndTick)
- quiesceEvent->schedule(quiesceEndTick);
- if (kernelStats)
- kernelStats->unserialize(cp, section);
-#endif
}
#if FULL_SYSTEM
diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh
index de65e9891..d36853db4 100644
--- a/src/cpu/simple_thread.hh
+++ b/src/cpu/simple_thread.hh
@@ -119,16 +119,20 @@ class SimpleThread : public ThreadState
#else
SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid,
MemObject *memobj);
- // Constructor to use SimpleThread to pass reg file around. Not
- // used for anything else.
- SimpleThread(RegFile *regFile);
#endif
+
+ SimpleThread();
+
virtual ~SimpleThread();
virtual void takeOverFrom(ThreadContext *oldContext);
void regStats(const std::string &name);
+ void copyTC(ThreadContext *context);
+
+ void copyState(ThreadContext *oldContext);
+
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh
index 70d705144..e019e22bc 100644
--- a/src/cpu/thread_context.hh
+++ b/src/cpu/thread_context.hh
@@ -143,7 +143,7 @@ class ThreadContext
virtual void suspend() = 0;
/// Set the status to Unallocated.
- virtual void deallocate() = 0;
+ virtual void deallocate(int delay = 0) = 0;
/// Set the status to Halted.
virtual void halt() = 0;
@@ -318,7 +318,7 @@ class ProxyThreadContext : public ThreadContext
void suspend() { actualTC->suspend(); }
/// Set the status to Unallocated.
- void deallocate() { actualTC->deallocate(); }
+ void deallocate(int delay = 0) { actualTC->deallocate(); }
/// Set the status to Halted.
void halt() { actualTC->halt(); }
diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc
index 872678a41..6a96560f1 100644
--- a/src/cpu/thread_state.cc
+++ b/src/cpu/thread_state.cc
@@ -31,6 +31,12 @@
#include "base/output.hh"
#include "cpu/profile.hh"
#include "cpu/thread_state.hh"
+#include "sim/serialize.hh"
+
+#if FULL_SYSTEM
+#include "cpu/quiesce_event.hh"
+#include "kern/kernel_stats.hh"
+#endif
#if FULL_SYSTEM
ThreadState::ThreadState(int _cpuId, int _tid)
@@ -49,6 +55,43 @@ ThreadState::ThreadState(int _cpuId, int _tid, Process *_process,
numLoad = 0;
}
+void
+ThreadState::serialize(std::ostream &os)
+{
+ SERIALIZE_ENUM(_status);
+ // thread_num and cpu_id are deterministic from the config
+ SERIALIZE_SCALAR(funcExeInst);
+ SERIALIZE_SCALAR(inst);
+
+#if FULL_SYSTEM
+ Tick quiesceEndTick = 0;
+ if (quiesceEvent->scheduled())
+ quiesceEndTick = quiesceEvent->when();
+ SERIALIZE_SCALAR(quiesceEndTick);
+ if (kernelStats)
+ kernelStats->serialize(os);
+#endif
+}
+
+void
+ThreadState::unserialize(Checkpoint *cp, const std::string &section)
+{
+
+ UNSERIALIZE_ENUM(_status);
+ // thread_num and cpu_id are deterministic from the config
+ UNSERIALIZE_SCALAR(funcExeInst);
+ UNSERIALIZE_SCALAR(inst);
+
+#if FULL_SYSTEM
+ Tick quiesceEndTick;
+ UNSERIALIZE_SCALAR(quiesceEndTick);
+ if (quiesceEndTick)
+ quiesceEvent->schedule(quiesceEndTick);
+ if (kernelStats)
+ kernelStats->unserialize(cp, section);
+#endif
+}
+
#if FULL_SYSTEM
void
diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh
index cb1449ac5..b03a2e2bb 100644
--- a/src/cpu/thread_state.hh
+++ b/src/cpu/thread_state.hh
@@ -49,6 +49,8 @@ namespace Kernel {
};
#endif
+class Checkpoint;
+
/**
* Struct for holding general thread state that is needed across CPU
* models. This includes things such as pointers to the process,
@@ -65,6 +67,10 @@ struct ThreadState {
short _asid, MemObject *mem);
#endif
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+
void setCpuId(int id) { cpuId = id; }
int readCpuId() { return cpuId; }
diff --git a/src/dev/tsunami_pchip.hh b/src/dev/tsunami_pchip.hh
index b9e900526..2c97a1fea 100644
--- a/src/dev/tsunami_pchip.hh
+++ b/src/dev/tsunami_pchip.hh
@@ -46,7 +46,7 @@ class TsunamiPChip : public BasicPioDevice
{
protected:
- static const Addr TsunamiPciBus0Config = 0x801fe000000;
+ static const Addr TsunamiPciBus0Config = ULL(0x801fe000000);
/** Pchip control register */
uint64_t pctl;
diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc
index 15a21efa1..451da28e8 100644
--- a/src/mem/cache/base_cache.cc
+++ b/src/mem/cache/base_cache.cc
@@ -59,7 +59,7 @@ void
BaseCache::CachePort::getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
{
- cache->getAddressRanges(resp, snoop);
+ cache->getAddressRanges(resp, snoop, isCpuSide);
}
int
@@ -117,10 +117,29 @@ BaseCache::CacheEvent::process()
if (!pkt)
{
if (!cachePort->isCpuSide)
+ {
pkt = cachePort->cache->getPacket();
- //Else get coherence req
+ bool success = cachePort->sendTiming(pkt);
+ DPRINTF(Cache, "Address %x was %s in sending the timing request\n",
+ pkt->getAddr(), success ? "succesful" : "unsuccesful");
+ cachePort->cache->sendResult(pkt, success);
+ if (success && cachePort->cache->doMasterRequest())
+ {
+ //Still more to issue, rerequest in 1 cycle
+ pkt = NULL;
+ this->schedule(curTick+1);
+ }
+ }
+ else
+ {
+ pkt = cachePort->cache->getCoherencePacket();
+ cachePort->sendTiming(pkt);
+ }
+ return;
}
- cachePort->sendTiming(pkt);
+ //Know the packet to send, no need to mark in service (must succed)
+ bool success = cachePort->sendTiming(pkt);
+ assert(success);
}
const char *
@@ -138,7 +157,13 @@ BaseCache::getPort(const std::string &if_name, int idx)
cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true);
return cpuSidePort;
}
- if (if_name == "functional")
+ else if (if_name == "functional")
+ {
+ if(cpuSidePort == NULL)
+ cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true);
+ return cpuSidePort;
+ }
+ else if (if_name == "cpu_side")
{
if(cpuSidePort == NULL)
cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true);
@@ -155,6 +180,14 @@ BaseCache::getPort(const std::string &if_name, int idx)
}
void
+BaseCache::init()
+{
+ if (!cpuSidePort || !memSidePort)
+ panic("Cache not hooked up on both sides\n");
+ cpuSidePort->sendStatusChange(Port::RangeChange);
+}
+
+void
BaseCache::regStats()
{
Request temp_req((Addr) NULL, 4, 0);
diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh
index 5370a73c8..0d1bfdfdb 100644
--- a/src/mem/cache/base_cache.hh
+++ b/src/mem/cache/base_cache.hh
@@ -143,9 +143,19 @@ class BaseCache : public MemObject
fatal("No implementation");
}
- virtual void recvStatusChange(Port::Status status, bool isCpuSide)
+ void recvStatusChange(Port::Status status, bool isCpuSide)
{
- fatal("No implementation");
+ if (status == Port::RangeChange)
+ {
+ if (!isCpuSide)
+ {
+ cpuSidePort->sendStatusChange(Port::RangeChange);
+ }
+ else
+ {
+ memSidePort->sendStatusChange(Port::RangeChange);
+ }
+ }
}
virtual Packet *getPacket()
@@ -153,6 +163,17 @@ class BaseCache : public MemObject
fatal("No implementation");
}
+ virtual Packet *getCoherencePacket()
+ {
+ fatal("No implementation");
+ }
+
+ virtual void sendResult(Packet* &pkt, bool success)
+ {
+
+ fatal("No implementation");
+ }
+
/**
* Bit vector of the blocking reasons for the access path.
* @sa #BlockedCause
@@ -309,6 +330,8 @@ class BaseCache : public MemObject
memSidePort = NULL;
}
+ virtual void init();
+
/**
* Query block size of a cache.
* @return The block size
@@ -508,9 +531,18 @@ class BaseCache : public MemObject
*/
void rangeChange() {}
- void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
+ void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop, bool isCpuSide)
{
- panic("Unimplimented\n");
+ if (isCpuSide)
+ {
+ AddrRangeList dummy;
+ memSidePort->getPeerAddressRanges(resp, dummy);
+ }
+ else
+ {
+ //This is where snoops get updated
+ return;
+ }
}
};
diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh
index 2e77444a0..ec5b800a8 100644
--- a/src/mem/cache/cache.hh
+++ b/src/mem/cache/cache.hh
@@ -175,7 +175,7 @@ class Cache : public BaseCache
* @param req The request.
* @param success True if the request was sent successfully.
*/
- void sendResult(Packet * &pkt, bool success);
+ virtual void sendResult(Packet * &pkt, bool success);
/**
* Handles a response (cache line fill/write ack) from the bus.
@@ -202,7 +202,7 @@ class Cache : public BaseCache
* Selects a coherence message to forward to lower levels of the hierarchy.
* @return The coherence message to forward.
*/
- Packet * getCoherenceReq();
+ virtual Packet * getCoherencePacket();
/**
* Snoops bus transactions to maintain coherence.
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index aae5cbf01..a447ae3d5 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -350,7 +350,7 @@ Cache<TagStore,Buffering,Coherence>::pseudoFill(MSHR *mshr)
template<class TagStore, class Buffering, class Coherence>
Packet *
-Cache<TagStore,Buffering,Coherence>::getCoherenceReq()
+Cache<TagStore,Buffering,Coherence>::getCoherencePacket()
{
return coherence->getPacket();
}
diff --git a/src/mem/cache/miss/miss_queue.cc b/src/mem/cache/miss/miss_queue.cc
index da0448ad3..4a3dc1062 100644
--- a/src/mem/cache/miss/miss_queue.cc
+++ b/src/mem/cache/miss/miss_queue.cc
@@ -352,7 +352,7 @@ MissQueue::setPrefetcher(BasePrefetcher *_prefetcher)
MSHR*
MissQueue::allocateMiss(Packet * &pkt, int size, Tick time)
{
- MSHR* mshr = mq.allocate(pkt, size);
+ MSHR* mshr = mq.allocate(pkt, blkSize);
mshr->order = order++;
if (!pkt->req->isUncacheable() ){//&& !pkt->isNoAllocate()) {
// Mark this as a cache line fill
@@ -372,7 +372,7 @@ MissQueue::allocateMiss(Packet * &pkt, int size, Tick time)
MSHR*
MissQueue::allocateWrite(Packet * &pkt, int size, Tick time)
{
- MSHR* mshr = wb.allocate(pkt,pkt->getSize());
+ MSHR* mshr = wb.allocate(pkt,blkSize);
mshr->order = order++;
//REMOVING COMPRESSION FOR NOW
@@ -446,11 +446,11 @@ MissQueue::handleMiss(Packet * &pkt, int blkSize, Tick time)
/**
* @todo Add write merging here.
*/
- mshr = allocateWrite(pkt, pkt->getSize(), time);
+ mshr = allocateWrite(pkt, blkSize, time);
return;
}
- mshr = allocateMiss(pkt, size, time);
+ mshr = allocateMiss(pkt, blkSize, time);
}
MSHR*
diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc
index 1a85d3018..db2f40c56 100644
--- a/src/mem/cache/miss/mshr.cc
+++ b/src/mem/cache/miss/mshr.cc
@@ -57,6 +57,7 @@ void
MSHR::allocate(Packet::Command cmd, Addr _addr, int _asid, int size,
Packet * &target)
{
+ addr = _addr;
if (target)
{
//Have a request, just use it
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index 2b97ab0c1..534db0077 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -183,19 +183,19 @@ class Packet
ReadReq = IsRead | IsRequest | NeedsResponse,
WriteReq = IsWrite | IsRequest | NeedsResponse,
WriteReqNoAck = IsWrite | IsRequest,
- ReadResp = IsRead | IsResponse,
- WriteResp = IsWrite | IsResponse,
+ ReadResp = IsRead | IsResponse | NeedsResponse,
+ WriteResp = IsWrite | IsResponse | NeedsResponse,
Writeback = IsWrite | IsRequest,
SoftPFReq = IsRead | IsRequest | IsSWPrefetch | NeedsResponse,
HardPFReq = IsRead | IsRequest | IsHWPrefetch | NeedsResponse,
- SoftPFResp = IsRead | IsRequest | IsSWPrefetch | IsResponse,
- HardPFResp = IsRead | IsRequest | IsHWPrefetch | IsResponse,
+ SoftPFResp = IsRead | IsResponse | IsSWPrefetch | NeedsResponse,
+ HardPFResp = IsRead | IsResponse | IsHWPrefetch | NeedsResponse,
InvalidateReq = IsInvalidate | IsRequest,
WriteInvalidateReq = IsWrite | IsInvalidate | IsRequest,
- UpgradeReq = IsInvalidate | NeedsResponse,
- UpgradeResp = IsInvalidate | IsResponse,
- ReadExReq = IsRead | IsInvalidate | NeedsResponse,
- ReadExResp = IsRead | IsInvalidate | IsResponse
+ UpgradeReq = IsInvalidate | IsRequest | NeedsResponse,
+ UpgradeResp = IsInvalidate | IsResponse | NeedsResponse,
+ ReadExReq = IsRead | IsInvalidate | IsRequest | NeedsResponse,
+ ReadExResp = IsRead | IsInvalidate | IsResponse | NeedsResponse
};
/** Return the string name of the cmd field (for debugging and
@@ -247,7 +247,7 @@ class Packet
Addr getAddr() const { assert(addrSizeValid); return addr; }
int getSize() const { assert(addrSizeValid); return size; }
- Addr getOffset(int blkSize) const { return req->getPaddr() & (Addr)(blkSize - 1); }
+ Addr getOffset(int blkSize) const { return addr & (Addr)(blkSize - 1); }
void addrOverride(Addr newAddr) { assert(addrSizeValid); addr = newAddr; }
void cmdOverride(Command newCmd) { cmd = newCmd; }
@@ -311,8 +311,9 @@ class Packet
* should not be called. */
void makeTimingResponse() {
assert(needsResponse());
+ assert(isRequest());
int icmd = (int)cmd;
- icmd &= ~(IsRequest | NeedsResponse);
+ icmd &= ~(IsRequest);
icmd |= IsResponse;
cmd = (Command)icmd;
dest = src;
diff --git a/src/python/SConscript b/src/python/SConscript
index 3a9def9a8..c9e713199 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -75,16 +75,27 @@ def addPkg(pkgdir):
# build_env flags.
def MakeDefinesPyFile(target, source, env):
f = file(str(target[0]), 'w')
- print >>f, "m5_build_env = ",
- print >>f, source[0]
+ print >>f, "m5_build_env = ", source[0]
f.close()
optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
env.Command('m5/defines.py', Value(optionDict), MakeDefinesPyFile)
+def MakeInfoPyFile(target, source, env):
+ f = file(str(target[0]), 'w')
+ for src in source:
+ data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
+ print >>f, "%s = %s" % (src, repr(data))
+ f.close()
+
+env.Command('m5/info.py',
+ [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
+ MakeInfoPyFile)
+
# Now specify the packages & files for the zip archive.
addPkg('m5')
pyzip_files.append('m5/defines.py')
+pyzip_files.append('m5/info.py')
pyzip_files.append(join(env['ROOT'], 'util/pbs/jobfile.py'))
env.Command(['swig/cc_main_wrap.cc', 'm5/cc_main.py'],
diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py
index 579785a46..3d0e3defa 100644
--- a/src/python/m5/__init__.py
+++ b/src/python/m5/__init__.py
@@ -27,14 +27,14 @@
# Authors: Nathan Binkert
# Steve Reinhardt
-import sys, os, time, atexit, optparse
+import atexit, os, sys
# import the SWIG-wrapped main C++ functions
import cc_main
# import a few SWIG-wrapped items (those that are likely to be used
# directly by user scripts) completely into this module for
# convenience
-from cc_main import simulate, SimLoopExitEvent, setCheckpointDir
+from cc_main import simulate, SimLoopExitEvent
# import the m5 compile options
import defines
@@ -57,111 +57,6 @@ def AddToPath(path):
# so place the new dir right after that.
sys.path.insert(1, path)
-
-# The m5 module's pointer to the parsed options object
-options = None
-
-
-# User should call this function after calling parse_args() to pass
-# parsed standard option values back into the m5 module for
-# processing.
-def setStandardOptions(_options):
- # Set module global var
- global options
- options = _options
- # tell C++ about output directory
- cc_main.setOutputDir(options.outdir)
-
-# Callback to set trace flags. Not necessarily the best way to do
-# things in the long run (particularly if we change how these global
-# options are handled).
-def setTraceFlags(option, opt_str, value, parser):
- objects.Trace.flags = value
-
-def setTraceStart(option, opt_str, value, parser):
- objects.Trace.start = value
-
-def setTraceFile(option, opt_str, value, parser):
- objects.Trace.file = value
-
-def noPCSymbol(option, opt_str, value, parser):
- objects.ExecutionTrace.pc_symbol = False
-
-def noPrintCycle(option, opt_str, value, parser):
- objects.ExecutionTrace.print_cycle = False
-
-def noPrintOpclass(option, opt_str, value, parser):
- objects.ExecutionTrace.print_opclass = False
-
-def noPrintThread(option, opt_str, value, parser):
- objects.ExecutionTrace.print_thread = False
-
-def noPrintEA(option, opt_str, value, parser):
- objects.ExecutionTrace.print_effaddr = False
-
-def noPrintData(option, opt_str, value, parser):
- objects.ExecutionTrace.print_data = False
-
-def printFetchseq(option, opt_str, value, parser):
- objects.ExecutionTrace.print_fetchseq = True
-
-def printCpseq(option, opt_str, value, parser):
- objects.ExecutionTrace.print_cpseq = True
-
-def dumpOnExit(option, opt_str, value, parser):
- objects.Trace.dump_on_exit = True
-
-def debugBreak(option, opt_str, value, parser):
- objects.Debug.break_cycles = value
-
-def statsTextFile(option, opt_str, value, parser):
- objects.Statistics.text_file = value
-
-# Standard optparse options. Need to be explicitly included by the
-# user script when it calls optparse.OptionParser().
-standardOptions = [
- optparse.make_option("--outdir", type="string", default="."),
- optparse.make_option("--traceflags", type="string", action="callback",
- callback=setTraceFlags),
- optparse.make_option("--tracestart", type="int", action="callback",
- callback=setTraceStart),
- optparse.make_option("--tracefile", type="string", action="callback",
- callback=setTraceFile),
- optparse.make_option("--nopcsymbol",
- action="callback", callback=noPCSymbol,
- help="Disable PC symbols in trace output"),
- optparse.make_option("--noprintcycle",
- action="callback", callback=noPrintCycle,
- help="Don't print cycle numbers in trace output"),
- optparse.make_option("--noprintopclass",
- action="callback", callback=noPrintOpclass,
- help="Don't print op class type in trace output"),
- optparse.make_option("--noprintthread",
- action="callback", callback=noPrintThread,
- help="Don't print thread number in trace output"),
- optparse.make_option("--noprinteffaddr",
- action="callback", callback=noPrintEA,
- help="Don't print effective address in trace output"),
- optparse.make_option("--noprintdata",
- action="callback", callback=noPrintData,
- help="Don't print result data in trace output"),
- optparse.make_option("--printfetchseq",
- action="callback", callback=printFetchseq,
- help="Print fetch sequence numbers in trace output"),
- optparse.make_option("--printcpseq",
- action="callback", callback=printCpseq,
- help="Print correct path sequence numbers in trace output"),
- optparse.make_option("--dumponexit",
- action="callback", callback=dumpOnExit,
- help="Dump trace buffer on exit"),
- optparse.make_option("--debugbreak", type="int", metavar="CYCLE",
- action="callback", callback=debugBreak,
- help="Cycle to create a breakpoint"),
- optparse.make_option("--statsfile", type="string", action="callback",
- callback=statsTextFile, metavar="FILE",
- help="Sets the output file for the statistics")
- ]
-
# make a SmartDict out of the build options for our local use
import smartdict
build_env = smartdict.SmartDict()
@@ -171,12 +66,13 @@ build_env.update(defines.m5_build_env)
env = smartdict.SmartDict()
env.update(os.environ)
-
# Function to provide to C++ so it can look up instances based on paths
def resolveSimObject(name):
obj = config.instanceDict[name]
return obj.getCCObject()
+from main import options, arguments, main
+
# The final hook to generate .ini files. Called from the user script
# once the config is built.
def instantiate(root):
@@ -213,29 +109,44 @@ atexit.register(cc_main.doExitCleanup)
# matter since most scripts will probably 'from m5.objects import *'.
import objects
+# This loops until all objects have been fully drained.
def doDrain(root):
+ all_drained = drain(root)
+ while (not all_drained):
+ all_drained = drain(root)
+
+# Tries to drain all objects. Draining might not be completed unless
+# all objects return that they are drained on the first call. This is
+# because as objects drain they may cause other objects to no longer
+# be drained.
+def drain(root):
+ all_drained = False
drain_event = cc_main.createCountedDrain()
unready_objects = root.startDrain(drain_event, True)
# If we've got some objects that can't drain immediately, then simulate
if unready_objects > 0:
drain_event.setCount(unready_objects)
simulate()
+ else:
+ all_drained = True
cc_main.cleanupCountedDrain(drain_event)
+ return all_drained
def resume(root):
root.resume()
-def checkpoint(root):
+def checkpoint(root, dir):
if not isinstance(root, objects.Root):
raise TypeError, "Object is not a root object. Checkpoint must be called on a root object."
doDrain(root)
print "Writing checkpoint"
- cc_main.serializeAll()
+ cc_main.serializeAll(dir)
resume(root)
-def restoreCheckpoint(root):
+def restoreCheckpoint(root, dir):
print "Restoring from checkpoint"
- cc_main.unserializeAll()
+ cc_main.unserializeAll(dir)
+ resume(root)
def changeToAtomic(system):
if not isinstance(system, objects.Root) and not isinstance(system, System):
diff --git a/src/python/m5/attrdict.py b/src/python/m5/attrdict.py
new file mode 100644
index 000000000..4ee7f1b8c
--- /dev/null
+++ b/src/python/m5/attrdict.py
@@ -0,0 +1,61 @@
+# Copyright (c) 2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+__all__ = [ 'attrdict' ]
+
+class attrdict(dict):
+ def __getattr__(self, attr):
+ if attr in self:
+ return self.__getitem__(attr)
+ return super(attrdict, self).__getattribute__(attr)
+
+ def __setattr__(self, attr, value):
+ if attr in dir(self):
+ return super(attrdict, self).__setattr__(attr, value)
+ return self.__setitem__(attr, value)
+
+ def __delattr__(self, attr):
+ if attr in self:
+ return self.__delitem__(attr)
+ return super(attrdict, self).__delattr__(attr, value)
+
+if __name__ == '__main__':
+ x = attrdict()
+ x.y = 1
+ x['z'] = 2
+ print x['y'], x.y
+ print x['z'], x.z
+ print dir(x)
+ print x
+
+ print
+
+ del x['y']
+ del x.z
+ print dir(x)
+ print(x)
diff --git a/src/python/m5/main.py b/src/python/m5/main.py
new file mode 100644
index 000000000..904b241ca
--- /dev/null
+++ b/src/python/m5/main.py
@@ -0,0 +1,307 @@
+# Copyright (c) 2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+import code, optparse, os, socket, sys
+from datetime import datetime
+from attrdict import attrdict
+
+try:
+ import info
+except ImportError:
+ info = None
+
+__all__ = [ 'options', 'arguments', 'main' ]
+
+usage="%prog [m5 options] script.py [script options]"
+version="%prog 2.0"
+brief_copyright='''
+Copyright (c) 2001-2006
+The Regents of The University of Michigan
+All Rights Reserved
+'''
+
+# there's only one option parsing done, so make it global and add some
+# helper functions to make it work well.
+parser = optparse.OptionParser(usage=usage, version=version,
+ description=brief_copyright,
+ formatter=optparse.TitledHelpFormatter())
+parser.disable_interspersed_args()
+
+# current option group
+group = None
+
+def set_group(*args, **kwargs):
+ '''set the current option group'''
+ global group
+ if not args and not kwargs:
+ group = None
+ else:
+ group = parser.add_option_group(*args, **kwargs)
+
+class splitter(object):
+ def __init__(self, split):
+ self.split = split
+ def __call__(self, option, opt_str, value, parser):
+ getattr(parser.values, option.dest).extend(value.split(self.split))
+
+def add_option(*args, **kwargs):
+ '''add an option to the current option group, or global none set'''
+
+ # if action=split, but allows the option arguments
+ # themselves to be lists separated by the split variable'''
+
+ if kwargs.get('action', None) == 'append' and 'split' in kwargs:
+ split = kwargs.pop('split')
+ kwargs['default'] = []
+ kwargs['type'] = 'string'
+ kwargs['action'] = 'callback'
+ kwargs['callback'] = splitter(split)
+
+ if group:
+ return group.add_option(*args, **kwargs)
+
+ return parser.add_option(*args, **kwargs)
+
+def bool_option(name, default, help):
+ '''add a boolean option called --name and --no-name.
+ Display help depending on which is the default'''
+
+ tname = '--%s' % name
+ fname = '--no-%s' % name
+ dest = name.replace('-', '_')
+ if default:
+ thelp = optparse.SUPPRESS_HELP
+ fhelp = help
+ else:
+ thelp = help
+ fhelp = optparse.SUPPRESS_HELP
+
+ add_option(tname, action="store_true", default=default, help=thelp)
+ add_option(fname, action="store_false", dest=dest, help=fhelp)
+
+# Help options
+add_option('-A', "--authors", action="store_true", default=False,
+ help="Show author information")
+add_option('-C', "--copyright", action="store_true", default=False,
+ help="Show full copyright information")
+add_option('-R', "--readme", action="store_true", default=False,
+ help="Show the readme")
+add_option('-N', "--release-notes", action="store_true", default=False,
+ help="Show the release notes")
+
+# Options for configuring the base simulator
+add_option('-d', "--outdir", metavar="DIR", default=".",
+ help="Set the output directory to DIR [Default: %default]")
+add_option('-i', "--interactive", action="store_true", default=False,
+ help="Invoke the interactive interpreter after running the script")
+add_option('-p', "--path", metavar="PATH[:PATH]", action='append', split=':',
+ help="Prepend PATH to the system path when invoking the script")
+add_option('-q', "--quiet", action="count", default=0,
+ help="Reduce verbosity")
+add_option('-v', "--verbose", action="count", default=0,
+ help="Increase verbosity")
+
+# Statistics options
+set_group("Statistics Options")
+add_option("--stats-file", metavar="FILE", default="m5stats.txt",
+ help="Sets the output file for statistics [Default: %default]")
+
+# Debugging options
+set_group("Debugging Options")
+add_option("--debug-break", metavar="TIME[,TIME]", action='append', split=',',
+ help="Cycle to create a breakpoint")
+
+# Tracing options
+set_group("Trace Options")
+add_option("--trace-flags", metavar="FLAG[,FLAG]", action='append', split=',',
+ help="Sets the flags for tracing")
+add_option("--trace-start", metavar="TIME", default='0s',
+ help="Start tracing at TIME (must have units)")
+add_option("--trace-file", metavar="FILE", default="cout",
+ help="Sets the output file for tracing [Default: %default]")
+add_option("--trace-circlebuf", metavar="SIZE", type="int", default=0,
+ help="If SIZE is non-zero, turn on the circular buffer with SIZE lines")
+add_option("--no-trace-circlebuf", action="store_const", const=0,
+ dest='trace_circlebuf', help=optparse.SUPPRESS_HELP)
+bool_option("trace-dumponexit", default=False,
+ help="Dump trace buffer on exit")
+add_option("--trace-ignore", metavar="EXPR", action='append', split=':',
+ help="Ignore EXPR sim objects")
+
+# Execution Trace options
+set_group("Execution Trace Options")
+bool_option("speculative", default=True,
+ help="Don't capture speculative instructions")
+bool_option("print-cycle", default=True,
+ help="Don't print cycle numbers in trace output")
+bool_option("print-symbol", default=True,
+ help="Disable PC symbols in trace output")
+bool_option("print-opclass", default=True,
+ help="Don't print op class type in trace output")
+bool_option("print-thread", default=True,
+ help="Don't print thread number in trace output")
+bool_option("print-effaddr", default=True,
+ help="Don't print effective address in trace output")
+bool_option("print-data", default=True,
+ help="Don't print result data in trace output")
+bool_option("print-iregs", default=False,
+ help="Print fetch sequence numbers in trace output")
+bool_option("print-fetch-seq", default=False,
+ help="Print fetch sequence numbers in trace output")
+bool_option("print-cpseq", default=False,
+ help="Print correct path sequence numbers in trace output")
+
+options = attrdict()
+arguments = []
+
+def usage(exitcode=None):
+ print parser.help
+ if exitcode is not None:
+ sys.exit(exitcode)
+
+def parse_args():
+ _opts,args = parser.parse_args()
+ opts = attrdict(_opts.__dict__)
+
+ # setting verbose and quiet at the same time doesn't make sense
+ if opts.verbose > 0 and opts.quiet > 0:
+ usage(2)
+
+ # store the verbosity in a single variable. 0 is default,
+ # negative numbers represent quiet and positive values indicate verbose
+ opts.verbose -= opts.quiet
+
+ del opts.quiet
+
+ options.update(opts)
+ arguments.extend(args)
+ return opts,args
+
+def main():
+ import cc_main
+
+ parse_args()
+
+ done = False
+ if options.copyright:
+ done = True
+ print info.LICENSE
+ print
+
+ if options.authors:
+ done = True
+ print 'Author information:'
+ print
+ print info.AUTHORS
+ print
+
+ if options.readme:
+ done = True
+ print 'Readme:'
+ print
+ print info.README
+ print
+
+ if options.release_notes:
+ done = True
+ print 'Release Notes:'
+ print
+ print info.RELEASE_NOTES
+ print
+
+ if done:
+ sys.exit(0)
+
+ if options.verbose >= 0:
+ print "M5 Simulator System"
+ print brief_copyright
+ print
+ print "M5 compiled %s" % cc_main.cvar.compileDate;
+ print "M5 started %s" % datetime.now().ctime()
+ print "M5 executing on %s" % socket.gethostname()
+
+ # check to make sure we can find the listed script
+ if not arguments or not os.path.isfile(arguments[0]):
+ usage(2)
+
+ # tell C++ about output directory
+ cc_main.setOutputDir(options.outdir)
+
+ # update the system path with elements from the -p option
+ sys.path[0:0] = options.path
+
+ import objects
+
+ # set stats options
+ objects.Statistics.text_file = options.stats_file
+
+ # set debugging options
+ objects.Debug.break_cycles = options.debug_break
+
+ # set tracing options
+ objects.Trace.flags = options.trace_flags
+ objects.Trace.start = options.trace_start
+ objects.Trace.file = options.trace_file
+ objects.Trace.bufsize = options.trace_circlebuf
+ objects.Trace.dump_on_exit = options.trace_dumponexit
+ objects.Trace.ignore = options.trace_ignore
+
+ # set execution trace options
+ objects.ExecutionTrace.speculative = options.speculative
+ objects.ExecutionTrace.print_cycle = options.print_cycle
+ objects.ExecutionTrace.pc_symbol = options.print_symbol
+ objects.ExecutionTrace.print_opclass = options.print_opclass
+ objects.ExecutionTrace.print_thread = options.print_thread
+ objects.ExecutionTrace.print_effaddr = options.print_effaddr
+ objects.ExecutionTrace.print_data = options.print_data
+ objects.ExecutionTrace.print_iregs = options.print_iregs
+ objects.ExecutionTrace.print_fetchseq = options.print_fetch_seq
+ objects.ExecutionTrace.print_cpseq = options.print_cpseq
+
+ scope = { '__file__' : sys.argv[0] }
+ sys.argv = arguments
+ sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path
+ exec("import readline", scope)
+ execfile(sys.argv[0], scope)
+
+ # once the script is done
+ if options.interactive:
+ interact = code.InteractiveConsole(scope)
+ interact.interact("M5 Interactive Console")
+
+if __name__ == '__main__':
+ from pprint import pprint
+
+ parse_args()
+
+ print 'opts:'
+ pprint(options, indent=4)
+ print
+
+ print 'args:'
+ pprint(arguments, indent=4)
diff --git a/src/python/m5/objects/O3CPU.py b/src/python/m5/objects/O3CPU.py
index 9ccbdcf53..d6bc454ad 100644
--- a/src/python/m5/objects/O3CPU.py
+++ b/src/python/m5/objects/O3CPU.py
@@ -10,6 +10,8 @@ class DerivO3CPU(BaseCPU):
checker = Param.BaseCPU(NULL, "checker")
cachePorts = Param.Unsigned("Cache Ports")
+ icache_port = Port("Instruction Port")
+ dcache_port = Port("Data Port")
decodeToFetchDelay = Param.Unsigned("Decode to fetch delay")
renameToFetchDelay = Param.Unsigned("Rename to fetch delay")
@@ -51,6 +53,9 @@ class DerivO3CPU(BaseCPU):
trapLatency = Param.Tick("Trap latency")
fetchTrapLatency = Param.Tick("Fetch trap latency")
+ backComSize = Param.Unsigned("Time buffer size for backwards communication")
+ forwardComSize = Param.Unsigned("Time buffer size for forward communication")
+
predType = Param.String("Branch predictor type ('local', 'tournament')")
localPredictorSize = Param.Unsigned("Size of local predictor")
localCtrBits = Param.Unsigned("Bits per counter")
diff --git a/src/python/m5/objects/OzoneCPU.py b/src/python/m5/objects/OzoneCPU.py
index 8aff89203..88fb63c74 100644
--- a/src/python/m5/objects/OzoneCPU.py
+++ b/src/python/m5/objects/OzoneCPU.py
@@ -9,6 +9,9 @@ class DerivOzoneCPU(BaseCPU):
checker = Param.BaseCPU("Checker CPU")
+ icache_port = Port("Instruction Port")
+ dcache_port = Port("Data Port")
+
width = Param.Unsigned("Width")
frontEndWidth = Param.Unsigned("Front end width")
backEndWidth = Param.Unsigned("Back end width")
diff --git a/src/sim/main.cc b/src/sim/main.cc
index e96a44930..d0725ab37 100644
--- a/src/sim/main.cc
+++ b/src/sim/main.cc
@@ -115,70 +115,11 @@ abortHandler(int sigtype)
#endif
}
-/// Simulator executable name
-char *myProgName = "";
-
-/// Show brief help message.
-void
-showBriefHelp(ostream &out)
-{
- char *prog = basename(myProgName);
-
- ccprintf(out, "Usage:\n");
- ccprintf(out,
-"%s [-p <path>] [-i ] [-h] <config file>\n"
-"\n"
-" -p, --path <path> prepends <path> to PYTHONPATH instead of using\n"
-" built-in zip archive. Useful when developing/debugging\n"
-" changes to built-in Python libraries, as the new Python\n"
-" can be tested without building a new m5 binary.\n\n"
-" -i, --interactive forces entry into interactive mode after the supplied\n"
-" script is executed (just like the -i option to the\n"
-" Python interpreter).\n\n"
-" -h Prints this help\n\n"
-" <configfile> config file name which ends in .py. (Normally you can\n"
-" run <configfile> --help to get help on that config files\n"
-" parameters.\n\n",
- prog);
-
-}
-
-const char *briefCopyright =
-"Copyright (c) 2001-2006\n"
-"The Regents of The University of Michigan\n"
-"All Rights Reserved\n";
-
-/// Print welcome message.
-void
-sayHello(ostream &out)
-{
- extern const char *compileDate; // from date.cc
-
- ccprintf(out, "M5 Simulator System\n");
- // display copyright
- ccprintf(out, "%s\n", briefCopyright);
- ccprintf(out, "M5 compiled %d\n", compileDate);
- ccprintf(out, "M5 started %s\n", Time::start);
-
- char *host = getenv("HOSTNAME");
- if (!host)
- host = getenv("HOST");
-
- if (host)
- ccprintf(out, "M5 executing on %s\n", host);
-}
-
-
extern "C" { void init_cc_main(); }
int
main(int argc, char **argv)
{
- // Saze off program name
- myProgName = argv[0];
-
- sayHello(cerr);
-
signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths
signal(SIGTRAP, SIG_IGN);
signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats
@@ -189,72 +130,18 @@ main(int argc, char **argv)
Py_SetProgramName(argv[0]);
// default path to m5 python code is the currently executing
- // file... Python ZipImporter will find embedded zip archive
- char *pythonpath = argv[0];
-
- bool interactive = false;
- bool show_help = false;
- bool getopt_done = false;
- int opt_index = 0;
-
- static struct option long_options[] = {
- {"python", 1, 0, 'p'},
- {"interactive", 0, 0, 'i'},
- {"help", 0, 0, 'h'},
- {0,0,0,0}
- };
-
- do {
- switch (getopt_long(argc, argv, "+p:ih", long_options, &opt_index)) {
- // -p <path> prepends <path> to PYTHONPATH instead of
- // using built-in zip archive. Useful when
- // developing/debugging changes to built-in Python
- // libraries, as the new Python can be tested without
- // building a new m5 binary.
- case 'p':
- pythonpath = optarg;
- break;
-
- // -i forces entry into interactive mode after the
- // supplied script is executed (just like the -i option to
- // the Python interpreter).
- case 'i':
- interactive = true;
- break;
-
- case 'h':
- show_help = true;
- break;
- case -1:
- getopt_done = true;
- break;
-
- default:
- fatal("Unrecognized option %c\n", optopt);
- }
- } while (!getopt_done);
-
- if (show_help) {
- showBriefHelp(cerr);
- exit(1);
- }
-
- // Fix up argc & argv to hide arguments we just processed.
- // getopt() sets optind to the index of the first non-processed
- // argv element.
- argc -= optind;
- argv += optind;
-
- // Set up PYTHONPATH to make sure the m5 module is found
- string newpath(pythonpath);
+ // file... Python ZipImporter will find embedded zip archive.
+ // The M5_ARCHIVE environment variable can be used to override this.
+ char *m5_archive = getenv("M5_ARCHIVE");
+ string pythonpath = m5_archive ? m5_archive : argv[0];
char *oldpath = getenv("PYTHONPATH");
if (oldpath != NULL) {
- newpath += ":";
- newpath += oldpath;
+ pythonpath += ":";
+ pythonpath += oldpath;
}
- if (setenv("PYTHONPATH", newpath.c_str(), true) == -1)
+ if (setenv("PYTHONPATH", pythonpath.c_str(), true) == -1)
fatal("setenv: %s\n", strerror(errno));
// initialize embedded Python interpreter
@@ -264,37 +151,8 @@ main(int argc, char **argv)
// initialize SWIG 'cc_main' module
init_cc_main();
- if (argc > 0) {
- // extra arg(s): first is script file, remaining ones are args
- // to script file
- char *filename = argv[0];
- FILE *fp = fopen(filename, "r");
- if (!fp) {
- fatal("cannot open file '%s'\n", filename);
- }
-
- PyRun_AnyFile(fp, filename);
- } else {
- // no script file argument... force interactive prompt
- interactive = true;
- }
-
- if (interactive) {
- // The following code to import readline was copied from Python
- // 2.4.3's Modules/main.c.
- // Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006
- // Python Software Foundation; All Rights Reserved
- // We should only enable this if we're actually using an
- // interactive prompt.
- PyObject *v;
- v = PyImport_ImportModule("readline");
- if (v == NULL)
- PyErr_Clear();
- else
- Py_DECREF(v);
-
- PyRun_InteractiveLoop(stdin, "stdin");
- }
+ PyRun_SimpleString("import m5");
+ PyRun_SimpleString("m5.main()");
// clean up Python intepreter.
Py_Finalize();
@@ -542,15 +400,15 @@ cleanupCountedDrain(Event *counted_drain)
}
void
-serializeAll()
+serializeAll(const std::string &cpt_dir)
{
- Serializable::serializeAll();
+ Serializable::serializeAll(cpt_dir);
}
void
-unserializeAll()
+unserializeAll(const std::string &cpt_dir)
{
- Serializable::unserializeAll();
+ Serializable::unserializeAll(cpt_dir);
}
/**
diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc
index 869805f5c..fcf0b957a 100644
--- a/src/sim/pseudo_inst.cc
+++ b/src/sim/pseudo_inst.cc
@@ -37,7 +37,6 @@
#include "sim/pseudo_inst.hh"
#include "arch/vtophys.hh"
#include "cpu/base.hh"
-#include "cpu/sampler/sampler.hh"
#include "cpu/thread_context.hh"
#include "cpu/quiesce_event.hh"
#include "kern/kernel_stats.hh"
diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc
index 7450d7b7e..6a1d084b7 100644
--- a/src/sim/serialize.cc
+++ b/src/sim/serialize.cc
@@ -231,8 +231,9 @@ Globals::unserialize(Checkpoint *cp)
}
void
-Serializable::serializeAll()
+Serializable::serializeAll(const std::string &cpt_dir)
{
+ setCheckpointDir(cpt_dir);
string dir = Checkpoint::dir();
if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
fatal("couldn't mkdir %s\n", dir);
@@ -247,8 +248,9 @@ Serializable::serializeAll()
}
void
-Serializable::unserializeAll()
+Serializable::unserializeAll(const std::string &cpt_dir)
{
+ setCheckpointDir(cpt_dir);
string dir = Checkpoint::dir();
string cpt_file = dir + Checkpoint::baseFilename;
string section = "";
@@ -289,9 +291,9 @@ Checkpoint::dir()
}
void
-debug_serialize()
+debug_serialize(const std::string &cpt_dir)
{
- Serializable::serializeAll();
+ Serializable::serializeAll(cpt_dir);
}
diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh
index a80dc99e4..880fb0785 100644
--- a/src/sim/serialize.hh
+++ b/src/sim/serialize.hh
@@ -126,8 +126,8 @@ class Serializable
static int ckptCount;
static int ckptMaxCount;
static int ckptPrevCount;
- static void serializeAll();
- static void unserializeAll();
+ static void serializeAll(const std::string &cpt_dir);
+ static void unserializeAll(const std::string &cpt_dir);
static void unserializeGlobals(Checkpoint *cp);
};
@@ -206,7 +206,7 @@ SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \
OBJ_CLASS::createForUnserialize);
void
-setCheckpointName(const std::string &name);
+setCheckpointDir(const std::string &name);
class Checkpoint
{
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index a3990e2fd..a3ff006ef 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -27,7 +27,6 @@
*
* Authors: Steve Reinhardt
* Kevin Lim
- * Korey Sewell
*/
#ifndef __SIM_SYSCALL_EMUL_HH__