summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SConscript203
-rwxr-xr-xsrc/arch/isa_parser.py8
-rw-r--r--src/arch/sparc/isa/base.isa70
-rw-r--r--src/arch/sparc/isa/formats/basic.isa2
-rw-r--r--src/arch/sparc/isa/formats/mem/basicmem.isa4
-rw-r--r--src/arch/sparc/isa/formats/mem/blockmem.isa2
-rw-r--r--src/arch/sparc/isa/formats/mem/swap.isa10
-rw-r--r--src/arch/sparc/isa/formats/micro.isa33
-rw-r--r--src/arch/sparc/isa/operands.isa54
-rw-r--r--src/arch/x86/faults.hh20
-rw-r--r--src/arch/x86/intregs.hh84
-rw-r--r--src/arch/x86/isa/base.isa39
-rw-r--r--src/arch/x86/isa/decoder/one_byte_opcodes.isa30
-rw-r--r--src/arch/x86/isa/formats/multi.isa106
-rw-r--r--src/arch/x86/isa/includes.isa7
-rw-r--r--src/arch/x86/isa/macroop.isa164
-rw-r--r--src/arch/x86/isa/main.isa48
-rw-r--r--src/arch/x86/isa/microasm.isa125
-rw-r--r--src/arch/x86/isa/microops/base.isa194
-rw-r--r--src/arch/x86/isa/microops/microops.isa8
-rw-r--r--src/arch/x86/isa/operands.isa6
-rw-r--r--src/arch/x86/isa/specialize.isa164
-rw-r--r--src/arch/x86/predecoder.cc81
-rw-r--r--src/arch/x86/predecoder.hh2
-rw-r--r--src/arch/x86/predecoder_tables.cc18
-rw-r--r--src/arch/x86/types.hh67
-rw-r--r--src/arch/x86/utility.hh12
-rw-r--r--src/base/SConscript2
-rw-r--r--src/cpu/base_dyn_inst.hh5
-rw-r--r--src/cpu/exetrace.cc2
-rw-r--r--src/cpu/o3/alpha/cpu_impl.hh13
-rw-r--r--src/cpu/o3/commit.hh5
-rw-r--r--src/cpu/o3/commit_impl.hh32
-rw-r--r--src/cpu/o3/cpu.cc18
-rw-r--r--src/cpu/o3/cpu.hh3
-rw-r--r--src/cpu/o3/decode.hh5
-rw-r--r--src/cpu/o3/decode_impl.hh17
-rw-r--r--src/cpu/o3/fetch.hh5
-rw-r--r--src/cpu/o3/fetch_impl.hh52
-rw-r--r--src/cpu/o3/iew.hh23
-rw-r--r--src/cpu/o3/iew_impl.hh26
-rw-r--r--src/cpu/o3/inst_queue.hh8
-rw-r--r--src/cpu/o3/inst_queue_impl.hh15
-rw-r--r--src/cpu/o3/lsq.hh20
-rw-r--r--src/cpu/o3/lsq_impl.hh40
-rw-r--r--src/cpu/o3/lsq_unit.hh47
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh64
-rw-r--r--src/cpu/o3/mips/cpu_builder.cc4
-rw-r--r--src/cpu/o3/mips/cpu_impl.hh14
-rw-r--r--src/cpu/o3/regfile.hh23
-rw-r--r--src/cpu/o3/rename.hh5
-rw-r--r--src/cpu/o3/rename_impl.hh33
-rw-r--r--src/cpu/o3/rob.hh11
-rw-r--r--src/cpu/o3/rob_impl.hh26
-rw-r--r--src/cpu/o3/sparc/cpu_builder.cc7
-rw-r--r--src/cpu/o3/sparc/cpu_impl.hh14
-rw-r--r--src/cpu/simple/atomic.cc2
-rw-r--r--src/mem/bus.cc19
-rw-r--r--src/mem/bus.hh7
-rw-r--r--src/mem/cache/cache_impl.hh3
-rw-r--r--src/mem/port.cc1
-rw-r--r--src/python/SConscript202
-rw-r--r--src/python/m5/internal/__init__.py35
-rw-r--r--src/python/m5/params.py25
-rw-r--r--src/sim/process.cc8
65 files changed, 1651 insertions, 751 deletions
diff --git a/src/SConscript b/src/SConscript
index 5efd2f794..34c5453b7 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -30,28 +30,71 @@
import os
import sys
+import zipfile
+from os.path import basename
from os.path import join as joinpath
+import SCons
+
# This file defines how to build a particular configuration of M5
# based on variable settings in the 'env' build environment.
Import('*')
+# Children need to see the environment
+Export('env')
+
+########################################################################
+# Code for adding source files
+#
sources = []
-def Source(*args):
- for arg in args:
- if isinstance(arg, (list, tuple)):
- # Recurse to load a list
- Source(*arg)
- elif isinstance(arg, str):
- sources.extend([ File(f) for f in Split(arg) ])
- else:
- sources.append(File(arg))
+def Source(source):
+ if isinstance(source, SCons.Node.FS.File):
+ sources.append(source)
+ else:
+ sources.append(File(source))
-Export('env')
+# Children should have access
Export('Source')
+########################################################################
+# Code for adding python objects
+#
+py_sources = []
+py_source_packages = {}
+def PySource(package, source):
+ if not isinstance(source, SCons.Node.FS.File):
+ source = File(source)
+ py_source_packages[source] = package
+ py_sources.append(source)
+
+sim_objects = []
+def SimObject(source):
+ if not isinstance(source, SCons.Node.FS.File):
+ source = File(source)
+ PySource('m5.objects', source)
+ modname = basename(str(source))
+ sim_objects.append(modname)
+
+swig_sources = []
+swig_source_packages = {}
+def SwigSource(package, source):
+ if not isinstance(source, SCons.Node.FS.File):
+ source = File(source)
+ swig_source_packages[source] = package
+ swig_sources.append(source)
+
+# Children should have access
+Export('PySource')
+Export('SimObject')
+Export('SwigSource')
+
+########################################################################
+#
+# Set some compiler variables
+#
+
# Include file paths are rooted in this directory. SCons will
# automatically expand '.' to refer to both the source directory and
# the corresponding build directory to pick up generated include
@@ -61,7 +104,9 @@ env.Append(CPPPATH=Dir('.'))
# Add a flag defining what THE_ISA should be for all compilation
env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
+########################################################################
# Walk the tree and execute all SConscripts
+#
scripts = []
srcdir = env['SRCDIR']
for root, dirs, files in os.walk(srcdir, topdown=True):
@@ -78,6 +123,132 @@ for root, dirs, files in os.walk(srcdir, topdown=True):
for opt in env.ExportOptions:
env.ConfigFile(opt)
+########################################################################
+#
+# Deal with python/swig, object code. Collect .py files and
+# generating a zip archive that is appended to the m5 binary.
+#
+
+# Generate Python file that contains a dict specifying the current
+# build_env flags.
+def MakeDefinesPyFile(target, source, env):
+ f = file(str(target[0]), 'w')
+ print >>f, "m5_build_env = ", source[0]
+ f.close()
+
+optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
+env.Command('python/m5/defines.py', Value(optionDict), MakeDefinesPyFile)
+PySource('m5', 'python/m5/defines.py')
+
+def MakeInfoPyFile(target, source, env):
+ f = file(str(target[0]), 'w')
+ for src in source:
+ data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
+ print >>f, "%s = %s" % (src, repr(data))
+ f.close()
+
+env.Command('python/m5/info.py',
+ [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
+ MakeInfoPyFile)
+PySource('m5', 'python/m5/info.py')
+
+def MakeObjectsInitFile(target, source, env):
+ f = file(str(target[0]), 'w')
+ print >>f, 'from m5.SimObject import *'
+ for src_path in source:
+ src_file = basename(src_path.get_contents())
+ assert(src_file.endswith('.py'))
+ src_module = src_file[:-3]
+ print >>f, 'from %s import *' % src_module
+ f.close()
+
+env.Command('python/m5/objects/__init__.py',
+ [ Value(o) for o in sim_objects],
+ MakeObjectsInitFile)
+PySource('m5.objects', 'python/m5/objects/__init__.py')
+
+swig_modules = []
+for source in swig_sources:
+ source.rfile() # Hack to cause the symlink to the .i file to be created
+ package = swig_source_packages[source]
+ filename = str(source)
+ module = basename(filename)
+
+ assert(module.endswith('.i'))
+ module = module[:-2]
+ cc_file = 'swig/%s_wrap.cc' % module
+ py_file = 'm5/internal/%s.py' % module
+
+ env.Command([cc_file, py_file], source,
+ '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
+ '-o ${TARGETS[0]} $SOURCES')
+ env.Depends(py_file, source)
+ env.Depends(cc_file, source)
+
+ swig_modules.append(Value(module))
+ Source(cc_file)
+ PySource(package, py_file)
+
+def MakeSwigInit(target, source, env):
+ f = file(str(target[0]), 'w')
+ print >>f, 'extern "C" {'
+ for module in source:
+ print >>f, ' void init_%s();' % module.get_contents()
+ print >>f, '}'
+ print >>f, 'void init_swig() {'
+ for module in source:
+ print >>f, ' init_%s();' % module.get_contents()
+ print >>f, '}'
+ f.close()
+env.Command('python/swig/init.cc', swig_modules, MakeSwigInit)
+
+def CompilePyFile(target, source, env):
+ import py_compile
+ py_compile.compile(str(source[0]), str(target[0]))
+
+py_compiled = []
+py_arcname = {}
+py_zip_depends = []
+for source in py_sources:
+ filename = str(source)
+ package = py_source_packages[source]
+ arc_path = package.split('.') + [ basename(filename) + 'c' ]
+ zip_path = [ 'zip' ] + arc_path
+ arcname = joinpath(*arc_path)
+ zipname = joinpath(*zip_path)
+ f = File(zipname)
+
+ env.Command(f, source, CompilePyFile)
+ py_compiled.append(f)
+ py_arcname[f] = arcname
+
+ # make the zipfile depend on the archive name so that the archive
+ # is rebuilt if the name changes
+ py_zip_depends.append(Value(arcname))
+
+# Action function to build the zip archive. Uses the PyZipFile module
+# included in the standard Python library.
+def buildPyZip(target, source, env):
+ zf = zipfile.ZipFile(str(target[0]), 'w')
+ for s in source:
+ arcname = py_arcname[s]
+ zipname = str(s)
+ zf.write(zipname, arcname)
+ zf.close()
+
+# Add the zip file target to the environment.
+env.Command('m5py.zip', py_compiled, buildPyZip)
+env.Depends('m5py.zip', py_zip_depends)
+
+########################################################################
+#
+# Define binaries. Each different build type (debug, opt, etc.) gets
+# a slightly different build environment.
+#
+
+# List of constructed environments to pass back to SConstruct
+envList = []
+
# This function adds the specified sources to the given build
# environment, and returns a list of all the corresponding SCons
# Object nodes (including an extra one for date.cc). We explicitly
@@ -92,16 +263,6 @@ def make_objs(sources, env):
objs.append(date_obj)
return objs
-###################################################
-#
-# Define binaries. Each different build type (debug, opt, etc.) gets
-# a slightly different build environment.
-#
-###################################################
-
-# List of constructed environments to pass back to SConstruct
-envList = []
-
# 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
@@ -120,7 +281,7 @@ def makeEnv(label, objsfx, strip = False, **kwargs):
else:
newEnv.Command(stripped_bin, bin, 'strip $SOURCE -o $TARGET')
bin = stripped_bin
- targets = newEnv.Concat(exe, [bin, 'python/m5py.zip'])
+ targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
newEnv.M5Binary = targets[0]
envList.append(newEnv)
diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py
index a0d671da1..4c8d0706d 100755
--- a/src/arch/isa_parser.py
+++ b/src/arch/isa_parser.py
@@ -866,7 +866,11 @@ class Format:
context = {}
updateExportContext()
context.update(exportContext)
- context.update({ 'name': name, 'Name': string.capitalize(name) })
+ if len(name):
+ Name = name[0].upper()
+ if len(name) > 1:
+ Name += name[1:]
+ context.update({ 'name': name, 'Name': Name })
try:
vars = self.func(self.user_code, context, *args[0], **args[1])
except Exception, exc:
@@ -1028,7 +1032,7 @@ def substBitOps(code):
# Template objects are format strings that allow substitution from
# the attribute spaces of other objects (e.g. InstObjParams instances).
-labelRE = re.compile(r'[^%]%\(([^\)]+)\)[sd]')
+labelRE = re.compile(r'(?<!%)%\(([^\)]+)\)[sd]')
class Template:
def __init__(self, t):
diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa
index bba63f407..4339003e0 100644
--- a/src/arch/sparc/isa/base.isa
+++ b/src/arch/sparc/isa/base.isa
@@ -154,6 +154,76 @@ def template ROrImmDecode {{
}
}};
+output header {{
+ union DoubleSingle
+ {
+ double d;
+ uint64_t ui;
+ uint32_t s[2];
+ DoubleSingle(double _d) : d(_d)
+ {}
+ DoubleSingle(uint64_t _ui) : ui(_ui)
+ {}
+ DoubleSingle(uint32_t _s0, uint32_t _s1)
+ {
+ s[0] = _s0;
+ s[1] = _s1;
+ }
+ };
+}};
+
+let {{
+ def filterDoubles(code):
+ assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
+ for opName in ("Frd", "Frs1", "Frs2", "Frd_N"):
+ next_pos = 0
+ operandsREString = (r'''
+ (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
+ ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
+ (?![\w\.]) # neg. lookahead assertion: prevent partial matches
+ ''' % opName)
+ operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
+ is_src = False
+ is_dest = False
+ extension = None
+ foundOne = False
+ while 1:
+ match = operandsRE.search(code, next_pos)
+ if not match:
+ break
+ foundOne = True
+ op = match.groups()
+ (op_full, op_base, op_ext) = op
+ is_dest_local = (assignRE.match(code, match.end()) != None)
+ is_dest = is_dest or is_dest_local
+ is_src = is_src or not is_dest_local
+ if extension and extension != op_ext:
+ raise Exception, "Inconsistent extensions in double filter."
+ extension = op_ext
+ next_pos = match.end()
+ if foundOne:
+ # Get rid of any unwanted extension
+ code = operandsRE.sub(op_base, code)
+ is_int = False
+ member = "d"
+ if extension in ("sb", "ub", "shw", "uhw", "sw", "uw", "sdw", "udw"):
+ is_int = True
+ member = "ui"
+ if is_src:
+ code = ("%s = DoubleSingle(%s_high, %s_low).%s;" % \
+ (opName, opName, opName, member)) + code
+ if is_dest:
+ code += '''
+ %s_low = DoubleSingle(%s).s[1];
+ %s_high = DoubleSingle(%s).s[0];''' % \
+ (opName, opName, opName, opName)
+ if is_int:
+ code = ("uint64_t %s;" % opName) + code
+ else:
+ code = ("double %s;" % opName) + code
+ return code
+}};
+
let {{
def splitOutImm(code):
matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?')
diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa
index 017f43780..7665d2d4f 100644
--- a/src/arch/sparc/isa/formats/basic.isa
+++ b/src/arch/sparc/isa/formats/basic.isa
@@ -97,6 +97,7 @@ def template BasicDecodeWithMnemonic {{
// The most basic instruction format... used only for a few misc. insts
def format BasicOperate(code, *flags) {{
+ code = filterDoubles(code)
iop = InstObjParams(name, Name, 'SparcStaticInst', code, flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
@@ -140,6 +141,7 @@ def format FpBasic(code, *flags) {{
fesetround(oldrnd);
#endif
"""
+ fp_code = filterDoubles(fp_code)
iop = InstObjParams(name, Name, 'SparcStaticInst', fp_code, flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
diff --git a/src/arch/sparc/isa/formats/mem/basicmem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa
index 751262811..2f62c7bef 100644
--- a/src/arch/sparc/isa/formats/mem/basicmem.isa
+++ b/src/arch/sparc/isa/formats/mem/basicmem.isa
@@ -71,6 +71,7 @@ let {{
}};
def format LoadAlt(code, asi, *opt_flags) {{
+ code = filterDoubles(code)
(header_output,
decoder_output,
exec_output,
@@ -79,6 +80,7 @@ def format LoadAlt(code, asi, *opt_flags) {{
}};
def format StoreAlt(code, asi, *opt_flags) {{
+ code = filterDoubles(code)
(header_output,
decoder_output,
exec_output,
@@ -87,6 +89,7 @@ def format StoreAlt(code, asi, *opt_flags) {{
}};
def format Load(code, *opt_flags) {{
+ code = filterDoubles(code)
(header_output,
decoder_output,
exec_output,
@@ -95,6 +98,7 @@ def format Load(code, *opt_flags) {{
}};
def format Store(code, *opt_flags) {{
+ code = filterDoubles(code)
(header_output,
decoder_output,
exec_output,
diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa
index 499685a5c..e19016bd0 100644
--- a/src/arch/sparc/isa/formats/mem/blockmem.isa
+++ b/src/arch/sparc/isa/formats/mem/blockmem.isa
@@ -317,6 +317,7 @@ let {{
}};
def format BlockLoad(code, asi, *opt_flags) {{
+ code = filterDoubles(code)
# We need to make sure to check the highest priority fault last.
# That way, if other faults have been detected, they'll be overwritten
# rather than the other way around.
@@ -329,6 +330,7 @@ def format BlockLoad(code, asi, *opt_flags) {{
}};
def format BlockStore(code, asi, *opt_flags) {{
+ code = filterDoubles(code)
# We need to make sure to check the highest priority fault last.
# That way, if other faults have been detected, they'll be overwritten
# rather than the other way around.
diff --git a/src/arch/sparc/isa/formats/mem/swap.isa b/src/arch/sparc/isa/formats/mem/swap.isa
index 818597a84..b71542a2b 100644
--- a/src/arch/sparc/isa/formats/mem/swap.isa
+++ b/src/arch/sparc/isa/formats/mem/swap.isa
@@ -137,7 +137,7 @@ def format Swap(code, postacc_code, mem_flags, *opt_flags) {{
decoder_output,
exec_output,
decode_block) = doMemFormat(code, SwapFuncs, '', name, Name, flags,
- opt_flags, postacc_code)
+ ["IsStoreConditional"], postacc_code)
}};
def format SwapAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{
@@ -148,7 +148,7 @@ def format SwapAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{
decoder_output,
exec_output,
decode_block) = doMemFormat(code, SwapFuncs, AlternateASIPrivFaultCheck,
- name, Name, flags, opt_flags, postacc_code)
+ name, Name, flags, ["IsStoreConditional"], postacc_code)
}};
@@ -163,8 +163,8 @@ let {{
decode_block = BasicDecode.subst(iop)
microParams = {"code": code, "postacc_code" : postacc_code,
"ea_code" : addrCalcReg, "fault_check" : faultCode}
- exec_output = doSplitExecute(execute, name, Name, asi, opt_flags,
- microParams);
+ exec_output = doSplitExecute(execute, name, Name, asi,
+ ["IsStoreConditional"], microParams);
return (header_output, decoder_output, exec_output, decode_block)
}};
@@ -177,7 +177,7 @@ def format CasAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{
decoder_output,
exec_output,
decode_block) = doCasFormat(code, SwapFuncs, AlternateASIPrivFaultCheck,
- name, Name, flags, opt_flags, postacc_code)
+ name, Name, flags, ["IsStoreConditional"], postacc_code)
}};
diff --git a/src/arch/sparc/isa/formats/micro.isa b/src/arch/sparc/isa/formats/micro.isa
index 82d7fb4cb..da0f97d1b 100644
--- a/src/arch/sparc/isa/formats/micro.isa
+++ b/src/arch/sparc/isa/formats/micro.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2006 The Regents of The University of Michigan
+// Copyright (c) 2006-2007 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -26,6 +26,33 @@
//
// Authors: Gabe Black
+//This delcares the initiateAcc function in memory operations
+def template MacroInitiateAcc {{
+ Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const
+ {
+ panic("Tried to execute a macroop directly!\n");
+ return NoFault;
+ }
+}};
+
+def template MacroCompleteAcc {{
+ Fault completeAcc(PacketPtr, %(CPU_exec_context)s *,
+ Trace::InstRecord *) const
+ {
+ panic("Tried to execute a macroop directly!\n");
+ return NoFault;
+ }
+}};
+
+//This template provides the execute functions for a store
+def template MacroExecute {{
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
+ {
+ panic("Tried to execute a macroop directly!\n");
+ return NoFault;
+ }
+}};
+
output header {{
class SparcMacroInst : public SparcStaticInst
@@ -60,7 +87,9 @@ output header {{
return microOps[microPC];
}
- %(BasicExecPanic)s
+ %(MacroExecute)s
+ %(MacroInitiateAcc)s
+ %(MacroCompleteAcc)s
};
class SparcMicroInst : public SparcStaticInst
diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa
index 038919bd1..58d616a7a 100644
--- a/src/arch/sparc/isa/operands.isa
+++ b/src/arch/sparc/isa/operands.isa
@@ -52,6 +52,16 @@ output header {{
{
return (regNum & (~1)) | ((regNum & 1) << 5);
}
+
+ static inline unsigned int dfprl(unsigned int regNum)
+ {
+ return dfpr(regNum) & (~0x1);
+ }
+
+ static inline unsigned int dfprh(unsigned int regNum)
+ {
+ return dfpr(regNum) | 0x1;
+ }
}};
def operands {{
@@ -79,21 +89,43 @@ def operands {{
# differently, they get different operands. The single precision versions
# have an s post pended to their name.
'Frds': ('FloatReg', 'sf', 'RD', 'IsFloating', 10),
- 'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
+ #'Frd': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
+ 'Frd_low': ('FloatReg', 'uw', 'dfprl(RD)', 'IsFloating', 10),
+ 'Frd_high': ('FloatReg', 'uw', 'dfprh(RD)', 'IsFloating', 10),
# Each Frd_N refers to the Nth double precision register from Frd.
# Note that this adds twice N to the register number.
- 'Frd_0': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
- 'Frd_1': ('FloatReg', 'df', 'dfpr(RD) + 2', 'IsFloating', 10),
- 'Frd_2': ('FloatReg', 'df', 'dfpr(RD) + 4', 'IsFloating', 10),
- 'Frd_3': ('FloatReg', 'df', 'dfpr(RD) + 6', 'IsFloating', 10),
- 'Frd_4': ('FloatReg', 'df', 'dfpr(RD) + 8', 'IsFloating', 10),
- 'Frd_5': ('FloatReg', 'df', 'dfpr(RD) + 10', 'IsFloating', 10),
- 'Frd_6': ('FloatReg', 'df', 'dfpr(RD) + 12', 'IsFloating', 10),
- 'Frd_7': ('FloatReg', 'df', 'dfpr(RD) + 14', 'IsFloating', 10),
+ #'Frd_0': ('FloatReg', 'df', 'dfpr(RD)', 'IsFloating', 10),
+ 'Frd_0_low': ('FloatReg', 'uw', 'dfprl(RD)', 'IsFloating', 10),
+ 'Frd_0_high': ('FloatReg', 'uw', 'dfprh(RD)', 'IsFloating', 10),
+ #'Frd_1': ('FloatReg', 'df', 'dfpr(RD) + 2', 'IsFloating', 10),
+ 'Frd_1_low': ('FloatReg', 'uw', 'dfprl(RD) + 2', 'IsFloating', 10),
+ 'Frd_1_high': ('FloatReg', 'uw', 'dfprh(RD) + 2', 'IsFloating', 10),
+ #'Frd_2': ('FloatReg', 'df', 'dfpr(RD) + 4', 'IsFloating', 10),
+ 'Frd_2_low': ('FloatReg', 'uw', 'dfprl(RD) + 4', 'IsFloating', 10),
+ 'Frd_2_high': ('FloatReg', 'uw', 'dfprh(RD) + 4', 'IsFloating', 10),
+ #'Frd_3': ('FloatReg', 'df', 'dfpr(RD) + 6', 'IsFloating', 10),
+ 'Frd_3_low': ('FloatReg', 'uw', 'dfprl(RD) + 6', 'IsFloating', 10),
+ 'Frd_3_high': ('FloatReg', 'uw', 'dfprh(RD) + 6', 'IsFloating', 10),
+ #'Frd_4': ('FloatReg', 'df', 'dfpr(RD) + 8', 'IsFloating', 10),
+ 'Frd_4_low': ('FloatReg', 'uw', 'dfprl(RD) + 8', 'IsFloating', 10),
+ 'Frd_4_high': ('FloatReg', 'uw', 'dfprh(RD) + 8', 'IsFloating', 10),
+ #'Frd_5': ('FloatReg', 'df', 'dfpr(RD) + 10', 'IsFloating', 10),
+ 'Frd_5_low': ('FloatReg', 'uw', 'dfprl(RD) + 10', 'IsFloating', 10),
+ 'Frd_5_high': ('FloatReg', 'uw', 'dfprh(RD) + 10', 'IsFloating', 10),
+ #'Frd_6': ('FloatReg', 'df', 'dfpr(RD) + 12', 'IsFloating', 10),
+ 'Frd_6_low': ('FloatReg', 'uw', 'dfprl(RD) + 12', 'IsFloating', 10),
+ 'Frd_6_high': ('FloatReg', 'uw', 'dfprh(RD) + 12', 'IsFloating', 10),
+ #'Frd_7': ('FloatReg', 'df', 'dfpr(RD) + 14', 'IsFloating', 10),
+ 'Frd_7_low': ('FloatReg', 'uw', 'dfprl(RD) + 14', 'IsFloating', 10),
+ 'Frd_7_high': ('FloatReg', 'uw', 'dfprh(RD) + 14', 'IsFloating', 10),
'Frs1s': ('FloatReg', 'sf', 'RS1', 'IsFloating', 11),
- 'Frs1': ('FloatReg', 'df', 'dfpr(RS1)', 'IsFloating', 11),
+ #'Frs1': ('FloatReg', 'df', 'dfpr(RS1)', 'IsFloating', 11),
+ 'Frs1_low': ('FloatReg', 'uw', 'dfprl(RS1)', 'IsFloating', 11),
+ 'Frs1_high': ('FloatReg', 'uw', 'dfprh(RS1)', 'IsFloating', 11),
'Frs2s': ('FloatReg', 'sf', 'RS2', 'IsFloating', 12),
- 'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12),
+ #'Frs2': ('FloatReg', 'df', 'dfpr(RS2)', 'IsFloating', 12),
+ 'Frs2_low': ('FloatReg', 'uw', 'dfprl(RS2)', 'IsFloating', 12),
+ 'Frs2_high': ('FloatReg', 'uw', 'dfprh(RS2)', 'IsFloating', 12),
'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31),
'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32),
# Registers which are used explicitly in instructions
diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh
index 6d89c273a..8c9afcdb5 100644
--- a/src/arch/x86/faults.hh
+++ b/src/arch/x86/faults.hh
@@ -65,12 +65,32 @@ namespace X86ISA
{
class X86Fault : public FaultBase
{
+ protected:
+ const char * name()
+ {
+ return "generic_x86_fault";
+ }
+
void invoke(ThreadContext * tc)
{
panic("X86 faults are not implemented!");
}
};
+ class UnimpInstFault : public FaultBase
+ {
+ public:
+ const char * name()
+ {
+ return "unimplemented_micro";
+ }
+
+ void invoke(ThreadContext * tc)
+ {
+ panic("Unimplemented instruction!");
+ }
+ };
+
static inline Fault genPageTableFault(Addr va)
{
panic("Page table fault not implemented in x86!\n");
diff --git a/src/arch/x86/intregs.hh b/src/arch/x86/intregs.hh
index ed801cc48..562539de9 100644
--- a/src/arch/x86/intregs.hh
+++ b/src/arch/x86/intregs.hh
@@ -63,21 +63,89 @@ namespace X86ISA
enum IntRegIndex
{
INTREG_RAX,
+ INTREG_EAX = INTREG_RAX,
+ INTREG_AX = INTREG_RAX,
+ INTREG_AL = INTREG_RAX,
+ INTREG_AH = INTREG_RAX,
+
INTREG_RCX,
+ INTREG_ECX = INTREG_RCX,
+ INTREG_CX = INTREG_RCX,
+ INTREG_CL = INTREG_RCX,
+ INTREG_CH = INTREG_RCX,
+
INTREG_RDX,
+ INTREG_EDX = INTREG_RDX,
+ INTREG_DX = INTREG_RDX,
+ INTREG_DL = INTREG_RDX,
+ INTREG_DH = INTREG_RDX,
+
INTREG_RBX,
+ INTREG_EBX = INTREG_RBX,
+ INTREG_BX = INTREG_RBX,
+ INTREG_BL = INTREG_RBX,
+ INTREG_BH = INTREG_RBX,
+
INTREG_RSP,
+ INTREG_ESP = INTREG_RSP,
+ INTREG_SP = INTREG_RSP,
+ INTREG_SPL = INTREG_RSP,
+
INTREG_RBP,
+ INTREG_EBP = INTREG_RBP,
+ INTREG_BP = INTREG_RBP,
+ INTREG_BPL = INTREG_RBP,
+
INTREG_RSI,
+ INTREG_ESI = INTREG_RSI,
+ INTREG_SI = INTREG_RSI,
+ INTREG_SIL = INTREG_RSI,
+
INTREG_RDI,
- INTREG_R8W,
- INTREG_R9W,
- INTREG_R10W,
- INTREG_R11W,
- INTREG_R12W,
- INTREG_R13W,
- INTREG_R14W,
- INTREG_R15W,
+ INTREG_EDI = INTREG_RDI,
+ INTREG_DI = INTREG_RDI,
+ INTREG_DIL = INTREG_RDI,
+
+ INTREG_R8,
+ INTREG_R8D = INTREG_R8,
+ INTREG_R8W = INTREG_R8,
+ INTREG_R8B = INTREG_R8,
+
+ INTREG_R9,
+ INTREG_R9D = INTREG_R9,
+ INTREG_R9W = INTREG_R9,
+ INTREG_R9B = INTREG_R9,
+
+ INTREG_R10,
+ INTREG_R10D = INTREG_R10,
+ INTREG_R10W = INTREG_R10,
+ INTREG_R10B = INTREG_R10,
+
+ INTREG_R11,
+ INTREG_R11D = INTREG_R11,
+ INTREG_R11W = INTREG_R11,
+ INTREG_R11B = INTREG_R11,
+
+ INTREG_R12,
+ INTREG_R12D = INTREG_R12,
+ INTREG_R12W = INTREG_R12,
+ INTREG_R12B = INTREG_R12,
+
+ INTREG_R13,
+ INTREG_R13D = INTREG_R13,
+ INTREG_R13W = INTREG_R13,
+ INTREG_R13B = INTREG_R13,
+
+ INTREG_R14,
+ INTREG_R14D = INTREG_R14,
+ INTREG_R14W = INTREG_R14,
+ INTREG_R14B = INTREG_R14,
+
+ INTREG_R15,
+ INTREG_R15D = INTREG_R15,
+ INTREG_R15W = INTREG_R15,
+ INTREG_R15B = INTREG_R15,
+
NUM_INTREGS
};
};
diff --git a/src/arch/x86/isa/base.isa b/src/arch/x86/isa/base.isa
index 4776f7a7e..eba24f709 100644
--- a/src/arch/x86/isa/base.isa
+++ b/src/arch/x86/isa/base.isa
@@ -58,6 +58,38 @@
// Base class for sparc instructions, and some support functions
//
+let {{
+ # This class will help make dealing with output a little less verbose
+ class OutputBlocks(object):
+ def __init__(self, header_output="",
+ decoder_output="",
+ decode_block="",
+ exec_output=""):
+ self.header_output = header_output
+ self.decoder_output = decoder_output
+ self.decode_block = decode_block
+ self.exec_output = exec_output
+
+ def append(self, blocks):
+ if isinstance(blocks, list) or isinstance(blocks, tuple):
+ assert(len(blocks) == 4)
+ self.header_output += blocks[0]
+ self.decoder_output += blocks[1]
+ self.decode_block += blocks[2]
+ self.exec_output += blocks[3]
+ else:
+ self.header_output += blocks.header_output
+ self.decoder_output += blocks.decoder_output
+ self.decode_block += blocks.decode_block
+ self.exec_output += blocks.exec_output
+
+ def makeList(self):
+ return (self.header_output,
+ self.decoder_output,
+ self.decode_block,
+ self.exec_output)
+}};
+
output header {{
/**
@@ -79,6 +111,13 @@ output header {{
void printReg(std::ostream &os, int reg) const;
void printSrcReg(std::ostream &os, int reg) const;
void printDestReg(std::ostream &os, int reg) const;
+
+ inline uint64_t merge(uint64_t into, uint64_t val, int size) const
+ {
+ //FIXME This needs to be significantly more sophisticated
+ return val;
+ }
+
};
}};
diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
index b4aeece07..4e044363b 100644
--- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
@@ -61,14 +61,12 @@
0x1: decode OPCODE_OP_TOP5 {
format WarnUnimpl {
0x00: decode OPCODE_OP_BOTTOM3 {
+ 0x4: Inst::ADD(rAl,Ib);
+ 0x5: Inst::ADD(rAx,Iz);
0x6: push_ES();
0x7: pop_ES();
- default: MultiOp::add(
- {{Add %0 %0 %1}},
- OPCODE_OP_BOTTOM3,
- [[Eb,Gb],[Ev,Gv],
- [Gb,Eb],[Gv,Ev],
- [Al,Ib],[rAx,Iz]]);
+ default: MultiInst::ADD(OPCODE_OP_BOTTOM3,
+ [Eb,Gb],[Ev,Gv],[Gb,Eb],[Gv,Ev]);
}
0x01: decode OPCODE_OP_BOTTOM3 {
0x0: or_Eb_Gb();
@@ -125,15 +123,13 @@
0x7: das();
}
0x06: decode OPCODE_OP_BOTTOM3 {
- 0x0: xor_Eb_Gb();
- 0x1: xor_Ev_Gv();
- 0x2: xor_Gb_Eb();
- 0x3: xor_Gv_Ev();
- 0x4: xor_Al_Ib();
- 0x5: xor_rAX_Iz();
+ 0x4: Inst::XOR(rAl,Ib);
+ 0x5: Inst::XOR(rAx,Iz);
0x6: M5InternalError::error(
{{"Tried to execute the SS segment override prefix!"}});
0x7: aaa();
+ default: MultiInst::XOR(OPCODE_OP_BOTTOM3,
+ [Eb,Gb],[Ev,Gv],[Gb,Eb],[Gv,Ev]);
}
0x07: decode OPCODE_OP_BOTTOM3 {
0x0: cmp_Eb_Gb();
@@ -241,11 +237,11 @@
0x7: xchg_Ev_Gv();
}
0x11: decode OPCODE_OP_BOTTOM3 {
- 0x0: mov_Eb_Gb();
- 0x1: mov_Ev_Gv();
- 0x2: mov_Gb_Eb();
- 0x3: mov_Gv_Ev();
- 0x4: mov_MwRv_Sw();
+ 0x0: Inst::MOV(); //mov_Eb_Gb();
+ 0x1: Inst::MOV(); //mov_Ev_Gv();
+ 0x2: Inst::MOV(); //mov_Gb_Eb();
+ 0x3: Inst::MOV(); //mov_Gv_Ev();
+ 0x4: Inst::MOV(); //mov_MwRv_Sw();
0x5: lea_Gv_M();
0x6: mov_Sw_MwRv();
0x7: group10_Ev(); //Make sure this is Ev
diff --git a/src/arch/x86/isa/formats/multi.isa b/src/arch/x86/isa/formats/multi.isa
index c14e80095..8f91c249c 100644
--- a/src/arch/x86/isa/formats/multi.isa
+++ b/src/arch/x86/isa/formats/multi.isa
@@ -60,95 +60,27 @@
// Instructions that do the same thing to multiple sets of arguments.
//
-output header {{
-}};
-
-output decoder {{
-}};
-
-output exec {{
-}};
-
let {{
- multiops = {}
+ def doInst(name, Name, opTypeSet):
+ if not instDict.has_key(Name):
+ raise Exception, "Unrecognized instruction: %s" % Name
+ inst = instDict[Name]()
+ return inst.emit(opTypeSet)
}};
-def format MultiOp(code, switchVal, opTags, *opt_flags) {{
- # These are C++ statements to create each type of static int. Since we
- # don't know what will be microcoded and what won't, we can't assume a
- # particular set of arguments for the constructor.
- instNew = []
- orig_code = code
- opRe = re.compile(r"%(?P<operandNum>[0-9]*)")
- # Get all the labels out of the code and make a dict for them. We'll do
- # this once since the position of labels shouldn't need to change at all.
- ops = assembleMicro(code)
- labels = buildLabelDict(ops)
- for tagSet in opTags:
- # A list of strings which either have the register number to use, or
- # a piece of code for calculating it.
- regNums = []
- code = orig_code
- # Build up a name for this instructions class using the argument
- # types. Each variation will get its own name this way.
- postfix = ''
- for tag in tagSet:
- postfix += '_' + tag
-
- # Figure out what register indexes to use for each operand. This
- # is where loads/stores could be set up. I need to distinguish
- # between inputs and outputs.
- # For right now, the indexes are just an increasing sequence
- counter = 0
- for tag in tagSet:
- regNums.append("%d" % counter)
- counter += 1
-
- # Replace the placeholders %0, %1, etc., with the right register
- # indexes.
- opMatch = opRe.search(code)
- while opMatch:
- opNum = opMatch.group("operandNum")
- opNum = int(opNum)
- if opNum > len(regNums):
- print "No operand type specified for operand %d!" % opNum
- print "I should bail out here too!"
- regNum = regNums[opNum]
- code = opRe.sub(regNum, code, 1)
- opMatch = opRe.search(code)
-
- # All the loads which feed this instruction
- loads = []
- # All the ops that make up the instruction proper.
- ops = assembleMicro(code)
- # Get all the labels out and make a dict for them
- # All the stores for this instruction's results
- stores = []
-
- # Various counts
- numLoads = len(loads)
- numOps = len(ops)
- numStores = len(stores)
- totalOps = numLoads + numOps + numStores
- print "There are %d total ops" % totalOps
-
- # If we can implement this instruction with exactly one microop, just
- # use that directly.
- newStmnt = ''
- if totalOps == 1:
- newStmnt = ops[0].getAllocator(labels)
- else:
- # Build up a macro op. We'll punt on this for now
- pass
-
- instNew.append(newStmnt)
+def format Inst(*opTypeSet) {{
+ (header_output,
+ decoder_output,
+ decode_block,
+ exce_output) = doInst(name, Name, list(opTypeSet)).makeList()
+}};
- decodeBlob = 'switch(%s) {\n' % switchVal
- counter = 0
- for newStmnt in instNew:
- decodeBlob += 'case %d: return (X86StaticInst *)(%s);\n' % \
- (counter, newStmnt)
- counter += 1
- decodeBlob += '}\n'
- decode_block = decodeBlob
+def format MultiInst(switchVal, *opTypeSets) {{
+ switcher = {}
+ for (count, opTypeSet) in zip(xrange(len(opTypeSets)), opTypeSets):
+ switcher[count] = (opTypeSet,)
+ (header_output,
+ decoder_output,
+ decode_block,
+ exec_output) = doSplitDecode(name, Name, doInst, switchVal, switcher).makeList()
}};
diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa
index 65e735b03..3440ec5da 100644
--- a/src/arch/x86/isa/includes.isa
+++ b/src/arch/x86/isa/includes.isa
@@ -83,9 +83,14 @@
////////////////////////////////////////////////////////////////////
//
-// Output include file directives.
+// Output include file directives. Also import the python modules we
+// need for all the x86 custom decoder stuff
//
+let {{
+ import copy
+}};
+
output header {{
#include <cstring>
#include <sstream>
diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa
new file mode 100644
index 000000000..663ec7aee
--- /dev/null
+++ b/src/arch/x86/isa/macroop.isa
@@ -0,0 +1,164 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007 The Hewlett-Packard Development Company
+// All rights reserved.
+//
+// Redistribution and use of this software in source and binary forms,
+// with or without modification, are permitted provided that the
+// following conditions are met:
+//
+// The software must be used only for Non-Commercial Use which means any
+// use which is NOT directed to receiving any direct monetary
+// compensation for, or commercial advantage from such use. Illustrative
+// examples of non-commercial use are academic research, personal study,
+// teaching, education and corporate research & development.
+// Illustrative examples of commercial use are distributing products for
+// commercial advantage and providing services using the software for
+// commercial advantage.
+//
+// If you wish to use this software or functionality therein that may be
+// covered by patents for commercial use, please contact:
+// Director of Intellectual Property Licensing
+// Office of Strategy and Technology
+// Hewlett-Packard Company
+// 1501 Page Mill Road
+// Palo Alto, California 94304
+//
+// 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission. No right of
+// sublicense is granted herewith. Derivatives of the software and
+// output created using the software may be prepared, but only for
+// Non-Commercial Uses. Derivatives of the software may be shared with
+// others provided: (i) the others agree to abide by the list of
+// conditions herein which includes the Non-Commercial Use restrictions;
+// and (ii) such Derivatives of the software include the above copyright
+// notice to acknowledge the contribution from this software where
+// applicable, this list of conditions and the disclaimer below.
+//
+// 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: Gabe Black
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Architecture independent
+//
+
+// Execute method for macroops.
+def template MacroExecPanic {{
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
+ {
+ panic("Tried to execute macroop directly!");
+ return NoFault;
+ }
+}};
+
+output header {{
+
+ // Base class for macroops
+ class MacroOp : public StaticInst
+ {
+ protected:
+ const uint32_t numMicroOps;
+
+ //Constructor.
+ MacroOp(const char *mnem, ExtMachInst _machInst,
+ uint32_t _numMicroOps)
+ : StaticInst(mnem, _machInst, No_OpClass),
+ numMicroOps(_numMicroOps)
+ {
+ assert(numMicroOps);
+ microOps = new StaticInstPtr[numMicroOps];
+ flags[IsMacroOp] = true;
+ }
+
+ ~MacroOp()
+ {
+ delete [] microOps;
+ }
+
+ StaticInstPtr * microOps;
+
+ StaticInstPtr fetchMicroOp(MicroPC microPC)
+ {
+ assert(microPC < numMicroOps);
+ return microOps[microPC];
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return mnemonic;
+ }
+
+ %(MacroExecPanic)s
+ };
+}};
+
+// Basic instruction class declaration template.
+def template MacroDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ // Constructor.
+ %(class_name)s(ExtMachInst machInst);
+ };
+}};
+
+// Basic instruction class constructor template.
+def template MacroConstructor {{
+ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(num_micro_ops)s)
+ {
+ %(constructor)s;
+ //alloc_micro_ops is the code that sets up the microOps
+ //array in the parent class.
+ %(alloc_micro_ops)s;
+ }
+}};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// X86 specific
+//
+
+let {{
+ def genMacroOp(name, Name, opSeq):
+ numMicroOps = len(opSeq)
+ allocMicroOps = ''
+ micropc = 0
+ for op in opSeq:
+ allocMicroOps += \
+ "microOps[%d] = %s;\n" % \
+ (micropc, op.getAllocator('"' + name + '"', True, False, #op.delayed,
+ micropc == 0,
+ micropc == numMicroOps - 1))
+ micropc += 1
+ iop = InstObjParams(name, Name, 'MacroOp',
+ {'code' : '', 'num_micro_ops' : numMicroOps,
+ 'alloc_micro_ops' : allocMicroOps})
+ header_output = MacroDeclare.subst(iop)
+ decoder_output = MacroConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = ''
+ return (header_output, decoder_output, decode_block, exec_output)
+}};
diff --git a/src/arch/x86/isa/main.isa b/src/arch/x86/isa/main.isa
index fe1d4e515..063d7125d 100644
--- a/src/arch/x86/isa/main.isa
+++ b/src/arch/x86/isa/main.isa
@@ -72,23 +72,55 @@
namespace X86ISA;
-//Include the simple microcode assembler
-##include "microasm.isa"
+////////////////////////////////////////////////////////////////////
+//
+// General infrastructure code. These files provide infrastructure
+// which was developed to support x86 but isn't specific to it.
+//
-//Include the bitfield definitions
-##include "bitfields.isa"
+//Include code to build macroops.
+##include "macroop.isa"
-//Include the operand_types and operand definitions
-##include "operands.isa"
+//Include the simple microcode assembler. This will hopefully stay
+//unspecialized for x86 and can later be made available to other ISAs.
+##include "microasm.isa"
+
+////////////////////////////////////////////////////////////////////
+//
+// X86 only infrastructure code.
+//
-//Include the base class for x86 instructions, and some support code
+//Include the base class for x86 instructions, and some support code.
##include "base.isa"
+//Include code to specialize an instruction template to operate on
+//a particular set of operands. This is specific to x86 and the x86
+//microcode ISA.
+##include "specialize.isa"
+
+////////////////////////////////////////////////////////////////////
+//
+// Code which directly specifies isa components like instructions
+// microops, and the decoder.
+//
+
//Include the definitions for the instruction formats
##include "formats/formats.isa"
-//Include the definitions of the micro ops
+//Include the operand_types and operand definitions. These are needed by
+//the microop definitions.
+##include "operands.isa"
+
+//Include the definitions of the micro ops.
+//These are StaticInst classes which stand on their own and make up an
+//internal instruction set.
##include "microops/microops.isa"
+//Include the instruction definitions which are microop assembler programs.
+##include "insts/insts.isa"
+
+//Include the bitfield definitions
+##include "bitfields.isa"
+
//Include the decoder definition
##include "decoder/decoder.isa"
diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa
index 2abce6e7f..9d21b6bcc 100644
--- a/src/arch/x86/isa/microasm.isa
+++ b/src/arch/x86/isa/microasm.isa
@@ -57,33 +57,59 @@
////////////////////////////////////////////////////////////////////
//
-// Code to "assemble" microcode sequences
+// The microcode assembler
//
let {{
- class MicroOpStatement:
+ # These are used when setting up microops so that they can specialize their
+ # base class template properly.
+ RegOpType = "RegisterOperand"
+ ImmOpType = "ImmediateOperand"
+}};
+
+let {{
+ class MicroOpStatement(object):
def __init__(self):
self.className = ''
self.label = ''
self.args = []
- def getAllocator(self, labelDict = {}):
+ # This converts a list of python bools into
+ # a comma seperated list of C++ bools.
+ def microFlagsText(self, vals):
+ text = ""
+ for val in vals:
+ if val:
+ text += ", true"
+ else:
+ text += ", false"
+ return text
+
+ def getAllocator(self, mnemonic, *microFlags):
args = ''
+ signature = "<"
+ emptySig = True
for arg in self.args:
- if arg.has_key("operandConst"):
- args += ", %s" % arg["operandConst"]
- elif arg.has_key("operandCode"):
- args += ", %s" % arg["operandCode"]
+ if not emptySig:
+ signature += ", "
+ emptySig = False
+ if arg.has_key("operandImm"):
+ args += ", %s" % arg["operandImm"]
+ signature += ImmOpType
+ elif arg.has_key("operandReg"):
+ args += ", %s" % arg["operandReg"]
+ signature += RegOpType
elif arg.has_key("operandLabel"):
- if not labelDict.has_key(arg["operandLabel"]):
- print "Unrecognized label %s!" % arg["operandLabel"]
- args += ", %s" % labelDict[arg["operandLabel"]]
+ raise Exception, "Found a label while creating allocator string."
else:
- print "Unrecognized operand type!"
- return 'new %s(machInst %s)' % (self.className, args)
+ raise Exception, "Unrecognized operand type."
+ signature += ">"
+ return 'new %s%s(machInst, %s%s%s)' % (self.className, signature, mnemonic, self.microFlagsText(microFlags), args)
+}};
+let{{
+ def assembleMicro(name, Name, code):
- def assembleMicro(code):
# This function takes in a block of microcode assembly and returns
# a python list of objects which describe it.
@@ -96,8 +122,8 @@ let {{
# time. Each expression expects the thing it's looking for to be at
# the beginning of the line, so the previous component is stripped
# before continuing.
- labelRe = re.compile(r'^[ \t]*(?P<label>[a-zA-Z_]\w*)[ \t]:')
- lineRe = re.compile(r'^(?P<line>[^\n][^\n]*)$')
+ labelRe = re.compile(r'^[ \t]*(?P<label>\w\w*)[ \t]:')
+ lineRe = re.compile(r'^(?P<line>..*)(\n|$)')
classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)')
# This recognizes three different flavors of operands:
# 1. Raw decimal numbers composed of digits between 0 and 9
@@ -107,31 +133,37 @@ let {{
# underscore, which is optionally followed by a sequence of
# capital or small letters, underscores, or digts between 0 and 9
opRe = re.compile( \
- r'^[ \t]*((?P<operandLabel>[a-zA-Z_]\w*)|(?P<operandConst>[0-9][0-9]*)|(\{(?P<operandCode>[^}]*)\}))')
+ r'^[ \t]*((\@(?P<operandLabel0>\w\w*))|' +
+ r'(\@\{(?P<operandLabel1>[^}]*)\})|' +
+ r'(\%(?P<operandReg0>\w\w*))|' +
+ r'(\%\{(?P<operandReg1>[^}]*)\})|' +
+ r'(\$(?P<operandImm0>\w\w*))|' +
+ r'(\$\{(?P<operandImm1>[^}]*)\}))')
lineMatch = lineRe.search(code)
while lineMatch != None:
statement = MicroOpStatement()
# Get a line and seperate it from the rest of the code
line = lineMatch.group("line")
- print "Parsing line %s" % line
+ orig_line = line
+ #print "Parsing line %s" % line
code = lineRe.sub('', code, 1)
# Find the label, if any
labelMatch = labelRe.search(line)
if labelMatch != None:
statement.label = labelMatch.group("label")
- print "Found label %s." % statement.label
+ #print "Found label %s." % statement.label
# Clear the label from the statement
line = labelRe.sub('', line, 1)
# Find the class name which is roughly equivalent to the op name
classMatch = classRe.search(line)
if classMatch == None:
- print "Oh no! I can't find what instruction you want!"
- print "I should really bail out here, but I don't know how!"
+ raise Exception, "Couldn't find class name in statement: %s" \
+ % orig_line
else:
statement.className = classMatch.group("className")
- print "Found class name %s." % statement.className
+ #print "Found class name %s." % statement.className
# Clear the class name from the statement
line = classRe.sub('', line, 1)
@@ -145,28 +177,55 @@ let {{
# representations of operand values. Different forms might be
# needed in different places, for instance to replace a label
# with an offset.
- for opType in ("operandLabel", "operandConst", "operandCode"):
+ for opType in ("operandLabel0", "operandReg0", "operandImm0",
+ "operandLabel1", "operandReg1", "operandImm1"):
if opMatch.group(opType):
- statement.args[-1][opType] = opMatch.group(opType)
+ statement.args[-1][opType[:-1]] = opMatch.group(opType)
if len(statement.args[-1]) == 0:
- print "I had a problem parsing an operand!"
+ print "Problem parsing operand in statement: %s" \
+ % orig_line
line = opRe.sub('', line, 1)
- print "Found operand %s." % statement.args[-1]
+ #print "Found operand %s." % statement.args[-1]
opMatch = opRe.search(line)
- print "Found operands", statement.args
+ #print "Found operands", statement.args
# Add this statement to our collection
statements.append(statement)
# Get the next line
lineMatch = lineRe.search(code)
- return statements
- def buildLabelDict(ops):
+ # Decode the labels into displacements
+
labels = {}
- count = 0
- for op in ops:
- if op.label:
- labels[op.label] = count
- count += 1
+ micropc = 0
+ for statement in statements:
+ if statement.label:
+ labels[statement.label] = count
+ micropc += 1
+ micropc = 0
+ for statement in statements:
+ for arg in statement.args:
+ if arg.has_key("operandLabel"):
+ if not labels.has_key(arg["operandLabel"]):
+ raise Exception, "Unrecognized label: %s." % arg["operandLabel"]
+ # This is assuming that intra microcode branches go to
+ # the next micropc + displacement, or
+ # micropc + 1 + displacement.
+ arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1
+ micropc += 1
+
+ if len(statements) == 0:
+ raise Exception, "Didn't find any microops in microcode: \n%s" % orig_code
+
+ # If we can implement this instruction with exactly one microop, just
+ # use that directly.
+ if len(statements) == 1:
+ decode_block = "return %s;" % \
+ statements[0].getAllocator('"' + name + '"')
+ return ('', '', decode_block, '')
+ else:
+ # Build a macroop to contain the sequence of microops we've
+ # been given.
+ return genMacroOp(name, Name, statements)
}};
diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa
new file mode 100644
index 000000000..f0aab7872
--- /dev/null
+++ b/src/arch/x86/isa/microops/base.isa
@@ -0,0 +1,194 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007 The Hewlett-Packard Development Company
+// All rights reserved.
+//
+// Redistribution and use of this software in source and binary forms,
+// with or without modification, are permitted provided that the
+// following conditions are met:
+//
+// The software must be used only for Non-Commercial Use which means any
+// use which is NOT directed to receiving any direct monetary
+// compensation for, or commercial advantage from such use. Illustrative
+// examples of non-commercial use are academic research, personal study,
+// teaching, education and corporate research & development.
+// Illustrative examples of commercial use are distributing products for
+// commercial advantage and providing services using the software for
+// commercial advantage.
+//
+// If you wish to use this software or functionality therein that may be
+// covered by patents for commercial use, please contact:
+// Director of Intellectual Property Licensing
+// Office of Strategy and Technology
+// Hewlett-Packard Company
+// 1501 Page Mill Road
+// Palo Alto, California 94304
+//
+// 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission. No right of
+// sublicense is granted herewith. Derivatives of the software and
+// output created using the software may be prepared, but only for
+// Non-Commercial Uses. Derivatives of the software may be shared with
+// others provided: (i) the others agree to abide by the list of
+// conditions herein which includes the Non-Commercial Use restrictions;
+// and (ii) such Derivatives of the software include the above copyright
+// notice to acknowledge the contribution from this software where
+// applicable, this list of conditions and the disclaimer below.
+//
+// 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: Gabe Black
+
+//The operand types a microop template can be specialized with
+output header {{
+ enum OperandType {
+ RegisterOperand,
+ ImmediateOperand
+ };
+}};
+
+//A class which is the base of all x86 micro ops. It provides a function to
+//set necessary flags appropriately.
+output header {{
+ class X86MicroOpBase : public X86StaticInst
+ {
+ protected:
+ const char * instMnem;
+ uint8_t opSize;
+ uint8_t addrSize;
+
+ X86MicroOpBase(ExtMachInst _machInst,
+ const char *mnem, const char *_instMnem,
+ bool isMicro, bool isDelayed,
+ bool isFirst, bool isLast,
+ OpClass __opClass) :
+ X86StaticInst(mnem, _machInst, __opClass),
+ instMnem(_instMnem)
+ {
+ flags[IsMicroOp] = isMicro;
+ flags[IsDelayedCommit] = isDelayed;
+ flags[IsFirstMicroOp] = isFirst;
+ flags[IsLastMicroOp] = isLast;
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "\t%s.%s", instMnem, mnemonic);
+
+ return ss.str();
+ }
+ };
+}};
+
+// This sets up a class which is templated on the type of
+// arguments a particular flavor of a microcode instruction
+// can accept. It's parameters are specialized to create polymorphic
+// behavior in microops.
+def template BaseMicroOpTemplateDeclare {{
+ template%(signature)s
+ class %(class_name)s;
+}};
+
+let {{
+ def buildBaseMicroOpTemplate(Name, numParams):
+ assert(numParams > 0)
+ signature = "<"
+ signature += "int SignatureOperandTypeSpecifier0"
+ for count in xrange(1,numParams):
+ signature += \
+ ", int SingatureOperandTypeSpecifier%d" % count
+ signature += ">"
+ subs = {"signature" : signature, "class_name" : Name}
+ return BaseMicroOpTemplateDeclare.subst(subs)
+}};
+
+let {{
+ def buildMicroOpTemplateDict(*params):
+ signature = "<"
+ if len(params):
+ signature += params[0]
+ if len(params) > 1:
+ for param in params[1:]:
+ signature += ", %s" % param
+ signature += ">"
+ subs = {"param_dec" : "", "param_arg_dec" : "",
+ "param_init" : "", "signature" : signature}
+ for count in xrange(len(params)):
+ subs["param_dec"] += "uint64_t param%d;\n" % count
+ subs["param_arg_dec"] += ", uint64_t _param%d" % count
+ subs["param_init"] += ", param%d(_param%d)" % (count, count)
+ return subs
+}};
+
+// A tmeplate for building a specialized version of the microcode
+// instruction which specifies which arguments it wants
+def template MicroOpDeclare {{
+ template<>
+ class %(class_name)s%(signature)s : public X86MicroOpBase
+ {
+ protected:
+ %(param_dec)s
+ void buildMe();
+
+ public:
+ %(class_name)s(ExtMachInst _machInst,
+ const char * instMnem,
+ bool isMicro, bool isDelayed,
+ bool isFirst, bool isLast
+ %(param_arg_dec)s);
+
+ %(class_name)s(ExtMachInst _machInst,
+ const char * instMnem
+ %(param_arg_dec)s);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template MicroOpConstructor {{
+
+ inline void %(class_name)s%(signature)s::buildMe()
+ {
+ %(constructor)s;
+ }
+
+ inline %(class_name)s%(signature)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem
+ %(param_arg_dec)s) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ false, false, false, false, %(op_class)s)
+ %(param_init)s
+ {
+ buildMe();
+ }
+
+ inline %(class_name)s%(signature)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast
+ %(param_arg_dec)s)
+ : %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast, %(op_class)s)
+ %(param_init)s
+ {
+ buildMe();
+ }
+}};
diff --git a/src/arch/x86/isa/microops/microops.isa b/src/arch/x86/isa/microops/microops.isa
index bbf26f605..d877152eb 100644
--- a/src/arch/x86/isa/microops/microops.isa
+++ b/src/arch/x86/isa/microops/microops.isa
@@ -53,5 +53,11 @@
//
// Authors: Gabe Black
-//Micro ops
+//Common microop stuff
+##include "base.isa"
+
+//A microop that generates a specified fault
+##include "fault.isa"
+
+//Integer microop definitions
##include "int.isa"
diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa
index 36b0ee4df..af469ab3d 100644
--- a/src/arch/x86/isa/operands.isa
+++ b/src/arch/x86/isa/operands.isa
@@ -96,7 +96,7 @@ def operand_types {{
}};
def operands {{
- 'IntRegOp0': ('IntReg', 'udw', 'regIndex0', 'IsInteger', 1),
- 'IntRegOp1': ('IntReg', 'udw', 'regIndex1', 'IsInteger', 2),
- 'IntRegOp2': ('IntReg', 'udw', 'regIndex2', 'IsInteger', 2),
+ 'IntRegOp0': ('IntReg', 'udw', 'param0', 'IsInteger', 1),
+ 'IntRegOp1': ('IntReg', 'udw', 'param1', 'IsInteger', 2),
+ 'IntRegOp2': ('IntReg', 'udw', 'param2', 'IsInteger', 2),
}};
diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa
new file mode 100644
index 000000000..ff92c3551
--- /dev/null
+++ b/src/arch/x86/isa/specialize.isa
@@ -0,0 +1,164 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007 The Hewlett-Packard Development Company
+// All rights reserved.
+//
+// Redistribution and use of this software in source and binary forms,
+// with or without modification, are permitted provided that the
+// following conditions are met:
+//
+// The software must be used only for Non-Commercial Use which means any
+// use which is NOT directed to receiving any direct monetary
+// compensation for, or commercial advantage from such use. Illustrative
+// examples of non-commercial use are academic research, personal study,
+// teaching, education and corporate research & development.
+// Illustrative examples of commercial use are distributing products for
+// commercial advantage and providing services using the software for
+// commercial advantage.
+//
+// If you wish to use this software or functionality therein that may be
+// covered by patents for commercial use, please contact:
+// Director of Intellectual Property Licensing
+// Office of Strategy and Technology
+// Hewlett-Packard Company
+// 1501 Page Mill Road
+// Palo Alto, California 94304
+//
+// 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission. No right of
+// sublicense is granted herewith. Derivatives of the software and
+// output created using the software may be prepared, but only for
+// Non-Commercial Uses. Derivatives of the software may be shared with
+// others provided: (i) the others agree to abide by the list of
+// conditions herein which includes the Non-Commercial Use restrictions;
+// and (ii) such Derivatives of the software include the above copyright
+// notice to acknowledge the contribution from this software where
+// applicable, this list of conditions and the disclaimer below.
+//
+// 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: Gabe Black
+
+////////////////////////////////////////////////////////////////////
+//
+// Code to "specialize" a microcode sequence to use a particular
+// variety of operands
+//
+
+let {{
+ # This code builds up a decode block which decodes based on switchval.
+ # vals is a dict which matches case values with what should be decoded to.
+ # builder is called on the exploded contents of "vals" values to generate
+ # whatever code should be used.
+ def doSplitDecode(name, Name, builder, switchVal, vals, default = None):
+ blocks = OutputBlocks()
+ blocks.decode_block += 'switch(%s) {\n' % switchVal
+ for (val, todo) in vals.items():
+ built = builder(name, Name, *todo)
+ built.decode_block = '\tcase %s: %s\n' % (val, built.decode_block)
+ blocks.append(built)
+ if default:
+ built = builder(name, Name, *default)
+ built.decode_block = '\tdefault: %s\n' % built.decode_block
+ blocks.append(built)
+ blocks.decode_block += '}\n'
+ return blocks
+}};
+
+let {{
+ class OpType(object):
+ parser = re.compile(r"(?P<tag>[A-Z][A-Z]*)(?P<size>[a-z][a-z]*)|(r(?P<reg>[A-Za-z0-9][A-Za-z0-9]*))")
+ def __init__(self, opTypeString):
+ match = OpType.parser.search(opTypeString)
+ if match == None:
+ raise Exception, "Problem parsing operand type %s" % opTypeString
+ self.reg = match.group("reg")
+ self.tag = match.group("tag")
+ self.size = match.group("size")
+
+ # This function specializes the given piece of code to use a particular
+ # set of argument types described by "opTypes". These are "implemented"
+ # in reverse order.
+ def specializeInst(name, Name, code, opTypes):
+ opNum = len(opTypes) - 1
+ while len(opTypes):
+ # print "Building a composite op with tags", opTypes
+ # print "And code", code
+ opNum = len(opTypes) - 1
+ # A regular expression to find the operand placeholders we're
+ # interested in.
+ opRe = re.compile("\\^(?P<operandNum>%d)(?=[^0-9]|$)" % opNum)
+
+ # Parse the operand type strign we're working with
+ opType = OpType(opTypes[opNum])
+
+ if opType.reg:
+ #Figure out what to do with fixed register operands
+ if opType.reg in ("Ax", "Bx", "Cx", "Dx"):
+ code = opRe.sub("%%{INTREG_R%s}" % opType.reg.upper(), code)
+ elif opType.reg == "Al":
+ # We need a way to specify register width
+ code = opRe.sub("%{INTREG_RAX}", code)
+ else:
+ print "Didn't know how to encode fixed register %s!" % opType.reg
+ elif opType.tag == None or opType.size == None:
+ raise Exception, "Problem parsing operand tag: %s" % opType.tag
+ elif opType.tag in ("C", "D", "G", "P", "S", "T", "V"):
+ # Use the "reg" field of the ModRM byte to select the register
+ code = opRe.sub("%{(uint8_t)MODRM_REG}", code)
+ elif opType.tag in ("E", "Q", "W"):
+ # This might refer to memory or to a register. We need to
+ # divide it up farther.
+ regCode = opRe.sub("%{(uint8_t)MODRM_RM}", code)
+ regTypes = copy.copy(opTypes)
+ regTypes.pop(-1)
+ # This needs to refer to memory, but we'll fill in the details
+ # later. It needs to take into account unaligned memory
+ # addresses.
+ code = "GenFault ${new UnimpInstFault}\n" + code
+ memCode = opRe.sub("%0", code)
+ memTypes = copy.copy(opTypes)
+ memTypes.pop(-1)
+ return doSplitDecode(name, Name, specializeInst, "MODRM_MOD",
+ {"3" : (regCode, regTypes)}, (memCode, memTypes))
+ elif opType.tag in ("I", "J"):
+ # Immediates are already in the instruction, so don't leave in
+ # those parameters
+ code = opRe.sub("${IMMEDIATE}", code)
+ elif opType.tag == "M":
+ # This needs to refer to memory, but we'll fill in the details
+ # later. It needs to take into account unaligned memory
+ # addresses.
+ code = "GenFault ${new UnimpInstFault}\n" + code
+ code = opRe.sub("%0", code)
+ elif opType.tag in ("PR", "R", "VR"):
+ # There should probably be a check here to verify that mod
+ # is equal to 11b
+ code = opRe.sub("%{(uint8_t)MODRM_RM}", code)
+ else:
+ raise Exception, "Unrecognized tag %s." % opType.tag
+ opTypes.pop(-1)
+
+ # At this point, we've built up "code" to have all the necessary extra
+ # instructions needed to implement whatever types of operands were
+ # specified. Now we'll assemble it it into a StaticInst.
+ blocks = OutputBlocks()
+ blocks.append(assembleMicro(name, Name, code))
+ return blocks
+}};
diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc
index fbed4fe41..573012ee6 100644
--- a/src/arch/x86/predecoder.cc
+++ b/src/arch/x86/predecoder.cc
@@ -117,37 +117,33 @@ namespace X86ISA
//Operand size override prefixes
case OperandSizeOverride:
DPRINTF(Predecoder, "Found operand size override prefix.\n");
+ emi.legacy.op = true;
break;
case AddressSizeOverride:
DPRINTF(Predecoder, "Found address size override prefix.\n");
+ emi.legacy.addr = true;
break;
//Segment override prefixes
case CSOverride:
- DPRINTF(Predecoder, "Found cs segment override.\n");
- break;
case DSOverride:
- DPRINTF(Predecoder, "Found ds segment override.\n");
- break;
case ESOverride:
- DPRINTF(Predecoder, "Found es segment override.\n");
- break;
case FSOverride:
- DPRINTF(Predecoder, "Found fs segment override.\n");
- break;
case GSOverride:
- DPRINTF(Predecoder, "Found gs segment override.\n");
- break;
case SSOverride:
- DPRINTF(Predecoder, "Found ss segment override.\n");
+ DPRINTF(Predecoder, "Found segment override.\n");
+ emi.legacy.seg = prefix;
break;
case Lock:
DPRINTF(Predecoder, "Found lock prefix.\n");
+ emi.legacy.lock = true;
break;
case Rep:
DPRINTF(Predecoder, "Found rep prefix.\n");
+ emi.legacy.rep = true;
break;
case Repne:
DPRINTF(Predecoder, "Found repne prefix.\n");
+ emi.legacy.repne = true;
break;
case RexPrefix:
DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte);
@@ -198,25 +194,50 @@ namespace X86ISA
displacementCollected = 0;
emi.displacement = 0;
+ //Figure out the effective operand size. This can be overriden to
+ //a fixed value at the decoder level.
+ if(/*FIXME long mode*/1)
+ {
+ if(emi.rex && emi.rex.w)
+ emi.opSize = 3; // 64 bit operand size
+ else if(emi.legacy.op)
+ emi.opSize = 1; // 16 bit operand size
+ else
+ emi.opSize = 2; // 32 bit operand size
+ }
+ else if(/*FIXME default 32*/1)
+ {
+ if(emi.legacy.op)
+ emi.opSize = 1; // 16 bit operand size
+ else
+ emi.opSize = 2; // 32 bit operand size
+ }
+ else // 16 bit default operand size
+ {
+ if(emi.legacy.op)
+ emi.opSize = 2; // 32 bit operand size
+ else
+ emi.opSize = 1; // 16 bit operand size
+ }
+
//Figure out how big of an immediate we'll retreive based
//on the opcode.
- int immType = ImmediateType[
- emi.opcode.num - 1][nextByte];
- if(0) //16 bit mode
- immediateSize = ImmediateTypeToSize[0][immType];
- else if(!(emi.rex & 0x4)) //32 bit mode
- immediateSize = ImmediateTypeToSize[1][immType];
- else //64 bit mode
- immediateSize = ImmediateTypeToSize[2][immType];
+ int immType = ImmediateType[emi.opcode.num - 1][nextByte];
+ immediateSize = SizeTypeToSize[emi.opSize - 1][immType];
//Determine what to expect next
if (UsesModRM[emi.opcode.num - 1][nextByte]) {
nextState = ModRMState;
- } else if(immediateSize) {
- nextState = ImmediateState;
} else {
- emiIsReady = true;
- nextState = PrefixState;
+ //If there's no modRM byte, set it to 0 so we can detect
+ //that later.
+ emi.modRM = 0;
+ if(immediateSize) {
+ nextState = ImmediateState;
+ } else {
+ emiIsReady = true;
+ nextState = PrefixState;
+ }
}
}
return nextState;
@@ -241,11 +262,11 @@ namespace X86ISA
displacementSize = 0;
} else {
//figure out 32/64 bit displacement size
- if(nextByte & 0xC7 == 0x05 ||
+ if(nextByte & 0xC6 == 0x04 ||
nextByte & 0xC0 == 0x80)
displacementSize = 4;
else if(nextByte & 0xC0 == 0x40)
- displacementSize = 2;
+ displacementSize = 1;
else
displacementSize = 0;
}
@@ -346,6 +367,16 @@ namespace X86ISA
if(immediateSize == immediateCollected)
{
+ //XXX Warning! The following is an observed pattern and might
+ //not always be true!
+
+ //Instructions which use 64 bit operands but 32 bit immediates
+ //need to have the immediate sign extended to 64 bits.
+ //Instructions which use true 64 bit immediates won't be
+ //affected, and instructions that use true 32 bit immediates
+ //won't notice.
+ if(immediateSize == 4)
+ emi.immediate = sext<32>(emi.immediate);
DPRINTF(Predecoder, "Collected immediate %#x.\n",
emi.immediate);
emiIsReady = true;
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index 1df17d6d2..6562ab9f5 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -73,7 +73,7 @@ namespace X86ISA
static const uint8_t Prefixes[256];
static const uint8_t UsesModRM[2][256];
static const uint8_t ImmediateType[2][256];
- static const uint8_t ImmediateTypeToSize[3][10];
+ static const uint8_t SizeTypeToSize[3][10];
protected:
ThreadContext * tc;
diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc
index f233ad234..38b9c57a3 100644
--- a/src/arch/x86/predecoder_tables.cc
+++ b/src/arch/x86/predecoder_tables.cc
@@ -141,7 +141,7 @@ namespace X86ISA
}
};
- enum ImmediateTypes {
+ enum SizeType {
NoImm,
NI = NoImm,
ByteImm,
@@ -158,19 +158,19 @@ namespace X86ISA
VW = VWordImm,
ZWordImm,
ZW = ZWordImm,
- Pointer,
- PO = Pointer,
//The enter instruction takes -2- immediates for a total of 3 bytes
Enter,
- EN = Enter
+ EN = Enter,
+ Pointer,
+ PO = Pointer
};
- const uint8_t Predecoder::ImmediateTypeToSize[3][10] =
+ const uint8_t Predecoder::SizeTypeToSize[3][10] =
{
-// noimm byte word dword qword oword vword zword enter
- {0, 1, 2, 4, 8, 16, 2, 2, 3, 4}, //16 bit
- {0, 1, 2, 4, 8, 16, 4, 4, 3, 6}, //32 bit
- {0, 1, 2, 4, 8, 16, 4, 8, 3, 0} //64 bit
+// noimm byte word dword qword oword vword zword enter pointer
+ {0, 1, 2, 4, 8, 16, 2, 2, 3, 4 }, //16 bit
+ {0, 1, 2, 4, 8, 16, 4, 4, 3, 6 }, //32 bit
+ {0, 1, 2, 4, 8, 16, 4, 8, 3, 0 } //64 bit
};
//This table determines the immediate type. The first index is the
diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh
index ca4a15d24..022f20ee5 100644
--- a/src/arch/x86/types.hh
+++ b/src/arch/x86/types.hh
@@ -70,25 +70,31 @@ namespace X86ISA
typedef uint64_t MachInst;
enum Prefixes {
- NoOverride = 0,
- CSOverride = 1,
- DSOverride = 2,
- ESOverride = 3,
- FSOverride = 4,
- GSOverride = 5,
- SSOverride = 6,
- //The Rex prefix obviously doesn't fit in with the above, but putting
- //it here lets us save double the space the enums take up.
- RexPrefix = 7,
+ NoOverride,
+ CSOverride,
+ DSOverride,
+ ESOverride,
+ FSOverride,
+ GSOverride,
+ SSOverride,
+ RexPrefix,
+ OperandSizeOverride,
+ AddressSizeOverride,
+ Lock,
+ Rep,
+ Repne
+ };
+
+ BitUnion8(LegacyPrefixVector)
+ Bitfield<7> repne;
+ Bitfield<6> rep;
+ Bitfield<5> lock;
+ Bitfield<4> addr;
+ Bitfield<3> op;
//There can be only one segment override, so they share the
//first 3 bits in the legacyPrefixes bitfield.
- SegmentOverride = 0x7,
- OperandSizeOverride = 8,
- AddressSizeOverride = 16,
- Lock = 32,
- Rep = 64,
- Repne = 128
- };
+ Bitfield<2,0> seg;
+ EndBitUnion(LegacyPrefixVector)
BitUnion8(ModRM)
Bitfield<7,6> mod;
@@ -118,7 +124,7 @@ namespace X86ISA
struct ExtMachInst
{
//Prefixes
- uint8_t legacy;
+ LegacyPrefixVector legacy;
Rex rex;
//This holds all of the bytes of the opcode
struct
@@ -140,6 +146,10 @@ namespace X86ISA
//Immediate fields
uint64_t immediate;
uint64_t displacement;
+
+ //The effective operand size.
+ uint8_t opSize;
+ //The
};
inline static std::ostream &
@@ -161,7 +171,26 @@ namespace X86ISA
inline static bool
operator == (const ExtMachInst &emi1, const ExtMachInst &emi2)
{
- //Since this is empty, it's always equal
+ if(emi1.legacy != emi2.legacy)
+ return false;
+ if(emi1.rex != emi2.rex)
+ return false;
+ if(emi1.opcode.num != emi2.opcode.num)
+ return false;
+ if(emi1.opcode.op != emi2.opcode.op)
+ return false;
+ if(emi1.opcode.prefixA != emi2.opcode.prefixA)
+ return false;
+ if(emi1.opcode.prefixB != emi2.opcode.prefixB)
+ return false;
+ if(emi1.modRM != emi2.modRM)
+ return false;
+ if(emi1.sib != emi2.sib)
+ return false;
+ if(emi1.immediate != emi2.immediate)
+ return false;
+ if(emi1.displacement != emi2.displacement)
+ return false;
return true;
}
diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh
index d89e223de..1c98e7fbc 100644
--- a/src/arch/x86/utility.hh
+++ b/src/arch/x86/utility.hh
@@ -70,8 +70,16 @@ namespace __hash_namespace {
template<>
struct hash<X86ISA::ExtMachInst> {
size_t operator()(const X86ISA::ExtMachInst &emi) const {
- //Because these are all the same, return 0
- return 0;
+ return (((uint64_t)emi.legacy << 56) |
+ ((uint64_t)emi.rex << 48) |
+ ((uint64_t)emi.modRM << 40) |
+ ((uint64_t)emi.sib << 32) |
+ ((uint64_t)emi.opcode.num << 24) |
+ ((uint64_t)emi.opcode.prefixA << 16) |
+ ((uint64_t)emi.opcode.prefixB << 8) |
+ ((uint64_t)emi.opcode.op)) ^
+ emi.immediate ^ emi.displacement ^
+ emi.opSize;
};
};
}
diff --git a/src/base/SConscript b/src/base/SConscript
index 6fc140145..5e4aaafc2 100644
--- a/src/base/SConscript
+++ b/src/base/SConscript
@@ -97,3 +97,5 @@ Source('stats/visit.cc')
if env['USE_MYSQL']:
Source('mysql.cc')
Source('stats/mysql.cc')
+
+PySource('m5', 'traceflags.py')
diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh
index 6c6d90076..eed05c2f1 100644
--- a/src/cpu/base_dyn_inst.hh
+++ b/src/cpu/base_dyn_inst.hh
@@ -877,6 +877,11 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
effAddrValid = true;
physEffAddr = req->getPaddr();
memReqFlags = req->getFlags();
+
+ if (req->isCondSwap()) {
+ assert(res);
+ req->setExtraData(*res);
+ }
#if 0
if (cpu->system->memctrl->badaddr(physEffAddr)) {
fault = TheISA::genMachineCheckFault();
diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc
index c568b1439..3e2b0f03e 100644
--- a/src/cpu/exetrace.cc
+++ b/src/cpu/exetrace.cc
@@ -652,7 +652,7 @@ Trace::InstRecord::dump()
predecoder.setTC(thread);
predecoder.moreBytes(m5Pc, 0, shared_data->instruction);
- assert(predecoder.extMachInstRead());
+ assert(predecoder.extMachInstReady());
StaticInstPtr legionInst =
StaticInst::decode(predecoder.getExtMachInst());
diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh
index 304ee6c38..1754300d2 100644
--- a/src/cpu/o3/alpha/cpu_impl.hh
+++ b/src/cpu/o3/alpha/cpu_impl.hh
@@ -55,7 +55,7 @@
#endif
template <class Impl>
-AlphaO3CPU<Impl>::AlphaO3CPU(Params *params) : FullO3CPU<Impl>(params)
+AlphaO3CPU<Impl>::AlphaO3CPU(Params *params) : FullO3CPU<Impl>(this, params)
{
DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n");
@@ -124,17 +124,6 @@ AlphaO3CPU<Impl>::AlphaO3CPU(Params *params) : FullO3CPU<Impl>(params)
this->thread[i]->setFuncExeInst(0);
}
- // Sets CPU pointers. These must be set at this level because the CPU
- // pointers are defined to be the highest level of CPU class.
- this->fetch.setCPU(this);
- this->decode.setCPU(this);
- this->rename.setCPU(this);
- this->iew.setCPU(this);
- this->commit.setCPU(this);
-
- this->rob.setCPU(this);
- this->regFile.setCPU(this);
-
lockAddr = 0;
lockFlag = false;
}
diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh
index e2ad23954..fba618c14 100644
--- a/src/cpu/o3/commit.hh
+++ b/src/cpu/o3/commit.hh
@@ -136,7 +136,7 @@ class DefaultCommit
public:
/** Construct a DefaultCommit with the given parameters. */
- DefaultCommit(Params *params);
+ DefaultCommit(O3CPU *_cpu, Params *params);
/** Returns the name of the DefaultCommit. */
std::string name() const;
@@ -144,9 +144,6 @@ class DefaultCommit
/** Registers statistics. */
void regStats();
- /** Sets the CPU pointer. */
- void setCPU(O3CPU *cpu_ptr);
-
/** Sets the list of threads. */
void setThreads(std::vector<Thread *> &threads);
diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index 3fd85595f..65625065d 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -71,8 +71,9 @@ DefaultCommit<Impl>::TrapEvent::description()
}
template <class Impl>
-DefaultCommit<Impl>::DefaultCommit(Params *params)
- : squashCounter(0),
+DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, Params *params)
+ : cpu(_cpu),
+ squashCounter(0),
iewToCommitDelay(params->iewToCommitDelay),
commitToIEWDelay(params->commitToIEWDelay),
renameToROBDelay(params->renameToROBDelay),
@@ -227,20 +228,6 @@ DefaultCommit<Impl>::regStats()
template <class Impl>
void
-DefaultCommit<Impl>::setCPU(O3CPU *cpu_ptr)
-{
- DPRINTF(Commit, "Commit: Setting CPU pointer.\n");
- cpu = cpu_ptr;
-
- // Commit must broadcast the number of free entries it has at the start of
- // the simulation, so it starts as active.
- cpu->activateStage(O3CPU::CommitIdx);
-
- trapLatency = cpu->cycles(trapLatency);
-}
-
-template <class Impl>
-void
DefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads)
{
thread = threads;
@@ -250,7 +237,6 @@ template <class Impl>
void
DefaultCommit<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
{
- DPRINTF(Commit, "Commit: Setting time buffer pointer.\n");
timeBuffer = tb_ptr;
// Setup wire to send information back to IEW.
@@ -264,7 +250,6 @@ template <class Impl>
void
DefaultCommit<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
{
- DPRINTF(Commit, "Commit: Setting fetch queue pointer.\n");
fetchQueue = fq_ptr;
// Setup wire to get instructions from rename (for the ROB).
@@ -275,7 +260,6 @@ template <class Impl>
void
DefaultCommit<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
{
- DPRINTF(Commit, "Commit: Setting rename queue pointer.\n");
renameQueue = rq_ptr;
// Setup wire to get instructions from rename (for the ROB).
@@ -286,7 +270,6 @@ template <class Impl>
void
DefaultCommit<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
{
- DPRINTF(Commit, "Commit: Setting IEW queue pointer.\n");
iewQueue = iq_ptr;
// Setup wire to get instructions from IEW.
@@ -304,7 +287,6 @@ template<class Impl>
void
DefaultCommit<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
- DPRINTF(Commit, "Commit: Setting active threads list pointer.\n");
activeThreads = at_ptr;
}
@@ -312,8 +294,6 @@ template <class Impl>
void
DefaultCommit<Impl>::setRenameMap(RenameMap rm_ptr[])
{
- DPRINTF(Commit, "Setting rename map pointers.\n");
-
for (int i=0; i < numThreads; i++) {
renameMap[i] = &rm_ptr[i];
}
@@ -323,7 +303,6 @@ template <class Impl>
void
DefaultCommit<Impl>::setROB(ROB *rob_ptr)
{
- DPRINTF(Commit, "Commit: Setting ROB pointer.\n");
rob = rob_ptr;
}
@@ -341,7 +320,12 @@ DefaultCommit<Impl>::initStage()
toIEW->commitInfo[i].emptyROB = true;
}
+ // Commit must broadcast the number of free entries it has at the
+ // start of the simulation, so it starts as active.
+ cpu->activateStage(O3CPU::CommitIdx);
+
cpu->activityThisCycle();
+ trapLatency = cpu->cycles(trapLatency);
}
template <class Impl>
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index 354e3c490..2e6a43f9c 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -148,7 +148,7 @@ FullO3CPU<Impl>::DeallocateContextEvent::description()
}
template <class Impl>
-FullO3CPU<Impl>::FullO3CPU(Params *params)
+FullO3CPU<Impl>::FullO3CPU(O3CPU *o3_cpu, Params *params)
: BaseO3CPU(params),
#if FULL_SYSTEM
itb(params->itb),
@@ -156,19 +156,21 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
#endif
tickEvent(this),
removeInstsThisCycle(false),
- fetch(params),
- decode(params),
- rename(params),
- iew(params),
- commit(params),
+ fetch(o3_cpu, params),
+ decode(o3_cpu, params),
+ rename(o3_cpu, params),
+ iew(o3_cpu, params),
+ commit(o3_cpu, params),
- regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
+ regFile(o3_cpu, params->numPhysIntRegs,
+ params->numPhysFloatRegs),
freeList(params->numberOfThreads,
TheISA::NumIntRegs, params->numPhysIntRegs,
TheISA::NumFloatRegs, params->numPhysFloatRegs),
- rob(params->numROBEntries, params->squashWidth,
+ rob(o3_cpu,
+ params->numROBEntries, params->squashWidth,
params->smtROBPolicy, params->smtROBThreshold,
params->numberOfThreads),
diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh
index 0ab20ba2a..e71d05c8e 100644
--- a/src/cpu/o3/cpu.hh
+++ b/src/cpu/o3/cpu.hh
@@ -95,6 +95,7 @@ class FullO3CPU : public BaseO3CPU
typedef typename Impl::CPUPol CPUPolicy;
typedef typename Impl::Params Params;
typedef typename Impl::DynInstPtr DynInstPtr;
+ typedef typename Impl::O3CPU O3CPU;
typedef O3ThreadState<Impl> Thread;
@@ -256,7 +257,7 @@ class FullO3CPU : public BaseO3CPU
public:
/** Constructs a CPU with the given parameters. */
- FullO3CPU(Params *params);
+ FullO3CPU(O3CPU *o3_cpu, Params *params);
/** Destructor. */
~FullO3CPU();
diff --git a/src/cpu/o3/decode.hh b/src/cpu/o3/decode.hh
index 4a845e670..3e82033ca 100644
--- a/src/cpu/o3/decode.hh
+++ b/src/cpu/o3/decode.hh
@@ -86,7 +86,7 @@ class DefaultDecode
public:
/** DefaultDecode constructor. */
- DefaultDecode(Params *params);
+ DefaultDecode(O3CPU *_cpu, Params *params);
/** Returns the name of decode. */
std::string name() const;
@@ -94,9 +94,6 @@ class DefaultDecode
/** Registers statistics. */
void regStats();
- /** Sets CPU pointer. */
- void setCPU(O3CPU *cpu_ptr);
-
/** Sets the main backwards communication time buffer pointer. */
void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh
index 79a0bfdbf..314864f94 100644
--- a/src/cpu/o3/decode_impl.hh
+++ b/src/cpu/o3/decode_impl.hh
@@ -31,8 +31,9 @@
#include "cpu/o3/decode.hh"
template<class Impl>
-DefaultDecode<Impl>::DefaultDecode(Params *params)
- : renameToDecodeDelay(params->renameToDecodeDelay),
+DefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, Params *params)
+ : cpu(_cpu),
+ renameToDecodeDelay(params->renameToDecodeDelay),
iewToDecodeDelay(params->iewToDecodeDelay),
commitToDecodeDelay(params->commitToDecodeDelay),
fetchToDecodeDelay(params->fetchToDecodeDelay),
@@ -112,17 +113,8 @@ DefaultDecode<Impl>::regStats()
template<class Impl>
void
-DefaultDecode<Impl>::setCPU(O3CPU *cpu_ptr)
-{
- DPRINTF(Decode, "Setting CPU pointer.\n");
- cpu = cpu_ptr;
-}
-
-template<class Impl>
-void
DefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
{
- DPRINTF(Decode, "Setting time buffer pointer.\n");
timeBuffer = tb_ptr;
// Setup wire to write information back to fetch.
@@ -138,7 +130,6 @@ template<class Impl>
void
DefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
{
- DPRINTF(Decode, "Setting decode queue pointer.\n");
decodeQueue = dq_ptr;
// Setup wire to write information to proper place in decode queue.
@@ -149,7 +140,6 @@ template<class Impl>
void
DefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
{
- DPRINTF(Decode, "Setting fetch queue pointer.\n");
fetchQueue = fq_ptr;
// Setup wire to read information from fetch queue.
@@ -160,7 +150,6 @@ template<class Impl>
void
DefaultDecode<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
- DPRINTF(Decode, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
}
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index 811f4d2bc..241935416 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -160,7 +160,7 @@ class DefaultFetch
public:
/** DefaultFetch constructor. */
- DefaultFetch(Params *params);
+ DefaultFetch(O3CPU *_cpu, Params *params);
/** Returns the name of fetch. */
std::string name() const;
@@ -171,9 +171,6 @@ class DefaultFetch
/** Returns the icache port. */
Port *getIcachePort() { return icachePort; }
- /** Sets CPU pointer. */
- void setCPU(O3CPU *cpu_ptr);
-
/** Sets the main backwards communication time buffer pointer. */
void setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer);
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 34b06420d..e16f97558 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -110,8 +110,9 @@ DefaultFetch<Impl>::IcachePort::recvRetry()
}
template<class Impl>
-DefaultFetch<Impl>::DefaultFetch(Params *params)
- : branchPred(params),
+DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, Params *params)
+ : cpu(_cpu),
+ branchPred(params),
predecoder(NULL),
decodeToFetchDelay(params->decodeToFetchDelay),
renameToFetchDelay(params->renameToFetchDelay),
@@ -163,6 +164,17 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
// Get the size of an instruction.
instSize = sizeof(TheISA::MachInst);
+
+ // Name is finally available, so create the port.
+ icachePort = new IcachePort(this);
+
+ icachePort->snoopRangeSent = false;
+
+#if USE_CHECKER
+ if (cpu->checker) {
+ cpu->checker->setIcachePort(icachePort);
+ }
+#endif
}
template <class Impl>
@@ -264,35 +276,8 @@ DefaultFetch<Impl>::regStats()
template<class Impl>
void
-DefaultFetch<Impl>::setCPU(O3CPU *cpu_ptr)
-{
- DPRINTF(Fetch, "Setting the CPU pointer.\n");
- cpu = cpu_ptr;
-
- // Name is finally available, so create the port.
- icachePort = new IcachePort(this);
-
- icachePort->snoopRangeSent = false;
-
-#if USE_CHECKER
- if (cpu->checker) {
- cpu->checker->setIcachePort(icachePort);
- }
-#endif
-
- // Schedule fetch to get the correct PC from the CPU
- // scheduleFetchStartupEvent(1);
-
- // Fetch needs to start fetching instructions at the very beginning,
- // so it must start up in active state.
- switchToActive();
-}
-
-template<class Impl>
-void
DefaultFetch<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer)
{
- DPRINTF(Fetch, "Setting the time buffer pointer.\n");
timeBuffer = time_buffer;
// Create wires to get information from proper places in time buffer.
@@ -306,7 +291,6 @@ template<class Impl>
void
DefaultFetch<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
- DPRINTF(Fetch, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
}
@@ -314,7 +298,6 @@ template<class Impl>
void
DefaultFetch<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
{
- DPRINTF(Fetch, "Setting the fetch queue pointer.\n");
fetchQueue = fq_ptr;
// Create wire to write information to proper place in fetch queue.
@@ -345,6 +328,13 @@ DefaultFetch<Impl>::initStage()
stalls[tid].iew = false;
stalls[tid].commit = false;
}
+
+ // Schedule fetch to get the correct PC from the CPU
+ // scheduleFetchStartupEvent(1);
+
+ // Fetch needs to start fetching instructions at the very beginning,
+ // so it must start up in active state.
+ switchToActive();
}
template<class Impl>
diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh
index a400c9fa8..ce2991cfb 100644
--- a/src/cpu/o3/iew.hh
+++ b/src/cpu/o3/iew.hh
@@ -115,7 +115,7 @@ class DefaultIEW
public:
/** Constructs a DefaultIEW with the given parameters. */
- DefaultIEW(Params *params);
+ DefaultIEW(O3CPU *_cpu, Params *params);
/** Returns the name of the DefaultIEW stage. */
std::string name() const;
@@ -129,9 +129,6 @@ class DefaultIEW
/** Returns the dcache port. */
Port *getDcachePort() { return ldstQueue.getDcachePort(); }
- /** Sets CPU pointer for IEW, IQ, and LSQ. */
- void setCPU(O3CPU *cpu_ptr);
-
/** Sets main time buffer used for backwards communication. */
void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
@@ -367,16 +364,6 @@ class DefaultIEW
/** Scoreboard pointer. */
Scoreboard* scoreboard;
- public:
- /** Instruction queue. */
- IQ instQueue;
-
- /** Load / store queue. */
- LSQ ldstQueue;
-
- /** Pointer to the functional unit pool. */
- FUPool *fuPool;
-
private:
/** CPU pointer. */
O3CPU *cpu;
@@ -398,6 +385,14 @@ class DefaultIEW
void printAvailableInsts();
public:
+ /** Instruction queue. */
+ IQ instQueue;
+
+ /** Load / store queue. */
+ LSQ ldstQueue;
+
+ /** Pointer to the functional unit pool. */
+ FUPool *fuPool;
/** Records if the LSQ needs to be updated on the next cycle, so that
* IEW knows if there will be activity on the next cycle.
*/
diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
index 4883e5a5c..62e656e93 100644
--- a/src/cpu/o3/iew_impl.hh
+++ b/src/cpu/o3/iew_impl.hh
@@ -39,10 +39,11 @@
#include "cpu/o3/iew.hh"
template<class Impl>
-DefaultIEW<Impl>::DefaultIEW(Params *params)
+DefaultIEW<Impl>::DefaultIEW(O3CPU *_cpu, Params *params)
: issueToExecQueue(params->backComSize, params->forwardComSize),
- instQueue(params),
- ldstQueue(params),
+ cpu(_cpu),
+ instQueue(_cpu, this, params),
+ ldstQueue(_cpu, this, params),
fuPool(params->fuPool),
commitToIEWDelay(params->commitToIEWDelay),
renameToIEWDelay(params->renameToIEWDelay),
@@ -64,9 +65,6 @@ DefaultIEW<Impl>::DefaultIEW(Params *params)
// Instruction queue needs the queue between issue and execute.
instQueue.setIssueToExecuteQueue(&issueToExecQueue);
- instQueue.setIEW(this);
- ldstQueue.setIEW(this);
-
for (int i=0; i < numThreads; i++) {
dispatchStatus[i] = Running;
stalls[i].commit = false;
@@ -276,17 +274,6 @@ DefaultIEW<Impl>::initStage()
toRename->iewInfo[tid].freeLSQEntries =
ldstQueue.numFreeEntries(tid);
}
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::setCPU(O3CPU *cpu_ptr)
-{
- DPRINTF(IEW, "Setting CPU pointer.\n");
- cpu = cpu_ptr;
-
- instQueue.setCPU(cpu_ptr);
- ldstQueue.setCPU(cpu_ptr);
cpu->activateStage(O3CPU::IEWIdx);
}
@@ -295,7 +282,6 @@ template<class Impl>
void
DefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
{
- DPRINTF(IEW, "Setting time buffer pointer.\n");
timeBuffer = tb_ptr;
// Setup wire to read information from time buffer, from commit.
@@ -314,7 +300,6 @@ template<class Impl>
void
DefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
{
- DPRINTF(IEW, "Setting rename queue pointer.\n");
renameQueue = rq_ptr;
// Setup wire to read information from rename queue.
@@ -325,7 +310,6 @@ template<class Impl>
void
DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
{
- DPRINTF(IEW, "Setting IEW queue pointer.\n");
iewQueue = iq_ptr;
// Setup wire to write instructions to commit.
@@ -336,7 +320,6 @@ template<class Impl>
void
DefaultIEW<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
- DPRINTF(IEW, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
ldstQueue.setActiveThreads(at_ptr);
@@ -347,7 +330,6 @@ template<class Impl>
void
DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
{
- DPRINTF(IEW, "Setting scoreboard pointer.\n");
scoreboard = sb_ptr;
}
diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh
index 3dd4dc658..9d7c457ca 100644
--- a/src/cpu/o3/inst_queue.hh
+++ b/src/cpu/o3/inst_queue.hh
@@ -110,7 +110,7 @@ class InstructionQueue
};
/** Constructs an IQ. */
- InstructionQueue(Params *params);
+ InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params);
/** Destructs the IQ. */
~InstructionQueue();
@@ -124,15 +124,9 @@ class InstructionQueue
/** Resets all instruction queue state. */
void resetState();
- /** Sets CPU pointer. */
- void setCPU(O3CPU *_cpu) { cpu = _cpu; }
-
/** Sets active threads list. */
void setActiveThreads(std::list<unsigned> *at_ptr);
- /** Sets the IEW pointer. */
- void setIEW(IEW *iew_ptr) { iewStage = iew_ptr; }
-
/** Sets the timer buffer between issue and execute. */
void setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2eQueue);
diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh
index 79e03d4bf..10c3287f2 100644
--- a/src/cpu/o3/inst_queue_impl.hh
+++ b/src/cpu/o3/inst_queue_impl.hh
@@ -64,8 +64,11 @@ InstructionQueue<Impl>::FUCompletion::description()
}
template <class Impl>
-InstructionQueue<Impl>::InstructionQueue(Params *params)
- : fuPool(params->fuPool),
+InstructionQueue<Impl>::InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr,
+ Params *params)
+ : cpu(cpu_ptr),
+ iewStage(iew_ptr),
+ fuPool(params->fuPool),
numEntries(params->numIQEntries),
totalWidth(params->issueWidth),
numPhysIntRegs(params->numPhysIntRegs),
@@ -81,8 +84,6 @@ InstructionQueue<Impl>::InstructionQueue(Params *params)
// Set the number of physical registers as the number of int + float
numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
- DPRINTF(IQ, "There are %i physical registers.\n", numPhysRegs);
-
//Create an entry for each physical register within the
//dependency graph.
dependGraph.resize(numPhysRegs);
@@ -126,7 +127,6 @@ InstructionQueue<Impl>::InstructionQueue(Params *params)
DPRINTF(IQ, "IQ sharing policy set to Partitioned:"
"%i entries per thread.\n",part_amt);
-
} else if (policy == "threshold") {
iqPolicy = Threshold;
@@ -360,7 +360,6 @@ template <class Impl>
void
InstructionQueue<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
- DPRINTF(IQ, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
}
@@ -368,15 +367,13 @@ template <class Impl>
void
InstructionQueue<Impl>::setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2e_ptr)
{
- DPRINTF(IQ, "Set the issue to execute queue.\n");
- issueToExecuteQueue = i2e_ptr;
+ issueToExecuteQueue = i2e_ptr;
}
template <class Impl>
void
InstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
{
- DPRINTF(IQ, "Set the time buffer.\n");
timeBuffer = tb_ptr;
fromCommit = timeBuffer->getWire(-commitToIEWDelay);
diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh
index 80f53a726..fd8f878a7 100644
--- a/src/cpu/o3/lsq.hh
+++ b/src/cpu/o3/lsq.hh
@@ -57,7 +57,7 @@ class LSQ {
};
/** Constructs an LSQ with the given parameters. */
- LSQ(Params *params);
+ LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params);
/** Returns the name of the LSQ. */
std::string name() const;
@@ -74,10 +74,6 @@ class LSQ {
/** Sets the pointer to the list of active threads. */
void setActiveThreads(std::list<unsigned> *at_ptr);
- /** Sets the CPU pointer. */
- void setCPU(O3CPU *cpu_ptr);
- /** Sets the IEW stage pointer. */
- void setIEW(IEW *iew_ptr);
/** Switches out the LSQ. */
void switchOut();
/** Takes over execution from another CPU's thread. */
@@ -283,6 +279,12 @@ class LSQ {
template <class T>
Fault write(RequestPtr req, T &data, int store_idx);
+ /** The CPU pointer. */
+ O3CPU *cpu;
+
+ /** The IEW stage pointer. */
+ IEW *iewStage;
+
/** DcachePort class for this LSQ. Handles doing the
* communication with the cache/memory.
*/
@@ -295,7 +297,7 @@ class LSQ {
public:
/** Default constructor. */
DcachePort(LSQ *_lsq)
- : lsq(_lsq)
+ : Port(_lsq->name() + "-dport"), lsq(_lsq)
{ }
bool snoopRangeSent;
@@ -341,12 +343,6 @@ class LSQ {
/** The LSQ units for individual threads. */
LSQUnit thread[Impl::MaxThreads];
- /** The CPU pointer. */
- O3CPU *cpu;
-
- /** The IEW stage pointer. */
- IEW *iewStage;
-
/** List of Active Threads in System. */
std::list<unsigned> *activeThreads;
diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh
index d4994fcb7..b4a6a02da 100644
--- a/src/cpu/o3/lsq_impl.hh
+++ b/src/cpu/o3/lsq_impl.hh
@@ -107,13 +107,13 @@ LSQ<Impl>::DcachePort::recvRetry()
}
template <class Impl>
-LSQ<Impl>::LSQ(Params *params)
- : dcachePort(this), LQEntries(params->LQEntries),
- SQEntries(params->SQEntries), numThreads(params->numberOfThreads),
+LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params)
+ : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this),
+ LQEntries(params->LQEntries),
+ SQEntries(params->SQEntries),
+ numThreads(params->numberOfThreads),
retryTid(-1)
{
- DPRINTF(LSQ, "Creating LSQ object.\n");
-
dcachePort.snoopRangeSent = false;
//**********************************************/
@@ -133,7 +133,6 @@ LSQ<Impl>::LSQ(Params *params)
maxSQEntries = SQEntries;
DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
-
} else if (policy == "partitioned") {
lsqPolicy = Partitioned;
@@ -144,7 +143,6 @@ LSQ<Impl>::LSQ(Params *params)
DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
"%i entries per LQ | %i entries per SQ",
maxLQEntries,maxSQEntries);
-
} else if (policy == "threshold") {
lsqPolicy = Threshold;
@@ -160,7 +158,6 @@ LSQ<Impl>::LSQ(Params *params)
DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
"%i entries per LQ | %i entries per SQ",
maxLQEntries,maxSQEntries);
-
} else {
assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic,"
"Partitioned, Threshold}");
@@ -168,7 +165,8 @@ LSQ<Impl>::LSQ(Params *params)
//Initialize LSQs
for (int tid=0; tid < numThreads; tid++) {
- thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid);
+ thread[tid].init(cpu, iew_ptr, params, this,
+ maxLQEntries, maxSQEntries, tid);
thread[tid].setDcachePort(&dcachePort);
}
}
@@ -199,30 +197,6 @@ LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
assert(activeThreads != 0);
}
-template<class Impl>
-void
-LSQ<Impl>::setCPU(O3CPU *cpu_ptr)
-{
- cpu = cpu_ptr;
-
- dcachePort.setName(name());
-
- for (int tid=0; tid < numThreads; tid++) {
- thread[tid].setCPU(cpu_ptr);
- }
-}
-
-template<class Impl>
-void
-LSQ<Impl>::setIEW(IEW *iew_ptr)
-{
- iewStage = iew_ptr;
-
- for (int tid=0; tid < numThreads; tid++) {
- thread[tid].setIEW(iew_ptr);
- }
-}
-
template <class Impl>
void
LSQ<Impl>::switchOut()
diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh
index 1b10843f5..f24de20d9 100644
--- a/src/cpu/o3/lsq_unit.hh
+++ b/src/cpu/o3/lsq_unit.hh
@@ -73,8 +73,8 @@ class LSQUnit {
LSQUnit();
/** Initializes the LSQ unit with the specified number of entries. */
- void init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
- unsigned maxSQEntries, unsigned id);
+ void init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr,
+ unsigned maxLQEntries, unsigned maxSQEntries, unsigned id);
/** Returns the name of the LSQ unit. */
std::string name() const;
@@ -82,16 +82,8 @@ class LSQUnit {
/** Registers statistics. */
void regStats();
- /** Sets the CPU pointer. */
- void setCPU(O3CPU *cpu_ptr);
-
- /** Sets the IEW stage pointer. */
- void setIEW(IEW *iew_ptr)
- { iewStage = iew_ptr; }
-
/** Sets the pointer to the dcache port. */
- void setDcachePort(Port *dcache_port)
- { dcachePort = dcache_port; }
+ void setDcachePort(Port *dcache_port);
/** Switches out LSQ unit. */
void switchOut();
@@ -297,15 +289,19 @@ class LSQUnit {
struct SQEntry {
/** Constructs an empty store queue entry. */
SQEntry()
- : inst(NULL), req(NULL), size(0), data(0),
+ : inst(NULL), req(NULL), size(0),
canWB(0), committed(0), completed(0)
- { }
+ {
+ bzero(data, sizeof(data));
+ }
/** Constructs a store queue entry for a given instruction. */
SQEntry(DynInstPtr &_inst)
- : inst(_inst), req(NULL), size(0), data(0),
+ : inst(_inst), req(NULL), size(0),
canWB(0), committed(0), completed(0)
- { }
+ {
+ bzero(data, sizeof(data));
+ }
/** The store instruction. */
DynInstPtr inst;
@@ -314,7 +310,7 @@ class LSQUnit {
/** The size of the store. */
int size;
/** The store data. */
- IntReg data;
+ char data[sizeof(IntReg)];
/** Whether or not the store can writeback. */
bool canWB;
/** Whether or not the store is committed. */
@@ -562,22 +558,14 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
if ((store_has_lower_limit && store_has_upper_limit)) {
// Get shift amount for offset into the store's data.
int shift_amt = req->getVaddr() & (store_size - 1);
- // @todo: Magic number, assumes byte addressing
- shift_amt = shift_amt << 3;
- // Cast this to type T?
- data = storeQueue[store_idx].data >> shift_amt;
-
- // When the data comes from the store queue entry, it's in host
- // order. When it gets sent to the load, it needs to be in guest
- // order so when the load converts it again, it ends up back
- // in host order like the inst expects.
- data = TheISA::htog(data);
+ memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T));
assert(!load_inst->memData);
load_inst->memData = new uint8_t[64];
- memcpy(load_inst->memData, &data, req->getSize());
+ memcpy(load_inst->memData,
+ storeQueue[store_idx].data + shift_amt, req->getSize());
DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
"addr %#x, data %#x\n",
@@ -724,7 +712,10 @@ LSQUnit<Impl>::write(Request *req, T &data, int store_idx)
storeQueue[store_idx].req = req;
storeQueue[store_idx].size = sizeof(T);
- storeQueue[store_idx].data = data;
+ assert(sizeof(T) <= sizeof(storeQueue[store_idx].data));
+
+ T gData = htog(data);
+ memcpy(storeQueue[store_idx].data, &gData, sizeof(T));
// This function only writes the data to the store queue, so no fault
// can happen here.
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index e70c960b3..44e2cea76 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -57,6 +57,11 @@ LSQUnit<Impl>::WritebackEvent::process()
if (!lsqPtr->isSwitchedOut()) {
lsqPtr->writeback(inst, pkt);
}
+
+ if (pkt->senderState)
+ delete pkt->senderState;
+
+ delete pkt->req;
delete pkt;
}
@@ -80,10 +85,6 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
if (isSwitchedOut() || inst->isSquashed()) {
iewStage->decrWb(inst->seqNum);
- delete state;
- delete pkt->req;
- delete pkt;
- return;
} else {
if (!state->noWB) {
writeback(inst, pkt);
@@ -109,9 +110,12 @@ LSQUnit<Impl>::LSQUnit()
template<class Impl>
void
-LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
- unsigned maxSQEntries, unsigned id)
+LSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr,
+ unsigned maxLQEntries, unsigned maxSQEntries, unsigned id)
{
+ cpu = cpu_ptr;
+ iewStage = iew_ptr;
+
DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
switchedOut = false;
@@ -141,19 +145,6 @@ LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
}
template<class Impl>
-void
-LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr)
-{
- cpu = cpu_ptr;
-
-#if USE_CHECKER
- if (cpu->checker) {
- cpu->checker->setDcachePort(dcachePort);
- }
-#endif
-}
-
-template<class Impl>
std::string
LSQUnit<Impl>::name() const
{
@@ -211,6 +202,19 @@ LSQUnit<Impl>::regStats()
template<class Impl>
void
+LSQUnit<Impl>::setDcachePort(Port *dcache_port)
+{
+ dcachePort = dcache_port;
+
+#if USE_CHECKER
+ if (cpu->checker) {
+ cpu->checker->setDcachePort(dcachePort);
+ }
+#endif
+}
+
+template<class Impl>
+void
LSQUnit<Impl>::clearLQ()
{
loadQueue.clear();
@@ -641,22 +645,10 @@ LSQUnit<Impl>::writebackStores()
assert(!inst->memData);
inst->memData = new uint8_t[64];
- TheISA::IntReg convertedData =
- TheISA::htog(storeQueue[storeWBIdx].data);
-
- //FIXME This is a hack to get SPARC working. It, along with endianness
- //in the memory system in general, need to be straightened out more
- //formally. The problem is that the data's endianness is swapped when
- //it's in the 64 bit data field in the store queue. The data that you
- //want won't start at the beginning of the field anymore unless it was
- //a 64 bit access.
- memcpy(inst->memData,
- (uint8_t *)&convertedData +
- (TheISA::ByteOrderDiffers ?
- (sizeof(TheISA::IntReg) - req->getSize()) : 0),
- req->getSize());
-
- PacketPtr data_pkt = new Packet(req, MemCmd::WriteReq,
+ memcpy(inst->memData, storeQueue[storeWBIdx].data, req->getSize());
+
+ MemCmd command = req->isSwap() ? MemCmd::SwapReq : MemCmd::WriteReq;
+ PacketPtr data_pkt = new Packet(req, command,
Packet::Broadcast);
data_pkt->dataStatic(inst->memData);
@@ -673,7 +665,7 @@ LSQUnit<Impl>::writebackStores()
inst->seqNum);
// @todo: Remove this SC hack once the memory system handles it.
- if (req->isLocked()) {
+ if (inst->isStoreConditional()) {
// Disable recording the result temporarily. Writing to
// misc regs normally updates the result, but this is not
// the desired behavior when handling store conditionals.
diff --git a/src/cpu/o3/mips/cpu_builder.cc b/src/cpu/o3/mips/cpu_builder.cc
index 66741aee9..c6acc0bfb 100644
--- a/src/cpu/o3/mips/cpu_builder.cc
+++ b/src/cpu/o3/mips/cpu_builder.cc
@@ -51,6 +51,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
Param<int> clock;
Param<int> phase;
Param<int> numThreads;
+Param<int> cpu_id;
Param<int> activity;
SimObjectVectorParam<Process *> workload;
@@ -149,6 +150,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
INIT_PARAM(clock, "clock speed"),
INIT_PARAM_DFLT(phase, "clock phase", 0),
INIT_PARAM(numThreads, "number of HW thread contexts"),
+ INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM_DFLT(activity, "Initial activity count", 0),
INIT_PARAM(workload, "Processes to run"),
@@ -275,9 +277,11 @@ CREATE_SIM_OBJECT(DerivO3CPU)
MipsSimpleParams *params = new MipsSimpleParams;
params->clock = clock;
+ params->phase = phase;
params->name = getInstanceName();
params->numberOfThreads = actual_num_threads;
+ params->cpu_id = cpu_id;
params->activity = activity;
params->workload = workload;
diff --git a/src/cpu/o3/mips/cpu_impl.hh b/src/cpu/o3/mips/cpu_impl.hh
index 317fd748e..d1135f048 100644
--- a/src/cpu/o3/mips/cpu_impl.hh
+++ b/src/cpu/o3/mips/cpu_impl.hh
@@ -47,7 +47,7 @@
template <class Impl>
MipsO3CPU<Impl>::MipsO3CPU(Params *params)
- : FullO3CPU<Impl>(params)
+ : FullO3CPU<Impl>(this, params)
{
DPRINTF(O3CPU, "Creating MipsO3CPU object.\n");
@@ -95,6 +95,7 @@ MipsO3CPU<Impl>::MipsO3CPU(Params *params)
// Give the thread the TC.
this->thread[i]->tc = tc;
+ this->thread[i]->setCpuId(params->cpu_id);
// Add the TC to the CPU's list of TC's.
this->threadContexts.push_back(tc);
@@ -104,17 +105,6 @@ MipsO3CPU<Impl>::MipsO3CPU(Params *params)
this->thread[i]->setFuncExeInst(0);
}
- // Sets CPU pointers. These must be set at this level because the CPU
- // pointers are defined to be the highest level of CPU class.
- this->fetch.setCPU(this);
- this->decode.setCPU(this);
- this->rename.setCPU(this);
- this->iew.setCPU(this);
- this->commit.setCPU(this);
-
- this->rob.setCPU(this);
- this->regFile.setCPU(this);
-
lockAddr = 0;
lockFlag = false;
}
diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh
index c4f8f3a9f..b5b1cd021 100644
--- a/src/cpu/o3/regfile.hh
+++ b/src/cpu/o3/regfile.hh
@@ -76,7 +76,7 @@ class PhysRegFile
* Constructs a physical register file with the specified amount of
* integer and floating point registers.
*/
- PhysRegFile(unsigned _numPhysicalIntRegs,
+ PhysRegFile(O3CPU *_cpu, unsigned _numPhysicalIntRegs,
unsigned _numPhysicalFloatRegs);
//Everything below should be pretty well identical to the normal
@@ -174,7 +174,7 @@ class PhysRegFile
// Remove the base Float reg dependency.
reg_idx = reg_idx - numPhysicalIntRegs;
- assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
+ assert(reg_idx < numPhysicalFloatRegs);
DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n",
int(reg_idx), (uint64_t)val);
@@ -189,7 +189,7 @@ class PhysRegFile
// Remove the base Float reg dependency.
reg_idx = reg_idx - numPhysicalIntRegs;
- assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
+ assert(reg_idx < numPhysicalFloatRegs);
DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n",
int(reg_idx), (uint64_t)val);
@@ -204,7 +204,7 @@ class PhysRegFile
// Remove the base Float reg dependency.
reg_idx = reg_idx - numPhysicalIntRegs;
- assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
+ assert(reg_idx < numPhysicalFloatRegs);
DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n",
int(reg_idx), (uint64_t)val);
@@ -217,7 +217,7 @@ class PhysRegFile
// Remove the base Float reg dependency.
reg_idx = reg_idx - numPhysicalIntRegs;
- assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
+ assert(reg_idx < numPhysicalFloatRegs);
DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n",
int(reg_idx), (uint64_t)val);
@@ -232,11 +232,11 @@ class PhysRegFile
MiscReg readMiscReg(int misc_reg, unsigned thread_id)
{
- return miscRegs[thread_id].readReg(misc_reg,
- cpu->tcBase(thread_id));
+ return miscRegs[thread_id].readReg(misc_reg, cpu->tcBase(thread_id));
}
- void setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned thread_id)
+ void setMiscRegNoEffect(int misc_reg,
+ const MiscReg &val, unsigned thread_id)
{
miscRegs[thread_id].setRegNoEffect(misc_reg, val);
}
@@ -268,9 +268,6 @@ class PhysRegFile
O3CPU *cpu;
public:
- /** Sets the CPU pointer. */
- void setCPU(O3CPU *cpu_ptr) { cpu = cpu_ptr; }
-
/** Number of physical integer registers. */
unsigned numPhysicalIntRegs;
/** Number of physical floating point registers. */
@@ -278,9 +275,9 @@ class PhysRegFile
};
template <class Impl>
-PhysRegFile<Impl>::PhysRegFile(unsigned _numPhysicalIntRegs,
+PhysRegFile<Impl>::PhysRegFile(O3CPU *_cpu, unsigned _numPhysicalIntRegs,
unsigned _numPhysicalFloatRegs)
- : numPhysicalIntRegs(_numPhysicalIntRegs),
+ : cpu(_cpu), numPhysicalIntRegs(_numPhysicalIntRegs),
numPhysicalFloatRegs(_numPhysicalFloatRegs)
{
intRegFile = new IntReg[numPhysicalIntRegs];
diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh
index 6b4628f92..b2faffe43 100644
--- a/src/cpu/o3/rename.hh
+++ b/src/cpu/o3/rename.hh
@@ -107,7 +107,7 @@ class DefaultRename
public:
/** DefaultRename constructor. */
- DefaultRename(Params *params);
+ DefaultRename(O3CPU *_cpu, Params *params);
/** Returns the name of rename. */
std::string name() const;
@@ -115,9 +115,6 @@ class DefaultRename
/** Registers statistics. */
void regStats();
- /** Sets CPU pointer. */
- void setCPU(O3CPU *cpu_ptr);
-
/** Sets the main backwards communication time buffer pointer. */
void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh
index e303f1cee..431705e19 100644
--- a/src/cpu/o3/rename_impl.hh
+++ b/src/cpu/o3/rename_impl.hh
@@ -37,8 +37,9 @@
#include "cpu/o3/rename.hh"
template <class Impl>
-DefaultRename<Impl>::DefaultRename(Params *params)
- : iewToRenameDelay(params->iewToRenameDelay),
+DefaultRename<Impl>::DefaultRename(O3CPU *_cpu, Params *params)
+ : cpu(_cpu),
+ iewToRenameDelay(params->iewToRenameDelay),
decodeToRenameDelay(params->decodeToRenameDelay),
commitToRenameDelay(params->commitToRenameDelay),
renameWidth(params->renameWidth),
@@ -166,17 +167,8 @@ DefaultRename<Impl>::regStats()
template <class Impl>
void
-DefaultRename<Impl>::setCPU(O3CPU *cpu_ptr)
-{
- DPRINTF(Rename, "Setting CPU pointer.\n");
- cpu = cpu_ptr;
-}
-
-template <class Impl>
-void
DefaultRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
{
- DPRINTF(Rename, "Setting time buffer pointer.\n");
timeBuffer = tb_ptr;
// Setup wire to read information from time buffer, from IEW stage.
@@ -193,7 +185,6 @@ template <class Impl>
void
DefaultRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
{
- DPRINTF(Rename, "Setting rename queue pointer.\n");
renameQueue = rq_ptr;
// Setup wire to write information to future stages.
@@ -204,7 +195,6 @@ template <class Impl>
void
DefaultRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
{
- DPRINTF(Rename, "Setting decode queue pointer.\n");
decodeQueue = dq_ptr;
// Setup wire to get information from decode.
@@ -228,7 +218,6 @@ template<class Impl>
void
DefaultRename<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
- DPRINTF(Rename, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
}
@@ -237,8 +226,6 @@ template <class Impl>
void
DefaultRename<Impl>::setRenameMap(RenameMap rm_ptr[])
{
- DPRINTF(Rename, "Setting rename map pointers.\n");
-
for (int i=0; i<numThreads; i++) {
renameMap[i] = &rm_ptr[i];
}
@@ -248,7 +235,6 @@ template <class Impl>
void
DefaultRename<Impl>::setFreeList(FreeList *fl_ptr)
{
- DPRINTF(Rename, "Setting free list pointer.\n");
freeList = fl_ptr;
}
@@ -256,7 +242,6 @@ template<class Impl>
void
DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard)
{
- DPRINTF(Rename, "Setting scoreboard pointer.\n");
scoreboard = _scoreboard;
}
@@ -707,7 +692,7 @@ DefaultRename<Impl>::renameInsts(unsigned tid)
DPRINTF(Rename, "Blocking due to lack of free "
"physical registers to rename to.\n");
blockThisCycle = true;
-
+ insts_to_rename.push_front(inst);
++renameFullRegistersEvents;
break;
@@ -1011,7 +996,12 @@ DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst,unsigned tid)
if (src_reg < TheISA::FP_Base_DepTag) {
flat_src_reg = TheISA::flattenIntIndex(inst->tcBase(), src_reg);
DPRINTF(Rename, "Flattening index %d to %d.\n", (int)src_reg, (int)flat_src_reg);
+ } else {
+ // Floating point and Miscellaneous registers need their indexes
+ // adjusted to account for the expanded number of flattened int regs.
+ flat_src_reg = src_reg - TheISA::FP_Base_DepTag + TheISA::NumIntRegs;
}
+
inst->flattenSrcReg(src_idx, flat_src_reg);
// Look up the source registers to get the phys. register they've
@@ -1048,8 +1038,13 @@ DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst,unsigned tid)
RegIndex dest_reg = inst->destRegIdx(dest_idx);
RegIndex flat_dest_reg = dest_reg;
if (dest_reg < TheISA::FP_Base_DepTag) {
+ // Integer registers are flattened.
flat_dest_reg = TheISA::flattenIntIndex(inst->tcBase(), dest_reg);
DPRINTF(Rename, "Flattening index %d to %d.\n", (int)dest_reg, (int)flat_dest_reg);
+ } else {
+ // Floating point and Miscellaneous registers need their indexes
+ // adjusted to account for the expanded number of flattened int regs.
+ flat_dest_reg = dest_reg - TheISA::FP_Base_DepTag + TheISA::NumIntRegs;
}
inst->flattenDestReg(dest_idx, flat_dest_reg);
diff --git a/src/cpu/o3/rob.hh b/src/cpu/o3/rob.hh
index 7cd5a5143..00329abb0 100644
--- a/src/cpu/o3/rob.hh
+++ b/src/cpu/o3/rob.hh
@@ -82,17 +82,12 @@ class ROB
* @param _smtROBThreshold Max Resources(by %) a thread can have in the ROB.
* @param _numThreads The number of active threads.
*/
- ROB(unsigned _numEntries, unsigned _squashWidth, std::string smtROBPolicy,
- unsigned _smtROBThreshold, unsigned _numThreads);
+ ROB(O3CPU *_cpu, unsigned _numEntries, unsigned _squashWidth,
+ std::string smtROBPolicy, unsigned _smtROBThreshold,
+ unsigned _numThreads);
std::string name() const;
- /** Function to set the CPU pointer, necessary due to which object the ROB
- * is created within.
- * @param cpu_ptr Pointer to the implementation specific full CPU object.
- */
- void setCPU(O3CPU *cpu_ptr);
-
/** Sets pointer to the list of active threads.
* @param at_ptr Pointer to the list of active threads.
*/
diff --git a/src/cpu/o3/rob_impl.hh b/src/cpu/o3/rob_impl.hh
index fde636754..7ff3aa274 100644
--- a/src/cpu/o3/rob_impl.hh
+++ b/src/cpu/o3/rob_impl.hh
@@ -35,10 +35,11 @@
#include <list>
template <class Impl>
-ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
+ROB<Impl>::ROB(O3CPU *_cpu, unsigned _numEntries, unsigned _squashWidth,
std::string _smtROBPolicy, unsigned _smtROBThreshold,
unsigned _numThreads)
- : numEntries(_numEntries),
+ : cpu(_cpu),
+ numEntries(_numEntries),
squashWidth(_squashWidth),
numInstsInROB(0),
numThreads(_numThreads)
@@ -90,20 +91,6 @@ ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic,"
"Partitioned, Threshold}");
}
-}
-
-template <class Impl>
-std::string
-ROB<Impl>::name() const
-{
- return cpu->name() + ".rob";
-}
-
-template <class Impl>
-void
-ROB<Impl>::setCPU(O3CPU *cpu_ptr)
-{
- cpu = cpu_ptr;
// Set the per-thread iterators to the end of the instruction list.
for (int i=0; i < numThreads;i++) {
@@ -117,6 +104,13 @@ ROB<Impl>::setCPU(O3CPU *cpu_ptr)
}
template <class Impl>
+std::string
+ROB<Impl>::name() const
+{
+ return cpu->name() + ".rob";
+}
+
+template <class Impl>
void
ROB<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
diff --git a/src/cpu/o3/sparc/cpu_builder.cc b/src/cpu/o3/sparc/cpu_builder.cc
index 3cac89bad..35badce2c 100644
--- a/src/cpu/o3/sparc/cpu_builder.cc
+++ b/src/cpu/o3/sparc/cpu_builder.cc
@@ -50,11 +50,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
Param<int> clock;
Param<int> phase;
Param<int> numThreads;
+ Param<int> cpu_id;
Param<int> activity;
#if FULL_SYSTEM
SimObjectParam<System *> system;
- Param<int> cpu_id;
SimObjectParam<SparcISA::ITB *> itb;
SimObjectParam<SparcISA::DTB *> dtb;
Param<Tick> profile;
@@ -161,11 +161,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
INIT_PARAM(clock, "clock speed"),
INIT_PARAM_DFLT(phase, "clock phase", 0),
INIT_PARAM(numThreads, "number of HW thread contexts"),
+ INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM_DFLT(activity, "Initial activity count", 0),
#if FULL_SYSTEM
INIT_PARAM(system, "System object"),
- INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM(itb, "Instruction translation buffer"),
INIT_PARAM(dtb, "Data translation buffer"),
INIT_PARAM(profile, ""),
@@ -305,14 +305,15 @@ CREATE_SIM_OBJECT(DerivO3CPU)
SparcSimpleParams *params = new SparcSimpleParams;
params->clock = clock;
+ params->phase = phase;
params->name = getInstanceName();
params->numberOfThreads = actual_num_threads;
+ params->cpu_id = cpu_id;
params->activity = activity;
#if FULL_SYSTEM
params->system = system;
- params->cpu_id = cpu_id;
params->itb = itb;
params->dtb = dtb;
params->profile = profile;
diff --git a/src/cpu/o3/sparc/cpu_impl.hh b/src/cpu/o3/sparc/cpu_impl.hh
index a425a8a56..50d980f55 100644
--- a/src/cpu/o3/sparc/cpu_impl.hh
+++ b/src/cpu/o3/sparc/cpu_impl.hh
@@ -55,7 +55,7 @@
#endif
template <class Impl>
-SparcO3CPU<Impl>::SparcO3CPU(Params *params) : FullO3CPU<Impl>(params)
+SparcO3CPU<Impl>::SparcO3CPU(Params *params) : FullO3CPU<Impl>(this, params)
{
DPRINTF(O3CPU, "Creating SparcO3CPU object.\n");
@@ -113,6 +113,7 @@ SparcO3CPU<Impl>::SparcO3CPU(Params *params) : FullO3CPU<Impl>(params)
#endif
// Give the thread the TC.
this->thread[i]->tc = tc;
+ this->thread[i]->setCpuId(params->cpu_id);
// Add the TC to the CPU's list of TC's.
this->threadContexts.push_back(tc);
@@ -122,17 +123,6 @@ SparcO3CPU<Impl>::SparcO3CPU(Params *params) : FullO3CPU<Impl>(params)
this->thread[i]->setFuncExeInst(0);
}
- // Sets CPU pointers. These must be set at this level because the CPU
- // pointers are defined to be the highest level of CPU class.
- this->fetch.setCPU(this);
- this->decode.setCPU(this);
- this->rename.setCPU(this);
- this->iew.setCPU(this);
- this->commit.setCPU(this);
-
- this->rob.setCPU(this);
- this->regFile.setCPU(this);
-
lockAddr = 0;
lockFlag = false;
}
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index 6f69b5ac4..b0a01c3a3 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -557,7 +557,7 @@ AtomicSimpleCPU::tick()
}
}
- if(predecoder.needMoreBytes())
+ if(predecoder.needMoreBytes() || fault != NoFault)
advancePC(fault);
}
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index 6e6ba2380..b0636ecc2 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -52,9 +52,19 @@ Bus::getPort(const std::string &if_name, int idx)
} else
fatal("Default port already set\n");
}
+ int id;
+ if (if_name == "functional") {
+ if (!funcPort) {
+ id = maxId++;
+ funcPort = new BusPort(csprintf("%s-p%d-func", name(), id), this, id);
+ funcPortId = id;
+ interfaces[id] = funcPort;
+ }
+ return funcPort;
+ }
// if_name ignored? forced to be empty?
- int id = maxId++;
+ id = maxId++;
assert(maxId < std::numeric_limits<typeof(maxId)>::max());
BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
interfaces[id] = bp;
@@ -64,10 +74,15 @@ Bus::getPort(const std::string &if_name, int idx)
void
Bus::deletePortRefs(Port *p)
{
+
BusPort *bp = dynamic_cast<BusPort*>(p);
if (bp == NULL)
panic("Couldn't convert Port* to BusPort*\n");
+ // If this is our one functional port
+ if (funcPort == bp)
+ return;
interfaces.erase(bp->getId());
+ delete bp;
}
/** Get the ranges of anyone other buses that we are connected to. */
@@ -520,7 +535,7 @@ Bus::recvStatusChange(Port::Status status, int id)
m5::hash_map<short,BusPort*>::iterator intIter;
for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
- if (intIter->first != id)
+ if (intIter->first != id && intIter->first != funcPortId)
intIter->second->sendStatusChange(Port::RangeChange);
if (id != defaultId && defaultPort)
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 6706b6c77..0dd7547c5 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -63,6 +63,7 @@ class Bus : public MemObject
Event * drainEvent;
+
static const int defaultId = -3; //Make it unique from Broadcast
struct DevMap {
@@ -249,6 +250,9 @@ class Bus : public MemObject
/** Port that handles requests that don't match any of the interfaces.*/
BusPort *defaultPort;
+ BusPort *funcPort;
+ int funcPortId;
+
/** Has the user specified their own default responder? */
bool responderSet;
@@ -266,7 +270,8 @@ class Bus : public MemObject
bool responder_set)
: MemObject(n), busId(bus_id), clock(_clock), width(_width),
tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false),
- maxId(0), defaultPort(NULL), responderSet(responder_set)
+ maxId(0), defaultPort(NULL), funcPort(NULL), funcPortId(-4),
+ responderSet(responder_set)
{
//Both the width and clock period must be positive
if (width <= 0)
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index ec0ef1be4..0a528aa5d 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -1183,7 +1183,8 @@ Cache<TagStore,Coherence>::deletePortRefs(Port *p)
{
if (cpuSidePort == p || memSidePort == p)
panic("Can only delete functional ports\n");
- // nothing else to do
+
+ delete p;
}
diff --git a/src/mem/port.cc b/src/mem/port.cc
index e75e50e4d..e6ea773f2 100644
--- a/src/mem/port.cc
+++ b/src/mem/port.cc
@@ -51,7 +51,6 @@ Port::removeConn()
{
if (peer->getOwner())
peer->getOwner()->deletePortRefs(peer);
- delete peer;
peer = NULL;
}
diff --git a/src/python/SConscript b/src/python/SConscript
index 6662c8a45..e1095eabe 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -30,129 +30,91 @@
# Nathan Binkert
import os
-import zipfile
-
-# handy function for path joins
-def join(*args):
- return os.path.normpath(os.path.join(*args))
-
Import('*')
-# This SConscript is in charge of collecting .py files and generating
-# a zip archive that is appended to the m5 binary.
-
-# List of files & directories to include in the zip file. To include
-# a package, list only the root directory of the package, not any
-# internal .py files (else they will get the path stripped off when
-# they are imported into the zip file).
-pyzip_files = []
-
-# List of additional files on which the zip archive depends, but which
-# are not included in pyzip_files... i.e. individual .py files within
-# a package.
-pyzip_dep_files = []
-
-# Add the specified package to the zip archive. Adds the directory to
-# pyzip_files and all included .py files to pyzip_dep_files.
-def addPkg(pkgdir):
- pyzip_files.append(pkgdir)
- origdir = os.getcwd()
- srcdir = join(Dir('.').srcnode().abspath, pkgdir)
- os.chdir(srcdir)
- for path, dirs, files in os.walk('.'):
- for i,dir in enumerate(dirs):
- if dir == 'SCCS':
- del dirs[i]
- break
-
- for f in files:
- if f.endswith('.py'):
- pyzip_dep_files.append(join(pkgdir, path, f))
-
- os.chdir(origdir)
-
-# Generate Python file that contains a dict specifying the current
-# build_env flags.
-def MakeDefinesPyFile(target, source, env):
- f = file(str(target[0]), 'w')
- print >>f, "m5_build_env = ", source[0]
- f.close()
-
-optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
-env.Command('m5/defines.py', Value(optionDict), MakeDefinesPyFile)
-
-def MakeInfoPyFile(target, source, env):
- f = file(str(target[0]), 'w')
- for src in source:
- data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
- print >>f, "%s = %s" % (src, repr(data))
- f.close()
-
-env.Command('m5/info.py',
- [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
- MakeInfoPyFile)
-
-# Now specify the packages & files for the zip archive.
-addPkg('m5')
-pyzip_files.append('m5/defines.py')
-pyzip_files.append('m5/info.py')
-pyzip_files.append(join(env['ROOT'], 'util/pbs/jobfile.py'))
-pyzip_files.append(join(env['ROOT'], 'src/base/traceflags.py'))
-
-swig_modules = []
-def swig_it(module):
- env.Command(['swig/%s_wrap.cc' % module, 'm5/internal/%s.py' % module],
- 'swig/%s.i' % module,
- '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
- '-o ${TARGETS[0]} $SOURCES')
- swig_modules.append(module)
- Source('swig/%s_wrap.cc' % module)
-
Source('swig/init.cc')
Source('swig/pyevent.cc')
Source('swig/pyobject.cc')
-swig_it('core')
-swig_it('debug')
-swig_it('event')
-swig_it('random')
-swig_it('sim_object')
-swig_it('stats')
-swig_it('trace')
-
-# Automatically generate m5/internals/__init__.py
-def MakeInternalsInit(target, source, env):
- f = file(str(target[0]), 'w')
- for m in swig_modules:
- print >>f, 'import %s' % m
- f.close()
-
-swig_py_files = [ 'm5/internal/%s.py' % m for m in swig_modules ]
-env.Command('m5/internal/__init__.py', swig_py_files, MakeInternalsInit)
-pyzip_dep_files.append('m5/internal/__init__.py')
-
-def MakeSwigInit(target, source, env):
- f = file(str(target[0]), 'w')
- print >>f, 'extern "C" {'
- for m in swig_modules:
- print >>f, ' void init_%s();' % m
- print >>f, '}'
- print >>f, 'void init_swig() {'
- for m in swig_modules:
- print >>f, ' init_%s();' % m
- print >>f, '}'
- f.close()
-
-swig_cc_files = [ 'swig/%s_wrap.cc' % m for m in swig_modules ]
-env.Command('swig/init.cc', swig_cc_files, MakeSwigInit)
-
-# Action function to build the zip archive. Uses the PyZipFile module
-# included in the standard Python library.
-def buildPyZip(target, source, env):
- pzf = zipfile.PyZipFile(str(target[0]), 'w')
- for s in source:
- pzf.writepy(str(s))
-
-# Add the zip file target to the environment.
-env.Command('m5py.zip', pyzip_files, buildPyZip)
-env.Depends('m5py.zip', pyzip_dep_files)
+PySource('m5', 'm5/__init__.py')
+PySource('m5', 'm5/SimObject.py')
+PySource('m5', 'm5/attrdict.py')
+PySource('m5', 'm5/convert.py')
+PySource('m5', 'm5/event.py')
+PySource('m5', 'm5/main.py')
+PySource('m5', 'm5/multidict.py')
+PySource('m5', 'm5/params.py')
+PySource('m5', 'm5/proxy.py')
+PySource('m5', 'm5/smartdict.py')
+PySource('m5', 'm5/stats.py')
+PySource('m5', 'm5/ticks.py')
+PySource('m5', 'm5/util.py')
+
+PySource('m5', os.path.join(env['ROOT'], 'util/pbs/jobfile.py'))
+
+SwigSource('m5.internal', 'swig/core.i')
+SwigSource('m5.internal', 'swig/debug.i')
+SwigSource('m5.internal', 'swig/event.i')
+SwigSource('m5.internal', 'swig/random.i')
+SwigSource('m5.internal', 'swig/sim_object.i')
+SwigSource('m5.internal', 'swig/stats.i')
+SwigSource('m5.internal', 'swig/trace.i')
+PySource('m5.internal', 'm5/internal/__init__.py')
+
+SimObject('m5/objects/AlphaConsole.py')
+SimObject('m5/objects/AlphaTLB.py')
+SimObject('m5/objects/BadDevice.py')
+SimObject('m5/objects/BaseCPU.py')
+SimObject('m5/objects/BaseCache.py')
+SimObject('m5/objects/BaseHier.py')
+SimObject('m5/objects/BaseMem.py')
+SimObject('m5/objects/BaseMemory.py')
+SimObject('m5/objects/BranchPred.py')
+SimObject('m5/objects/Bridge.py')
+SimObject('m5/objects/Bus.py')
+SimObject('m5/objects/Checker.py')
+SimObject('m5/objects/CoherenceProtocol.py')
+SimObject('m5/objects/DRAMMemory.py')
+SimObject('m5/objects/Device.py')
+SimObject('m5/objects/DiskImage.py')
+SimObject('m5/objects/Ethernet.py')
+SimObject('m5/objects/FUPool.py')
+SimObject('m5/objects/FastCPU.py')
+#SimObject('m5/objects/FreebsdSystem.py')
+SimObject('m5/objects/FullCPU.py')
+SimObject('m5/objects/FuncUnit.py')
+SimObject('m5/objects/FuncUnitConfig.py')
+SimObject('m5/objects/FunctionalMemory.py')
+SimObject('m5/objects/HierParams.py')
+SimObject('m5/objects/Ide.py')
+SimObject('m5/objects/IntrControl.py')
+SimObject('m5/objects/LinuxSystem.py')
+SimObject('m5/objects/MainMemory.py')
+SimObject('m5/objects/MemObject.py')
+SimObject('m5/objects/MemTest.py')
+SimObject('m5/objects/MemoryController.py')
+SimObject('m5/objects/O3CPU.py')
+SimObject('m5/objects/OzoneCPU.py')
+SimObject('m5/objects/Pci.py')
+SimObject('m5/objects/PhysicalMemory.py')
+SimObject('m5/objects/PipeTrace.py')
+SimObject('m5/objects/Platform.py')
+SimObject('m5/objects/Process.py')
+SimObject('m5/objects/Repl.py')
+SimObject('m5/objects/Root.py')
+SimObject('m5/objects/Sampler.py')
+SimObject('m5/objects/Scsi.py')
+SimObject('m5/objects/SimConsole.py')
+SimObject('m5/objects/SimpleCPU.py')
+SimObject('m5/objects/SimpleDisk.py')
+#SimObject('m5/objects/SimpleOzoneCPU.py')
+SimObject('m5/objects/SparcTLB.py')
+SimObject('m5/objects/System.py')
+SimObject('m5/objects/T1000.py')
+#SimObject('m5/objects/Tru64System.py')
+SimObject('m5/objects/Tsunami.py')
+SimObject('m5/objects/Uart.py')
+
+if env['ALPHA_TLASER']:
+ SimObject('m5/objects/DmaEngine.py')
+ SimObject('m5/objects/Turbolaser.py')
diff --git a/src/python/m5/internal/__init__.py b/src/python/m5/internal/__init__.py
new file mode 100644
index 000000000..6b7859cd7
--- /dev/null
+++ b/src/python/m5/internal/__init__.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# 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: Nathan Binkert
+
+import core
+import debug
+import event
+import random
+import sim_object
+import stats
+import trace
diff --git a/src/python/m5/params.py b/src/python/m5/params.py
index 9892df97c..da7ddd65e 100644
--- a/src/python/m5/params.py
+++ b/src/python/m5/params.py
@@ -51,6 +51,7 @@ import sys
import time
import convert
+import proxy
import ticks
from util import *
@@ -477,12 +478,13 @@ def IncEthernetAddr(addr, val = 1):
assert(bytes[0] <= 255)
return ':'.join(map(lambda x: '%02x' % x, bytes))
-class NextEthernetAddr(object):
- addr = "00:90:00:00:00:01"
+_NextEthernetAddr = "00:90:00:00:00:01"
+def NextEthernetAddr():
+ global _NextEthernetAddr
- def __init__(self, inc = 1):
- self.value = NextEthernetAddr.addr
- NextEthernetAddr.addr = IncEthernetAddr(NextEthernetAddr.addr, inc)
+ value = _NextEthernetAddr
+ _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
+ return value
class EthernetAddr(ParamValue):
cxx_type = 'Net::EthAddr'
@@ -508,17 +510,11 @@ class EthernetAddr(ParamValue):
def unproxy(self, base):
if self.value == NextEthernetAddr:
- self.addr = self.value().value
+ return EthernetAddr(self.value())
return self
- def __str__(self):
- if self.value == NextEthernetAddr:
- if hasattr(self, 'addr'):
- return self.addr
- else:
- return "NextEthernetAddr (unresolved)"
- else:
- return self.value
+ def ini_str(self):
+ return self.value
time_formats = [ "%a %b %d %H:%M:%S %Z %Y",
"%a %b %d %H:%M:%S %Z %Y",
@@ -1028,6 +1024,5 @@ __all__ = ['Param', 'VectorParam',
# see comment on imports at end of __init__.py.
from SimObject import isSimObject, isSimObjectSequence, isSimObjectClass
-import proxy
import objects
import internal
diff --git a/src/sim/process.cc b/src/sim/process.cc
index 2b283c9d1..68239fa52 100644
--- a/src/sim/process.cc
+++ b/src/sim/process.cc
@@ -157,12 +157,12 @@ Process::registerThreadContext(ThreadContext *tc)
int myIndex = threadContexts.size();
threadContexts.push_back(tc);
- RemoteGDB *rgdb = new RemoteGDB(system, tc);
- GDBListener *gdbl = new GDBListener(rgdb, 7000 + myIndex);
- gdbl->listen();
+// RemoteGDB *rgdb = new RemoteGDB(system, tc);
+// GDBListener *gdbl = new GDBListener(rgdb, 7000 + myIndex);
+// gdbl->listen();
//gdbl->accept();
- remoteGDB.push_back(rgdb);
+// remoteGDB.push_back(rgdb);
// return CPU number to caller
return myIndex;