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:
parent
e1ac962939
commit
326662b01b
23 changed files with 406 additions and 294 deletions
12
SConstruct
12
SConstruct
|
@ -1025,17 +1025,10 @@ class CpuModel(object):
|
||||||
|
|
||||||
# Dict of available CPU model objects. Accessible as CpuModel.dict.
|
# Dict of available CPU model objects. Accessible as CpuModel.dict.
|
||||||
dict = {}
|
dict = {}
|
||||||
list = []
|
|
||||||
defaults = []
|
|
||||||
|
|
||||||
# Constructor. Automatically adds models to CpuModel.dict.
|
# 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.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
|
# This cpu is enabled by default
|
||||||
self.default = default
|
self.default = default
|
||||||
|
@ -1044,7 +1037,6 @@ class CpuModel(object):
|
||||||
if name in CpuModel.dict:
|
if name in CpuModel.dict:
|
||||||
raise AttributeError, "CpuModel '%s' already registered" % name
|
raise AttributeError, "CpuModel '%s' already registered" % name
|
||||||
CpuModel.dict[name] = self
|
CpuModel.dict[name] = self
|
||||||
CpuModel.list.append(name)
|
|
||||||
|
|
||||||
Export('CpuModel')
|
Export('CpuModel')
|
||||||
|
|
||||||
|
@ -1086,7 +1078,7 @@ sticky_vars.AddVariables(
|
||||||
EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
|
EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
|
||||||
ListVariable('CPU_MODELS', 'CPU models',
|
ListVariable('CPU_MODELS', 'CPU models',
|
||||||
sorted(n for n,m in CpuModel.dict.iteritems() if m.default),
|
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',
|
BoolVariable('EFENCE', 'Link with Electric Fence malloc debugger',
|
||||||
False),
|
False),
|
||||||
BoolVariable('SS_COMPATIBLE_FP',
|
BoolVariable('SS_COMPATIBLE_FP',
|
||||||
|
|
|
@ -95,13 +95,11 @@ isa_parser = File('isa_parser.py')
|
||||||
# The emitter patches up the sources & targets to include the
|
# The emitter patches up the sources & targets to include the
|
||||||
# autogenerated files as targets and isa parser itself as a source.
|
# autogenerated files as targets and isa parser itself as a source.
|
||||||
def isa_desc_emitter(target, source, env):
|
def isa_desc_emitter(target, source, env):
|
||||||
cpu_models = list(env['CPU_MODELS'])
|
|
||||||
cpu_models.append('CheckerCPU')
|
|
||||||
|
|
||||||
# List the isa parser as a source.
|
# List the isa parser as a source.
|
||||||
source += [ isa_parser ]
|
source += [
|
||||||
# Add in the CPU models.
|
isa_parser,
|
||||||
source += [ Value(m) for m in cpu_models ]
|
Value("ExecContext"),
|
||||||
|
]
|
||||||
|
|
||||||
# Specify different targets depending on if we're running the ISA
|
# Specify different targets depending on if we're running the ISA
|
||||||
# parser for its dependency information, or for the generated files.
|
# 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.
|
# Skip over the ISA description itself and the parser to the CPU models.
|
||||||
models = [ s.get_contents() for s in source[2:] ]
|
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)
|
||||||
parser = isa_parser.ISAParser(target[0].dir.abspath, cpu_models)
|
|
||||||
parser.parse_isa_desc(source[0].abspath)
|
parser.parse_isa_desc(source[0].abspath)
|
||||||
isa_desc_action = MakeAction(isa_desc_action_func, Transform("ISA DESC", 1))
|
isa_desc_action = MakeAction(isa_desc_action_func, Transform("ISA DESC", 1))
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ output exec {{
|
||||||
#include "arch/arm/utility.hh"
|
#include "arch/arm/utility.hh"
|
||||||
#include "arch/generic/memhelpers.hh"
|
#include "arch/generic/memhelpers.hh"
|
||||||
#include "base/condcodes.hh"
|
#include "base/condcodes.hh"
|
||||||
|
#include "cpu/base.hh"
|
||||||
#include "sim/pseudo_inst.hh"
|
#include "sim/pseudo_inst.hh"
|
||||||
#if defined(linux)
|
#if defined(linux)
|
||||||
#include <fenv.h>
|
#include <fenv.h>
|
||||||
|
|
|
@ -1178,13 +1178,25 @@ class Stack(list):
|
||||||
#
|
#
|
||||||
|
|
||||||
class ISAParser(Grammar):
|
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__()
|
super(ISAParser, self).__init__()
|
||||||
self.output_dir = output_dir
|
self.output_dir = output_dir
|
||||||
|
|
||||||
self.filename = None # for output file watermarking/scaremongering
|
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
|
# variable to hold templates
|
||||||
self.templateMap = {}
|
self.templateMap = {}
|
||||||
|
@ -2376,8 +2388,6 @@ StaticInstPtr
|
||||||
e.exit(self.fileNameStack)
|
e.exit(self.fileNameStack)
|
||||||
|
|
||||||
# Called as script: get args from command line.
|
# 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__':
|
if __name__ == '__main__':
|
||||||
execfile(sys.argv[1]) # read in CpuModel definitions
|
ISAParser(sys.argv[2]).parse_isa_desc(sys.argv[1])
|
||||||
cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
|
|
||||||
ISAParser(sys.argv[3], cpu_models).parse_isa_desc(sys.argv[2])
|
|
||||||
|
|
|
@ -35,71 +35,8 @@ if env['TARGET_ISA'] == 'null':
|
||||||
Source('intr_control_noisa.cc')
|
Source('intr_control_noisa.cc')
|
||||||
Return()
|
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')
|
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('BaseCPU.py')
|
||||||
SimObject('FuncUnit.py')
|
SimObject('FuncUnit.py')
|
||||||
SimObject('ExeTracer.py')
|
SimObject('ExeTracer.py')
|
||||||
|
@ -112,6 +49,7 @@ Source('activity.cc')
|
||||||
Source('base.cc')
|
Source('base.cc')
|
||||||
Source('cpuevent.cc')
|
Source('cpuevent.cc')
|
||||||
Source('exetrace.cc')
|
Source('exetrace.cc')
|
||||||
|
Source('exec_context.cc')
|
||||||
Source('func_unit.cc')
|
Source('func_unit.cc')
|
||||||
Source('inteltrace.cc')
|
Source('inteltrace.cc')
|
||||||
Source('intr_control.cc')
|
Source('intr_control.cc')
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
#include "cpu/checker/cpu.hh"
|
#include "cpu/checker/cpu.hh"
|
||||||
#include "cpu/o3/comm.hh"
|
#include "cpu/o3/comm.hh"
|
||||||
|
#include "cpu/exec_context.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
#include "cpu/inst_seq.hh"
|
#include "cpu/inst_seq.hh"
|
||||||
#include "cpu/op_class.hh"
|
#include "cpu/op_class.hh"
|
||||||
|
@ -73,7 +74,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
class BaseDynInst : public RefCounted
|
class BaseDynInst : public ExecContext, public RefCounted
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Typedef for the CPU.
|
// Typedef for the CPU.
|
||||||
|
@ -82,10 +83,6 @@ class BaseDynInst : public RefCounted
|
||||||
|
|
||||||
// Logical register index type.
|
// Logical register index type.
|
||||||
typedef TheISA::RegIndex RegIndex;
|
typedef TheISA::RegIndex RegIndex;
|
||||||
// Integer register type.
|
|
||||||
typedef TheISA::IntReg IntReg;
|
|
||||||
// Floating point register type.
|
|
||||||
typedef TheISA::FloatReg FloatReg;
|
|
||||||
|
|
||||||
// The DynInstPtr type.
|
// The DynInstPtr type.
|
||||||
typedef typename Impl::DynInstPtr DynInstPtr;
|
typedef typename Impl::DynInstPtr DynInstPtr;
|
||||||
|
@ -634,28 +631,17 @@ class BaseDynInst : public RefCounted
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Records an integer register being set to a value. */
|
/** 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);
|
setResult<uint64_t>(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Records a CC register being set to a value. */
|
/** 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);
|
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. */
|
/** Records an fp register being set to a value. */
|
||||||
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
|
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. */
|
/** 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)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
setResult<uint64_t>(val);
|
setResult<uint64_t>(val);
|
||||||
}
|
}
|
||||||
|
@ -802,10 +781,10 @@ class BaseDynInst : public RefCounted
|
||||||
bool isSquashedInROB() const { return status[SquashedInROB]; }
|
bool isSquashedInROB() const { return status[SquashedInROB]; }
|
||||||
|
|
||||||
/** Read the PC state of this instruction. */
|
/** 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. */
|
/** 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. */
|
/** Read the PC of this instruction. */
|
||||||
const Addr instAddr() const { return pc.instAddr(); }
|
const Addr instAddr() const { return pc.instAddr(); }
|
||||||
|
@ -844,10 +823,10 @@ class BaseDynInst : public RefCounted
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Sets the effective address. */
|
/** 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. */
|
/** 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. */
|
/** Returns whether or not the eff. addr. calculation has been completed. */
|
||||||
bool doneEACalc() { return instFlags[EACalcDone]; }
|
bool doneEACalc() { return instFlags[EACalcDone]; }
|
||||||
|
@ -869,11 +848,11 @@ class BaseDynInst : public RefCounted
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Returns the number of consecutive store conditional failures. */
|
/** Returns the number of consecutive store conditional failures. */
|
||||||
unsigned readStCondFailures()
|
unsigned int readStCondFailures() const
|
||||||
{ return thread->storeCondFailures; }
|
{ return thread->storeCondFailures; }
|
||||||
|
|
||||||
/** Sets the number of consecutive store conditional failures. */
|
/** Sets the number of consecutive store conditional failures. */
|
||||||
void setStCondFailures(unsigned sc_failures)
|
void setStCondFailures(unsigned int sc_failures)
|
||||||
{ thread->storeCondFailures = sc_failures; }
|
{ thread->storeCondFailures = sc_failures; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,4 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
CpuModel('CheckerCPU', 'checker_cpu_exec.cc',
|
CpuModel('CheckerCPU')
|
||||||
'#include "cpu/checker/cpu.hh"',
|
|
||||||
{ 'CPU_exec_context': 'CheckerCPU' })
|
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/base_dyn_inst.hh"
|
#include "cpu/base_dyn_inst.hh"
|
||||||
|
#include "cpu/exec_context.hh"
|
||||||
#include "cpu/pc_event.hh"
|
#include "cpu/pc_event.hh"
|
||||||
#include "cpu/simple_thread.hh"
|
#include "cpu/simple_thread.hh"
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
|
@ -86,7 +87,7 @@ class Request;
|
||||||
* checker to be able to correctly verify instructions, even with
|
* checker to be able to correctly verify instructions, even with
|
||||||
* external accesses to the ThreadContext that change state.
|
* external accesses to the ThreadContext that change state.
|
||||||
*/
|
*/
|
||||||
class CheckerCPU : public BaseCPU
|
class CheckerCPU : public BaseCPU, public ExecContext
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
typedef TheISA::MachInst MachInst;
|
typedef TheISA::MachInst MachInst;
|
||||||
|
@ -194,7 +195,7 @@ class CheckerCPU : public BaseCPU
|
||||||
// These functions are only used in CPU models that split
|
// These functions are only used in CPU models that split
|
||||||
// effective address computation from the actual memory access.
|
// effective address computation from the actual memory access.
|
||||||
void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
|
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
|
// The register accessor methods provide the index of the
|
||||||
// instruction's operand (e.g., 0 or 1), not the architectural
|
// 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
|
// storage (which is pretty hard to imagine they would have reason
|
||||||
// to do).
|
// to do).
|
||||||
|
|
||||||
uint64_t readIntRegOperand(const StaticInst *si, int idx)
|
IntReg readIntRegOperand(const StaticInst *si, int idx)
|
||||||
{
|
{
|
||||||
return thread->readIntReg(si->srcRegIdx(idx));
|
return thread->readIntReg(si->srcRegIdx(idx));
|
||||||
}
|
}
|
||||||
|
@ -224,7 +225,7 @@ class CheckerCPU : public BaseCPU
|
||||||
return thread->readFloatRegBits(reg_idx);
|
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;
|
int reg_idx = si->srcRegIdx(idx) - TheISA::CC_Reg_Base;
|
||||||
return thread->readCCReg(reg_idx);
|
return thread->readCCReg(reg_idx);
|
||||||
|
@ -238,7 +239,7 @@ class CheckerCPU : public BaseCPU
|
||||||
result.push(instRes);
|
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);
|
thread->setIntReg(si->destRegIdx(idx), val);
|
||||||
setResult<uint64_t>(val);
|
setResult<uint64_t>(val);
|
||||||
|
@ -259,7 +260,7 @@ class CheckerCPU : public BaseCPU
|
||||||
setResult<uint64_t>(val);
|
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;
|
int reg_idx = si->destRegIdx(idx) - TheISA::CC_Reg_Base;
|
||||||
thread->setCCReg(reg_idx, val);
|
thread->setCCReg(reg_idx, val);
|
||||||
|
@ -272,7 +273,7 @@ class CheckerCPU : public BaseCPU
|
||||||
thread->setPredicate(val);
|
thread->setPredicate(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
TheISA::PCState pcState() { return thread->pcState(); }
|
TheISA::PCState pcState() const { return thread->pcState(); }
|
||||||
void pcState(const TheISA::PCState &val)
|
void pcState(const TheISA::PCState &val)
|
||||||
{
|
{
|
||||||
DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
|
DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
|
||||||
|
@ -322,13 +323,13 @@ class CheckerCPU : public BaseCPU
|
||||||
}
|
}
|
||||||
|
|
||||||
#if THE_ISA == MIPS_ISA
|
#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");
|
panic("MIPS MT not defined for CheckerCPU.\n");
|
||||||
return 0;
|
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");
|
panic("MIPS MT not defined for CheckerCPU.\n");
|
||||||
}
|
}
|
||||||
|
@ -362,7 +363,11 @@ class CheckerCPU : public BaseCPU
|
||||||
Fault writeMem(uint8_t *data, unsigned size,
|
Fault writeMem(uint8_t *data, unsigned size,
|
||||||
Addr addr, unsigned flags, uint64_t *res);
|
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() { }
|
void wakeup() { }
|
||||||
// Assume that the normal CPU's call to syscall was successful.
|
// Assume that the normal CPU's call to syscall was successful.
|
||||||
// The checker's state would have already been updated by the syscall.
|
// The checker's state would have already been updated by the syscall.
|
||||||
void syscall(uint64_t callnum) { }
|
void syscall(int64_t callnum) { }
|
||||||
|
|
||||||
void handleError()
|
void handleError()
|
||||||
{
|
{
|
||||||
|
|
40
src/cpu/exec_context.cc
Normal file
40
src/cpu/exec_context.cc
Normal 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"
|
|
@ -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
|
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -26,104 +38,228 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Authors: Kevin Lim
|
* 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
|
* The ExecContext is an abstract base class the provides the
|
||||||
* documentation purposes. It shows the interface that is used by the
|
* interface used by the ISA to manipulate the state of the CPU model.
|
||||||
* ISA to access and change CPU state.
|
*
|
||||||
|
* 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 {
|
class ExecContext {
|
||||||
// The register accessor methods provide the index of the
|
public:
|
||||||
// instruction's operand (e.g., 0 or 1), not the architectural
|
typedef TheISA::IntReg IntReg;
|
||||||
// register index, to simplify the implementation of register
|
typedef TheISA::PCState PCState;
|
||||||
// renaming. We find the architectural register index by indexing
|
typedef TheISA::FloatReg FloatReg;
|
||||||
// into the instruction's own operand index table. Note that a
|
typedef TheISA::FloatRegBits FloatRegBits;
|
||||||
// raw pointer to the StaticInst is provided instead of a
|
typedef TheISA::MiscReg MiscReg;
|
||||||
// ref-counted StaticInstPtr to reduce overhead. This is fine as
|
|
||||||
// long as these methods don't copy the pointer into any long-term
|
typedef TheISA::CCReg CCReg;
|
||||||
// storage (which is pretty hard to imagine they would have reason
|
|
||||||
// to do).
|
public:
|
||||||
|
/**
|
||||||
|
* @{
|
||||||
|
* @name Integer Register Interfaces
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/** Reads an integer register. */
|
/** 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. */
|
/** 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
|
/** Reads a floating point register in its binary format, instead
|
||||||
* of by value. */
|
* of by value. */
|
||||||
FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx);
|
virtual FloatRegBits readFloatRegOperandBits(const StaticInst *si,
|
||||||
|
int idx) = 0;
|
||||||
/** Sets an integer register to a value. */
|
|
||||||
void setIntRegOperand(const StaticInst *si, int idx, uint64_t val);
|
|
||||||
|
|
||||||
/** Sets a floating point register of single width to a value. */
|
/** 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
|
/** Sets the bits of a floating point register of single width
|
||||||
* to a binary value. */
|
* to a binary value. */
|
||||||
void setFloatRegOperandBits(const StaticInst *si, int idx,
|
virtual void setFloatRegOperandBits(const StaticInst *si,
|
||||||
FloatRegBits val);
|
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. */
|
* @name Condition Code Registers
|
||||||
void setNextPC(uint64_t val);
|
*/
|
||||||
/** Sets the Next-NextPC. Only for architectures like SPARC or MIPS. */
|
virtual CCReg readCCRegOperand(const StaticInst *si, int idx) = 0;
|
||||||
void setNextNPC(uint64_t val);
|
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. */
|
* Reads a miscellaneous register, handling any architectural
|
||||||
MiscReg readMiscReg(int misc_reg);
|
* 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);
|
* @name PC Control
|
||||||
/** Returns the effective address of the instruction. Only valid
|
*/
|
||||||
* for memory ops. */
|
virtual PCState pcState() const = 0;
|
||||||
Addr getEA();
|
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. */
|
/** 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.
|
||||||
/** Somewhat Alpha-specific function that handles returning from
|
*/
|
||||||
* an error or interrupt. */
|
virtual Fault hwrei() = 0;
|
||||||
Fault hwrei();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for special simulator handling of specific PAL calls. If
|
* Check for special simulator handling of specific PAL calls. If
|
||||||
* return value is false, actual PAL call will be suppressed.
|
* 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__
|
||||||
|
|
|
@ -30,7 +30,4 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
CpuModel('InOrderCPU', 'inorder_cpu_exec.cc',
|
CpuModel('InOrderCPU', default=True)
|
||||||
'#include "cpu/inorder/inorder_dyn_inst.hh"',
|
|
||||||
{ 'CPU_exec_context': 'InOrderDynInst' },
|
|
||||||
default=True)
|
|
||||||
|
|
|
@ -469,7 +469,7 @@ InOrderDynInst::setMiscRegOperand(const StaticInst *si, int idx,
|
||||||
}
|
}
|
||||||
|
|
||||||
MiscReg
|
MiscReg
|
||||||
InOrderDynInst::readRegOtherThread(unsigned reg_idx, ThreadID tid)
|
InOrderDynInst::readRegOtherThread(int reg_idx, ThreadID tid)
|
||||||
{
|
{
|
||||||
if (tid == -1) {
|
if (tid == -1) {
|
||||||
tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber));
|
tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber));
|
||||||
|
@ -544,8 +544,7 @@ InOrderDynInst::setMiscReg(int misc_reg, const MiscReg &val)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
InOrderDynInst::setRegOtherThread(unsigned reg_idx, const MiscReg &val,
|
InOrderDynInst::setRegOtherThread(int reg_idx, MiscReg val, ThreadID tid)
|
||||||
ThreadID tid)
|
|
||||||
{
|
{
|
||||||
if (tid == InvalidThreadID) {
|
if (tid == InvalidThreadID) {
|
||||||
tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber));
|
tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber));
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "base/types.hh"
|
#include "base/types.hh"
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
|
#include "cpu/exec_context.hh"
|
||||||
#include "cpu/inorder/inorder_trace.hh"
|
#include "cpu/inorder/inorder_trace.hh"
|
||||||
#include "cpu/inorder/pipeline_traits.hh"
|
#include "cpu/inorder/pipeline_traits.hh"
|
||||||
#include "cpu/inorder/resource.hh"
|
#include "cpu/inorder/resource.hh"
|
||||||
|
@ -73,7 +74,7 @@
|
||||||
class ResourceRequest;
|
class ResourceRequest;
|
||||||
class Packet;
|
class Packet;
|
||||||
|
|
||||||
class InOrderDynInst : public RefCounted
|
class InOrderDynInst : public ExecContext, public RefCounted
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Binary machine instruction type.
|
// Binary machine instruction type.
|
||||||
|
@ -543,7 +544,7 @@ class InOrderDynInst : public RefCounted
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/** Read the PC of this instruction. */
|
/** 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. */
|
/** Sets the PC of this instruction. */
|
||||||
void pcState(const TheISA::PCState &_pc) { pc = _pc; }
|
void pcState(const TheISA::PCState &_pc) { pc = _pc; }
|
||||||
|
@ -649,10 +650,10 @@ class InOrderDynInst : public RefCounted
|
||||||
{ return memAddr; }
|
{ return memAddr; }
|
||||||
|
|
||||||
/** Sets the effective address. */
|
/** Sets the effective address. */
|
||||||
void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
|
void setEA(Addr ea) { instEffAddr = ea; eaCalcDone = true; }
|
||||||
|
|
||||||
/** Returns the effective address. */
|
/** 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.*/
|
/** Returns whether or not the eff. addr. calculation has been completed.*/
|
||||||
bool doneEACalc() { return eaCalcDone; }
|
bool doneEACalc() { return eaCalcDone; }
|
||||||
|
@ -854,7 +855,10 @@ class InOrderDynInst : public RefCounted
|
||||||
* language (which is why the name isnt readIntSrc(...)) Note: That
|
* language (which is why the name isnt readIntSrc(...)) Note: That
|
||||||
* the source reg. value is set using the setSrcReg() function.
|
* 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);
|
FloatReg readFloatRegOperand(const StaticInst *si, int idx);
|
||||||
TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx);
|
TheISA::FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx);
|
||||||
MiscReg readMiscReg(int misc_reg);
|
MiscReg readMiscReg(int misc_reg);
|
||||||
|
@ -899,24 +903,21 @@ class InOrderDynInst : public RefCounted
|
||||||
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val);
|
void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val);
|
||||||
void setFloatRegOperandBits(const StaticInst *si, int idx,
|
void setFloatRegOperandBits(const StaticInst *si, int idx,
|
||||||
TheISA::FloatRegBits val);
|
TheISA::FloatRegBits val);
|
||||||
void setCCRegOperand(const StaticInst *si, int idx, CCReg val);
|
|
||||||
void setMiscReg(int misc_reg, const MiscReg &val);
|
void setMiscReg(int misc_reg, const MiscReg &val);
|
||||||
void setMiscRegNoEffect(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 setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val);
|
||||||
void setMiscRegOperandNoEffect(const StaticInst *si, int idx,
|
void setMiscRegOperandNoEffect(const StaticInst *si, int idx,
|
||||||
const MiscReg &val);
|
const MiscReg &val);
|
||||||
|
|
||||||
virtual uint64_t readRegOtherThread(unsigned idx,
|
MiscReg readRegOtherThread(int idx, ThreadID tid);
|
||||||
ThreadID tid = InvalidThreadID);
|
void setRegOtherThread(int idx, MiscReg val, ThreadID tid);
|
||||||
virtual void setRegOtherThread(unsigned idx, const uint64_t &val,
|
|
||||||
ThreadID tid = InvalidThreadID);
|
|
||||||
|
|
||||||
/** Returns the number of consecutive store conditional failures. */
|
/** Returns the number of consecutive store conditional failures. */
|
||||||
unsigned readStCondFailures()
|
unsigned int readStCondFailures() const
|
||||||
{ return thread->storeCondFailures; }
|
{ return thread->storeCondFailures; }
|
||||||
|
|
||||||
/** Sets the number of consecutive store conditional failures. */
|
/** Sets the number of consecutive store conditional failures. */
|
||||||
void setStCondFailures(unsigned sc_failures)
|
void setStCondFailures(unsigned int sc_failures)
|
||||||
{ thread->storeCondFailures = sc_failures; }
|
{ thread->storeCondFailures = sc_failures; }
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
|
@ -1063,6 +1064,27 @@ class InOrderDynInst : public RefCounted
|
||||||
void dump(std::string &outstring);
|
void dump(std::string &outstring);
|
||||||
|
|
||||||
//inline int curCount() { return curCount(); }
|
//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");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,4 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
CpuModel('MinorCPU', 'minor_cpu_exec.cc',
|
CpuModel('MinorCPU', default=True)
|
||||||
'#include "cpu/minor/exec_context.hh"',
|
|
||||||
{ 'CPU_exec_context': 'Minor::ExecContext' },
|
|
||||||
default=True)
|
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#ifndef __CPU_MINOR_EXEC_CONTEXT_HH__
|
#ifndef __CPU_MINOR_EXEC_CONTEXT_HH__
|
||||||
#define __CPU_MINOR_EXEC_CONTEXT_HH__
|
#define __CPU_MINOR_EXEC_CONTEXT_HH__
|
||||||
|
|
||||||
|
#include "cpu/exec_context.hh"
|
||||||
#include "cpu/minor/execute.hh"
|
#include "cpu/minor/execute.hh"
|
||||||
#include "cpu/minor/pipeline.hh"
|
#include "cpu/minor/pipeline.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
|
@ -69,7 +70,7 @@ class Execute;
|
||||||
* separates that interface from other classes such as Pipeline, MinorCPU
|
* separates that interface from other classes such as Pipeline, MinorCPU
|
||||||
* and DynMinorInst and makes it easier to see what state is accessed by it.
|
* and DynMinorInst and makes it easier to see what state is accessed by it.
|
||||||
*/
|
*/
|
||||||
class ExecContext
|
class ExecContext : public ::ExecContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MinorCPU &cpu;
|
MinorCPU &cpu;
|
||||||
|
@ -119,7 +120,7 @@ class ExecContext
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
IntReg
|
||||||
readIntRegOperand(const StaticInst *si, int idx)
|
readIntRegOperand(const StaticInst *si, int idx)
|
||||||
{
|
{
|
||||||
return thread.readIntReg(si->srcRegIdx(idx));
|
return thread.readIntReg(si->srcRegIdx(idx));
|
||||||
|
@ -140,7 +141,7 @@ class ExecContext
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
|
setIntRegOperand(const StaticInst *si, int idx, IntReg val)
|
||||||
{
|
{
|
||||||
thread.setIntReg(si->destRegIdx(idx), val);
|
thread.setIntReg(si->destRegIdx(idx), val);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +175,7 @@ class ExecContext
|
||||||
}
|
}
|
||||||
|
|
||||||
TheISA::PCState
|
TheISA::PCState
|
||||||
pcState()
|
pcState() const
|
||||||
{
|
{
|
||||||
return thread.pcState();
|
return thread.pcState();
|
||||||
}
|
}
|
||||||
|
@ -250,12 +251,8 @@ class ExecContext
|
||||||
ThreadContext *tcBase() { return thread.getTC(); }
|
ThreadContext *tcBase() { return thread.getTC(); }
|
||||||
|
|
||||||
/* @todo, should make stCondFailures persistent somewhere */
|
/* @todo, should make stCondFailures persistent somewhere */
|
||||||
unsigned int readStCondFailures() { return 0; }
|
unsigned int readStCondFailures() const { return 0; }
|
||||||
unsigned int
|
void setStCondFailures(unsigned int st_cond_failures) {}
|
||||||
setStCondFailures(unsigned int st_cond_failures)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int contextId() { return thread.contextId(); }
|
int contextId() { return thread.contextId(); }
|
||||||
/* ISA-specific (or at least currently ISA singleton) functions */
|
/* ISA-specific (or at least currently ISA singleton) functions */
|
||||||
|
@ -295,7 +292,7 @@ class ExecContext
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ALPHA/POWER: Effective address storage */
|
/* ALPHA/POWER: Effective address storage */
|
||||||
void setEA(Addr &ea)
|
void setEA(Addr ea)
|
||||||
{
|
{
|
||||||
inst->ea = ea;
|
inst->ea = ea;
|
||||||
}
|
}
|
||||||
|
@ -303,14 +300,14 @@ class ExecContext
|
||||||
BaseCPU *getCpuPtr() { return &cpu; }
|
BaseCPU *getCpuPtr() { return &cpu; }
|
||||||
|
|
||||||
/* POWER: Effective address storage */
|
/* POWER: Effective address storage */
|
||||||
Addr getEA()
|
Addr getEA() const
|
||||||
{
|
{
|
||||||
return inst->ea;
|
return inst->ea;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MIPS: other thread register reading/writing */
|
/* MIPS: other thread register reading/writing */
|
||||||
uint64_t
|
uint64_t
|
||||||
readRegOtherThread(unsigned idx, ThreadID tid = InvalidThreadID)
|
readRegOtherThread(int idx, ThreadID tid = InvalidThreadID)
|
||||||
{
|
{
|
||||||
SimpleThread *other_thread = (tid == InvalidThreadID
|
SimpleThread *other_thread = (tid == InvalidThreadID
|
||||||
? &thread : cpu.threads[tid]);
|
? &thread : cpu.threads[tid]);
|
||||||
|
@ -327,7 +324,7 @@ class ExecContext
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
setRegOtherThread(unsigned idx, const TheISA::MiscReg &val,
|
setRegOtherThread(int idx, const TheISA::MiscReg &val,
|
||||||
ThreadID tid = InvalidThreadID)
|
ThreadID tid = InvalidThreadID)
|
||||||
{
|
{
|
||||||
SimpleThread *other_thread = (tid == InvalidThreadID
|
SimpleThread *other_thread = (tid == InvalidThreadID
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
CpuModel('no', '', '', { '': '' })
|
CpuModel('no')
|
||||||
|
|
|
@ -30,7 +30,4 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
CpuModel('O3CPU', 'o3_cpu_exec.cc',
|
CpuModel('O3CPU', default=True)
|
||||||
'#include "cpu/o3/isa_specific.hh"',
|
|
||||||
{ 'CPU_exec_context': 'O3DynInst' },
|
|
||||||
default=True)
|
|
||||||
|
|
|
@ -71,9 +71,8 @@ class BaseO3DynInst : public BaseDynInst<Impl>
|
||||||
typedef TheISA::IntReg IntReg;
|
typedef TheISA::IntReg IntReg;
|
||||||
typedef TheISA::FloatReg FloatReg;
|
typedef TheISA::FloatReg FloatReg;
|
||||||
typedef TheISA::FloatRegBits FloatRegBits;
|
typedef TheISA::FloatRegBits FloatRegBits;
|
||||||
#ifdef ISA_HAS_CC_REGS
|
|
||||||
typedef TheISA::CCReg CCReg;
|
typedef TheISA::CCReg CCReg;
|
||||||
#endif
|
|
||||||
/** Misc register index type. */
|
/** Misc register index type. */
|
||||||
typedef TheISA::MiscReg MiscReg;
|
typedef TheISA::MiscReg MiscReg;
|
||||||
|
|
||||||
|
@ -250,7 +249,7 @@ class BaseO3DynInst : public BaseDynInst<Impl>
|
||||||
// storage (which is pretty hard to imagine they would have reason
|
// storage (which is pretty hard to imagine they would have reason
|
||||||
// to do).
|
// to do).
|
||||||
|
|
||||||
uint64_t readIntRegOperand(const StaticInst *si, int idx)
|
IntReg readIntRegOperand(const StaticInst *si, int idx)
|
||||||
{
|
{
|
||||||
return this->cpu->readIntReg(this->_srcRegIdx[idx]);
|
return this->cpu->readIntReg(this->_srcRegIdx[idx]);
|
||||||
}
|
}
|
||||||
|
@ -265,7 +264,7 @@ class BaseO3DynInst : public BaseDynInst<Impl>
|
||||||
return this->cpu->readFloatRegBits(this->_srcRegIdx[idx]);
|
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]);
|
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
|
/** @todo: Make results into arrays so they can handle multiple dest
|
||||||
* registers.
|
* 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);
|
this->cpu->setIntReg(this->_destRegIdx[idx], val);
|
||||||
BaseDynInst<Impl>::setIntRegOperand(si, idx, val);
|
BaseDynInst<Impl>::setIntRegOperand(si, idx, val);
|
||||||
|
@ -292,20 +291,20 @@ class BaseO3DynInst : public BaseDynInst<Impl>
|
||||||
BaseDynInst<Impl>::setFloatRegOperandBits(si, idx, val);
|
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);
|
this->cpu->setCCReg(this->_destRegIdx[idx], val);
|
||||||
BaseDynInst<Impl>::setCCRegOperand(si, idx, val);
|
BaseDynInst<Impl>::setCCRegOperand(si, idx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if THE_ISA == MIPS_ISA
|
#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");
|
panic("MIPS MT not defined for O3 CPU.\n");
|
||||||
return 0;
|
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");
|
panic("MIPS MT not defined for O3 CPU.\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,6 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
CpuModel('OzoneSimpleCPU', 'ozone_simple_exec.cc',
|
CpuModel('OzoneSimpleCPU')
|
||||||
'#include "cpu/ozone/dyn_inst.hh"',
|
CpuModel('OzoneCPU')
|
||||||
{ 'CPU_exec_context': 'OzoneDynInst<SimpleImpl>' })
|
|
||||||
CpuModel('OzoneCPU', 'ozone_exec.cc',
|
|
||||||
'#include "cpu/ozone/dyn_inst.hh"',
|
|
||||||
{ 'CPU_exec_context': 'OzoneDynInst<OzoneImpl>' })
|
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,5 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
CpuModel('AtomicSimpleCPU', 'atomic_simple_cpu_exec.cc',
|
CpuModel('AtomicSimpleCPU', default=True)
|
||||||
'#include "cpu/simple/atomic.hh"',
|
CpuModel('TimingSimpleCPU', default=True)
|
||||||
{ 'CPU_exec_context': 'AtomicSimpleCPU' },
|
|
||||||
default=True)
|
|
||||||
CpuModel('TimingSimpleCPU', 'timing_simple_cpu_exec.cc',
|
|
||||||
'#include "cpu/simple/timing.hh"',
|
|
||||||
{ 'CPU_exec_context': 'TimingSimpleCPU' },
|
|
||||||
default=True)
|
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "config/the_isa.hh"
|
#include "config/the_isa.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/checker/cpu.hh"
|
#include "cpu/checker/cpu.hh"
|
||||||
|
#include "cpu/exec_context.hh"
|
||||||
#include "cpu/pc_event.hh"
|
#include "cpu/pc_event.hh"
|
||||||
#include "cpu/simple_thread.hh"
|
#include "cpu/simple_thread.hh"
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
|
@ -79,7 +80,7 @@ namespace Trace {
|
||||||
struct BaseSimpleCPUParams;
|
struct BaseSimpleCPUParams;
|
||||||
class BPredUnit;
|
class BPredUnit;
|
||||||
|
|
||||||
class BaseSimpleCPU : public BaseCPU
|
class BaseSimpleCPU : public BaseCPU, public ExecContext
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
typedef TheISA::MiscReg MiscReg;
|
typedef TheISA::MiscReg MiscReg;
|
||||||
|
@ -293,8 +294,7 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
// These functions are only used in CPU models that split
|
// These functions are only used in CPU models that split
|
||||||
// effective address computation from the actual memory access.
|
// effective address computation from the actual memory access.
|
||||||
void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); }
|
void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); }
|
||||||
Addr getEA() { panic("BaseSimpleCPU::getEA() not implemented\n");
|
Addr getEA() const { panic("BaseSimpleCPU::getEA() not implemented\n"); }
|
||||||
M5_DUMMY_RETURN}
|
|
||||||
|
|
||||||
// The register accessor methods provide the index of the
|
// The register accessor methods provide the index of the
|
||||||
// instruction's operand (e.g., 0 or 1), not the architectural
|
// 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
|
// storage (which is pretty hard to imagine they would have reason
|
||||||
// to do).
|
// to do).
|
||||||
|
|
||||||
uint64_t readIntRegOperand(const StaticInst *si, int idx)
|
IntReg readIntRegOperand(const StaticInst *si, int idx)
|
||||||
{
|
{
|
||||||
numIntRegReads++;
|
numIntRegReads++;
|
||||||
return thread->readIntReg(si->srcRegIdx(idx));
|
return thread->readIntReg(si->srcRegIdx(idx));
|
||||||
|
@ -334,7 +334,7 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
return thread->readCCReg(reg_idx);
|
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++;
|
numIntRegWrites++;
|
||||||
thread->setIntReg(si->destRegIdx(idx), val);
|
thread->setIntReg(si->destRegIdx(idx), val);
|
||||||
|
@ -370,7 +370,7 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
traceData->setPredicate(val);
|
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); }
|
void pcState(const TheISA::PCState &val) { thread->pcState(val); }
|
||||||
Addr instAddr() { return thread->instAddr(); }
|
Addr instAddr() { return thread->instAddr(); }
|
||||||
Addr nextInstAddr() { return thread->nextInstAddr(); }
|
Addr nextInstAddr() { return thread->nextInstAddr(); }
|
||||||
|
@ -423,26 +423,26 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
thread->demapDataPage(vaddr, asn);
|
thread->demapDataPage(vaddr, asn);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned readStCondFailures() {
|
unsigned int readStCondFailures() const {
|
||||||
return thread->readStCondFailures();
|
return thread->readStCondFailures();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStCondFailures(unsigned sc_failures) {
|
void setStCondFailures(unsigned int sc_failures) {
|
||||||
thread->setStCondFailures(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 "
|
panic("Simple CPU models do not support multithreaded "
|
||||||
"register access.\n");
|
"register access.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRegOtherThread(int regIdx, const MiscReg &val,
|
void setRegOtherThread(int regIdx, MiscReg val,
|
||||||
ThreadID tid = InvalidThreadID)
|
ThreadID tid = InvalidThreadID)
|
||||||
{
|
{
|
||||||
panic("Simple CPU models do not support multithreaded "
|
panic("Simple CPU models do not support multithreaded "
|
||||||
"register access.\n");
|
"register access.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Fault CacheOp(uint8_t Op, Addr EA);
|
//Fault CacheOp(uint8_t Op, Addr EA);
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "mem/fs_translating_port_proxy.hh"
|
#include "mem/fs_translating_port_proxy.hh"
|
||||||
#include "mem/se_translating_port_proxy.hh"
|
#include "mem/se_translating_port_proxy.hh"
|
||||||
#include "params/BaseCPU.hh"
|
#include "params/BaseCPU.hh"
|
||||||
|
#include "sim/faults.hh"
|
||||||
#include "sim/full_system.hh"
|
#include "sim/full_system.hh"
|
||||||
#include "sim/process.hh"
|
#include "sim/process.hh"
|
||||||
#include "sim/serialize.hh"
|
#include "sim/serialize.hh"
|
||||||
|
@ -213,3 +214,18 @@ SimpleThread::copyArchRegs(ThreadContext *src_tc)
|
||||||
TheISA::copyRegs(src_tc, 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
|
||||||
|
|
|
@ -50,19 +50,7 @@
|
||||||
// forward declarations
|
// forward declarations
|
||||||
class Packet;
|
class Packet;
|
||||||
|
|
||||||
struct O3CPUImpl;
|
class ExecContext;
|
||||||
template <class Impl> class BaseO3DynInst;
|
|
||||||
typedef BaseO3DynInst<O3CPUImpl> O3DynInst;
|
|
||||||
class InOrderDynInst;
|
|
||||||
|
|
||||||
class CheckerCPU;
|
|
||||||
class AtomicSimpleCPU;
|
|
||||||
class TimingSimpleCPU;
|
|
||||||
class InorderCPU;
|
|
||||||
namespace Minor
|
|
||||||
{
|
|
||||||
class ExecContext;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SymbolTable;
|
class SymbolTable;
|
||||||
|
|
||||||
|
@ -267,11 +255,25 @@ class StaticInst : public RefCounted, public StaticInstFlags
|
||||||
public:
|
public:
|
||||||
virtual ~StaticInst();
|
virtual ~StaticInst();
|
||||||
|
|
||||||
/**
|
virtual Fault execute(ExecContext *xc,
|
||||||
* The execute() signatures are auto-generated by scons based on the
|
Trace::InstRecord *traceData) const = 0;
|
||||||
* set of CPU models we are compiling in today.
|
virtual Fault eaComp(ExecContext *xc,
|
||||||
*/
|
Trace::InstRecord *traceData) const
|
||||||
#include "cpu/static_inst_exec_sigs.hh"
|
{
|
||||||
|
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;
|
virtual void advancePC(TheISA::PCState &pcState) const = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue