diff --git a/SConstruct b/SConstruct index 6250bdd2f..9a64840fc 100755 --- a/SConstruct +++ b/SConstruct @@ -1025,17 +1025,10 @@ class CpuModel(object): # 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 @@ class CpuModel(object): 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 @@ sticky_vars.AddVariables( 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 --git a/src/arch/SConscript b/src/arch/SConscript index e9b5c5365..31ea0b78f 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -95,13 +95,11 @@ isa_parser = File('isa_parser.py') # 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 @@ def isa_desc_action_func(target, source, env): # 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 --git a/src/arch/arm/isa/includes.isa b/src/arch/arm/isa/includes.isa index a2ce84345..7328e5307 100644 --- a/src/arch/arm/isa/includes.isa +++ b/src/arch/arm/isa/includes.isa @@ -90,6 +90,7 @@ output exec {{ #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 --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index 6aa553588..adadbe14d 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -1178,13 +1178,25 @@ class Stack(list): # 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 = {} @@ -2376,8 +2388,6 @@ StaticInstPtr 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 --git a/src/cpu/SConscript b/src/cpu/SConscript index 1ea92114a..5d9a48716 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -35,71 +35,8 @@ if env['TARGET_ISA'] == 'null': 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('activity.cc') 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 --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 08e16d330..9346b69cc 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -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 @@ class BaseDynInst : public RefCounted // 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,28 +631,17 @@ class BaseDynInst : public RefCounted } /** 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) { @@ -663,14 +649,7 @@ class BaseDynInst : public RefCounted } /** 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 @@ class BaseDynInst : public RefCounted 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 @@ class BaseDynInst : public RefCounted 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 @@ class BaseDynInst : public RefCounted 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 --git a/src/cpu/checker/SConsopts b/src/cpu/checker/SConsopts index 94d8e0e9f..5d676ba1b 100644 --- a/src/cpu/checker/SConsopts +++ b/src/cpu/checker/SConsopts @@ -30,6 +30,4 @@ Import('*') -CpuModel('CheckerCPU', 'checker_cpu_exec.cc', - '#include "cpu/checker/cpu.hh"', - { 'CPU_exec_context': 'CheckerCPU' }) +CpuModel('CheckerCPU') diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 9f4c4d58c..bf71dc30e 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -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 @@ class Request; * 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 @@ class CheckerCPU : public BaseCPU // 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 @@ class CheckerCPU : public BaseCPU // 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 @@ class CheckerCPU : public BaseCPU 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 @@ class CheckerCPU : public BaseCPU 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 @@ class CheckerCPU : public BaseCPU 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 @@ class CheckerCPU : public BaseCPU 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 @@ class CheckerCPU : public BaseCPU } #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 @@ class CheckerCPU : public BaseCPU 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 @@ class CheckerCPU : public BaseCPU 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 --git a/src/cpu/exec_context.cc b/src/cpu/exec_context.cc new file mode 100644 index 000000000..0dde0dc71 --- /dev/null +++ b/src/cpu/exec_context.cc @@ -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 --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh index 2f4d26976..c93f7f32b 100644 --- a/src/cpu/exec_context.hh +++ b/src/cpu/exec_context.hh @@ -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 --git a/src/cpu/inorder/SConsopts b/src/cpu/inorder/SConsopts index 709051407..f6b8917c6 100644 --- a/src/cpu/inorder/SConsopts +++ b/src/cpu/inorder/SConsopts @@ -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 --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index 86dbdf97c..d0d308f7a 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -469,7 +469,7 @@ InOrderDynInst::setMiscRegOperand(const StaticInst *si, int idx, } 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 @@ InOrderDynInst::setMiscReg(int misc_reg, const MiscReg &val) } 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 --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh index 578fd604a..759da4b04 100644 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -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 @@ class InOrderDynInst : public RefCounted // //////////////////////////////////////////////////////////// /** 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 @@ class InOrderDynInst : public RefCounted { 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 @@ class InOrderDynInst : public RefCounted * 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 @@ class InOrderDynInst : public RefCounted 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 @@ class InOrderDynInst : public RefCounted 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 --git a/src/cpu/minor/SConsopts b/src/cpu/minor/SConsopts index 68c420779..b74e15730 100644 --- a/src/cpu/minor/SConsopts +++ b/src/cpu/minor/SConsopts @@ -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 --git a/src/cpu/minor/exec_context.hh b/src/cpu/minor/exec_context.hh index df909a95c..f1143498e 100644 --- a/src/cpu/minor/exec_context.hh +++ b/src/cpu/minor/exec_context.hh @@ -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 @@ class Execute; * 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 @@ class ExecContext return NoFault; } - uint64_t + IntReg readIntRegOperand(const StaticInst *si, int idx) { return thread.readIntReg(si->srcRegIdx(idx)); @@ -140,7 +141,7 @@ class ExecContext } 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 @@ class ExecContext } TheISA::PCState - pcState() + pcState() const { return thread.pcState(); } @@ -250,12 +251,8 @@ class ExecContext 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 @@ class ExecContext } /* ALPHA/POWER: Effective address storage */ - void setEA(Addr &ea) + void setEA(Addr ea) { inst->ea = ea; } @@ -303,14 +300,14 @@ class ExecContext 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 @@ class ExecContext } void - setRegOtherThread(unsigned idx, const TheISA::MiscReg &val, + setRegOtherThread(int idx, const TheISA::MiscReg &val, ThreadID tid = InvalidThreadID) { SimpleThread *other_thread = (tid == InvalidThreadID diff --git a/src/cpu/nocpu/SConsopts b/src/cpu/nocpu/SConsopts index 0baef0a82..40bf503ea 100644 --- a/src/cpu/nocpu/SConsopts +++ b/src/cpu/nocpu/SConsopts @@ -1,4 +1,4 @@ Import('*') -CpuModel('no', '', '', { '': '' }) +CpuModel('no') diff --git a/src/cpu/o3/SConsopts b/src/cpu/o3/SConsopts index b780f6b2a..dfee888e5 100644 --- a/src/cpu/o3/SConsopts +++ b/src/cpu/o3/SConsopts @@ -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 --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 76bd8b291..52ea1101a 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -71,9 +71,8 @@ class BaseO3DynInst : public BaseDynInst 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 @@ class BaseO3DynInst : public BaseDynInst // 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 @@ class BaseO3DynInst : public BaseDynInst 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 @@ class BaseO3DynInst : public BaseDynInst /** @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 @@ class BaseO3DynInst : public BaseDynInst 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 --git a/src/cpu/ozone/SConsopts b/src/cpu/ozone/SConsopts index adfda63a9..c1ee00ec3 100644 --- a/src/cpu/ozone/SConsopts +++ b/src/cpu/ozone/SConsopts @@ -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 --git a/src/cpu/simple/SConsopts b/src/cpu/simple/SConsopts index ab84144af..9c99a818f 100644 --- a/src/cpu/simple/SConsopts +++ b/src/cpu/simple/SConsopts @@ -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 --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 47034c300..3755a94a9 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -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 @@ namespace Trace { struct BaseSimpleCPUParams; class BPredUnit; -class BaseSimpleCPU : public BaseCPU +class BaseSimpleCPU : public BaseCPU, public ExecContext { protected: typedef TheISA::MiscReg MiscReg; @@ -293,8 +294,7 @@ class BaseSimpleCPU : public BaseCPU // 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 @@ class BaseSimpleCPU : public BaseCPU // 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 @@ class BaseSimpleCPU : public BaseCPU 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 @@ class BaseSimpleCPU : public BaseCPU 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 @@ class BaseSimpleCPU : public BaseCPU 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 --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index de01124e0..4e2e70e63 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -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 @@ SimpleThread::copyArchRegs(ThreadContext *src_tc) 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 --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 375b7d0ba..c4dd3a6b5 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -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 @@ class StaticInst : public RefCounted, public StaticInstFlags 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;