diff options
Diffstat (limited to 'cpu')
58 files changed, 1725 insertions, 1334 deletions
diff --git a/cpu/SConscript b/cpu/SConscript new file mode 100644 index 000000000..af6bab4eb --- /dev/null +++ b/cpu/SConscript @@ -0,0 +1,129 @@ +# -*- mode:python -*- + +# 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. + +import os +import os.path + +# Import build environment variable from SConstruct. +Import('env') + +################################################################# +# +# Generate StaticInst execute() method signatures. +# +# There must be one signature for each CPU model compiled in. +# Since the set of compiled-in models is flexible, we generate a +# header containing the appropriate set of signatures on the fly. +# +################################################################# + +# CPU model-specific data is contained in cpu_models.py +# Convert to SCons File node to get path handling +models_db = File('cpu_models.py') +# slurp in contents of file +execfile(models_db.srcnode().abspath) + +# Template for execute() signature. +exec_sig_template = ''' +virtual Fault execute(%s *xc, Trace::InstRecord *traceData) const = 0; +''' + +# Generate header. +def gen_cpu_exec_signatures(target, source, env): + f = open(str(target[0]), 'w') + print >> f, ''' +#ifndef __CPU_STATIC_INST_EXEC_SIGS_HH__ +#define __CPU_STATIC_INST_EXEC_SIGS_HH__ +''' + for cpu in env['CPU_MODELS']: + xc_type = CpuModel.dict[cpu].strings['CPU_exec_context'] + print >> f, exec_sig_template % xc_type + print >> f, ''' +#endif // __CPU_STATIC_INST_EXEC_SIGS_HH__ +''' + +# Generate string that gets printed when header is rebuilt +def gen_sigs_string(target, source, env): + return "Generating static_inst_exec_sigs.hh: " \ + + ', '.join(env['CPU_MODELS']) + +# Add command to generate header to environment. +env.Command('static_inst_exec_sigs.hh', models_db, + Action(gen_cpu_exec_signatures, gen_sigs_string, + varlist = ['CPU_MODELS'])) + +################################################################# +# +# Include CPU-model-specific files based on set of models +# specified in CPU_MODELS build option. +# +################################################################# + +sources = [] + +if 'SimpleCPU' in env['CPU_MODELS']: + sources += Split('simple/cpu.cc') + +if 'FastCPU' in env['CPU_MODELS']: + sources += Split('fast/cpu.cc') + +if 'AlphaFullCPU' in env['CPU_MODELS']: + sources += Split(''' + o3/2bit_local_pred.cc + o3/alpha_dyn_inst.cc + o3/alpha_cpu.cc + o3/alpha_cpu_builder.cc + o3/bpred_unit.cc + o3/btb.cc + o3/commit.cc + o3/decode.cc + o3/fetch.cc + o3/free_list.cc + o3/cpu.cc + o3/iew.cc + o3/inst_queue.cc + o3/ldstq.cc + o3/mem_dep_unit.cc + o3/ras.cc + o3/rename.cc + o3/rename_map.cc + o3/rob.cc + o3/sat_counter.cc + o3/store_set.cc + o3/tournament_pred.cc + ''') + +# FullCPU sources are included from m5/SConscript since they're not +# below this point in the file hierarchy. + +# Convert file names to SCons File objects. This takes care of the +# path relative to the top of the directory tree. +sources = [File(s) for s in sources] + +Return('sources') + diff --git a/cpu/base.cc b/cpu/base.cc index 154143712..9ce458c64 100644 --- a/cpu/base.cc +++ b/cpu/base.cc @@ -39,10 +39,16 @@ #include "cpu/profile.hh" #include "cpu/sampler/sampler.hh" #include "sim/param.hh" +#include "sim/process.hh" #include "sim/sim_events.hh" +#include "sim/system.hh" #include "base/trace.hh" +#if FULL_SYSTEM +#include "kern/kernel_stats.hh" +#endif + using namespace std; vector<BaseCPU *> BaseCPU::cpuList; @@ -147,7 +153,10 @@ BaseCPU::BaseCPU(Params *p) profileEvent = NULL; if (params->profile) profileEvent = new ProfileEvent(this, params->profile); + + kernelStats = new Kernel::Statistics(system); #endif + } BaseCPU::Params::Params() @@ -165,6 +174,10 @@ BaseCPU::enableFunctionTrace() BaseCPU::~BaseCPU() { +#if FULL_SYSTEM + if (kernelStats) + delete kernelStats; +#endif } void @@ -203,6 +216,11 @@ BaseCPU::regStats() } } else if (size == 1) execContexts[0]->regStats(name()); + +#if FULL_SYSTEM + if (kernelStats) + kernelStats->regStats(name() + ".kern"); +#endif } @@ -217,9 +235,9 @@ BaseCPU::registerExecContexts() if (id != -1) id += i; - xc->cpu_id = system->registerExecContext(xc, id); + xc->setCpuId(system->registerExecContext(xc, id)); #else - xc->cpu_id = xc->process->registerExecContext(xc); + xc->setCpuId(xc->getProcessPtr()->registerExecContext(xc)); #endif } } @@ -241,23 +259,22 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) ExecContext *oldXC = oldCPU->execContexts[i]; newXC->takeOverFrom(oldXC); - assert(newXC->cpu_id == oldXC->cpu_id); + assert(newXC->readCpuId() == oldXC->readCpuId()); #if FULL_SYSTEM - system->replaceExecContext(newXC, newXC->cpu_id); + system->replaceExecContext(newXC, newXC->readCpuId()); #else - assert(newXC->process == oldXC->process); - newXC->process->replaceExecContext(newXC, newXC->cpu_id); + assert(newXC->getProcessPtr() == oldXC->getProcessPtr()); + newXC->getProcessPtr()->replaceExecContext(newXC, newXC->readCpuId()); #endif } #if FULL_SYSTEM - for (int i = 0; i < NumInterruptLevels; ++i) + for (int i = 0; i < TheISA::NumInterruptLevels; ++i) interrupts[i] = oldCPU->interrupts[i]; intstatus = oldCPU->intstatus; for (int i = 0; i < execContexts.size(); ++i) - if (execContexts[i]->profile) - execContexts[i]->profile->clear(); + execContexts[i]->profileClear(); if (profileEvent) profileEvent->schedule(curTick); @@ -275,7 +292,7 @@ BaseCPU::ProfileEvent::process() { for (int i = 0, size = cpu->execContexts.size(); i < size; ++i) { ExecContext *xc = cpu->execContexts[i]; - xc->profile->sample(xc->profileNode, xc->profilePC); + xc->profileSample(); } schedule(curTick + interval); @@ -286,7 +303,7 @@ BaseCPU::post_interrupt(int int_num, int index) { DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); - if (int_num < 0 || int_num >= NumInterruptLevels) + if (int_num < 0 || int_num >= TheISA::NumInterruptLevels) panic("int_num out of bounds\n"); if (index < 0 || index >= sizeof(uint64_t) * 8) @@ -302,7 +319,7 @@ BaseCPU::clear_interrupt(int int_num, int index) { DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); - if (int_num < 0 || int_num >= NumInterruptLevels) + if (int_num < 0 || int_num >= TheISA::NumInterruptLevels) panic("int_num out of bounds\n"); if (index < 0 || index >= sizeof(uint64_t) * 8) @@ -326,15 +343,26 @@ BaseCPU::clear_interrupts() void BaseCPU::serialize(std::ostream &os) { - SERIALIZE_ARRAY(interrupts, NumInterruptLevels); + SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels); SERIALIZE_SCALAR(intstatus); + +#if FULL_SYSTEM + if (kernelStats) + kernelStats->serialize(os); +#endif + } void BaseCPU::unserialize(Checkpoint *cp, const std::string §ion) { - UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); + UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels); UNSERIALIZE_SCALAR(intstatus); + +#if FULL_SYSTEM + if (kernelStats) + kernelStats->unserialize(cp, section); +#endif } #endif // FULL_SYSTEM diff --git a/cpu/base.hh b/cpu/base.hh index c0e087f42..0866b49a7 100644 --- a/cpu/base.hh +++ b/cpu/base.hh @@ -36,9 +36,10 @@ #include "cpu/sampler/sampler.hh" #include "sim/eventq.hh" #include "sim/sim_object.hh" -#include "targetarch/isa_traits.hh" +#include "arch/isa_traits.hh" class System; +namespace Kernel { class Statistics; } class BranchPred; class ExecContext; class Port; @@ -56,7 +57,7 @@ class BaseCPU : public SimObject #if FULL_SYSTEM protected: - uint64_t interrupts[NumInterruptLevels]; + uint64_t interrupts[TheISA::NumInterruptLevels]; uint64_t intstatus; public: @@ -66,7 +67,7 @@ class BaseCPU : public SimObject bool checkInterrupts; bool check_interrupt(int int_num) const { - if (int_num > NumInterruptLevels) + if (int_num > TheISA::NumInterruptLevels) panic("int_num out of bounds\n"); return interrupts[int_num] != 0; @@ -138,6 +139,8 @@ class BaseCPU : public SimObject virtual void startup(); virtual void regStats(); + virtual void activateWhenReady(int tid) {}; + void registerExecContexts(); /// Prepare for another CPU to take over execution. When it is @@ -230,6 +233,10 @@ class BaseCPU : public SimObject public: // Number of CPU cycles simulated Stats::Scalar<> numCycles; + +#if FULL_SYSTEM + Kernel::Statistics *kernelStats; +#endif }; #endif // __CPU_BASE_HH__ diff --git a/cpu/base_dyn_inst.cc b/cpu/base_dyn_inst.cc index d921bd148..bf7c35cad 100644 --- a/cpu/base_dyn_inst.cc +++ b/cpu/base_dyn_inst.cc @@ -36,7 +36,7 @@ #include "base/cprintf.hh" #include "base/trace.hh" -#include "arch/alpha/faults.hh" +#include "arch/faults.hh" #include "cpu/exetrace.hh" #include "mem/mem_req.hh" @@ -45,6 +45,7 @@ #include "cpu/o3/alpha_cpu.hh" using namespace std; +using namespace TheISA; #define NOHASH #ifndef NOHASH @@ -67,7 +68,7 @@ template <class Impl> BaseDynInst<Impl>::BaseDynInst(MachInst machInst, Addr inst_PC, Addr pred_PC, InstSeqNum seq_num, FullCPU *cpu) - : staticInst(machInst), traceData(NULL), cpu(cpu), xc(cpu->xcBase()) + : staticInst(machInst), traceData(NULL), cpu(cpu), cpuXC(cpu->cpuXCBase()) { seqNum = seq_num; @@ -79,7 +80,7 @@ BaseDynInst<Impl>::BaseDynInst(MachInst machInst, Addr inst_PC, } template <class Impl> -BaseDynInst<Impl>::BaseDynInst(StaticInstPtr<ISA> &_staticInst) +BaseDynInst<Impl>::BaseDynInst(StaticInstPtr &_staticInst) : staticInst(_staticInst), traceData(NULL) { initVars(); @@ -113,7 +114,7 @@ BaseDynInst<Impl>::initVars() asid = 0; // Initialize the fault to be unimplemented opcode. - fault = Unimplemented_Opcode_Fault; + fault = new UnimplementedOpcodeFault; ++instcount; @@ -138,16 +139,16 @@ BaseDynInst<Impl>::prefetch(Addr addr, unsigned flags) // state. // Generate a MemReq so we can translate the effective address. - MemReqPtr req = new MemReq(addr, xc, 1, flags); + MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), 1, flags); req->asid = asid; // Prefetches never cause faults. - fault = No_Fault; + fault = NoFault; // note this is a local, not BaseDynInst::fault - Fault trans_fault = xc->translateDataReadReq(req); + Fault trans_fault = cpuXC->translateDataReadReq(req); - if (trans_fault == No_Fault && !(req->flags & UNCACHEABLE)) { + if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) { // It's a valid address to cacheable space. Record key MemReq // parameters so we can generate another one just like it for // the timing access without calling translate() again (which @@ -183,12 +184,12 @@ BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags) // will casue a TLB miss trap if necessary... not sure whether // that's the best thing to do or not. We don't really need the // MemReq otherwise, since wh64 has no functional effect. - MemReqPtr req = new MemReq(addr, xc, size, flags); + MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), size, flags); req->asid = asid; - fault = xc->translateDataWriteReq(req); + fault = cpuXC->translateDataWriteReq(req); - if (fault == No_Fault && !(req->flags & UNCACHEABLE)) { + if (fault == NoFault && !(req->flags & UNCACHEABLE)) { // Record key MemReq parameters so we can generate another one // just like it for the timing access without calling translate() // again (which might mess up the TLB). @@ -211,18 +212,18 @@ template <class Impl> Fault BaseDynInst<Impl>::copySrcTranslate(Addr src) { - MemReqPtr req = new MemReq(src, xc, 64); + MemReqPtr req = new MemReq(src, cpuXC->getProxy(), 64); req->asid = asid; // translate to physical address - Fault fault = xc->translateDataReadReq(req); + Fault fault = cpuXC->translateDataReadReq(req); - if (fault == No_Fault) { - xc->copySrcAddr = src; - xc->copySrcPhysAddr = req->paddr; + if (fault == NoFault) { + cpuXC->copySrcAddr = src; + cpuXC->copySrcPhysAddr = req->paddr; } else { - xc->copySrcAddr = 0; - xc->copySrcPhysAddr = 0; + cpuXC->copySrcAddr = 0; + cpuXC->copySrcPhysAddr = 0; } return fault; } @@ -235,18 +236,18 @@ Fault BaseDynInst<Impl>::copy(Addr dest) { uint8_t data[64]; - FunctionalMemory *mem = xc->mem; - assert(xc->copySrcPhysAddr || xc->misspeculating()); - MemReqPtr req = new MemReq(dest, xc, 64); + FunctionalMemory *mem = cpuXC->mem; + assert(cpuXC->copySrcPhysAddr || cpuXC->misspeculating()); + MemReqPtr req = new MemReq(dest, cpuXC->getProxy(), 64); req->asid = asid; // translate to physical address - Fault fault = xc->translateDataWriteReq(req); + Fault fault = cpuXC->translateDataWriteReq(req); - if (fault == No_Fault) { + if (fault == NoFault) { Addr dest_addr = req->paddr; // Need to read straight from memory since we have more than 8 bytes. - req->paddr = xc->copySrcPhysAddr; + req->paddr = cpuXC->copySrcPhysAddr; mem->read(req, data); req->paddr = dest_addr; mem->write(req, data); @@ -292,7 +293,7 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes) #if 0 panic("unaligned access. Cycle = %n", curTick); #endif - return No_Fault; + return NoFault; } MemReqPtr req = new MemReq(addr, thread, nbytes); @@ -303,7 +304,7 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes) case Write: fault = spec_mem->write(req, (uint8_t *)p); - if (fault != No_Fault) + if (fault != NoFault) break; specMemWrite = true; @@ -325,7 +326,7 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes) break; default: - fault = Machine_Check_Fault; + fault = genMachineCheckFault(); break; } diff --git a/cpu/base_dyn_inst.hh b/cpu/base_dyn_inst.hh index d29257a52..3a7852f79 100644 --- a/cpu/base_dyn_inst.hh +++ b/cpu/base_dyn_inst.hh @@ -51,7 +51,6 @@ */ // Forward declaration. -template <class ISA> class StaticInstPtr; template <class Impl> @@ -61,25 +60,20 @@ class BaseDynInst : public FastAlloc, public RefCounted // Typedef for the CPU. typedef typename Impl::FullCPU FullCPU; - //Typedef to get the ISA. - typedef typename Impl::ISA ISA; - /// Binary machine instruction type. - typedef typename ISA::MachInst MachInst; - /// Memory address type. - typedef typename ISA::Addr Addr; + typedef TheISA::MachInst MachInst; /// Logical register index type. - typedef typename ISA::RegIndex RegIndex; + typedef TheISA::RegIndex RegIndex; /// Integer register index type. - typedef typename ISA::IntReg IntReg; + typedef TheISA::IntReg IntReg; enum { - MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs }; /** The static inst used by this dyn inst. */ - StaticInstPtr<ISA> staticInst; + StaticInstPtr staticInst; //////////////////////////////////////////// // @@ -151,7 +145,7 @@ class BaseDynInst : public FastAlloc, public RefCounted FullCPU *cpu; /** Pointer to the exec context. Will not exist in the final version. */ - ExecContext *xc; + CPUExecContext *cpuXC; /** The kind of fault this instruction has generated. */ Fault fault; @@ -214,7 +208,7 @@ class BaseDynInst : public FastAlloc, public RefCounted FullCPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ - BaseDynInst(StaticInstPtr<ISA> &_staticInst); + BaseDynInst(StaticInstPtr &_staticInst); /** BaseDynInst destructor. */ ~BaseDynInst(); @@ -412,7 +406,7 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns the exec context. * @todo: Remove this once the ExecContext is no longer used. */ - ExecContext *xcBase() { return xc; } + ExecContext *xcBase() { return cpuXC->getProxy(); } private: /** Instruction effective address. @@ -450,7 +444,7 @@ template<class T> inline Fault BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags) { - MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags); + MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), sizeof(T), flags); req->asid = asid; fault = cpu->translateDataReadReq(req); @@ -472,7 +466,7 @@ BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags) req->paddr = req->vaddr; #endif - if (fault == No_Fault) { + if (fault == NoFault) { fault = cpu->read(req, data, lqIdx); } else { // Return a fixed value to keep simulation deterministic even @@ -498,7 +492,7 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res) traceData->setData(data); } - MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags); + MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), sizeof(T), flags); req->asid = asid; @@ -520,14 +514,14 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res) req->paddr = req->vaddr; #endif - if (fault == No_Fault) { + if (fault == NoFault) { fault = cpu->write(req, data, sqIdx); } if (res) { // always return some result to keep misspeculated paths // (which will ignore faults) deterministic - *res = (fault == No_Fault) ? req->result : 0; + *res = (fault == NoFault) ? req->result : 0; } return fault; diff --git a/cpu/exec_context.cc b/cpu/cpu_exec_context.cc index 0b91992cf..6ef42762d 100644 --- a/cpu/exec_context.cc +++ b/cpu/cpu_exec_context.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2001-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,18 +29,20 @@ #include <string> #include "cpu/base.hh" +#include "cpu/cpu_exec_context.hh" #include "cpu/exec_context.hh" #if FULL_SYSTEM #include "base/callback.hh" #include "base/cprintf.hh" #include "base/output.hh" +#include "base/trace.hh" #include "cpu/profile.hh" #include "kern/kernel_stats.hh" #include "sim/serialize.hh" #include "sim/sim_exit.hh" #include "sim/system.hh" -#include "targetarch/stacktrace.hh" +#include "arch/stacktrace.hh" #else #include "sim/process.hh" #include "mem/translating_port.hh" @@ -50,23 +52,23 @@ using namespace std; // constructor #if FULL_SYSTEM -ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, +CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, AlphaITB *_itb, AlphaDTB *_dtb, Memory *_mem) : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), - cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys), - memctrl(_sys->memctrl), physmem(_sys->physmem), - kernelBinning(system->kernelBinning), bin(kernelBinning->bin), - fnbin(kernelBinning->fnbin), profile(NULL), - func_exe_inst(0), storeCondFailures(0) + cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb), + dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem), + profile(NULL), quiesceEvent(this), func_exe_inst(0), storeCondFailures(0) { - kernelStats = new Kernel::Statistics(this); + proxy = new ProxyExecContext<CPUExecContext>(this); + memset(®s, 0, sizeof(RegFile)); if (cpu->params->profile) { profile = new FunctionProfile(system->kernelSymtab); Callback *cb = - new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this); + new MakeCallback<CPUExecContext, + &CPUExecContext::dumpFuncProfile>(this); registerExitCallback(cb); } @@ -77,59 +79,99 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, profilePC = 3; } #else -ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, +CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, Port *mem_port) : _status(ExecContext::Unallocated), - cpu(_cpu), thread_num(_thread_num), cpu_id(-1), - process(_process), - asid(_asid), + cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), + lastSuspend(0), process(_process), asid(_asid), func_exe_inst(0), storeCondFailures(0) { port = new TranslatingPort(mem_port, process->pTable); memset(®s, 0, sizeof(RegFile)); + proxy = new ProxyExecContext<CPUExecContext>(this); } -#endif -ExecContext::~ExecContext() +CPUExecContext::CPUExecContext(RegFile *regFile) + : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1), + func_exe_inst(0), storeCondFailures(0) { -#if FULL_SYSTEM - delete kernelStats; + regs = *regFile; + proxy = new ProxyExecContext<CPUExecContext>(this); +} + #endif + +CPUExecContext::~CPUExecContext() +{ + delete proxy; } #if FULL_SYSTEM void -ExecContext::dumpFuncProfile() +CPUExecContext::dumpFuncProfile() { std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); - profile->dump(this, *os); + profile->dump(proxy, *os); +} + +CPUExecContext::EndQuiesceEvent::EndQuiesceEvent(CPUExecContext *_cpuXC) + : Event(&mainEventQueue), cpuXC(_cpuXC) +{ +} + +void +CPUExecContext::EndQuiesceEvent::process() +{ + cpuXC->activate(); } + +const char* +CPUExecContext::EndQuiesceEvent::description() +{ + return "End Quiesce Event."; +} + +void +CPUExecContext::profileClear() +{ + if (profile) + profile->clear(); +} + +void +CPUExecContext::profileSample() +{ + if (profile) + profile->sample(profileNode, profilePC); +} + #endif void -ExecContext::takeOverFrom(ExecContext *oldContext) +CPUExecContext::takeOverFrom(ExecContext *oldContext) { // some things should already be set up -// assert(mem == oldContext->mem); #if FULL_SYSTEM - assert(system == oldContext->system); + assert(system == oldContext->getSystemPtr()); #else - assert(process == oldContext->process); + assert(process == oldContext->getProcessPtr()); #endif // copy over functional state - _status = oldContext->_status; - regs = oldContext->regs; - cpu_id = oldContext->cpu_id; - func_exe_inst = oldContext->func_exe_inst; + _status = oldContext->status(); + copyArchRegs(oldContext); + cpu_id = oldContext->readCpuId(); +#if !FULL_SYSTEM + func_exe_inst = oldContext->readFuncExeInst(); +#endif storeCondFailures = 0; - oldContext->_status = ExecContext::Unallocated; + oldContext->setStatus(ExecContext::Unallocated); } void -ExecContext::serialize(ostream &os) +CPUExecContext::serialize(ostream &os) { SERIALIZE_ENUM(_status); regs.serialize(os); @@ -138,13 +180,17 @@ ExecContext::serialize(ostream &os) SERIALIZE_SCALAR(inst); #if FULL_SYSTEM - kernelStats->serialize(os); + Tick quiesceEndTick = 0; + if (quiesceEvent.scheduled()) + quiesceEndTick = quiesceEvent.when(); + SERIALIZE_SCALAR(quiesceEndTick); + #endif } void -ExecContext::unserialize(Checkpoint *cp, const std::string §ion) +CPUExecContext::unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_ENUM(_status); regs.unserialize(cp, section); @@ -153,77 +199,92 @@ ExecContext::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(inst); #if FULL_SYSTEM - kernelStats->unserialize(cp, section); + Tick quiesceEndTick; + UNSERIALIZE_SCALAR(quiesceEndTick); + if (quiesceEndTick) + quiesceEvent.schedule(quiesceEndTick); #endif } void -ExecContext::activate(int delay) +CPUExecContext::activate(int delay) { - if (status() == Active) + if (status() == ExecContext::Active) return; - _status = Active; + lastActivate = curTick; + + _status = ExecContext::Active; cpu->activateContext(thread_num, delay); } void -ExecContext::suspend() +CPUExecContext::suspend() { - if (status() == Suspended) + if (status() == ExecContext::Suspended) return; + lastActivate = curTick; + lastSuspend = curTick; +/* #if FULL_SYSTEM // Don't change the status from active if there are pending interrupts if (cpu->check_interrupts()) { - assert(status() == Active); + assert(status() == ExecContext::Active); return; } #endif - - _status = Suspended; +*/ + _status = ExecContext::Suspended; cpu->suspendContext(thread_num); } void -ExecContext::deallocate() +CPUExecContext::deallocate() { - if (status() == Unallocated) + if (status() == ExecContext::Unallocated) return; - _status = Unallocated; + _status = ExecContext::Unallocated; cpu->deallocateContext(thread_num); } void -ExecContext::halt() +CPUExecContext::halt() { - if (status() == Halted) + if (status() == ExecContext::Halted) return; - _status = Halted; + _status = ExecContext::Halted; cpu->haltContext(thread_num); } void -ExecContext::regStats(const string &name) +CPUExecContext::regStats(const string &name) { -#if FULL_SYSTEM - kernelStats->regStats(name + ".kern"); -#endif } void -ExecContext::trap(Fault fault) +CPUExecContext::copyArchRegs(ExecContext *xc) { - //TheISA::trap(fault); //One possible way to do it... + // First loop through the integer registers. + for (int i = 0; i < AlphaISA::NumIntRegs; ++i) { + setIntReg(i, xc->readIntReg(i)); + } - /** @todo: Going to hack it for now. Do a true fixup later. */ -#if FULL_SYSTEM - ev5_trap(fault); -#else - fatal("fault (%d) detected @ PC 0x%08p", fault, readPC()); -#endif + // Then loop through the floating point registers. + for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { + setFloatRegDouble(i, xc->readFloatRegDouble(i)); + setFloatRegInt(i, xc->readFloatRegInt(i)); + } + + // Copy misc. registers + regs.miscRegs.copyMiscRegs(xc); + + // Lastly copy PC/NPC + setPC(xc->readPC()); + setNextPC(xc->readNextPC()); } + diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh new file mode 100644 index 000000000..e17cfbb94 --- /dev/null +++ b/cpu/cpu_exec_context.hh @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2001-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. + */ + +#ifndef __CPU_CPU_EXEC_CONTEXT_HH__ +#define __CPU_CPU_EXEC_CONTEXT_HH__ + +#include "arch/isa_traits.hh" +#include "config/full_system.hh" +#include "cpu/exec_context.hh" +#include "mem/physical.hh" +#include "mem/request.hh" +#include "sim/byteswap.hh" +#include "sim/eventq.hh" +#include "sim/host.hh" +#include "sim/serialize.hh" + +class BaseCPU; + +#if FULL_SYSTEM + +#include "sim/system.hh" +#include "arch/tlb.hh" + +class FunctionProfile; +class ProfileNode; +class MemoryController; + +#else // !FULL_SYSTEM + +#include "sim/process.hh" +class TranslatingPort; + +#endif // FULL_SYSTEM + +// +// The CPUExecContext object represents a functional context for +// instruction execution. It incorporates everything required for +// architecture-level functional simulation of a single thread. +// + +class CPUExecContext +{ + protected: + typedef TheISA::RegFile RegFile; + typedef TheISA::MachInst MachInst; + typedef TheISA::MiscRegFile MiscRegFile; + typedef TheISA::MiscReg MiscReg; + public: + typedef ExecContext::Status Status; + + private: + Status _status; + + public: + Status status() const { return _status; } + + void setStatus(Status newStatus) { _status = newStatus; } + + /// Set the status to Active. Optional delay indicates number of + /// cycles to wait before beginning execution. + void activate(int delay = 1); + + /// Set the status to Suspended. + void suspend(); + + /// Set the status to Unallocated. + void deallocate(); + + /// Set the status to Halted. + void halt(); + + protected: + RegFile regs; // correct-path register context + + public: + // pointer to CPU associated with this context + BaseCPU *cpu; + + ProxyExecContext<CPUExecContext> *proxy; + + // Current instruction + MachInst inst; + + // Index of hardware thread context on the CPU that this represents. + int thread_num; + + // ID of this context w.r.t. the System or Process object to which + // it belongs. For full-system mode, this is the system CPU ID. + int cpu_id; + + Tick lastActivate; + Tick lastSuspend; + + System *system; + + /// Port that syscalls can use to access memory (provides translation step). + TranslatingPort *port; +// Memory *mem; + +#if FULL_SYSTEM + AlphaITB *itb; + AlphaDTB *dtb; + + // the following two fields are redundant, since we can always + // look them up through the system pointer, but we'll leave them + // here for now for convenience + MemoryController *memctrl; +// PhysicalMemory *physmem; + + FunctionProfile *profile; + ProfileNode *profileNode; + Addr profilePC; + void dumpFuncProfile(); + + /** Event for timing out quiesce instruction */ + struct EndQuiesceEvent : public Event + { + /** A pointer to the execution context that is quiesced */ + CPUExecContext *cpuXC; + + EndQuiesceEvent(CPUExecContext *_cpuXC); + + /** Event process to occur at interrupt*/ + virtual void process(); + + /** Event description */ + virtual const char *description(); + }; + EndQuiesceEvent quiesceEvent; + + Event *getQuiesceEvent() { return &quiesceEvent; } + + Tick readLastActivate() { return lastActivate; } + + Tick readLastSuspend() { return lastSuspend; } + + void profileClear(); + + void profileSample(); + +#else + Process *process; + + // Address space ID. Note that this is used for TIMING cache + // simulation only; all functional memory accesses should use + // one of the FunctionalMemory pointers above. + short asid; + +#endif + + /** + * Temporary storage to pass the source address from copy_load to + * copy_store. + * @todo Remove this temporary when we have a better way to do it. + */ + Addr copySrcAddr; + /** + * Temp storage for the physical source address of a copy. + * @todo Remove this temporary when we have a better way to do it. + */ + Addr copySrcPhysAddr; + + + /* + * number of executed instructions, for matching with syscall trace + * points in EIO files. + */ + Counter func_exe_inst; + + // + // Count failed store conditionals so we can warn of apparent + // application deadlock situations. + unsigned storeCondFailures; + + // constructor: initialize context from given process structure +#if FULL_SYSTEM + CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system, + AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem); +#else + CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, Port *mem_port); + // Constructor to use XC to pass reg file around. Not used for anything + // else. + CPUExecContext(RegFile *regFile); +#endif + virtual ~CPUExecContext(); + + virtual void takeOverFrom(ExecContext *oldContext); + + void regStats(const std::string &name); + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + BaseCPU *getCpuPtr() { return cpu; } + + ExecContext *getProxy() { return proxy; } + + int getThreadNum() { return thread_num; } + +#if FULL_SYSTEM + System *getSystemPtr() { return system; } + + PhysicalMemory *getPhysMemPtr() { return physmem; } + + AlphaITB *getITBPtr() { return itb; } + + AlphaDTB *getDTBPtr() { return dtb; } + + bool validInstAddr(Addr addr) { return true; } + bool validDataAddr(Addr addr) { return true; } + int getInstAsid() { return regs.instAsid(); } + int getDataAsid() { return regs.dataAsid(); } + + Fault translateInstReq(CpuRequestPtr &req) + { + return itb->translate(req); + } + + Fault translateDataReadReq(CpuRequestPtr &req) + { + return dtb->translate(req, false); + } + + Fault translateDataWriteReq(CpuRequestPtr &req) + { + return dtb->translate(req, true); + } + +#else + Process *getProcessPtr() { return process; } + + bool validInstAddr(Addr addr) + { return process->validInstAddr(addr); } + + bool validDataAddr(Addr addr) + { return process->validDataAddr(addr); } + + int getInstAsid() { return asid; } + int getDataAsid() { return asid; } + + Fault translateInstReq(CpuRequestPtr &req) + { + return process->pTable->translate(req); + } + + Fault translateDataReadReq(CpuRequestPtr &req) + { + return process->pTable->translate(req); + } + + Fault translateDataWriteReq(CpuRequestPtr &req) + { + return process->pTable->translate(req); + } + +#endif + +/* + template <class T> + Fault read(CpuRequestPtr &req, T &data) + { +#if FULL_SYSTEM && defined(TARGET_ALPHA) + if (req->flags & LOCKED) { + req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr); + req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true); + } +#endif + + Fault error; + error = mem->prot_read(req->paddr, data, req->size); + data = LittleEndianGuest::gtoh(data); + return error; + } + + template <class T> + Fault write(CpuRequestPtr &req, T &data) + { +#if FULL_SYSTEM && defined(TARGET_ALPHA) + ExecContext *xc; + + // If this is a store conditional, act appropriately + if (req->flags & LOCKED) { + xc = req->xc; + + if (req->flags & UNCACHEABLE) { + // Don't update result register (see stq_c in isa_desc) + req->result = 2; + xc->setStCondFailures(0);//Needed? [RGD] + } else { + bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag); + Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag); + req->result = lock_flag; + if (!lock_flag || + ((lock_addr & ~0xf) != (req->paddr & ~0xf))) { + xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); + xc->setStCondFailures(xc->readStCondFailures() + 1); + if (((xc->readStCondFailures()) % 100000) == 0) { + std::cerr << "Warning: " + << xc->readStCondFailures() + << " consecutive store conditional failures " + << "on cpu " << req->xc->readCpuId() + << std::endl; + } + return NoFault; + } + else xc->setStCondFailures(0); + } + } + + // Need to clear any locked flags on other proccessors for + // this address. Only do this for succsful Store Conditionals + // and all other stores (WH64?). Unsuccessful Store + // Conditionals would have returned above, and wouldn't fall + // through. + for (int i = 0; i < system->execContexts.size(); i++){ + xc = system->execContexts[i]; + if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) == + (req->paddr & ~0xf)) { + xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); + } + } + +#endif + return mem->prot_write(req->paddr, (T)htog(data), req->size); + } +*/ + virtual bool misspeculating(); + + + MachInst getInst() { return inst; } + + void setInst(MachInst new_inst) + { + inst = new_inst; + } + + Fault instRead(CpuRequestPtr &req) + { + panic("instRead not implemented"); + // return funcPhysMem->read(req, inst); + return No_Fault; + } + + void setCpuId(int id) { cpu_id = id; } + + int readCpuId() { return cpu_id; } + + FunctionalMemory *getMemPtr() { return mem; } + + void copyArchRegs(ExecContext *xc); + + // + // New accessors for new decoder. + // + uint64_t readIntReg(int reg_idx) + { + return regs.intRegFile[reg_idx]; + } + + float readFloatRegSingle(int reg_idx) + { + return (float)regs.floatRegFile.d[reg_idx]; + } + + double readFloatRegDouble(int reg_idx) + { + return regs.floatRegFile.d[reg_idx]; + } + + uint64_t readFloatRegInt(int reg_idx) + { + return regs.floatRegFile.q[reg_idx]; + } + + void setIntReg(int reg_idx, uint64_t val) + { + regs.intRegFile[reg_idx] = val; + } + + void setFloatRegSingle(int reg_idx, float val) + { + regs.floatRegFile.d[reg_idx] = (double)val; + } + + void setFloatRegDouble(int reg_idx, double val) + { + regs.floatRegFile.d[reg_idx] = val; + } + + void setFloatRegInt(int reg_idx, uint64_t val) + { + regs.floatRegFile.q[reg_idx] = val; + } + + uint64_t readPC() + { + return regs.pc; + } + + void setPC(uint64_t val) + { + regs.pc = val; + } + + uint64_t readNextPC() + { + return regs.npc; + } + + void setNextPC(uint64_t val) + { + regs.npc = val; + } + + uint64_t readNextNPC() + { + return regs.nnpc; + } + + void setNextNPC(uint64_t val) + { + regs.nnpc = val; + } + + + MiscReg readMiscReg(int misc_reg) + { + return regs.miscRegs.readReg(misc_reg); + } + + MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) + { + return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy); + } + + Fault setMiscReg(int misc_reg, const MiscReg &val) + { + return regs.miscRegs.setReg(misc_reg, val); + } + + Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) + { + return regs.miscRegs.setRegWithEffect(misc_reg, val, proxy); + } + + unsigned readStCondFailures() { return storeCondFailures; } + + void setStCondFailures(unsigned sc_failures) + { storeCondFailures = sc_failures; } + + void clearArchRegs() { memset(®s, 0, sizeof(regs)); } + +#if FULL_SYSTEM + int readIntrFlag() { return regs.intrflag; } + void setIntrFlag(int val) { regs.intrflag = val; } + Fault hwrei(); + bool inPalMode() { return AlphaISA::PcPAL(regs.pc); } + bool simPalCheck(int palFunc); +#endif + +#if !FULL_SYSTEM + TheISA::IntReg getSyscallArg(int i) + { + return regs.intRegFile[TheISA::ArgumentReg0 + i]; + } + + // used to shift args for indirect syscall + void setSyscallArg(int i, TheISA::IntReg val) + { + regs.intRegFile[TheISA::ArgumentReg0 + i] = val; + } + + void setSyscallReturn(SyscallReturn return_value) + { + TheISA::setSyscallReturn(return_value, ®s); + } + + void syscall() + { + process->syscall(proxy); + } + + Counter readFuncExeInst() { return func_exe_inst; } + + void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; } +#endif +}; + + +// for non-speculative execution context, spec_mode is always false +inline bool +CPUExecContext::misspeculating() +{ + return false; +} + +#endif // __CPU_CPU_EXEC_CONTEXT_HH__ diff --git a/cpu/cpu_models.py b/cpu/cpu_models.py new file mode 100644 index 000000000..675204e5b --- /dev/null +++ b/cpu/cpu_models.py @@ -0,0 +1,71 @@ +# Copyright (c) 2003-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. + +################ +# CpuModel class +# +# The CpuModel class encapsulates everything the ISA parser needs to +# know about a particular CPU model. + +class CpuModel: + # Dict of available CPU model objects. Accessible as CpuModel.dict. + dict = {} + + # Constructor. Automatically adds models to CpuModel.dict. + def __init__(self, name, filename, includes, strings): + self.name = name + self.filename = filename # filename for output exec code + self.includes = includes # include files needed in exec file + # The 'strings' dict holds all the per-CPU symbols we can + # substitute into templates etc. + self.strings = strings + # Add self to dict + CpuModel.dict[name] = self + + +# +# Define CPU models. +# +# Parameters are: +# - name of model +# - filename for generated ISA execution file +# - includes needed for generated ISA execution file +# - substitution strings for ISA description templates +# + +CpuModel('SimpleCPU', 'simple_cpu_exec.cc', + '#include "cpu/simple/cpu.hh"', + { 'CPU_exec_context': 'SimpleCPU' }) +CpuModel('FastCPU', 'fast_cpu_exec.cc', + '#include "cpu/fast/cpu.hh"', + { 'CPU_exec_context': 'FastCPU' }) +CpuModel('FullCPU', 'full_cpu_exec.cc', + '#include "encumbered/cpu/full/dyn_inst.hh"', + { 'CPU_exec_context': 'DynInst' }) +CpuModel('AlphaFullCPU', 'alpha_o3_exec.cc', + '#include "cpu/o3/alpha_dyn_inst.hh"', + { 'CPU_exec_context': 'AlphaDynInst<AlphaSimpleImpl>' }) + diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index f55b45de1..2b6c41bd7 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,39 +30,32 @@ #define __CPU_EXEC_CONTEXT_HH__ #include "config/full_system.hh" -#include "mem/physical.hh" -#include "mem/request.hh" +#include "mem/mem_req.hh" +#include "sim/faults.hh" #include "sim/host.hh" #include "sim/serialize.hh" -#include "targetarch/byte_swap.hh" +#include "sim/byteswap.hh" +// forward declaration: see functional_memory.hh +// @todo: Figure out a more architecture independent way to obtain the ITB and +// DTB pointers. +class AlphaDTB; +class AlphaITB; class BaseCPU; - -#if FULL_SYSTEM - -#include "sim/system.hh" -#include "targetarch/alpha_memory.hh" - -class FunctionProfile; -class ProfileNode; -class MemoryController; -namespace Kernel { class Binning; class Statistics; } - -#else // !FULL_SYSTEM - -#include "sim/process.hh" -class TranslatingPort; - -#endif // FULL_SYSTEM - -// -// The ExecContext object represents a functional context for -// instruction execution. It incorporates everything required for -// architecture-level functional simulation of a single thread. -// +class Event; +class FunctionalMemory; +class PhysicalMemory; +class Process; +class System; class ExecContext { + protected: + typedef TheISA::RegFile RegFile; + typedef TheISA::MachInst MachInst; + typedef TheISA::IntReg IntReg; + typedef TheISA::MiscRegFile MiscRegFile; + typedef TheISA::MiscReg MiscReg; public: enum Status { @@ -86,384 +79,339 @@ class ExecContext Halted }; - private: - Status _status; + virtual ~ExecContext() { }; - public: - Status status() const { return _status; } + virtual BaseCPU *getCpuPtr() = 0; + + virtual void setCpuId(int id) = 0; + + virtual int readCpuId() = 0; + + virtual FunctionalMemory *getMemPtr() = 0; + +#if FULL_SYSTEM + virtual System *getSystemPtr() = 0; + + virtual PhysicalMemory *getPhysMemPtr() = 0; + + virtual AlphaITB *getITBPtr() = 0; + + virtual AlphaDTB * getDTBPtr() = 0; +#else + virtual Process *getProcessPtr() = 0; +#endif + + virtual Status status() const = 0; + + virtual void setStatus(Status new_status) = 0; /// Set the status to Active. Optional delay indicates number of /// cycles to wait before beginning execution. - void activate(int delay = 1); + virtual void activate(int delay = 1) = 0; /// Set the status to Suspended. - void suspend(); + virtual void suspend() = 0; /// Set the status to Unallocated. - void deallocate(); + virtual void deallocate() = 0; /// Set the status to Halted. - void halt(); + virtual void halt() = 0; - public: - RegFile regs; // correct-path register context +#if FULL_SYSTEM + virtual void dumpFuncProfile() = 0; +#endif - // pointer to CPU associated with this context - BaseCPU *cpu; + virtual void takeOverFrom(ExecContext *old_context) = 0; - // Current instruction - MachInst inst; + virtual void regStats(const std::string &name) = 0; - // Index of hardware thread context on the CPU that this represents. - int thread_num; + virtual void serialize(std::ostream &os) = 0; + virtual void unserialize(Checkpoint *cp, const std::string §ion) = 0; - // ID of this context w.r.t. the System or Process object to which - // it belongs. For full-system mode, this is the system CPU ID. - int cpu_id; +#if FULL_SYSTEM + virtual Event *getQuiesceEvent() = 0; - System *system; + // Not necessarily the best location for these... + // Having an extra function just to read these is obnoxious + virtual Tick readLastActivate() = 0; + virtual Tick readLastSuspend() = 0; - /// Port that syscalls can use to access memory (provides translation step). - TranslatingPort *port; -// Memory *mem; + virtual void profileClear() = 0; + virtual void profileSample() = 0; +#endif -#if FULL_SYSTEM - AlphaITB *itb; - AlphaDTB *dtb; + virtual int getThreadNum() = 0; - // the following two fields are redundant, since we can always - // look them up through the system pointer, but we'll leave them - // here for now for convenience - MemoryController *memctrl; -// PhysicalMemory *physmem; + virtual bool validInstAddr(Addr addr) = 0; + virtual bool validDataAddr(Addr addr) = 0; + virtual int getInstAsid() = 0; + virtual int getDataAsid() = 0; - Kernel::Binning *kernelBinning; - Kernel::Statistics *kernelStats; - bool bin; - bool fnbin; + virtual Fault translateInstReq(MemReqPtr &req) = 0; - FunctionProfile *profile; - ProfileNode *profileNode; - Addr profilePC; - void dumpFuncProfile(); + virtual Fault translateDataReadReq(MemReqPtr &req) = 0; -#else - Process *process; + virtual Fault translateDataWriteReq(MemReqPtr &req) = 0; - // Address space ID. Note that this is used for TIMING cache - // simulation only; all functional memory accesses should use - // one of the FunctionalMemory pointers above. - short asid; + // Also somewhat obnoxious. Really only used for the TLB fault. + // However, may be quite useful in SPARC. + virtual TheISA::MachInst getInst() = 0; -#endif + virtual void copyArchRegs(ExecContext *xc) = 0; - /** - * Temporary storage to pass the source address from copy_load to - * copy_store. - * @todo Remove this temporary when we have a better way to do it. - */ - Addr copySrcAddr; - /** - * Temp storage for the physical source address of a copy. - * @todo Remove this temporary when we have a better way to do it. - */ - Addr copySrcPhysAddr; - - - /* - * number of executed instructions, for matching with syscall trace - * points in EIO files. - */ - Counter func_exe_inst; + virtual void clearArchRegs() = 0; // - // Count failed store conditionals so we can warn of apparent - // application deadlock situations. - unsigned storeCondFailures; + // New accessors for new decoder. + // + virtual uint64_t readIntReg(int reg_idx) = 0; + + virtual float readFloatRegSingle(int reg_idx) = 0; + + virtual double readFloatRegDouble(int reg_idx) = 0; + + virtual uint64_t readFloatRegInt(int reg_idx) = 0; + + virtual void setIntReg(int reg_idx, uint64_t val) = 0; + + virtual void setFloatRegSingle(int reg_idx, float val) = 0; + + virtual void setFloatRegDouble(int reg_idx, double val) = 0; + + virtual void setFloatRegInt(int reg_idx, uint64_t val) = 0; + + virtual uint64_t readPC() = 0; + + virtual void setPC(uint64_t val) = 0; + + virtual uint64_t readNextPC() = 0; + + virtual void setNextPC(uint64_t val) = 0; + + virtual MiscReg readMiscReg(int misc_reg) = 0; + + virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) = 0; + + virtual Fault setMiscReg(int misc_reg, const MiscReg &val) = 0; + + virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) = 0; + + // Also not necessarily the best location for these two. Hopefully will go + // away once we decide upon where st cond failures goes. + virtual unsigned readStCondFailures() = 0; + + virtual void setStCondFailures(unsigned sc_failures) = 0; - // constructor: initialize context from given process structure #if FULL_SYSTEM - ExecContext(BaseCPU *_cpu, int _thread_num, System *_system, - AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem); -#else - ExecContext(BaseCPU *_cpu, int _thread_num, - Process *_process, int _asid, Port *mem_port); + virtual int readIntrFlag() = 0; + virtual void setIntrFlag(int val) = 0; + virtual Fault hwrei() = 0; + virtual bool inPalMode() = 0; + virtual bool simPalCheck(int palFunc) = 0; #endif - virtual ~ExecContext(); - virtual void takeOverFrom(ExecContext *oldContext); + // Only really makes sense for old CPU model. Still could be useful though. + virtual bool misspeculating() = 0; - void regStats(const std::string &name); +#if !FULL_SYSTEM + virtual IntReg getSyscallArg(int i) = 0; - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + // used to shift args for indirect syscall + virtual void setSyscallArg(int i, IntReg val) = 0; -#if FULL_SYSTEM - bool validInstAddr(Addr addr) { return true; } - bool validDataAddr(Addr addr) { return true; } - int getInstAsid() { return regs.instAsid(); } - int getDataAsid() { return regs.dataAsid(); } + virtual void setSyscallReturn(SyscallReturn return_value) = 0; - Fault translateInstReq(CpuRequestPtr &req) - { - return itb->translate(req); - } + virtual void syscall() = 0; - Fault translateDataReadReq(CpuRequestPtr &req) - { - return dtb->translate(req, false); - } + // Same with st cond failures. + virtual Counter readFuncExeInst() = 0; - Fault translateDataWriteReq(CpuRequestPtr &req) - { - return dtb->translate(req, true); - } + virtual void setFuncExeInst(Counter new_val) = 0; +#endif +}; -#else - bool validInstAddr(Addr addr) - { return process->validInstAddr(addr); } +template <class XC> +class ProxyExecContext : public ExecContext +{ + public: + ProxyExecContext(XC *actual_xc) + { actualXC = actual_xc; } - bool validDataAddr(Addr addr) - { return process->validDataAddr(addr); } + private: + XC *actualXC; - int getInstAsid() { return asid; } - int getDataAsid() { return asid; } + public: - Fault translateInstReq(CpuRequestPtr &req) - { - return process->pTable->translate(req); - } + BaseCPU *getCpuPtr() { return actualXC->getCpuPtr(); } - Fault translateDataReadReq(CpuRequestPtr &req) - { - return process->pTable->translate(req); - } + void setCpuId(int id) { actualXC->setCpuId(id); } - Fault translateDataWriteReq(CpuRequestPtr &req) - { - return process->pTable->translate(req); - } + int readCpuId() { return actualXC->readCpuId(); } + FunctionalMemory *getMemPtr() { return actualXC->getMemPtr(); } + +#if FULL_SYSTEM + System *getSystemPtr() { return actualXC->getSystemPtr(); } + + PhysicalMemory *getPhysMemPtr() { return actualXC->getPhysMemPtr(); } + + AlphaITB *getITBPtr() { return actualXC->getITBPtr(); } + + AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); } +#else + Process *getProcessPtr() { return actualXC->getProcessPtr(); } #endif -/* - template <class T> - Fault read(CpuRequestPtr &req, T &data) - { -#if FULL_SYSTEM && defined(TARGET_ALPHA) - if (req->flags & LOCKED) { - MiscRegFile *cregs = &req->xc->regs.miscRegs; - cregs->lock_addr = req->paddr; - cregs->lock_flag = true; - } + Status status() const { return actualXC->status(); } + + void setStatus(Status new_status) { actualXC->setStatus(new_status); } + + /// Set the status to Active. Optional delay indicates number of + /// cycles to wait before beginning execution. + void activate(int delay = 1) { actualXC->activate(delay); } + + /// Set the status to Suspended. + void suspend() { actualXC->suspend(); } + + /// Set the status to Unallocated. + void deallocate() { actualXC->deallocate(); } + + /// Set the status to Halted. + void halt() { actualXC->halt(); } + +#if FULL_SYSTEM + void dumpFuncProfile() { actualXC->dumpFuncProfile(); } #endif - Fault error; - error = mem->prot_read(req->paddr, data, req->size); - data = gtoh(data); - return error; - } + void takeOverFrom(ExecContext *oldContext) + { actualXC->takeOverFrom(oldContext); } - template <class T> - Fault write(CpuRequestPtr &req, T &data) - { -#if FULL_SYSTEM && defined(TARGET_ALPHA) - - MiscRegFile *cregs; - - // If this is a store conditional, act appropriately - if (req->flags & LOCKED) { - cregs = &req->xc->regs.miscRegs; - - if (req->flags & UNCACHEABLE) { - // Don't update result register (see stq_c in isa_desc) - req->result = 2; - req->xc->storeCondFailures = 0;//Needed? [RGD] - } else { - req->result = cregs->lock_flag; - if (!cregs->lock_flag || - ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) { - cregs->lock_flag = false; - if (((++req->xc->storeCondFailures) % 100000) == 0) { - std::cerr << "Warning: " - << req->xc->storeCondFailures - << " consecutive store conditional failures " - << "on cpu " << req->xc->cpu_id - << std::endl; - } - return No_Fault; - } - else req->xc->storeCondFailures = 0; - } - } - - // Need to clear any locked flags on other proccessors for - // this address. Only do this for succsful Store Conditionals - // and all other stores (WH64?). Unsuccessful Store - // Conditionals would have returned above, and wouldn't fall - // through. - for (int i = 0; i < system->execContexts.size(); i++){ - cregs = &system->execContexts[i]->regs.miscRegs; - if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) { - cregs->lock_flag = false; - } - } + void regStats(const std::string &name) { actualXC->regStats(name); } + + void serialize(std::ostream &os) { actualXC->serialize(os); } + void unserialize(Checkpoint *cp, const std::string §ion) + { actualXC->unserialize(cp, section); } + +#if FULL_SYSTEM + Event *getQuiesceEvent() { return actualXC->getQuiesceEvent(); } + + Tick readLastActivate() { return actualXC->readLastActivate(); } + Tick readLastSuspend() { return actualXC->readLastSuspend(); } + void profileClear() { return actualXC->profileClear(); } + void profileSample() { return actualXC->profileSample(); } #endif - return mem->prot_write(req->paddr, (T)htog(data), req->size); - } -*/ - virtual bool misspeculating(); + int getThreadNum() { return actualXC->getThreadNum(); } - MachInst getInst() { return inst; } + bool validInstAddr(Addr addr) { return actualXC->validInstAddr(addr); } + bool validDataAddr(Addr addr) { return actualXC->validDataAddr(addr); } + int getInstAsid() { return actualXC->getInstAsid(); } + int getDataAsid() { return actualXC->getDataAsid(); } - void setInst(MachInst new_inst) - { - inst = new_inst; - } + Fault translateInstReq(MemReqPtr &req) + { return actualXC->translateInstReq(req); } - Fault instRead(CpuRequestPtr &req) - { - panic("instRead not implemented"); - // return funcPhysMem->read(req, inst); - return No_Fault; - } + Fault translateDataReadReq(MemReqPtr &req) + { return actualXC->translateDataReadReq(req); } + + Fault translateDataWriteReq(MemReqPtr &req) + { return actualXC->translateDataWriteReq(req); } + + // @todo: Do I need this? + MachInst getInst() { return actualXC->getInst(); } + + // @todo: Do I need this? + void copyArchRegs(ExecContext *xc) { actualXC->copyArchRegs(xc); } + + void clearArchRegs() { actualXC->clearArchRegs(); } // // New accessors for new decoder. // uint64_t readIntReg(int reg_idx) - { - return regs.intRegFile[reg_idx]; - } + { return actualXC->readIntReg(reg_idx); } float readFloatRegSingle(int reg_idx) - { - return (float)regs.floatRegFile.d[reg_idx]; - } + { return actualXC->readFloatRegSingle(reg_idx); } double readFloatRegDouble(int reg_idx) - { - return regs.floatRegFile.d[reg_idx]; - } + { return actualXC->readFloatRegDouble(reg_idx); } uint64_t readFloatRegInt(int reg_idx) - { - return regs.floatRegFile.q[reg_idx]; - } + { return actualXC->readFloatRegInt(reg_idx); } void setIntReg(int reg_idx, uint64_t val) - { - regs.intRegFile[reg_idx] = val; - } + { actualXC->setIntReg(reg_idx, val); } void setFloatRegSingle(int reg_idx, float val) - { - regs.floatRegFile.d[reg_idx] = (double)val; - } + { actualXC->setFloatRegSingle(reg_idx, val); } void setFloatRegDouble(int reg_idx, double val) - { - regs.floatRegFile.d[reg_idx] = val; - } + { actualXC->setFloatRegDouble(reg_idx, val); } void setFloatRegInt(int reg_idx, uint64_t val) - { - regs.floatRegFile.q[reg_idx] = val; - } + { actualXC->setFloatRegInt(reg_idx, val); } - uint64_t readPC() - { - return regs.pc; - } + uint64_t readPC() { return actualXC->readPC(); } - void setNextPC(uint64_t val) - { - regs.npc = val; - } + void setPC(uint64_t val) { actualXC->setPC(val); } - uint64_t readUniq() - { - return regs.miscRegs.uniq; - } + uint64_t readNextPC() { return actualXC->readNextPC(); } - void setUniq(uint64_t val) - { - regs.miscRegs.uniq = val; - } + void setNextPC(uint64_t val) { actualXC->setNextPC(val); } - uint64_t readFpcr() - { - return regs.miscRegs.fpcr; - } + MiscReg readMiscReg(int misc_reg) + { return actualXC->readMiscReg(misc_reg); } - void setFpcr(uint64_t val) - { - regs.miscRegs.fpcr = val; - } + MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) + { return actualXC->readMiscRegWithEffect(misc_reg, fault); } + + Fault setMiscReg(int misc_reg, const MiscReg &val) + { return actualXC->setMiscReg(misc_reg, val); } + + Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) + { return actualXC->setMiscRegWithEffect(misc_reg, val); } + + unsigned readStCondFailures() + { return actualXC->readStCondFailures(); } + + void setStCondFailures(unsigned sc_failures) + { actualXC->setStCondFailures(sc_failures); } #if FULL_SYSTEM - uint64_t readIpr(int idx, Fault &fault); - Fault setIpr(int idx, uint64_t val); - int readIntrFlag() { return regs.intrflag; } - void setIntrFlag(int val) { regs.intrflag = val; } - Fault hwrei(); - bool inPalMode() { return AlphaISA::PcPAL(regs.pc); } - void ev5_trap(Fault fault); - bool simPalCheck(int palFunc); -#endif + int readIntrFlag() { return actualXC->readIntrFlag(); } + + void setIntrFlag(int val) { actualXC->setIntrFlag(val); } + + Fault hwrei() { return actualXC->hwrei(); } + + bool inPalMode() { return actualXC->inPalMode(); } - /** Meant to be more generic trap function to be - * called when an instruction faults. - * @param fault The fault generated by executing the instruction. - * @todo How to do this properly so it's dependent upon ISA only? - */ + bool simPalCheck(int palFunc) { return actualXC->simPalCheck(palFunc); } +#endif - void trap(Fault fault); + // @todo: Fix this! + bool misspeculating() { return actualXC->misspeculating(); } #if !FULL_SYSTEM - IntReg getSyscallArg(int i) - { - return regs.intRegFile[ArgumentReg0 + i]; - } + IntReg getSyscallArg(int i) { return actualXC->getSyscallArg(i); } // used to shift args for indirect syscall void setSyscallArg(int i, IntReg val) - { - regs.intRegFile[ArgumentReg0 + i] = val; - } + { actualXC->setSyscallArg(i, val); } void setSyscallReturn(SyscallReturn return_value) - { - // check for error condition. Alpha syscall convention is to - // indicate success/failure in reg a3 (r19) and put the - // return value itself in the standard return value reg (v0). - const int RegA3 = 19; // only place this is used - if (return_value.successful()) { - // no error - regs.intRegFile[RegA3] = 0; - regs.intRegFile[ReturnValueReg] = return_value.value(); - } else { - // got an error, return details - regs.intRegFile[RegA3] = (IntReg) -1; - regs.intRegFile[ReturnValueReg] = -return_value.value(); - } - } - - void syscall() - { - process->syscall(this); - } -#endif -}; + { actualXC->setSyscallReturn(return_value); } + void syscall() { actualXC->syscall(); } -// for non-speculative execution context, spec_mode is always false -inline bool -ExecContext::misspeculating() -{ - return false; -} + Counter readFuncExeInst() { return actualXC->readFuncExeInst(); } -#endif // __CPU_EXEC_CONTEXT_HH__ + void setFuncExeInst(Counter new_val) + { return actualXC->setFuncExeInst(new_val); } +#endif +}; + +#endif diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc index 5c7dc953c..ebb719b2c 100644 --- a/cpu/exetrace.cc +++ b/cpu/exetrace.cc @@ -31,7 +31,6 @@ #include "sim/param.hh" #include "cpu/exetrace.hh" -#include "cpu/exec_context.hh" #include "base/loader/symtab.hh" #include "cpu/base.hh" #include "cpu/static_inst.hh" diff --git a/cpu/exetrace.hh b/cpu/exetrace.hh index 48d8966d8..67d042ec8 100644 --- a/cpu/exetrace.hh +++ b/cpu/exetrace.hh @@ -46,13 +46,14 @@ namespace Trace { class InstRecord : public Record { protected: + typedef TheISA::IntRegFile IntRegFile; // The following fields are initialized by the constructor and // thus guaranteed to be valid. BaseCPU *cpu; // need to make this ref-counted so it doesn't go away before we // dump the record - StaticInstPtr<TheISA> staticInst; + StaticInstPtr staticInst; Addr PC; bool misspeculating; unsigned thread; @@ -92,7 +93,7 @@ class InstRecord : public Record public: InstRecord(Tick _cycle, BaseCPU *_cpu, - const StaticInstPtr<TheISA> &_staticInst, + const StaticInstPtr &_staticInst, Addr _pc, bool spec, int _thread) : Record(_cycle), cpu(_cpu), staticInst(_staticInst), PC(_pc), misspeculating(spec), thread(_thread) @@ -169,7 +170,7 @@ InstRecord::setRegs(const IntRegFile ®s) inline InstRecord * getInstRecord(Tick cycle, ExecContext *xc, BaseCPU *cpu, - const StaticInstPtr<TheISA> staticInst, + const StaticInstPtr staticInst, Addr pc, int thread = 0) { if (DTRACE(InstExec) && diff --git a/cpu/inst_seq.hh b/cpu/inst_seq.hh index 3239d4d24..8de047af7 100644 --- a/cpu/inst_seq.hh +++ b/cpu/inst_seq.hh @@ -32,7 +32,7 @@ // inst sequence type, used to order instructions in the ready list, // if this rolls over the ready list order temporarily will get messed // up, but execution will continue and complete correctly -typedef unsigned long long InstSeqNum; +typedef uint64_t InstSeqNum; // inst tag type, used to tag an operation instance in the IQ typedef unsigned int InstTag; diff --git a/cpu/intr_control.cc b/cpu/intr_control.cc index 5f17c7212..43e7f654c 100644 --- a/cpu/intr_control.cc +++ b/cpu/intr_control.cc @@ -30,6 +30,7 @@ #include <vector> #include "cpu/base.hh" +#include "cpu/exec_context.hh" #include "cpu/intr_control.hh" #include "sim/builder.hh" #include "sim/sim_object.hh" @@ -48,7 +49,7 @@ void IntrControl::post(int int_num, int index) { std::vector<ExecContext *> &xcvec = cpu->system->execContexts; - BaseCPU *temp = xcvec[0]->cpu; + BaseCPU *temp = xcvec[0]->getCpuPtr(); temp->post_interrupt(int_num, index); } @@ -56,7 +57,7 @@ void IntrControl::post(int cpu_id, int int_num, int index) { std::vector<ExecContext *> &xcvec = cpu->system->execContexts; - BaseCPU *temp = xcvec[cpu_id]->cpu; + BaseCPU *temp = xcvec[cpu_id]->getCpuPtr(); temp->post_interrupt(int_num, index); } @@ -64,7 +65,7 @@ void IntrControl::clear(int int_num, int index) { std::vector<ExecContext *> &xcvec = cpu->system->execContexts; - BaseCPU *temp = xcvec[0]->cpu; + BaseCPU *temp = xcvec[0]->getCpuPtr(); temp->clear_interrupt(int_num, index); } @@ -72,7 +73,7 @@ void IntrControl::clear(int cpu_id, int int_num, int index) { std::vector<ExecContext *> &xcvec = cpu->system->execContexts; - BaseCPU *temp = xcvec[cpu_id]->cpu; + BaseCPU *temp = xcvec[cpu_id]->getCpuPtr(); temp->clear_interrupt(int_num, index); } diff --git a/cpu/intr_control.hh b/cpu/intr_control.hh index 2a57a8dfc..5ec4e14cb 100644 --- a/cpu/intr_control.hh +++ b/cpu/intr_control.hh @@ -34,7 +34,6 @@ #include "cpu/base.hh" #include "sim/sim_object.hh" #include "sim/system.hh" -#include "cpu/exec_context.hh" class IntrControl : public SimObject diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc index 27f790fac..94b66b70b 100644 --- a/cpu/memtest/memtest.cc +++ b/cpu/memtest/memtest.cc @@ -36,7 +36,7 @@ #include "base/misc.hh" #include "base/statistics.hh" -#include "cpu/exec_context.hh" +#include "cpu/cpu_exec_context.hh" #include "cpu/memtest/memtest.hh" #include "mem/cache/base_cache.hh" #include "sim/builder.hh" @@ -44,6 +44,7 @@ #include "sim/stats.hh" using namespace std; +using namespace TheISA; int TESTER_ALLOCATOR=0; @@ -78,7 +79,7 @@ MemTest::MemTest(const string &name, vector<string> cmd; cmd.push_back("/bin/ls"); vector<string> null_vec; - xc = new ExecContext(NULL, 0, mainMem, 0); + cpuXC = new CPUExecContext(NULL, 0, mainMem, 0); blockSize = cacheInterface->getBlockSize(); blockAddrMask = blockSize - 1; @@ -268,7 +269,7 @@ MemTest::tick() req->data = new uint8_t[req->size]; req->paddr &= ~(req->size - 1); req->time = curTick; - req->xc = xc; + req->xc = cpuXC->getProxy(); if (cmd < percentReads) { // read diff --git a/cpu/memtest/memtest.hh b/cpu/memtest/memtest.hh index 7abcf017a..cdb40a26a 100644 --- a/cpu/memtest/memtest.hh +++ b/cpu/memtest/memtest.hh @@ -83,7 +83,7 @@ class MemTest : public SimObject MemInterface *cacheInterface; FunctionalMemory *mainMem; FunctionalMemory *checkMem; - ExecContext *xc; + CPUExecContext *cpuXC; unsigned size; // size of testing memory region diff --git a/cpu/o3/2bit_local_pred.hh b/cpu/o3/2bit_local_pred.hh index a97ce455c..97433e542 100644 --- a/cpu/o3/2bit_local_pred.hh +++ b/cpu/o3/2bit_local_pred.hh @@ -30,7 +30,7 @@ #define __CPU_O3_CPU_2BIT_LOCAL_PRED_HH__ // For Addr type. -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "cpu/o3/sat_counter.hh" class DefaultBP diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh index cba57d189..0352e9972 100644 --- a/cpu/o3/alpha_cpu.hh +++ b/cpu/o3/alpha_cpu.hh @@ -33,12 +33,19 @@ #define __CPU_O3_CPU_ALPHA_FULL_CPU_HH__ #include "cpu/o3/cpu.hh" +#include "arch/isa_traits.hh" +#include "sim/byteswap.hh" template <class Impl> class AlphaFullCPU : public FullO3CPU<Impl> { + protected: + typedef TheISA::IntReg IntReg; + typedef TheISA::MiscReg MiscReg; + typedef TheISA::RegFile RegFile; + typedef TheISA::MiscRegFile MiscRegFile; + public: - typedef typename Impl::ISA AlphaISA; typedef typename Impl::Params Params; public: @@ -85,7 +92,7 @@ class AlphaFullCPU : public FullO3CPU<Impl> // put the asid in the upper 16 bits of the paddr req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; - return No_Fault; + return NoFault; } Fault translateInstReq(MemReqPtr &req) @@ -108,33 +115,24 @@ class AlphaFullCPU : public FullO3CPU<Impl> // Later on may want to remove this misc stuff from the regfile and // have it handled at this level. Might prove to be an issue when // trying to rename source/destination registers... - uint64_t readUniq() - { - return this->regFile.readUniq(); - } - - void setUniq(uint64_t val) + MiscReg readMiscReg(int misc_reg) { - this->regFile.setUniq(val); + // Dummy function for now. + // @todo: Fix this once reg file gets fixed. + return 0; } - uint64_t readFpcr() + Fault setMiscReg(int misc_reg, const MiscReg &val) { - return this->regFile.readFpcr(); - } - - void setFpcr(uint64_t val) - { - this->regFile.setFpcr(val); + // Dummy function for now. + // @todo: Fix this once reg file gets fixed. + return NoFault; } // Most of the full system code and syscall emulation is not yet // implemented. These functions do show what the final interface will // look like. #if FULL_SYSTEM - uint64_t *getIpr(); - uint64_t readIpr(int idx, Fault &fault); - Fault setIpr(int idx, uint64_t val); int readIntrFlag(); void setIntrFlag(int val); Fault hwrei(); @@ -156,13 +154,13 @@ class AlphaFullCPU : public FullO3CPU<Impl> // set the register. IntReg getSyscallArg(int i) { - return this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i]; + return this->cpuXC->readIntReg(AlphaISA::ArgumentReg0 + i); } // used to shift args for indirect syscall void setSyscallArg(int i, IntReg val) { - this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i] = val; + this->cpuXC->setIntReg(AlphaISA::ArgumentReg0 + i, val); } void setSyscallReturn(int64_t return_value) @@ -173,12 +171,12 @@ class AlphaFullCPU : public FullO3CPU<Impl> const int RegA3 = 19; // only place this is used if (return_value >= 0) { // no error - this->xc->regs.intRegFile[RegA3] = 0; - this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = return_value; + this->cpuXC->setIntReg(RegA3, 0); + this->cpuXC->setIntReg(AlphaISA::ReturnValueReg, return_value); } else { // got an error, return details - this->xc->regs.intRegFile[RegA3] = (IntReg) -1; - this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = -return_value; + this->cpuXC->setIntReg(RegA3, (IntReg) -1); + this->cpuXC->setIntReg(AlphaISA::ReturnValueReg, -return_value); } } @@ -212,9 +210,8 @@ class AlphaFullCPU : public FullO3CPU<Impl> { #if FULL_SYSTEM && defined(TARGET_ALPHA) if (req->flags & LOCKED) { - MiscRegFile *cregs = &req->xc->regs.miscRegs; - cregs->lock_addr = req->paddr; - cregs->lock_flag = true; + req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr); + req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true); } #endif @@ -234,32 +231,34 @@ class AlphaFullCPU : public FullO3CPU<Impl> Fault write(MemReqPtr &req, T &data) { #if FULL_SYSTEM && defined(TARGET_ALPHA) - - MiscRegFile *cregs; + ExecContext *xc; // If this is a store conditional, act appropriately if (req->flags & LOCKED) { - cregs = &this->xc->regs.miscRegs; + xc = req->xc; if (req->flags & UNCACHEABLE) { // Don't update result register (see stq_c in isa_desc) req->result = 2; - req->xc->storeCondFailures = 0;//Needed? [RGD] + xc->setStCondFailures(0);//Needed? [RGD] } else { - req->result = cregs->lock_flag; - if (!cregs->lock_flag || - ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) { - cregs->lock_flag = false; - if (((++req->xc->storeCondFailures) % 100000) == 0) { + bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag); + Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag); + req->result = lock_flag; + if (!lock_flag || + ((lock_addr & ~0xf) != (req->paddr & ~0xf))) { + xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); + xc->setStCondFailures(xc->readStCondFailures() + 1); + if (((xc->readStCondFailures()) % 100000) == 0) { std::cerr << "Warning: " - << req->xc->storeCondFailures + << xc->readStCondFailures() << " consecutive store conditional failures " - << "on cpu " << this->cpu_id + << "on cpu " << req->xc->readCpuId() << std::endl; } - return No_Fault; + return NoFault; } - else req->xc->storeCondFailures = 0; + else xc->setStCondFailures(0); } } @@ -269,9 +268,10 @@ class AlphaFullCPU : public FullO3CPU<Impl> // Conditionals would have returned above, and wouldn't fall // through. for (int i = 0; i < this->system->execContexts.size(); i++){ - cregs = &this->system->execContexts[i]->regs.miscRegs; - if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) { - cregs->lock_flag = false; + xc = this->system->execContexts[i]; + if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) == + (req->paddr & ~0xf)) { + xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); } } diff --git a/cpu/o3/alpha_cpu_builder.cc b/cpu/o3/alpha_cpu_builder.cc index 3547fb1b5..6025b8ef2 100644 --- a/cpu/o3/alpha_cpu_builder.cc +++ b/cpu/o3/alpha_cpu_builder.cc @@ -30,7 +30,6 @@ #include "base/loader/symtab.hh" #include "base/misc.hh" #include "cpu/base.hh" -#include "cpu/exec_context.hh" #include "cpu/exetrace.hh" #include "cpu/o3/alpha_cpu.hh" #include "cpu/o3/alpha_impl.hh" @@ -50,8 +49,8 @@ #include "mem/functional/memory_control.hh" #include "mem/functional/physical.hh" #include "sim/system.hh" -#include "targetarch/alpha_memory.hh" -#include "targetarch/vtophys.hh" +#include "arch/tlb.hh" +#include "arch/vtophys.hh" #else // !FULL_SYSTEM #include "mem/functional/functional.hh" #endif // FULL_SYSTEM diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh index 2a764740b..9f1fa24f6 100644 --- a/cpu/o3/alpha_cpu_impl.hh +++ b/cpu/o3/alpha_cpu_impl.hh @@ -26,6 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "arch/alpha/faults.hh" #include "base/cprintf.hh" #include "base/statistics.hh" #include "base/timebuf.hh" @@ -42,9 +43,6 @@ #if FULL_SYSTEM #include "arch/alpha/osfpal.hh" #include "arch/alpha/isa_traits.hh" -//#include "arch/alpha/ev5.hh" - -//using namespace EV5; #endif template <class Impl> @@ -168,7 +166,7 @@ AlphaFullCPU<Impl>::copyToXC() for (int i = 0; i < AlphaISA::NumIntRegs; ++i) { renamed_reg = this->renameMap.lookup(i); - this->xc->regs.intRegFile[i] = this->regFile.readIntReg(renamed_reg); + this->cpuXC->setIntReg(i, this->regFile.readIntReg(renamed_reg)); DPRINTF(FullCPU, "FullCPU: Copying register %i, has data %lli.\n", renamed_reg, this->regFile.intRegFile[renamed_reg]); } @@ -177,21 +175,27 @@ AlphaFullCPU<Impl>::copyToXC() for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag); - this->xc->regs.floatRegFile.d[i] = - this->regFile.readFloatRegDouble(renamed_reg); - this->xc->regs.floatRegFile.q[i] = - this->regFile.readFloatRegInt(renamed_reg); + this->cpuXC->setFloatRegDouble(i, + this->regFile.readFloatRegDouble(renamed_reg)); + this->cpuXC->setFloatRegInt(i, + this->regFile.readFloatRegInt(renamed_reg)); } - this->xc->regs.miscRegs.fpcr = this->regFile.miscRegs.fpcr; - this->xc->regs.miscRegs.uniq = this->regFile.miscRegs.uniq; - this->xc->regs.miscRegs.lock_flag = this->regFile.miscRegs.lock_flag; - this->xc->regs.miscRegs.lock_addr = this->regFile.miscRegs.lock_addr; + this->cpuXC->setMiscReg(AlphaISA::Fpcr_DepTag, + this->regFile.readMiscReg(AlphaISA::Fpcr_DepTag)); + this->cpuXC->setMiscReg(AlphaISA::Uniq_DepTag, + this->regFile.readMiscReg(AlphaISA::Uniq_DepTag)); + this->cpuXC->setMiscReg(AlphaISA::Lock_Flag_DepTag, + this->regFile.readMiscReg(AlphaISA::Lock_Flag_DepTag)); + this->cpuXC->setMiscReg(AlphaISA::Lock_Addr_DepTag, + this->regFile.readMiscReg(AlphaISA::Lock_Addr_DepTag)); - this->xc->regs.pc = this->rob.readHeadPC(); - this->xc->regs.npc = this->xc->regs.pc+4; + this->cpuXC->setPC(this->rob.readHeadPC()); + this->cpuXC->setNextPC(this->cpuXC->readPC()+4); - this->xc->func_exe_inst = this->funcExeInst; +#if !FULL_SYSTEM + this->cpuXC->setFuncExeInst(this->funcExeInst); +#endif } // This function will probably mess things up unless the ROB is empty and @@ -210,9 +214,9 @@ AlphaFullCPU<Impl>::copyFromXC() DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, " "now has data %lli.\n", renamed_reg, this->regFile.intRegFile[renamed_reg], - this->xc->regs.intRegFile[i]); + this->cpuXC->readIntReg(i)); - this->regFile.setIntReg(renamed_reg, this->xc->regs.intRegFile[i]); + this->regFile.setIntReg(renamed_reg, this->cpuXC->readIntReg(i)); } // Then loop through the floating point registers. @@ -220,48 +224,32 @@ AlphaFullCPU<Impl>::copyFromXC() { renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag); this->regFile.setFloatRegDouble(renamed_reg, - this->xc->regs.floatRegFile.d[i]); + this->cpuXC->readFloatRegDouble(i)); this->regFile.setFloatRegInt(renamed_reg, - this->xc->regs.floatRegFile.q[i]); + this->cpuXC->readFloatRegInt(i)); } // Then loop through the misc registers. - this->regFile.miscRegs.fpcr = this->xc->regs.miscRegs.fpcr; - this->regFile.miscRegs.uniq = this->xc->regs.miscRegs.uniq; - this->regFile.miscRegs.lock_flag = this->xc->regs.miscRegs.lock_flag; - this->regFile.miscRegs.lock_addr = this->xc->regs.miscRegs.lock_addr; + this->regFile.setMiscReg(AlphaISA::Fpcr_DepTag, + this->cpuXC->readMiscReg(AlphaISA::Fpcr_DepTag)); + this->regFile.setMiscReg(AlphaISA::Uniq_DepTag, + this->cpuXC->readMiscReg(AlphaISA::Uniq_DepTag)); + this->regFile.setMiscReg(AlphaISA::Lock_Flag_DepTag, + this->cpuXC->readMiscReg(AlphaISA::Lock_Flag_DepTag)); + this->regFile.setMiscReg(AlphaISA::Lock_Addr_DepTag, + this->cpuXC->readMiscReg(AlphaISA::Lock_Addr_DepTag)); // Then finally set the PC and the next PC. -// regFile.pc = xc->regs.pc; -// regFile.npc = xc->regs.npc; - - this->funcExeInst = this->xc->func_exe_inst; +// regFile.pc = cpuXC->regs.pc; +// regFile.npc = cpuXC->regs.npc; +#if !FULL_SYSTEM + this->funcExeInst = this->cpuXC->readFuncExeInst(); +#endif } #if FULL_SYSTEM template <class Impl> -uint64_t * -AlphaFullCPU<Impl>::getIpr() -{ - return this->regFile.getIpr(); -} - -template <class Impl> -uint64_t -AlphaFullCPU<Impl>::readIpr(int idx, Fault &fault) -{ - return this->regFile.readIpr(idx, fault); -} - -template <class Impl> -Fault -AlphaFullCPU<Impl>::setIpr(int idx, uint64_t val) -{ - return this->regFile.setIpr(idx, val); -} - -template <class Impl> int AlphaFullCPU<Impl>::readIntrFlag() { @@ -280,22 +268,20 @@ template <class Impl> Fault AlphaFullCPU<Impl>::hwrei() { - uint64_t *ipr = getIpr(); - if (!inPalMode()) - return Unimplemented_Opcode_Fault; + return new AlphaISA::UnimplementedOpcodeFault; - setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]); + this->setNextPC(this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR)); // kernelStats.hwrei(); - if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0) + if ((this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR) & 1) == 0) // AlphaISA::swap_palshadow(®s, false); this->checkInterrupts = true; // FIXME: XXX check for interrupts? XXX - return No_Fault; + return NoFault; } template <class Impl> @@ -328,36 +314,38 @@ template <class Impl> void AlphaFullCPU<Impl>::trap(Fault fault) { - // Keep in mind that a trap may be initiated by fetch if there's a TLB +/* // Keep in mind that a trap may be initiated by fetch if there's a TLB // miss uint64_t PC = this->commit.readCommitPC(); - DPRINTF(Fault, "Fault %s\n", FaultName(fault)); - this->recordEvent(csprintf("Fault %s", FaultName(fault))); + DPRINTF(Fault, "Fault %s\n", fault->name()); + this->recordEvent(csprintf("Fault %s", fault->name())); -// kernelStats.fault(fault); + //kernelStats.fault(fault); - if (fault == Arithmetic_Fault) + if (fault->isA<ArithmeticFault>()) panic("Arithmetic traps are unimplemented!"); - typename AlphaISA::InternalProcReg *ipr = getIpr(); - // exception restart address - Get the commit PC - if (fault != Interrupt_Fault || !inPalMode(PC)) - ipr[AlphaISA::IPR_EXC_ADDR] = PC; + if (!fault->isA<InterruptFault>() || !inPalMode(PC)) + this->regFile.miscRegs.setReg(AlphaISA::IPR_EXC_ADDR, PC); - if (fault == Pal_Fault || fault == Arithmetic_Fault /* || - fault == Interrupt_Fault && !PC_PAL(regs.pc) */) { + if (fault->isA<PalFault>() || fault->isA<ArithmeticFault>()) + // || fault == InterruptFault && !PC_PAL(regs.pc) + { // traps... skip faulting instruction - ipr[AlphaISA::IPR_EXC_ADDR] += 4; + AlphaISA::MiscReg ipr_exc_addr = + this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR); + this->regFile.miscRegs.setReg(AlphaISA::IPR_EXC_ADDR, + ipr_exc_addr + 4); } if (!inPalMode(PC)) swapPALShadow(true); - this->regFile.setPC( ipr[AlphaISA::IPR_PAL_BASE] + - AlphaISA::fault_addr[fault] ); - this->regFile.setNextPC(PC + sizeof(MachInst)); + this->regFile.setPC(this->regFile.miscRegs.readReg(AlphaISA::IPR_PAL_BASE) + + (dynamic_cast<AlphaFault *>(fault.get()))->vect()); + this->regFile.setNextPC(PC + sizeof(MachInst));*/ } template <class Impl> diff --git a/cpu/o3/alpha_dyn_inst.hh b/cpu/o3/alpha_dyn_inst.hh index bb90bf21a..e7f7d3a57 100644 --- a/cpu/o3/alpha_dyn_inst.hh +++ b/cpu/o3/alpha_dyn_inst.hh @@ -48,21 +48,18 @@ class AlphaDynInst : public BaseDynInst<Impl> /** Typedef for the CPU. */ typedef typename Impl::FullCPU FullCPU; - /** Typedef to get the ISA. */ - typedef typename Impl::ISA ISA; - /** Binary machine instruction type. */ - typedef typename ISA::MachInst MachInst; - /** Memory address type. */ - typedef typename ISA::Addr Addr; + typedef TheISA::MachInst MachInst; /** Logical register index type. */ - typedef typename ISA::RegIndex RegIndex; + typedef TheISA::RegIndex RegIndex; /** Integer register index type. */ - typedef typename ISA::IntReg IntReg; + typedef TheISA::IntReg IntReg; + /** Misc register index type. */ + typedef TheISA::MiscReg MiscReg; enum { - MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs }; public: @@ -71,7 +68,7 @@ class AlphaDynInst : public BaseDynInst<Impl> FullCPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ - AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst); + AlphaDynInst(StaticInstPtr &_staticInst); /** Executes the instruction.*/ Fault execute() @@ -80,15 +77,35 @@ class AlphaDynInst : public BaseDynInst<Impl> } public: - uint64_t readUniq(); - void setUniq(uint64_t val); + MiscReg readMiscReg(int misc_reg) + { + // Dummy function for now. + // @todo: Fix this once reg file gets fixed. + return 0; + } + + MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) + { + // Dummy function for now. + // @todo: Fix this once reg file gets fixed. + return 0; + } - uint64_t readFpcr(); - void setFpcr(uint64_t val); + Fault setMiscReg(int misc_reg, const MiscReg &val) + { + // Dummy function for now. + // @todo: Fix this once reg file gets fixed. + return NoFault; + } + + Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) + { + // Dummy function for now. + // @todo: Fix this once reg file gets fixed. + return NoFault; + } #if FULL_SYSTEM - uint64_t readIpr(int idx, Fault &fault); - Fault setIpr(int idx, uint64_t val); Fault hwrei(); int readIntrFlag(); void setIntrFlag(int val); @@ -130,22 +147,22 @@ class AlphaDynInst : public BaseDynInst<Impl> // storage (which is pretty hard to imagine they would have reason // to do). - uint64_t readIntReg(const StaticInst<ISA> *si, int idx) + uint64_t readIntReg(const StaticInst *si, int idx) { return this->cpu->readIntReg(_srcRegIdx[idx]); } - float readFloatRegSingle(const StaticInst<ISA> *si, int idx) + float readFloatRegSingle(const StaticInst *si, int idx) { return this->cpu->readFloatRegSingle(_srcRegIdx[idx]); } - double readFloatRegDouble(const StaticInst<ISA> *si, int idx) + double readFloatRegDouble(const StaticInst *si, int idx) { return this->cpu->readFloatRegDouble(_srcRegIdx[idx]); } - uint64_t readFloatRegInt(const StaticInst<ISA> *si, int idx) + uint64_t readFloatRegInt(const StaticInst *si, int idx) { return this->cpu->readFloatRegInt(_srcRegIdx[idx]); } @@ -153,25 +170,25 @@ class AlphaDynInst : public BaseDynInst<Impl> /** @todo: Make results into arrays so they can handle multiple dest * registers. */ - void setIntReg(const StaticInst<ISA> *si, int idx, uint64_t val) + void setIntReg(const StaticInst *si, int idx, uint64_t val) { this->cpu->setIntReg(_destRegIdx[idx], val); this->instResult.integer = val; } - void setFloatRegSingle(const StaticInst<ISA> *si, int idx, float val) + void setFloatRegSingle(const StaticInst *si, int idx, float val) { this->cpu->setFloatRegSingle(_destRegIdx[idx], val); this->instResult.fp = val; } - void setFloatRegDouble(const StaticInst<ISA> *si, int idx, double val) + void setFloatRegDouble(const StaticInst *si, int idx, double val) { this->cpu->setFloatRegDouble(_destRegIdx[idx], val); this->instResult.dbl = val; } - void setFloatRegInt(const StaticInst<ISA> *si, int idx, uint64_t val) + void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) { this->cpu->setFloatRegInt(_destRegIdx[idx], val); this->instResult.integer = val; diff --git a/cpu/o3/alpha_dyn_inst_impl.hh b/cpu/o3/alpha_dyn_inst_impl.hh index d1ebb812d..96b7d3430 100644 --- a/cpu/o3/alpha_dyn_inst_impl.hh +++ b/cpu/o3/alpha_dyn_inst_impl.hh @@ -50,7 +50,7 @@ AlphaDynInst<Impl>::AlphaDynInst(MachInst inst, Addr PC, Addr Pred_PC, } template <class Impl> -AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst) +AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr &_staticInst) : BaseDynInst<Impl>(_staticInst) { // Make sure to have the renamed register entries set to the same @@ -67,50 +67,8 @@ AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst) } } -template <class Impl> -uint64_t -AlphaDynInst<Impl>::readUniq() -{ - return this->cpu->readUniq(); -} - -template <class Impl> -void -AlphaDynInst<Impl>::setUniq(uint64_t val) -{ - this->cpu->setUniq(val); -} - -template <class Impl> -uint64_t -AlphaDynInst<Impl>::readFpcr() -{ - return this->cpu->readFpcr(); -} - -template <class Impl> -void -AlphaDynInst<Impl>::setFpcr(uint64_t val) -{ - this->cpu->setFpcr(val); -} - #if FULL_SYSTEM template <class Impl> -uint64_t -AlphaDynInst<Impl>::readIpr(int idx, Fault &fault) -{ - return this->cpu->readIpr(idx, fault); -} - -template <class Impl> -Fault -AlphaDynInst<Impl>::setIpr(int idx, uint64_t val) -{ - return this->cpu->setIpr(idx, val); -} - -template <class Impl> Fault AlphaDynInst<Impl>::hwrei() { diff --git a/cpu/o3/alpha_impl.hh b/cpu/o3/alpha_impl.hh index 6c1156041..5e39fcb37 100644 --- a/cpu/o3/alpha_impl.hh +++ b/cpu/o3/alpha_impl.hh @@ -51,11 +51,8 @@ class AlphaFullCPU; */ struct AlphaSimpleImpl { - /** The ISA to be used. */ - typedef AlphaISA ISA; - /** The type of MachInst. */ - typedef ISA::MachInst MachInst; + typedef TheISA::MachInst MachInst; /** The CPU policy to be used (ie fetch, decode, etc.). */ typedef SimpleCPUPolicy<AlphaSimpleImpl> CPUPol; diff --git a/cpu/o3/bpred_unit.hh b/cpu/o3/bpred_unit.hh index 0a77b83dc..2725684f7 100644 --- a/cpu/o3/bpred_unit.hh +++ b/cpu/o3/bpred_unit.hh @@ -30,7 +30,7 @@ #define __BPRED_UNIT_HH__ // For Addr type. -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "base/statistics.hh" #include "cpu/inst_seq.hh" diff --git a/cpu/o3/bpred_unit_impl.hh b/cpu/o3/bpred_unit_impl.hh index 9cb2e0490..8d16a0cdf 100644 --- a/cpu/o3/bpred_unit_impl.hh +++ b/cpu/o3/bpred_unit_impl.hh @@ -98,6 +98,8 @@ TwobitBPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC) // Save off record of branch stuff so the RAS can be fixed // up once it's done. + using TheISA::MachInst; + bool pred_taken = false; Addr target; diff --git a/cpu/o3/btb.cc b/cpu/o3/btb.cc index 7671e61e2..2d39c3856 100644 --- a/cpu/o3/btb.cc +++ b/cpu/o3/btb.cc @@ -30,6 +30,8 @@ #include "base/trace.hh" #include "cpu/o3/btb.hh" +using namespace TheISA; + DefaultBTB::DefaultBTB(unsigned _numEntries, unsigned _tagBits, unsigned _instShiftAmt) diff --git a/cpu/o3/btb.hh b/cpu/o3/btb.hh index a4ddfecb4..77bdc32ea 100644 --- a/cpu/o3/btb.hh +++ b/cpu/o3/btb.hh @@ -30,7 +30,7 @@ #define __CPU_O3_CPU_BTB_HH__ // For Addr type. -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" class DefaultBTB { diff --git a/cpu/o3/comm.hh b/cpu/o3/comm.hh index e4de1d304..c74c77ddf 100644 --- a/cpu/o3/comm.hh +++ b/cpu/o3/comm.hh @@ -31,7 +31,7 @@ #include <vector> -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "cpu/inst_seq.hh" #include "sim/host.hh" diff --git a/cpu/o3/commit.hh b/cpu/o3/commit.hh index 6ddc8d6b9..580c1a316 100644 --- a/cpu/o3/commit.hh +++ b/cpu/o3/commit.hh @@ -52,7 +52,6 @@ class SimpleCommit { public: // Typedefs from the Impl. - typedef typename Impl::ISA ISA; typedef typename Impl::FullCPU FullCPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::Params Params; diff --git a/cpu/o3/commit_impl.hh b/cpu/o3/commit_impl.hh index dc0986772..e289bc0c0 100644 --- a/cpu/o3/commit_impl.hh +++ b/cpu/o3/commit_impl.hh @@ -395,7 +395,7 @@ SimpleCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) // Check if the instruction caused a fault. If so, trap. Fault inst_fault = head_inst->getFault(); - if (inst_fault != No_Fault && inst_fault != Fake_Mem_Fault) { + if (inst_fault != NoFault) { if (!head_inst->isNop()) { #if FULL_SYSTEM cpu->trap(inst_fault); diff --git a/cpu/o3/cpu.cc b/cpu/o3/cpu.cc index adc7b6bbc..62d68bb33 100644 --- a/cpu/o3/cpu.cc +++ b/cpu/o3/cpu.cc @@ -35,10 +35,11 @@ #endif #include "sim/root.hh" +#include "cpu/cpu_exec_context.hh" +#include "cpu/exec_context.hh" #include "cpu/o3/alpha_dyn_inst.hh" #include "cpu/o3/alpha_impl.hh" #include "cpu/o3/cpu.hh" -#include "cpu/exec_context.hh" using namespace std; @@ -84,14 +85,14 @@ FullO3CPU<Impl>::FullO3CPU(Params ¶ms) regFile(params.numPhysIntRegs, params.numPhysFloatRegs), - freeList(Impl::ISA::NumIntRegs, params.numPhysIntRegs, - Impl::ISA::NumFloatRegs, params.numPhysFloatRegs), + freeList(TheISA::NumIntRegs, params.numPhysIntRegs, + TheISA::NumFloatRegs, params.numPhysFloatRegs), - renameMap(Impl::ISA::NumIntRegs, params.numPhysIntRegs, - Impl::ISA::NumFloatRegs, params.numPhysFloatRegs, - Impl::ISA::NumMiscRegs, - Impl::ISA::ZeroReg, - Impl::ISA::ZeroReg + Impl::ISA::NumIntRegs), + renameMap(TheISA::NumIntRegs, params.numPhysIntRegs, + TheISA::NumFloatRegs, params.numPhysFloatRegs, + TheISA::NumMiscRegs, + TheISA::ZeroReg, + TheISA::ZeroReg + TheISA::NumIntRegs), rob(params.numROBEntries, params.squashWidth), @@ -103,7 +104,7 @@ FullO3CPU<Impl>::FullO3CPU(Params ¶ms) renameQueue(5, 5), iewQueue(5, 5), - xc(NULL), + cpuXC(NULL), globalSeqNum(1), @@ -134,32 +135,26 @@ FullO3CPU<Impl>::FullO3CPU(Params ¶ms) for (int i = 0; i < this->number_of_threads; ++i) { #if FULL_SYSTEM assert(i == 0); - system->execContexts[i] = - new ExecContext(this, i, system, itb, dtb, mem); + thread[i] = new CPUExecContext(this, 0, system, itb, dtb, mem); + system->execContexts[i] = thread[i]->getProxy(); - // initialize CPU, including PC - TheISA::initCPU(&system->execContexts[i]->regs); execContexts.push_back(system->execContexts[i]); #else if (i < params.workload.size()) { DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, " "process is %#x", i, params.workload[i]->prog_entry, thread[i]); - thread[i] = new ExecContext(this, i, params.workload[i], i); + thread[i] = new CPUExecContext(this, i, params.workload[i], i); } assert(params.workload[i]->getMemory() != NULL); assert(mem != NULL); - execContexts.push_back(thread[i]); + execContexts.push_back(thread[i]->getProxy()); #endif // !FULL_SYSTEM } // Note that this is a hack so that my code which still uses xc-> will // still work. I should remove this eventually -#if FULL_SYSTEM - xc = system->execContexts[0]; -#else - xc = thread[0]; -#endif + cpuXC = thread[0]; // The stages also need their CPU pointer setup. However this must be // done at the upper level CPU because they have pointers to the upper @@ -250,31 +245,32 @@ FullO3CPU<Impl>::init() // that it can start properly. #if FULL_SYSTEM ExecContext *src_xc = system->execContexts[0]; + TheISA::initCPU(src_xc, src_xc->readCpuId()); #else - ExecContext *src_xc = thread[0]; + ExecContext *src_xc = thread[0]->getProxy(); #endif // First loop through the integer registers. - for (int i = 0; i < Impl::ISA::NumIntRegs; ++i) + for (int i = 0; i < TheISA::NumIntRegs; ++i) { - regFile.intRegFile[i] = src_xc->regs.intRegFile[i]; + regFile.intRegFile[i] = src_xc->readIntReg(i); } // Then loop through the floating point registers. - for (int i = 0; i < Impl::ISA::NumFloatRegs; ++i) + for (int i = 0; i < TheISA::NumFloatRegs; ++i) { - regFile.floatRegFile[i].d = src_xc->regs.floatRegFile.d[i]; - regFile.floatRegFile[i].q = src_xc->regs.floatRegFile.q[i]; + regFile.floatRegFile[i].d = src_xc->readFloatRegDouble(i); + regFile.floatRegFile[i].q = src_xc->readFloatRegInt(i); } - +/* // Then loop through the misc registers. regFile.miscRegs.fpcr = src_xc->regs.miscRegs.fpcr; regFile.miscRegs.uniq = src_xc->regs.miscRegs.uniq; regFile.miscRegs.lock_flag = src_xc->regs.miscRegs.lock_flag; regFile.miscRegs.lock_addr = src_xc->regs.miscRegs.lock_addr; - +*/ // Then finally set the PC and the next PC. - regFile.pc = src_xc->regs.pc; - regFile.npc = src_xc->regs.npc; + regFile.pc = src_xc->readPC(); + regFile.npc = src_xc->readNextPC(); } } diff --git a/cpu/o3/cpu.hh b/cpu/o3/cpu.hh index 75dca5056..6577e46e4 100644 --- a/cpu/o3/cpu.hh +++ b/cpu/o3/cpu.hh @@ -44,16 +44,12 @@ #include "base/timebuf.hh" #include "config/full_system.hh" #include "cpu/base.hh" +#include "cpu/cpu_exec_context.hh" #include "cpu/o3/comm.hh" #include "cpu/o3/cpu_policy.hh" -#include "cpu/exec_context.hh" #include "sim/process.hh" -#if FULL_SYSTEM -#include "arch/alpha/ev5.hh" -using namespace EV5; -#endif - +class ExecContext; class FunctionalMemory; class Process; @@ -78,7 +74,6 @@ class FullO3CPU : public BaseFullCPU { public: //Put typedefs from the Impl here. - typedef typename Impl::ISA ISA; typedef typename Impl::CPUPol CPUPolicy; typedef typename Impl::Params Params; typedef typename Impl::DynInstPtr DynInstPtr; @@ -153,11 +148,11 @@ class FullO3CPU : public BaseFullCPU /** Get instruction asid. */ int getInstAsid() - { return ITB_ASN_ASN(regFile.getIpr()[ISA::IPR_ITB_ASN]); } + { return regFile.miscRegs.getInstAsid(); } /** Get data asid. */ int getDataAsid() - { return DTB_ASN_ASN(regFile.getIpr()[ISA::IPR_DTB_ASN]); } + { return regFile.miscRegs.getDataAsid(); } #else bool validInstAddr(Addr addr) { return thread[0]->validInstAddr(addr); } @@ -165,8 +160,8 @@ class FullO3CPU : public BaseFullCPU bool validDataAddr(Addr addr) { return thread[0]->validDataAddr(addr); } - int getInstAsid() { return thread[0]->asid; } - int getDataAsid() { return thread[0]->asid; } + int getInstAsid() { return thread[0]->getInstAsid(); } + int getDataAsid() { return thread[0]->getDataAsid(); } #endif @@ -321,16 +316,17 @@ class FullO3CPU : public BaseFullCPU public: /** The temporary exec context to support older accessors. */ - ExecContext *xc; + CPUExecContext *cpuXC; /** Temporary function to get pointer to exec context. */ ExecContext *xcBase() { -#if FULL_SYSTEM - return system->execContexts[0]; -#else + return thread[0]->getProxy(); + } + + CPUExecContext *cpuXCBase() + { return thread[0]; -#endif } InstSeqNum globalSeqNum; @@ -345,9 +341,8 @@ class FullO3CPU : public BaseFullCPU AlphaDTB *dtb; // SWContext *swCtx; -#else - std::vector<ExecContext *> thread; #endif + std::vector<CPUExecContext *> thread; FunctionalMemory *mem; diff --git a/cpu/o3/decode.hh b/cpu/o3/decode.hh index 42313d83a..5b9a0f822 100644 --- a/cpu/o3/decode.hh +++ b/cpu/o3/decode.hh @@ -39,7 +39,6 @@ class SimpleDecode { private: // Typedefs from the Impl. - typedef typename Impl::ISA ISA; typedef typename Impl::FullCPU FullCPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::Params Params; @@ -50,9 +49,6 @@ class SimpleDecode typedef typename CPUPol::DecodeStruct DecodeStruct; typedef typename CPUPol::TimeStruct TimeStruct; - // Typedefs from the ISA. - typedef typename ISA::Addr Addr; - public: // The only time decode will become blocked is if dispatch becomes // blocked, which means IQ or ROB is probably full. diff --git a/cpu/o3/fetch.hh b/cpu/o3/fetch.hh index 24e445f0b..cc64800d9 100644 --- a/cpu/o3/fetch.hh +++ b/cpu/o3/fetch.hh @@ -49,7 +49,6 @@ class SimpleFetch { public: /** Typedefs from Impl. */ - typedef typename Impl::ISA ISA; typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInst DynInst; typedef typename Impl::DynInstPtr DynInstPtr; @@ -61,7 +60,7 @@ class SimpleFetch typedef typename CPUPol::TimeStruct TimeStruct; /** Typedefs from ISA. */ - typedef typename ISA::MachInst MachInst; + typedef TheISA::MachInst MachInst; public: enum Status { @@ -141,7 +140,7 @@ class SimpleFetch // We fold in the PISA 64- to 32-bit conversion here as well. Addr icacheBlockAlignPC(Addr addr) { - addr = ISA::realPCToFetchPC(addr); + addr = TheISA::realPCToFetchPC(addr); return (addr & ~(cacheBlkMask)); } diff --git a/cpu/o3/fetch_impl.hh b/cpu/o3/fetch_impl.hh index c943fd36a..8029fc732 100644 --- a/cpu/o3/fetch_impl.hh +++ b/cpu/o3/fetch_impl.hh @@ -29,8 +29,8 @@ // Remove this later; used only for debugging. #define OPCODE(X) (X >> 26) & 0x3f - -#include "arch/alpha/byte_swap.hh" +#include "arch/isa_traits.hh" +#include "sim/byteswap.hh" #include "cpu/exetrace.hh" #include "mem/base_mem.hh" #include "mem/mem_interface.hh" @@ -236,7 +236,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC) unsigned flags = 0; #endif // FULL_SYSTEM - Fault fault = No_Fault; + Fault fault = NoFault; // Align the fetch PC so it's at the start of a cache block. fetch_PC = icacheBlockAlignPC(fetch_PC); @@ -258,7 +258,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC) // If translation was successful, attempt to read the first // instruction. - if (fault == No_Fault) { + if (fault == NoFault) { DPRINTF(Fetch, "Fetch: Doing instruction read.\n"); fault = cpu->mem->read(memReq, cacheData); // This read may change when the mem interface changes. @@ -268,7 +268,7 @@ SimpleFetch<Impl>::fetchCacheLine(Addr fetch_PC) // Now do the timing access to see whether or not the instruction // exists within the cache. - if (icacheInterface && fault == No_Fault) { + if (icacheInterface && fault == NoFault) { DPRINTF(Fetch, "Fetch: Doing timing memory access.\n"); memReq->completionEvent = NULL; @@ -468,7 +468,7 @@ SimpleFetch<Impl>::fetch() Addr fetch_PC = cpu->readPC(); // Fault code for memory access. - Fault fault = No_Fault; + Fault fault = NoFault; // If returning from the delay of a cache miss, then update the status // to running, otherwise do the cache access. Possibly move this up @@ -506,7 +506,7 @@ SimpleFetch<Impl>::fetch() unsigned offset = fetch_PC & cacheBlkMask; unsigned fetched; - if (fault == No_Fault) { + if (fault == NoFault) { // If the read of the first instruction was successful, then grab the // instructions from the rest of the cache line and put them into the // queue heading to decode. @@ -582,7 +582,7 @@ SimpleFetch<Impl>::fetch() // Or might want to leave setting the PC to the main CPU, with fetch // only changing the nextPC (will require correct determination of // next PC). - if (fault == No_Fault) { + if (fault == NoFault) { DPRINTF(Fetch, "Fetch: Setting PC to %08p.\n", next_PC); cpu->setPC(next_PC); cpu->setNextPC(next_PC + instSize); diff --git a/cpu/o3/free_list.hh b/cpu/o3/free_list.hh index 733d142fc..0b85dba1e 100644 --- a/cpu/o3/free_list.hh +++ b/cpu/o3/free_list.hh @@ -32,7 +32,7 @@ #include <iostream> #include <queue> -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "base/trace.hh" #include "base/traceflags.hh" #include "cpu/o3/comm.hh" diff --git a/cpu/o3/iew.hh b/cpu/o3/iew.hh index af23c6f45..1e370d4e6 100644 --- a/cpu/o3/iew.hh +++ b/cpu/o3/iew.hh @@ -45,7 +45,6 @@ class SimpleIEW { private: //Typedefs from Impl - typedef typename Impl::ISA ISA; typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::FullCPU FullCPU; diff --git a/cpu/o3/iew_impl.hh b/cpu/o3/iew_impl.hh index b8a2b4dc9..85217dd10 100644 --- a/cpu/o3/iew_impl.hh +++ b/cpu/o3/iew_impl.hh @@ -256,7 +256,7 @@ SimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst) toCommit->branchMispredict = true; // Prediction was incorrect, so send back inverse. toCommit->branchTaken = inst->readNextPC() != - (inst->readPC() + sizeof(MachInst)); + (inst->readPC() + sizeof(TheISA::MachInst)); } template<class Impl> diff --git a/cpu/o3/inst_queue_impl.hh b/cpu/o3/inst_queue_impl.hh index 2221ba456..048dc7c00 100644 --- a/cpu/o3/inst_queue_impl.hh +++ b/cpu/o3/inst_queue_impl.hh @@ -34,6 +34,7 @@ // but probably is more flexible to actually add in a delay parameter than // just running it backwards. +#include <limits> #include <vector> #include "sim/root.hh" @@ -42,7 +43,7 @@ // Either compile error or max int due to sign extension. // Hack to avoid compile warnings. -const InstSeqNum MaxInstSeqNum = 0 - 1; +const InstSeqNum MaxInstSeqNum = std::numeric_limits<InstSeqNum>::max(); template <class Impl> InstructionQueue<Impl>::InstructionQueue(Params ¶ms) diff --git a/cpu/o3/ras.hh b/cpu/o3/ras.hh index bbc4162a6..46d98181e 100644 --- a/cpu/o3/ras.hh +++ b/cpu/o3/ras.hh @@ -30,7 +30,7 @@ #define __CPU_O3_CPU_RAS_HH__ // For Addr type. -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" class ReturnAddrStack { diff --git a/cpu/o3/regfile.hh b/cpu/o3/regfile.hh index 4d47b8f9c..1e6e10f29 100644 --- a/cpu/o3/regfile.hh +++ b/cpu/o3/regfile.hh @@ -31,16 +31,15 @@ // @todo: Destructor -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" +#include "arch/faults.hh" #include "base/trace.hh" #include "config/full_system.hh" #include "cpu/o3/comm.hh" #if FULL_SYSTEM -#include "arch/alpha/ev5.hh" #include "kern/kernel_stats.hh" -using namespace EV5; #endif // This really only depends on the ISA, and not the Impl. It might be nicer @@ -51,6 +50,12 @@ using namespace EV5; template <class Impl> class PhysRegFile { + protected: + typedef TheISA::IntReg IntReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::MiscRegFile MiscRegFile; + typedef TheISA::MiscReg MiscReg; + //Note that most of the definitions of the IntReg, FloatReg, etc. exist //within the Impl/ISA class and not within this PhysRegFile class. @@ -61,7 +66,6 @@ class PhysRegFile //Will make these registers public for now, but they probably should //be private eventually with some accessor functions. public: - typedef typename Impl::ISA ISA; typedef typename Impl::FullCPU FullCPU; PhysRegFile(unsigned _numPhysicalIntRegs, @@ -190,30 +194,21 @@ class PhysRegFile //Consider leaving this stuff and below in some implementation specific //file as opposed to the general register file. Or have a derived class. - uint64_t readUniq() - { - return miscRegs.uniq; - } - - void setUniq(uint64_t val) - { - miscRegs.uniq = val; - } - - uint64_t readFpcr() + MiscReg readMiscReg(int misc_reg) { - return miscRegs.fpcr; + // Dummy function for now. + // @todo: Fix this once proxy XC is used. + return 0; } - void setFpcr(uint64_t val) + Fault setMiscReg(int misc_reg, const MiscReg &val) { - miscRegs.fpcr = val; + // Dummy function for now. + // @todo: Fix this once proxy XC is used. + return NoFault; } #if FULL_SYSTEM - uint64_t readIpr(int idx, Fault &fault); - Fault setIpr(int idx, uint64_t val); - InternalProcReg *getIpr() { return ipr; } int readIntrFlag() { return intrflag; } void setIntrFlag(int val) { intrflag = val; } #endif @@ -239,8 +234,7 @@ class PhysRegFile #if FULL_SYSTEM private: // This is ISA specifc stuff; remove it eventually once ISAImpl is used - IntReg palregs[NumIntRegs]; // PAL shadow registers - InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs +// IntReg palregs[NumIntRegs]; // PAL shadow registers int intrflag; // interrupt flag bool pal_shadow; // using pal_shadow registers #endif @@ -268,368 +262,4 @@ PhysRegFile<Impl>::PhysRegFile(unsigned _numPhysicalIntRegs, memset(floatRegFile, 0, sizeof(*floatRegFile)); } -#if FULL_SYSTEM - -//Problem: This code doesn't make sense at the RegFile level because it -//needs things such as the itb and dtb. Either put it at the CPU level or -//the DynInst level. -template <class Impl> -uint64_t -PhysRegFile<Impl>::readIpr(int idx, Fault &fault) -{ - uint64_t retval = 0; // return value, default 0 - - switch (idx) { - case ISA::IPR_PALtemp0: - case ISA::IPR_PALtemp1: - case ISA::IPR_PALtemp2: - case ISA::IPR_PALtemp3: - case ISA::IPR_PALtemp4: - case ISA::IPR_PALtemp5: - case ISA::IPR_PALtemp6: - case ISA::IPR_PALtemp7: - case ISA::IPR_PALtemp8: - case ISA::IPR_PALtemp9: - case ISA::IPR_PALtemp10: - case ISA::IPR_PALtemp11: - case ISA::IPR_PALtemp12: - case ISA::IPR_PALtemp13: - case ISA::IPR_PALtemp14: - case ISA::IPR_PALtemp15: - case ISA::IPR_PALtemp16: - case ISA::IPR_PALtemp17: - case ISA::IPR_PALtemp18: - case ISA::IPR_PALtemp19: - case ISA::IPR_PALtemp20: - case ISA::IPR_PALtemp21: - case ISA::IPR_PALtemp22: - case ISA::IPR_PALtemp23: - case ISA::IPR_PAL_BASE: - - case ISA::IPR_IVPTBR: - case ISA::IPR_DC_MODE: - case ISA::IPR_MAF_MODE: - case ISA::IPR_ISR: - case ISA::IPR_EXC_ADDR: - case ISA::IPR_IC_PERR_STAT: - case ISA::IPR_DC_PERR_STAT: - case ISA::IPR_MCSR: - case ISA::IPR_ASTRR: - case ISA::IPR_ASTER: - case ISA::IPR_SIRR: - case ISA::IPR_ICSR: - case ISA::IPR_ICM: - case ISA::IPR_DTB_CM: - case ISA::IPR_IPLR: - case ISA::IPR_INTID: - case ISA::IPR_PMCTR: - // no side-effect - retval = ipr[idx]; - break; - - case ISA::IPR_CC: - retval |= ipr[idx] & ULL(0xffffffff00000000); - retval |= curTick & ULL(0x00000000ffffffff); - break; - - case ISA::IPR_VA: - retval = ipr[idx]; - break; - - case ISA::IPR_VA_FORM: - case ISA::IPR_MM_STAT: - case ISA::IPR_IFAULT_VA_FORM: - case ISA::IPR_EXC_MASK: - case ISA::IPR_EXC_SUM: - retval = ipr[idx]; - break; - - case ISA::IPR_DTB_PTE: - { - typename ISA::PTE &pte = cpu->dtb->index(1); - - retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32; - retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8; - retval |= ((u_int64_t)pte.xwe & ULL(0xf)) << 12; - retval |= ((u_int64_t)pte.fonr & ULL(0x1)) << 1; - retval |= ((u_int64_t)pte.fonw & ULL(0x1))<< 2; - retval |= ((u_int64_t)pte.asma & ULL(0x1)) << 4; - retval |= ((u_int64_t)pte.asn & ULL(0x7f)) << 57; - } - break; - - // write only registers - case ISA::IPR_HWINT_CLR: - case ISA::IPR_SL_XMIT: - case ISA::IPR_DC_FLUSH: - case ISA::IPR_IC_FLUSH: - case ISA::IPR_ALT_MODE: - case ISA::IPR_DTB_IA: - case ISA::IPR_DTB_IAP: - case ISA::IPR_ITB_IA: - case ISA::IPR_ITB_IAP: - fault = Unimplemented_Opcode_Fault; - break; - - default: - // invalid IPR - fault = Unimplemented_Opcode_Fault; - break; - } - - return retval; -} - -extern int break_ipl; - -template <class Impl> -Fault -PhysRegFile<Impl>::setIpr(int idx, uint64_t val) -{ - uint64_t old; - - switch (idx) { - case ISA::IPR_PALtemp0: - case ISA::IPR_PALtemp1: - case ISA::IPR_PALtemp2: - case ISA::IPR_PALtemp3: - case ISA::IPR_PALtemp4: - case ISA::IPR_PALtemp5: - case ISA::IPR_PALtemp6: - case ISA::IPR_PALtemp7: - case ISA::IPR_PALtemp8: - case ISA::IPR_PALtemp9: - case ISA::IPR_PALtemp10: - case ISA::IPR_PALtemp11: - case ISA::IPR_PALtemp12: - case ISA::IPR_PALtemp13: - case ISA::IPR_PALtemp14: - case ISA::IPR_PALtemp15: - case ISA::IPR_PALtemp16: - case ISA::IPR_PALtemp17: - case ISA::IPR_PALtemp18: - case ISA::IPR_PALtemp19: - case ISA::IPR_PALtemp20: - case ISA::IPR_PALtemp21: - case ISA::IPR_PALtemp22: - case ISA::IPR_PAL_BASE: - case ISA::IPR_IC_PERR_STAT: - case ISA::IPR_DC_PERR_STAT: - case ISA::IPR_PMCTR: - // write entire quad w/ no side-effect - ipr[idx] = val; - break; - - case ISA::IPR_CC_CTL: - // This IPR resets the cycle counter. We assume this only - // happens once... let's verify that. - assert(ipr[idx] == 0); - ipr[idx] = 1; - break; - - case ISA::IPR_CC: - // This IPR only writes the upper 64 bits. It's ok to write - // all 64 here since we mask out the lower 32 in rpcc (see - // isa_desc). - ipr[idx] = val; - break; - - case ISA::IPR_PALtemp23: - // write entire quad w/ no side-effect - old = ipr[idx]; - ipr[idx] = val; - break; - - case ISA::IPR_DTB_PTE: - // write entire quad w/ no side-effect, tag is forthcoming - ipr[idx] = val; - break; - - case ISA::IPR_EXC_ADDR: - // second least significant bit in PC is always zero - ipr[idx] = val & ~2; - break; - - case ISA::IPR_ASTRR: - case ISA::IPR_ASTER: - // only write least significant four bits - privilege mask - ipr[idx] = val & 0xf; - break; - - case ISA::IPR_IPLR: - // only write least significant five bits - interrupt level - ipr[idx] = val & 0x1f; - break; - - case ISA::IPR_DTB_CM: - - case ISA::IPR_ICM: - // only write two mode bits - processor mode - ipr[idx] = val & 0x18; - break; - - case ISA::IPR_ALT_MODE: - // only write two mode bits - processor mode - ipr[idx] = val & 0x18; - break; - - case ISA::IPR_MCSR: - // more here after optimization... - ipr[idx] = val; - break; - - case ISA::IPR_SIRR: - // only write software interrupt mask - ipr[idx] = val & 0x7fff0; - break; - - case ISA::IPR_ICSR: - ipr[idx] = val & ULL(0xffffff0300); - break; - - case ISA::IPR_IVPTBR: - case ISA::IPR_MVPTBR: - ipr[idx] = val & ULL(0xffffffffc0000000); - break; - - case ISA::IPR_DC_TEST_CTL: - ipr[idx] = val & 0x1ffb; - break; - - case ISA::IPR_DC_MODE: - case ISA::IPR_MAF_MODE: - ipr[idx] = val & 0x3f; - break; - - case ISA::IPR_ITB_ASN: - ipr[idx] = val & 0x7f0; - break; - - case ISA::IPR_DTB_ASN: - ipr[idx] = val & ULL(0xfe00000000000000); - break; - - case ISA::IPR_EXC_SUM: - case ISA::IPR_EXC_MASK: - // any write to this register clears it - ipr[idx] = 0; - break; - - case ISA::IPR_INTID: - case ISA::IPR_SL_RCV: - case ISA::IPR_MM_STAT: - case ISA::IPR_ITB_PTE_TEMP: - case ISA::IPR_DTB_PTE_TEMP: - // read-only registers - return Unimplemented_Opcode_Fault; - - case ISA::IPR_HWINT_CLR: - case ISA::IPR_SL_XMIT: - case ISA::IPR_DC_FLUSH: - case ISA::IPR_IC_FLUSH: - // the following are write only - ipr[idx] = val; - break; - - case ISA::IPR_DTB_IA: - // really a control write - ipr[idx] = 0; - - cpu->dtb->flushAll(); - break; - - case ISA::IPR_DTB_IAP: - // really a control write - ipr[idx] = 0; - - cpu->dtb->flushProcesses(); - break; - - case ISA::IPR_DTB_IS: - // really a control write - ipr[idx] = val; - - cpu->dtb->flushAddr(val, DTB_ASN_ASN(ipr[ISA::IPR_DTB_ASN])); - break; - - case ISA::IPR_DTB_TAG: { - struct ISA::PTE pte; - - // FIXME: granularity hints NYI... - if (DTB_PTE_GH(ipr[ISA::IPR_DTB_PTE]) != 0) - panic("PTE GH field != 0"); - - // write entire quad - ipr[idx] = val; - - // construct PTE for new entry - pte.ppn = DTB_PTE_PPN(ipr[ISA::IPR_DTB_PTE]); - pte.xre = DTB_PTE_XRE(ipr[ISA::IPR_DTB_PTE]); - pte.xwe = DTB_PTE_XWE(ipr[ISA::IPR_DTB_PTE]); - pte.fonr = DTB_PTE_FONR(ipr[ISA::IPR_DTB_PTE]); - pte.fonw = DTB_PTE_FONW(ipr[ISA::IPR_DTB_PTE]); - pte.asma = DTB_PTE_ASMA(ipr[ISA::IPR_DTB_PTE]); - pte.asn = DTB_ASN_ASN(ipr[ISA::IPR_DTB_ASN]); - - // insert new TAG/PTE value into data TLB - cpu->dtb->insert(val, pte); - } - break; - - case ISA::IPR_ITB_PTE: { - struct ISA::PTE pte; - - // FIXME: granularity hints NYI... - if (ITB_PTE_GH(val) != 0) - panic("PTE GH field != 0"); - - // write entire quad - ipr[idx] = val; - - // construct PTE for new entry - pte.ppn = ITB_PTE_PPN(val); - pte.xre = ITB_PTE_XRE(val); - pte.xwe = 0; - pte.fonr = ITB_PTE_FONR(val); - pte.fonw = ITB_PTE_FONW(val); - pte.asma = ITB_PTE_ASMA(val); - pte.asn = ITB_ASN_ASN(ipr[ISA::IPR_ITB_ASN]); - - // insert new TAG/PTE value into data TLB - cpu->itb->insert(ipr[ISA::IPR_ITB_TAG], pte); - } - break; - - case ISA::IPR_ITB_IA: - // really a control write - ipr[idx] = 0; - - cpu->itb->flushAll(); - break; - - case ISA::IPR_ITB_IAP: - // really a control write - ipr[idx] = 0; - - cpu->itb->flushProcesses(); - break; - - case ISA::IPR_ITB_IS: - // really a control write - ipr[idx] = val; - - cpu->itb->flushAddr(val, ITB_ASN_ASN(ipr[ISA::IPR_ITB_ASN])); - break; - - default: - // invalid IPR - return Unimplemented_Opcode_Fault; - } - - // no error... - return No_Fault; -} - -#endif // #if FULL_SYSTEM - #endif // __CPU_O3_CPU_REGFILE_HH__ diff --git a/cpu/o3/rename.hh b/cpu/o3/rename.hh index a17ec7311..07b442964 100644 --- a/cpu/o3/rename.hh +++ b/cpu/o3/rename.hh @@ -46,7 +46,6 @@ class SimpleRename { public: // Typedefs from the Impl. - typedef typename Impl::ISA ISA; typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::FullCPU FullCPU; @@ -62,7 +61,7 @@ class SimpleRename typedef typename CPUPol::RenameMap RenameMap; // Typedefs from the ISA. - typedef typename ISA::Addr Addr; + typedef TheISA::RegIndex RegIndex; public: // Rename will block if ROB becomes full or issue queue becomes full, diff --git a/cpu/o3/rename_map.hh b/cpu/o3/rename_map.hh index c44c7a1ea..57be4a64a 100644 --- a/cpu/o3/rename_map.hh +++ b/cpu/o3/rename_map.hh @@ -38,9 +38,13 @@ #include <vector> #include "cpu/o3/free_list.hh" +//For RegIndex +#include "arch/isa_traits.hh" class SimpleRenameMap { + protected: + typedef TheISA::RegIndex RegIndex; public: /** * Pair of a logical register and a physical register. Tells the diff --git a/cpu/o3/rob.hh b/cpu/o3/rob.hh index 29ec48007..1185564ad 100644 --- a/cpu/o3/rob.hh +++ b/cpu/o3/rob.hh @@ -47,6 +47,8 @@ template <class Impl> class ROB { + protected: + typedef TheISA::RegIndex RegIndex; public: //Typedefs from the Impl. typedef typename Impl::FullCPU FullCPU; diff --git a/cpu/o3/store_set.hh b/cpu/o3/store_set.hh index bcd590384..5a885d838 100644 --- a/cpu/o3/store_set.hh +++ b/cpu/o3/store_set.hh @@ -31,7 +31,7 @@ #include <vector> -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "cpu/inst_seq.hh" class StoreSet diff --git a/cpu/o3/tournament_pred.hh b/cpu/o3/tournament_pred.hh index 58ea1a7d9..cb93c2f67 100644 --- a/cpu/o3/tournament_pred.hh +++ b/cpu/o3/tournament_pred.hh @@ -30,7 +30,7 @@ #define __CPU_O3_CPU_TOURNAMENT_PRED_HH__ // For Addr type. -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "cpu/o3/sat_counter.hh" class TournamentBP diff --git a/cpu/ozone/cpu.hh b/cpu/ozone/cpu.hh index 5af77862a..f5d84d656 100644 --- a/cpu/ozone/cpu.hh +++ b/cpu/ozone/cpu.hh @@ -77,7 +77,6 @@ class OoOCPU : public BaseCPU private: typedef typename Impl::DynInst DynInst; typedef typename Impl::DynInstPtr DynInstPtr; - typedef typename Impl::ISA ISA; public: // main simulation loop (one cycle) @@ -320,7 +319,7 @@ class OoOCPU : public BaseCPU // put the asid in the upper 16 bits of the paddr req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; - return No_Fault; + return NoFault; } Fault translateInstReq(MemReqPtr &req) { @@ -378,12 +377,12 @@ class OoOCPU : public BaseCPU private: InstSeqNum globalSeqNum; - DynInstPtr renameTable[ISA::TotalNumRegs]; - DynInstPtr commitTable[ISA::TotalNumRegs]; + DynInstPtr renameTable[TheISA::TotalNumRegs]; + DynInstPtr commitTable[TheISA::TotalNumRegs]; // Might need a table of the shadow registers as well. #if FULL_SYSTEM - DynInstPtr palShadowTable[ISA::NumIntRegs]; + DynInstPtr palShadowTable[TheISA::NumIntRegs]; #endif public: @@ -402,47 +401,47 @@ class OoOCPU : public BaseCPU // rename table of DynInsts. Also these likely shouldn't be called very // often, other than when adding things into the xc during say a syscall. - uint64_t readIntReg(StaticInst<TheISA> *si, int idx) + uint64_t readIntReg(StaticInst *si, int idx) { return xc->readIntReg(si->srcRegIdx(idx)); } - float readFloatRegSingle(StaticInst<TheISA> *si, int idx) + float readFloatRegSingle(StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; return xc->readFloatRegSingle(reg_idx); } - double readFloatRegDouble(StaticInst<TheISA> *si, int idx) + double readFloatRegDouble(StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; return xc->readFloatRegDouble(reg_idx); } - uint64_t readFloatRegInt(StaticInst<TheISA> *si, int idx) + uint64_t readFloatRegInt(StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; return xc->readFloatRegInt(reg_idx); } - void setIntReg(StaticInst<TheISA> *si, int idx, uint64_t val) + void setIntReg(StaticInst *si, int idx, uint64_t val) { xc->setIntReg(si->destRegIdx(idx), val); } - void setFloatRegSingle(StaticInst<TheISA> *si, int idx, float val) + void setFloatRegSingle(StaticInst *si, int idx, float val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; xc->setFloatRegSingle(reg_idx, val); } - void setFloatRegDouble(StaticInst<TheISA> *si, int idx, double val) + void setFloatRegDouble(StaticInst *si, int idx, double val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; xc->setFloatRegDouble(reg_idx, val); } - void setFloatRegInt(StaticInst<TheISA> *si, int idx, uint64_t val) + void setFloatRegInt(StaticInst *si, int idx, uint64_t val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; xc->setFloatRegInt(reg_idx, val); @@ -479,7 +478,7 @@ class OoOCPU : public BaseCPU // We fold in the PISA 64- to 32-bit conversion here as well. Addr icacheBlockAlignPC(Addr addr) { - addr = ISA::realPCToFetchPC(addr); + addr = TheISA::realPCToFetchPC(addr); return (addr & ~(cacheBlkMask)); } @@ -518,7 +517,7 @@ class OoOCPU : public BaseCPU int readIntrFlag() { return xc->readIntrFlag(); } void setIntrFlag(int val) { xc->setIntrFlag(val); } bool inPalMode() { return xc->inPalMode(); } - void ev5_trap(Fault fault) { xc->ev5_trap(fault); } + void trap(Fault fault) { fault->invoke(xc); } bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); } #else void syscall() { xc->syscall(); } @@ -545,18 +544,18 @@ OoOCPU<Impl>::read(Addr addr, T &data, unsigned flags, DynInstPtr inst) Fault fault = translateDataReadReq(readReq); // do functional access - if (fault == No_Fault) + if (fault == NoFault) fault = xc->mem->read(readReq, data); #if 0 if (traceData) { traceData->setAddr(addr); - if (fault == No_Fault) + if (fault == NoFault) traceData->setData(data); } #endif // if we have a cache, do cache access too - if (fault == No_Fault && dcacheInterface) { + if (fault == NoFault && dcacheInterface) { readReq->cmd = Read; readReq->completionEvent = NULL; readReq->time = curTick; @@ -598,10 +597,10 @@ OoOCPU<Impl>::write(T data, Addr addr, unsigned flags, Fault fault = translateDataWriteReq(writeReq); // do functional access - if (fault == No_Fault) + if (fault == NoFault) fault = xc->write(writeReq, data); - if (fault == No_Fault && dcacheInterface) { + if (fault == NoFault && dcacheInterface) { writeReq->cmd = Write; memcpy(writeReq->data,(uint8_t *)&data,writeReq->size); writeReq->completionEvent = NULL; @@ -614,7 +613,7 @@ OoOCPU<Impl>::write(T data, Addr addr, unsigned flags, } } - if (res && (fault == No_Fault)) + if (res && (fault == NoFault)) *res = writeReq->result; if (!dcacheInterface && (writeReq->flags & UNCACHEABLE)) diff --git a/cpu/ozone/cpu_impl.hh b/cpu/ozone/cpu_impl.hh index 009a81b98..e7ed3cfe0 100644 --- a/cpu/ozone/cpu_impl.hh +++ b/cpu/ozone/cpu_impl.hh @@ -29,7 +29,7 @@ #ifndef __CPU_OOO_CPU_OOO_IMPL_HH__ #define __CPU_OOO_CPU_OOO_IMPL_HH__ -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" template <class Impl> class OoOCPU; diff --git a/cpu/ozone/ea_list.cc b/cpu/ozone/ea_list.cc index 80cf80fb8..6114a0ca1 100644 --- a/cpu/ozone/ea_list.cc +++ b/cpu/ozone/ea_list.cc @@ -26,7 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "cpu/inst_seq.hh" #include "cpu/ooo_cpu/ea_list.hh" diff --git a/cpu/ozone/ea_list.hh b/cpu/ozone/ea_list.hh index def7e67d5..c0eee4bb8 100644 --- a/cpu/ozone/ea_list.hh +++ b/cpu/ozone/ea_list.hh @@ -32,7 +32,7 @@ #include <list> #include <utility> -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" #include "cpu/inst_seq.hh" /** diff --git a/cpu/pc_event.cc b/cpu/pc_event.cc index 83fbc3e2d..050bf1a88 100644 --- a/cpu/pc_event.cc +++ b/cpu/pc_event.cc @@ -38,6 +38,7 @@ #include "cpu/pc_event.hh" #include "sim/debug.hh" #include "sim/root.hh" +#include "sim/system.hh" using namespace std; @@ -79,7 +80,7 @@ PCEventQueue::schedule(PCEvent *event) bool PCEventQueue::doService(ExecContext *xc) { - Addr pc = xc->regs.pc & ~0x3; + Addr pc = xc->readPC() & ~0x3; int serviced = 0; range_t range = equal_range(pc); for (iterator i = range.first; i != range.second; ++i) { @@ -87,7 +88,7 @@ PCEventQueue::doService(ExecContext *xc) // another event. This for example, prevents two invocations // of the SkipFuncEvent. Maybe we should have separate PC // event queues for each processor? - if (pc != (xc->regs.pc & ~0x3)) + if (pc != (xc->readPC() & ~0x3)) continue; DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n", @@ -126,7 +127,7 @@ BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, Addr addr, void BreakPCEvent::process(ExecContext *xc) { - StringWrap name(xc->cpu->name() + ".break_event"); + StringWrap name(xc->getCpuPtr()->name() + ".break_event"); DPRINTFN("break event %s triggered\n", descr()); debug_break(); if (remove) diff --git a/cpu/profile.cc b/cpu/profile.cc index 1a38792a0..fe3458b61 100644 --- a/cpu/profile.cc +++ b/cpu/profile.cc @@ -32,6 +32,7 @@ #include "base/callback.hh" #include "base/statistics.hh" #include "base/trace.hh" +#include "base/loader/symtab.hh" #include "cpu/base.hh" #include "cpu/exec_context.hh" #include "cpu/profile.hh" diff --git a/cpu/profile.hh b/cpu/profile.hh index 58cd7e79f..d55c9eec9 100644 --- a/cpu/profile.hh +++ b/cpu/profile.hh @@ -33,7 +33,9 @@ #include "cpu/static_inst.hh" #include "sim/host.hh" -#include "targetarch/stacktrace.hh" +#include "arch/stacktrace.hh" + +class ExecContext; class ProfileNode { @@ -68,7 +70,7 @@ class FunctionProfile FunctionProfile(const SymbolTable *symtab); ~FunctionProfile(); - ProfileNode *consume(ExecContext *xc, StaticInstPtr<TheISA> inst); + ProfileNode *consume(ExecContext *xc, StaticInstPtr inst); ProfileNode *consume(const std::vector<Addr> &stack); void clear(); void dump(ExecContext *xc, std::ostream &out) const; @@ -76,7 +78,7 @@ class FunctionProfile }; inline ProfileNode * -FunctionProfile::consume(ExecContext *xc, StaticInstPtr<TheISA> inst) +FunctionProfile::consume(ExecContext *xc, StaticInstPtr inst) { if (!trace.trace(xc, inst)) return NULL; diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc index d8d4c3644..fc70df662 100644 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@ -44,6 +44,7 @@ #include "base/stats/events.hh" #include "base/trace.hh" #include "cpu/base.hh" +#include "cpu/cpu_exec_context.hh" #include "cpu/exec_context.hh" #include "cpu/exetrace.hh" #include "cpu/profile.hh" @@ -52,6 +53,7 @@ #include "cpu/smt.hh" #include "cpu/static_inst.hh" #include "kern/kernel_stats.hh" +#include "sim/byteswap.hh" #include "sim/builder.hh" #include "sim/debug.hh" #include "sim/host.hh" @@ -64,14 +66,16 @@ #include "mem/functional/memory_control.hh" #include "mem/functional/physical.hh" #include "sim/system.hh" -#include "targetarch/alpha_memory.hh" -#include "targetarch/stacktrace.hh" -#include "targetarch/vtophys.hh" +#include "arch/tlb.hh" +#include "arch/stacktrace.hh" +#include "arch/vtophys.hh" #else // !FULL_SYSTEM #include "mem/memory.hh" #endif // FULL_SYSTEM using namespace std; +//The SimpleCPU does alpha only +using namespace AlphaISA; SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w) @@ -79,6 +83,21 @@ SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w) { } + +void +SimpleCPU::init() +{ + BaseCPU::init(); +#if FULL_SYSTEM + for (int i = 0; i < execContexts.size(); ++i) { + ExecContext *xc = execContexts[i]; + + // initialize CPU, including PC + TheISA::initCPU(xc, xc->readCpuId()); + } +#endif +} + void SimpleCPU::TickEvent::process() { @@ -129,7 +148,7 @@ SimpleCPU::CpuPort::recvRetry() SimpleCPU::SimpleCPU(Params *p) : BaseCPU(p), icachePort(this), - dcachePort(this), tickEvent(this, p->width), xc(NULL) + dcachePort(this), tickEvent(this, p->width), cpuXC(NULL) { _status = Idle; @@ -143,15 +162,14 @@ SimpleCPU::SimpleCPU(Params *p) (p->mem->getPort("ICACHE"))->setPeer(&icachePort); #if FULL_SYSTEM - xc = new ExecContext(this, 0, p->system, p->itb, p->dtb, p->mem); - - // initialize CPU, including PC - TheISA::initCPU(&xc->regs); + cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem); #else - xc = new ExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0, + cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0, &dcachePort); #endif // !FULL_SYSTEM + xcProxy = cpuXC->getProxy(); + #if SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE ifetch_req = new CpuRequest; ifetch_req->asid = 0; @@ -183,7 +201,7 @@ SimpleCPU::SimpleCPU(Params *p) lastIcacheStall = 0; lastDcacheStall = 0; - execContexts.push_back(xc); + execContexts.push_back(xcProxy); } SimpleCPU::~SimpleCPU() @@ -232,7 +250,7 @@ void SimpleCPU::activateContext(int thread_num, int delay) { assert(thread_num == 0); - assert(xc); + assert(cpuXC); assert(_status == Idle); notIdleFraction++; @@ -245,7 +263,7 @@ void SimpleCPU::suspendContext(int thread_num) { assert(thread_num == 0); - assert(xc); + assert(cpuXC); assert(_status == Running); notIdleFraction--; @@ -338,7 +356,7 @@ SimpleCPU::serialize(ostream &os) SERIALIZE_ENUM(_status); SERIALIZE_SCALAR(inst); nameOut(os, csprintf("%s.xc", name())); - xc->serialize(os); + cpuXC->serialize(os); nameOut(os, csprintf("%s.tickEvent", name())); tickEvent.serialize(os); nameOut(os, csprintf("%s.cacheCompletionEvent", name())); @@ -350,7 +368,7 @@ SimpleCPU::unserialize(Checkpoint *cp, const string §ion) BaseCPU::unserialize(cp, section); UNSERIALIZE_ENUM(_status); UNSERIALIZE_SCALAR(inst); - xc->unserialize(cp, csprintf("%s.xc", section)); + cpuXC->unserialize(cp, csprintf("%s.xc", section)); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); } @@ -371,7 +389,7 @@ SimpleCPU::copySrcTranslate(Addr src) // Make sure block doesn't span page if (no_warn && - (src & TheISA::PageMask) != ((src + blk_size) & TheISA::PageMask) && + (src & PageMask) != ((src + blk_size) & PageMask) && (src >> 40) != 0xfffffc) { warn("Copied block source spans pages %x.", src); no_warn = false; @@ -379,17 +397,16 @@ SimpleCPU::copySrcTranslate(Addr src) memReq->reset(src & ~(blk_size - 1), blk_size); - // translate to physical address - Fault fault = xc->translateDataReadReq(req); - - assert(fault != Alignment_Fault); + // translate to physical address Fault fault = cpuXC->translateDataReadReq(req); - if (fault == No_Fault) { - xc->copySrcAddr = src; - xc->copySrcPhysAddr = memReq->paddr + offset; + if (fault == NoFault) { + cpuXC->copySrcAddr = src; + cpuXC->copySrcPhysAddr = memReq->paddr + offset; } else { - xc->copySrcAddr = 0; - xc->copySrcPhysAddr = 0; + assert(!fault->isAlignmentFault()); + + cpuXC->copySrcAddr = 0; + cpuXC->copySrcPhysAddr = 0; } return fault; #else @@ -406,12 +423,12 @@ SimpleCPU::copy(Addr dest) // Only support block sizes of 64 atm. assert(blk_size == 64); uint8_t data[blk_size]; - //assert(xc->copySrcAddr); + //assert(cpuXC->copySrcAddr); int offset = dest & (blk_size - 1); // Make sure block doesn't span page if (no_warn && - (dest & TheISA::PageMask) != ((dest + blk_size) & TheISA::PageMask) && + (dest & PageMask) != ((dest + blk_size) & PageMask) && (dest >> 40) != 0xfffffc) { no_warn = false; warn("Copied block destination spans pages %x. ", dest); @@ -419,21 +436,19 @@ SimpleCPU::copy(Addr dest) memReq->reset(dest & ~(blk_size -1), blk_size); // translate to physical address - Fault fault = xc->translateDataWriteReq(req); - - assert(fault != Alignment_Fault); + Fault fault = cpuXC->translateDataWriteReq(req); - if (fault == No_Fault) { + if (fault == NoFault) { Addr dest_addr = memReq->paddr + offset; // Need to read straight from memory since we have more than 8 bytes. - memReq->paddr = xc->copySrcPhysAddr; - xc->mem->read(memReq, data); + memReq->paddr = cpuXC->copySrcPhysAddr; + cpuXC->mem->read(memReq, data); memReq->paddr = dest_addr; - xc->mem->write(memReq, data); + cpuXC->mem->write(memReq, data); if (dcacheInterface) { memReq->cmd = Copy; memReq->completionEvent = NULL; - memReq->paddr = xc->copySrcPhysAddr; + memReq->paddr = cpuXC->copySrcPhysAddr; memReq->dest = dest_addr; memReq->size = 64; memReq->time = curTick; @@ -441,6 +456,9 @@ SimpleCPU::copy(Addr dest) dcacheInterface->access(memReq); } } + else + assert(!fault->isAlignmentFault()); + return fault; #else panic("copy not implemented"); @@ -480,7 +498,7 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) data_read_req->time = curTick; // translate to physical address - Fault fault = xc->translateDataReadReq(data_read_req); + Fault fault = cpuXC->translateDataReadReq(data_read_req); // Now do the access. if (fault == No_Fault) { @@ -527,13 +545,12 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) _status = DcacheMissStall; } else { // do functional access - fault = xc->read(memReq, data); + fault = cpuXC->read(memReq, data); } - - } else if(fault == No_Fault) { + } else if(fault == NoFault) { // do functional access - fault = xc->read(memReq, data); + fault = cpuXC->read(memReq, data); } */ @@ -597,8 +614,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) data_write_req->flags = flags; // translate to physical address - Fault fault = xc->translateDataWriteReq(data_write_req); - + Fault fault = cpuXC->translateDataWriteReq(data_write_req); // Now do the access. if (fault == No_Fault) { #if SIMPLE_CPU_MEM_TIMING @@ -618,10 +634,10 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) /* // do functional access - if (fault == No_Fault) - fault = xc->write(memReq, data); + if (fault == NoFault) + fault = cpuXC->write(memReq, data); - if (fault == No_Fault && dcacheInterface) { + if (fault == NoFault && dcacheInterface) { memReq->cmd = Write; memcpy(memReq->data,(uint8_t *)&data,memReq->size); memReq->completionEvent = NULL; @@ -640,7 +656,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) } } */ - if (res && (fault == No_Fault)) + if (res && (fault == NoFault)) *res = data_write_pkt->result; // This will need a new way to tell if it's hooked up to a cache or not. @@ -699,7 +715,7 @@ SimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) Addr SimpleCPU::dbg_vtophys(Addr addr) { - return vtophys(xc, addr); + return vtophys(xcProxy, addr); } #endif // FULL_SYSTEM @@ -863,9 +879,9 @@ SimpleCPU::post_interrupt(int int_num, int index) { BaseCPU::post_interrupt(int_num, index); - if (xc->status() == ExecContext::Suspended) { + if (cpuXC->status() == ExecContext::Suspended) { DPRINTF(IPI,"Suspended Processor awoke\n"); - xc->activate(); + cpuXC->activate(); } } #endif // FULL_SYSTEM @@ -878,30 +894,29 @@ SimpleCPU::tick() traceData = NULL; - Fault fault = No_Fault; + Fault fault = NoFault; #if FULL_SYSTEM - if (checkInterrupts && check_interrupts() && !xc->inPalMode() && + if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode() && status() != IcacheMissComplete) { int ipl = 0; int summary = 0; checkInterrupts = false; - IntReg *ipr = xc->regs.ipr; - if (xc->regs.ipr[TheISA::IPR_SIRR]) { - for (int i = TheISA::INTLEVEL_SOFTWARE_MIN; - i < TheISA::INTLEVEL_SOFTWARE_MAX; i++) { - if (ipr[TheISA::IPR_SIRR] & (ULL(1) << i)) { + if (cpuXC->readMiscReg(IPR_SIRR)) { + for (int i = INTLEVEL_SOFTWARE_MIN; + i < INTLEVEL_SOFTWARE_MAX; i++) { + if (cpuXC->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { // See table 4-19 of 21164 hardware reference - ipl = (i - TheISA::INTLEVEL_SOFTWARE_MIN) + 1; + ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; summary |= (ULL(1) << i); } } } - uint64_t interrupts = xc->cpu->intr_status(); - for (int i = TheISA::INTLEVEL_EXTERNAL_MIN; - i < TheISA::INTLEVEL_EXTERNAL_MAX; i++) { + uint64_t interrupts = cpuXC->cpu->intr_status(); + for (int i = INTLEVEL_EXTERNAL_MIN; + i < INTLEVEL_EXTERNAL_MAX; i++) { if (interrupts & (ULL(1) << i)) { // See table 4-19 of 21164 hardware reference ipl = i; @@ -909,24 +924,25 @@ SimpleCPU::tick() } } - if (ipr[TheISA::IPR_ASTRR]) + if (cpuXC->readMiscReg(IPR_ASTRR)) panic("asynchronous traps not implemented\n"); - if (ipl && ipl > xc->regs.ipr[TheISA::IPR_IPLR]) { - ipr[TheISA::IPR_ISR] = summary; - ipr[TheISA::IPR_INTID] = ipl; - xc->ev5_trap(Interrupt_Fault); + if (ipl && ipl > cpuXC->readMiscReg(IPR_IPLR)) { + cpuXC->setMiscReg(IPR_ISR, summary); + cpuXC->setMiscReg(IPR_INTID, ipl); + + Fault(new InterruptFault)->invoke(xcProxy); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - ipr[TheISA::IPR_IPLR], ipl, summary); + cpuXC->readMiscReg(IPR_IPLR), ipl, summary); } } #endif // maintain $r0 semantics - xc->regs.intRegFile[ZeroReg] = 0; + cpuXC->setIntReg(ZeroReg, 0); #ifdef TARGET_ALPHA - xc->regs.floatRegFile.d[ZeroReg] = 0.0; + cpuXC->setFloatRegDouble(ZeroReg, 0.0); #endif // TARGET_ALPHA if (status() == IcacheAccessComplete) { @@ -951,7 +967,7 @@ SimpleCPU::tick() ifetch_req->size = sizeof(MachInst); #endif - ifetch_req->vaddr = xc->regs.pc & ~3; + ifetch_req->vaddr = cpuXC->readPC() & ~3; ifetch_req->time = curTick; /* memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t), @@ -960,7 +976,7 @@ SimpleCPU::tick() fault = xc->translateInstReq(ifetch_req); - if (fault == No_Fault) { + if (fault == NoFault) { #if SIMPLE_CPU_MEM_TIMING Packet *ifetch_pkt = new Packet; ifetch_pkt->cmd = Read; @@ -975,7 +991,7 @@ SimpleCPU::tick() return; #endif /* - if (icacheInterface && fault == No_Fault) { + if (icacheInterface && fault == NoFault) { memReq->completionEvent = NULL; memReq->time = curTick; @@ -999,7 +1015,7 @@ SimpleCPU::tick() // If we've got a valid instruction (i.e., no fault on instruction // fetch), then execute it. - if (fault == No_Fault) { + if (fault == NoFault) { // keep an instruction count numInst++; @@ -1010,31 +1026,32 @@ SimpleCPU::tick() // decode the instruction inst = gtoh(inst); - curStaticInst = StaticInst<TheISA>::decode(inst); + curStaticInst = StaticInst::decode(makeExtMI(inst, cpuXC->readPC())); - traceData = Trace::getInstRecord(curTick, xc, this, curStaticInst, - xc->regs.pc); + traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst, + cpuXC->readPC()); #if FULL_SYSTEM - xc->setInst(inst); + cpuXC->setInst(inst); #endif // FULL_SYSTEM - xc->func_exe_inst++; + cpuXC->func_exe_inst++; fault = curStaticInst->execute(this, traceData); #if FULL_SYSTEM - if (xc->fnbin) { - assert(xc->kernelStats); - system->kernelBinning->execute(xc, inst); + if (system->kernelBinning->fnbin) { + assert(kernelStats); + system->kernelBinning->execute(xcProxy, inst); } - if (xc->profile) { - bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0; - xc->profilePC = usermode ? 1 : xc->regs.pc; - ProfileNode *node = xc->profile->consume(xc, inst); + if (cpuXC->profile) { + bool usermode = + (cpuXC->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + cpuXC->profilePC = usermode ? 1 : cpuXC->readPC(); + ProfileNode *node = cpuXC->profile->consume(xcProxy, inst); if (node) - xc->profileNode = node; + cpuXC->profileNode = node; } #endif @@ -1053,29 +1070,37 @@ SimpleCPU::tick() traceData->finalize(); } - traceFunctions(xc->regs.pc); + traceFunctions(cpuXC->readPC()); - } // if (fault == No_Fault) + } // if (fault == NoFault) - if (fault != No_Fault) { + if (fault != NoFault) { #if FULL_SYSTEM - xc->ev5_trap(fault); + fault->invoke(xcProxy); #else // !FULL_SYSTEM - fatal("fault (%d) detected @ PC 0x%08p", fault, xc->regs.pc); + fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC()); #endif // FULL_SYSTEM } else { +#if THE_ISA != MIPS_ISA // go to the next instruction - xc->regs.pc = xc->regs.npc; - xc->regs.npc += sizeof(MachInst); + cpuXC->setPC(cpuXC->readNextPC()); + cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); +#else + // go to the next instruction + cpuXC->setPC(cpuXC->readNextPC()); + cpuXC->setNextPC(cpuXC->readNextNPC()); + cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst)); +#endif + } #if FULL_SYSTEM Addr oldpc; do { - oldpc = xc->regs.pc; - system->pcEventQueue.service(xc); - } while (oldpc != xc->regs.pc); + oldpc = cpuXC->readPC(); + system->pcEventQueue.service(xcProxy); + } while (oldpc != cpuXC->readPC()); #endif assert(status() == Running || diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh index ca10134f7..fbfae950f 100644 --- a/cpu/simple/cpu.hh +++ b/cpu/simple/cpu.hh @@ -32,7 +32,7 @@ #include "base/statistics.hh" #include "config/full_system.hh" #include "cpu/base.hh" -#include "cpu/exec_context.hh" +#include "cpu/cpu_exec_context.hh" #include "cpu/pc_event.hh" #include "cpu/sampler/sampler.hh" #include "cpu/static_inst.hh" @@ -57,6 +57,7 @@ class Process; #endif // FULL_SYSTEM +class ExecContext; class MemInterface; class Checkpoint; @@ -76,6 +77,9 @@ namespace Trace { class SimpleCPU : public BaseCPU { + protected: + typedef TheISA::MachInst MachInst; + typedef TheISA::MiscReg MiscReg; class CpuPort : public Port { @@ -106,6 +110,7 @@ class SimpleCPU : public BaseCPU public: // main simulation loop (one cycle) void tick(); + virtual void init(); private: struct TickEvent : public Event @@ -184,7 +189,9 @@ class SimpleCPU : public BaseCPU public: // execution context - ExecContext *xc; + CPUExecContext *cpuXC; + + ExecContext *xcProxy; void switchOut(Sampler *s); void takeOverFrom(BaseCPU *oldCPU); @@ -214,7 +221,7 @@ class SimpleCPU : public BaseCPU // the next switchover Sampler *sampler; - StaticInstPtr<TheISA> curStaticInst; + StaticInstPtr curStaticInst; Status status() const { return _status; } @@ -310,76 +317,88 @@ class SimpleCPU : public BaseCPU // storage (which is pretty hard to imagine they would have reason // to do). - uint64_t readIntReg(const StaticInst<TheISA> *si, int idx) + uint64_t readIntReg(const StaticInst *si, int idx) { - return xc->readIntReg(si->srcRegIdx(idx)); + return cpuXC->readIntReg(si->srcRegIdx(idx)); } - float readFloatRegSingle(const StaticInst<TheISA> *si, int idx) + float readFloatRegSingle(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return xc->readFloatRegSingle(reg_idx); + return cpuXC->readFloatRegSingle(reg_idx); } - double readFloatRegDouble(const StaticInst<TheISA> *si, int idx) + double readFloatRegDouble(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return xc->readFloatRegDouble(reg_idx); + return cpuXC->readFloatRegDouble(reg_idx); } - uint64_t readFloatRegInt(const StaticInst<TheISA> *si, int idx) + uint64_t readFloatRegInt(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return xc->readFloatRegInt(reg_idx); + return cpuXC->readFloatRegInt(reg_idx); } - void setIntReg(const StaticInst<TheISA> *si, int idx, uint64_t val) + void setIntReg(const StaticInst *si, int idx, uint64_t val) { - xc->setIntReg(si->destRegIdx(idx), val); + cpuXC->setIntReg(si->destRegIdx(idx), val); } - void setFloatRegSingle(const StaticInst<TheISA> *si, int idx, float val) + void setFloatRegSingle(const StaticInst *si, int idx, float val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - xc->setFloatRegSingle(reg_idx, val); + cpuXC->setFloatRegSingle(reg_idx, val); } - void setFloatRegDouble(const StaticInst<TheISA> *si, int idx, double val) + void setFloatRegDouble(const StaticInst *si, int idx, double val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - xc->setFloatRegDouble(reg_idx, val); + cpuXC->setFloatRegDouble(reg_idx, val); } - void setFloatRegInt(const StaticInst<TheISA> *si, int idx, uint64_t val) + void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - xc->setFloatRegInt(reg_idx, val); + cpuXC->setFloatRegInt(reg_idx, val); } - uint64_t readPC() { return xc->readPC(); } - void setNextPC(uint64_t val) { xc->setNextPC(val); } + uint64_t readPC() { return cpuXC->readPC(); } + void setNextPC(uint64_t val) { cpuXC->setNextPC(val); } + + MiscReg readMiscReg(int misc_reg) + { + return cpuXC->readMiscReg(misc_reg); + } - uint64_t readUniq() { return xc->readUniq(); } - void setUniq(uint64_t val) { xc->setUniq(val); } + MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) + { + return cpuXC->readMiscRegWithEffect(misc_reg, fault); + } - uint64_t readFpcr() { return xc->readFpcr(); } - void setFpcr(uint64_t val) { xc->setFpcr(val); } + Fault setMiscReg(int misc_reg, const MiscReg &val) + { + return cpuXC->setMiscReg(misc_reg, val); + } + + Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) + { + return cpuXC->setMiscRegWithEffect(misc_reg, val); + } #if FULL_SYSTEM - uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); } - Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); } - Fault hwrei() { return xc->hwrei(); } - int readIntrFlag() { return xc->readIntrFlag(); } - void setIntrFlag(int val) { xc->setIntrFlag(val); } - bool inPalMode() { return xc->inPalMode(); } - void ev5_trap(Fault fault) { xc->ev5_trap(fault); } - bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); } + Fault hwrei() { return cpuXC->hwrei(); } + int readIntrFlag() { return cpuXC->readIntrFlag(); } + void setIntrFlag(int val) { cpuXC->setIntrFlag(val); } + bool inPalMode() { return cpuXC->inPalMode(); } + void ev5_trap(Fault fault) { fault->invoke(xcProxy); } + bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); } #else - void syscall() { xc->syscall(); } + void syscall() { cpuXC->syscall(); } #endif - bool misspeculating() { return xc->misspeculating(); } - ExecContext *xcBase() { return xc; } + bool misspeculating() { return cpuXC->misspeculating(); } + ExecContext *xcBase() { return xcProxy; } }; #endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__ diff --git a/cpu/static_inst.cc b/cpu/static_inst.cc index 54bd9914e..c307dc6fc 100644 --- a/cpu/static_inst.cc +++ b/cpu/static_inst.cc @@ -30,19 +30,13 @@ #include "cpu/static_inst.hh" #include "sim/root.hh" -template <class ISA> -StaticInstPtr<ISA> StaticInst<ISA>::nullStaticInstPtr; - -template <class ISA> -typename StaticInst<ISA>::DecodeCache StaticInst<ISA>::decodeCache; +StaticInstPtr StaticInst::nullStaticInstPtr; // Define the decode cache hash map. -template StaticInst<AlphaISA>::DecodeCache -StaticInst<AlphaISA>::decodeCache; +StaticInst::DecodeCache StaticInst::decodeCache; -template <class ISA> void -StaticInst<ISA>::dumpDecodeCacheStats() +StaticInst::dumpDecodeCacheStats() { using namespace std; @@ -62,13 +56,8 @@ StaticInst<ISA>::dumpDecodeCacheStats() } } - -template StaticInstPtr<AlphaISA> -StaticInst<AlphaISA>::nullStaticInstPtr; - -template <class ISA> bool -StaticInst<ISA>::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const +StaticInst::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const { if (isDirectCtrl()) { tgt = branchTarget(pc); @@ -83,6 +72,3 @@ StaticInst<ISA>::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const return false; } - -// force instantiation of template function(s) above -template class StaticInst<AlphaISA>; diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh index 09eb7efbf..2ed2fe61c 100644 --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@ -36,7 +36,7 @@ #include "base/refcnt.hh" #include "cpu/op_class.hh" #include "sim/host.hh" -#include "targetarch/isa_traits.hh" +#include "arch/isa_traits.hh" // forward declarations struct AlphaSimpleImpl; @@ -109,10 +109,14 @@ class StaticInstBase : public RefCounted IsCall, ///< Subroutine call. IsReturn, ///< Subroutine return. + IsCondDelaySlot,///< Conditional Delay-Slot Instruction + IsThreadSync, ///< Thread synchronization operation. IsSerializing, ///< Serializes pipeline: won't execute until all /// older instructions have committed. + IsSerializeBefore, + IsSerializeAfter, IsMemBarrier, ///< Is a memory barrier IsWriteBarrier, ///< Is a write barrier @@ -196,7 +200,11 @@ class StaticInstBase : public RefCounted bool isUncondCtrl() const { return flags[IsUncondControl]; } bool isThreadSync() const { return flags[IsThreadSync]; } - bool isSerializing() const { return flags[IsSerializing]; } + bool isSerializing() const { return flags[IsSerializing] || + flags[IsSerializeBefore] || + flags[IsSerializeAfter]; } + bool isSerializeBefore() const { return flags[IsSerializeBefore]; } + bool isSerializeAfter() const { return flags[IsSerializeAfter]; } bool isMemBarrier() const { return flags[IsMemBarrier]; } bool isWriteBarrier() const { return flags[IsWriteBarrier]; } bool isNonSpeculative() const { return flags[IsNonSpeculative]; } @@ -208,7 +216,6 @@ class StaticInstBase : public RefCounted // forward declaration -template <class ISA> class StaticInstPtr; /** @@ -218,21 +225,20 @@ class StaticInstPtr; * that are generic across all ISAs but that differ in details * according to the specific ISA being used. */ -template <class ISA> class StaticInst : public StaticInstBase { public: /// Binary machine instruction type. - typedef typename ISA::MachInst MachInst; - /// Memory address type. - typedef typename ISA::Addr Addr; + typedef TheISA::MachInst MachInst; + /// Binary extended machine instruction type. + typedef TheISA::ExtMachInst ExtMachInst; /// Logical register index type. - typedef typename ISA::RegIndex RegIndex; + typedef TheISA::RegIndex RegIndex; enum { - MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs + MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs }; @@ -247,7 +253,7 @@ class StaticInst : public StaticInstBase /// Pointer to a statically allocated "null" instruction object. /// Used to give eaCompInst() and memAccInst() something to return /// when called on non-memory instructions. - static StaticInstPtr<ISA> nullStaticInstPtr; + static StaticInstPtr nullStaticInstPtr; /** * Memory references only: returns "fake" instruction representing @@ -256,7 +262,7 @@ class StaticInst : public StaticInstBase * just the EA computation. */ virtual const - StaticInstPtr<ISA> &eaCompInst() const { return nullStaticInstPtr; } + StaticInstPtr &eaCompInst() const { return nullStaticInstPtr; } /** * Memory references only: returns "fake" instruction representing @@ -265,10 +271,10 @@ class StaticInst : public StaticInstBase * just the memory access (not the EA computation). */ virtual const - StaticInstPtr<ISA> &memAccInst() const { return nullStaticInstPtr; } + StaticInstPtr &memAccInst() const { return nullStaticInstPtr; } /// The binary machine instruction. - const MachInst machInst; + const ExtMachInst machInst; protected: @@ -298,7 +304,7 @@ class StaticInst : public StaticInstBase generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0; /// Constructor. - StaticInst(const char *_mnemonic, MachInst _machInst, OpClass __opClass) + StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass) : StaticInstBase(__opClass), machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0) { @@ -312,7 +318,11 @@ class StaticInst : public StaticInstBase delete cachedDisassembly; } -#include "static_inst_impl.hh" +/** + * The execute() signatures are auto-generated by scons based on the + * set of CPU models we are compiling in today. + */ +#include "cpu/static_inst_exec_sigs.hh" /** * Return the target address for a PC-relative branch. @@ -364,7 +374,7 @@ class StaticInst : public StaticInstBase /// Decoded instruction cache type. /// For now we're using a generic hash_map; this seems to work /// pretty well. - typedef m5::hash_map<MachInst, StaticInstPtr<ISA> > DecodeCache; + typedef m5::hash_map<ExtMachInst, StaticInstPtr> DecodeCache; /// A cache of decoded instruction objects. static DecodeCache decodeCache; @@ -378,63 +388,40 @@ class StaticInst : public StaticInstBase /// Decode a machine instruction. /// @param mach_inst The binary instruction to decode. /// @retval A pointer to the corresponding StaticInst object. - static - StaticInstPtr<ISA> decode(MachInst mach_inst) - { -#ifdef DECODE_CACHE_HASH_STATS - // Simple stats on decode hash_map. Turns out the default - // hash function is as good as anything I could come up with. - const int dump_every_n = 10000000; - static int decodes_til_dump = dump_every_n; - - if (--decodes_til_dump == 0) { - dumpDecodeCacheStats(); - decodes_til_dump = dump_every_n; - } -#endif - - typename DecodeCache::iterator iter = decodeCache.find(mach_inst); - if (iter != decodeCache.end()) { - return iter->second; - } - - StaticInstPtr<ISA> si = ISA::decodeInst(mach_inst); - decodeCache[mach_inst] = si; - return si; - } + //This is defined as inline below. + static StaticInstPtr decode(ExtMachInst mach_inst); }; typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr; /// Reference-counted pointer to a StaticInst object. -/// This type should be used instead of "StaticInst<ISA> *" so that +/// This type should be used instead of "StaticInst *" so that /// StaticInst objects can be properly reference-counted. -template <class ISA> -class StaticInstPtr : public RefCountingPtr<StaticInst<ISA> > +class StaticInstPtr : public RefCountingPtr<StaticInst> { public: /// Constructor. StaticInstPtr() - : RefCountingPtr<StaticInst<ISA> >() + : RefCountingPtr<StaticInst>() { } - /// Conversion from "StaticInst<ISA> *". - StaticInstPtr(StaticInst<ISA> *p) - : RefCountingPtr<StaticInst<ISA> >(p) + /// Conversion from "StaticInst *". + StaticInstPtr(StaticInst *p) + : RefCountingPtr<StaticInst>(p) { } /// Copy constructor. StaticInstPtr(const StaticInstPtr &r) - : RefCountingPtr<StaticInst<ISA> >(r) + : RefCountingPtr<StaticInst>(r) { } /// Construct directly from machine instruction. - /// Calls StaticInst<ISA>::decode(). - StaticInstPtr(typename ISA::MachInst mach_inst) - : RefCountingPtr<StaticInst<ISA> >(StaticInst<ISA>::decode(mach_inst)) + /// Calls StaticInst::decode(). + StaticInstPtr(TheISA::ExtMachInst mach_inst) + : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst)) { } @@ -445,4 +432,29 @@ class StaticInstPtr : public RefCountingPtr<StaticInst<ISA> > } }; +inline StaticInstPtr +StaticInst::decode(StaticInst::ExtMachInst mach_inst) +{ +#ifdef DECODE_CACHE_HASH_STATS + // Simple stats on decode hash_map. Turns out the default + // hash function is as good as anything I could come up with. + const int dump_every_n = 10000000; + static int decodes_til_dump = dump_every_n; + + if (--decodes_til_dump == 0) { + dumpDecodeCacheStats(); + decodes_til_dump = dump_every_n; + } +#endif + + DecodeCache::iterator iter = decodeCache.find(mach_inst); + if (iter != decodeCache.end()) { + return iter->second; + } + + StaticInstPtr si = TheISA::decodeInst(mach_inst); + decodeCache[mach_inst] = si; + return si; +} + #endif // __CPU_STATIC_INST_HH__ diff --git a/cpu/trace/reader/itx_reader.hh b/cpu/trace/reader/itx_reader.hh index faec73138..a16a08085 100644 --- a/cpu/trace/reader/itx_reader.hh +++ b/cpu/trace/reader/itx_reader.hh @@ -46,6 +46,7 @@ */ class ITXReader : public MemTraceReader { + private: /** Trace file. */ FILE *trace; |