raise
# Global Python includes
+import itertools
import os
import re
import subprocess
###################################################
main['ALL_ISA_LIST'] = all_isa_list
+all_isa_deps = {}
def make_switching_dir(dname, switch_headers, env):
# Generate the header. target[0] is the full path of the output
# header to generate. 'source' is a dummy variable, since we get the
# list of ISAs from env['ALL_ISA_LIST'].
def gen_switch_hdr(target, source, env):
fname = str(target[0])
- f = open(fname, 'w')
isa = env['TARGET_ISA'].lower()
- print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname))
- f.close()
+ try:
+ f = open(fname, 'w')
+ print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname))
+ f.close()
+ except IOError:
+ print "Failed to create %s" % fname
+ raise
# Build SCons Action object. 'varlist' specifies env vars that this
# action depends on; when env['ALL_ISA_LIST'] changes these actions
# Instantiate actions for each header
for hdr in switch_headers:
env.Command(hdr, [], switch_hdr_action)
+
+ isa_target = Dir('.').up().name.lower().replace('_', '-')
+ env['PHONY_BASE'] = '#'+isa_target
+ all_isa_deps[isa_target] = None
+
Export('make_switching_dir')
+# all-isas -> all-deps -> all-environs -> all_targets
+main.Alias('#all-isas', [])
+main.Alias('#all-deps', '#all-isas')
+
+# Dummy target to ensure all environments are created before telling
+# SCons what to actually make (the command line arguments). We attach
+# them to the dependence graph after the environments are complete.
+ORIG_BUILD_TARGETS = list(BUILD_TARGETS) # force a copy; gets closure to work.
+def environsComplete(target, source, env):
+ for t in ORIG_BUILD_TARGETS:
+ main.Depends('#all-targets', t)
+
+# Each build/* switching_dir attaches its *-environs target to #all-environs.
+main.Append(BUILDERS = {'CompleteEnvirons' :
+ Builder(action=MakeAction(environsComplete, None))})
+main.CompleteEnvirons('#all-environs', [])
+
+def doNothing(**ignored): pass
+main.Append(BUILDERS = {'Dummy': Builder(action=MakeAction(doNothing, None))})
+
+# The final target to which all the original targets ultimately get attached.
+main.Dummy('#all-targets', '#all-environs')
+BUILD_TARGETS[:] = ['#all-targets']
+
###################################################
#
# Define build environments for selected configurations.
# The src/SConscript file sets up the build rules in 'env' according
# to the configured variables. It returns a list of environments,
# one for each variant build (debug, opt, etc.)
- envList = SConscript('src/SConscript', variant_dir = variant_path,
- exports = 'env')
-
- # Set up the regression tests for each build.
- for e in envList:
- SConscript('tests/SConscript',
- variant_dir = joinpath(variant_path, 'tests', e.Label),
- exports = { 'env' : e }, duplicate = False)
+ SConscript('src/SConscript', variant_dir = variant_path, exports = 'env')
+
+def pairwise(iterable):
+ "s -> (s0,s1), (s1,s2), (s2, s3), ..."
+ a, b = itertools.tee(iterable)
+ b.next()
+ return itertools.izip(a, b)
+
+# Create false dependencies so SCons will parse ISAs, establish
+# dependencies, and setup the build Environments serially. Either
+# SCons (likely) and/or our SConscripts (possibly) cannot cope with -j
+# greater than 1. It appears to be standard race condition stuff; it
+# doesn't always fail, but usually, and the behaviors are different.
+# Every time I tried to remove this, builds would fail in some
+# creative new way. So, don't do that. You'll want to, though, because
+# tests/SConscript takes a long time to make its Environments.
+for t1, t2 in pairwise(sorted(all_isa_deps.iterkeys())):
+ main.Depends('#%s-deps' % t2, '#%s-deps' % t1)
+ main.Depends('#%s-environs' % t2, '#%s-environs' % t1)
# base help text
Help('''
def __eq__(self, other): return self.filename == other.filename
def __ne__(self, other): return self.filename != other.filename
+ @staticmethod
+ def done():
+ def disabled(cls, name, *ignored):
+ raise RuntimeError("Additional SourceFile '%s'" % name,\
+ "declared, but targets deps are already fixed.")
+ SourceFile.__init__ = disabled
+
+
class Source(SourceFile):
'''Add a c/c++ source file to the build'''
def __init__(self, source, Werror=True, swig=False, **guards):
#
# List of constructed environments to pass back to SConstruct
-envList = []
-
date_source = Source('base/date.cc', skip_lib=True)
+# Capture this directory for the closure makeEnv, otherwise when it is
+# called, it won't know what directory it should use.
+variant_dir = Dir('.').path
+def variant(*path):
+ return os.path.join(variant_dir, *path)
+def variantd(*path):
+ return variant(*path)+'/'
+
# Function to create a new build environment as clone of current
# environment 'env' with modified object suffix and optional stripped
# binary. Additional keyword arguments are appended to corresponding
# build environment vars.
-def makeEnv(label, objsfx, strip = False, **kwargs):
+def makeEnv(env, label, objsfx, strip = False, **kwargs):
# SCons doesn't know to append a library suffix when there is a '.' in the
# name. Use '_' instead.
- libname = 'gem5_' + label
- exename = 'gem5.' + label
- secondary_exename = 'm5.' + label
+ libname = variant('gem5_' + label)
+ exename = variant('gem5.' + label)
+ secondary_exename = variant('m5.' + label)
new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's')
new_env.Label = label
test_objs = [ make_obj(s, static=True) for s in test_sources ]
if test.main:
test_objs += main_objs
- testname = "unittest/%s.%s" % (test.target, label)
- new_env.Program(testname, test_objs + static_objs)
+ path = variant('unittest/%s.%s' % (test.target, label))
+ new_env.Program(path, test_objs + static_objs)
progname = exename
if strip:
MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK")))
new_env.M5Binary = targets[0]
- envList.append(new_env)
+ return new_env
# Start out with the compiler flags common to all compilers,
# i.e. they all use -g for opt and -g -pg for prof
if 'all' in needed_envs:
needed_envs += target_types
-# Debug binary
-if 'debug' in needed_envs:
- makeEnv('debug', '.do',
- CCFLAGS = Split(ccflags['debug']),
- CPPDEFINES = ['DEBUG', 'TRACING_ON=1'],
- LINKFLAGS = Split(ldflags['debug']))
-
-# Optimized binary
-if 'opt' in needed_envs:
- makeEnv('opt', '.o',
- CCFLAGS = Split(ccflags['opt']),
- CPPDEFINES = ['TRACING_ON=1'],
- LINKFLAGS = Split(ldflags['opt']))
-
-# "Fast" binary
-if 'fast' in needed_envs:
- makeEnv('fast', '.fo', strip = True,
- CCFLAGS = Split(ccflags['fast']),
- CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
- LINKFLAGS = Split(ldflags['fast']))
-
-# Profiled binary using gprof
-if 'prof' in needed_envs:
- makeEnv('prof', '.po',
- CCFLAGS = Split(ccflags['prof']),
- CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
- LINKFLAGS = Split(ldflags['prof']))
-
-# Profiled binary using google-pprof
-if 'perf' in needed_envs:
- makeEnv('perf', '.gpo',
- CCFLAGS = Split(ccflags['perf']),
- CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
- LINKFLAGS = Split(ldflags['perf']))
-
-Return('envList')
+gem5_root = Dir('.').up().up().abspath
+def makeEnvirons(target, source, env):
+ # cause any later Source() calls to be fatal, as a diagnostic.
+ Source.done()
+
+ envList = []
+
+ # Debug binary
+ if 'debug' in needed_envs:
+ envList.append(
+ makeEnv(env, 'debug', '.do',
+ CCFLAGS = Split(ccflags['debug']),
+ CPPDEFINES = ['DEBUG', 'TRACING_ON=1'],
+ LINKFLAGS = Split(ldflags['debug'])))
+
+ # Optimized binary
+ if 'opt' in needed_envs:
+ envList.append(
+ makeEnv(env, 'opt', '.o',
+ CCFLAGS = Split(ccflags['opt']),
+ CPPDEFINES = ['TRACING_ON=1'],
+ LINKFLAGS = Split(ldflags['opt'])))
+
+ # "Fast" binary
+ if 'fast' in needed_envs:
+ envList.append(
+ makeEnv(env, 'fast', '.fo', strip = True,
+ CCFLAGS = Split(ccflags['fast']),
+ CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
+ LINKFLAGS = Split(ldflags['fast'])))
+
+ # Profiled binary using gprof
+ if 'prof' in needed_envs:
+ envList.append(
+ makeEnv(env, 'prof', '.po',
+ CCFLAGS = Split(ccflags['prof']),
+ CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
+ LINKFLAGS = Split(ldflags['prof'])))
+
+ # Profiled binary using google-pprof
+ if 'perf' in needed_envs:
+ envList.append(
+ makeEnv(env, 'perf', '.gpo',
+ CCFLAGS = Split(ccflags['perf']),
+ CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
+ LINKFLAGS = Split(ldflags['perf'])))
+
+ # Set up the regression tests for each build.
+ for e in envList:
+ SConscript(os.path.join(gem5_root, 'tests', 'SConscript'),
+ variant_dir = variantd('tests', e.Label),
+ exports = { 'env' : e }, duplicate = False)
+
+# The MakeEnvirons Builder defers the full dependency collection until
+# after processing the ISA definition (due to dynamically generated
+# source files). Add this dependency to all targets so they will wait
+# until the environments are completely set up. Otherwise, a second
+# process (e.g. -j2 or higher) will try to compile the requested target,
+# not know how, and fail.
+env.Append(BUILDERS = {'MakeEnvirons' :
+ Builder(action=MakeAction(makeEnvirons,
+ Transform("ENVIRONS", 1)))})
+
+isa_target = env['PHONY_BASE'] + '-deps'
+environs = env['PHONY_BASE'] + '-environs'
+env.Depends('#all-deps', isa_target)
+env.Depends('#all-environs', environs)
+env.ScanISA(isa_target, File('arch/%s/generated/inc.d' % env['TARGET_ISA']))
+envSetup = env.MakeEnvirons(environs, isa_target)
+
+# make sure no -deps targets occur before all ISAs are complete
+env.Depends(isa_target, '#all-isas')
+# likewise for -environs targets and all the -deps targets
+env.Depends(environs, '#all-deps')
import sys
import os
+import re
Import('*')
cpu_models = list(env['CPU_MODELS'])
cpu_models.append('CheckerCPU')
- # Several files are generated from the ISA description.
- # We always get the basic decoder and header file.
- target = [ 'decoder.cc', 'decoder.hh', 'max_inst_regs.hh' ]
- # We also get an execute file for each selected CPU model.
- target += [CpuModel.dict[cpu].filename for cpu in cpu_models]
-
# List the isa parser as a source.
source += [ isa_parser ]
# Add in the CPU models.
source += [ Value(m) for m in cpu_models ]
- return [os.path.join("generated", t) for t in target], source
+ # Specify different targets depending on if we're running the ISA
+ # parser for its dependency information, or for the generated files.
+ # (As an optimization, the ISA parser detects the useless second run
+ # and skips doing any work, if the first run was performed, since it
+ # always generates all its files). The way we track this in SCons is the
+ # <arch>_isa_outputs value in the environment (env). If it's unset, we
+ # don't know what the dependencies are so we ask for generated/inc.d to
+ # be generated so they can be acquired. If we know what they are, then
+ # it's because we've already processed inc.d and then claim that our
+ # outputs (targets) will be thus.
+ isa = env['TARGET_ISA']
+ key = '%s_isa_outputs' % isa
+ if key in env:
+ targets = [ os.path.join('generated', f) for f in env[key] ]
+ else:
+ targets = [ os.path.join('generated','inc.d') ]
+
+ def prefix(s):
+ return os.path.join(target[0].dir.up().abspath, s)
+
+ return [ prefix(t) for t in targets ], source
ARCH_DIR = Dir('.')
env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
+# The ISA is generated twice: the first time to find out what it generates,
+# and the second time to make scons happy by telling the ISADesc builder
+# what it will make before it builds it.
+def scan_isa_deps(target, source, env):
+ # Process dependency file generated by the ISA parser --
+ # add the listed files to the dependency tree of the build.
+ source = source[0]
+ archbase = source.dir.up().path
+
+ try:
+ depfile = open(source.abspath, 'r')
+ except:
+ print "scan_isa_deps: Can't open ISA deps file '%s' in %s" % \
+ (source.path,os.getcwd())
+ raise
+
+ # Scan through the lines
+ targets = {}
+ for line in depfile:
+ # Read the dependency line with the format
+ # <target file>: [ <dependent file>* ]
+ m = re.match(r'^\s*([^:]+\.([^\.:]+))\s*:\s*(.*)', line)
+ assert(m)
+ targ, extn = m.group(1,2)
+ deps = m.group(3).split()
+
+ files = [ targ ] + deps
+ for f in files:
+ targets[f] = True
+ # Eliminate unnecessary re-generation if we already generated it
+ env.Precious(os.path.join(archbase, 'generated', f))
+
+ files = [ os.path.join(archbase, 'generated', f) for f in files ]
+
+ if extn == 'cc':
+ Source(os.path.join(archbase,'generated', targ))
+ depfile.close()
+ env[env['TARGET_ISA'] + '_isa_outputs'] = targets.keys()
+
+ isa = env.ISADesc(os.path.join(archbase,'isa','main.isa'))
+ for t in targets:
+ env.Depends('#all-isas', isa)
+
+env.Append(BUILDERS = {'ScanISA' :
+ Builder(action=MakeAction(scan_isa_deps,
+ Transform("NEW DEPS", 1)))})
+
DebugFlag('IntRegs')
DebugFlag('FloatRegs')
DebugFlag('CCRegs')
SimObject('AlphaSystem.py')
SimObject('AlphaTLB.py')
-
# Add in files generated by the ISA description.
- isa_desc_files = env.ISADesc('isa/main.isa')
- # Only non-header files need to be compiled.
- for f in isa_desc_files:
- if not f.path.endswith('.hh'):
- Source(f)
+ env.ISADesc('isa/main.isa')
/// instruction in full-system mode.
/// @retval Full-system mode: NoFault if FP is enabled, FenFault
/// if not. Non-full-system mode: always returns NoFault.
- inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ inline Fault checkFpEnableFault(CPU_EXEC_CONTEXT *xc)
{
Fault fault = NoFault; // dummy... this ipr access should not fault
if (FullSystem && !ICSR_FPE(xc->readMiscReg(IPR_ICSR))) {
// FP instruction class execute method template. Handles non-standard
// rounding modes.
def template FloatingPointExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (trappingMode != Imprecise && !warnedOnTrapping) {
// rounding mode control is needed. Like BasicExecute, but includes
// check & warning for non-standard trapping mode.
def template FPFixedRoundingExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (trappingMode != Imprecise && !warnedOnTrapping) {
// Basic instruction class execute method template.
def template BasicExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
output exec {{
Fault
- Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
+ Nop::execute(CPU_EXEC_CONTEXT *, Trace::InstRecord *) const
{
return NoFault;
}
}};
def template EACompExecute {{
- Fault %(class_name)s::eaComp(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template LoadExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template LoadInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template LoadCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template StoreExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template StoreCondExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template StoreInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template StoreCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return NoFault;
def template StoreCondCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template MiscExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA M5_VAR_USED;
// Prefetches in Alpha don't actually do anything
// They just build an effective address and complete
def template MiscInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
warn("initiateAcc undefined: Misc instruction does not support split "
def template MiscCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
warn("completeAcc undefined: Misc instruction does not support split "
output exec {{
Fault
- OpcdecFault::execute(%(CPU_exec_context)s *xc,
+ OpcdecFault::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return new UnimplementedOpcodeFault;
output exec {{
Fault
- FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ FailUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("attempt to execute unimplemented instruction '%s' "
}
Fault
- WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ WarnUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (!warned) {
output exec {{
Fault
- Unknown::execute(%(CPU_exec_context)s *xc,
+ Unknown::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("attempt to execute unknown instruction "
DebugFlag('Faults', "Trace Exceptions, interrupts, svc/swi")
DebugFlag('TLBVerbose')
- # Add in files generated by the ISA description.
- isa_desc_files = env.ISADesc('isa/main.isa')
- # Only non-header files need to be compiled.
- for f in isa_desc_files:
- if not f.path.endswith('.hh'):
- Source(f)
-
+ # Add files generated by the ISA description.
+ env.ISADesc('isa/main.isa')
output exec {{
Fault
- Breakpoint::execute(%(CPU_exec_context)s *xc,
+ Breakpoint::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return new PrefetchAbort(xc->pcState().pc(), ArmFault::DebugEvent);
output exec {{
Fault
- FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ FailUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return new UndefinedInstruction(machInst, false, mnemonic);
}
Fault
- WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ WarnUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (!warned) {
}
Fault
- FlushPipeInst::execute(%(CPU_exec_context)s *xc,
+ FlushPipeInst::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return new FlushPipe();
// Basic instruction class execute method template.
def template BasicExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template MicroNeonMemExecDeclare {{
template
Fault %(class_name)s<%(targs)s>::execute(
- %(CPU_exec_context)s *, Trace::InstRecord *) const;
+ CPU_EXEC_CONTEXT *, Trace::InstRecord *) const;
template
Fault %(class_name)s<%(targs)s>::initiateAcc(
- %(CPU_exec_context)s *, Trace::InstRecord *) const;
+ CPU_EXEC_CONTEXT *, Trace::InstRecord *) const;
template
Fault %(class_name)s<%(targs)s>::completeAcc(PacketPtr,
- %(CPU_exec_context)s *, Trace::InstRecord *) const;
+ CPU_EXEC_CONTEXT *, Trace::InstRecord *) const;
}};
def template MicroNeonExecDeclare {{
template
Fault %(class_name)s<%(targs)s>::execute(
- %(CPU_exec_context)s *, Trace::InstRecord *) const;
+ CPU_EXEC_CONTEXT *, Trace::InstRecord *) const;
}};
////////////////////////////////////////////////////////////////////
def template MicroNeonMixExecute {{
template <class Element>
- Fault %(class_name)s<Element>::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s<Element>::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template PanicExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("Execute function executed when it shouldn't be!\n");
}};
def template PanicInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("InitiateAcc function executed when it shouldn't be!\n");
def template PanicCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("CompleteAcc function executed when it shouldn't be!\n");
def template SwapExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template SwapInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template SwapCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template LoadExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template NeonLoadExecute {{
template <class Element>
Fault %(class_name)s<Element>::execute(
- %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
}};
def template StoreExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template NeonStoreExecute {{
template <class Element>
Fault %(class_name)s<Element>::execute(
- %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
}};
def template StoreExExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template StoreExInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template StoreInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template NeonStoreInitiateAcc {{
template <class Element>
Fault %(class_name)s<Element>::initiateAcc(
- %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
}};
def template LoadInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template NeonLoadInitiateAcc {{
template <class Element>
Fault %(class_name)s<Element>::initiateAcc(
- %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
def template LoadCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template NeonLoadCompleteAcc {{
template <class Element>
Fault %(class_name)s<Element>::completeAcc(
- PacketPtr pkt, %(CPU_exec_context)s *xc,
+ PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template StoreCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return NoFault;
def template NeonStoreCompleteAcc {{
template <class Element>
Fault %(class_name)s<Element>::completeAcc(
- PacketPtr pkt, %(CPU_exec_context)s *xc,
+ PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return NoFault;
def template StoreExCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template Load64Execute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template Store64Execute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template Store64InitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template StoreEx64Execute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template StoreEx64InitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template Load64InitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template Load64CompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template Store64CompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return NoFault;
def template StoreEx64CompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template DCStore64Execute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template DCStore64InitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template NeonExecDeclare {{
template
Fault %(class_name)s<%(targs)s>::execute(
- %(CPU_exec_context)s *, Trace::InstRecord *) const;
+ CPU_EXEC_CONTEXT *, Trace::InstRecord *) const;
}};
output header {{
def template NeonEqualRegExecute {{
template <class Element>
- Fault %(class_name)s<Element>::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s<Element>::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template NeonUnequalRegExecute {{
template <class Element>
- Fault %(class_name)s<Element>::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s<Element>::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
typedef typename bigger_type_t<Element>::type BigElement;
def template NeonXExecDeclare {{
template
Fault %(class_name)s<%(targs)s>::execute(
- %(CPU_exec_context)s *, Trace::InstRecord *) const;
+ CPU_EXEC_CONTEXT *, Trace::InstRecord *) const;
}};
def template NeonXEqualRegOpExecute {{
template <class Element>
- Fault %(class_name)s<Element>::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s<Element>::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template NeonXUnequalRegOpExecute {{
template <class Element>
- Fault %(class_name)s<Element>::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s<Element>::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
typedef typename bigger_type_t<Element>::type BigElement;
def template NeonLoadExecute64 {{
Fault %(class_name)s::execute(
- %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
def template NeonLoadInitiateAcc64 {{
Fault %(class_name)s::initiateAcc(
- %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
def template NeonLoadCompleteAcc64 {{
Fault %(class_name)s::completeAcc(
- PacketPtr pkt, %(CPU_exec_context)s *xc,
+ PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template NeonStoreExecute64 {{
Fault %(class_name)s::execute(
- %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
def template NeonStoreInitiateAcc64 {{
Fault %(class_name)s::initiateAcc(
- %(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = NoFault;
def template NeonStoreCompleteAcc64 {{
Fault %(class_name)s::completeAcc(
- PacketPtr pkt, %(CPU_exec_context)s *xc,
+ PacketPtr pkt, CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return NoFault;
}};
def template MicroNeonMixExecute64 {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template PredOpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
uint64_t resTemp = 0;
}};
def template QuiescePredOpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
uint64_t resTemp = 0;
}};
def template QuiescePredOpExecuteWithFixup {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
uint64_t resTemp = 0;
#
# Authors: Steve Reinhardt
+from __future__ import with_statement
import os
import sys
import re
self.parser = parser
self.header_output = parser.expandCpuSymbolsToString(header_output)
self.decoder_output = parser.expandCpuSymbolsToString(decoder_output)
- if isinstance(exec_output, dict):
- self.exec_output = exec_output
- elif isinstance(exec_output, str):
- # If the exec_output arg is a single string, we replicate
- # it for each of the CPU models, substituting and
- # %(CPU_foo)s params appropriately.
- self.exec_output = parser.expandCpuSymbolsToDict(exec_output)
- self.decode_block = parser.expandCpuSymbolsToString(decode_block)
+ self.exec_output = exec_output
+ self.decode_block = decode_block
self.has_decode_default = has_decode_default
+ # Write these code chunks out to the filesystem. They will be properly
+ # interwoven by the write_top_level_files().
+ def emit(self):
+ if self.header_output:
+ self.parser.get_file('header').write(self.header_output)
+ if self.decoder_output:
+ self.parser.get_file('decoder').write(self.decoder_output)
+ if self.exec_output:
+ self.parser.get_file('exec').write(self.exec_output)
+ if self.decode_block:
+ self.parser.get_file('decode_block').write(self.decode_block)
+
# Override '+' operator: generate a new GenCode object that
# concatenates all the individual strings in the operands.
def __add__(self, other):
- exec_output = {}
- for cpu in self.parser.cpuModels:
- n = cpu.name
- exec_output[n] = self.exec_output[n] + other.exec_output[n]
return GenCode(self.parser,
self.header_output + other.header_output,
self.decoder_output + other.decoder_output,
- exec_output,
+ self.exec_output + other.exec_output,
self.decode_block + other.decode_block,
self.has_decode_default or other.has_decode_default)
self.header_output = pre + self.header_output
self.decoder_output = pre + self.decoder_output
self.decode_block = pre + self.decode_block
- for cpu in self.parser.cpuModels:
- self.exec_output[cpu.name] = pre + self.exec_output[cpu.name]
+ self.exec_output = pre + self.exec_output
# Wrap the decode block in a pair of strings (e.g., 'case foo:'
# and 'break;'). Used to build the big nested switch statement.
#######################
#
-# Output file template
+# ISA Parser
+# parses ISA DSL and emits C++ headers and source
#
-file_template = '''
-/*
- * DO NOT EDIT THIS FILE!!!
- *
- * It was automatically generated from the ISA description in %(filename)s
- */
-
-%(includes)s
-
-%(global_output)s
-
-namespace %(namespace)s {
-
-%(namespace_output)s
-
-} // namespace %(namespace)s
-
-%(decode_function)s
-'''
-
-max_inst_regs_template = '''
-/*
- * DO NOT EDIT THIS FILE!!!
- *
- * It was automatically generated from the ISA description in %(filename)s
- */
-
-namespace %(namespace)s {
-
- const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
- const int MaxInstDestRegs = %(MaxInstDestRegs)d;
- const int MaxMiscDestRegs = %(MaxMiscDestRegs)d;
-
-} // namespace %(namespace)s
-
-'''
-
class ISAParser(Grammar):
def __init__(self, output_dir, cpu_models):
super(ISAParser, self).__init__()
self.output_dir = output_dir
+ self.filename = None # for output file watermarking/scaremongering
+
self.cpuModels = cpu_models
# variable to hold templates
# This dictionary maps format name strings to Format objects.
self.formatMap = {}
+ # Track open files and, if applicable, how many chunks it has been
+ # split into so far.
+ self.files = {}
+ self.splits = {}
+
+ # isa_name / namespace identifier from namespace declaration.
+ # before the namespace declaration, None.
+ self.isa_name = None
+ self.namespace = None
+
# The format stack.
self.formatStack = Stack(NoFormat())
self.maxInstDestRegs = 0
self.maxMiscDestRegs = 0
+ def __getitem__(self, i): # Allow object (self) to be
+ return getattr(self, i) # passed to %-substitutions
+
+ # Change the file suffix of a base filename:
+ # (e.g.) decoder.cc -> decoder-g.cc.inc for 'global' outputs
+ def suffixize(self, s, sec):
+ extn = re.compile('(\.[^\.]+)$') # isolate extension
+ if self.namespace:
+ return extn.sub(r'-ns\1.inc', s) # insert some text on either side
+ else:
+ return extn.sub(r'-g\1.inc', s)
+
+ # Get the file object for emitting code into the specified section
+ # (header, decoder, exec, decode_block).
+ def get_file(self, section):
+ if section == 'decode_block':
+ filename = 'decode-method.cc.inc'
+ else:
+ if section == 'header':
+ file = 'decoder.hh'
+ else:
+ file = '%s.cc' % section
+ filename = self.suffixize(file, section)
+ try:
+ return self.files[filename]
+ except KeyError: pass
+
+ f = self.open(filename)
+ self.files[filename] = f
+
+ # The splittable files are the ones with many independent
+ # per-instruction functions - the decoder's instruction constructors
+ # and the instruction execution (execute()) methods. These both have
+ # the suffix -ns.cc.inc, meaning they are within the namespace part
+ # of the ISA, contain object-emitting C++ source, and are included
+ # into other top-level files. These are the files that need special
+ # #define's to allow parts of them to be compiled separately. Rather
+ # than splitting the emissions into separate files, the monolithic
+ # output of the ISA parser is maintained, but the value (or lack
+ # thereof) of the __SPLIT definition during C preprocessing will
+ # select the different chunks. If no 'split' directives are used,
+ # the cpp emissions have no effect.
+ if re.search('-ns.cc.inc$', filename):
+ print >>f, '#if !defined(__SPLIT) || (__SPLIT == 1)'
+ self.splits[f] = 1
+ # ensure requisite #include's
+ elif filename in ['decoder-g.cc.inc', 'exec-g.cc.inc']:
+ print >>f, '#include "decoder.hh"'
+ elif filename == 'decoder-g.hh.inc':
+ print >>f, '#include "base/bitfield.hh"'
+
+ return f
+
+ # Weave together the parts of the different output sections by
+ # #include'ing them into some very short top-level .cc/.hh files.
+ # These small files make it much clearer how this tool works, since
+ # you directly see the chunks emitted as files that are #include'd.
+ def write_top_level_files(self):
+ dep = self.open('inc.d', bare=True)
+
+ # decoder header - everything depends on this
+ file = 'decoder.hh'
+ with self.open(file) as f:
+ inc = []
+
+ fn = 'decoder-g.hh.inc'
+ assert(fn in self.files)
+ f.write('#include "%s"\n' % fn)
+ inc.append(fn)
+
+ fn = 'decoder-ns.hh.inc'
+ assert(fn in self.files)
+ f.write('namespace %s {\n#include "%s"\n}\n'
+ % (self.namespace, fn))
+ inc.append(fn)
+
+ print >>dep, file+':', ' '.join(inc)
+
+ # decoder method - cannot be split
+ file = 'decoder.cc'
+ with self.open(file) as f:
+ inc = []
+
+ fn = 'decoder-g.cc.inc'
+ assert(fn in self.files)
+ f.write('#include "%s"\n' % fn)
+ inc.append(fn)
+
+ fn = 'decode-method.cc.inc'
+ # is guaranteed to have been written for parse to complete
+ f.write('#include "%s"\n' % fn)
+ inc.append(fn)
+
+ inc.append("decoder.hh")
+ print >>dep, file+':', ' '.join(inc)
+
+ extn = re.compile('(\.[^\.]+)$')
+
+ # instruction constructors
+ splits = self.splits[self.get_file('decoder')]
+ file_ = 'inst-constrs.cc'
+ for i in range(1, splits+1):
+ if splits > 1:
+ file = extn.sub(r'-%d\1' % i, file_)
+ else:
+ file = file_
+ with self.open(file) as f:
+ inc = []
+
+ fn = 'decoder-g.cc.inc'
+ assert(fn in self.files)
+ f.write('#include "%s"\n' % fn)
+ inc.append(fn)
+
+ fn = 'decoder-ns.cc.inc'
+ assert(fn in self.files)
+ print >>f, 'namespace %s {' % self.namespace
+ if splits > 1:
+ print >>f, '#define __SPLIT %u' % i
+ print >>f, '#include "%s"' % fn
+ print >>f, '}'
+ inc.append(fn)
+
+ inc.append("decoder.hh")
+ print >>dep, file+':', ' '.join(inc)
+
+ # instruction execution per-CPU model
+ splits = self.splits[self.get_file('exec')]
+ for cpu in self.cpuModels:
+ for i in range(1, splits+1):
+ if splits > 1:
+ file = extn.sub(r'_%d\1' % i, cpu.filename)
+ else:
+ file = cpu.filename
+ with self.open(file) as f:
+ inc = []
+
+ fn = 'exec-g.cc.inc'
+ assert(fn in self.files)
+ f.write('#include "%s"\n' % fn)
+ inc.append(fn)
+
+ f.write(cpu.includes+"\n")
+
+ fn = 'exec-ns.cc.inc'
+ assert(fn in self.files)
+ print >>f, 'namespace %s {' % self.namespace
+ print >>f, '#define CPU_EXEC_CONTEXT %s' \
+ % cpu.strings['CPU_exec_context']
+ if splits > 1:
+ print >>f, '#define __SPLIT %u' % i
+ print >>f, '#include "%s"' % fn
+ print >>f, '}'
+ inc.append(fn)
+
+ inc.append("decoder.hh")
+ print >>dep, file+':', ' '.join(inc)
+
+ # max_inst_regs.hh
+ self.update('max_inst_regs.hh',
+ '''namespace %(namespace)s {
+ const int MaxInstSrcRegs = %(maxInstSrcRegs)d;
+ const int MaxInstDestRegs = %(maxInstDestRegs)d;
+ const int MaxMiscDestRegs = %(maxMiscDestRegs)d;\n}\n''' % self)
+ print >>dep, 'max_inst_regs.hh:'
+
+ dep.close()
+
+
+ scaremonger_template ='''// DO NOT EDIT
+// This file was automatically generated from an ISA description:
+// %(filename)s
+
+''';
+
#####################################################################
#
# Lexer
reserved = (
'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
- 'OUTPUT', 'SIGNED', 'TEMPLATE'
+ 'OUTPUT', 'SIGNED', 'SPLIT', 'TEMPLATE'
)
# List of tokens. The lex module requires this.
# after will be inside. The decoder function is always inside the
# namespace.
def p_specification(self, t):
- 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
- global_code = t[1]
- isa_name = t[2]
- namespace = isa_name + "Inst"
- # wrap the decode block as a function definition
- t[4].wrap_decode_block('''
-StaticInstPtr
-%(isa_name)s::Decoder::decodeInst(%(isa_name)s::ExtMachInst machInst)
-{
- using namespace %(namespace)s;
-''' % vars(), '}')
- # both the latter output blocks and the decode block are in
- # the namespace
- namespace_code = t[3] + t[4]
- # pass it all back to the caller of yacc.parse()
- t[0] = (isa_name, namespace, global_code, namespace_code)
+ 'specification : opt_defs_and_outputs top_level_decode_block'
- # ISA name declaration looks like "namespace <foo>;"
- def p_name_decl(self, t):
- 'name_decl : NAMESPACE ID SEMI'
- t[0] = t[2]
+ for f in self.splits.iterkeys():
+ f.write('\n#endif\n')
- # 'opt_defs_and_outputs' is a possibly empty sequence of
- # def and/or output statements.
+ for f in self.files.itervalues(): # close ALL the files;
+ f.close() # not doing so can cause compilation to fail
+
+ self.write_top_level_files()
+
+ t[0] = True
+
+ # 'opt_defs_and_outputs' is a possibly empty sequence of def and/or
+ # output statements. Its productions do the hard work of eventually
+ # instantiating a GenCode, which are generally emitted (written to disk)
+ # as soon as possible, except for the decode_block, which has to be
+ # accumulated into one large function of nested switch/case blocks.
def p_opt_defs_and_outputs_0(self, t):
'opt_defs_and_outputs : empty'
- t[0] = GenCode(self)
def p_opt_defs_and_outputs_1(self, t):
'opt_defs_and_outputs : defs_and_outputs'
- t[0] = t[1]
def p_defs_and_outputs_0(self, t):
'defs_and_outputs : def_or_output'
- t[0] = t[1]
def p_defs_and_outputs_1(self, t):
'defs_and_outputs : defs_and_outputs def_or_output'
- t[0] = t[1] + t[2]
# The list of possible definition/output statements.
+ # They are all processed as they are seen.
def p_def_or_output(self, t):
- '''def_or_output : def_format
+ '''def_or_output : name_decl
+ | def_format
| def_bitfield
| def_bitfield_struct
| def_template
| def_operand_types
| def_operands
- | output_header
- | output_decoder
- | output_exec
- | global_let'''
+ | output
+ | global_let
+ | split'''
+
+ # Utility function used by both invocations of splitting - explicit
+ # 'split' keyword and split() function inside "let {{ }};" blocks.
+ def split(self, sec, write=False):
+ assert(sec != 'header' and "header cannot be split")
+
+ f = self.get_file(sec)
+ self.splits[f] += 1
+ s = '\n#endif\n#if __SPLIT == %u\n' % self.splits[f]
+ if write:
+ f.write(s)
+ else:
+ return s
+
+ # split output file to reduce compilation time
+ def p_split(self, t):
+ 'split : SPLIT output_type SEMI'
+ assert(self.isa_name and "'split' not allowed before namespace decl")
+
+ self.split(t[2], True)
+
+ def p_output_type(self, t):
+ '''output_type : DECODER
+ | HEADER
+ | EXEC'''
t[0] = t[1]
+ # ISA name declaration looks like "namespace <foo>;"
+ def p_name_decl(self, t):
+ 'name_decl : NAMESPACE ID SEMI'
+ assert(self.isa_name == None and "Only 1 namespace decl permitted")
+ self.isa_name = t[2]
+ self.namespace = t[2] + 'Inst'
+
# Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
# directly to the appropriate output section.
s = self.protectCpuSymbols(s)
return substBitOps(s % self.templateMap)
- def p_output_header(self, t):
- 'output_header : OUTPUT HEADER CODELIT SEMI'
- t[0] = GenCode(self, header_output = self.process_output(t[3]))
-
- def p_output_decoder(self, t):
- 'output_decoder : OUTPUT DECODER CODELIT SEMI'
- t[0] = GenCode(self, decoder_output = self.process_output(t[3]))
-
- def p_output_exec(self, t):
- 'output_exec : OUTPUT EXEC CODELIT SEMI'
- t[0] = GenCode(self, exec_output = self.process_output(t[3]))
+ def p_output(self, t):
+ 'output : OUTPUT output_type CODELIT SEMI'
+ kwargs = { t[2]+'_output' : self.process_output(t[3]) }
+ GenCode(self, **kwargs).emit()
# global let blocks 'let {{...}}' (Python code blocks) are
# executed directly when seen. Note that these execute in a
# from polluting this script's namespace.
def p_global_let(self, t):
'global_let : LET CODELIT SEMI'
+ def _split(sec):
+ return self.split(sec)
self.updateExportContext()
self.exportContext["header_output"] = ''
self.exportContext["decoder_output"] = ''
self.exportContext["exec_output"] = ''
self.exportContext["decode_block"] = ''
+ self.exportContext["split"] = _split
+ split_setup = '''
+def wrap(func):
+ def split(sec):
+ globals()[sec + '_output'] += func(sec)
+ return split
+split = wrap(split)
+del wrap
+'''
+ # This tricky setup (immediately above) allows us to just write
+ # (e.g.) "split('exec')" in the Python code and the split #ifdef's
+ # will automatically be added to the exec_output variable. The inner
+ # Python execution environment doesn't know about the split points,
+ # so we carefully inject and wrap a closure that can retrieve the
+ # next split's #define from the parser and add it to the current
+ # emission-in-progress.
try:
- exec fixPythonIndentation(t[2]) in self.exportContext
+ exec split_setup+fixPythonIndentation(t[2]) in self.exportContext
except Exception, exc:
if debug:
raise
error(t, 'error: %s in global let block "%s".' % (exc, t[2]))
- t[0] = GenCode(self,
- header_output=self.exportContext["header_output"],
- decoder_output=self.exportContext["decoder_output"],
- exec_output=self.exportContext["exec_output"],
- decode_block=self.exportContext["decode_block"])
+ GenCode(self,
+ header_output=self.exportContext["header_output"],
+ decoder_output=self.exportContext["decoder_output"],
+ exec_output=self.exportContext["exec_output"],
+ decode_block=self.exportContext["decode_block"]).emit()
# Define the mapping from operand type extensions to C++ types and
# bit widths (stored in operandTypeMap).
raise
error(t,
'error: %s in def operand_types block "%s".' % (exc, t[3]))
- t[0] = GenCode(self) # contributes nothing to the output C++ file
# Define the mapping from operand names to operand classes and
# other traits. Stored in operandNameMap.
raise
error(t, 'error: %s in def operands block "%s".' % (exc, t[3]))
self.buildOperandNameMap(user_dict, t.lexer.lineno)
- t[0] = GenCode(self) # contributes nothing to the output C++ file
# A bitfield definition looks like:
# 'def [signed] bitfield <ID> [<first>:<last>]'
if (t[2] == 'signed'):
expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr)
hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
- t[0] = GenCode(self, header_output=hash_define)
+ GenCode(self, header_output=hash_define).emit()
# alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
def p_def_bitfield_1(self, t):
if (t[2] == 'signed'):
expr = 'sext<%d>(%s)' % (1, expr)
hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
- t[0] = GenCode(self, header_output=hash_define)
+ GenCode(self, header_output=hash_define).emit()
# alternate form for structure member: 'def bitfield <ID> <ID>'
def p_def_bitfield_struct(self, t):
error(t, 'error: structure bitfields are always unsigned.')
expr = 'machInst.%s' % t[5]
hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
- t[0] = GenCode(self, header_output=hash_define)
+ GenCode(self, header_output=hash_define).emit()
def p_id_with_dot_0(self, t):
'id_with_dot : ID'
def p_def_template(self, t):
'def_template : DEF TEMPLATE ID CODELIT SEMI'
+ if t[3] in self.templateMap:
+ print "warning: template %s already defined" % t[3]
self.templateMap[t[3]] = Template(self, t[4])
- t[0] = GenCode(self)
# An instruction format definition looks like
# "def format <fmt>(<params>) {{...}};"
'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
(id, params, code) = (t[3], t[5], t[7])
self.defFormat(id, params, code, t.lexer.lineno)
- t[0] = GenCode(self)
# The formal parameter list for an instruction format is a
# possibly empty list of comma-separated parameters. Positional
# A decode block looks like:
# decode <field1> [, <field2>]* [default <inst>] { ... }
#
+ def p_top_level_decode_block(self, t):
+ 'top_level_decode_block : decode_block'
+ codeObj = t[1]
+ codeObj.wrap_decode_block('''
+StaticInstPtr
+%(isa_name)s::Decoder::decodeInst(%(isa_name)s::ExtMachInst machInst)
+{
+ using namespace %(namespace)s;
+''' % self, '}')
+
+ codeObj.emit()
+
def p_decode_block(self, t):
'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
default_defaults = self.defaultStack.pop()
else:
return s
+ def open(self, name, bare=False):
+ '''Open the output file for writing and include scary warning.'''
+ filename = os.path.join(self.output_dir, name)
+ f = open(filename, 'w')
+ if f:
+ if not bare:
+ f.write(ISAParser.scaremonger_template % self)
+ return f
+
def update(self, file, contents):
- '''Update the output file. If the contents are unchanged,
- the scons hash feature will avoid recompilation.'''
- file = os.path.join(self.output_dir, file)
- f = open(file, 'w')
+ '''Update the output file only. Scons should handle the case when
+ the new contents are unchanged using its built-in hash feature.'''
+ f = self.open(file)
f.write(contents)
f.close()
self.fileNameStack.pop()
return contents
+ AlreadyGenerated = {}
+
def _parse_isa_desc(self, isa_desc_file):
'''Read in and parse the ISA description.'''
+ # The build system can end up running the ISA parser twice: once to
+ # finalize the build dependencies, and then to actually generate
+ # the files it expects (in src/arch/$ARCH/generated). This code
+ # doesn't do anything different either time, however; the SCons
+ # invocations just expect different things. Since this code runs
+ # within SCons, we can just remember that we've already run and
+ # not perform a completely unnecessary run, since the ISA parser's
+ # effect is idempotent.
+ if isa_desc_file in ISAParser.AlreadyGenerated:
+ return
+
+ # grab the last three path components of isa_desc_file
+ self.filename = '/'.join(isa_desc_file.split('/')[-3:])
+
# Read file and (recursively) all included files into a string.
# PLY requires that the input be in a single string so we have to
# do this up front.
# Initialize filename stack with outer file.
self.fileNameStack.push((isa_desc_file, 0))
- # Parse it.
- (isa_name, namespace, global_code, namespace_code) = \
- self.parse_string(isa_desc)
-
- # grab the last three path components of isa_desc_file to put in
- # the output
- filename = '/'.join(isa_desc_file.split('/')[-3:])
-
- # generate decoder.hh
- includes = '#include "base/bitfield.hh" // for bitfield support'
- global_output = global_code.header_output
- namespace_output = namespace_code.header_output
- decode_function = ''
- self.update('decoder.hh', file_template % vars())
-
- # generate decoder.cc
- includes = '#include "decoder.hh"'
- global_output = global_code.decoder_output
- namespace_output = namespace_code.decoder_output
- # namespace_output += namespace_code.decode_block
- decode_function = namespace_code.decode_block
- self.update('decoder.cc', file_template % vars())
-
- # generate per-cpu exec files
- for cpu in self.cpuModels:
- includes = '#include "decoder.hh"\n'
- includes += cpu.includes
- global_output = global_code.exec_output[cpu.name]
- namespace_output = namespace_code.exec_output[cpu.name]
- decode_function = ''
- self.update(cpu.filename, file_template % vars())
-
- # The variable names here are hacky, but this will creat local
- # variables which will be referenced in vars() which have the
- # value of the globals.
- MaxInstSrcRegs = self.maxInstSrcRegs
- MaxInstDestRegs = self.maxInstDestRegs
- MaxMiscDestRegs = self.maxMiscDestRegs
- # max_inst_regs.hh
- self.update('max_inst_regs.hh',
- max_inst_regs_template % vars())
+ # Parse.
+ self.parse_string(isa_desc)
+
+ ISAParser.AlreadyGenerated[isa_desc_file] = None
def parse_isa_desc(self, *args, **kwargs):
try:
DebugFlag('MipsPRA')
- # Add in files generated by the ISA description.
- isa_desc_files = env.ISADesc('isa/main.isa')
- # Only non-header files need to be compiled.
- for f in isa_desc_files:
- if not f.path.endswith('.hh'):
- Source(f)
+ env.ISADesc('isa/main.isa')
// Basic instruction class execute method template.
def template BasicExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
// Basic instruction class execute method template.
def template CP0Execute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
}};
def template CP1Execute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
}};
// Basic instruction class execute method template.
def template ControlTLBExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
output exec {{
bool
- isCoprocessorEnabled(%(CPU_exec_context)s *xc, unsigned cop_num)
+ isCoprocessorEnabled(CPU_EXEC_CONTEXT *xc, unsigned cop_num)
{
if (!FullSystem)
return true;
}
bool inline
- isCoprocessor0Enabled(%(CPU_exec_context)s *xc)
+ isCoprocessor0Enabled(CPU_EXEC_CONTEXT *xc)
{
if (FullSystem) {
MiscReg Stat = xc->readMiscReg(MISCREG_STATUS);
}
bool
- isMMUTLB(%(CPU_exec_context)s *xc)
+ isMMUTLB(CPU_EXEC_CONTEXT *xc)
{
MiscReg Config = xc->readMiscReg(MISCREG_CONFIG);
return FullSystem && (Config & 0x380) == 0x80;
// Dsp instruction class execute method template.
def template DspExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
// DspHiLo instruction class execute method template.
def template DspHiLoExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
output exec {{
bool
- isDspEnabled(%(CPU_exec_context)s *xc)
+ isDspEnabled(CPU_EXEC_CONTEXT *xc)
{
return !FullSystem || bits(xc->readMiscReg(MISCREG_STATUS), 24);
}
output exec {{
bool
- isDspPresent(%(CPU_exec_context)s *xc)
+ isDspPresent(CPU_EXEC_CONTEXT *xc)
{
return !FullSystem || bits(xc->readMiscReg(MISCREG_CONFIG3), 10);
}
}};
output exec {{
- inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ inline Fault checkFpEnableFault(CPU_EXEC_CONTEXT *xc)
{
//@TODO: Implement correct CP0 checks to see if the CP1
// unit is enable or not
//If any operand is Nan return the appropriate QNaN
template <class T>
bool
- fpNanOperands(FPOp *inst, %(CPU_exec_context)s *xc, const T &src_type,
+ fpNanOperands(FPOp *inst, CPU_EXEC_CONTEXT *xc, const T &src_type,
Trace::InstRecord *traceData)
{
uint64_t mips_nan = 0;
template <class T>
bool
- fpInvalidOp(FPOp *inst, %(CPU_exec_context)s *cpu, const T dest_val,
+ fpInvalidOp(FPOp *inst, CPU_EXEC_CONTEXT *cpu, const T dest_val,
Trace::InstRecord *traceData)
{
uint64_t mips_nan = 0;
}
void
- fpResetCauseBits(%(CPU_exec_context)s *cpu)
+ fpResetCauseBits(CPU_EXEC_CONTEXT *cpu)
{
//Read FCSR from FloatRegFile
uint32_t fcsr = cpu->tcBase()->readFloatRegBits(FLOATREG_FCSR);
}};
def template FloatingPointExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
// HiLo instruction class execute method template.
def template HiLoExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
// HiLoRsSel instruction class execute method template.
def template HiLoRsSelExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
// HiLoRdSel instruction class execute method template.
def template HiLoRdSelExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
/** return data in cases where there the size of data is only
known in the packet
*/
- uint64_t getMemData(%(CPU_exec_context)s *xc, Packet *packet) {
+ uint64_t getMemData(CPU_EXEC_CONTEXT *xc, Packet *packet) {
switch (packet->getSize())
{
case 1:
def template EACompExecute {{
Fault
- %(class_name)s::eaComp(%(CPU_exec_context)s *xc,
+ %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template LoadExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template LoadInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template LoadCompleteAcc {{
Fault %(class_name)s::completeAcc(Packet *pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template StoreExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template StoreFPExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template StoreCondExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template StoreInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template StoreCompleteAcc {{
Fault %(class_name)s::completeAcc(Packet *pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return NoFault;
def template StoreCondCompleteAcc {{
Fault %(class_name)s::completeAcc(Packet *pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template MiscExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA M5_VAR_USED = 0;
}};
def template MiscInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("Misc instruction does not support split access method!");
def template MiscCompleteAcc {{
Fault %(class_name)s::completeAcc(Packet *pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("Misc instruction does not support split access method!");
}};
output exec {{
- void getThrRegExValues(%(CPU_exec_context)s *xc,
+ void getThrRegExValues(CPU_EXEC_CONTEXT *xc,
VPEConf0Reg &vpe_conf0, TCBindReg &tc_bind_mt,
TCBindReg &tc_bind, VPEControlReg &vpe_control,
MVPConf0Reg &mvp_conf0)
mvp_conf0 = xc->readMiscReg(MISCREG_MVP_CONF0);
}
- void getMTExValues(%(CPU_exec_context)s *xc, Config3Reg &config3)
+ void getMTExValues(CPU_EXEC_CONTEXT *xc, Config3Reg &config3)
{
config3 = xc->readMiscReg(MISCREG_CONFIG3);
}
}};
def template ThreadRegisterExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
int64_t data M5_VAR_USED;
}};
def template MTExecute{{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
output exec {{
Fault
- Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
+ Nop::execute(CPU_EXEC_CONTEXT *, Trace::InstRecord *) const
{
return NoFault;
}
}};
def template TlbOpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
//Write the resulting state to the execution context
%(op_wb)s;
def template TrapExecute {{
//Edit This Template When Traps Are Implemented
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
//Write the resulting state to the execution context
%(op_wb)s;
output exec {{
Fault
- FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ FailUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("attempt to execute unimplemented instruction '%s' "
}
Fault
- CP0Unimplemented::execute(%(CPU_exec_context)s *xc,
+ CP0Unimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (FullSystem) {
}
Fault
- CP1Unimplemented::execute(%(CPU_exec_context)s *xc,
+ CP1Unimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (FullSystem) {
}
Fault
- CP2Unimplemented::execute(%(CPU_exec_context)s *xc,
+ CP2Unimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (FullSystem) {
}
Fault
- WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ WarnUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (!warned) {
output exec {{
Fault
- Unknown::execute(%(CPU_exec_context)s *xc,
+ Unknown::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return new ReservedInstructionFault;
DebugFlag('Power')
- # Add in files generated by the ISA description.
- isa_desc_files = env.ISADesc('isa/main.isa')
-
- # Only non-header files need to be compiled.
- for f in isa_desc_files:
- if not f.path.endswith('.hh'):
- Source(f)
-
+ env.ISADesc('isa/main.isa')
// Basic instruction class execute method template.
def template BasicExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template LoadExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template LoadInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template LoadCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr M5_VAR_USED EA;
def template StoreExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template StoreInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
def template StoreCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s *xc,
+ CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return NoFault;
//
def template MiscOpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
%(op_decl)s;
output exec {{
Fault
- FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ FailUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("attempt to execute unimplemented instruction '%s' "
}
Fault
- WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ WarnUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (!warned) {
output exec {{
Fault
- Unknown::execute(%(CPU_exec_context)s *xc,
+ Unknown::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("attempt to execute unknown instruction at %#x"
DebugFlag('Sparc', "Generic SPARC ISA stuff")
DebugFlag('RegisterWindows', "Register window manipulation")
- # Add in files generated by the ISA description.
- isa_desc_files = env.ISADesc('isa/main.isa')
- # Only non-header files need to be compiled.
- for f in isa_desc_files:
- if not f.path.endswith('.hh'):
- Source(f)
+ env.ISADesc('isa/main.isa')
/// @retval Full-system mode: NoFault if FP is enabled, FpDisabled
/// if not. Non-full-system mode: always returns NoFault.
static inline Fault
- checkFpEnableFault(%(CPU_exec_context)s *xc)
+ checkFpEnableFault(CPU_EXEC_CONTEXT *xc)
{
if (FullSystem) {
PSTATE pstate = xc->readMiscReg(MISCREG_PSTATE);
// Basic instruction class execute method template.
def template BasicExecute {{
Fault
- %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template DoFpOpExecute {{
Fault
- %(class_name)s::doFpOp(%(CPU_exec_context)s *xc,
+ %(class_name)s::doFpOp(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template JumpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
// Attempt to execute the instruction
def template BranchExecute {{
Fault
- %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
// Attempt to execute the instruction
}};
def template IntOpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
// This template provides the execute functions for a swap
def template SwapExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template SwapInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
def template SwapCompleteAcc {{
- Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc,
+ Fault %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
// This template provides the execute functions for a load
def template LoadExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template LoadInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
}};
def template LoadCompleteAcc {{
- Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc,
+ Fault %(class_name)s::completeAcc(PacketPtr pkt, CPU_EXEC_CONTEXT * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
// This template provides the execute functions for a store
def template StoreExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template StoreInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
}};
def template StoreCompleteAcc {{
- Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
+ Fault %(class_name)s::completeAcc(PacketPtr, CPU_EXEC_CONTEXT * xc,
Trace::InstRecord * traceData) const
{
return NoFault;
def template EACompExecute {{
Fault
- %(class_name)s::eaComp(%(CPU_exec_context)s *xc,
+ %(class_name)s::eaComp(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Addr EA;
}};
def template NopExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
// Nothing to see here, move along
}};
def template PrivExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
%(op_decl)s;
def template TrapExecute {{
Fault
- %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
def template FpUnimplExecute {{
Fault
- %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
output exec {{
Fault
- FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ FailUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("attempt to execute unimplemented instruction '%s' "
}
Fault
- WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ WarnUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (!warned) {
}};
output exec {{
- Fault Unknown::execute(%(CPU_exec_context)s *xc,
+ Fault Unknown::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return new IllegalInstruction;
# Add in python file dependencies that won't be caught otherwise
for pyfile in python_files:
env.Depends(f, "isa/insts/%s" % pyfile)
- # Only non-header files need to be compiled.
- if not f.path.endswith('.hh'):
- Source(f)
// Basic instruction class execute method template.
def template BasicExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template CPUIDExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
// If the CPUID instruction used a valid function number, this will
}};
def template NopExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return NoFault;
}};
def template SyscallExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
output exec {{
Fault
- FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ FailUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
panic("attempt to execute unimplemented instruction '%s' %s",
}
Fault
- WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ WarnUnimplemented::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
if (!warned) {
}};
output exec {{
- Fault Unknown::execute(%(CPU_exec_context)s *xc,
+ Fault Unknown::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
return new InvalidOpcode();
def template MicroDebugExecute {{
Fault
- %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
%(op_decl)s
//////////////////////////////////////////////////////////////////////////
def template MicroFpOpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
// LEA template
def template MicroLeaExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
// Load templates
def template MicroLoadExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template MicroLoadInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
def template MicroLoadCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s * xc,
+ CPU_EXEC_CONTEXT * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
// Store templates
def template MicroStoreExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s * xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT * xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template MicroStoreInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
+ Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc,
Trace::InstRecord * traceData) const
{
Fault fault = NoFault;
def template MicroStoreCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
- %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const
+ CPU_EXEC_CONTEXT * xc, Trace::InstRecord * traceData) const
{
%(op_decl)s;
%(op_rd)s;
//////////////////////////////////////////////////////////////////////////
def template MicroLimmOpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
%(op_decl)s;
// Authors: Gabe Black
def template MediaOpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
//////////////////////////////////////////////////////////////////////////
def template MicroRegOpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template MicroRegOpImmExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
}};
def template SeqOpExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
%(op_decl)s;
}};
def template MicroFaultExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord *traceData) const
{
%(op_decl)s;
output exec {{
Fault
- MicroHalt::execute(%(CPU_exec_context)s *xc,
+ MicroHalt::execute(CPU_EXEC_CONTEXT *xc,
Trace::InstRecord * traceData) const
{
xc->tcBase()->suspend();
def test_builder(env, ref_dir):
"""Define a test."""
- (category, mode, name, _ref, isa, opsys, config) = ref_dir.split('/')
- assert(_ref == 'ref')
+ path = list(ref_dir.split('/'))
- # target path (where test output goes) is the same except without
- # the 'ref' component
- tgt_dir = os.path.join(category, mode, name, isa, opsys, config)
+ # target path (where test output goes) consists of category, mode,
+ # name, isa, opsys, and config (skips the 'ref' component)
+ assert(path.pop(-4) == 'ref')
+ tgt_dir = os.path.join(*path[-6:])
- # prepend file name with tgt_dir
+ # local closure for prepending target path to filename
def tgt(f):
return os.path.join(tgt_dir, f)
else:
configs = [c + "-ruby-" + env['PROTOCOL'] for c in configs]
-cwd = os.getcwd()
-os.chdir(str(Dir('.').srcdir))
+src = Dir('.').srcdir
for config in configs:
- dirs = glob.glob('*/*/*/ref/%s/*/%s' % (env['TARGET_ISA'], config))
+ dirs = src.glob('*/*/*/ref/%s/*/%s' % (env['TARGET_ISA'], config))
for d in dirs:
+ d = str(d)
if not os.path.exists(os.path.join(d, 'skip')):
test_builder(env, d)
-os.chdir(cwd)