# Define the universe of supported CPU models
env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU',
'FullCPU', 'AlphaO3CPU',
- 'OzoneSimpleCPU', 'OzoneCPU']
+ 'OzoneCPU']
# Sticky options get saved in the options file so they persist from
# one invocation to the next (unless overridden, in which case the new
if env['USE_CHECKER']:
sources += Split('o3/checker_builder.cc')
-if 'OzoneSimpleCPU' in env['CPU_MODELS']:
+if 'OzoneCPU' in env['CPU_MODELS']:
sources += Split('''
+ ozone/base_dyn_inst.cc
+ ozone/bpred_unit.cc
ozone/cpu.cc
ozone/cpu_builder.cc
ozone/dyn_inst.cc
ozone/front_end.cc
- ozone/inorder_back_end.cc
- ozone/inst_queue.cc
- ozone/rename_table.cc
- ''')
-
-if 'OzoneCPU' in env['CPU_MODELS']:
- sources += Split('''
- ozone/base_dyn_inst.cc
- ozone/bpred_unit.cc
- ozone/lsq_unit.cc
ozone/lw_back_end.cc
ozone/lw_lsq.cc
+ ozone/rename_table.cc
''')
if env['USE_CHECKER']:
sources += Split('ozone/checker_builder.cc')
--- /dev/null
+/*
+ * 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: Kevin Lim
+ */
+
+#include "cpu/base_dyn_inst_impl.hh"
+#include "cpu/ozone/ozone_impl.hh"
+
+// Explicit instantiation
+template class BaseDynInst<OzoneImpl>;
+
+template <>
+int
+BaseDynInst<OzoneImpl>::instcount = 0;
#include "cpu/o3/bpred_unit_impl.hh"
#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
+//#include "cpu/ozone/simple_impl.hh"
template class BPredUnit<OzoneImpl>;
-template class BPredUnit<SimpleImpl>;
+//template class BPredUnit<SimpleImpl>;
#include "cpu/inst_seq.hh"
#include "cpu/ozone/dyn_inst.hh"
#include "cpu/ozone/ozone_impl.hh"
-#include "mem/base_mem.hh"
#include "sim/builder.hh"
#include "sim/process.hh"
#include "sim/sim_object.hh"
+class MemObject;
+
template
class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >;
/**
* Specific non-templated derived class used for SimObject configuration.
*/
-class OzoneChecker : public Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >
+class OzoneChecker :
+ public Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >
{
public:
OzoneChecker(Params *p)
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<FunctionalMemory *> mem;
SimObjectParam<System *> system;
Param<int> cpu_id;
Param<Tick> profile;
SimObjectParam<Process *> workload;
#endif // FULL_SYSTEM
Param<int> clock;
- SimObjectParam<BaseMem *> icache;
- SimObjectParam<BaseMem *> dcache;
Param<bool> defer_registration;
Param<bool> exitOnError;
#if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(dtb, "Data TLB"),
- INIT_PARAM(mem, "memory"),
INIT_PARAM(system, "system object"),
INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM(profile, ""),
#endif // FULL_SYSTEM
INIT_PARAM(clock, "clock speed"),
- INIT_PARAM(icache, "L1 instruction cache object"),
- INIT_PARAM(dcache, "L1 data cache object"),
INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
INIT_PARAM(exitOnError, "exit on error"),
temp = max_insts_all_threads;
temp = max_loads_any_thread;
temp = max_loads_all_threads;
- BaseMem *cache = icache;
- cache = dcache;
#if FULL_SYSTEM
params->itb = itb;
params->dtb = dtb;
- params->mem = mem;
params->system = system;
params->cpu_id = cpu_id;
params->profile = profile;
#include "cpu/ozone/cpu_impl.hh"
#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
+//#include "cpu/ozone/simple_impl.hh"
-template class OzoneCPU<SimpleImpl>;
+//template class OzoneCPU<SimpleImpl>;
template class OzoneCPU<OzoneImpl>;
#include "cpu/ozone/thread_state.hh"
#include "cpu/pc_event.hh"
#include "cpu/static_inst.hh"
+#include "mem/page_table.hh"
#include "sim/eventq.hh"
// forward declarations
class Checkpoint;
class EndQuiesceEvent;
+class MemObject;
class Request;
namespace Trace {
void setCpuId(int id);
- int readCpuId() { return thread->cpuId; }
+ int readCpuId() { return thread->readCpuId(); }
#if FULL_SYSTEM
System *getSystemPtr() { return cpu->system; }
AlphaDTB * getDTBPtr() { return cpu->dtb; }
- Kernel::Statistics *getKernelStats() { return thread->kernelStats; }
+ Kernel::Statistics *getKernelStats()
+ { return thread->getKernelStats(); }
FunctionalPort *getPhysPort() { return thread->getPhysPort(); }
VirtualPort *getVirtPort(ThreadContext *tc = NULL)
{ return thread->getVirtPort(tc); }
- void delVirtPort(VirtualPort *vp)
- { thread->delVirtPort(vp); }
+ void delVirtPort(VirtualPort *vp);
#else
- TranslatingPort *getMemPort() { return thread->port; }
+ TranslatingPort *getMemPort() { return thread->getMemPort(); }
- Process *getProcessPtr() { return thread->process; }
+ Process *getProcessPtr() { return thread->getProcessPtr(); }
#endif
- Status status() const { return thread->_status; }
+ Status status() const { return thread->status(); }
void setStatus(Status new_status);
{ thread->renameTable[TheISA::ArgumentReg0 + i]->setIntResult(i); }
void setSyscallReturn(SyscallReturn return_value)
- { cpu->setSyscallReturn(return_value, thread->tid); }
+ { cpu->setSyscallReturn(return_value, thread->readTid()); }
Counter readFuncExeInst() { return thread->funcExeInst; }
PhysicalMemory *physmem;
#endif
+ MemObject *mem;
+
FrontEnd *frontEnd;
BackEnd *backEnd;
#if FULL_SYSTEM
- bool validInstAddr(Addr addr) { return true; }
- bool validDataAddr(Addr addr) { return true; }
-
- Fault translateInstReq(Request *req)
+ /** Translates instruction requestion. */
+ Fault translateInstReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
{
- return itb->translate(req, tc);
+ return itb->translate(req, thread->getTC());
}
- Fault translateDataReadReq(Request *req)
+ /** Translates data read request. */
+ Fault translateDataReadReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
{
- return dtb->translate(req, tc, false);
+ return dtb->translate(req, thread->getTC(), false);
}
- Fault translateDataWriteReq(Request *req)
+ /** Translates data write request. */
+ Fault translateDataWriteReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
{
- return dtb->translate(req, tc, true);
+ return dtb->translate(req, thread->getTC(), true);
}
#else
- bool validInstAddr(Addr addr)
- { return true; }
-
- bool validDataAddr(Addr addr)
- { return true; }
-
- int getInstAsid() { return thread.asid; }
- int getDataAsid() { return thread.asid; }
-
/** Translates instruction requestion in syscall emulation mode. */
- Fault translateInstReq(Request *req)
+ Fault translateInstReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
{
- return thread.translateInstReq(req);
+ return thread->getProcessPtr()->pTable->translate(req);
}
/** Translates data read request in syscall emulation mode. */
- Fault translateDataReadReq(Request *req)
+ Fault translateDataReadReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
{
- return thread.translateDataReadReq(req);
+ return thread->getProcessPtr()->pTable->translate(req);
}
/** Translates data write request in syscall emulation mode. */
- Fault translateDataWriteReq(Request *req)
+ Fault translateDataWriteReq(RequestPtr &req, OzoneThreadState<Impl> *thread)
{
- return thread.translateDataWriteReq(req);
+ return thread->getProcessPtr()->pTable->translate(req);
}
#endif
#if FULL_SYSTEM
Fault hwrei();
- int readIntrFlag() { return thread.regs.intrflag; }
- void setIntrFlag(int val) { thread.regs.intrflag = val; }
+ int readIntrFlag() { return thread.intrflag; }
+ void setIntrFlag(int val) { thread.intrflag = val; }
bool inPalMode() { return AlphaISA::PcPAL(thread.PC); }
bool inPalMode(Addr pc) { return AlphaISA::PcPAL(pc); }
bool simPalCheck(int palFunc);
void processInterrupts();
#else
- void syscall();
+ void syscall(uint64_t &callnum);
void setSyscallReturn(SyscallReturn return_value, int tid);
#endif
#include "cpu/inst_seq.hh"
#include "cpu/ozone/cpu.hh"
#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
#include "cpu/ozone/simple_params.hh"
-#include "mem/cache/base_cache.hh"
#include "sim/builder.hh"
#include "sim/process.hh"
#include "sim/sim_object.hh"
{ }
};
-class SimpleOzoneCPU : public OzoneCPU<SimpleImpl>
-{
- public:
- SimpleOzoneCPU(SimpleParams *p)
- : OzoneCPU<SimpleImpl>(p)
- { }
-};
-
////////////////////////////////////////////////////////////////////////
//
//SimObjectParam<PageTable *> page_table;
#endif // FULL_SYSTEM
-SimObjectParam<FunctionalMemory *> mem;
+SimObjectParam<MemObject *> mem;
SimObjectParam<BaseCPU *> checker;
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
-SimObjectParam<BaseCache *> icache;
-SimObjectParam<BaseCache *> dcache;
+//SimObjectParam<BaseCache *> icache;
+//SimObjectParam<BaseCache *> dcache;
Param<unsigned> cachePorts;
Param<unsigned> width;
"count",
0),
- INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
- INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
+// INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
+// INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
INIT_PARAM_DFLT(width, "Width", 1),
//
// Caches
//
- params->icacheInterface = icache ? icache->getInterface() : NULL;
- params->dcacheInterface = dcache ? dcache->getInterface() : NULL;
+// params->icacheInterface = icache ? icache->getInterface() : NULL;
+// params->dcacheInterface = dcache ? dcache->getInterface() : NULL;
params->cachePorts = cachePorts;
params->width = width;
}
REGISTER_SIM_OBJECT("DerivOzoneCPU", DerivOzoneCPU)
-
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// OzoneCPU Simulation Object
-//
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
-
- Param<int> clock;
- Param<int> numThreads;
-
-#if FULL_SYSTEM
-SimObjectParam<System *> system;
-Param<int> cpu_id;
-SimObjectParam<AlphaITB *> itb;
-SimObjectParam<AlphaDTB *> dtb;
-#else
-SimObjectVectorParam<Process *> workload;
-//SimObjectParam<PageTable *> page_table;
-#endif // FULL_SYSTEM
-
-SimObjectParam<FunctionalMemory *> mem;
-
-SimObjectParam<BaseCPU *> checker;
-
-Param<Counter> max_insts_any_thread;
-Param<Counter> max_insts_all_threads;
-Param<Counter> max_loads_any_thread;
-Param<Counter> max_loads_all_threads;
-
-SimObjectParam<BaseCache *> icache;
-SimObjectParam<BaseCache *> dcache;
-
-Param<unsigned> cachePorts;
-Param<unsigned> width;
-Param<unsigned> frontEndWidth;
-Param<unsigned> backEndWidth;
-Param<unsigned> backEndSquashLatency;
-Param<unsigned> backEndLatency;
-Param<unsigned> maxInstBufferSize;
-Param<unsigned> numPhysicalRegs;
-
-Param<unsigned> decodeToFetchDelay;
-Param<unsigned> renameToFetchDelay;
-Param<unsigned> iewToFetchDelay;
-Param<unsigned> commitToFetchDelay;
-Param<unsigned> fetchWidth;
-
-Param<unsigned> renameToDecodeDelay;
-Param<unsigned> iewToDecodeDelay;
-Param<unsigned> commitToDecodeDelay;
-Param<unsigned> fetchToDecodeDelay;
-Param<unsigned> decodeWidth;
-
-Param<unsigned> iewToRenameDelay;
-Param<unsigned> commitToRenameDelay;
-Param<unsigned> decodeToRenameDelay;
-Param<unsigned> renameWidth;
-
-Param<unsigned> commitToIEWDelay;
-Param<unsigned> renameToIEWDelay;
-Param<unsigned> issueToExecuteDelay;
-Param<unsigned> issueWidth;
-Param<unsigned> executeWidth;
-Param<unsigned> executeIntWidth;
-Param<unsigned> executeFloatWidth;
-Param<unsigned> executeBranchWidth;
-Param<unsigned> executeMemoryWidth;
-
-Param<unsigned> iewToCommitDelay;
-Param<unsigned> renameToROBDelay;
-Param<unsigned> commitWidth;
-Param<unsigned> squashWidth;
-
-Param<std::string> predType;
-Param<unsigned> localPredictorSize;
-Param<unsigned> localCtrBits;
-Param<unsigned> localHistoryTableSize;
-Param<unsigned> localHistoryBits;
-Param<unsigned> globalPredictorSize;
-Param<unsigned> globalCtrBits;
-Param<unsigned> globalHistoryBits;
-Param<unsigned> choicePredictorSize;
-Param<unsigned> choiceCtrBits;
-
-Param<unsigned> BTBEntries;
-Param<unsigned> BTBTagSize;
-
-Param<unsigned> RASSize;
-
-Param<unsigned> LQEntries;
-Param<unsigned> SQEntries;
-Param<unsigned> LFSTSize;
-Param<unsigned> SSITSize;
-
-Param<unsigned> numPhysIntRegs;
-Param<unsigned> numPhysFloatRegs;
-Param<unsigned> numIQEntries;
-Param<unsigned> numROBEntries;
-
-Param<bool> decoupledFrontEnd;
-Param<int> dispatchWidth;
-Param<int> wbWidth;
-
-Param<unsigned> smtNumFetchingThreads;
-Param<std::string> smtFetchPolicy;
-Param<std::string> smtLSQPolicy;
-Param<unsigned> smtLSQThreshold;
-Param<std::string> smtIQPolicy;
-Param<unsigned> smtIQThreshold;
-Param<std::string> smtROBPolicy;
-Param<unsigned> smtROBThreshold;
-Param<std::string> smtCommitPolicy;
-
-Param<unsigned> instShiftAmt;
-
-Param<bool> defer_registration;
-
-Param<bool> function_trace;
-Param<Tick> function_trace_start;
-
-END_DECLARE_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
-
- INIT_PARAM(clock, "clock speed"),
- INIT_PARAM(numThreads, "number of HW thread contexts"),
-
-#if FULL_SYSTEM
- INIT_PARAM(system, "System object"),
- INIT_PARAM(cpu_id, "processor ID"),
- INIT_PARAM(itb, "Instruction translation buffer"),
- INIT_PARAM(dtb, "Data translation buffer"),
-#else
- INIT_PARAM(workload, "Processes to run"),
-// INIT_PARAM(page_table, "Page table"),
-#endif // FULL_SYSTEM
-
- INIT_PARAM_DFLT(mem, "Memory", NULL),
-
- INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
-
- INIT_PARAM_DFLT(max_insts_any_thread,
- "Terminate when any thread reaches this inst count",
- 0),
- INIT_PARAM_DFLT(max_insts_all_threads,
- "Terminate when all threads have reached"
- "this inst count",
- 0),
- INIT_PARAM_DFLT(max_loads_any_thread,
- "Terminate when any thread reaches this load count",
- 0),
- INIT_PARAM_DFLT(max_loads_all_threads,
- "Terminate when all threads have reached this load"
- "count",
- 0),
-
- INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
- INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
-
- INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
- INIT_PARAM_DFLT(width, "Width", 1),
- INIT_PARAM_DFLT(frontEndWidth, "Front end width", 1),
- INIT_PARAM_DFLT(backEndWidth, "Back end width", 1),
- INIT_PARAM_DFLT(backEndSquashLatency, "Back end squash latency", 1),
- INIT_PARAM_DFLT(backEndLatency, "Back end latency", 1),
- INIT_PARAM_DFLT(maxInstBufferSize, "Maximum instruction buffer size", 16),
- INIT_PARAM(numPhysicalRegs, "Number of physical registers"),
-
- INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
- INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"),
- INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch"
- "delay"),
- INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"),
- INIT_PARAM(fetchWidth, "Fetch width"),
- INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"),
- INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode"
- "delay"),
- INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"),
- INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"),
- INIT_PARAM(decodeWidth, "Decode width"),
-
- INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename"
- "delay"),
- INIT_PARAM(commitToRenameDelay, "Commit to rename delay"),
- INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"),
- INIT_PARAM(renameWidth, "Rename width"),
-
- INIT_PARAM(commitToIEWDelay, "Commit to "
- "Issue/Execute/Writeback delay"),
- INIT_PARAM(renameToIEWDelay, "Rename to "
- "Issue/Execute/Writeback delay"),
- INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
- "to the IEW stage)"),
- INIT_PARAM(issueWidth, "Issue width"),
- INIT_PARAM(executeWidth, "Execute width"),
- INIT_PARAM(executeIntWidth, "Integer execute width"),
- INIT_PARAM(executeFloatWidth, "Floating point execute width"),
- INIT_PARAM(executeBranchWidth, "Branch execute width"),
- INIT_PARAM(executeMemoryWidth, "Memory execute width"),
-
- INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
- "delay"),
- INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"),
- INIT_PARAM(commitWidth, "Commit width"),
- INIT_PARAM(squashWidth, "Squash width"),
-
- INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
- INIT_PARAM(localPredictorSize, "Size of local predictor"),
- INIT_PARAM(localCtrBits, "Bits per counter"),
- INIT_PARAM(localHistoryTableSize, "Size of local history table"),
- INIT_PARAM(localHistoryBits, "Bits for the local history"),
- INIT_PARAM(globalPredictorSize, "Size of global predictor"),
- INIT_PARAM(globalCtrBits, "Bits per counter"),
- INIT_PARAM(globalHistoryBits, "Bits of history"),
- INIT_PARAM(choicePredictorSize, "Size of choice predictor"),
- INIT_PARAM(choiceCtrBits, "Bits of choice counters"),
-
- INIT_PARAM(BTBEntries, "Number of BTB entries"),
- INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"),
-
- INIT_PARAM(RASSize, "RAS size"),
-
- INIT_PARAM(LQEntries, "Number of load queue entries"),
- INIT_PARAM(SQEntries, "Number of store queue entries"),
- INIT_PARAM(LFSTSize, "Last fetched store table size"),
- INIT_PARAM(SSITSize, "Store set ID table size"),
-
- INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"),
- INIT_PARAM(numPhysFloatRegs, "Number of physical floating point "
- "registers"),
- INIT_PARAM(numIQEntries, "Number of instruction queue entries"),
- INIT_PARAM(numROBEntries, "Number of reorder buffer entries"),
-
- INIT_PARAM_DFLT(decoupledFrontEnd, "Decoupled front end", true),
- INIT_PARAM_DFLT(dispatchWidth, "Dispatch width", 0),
- INIT_PARAM_DFLT(wbWidth, "Writeback width", 0),
-
- INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1),
- INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"),
- INIT_PARAM_DFLT(smtLSQPolicy, "SMT LSQ Sharing Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100),
- INIT_PARAM_DFLT(smtIQPolicy, "SMT IQ Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100),
- INIT_PARAM_DFLT(smtROBPolicy, "SMT ROB Sharing Policy", "Partitioned"),
- INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100),
- INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"),
-
- INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"),
- INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
-
- INIT_PARAM(function_trace, "Enable function trace"),
- INIT_PARAM(function_trace_start, "Cycle to start function trace")
-
-END_INIT_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
-
-CREATE_SIM_OBJECT(SimpleOzoneCPU)
-{
- SimpleOzoneCPU *cpu;
-
-#if FULL_SYSTEM
- // Full-system only supports a single thread for the moment.
- int actual_num_threads = 1;
-#else
- // In non-full-system mode, we infer the number of threads from
- // the workload if it's not explicitly specified.
- int actual_num_threads =
- numThreads.isValid() ? numThreads : workload.size();
-
- if (workload.size() == 0) {
- fatal("Must specify at least one workload!");
- }
-
-#endif
-
- SimpleParams *params = new SimpleParams;
-
- params->clock = clock;
-
- params->name = getInstanceName();
- params->numberOfThreads = actual_num_threads;
-
-#if FULL_SYSTEM
- params->system = system;
- params->cpu_id = cpu_id;
- params->itb = itb;
- params->dtb = dtb;
-#else
- params->workload = workload;
-// params->pTable = page_table;
-#endif // FULL_SYSTEM
-
- params->mem = mem;
- params->checker = checker;
- params->max_insts_any_thread = max_insts_any_thread;
- params->max_insts_all_threads = max_insts_all_threads;
- params->max_loads_any_thread = max_loads_any_thread;
- params->max_loads_all_threads = max_loads_all_threads;
-
- //
- // Caches
- //
- params->icacheInterface = icache ? icache->getInterface() : NULL;
- params->dcacheInterface = dcache ? dcache->getInterface() : NULL;
- params->cachePorts = cachePorts;
-
- params->width = width;
- params->frontEndWidth = frontEndWidth;
- params->backEndWidth = backEndWidth;
- params->backEndSquashLatency = backEndSquashLatency;
- params->backEndLatency = backEndLatency;
- params->maxInstBufferSize = maxInstBufferSize;
- params->numPhysicalRegs = numPhysIntRegs + numPhysFloatRegs;
-
- params->decodeToFetchDelay = decodeToFetchDelay;
- params->renameToFetchDelay = renameToFetchDelay;
- params->iewToFetchDelay = iewToFetchDelay;
- params->commitToFetchDelay = commitToFetchDelay;
- params->fetchWidth = fetchWidth;
-
- params->renameToDecodeDelay = renameToDecodeDelay;
- params->iewToDecodeDelay = iewToDecodeDelay;
- params->commitToDecodeDelay = commitToDecodeDelay;
- params->fetchToDecodeDelay = fetchToDecodeDelay;
- params->decodeWidth = decodeWidth;
-
- params->iewToRenameDelay = iewToRenameDelay;
- params->commitToRenameDelay = commitToRenameDelay;
- params->decodeToRenameDelay = decodeToRenameDelay;
- params->renameWidth = renameWidth;
-
- params->commitToIEWDelay = commitToIEWDelay;
- params->renameToIEWDelay = renameToIEWDelay;
- params->issueToExecuteDelay = issueToExecuteDelay;
- params->issueWidth = issueWidth;
- params->executeWidth = executeWidth;
- params->executeIntWidth = executeIntWidth;
- params->executeFloatWidth = executeFloatWidth;
- params->executeBranchWidth = executeBranchWidth;
- params->executeMemoryWidth = executeMemoryWidth;
-
- params->iewToCommitDelay = iewToCommitDelay;
- params->renameToROBDelay = renameToROBDelay;
- params->commitWidth = commitWidth;
- params->squashWidth = squashWidth;
-
- params->predType = predType;
- params->localPredictorSize = localPredictorSize;
- params->localCtrBits = localCtrBits;
- params->localHistoryTableSize = localHistoryTableSize;
- params->localHistoryBits = localHistoryBits;
- params->globalPredictorSize = globalPredictorSize;
- params->globalCtrBits = globalCtrBits;
- params->globalHistoryBits = globalHistoryBits;
- params->choicePredictorSize = choicePredictorSize;
- params->choiceCtrBits = choiceCtrBits;
-
- params->BTBEntries = BTBEntries;
- params->BTBTagSize = BTBTagSize;
-
- params->RASSize = RASSize;
-
- params->LQEntries = LQEntries;
- params->SQEntries = SQEntries;
-
- params->SSITSize = SSITSize;
- params->LFSTSize = LFSTSize;
-
- params->numPhysIntRegs = numPhysIntRegs;
- params->numPhysFloatRegs = numPhysFloatRegs;
- params->numIQEntries = numIQEntries;
- params->numROBEntries = numROBEntries;
-
- params->decoupledFrontEnd = decoupledFrontEnd;
- params->dispatchWidth = dispatchWidth;
- params->wbWidth = wbWidth;
-
- params->smtNumFetchingThreads = smtNumFetchingThreads;
- params->smtFetchPolicy = smtFetchPolicy;
- params->smtIQPolicy = smtIQPolicy;
- params->smtLSQPolicy = smtLSQPolicy;
- params->smtLSQThreshold = smtLSQThreshold;
- params->smtROBPolicy = smtROBPolicy;
- params->smtROBThreshold = smtROBThreshold;
- params->smtCommitPolicy = smtCommitPolicy;
-
- params->instShiftAmt = 2;
-
- params->deferRegistration = defer_registration;
-
- params->functionTrace = function_trace;
- params->functionTraceStart = function_trace_start;
-
- cpu = new SimpleOzoneCPU(params);
-
- return cpu;
-}
-
-REGISTER_SIM_OBJECT("SimpleOzoneCPU", SimpleOzoneCPU)
-
* Nathan Binkert
*/
-//#include <cstdio>
-//#include <cstdlib>
+#include "config/full_system.hh"
+#include "config/use_checker.hh"
#include "arch/isa_traits.hh" // For MachInst
#include "base/trace.hh"
-#include "config/full_system.hh"
#include "cpu/base.hh"
-#include "cpu/checker/thread_context.hh"
#include "cpu/thread_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/ozone/cpu.hh"
#include "cpu/quiesce_event.hh"
#include "cpu/static_inst.hh"
-//#include "mem/base_mem.hh"
-#include "mem/mem_interface.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
//#include "base/remote_gdb.hh"
#include "cpu/profile.hh"
#include "kern/kernel_stats.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
#include "sim/faults.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/system.hh"
#else // !FULL_SYSTEM
-#include "mem/functional/functional.hh"
#include "sim/process.hh"
#endif // FULL_SYSTEM
+#if USE_CHECKER
+#include "cpu/checker/thread_context.hh"
+#endif
+
using namespace TheISA;
template <class Impl>
template <class Impl>
OzoneCPU<Impl>::OzoneCPU(Params *p)
#if FULL_SYSTEM
- : BaseCPU(p), thread(this, 0, p->mem), tickEvent(this, p->width),
- mem(p->mem),
+ : BaseCPU(p), thread(this, 0), tickEvent(this, p->width),
#else
- : BaseCPU(p), thread(this, 0, p->workload[0], 0), tickEvent(this, p->width),
- mem(p->workload[0]->getMemory()),
+ : BaseCPU(p), thread(this, 0, p->workload[0], 0, p->mem),
+ tickEvent(this, p->width),
#endif
- comm(5, 5)
+ mem(p->mem), comm(5, 5)
{
frontEnd = new FrontEnd(p);
backEnd = new BackEnd(p);
_status = Idle;
if (p->checker) {
+#if USE_CHECKER
BaseCPU *temp_checker = p->checker;
checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
checker->setMemory(mem);
#endif
checkerTC = new CheckerThreadContext<OzoneTC>(&ozoneTC, checker);
thread.tc = checkerTC;
- tc = checkerXC;
+ tc = checkerTC;
+#else
+ panic("Checker enabled but not compiled in!");
+#endif
} else {
checker = NULL;
thread.tc = &ozoneTC;
#if FULL_SYSTEM
/***** All thread state stuff *****/
thread.cpu = this;
- thread.tid = 0;
- thread.mem = p->mem;
+ thread.setTid(0);
thread.quiesceEvent = new EndQuiesceEvent(tc);
system = p->system;
itb = p->itb;
dtb = p->dtb;
- memctrl = p->system->memctrl;
physmem = p->system->physmem;
if (p->profile) {
thread.profilePC = 3;
#else
thread.cpu = this;
- thread.tid = 0;
- thread.process = p->workload[0];
- thread.asid = 0;
#endif // !FULL_SYSTEM
numInst = 0;
if (++switchCount == 2) {
backEnd->doSwitchOut();
frontEnd->doSwitchOut();
+#if USE_CHECKER
if (checker)
checker->switchOut(sampler);
+#endif
+
_status = SwitchedOut;
if (tickEvent.scheduled())
tickEvent.squash();
notIdleFraction++;
scheduleTickEvent(delay);
_status = Running;
- thread._status = ThreadContext::Active;
+ thread.setStatus(ThreadContext::Active);
frontEnd->wakeFromQuiesce();
}
Addr
OzoneCPU<Impl>::dbg_vtophys(Addr addr)
{
- return vtophys(tcProxy, addr);
+ return vtophys(tc, addr);
}
#endif // FULL_SYSTEM
// thread.activate();
// Hack for now. Otherwise might have to go through the tc, or
// I need to figure out what's the right thing to call.
- activateContext(thread.tid, 1);
+ activateContext(thread.readTid(), 1);
}
}
#endif // FULL_SYSTEM
#if !FULL_SYSTEM
template <class Impl>
void
-OzoneCPU<Impl>::syscall()
+OzoneCPU<Impl>::syscall(uint64_t &callnum)
{
// Not sure this copy is needed, depending on how the TC proxy is made.
thread.renameTable.copyFrom(backEnd->renameTable);
DPRINTF(OzoneCPU, "FuncExeInst: %i\n", thread.funcExeInst);
- thread.process->syscall(yc);
+ thread.process->syscall(callnum, tc);
thread.funcExeInst--;
switch (palFunc) {
case PAL::halt:
- haltContext(thread.tid);
+ haltContext(thread.readTid());
if (--System::numSystemsRunning == 0)
- new SimExitEvent("all cpus halted");
+ exitSimLoop("all cpus halted");
break;
case PAL::bpt:
OzoneCPU<Impl>::OzoneTC::setCpuId(int id)
{
cpu->cpuId = id;
- thread->cpuId = id;
+ thread->setCpuId(id);
+}
+
+#if FULL_SYSTEM
+template <class Impl>
+void
+OzoneCPU<Impl>::OzoneTC::delVirtPort(VirtualPort *vp)
+{
+ delete vp->getPeer();
+ delete vp;
}
+#endif
template <class Impl>
void
OzoneCPU<Impl>::OzoneTC::setStatus(Status new_status)
{
- thread->_status = new_status;
+ thread->setStatus(new_status);
}
template <class Impl>
void
OzoneCPU<Impl>::OzoneTC::activate(int delay)
{
- cpu->activateContext(thread->tid, delay);
+ cpu->activateContext(thread->readTid(), delay);
}
/// Set the status to Suspended.
void
OzoneCPU<Impl>::OzoneTC::suspend()
{
- cpu->suspendContext(thread->tid);
+ cpu->suspendContext(thread->readTid());
}
/// Set the status to Unallocated.
void
OzoneCPU<Impl>::OzoneTC::deallocate()
{
- cpu->deallocateContext(thread->tid);
+ cpu->deallocateContext(thread->readTid());
}
/// Set the status to Halted.
void
OzoneCPU<Impl>::OzoneTC::halt()
{
- cpu->haltContext(thread->tid);
+ cpu->haltContext(thread->readTid());
}
#if FULL_SYSTEM
OzoneCPU<Impl>::OzoneTC::takeOverFrom(ThreadContext *old_context)
{
// some things should already be set up
- assert(getMemPtr() == old_context->getMemPtr());
#if FULL_SYSTEM
assert(getSystemPtr() == old_context->getSystemPtr());
#else
int
OzoneCPU<Impl>::OzoneTC::getThreadNum()
{
- return thread->tid;
+ return thread->readTid();
}
// Also somewhat obnoxious. Really only used for the TLB fault.
TheISA::MachInst
OzoneCPU<Impl>::OzoneTC::getInst()
{
- return thread->inst;
+ return thread->getInst();
}
template <class Impl>
} else if (i < (TheISA::FP_Base_DepTag + TheISA::NumFloatRegs)) {
int fp_idx = i - TheISA::FP_Base_DepTag;
thread->renameTable[i]->setDoubleResult(
- tc->readFloatRegDouble(fp_idx));
+ tc->readFloatReg(fp_idx, 64));
}
}
// Need to copy the TC values into the current rename table,
// copy the misc regs.
- thread->regs.miscRegs.copyMiscRegs(tc);
+ copyMiscRegs(tc, this);
}
template <class Impl>
}
template <class Impl>
-float
+TheISA::FloatReg
OzoneCPU<Impl>::OzoneTC::readFloatReg(int reg_idx, int width)
{
int idx = reg_idx + TheISA::FP_Base_DepTag;
TheISA::MiscReg
OzoneCPU<Impl>::OzoneTC::readMiscReg(int misc_reg)
{
- return thread->regs.miscRegs.readReg(misc_reg);
+ return thread->miscRegFile.readReg(misc_reg);
}
template <class Impl>
TheISA::MiscReg
OzoneCPU<Impl>::OzoneTC::readMiscRegWithEffect(int misc_reg, Fault &fault)
{
- return thread->regs.miscRegs.readRegWithEffect(misc_reg,
- fault, this);
+ return thread->miscRegFile.readRegWithEffect(misc_reg,
+ fault, this);
}
template <class Impl>
OzoneCPU<Impl>::OzoneTC::setMiscReg(int misc_reg, const MiscReg &val)
{
// Needs to setup a squash event unless we're in syscall mode
- Fault ret_fault = thread->regs.miscRegs.setReg(misc_reg, val);
+ Fault ret_fault = thread->miscRegFile.setReg(misc_reg, val);
if (!thread->inSyscall) {
cpu->squashFromTC();
OzoneCPU<Impl>::OzoneTC::setMiscRegWithEffect(int misc_reg, const MiscReg &val)
{
// Needs to setup a squash event unless we're in syscall mode
- Fault ret_fault = thread->regs.miscRegs.setRegWithEffect(misc_reg, val,
- this);
+ Fault ret_fault = thread->miscRegFile.setRegWithEffect(misc_reg, val,
+ this);
if (!thread->inSyscall) {
cpu->squashFromTC();
#include "arch/isa_traits.hh"
#include "config/full_system.hh"
#include "cpu/base_dyn_inst.hh"
-#include "cpu/ozone/cpu.hh" // MUST include this
#include "cpu/inst_seq.hh"
-//#include "cpu/ozone/simple_impl.hh" // Would be nice to not have to include this
+#include "cpu/ozone/cpu.hh" // MUST include this
#include "cpu/ozone/ozone_impl.hh"
#include <list>
{
public:
// Typedefs
- typedef typename Impl::FullCPU FullCPU;
+ typedef typename Impl::OzoneCPU OzoneCPU;
- typedef typename FullCPU::ImplState ImplState;
+ typedef typename OzoneCPU::ImplState ImplState;
// Typedef for DynInstPtr. This is really just a RefCountingPtr<OoODynInst>.
typedef typename Impl::DynInstPtr DynInstPtr;
typedef TheISA::ExtMachInst ExtMachInst;
typedef TheISA::MachInst MachInst;
+ typedef TheISA::FloatReg FloatReg;
+ typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::MiscReg MiscReg;
typedef typename std::list<DynInstPtr>::iterator ListIt;
MaxInstDestRegs = TheISA::MaxInstDestRegs
};
- OzoneDynInst(FullCPU *cpu);
+ OzoneDynInst(OzoneCPU *cpu);
OzoneDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC,
- InstSeqNum seq_num, FullCPU *cpu);
+ InstSeqNum seq_num, OzoneCPU *cpu);
OzoneDynInst(StaticInstPtr inst);
Fault initiateAcc();
- Fault completeAcc();
+ Fault completeAcc(Packet *pkt);
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
return srcInsts[idx]->readIntResult();
}
- float readFloatRegSingle(const StaticInst *si, int idx)
+ FloatReg readFloatReg(const StaticInst *si, int idx, int width)
+ {
+ switch(width) {
+ case 32:
+ return srcInsts[idx]->readFloatResult();
+ case 64:
+ return srcInsts[idx]->readDoubleResult();
+ default:
+ panic("Width not supported");
+ return 0;
+ }
+ }
+
+ FloatReg readFloatReg(const StaticInst *si, int idx)
{
return srcInsts[idx]->readFloatResult();
}
- double readFloatRegDouble(const StaticInst *si, int idx)
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
{
- return srcInsts[idx]->readDoubleResult();
+ return srcInsts[idx]->readIntResult();
}
- uint64_t readFloatRegInt(const StaticInst *si, int idx)
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
{
return srcInsts[idx]->readIntResult();
}
BaseDynInst<Impl>::setIntReg(si, idx, val);
}
- void setFloatRegSingle(const StaticInst *si, int idx, float val)
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
+ {
+ BaseDynInst<Impl>::setFloatReg(si, idx, val, width);
+ }
+
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val)
{
- BaseDynInst<Impl>::setFloatRegSingle(si, idx, val);
+ BaseDynInst<Impl>::setFloatReg(si, idx, val);
}
- void setFloatRegDouble(const StaticInst *si, int idx, double val)
+ void setFloatRegBits(const StaticInst *si, int idx,
+ FloatRegBits val, int width)
{
- BaseDynInst<Impl>::setFloatRegDouble(si, idx, val);
+ BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
}
- void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
+ void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
{
- BaseDynInst<Impl>::setFloatRegInt(si, idx, val);
+ BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
}
void setIntResult(uint64_t result) { this->instResult.integer = result; }
void trap(Fault fault);
bool simPalCheck(int palFunc);
#else
- void syscall();
+ void syscall(uint64_t &callnum);
#endif
ListIt iqIt;
using namespace TheISA;
template <class Impl>
-OzoneDynInst<Impl>::OzoneDynInst(FullCPU *cpu)
+OzoneDynInst<Impl>::OzoneDynInst(OzoneCPU *cpu)
: BaseDynInst<Impl>(0, 0, 0, 0, cpu)
{
this->setResultReady();
template <class Impl>
OzoneDynInst<Impl>::OzoneDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC,
- InstSeqNum seq_num, FullCPU *cpu)
+ InstSeqNum seq_num, OzoneCPU *cpu)
: BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu)
{
initInstPtrs();
template <class Impl>
Fault
-OzoneDynInst<Impl>::completeAcc()
+OzoneDynInst<Impl>::completeAcc(Packet *pkt)
{
- if (this->isLoad()) {
- this->fault = this->staticInst->completeAcc(this->req->data,
- this,
- this->traceData);
- } else if (this->isStore()) {
- this->fault = this->staticInst->completeAcc((uint8_t*)&this->req->result,
- this,
- this->traceData);
- } else {
- panic("Unknown type!");
- }
+ this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
return this->fault;
}
void
OzoneDynInst<Impl>::trap(Fault fault)
{
- fault->invoke(this->thread->getXCProxy());
+ fault->invoke(this->thread->getTC());
}
template <class Impl>
#else
template <class Impl>
void
-OzoneDynInst<Impl>::syscall()
+OzoneDynInst<Impl>::syscall(uint64_t &callnum)
{
- this->cpu->syscall();
+ this->cpu->syscall(callnum);
}
#endif
#include "cpu/ozone/front_end_impl.hh"
#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
+//#include "cpu/ozone/simple_impl.hh"
template class FrontEnd<OzoneImpl>;
-template class FrontEnd<SimpleImpl>;
+//template class FrontEnd<SimpleImpl>;
#include <deque>
+#include "arch/utility.hh"
#include "cpu/inst_seq.hh"
#include "cpu/o3/bpred_unit.hh"
#include "cpu/ozone/rename_table.hh"
+#include "mem/port.hh"
#include "mem/request.hh"
#include "sim/eventq.hh"
#include "sim/stats.hh"
typedef typename Impl::Params Params;
typedef typename Impl::DynInst DynInst;
typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::FullCPU FullCPU;
+ typedef typename Impl::CPUType CPUType;
typedef typename Impl::BackEnd BackEnd;
- typedef typename Impl::FullCPU::OzoneTC OzoneTC;
- typedef typename Impl::FullCPU::CommStruct CommStruct;
+ typedef typename Impl::CPUType::OzoneTC OzoneTC;
+ typedef typename Impl::CPUType::CommStruct CommStruct;
+
+ /** IcachePort class. Handles doing the communication with the
+ * cache/memory.
+ */
+ class IcachePort : public Port
+ {
+ protected:
+ /** Pointer to FE. */
+ FrontEnd<Impl> *fe;
+
+ public:
+ /** Default constructor. */
+ IcachePort(FrontEnd<Impl> *_fe)
+ : Port(_fe->name() + "-iport"), fe(_fe)
+ { }
+
+ protected:
+ /** Atomic version of receive. Panics. */
+ virtual Tick recvAtomic(PacketPtr pkt);
+
+ /** Functional version of receive. Panics. */
+ virtual void recvFunctional(PacketPtr pkt);
+
+ /** Receives status change. Other than range changing, panics. */
+ virtual void recvStatusChange(Status status);
+
+ /** Returns the address ranges of this device. */
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+ { resp.clear(); snoop.clear(); }
+
+ /** Timing version of receive. Handles setting fetch to the
+ * proper status to start fetching. */
+ virtual bool recvTiming(PacketPtr pkt);
+
+ /** Handles doing a retry of a failed fetch. */
+ virtual void recvRetry();
+ };
FrontEnd(Params *params);
std::string name() const;
- void setCPU(FullCPU *cpu_ptr)
+ void setCPU(CPUType *cpu_ptr)
{ cpu = cpu_ptr; }
void setBackEnd(BackEnd *back_end_ptr)
bool switchedOut;
private:
+ void recvRetry();
+
bool updateStatus();
void checkBE();
{ return cpu->globalSeqNum++; }
public:
- FullCPU *cpu;
+ CPUType *cpu;
BackEnd *backEnd;
enum Status {
Running,
Idle,
- IcacheMissStall,
- IcacheMissComplete,
+ IcacheWaitResponse,
+ IcacheWaitRetry,
+ IcacheAccessComplete,
SerializeBlocked,
SerializeComplete,
RenameBlocked,
BranchPred branchPred;
- class IcachePort : public Port
- {
- protected:
- FrontEnd *fe;
-
- public:
- IcachePort(const std::string &_name, FrontEnd *_fe)
- : Port(_name), fe(_fe)
- { }
-
- protected:
- virtual Tick recvAtomic(PacketPtr pkt);
-
- virtual void recvFunctional(PacketPtr pkt);
-
- virtual void recvStatusChange(Status status);
-
- virtual void getDeviceAddressRanges(AddrRangeList &resp,
- AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); }
-
- virtual bool recvTiming(PacketPtr pkt);
-
- virtual void recvRetry();
- };
-
IcachePort icachePort;
-#if !FULL_SYSTEM
- PageTable *pTable;
-#endif
-
RequestPtr memReq;
/** Mask to get a cache block's address. */
bool cacheBlkValid;
+ bool cacheBlocked;
+
+ /** The packet that is waiting to be retried. */
+ PacketPtr retryPkt;
+
public:
RenameTable<Impl> renameTable;
#include "cpu/thread_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/ozone/front_end.hh"
-#include "mem/mem_interface.hh"
+#include "mem/packet.hh"
+#include "mem/request.hh"
using namespace TheISA;
+template<class Impl>
+Tick
+FrontEnd<Impl>::IcachePort::recvAtomic(PacketPtr pkt)
+{
+ panic("FrontEnd doesn't expect recvAtomic callback!");
+ return curTick;
+}
+
+template<class Impl>
+void
+FrontEnd<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
+{
+ panic("FrontEnd doesn't expect recvFunctional callback!");
+}
+
+template<class Impl>
+void
+FrontEnd<Impl>::IcachePort::recvStatusChange(Status status)
+{
+ if (status == RangeChange)
+ return;
+
+ panic("FrontEnd doesn't expect recvStatusChange callback!");
+}
+
+template<class Impl>
+bool
+FrontEnd<Impl>::IcachePort::recvTiming(Packet *pkt)
+{
+ fe->processCacheCompletion(pkt);
+ return true;
+}
+
+template<class Impl>
+void
+FrontEnd<Impl>::IcachePort::recvRetry()
+{
+ fe->recvRetry();
+}
+
template <class Impl>
FrontEnd<Impl>::FrontEnd(Params *params)
: branchPred(params),
- icacheInterface(params->icacheInterface),
+ icachePort(this),
instBufferSize(0),
maxInstBufferSize(params->maxInstBufferSize),
width(params->frontEndWidth),
memReq = NULL;
// Size of cache block.
- cacheBlkSize = icacheInterface ? icacheInterface->getBlockSize() : 64;
+ cacheBlkSize = 64;
assert(isPowerOf2(cacheBlkSize));
fetchCacheLineNextCycle = true;
- cacheBlkValid = false;
+ cacheBlkValid = cacheBlocked = false;
+
+ retryPkt = NULL;
-#if !FULL_SYSTEM
-// pTable = params->pTable;
-#endif
fetchFault = NoFault;
}
IFQFcount += instBufferSize == maxInstBufferSize;
// Fetch cache line
- if (status == IcacheMissComplete) {
+ if (status == IcacheAccessComplete) {
cacheBlkValid = true;
status = Running;
if (freeRegs <= 0)
status = RenameBlocked;
checkBE();
- } else if (status == IcacheMissStall) {
- DPRINTF(FE, "Still in Icache miss stall.\n");
+ } else if (status == IcacheWaitResponse || status == IcacheWaitRetry) {
+ DPRINTF(FE, "Still in Icache wait.\n");
icacheStallCycles++;
return;
}
} else if (status == QuiescePending) {
DPRINTF(FE, "Waiting for quiesce to execute or get squashed.\n");
return;
- } else if (status != IcacheMissComplete) {
+ } else if (status != IcacheAccessComplete) {
if (fetchCacheLineNextCycle) {
Fault fault = fetchCacheLine();
if (fault != NoFault) {
fetchCacheLineNextCycle = false;
}
// If miss, stall until it returns.
- if (status == IcacheMissStall) {
+ if (status == IcacheWaitResponse || status == IcacheWaitRetry) {
// Tell CPU to not tick me for now.
return;
}
// Setup the memReq to do a read of the first isntruction's address.
// Set the appropriate read size and flags as well.
- memReq = new MemReq();
-
- memReq->asid = 0;
- memReq->thread_num = 0;
- memReq->data = new uint8_t[64];
- memReq->tc = tc;
- memReq->cmd = Read;
- memReq->reset(fetch_PC, cacheBlkSize, flags);
+ memReq = new Request(0, fetch_PC, cacheBlkSize, flags,
+ fetch_PC, cpu->readCpuId(), 0);
// Translate the instruction request.
- fault = cpu->translateInstReq(memReq);
+ fault = cpu->translateInstReq(memReq, thread);
// Now do the timing access to see whether or not the instruction
// exists within the cache.
- if (icacheInterface && fault == NoFault) {
-#if FULL_SYSTEM
+ if (fault == NoFault) {
+#if 0
if (cpu->system->memctrl->badaddr(memReq->paddr) ||
memReq->flags & UNCACHEABLE) {
DPRINTF(FE, "Fetch: Bad address %#x (hopefully on a "
}
#endif
- memReq->completionEvent = NULL;
-
- memReq->time = curTick;
- fault = cpu->mem->read(memReq, cacheData);
-
- MemAccessResult res = icacheInterface->access(memReq);
-
- // If the cache missed then schedule an event to wake
- // up this stage once the cache miss completes.
- if (icacheInterface->doEvents() && res != MA_HIT) {
- memReq->completionEvent = new ICacheCompletionEvent(memReq, this);
-
- status = IcacheMissStall;
-
- cacheBlkValid = false;
-
- DPRINTF(FE, "Cache miss.\n");
- } else {
- DPRINTF(FE, "Cache hit.\n");
-
- cacheBlkValid = true;
-
-// memcpy(cacheData, memReq->data, memReq->size);
+ // Build packet here.
+ PacketPtr data_pkt = new Packet(memReq,
+ Packet::ReadReq, Packet::Broadcast);
+ data_pkt->dataStatic(cacheData);
+
+ if (!icachePort.sendTiming(data_pkt)) {
+ assert(retryPkt == NULL);
+ DPRINTF(Fetch, "Out of MSHRs!\n");
+ status = IcacheWaitRetry;
+ retryPkt = data_pkt;
+ cacheBlocked = true;
+ return NoFault;
}
+
+ status = IcacheWaitResponse;
}
// Note that this will set the cache block PC a bit earlier than it should
// instruction->setASID(tid);
- instruction->setState(thread);
+ instruction->setThreadState(thread);
instruction->traceData = NULL;
}
// Clear the icache miss if it's outstanding.
- if (status == IcacheMissStall && icacheInterface) {
- DPRINTF(FE, "Squashing outstanding Icache miss.\n");
+ if (status == IcacheWaitResponse) {
+ DPRINTF(FE, "Squashing outstanding Icache access.\n");
memReq = NULL;
}
template <class Impl>
void
-FrontEnd<Impl>::processCacheCompletion(MemReqPtr &req)
+FrontEnd<Impl>::processCacheCompletion(PacketPtr pkt)
{
DPRINTF(FE, "Processing cache completion\n");
// Do something here.
- if (status != IcacheMissStall ||
- req != memReq ||
+ if (status != IcacheWaitResponse ||
+ pkt->req != memReq ||
switchedOut) {
DPRINTF(FE, "Previous fetch was squashed.\n");
fetchIcacheSquashes++;
+ delete pkt->req;
+ delete pkt;
return;
}
- status = IcacheMissComplete;
+ status = IcacheAccessComplete;
/* if (checkStall(tid)) {
fetchStatus[tid] = Blocked;
// Reset the completion event to NULL.
// memReq->completionEvent = NULL;
+ delete pkt->req;
+ delete pkt;
memReq = NULL;
}
freeRegs = numPhysRegs;
}
+template <class Impl>
+void
+FrontEnd<Impl>::recvRetry()
+{
+ assert(cacheBlocked);
+ if (retryPkt != NULL) {
+ assert(status == IcacheWaitRetry);
+
+ if (icachePort.sendTiming(retryPkt)) {
+ status = IcacheWaitResponse;
+ retryPkt = NULL;
+ cacheBlocked = false;
+ }
+ } else {
+ // Access has been squashed since it was sent out. Just clear
+ // the cache being blocked.
+ cacheBlocked = false;
+ }
+
+}
+
template <class Impl>
bool
FrontEnd<Impl>::updateStatus()
DynInstPtr instruction = new DynInst(decode_inst, PC, PC+sizeof(MachInst),
inst_seq, cpu);
- instruction->setState(thread);
+ instruction->setThreadState(thread);
DPRINTF(FE, "Instruction [sn:%lli] created, with PC %#x\n%s\n",
inst_seq, instruction->readPC(),
buff_it++;
}
}
-
-template <class Impl>
-FrontEnd<Impl>::ICacheCompletionEvent::ICacheCompletionEvent(MemReqPtr &_req, FrontEnd *fe)
- : Event(&mainEventQueue, Delayed_Writeback_Pri), req(_req), frontEnd(fe)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template <class Impl>
-void
-FrontEnd<Impl>::ICacheCompletionEvent::process()
-{
- frontEnd->processCacheCompletion(req);
-}
-
-template <class Impl>
-const char *
-FrontEnd<Impl>::ICacheCompletionEvent::description()
-{
- return "ICache completion event";
-}
typedef typename Impl::Params Params;
typedef typename Impl::DynInst DynInst;
typedef typename Impl::DynInstPtr DynInstPtr;
- typedef typename Impl::FullCPU FullCPU;
+ typedef typename Impl::OzoneCPU OzoneCPU;
typedef typename Impl::FrontEnd FrontEnd;
- typedef typename Impl::FullCPU::CommStruct CommStruct;
+ typedef typename Impl::OzoneCPU::CommStruct CommStruct;
struct SizeStruct {
int size;
const char *description();
};
- /** LdWriteback event for a load completion. */
- class LdWritebackEvent : public Event {
- private:
- /** Instruction that is writing back data to the register file. */
- DynInstPtr inst;
- /** Pointer to IEW stage. */
- LWBackEnd *be;
-
- bool dcacheMiss;
-
- public:
- /** Constructs a load writeback event. */
- LdWritebackEvent(DynInstPtr &_inst, LWBackEnd *be);
-
- /** Processes writeback event. */
- virtual void process();
- /** Returns the description of the writeback event. */
- virtual const char *description();
-
- void setDcacheMiss() { dcacheMiss = true; be->addDcacheMiss(inst); }
- };
-
LWBackEnd(Params *params);
std::string name() const;
void regStats();
- void setCPU(FullCPU *cpu_ptr);
+ void setCPU(OzoneCPU *cpu_ptr);
void setFrontEnd(FrontEnd *front_end_ptr)
{ frontEnd = front_end_ptr; }
void updateComInstStats(DynInstPtr &inst);
public:
- FullCPU *cpu;
+ OzoneCPU *cpu;
FrontEnd *frontEnd;
RenameTable<Impl> renameTable;
private:
- class DCacheCompletionEvent : public Event
- {
- private:
- LWBackEnd *be;
-
- public:
- DCacheCompletionEvent(LWBackEnd *_be);
-
- virtual void process();
- virtual const char *description();
- };
-
- friend class DCacheCompletionEvent;
-
- DCacheCompletionEvent cacheCompletionEvent;
-
- MemInterface *dcacheInterface;
-
// General back end width. Used if the more specific isn't given.
int width;
* Authors: Kevin Lim
*/
-#include "cpu/checker/cpu.hh"
+#include "config/use_checker.hh"
+
#include "cpu/ozone/lw_back_end.hh"
-#include "encumbered/cpu/full/op_class.hh"
+#include "cpu/op_class.hh"
+
+#if USE_CHECKER
+#include "cpu/checker/cpu.hh"
+#endif
template <class Impl>
void
assert(found_inst);
}
-template<class Impl>
-LWBackEnd<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst,
- LWBackEnd<Impl> *_be)
- : Event(&mainEventQueue), inst(_inst), be(_be), dcacheMiss(false)
-{
- this->setFlags(Event::AutoDelete);
-}
-
-template<class Impl>
-void
-LWBackEnd<Impl>::LdWritebackEvent::process()
-{
- DPRINTF(BE, "Load writeback event [sn:%lli]\n", inst->seqNum);
-// DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
-
- //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
-
-// iewStage->wakeCPU();
-
- if (be->isSwitchedOut())
- return;
-
- if (dcacheMiss) {
- be->removeDcacheMiss(inst);
- }
-
- if (inst->isSquashed()) {
- inst = NULL;
- return;
- }
-
- if (!inst->isExecuted()) {
- inst->setExecuted();
-
- // Execute again to copy data to proper place.
- inst->completeAcc();
- }
-
- // Need to insert instruction into queue to commit
- be->instToCommit(inst);
-
- //wroteToTimeBuffer = true;
-// iewStage->activityThisCycle();
-
- inst = NULL;
-}
-
-template<class Impl>
-const char *
-LWBackEnd<Impl>::LdWritebackEvent::description()
-{
- return "Load writeback event";
-}
-
-
-template <class Impl>
-LWBackEnd<Impl>::DCacheCompletionEvent::DCacheCompletionEvent(LWBackEnd *_be)
- : Event(&mainEventQueue, CPU_Tick_Pri), be(_be)
-{
-}
-
-template <class Impl>
-void
-LWBackEnd<Impl>::DCacheCompletionEvent::process()
-{
-}
-
-template <class Impl>
-const char *
-LWBackEnd<Impl>::DCacheCompletionEvent::description()
-{
- return "Cache completion event";
-}
-
template <class Impl>
LWBackEnd<Impl>::LWBackEnd(Params *params)
: d2i(5, 5), i2e(5, 5), e2c(5, 5), numInstsToWB(5, 5),
- trapSquash(false), tcSquash(false), cacheCompletionEvent(this),
- dcacheInterface(params->dcacheInterface), width(params->backEndWidth),
- exactFullStall(true)
+ trapSquash(false), tcSquash(false),
+ width(params->backEndWidth), exactFullStall(true)
{
numROBEntries = params->numROBEntries;
numInsts = 0;
template <class Impl>
void
-LWBackEnd<Impl>::setCPU(FullCPU *cpu_ptr)
+LWBackEnd<Impl>::setCPU(OzoneCPU *cpu_ptr)
{
cpu = cpu_ptr;
LSQ.setCPU(cpu_ptr);
// Consider holding onto the trap and waiting until the trap event
// happens for this to be executed.
- fault->invoke(thread->getTCProxy());
+ fault->invoke(thread->getTC());
// Exit state update mode to avoid accidental updating.
thread->inSyscall = false;
// at the commit stage.
if (inst->isMemRef() &&
(!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
- if (dcacheInterface->isBlocked()) {
- // Should I move the instruction aside?
- DPRINTF(BE, "Execute: dcache is blocked\n");
- break;
- }
DPRINTF(BE, "Execute: Initiating access for memory "
"reference.\n");
LSQ.executeLoad(inst);
} else if (inst->isStore()) {
LSQ.executeStore(inst);
- if (inst->req && !(inst->req->flags & LOCKED)) {
+ if (inst->req && !(inst->req->getFlags() & LOCKED)) {
inst->setExecuted();
instToCommit(inst);
thread->setPC(inst->readPC());
thread->setNextPC(inst->readNextPC());
- inst->reachedCommit = true;
+ inst->setAtCommit();
// If the instruction is not executed yet, then it is a non-speculative
// or store inst. Signal backwards that it should be executed.
// Use checker prior to updating anything due to traps or PC
// based events.
+#if USE_CHECKER
if (checker) {
- checker->tick(inst);
+ checker->verify(inst);
}
+#endif
if (inst_fault != NoFault) {
DPRINTF(BE, "Inst [sn:%lli] PC %#x has a fault\n",
} else if (inst_num != 0) {
DPRINTF(BE, "Will wait until instruction is head of commit group.\n");
return false;
- } else if (checker && inst->isStore()) {
- checker->tick(inst);
}
+#if USE_CHECKER
+ else if (checker && inst->isStore()) {
+ checker->verify(inst);
+ }
+#endif
thread->setInst(
static_cast<TheISA::MachInst>(inst->staticInst->machInst));
assert(!thread->inSyscall && !thread->trapPending);
oldpc = thread->readPC();
cpu->system->pcEventQueue.service(
- thread->getTCProxy());
+ thread->getTC());
count++;
} while (oldpc != thread->readPC());
if (count > 1) {
(*insts_it)->setCanCommit();
- (*insts_it)->removeInROB();
+ (*insts_it)->clearInROB();
for (int i = 0; i < (*insts_it)->numDestRegs(); ++i) {
DynInstPtr prev_dest = (*insts_it)->getPrevDestInst(i);
template <class Impl>
void
-LWBackEnd<Impl>::takeOverFrom(ThreadContext *old_xc)
+LWBackEnd<Impl>::takeOverFrom(ThreadContext *old_tc)
{
switchedOut = false;
- xcSquash = false;
+ tcSquash = false;
trapSquash = false;
numInsts = 0;
switchedOut = false;
dispatchStatus = Running;
commitStatus = Running;
- LSQ.takeOverFrom(old_xc);
+ LSQ.takeOverFrom(old_tc);
}
template <class Impl>
#include "sim/debug.hh"
#include "sim/sim_object.hh"
-//class PageTable;
+class MemObject;
/**
* Class that implements the actual LQ and SQ for each specific thread.
class OzoneLWLSQ {
public:
typedef typename Impl::Params Params;
- typedef typename Impl::FullCPU FullCPU;
+ typedef typename Impl::OzoneCPU OzoneCPU;
typedef typename Impl::BackEnd BackEnd;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::IssueStruct IssueStruct;
typedef typename std::map<InstSeqNum, DynInstPtr>::iterator LdMapIt;
- private:
- class StoreCompletionEvent : public Event {
- public:
- /** Constructs a store completion event. */
- StoreCompletionEvent(DynInstPtr &inst, BackEnd *be,
- Event *wb_event, OzoneLWLSQ *lsq_ptr);
-
- /** Processes the store completion event. */
- void process();
-
- /** Returns the description of this event. */
- const char *description();
-
- private:
- /** The store index of the store being written back. */
- DynInstPtr inst;
-
- BackEnd *be;
- /** The writeback event for the store. Needed for store
- * conditionals.
- */
- public:
- Event *wbEvent;
- bool miss;
- private:
- /** The pointer to the LSQ unit that issued the store. */
- OzoneLWLSQ<Impl> *lsqPtr;
- };
-
public:
/** Constructs an LSQ unit. init() must be called prior to use. */
OzoneLWLSQ();
std::string name() const;
/** Sets the CPU pointer. */
- void setCPU(FullCPU *cpu_ptr)
- { cpu = cpu_ptr; }
+ void setCPU(OzoneCPU *cpu_ptr);
/** Sets the back-end stage pointer. */
void setBE(BackEnd *be_ptr)
/** Writes back stores. */
void writebackStores();
+ /** Completes the data access that has been returned from the
+ * memory system. */
+ void completeDataAccess(PacketPtr pkt);
+
// @todo: Include stats in the LSQ unit.
//void regStats();
/** Returns if the LSQ unit will writeback on this cycle. */
bool willWB() { return storeQueue.back().canWB &&
- !storeQueue.back().completed/* &&
- !dcacheInterface->isBlocked()*/; }
+ !storeQueue.back().completed &&
+ !isStoreBlocked; }
void switchOut();
bool switchedOut;
private:
+ /** Writes back the instruction, sending it to IEW. */
+ void writeback(DynInstPtr &inst, PacketPtr pkt);
+
+ /** Handles completing the send of a store to memory. */
+ void storePostSend(Packet *pkt, DynInstPtr &inst);
+
/** Completes the store at the specified index. */
void completeStore(int store_idx);
+ /** Handles doing the retry. */
+ void recvRetry();
+
private:
/** Pointer to the CPU. */
- FullCPU *cpu;
+ OzoneCPU *cpu;
/** Pointer to the back-end stage. */
BackEnd *be;
class DcachePort : public Port
{
protected:
- FullCPU *cpu;
+ OzoneCPU *cpu;
+
+ OzoneLWLSQ *lsq;
public:
- DcachePort(const std::string &_name, FullCPU *_cpu)
- : Port(_name), cpu(_cpu)
+ DcachePort(OzoneCPU *_cpu, OzoneLWLSQ *_lsq)
+ : Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq)
{ }
protected:
};
/** Pointer to the D-cache. */
- DcachePort dcachePort;
+ DcachePort *dcachePort;
/** Pointer to the page table. */
// PageTable *pTable;
typename std::list<DynInstPtr>::iterator lqIt;
};
+ /** Derived class to hold any sender state the LSQ needs. */
+ class LSQSenderState : public Packet::SenderState
+ {
+ public:
+ /** Default constructor. */
+ LSQSenderState()
+ : noWB(false)
+ { }
+
+ /** Instruction who initiated the access to memory. */
+ DynInstPtr inst;
+ /** Whether or not it is a load. */
+ bool isLoad;
+ /** The LQ/SQ index of the instruction. */
+ int idx;
+ /** Whether or not the instruction will need to writeback. */
+ bool noWB;
+ };
+
+ /** Writeback event, specifically for when stores forward data to loads. */
+ class WritebackEvent : public Event {
+ public:
+ /** Constructs a writeback event. */
+ WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, OzoneLWLSQ *lsq_ptr);
+
+ /** Processes the writeback event. */
+ void process();
+
+ /** Returns the description of this event. */
+ const char *description();
+
+ private:
+ /** Instruction whose results are being written back. */
+ DynInstPtr inst;
+
+ /** The packet that would have been sent to memory. */
+ PacketPtr pkt;
+
+ /** The pointer to the LSQ unit that issued the store. */
+ OzoneLWLSQ<Impl> *lsqPtr;
+ };
+
enum Status {
Running,
Idle,
/** The index of the above store. */
LQIt stallingLoad;
+ /** The packet that needs to be retried. */
+ PacketPtr retryPkt;
+
+ /** Whehter or not a store is blocked due to the memory system. */
+ bool isStoreBlocked;
+
/** Whether or not a load is blocked due to the memory system. It is
* cleared when this value is checked via loadBlocked().
*/
// too).
// @todo: Fix uncached accesses.
if (req->getFlags() & UNCACHEABLE &&
- (inst != loadQueue.back() || !inst->reachedCommit)) {
+ (inst != loadQueue.back() || !inst->isAtCommit())) {
DPRINTF(OzoneLSQ, "[sn:%lli] Uncached load and not head of "
"commit/LSQ!\n",
inst->seqNum);
DPRINTF(OzoneLSQ, "Forwarding from store [sn:%lli] to load to "
"[sn:%lli] addr %#x, data %#x\n",
- (*sq_it).inst->seqNum, inst->seqNum, req->vaddr, *(inst->memData));
-/*
- typename BackEnd::LdWritebackEvent *wb =
- new typename BackEnd::LdWritebackEvent(inst,
- be);
+ (*sq_it).inst->seqNum, inst->seqNum, req->getVaddr(),
+ *(inst->memData));
+
+ PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
+ data_pkt->dataStatic(inst->memData);
+
+ WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
// We'll say this has a 1 cycle load-store forwarding latency
// for now.
- // FIXME - Need to make this a parameter.
+ // @todo: Need to make this a parameter.
wb->schedule(curTick);
-*/
+
// Should keep track of stat for forwarded data
return NoFault;
} else if ((store_has_lower_limit && lower_load_has_store_part) ||
DPRINTF(OzoneLSQ, "Load-store forwarding mis-match. "
"Store [sn:%lli] to load addr %#x\n",
- (*sq_it).inst->seqNum, req->vaddr);
+ (*sq_it).inst->seqNum, req->getVaddr());
return NoFault;
}
PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
data_pkt->dataStatic(inst->memData);
+ LSQSenderState *state = new LSQSenderState;
+ state->isLoad = true;
+ state->idx = load_idx;
+ state->inst = inst;
+ 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;
* Authors: Kevin Lim
*/
+#include "config/use_checker.hh"
+
#include "arch/isa_traits.hh"
#include "base/str.hh"
#include "cpu/ozone/lw_lsq.hh"
#include "cpu/checker/cpu.hh"
-template <class Impl>
-OzoneLWLSQ<Impl>::StoreCompletionEvent::StoreCompletionEvent(DynInstPtr &_inst,
- BackEnd *_be,
- Event *wb_event,
- OzoneLWLSQ<Impl> *lsq_ptr)
- : Event(&mainEventQueue),
- inst(_inst),
- be(_be),
- wbEvent(wb_event),
- miss(false),
- lsqPtr(lsq_ptr)
+template<class Impl>
+OzoneLWLSQ<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt,
+ OzoneLWLSQ *lsq_ptr)
+ : Event(&mainEventQueue), inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
{
this->setFlags(Event::AutoDelete);
}
-template <class Impl>
+template<class Impl>
void
-OzoneLWLSQ<Impl>::StoreCompletionEvent::process()
+OzoneLWLSQ<Impl>::WritebackEvent::process()
+{
+ if (!lsqPtr->isSwitchedOut()) {
+ lsqPtr->writeback(inst, pkt);
+ }
+ delete pkt;
+}
+
+template<class Impl>
+const char *
+OzoneLWLSQ<Impl>::WritebackEvent::description()
{
- DPRINTF(OzoneLSQ, "Cache miss complete for store [sn:%lli]\n",
- inst->seqNum);
+ return "Store writeback event";
+}
- //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum);
+template <class Impl>
+Tick
+OzoneLWLSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
+{
+ panic("O3CPU model does not work with atomic mode!");
+ return curTick;
+}
-// lsqPtr->cpu->wakeCPU();
- if (lsqPtr->isSwitchedOut()) {
- if (wbEvent)
- delete wbEvent;
+template <class Impl>
+void
+OzoneLWLSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
+{
+ panic("O3CPU doesn't expect recvFunctional callback!");
+}
+template <class Impl>
+void
+OzoneLWLSQ<Impl>::DcachePort::recvStatusChange(Status status)
+{
+ if (status == RangeChange)
return;
- }
- if (wbEvent) {
- wbEvent->process();
- delete wbEvent;
- }
+ panic("O3CPU doesn't expect recvStatusChange callback!");
+}
- lsqPtr->completeStore(inst->sqIdx);
- if (miss)
- be->removeDcacheMiss(inst);
+template <class Impl>
+bool
+OzoneLWLSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
+{
+ lsq->completeDataAccess(pkt);
+ return true;
}
template <class Impl>
-const char *
-OzoneLWLSQ<Impl>::StoreCompletionEvent::description()
+void
+OzoneLWLSQ<Impl>::DcachePort::recvRetry()
+{
+ lsq->recvRetry();
+}
+
+template<class Impl>
+void
+OzoneLWLSQ<Impl>::completeDataAccess(PacketPtr pkt)
{
- return "LSQ store completion event";
+ LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState);
+ DynInstPtr inst = state->inst;
+ DPRINTF(IEW, "Writeback event [sn:%lli]\n", inst->seqNum);
+ DPRINTF(Activity, "Activity: Writeback event [sn:%lli]\n", inst->seqNum);
+
+ //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
+
+ if (isSwitchedOut() || inst->isSquashed()) {
+ delete state;
+ delete pkt;
+ return;
+ } else {
+ if (!state->noWB) {
+ writeback(inst, pkt);
+ }
+
+ if (inst->isStore()) {
+ completeStore(state->idx);
+ }
+ }
+
+ delete state;
+ delete pkt;
}
template <class Impl>
usedPorts = 0;
cachePorts = params->cachePorts;
- dcacheInterface = params->dcacheInterface;
-
loadFaultInst = storeFaultInst = memDepViolator = NULL;
blockedLoadSeqNum = 0;
return "lsqunit";
}
+template<class Impl>
+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);
+
+#if USE_CHECKER
+ if (cpu->checker) {
+ cpu->checker->setDcachePort(dcachePort);
+ }
+#endif
+}
+
template<class Impl>
void
OzoneLWLSQ<Impl>::clearLQ()
(*sq_it).canWB &&
usedPorts < cachePorts) {
+ if (isStoreBlocked) {
+ DPRINTF(OzoneLSQ, "Unable to write back any more stores, cache"
+ " is blocked!\n");
+ break;
+ }
+
DynInstPtr inst = (*sq_it).inst;
if ((*sq_it).size == 0 && !(*sq_it).completed) {
continue;
}
- if (dcacheInterface && dcacheInterface->isBlocked()) {
- DPRINTF(OzoneLSQ, "Unable to write back any more stores, cache"
- " is blocked!\n");
- break;
- }
-
++usedPorts;
assert((*sq_it).req);
assert(!(*sq_it).committed);
+ Request *req = (*sq_it).req;
(*sq_it).committed = true;
- MemReqPtr req = (*sq_it).req;
+ assert(!inst->memData);
+ inst->memData = new uint8_t[64];
+ memcpy(inst->memData, (uint8_t *)&(*sq_it).data,
+ req->getSize());
- req->cmd = Write;
- req->completionEvent = NULL;
- req->time = curTick;
+ PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
+ data_pkt->dataStatic(inst->memData);
- switch((*sq_it).size) {
- case 1:
- cpu->write(req, (uint8_t &)(*sq_it).data);
- break;
- case 2:
- cpu->write(req, (uint16_t &)(*sq_it).data);
- break;
- case 4:
- cpu->write(req, (uint32_t &)(*sq_it).data);
- break;
- case 8:
- cpu->write(req, (uint64_t &)(*sq_it).data);
- break;
- default:
- panic("Unexpected store size!\n");
- }
- if (!(req->flags & LOCKED)) {
- (*sq_it).inst->setCompleted();
- if (cpu->checker) {
- cpu->checker->tick((*sq_it).inst);
+ LSQSenderState *state = new LSQSenderState;
+ state->isLoad = false;
+ state->idx = inst->sqIdx;
+ state->inst = inst;
+ data_pkt->senderState = state;
+
+ DPRINTF(OzoneLSQ, "D-Cache: Writing back store PC:%#x "
+ "to Addr:%#x, data:%#x [sn:%lli]\n",
+ (*sq_it).inst->readPC(),
+ req->getPaddr(), *(inst->memData),
+ inst->seqNum);
+
+ // @todo: Remove this SC hack once the memory system handles it.
+ if (req->getFlags() & LOCKED) {
+ if (req->getFlags() & UNCACHEABLE) {
+ req->setScResult(2);
+ } else {
+ if (cpu->lockFlag) {
+ req->setScResult(1);
+ } else {
+ req->setScResult(0);
+ // Hack: Instantly complete this store.
+ completeDataAccess(data_pkt);
+ --sq_it;
+ continue;
+ }
}
+ } else {
+ // Non-store conditionals do not need a writeback.
+ state->noWB = true;
}
+ if (!dcachePort->sendTiming(data_pkt)) {
+ // Need to handle becoming blocked on a store.
+ isStoreBlocked = true;
+ assert(retryPkt == NULL);
+ retryPkt = data_pkt;
+ } else {
+ storePostSend(data_pkt, inst);
+ --sq_it;
+ }
+/*
DPRINTF(OzoneLSQ, "D-Cache: Writing back store idx:%i PC:%#x "
"to Addr:%#x, data:%#x [sn:%lli]\n",
inst->sqIdx,inst->readPC(),
} else {
panic("Must HAVE DCACHE!!!!!\n");
}
+*/
}
// Not sure this should set it to 0.
SQIndices.push((*sq_it).inst->sqIdx);
(*sq_it).inst = NULL;
(*sq_it).canWB = 0;
-
- if ((*sq_it).req) {
- assert(!(*sq_it).req->completionEvent);
- }
(*sq_it).req = NULL;
--stores;
storeQueue.erase(sq_it++);
cprintf("\n");
}
+template <class Impl>
+void
+OzoneLWLSQ<Impl>::storePostSend(Packet *pkt, DynInstPtr &inst)
+{
+ if (isStalled() &&
+ inst->seqNum == stallingStoreIsn) {
+ DPRINTF(OzoneLSQ, "Unstalling, stalling store [sn:%lli] "
+ "load [sn:%lli]\n",
+ stallingStoreIsn, (*stallingLoad)->seqNum);
+ stalled = false;
+ stallingStoreIsn = 0;
+ be->replayMemInst((*stallingLoad));
+ }
+
+ if (!inst->isStoreConditional()) {
+ // The store is basically completed at this time. This
+ // only works so long as the checker doesn't try to
+ // verify the value in memory for stores.
+ inst->setCompleted();
+#if USE_CHECKER
+ if (cpu->checker) {
+ cpu->checker->verify(inst);
+ }
+#endif
+ }
+
+ if (pkt->result != Packet::Success) {
+ DPRINTF(OzoneLSQ,"D-Cache Write Miss!\n");
+
+ DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n",
+ inst->seqNum);
+
+ //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum);
+
+ //DPRINTF(OzoneLWLSQ, "Added MSHR. count = %i\n",mshrSeqNums.size());
+
+ // @todo: Increment stat here.
+ } else {
+ DPRINTF(OzoneLSQ,"D-Cache: Write Hit!\n");
+
+ DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
+ inst->seqNum);
+ }
+}
+
+template <class Impl>
+void
+OzoneLWLSQ<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt)
+{
+ // Squashed instructions do not need to complete their access.
+ if (inst->isSquashed()) {
+ assert(!inst->isStore());
+ return;
+ }
+
+ if (!inst->isExecuted()) {
+ inst->setExecuted();
+
+ // Complete access to copy data to proper place.
+ inst->completeAcc(pkt);
+ }
+
+ // Need to insert instruction into queue to commit
+ be->instToCommit(inst);
+}
+
template <class Impl>
void
OzoneLWLSQ<Impl>::completeStore(int store_idx)
--stores;
inst->setCompleted();
+#if USE_CHECKER
if (cpu->checker) {
- cpu->checker->tick(inst);
+ cpu->checker->verify(inst);
}
+#endif
+}
+
+template <class Impl>
+void
+OzoneLWLSQ<Impl>::recvRetry()
+{
+ panic("Unimplemented!");
}
template <class Impl>
{
assert(storesToWB == 0);
switchedOut = true;
- SQIt sq_it = --(storeQueue.end());
- while (storesToWB > 0 &&
- sq_it != storeQueue.end() &&
- (*sq_it).inst &&
- (*sq_it).canWB) {
-
- DynInstPtr inst = (*sq_it).inst;
-
- if ((*sq_it).size == 0 && !(*sq_it).completed) {
- sq_it--;
- continue;
- }
-
- // Store conditionals don't complete until *after* they have written
- // back. If it's here and not yet sent to memory, then don't bother
- // as it's not part of committed state.
- if (inst->isDataPrefetch() || (*sq_it).committed) {
- sq_it--;
- continue;
- } else if ((*sq_it).req->flags & LOCKED) {
- sq_it--;
- assert(!(*sq_it).canWB ||
- ((*sq_it).canWB && (*sq_it).req->flags & LOCKED));
- continue;
- }
-
- assert((*sq_it).req);
- assert(!(*sq_it).committed);
-
- MemReqPtr req = (*sq_it).req;
- (*sq_it).committed = true;
-
- req->cmd = Write;
- req->completionEvent = NULL;
- req->time = curTick;
- assert(!req->data);
- req->data = new uint8_t[64];
- memcpy(req->data, (uint8_t *)&(*sq_it).data, req->size);
-
- DPRINTF(OzoneLSQ, "Switching out : Writing back store idx:%i PC:%#x "
- "to Addr:%#x, data:%#x directly to memory [sn:%lli]\n",
- inst->sqIdx,inst->readPC(),
- req->paddr, *(req->data),
- inst->seqNum);
-
- switch((*sq_it).size) {
- case 1:
- cpu->write(req, (uint8_t &)(*sq_it).data);
- break;
- case 2:
- cpu->write(req, (uint16_t &)(*sq_it).data);
- break;
- case 4:
- cpu->write(req, (uint32_t &)(*sq_it).data);
- break;
- case 8:
- cpu->write(req, (uint64_t &)(*sq_it).data);
- break;
- default:
- panic("Unexpected store size!\n");
- }
- }
// Clear the queue to free up resources
storeQueue.clear();
struct OzoneImpl {
typedef SimpleParams Params;
typedef OzoneCPU<OzoneImpl> OzoneCPU;
- typedef OzoneCPU FullCPU;
+ typedef OzoneCPU CPUType;
// Would like to put these into their own area.
// typedef NullPredictor BranchPred;
#include "cpu/ozone/rename_table_impl.hh"
#include "cpu/ozone/ozone_impl.hh"
-#include "cpu/ozone/simple_impl.hh"
+//#include "cpu/ozone/simple_impl.hh"
template class RenameTable<OzoneImpl>;
-template class RenameTable<SimpleImpl>;
+//template class RenameTable<SimpleImpl>;
--- /dev/null
+/*
+ * 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: Kevin Lim
+ */
+
+#include <string>
+
+#include "cpu/checker/cpu.hh"
+#include "cpu/inst_seq.hh"
+#include "cpu/ozone/cpu_impl.hh"
+#include "cpu/ozone/simple_impl.hh"
+#include "cpu/ozone/simple_params.hh"
+#include "mem/cache/base_cache.hh"
+#include "sim/builder.hh"
+#include "sim/process.hh"
+#include "sim/sim_object.hh"
+
+template
+class OzoneCPU<SimpleImpl>;
+
+class SimpleOzoneCPU : public OzoneCPU<SimpleImpl>
+{
+ public:
+ SimpleOzoneCPU(SimpleParams *p)
+ : OzoneCPU<SimpleImpl>(p)
+ { }
+};
+
+////////////////////////////////////////////////////////////////////////
+//
+// OzoneCPU Simulation Object
+//
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
+
+ Param<int> clock;
+ Param<int> numThreads;
+
+#if FULL_SYSTEM
+SimObjectParam<System *> system;
+Param<int> cpu_id;
+SimObjectParam<AlphaITB *> itb;
+SimObjectParam<AlphaDTB *> dtb;
+#else
+SimObjectVectorParam<Process *> workload;
+//SimObjectParam<PageTable *> page_table;
+#endif // FULL_SYSTEM
+
+SimObjectParam<FunctionalMemory *> mem;
+
+SimObjectParam<BaseCPU *> checker;
+
+Param<Counter> max_insts_any_thread;
+Param<Counter> max_insts_all_threads;
+Param<Counter> max_loads_any_thread;
+Param<Counter> max_loads_all_threads;
+
+SimObjectParam<BaseCache *> icache;
+SimObjectParam<BaseCache *> dcache;
+
+Param<unsigned> cachePorts;
+Param<unsigned> width;
+Param<unsigned> frontEndWidth;
+Param<unsigned> backEndWidth;
+Param<unsigned> backEndSquashLatency;
+Param<unsigned> backEndLatency;
+Param<unsigned> maxInstBufferSize;
+Param<unsigned> numPhysicalRegs;
+
+Param<unsigned> decodeToFetchDelay;
+Param<unsigned> renameToFetchDelay;
+Param<unsigned> iewToFetchDelay;
+Param<unsigned> commitToFetchDelay;
+Param<unsigned> fetchWidth;
+
+Param<unsigned> renameToDecodeDelay;
+Param<unsigned> iewToDecodeDelay;
+Param<unsigned> commitToDecodeDelay;
+Param<unsigned> fetchToDecodeDelay;
+Param<unsigned> decodeWidth;
+
+Param<unsigned> iewToRenameDelay;
+Param<unsigned> commitToRenameDelay;
+Param<unsigned> decodeToRenameDelay;
+Param<unsigned> renameWidth;
+
+Param<unsigned> commitToIEWDelay;
+Param<unsigned> renameToIEWDelay;
+Param<unsigned> issueToExecuteDelay;
+Param<unsigned> issueWidth;
+Param<unsigned> executeWidth;
+Param<unsigned> executeIntWidth;
+Param<unsigned> executeFloatWidth;
+Param<unsigned> executeBranchWidth;
+Param<unsigned> executeMemoryWidth;
+
+Param<unsigned> iewToCommitDelay;
+Param<unsigned> renameToROBDelay;
+Param<unsigned> commitWidth;
+Param<unsigned> squashWidth;
+
+Param<std::string> predType;
+Param<unsigned> localPredictorSize;
+Param<unsigned> localCtrBits;
+Param<unsigned> localHistoryTableSize;
+Param<unsigned> localHistoryBits;
+Param<unsigned> globalPredictorSize;
+Param<unsigned> globalCtrBits;
+Param<unsigned> globalHistoryBits;
+Param<unsigned> choicePredictorSize;
+Param<unsigned> choiceCtrBits;
+
+Param<unsigned> BTBEntries;
+Param<unsigned> BTBTagSize;
+
+Param<unsigned> RASSize;
+
+Param<unsigned> LQEntries;
+Param<unsigned> SQEntries;
+Param<unsigned> LFSTSize;
+Param<unsigned> SSITSize;
+
+Param<unsigned> numPhysIntRegs;
+Param<unsigned> numPhysFloatRegs;
+Param<unsigned> numIQEntries;
+Param<unsigned> numROBEntries;
+
+Param<bool> decoupledFrontEnd;
+Param<int> dispatchWidth;
+Param<int> wbWidth;
+
+Param<unsigned> smtNumFetchingThreads;
+Param<std::string> smtFetchPolicy;
+Param<std::string> smtLSQPolicy;
+Param<unsigned> smtLSQThreshold;
+Param<std::string> smtIQPolicy;
+Param<unsigned> smtIQThreshold;
+Param<std::string> smtROBPolicy;
+Param<unsigned> smtROBThreshold;
+Param<std::string> smtCommitPolicy;
+
+Param<unsigned> instShiftAmt;
+
+Param<bool> defer_registration;
+
+Param<bool> function_trace;
+Param<Tick> function_trace_start;
+
+END_DECLARE_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
+
+ INIT_PARAM(clock, "clock speed"),
+ INIT_PARAM(numThreads, "number of HW thread contexts"),
+
+#if FULL_SYSTEM
+ INIT_PARAM(system, "System object"),
+ INIT_PARAM(cpu_id, "processor ID"),
+ INIT_PARAM(itb, "Instruction translation buffer"),
+ INIT_PARAM(dtb, "Data translation buffer"),
+#else
+ INIT_PARAM(workload, "Processes to run"),
+// INIT_PARAM(page_table, "Page table"),
+#endif // FULL_SYSTEM
+
+ INIT_PARAM_DFLT(mem, "Memory", NULL),
+
+ INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
+
+ INIT_PARAM_DFLT(max_insts_any_thread,
+ "Terminate when any thread reaches this inst count",
+ 0),
+ INIT_PARAM_DFLT(max_insts_all_threads,
+ "Terminate when all threads have reached"
+ "this inst count",
+ 0),
+ INIT_PARAM_DFLT(max_loads_any_thread,
+ "Terminate when any thread reaches this load count",
+ 0),
+ INIT_PARAM_DFLT(max_loads_all_threads,
+ "Terminate when all threads have reached this load"
+ "count",
+ 0),
+
+ INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
+ INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
+
+ INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
+ INIT_PARAM_DFLT(width, "Width", 1),
+ INIT_PARAM_DFLT(frontEndWidth, "Front end width", 1),
+ INIT_PARAM_DFLT(backEndWidth, "Back end width", 1),
+ INIT_PARAM_DFLT(backEndSquashLatency, "Back end squash latency", 1),
+ INIT_PARAM_DFLT(backEndLatency, "Back end latency", 1),
+ INIT_PARAM_DFLT(maxInstBufferSize, "Maximum instruction buffer size", 16),
+ INIT_PARAM(numPhysicalRegs, "Number of physical registers"),
+
+ INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
+ INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"),
+ INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch"
+ "delay"),
+ INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"),
+ INIT_PARAM(fetchWidth, "Fetch width"),
+ INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"),
+ INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode"
+ "delay"),
+ INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"),
+ INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"),
+ INIT_PARAM(decodeWidth, "Decode width"),
+
+ INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename"
+ "delay"),
+ INIT_PARAM(commitToRenameDelay, "Commit to rename delay"),
+ INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"),
+ INIT_PARAM(renameWidth, "Rename width"),
+
+ INIT_PARAM(commitToIEWDelay, "Commit to "
+ "Issue/Execute/Writeback delay"),
+ INIT_PARAM(renameToIEWDelay, "Rename to "
+ "Issue/Execute/Writeback delay"),
+ INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
+ "to the IEW stage)"),
+ INIT_PARAM(issueWidth, "Issue width"),
+ INIT_PARAM(executeWidth, "Execute width"),
+ INIT_PARAM(executeIntWidth, "Integer execute width"),
+ INIT_PARAM(executeFloatWidth, "Floating point execute width"),
+ INIT_PARAM(executeBranchWidth, "Branch execute width"),
+ INIT_PARAM(executeMemoryWidth, "Memory execute width"),
+
+ INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
+ "delay"),
+ INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"),
+ INIT_PARAM(commitWidth, "Commit width"),
+ INIT_PARAM(squashWidth, "Squash width"),
+
+ INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
+ INIT_PARAM(localPredictorSize, "Size of local predictor"),
+ INIT_PARAM(localCtrBits, "Bits per counter"),
+ INIT_PARAM(localHistoryTableSize, "Size of local history table"),
+ INIT_PARAM(localHistoryBits, "Bits for the local history"),
+ INIT_PARAM(globalPredictorSize, "Size of global predictor"),
+ INIT_PARAM(globalCtrBits, "Bits per counter"),
+ INIT_PARAM(globalHistoryBits, "Bits of history"),
+ INIT_PARAM(choicePredictorSize, "Size of choice predictor"),
+ INIT_PARAM(choiceCtrBits, "Bits of choice counters"),
+
+ INIT_PARAM(BTBEntries, "Number of BTB entries"),
+ INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"),
+
+ INIT_PARAM(RASSize, "RAS size"),
+
+ INIT_PARAM(LQEntries, "Number of load queue entries"),
+ INIT_PARAM(SQEntries, "Number of store queue entries"),
+ INIT_PARAM(LFSTSize, "Last fetched store table size"),
+ INIT_PARAM(SSITSize, "Store set ID table size"),
+
+ INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"),
+ INIT_PARAM(numPhysFloatRegs, "Number of physical floating point "
+ "registers"),
+ INIT_PARAM(numIQEntries, "Number of instruction queue entries"),
+ INIT_PARAM(numROBEntries, "Number of reorder buffer entries"),
+
+ INIT_PARAM_DFLT(decoupledFrontEnd, "Decoupled front end", true),
+ INIT_PARAM_DFLT(dispatchWidth, "Dispatch width", 0),
+ INIT_PARAM_DFLT(wbWidth, "Writeback width", 0),
+
+ INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1),
+ INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"),
+ INIT_PARAM_DFLT(smtLSQPolicy, "SMT LSQ Sharing Policy", "Partitioned"),
+ INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100),
+ INIT_PARAM_DFLT(smtIQPolicy, "SMT IQ Policy", "Partitioned"),
+ INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100),
+ INIT_PARAM_DFLT(smtROBPolicy, "SMT ROB Sharing Policy", "Partitioned"),
+ INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100),
+ INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"),
+
+ INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"),
+ INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
+
+ INIT_PARAM(function_trace, "Enable function trace"),
+ INIT_PARAM(function_trace_start, "Cycle to start function trace")
+
+END_INIT_SIM_OBJECT_PARAMS(SimpleOzoneCPU)
+
+CREATE_SIM_OBJECT(SimpleOzoneCPU)
+{
+ SimpleOzoneCPU *cpu;
+
+#if FULL_SYSTEM
+ // Full-system only supports a single thread for the moment.
+ int actual_num_threads = 1;
+#else
+ // In non-full-system mode, we infer the number of threads from
+ // the workload if it's not explicitly specified.
+ int actual_num_threads =
+ numThreads.isValid() ? numThreads : workload.size();
+
+ if (workload.size() == 0) {
+ fatal("Must specify at least one workload!");
+ }
+
+#endif
+
+ SimpleParams *params = new SimpleParams;
+
+ params->clock = clock;
+
+ params->name = getInstanceName();
+ params->numberOfThreads = actual_num_threads;
+
+#if FULL_SYSTEM
+ params->system = system;
+ params->cpu_id = cpu_id;
+ params->itb = itb;
+ params->dtb = dtb;
+#else
+ params->workload = workload;
+// params->pTable = page_table;
+#endif // FULL_SYSTEM
+
+ params->mem = mem;
+ params->checker = checker;
+ params->max_insts_any_thread = max_insts_any_thread;
+ params->max_insts_all_threads = max_insts_all_threads;
+ params->max_loads_any_thread = max_loads_any_thread;
+ params->max_loads_all_threads = max_loads_all_threads;
+
+ //
+ // Caches
+ //
+ params->icacheInterface = icache ? icache->getInterface() : NULL;
+ params->dcacheInterface = dcache ? dcache->getInterface() : NULL;
+ params->cachePorts = cachePorts;
+
+ params->width = width;
+ params->frontEndWidth = frontEndWidth;
+ params->backEndWidth = backEndWidth;
+ params->backEndSquashLatency = backEndSquashLatency;
+ params->backEndLatency = backEndLatency;
+ params->maxInstBufferSize = maxInstBufferSize;
+ params->numPhysicalRegs = numPhysIntRegs + numPhysFloatRegs;
+
+ params->decodeToFetchDelay = decodeToFetchDelay;
+ params->renameToFetchDelay = renameToFetchDelay;
+ params->iewToFetchDelay = iewToFetchDelay;
+ params->commitToFetchDelay = commitToFetchDelay;
+ params->fetchWidth = fetchWidth;
+
+ params->renameToDecodeDelay = renameToDecodeDelay;
+ params->iewToDecodeDelay = iewToDecodeDelay;
+ params->commitToDecodeDelay = commitToDecodeDelay;
+ params->fetchToDecodeDelay = fetchToDecodeDelay;
+ params->decodeWidth = decodeWidth;
+
+ params->iewToRenameDelay = iewToRenameDelay;
+ params->commitToRenameDelay = commitToRenameDelay;
+ params->decodeToRenameDelay = decodeToRenameDelay;
+ params->renameWidth = renameWidth;
+
+ params->commitToIEWDelay = commitToIEWDelay;
+ params->renameToIEWDelay = renameToIEWDelay;
+ params->issueToExecuteDelay = issueToExecuteDelay;
+ params->issueWidth = issueWidth;
+ params->executeWidth = executeWidth;
+ params->executeIntWidth = executeIntWidth;
+ params->executeFloatWidth = executeFloatWidth;
+ params->executeBranchWidth = executeBranchWidth;
+ params->executeMemoryWidth = executeMemoryWidth;
+
+ params->iewToCommitDelay = iewToCommitDelay;
+ params->renameToROBDelay = renameToROBDelay;
+ params->commitWidth = commitWidth;
+ params->squashWidth = squashWidth;
+
+ params->predType = predType;
+ params->localPredictorSize = localPredictorSize;
+ params->localCtrBits = localCtrBits;
+ params->localHistoryTableSize = localHistoryTableSize;
+ params->localHistoryBits = localHistoryBits;
+ params->globalPredictorSize = globalPredictorSize;
+ params->globalCtrBits = globalCtrBits;
+ params->globalHistoryBits = globalHistoryBits;
+ params->choicePredictorSize = choicePredictorSize;
+ params->choiceCtrBits = choiceCtrBits;
+
+ params->BTBEntries = BTBEntries;
+ params->BTBTagSize = BTBTagSize;
+
+ params->RASSize = RASSize;
+
+ params->LQEntries = LQEntries;
+ params->SQEntries = SQEntries;
+
+ params->SSITSize = SSITSize;
+ params->LFSTSize = LFSTSize;
+
+ params->numPhysIntRegs = numPhysIntRegs;
+ params->numPhysFloatRegs = numPhysFloatRegs;
+ params->numIQEntries = numIQEntries;
+ params->numROBEntries = numROBEntries;
+
+ params->decoupledFrontEnd = decoupledFrontEnd;
+ params->dispatchWidth = dispatchWidth;
+ params->wbWidth = wbWidth;
+
+ params->smtNumFetchingThreads = smtNumFetchingThreads;
+ params->smtFetchPolicy = smtFetchPolicy;
+ params->smtIQPolicy = smtIQPolicy;
+ params->smtLSQPolicy = smtLSQPolicy;
+ params->smtLSQThreshold = smtLSQThreshold;
+ params->smtROBPolicy = smtROBPolicy;
+ params->smtROBThreshold = smtROBThreshold;
+ params->smtCommitPolicy = smtCommitPolicy;
+
+ params->instShiftAmt = 2;
+
+ params->deferRegistration = defer_registration;
+
+ params->functionTrace = function_trace;
+ params->functionTraceStart = function_trace_start;
+
+ cpu = new SimpleOzoneCPU(params);
+
+ return cpu;
+}
+
+REGISTER_SIM_OBJECT("SimpleOzoneCPU", SimpleOzoneCPU)
+
class AlphaDTB;
class AlphaITB;
class FUPool;
-class FunctionalMemory;
-class MemInterface;
+class MemObject;
class PageTable;
class Process;
class System;
//Page Table
PageTable *pTable;
- FunctionalMemory *mem;
+ MemObject *mem;
//
// Caches
//
- MemInterface *icacheInterface;
- MemInterface *dcacheInterface;
+// MemInterface *icacheInterface;
+// MemInterface *dcacheInterface;
unsigned cachePorts;
unsigned width;
template <class Impl>
struct OzoneThreadState : public ThreadState {
typedef typename ThreadContext::Status Status;
- typedef typename Impl::FullCPU FullCPU;
+ typedef typename Impl::CPUType CPUType;
typedef TheISA::MiscReg MiscReg;
#if FULL_SYSTEM
- OzoneThreadState(FullCPU *_cpu, int _thread_num)
+ OzoneThreadState(CPUType *_cpu, int _thread_num)
: ThreadState(-1, _thread_num),
- inSyscall(0), trapPending(0)
+ intrflag(0), inSyscall(0), trapPending(0)
{
- memset(®s, 0, sizeof(TheISA::RegFile));
+ miscRegFile.clear();
}
#else
- OzoneThreadState(FullCPU *_cpu, int _thread_num, Process *_process, int _asid)
- : ThreadState(-1, _thread_num, NULL, _process, _asid),
+ OzoneThreadState(CPUType *_cpu, int _thread_num, Process *_process,
+ int _asid, MemObject *mem)
+ : ThreadState(-1, _thread_num, _process, _asid, mem),
cpu(_cpu), inSyscall(0), trapPending(0)
{
- memset(®s, 0, sizeof(TheISA::RegFile));
- }
-
- OzoneThreadState(FullCPU *_cpu, int _thread_num,
- int _asid)
- : ThreadState(-1, _thread_num, NULL, NULL, _asid),
- cpu(_cpu), inSyscall(0), trapPending(0)
- {
- memset(®s, 0, sizeof(TheISA::RegFile));
+ miscRegFile.clear();
}
#endif
Addr nextPC;
- TheISA::RegFile regs;
+ TheISA::MiscRegFile miscRegFile;
+
+ int intrflag;
- typename Impl::FullCPU *cpu;
+ typename Impl::CPUType *cpu;
bool inSyscall;
ThreadContext *getTC() { return tc; }
-#if !FULL_SYSTEM
- Fault translateInstReq(Request *req)
- {
- return process->pTable->translate(req);
- }
- Fault translateDataReadReq(Request *req)
- {
- return process->pTable->translate(req);
- }
- Fault translateDataWriteReq(Request *req)
- {
- return process->pTable->translate(req);
- }
-#else
- Fault translateInstReq(Request *req)
- {
- return cpu->itb->translate(req);
- }
-
- Fault translateDataReadReq(Request *req)
- {
- return cpu->dtb->translate(req, false);
- }
-
- Fault translateDataWriteReq(Request *req)
- {
- return cpu->dtb->translate(req, true);
- }
-#endif
-
MiscReg readMiscReg(int misc_reg)
{
- return regs.readMiscReg(misc_reg);
+ return miscRegFile.readReg(misc_reg);
}
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
{
- return regs.readMiscRegWithEffect(misc_reg, fault, tc);
+ return miscRegFile.readRegWithEffect(misc_reg, fault, tc);
}
Fault setMiscReg(int misc_reg, const MiscReg &val)
{
- return regs.setMiscReg(misc_reg, val);
+ return miscRegFile.setReg(misc_reg, val);
}
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
{
- return regs.setMiscRegWithEffect(misc_reg, val, tc);
+ return miscRegFile.setRegWithEffect(misc_reg, val, tc);
}
uint64_t readPC()