arch, cpu: Factor out the ExecContext into a proper base class

We currently generate and compile one version of the ISA code per CPU
model. This is obviously wasting a lot of resources at compile
time. This changeset factors out the interface into a separate
ExecContext class, which also serves as documentation for the
interface between CPUs and the ISA code. While doing so, this
changeset also fixes up interface inconsistencies between the
different CPU models.

The main argument for using one set of ISA code per CPU model has
always been performance as this avoid indirect branches in the
generated code. However, this argument does not hold water. Booting
Linux on a simulated ARM system running in atomic mode
(opt/10.linux-boot/realview-simple-atomic) is actually 2% faster
(compiled using clang 3.4) after applying this patch. Additionally,
compilation time is decreased by 35%.
This commit is contained in:
Andreas Sandberg 2014-09-03 07:42:22 -04:00
parent e1ac962939
commit 326662b01b
23 changed files with 406 additions and 294 deletions

View file

@ -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',

View file

@ -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))

View file

@ -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 <fenv.h>

View file

@ -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: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
# Args are: <isa desc file> <output dir>
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])

View file

@ -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')

View file

@ -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 Impl>
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<uint64_t>(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<uint64_t>(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<double>(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<uint64_t>(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<uint64_t>(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; }
};

View file

@ -30,6 +30,4 @@
Import('*')
CpuModel('CheckerCPU', 'checker_cpu_exec.cc',
'#include "cpu/checker/cpu.hh"',
{ 'CPU_exec_context': 'CheckerCPU' })
CpuModel('CheckerCPU')

View file

@ -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<uint64_t>(val);
@ -259,7 +260,7 @@ class CheckerCPU : public BaseCPU
setResult<uint64_t>(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()
{

40
src/cpu/exec_context.cc Normal file
View file

@ -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"

View file

@ -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 <i>and</i> 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__

View file

@ -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)

View file

@ -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));

View file

@ -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");
}
};

View file

@ -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)

View file

@ -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

View file

@ -1,4 +1,4 @@
Import('*')
CpuModel('no', '', '', { '': '' })
CpuModel('no')

View file

@ -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)

View file

@ -71,9 +71,8 @@ class BaseO3DynInst : public BaseDynInst<Impl>
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<Impl>
// 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<Impl>
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<Impl>
/** @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<Impl>::setIntRegOperand(si, idx, val);
@ -292,20 +291,20 @@ class BaseO3DynInst : public BaseDynInst<Impl>
BaseDynInst<Impl>::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<Impl>::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");
}

View file

@ -30,10 +30,6 @@
Import('*')
CpuModel('OzoneSimpleCPU', 'ozone_simple_exec.cc',
'#include "cpu/ozone/dyn_inst.hh"',
{ 'CPU_exec_context': 'OzoneDynInst<SimpleImpl>' })
CpuModel('OzoneCPU', 'ozone_exec.cc',
'#include "cpu/ozone/dyn_inst.hh"',
{ 'CPU_exec_context': 'OzoneDynInst<OzoneImpl>' })
CpuModel('OzoneSimpleCPU')
CpuModel('OzoneCPU')

View file

@ -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)

View file

@ -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);

View file

@ -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

View file

@ -50,19 +50,7 @@
// forward declarations
class Packet;
struct O3CPUImpl;
template <class Impl> class BaseO3DynInst;
typedef BaseO3DynInst<O3CPUImpl> 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;