diff -r b7e2c396b242 -r 523ac80e06ae SConstruct --- a/SConstruct Tue Aug 19 10:33:32 2014 +0100 +++ b/SConstruct Tue Aug 19 10:33:34 2014 +0100 @@ -1025,17 +1025,10 @@ # Dict of available CPU model objects. Accessible as CpuModel.dict. dict = {} - list = [] - defaults = [] # Constructor. Automatically adds models to CpuModel.dict. - def __init__(self, name, filename, includes, strings, default=False): + def __init__(self, name, default=False): self.name = name # name of model - 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 # This cpu is enabled by default self.default = default @@ -1044,7 +1037,6 @@ if name in CpuModel.dict: raise AttributeError, "CpuModel '%s' already registered" % name CpuModel.dict[name] = self - CpuModel.list.append(name) Export('CpuModel') @@ -1086,7 +1078,7 @@ EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list), ListVariable('CPU_MODELS', 'CPU models', sorted(n for n,m in CpuModel.dict.iteritems() if m.default), - sorted(CpuModel.list)), + sorted(CpuModel.dict.keys())), BoolVariable('EFENCE', 'Link with Electric Fence malloc debugger', False), BoolVariable('SS_COMPATIBLE_FP', diff -r b7e2c396b242 -r 523ac80e06ae src/arch/SConscript --- a/src/arch/SConscript Tue Aug 19 10:33:32 2014 +0100 +++ b/src/arch/SConscript Tue Aug 19 10:33:34 2014 +0100 @@ -95,13 +95,11 @@ # The emitter patches up the sources & targets to include the # autogenerated files as targets and isa parser itself as a source. def isa_desc_emitter(target, source, env): - cpu_models = list(env['CPU_MODELS']) - cpu_models.append('CheckerCPU') - # List the isa parser as a source. - source += [ isa_parser ] - # Add in the CPU models. - source += [ Value(m) for m in cpu_models ] + source += [ + isa_parser, + Value("ExecContext"), + ] # Specify different targets depending on if we're running the ISA # parser for its dependency information, or for the generated files. @@ -137,8 +135,7 @@ # Skip over the ISA description itself and the parser to the CPU models. models = [ s.get_contents() for s in source[2:] ] - cpu_models = [CpuModel.dict[cpu] for cpu in models] - parser = isa_parser.ISAParser(target[0].dir.abspath, cpu_models) + parser = isa_parser.ISAParser(target[0].dir.abspath) parser.parse_isa_desc(source[0].abspath) isa_desc_action = MakeAction(isa_desc_action_func, Transform("ISA DESC", 1)) diff -r b7e2c396b242 -r 523ac80e06ae src/arch/arm/isa/includes.isa --- a/src/arch/arm/isa/includes.isa Tue Aug 19 10:33:32 2014 +0100 +++ b/src/arch/arm/isa/includes.isa Tue Aug 19 10:33:34 2014 +0100 @@ -90,6 +90,7 @@ #include "arch/arm/utility.hh" #include "arch/generic/memhelpers.hh" #include "base/condcodes.hh" +#include "cpu/base.hh" #include "sim/pseudo_inst.hh" #if defined(linux) #include diff -r b7e2c396b242 -r 523ac80e06ae src/arch/isa_parser.py --- a/src/arch/isa_parser.py Tue Aug 19 10:33:32 2014 +0100 +++ b/src/arch/isa_parser.py Tue Aug 19 10:33:34 2014 +0100 @@ -1192,13 +1192,25 @@ # class ISAParser(Grammar): - def __init__(self, output_dir, cpu_models): + class CpuModel(object): + def __init__(self, name, filename, includes, strings): + self.name = name + self.filename = filename + self.includes = includes + self.strings = strings + + def __init__(self, output_dir): super(ISAParser, self).__init__() self.output_dir = output_dir self.filename = None # for output file watermarking/scaremongering - self.cpuModels = cpu_models + self.cpuModels = [ + ISAParser.CpuModel('ExecContext', + 'generic_cpu_exec.cc', + '#include "cpu/exec_context.hh"', + { "CPU_exec_context" : "ExecContext" }), + ] # variable to hold templates self.templateMap = {} @@ -2390,8 +2402,6 @@ e.exit(self.fileNameStack) # Called as script: get args from command line. -# Args are: +# Args are: if __name__ == '__main__': - execfile(sys.argv[1]) # read in CpuModel definitions - cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]] - ISAParser(sys.argv[3], cpu_models).parse_isa_desc(sys.argv[2]) + ISAParser(sys.argv[2]).parse_isa_desc(sys.argv[1]) diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/SConscript --- a/src/cpu/SConscript Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/SConscript Tue Aug 19 10:33:34 2014 +0100 @@ -35,71 +35,8 @@ Source('intr_control_noisa.cc') Return() -################################################################# -# -# 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. -# -################################################################# - -# Template for execute() signature. -exec_sig_template = ''' -virtual Fault execute(%(type)s *xc, Trace::InstRecord *traceData) const = 0; -virtual Fault eaComp(%(type)s *xc, Trace::InstRecord *traceData) const -{ panic("eaComp not defined!"); M5_DUMMY_RETURN }; -virtual Fault initiateAcc(%(type)s *xc, Trace::InstRecord *traceData) const -{ panic("initiateAcc not defined!"); M5_DUMMY_RETURN }; -virtual Fault completeAcc(Packet *pkt, %(type)s *xc, - Trace::InstRecord *traceData) const -{ panic("completeAcc not defined!"); M5_DUMMY_RETURN }; -''' - -mem_ini_sig_template = ''' -virtual Fault eaComp(%(type)s *xc, Trace::InstRecord *traceData) const -{ panic("eaComp not defined!"); M5_DUMMY_RETURN }; -virtual Fault initiateAcc(%s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); M5_DUMMY_RETURN }; -''' - -mem_comp_sig_template = ''' -virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); return NoFault; M5_DUMMY_RETURN }; -''' - -# Generate a temporary CPU list, including the CheckerCPU if -# it's enabled. This isn't used for anything else other than StaticInst -# headers. -temp_cpu_list = env['CPU_MODELS'][:] -temp_cpu_list.append('CheckerCPU') SimObject('CheckerCPU.py') -# 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 temp_cpu_list: - xc_type = CpuModel.dict[cpu].strings['CPU_exec_context'] - print >> f, exec_sig_template % { 'type' : 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 " [GENERATE] static_inst_exec_sigs.hh: " \ - + ', '.join(temp_cpu_list) - -# Add command to generate header to environment. -env.Command('static_inst_exec_sigs.hh', (), - Action(gen_cpu_exec_signatures, gen_sigs_string, - varlist = temp_cpu_list)) - -env.Depends('static_inst_exec_sigs.hh', Value(env['CPU_MODELS'])) - SimObject('BaseCPU.py') SimObject('FuncUnit.py') SimObject('ExeTracer.py') @@ -112,6 +49,7 @@ Source('base.cc') Source('cpuevent.cc') Source('exetrace.cc') +Source('exec_context.cc') Source('func_unit.cc') Source('inteltrace.cc') Source('intr_control.cc') diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/base_dyn_inst.hh --- a/src/cpu/base_dyn_inst.hh Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/base_dyn_inst.hh Tue Aug 19 10:33:34 2014 +0100 @@ -56,6 +56,7 @@ #include "config/the_isa.hh" #include "cpu/checker/cpu.hh" #include "cpu/o3/comm.hh" +#include "cpu/exec_context.hh" #include "cpu/exetrace.hh" #include "cpu/inst_seq.hh" #include "cpu/op_class.hh" @@ -73,7 +74,7 @@ */ template -class BaseDynInst : public RefCounted +class BaseDynInst : public ExecContext, public RefCounted { public: // Typedef for the CPU. @@ -82,10 +83,6 @@ // Logical register index type. typedef TheISA::RegIndex RegIndex; - // Integer register type. - typedef TheISA::IntReg IntReg; - // Floating point register type. - typedef TheISA::FloatReg FloatReg; // The DynInstPtr type. typedef typename Impl::DynInstPtr DynInstPtr; @@ -634,43 +631,25 @@ } /** Records an integer register being set to a value. */ - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) + void setIntRegOperand(const StaticInst *si, int idx, IntReg val) { setResult(val); } /** Records a CC register being set to a value. */ - void setCCRegOperand(const StaticInst *si, int idx, uint64_t val) + void setCCRegOperand(const StaticInst *si, int idx, CCReg val) { setResult(val); } /** Records an fp register being set to a value. */ - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, - int width) - { - if (width == 32 || width == 64) { - setResult(val); - } else { - panic("Unsupported width!"); - } - } - - /** Records an fp register being set to a value. */ void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) { setResult(val); } /** Records an fp register being set to an integer value. */ - void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val, - int width) - { - setResult(val); - } - - /** Records an fp register being set to an integer value. */ - void setFloatRegOperandBits(const StaticInst *si, int idx, uint64_t val) + void setFloatRegOperandBits(const StaticInst *si, int idx, FloatRegBits val) { setResult(val); } @@ -802,10 +781,10 @@ bool isSquashedInROB() const { return status[SquashedInROB]; } /** Read the PC state of this instruction. */ - const TheISA::PCState pcState() const { return pc; } + TheISA::PCState pcState() const { return pc; } /** Set the PC state of this instruction. */ - const void pcState(const TheISA::PCState &val) { pc = val; } + void pcState(const TheISA::PCState &val) { pc = val; } /** Read the PC of this instruction. */ const Addr instAddr() const { return pc.instAddr(); } @@ -844,10 +823,10 @@ public: /** Sets the effective address. */ - void setEA(Addr &ea) { instEffAddr = ea; instFlags[EACalcDone] = true; } + void setEA(Addr ea) { instEffAddr = ea; instFlags[EACalcDone] = true; } /** Returns the effective address. */ - const Addr &getEA() const { return instEffAddr; } + Addr getEA() const { return instEffAddr; } /** Returns whether or not the eff. addr. calculation has been completed. */ bool doneEACalc() { return instFlags[EACalcDone]; } @@ -869,11 +848,11 @@ public: /** Returns the number of consecutive store conditional failures. */ - unsigned readStCondFailures() + unsigned int readStCondFailures() const { return thread->storeCondFailures; } /** Sets the number of consecutive store conditional failures. */ - void setStCondFailures(unsigned sc_failures) + void setStCondFailures(unsigned int sc_failures) { thread->storeCondFailures = sc_failures; } }; diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/checker/SConsopts --- a/src/cpu/checker/SConsopts Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/checker/SConsopts Tue Aug 19 10:33:34 2014 +0100 @@ -30,6 +30,4 @@ Import('*') -CpuModel('CheckerCPU', 'checker_cpu_exec.cc', - '#include "cpu/checker/cpu.hh"', - { 'CPU_exec_context': 'CheckerCPU' }) +CpuModel('CheckerCPU') diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/checker/cpu.hh --- a/src/cpu/checker/cpu.hh Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/checker/cpu.hh Tue Aug 19 10:33:34 2014 +0100 @@ -52,6 +52,7 @@ #include "base/statistics.hh" #include "cpu/base.hh" #include "cpu/base_dyn_inst.hh" +#include "cpu/exec_context.hh" #include "cpu/pc_event.hh" #include "cpu/simple_thread.hh" #include "cpu/static_inst.hh" @@ -86,7 +87,7 @@ * checker to be able to correctly verify instructions, even with * external accesses to the ThreadContext that change state. */ -class CheckerCPU : public BaseCPU +class CheckerCPU : public BaseCPU, public ExecContext { protected: typedef TheISA::MachInst MachInst; @@ -194,7 +195,7 @@ // These functions are only used in CPU models that split // effective address computation from the actual memory access. void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } - Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } + Addr getEA() const { panic("SimpleCPU::getEA() not implemented\n"); } // The register accessor methods provide the index of the // instruction's operand (e.g., 0 or 1), not the architectural @@ -207,7 +208,7 @@ // storage (which is pretty hard to imagine they would have reason // to do). - uint64_t readIntRegOperand(const StaticInst *si, int idx) + IntReg readIntRegOperand(const StaticInst *si, int idx) { return thread->readIntReg(si->srcRegIdx(idx)); } @@ -224,7 +225,7 @@ return thread->readFloatRegBits(reg_idx); } - uint64_t readCCRegOperand(const StaticInst *si, int idx) + CCReg readCCRegOperand(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::CC_Reg_Base; return thread->readCCReg(reg_idx); @@ -238,7 +239,7 @@ result.push(instRes); } - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) + void setIntRegOperand(const StaticInst *si, int idx, IntReg val) { thread->setIntReg(si->destRegIdx(idx), val); setResult(val); @@ -259,7 +260,7 @@ setResult(val); } - void setCCRegOperand(const StaticInst *si, int idx, uint64_t val) + void setCCRegOperand(const StaticInst *si, int idx, CCReg val) { int reg_idx = si->destRegIdx(idx) - TheISA::CC_Reg_Base; thread->setCCReg(reg_idx, val); @@ -272,7 +273,7 @@ thread->setPredicate(val); } - TheISA::PCState pcState() { return thread->pcState(); } + TheISA::PCState pcState() const { return thread->pcState(); } void pcState(const TheISA::PCState &val) { DPRINTF(Checker, "Changing PC to %s, old PC %s.\n", @@ -322,13 +323,13 @@ } #if THE_ISA == MIPS_ISA - uint64_t readRegOtherThread(int misc_reg) + MiscReg readRegOtherThread(int misc_reg, ThreadID tid) { panic("MIPS MT not defined for CheckerCPU.\n"); return 0; } - void setRegOtherThread(int misc_reg, const TheISA::MiscReg &val) + void setRegOtherThread(int misc_reg, MiscReg val, ThreadID tid) { panic("MIPS MT not defined for CheckerCPU.\n"); } @@ -362,7 +363,11 @@ Fault writeMem(uint8_t *data, unsigned size, Addr addr, unsigned flags, uint64_t *res); - void setStCondFailures(unsigned sc_failures) + unsigned int readStCondFailures() const { + return thread->readStCondFailures(); + } + + void setStCondFailures(unsigned int sc_failures) {} ///////////////////////////////////////////////////// @@ -371,7 +376,7 @@ void wakeup() { } // Assume that the normal CPU's call to syscall was successful. // The checker's state would have already been updated by the syscall. - void syscall(uint64_t callnum) { } + void syscall(int64_t callnum) { } void handleError() { diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/exec_context.hh --- a/src/cpu/exec_context.hh Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/exec_context.hh Tue Aug 19 10:33:34 2014 +0100 @@ -1,4 +1,16 @@ /* + * Copyright (c) 2014 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -26,104 +38,228 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Kevin Lim + * Andreas Sandberg */ -#error "Cannot include this file" +#ifndef __CPU_EXEC_CONTEXT_HH__ +#define __CPU_EXEC_CONTEXT_HH__ + +#include "arch/registers.hh" +#include "base/types.hh" +#include "config/the_isa.hh" +#include "cpu/static_inst_fwd.hh" +#include "cpu/translation.hh" +#include "sim/fault_fwd.hh" /** - * The ExecContext is not a usable class. It is simply here for - * documentation purposes. It shows the interface that is used by the - * ISA to access and change CPU state. + * The ExecContext is an abstract base class the provides the + * interface used by the ISA to manipulate the state of the CPU model. + * + * Register accessor methods in this class typically provide the index + * of the instruction's operand (e.g., 0 or 1), not the architectural + * register index, to simplify the implementation of register + * renaming. The architectural register index can be found by + * indexing into the instruction's own operand index table. + * + * @note The methods in this class typically take a raw pointer to the + * StaticInst is provided instead of a ref-counted StaticInstPtr to + * reduce overhead as an argument. This is fine as long as the + * implementation doesn't copy the pointer into any long-term storage + * (which is pretty hard to imagine they would have reason to do). */ class ExecContext { - // The register accessor methods provide the index of the - // instruction's operand (e.g., 0 or 1), not the architectural - // register index, to simplify the implementation of register - // renaming. We find the architectural register index by indexing - // into the instruction's own operand index table. Note that a - // raw pointer to the StaticInst is provided instead of a - // ref-counted StaticInstPtr to reduce overhead. This is fine as - // long as these methods don't copy the pointer into any long-term - // storage (which is pretty hard to imagine they would have reason - // to do). + public: + typedef TheISA::IntReg IntReg; + typedef TheISA::PCState PCState; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; + typedef TheISA::MiscReg MiscReg; + + typedef TheISA::CCReg CCReg; + + public: + /** + * @{ + * @name Integer Register Interfaces + * + */ /** Reads an integer register. */ - uint64_t readIntRegOperand(const StaticInst *si, int idx); + virtual IntReg readIntRegOperand(const StaticInst *si, int idx) = 0; + + /** Sets an integer register to a value. */ + virtual void setIntRegOperand(const StaticInst *si, + int idx, IntReg val) = 0; + + /** @} */ + + + /** + * @{ + * @name Floating Point Register Interfaces + */ /** Reads a floating point register of single register width. */ - FloatReg readFloatRegOperand(const StaticInst *si, int idx); + virtual FloatReg readFloatRegOperand(const StaticInst *si, int idx) = 0; /** Reads a floating point register in its binary format, instead * of by value. */ - FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx); - - /** Sets an integer register to a value. */ - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val); + virtual FloatRegBits readFloatRegOperandBits(const StaticInst *si, + int idx) = 0; /** Sets a floating point register of single width to a value. */ - void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val); + virtual void setFloatRegOperand(const StaticInst *si, + int idx, FloatReg val) = 0; /** Sets the bits of a floating point register of single width * to a binary value. */ - void setFloatRegOperandBits(const StaticInst *si, int idx, - FloatRegBits val); + virtual void setFloatRegOperandBits(const StaticInst *si, + int idx, FloatRegBits val) = 0; - /** Reads the PC. */ - uint64_t readPC(); - /** Reads the NextPC. */ - uint64_t readNextPC(); - /** Reads the Next-NextPC. Only for architectures like SPARC or MIPS. */ - uint64_t readNextNPC(); + /** @} */ - /** Sets the PC. */ - void setPC(uint64_t val); - /** Sets the NextPC. */ - void setNextPC(uint64_t val); - /** Sets the Next-NextPC. Only for architectures like SPARC or MIPS. */ - void setNextNPC(uint64_t val); + /** + * @{ + * @name Condition Code Registers + */ + virtual CCReg readCCRegOperand(const StaticInst *si, int idx) = 0; + virtual void setCCRegOperand(const StaticInst *si, int idx, CCReg val) = 0; + /** @} */ - /** Reads a miscellaneous register. */ - MiscReg readMiscRegNoEffect(int misc_reg); + /** + * @{ + * @name Misc Register Interfaces + */ + virtual MiscReg readMiscRegOperand(const StaticInst *si, int idx) = 0; + virtual void setMiscRegOperand(const StaticInst *si, + int idx, const MiscReg &val) = 0; - /** Reads a miscellaneous register, handling any architectural - * side effects due to reading that register. */ - MiscReg readMiscReg(int misc_reg); + /** + * Reads a miscellaneous register, handling any architectural + * side effects due to reading that register. + */ + virtual MiscReg readMiscReg(int misc_reg) = 0; - /** Sets a miscellaneous register. */ - void setMiscRegNoEffect(int misc_reg, const MiscReg &val); + /** + * Sets a miscellaneous register, handling any architectural + * side effects due to writing that register. + */ + virtual void setMiscReg(int misc_reg, const MiscReg &val) = 0; - /** Sets a miscellaneous register, handling any architectural - * side effects due to writing that register. */ - void setMiscReg(int misc_reg, const MiscReg &val); + /** @} */ - /** Records the effective address of the instruction. Only valid - * for memory ops. */ - void setEA(Addr EA); - /** Returns the effective address of the instruction. Only valid - * for memory ops. */ - Addr getEA(); + /** + * @{ + * @name PC Control + */ + virtual PCState pcState() const = 0; + virtual void pcState(const PCState &val) = 0; + /** @} */ + + /** + * @{ + * @name Memory Interface + */ + /** + * Record the effective address of the instruction. + * + * @note Only valid for memory ops. + */ + virtual void setEA(Addr EA) = 0; + /** + * Get the effective address of the instruction. + * + * @note Only valid for memory ops. + */ + virtual Addr getEA() const = 0; + + virtual Fault readMem(Addr addr, uint8_t *data, unsigned int size, + unsigned int flags) = 0; + + virtual Fault writeMem(uint8_t *data, unsigned int size, Addr addr, + unsigned int flags, uint64_t *res) = 0; + + /** + * Sets the number of consecutive store conditional failures. + */ + virtual void setStCondFailures(unsigned int sc_failures) = 0; + + /** + * Returns the number of consecutive store conditional failures. + */ + virtual unsigned int readStCondFailures() const = 0; + + /** @} */ + + /** + * @{ + * @name SysCall Emulation Interfaces + */ + + /** + * Executes a syscall specified by the callnum. + */ + virtual void syscall(int64_t callnum) = 0; + + /** @} */ /** Returns a pointer to the ThreadContext. */ - ThreadContext *tcBase(); + virtual ThreadContext *tcBase() = 0; - Fault readMem(Addr addr, uint8_t *data, unsigned size, unsigned flags); + /** + * @{ + * @name Alpha-Specific Interfaces + */ - Fault writeMem(uint8_t *data, unsigned size, - Addr addr, unsigned flags, uint64_t *res); - - /** Somewhat Alpha-specific function that handles returning from - * an error or interrupt. */ - Fault hwrei(); + /** + * Somewhat Alpha-specific function that handles returning from an + * error or interrupt. + */ + virtual Fault hwrei() = 0; /** * Check for special simulator handling of specific PAL calls. If * return value is false, actual PAL call will be suppressed. */ - bool simPalCheck(int palFunc); + virtual bool simPalCheck(int palFunc) = 0; - /** Executes a syscall specified by the callnum. */ - void syscall(int64_t callnum); + /** @} */ - /** Finish a DTB address translation. */ - void finishTranslation(WholeTranslationState *state); + /** + * @{ + * @name ARM-Specific Interfaces + */ + + virtual bool readPredicate() = 0; + virtual void setPredicate(bool val) = 0; + + /** @} */ + + /** + * @{ + * @name X86-Specific Interfaces + */ + + /** + * Invalidate a page in the DTLB and ITLB. + */ + virtual void demapPage(Addr vaddr, uint64_t asn) = 0; + + /** @} */ + + /** + * @{ + * @name MIPS-Specific Interfaces + */ + +#if THE_ISA == MIPS_ISA + virtual MiscReg readRegOtherThread(int regIdx, + ThreadID tid = InvalidThreadID) = 0; + virtual void setRegOtherThread(int regIdx, MiscReg val, + ThreadID tid = InvalidThreadID) = 0; +#endif + + /** @} */ }; + +#endif // __CPU_EXEC_CONTEXT_HH__ diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/exec_context.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/exec_context.cc Tue Aug 19 10:33:34 2014 +0100 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Andreas Sandberg + */ + +#include "cpu/exec_context.hh" diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/inorder/SConsopts --- a/src/cpu/inorder/SConsopts Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/inorder/SConsopts Tue Aug 19 10:33:34 2014 +0100 @@ -30,7 +30,4 @@ Import('*') -CpuModel('InOrderCPU', 'inorder_cpu_exec.cc', - '#include "cpu/inorder/inorder_dyn_inst.hh"', - { 'CPU_exec_context': 'InOrderDynInst' }, - default=True) +CpuModel('InOrderCPU', default=True) diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/inorder/inorder_dyn_inst.hh --- a/src/cpu/inorder/inorder_dyn_inst.hh Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/inorder/inorder_dyn_inst.hh Tue Aug 19 10:33:34 2014 +0100 @@ -45,6 +45,7 @@ #include "base/trace.hh" #include "base/types.hh" #include "config/the_isa.hh" +#include "cpu/exec_context.hh" #include "cpu/inorder/inorder_trace.hh" #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/resource.hh" @@ -73,7 +74,7 @@ class ResourceRequest; class Packet; -class InOrderDynInst : public RefCounted +class InOrderDynInst : public ExecContext, public RefCounted { public: // Binary machine instruction type. @@ -543,7 +544,7 @@ // //////////////////////////////////////////////////////////// /** Read the PC of this instruction. */ - const TheISA::PCState &pcState() const { return pc; } + TheISA::PCState pcState() const { return pc; } /** Sets the PC of this instruction. */ void pcState(const TheISA::PCState &_pc) { pc = _pc; } @@ -649,10 +650,10 @@ { return memAddr; } /** Sets the effective address. */ - void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; } + void setEA(Addr ea) { instEffAddr = ea; eaCalcDone = true; } /** Returns the effective address. */ - const Addr &getEA() const { return instEffAddr; } + Addr getEA() const { return instEffAddr; } /** Returns whether or not the eff. addr. calculation has been completed.*/ bool doneEACalc() { return eaCalcDone; } @@ -854,7 +855,10 @@ * language (which is why the name isnt readIntSrc(...)) Note: That * the source reg. value is set using the setSrcReg() function. */ - IntReg readIntRegOperand(const StaticInst *si, int idx, ThreadID tid = 0); + IntReg readIntRegOperand(const StaticInst *si, int idx, ThreadID tid); + IntReg readIntRegOperand(const StaticInst *si, int idx) { + return readIntRegOperand(si, idx, 0); + } FloatReg readFloatRegOperand(const StaticInst *si, int idx); TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx); MiscReg readMiscReg(int misc_reg); @@ -899,24 +903,21 @@ void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val); void setFloatRegOperandBits(const StaticInst *si, int idx, TheISA::FloatRegBits val); - void setCCRegOperand(const StaticInst *si, int idx, CCReg val); void setMiscReg(int misc_reg, const MiscReg &val); void setMiscRegNoEffect(int misc_reg, const MiscReg &val); void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val); void setMiscRegOperandNoEffect(const StaticInst *si, int idx, const MiscReg &val); - virtual uint64_t readRegOtherThread(unsigned idx, - ThreadID tid = InvalidThreadID); - virtual void setRegOtherThread(unsigned idx, const uint64_t &val, - ThreadID tid = InvalidThreadID); + MiscReg readRegOtherThread(int idx, ThreadID tid); + void setRegOtherThread(int idx, MiscReg val, ThreadID tid); /** Returns the number of consecutive store conditional failures. */ - unsigned readStCondFailures() + unsigned int readStCondFailures() const { return thread->storeCondFailures; } /** Sets the number of consecutive store conditional failures. */ - void setStCondFailures(unsigned sc_failures) + void setStCondFailures(unsigned int sc_failures) { thread->storeCondFailures = sc_failures; } ////////////////////////////////////////////////////////////// @@ -1063,6 +1064,27 @@ void dump(std::string &outstring); //inline int curCount() { return curCount(); } + + + CCReg readCCRegOperand(const StaticInst *si, int idx) { + panic("readCCRegOperand unimplemented"); + } + + void setCCRegOperand(const StaticInst *si, int idx, CCReg val) { + panic("setCCRegOperand unimplemented"); + } + + void setPredicate(bool val) { + panic("setPredicate unimplemented"); + } + + bool readPredicate() { + panic("readPredicate unimplemented"); + } + + void demapPage(Addr vaddr, uint64_t asn) { + panic("demapPage unimplemented"); + } }; diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/inorder/inorder_dyn_inst.cc --- a/src/cpu/inorder/inorder_dyn_inst.cc Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/inorder/inorder_dyn_inst.cc Tue Aug 19 10:33:34 2014 +0100 @@ -469,7 +469,7 @@ } MiscReg -InOrderDynInst::readRegOtherThread(unsigned reg_idx, ThreadID tid) +InOrderDynInst::readRegOtherThread(int reg_idx, ThreadID tid) { if (tid == -1) { tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber)); @@ -544,8 +544,7 @@ } void -InOrderDynInst::setRegOtherThread(unsigned reg_idx, const MiscReg &val, - ThreadID tid) +InOrderDynInst::setRegOtherThread(int reg_idx, MiscReg val, ThreadID tid) { if (tid == InvalidThreadID) { tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber)); diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/minor/SConsopts --- a/src/cpu/minor/SConsopts Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/minor/SConsopts Tue Aug 19 10:33:34 2014 +0100 @@ -39,7 +39,4 @@ Import('*') -CpuModel('MinorCPU', 'minor_cpu_exec.cc', - '#include "cpu/minor/exec_context.hh"', - { 'CPU_exec_context': 'Minor::ExecContext' }, - default=True) +CpuModel('MinorCPU', default=True) diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/minor/exec_context.hh --- a/src/cpu/minor/exec_context.hh Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/minor/exec_context.hh Tue Aug 19 10:33:34 2014 +0100 @@ -53,6 +53,7 @@ #ifndef __CPU_MINOR_EXEC_CONTEXT_HH__ #define __CPU_MINOR_EXEC_CONTEXT_HH__ +#include "cpu/exec_context.hh" #include "cpu/minor/execute.hh" #include "cpu/minor/pipeline.hh" #include "cpu/base.hh" @@ -69,7 +70,7 @@ * separates that interface from other classes such as Pipeline, MinorCPU * and DynMinorInst and makes it easier to see what state is accessed by it. */ -class ExecContext +class ExecContext : public ::ExecContext { public: MinorCPU &cpu; @@ -119,7 +120,7 @@ return NoFault; } - uint64_t + IntReg readIntRegOperand(const StaticInst *si, int idx) { return thread.readIntReg(si->srcRegIdx(idx)); @@ -140,7 +141,7 @@ } void - setIntRegOperand(const StaticInst *si, int idx, uint64_t val) + setIntRegOperand(const StaticInst *si, int idx, IntReg val) { thread.setIntReg(si->destRegIdx(idx), val); } @@ -174,7 +175,7 @@ } TheISA::PCState - pcState() + pcState() const { return thread.pcState(); } @@ -250,12 +251,8 @@ ThreadContext *tcBase() { return thread.getTC(); } /* @todo, should make stCondFailures persistent somewhere */ - unsigned int readStCondFailures() { return 0; } - unsigned int - setStCondFailures(unsigned int st_cond_failures) - { - return 0; - } + unsigned int readStCondFailures() const { return 0; } + void setStCondFailures(unsigned int st_cond_failures) {} int contextId() { return thread.contextId(); } /* ISA-specific (or at least currently ISA singleton) functions */ @@ -295,7 +292,7 @@ } /* ALPHA/POWER: Effective address storage */ - void setEA(Addr &ea) + void setEA(Addr ea) { inst->ea = ea; } @@ -303,14 +300,14 @@ BaseCPU *getCpuPtr() { return &cpu; } /* POWER: Effective address storage */ - Addr getEA() + Addr getEA() const { return inst->ea; } /* MIPS: other thread register reading/writing */ uint64_t - readRegOtherThread(unsigned idx, ThreadID tid = InvalidThreadID) + readRegOtherThread(int idx, ThreadID tid = InvalidThreadID) { SimpleThread *other_thread = (tid == InvalidThreadID ? &thread : cpu.threads[tid]); @@ -327,7 +324,7 @@ } void - setRegOtherThread(unsigned idx, const TheISA::MiscReg &val, + setRegOtherThread(int idx, const TheISA::MiscReg &val, ThreadID tid = InvalidThreadID) { SimpleThread *other_thread = (tid == InvalidThreadID diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/nocpu/SConsopts --- a/src/cpu/nocpu/SConsopts Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/nocpu/SConsopts Tue Aug 19 10:33:34 2014 +0100 @@ -1,4 +1,4 @@ Import('*') -CpuModel('no', '', '', { '': '' }) +CpuModel('no') diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/o3/SConsopts --- a/src/cpu/o3/SConsopts Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/o3/SConsopts Tue Aug 19 10:33:34 2014 +0100 @@ -30,7 +30,4 @@ Import('*') -CpuModel('O3CPU', 'o3_cpu_exec.cc', - '#include "cpu/o3/isa_specific.hh"', - { 'CPU_exec_context': 'O3DynInst' }, - default=True) +CpuModel('O3CPU', default=True) diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/o3/dyn_inst.hh --- a/src/cpu/o3/dyn_inst.hh Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/o3/dyn_inst.hh Tue Aug 19 10:33:34 2014 +0100 @@ -71,9 +71,8 @@ typedef TheISA::IntReg IntReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; -#ifdef ISA_HAS_CC_REGS typedef TheISA::CCReg CCReg; -#endif + /** Misc register index type. */ typedef TheISA::MiscReg MiscReg; @@ -250,7 +249,7 @@ // storage (which is pretty hard to imagine they would have reason // to do). - uint64_t readIntRegOperand(const StaticInst *si, int idx) + IntReg readIntRegOperand(const StaticInst *si, int idx) { return this->cpu->readIntReg(this->_srcRegIdx[idx]); } @@ -265,7 +264,7 @@ return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]); } - uint64_t readCCRegOperand(const StaticInst *si, int idx) + CCReg readCCRegOperand(const StaticInst *si, int idx) { return this->cpu->readCCReg(this->_srcRegIdx[idx]); } @@ -273,7 +272,7 @@ /** @todo: Make results into arrays so they can handle multiple dest * registers. */ - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) + void setIntRegOperand(const StaticInst *si, int idx, IntReg val) { this->cpu->setIntReg(this->_destRegIdx[idx], val); BaseDynInst::setIntRegOperand(si, idx, val); @@ -292,20 +291,20 @@ BaseDynInst::setFloatRegOperandBits(si, idx, val); } - void setCCRegOperand(const StaticInst *si, int idx, uint64_t val) + void setCCRegOperand(const StaticInst *si, int idx, CCReg val) { this->cpu->setCCReg(this->_destRegIdx[idx], val); BaseDynInst::setCCRegOperand(si, idx, val); } #if THE_ISA == MIPS_ISA - uint64_t readRegOtherThread(int misc_reg) + MiscReg readRegOtherThread(int misc_reg, ThreadID tid) { panic("MIPS MT not defined for O3 CPU.\n"); return 0; } - void setRegOtherThread(int misc_reg, const TheISA::MiscReg &val) + void setRegOtherThread(int misc_reg, MiscReg val, ThreadID tid) { panic("MIPS MT not defined for O3 CPU.\n"); } diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/ozone/SConsopts --- a/src/cpu/ozone/SConsopts Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/ozone/SConsopts Tue Aug 19 10:33:34 2014 +0100 @@ -30,10 +30,6 @@ Import('*') -CpuModel('OzoneSimpleCPU', 'ozone_simple_exec.cc', - '#include "cpu/ozone/dyn_inst.hh"', - { 'CPU_exec_context': 'OzoneDynInst' }) -CpuModel('OzoneCPU', 'ozone_exec.cc', - '#include "cpu/ozone/dyn_inst.hh"', - { 'CPU_exec_context': 'OzoneDynInst' }) +CpuModel('OzoneSimpleCPU') +CpuModel('OzoneCPU') diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/simple/SConsopts --- a/src/cpu/simple/SConsopts Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/simple/SConsopts Tue Aug 19 10:33:34 2014 +0100 @@ -30,11 +30,5 @@ Import('*') -CpuModel('AtomicSimpleCPU', 'atomic_simple_cpu_exec.cc', - '#include "cpu/simple/atomic.hh"', - { 'CPU_exec_context': 'AtomicSimpleCPU' }, - default=True) -CpuModel('TimingSimpleCPU', 'timing_simple_cpu_exec.cc', - '#include "cpu/simple/timing.hh"', - { 'CPU_exec_context': 'TimingSimpleCPU' }, - default=True) +CpuModel('AtomicSimpleCPU', default=True) +CpuModel('TimingSimpleCPU', default=True) diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/simple/base.hh --- a/src/cpu/simple/base.hh Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/simple/base.hh Tue Aug 19 10:33:34 2014 +0100 @@ -50,6 +50,7 @@ #include "config/the_isa.hh" #include "cpu/base.hh" #include "cpu/checker/cpu.hh" +#include "cpu/exec_context.hh" #include "cpu/pc_event.hh" #include "cpu/simple_thread.hh" #include "cpu/static_inst.hh" @@ -79,7 +80,7 @@ struct BaseSimpleCPUParams; class BPredUnit; -class BaseSimpleCPU : public BaseCPU +class BaseSimpleCPU : public BaseCPU, public ExecContext { protected: typedef TheISA::MiscReg MiscReg; @@ -293,8 +294,7 @@ // These functions are only used in CPU models that split // effective address computation from the actual memory access. void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); } - Addr getEA() { panic("BaseSimpleCPU::getEA() not implemented\n"); - M5_DUMMY_RETURN} + Addr getEA() const { panic("BaseSimpleCPU::getEA() not implemented\n"); } // The register accessor methods provide the index of the // instruction's operand (e.g., 0 or 1), not the architectural @@ -307,7 +307,7 @@ // storage (which is pretty hard to imagine they would have reason // to do). - uint64_t readIntRegOperand(const StaticInst *si, int idx) + IntReg readIntRegOperand(const StaticInst *si, int idx) { numIntRegReads++; return thread->readIntReg(si->srcRegIdx(idx)); @@ -334,7 +334,7 @@ return thread->readCCReg(reg_idx); } - void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) + void setIntRegOperand(const StaticInst *si, int idx, IntReg val) { numIntRegWrites++; thread->setIntReg(si->destRegIdx(idx), val); @@ -370,7 +370,7 @@ traceData->setPredicate(val); } } - TheISA::PCState pcState() { return thread->pcState(); } + TheISA::PCState pcState() const { return thread->pcState(); } void pcState(const TheISA::PCState &val) { thread->pcState(val); } Addr instAddr() { return thread->instAddr(); } Addr nextInstAddr() { return thread->nextInstAddr(); } @@ -423,26 +423,26 @@ thread->demapDataPage(vaddr, asn); } - unsigned readStCondFailures() { + unsigned int readStCondFailures() const { return thread->readStCondFailures(); } - void setStCondFailures(unsigned sc_failures) { + void setStCondFailures(unsigned int sc_failures) { thread->setStCondFailures(sc_failures); } - MiscReg readRegOtherThread(int regIdx, ThreadID tid = InvalidThreadID) - { + MiscReg readRegOtherThread(int regIdx, ThreadID tid = InvalidThreadID) + { panic("Simple CPU models do not support multithreaded " "register access.\n"); - } + } - void setRegOtherThread(int regIdx, const MiscReg &val, - ThreadID tid = InvalidThreadID) - { + void setRegOtherThread(int regIdx, MiscReg val, + ThreadID tid = InvalidThreadID) + { panic("Simple CPU models do not support multithreaded " "register access.\n"); - } + } //Fault CacheOp(uint8_t Op, Addr EA); diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/simple_thread.cc --- a/src/cpu/simple_thread.cc Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/simple_thread.cc Tue Aug 19 10:33:34 2014 +0100 @@ -50,6 +50,7 @@ #include "mem/fs_translating_port_proxy.hh" #include "mem/se_translating_port_proxy.hh" #include "params/BaseCPU.hh" +#include "sim/faults.hh" #include "sim/full_system.hh" #include "sim/process.hh" #include "sim/serialize.hh" @@ -213,3 +214,18 @@ TheISA::copyRegs(src_tc, tc); } +// The following methods are defined in src/arch/alpha/ev5.cc for +// Alpha. +#if THE_ISA != ALPHA_ISA +Fault +SimpleThread::hwrei() +{ + return NoFault; +} + +bool +SimpleThread::simPalCheck(int palFunc) +{ + return true; +} +#endif diff -r b7e2c396b242 -r 523ac80e06ae src/cpu/static_inst.hh --- a/src/cpu/static_inst.hh Tue Aug 19 10:33:32 2014 +0100 +++ b/src/cpu/static_inst.hh Tue Aug 19 10:33:34 2014 +0100 @@ -50,19 +50,7 @@ // forward declarations class Packet; -struct O3CPUImpl; -template class BaseO3DynInst; -typedef BaseO3DynInst O3DynInst; -class InOrderDynInst; - -class CheckerCPU; -class AtomicSimpleCPU; -class TimingSimpleCPU; -class InorderCPU; -namespace Minor -{ - class ExecContext; -}; +class ExecContext; class SymbolTable; @@ -267,11 +255,25 @@ public: virtual ~StaticInst(); -/** - * 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" + virtual Fault execute(ExecContext *xc, + Trace::InstRecord *traceData) const = 0; + virtual Fault eaComp(ExecContext *xc, + Trace::InstRecord *traceData) const + { + panic("eaComp not defined!"); + } + + virtual Fault initiateAcc(ExecContext *xc, + Trace::InstRecord *traceData) const + { + panic("initiateAcc not defined!"); + } + + virtual Fault completeAcc(Packet *pkt, ExecContext *xc, + Trace::InstRecord *traceData) const + { + panic("completeAcc not defined!"); + } virtual void advancePC(TheISA::PCState &pcState) const = 0;