summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Doxyfile4
-rw-r--r--src/SConscript3
-rw-r--r--src/arch/SConscript13
-rw-r--r--src/arch/alpha/ev5.cc3
-rw-r--r--src/arch/alpha/faults.hh2
-rw-r--r--src/arch/alpha/freebsd/system.cc4
-rw-r--r--src/arch/alpha/isa/mem.isa1
-rw-r--r--src/arch/alpha/isa_traits.hh289
-rw-r--r--src/arch/alpha/linux/linux.cc2
-rw-r--r--src/arch/alpha/linux/system.cc4
-rw-r--r--src/arch/alpha/pagetable.hh112
-rw-r--r--src/arch/alpha/process.cc2
-rw-r--r--src/arch/alpha/regfile.hh31
-rw-r--r--src/arch/alpha/syscallreturn.hh87
-rw-r--r--src/arch/alpha/system.cc4
-rw-r--r--src/arch/alpha/tlb.cc2
-rw-r--r--src/arch/alpha/tlb.hh4
-rw-r--r--src/arch/alpha/tru64/system.cc4
-rw-r--r--src/arch/alpha/types.hh9
-rw-r--r--src/arch/alpha/utility.hh2
-rw-r--r--src/arch/alpha/vtophys.hh18
-rw-r--r--src/arch/mips/faults.cc34
-rw-r--r--src/arch/mips/faults.hh3
-rw-r--r--src/arch/mips/isa/base.isa32
-rw-r--r--src/arch/mips/isa/decoder.isa5
-rw-r--r--src/arch/mips/isa/formats/basic.isa5
-rw-r--r--src/arch/mips/isa/formats/branch.isa6
-rw-r--r--src/arch/mips/isa/formats/int.isa1
-rw-r--r--src/arch/mips/isa/formats/mem.isa42
-rw-r--r--src/arch/mips/isa/formats/util.isa14
-rw-r--r--src/arch/mips/isa_traits.cc18
-rw-r--r--src/arch/mips/isa_traits.hh194
-rw-r--r--src/arch/mips/linux/linux.cc2
-rw-r--r--src/arch/mips/process.hh1
-rw-r--r--src/arch/mips/regfile.hh36
-rw-r--r--src/arch/mips/regfile/float_regfile.hh55
-rw-r--r--src/arch/mips/regfile/int_regfile.hh17
-rw-r--r--src/arch/mips/regfile/misc_regfile.hh172
-rw-r--r--src/arch/mips/regfile/regfile.hh10
-rw-r--r--src/arch/mips/syscallreturn.hh84
-rw-r--r--src/arch/mips/types.hh3
-rw-r--r--src/arch/mips/utility.cc7
-rw-r--r--src/arch/mips/utility.hh48
-rw-r--r--src/arch/sparc/SConscript11
-rw-r--r--src/arch/sparc/floatregfile.cc174
-rw-r--r--src/arch/sparc/floatregfile.hh83
-rw-r--r--src/arch/sparc/intregfile.cc133
-rw-r--r--src/arch/sparc/intregfile.hh103
-rw-r--r--src/arch/sparc/isa/base.isa32
-rw-r--r--src/arch/sparc/isa/decoder.isa305
-rw-r--r--src/arch/sparc/isa/formats/basic.isa6
-rw-r--r--src/arch/sparc/isa/formats/branch.isa109
-rw-r--r--src/arch/sparc/isa/formats/integerop.isa145
-rw-r--r--src/arch/sparc/isa/formats/priv.isa20
-rw-r--r--src/arch/sparc/isa/includes.isa6
-rw-r--r--src/arch/sparc/isa/operands.isa45
-rw-r--r--src/arch/sparc/isa_traits.hh106
-rw-r--r--src/arch/sparc/linux/linux.cc1
-rw-r--r--src/arch/sparc/linux/process.cc4
-rw-r--r--src/arch/sparc/linux/process.hh1
-rw-r--r--src/arch/sparc/miscregfile.cc540
-rw-r--r--src/arch/sparc/miscregfile.hh410
-rw-r--r--src/arch/sparc/process.cc65
-rw-r--r--src/arch/sparc/regfile.cc279
-rw-r--r--src/arch/sparc/regfile.hh825
-rw-r--r--src/arch/sparc/solaris/solaris.cc2
-rw-r--r--src/arch/sparc/stacktrace.hh6
-rw-r--r--src/arch/sparc/syscallreturn.hh92
-rw-r--r--src/arch/sparc/system.cc4
-rw-r--r--src/arch/sparc/types.hh63
-rw-r--r--src/arch/sparc/ua2005.cc10
-rw-r--r--src/base/chunk_generator.hh2
-rw-r--r--src/base/loader/elf_object.cc32
-rw-r--r--src/base/loader/elf_object.hh9
-rw-r--r--src/base/loader/symtab.hh12
-rw-r--r--src/base/remote_gdb.hh1
-rw-r--r--src/cpu/SConscript8
-rw-r--r--src/cpu/base_dyn_inst.hh30
-rw-r--r--src/cpu/base_dyn_inst_impl.hh12
-rw-r--r--src/cpu/checker/cpu.hh2
-rw-r--r--src/cpu/checker/thread_context.hh5
-rw-r--r--src/cpu/exetrace.cc44
-rw-r--r--src/cpu/exetrace.hh1
-rw-r--r--src/cpu/o3/2bit_local_pred.hh3
-rwxr-xr-xsrc/cpu/o3/SConscript26
-rw-r--r--src/cpu/o3/alpha/cpu.hh3
-rw-r--r--src/cpu/o3/alpha/cpu_impl.hh16
-rw-r--r--src/cpu/o3/alpha/thread_context.hh6
-rw-r--r--src/cpu/o3/bpred_unit.hh4
-rw-r--r--src/cpu/o3/bpred_unit_impl.hh25
-rw-r--r--src/cpu/o3/btb.cc2
-rw-r--r--src/cpu/o3/btb.hh3
-rw-r--r--src/cpu/o3/comm.hh8
-rw-r--r--src/cpu/o3/commit.hh15
-rw-r--r--src/cpu/o3/commit_impl.hh172
-rw-r--r--src/cpu/o3/cpu.cc84
-rw-r--r--src/cpu/o3/cpu.hh10
-rw-r--r--src/cpu/o3/decode.hh13
-rw-r--r--src/cpu/o3/decode_impl.hh88
-rw-r--r--src/cpu/o3/dyn_inst.hh19
-rw-r--r--src/cpu/o3/fetch.hh28
-rw-r--r--src/cpu/o3/fetch_impl.hh223
-rw-r--r--src/cpu/o3/iew.hh12
-rw-r--r--src/cpu/o3/iew_impl.hh91
-rw-r--r--src/cpu/o3/inst_queue.hh1
-rw-r--r--src/cpu/o3/inst_queue_impl.hh16
-rwxr-xr-xsrc/cpu/o3/isa_specific.hh7
-rw-r--r--src/cpu/o3/lsq.hh59
-rw-r--r--src/cpu/o3/lsq_impl.hh92
-rw-r--r--src/cpu/o3/lsq_unit.hh89
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh52
-rwxr-xr-xsrc/cpu/o3/mips/cpu.cc39
-rwxr-xr-xsrc/cpu/o3/mips/cpu.hh149
-rw-r--r--src/cpu/o3/mips/cpu_builder.cc394
-rw-r--r--src/cpu/o3/mips/cpu_impl.hh250
-rwxr-xr-xsrc/cpu/o3/mips/dyn_inst.cc37
-rwxr-xr-xsrc/cpu/o3/mips/dyn_inst.hh282
-rwxr-xr-xsrc/cpu/o3/mips/dyn_inst_impl.hh116
-rw-r--r--src/cpu/o3/mips/impl.hh93
-rw-r--r--src/cpu/o3/mips/params.hh63
-rwxr-xr-xsrc/cpu/o3/mips/thread_context.cc36
-rw-r--r--src/cpu/o3/mips/thread_context.hh68
-rw-r--r--src/cpu/o3/ras.hh3
-rw-r--r--src/cpu/o3/regfile.hh2
-rw-r--r--src/cpu/o3/rename.hh5
-rw-r--r--src/cpu/o3/rename_impl.hh87
-rw-r--r--src/cpu/o3/rename_map.hh3
-rw-r--r--src/cpu/o3/rob_impl.hh18
-rw-r--r--src/cpu/o3/scoreboard.hh1
-rw-r--r--src/cpu/o3/store_set.hh2
-rwxr-xr-xsrc/cpu/o3/thread_context.hh2
-rwxr-xr-xsrc/cpu/o3/thread_context_impl.hh12
-rw-r--r--src/cpu/o3/thread_state.hh2
-rw-r--r--src/cpu/o3/tournament_pred.hh3
-rw-r--r--src/cpu/ozone/cpu_impl.hh1
-rw-r--r--src/cpu/ozone/dyn_inst.hh1
-rw-r--r--src/cpu/ozone/dyn_inst_impl.hh3
-rw-r--r--src/cpu/ozone/ea_list.hh2
-rw-r--r--src/cpu/ozone/front_end_impl.hh1
-rw-r--r--src/cpu/ozone/inorder_back_end_impl.hh4
-rw-r--r--src/cpu/ozone/lsq_unit.hh2
-rw-r--r--src/cpu/ozone/lsq_unit_impl.hh2
-rw-r--r--src/cpu/ozone/lw_lsq.hh2
-rw-r--r--src/cpu/ozone/lw_lsq_impl.hh2
-rw-r--r--src/cpu/ozone/null_predictor.hh2
-rw-r--r--src/cpu/ozone/ozone_impl.hh1
-rw-r--r--src/cpu/ozone/simple_impl.hh1
-rw-r--r--src/cpu/ozone/thread_state.hh3
-rw-r--r--src/cpu/simple/atomic.cc28
-rw-r--r--src/cpu/simple/atomic.hh1
-rw-r--r--src/cpu/simple/base.cc13
-rw-r--r--src/cpu/simple/timing.cc79
-rw-r--r--src/cpu/simple/timing.hh51
-rw-r--r--src/cpu/simple_thread.cc1
-rw-r--r--src/cpu/simple_thread.hh4
-rw-r--r--src/cpu/static_inst.hh5
-rw-r--r--src/cpu/thread_context.hh11
-rw-r--r--src/cpu/thread_state.hh2
-rw-r--r--src/dev/ide_ctrl.cc3
-rw-r--r--src/dev/ide_disk.cc8
-rw-r--r--src/dev/io_device.cc162
-rw-r--r--src/dev/io_device.hh86
-rw-r--r--src/dev/isa_fake.hh4
-rw-r--r--src/dev/ns_gige.cc25
-rw-r--r--src/dev/ns_gige.hh2
-rw-r--r--src/dev/pcidev.cc16
-rw-r--r--src/dev/pcidev.hh5
-rw-r--r--src/dev/platform.cc1
-rw-r--r--src/dev/sinic.cc19
-rw-r--r--src/dev/sinic.hh1
-rw-r--r--src/dev/tsunami.hh3
-rw-r--r--src/dev/tsunami_io.hh8
-rw-r--r--src/doxygen/footer.html5
-rw-r--r--src/doxygen/stl.hh69
-rw-r--r--src/mem/bridge.cc3
-rw-r--r--src/mem/bridge.hh5
-rw-r--r--src/mem/bus.cc3
-rw-r--r--src/mem/bus.hh5
-rw-r--r--src/mem/cache/base_cache.hh6
-rw-r--r--src/mem/cache/cache.hh20
-rw-r--r--src/mem/cache/cache_blk.hh2
-rw-r--r--src/mem/cache/cache_impl.hh4
-rw-r--r--src/mem/cache/coherence/coherence_protocol.hh4
-rw-r--r--src/mem/cache/coherence/simple_coherence.hh4
-rw-r--r--src/mem/cache/coherence/uni_coherence.hh4
-rw-r--r--src/mem/cache/miss/blocking_buffer.cc2
-rw-r--r--src/mem/cache/miss/blocking_buffer.hh34
-rw-r--r--src/mem/cache/miss/miss_queue.hh42
-rw-r--r--src/mem/cache/miss/mshr.hh22
-rw-r--r--src/mem/cache/miss/mshr_queue.hh34
-rw-r--r--src/mem/cache/prefetch/tagged_prefetcher_impl.hh1
-rw-r--r--src/mem/cache/tags/fa_lru.hh6
-rw-r--r--src/mem/cache/tags/iic.hh10
-rw-r--r--src/mem/cache/tags/lru.hh6
-rw-r--r--src/mem/cache/tags/split.hh14
-rw-r--r--src/mem/cache/tags/split_blk.hh2
-rw-r--r--src/mem/cache/tags/split_lifo.hh6
-rw-r--r--src/mem/cache/tags/split_lru.hh6
-rw-r--r--src/mem/mem_object.hh2
-rw-r--r--src/mem/packet.hh2
-rw-r--r--src/mem/page_table.cc4
-rw-r--r--src/mem/page_table.hh7
-rw-r--r--src/mem/physical.cc63
-rw-r--r--src/mem/physical.hh21
-rw-r--r--src/mem/port.cc3
-rw-r--r--src/mem/port.hh2
-rw-r--r--src/mem/port_impl.hh6
-rw-r--r--src/mem/request.hh6
-rw-r--r--src/mem/tport.cc82
-rw-r--r--src/mem/tport.hh134
-rw-r--r--src/mem/vport.cc3
-rw-r--r--src/mem/vport.hh2
-rw-r--r--src/python/m5/__init__.py5
-rw-r--r--src/python/m5/config.py8
-rw-r--r--src/python/m5/main.py31
-rw-r--r--src/python/m5/objects/BaseCPU.py2
-rw-r--r--src/python/m5/objects/Device.py2
-rw-r--r--src/python/m5/objects/DiskImage.py4
-rw-r--r--src/python/m5/objects/Ethernet.py47
-rw-r--r--src/python/m5/objects/Ide.py29
-rw-r--r--src/python/m5/objects/O3CPU.py144
-rw-r--r--src/python/m5/objects/Pci.py2
-rw-r--r--src/python/m5/objects/Root.py2
-rw-r--r--src/python/m5/objects/System.py3
-rw-r--r--src/python/m5/objects/Tsunami.py77
-rw-r--r--src/sim/byteswap.hh3
-rw-r--r--src/sim/main.cc2
-rw-r--r--src/sim/pseudo_inst.hh4
-rw-r--r--src/sim/sim_object.cc29
-rw-r--r--src/sim/sim_object.hh15
-rw-r--r--src/sim/system.cc19
-rw-r--r--src/sim/system.hh21
232 files changed, 7176 insertions, 2455 deletions
diff --git a/src/Doxyfile b/src/Doxyfile
index 38116f6b0..ed4245dd2 100644
--- a/src/Doxyfile
+++ b/src/Doxyfile
@@ -30,7 +30,7 @@ PROJECT_NUMBER =
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
-OUTPUT_DIRECTORY = docs/doxygen
+OUTPUT_DIRECTORY = doxygen
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
@@ -570,7 +570,7 @@ HTML_HEADER =
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
-HTML_FOOTER = docs/footer.html
+HTML_FOOTER = doxygen/footer.html
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
diff --git a/src/SConscript b/src/SConscript
index 9825cafe7..812089a00 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -98,6 +98,7 @@ base_sources = Split('''
mem/packet.cc
mem/physical.cc
mem/port.cc
+ mem/tport.cc
mem/cache/base_cache.cc
mem/cache/cache.cc
@@ -298,7 +299,7 @@ alpha_eio_sources = Split('''
encumbered/eio/eio.cc
''')
-if env['TARGET_ISA'] == 'ALPHA_ISA':
+if env['TARGET_ISA'] == 'alpha':
syscall_emulation_sources += alpha_eio_sources
memtest_sources = Split('''
diff --git a/src/arch/SConscript b/src/arch/SConscript
index bc517341a..59cea6211 100644
--- a/src/arch/SConscript
+++ b/src/arch/SConscript
@@ -48,12 +48,12 @@ sources = []
# List of headers to generate
isa_switch_hdrs = Split('''
arguments.hh
- constants.hh
faults.hh
isa_traits.hh
process.hh
regfile.hh
stacktrace.hh
+ syscallreturn.hh
tlb.hh
types.hh
utility.hh
@@ -140,8 +140,15 @@ def isa_desc_emitter(target, source, env):
# Pieces are in place, so create the builder.
python = sys.executable # use same Python binary used to run scons
-isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS',
- emitter = isa_desc_emitter)
+
+# Also include the CheckerCPU as one of the models if it is being
+# enabled via command line.
+if env['USE_CHECKER']:
+ isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS CheckerCPU',
+ emitter = isa_desc_emitter)
+else:
+ isa_desc_builder = Builder(action=python + ' $SOURCES $TARGET.dir $CPU_MODELS',
+ emitter = isa_desc_emitter)
env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc
index ae3b668ea..796ed07de 100644
--- a/src/arch/alpha/ev5.cc
+++ b/src/arch/alpha/ev5.cc
@@ -29,9 +29,10 @@
* Nathan Binkert
*/
-#include "arch/alpha/tlb.hh"
+#include "arch/alpha/faults.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/osfpal.hh"
+#include "arch/alpha/tlb.hh"
#include "base/kgdb.h"
#include "base/remote_gdb.hh"
#include "base/stats/events.hh"
diff --git a/src/arch/alpha/faults.hh b/src/arch/alpha/faults.hh
index 11a568174..3ef4d5521 100644
--- a/src/arch/alpha/faults.hh
+++ b/src/arch/alpha/faults.hh
@@ -32,7 +32,7 @@
#ifndef __ALPHA_FAULTS_HH__
#define __ALPHA_FAULTS_HH__
-#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/pagetable.hh"
#include "sim/faults.hh"
// The design of the "name" and "vect" functions is in sim/faults.hh
diff --git a/src/arch/alpha/freebsd/system.cc b/src/arch/alpha/freebsd/system.cc
index 7cf68e0db..8d50e1612 100644
--- a/src/arch/alpha/freebsd/system.cc
+++ b/src/arch/alpha/freebsd/system.cc
@@ -97,6 +97,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -115,6 +116,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -133,6 +136,7 @@ CREATE_SIM_OBJECT(FreebsdAlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
+ p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;
diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa
index 08a0a2343..a5dda7fc6 100644
--- a/src/arch/alpha/isa/mem.isa
+++ b/src/arch/alpha/isa/mem.isa
@@ -668,7 +668,6 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ completeAccTemplate.subst(completeacc_iop))
}};
-
def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh
index 663b144ab..72e38ae3e 100644
--- a/src/arch/alpha/isa_traits.hh
+++ b/src/arch/alpha/isa_traits.hh
@@ -35,81 +35,252 @@
namespace LittleEndianGuest {}
#include "arch/alpha/types.hh"
-#include "arch/alpha/constants.hh"
-#include "arch/alpha/regfile.hh"
#include "config/full_system.hh"
#include "sim/host.hh"
class StaticInstPtr;
-#if !FULL_SYSTEM
-class SyscallReturn {
- public:
- template <class T>
- SyscallReturn(T v, bool s)
- {
- retval = (uint64_t)v;
- success = s;
- }
-
- template <class T>
- SyscallReturn(T v)
- {
- success = (v >= 0);
- retval = (uint64_t)v;
- }
-
- ~SyscallReturn() {}
-
- SyscallReturn& operator=(const SyscallReturn& s) {
- retval = s.retval;
- success = s.success;
- return *this;
- }
-
- bool successful() { return success; }
- uint64_t value() { return retval; }
-
-
- private:
- uint64_t retval;
- bool success;
-};
+namespace AlphaISA
+{
+
+ using namespace LittleEndianGuest;
+
+ // These enumerate all the registers for dependence tracking.
+ enum DependenceTags {
+ // 0..31 are the integer regs 0..31
+ // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
+ FP_Base_DepTag = 40,
+ Ctrl_Base_DepTag = 72,
+ Fpcr_DepTag = 72, // floating point control register
+ Uniq_DepTag = 73,
+ Lock_Flag_DepTag = 74,
+ Lock_Addr_DepTag = 75,
+ IPR_Base_DepTag = 76
+ };
+
+ StaticInstPtr decodeInst(ExtMachInst);
+
+ const Addr PageShift = 13;
+ const Addr PageBytes = ULL(1) << PageShift;
+ const Addr PageMask = ~(PageBytes - 1);
+ const Addr PageOffset = PageBytes - 1;
-#endif
#if FULL_SYSTEM
-#include "arch/alpha/isa_fullsys_traits.hh"
-#endif
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Translation stuff
+ //
-namespace AlphaISA
-{
+ const Addr PteShift = 3;
+ const Addr NPtePageShift = PageShift - PteShift;
+ const Addr NPtePage = ULL(1) << NPtePageShift;
+ const Addr PteMask = NPtePage - 1;
-using namespace LittleEndianGuest;
+ // User Virtual
+ const Addr USegBase = ULL(0x0);
+ const Addr USegEnd = ULL(0x000003ffffffffff);
-// redirected register map, really only used for the full system case.
-extern const int reg_redir[NumIntRegs];
+ // Kernel Direct Mapped
+ const Addr K0SegBase = ULL(0xfffffc0000000000);
+ const Addr K0SegEnd = ULL(0xfffffdffffffffff);
- StaticInstPtr decodeInst(ExtMachInst);
+ // Kernel Virtual
+ const Addr K1SegBase = ULL(0xfffffe0000000000);
+ const Addr K1SegEnd = ULL(0xffffffffffffffff);
+
+ // For loading... XXX This maybe could be USegEnd?? --ali
+ const Addr LoadAddrMask = ULL(0xffffffffff);
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Interrupt levels
+ //
+ enum InterruptLevels
+ {
+ INTLEVEL_SOFTWARE_MIN = 4,
+ INTLEVEL_SOFTWARE_MAX = 19,
+
+ INTLEVEL_EXTERNAL_MIN = 20,
+ INTLEVEL_EXTERNAL_MAX = 34,
+
+ INTLEVEL_IRQ0 = 20,
+ INTLEVEL_IRQ1 = 21,
+ INTINDEX_ETHERNET = 0,
+ INTINDEX_SCSI = 1,
+ INTLEVEL_IRQ2 = 22,
+ INTLEVEL_IRQ3 = 23,
+
+ INTLEVEL_SERIAL = 33,
+
+ NumInterruptLevels = INTLEVEL_EXTERNAL_MAX
+ };
+
+
+ // EV5 modes
+ enum mode_type
+ {
+ mode_kernel = 0, // kernel
+ mode_executive = 1, // executive (unused by unix)
+ mode_supervisor = 2, // supervisor (unused by unix)
+ mode_user = 3, // user mode
+ mode_number // number of modes
+ };
+
+#endif
-#if !FULL_SYSTEM
- static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs)
+#if FULL_SYSTEM
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Internal Processor Reigsters
+ //
+ enum md_ipr_names
{
- // check for error condition. Alpha syscall convention is to
- // indicate success/failure in reg a3 (r19) and put the
- // return value itself in the standard return value reg (v0).
- if (return_value.successful()) {
- // no error
- regs->setIntReg(SyscallSuccessReg, 0);
- regs->setIntReg(ReturnValueReg, return_value.value());
- } else {
- // got an error, return details
- regs->setIntReg(SyscallSuccessReg, (IntReg)-1);
- regs->setIntReg(ReturnValueReg, -return_value.value());
- }
- }
+ IPR_ISR = 0x100, // interrupt summary register
+ IPR_ITB_TAG = 0x101, // ITLB tag register
+ IPR_ITB_PTE = 0x102, // ITLB page table entry register
+ IPR_ITB_ASN = 0x103, // ITLB address space register
+ IPR_ITB_PTE_TEMP = 0x104, // ITLB page table entry temp register
+ IPR_ITB_IA = 0x105, // ITLB invalidate all register
+ IPR_ITB_IAP = 0x106, // ITLB invalidate all process register
+ IPR_ITB_IS = 0x107, // ITLB invalidate select register
+ IPR_SIRR = 0x108, // software interrupt request register
+ IPR_ASTRR = 0x109, // asynchronous system trap request register
+ IPR_ASTER = 0x10a, // asynchronous system trap enable register
+ IPR_EXC_ADDR = 0x10b, // exception address register
+ IPR_EXC_SUM = 0x10c, // exception summary register
+ IPR_EXC_MASK = 0x10d, // exception mask register
+ IPR_PAL_BASE = 0x10e, // PAL base address register
+ IPR_ICM = 0x10f, // instruction current mode
+ IPR_IPLR = 0x110, // interrupt priority level register
+ IPR_INTID = 0x111, // interrupt ID register
+ IPR_IFAULT_VA_FORM = 0x112, // formatted faulting virtual addr register
+ IPR_IVPTBR = 0x113, // virtual page table base register
+ IPR_HWINT_CLR = 0x115, // H/W interrupt clear register
+ IPR_SL_XMIT = 0x116, // serial line transmit register
+ IPR_SL_RCV = 0x117, // serial line receive register
+ IPR_ICSR = 0x118, // instruction control and status register
+ IPR_IC_FLUSH = 0x119, // instruction cache flush control
+ IPR_IC_PERR_STAT = 0x11a, // inst cache parity error status register
+ IPR_PMCTR = 0x11c, // performance counter register
+
+ // PAL temporary registers...
+ // register meanings gleaned from osfpal.s source code
+ IPR_PALtemp0 = 0x140, // local scratch
+ IPR_PALtemp1 = 0x141, // local scratch
+ IPR_PALtemp2 = 0x142, // entUna
+ IPR_PALtemp3 = 0x143, // CPU specific impure area pointer
+ IPR_PALtemp4 = 0x144, // memory management temp
+ IPR_PALtemp5 = 0x145, // memory management temp
+ IPR_PALtemp6 = 0x146, // memory management temp
+ IPR_PALtemp7 = 0x147, // entIF
+ IPR_PALtemp8 = 0x148, // intmask
+ IPR_PALtemp9 = 0x149, // entSys
+ IPR_PALtemp10 = 0x14a, // ??
+ IPR_PALtemp11 = 0x14b, // entInt
+ IPR_PALtemp12 = 0x14c, // entArith
+ IPR_PALtemp13 = 0x14d, // reserved for platform specific PAL
+ IPR_PALtemp14 = 0x14e, // reserved for platform specific PAL
+ IPR_PALtemp15 = 0x14f, // reserved for platform specific PAL
+ IPR_PALtemp16 = 0x150, // scratch / whami<7:0> / mces<4:0>
+ IPR_PALtemp17 = 0x151, // sysval
+ IPR_PALtemp18 = 0x152, // usp
+ IPR_PALtemp19 = 0x153, // ksp
+ IPR_PALtemp20 = 0x154, // PTBR
+ IPR_PALtemp21 = 0x155, // entMM
+ IPR_PALtemp22 = 0x156, // kgp
+ IPR_PALtemp23 = 0x157, // PCBB
+
+ IPR_DTB_ASN = 0x200, // DTLB address space number register
+ IPR_DTB_CM = 0x201, // DTLB current mode register
+ IPR_DTB_TAG = 0x202, // DTLB tag register
+ IPR_DTB_PTE = 0x203, // DTLB page table entry register
+ IPR_DTB_PTE_TEMP = 0x204, // DTLB page table entry temporary register
+
+ IPR_MM_STAT = 0x205, // data MMU fault status register
+ IPR_VA = 0x206, // fault virtual address register
+ IPR_VA_FORM = 0x207, // formatted virtual address register
+ IPR_MVPTBR = 0x208, // MTU virtual page table base register
+ IPR_DTB_IAP = 0x209, // DTLB invalidate all process register
+ IPR_DTB_IA = 0x20a, // DTLB invalidate all register
+ IPR_DTB_IS = 0x20b, // DTLB invalidate single register
+ IPR_ALT_MODE = 0x20c, // alternate mode register
+ IPR_CC = 0x20d, // cycle counter register
+ IPR_CC_CTL = 0x20e, // cycle counter control register
+ IPR_MCSR = 0x20f, // MTU control register
+
+ IPR_DC_FLUSH = 0x210,
+ IPR_DC_PERR_STAT = 0x212, // Dcache parity error status register
+ IPR_DC_TEST_CTL = 0x213, // Dcache test tag control register
+ IPR_DC_TEST_TAG = 0x214, // Dcache test tag register
+ IPR_DC_TEST_TAG_TEMP = 0x215, // Dcache test tag temporary register
+ IPR_DC_MODE = 0x216, // Dcache mode register
+ IPR_MAF_MODE = 0x217, // miss address file mode register
+
+ NumInternalProcRegs // number of IPR registers
+ };
+#else
+ const int NumInternalProcRegs = 0;
#endif
+
+ // Constants Related to the number of registers
+
+ const int NumIntArchRegs = 32;
+ const int NumPALShadowRegs = 8;
+ const int NumFloatArchRegs = 32;
+ // @todo: Figure out what this number really should be.
+ const int NumMiscArchRegs = 32;
+
+ const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs;
+ const int NumFloatRegs = NumFloatArchRegs;
+ const int NumMiscRegs = NumMiscArchRegs;
+
+ const int TotalNumRegs = NumIntRegs + NumFloatRegs +
+ NumMiscRegs + NumInternalProcRegs;
+
+ const int TotalDataRegs = NumIntRegs + NumFloatRegs;
+
+ // Static instruction parameters
+ const int MaxInstSrcRegs = 3;
+ const int MaxInstDestRegs = 2;
+
+ // semantically meaningful register indices
+ const int ZeroReg = 31; // architecturally meaningful
+ // the rest of these depend on the ABI
+ const int StackPointerReg = 30;
+ const int GlobalPointerReg = 29;
+ const int ProcedureValueReg = 27;
+ const int ReturnAddressReg = 26;
+ const int ReturnValueReg = 0;
+ const int FramePointerReg = 15;
+ const int ArgumentReg0 = 16;
+ const int ArgumentReg1 = 17;
+ const int ArgumentReg2 = 18;
+ const int ArgumentReg3 = 19;
+ const int ArgumentReg4 = 20;
+ const int ArgumentReg5 = 21;
+ const int SyscallNumReg = ReturnValueReg;
+ const int SyscallPseudoReturnReg = ArgumentReg4;
+ const int SyscallSuccessReg = 19;
+
+ const int LogVMPageSize = 13; // 8K bytes
+ const int VMPageSize = (1 << LogVMPageSize);
+
+ const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
+
+ const int MachineBytes = 8;
+ const int WordBytes = 4;
+ const int HalfwordBytes = 2;
+ const int ByteBytes = 1;
+
+ // return a no-op instruction... used for instruction fetch faults
+ // Alpha UNOP (ldq_u r31,0(r0))
+ const ExtMachInst NoopMachInst = 0x2ffe0000;
+
+ // redirected register map, really only used for the full system case.
+ extern const int reg_redir[NumIntRegs];
+
};
#endif // __ARCH_ALPHA_ISA_TRAITS_HH__
diff --git a/src/arch/alpha/linux/linux.cc b/src/arch/alpha/linux/linux.cc
index bc0d48e0d..e6908a572 100644
--- a/src/arch/alpha/linux/linux.cc
+++ b/src/arch/alpha/linux/linux.cc
@@ -30,6 +30,8 @@
#include "arch/alpha/linux/linux.hh"
+#include <fcntl.h>
+
// open(2) flags translation table
OpenFlagTransTable AlphaLinux::openFlagTable[] = {
#ifdef _MSC_VER
diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc
index 9fe63c390..ef4e18cb5 100644
--- a/src/arch/alpha/linux/system.cc
+++ b/src/arch/alpha/linux/system.cc
@@ -191,6 +191,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -209,6 +210,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -227,6 +230,7 @@ CREATE_SIM_OBJECT(LinuxAlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
+ p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;
diff --git a/src/arch/alpha/pagetable.hh b/src/arch/alpha/pagetable.hh
new file mode 100644
index 000000000..3108c0a3e
--- /dev/null
+++ b/src/arch/alpha/pagetable.hh
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2002-2005 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
+ * Steve Reinhardt
+ */
+
+#ifndef __ARCH_ALPHA_PAGETABLE_H__
+#define __ARCH_ALPHA_PAGETABLE_H__
+
+#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/utility.hh"
+#include "config/full_system.hh"
+
+namespace AlphaISA {
+
+#if FULL_SYSTEM
+ struct VAddr
+ {
+ static const int ImplBits = 43;
+ static const Addr ImplMask = (ULL(1) << ImplBits) - 1;
+ static const Addr UnImplMask = ~ImplMask;
+
+ VAddr(Addr a) : addr(a) {}
+ Addr addr;
+ operator Addr() const { return addr; }
+ const VAddr &operator=(Addr a) { addr = a; return *this; }
+
+ Addr vpn() const { return (addr & ImplMask) >> PageShift; }
+ Addr page() const { return addr & PageMask; }
+ Addr offset() const { return addr & PageOffset; }
+
+ Addr level3() const
+ { return AlphaISA::PteAddr(addr >> PageShift); }
+ Addr level2() const
+ { return AlphaISA::PteAddr(addr >> NPtePageShift + PageShift); }
+ Addr level1() const
+ { return AlphaISA::PteAddr(addr >> 2 * NPtePageShift + PageShift); }
+ };
+
+ struct PageTableEntry
+ {
+ PageTableEntry(uint64_t e) : entry(e) {}
+ uint64_t entry;
+ operator uint64_t() const { return entry; }
+ const PageTableEntry &operator=(uint64_t e) { entry = e; return *this; }
+ const PageTableEntry &operator=(const PageTableEntry &e)
+ { entry = e.entry; return *this; }
+
+ Addr _pfn() const { return (entry >> 32) & 0xffffffff; }
+ Addr _sw() const { return (entry >> 16) & 0xffff; }
+ int _rsv0() const { return (entry >> 14) & 0x3; }
+ bool _uwe() const { return (entry >> 13) & 0x1; }
+ bool _kwe() const { return (entry >> 12) & 0x1; }
+ int _rsv1() const { return (entry >> 10) & 0x3; }
+ bool _ure() const { return (entry >> 9) & 0x1; }
+ bool _kre() const { return (entry >> 8) & 0x1; }
+ bool _nomb() const { return (entry >> 7) & 0x1; }
+ int _gh() const { return (entry >> 5) & 0x3; }
+ bool _asm() const { return (entry >> 4) & 0x1; }
+ bool _foe() const { return (entry >> 3) & 0x1; }
+ bool _fow() const { return (entry >> 2) & 0x1; }
+ bool _for() const { return (entry >> 1) & 0x1; }
+ bool valid() const { return (entry >> 0) & 0x1; }
+
+ Addr paddr() const { return _pfn() << PageShift; }
+ };
+
+ // ITB/DTB page table entry
+ struct PTE
+ {
+ Addr tag; // virtual page number tag
+ Addr ppn; // physical page number
+ uint8_t xre; // read permissions - VMEM_PERM_* mask
+ uint8_t xwe; // write permissions - VMEM_PERM_* mask
+ uint8_t asn; // address space number
+ bool asma; // address space match
+ bool fonr; // fault on read
+ bool fonw; // fault on write
+ bool valid; // valid page table entry
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+ };
+#endif
+};
+#endif // __ARCH_ALPHA_PAGETABLE_H__
+
diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc
index 970292cd8..32fb97229 100644
--- a/src/arch/alpha/process.cc
+++ b/src/arch/alpha/process.cc
@@ -29,7 +29,7 @@
* Ali Saidi
*/
-#include "arch/alpha/constants.hh"
+#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/process.hh"
#include "base/loader/object_file.hh"
#include "base/misc.hh"
diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh
index 9ecad6f42..43b48a0ab 100644
--- a/src/arch/alpha/regfile.hh
+++ b/src/arch/alpha/regfile.hh
@@ -32,14 +32,34 @@
#define __ARCH_ALPHA_REGFILE_HH__
#include "arch/alpha/types.hh"
-#include "arch/alpha/constants.hh"
+#include "arch/alpha/isa_traits.hh"
#include "sim/faults.hh"
+#include <string>
+
+//XXX These should be implemented by someone who knows the alpha stuff better
+
class Checkpoint;
class ThreadContext;
namespace AlphaISA
{
+
+ static inline std::string getIntRegName(RegIndex)
+ {
+ return "";
+ }
+
+ static inline std::string getFloatRegName(RegIndex)
+ {
+ return "";
+ }
+
+ static inline std::string getMiscRegName(RegIndex)
+ {
+ return "";
+ }
+
class IntRegFile
{
protected:
@@ -268,14 +288,7 @@ namespace AlphaISA
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
- enum ContextParam
- {
- CONTEXT_PALMODE
- };
-
- typedef bool ContextVal;
-
- void changeContext(ContextParam param, ContextVal val)
+ void changeContext(RegContextParam param, RegContextVal val)
{
//This would be an alternative place to call/implement
//the swapPALShadow function
diff --git a/src/arch/alpha/syscallreturn.hh b/src/arch/alpha/syscallreturn.hh
new file mode 100644
index 000000000..803c3b7da
--- /dev/null
+++ b/src/arch/alpha/syscallreturn.hh
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2003-2005 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: Steve Reinhardt
+ * Gabe Black
+ */
+
+#ifndef __ARCH_ALPHA_SYSCALLRETURN_HH__
+#define __ARCH_ALPHA_SYSCALLRETURN_HH__
+
+class SyscallReturn {
+ public:
+ template <class T>
+ SyscallReturn(T v, bool s)
+ {
+ retval = (uint64_t)v;
+ success = s;
+ }
+
+ template <class T>
+ SyscallReturn(T v)
+ {
+ success = (v >= 0);
+ retval = (uint64_t)v;
+ }
+
+ ~SyscallReturn() {}
+
+ SyscallReturn& operator=(const SyscallReturn& s) {
+ retval = s.retval;
+ success = s.success;
+ return *this;
+ }
+
+ bool successful() { return success; }
+ uint64_t value() { return retval; }
+
+
+ private:
+ uint64_t retval;
+ bool success;
+};
+
+namespace AlphaISA
+{
+ static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs)
+ {
+ // check for error condition. Alpha syscall convention is to
+ // indicate success/failure in reg a3 (r19) and put the
+ // return value itself in the standard return value reg (v0).
+ if (return_value.successful()) {
+ // no error
+ regs->setIntReg(SyscallSuccessReg, 0);
+ regs->setIntReg(ReturnValueReg, return_value.value());
+ } else {
+ // got an error, return details
+ regs->setIntReg(SyscallSuccessReg, (IntReg)-1);
+ regs->setIntReg(ReturnValueReg, -return_value.value());
+ }
+ }
+}
+
+#endif
diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc
index dce7365aa..a7e615531 100644
--- a/src/arch/alpha/system.cc
+++ b/src/arch/alpha/system.cc
@@ -221,6 +221,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
Param<std::string> kernel;
Param<std::string> console;
@@ -239,6 +240,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -257,6 +260,7 @@ CREATE_SIM_OBJECT(AlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
+ p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc
index c6684274b..bab44c434 100644
--- a/src/arch/alpha/tlb.cc
+++ b/src/arch/alpha/tlb.cc
@@ -33,7 +33,9 @@
#include <string>
#include <vector>
+#include "arch/alpha/pagetable.hh"
#include "arch/alpha/tlb.hh"
+#include "arch/alpha/faults.hh"
#include "base/inifile.hh"
#include "base/str.hh"
#include "base/trace.hh"
diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh
index 07d01fa5c..955460649 100644
--- a/src/arch/alpha/tlb.hh
+++ b/src/arch/alpha/tlb.hh
@@ -36,9 +36,11 @@
#include "arch/alpha/ev5.hh"
#include "arch/alpha/isa_traits.hh"
-#include "arch/alpha/faults.hh"
+#include "arch/alpha/utility.hh"
+#include "arch/alpha/vtophys.hh"
#include "base/statistics.hh"
#include "mem/request.hh"
+#include "sim/faults.hh"
#include "sim/sim_object.hh"
class ThreadContext;
diff --git a/src/arch/alpha/tru64/system.cc b/src/arch/alpha/tru64/system.cc
index 6c0edc1ee..3ef1e4d3c 100644
--- a/src/arch/alpha/tru64/system.cc
+++ b/src/arch/alpha/tru64/system.cc
@@ -95,6 +95,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
Param<Tick> boot_cpu_frequency;
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
Param<string> kernel;
Param<string> console;
@@ -113,6 +114,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
INIT_PARAM(boot_cpu_frequency, "frequency of the boot cpu"),
INIT_PARAM(physmem, "phsyical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(console, "file that contains the console code"),
INIT_PARAM(pal, "file that contains palcode"),
@@ -131,6 +134,7 @@ CREATE_SIM_OBJECT(Tru64AlphaSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
+ p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->console_path = console;
p->palcode = pal;
diff --git a/src/arch/alpha/types.hh b/src/arch/alpha/types.hh
index 5859052e9..ae42552d8 100644
--- a/src/arch/alpha/types.hh
+++ b/src/arch/alpha/types.hh
@@ -32,7 +32,7 @@
#ifndef __ARCH_ALPHA_TYPES_HH__
#define __ARCH_ALPHA_TYPES_HH__
-#include "sim/host.hh"
+#include <inttypes.h>
namespace AlphaISA
{
@@ -56,6 +56,13 @@ namespace AlphaISA
MiscReg ctrlreg;
} AnyReg;
+ enum RegContextParam
+ {
+ CONTEXT_PALMODE
+ };
+
+ typedef bool RegContextVal;
+
enum annotes {
ANNOTE_NONE = 0,
// An impossible number for instruction annotations
diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh
index ec136091c..d3ccc0444 100644
--- a/src/arch/alpha/utility.hh
+++ b/src/arch/alpha/utility.hh
@@ -34,7 +34,7 @@
#include "config/full_system.hh"
#include "arch/alpha/types.hh"
-#include "arch/alpha/constants.hh"
+#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/regfile.hh"
#include "base/misc.hh"
diff --git a/src/arch/alpha/vtophys.hh b/src/arch/alpha/vtophys.hh
index 472c694ff..32b999c37 100644
--- a/src/arch/alpha/vtophys.hh
+++ b/src/arch/alpha/vtophys.hh
@@ -33,22 +33,24 @@
#define __ARCH_ALPHA_VTOPHYS_H__
#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/pagetable.hh"
+#include "arch/alpha/utility.hh"
class ThreadContext;
class FunctionalPort;
namespace AlphaISA {
-PageTableEntry
-kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr);
+ PageTableEntry
+ kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr);
-Addr vtophys(Addr vaddr);
-Addr vtophys(ThreadContext *tc, Addr vaddr);
+ Addr vtophys(Addr vaddr);
+ Addr vtophys(ThreadContext *tc, Addr vaddr);
-void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len);
-void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len);
-void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen);
-void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr);
+ void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len);
+ void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len);
+ void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen);
+ void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr);
};
#endif // __ARCH_ALPHA_VTOPHYS_H__
diff --git a/src/arch/mips/faults.cc b/src/arch/mips/faults.cc
index cfeb045eb..2a8ab1df5 100644
--- a/src/arch/mips/faults.cc
+++ b/src/arch/mips/faults.cc
@@ -25,13 +25,15 @@
* (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: Korey Sewell
+ * Authors: Gabe Black
+ * Korey Sewell
*/
#include "arch/mips/faults.hh"
#include "cpu/thread_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
+
#if !FULL_SYSTEM
#include "sim/process.hh"
#include "mem/page_table.hh"
@@ -110,35 +112,6 @@ FaultName IntegerOverflowFault::_name = "intover";
FaultVect IntegerOverflowFault::_vect = 0x0501;
FaultStat IntegerOverflowFault::_count;
-#if FULL_SYSTEM
-
-void MipsFault::invoke(ThreadContext * tc)
-{
- FaultBase::invoke(tc);
- countStat()++;
-
- // exception restart address
- if (setRestartAddress() || !tc->inPalMode())
- tc->setMiscReg(MipsISA::IPR_EXC_ADDR, tc->readPC());
-
- if (skipFaultingInstruction()) {
- // traps... skip faulting instruction.
- tc->setMiscReg(MipsISA::IPR_EXC_ADDR,
- tc->readMiscReg(MipsISA::IPR_EXC_ADDR) + 4);
- }
-
- tc->setPC(tc->readMiscReg(MipsISA::IPR_PAL_BASE) + vect());
- tc->setNextPC(tc->readPC() + sizeof(MachInst));
-}
-
-void ArithmeticFault::invoke(ThreadContext * tc)
-{
- FaultBase::invoke(tc);
- panic("Arithmetic traps are unimplemented!");
-}
-
-#else //!FULL_SYSTEM
-
void PageTableFault::invoke(ThreadContext *tc)
{
Process *p = tc->getProcessPtr();
@@ -159,6 +132,5 @@ void PageTableFault::invoke(ThreadContext *tc)
}
}
-#endif
} // namespace MipsISA
diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh
index 95c61cfbc..9d2c5df32 100644
--- a/src/arch/mips/faults.hh
+++ b/src/arch/mips/faults.hh
@@ -25,7 +25,8 @@
* (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: Korey Sewell
+ * Authors: Gabe Black
+ * Korey Sewell
*/
#ifndef __MIPS_FAULTS_HH__
diff --git a/src/arch/mips/isa/base.isa b/src/arch/mips/isa/base.isa
index f07b06e03..7c042f16f 100644
--- a/src/arch/mips/isa/base.isa
+++ b/src/arch/mips/isa/base.isa
@@ -79,21 +79,27 @@ output decoder {{
ccprintf(ss, "%-10s ", mnemonic);
- if(_numDestRegs > 0){
- printReg(ss, _destRegIdx[0]);
+ // Need to find standard way to not print
+ // this info. Maybe add bool variable to
+ // class?
+ if (mnemonic != "syscall") {
+ if(_numDestRegs > 0){
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ if(_numSrcRegs > 0) {
+ ss << ", ";
+ printReg(ss, _srcRegIdx[0]);
+ }
+
+ if(_numSrcRegs > 1) {
+ ss << ", ";
+ printReg(ss, _srcRegIdx[1]);
+ }
}
- if(_numSrcRegs > 0) {
- ss << ", ";
- printReg(ss, _srcRegIdx[0]);
- }
-
- if(_numSrcRegs > 1) {
- ss << ", ";
- printReg(ss, _srcRegIdx[1]);
- }
-
-
+ // Should we define a separate inst. class
+ // just for two insts?
if(mnemonic == "sll" || mnemonic == "sra"){
ccprintf(ss,", %d",SA);
}
diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa
index 9ac982e34..d65e3eb94 100644
--- a/src/arch/mips/isa/decoder.isa
+++ b/src/arch/mips/isa/decoder.isa
@@ -133,7 +133,8 @@ decode OPCODE_HI default Unknown::unknown() {
format BasicOp {
0x2: movz({{ Rd = (Rt == 0) ? Rs : Rd; }});
0x3: movn({{ Rd = (Rt != 0) ? Rs : Rd; }});
- 0x4: syscall({{ xc->syscall(R2); }}, IsNonSpeculative);
+ 0x4: syscall({{ xc->syscall(R2); }},
+ IsSerializeAfter, IsNonSpeculative);
0x7: sync({{ ; }}, IsMemBarrier);
}
@@ -1089,7 +1090,7 @@ decode OPCODE_HI default Unknown::unknown() {
0x0: StoreCond::sc({{ Mem.uw = Rt.uw;}},
{{ uint64_t tmp = write_result;
Rt.uw = (tmp == 0 || tmp == 1) ? tmp : Rt.uw;
- }}, mem_flags=LOCKED);
+ }}, mem_flags=LOCKED, inst_flags = IsStoreConditional);
format StoreMemory {
0x1: swc1({{ Mem.uw = Ft.uw; }});
diff --git a/src/arch/mips/isa/formats/basic.isa b/src/arch/mips/isa/formats/basic.isa
index 29dafd541..29a445b2c 100644
--- a/src/arch/mips/isa/formats/basic.isa
+++ b/src/arch/mips/isa/formats/basic.isa
@@ -26,7 +26,8 @@
// (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: Korey Sewell
+// Authors: Steve Reinhardt
+// Korey Sewell
// Declarations for execute() methods.
def template BasicExecDeclare {{
@@ -85,7 +86,7 @@ def template BasicDecodeWithMnemonic {{
return new %(class_name)s("%(mnemonic)s", machInst);
}};
-// The most basic instruction format... used only for a few misc. insts
+// The most basic instruction format...
def format BasicOp(code, *flags) {{
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
header_output = BasicDeclare.subst(iop)
diff --git a/src/arch/mips/isa/formats/branch.isa b/src/arch/mips/isa/formats/branch.isa
index 5230ce9cc..8c89fbfa2 100644
--- a/src/arch/mips/isa/formats/branch.isa
+++ b/src/arch/mips/isa/formats/branch.isa
@@ -36,7 +36,6 @@
output header {{
#include <iostream>
- using namespace std;
/**
* Base class for instructions whose disassembly is not purely a
@@ -235,10 +234,11 @@ def format Branch(code,*opt_flags) {{
else:
inst_flags += (x, )
+ #Take into account uncond. branch instruction
if 'cond == 1' in code:
- inst_flags += ('IsCondControl', )
+ inst_flags += ('IsUnCondControl', )
else:
- inst_flags += ('IsUncondControl', )
+ inst_flags += ('IsCondControl', )
#Condition code
code = 'bool cond;\n' + code
diff --git a/src/arch/mips/isa/formats/int.isa b/src/arch/mips/isa/formats/int.isa
index 56a4ec204..654dd8921 100644
--- a/src/arch/mips/isa/formats/int.isa
+++ b/src/arch/mips/isa/formats/int.isa
@@ -34,7 +34,6 @@
//
output header {{
#include <iostream>
- using namespace std;
/**
* Base class for integer operations.
*/
diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa
index f03f7becd..d6b0c2938 100644
--- a/src/arch/mips/isa/formats/mem.isa
+++ b/src/arch/mips/isa/formats/mem.isa
@@ -26,7 +26,7 @@
// (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
+// Authors: Steve Reinhardt
// Korey Sewell
////////////////////////////////////////////////////////////////////
@@ -162,7 +162,7 @@ def template InitiateAccDeclare {{
def template CompleteAccDeclare {{
- Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
+ Fault completeAcc(Packet *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
}};
@@ -288,7 +288,7 @@ def template LoadInitiateAcc {{
def template LoadCompleteAcc {{
- Fault %(class_name)s::completeAcc(uint8_t *data,
+ Fault %(class_name)s::completeAcc(Packet *pkt,
%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
@@ -297,7 +297,7 @@ def template LoadCompleteAcc {{
%(fp_enable_check)s;
%(op_decl)s;
- memcpy(&Mem, data, sizeof(Mem));
+ Mem = pkt->get<typeof(Mem)>();
if (fault == NoFault) {
%(memacc_code)s;
@@ -390,7 +390,6 @@ def template StoreInitiateAcc {{
{
Addr EA;
Fault fault = NoFault;
- uint64_t write_result = 0;
%(fp_enable_check)s;
%(op_decl)s;
@@ -403,7 +402,7 @@ def template StoreInitiateAcc {{
if (fault == NoFault) {
fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
- memAccessFlags, &write_result);
+ memAccessFlags, NULL);
if (traceData) { traceData->setData(Mem); }
}
@@ -413,17 +412,38 @@ def template StoreInitiateAcc {{
def template StoreCompleteAcc {{
- Fault %(class_name)s::completeAcc(uint8_t *data,
+ Fault %(class_name)s::completeAcc(Packet *pkt,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_dest_decl)s;
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template StoreCondCompleteAcc {{
+ Fault %(class_name)s::completeAcc(Packet *pkt,
%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
Fault fault = NoFault;
- uint64_t write_result = 0;
%(fp_enable_check)s;
%(op_dest_decl)s;
- memcpy(&write_result, data, sizeof(write_result));
+ uint64_t write_result = pkt->req->getScResult();
if (fault == NoFault) {
%(postacc_code)s;
@@ -489,7 +509,7 @@ def template MiscInitiateAcc {{
def template MiscCompleteAcc {{
- Fault %(class_name)s::completeAcc(uint8_t *data,
+ Fault %(class_name)s::completeAcc(Packet *pkt,
%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
@@ -580,5 +600,5 @@ def format StoreCond(memacc_code, postacc_code,
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- postacc_code, exec_template_base = 'Store')
+ postacc_code, exec_template_base = 'StoreCond')
}};
diff --git a/src/arch/mips/isa/formats/util.isa b/src/arch/mips/isa/formats/util.isa
index 0cc375af3..73164bc0d 100644
--- a/src/arch/mips/isa/formats/util.isa
+++ b/src/arch/mips/isa/formats/util.isa
@@ -65,7 +65,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
if (exec_template_base == 'Load'):
initiateacc_cblk = CodeBlock(ea_code + memacc_code)
completeacc_cblk = CodeBlock(memacc_code + postacc_code)
- elif (exec_template_base == 'Store'):
+ elif (exec_template_base.startswith('Store')):
initiateacc_cblk = CodeBlock(ea_code + memacc_code)
completeacc_cblk = CodeBlock(postacc_code)
else:
@@ -83,7 +83,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
initiateacc_iop.memacc_code = memacc_cblk.code
completeacc_iop.memacc_code = memacc_cblk.code
completeacc_iop.postacc_code = postacc_cblk.code
- elif (exec_template_base == 'Store'):
+ elif (exec_template_base.startswith('Store')):
initiateacc_iop.ea_code = ea_cblk.code
initiateacc_iop.memacc_code = memacc_cblk.code
completeacc_iop.postacc_code = postacc_cblk.code
@@ -104,6 +104,13 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
memacc_iop.constructor += s
# select templates
+
+ # define aliases... most StoreCond templates are the same as the
+ # corresponding Store templates (only CompleteAcc is different).
+ StoreCondMemAccExecute = StoreMemAccExecute
+ StoreCondExecute = StoreExecute
+ StoreCondInitiateAcc = StoreInitiateAcc
+
memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
fullExecTemplate = eval(exec_template_base + 'Execute')
initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
@@ -118,7 +125,6 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ initiateAccTemplate.subst(initiateacc_iop)
+ completeAccTemplate.subst(completeacc_iop))
}};
-
output header {{
std::string inst2string(MachInst machInst);
}};
@@ -127,7 +133,7 @@ output decoder {{
std::string inst2string(MachInst machInst)
{
- string str = "";
+ std::string str = "";
uint32_t mask = 0x80000000;
for(int i=0; i < 32; i++) {
diff --git a/src/arch/mips/isa_traits.cc b/src/arch/mips/isa_traits.cc
index 85acc4e8c..3a8cb46a5 100644
--- a/src/arch/mips/isa_traits.cc
+++ b/src/arch/mips/isa_traits.cc
@@ -30,15 +30,13 @@
*/
#include "arch/mips/isa_traits.hh"
-//#include "config/full_system.hh"
-#include "cpu/static_inst.hh"
+#include "arch/mips/regfile/regfile.hh"
#include "sim/serialize.hh"
#include "base/bitfield.hh"
using namespace MipsISA;
using namespace std;
-
void
MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest)
{
@@ -46,6 +44,12 @@ MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest)
}
void
+MipsISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
+{
+ panic("Copy Misc. Regs Not Implemented Yet\n");
+}
+
+void
MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc)
{
panic("Copy Misc. Regs Not Implemented Yet\n");
@@ -67,9 +71,9 @@ void
RegFile::serialize(std::ostream &os)
{
intRegFile.serialize(os);
- //SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
+ //SERIALIZE_ARRAY(floatRegFile, NumFloatRegs);
+ //SERIALZE_ARRAY(miscRegFile);
//SERIALIZE_SCALAR(miscRegs.fpcr);
- //SERIALIZE_SCALAR(miscRegs.uniq);
//SERIALIZE_SCALAR(miscRegs.lock_flag);
//SERIALIZE_SCALAR(miscRegs.lock_addr);
SERIALIZE_SCALAR(pc);
@@ -82,9 +86,9 @@ void
RegFile::unserialize(Checkpoint *cp, const std::string &section)
{
intRegFile.unserialize(cp, section);
- //UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
+ //UNSERIALIZE_ARRAY(floatRegFile);
+ //UNSERIALZE_ARRAY(miscRegFile);
//UNSERIALIZE_SCALAR(miscRegs.fpcr);
- //UNSERIALIZE_SCALAR(miscRegs.uniq);
//UNSERIALIZE_SCALAR(miscRegs.lock_flag);
//UNSERIALIZE_SCALAR(miscRegs.lock_addr);
UNSERIALIZE_SCALAR(pc);
diff --git a/src/arch/mips/isa_traits.hh b/src/arch/mips/isa_traits.hh
index ff994bef9..fd484e315 100644
--- a/src/arch/mips/isa_traits.hh
+++ b/src/arch/mips/isa_traits.hh
@@ -32,149 +32,87 @@
#ifndef __ARCH_MIPS_ISA_TRAITS_HH__
#define __ARCH_MIPS_ISA_TRAITS_HH__
-#include "arch/mips/constants.hh"
#include "arch/mips/types.hh"
-#include "arch/mips/regfile/regfile.hh"
-#include "arch/mips/faults.hh"
-#include "arch/mips/utility.hh"
-#include "base/misc.hh"
-#include "config/full_system.hh"
-#include "sim/byteswap.hh"
#include "sim/host.hh"
-#include "sim/faults.hh"
-
-#include <vector>
-
-class FastCPU;
-class FullCPU;
-class Checkpoint;
-class ThreadContext;
namespace LittleEndianGuest {};
#define TARGET_MIPS
-class StaticInst;
class StaticInstPtr;
-class SyscallReturn {
- public:
- template <class T>
- SyscallReturn(T v, bool s)
- {
- retval = (uint32_t)v;
- success = s;
- }
-
- template <class T>
- SyscallReturn(T v)
- {
- success = (v >= 0);
- retval = (uint32_t)v;
- }
-
- ~SyscallReturn() {}
-
- SyscallReturn& operator=(const SyscallReturn& s) {
- retval = s.retval;
- success = s.success;
- return *this;
- }
-
- bool successful() { return success; }
- uint64_t value() { return retval; }
-
-
- private:
- uint64_t retval;
- bool success;
-};
-
namespace MipsISA
{
using namespace LittleEndianGuest;
- static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs)
- {
- if (return_value.successful()) {
- // no error
- regs->setIntReg(SyscallSuccessReg, 0);
- regs->setIntReg(ReturnValueReg1, return_value.value());
- } else {
- // got an error, return details
- regs->setIntReg(SyscallSuccessReg, (IntReg) -1);
- regs->setIntReg(ReturnValueReg1, -return_value.value());
- }
- }
-
StaticInstPtr decodeInst(ExtMachInst);
- static inline ExtMachInst
- makeExtMI(MachInst inst, const uint64_t &pc) {
-#if FULL_SYSTEM
- ExtMachInst ext_inst = inst;
- if (pc && 0x1)
- return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
- else
- return ext_inst;
-#else
- return ExtMachInst(inst);
-#endif
- }
-
- /**
- * Function to insure ISA semantics about 0 registers.
- * @param tc The thread context.
- */
- template <class TC>
- void zeroRegisters(TC *tc);
-
- const Addr MaxAddr = (Addr)-1;
-
- void copyRegs(ThreadContext *src, ThreadContext *dest);
-
- // Machine operations
-
- void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
- int regnum);
-
- void restoreMachineReg(RegFile &regs, const AnyReg &reg,
- int regnum);
-
-#if 0
- static void serializeSpecialRegs(const Serializable::Proxy &proxy,
- const RegFile &regs);
-
- static void unserializeSpecialRegs(const IniFile *db,
- const std::string &category,
- ConfigNode *node,
- RegFile &regs);
-#endif
-
- static inline Addr alignAddress(const Addr &addr,
- unsigned int nbytes) {
- return (addr & ~(nbytes - 1));
- }
-
- // Instruction address compression hooks
- static inline Addr realPCToFetchPC(const Addr &addr) {
- return addr;
- }
-
- static inline Addr fetchPCToRealPC(const Addr &addr) {
- return addr;
- }
-
- // the size of "fetched" instructions (not necessarily the size
- // of real instructions for PISA)
- static inline size_t fetchInstSize() {
- return sizeof(MachInst);
- }
-
- static inline MachInst makeRegisterCopy(int dest, int src) {
- panic("makeRegisterCopy not implemented");
- return 0;
- }
+ const Addr PageShift = 13;
+ const Addr PageBytes = ULL(1) << PageShift;
+ const Addr PageMask = ~(PageBytes - 1);
+ const Addr PageOffset = PageBytes - 1;
+
+ // return a no-op instruction... used for instruction fetch faults
+ const ExtMachInst NoopMachInst = 0x00000000;
+
+ // Constants Related to the number of registers
+ const int NumIntArchRegs = 32;
+ const int NumIntSpecialRegs = 2;
+ const int NumFloatArchRegs = 32;
+ const int NumFloatSpecialRegs = 5;
+ const int NumControlRegs = 265;
+ const int NumInternalProcRegs = 0;
+
+ const int NumIntRegs = NumIntArchRegs + NumIntSpecialRegs; //HI & LO Regs
+ const int NumFloatRegs = NumFloatArchRegs + NumFloatSpecialRegs;//
+ const int NumMiscRegs = NumControlRegs;
+
+ const int TotalNumRegs = NumIntRegs + NumFloatRegs +
+ NumMiscRegs + 0/*NumInternalProcRegs*/;
+
+ const int TotalDataRegs = NumIntRegs + NumFloatRegs;
+
+ // Static instruction parameters
+ const int MaxInstSrcRegs = 3;
+ const int MaxInstDestRegs = 2;
+
+ // semantically meaningful register indices
+ const int ZeroReg = 0;
+ const int AssemblerReg = 1;
+ const int ReturnValueReg = 2;
+ const int ReturnValueReg1 = 2;
+ const int ReturnValueReg2 = 3;
+ const int ArgumentReg0 = 4;
+ const int ArgumentReg1 = 5;
+ const int ArgumentReg2 = 6;
+ const int ArgumentReg3 = 7;
+ const int KernelReg0 = 26;
+ const int KernelReg1 = 27;
+ const int GlobalPointerReg = 28;
+ const int StackPointerReg = 29;
+ const int FramePointerReg = 30;
+ const int ReturnAddressReg = 31;
+
+ const int SyscallNumReg = ReturnValueReg1;
+ const int SyscallPseudoReturnReg = ReturnValueReg1;
+ const int SyscallSuccessReg = ArgumentReg3;
+
+ const int LogVMPageSize = 13; // 8K bytes
+ const int VMPageSize = (1 << LogVMPageSize);
+
+ const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
+
+ const int MachineBytes = 4;
+ const int WordBytes = 4;
+ const int HalfwordBytes = 2;
+ const int ByteBytes = 1;
+
+ // These help enumerate all the registers for dependence tracking.
+ const int FP_Base_DepTag = 34;
+ const int Ctrl_Base_DepTag = 257;
+
+ const int ANNOTE_NONE = 0;
+ const uint32_t ITOUCH_ANNOTE = 0xffffffff;
};
diff --git a/src/arch/mips/linux/linux.cc b/src/arch/mips/linux/linux.cc
index 26e3dd479..90404af53 100644
--- a/src/arch/mips/linux/linux.cc
+++ b/src/arch/mips/linux/linux.cc
@@ -30,6 +30,8 @@
#include "arch/mips/linux/linux.hh"
+#include <fcntl.h>
+
// open(2) flags translation table
OpenFlagTransTable MipsLinux::openFlagTable[] = {
#ifdef _MSC_VER
diff --git a/src/arch/mips/process.hh b/src/arch/mips/process.hh
index b0ef20399..400591599 100644
--- a/src/arch/mips/process.hh
+++ b/src/arch/mips/process.hh
@@ -50,6 +50,7 @@ class MipsLiveProcess : public LiveProcess
std::vector<std::string> &envp);
void startup();
+
};
diff --git a/src/arch/mips/regfile.hh b/src/arch/mips/regfile.hh
new file mode 100644
index 000000000..4b2f1ac35
--- /dev/null
+++ b/src/arch/mips/regfile.hh
@@ -0,0 +1,36 @@
+/*
+ * 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: Korey Sewell
+ */
+
+#ifndef __ARCH_MIPS_REGFILE_HH__
+#define __ARCH_MIPS_REGFILE_HH__
+
+#include "arch/mips/regfile/regfile.hh"
+
+#endif
diff --git a/src/arch/mips/regfile/float_regfile.hh b/src/arch/mips/regfile/float_regfile.hh
index 61efbb416..ce5f1fdde 100644
--- a/src/arch/mips/regfile/float_regfile.hh
+++ b/src/arch/mips/regfile/float_regfile.hh
@@ -26,24 +26,61 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __ARCH_MIPS_FLOAT_REGFILE_HH__
-#define __ARCH_MIPS_FLOAT_REGFILE_HH__
+#ifndef __ARCH_MIPS_REGFILE_FLOAT_REGFILE_HH__
+#define __ARCH_MIPS_REGFILE_FLOAT_REGFILE_HH__
#include "arch/mips/types.hh"
-#include "arch/mips/constants.hh"
+#include "arch/mips/isa_traits.hh"
#include "base/misc.hh"
#include "base/bitfield.hh"
-#include "config/full_system.hh"
-#include "sim/byteswap.hh"
#include "sim/faults.hh"
-#include "sim/host.hh"
+
+#include <string>
class Checkpoint;
-class ExecContext;
-class Regfile;
namespace MipsISA
{
+ static inline std::string getFloatRegName(RegIndex)
+ {
+ return "";
+ }
+
+ const uint32_t MIPS32_QNAN = 0x7fbfffff;
+ const uint64_t MIPS64_QNAN = ULL(0x7fbfffffffffffff);
+
+ enum FPControlRegNums {
+ FIR = NumFloatArchRegs,
+ FCCR,
+ FEXR,
+ FENR,
+ FCSR
+ };
+
+ enum FCSRBits {
+ Inexact = 1,
+ Underflow,
+ Overflow,
+ DivideByZero,
+ Invalid,
+ Unimplemented
+ };
+
+ enum FCSRFields {
+ Flag_Field = 1,
+ Enable_Field = 6,
+ Cause_Field = 11
+ };
+
+ const int SingleWidth = 32;
+ const int SingleBytes = SingleWidth / 4;
+
+ const int DoubleWidth = 64;
+ const int DoubleBytes = DoubleWidth / 4;
+
+ const int QuadWidth = 128;
+ const int QuadBytes = QuadWidth / 4;
+
class FloatRegFile
{
protected:
@@ -102,7 +139,6 @@ namespace MipsISA
Fault setReg(int floatReg, const FloatRegVal &val, int width)
{
- using namespace std;
switch(width)
{
case SingleWidth:
@@ -131,7 +167,6 @@ namespace MipsISA
Fault setRegBits(int floatReg, const FloatRegBits &val, int width)
{
- using namespace std;
switch(width)
{
diff --git a/src/arch/mips/regfile/int_regfile.hh b/src/arch/mips/regfile/int_regfile.hh
index 5add1b7be..a45a17a85 100644
--- a/src/arch/mips/regfile/int_regfile.hh
+++ b/src/arch/mips/regfile/int_regfile.hh
@@ -28,20 +28,29 @@
* Authors: Korey Sewell
*/
-#ifndef __ARCH_MIPS_INT_REGFILE_HH__
-#define __ARCH_MIPS_INT_REGFILE_HH__
+#ifndef __ARCH_MIPS_REGFILE_INT_REGFILE_HH__
+#define __ARCH_MIPS_REGFILE_INT_REGFILE_HH__
#include "arch/mips/types.hh"
-#include "arch/mips/constants.hh"
+#include "arch/mips/isa_traits.hh"
#include "base/misc.hh"
#include "sim/faults.hh"
class Checkpoint;
class ThreadContext;
-class Regfile;
namespace MipsISA
{
+ static inline std::string getIntRegName(RegIndex)
+ {
+ return "";
+ }
+
+ enum MiscIntRegNums {
+ HI = NumIntArchRegs,
+ LO
+ };
+
class IntRegFile
{
protected:
diff --git a/src/arch/mips/regfile/misc_regfile.hh b/src/arch/mips/regfile/misc_regfile.hh
index 87961f97e..a4527a203 100644
--- a/src/arch/mips/regfile/misc_regfile.hh
+++ b/src/arch/mips/regfile/misc_regfile.hh
@@ -28,29 +28,191 @@
* Authors: Korey Sewell
*/
-#ifndef __ARCH_MIPS_MISC_REGFILE_HH__
-#define __ARCH_MIPS_MISC_REGFILE_HH__
+#ifndef __ARCH_MIPS_REGFILE_MISC_REGFILE_HH__
+#define __ARCH_MIPS_REGFILE_MISC_REGFILE_HH__
#include "arch/mips/types.hh"
-#include "arch/mips/constants.hh"
#include "sim/faults.hh"
-class Checkpoint;
class ThreadContext;
-class Regfile;
namespace MipsISA
{
+ static inline std::string getMiscRegName(RegIndex)
+ {
+ return "";
+ }
+
+ //Coprocessor 0 Register Names
+ enum MiscRegTags {
+ //Reference MIPS32 Arch. for Programmers, Vol. III, Ch.8
+ //(Register Number-Register Select) Summary of Register
+ //------------------------------------------------------
+ Index = 0, //Bank 0: 0 - 3
+ MVPControl,
+ MVPConf0,
+ MVPConf1,
+
+ Random = 8, //Bank 1: 8 - 15
+ VPEControl,
+ VPEConf0,
+ VPEConf1,
+ YQMask,
+ VPESchedule,
+ VPEScheFBack,
+ VPEOpt,
+
+ EntryLo0 = 16, //Bank 2: 16 - 23
+ TCStatus,
+ TCBind,
+ TCRestart,
+ TCHalt,
+ TCContext,
+ TCSchedule,
+ TCScheFBack,
+
+ EntryLo1 = 24, // Bank 3: 24
+
+ Context = 32, // Bank 4: 32 - 33
+ ContextConfig,
+
+ //PageMask = 40, //Bank 5: 40 - 41
+ PageGrain = 41,
+
+ Wired = 48, //Bank 6: 48 - 55
+ SRSConf0,
+ SRSConf1,
+ SRSConf2,
+ SRSConf3,
+ SRSConf4,
+
+ HWRena = 56, //Bank 7: 56
+
+ BadVAddr = 63, //Bank 8: 63
+
+ Count = 64, //Bank 9: 64
+
+ EntryHi = 72, //Bank 10:72 - 79
+
+ Compare = 80, //Bank 10:80 - 87
+
+ Status = 88, //Bank 12:88 - 96
+ IntCtl = 89,
+ SRSCtl = 90,
+ SRSMap = 91,
+
+ Cause = 97, //97-104
+
+ EPC = 105, //105-112
+
+ PRId = 113, //113-120,
+ EBase = 114,
+
+ Config = 121, //Bank 16: 121-128
+ Config1 = 122,
+ Config2 = 123,
+ Config3 = 124,
+ Config6 = 127,
+ Config7 = 128,
+
+
+ LLAddr = 129, //Bank 17: 129-136
+
+ WatchLo0 = 137, //Bank 18: 137-144
+ WatchLo1 = 138,
+ WatchLo2 = 139,
+ WatchLo3 = 140,
+ WatchLo4 = 141,
+ WatchLo5 = 142,
+ WatchLo6 = 143,
+ WatchLo7 = 144,
+
+ WatchHi0 = 145,//Bank 19: 145-152
+ WatchHi1 = 146,
+ WatchHi2 = 147,
+ WatchHi3 = 148,
+ WatchHi4 = 149,
+ WatchHi5 = 150,
+ WatchHi6 = 151,
+ WatchHi7 = 152,
+
+ XCContext64 = 153, //Bank 20: 153-160
+
+ //Bank 21: 161-168
+
+ //Bank 22: 169-176
+
+ Debug = 177, //Bank 23: 177-184
+ TraceControl1 = 178,
+ TraceControl2 = 179,
+ UserTraceData = 180,
+ TraceBPC = 181,
+
+ DEPC = 185,//Bank 24: 185-192
+
+ PerfCnt0 = 193,//Bank 25: 193 - 200
+ PerfCnt1 = 194,
+ PerfCnt2 = 195,
+ PerfCnt3 = 196,
+ PerfCnt4 = 197,
+ PerfCnt5 = 198,
+ PerfCnt6 = 199,
+ PerfCnt7 = 200,
+
+ ErrCtl = 201, //Bank 26: 201 - 208
+
+ CacheErr0 = 209, //Bank 27: 209 - 216
+ CacheErr1 = 210,
+ CacheErr2 = 211,
+ CacheErr3 = 212,
+
+ TagLo0 = 217,//Bank 28: 217 - 224
+ DataLo1 = 218,
+ TagLo2 = 219,
+ DataLo3 = 220,
+ TagLo4 = 221,
+ DataLo5 = 222,
+ TagLo6 = 223,
+ DataLo7 = 234,
+
+ TagHi0 = 233,//Bank 29: 233 - 240
+ DataHi1 = 234,
+ TagHi2 = 235,
+ DataHi3 = 236,
+ TagHi4 = 237,
+ DataHi5 = 238,
+ TagHi6 = 239,
+ DataHi7 = 240,
+
+
+ ErrorEPC = 249,//Bank 30: 241 - 248
+
+ DESAVE = 257//Bank 31: 249-256
+ };
+
class MiscRegFile {
protected:
uint64_t fpcr; // floating point condition codes
+ // FPCR is not used in MIPS. Condition
+ // codes are kept as part of the FloatRegFile
+
bool lock_flag; // lock flag for LL/SC
+ // use LL reg. in the future
+
Addr lock_addr; // lock address for LL/SC
+ // use LLAddr reg. in the future
MiscReg miscRegFile[NumMiscRegs];
public:
+ void clear()
+ {
+ fpcr = 0;
+ lock_flag = 0;
+ lock_addr = 0;
+ }
+
void copyMiscRegs(ThreadContext *tc);
MiscReg readReg(int misc_reg)
diff --git a/src/arch/mips/regfile/regfile.hh b/src/arch/mips/regfile/regfile.hh
index a68120299..3a18c681b 100644
--- a/src/arch/mips/regfile/regfile.hh
+++ b/src/arch/mips/regfile/regfile.hh
@@ -28,11 +28,10 @@
* Authors: Korey Sewell
*/
-#ifndef __ARCH_MIPS_REGFILE_HH__
-#define __ARCH_MIPS_REGFILE_HH__
+#ifndef __ARCH_MIPS_REGFILE_REGFILE_HH__
+#define __ARCH_MIPS_REGFILE_REGFILE_HH__
#include "arch/mips/types.hh"
-#include "arch/mips/constants.hh"
#include "arch/mips/regfile/int_regfile.hh"
#include "arch/mips/regfile/float_regfile.hh"
#include "arch/mips/regfile/misc_regfile.hh"
@@ -171,10 +170,7 @@ namespace MipsISA
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
- typedef int ContextParam;
- typedef int ContextVal;
-
- void changeContext(ContextParam param, ContextVal val)
+ void changeContext(RegContextParam param, RegContextVal val)
{
}
};
diff --git a/src/arch/mips/syscallreturn.hh b/src/arch/mips/syscallreturn.hh
new file mode 100644
index 000000000..ef1093caf
--- /dev/null
+++ b/src/arch/mips/syscallreturn.hh
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ * Korey Sewell
+ */
+
+#ifndef __ARCH_MIPS_SYSCALLRETURN_HH__
+#define __ARCH_MIPS_SYSCALLRETURN_HH__
+
+class SyscallReturn {
+ public:
+ template <class T>
+ SyscallReturn(T v, bool s)
+ {
+ retval = (uint32_t)v;
+ success = s;
+ }
+
+ template <class T>
+ SyscallReturn(T v)
+ {
+ success = (v >= 0);
+ retval = (uint32_t)v;
+ }
+
+ ~SyscallReturn() {}
+
+ SyscallReturn& operator=(const SyscallReturn& s) {
+ retval = s.retval;
+ success = s.success;
+ return *this;
+ }
+
+ bool successful() { return success; }
+ uint64_t value() { return retval; }
+
+
+ private:
+ uint64_t retval;
+ bool success;
+};
+
+namespace MipsISA
+{
+ static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs)
+ {
+ if (return_value.successful()) {
+ // no error
+ regs->setIntReg(SyscallSuccessReg, 0);
+ regs->setIntReg(ReturnValueReg1, return_value.value());
+ } else {
+ // got an error, return details
+ regs->setIntReg(SyscallSuccessReg, (IntReg) -1);
+ regs->setIntReg(ReturnValueReg1, -return_value.value());
+ }
+ }
+}
+
+#endif
diff --git a/src/arch/mips/types.hh b/src/arch/mips/types.hh
index 6330044d9..d4fa296fd 100644
--- a/src/arch/mips/types.hh
+++ b/src/arch/mips/types.hh
@@ -58,6 +58,9 @@ namespace MipsISA
MiscReg ctrlreg;
} AnyReg;
+ typedef int RegContextParam;
+ typedef int RegContextVal;
+
//used in FP convert & round function
enum ConvertType{
SINGLE_TO_DOUBLE,
diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc
index e7455fdbf..9ac4bb6d8 100644
--- a/src/arch/mips/utility.cc
+++ b/src/arch/mips/utility.cc
@@ -28,15 +28,12 @@
* Authors: Korey Sewell
*/
-#include "arch/mips/isa_traits.hh"
+#include "arch/mips/regfile.hh"
#include "arch/mips/utility.hh"
-#include "config/full_system.hh"
-#include "cpu/static_inst.hh"
-#include "sim/serialize.hh"
+#include "base/misc.hh"
#include "base/bitfield.hh"
using namespace MipsISA;
-using namespace std;
uint64_t
MipsISA::fpConvert(ConvertType cvt_type, double fp_val)
diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh
index c5c69ddcd..ae2fe1aea 100644
--- a/src/arch/mips/utility.hh
+++ b/src/arch/mips/utility.hh
@@ -33,10 +33,14 @@
#define __ARCH_MIPS_UTILITY_HH__
#include "arch/mips/types.hh"
-#include "arch/mips/constants.hh"
#include "base/misc.hh"
+#include "config/full_system.hh"
+//XXX This is needed for size_t. We should use something other than size_t
+//#include "kern/linux/linux.hh"
#include "sim/host.hh"
+class ThreadContext;
+
namespace MipsISA {
//Floating Point Utility Functions
@@ -51,6 +55,48 @@ namespace MipsISA {
bool isNan(void *val_ptr, int size);
bool isQnan(void *val_ptr, int size);
bool isSnan(void *val_ptr, int size);
+
+ /**
+ * Function to insure ISA semantics about 0 registers.
+ * @param tc The thread context.
+ */
+ template <class TC>
+ void zeroRegisters(TC *tc);
+
+ void copyRegs(ThreadContext *src, ThreadContext *dest);
+
+ // Instruction address compression hooks
+ static inline Addr realPCToFetchPC(const Addr &addr) {
+ return addr;
+ }
+
+ static inline Addr fetchPCToRealPC(const Addr &addr) {
+ return addr;
+ }
+
+ // the size of "fetched" instructions (not necessarily the size
+ // of real instructions for PISA)
+ static inline size_t fetchInstSize() {
+ return sizeof(MachInst);
+ }
+
+ static inline MachInst makeRegisterCopy(int dest, int src) {
+ panic("makeRegisterCopy not implemented");
+ return 0;
+ }
+
+ static inline ExtMachInst
+ makeExtMI(MachInst inst, const uint64_t &pc) {
+#if FULL_SYSTEM
+ ExtMachInst ext_inst = inst;
+ if (pc && 0x1)
+ return ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32);
+ else
+ return ext_inst;
+#else
+ return ExtMachInst(inst);
+#endif
+ }
};
diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript
index e7a8278db..66f2b57e0 100644
--- a/src/arch/sparc/SConscript
+++ b/src/arch/sparc/SConscript
@@ -45,22 +45,25 @@ Import('env')
# Base sources used by all configurations.
base_sources = Split('''
faults.cc
- isa_traits.cc
+ floatregfile.cc
+ intregfile.cc
+ miscregfile.cc
+ regfile.cc
''')
# Full-system sources
full_system_sources = Split('''
- vtophys.cc
ua2005.cc
+ vtophys.cc
''')
# Syscall emulation (non-full-system) sources
syscall_emulation_sources = Split('''
linux/linux.cc
linux/process.cc
- solaris/solaris.cc
- solaris/process.cc
process.cc
+ solaris/process.cc
+ solaris/solaris.cc
''')
sources = base_sources
diff --git a/src/arch/sparc/floatregfile.cc b/src/arch/sparc/floatregfile.cc
new file mode 100644
index 000000000..3cacbb278
--- /dev/null
+++ b/src/arch/sparc/floatregfile.cc
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ * Ali Saidi
+ */
+
+#include "arch/sparc/floatregfile.hh"
+#include "base/trace.hh"
+#include "sim/byteswap.hh"
+#include "sim/serialize.hh"
+
+using namespace SparcISA;
+using namespace std;
+
+class Checkpoint;
+
+string SparcISA::getFloatRegName(RegIndex index)
+{
+ static std::string floatRegName[NumFloatRegs] =
+ {"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
+ "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47",
+ "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55",
+ "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63"};
+ return floatRegName[index];
+}
+
+void FloatRegFile::clear()
+{
+ bzero(regSpace, sizeof(regSpace));
+}
+
+FloatReg FloatRegFile::readReg(int floatReg, int width)
+{
+ //In each of these cases, we have to copy the value into a temporary
+ //variable. This is because we may otherwise try to access an
+ //unaligned portion of memory.
+ switch(width)
+ {
+ case SingleWidth:
+ float32_t result32;
+ memcpy(&result32, regSpace + 4 * floatReg, sizeof(result32));
+ return htog(result32);
+ case DoubleWidth:
+ float64_t result64;
+ memcpy(&result64, regSpace + 4 * floatReg, sizeof(result64));
+ return htog(result64);
+ case QuadWidth:
+ float128_t result128;
+ memcpy(&result128, regSpace + 4 * floatReg, sizeof(result128));
+ return htog(result128);
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+}
+
+FloatRegBits FloatRegFile::readRegBits(int floatReg, int width)
+{
+ //In each of these cases, we have to copy the value into a temporary
+ //variable. This is because we may otherwise try to access an
+ //unaligned portion of memory.
+ switch(width)
+ {
+ case SingleWidth:
+ uint32_t result32;
+ memcpy(&result32, regSpace + 4 * floatReg, sizeof(result32));
+ return htog(result32);
+ case DoubleWidth:
+ uint64_t result64;
+ memcpy(&result64, regSpace + 4 * floatReg, sizeof(result64));
+ return htog(result64);
+ case QuadWidth:
+ uint64_t result128;
+ memcpy(&result128, regSpace + 4 * floatReg, sizeof(result128));
+ return htog(result128);
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+}
+
+Fault FloatRegFile::setReg(int floatReg, const FloatReg &val, int width)
+{
+ //In each of these cases, we have to copy the value into a temporary
+ //variable. This is because we may otherwise try to access an
+ //unaligned portion of memory.
+
+ uint32_t result32;
+ uint64_t result64;
+ DPRINTF(Sparc, "Setting floating point register %d\n", floatReg);
+ switch(width)
+ {
+ case SingleWidth:
+ result32 = gtoh((uint32_t)val);
+ memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32));
+ break;
+ case DoubleWidth:
+ result64 = gtoh((uint64_t)val);
+ memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64));
+ break;
+ case QuadWidth:
+ panic("Quad width FP not implemented.");
+ break;
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+ return NoFault;
+}
+
+Fault FloatRegFile::setRegBits(int floatReg, const FloatRegBits &val, int width)
+{
+ //In each of these cases, we have to copy the value into a temporary
+ //variable. This is because we may otherwise try to access an
+ //unaligned portion of memory.
+ uint32_t result32;
+ uint64_t result64;
+ switch(width)
+ {
+ case SingleWidth:
+ result32 = gtoh((uint32_t)val);
+ memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32));
+ break;
+ case DoubleWidth:
+ result64 = gtoh((uint64_t)val);
+ memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64));
+ break;
+ case QuadWidth:
+ panic("Quad width FP not implemented.");
+ break;
+ default:
+ panic("Attempted to read a %d bit floating point register!", width);
+ }
+ return NoFault;
+}
+
+void FloatRegFile::serialize(std::ostream &os)
+{
+ SERIALIZE_ARRAY((unsigned char *)regSpace,
+ SingleWidth / 8 * NumFloatRegs);
+}
+
+void FloatRegFile::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_ARRAY((unsigned char *)regSpace,
+ SingleWidth / 8 * NumFloatRegs);
+}
+
diff --git a/src/arch/sparc/floatregfile.hh b/src/arch/sparc/floatregfile.hh
new file mode 100644
index 000000000..9d760c9ff
--- /dev/null
+++ b/src/arch/sparc/floatregfile.hh
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ * Ali Saidi
+ */
+
+#ifndef __ARCH_SPARC_FLOATREGFILE_HH__
+#define __ARCH_SPARC_FLOATREGFILE_HH__
+
+#include "arch/sparc/faults.hh"
+#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/types.hh"
+
+#include <string>
+
+namespace SparcISA
+{
+ std::string getFloatRegName(RegIndex);
+
+ typedef float float32_t;
+ typedef double float64_t;
+ //FIXME long double refers to a 10 byte float, rather than a
+ //16 byte float as required. This data type may have to be emulated.
+ typedef double float128_t;
+
+ class FloatRegFile
+ {
+ public:
+ static const int SingleWidth = 32;
+ static const int DoubleWidth = 64;
+ static const int QuadWidth = 128;
+
+ protected:
+
+ //Since the floating point registers overlap each other,
+ //A generic storage space is used. The float to be returned is
+ //pulled from the appropriate section of this region.
+ char regSpace[(SingleWidth / 8) * NumFloatRegs];
+
+ public:
+
+ void clear();
+
+ FloatReg readReg(int floatReg, int width);
+
+ FloatRegBits readRegBits(int floatReg, int width);
+
+ Fault setReg(int floatReg, const FloatReg &val, int width);
+
+ Fault setRegBits(int floatReg, const FloatRegBits &val, int width);
+
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+ };
+}
+
+#endif
diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc
new file mode 100644
index 000000000..0cc0a886a
--- /dev/null
+++ b/src/arch/sparc/intregfile.cc
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ * Ali Saidi
+ */
+
+#include "arch/sparc/intregfile.hh"
+#include "base/trace.hh"
+#include "sim/serialize.hh"
+
+using namespace SparcISA;
+using namespace std;
+
+class Checkpoint;
+
+string SparcISA::getIntRegName(RegIndex index)
+{
+ static std::string intRegName[NumIntRegs] =
+ {"g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
+ "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
+ "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7"};
+ return intRegName[index];
+}
+
+int IntRegFile::flattenIndex(int reg)
+{
+ int flatIndex = offset[reg >> FrameOffsetBits]
+ | (reg & FrameOffsetMask);
+ DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex);
+ return flatIndex;
+}
+
+void IntRegFile::clear()
+{
+ int x;
+ for (x = 0; x < MaxGL; x++)
+ memset(regGlobals[x], 0, sizeof(regGlobals[x]));
+ for(int x = 0; x < 2 * NWindows; x++)
+ bzero(regSegments[x], sizeof(regSegments[x]));
+}
+
+IntRegFile::IntRegFile()
+{
+ offset[Globals] = 0;
+ regView[Globals] = regGlobals[0];
+ setCWP(0);
+ clear();
+}
+
+IntReg IntRegFile::readReg(int intReg)
+{
+ IntReg val =
+ regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask];
+ DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val);
+ return val;
+}
+
+Fault IntRegFile::setReg(int intReg, const IntReg &val)
+{
+ if(intReg)
+ DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val);
+ regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val;
+ return NoFault;
+}
+
+//This doesn't effect the actual CWP register.
+//It's purpose is to adjust the view of the register file
+//to what it would be if CWP = cwp.
+void IntRegFile::setCWP(int cwp)
+{
+ int index = ((NWindows - cwp) % NWindows) * 2;
+ offset[Outputs] = FrameOffset + (index * RegsPerFrame);
+ offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame);
+ offset[Inputs] = FrameOffset +
+ (((index+2) % (NWindows * 2)) * RegsPerFrame);
+ regView[Outputs] = regSegments[index];
+ regView[Locals] = regSegments[index+1];
+ regView[Inputs] = regSegments[(index+2) % (NWindows * 2)];
+
+ DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp);
+}
+
+void IntRegFile::setGlobals(int gl)
+{
+ DPRINTF(Sparc, "Now using %d globals", gl);
+
+ regView[Globals] = regGlobals[gl];
+ offset[Globals] = RegGlobalOffset + gl * RegsPerFrame;
+}
+
+void IntRegFile::serialize(std::ostream &os)
+{
+ unsigned int x;
+ for(x = 0; x < MaxGL; x++)
+ SERIALIZE_ARRAY(regGlobals[x], RegsPerFrame);
+ for(x = 0; x < 2 * NWindows; x++)
+ SERIALIZE_ARRAY(regSegments[x], RegsPerFrame);
+}
+
+void IntRegFile::unserialize(Checkpoint *cp, const std::string &section)
+{
+ unsigned int x;
+ for(x = 0; x < MaxGL; x++)
+ UNSERIALIZE_ARRAY(regGlobals[x], RegsPerFrame);
+ for(unsigned int x = 0; x < 2 * NWindows; x++)
+ UNSERIALIZE_ARRAY(regSegments[x], RegsPerFrame);
+}
diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh
new file mode 100644
index 000000000..d305c753b
--- /dev/null
+++ b/src/arch/sparc/intregfile.hh
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ * Ali Saidi
+ */
+
+#ifndef __ARCH_SPARC_INTREGFILE_HH__
+#define __ARCH_SPARC_INTREGFILE_HH__
+
+#include "arch/sparc/faults.hh"
+#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/types.hh"
+
+#include <string>
+
+namespace SparcISA
+{
+ class RegFile;
+
+ //This function translates integer register file indices into names
+ std::string getIntRegName(RegIndex);
+
+ class IntRegFile
+ {
+ private:
+ friend class RegFile;
+ protected:
+ static const int FrameOffsetBits = 3;
+ static const int FrameNumBits = 2;
+
+ static const int RegsPerFrame = 1 << FrameOffsetBits;
+ static const int FrameNumMask =
+ (FrameNumBits == sizeof(int)) ?
+ (unsigned int)(-1) :
+ (1 << FrameNumBits) - 1;
+ static const int FrameOffsetMask =
+ (FrameOffsetBits == sizeof(int)) ?
+ (unsigned int)(-1) :
+ (1 << FrameOffsetBits) - 1;
+
+ IntReg regGlobals[MaxGL][RegsPerFrame];
+ IntReg regSegments[2 * NWindows][RegsPerFrame];
+
+ enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames};
+
+ IntReg * regView[NumFrames];
+
+ static const int RegGlobalOffset = 0;
+ static const int FrameOffset = MaxGL * RegsPerFrame;
+ int offset[NumFrames];
+
+ public:
+
+ int flattenIndex(int reg);
+
+ void clear();
+
+ IntRegFile();
+
+ IntReg readReg(int intReg);
+
+ Fault setReg(int intReg, const IntReg &val);
+
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ protected:
+ //This doesn't effect the actual CWP register.
+ //It's purpose is to adjust the view of the register file
+ //to what it would be if CWP = cwp.
+ void setCWP(int cwp);
+
+ void setGlobals(int gl);
+ };
+}
+
+#endif
diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa
index 02f7cf61a..b518265aa 100644
--- a/src/arch/sparc/isa/base.isa
+++ b/src/arch/sparc/isa/base.isa
@@ -86,6 +86,11 @@ output header {{
const SymbolTable *symtab) const;
void printReg(std::ostream &os, int reg) const;
+ void printSrcReg(std::ostream &os, int reg) const;
+ void printDestReg(std::ostream &os, int reg) const;
+
+ void printRegArray(std::ostream &os,
+ const RegIndex indexArray[], int num) const;
};
bool passesCondition(uint32_t codes, uint32_t condition);
@@ -150,6 +155,33 @@ output decoder {{
ccprintf(os, "\t%s ", mnemonic);
}
+ void SparcStaticInst::printRegArray(std::ostream &os,
+ const RegIndex indexArray[], int num) const
+ {
+ if(num <= 0)
+ return;
+ printReg(os, indexArray[0]);
+ for(int x = 1; x < num; x++)
+ {
+ os << ", ";
+ printReg(os, indexArray[x]);
+ }
+ }
+
+ void
+ SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
+ {
+ if(_numSrcRegs > reg)
+ printReg(os, _srcRegIdx[reg]);
+ }
+
+ void
+ SparcStaticInst::printDestReg(std::ostream &os, int reg) const
+ {
+ if(_numDestRegs > reg)
+ printReg(os, _destRegIdx[reg]);
+ }
+
void
SparcStaticInst::printReg(std::ostream &os, int reg) const
{
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa
index fa8832920..0c2729833 100644
--- a/src/arch/sparc/isa/decoder.isa
+++ b/src/arch/sparc/isa/decoder.isa
@@ -39,30 +39,30 @@ decode OP default Unknown::unknown()
{
//Throw an illegal instruction acception
0x0: Trap::illtrap({{fault = new IllegalInstruction;}});
- 0x1: decode BPCC
+ format BranchN
{
- format Branch19
+ 0x1: decode BPCC
{
- 0x0: bpcci({{
+ 0x0: bpcci(19, {{
if(passesCondition(Ccr<3:0>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
- 0x2: bpccx({{
+ 0x2: bpccx(19, {{
if(passesCondition(Ccr<7:4>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
}
+ 0x2: bicc(22, {{
+ if(passesCondition(Ccr<3:0>, COND2))
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
}
- 0x2: Branch22::bicc({{
- if(passesCondition(Ccr<3:0>, COND2))
- NNPC = xc->readPC() + disp;
- else
- handle_annul
- }});
0x3: decode RCOND2
{
format BranchSplit
@@ -110,22 +110,22 @@ decode OP default Unknown::unknown()
0x5: Trap::fbpfcc({{fault = new FpDisabled;}});
0x6: Trap::fbfcc({{fault = new FpDisabled;}});
}
- 0x1: Branch30::call({{
+ 0x1: BranchN::call(30, {{
R15 = xc->readPC();
NNPC = R15 + disp;
}});
0x2: decode OP3 {
format IntOp {
0x00: add({{Rd = Rs1.sdw + Rs2_or_imm13;}});
- 0x01: and({{Rd = Rs1.udw & Rs2_or_imm13;}});
- 0x02: or({{Rd = Rs1.udw | Rs2_or_imm13;}});
- 0x03: xor({{Rd = Rs1.udw ^ Rs2_or_imm13;}});
+ 0x01: and({{Rd = Rs1.sdw & Rs2_or_imm13;}});
+ 0x02: or({{Rd = Rs1.sdw | Rs2_or_imm13;}});
+ 0x03: xor({{Rd = Rs1.sdw ^ Rs2_or_imm13;}});
0x04: sub({{Rd = Rs1.sdw - Rs2_or_imm13;}});
- 0x05: andn({{Rd = Rs1.udw & ~Rs2_or_imm13;}});
- 0x06: orn({{Rd = Rs1.udw | ~Rs2_or_imm13;}});
- 0x07: xnor({{Rd = ~(Rs1.udw ^ Rs2_or_imm13);}});
+ 0x05: andn({{Rd = Rs1.sdw & ~Rs2_or_imm13;}});
+ 0x06: orn({{Rd = Rs1.sdw | ~Rs2_or_imm13;}});
+ 0x07: xnor({{Rd = ~(Rs1.sdw ^ Rs2_or_imm13);}});
0x08: addc({{Rd = Rs1.sdw + Rs2_or_imm13 + Ccr<0:0>;}});
- 0x09: mulx({{Rd = Rs1 * Rs2_or_imm13;}});
+ 0x09: mulx({{Rd = Rs1.sdw * Rs2_or_imm13;}});
0x0A: umul({{
Rd = Rs1.udw<31:0> * Rs2_or_imm13<31:0>;
Y = Rd<63:32>;
@@ -134,7 +134,7 @@ decode OP default Unknown::unknown()
Rd.sdw = Rs1.sdw<31:0> * Rs2_or_imm13<31:0>;
Y = Rd.sdw;
}});
- 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 + Ccr<0:0>}});
+ 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 - Ccr<0:0>}});
0x0D: udivx({{
if(Rs2_or_imm13 == 0) fault = new DivisionByZero;
else Rd.udw = Rs1.udw / Rs2_or_imm13;
@@ -208,7 +208,7 @@ decode OP default Unknown::unknown()
0x1C: subccc({{
int64_t resTemp, val2 = Rs2_or_imm13;
int64_t carryin = Ccr<0:0>;
- Rd = resTemp = Rs1 + ~(val2 + carryin) + 1;}},
+ Rd = resTemp = Rs1 + ~val2 + 1 - carryin;}},
{{(~((Rs1<31:0> + (~(val2 + carryin))<31:0> + 1))<32:>)}},
{{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}},
{{(~((Rs1<63:1> + (~(val2 + carryin))<63:1>) + (Rs1<0:> + (~(val2+carryin))<0:> + 1)<63:1>))<63:>}},
@@ -272,8 +272,9 @@ decode OP default Unknown::unknown()
);
0x22: taddcctv({{
int64_t resTemp, val2 = Rs2_or_imm13;
- Rd = resTemp = Rs1 + val2;
- int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);
+ Rd = Rs1 + val2;
+ int32_t overflow = Rs1<1:0> || val2<1:0> ||
+ (Rs1<31:> == val2<31:> && val2<31:> != Rd<31:>);
if(overflow) fault = new TagOverflow;}},
{{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
{{overflow}},
@@ -322,15 +323,21 @@ decode OP default Unknown::unknown()
0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});
}
// XXX might want a format rdipr thing here
- 0x28: rdasr({{
+ 0x28: decode RS1 {
+ 0xF: decode I {
+ 0x0: Nop::stbar({{/*stuff*/}});
+ 0x1: Nop::membar({{/*stuff*/}});
+ }
+ default: rdasr({{
Rd = xc->readMiscRegWithEffect(RS1 + AsrStart, fault);
- }});
- 0x29: rdhpr({{
+ }});
+ }
+ 0x29: HPriv::rdhpr({{
// XXX Need to protect with format that traps non-priv/priv
// access
Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault);
}});
- 0x2A: rdpr({{
+ 0x2A: Priv::rdpr({{
// XXX Need to protect with format that traps non-priv
// access
Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault);
@@ -397,18 +404,233 @@ decode OP default Unknown::unknown()
0x0: BasicOperate::saved({{/*Boogy Boogy*/}});
0x1: BasicOperate::restored({{/*Boogy Boogy*/}});
}
- 0x32: wrpr({{
+ 0x32: Priv::wrpr({{
// XXX Need to protect with format that traps non-priv
// access
- xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
+ fault = xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
}});
- 0x33: wrhpr({{
+ 0x33: HPriv::wrhpr({{
// XXX Need to protect with format that traps non-priv/priv
// access
- xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13);
+ fault = xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13);
}});
- 0x34: Trap::fpop1({{fault = new FpDisabled;}});
+ 0x34: decode OPF{
+ format BasicOperate{
+ 0x01: fmovs({{
+ Frd.sf = Frs2.sf;
+ //fsr.ftt = fsr.cexc = 0
+ Fsr &= ~(7 << 14);
+ Fsr &= ~(0x1F);
+ }});
+ 0x02: fmovd({{
+ Frd.df = Frs2.df;
+ //fsr.ftt = fsr.cexc = 0
+ Fsr &= ~(7 << 14);
+ Fsr &= ~(0x1F);
+ }});
+ 0x03: Trap::fmovq({{fault = new FpDisabled;}});
+ 0x05: fnegs({{
+ //XXX might want to explicitly flip the sign bit
+ //So cases with Nan and +/-0 don't do weird things
+ Frd.sf = -Frs2.sf;
+ //fsr.ftt = fsr.cexc = 0
+ Fsr &= ~(7 << 14);
+ Fsr &= ~(0x1F);
+ }});
+ 0x06: fnegd({{
+ //XXX might want to explicitly flip the sign bit
+ //So cases with Nan and +/-0 don't do weird things
+ Frd.df = -Frs2.df;
+ //fsr.ftt = fsr.cexc = 0
+ Fsr &= ~(7 << 14);
+ Fsr &= ~(0x1F);
+ }});
+ 0x07: Trap::fnegq({{fault = new FpDisabled;}});
+ 0x09: fabss({{
+ //XXX this instruction should be tested individually
+ //Clear the sign bit
+ Frd.sf = (float)(~(1 << 31) & ((uint32_t)Frs2.sf));
+ //fsr.ftt = fsr.cexc = 0
+ Fsr &= ~(7 << 14);
+ Fsr &= ~(0x1F);
+ }});
+ 0x0A: fabsd({{
+ //XXX this instruction should be tested individually
+ //Clear the sign bit
+ Frd.df = (float)(~((uint64_t)1 << 63) & ((uint64_t)Frs2.df));
+ //fsr.ftt = fsr.cexc = 0
+ Fsr &= ~(7 << 14);
+ Fsr &= ~(0x1F);
+ }});
+ 0x0B: Trap::fabsq({{fault = new FpDisabled;}});
+ 0x29: fsqrts({{Frd.sf = sqrt(Frs2.sf);}});
+ 0x2A: fsqrtd({{Frd.df = sqrt(Frs2.df);}});
+ 0x2B: Trap::fsqrtq({{fault = new FpDisabled;}});
+ 0x41: fadds({{Frd.sf = Frs1.sf + Frs2.sf;}});
+ 0x42: faddd({{Frd.df = Frs1.df + Frs2.df;}});
+ 0x43: Trap::faddq({{fault = new FpDisabled;}});
+ 0x45: fsubs({{Frd.sf = Frs1.sf - Frs2.sf;}});
+ 0x46: fsubd({{Frd.df = Frs1.df - Frs2.df;}});
+ 0x47: Trap::fsubq({{fault = new FpDisabled;}});
+ 0x49: fmuls({{Frd.sf = Frs1.sf * Frs2.sf;}});
+ 0x4A: fmuld({{Frd.df = Frs1.df * Frs2.df;}});
+ 0x4B: Trap::fmulq({{fault = new FpDisabled;}});
+ 0x4D: fdivs({{Frd.sf = Frs1.sf / Frs2.sf;}});
+ 0x4E: fdivd({{Frd.df = Frs1.df / Frs2.df;}});
+ 0x4F: Trap::fdivq({{fault = new FpDisabled;}});
+ 0x69: fsmuld({{Frd.df = Frs1.sf * Frs2.sf;}});
+ 0x6E: Trap::fdmulq({{fault = new FpDisabled;}});
+ 0x81: fstox({{
+ Frd.df = (double)static_cast<int64_t>(Frs2.sf);
+ }});
+ 0x82: fdtox({{
+ Frd.df = (double)static_cast<int64_t>(Frs2.df);
+ }});
+ 0x83: Trap::fqtox({{fault = new FpDisabled;}});
+ 0x84: fxtos({{
+ Frd.sf = static_cast<float>((int64_t)Frs2.df);
+ }});
+ 0x88: fxtod({{
+ Frd.df = static_cast<double>((int64_t)Frs2.df);
+ }});
+ 0x8C: Trap::fxtoq({{fault = new FpDisabled;}});
+ 0xC4: fitos({{
+ Frd.sf = static_cast<float>((int32_t)Frs2.sf);
+ }});
+ 0xC6: fdtos({{Frd.sf = Frs2.df;}});
+ 0xC7: Trap::fqtos({{fault = new FpDisabled;}});
+ 0xC8: fitod({{
+ Frd.df = static_cast<double>((int32_t)Frs2.sf);
+ }});
+ 0xC9: fstod({{Frd.df = Frs2.sf;}});
+ 0xCB: Trap::fqtod({{fault = new FpDisabled;}});
+ 0xCC: Trap::fitoq({{fault = new FpDisabled;}});
+ 0xCD: Trap::fstoq({{fault = new FpDisabled;}});
+ 0xCE: Trap::fdtoq({{fault = new FpDisabled;}});
+ 0xD1: fstoi({{
+ Frd.sf = (float)static_cast<int32_t>(Frs2.sf);
+ }});
+ 0xD2: fdtoi({{
+ Frd.sf = (float)static_cast<int32_t>(Frs2.df);
+ }});
+ 0xD3: Trap::fqtoi({{fault = new FpDisabled;}});
+ default: Trap::fpop1({{fault = new FpDisabled;}});
+ }
+ }
0x35: Trap::fpop2({{fault = new FpDisabled;}});
+ //This used to be just impdep1, but now it's a whole bunch
+ //of instructions
+ 0x36: decode OPF{
+ 0x00: Trap::edge8({{fault = new IllegalInstruction;}});
+ 0x01: Trap::edge8n({{fault = new IllegalInstruction;}});
+ 0x02: Trap::edge8l({{fault = new IllegalInstruction;}});
+ 0x03: Trap::edge8ln({{fault = new IllegalInstruction;}});
+ 0x04: Trap::edge16({{fault = new IllegalInstruction;}});
+ 0x05: Trap::edge16n({{fault = new IllegalInstruction;}});
+ 0x06: Trap::edge16l({{fault = new IllegalInstruction;}});
+ 0x07: Trap::edge16ln({{fault = new IllegalInstruction;}});
+ 0x08: Trap::edge32({{fault = new IllegalInstruction;}});
+ 0x09: Trap::edge32n({{fault = new IllegalInstruction;}});
+ 0x0A: Trap::edge32l({{fault = new IllegalInstruction;}});
+ 0x0B: Trap::edge32ln({{fault = new IllegalInstruction;}});
+ 0x10: Trap::array8({{fault = new IllegalInstruction;}});
+ 0x12: Trap::array16({{fault = new IllegalInstruction;}});
+ 0x14: Trap::array32({{fault = new IllegalInstruction;}});
+ 0x18: BasicOperate::alignaddress({{
+ uint64_t sum = Rs1 + Rs2;
+ Frd = sum & ~7;
+ Gsr = (Gsr & ~7) | (sum & 7);
+ }});
+ 0x19: Trap::bmask({{fault = new IllegalInstruction;}});
+ 0x1A: BasicOperate::alignaddresslittle({{
+ uint64_t sum = Rs1 + Rs2;
+ Frd = sum & ~7;
+ Gsr = (Gsr & ~7) | ((~sum + 1) & 7);
+ }});
+ 0x20: Trap::fcmple16({{fault = new IllegalInstruction;}});
+ 0x22: Trap::fcmpne16({{fault = new IllegalInstruction;}});
+ 0x24: Trap::fcmple32({{fault = new IllegalInstruction;}});
+ 0x26: Trap::fcmpne32({{fault = new IllegalInstruction;}});
+ 0x28: Trap::fcmpgt16({{fault = new IllegalInstruction;}});
+ 0x2A: Trap::fcmpeq16({{fault = new IllegalInstruction;}});
+ 0x2C: Trap::fcmpgt32({{fault = new IllegalInstruction;}});
+ 0x2E: Trap::fcmpeq32({{fault = new IllegalInstruction;}});
+ 0x31: Trap::fmul8x16({{fault = new IllegalInstruction;}});
+ 0x33: Trap::fmul8x16au({{fault = new IllegalInstruction;}});
+ 0x35: Trap::fmul8x16al({{fault = new IllegalInstruction;}});
+ 0x36: Trap::fmul8sux16({{fault = new IllegalInstruction;}});
+ 0x37: Trap::fmul8ulx16({{fault = new IllegalInstruction;}});
+ 0x38: Trap::fmuld8sux16({{fault = new IllegalInstruction;}});
+ 0x39: Trap::fmuld8ulx16({{fault = new IllegalInstruction;}});
+ 0x3A: Trap::fpack32({{fault = new IllegalInstruction;}});
+ 0x3B: Trap::fpack16({{fault = new IllegalInstruction;}});
+ 0x3D: Trap::fpackfix({{fault = new IllegalInstruction;}});
+ 0x3E: Trap::pdist({{fault = new IllegalInstruction;}});
+ 0x48: BasicOperate::faligndata({{
+ uint64_t msbX = (uint64_t)Frs1;
+ uint64_t lsbX = (uint64_t)Frs2;
+ uint64_t msbShift = Gsr<2:0> * 8;
+ uint64_t lsbShift = (8 - Gsr<2:0>) * 8;
+ uint64_t msbMask = ((uint64_t)(-1)) << msbShift;
+ uint64_t lsbMask = ((uint64_t)(-1)) << lsbShift;
+ Frd = ((msbX << msbShift) & msbMask) |
+ ((lsbX << lsbShift) & lsbMask);
+ }});
+ 0x4B: Trap::fpmerge({{fault = new IllegalInstruction;}});
+ 0x4C: Trap::bshuffle({{fault = new IllegalInstruction;}});
+ 0x4D: Trap::fexpand({{fault = new IllegalInstruction;}});
+ 0x50: Trap::fpadd16({{fault = new IllegalInstruction;}});
+ 0x51: Trap::fpadd16s({{fault = new IllegalInstruction;}});
+ 0x52: Trap::fpadd32({{fault = new IllegalInstruction;}});
+ 0x53: Trap::fpadd32s({{fault = new IllegalInstruction;}});
+ 0x54: Trap::fpsub16({{fault = new IllegalInstruction;}});
+ 0x55: Trap::fpsub16s({{fault = new IllegalInstruction;}});
+ 0x56: Trap::fpsub32({{fault = new IllegalInstruction;}});
+ 0x57: Trap::fpsub32s({{fault = new IllegalInstruction;}});
+ 0x60: BasicOperate::fzero({{Frd.df = 0;}});
+ 0x61: BasicOperate::fzeros({{Frd.sf = 0;}});
+ 0x62: Trap::fnor({{fault = new IllegalInstruction;}});
+ 0x63: Trap::fnors({{fault = new IllegalInstruction;}});
+ 0x64: Trap::fandnot2({{fault = new IllegalInstruction;}});
+ 0x65: Trap::fandnot2s({{fault = new IllegalInstruction;}});
+ 0x66: BasicOperate::fnot2({{
+ Frd.df = (double)(~((uint64_t)Frs2.df));
+ }});
+ 0x67: BasicOperate::fnot2s({{
+ Frd.sf = (float)(~((uint32_t)Frs2.sf));
+ }});
+ 0x68: Trap::fandnot1({{fault = new IllegalInstruction;}});
+ 0x69: Trap::fandnot1s({{fault = new IllegalInstruction;}});
+ 0x6A: BasicOperate::fnot1({{
+ Frd.df = (double)(~((uint64_t)Frs1.df));
+ }});
+ 0x6B: BasicOperate::fnot1s({{
+ Frd.sf = (float)(~((uint32_t)Frs1.sf));
+ }});
+ 0x6C: Trap::fxor({{fault = new IllegalInstruction;}});
+ 0x6D: Trap::fxors({{fault = new IllegalInstruction;}});
+ 0x6E: Trap::fnand({{fault = new IllegalInstruction;}});
+ 0x6F: Trap::fnands({{fault = new IllegalInstruction;}});
+ 0x70: Trap::fand({{fault = new IllegalInstruction;}});
+ 0x71: Trap::fands({{fault = new IllegalInstruction;}});
+ 0x72: Trap::fxnor({{fault = new IllegalInstruction;}});
+ 0x73: Trap::fxnors({{fault = new IllegalInstruction;}});
+ 0x74: BasicOperate::fsrc1({{Frd.df = Frs1.df;}});
+ 0x75: BasicOperate::fsrc1s({{Frd.sf = Frs1.sf;}});
+ 0x76: Trap::fornot2({{fault = new IllegalInstruction;}});
+ 0x77: Trap::fornot2s({{fault = new IllegalInstruction;}});
+ 0x78: BasicOperate::fsrc2({{Frd.df = Frs2.df;}});
+ 0x79: BasicOperate::fsrc2s({{Frd.sf = Frs2.sf;}});
+ 0x7A: Trap::fornot1({{fault = new IllegalInstruction;}});
+ 0x7B: Trap::fornot1s({{fault = new IllegalInstruction;}});
+ 0x7C: Trap::for({{fault = new IllegalInstruction;}});
+ 0x7D: Trap::fors({{fault = new IllegalInstruction;}});
+ 0x7E: Trap::fone({{fault = new IllegalInstruction;}});
+ 0x7F: Trap::fones({{fault = new IllegalInstruction;}});
+ 0x80: Trap::shutdown({{fault = new IllegalInstruction;}});
+ 0x81: Trap::siam({{fault = new IllegalInstruction;}});
+ }
+ 0x37: Trap::impdep2({{fault = new IllegalInstruction;}});
0x38: Branch::jmpl({{
Addr target = Rs1 + Rs2_or_imm13;
if(target & 0x3)
@@ -549,7 +771,7 @@ decode OP default Unknown::unknown()
NNPC = Tnpc + 4;
Tl = Tl - 1;
}});
- 0x1: BasicOperate::retry({{
+ 0x1: Priv::retry({{
if(Tl == 0)
return new IllegalInstruction;
Cwp = Tstate<4:0>;
@@ -630,27 +852,28 @@ decode OP default Unknown::unknown()
Mem = temp;
}}, {{32}});
format Trap {
- 0x20: ldf({{fault = new FpDisabled;}});
+ 0x20: Load::ldf({{Frd.sf = ((float)Mem);}}, {{32}});
0x21: decode X {
0x0: Load::ldfsr({{Fsr = Mem<31:0> | Fsr<63:32>;}}, {{32}});
0x1: Load::ldxfsr({{Fsr = Mem;}}, {{64}});
}
0x22: ldqf({{fault = new FpDisabled;}});
- 0x23: lddf({{fault = new FpDisabled;}});
- 0x24: stf({{fault = new FpDisabled;}});
+ 0x23: Load::lddf({{Frd.df = ((double)Mem);}}, {{64}});
+ 0x24: Store::stf({{Mem = ((int32_t)Frd.sf);}}, {{32}});
0x25: decode X {
0x0: Store::stfsr({{Mem = Fsr<31:0>;}}, {{32}});
0x1: Store::stxfsr({{Mem = Fsr;}}, {{64}});
}
0x26: stqf({{fault = new FpDisabled;}});
- 0x27: stdf({{fault = new FpDisabled;}});
+ 0x27: Store::stdf({{Mem = ((int64_t)Frd.df);}}, {{64}});
0x2D: Nop::prefetch({{ }});
- 0x30: ldfa({{return new FpDisabled;}});
+ 0x30: Load::ldfa({{Frd.sf = ((float)Mem);}}, {{32}});
0x32: ldqfa({{fault = new FpDisabled;}});
- 0x33: lddfa({{fault = new FpDisabled;}});
- 0x34: stfa({{fault = new FpDisabled;}});
- 0x35: stqfa({{fault = new FpDisabled;}});
- 0x36: stdfa({{fault = new FpDisabled;}});
+ 0x33: Load::lddfa({{Frd.df = ((double)Mem);}}, {{64}});
+ 0x34: Store::stfa({{Mem = ((int32_t)Frd.sf);}}, {{32}});
+ 0x36: stqfa({{fault = new FpDisabled;}});
+ //XXX need to work in the ASI thing
+ 0x37: Store::stdfa({{Mem = ((uint64_t)Frd.df);}}, {{64}});
0x3C: Cas::casa({{
uint64_t val = Mem.uw;
if(Rs2.uw == val)
diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa
index 60432cb6b..0a47a7ffe 100644
--- a/src/arch/sparc/isa/formats/basic.isa
+++ b/src/arch/sparc/isa/formats/basic.isa
@@ -63,7 +63,6 @@ def template BasicExecute {{
{
Fault fault = NoFault;
- %(fp_enable_check)s;
%(op_decl)s;
%(op_rd)s;
%(code)s;
@@ -81,11 +80,6 @@ def template BasicDecode {{
return new %(class_name)s(machInst);
}};
-// Basic decode template, passing mnemonic in as string arg to constructor.
-def template BasicDecodeWithMnemonic {{
- return new %(class_name)s("%(mnemonic)s", machInst);
-}};
-
// The most basic instruction format... used only for a few misc. insts
def format BasicOperate(code, *flags) {{
iop = InstObjParams(name, Name, 'SparcStaticInst',
diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa
index 7d46ce739..8a3f05173 100644
--- a/src/arch/sparc/isa/formats/branch.isa
+++ b/src/arch/sparc/isa/formats/branch.isa
@@ -69,47 +69,18 @@ output header {{
};
/**
- * Base class for branches with 19 bit displacements.
+ * Base class for branches with n bit displacements.
*/
- class Branch19 : public BranchDisp
+ template<int bits>
+ class BranchNBits : public BranchDisp
{
protected:
// Constructor
- Branch19(const char *mnem, MachInst _machInst,
+ BranchNBits(const char *mnem, MachInst _machInst,
OpClass __opClass) :
BranchDisp(mnem, _machInst, __opClass)
{
- disp = sign_ext(DISP19 << 2, 21);
- }
- };
-
- /**
- * Base class for branches with 22 bit displacements.
- */
- class Branch22 : public BranchDisp
- {
- protected:
- // Constructor
- Branch22(const char *mnem, MachInst _machInst,
- OpClass __opClass) :
- BranchDisp(mnem, _machInst, __opClass)
- {
- disp = sign_ext(DISP22 << 2, 24);
- }
- };
-
- /**
- * Base class for branches with 30 bit displacements.
- */
- class Branch30 : public BranchDisp
- {
- protected:
- // Constructor
- Branch30(const char *mnem, MachInst _machInst,
- OpClass __opClass) :
- BranchDisp(mnem, _machInst, __opClass)
- {
- disp = sign_ext(DISP30 << 2, 32);
+ disp = sign_ext(_machInst << 2, bits + 2);
}
};
@@ -149,29 +120,23 @@ output header {{
}};
output decoder {{
+
+ template class BranchNBits<19>;
+
+ template class BranchNBits<22>;
+
+ template class BranchNBits<30>;
+
std::string Branch::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, mnemonic);
-
- if (_numSrcRegs > 0)
- {
- printReg(response, _srcRegIdx[0]);
- for(int x = 1; x < _numSrcRegs; x++)
- {
+ printRegArray(response, _srcRegIdx, _numSrcRegs);
+ if(_numDestRegs && _numSrcRegs)
response << ", ";
- printReg(response, _srcRegIdx[x]);
- }
- }
-
- if (_numDestRegs > 0)
- {
- if(_numSrcRegs > 0)
- response << ", ";
- printReg(response, _destRegIdx[0]);
- }
+ printDestReg(response, 0);
return response.str();
}
@@ -182,27 +147,13 @@ output decoder {{
std::stringstream response;
printMnemonic(response, mnemonic);
-
- if (_numSrcRegs > 0)
- {
- printReg(response, _srcRegIdx[0]);
- for(int x = 1; x < _numSrcRegs; x++)
- {
- response << ", ";
- printReg(response, _srcRegIdx[x]);
- }
- }
-
+ printRegArray(response, _srcRegIdx, _numSrcRegs);
if(_numSrcRegs > 0)
response << ", ";
-
ccprintf(response, "0x%x", imm);
-
if (_numDestRegs > 0)
- {
response << ", ";
- printReg(response, _destRegIdx[0]);
- }
+ printDestReg(response, 0);
return response.str();
}
@@ -292,32 +243,10 @@ def format Branch(code, *opt_flags) {{
}};
// Primary format for branch instructions:
-def format Branch19(code, *opt_flags) {{
- code = re.sub(r'handle_annul', handle_annul, code)
- codeBlk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'Branch19', codeBlk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = BranchExecute.subst(iop)
- decode_block = BasicDecode.subst(iop)
-}};
-
-// Primary format for branch instructions:
-def format Branch22(code, *opt_flags) {{
- code = re.sub(r'handle_annul', handle_annul, code)
- codeBlk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'Branch22', codeBlk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = BranchExecute.subst(iop)
- decode_block = BasicDecode.subst(iop)
-}};
-
-// Primary format for branch instructions:
-def format Branch30(code, *opt_flags) {{
+def format BranchN(bits, code, *opt_flags) {{
code = re.sub(r'handle_annul', handle_annul, code)
codeBlk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags)
+ iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, codeBlk, opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
exec_output = BranchExecute.subst(iop)
diff --git a/src/arch/sparc/isa/formats/integerop.isa b/src/arch/sparc/isa/formats/integerop.isa
index 1894ce541..27616216e 100644
--- a/src/arch/sparc/isa/formats/integerop.isa
+++ b/src/arch/sparc/isa/formats/integerop.isa
@@ -132,7 +132,7 @@ output header {{
OpClass __opClass) :
IntOpImm(mnem, _machInst, __opClass)
{
- imm = (IMM22 << 10) & 0xFFFFFC00;
+ imm = (IMM22 & 0x3FFFFF) << 10;
}
std::string generateDisassembly(Addr pc,
@@ -157,12 +157,9 @@ output decoder {{
if(!strcmp(mnemonic, "or") && _srcRegIdx[0] == 0)
{
printMnemonic(os, "mov");
- if(_numSrcRegs > 0)
- printReg(os, _srcRegIdx[1]);
+ printSrcReg(os, 1);
ccprintf(os, ", ");
- if(_numDestRegs > 0)
- printReg(os, _destRegIdx[0]);
-
+ printDestReg(os, 0);
return true;
}
return false;
@@ -173,32 +170,24 @@ output decoder {{
{
if(!strcmp(mnemonic, "or"))
{
- if(_srcRegIdx[0] == 0)
+ if(_numSrcRegs > 0 && _srcRegIdx[0] == 0)
{
if(imm == 0)
- {
printMnemonic(os, "clr");
- if(_numDestRegs > 0)
- printReg(os, _destRegIdx[0]);
- return true;
- }
else
{
printMnemonic(os, "mov");
- ccprintf(os, ", 0x%x, ", imm);
- if(_numDestRegs > 0)
- printReg(os, _destRegIdx[0]);
- return true;
+ ccprintf(os, " 0x%x, ", imm);
}
+ printDestReg(os, 0);
+ return true;
}
else if(imm == 0)
{
printMnemonic(os, "mov");
- if(_numSrcRegs > 0)
- printReg(os, _srcRegIdx[0]);
+ printSrcReg(os, 0);
ccprintf(os, ", ");
- if(_numDestRegs > 0)
- printReg(os, _destRegIdx[0]);
+ printDestReg(os, 0);
return true;
}
}
@@ -210,25 +199,13 @@ output decoder {{
{
std::stringstream response;
- if(!printPseudoOps(response, pc, symtab))
- {
- printMnemonic(response, mnemonic);
- if (_numSrcRegs > 0)
- {
- printReg(response, _srcRegIdx[0]);
- for(int x = 1; x < _numSrcRegs; x++)
- {
- response << ", ";
- printReg(response, _srcRegIdx[x]);
- }
- }
- if (_numDestRegs > 0)
- {
- if(_numSrcRegs > 0)
- response << ", ";
- printReg(response, _destRegIdx[0]);
- }
- }
+ if(printPseudoOps(response, pc, symtab))
+ return response.str();
+ printMnemonic(response, mnemonic);
+ printRegArray(response, _srcRegIdx, _numSrcRegs);
+ if(_numDestRegs && _numSrcRegs)
+ response << ", ";
+ printDestReg(response, 0);
return response.str();
}
@@ -237,27 +214,16 @@ output decoder {{
{
std::stringstream response;
- if(!printPseudoOps(response, pc, symtab))
- {
- printMnemonic(response, mnemonic);
- if (_numSrcRegs > 0)
- {
- printReg(response, _srcRegIdx[0]);
- for(int x = 1; x < _numSrcRegs - 1; x++)
- {
- response << ", ";
- printReg(response, _srcRegIdx[x]);
- }
- }
- if(_numSrcRegs > 0)
- response << ", ";
- ccprintf(response, "0x%x", imm);
- if (_numDestRegs > 0)
- {
- response << ", ";
- printReg(response, _destRegIdx[0]);
- }
- }
+ if(printPseudoOps(response, pc, symtab))
+ return response.str();
+ printMnemonic(response, mnemonic);
+ printRegArray(response, _srcRegIdx, _numSrcRegs);
+ if(_numSrcRegs > 0)
+ response << ", ";
+ ccprintf(response, "0x%x", imm);
+ if(_numDestRegs > 0)
+ response << ", ";
+ printDestReg(response, 0);
return response.str();
}
@@ -267,10 +233,8 @@ output decoder {{
std::stringstream response;
printMnemonic(response, mnemonic);
- if(_numSrcRegs > 0)
- response << ", ";
ccprintf(response, "%%hi(0x%x), ", imm);
- printReg(response, _destRegIdx[0]);
+ printDestReg(response, 0);
return response.str();
}
}};
@@ -316,38 +280,29 @@ let {{
return (header_output, decoder_output, exec_output, decode_block)
calcCcCode = '''
- uint8_t tmp_ccriccc;
- uint8_t tmp_ccriccv;
- uint8_t tmp_ccriccz;
- uint8_t tmp_ccriccn;
- uint8_t tmp_ccrxccc;
- uint8_t tmp_ccrxccv;
- uint8_t tmp_ccrxccz;
- uint8_t tmp_ccrxccn;
-
- tmp_ccriccn = (Rd >> 31) & 1;
- tmp_ccriccz = ((Rd & 0xFFFFFFFF) == 0);
- tmp_ccrxccn = (Rd >> 63) & 1;
- tmp_ccrxccz = (Rd == 0);
- tmp_ccriccv = %(ivValue)s & 1;
- tmp_ccriccc = %(icValue)s & 1;
- tmp_ccrxccv = %(xvValue)s & 1;
- tmp_ccrxccc = %(xcValue)s & 1;
-
- Ccr = tmp_ccriccc | tmp_ccriccv << 1 |
- tmp_ccriccz << 2 | tmp_ccriccn << 3|
- tmp_ccrxccc << 4 | tmp_ccrxccv << 5|
- tmp_ccrxccz << 6| tmp_ccrxccn << 7;
-
-
- DPRINTF(Sparc, "in = %%d\\n", (uint16_t)tmp_ccriccn);
- DPRINTF(Sparc, "iz = %%d\\n", (uint16_t)tmp_ccriccz);
- DPRINTF(Sparc, "xn = %%d\\n", (uint16_t)tmp_ccrxccn);
- DPRINTF(Sparc, "xz = %%d\\n", (uint16_t)tmp_ccrxccz);
- DPRINTF(Sparc, "iv = %%d\\n", (uint16_t)tmp_ccriccv);
- DPRINTF(Sparc, "ic = %%d\\n", (uint16_t)tmp_ccriccc);
- DPRINTF(Sparc, "xv = %%d\\n", (uint16_t)tmp_ccrxccv);
- DPRINTF(Sparc, "xc = %%d\\n", (uint16_t)tmp_ccrxccc);
+ uint16_t _ic, _iv, _iz, _in, _xc, _xv, _xz, _xn;
+
+ _in = (Rd >> 31) & 1;
+ _iz = ((Rd & 0xFFFFFFFF) == 0);
+ _xn = (Rd >> 63) & 1;
+ _xz = (Rd == 0);
+ _iv = %(ivValue)s & 1;
+ _ic = %(icValue)s & 1;
+ _xv = %(xvValue)s & 1;
+ _xc = %(xcValue)s & 1;
+
+ Ccr = _ic << 0 | _iv << 1 | _iz << 2 | _in << 3 |
+ _xc << 4 | _xv << 5 | _xz << 6 | _xn << 7;
+
+
+ DPRINTF(Sparc, "in = %%d\\n", _in);
+ DPRINTF(Sparc, "iz = %%d\\n", _iz);
+ DPRINTF(Sparc, "xn = %%d\\n", _xn);
+ DPRINTF(Sparc, "xz = %%d\\n", _xz);
+ DPRINTF(Sparc, "iv = %%d\\n", _iv);
+ DPRINTF(Sparc, "ic = %%d\\n", _ic);
+ DPRINTF(Sparc, "xv = %%d\\n", _xv);
+ DPRINTF(Sparc, "xc = %%d\\n", _xc);
'''
}};
diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa
index 7df59d736..d7ee01519 100644
--- a/src/arch/sparc/isa/formats/priv.isa
+++ b/src/arch/sparc/isa/formats/priv.isa
@@ -72,7 +72,11 @@ output decoder {{
std::string Priv::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
- return "Privileged Instruction";
+ std::stringstream response;
+
+ printMnemonic(response, mnemonic);
+
+ return response.str();
}
}};
@@ -87,9 +91,10 @@ def template PrivExecute {{
if(%(check)s)
return new PrivilegedAction;
+ Fault fault = NoFault;
%(code)s;
%(op_wb)s;
- return NoFault;
+ return fault;
}
}};
@@ -116,10 +121,17 @@ let {{
// Primary format for integer operate instructions:
def format Priv(code, *opt_flags) {{
- checkCode = "((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>)"
+ checkCode = '''((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>) ||
+ ((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)'''
(header_output, decoder_output,
exec_output, decode_block) = doPrivFormat(code,
- checkCode, name, Name, opt_flags)
+ checkCode, name, Name, opt_flags + ('IprAccessOp',))
}};
+def format HPriv(code, *opt_flags) {{
+ checkCode = "((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)"
+ (header_output, decoder_output,
+ exec_output, decode_block) = doPrivFormat(code,
+ checkCode, name, Name, opt_flags + ('IprAccessOp',))
+}};
diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa
index 40afb3722..3783051c4 100644
--- a/src/arch/sparc/isa/includes.isa
+++ b/src/arch/sparc/isa/includes.isa
@@ -36,7 +36,6 @@
output header {{
#include <sstream>
#include <iostream>
-#include <iomanip>
#include "cpu/static_inst.hh"
#include "arch/sparc/faults.hh"
@@ -50,7 +49,6 @@ output decoder {{
#include "base/loader/symtab.hh"
#include "cpu/thread_context.hh" // for Jump::branchTarget()
-#include <math.h>
#if defined(linux)
#include <fenv.h>
#endif
@@ -59,14 +57,10 @@ using namespace SparcISA;
}};
output exec {{
-#include <math.h>
#if defined(linux)
#include <fenv.h>
#endif
-#ifdef FULL_SYSTEM
-//#include "sim/pseudo_inst.hh"
-#endif
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
#include "sim/sim_exit.hh"
diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa
index 9e5c783e8..605816083 100644
--- a/src/arch/sparc/isa/operands.isa
+++ b/src/arch/sparc/isa/operands.isa
@@ -51,12 +51,12 @@ def operands {{
'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3),
'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4),
'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5),
- #'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
- #'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
- #'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
- 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
- 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 4),
- 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 4),
+ 'Frd': ('FloatReg', 'df', 'RD', 'IsFloating', 10),
+ 'Frs1': ('FloatReg', 'df', 'RS1', 'IsFloating', 11),
+ 'Frs2': ('FloatReg', 'df', 'RS2', 'IsFloating', 12),
+ 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 20),
+ 'NPC': ('NPC', 'udw', None, ( None, None, 'IsControl' ), 31),
+ 'NNPC': ('NNPC', 'udw', None, (None, None, 'IsControl' ), 32),
#'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
#'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1),
'R0': ('IntReg', 'udw', '0', None, 6),
@@ -65,24 +65,25 @@ def operands {{
'R16': ('IntReg', 'udw', '16', None, 9),
# Control registers
- 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 12),
- 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 17),
- 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 26),
+ 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40),
+ 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 41),
+ 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 42),
- 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 28),
- 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 28),
- 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 28),
- 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 1),
- 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 27),
+ 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 43),
+ 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 44),
+ 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 45),
+ 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 46),
+ 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 47),
- 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 15),
- 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 34),
- 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 35),
- 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 37),
- 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 36),
- 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 38),
- 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 12),
+ 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 48),
+ 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 49),
+ 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 50),
+ 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 51),
+ 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 52),
+ 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 53),
+ 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 54),
- 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 47)
+ 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 55),
+ 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 56)
}};
diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh
index 346f7b730..7f830eb28 100644
--- a/src/arch/sparc/isa_traits.hh
+++ b/src/arch/sparc/isa_traits.hh
@@ -25,13 +25,13 @@
* (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: Korey Sewell
- * Gabe Black
+ * Authors: Gabe Black
*/
#ifndef __ARCH_SPARC_ISA_TRAITS_HH__
#define __ARCH_SPARC_ISA_TRAITS_HH__
+#include "arch/sparc/types.hh"
#include "base/misc.hh"
#include "config/full_system.hh"
#include "sim/host.hh"
@@ -46,70 +46,45 @@ class StaticInstPtr;
namespace BigEndianGuest {}
-#if !FULL_SYSTEM
-class SyscallReturn
-{
- public:
- template <class T>
- SyscallReturn(T v, bool s)
- {
- retval = (uint64_t)v;
- success = s;
- }
-
- template <class T>
- SyscallReturn(T v)
- {
- success = (v >= 0);
- retval = (uint64_t)v;
- }
-
- ~SyscallReturn() {}
-
- SyscallReturn& operator=(const SyscallReturn& s)
- {
- retval = s.retval;
- success = s.success;
- return *this;
- }
-
- bool successful() { return success; }
- uint64_t value() { return retval; }
-
- private:
- uint64_t retval;
- bool success;
-};
-
-#endif
-
#if FULL_SYSTEM
#include "arch/sparc/isa_fullsys_traits.hh"
#endif
namespace SparcISA
{
+ class RegFile;
+
+ //This makes sure the big endian versions of certain functions are used.
+ using namespace BigEndianGuest;
+
+ //TODO this needs to be a SPARC Noop
+ // Alpha UNOP (ldq_u r31,0(r0))
+ const MachInst NoopMachInst = 0x2ffe0000;
+
+ const int NumIntRegs = 32;
+ const int NumFloatRegs = 64;
+ const int NumMiscRegs = 40;
// These enumerate all the registers for dependence tracking.
enum DependenceTags {
// 0..31 are the integer regs 0..31
- // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
- FP_Base_DepTag = 32,
- Ctrl_Base_DepTag = 96,
+ // 32..95 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
+ FP_Base_DepTag = NumIntRegs,
+ Ctrl_Base_DepTag = NumIntRegs + NumFloatRegs,
//XXX These are here solely to get compilation and won't work
Fpcr_DepTag = 0,
Uniq_DepTag = 0
};
- //This makes sure the big endian versions of certain functions are used.
- using namespace BigEndianGuest;
- typedef uint32_t MachInst;
- typedef uint64_t ExtMachInst;
+ // MAXTL - maximum trap level
+ const int MaxPTL = 2;
+ const int MaxTL = 6;
+ const int MaxGL = 3;
+ const int MaxPGL = 2;
- const int NumIntRegs = 32;
- const int NumFloatRegs = 64;
- const int NumMiscRegs = 32;
+ // NWINDOWS - number of register windows, can be 3 to 32
+ const int NWindows = 32;
// semantically meaningful register indices
const int ZeroReg = 0; // architecturally meaningful
@@ -131,14 +106,6 @@ namespace SparcISA
const int MaxInstSrcRegs = 8;
const int MaxInstDestRegs = 9;
- typedef uint64_t IntReg;
-
- // control register file contents
- typedef uint64_t MiscReg;
-
- typedef double FloatReg;
- typedef uint64_t FloatRegBits;
-
//8K. This value is implmentation specific; and should probably
//be somewhere else.
const int LogVMPageSize = 13;
@@ -165,29 +132,4 @@ namespace SparcISA
extern const MachInst NoopMachInst;
}
-#include "arch/sparc/regfile.hh"
-
-namespace SparcISA
-{
-
-#if !FULL_SYSTEM
- static inline void setSyscallReturn(SyscallReturn return_value,
- RegFile *regs)
- {
- // check for error condition. SPARC syscall convention is to
- // indicate success/failure in reg the carry bit of the ccr
- // and put the return value itself in the standard return value reg ().
- if (return_value.successful()) {
- // no error, clear XCC.C
- regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) & 0xEF);
- regs->setIntReg(ReturnValueReg, return_value.value());
- } else {
- // got an error, set XCC.C
- regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) | 0x10);
- regs->setIntReg(ReturnValueReg, return_value.value());
- }
- }
-#endif
-};
-
#endif // __ARCH_SPARC_ISA_TRAITS_HH__
diff --git a/src/arch/sparc/linux/linux.cc b/src/arch/sparc/linux/linux.cc
index ae6ffbc2a..1211d5f65 100644
--- a/src/arch/sparc/linux/linux.cc
+++ b/src/arch/sparc/linux/linux.cc
@@ -29,6 +29,7 @@
*/
#include "arch/sparc/linux/linux.hh"
+#include <fcntl.h>
// open(2) flags translation table
OpenFlagTransTable SparcLinux::openFlagTable[] = {
diff --git a/src/arch/sparc/linux/process.cc b/src/arch/sparc/linux/process.cc
index e27255e67..8c2de8ca3 100644
--- a/src/arch/sparc/linux/process.cc
+++ b/src/arch/sparc/linux/process.cc
@@ -199,7 +199,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 99 */ SyscallDesc("accept", unimplementedFunc),
/* 100 */ SyscallDesc("getpriority", unimplementedFunc),
/* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
- /* 102 */ SyscallDesc("rt_sigaction", unimplementedFunc),
+ /* 102 */ SyscallDesc("rt_sigaction", ignoreFunc),
/* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
/* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc),
/* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
@@ -295,7 +295,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 195 */ SyscallDesc("epoll_wait", unimplementedFunc),
/* 196 */ SyscallDesc("ioprio_set", unimplementedFunc),
/* 197 */ SyscallDesc("getppid", getppidFunc),
- /* 198 */ SyscallDesc("sigaction", unimplementedFunc),
+ /* 198 */ SyscallDesc("sigaction", ignoreFunc),
/* 199 */ SyscallDesc("sgetmask", unimplementedFunc),
/* 200 */ SyscallDesc("ssetmask", unimplementedFunc),
/* 201 */ SyscallDesc("sigsuspend", unimplementedFunc),
diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh
index f4819ba84..4af8f0f75 100644
--- a/src/arch/sparc/linux/process.hh
+++ b/src/arch/sparc/linux/process.hh
@@ -32,6 +32,7 @@
#define __SPARC_LINUX_PROCESS_HH__
#include "arch/sparc/linux/linux.hh"
+#include "arch/sparc/syscallreturn.hh"
#include "arch/sparc/process.hh"
#include "sim/process.hh"
diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc
new file mode 100644
index 000000000..8041e45c0
--- /dev/null
+++ b/src/arch/sparc/miscregfile.cc
@@ -0,0 +1,540 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ * Ali Saidi
+ */
+
+#include "arch/sparc/miscregfile.hh"
+#include "base/trace.hh"
+#include "cpu/base.hh"
+#include "cpu/thread_context.hh"
+
+using namespace SparcISA;
+using namespace std;
+
+class Checkpoint;
+
+//These functions map register indices to names
+string SparcISA::getMiscRegName(RegIndex index)
+{
+ static::string miscRegName[NumMiscRegs] =
+ {"y", "ccr", "asi", "tick", "pc", "fprs", "pcr", "pic",
+ "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr",
+ "stick", "stick_cmpr",
+ "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl",
+ "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
+ "wstate", "gl",
+ "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg",
+ "hstick_cmpr",
+ "fsr"};
+ return miscRegName[index];
+}
+
+#if FULL_SYSTEM
+
+//XXX These need an implementation someplace
+/** Fullsystem only register version of ReadRegWithEffect() */
+MiscReg MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc);
+/** Fullsystem only register version of SetRegWithEffect() */
+Fault MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
+ ThreadContext * tc);
+#endif
+
+void MiscRegFile::reset()
+{
+ pstateFields.pef = 0; //No FPU
+ //pstateFields.pef = 1; //FPU
+#if FULL_SYSTEM
+ //For SPARC, when a system is first started, there is a power
+ //on reset Trap which sets the processor into the following state.
+ //Bits that aren't set aren't defined on startup.
+ tl = MaxTL;
+ gl = MaxGL;
+
+ tickFields.counter = 0; //The TICK register is unreadable bya
+ tickFields.npt = 1; //The TICK register is unreadable by by !priv
+
+ softint = 0; // Clear all the soft interrupt bits
+ tick_cmprFields.int_dis = 1; // disable timer compare interrupts
+ tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
+ stickFields.npt = 1; //The TICK register is unreadable by by !priv
+ stick_cmprFields.int_dis = 1; // disable timer compare interrupts
+ stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
+
+
+ tt[tl] = power_on_reset;
+ pstate = 0; // fields 0 but pef
+ pstateFields.pef = 1;
+
+ hpstate = 0;
+ hpstateFields.red = 1;
+ hpstateFields.hpriv = 1;
+ hpstateFields.tlz = 0; // this is a guess
+ hintp = 0; // no interrupts pending
+ hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
+ hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
+#else
+/* //This sets up the initial state of the processor for usermode processes
+ pstateFields.priv = 0; //Process runs in user mode
+ pstateFields.ie = 1; //Interrupts are enabled
+ fsrFields.rd = 0; //Round to nearest
+ fsrFields.tem = 0; //Floating point traps not enabled
+ fsrFields.ns = 0; //Non standard mode off
+ fsrFields.qne = 0; //Floating point queue is empty
+ fsrFields.aexc = 0; //No accrued exceptions
+ fsrFields.cexc = 0; //No current exceptions
+
+ //Register window management registers
+ otherwin = 0; //No windows contain info from other programs
+ canrestore = 0; //There are no windows to pop
+ cansave = MaxTL - 2; //All windows are available to save into
+ cleanwin = MaxTL;*/
+#endif
+}
+
+MiscReg MiscRegFile::readReg(int miscReg)
+{
+ switch (miscReg) {
+ case MISCREG_Y:
+ return y;
+ case MISCREG_CCR:
+ return ccr;
+ case MISCREG_ASI:
+ return asi;
+ case MISCREG_FPRS:
+ return fprs;
+ case MISCREG_TICK:
+ return tick;
+ case MISCREG_PCR:
+ case MISCREG_PIC:
+ panic("ASR number %d not implemented\n", miscReg - AsrStart);
+ case MISCREG_GSR:
+ return gsr;
+ case MISCREG_SOFTINT:
+ return softint;
+ case MISCREG_TICK_CMPR:
+ return tick_cmpr;
+ case MISCREG_STICK:
+ return stick;
+ case MISCREG_STICK_CMPR:
+ return stick_cmpr;
+
+ /** Privilged Registers */
+ case MISCREG_TPC:
+ return tpc[tl-1];
+ case MISCREG_TNPC:
+ return tnpc[tl-1];
+ case MISCREG_TSTATE:
+ return tstate[tl-1];
+ case MISCREG_TT:
+ return tt[tl-1];
+ case MISCREG_PRIVTICK:
+ panic("Priviliged access to tick registers not implemented\n");
+ case MISCREG_TBA:
+ return tba;
+ case MISCREG_PSTATE:
+ return pstate;
+ case MISCREG_TL:
+ return tl;
+ case MISCREG_PIL:
+ return pil;
+ case MISCREG_CWP:
+ return cwp;
+ case MISCREG_CANSAVE:
+ return cansave;
+ case MISCREG_CANRESTORE:
+ return canrestore;
+ case MISCREG_CLEANWIN:
+ return cleanwin;
+ case MISCREG_OTHERWIN:
+ return otherwin;
+ case MISCREG_WSTATE:
+ return wstate;
+ case MISCREG_GL:
+ return gl;
+
+ /** Hyper privileged registers */
+ case MISCREG_HPSTATE:
+ return hpstate;
+ case MISCREG_HTSTATE:
+ return htstate[tl-1];
+ case MISCREG_HINTP:
+ panic("HINTP not implemented\n");
+ case MISCREG_HTBA:
+ return htba;
+ case MISCREG_HVER:
+ return NWindows | MaxTL << 8 | MaxGL << 16;
+ case MISCREG_STRAND_STS_REG:
+ return strandStatusReg;
+ case MISCREG_HSTICK_CMPR:
+ return hstick_cmpr;
+
+ /** Floating Point Status Register */
+ case MISCREG_FSR:
+ return fsr;
+ default:
+ panic("Miscellaneous register %d not implemented\n", miscReg);
+ }
+}
+
+MiscReg MiscRegFile::readRegWithEffect(int miscReg,
+ Fault &fault, ThreadContext * tc)
+{
+ fault = NoFault;
+ switch (miscReg) {
+ case MISCREG_Y:
+ case MISCREG_CCR:
+ case MISCREG_ASI:
+ return readReg(miscReg);
+
+ case MISCREG_TICK:
+ case MISCREG_PRIVTICK:
+ // Check for reading privilege
+ if (tickFields.npt && !isNonPriv()) {
+ fault = new PrivilegedAction;
+ return 0;
+ }
+ return tc->getCpuPtr()->curCycle() - tickFields.counter |
+ tickFields.npt << 63;
+ case MISCREG_PC:
+ return tc->readPC();
+ case MISCREG_FPRS:
+ fault = new UnimpFault("FPU not implemented\n");
+ return 0;
+ case MISCREG_PCR:
+ fault = new UnimpFault("Performance Instrumentation not impl\n");
+ return 0;
+ case MISCREG_PIC:
+ fault = new UnimpFault("Performance Instrumentation not impl\n");
+ return 0;
+ case MISCREG_GSR:
+ return readReg(miscReg);
+
+ /** Privilged Registers */
+ case MISCREG_TPC:
+ case MISCREG_TNPC:
+ case MISCREG_TSTATE:
+ case MISCREG_TT:
+ if (tl == 0) {
+ fault = new IllegalInstruction;
+ return 0;
+ } // NOTE THE FALL THROUGH!
+ case MISCREG_PSTATE:
+ case MISCREG_TL:
+ return readReg(miscReg);
+
+ case MISCREG_TBA:
+ return readReg(miscReg) & ULL(~0x7FFF);
+
+ case MISCREG_PIL:
+
+ case MISCREG_CWP:
+ case MISCREG_CANSAVE:
+ case MISCREG_CANRESTORE:
+ case MISCREG_CLEANWIN:
+ case MISCREG_OTHERWIN:
+ case MISCREG_WSTATE:
+ case MISCREG_GL:
+ return readReg(miscReg);
+
+ /** Floating Point Status Register */
+ case MISCREG_FSR:
+ panic("Floating Point not implemented\n");
+ default:
+#if FULL_SYSTEM
+ return readFSRegWithEffect(miscReg, fault, tc);
+#else
+ fault = new IllegalInstruction;
+ return 0;
+#endif
+ }
+}
+
+Fault MiscRegFile::setReg(int miscReg, const MiscReg &val)
+{
+ switch (miscReg) {
+ case MISCREG_Y:
+ y = val;
+ return NoFault;
+ case MISCREG_CCR:
+ ccr = val;
+ return NoFault;
+ case MISCREG_ASI:
+ asi = val;
+ return NoFault;
+ case MISCREG_FPRS:
+ fprs = val;
+ return NoFault;
+ case MISCREG_TICK:
+ tick = val;
+ return NoFault;
+ case MISCREG_PCR:
+ case MISCREG_PIC:
+ panic("ASR number %d not implemented\n", miscReg - AsrStart);
+ case MISCREG_GSR:
+ gsr = val;
+ case MISCREG_SOFTINT:
+ softint = val;
+ return NoFault;
+ case MISCREG_TICK_CMPR:
+ tick_cmpr = val;
+ return NoFault;
+ case MISCREG_STICK:
+ stick = val;
+ return NoFault;
+ case MISCREG_STICK_CMPR:
+ stick_cmpr = val;
+ return NoFault;
+
+ /** Privilged Registers */
+ case MISCREG_TPC:
+ tpc[tl-1] = val;
+ return NoFault;
+ case MISCREG_TNPC:
+ tnpc[tl-1] = val;
+ return NoFault;
+ case MISCREG_TSTATE:
+ tstate[tl-1] = val;
+ return NoFault;
+ case MISCREG_TT:
+ tt[tl-1] = val;
+ return NoFault;
+ case MISCREG_PRIVTICK:
+ panic("Priviliged access to tick regesiters not implemented\n");
+ case MISCREG_TBA:
+ tba = val;
+ return NoFault;
+ case MISCREG_PSTATE:
+ pstate = val;
+ return NoFault;
+ case MISCREG_TL:
+ tl = val;
+ return NoFault;
+ case MISCREG_PIL:
+ pil = val;
+ return NoFault;
+ case MISCREG_CWP:
+ cwp = val;
+ return NoFault;
+ case MISCREG_CANSAVE:
+ cansave = val;
+ return NoFault;
+ case MISCREG_CANRESTORE:
+ canrestore = val;
+ return NoFault;
+ case MISCREG_CLEANWIN:
+ cleanwin = val;
+ return NoFault;
+ case MISCREG_OTHERWIN:
+ otherwin = val;
+ return NoFault;
+ case MISCREG_WSTATE:
+ wstate = val;
+ return NoFault;
+ case MISCREG_GL:
+ gl = val;
+ return NoFault;
+
+ /** Hyper privileged registers */
+ case MISCREG_HPSTATE:
+ hpstate = val;
+ return NoFault;
+ case MISCREG_HTSTATE:
+ htstate[tl-1] = val;
+ return NoFault;
+ case MISCREG_HINTP:
+ panic("HINTP not implemented\n");
+ case MISCREG_HTBA:
+ htba = val;
+ return NoFault;
+ case MISCREG_STRAND_STS_REG:
+ strandStatusReg = val;
+ return NoFault;
+ case MISCREG_HSTICK_CMPR:
+ hstick_cmpr = val;
+ return NoFault;
+
+ /** Floating Point Status Register */
+ case MISCREG_FSR:
+ fsr = val;
+ return NoFault;
+ default:
+ panic("Miscellaneous register %d not implemented\n", miscReg);
+ }
+}
+
+Fault MiscRegFile::setRegWithEffect(int miscReg,
+ const MiscReg &val, ThreadContext * tc)
+{
+ const uint64_t Bit64 = (1ULL << 63);
+ switch (miscReg) {
+ case MISCREG_Y:
+ case MISCREG_CCR:
+ case MISCREG_ASI:
+ setReg(miscReg, val);
+ return NoFault;
+ case MISCREG_PRIVTICK:
+ case MISCREG_TICK:
+ if (isNonPriv())
+ return new PrivilegedOpcode;
+ if (isPriv())
+ return new PrivilegedAction;
+ tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64;
+ tickFields.npt = val & Bit64 ? 1 : 0;
+ return NoFault;
+ case MISCREG_PC:
+ return new IllegalInstruction;
+ case MISCREG_FPRS:
+ return new UnimpFault("FPU not implemented\n");
+ case MISCREG_PCR:
+ return new UnimpFault("Performance Instrumentation not impl\n");
+ case MISCREG_PIC:
+ return new UnimpFault("Performance Instrumentation not impl\n");
+ case MISCREG_GSR:
+ return setReg(miscReg, val);
+
+ /** Privilged Registers */
+ case MISCREG_TPC:
+ case MISCREG_TNPC:
+ case MISCREG_TSTATE:
+ case MISCREG_TT:
+ if (tl == 0)
+ return new IllegalInstruction;
+ setReg(miscReg, val);
+ return NoFault;
+
+ case MISCREG_TBA:
+ // clear lower 7 bits on writes.
+ setReg(miscReg, val & ULL(~0x7FFF));
+ return NoFault;
+
+ case MISCREG_PSTATE:
+ setReg(miscReg, val);
+ return NoFault;
+
+ case MISCREG_TL:
+ if (isHyperPriv() && val > MaxTL)
+ setReg(miscReg, MaxTL);
+ else if (isPriv() && !isHyperPriv() && val > MaxPTL)
+ setReg(miscReg, MaxPTL);
+ else
+ setReg(miscReg, val);
+ return NoFault;
+
+ case MISCREG_CWP:
+ tc->changeRegFileContext(CONTEXT_CWP, val);
+ case MISCREG_CANSAVE:
+ case MISCREG_CANRESTORE:
+ case MISCREG_CLEANWIN:
+ case MISCREG_OTHERWIN:
+ case MISCREG_WSTATE:
+ setReg(miscReg, val);
+ return NoFault;
+
+ case MISCREG_GL:
+ int newval;
+ if (isHyperPriv() && val > MaxGL)
+ newval = MaxGL;
+ else if (isPriv() && !isHyperPriv() && val > MaxPGL)
+ newval = MaxPGL;
+ else
+ newval = val;
+ tc->changeRegFileContext(CONTEXT_GLOBALS, newval);
+ setReg(miscReg, newval);
+ return NoFault;
+
+ /** Floating Point Status Register */
+ case MISCREG_FSR:
+ panic("Floating Point not implemented\n");
+ default:
+#if FULL_SYSTEM
+ setFSRegWithEffect(miscReg, val, tc);
+#else
+ return new IllegalInstruction;
+#endif
+ }
+}
+
+void MiscRegFile::serialize(std::ostream & os)
+{
+ SERIALIZE_SCALAR(pstate);
+ SERIALIZE_SCALAR(tba);
+ SERIALIZE_SCALAR(y);
+ SERIALIZE_SCALAR(pil);
+ SERIALIZE_SCALAR(gl);
+ SERIALIZE_SCALAR(cwp);
+ SERIALIZE_ARRAY(tt, MaxTL);
+ SERIALIZE_SCALAR(ccr);
+ SERIALIZE_SCALAR(asi);
+ SERIALIZE_SCALAR(tl);
+ SERIALIZE_ARRAY(tpc, MaxTL);
+ SERIALIZE_ARRAY(tnpc, MaxTL);
+ SERIALIZE_ARRAY(tstate, MaxTL);
+ SERIALIZE_SCALAR(tick);
+ SERIALIZE_SCALAR(cansave);
+ SERIALIZE_SCALAR(canrestore);
+ SERIALIZE_SCALAR(otherwin);
+ SERIALIZE_SCALAR(cleanwin);
+ SERIALIZE_SCALAR(wstate);
+ SERIALIZE_SCALAR(fsr);
+ SERIALIZE_SCALAR(fprs);
+ SERIALIZE_SCALAR(hpstate);
+ SERIALIZE_ARRAY(htstate, MaxTL);
+ SERIALIZE_SCALAR(htba);
+ SERIALIZE_SCALAR(hstick_cmpr);
+}
+
+void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
+{
+ UNSERIALIZE_SCALAR(pstate);
+ UNSERIALIZE_SCALAR(tba);
+ UNSERIALIZE_SCALAR(y);
+ UNSERIALIZE_SCALAR(pil);
+ UNSERIALIZE_SCALAR(gl);
+ UNSERIALIZE_SCALAR(cwp);
+ UNSERIALIZE_ARRAY(tt, MaxTL);
+ UNSERIALIZE_SCALAR(ccr);
+ UNSERIALIZE_SCALAR(asi);
+ UNSERIALIZE_SCALAR(tl);
+ UNSERIALIZE_ARRAY(tpc, MaxTL);
+ UNSERIALIZE_ARRAY(tnpc, MaxTL);
+ UNSERIALIZE_ARRAY(tstate, MaxTL);
+ UNSERIALIZE_SCALAR(tick);
+ UNSERIALIZE_SCALAR(cansave);
+ UNSERIALIZE_SCALAR(canrestore);
+ UNSERIALIZE_SCALAR(otherwin);
+ UNSERIALIZE_SCALAR(cleanwin);
+ UNSERIALIZE_SCALAR(wstate);
+ UNSERIALIZE_SCALAR(fsr);
+ UNSERIALIZE_SCALAR(fprs);
+ UNSERIALIZE_SCALAR(hpstate);
+ UNSERIALIZE_ARRAY(htstate, MaxTL);
+ UNSERIALIZE_SCALAR(htba);
+ UNSERIALIZE_SCALAR(hstick_cmpr);
+}
+
diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh
new file mode 100644
index 000000000..be143311f
--- /dev/null
+++ b/src/arch/sparc/miscregfile.hh
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ * Ali Saidi
+ */
+
+#ifndef __ARCH_SPARC_MISCREGFILE_HH__
+#define __ARCH_SPARC_MISCREGFILE_HH__
+
+#include "arch/sparc/faults.hh"
+#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/types.hh"
+
+#include <string>
+
+namespace SparcISA
+{
+
+ //These functions map register indices to names
+ std::string getMiscRegName(RegIndex);
+
+ const int AsrStart = 0;
+ const int PrStart = 32;
+ const int HprStart = 64;
+ const int MiscStart = 96;
+
+ enum MiscRegIndex
+ {
+ /** Ancillary State Registers */
+ MISCREG_Y = AsrStart + 0,
+ MISCREG_CCR = AsrStart + 2,
+ MISCREG_ASI = AsrStart + 3,
+ MISCREG_TICK = AsrStart + 4,
+ MISCREG_PC = AsrStart + 5,
+ MISCREG_FPRS = AsrStart + 6,
+ MISCREG_PCR = AsrStart + 16,
+ MISCREG_PIC = AsrStart + 17,
+ MISCREG_GSR = AsrStart + 19,
+ MISCREG_SOFTINT_SET = AsrStart + 20,
+ MISCREG_SOFTINT_CLR = AsrStart + 21,
+ MISCREG_SOFTINT = AsrStart + 22,
+ MISCREG_TICK_CMPR = AsrStart + 23,
+ MISCREG_STICK = AsrStart + 24,
+ MISCREG_STICK_CMPR = AsrStart + 25,
+
+ /** Privilged Registers */
+ MISCREG_TPC = PrStart + 0,
+ MISCREG_TNPC = PrStart + 1,
+ MISCREG_TSTATE = PrStart + 2,
+ MISCREG_TT = PrStart + 3,
+ MISCREG_PRIVTICK = PrStart + 4,
+ MISCREG_TBA = PrStart + 5,
+ MISCREG_PSTATE = PrStart + 6,
+ MISCREG_TL = PrStart + 7,
+ MISCREG_PIL = PrStart + 8,
+ MISCREG_CWP = PrStart + 9,
+ MISCREG_CANSAVE = PrStart + 10,
+ MISCREG_CANRESTORE = PrStart + 11,
+ MISCREG_CLEANWIN = PrStart + 12,
+ MISCREG_OTHERWIN = PrStart + 13,
+ MISCREG_WSTATE = PrStart + 14,
+ MISCREG_GL = PrStart + 16,
+
+ /** Hyper privileged registers */
+ MISCREG_HPSTATE = HprStart + 0,
+ MISCREG_HTSTATE = HprStart + 1,
+ MISCREG_HINTP = HprStart + 3,
+ MISCREG_HTBA = HprStart + 5,
+ MISCREG_HVER = HprStart + 6,
+ MISCREG_STRAND_STS_REG = HprStart + 16,
+ MISCREG_HSTICK_CMPR = HprStart + 31,
+
+ /** Floating Point Status Register */
+ MISCREG_FSR = MiscStart + 0
+
+ };
+
+ // The control registers, broken out into fields
+ class MiscRegFile
+ {
+ private:
+
+ /* ASR Registers */
+ union {
+ uint64_t y; // Y (used in obsolete multiplication)
+ struct {
+ uint64_t value:32; // The actual value stored in y
+ uint64_t :32; // reserved bits
+ } yFields;
+ };
+ union {
+ uint8_t ccr; // Condition Code Register
+ struct {
+ union {
+ uint8_t icc:4; // 32-bit condition codes
+ struct {
+ uint8_t c:1; // Carry
+ uint8_t v:1; // Overflow
+ uint8_t z:1; // Zero
+ uint8_t n:1; // Negative
+ } iccFields;
+ };
+ union {
+ uint8_t xcc:4; // 64-bit condition codes
+ struct {
+ uint8_t c:1; // Carry
+ uint8_t v:1; // Overflow
+ uint8_t z:1; // Zero
+ uint8_t n:1; // Negative
+ } xccFields;
+ };
+ } ccrFields;
+ };
+ uint8_t asi; // Address Space Identifier
+ union {
+ uint64_t tick; // Hardware clock-tick counter
+ struct {
+ int64_t counter:63; // Clock-tick count
+ uint64_t npt:1; // Non-priveleged trap
+ } tickFields;
+ };
+ union {
+ uint8_t fprs; // Floating-Point Register State
+ struct {
+ uint8_t dl:1; // Dirty lower
+ uint8_t du:1; // Dirty upper
+ uint8_t fef:1; // FPRS enable floating-Point
+ } fprsFields;
+ };
+ union {
+ uint64_t gsr; //General Status Register
+ struct {
+ uint64_t mask:32;
+ uint64_t :4;
+ uint64_t im:1;
+ uint64_t irnd:2;
+ uint64_t :17;
+ uint64_t scale:5;
+ uint64_t align:3;
+ } gsrFields;
+ };
+ union {
+ uint64_t softint;
+ struct {
+ uint64_t tm:1;
+ uint64_t int_level:14;
+ uint64_t sm:1;
+ } softintFields;
+ };
+ union {
+ uint64_t tick_cmpr; // Hardware tick compare registers
+ struct {
+ uint64_t tick_cmpr:63; // Clock-tick count
+ uint64_t int_dis:1; // Non-priveleged trap
+ } tick_cmprFields;
+ };
+ union {
+ uint64_t stick; // Hardware clock-tick counter
+ struct {
+ int64_t :63; // Not used, storage in SparcSystem
+ uint64_t npt:1; // Non-priveleged trap
+ } stickFields;
+ };
+ union {
+ uint64_t stick_cmpr; // Hardware tick compare registers
+ struct {
+ uint64_t tick_cmpr:63; // Clock-tick count
+ uint64_t int_dis:1; // Non-priveleged trap
+ } stick_cmprFields;
+ };
+
+
+ /* Privileged Registers */
+ uint64_t tpc[MaxTL]; // Trap Program Counter (value from
+ // previous trap level)
+ uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from
+ // previous trap level)
+ union {
+ uint64_t tstate[MaxTL]; // Trap State
+ struct {
+ //Values are from previous trap level
+ uint64_t cwp:5; // Current Window Pointer
+ uint64_t :3; // Reserved bits
+ uint64_t pstate:13; // Process State
+ uint64_t :3; // Reserved bits
+ uint64_t asi:8; // Address Space Identifier
+ uint64_t ccr:8; // Condition Code Register
+ uint64_t gl:8; // Global level
+ } tstateFields[MaxTL];
+ };
+ uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured
+ // on the previous level)
+ uint64_t tba; // Trap Base Address
+
+ union {
+ uint16_t pstate; // Process State Register
+ struct {
+ uint16_t :1; // reserved
+ uint16_t ie:1; // Interrupt enable
+ uint16_t priv:1; // Privelege mode
+ uint16_t am:1; // Address mask
+ uint16_t pef:1; // PSTATE enable floating-point
+ uint16_t :1; // reserved2
+ uint16_t mm:2; // Memory Model
+ uint16_t tle:1; // Trap little-endian
+ uint16_t cle:1; // Current little-endian
+ } pstateFields;
+ };
+ uint8_t tl; // Trap Level
+ uint8_t pil; // Process Interrupt Register
+ uint8_t cwp; // Current Window Pointer
+ uint8_t cansave; // Savable windows
+ uint8_t canrestore; // Restorable windows
+ uint8_t cleanwin; // Clean windows
+ uint8_t otherwin; // Other windows
+ union {
+ uint8_t wstate; // Window State
+ struct {
+ uint8_t normal:3; // Bits TT<4:2> are set to on a normal
+ // register window trap
+ uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin"
+ // register window trap
+ } wstateFields;
+ };
+ uint8_t gl; // Global level register
+
+
+ /** Hyperprivileged Registers */
+ union {
+ uint64_t hpstate; // Hyperprivileged State Register
+ struct {
+ uint8_t tlz: 1;
+ uint8_t :1;
+ uint8_t hpriv:1;
+ uint8_t :2;
+ uint8_t red:1;
+ uint8_t :4;
+ uint8_t ibe:1;
+ uint8_t id:1;
+ } hpstateFields;
+ };
+
+ uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register
+ uint64_t hintp;
+ uint64_t htba; // Hyperprivileged Trap Base Address register
+ union {
+ uint64_t hstick_cmpr; // Hardware tick compare registers
+ struct {
+ uint64_t tick_cmpr:63; // Clock-tick count
+ uint64_t int_dis:1; // Non-priveleged trap
+ } hstick_cmprFields;
+ };
+
+ uint64_t strandStatusReg; // Per strand status register
+
+
+ /** Floating point misc registers. */
+ union {
+ uint64_t fsr; // Floating-Point State Register
+ struct {
+ union {
+ uint64_t cexc:5; // Current excpetion
+ struct {
+ uint64_t nxc:1; // Inexact
+ uint64_t dzc:1; // Divide by zero
+ uint64_t ufc:1; // Underflow
+ uint64_t ofc:1; // Overflow
+ uint64_t nvc:1; // Invalid operand
+ } cexcFields;
+ };
+ union {
+ uint64_t aexc:5; // Accrued exception
+ struct {
+ uint64_t nxc:1; // Inexact
+ uint64_t dzc:1; // Divide by zero
+ uint64_t ufc:1; // Underflow
+ uint64_t ofc:1; // Overflow
+ uint64_t nvc:1; // Invalid operand
+ } aexcFields;
+ };
+ uint64_t fcc0:2; // Floating-Point condtion codes
+ uint64_t :1; // Reserved bits
+ uint64_t qne:1; // Deferred trap queue not empty
+ // with no queue, it should read 0
+ uint64_t ftt:3; // Floating-Point trap type
+ uint64_t ver:3; // Version (of the FPU)
+ uint64_t :2; // Reserved bits
+ uint64_t ns:1; // Nonstandard floating point
+ union {
+ uint64_t tem:5; // Trap Enable Mask
+ struct {
+ uint64_t nxm:1; // Inexact
+ uint64_t dzm:1; // Divide by zero
+ uint64_t ufm:1; // Underflow
+ uint64_t ofm:1; // Overflow
+ uint64_t nvm:1; // Invalid operand
+ } temFields;
+ };
+ uint64_t :2; // Reserved bits
+ uint64_t rd:2; // Rounding direction
+ uint64_t fcc1:2; // Floating-Point condition codes
+ uint64_t fcc2:2; // Floating-Point condition codes
+ uint64_t fcc3:2; // Floating-Point condition codes
+ uint64_t :26; // Reserved bits
+ } fsrFields;
+ };
+
+ // These need to check the int_dis field and if 0 then
+ // set appropriate bit in softint and checkinterrutps on the cpu
+#if FULL_SYSTEM
+ /** Process a tick compare event and generate an interrupt on the cpu if
+ * appropriate. */
+ void processTickCompare(ThreadContext *tc);
+ void processSTickCompare(ThreadContext *tc);
+ void processHSTickCompare(ThreadContext *tc);
+
+ typedef CpuEventWrapper<MiscRegFile,
+ &MiscRegFile::processTickCompare> TickCompareEvent;
+ TickCompareEvent *tickCompare;
+
+ typedef CpuEventWrapper<MiscRegFile,
+ &MiscRegFile::processSTickCompare> STickCompareEvent;
+ STickCompareEvent *sTickCompare;
+
+ typedef CpuEventWrapper<MiscRegFile,
+ &MiscRegFile::processHSTickCompare> HSTickCompareEvent;
+ HSTickCompareEvent *hSTickCompare;
+
+ /** Fullsystem only register version of ReadRegWithEffect() */
+ MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc);
+ /** Fullsystem only register version of SetRegWithEffect() */
+ Fault setFSRegWithEffect(int miscReg, const MiscReg &val,
+ ThreadContext * tc);
+#endif
+ public:
+
+ void reset();
+
+ MiscRegFile()
+ {
+ reset();
+ }
+
+ /** read a value out of an either an SE or FS IPR. No checking is done
+ * about SE vs. FS as this is mostly used to copy the regfile. Thus more
+ * register are copied that are necessary for FS. However this prevents
+ * a bunch of ifdefs and is rarely called so is not performance
+ * criticial. */
+ MiscReg readReg(int miscReg);
+
+ /** Read a value from an IPR. Only the SE iprs are here and the rest
+ * are are readFSRegWithEffect (which is called by readRegWithEffect()).
+ * Checking is done for permission based on state bits in the miscreg
+ * file. */
+ MiscReg readRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc);
+
+ /** write a value into an either an SE or FS IPR. No checking is done
+ * about SE vs. FS as this is mostly used to copy the regfile. Thus more
+ * register are copied that are necessary for FS. However this prevents
+ * a bunch of ifdefs and is rarely called so is not performance
+ * criticial.*/
+ Fault setReg(int miscReg, const MiscReg &val);
+
+ /** Write a value into an IPR. Only the SE iprs are here and the rest
+ * are are setFSRegWithEffect (which is called by setRegWithEffect()).
+ * Checking is done for permission based on state bits in the miscreg
+ * file. */
+ Fault setRegWithEffect(int miscReg,
+ const MiscReg &val, ThreadContext * tc);
+
+ void serialize(std::ostream & os);
+
+ void unserialize(Checkpoint * cp, const std::string & section);
+
+ void copyMiscRegs(ThreadContext * tc);
+
+ protected:
+
+ bool isHyperPriv() { return hpstateFields.hpriv; }
+ bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; }
+ bool isNonPriv() { return !isPriv(); }
+ };
+}
+
+#endif
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index 75f01e038..70c7e719f 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -32,6 +32,7 @@
#include "arch/sparc/isa_traits.hh"
#include "arch/sparc/process.hh"
#include "base/loader/object_file.hh"
+#include "base/loader/elf_object.hh"
#include "base/misc.hh"
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
@@ -129,7 +130,8 @@ SparcLiveProcess::argsInit(int intSize, int pageSize)
SPARC_AT_UID = 11,
SPARC_AT_EUID = 12,
SPARC_AT_GID = 13,
- SPARC_AT_EGID = 14
+ SPARC_AT_EGID = 14,
+ SPARC_AT_SECURE = 23
};
enum hardwareCaps
@@ -153,31 +155,42 @@ SparcLiveProcess::argsInit(int intSize, int pageSize)
M5_HWCAP_SPARC_V9 |
M5_HWCAP_SPARC_ULTRA3;
- //Setup the auxilliary vectors. These will already have
- //endian conversion.
- auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100));
- auxv.push_back(buildAuxVect(SPARC_AT_GID, 100));
- auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100));
- auxv.push_back(buildAuxVect(SPARC_AT_UID, 100));
- //This would work, but the entry point is a protected member
- //auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entry));
- auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0));
- //This is the address of the elf "interpreter", which I don't
- //think we currently set up. It should be set to 0 (I think)
- //auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0));
- //This is the number of headers which were in the original elf
- //file. This information isn't avaibale by this point.
- //auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, 3));
- //This is the size of a program header entry. This isn't easy
- //to compute here.
- //auxv.push_back(buildAuxVect(SPARC_AT_PHENT, blah));
- //This is should be set to load_addr (whatever that is) +
- //e_phoff. I think it's a pointer to the program headers.
- //auxv.push_back(buildAuxVect(SPARC_AT_PHDR, blah));
- //This should be easy to get right, but I won't set it for now
- //auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, blah));
- auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
- auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap));
+
+ //Setup the auxilliary vectors. These will already have endian conversion.
+ //Auxilliary vectors are loaded only for elf formatted executables.
+ ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
+ if(elfObject)
+ {
+ //Bits which describe the system hardware capabilities
+ auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap));
+ //The system page size
+ auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
+ //Defined to be 100 in the kernel source.
+ //Frequency at which times() increments
+ auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, 100));
+ // For statically linked executables, this is the virtual address of the
+ // program header tables if they appear in the executable image
+ auxv.push_back(buildAuxVect(SPARC_AT_PHDR, elfObject->programHeaderTable()));
+ // This is the size of a program header entry from the elf file.
+ auxv.push_back(buildAuxVect(SPARC_AT_PHENT, elfObject->programHeaderSize()));
+ // This is the number of program headers from the original elf file.
+ auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, elfObject->programHeaderCount()));
+ //This is the address of the elf "interpreter", It should be set
+ //to 0 for regular executables. It should be something else
+ //(not sure what) for dynamic libraries.
+ auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0));
+ //This is hardwired to 0 in the elf loading code in the kernel
+ auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0));
+ //The entry point to the program
+ auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entryPoint()));
+ //Different user and group IDs
+ auxv.push_back(buildAuxVect(SPARC_AT_UID, 100));
+ auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100));
+ auxv.push_back(buildAuxVect(SPARC_AT_GID, 100));
+ auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100));
+ //Whether to enable "secure mode" in the executable
+ auxv.push_back(buildAuxVect(SPARC_AT_SECURE, 0));
+ }
//Figure out how big the initial stack needs to be
diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc
new file mode 100644
index 000000000..747426781
--- /dev/null
+++ b/src/arch/sparc/regfile.cc
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ * Ali Saidi
+ */
+
+#include "arch/sparc/regfile.hh"
+#include "cpu/thread_context.hh"
+
+class Checkpoint;
+
+using namespace SparcISA;
+using namespace std;
+
+//RegFile class methods
+Addr RegFile::readPC()
+{
+ return pc;
+}
+
+void RegFile::setPC(Addr val)
+{
+ pc = val;
+}
+
+Addr RegFile::readNextPC()
+{
+ return npc;
+}
+
+void RegFile::setNextPC(Addr val)
+{
+ npc = val;
+}
+
+Addr RegFile::readNextNPC()
+{
+ return nnpc;
+}
+
+void RegFile::setNextNPC(Addr val)
+{
+ nnpc = val;
+}
+
+void RegFile::clear()
+{
+ intRegFile.clear();
+ floatRegFile.clear();
+}
+
+MiscReg RegFile::readMiscReg(int miscReg)
+{
+ return miscRegFile.readReg(miscReg);
+}
+
+MiscReg RegFile::readMiscRegWithEffect(int miscReg,
+ Fault &fault, ThreadContext *tc)
+{
+ return miscRegFile.readRegWithEffect(miscReg, fault, tc);
+}
+
+Fault RegFile::setMiscReg(int miscReg, const MiscReg &val)
+{
+ return miscRegFile.setReg(miscReg, val);
+}
+
+Fault RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val,
+ ThreadContext * tc)
+{
+ return miscRegFile.setRegWithEffect(miscReg, val, tc);
+}
+
+FloatReg RegFile::readFloatReg(int floatReg, int width)
+{
+ return floatRegFile.readReg(floatReg, width);
+}
+
+FloatReg RegFile::readFloatReg(int floatReg)
+{
+ //Use the "natural" width of a single float
+ return floatRegFile.readReg(floatReg, FloatRegFile::SingleWidth);
+}
+
+FloatRegBits RegFile::readFloatRegBits(int floatReg, int width)
+{
+ return floatRegFile.readRegBits(floatReg, width);
+}
+
+FloatRegBits RegFile::readFloatRegBits(int floatReg)
+{
+ //Use the "natural" width of a single float
+ return floatRegFile.readRegBits(floatReg,
+ FloatRegFile::SingleWidth);
+}
+
+Fault RegFile::setFloatReg(int floatReg, const FloatReg &val, int width)
+{
+ return floatRegFile.setReg(floatReg, val, width);
+}
+
+Fault RegFile::setFloatReg(int floatReg, const FloatReg &val)
+{
+ //Use the "natural" width of a single float
+ return setFloatReg(floatReg, val, FloatRegFile::SingleWidth);
+}
+
+Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
+{
+ return floatRegFile.setRegBits(floatReg, val, width);
+}
+
+Fault RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val)
+{
+ //Use the "natural" width of a single float
+ return floatRegFile.setRegBits(floatReg, val,
+ FloatRegFile::SingleWidth);
+}
+
+IntReg RegFile::readIntReg(int intReg)
+{
+ return intRegFile.readReg(intReg);
+}
+
+Fault RegFile::setIntReg(int intReg, const IntReg &val)
+{
+ return intRegFile.setReg(intReg, val);
+}
+
+void RegFile::serialize(std::ostream &os)
+{
+ intRegFile.serialize(os);
+ floatRegFile.serialize(os);
+ miscRegFile.serialize(os);
+ SERIALIZE_SCALAR(pc);
+ SERIALIZE_SCALAR(npc);
+}
+
+void RegFile::unserialize(Checkpoint *cp, const std::string &section)
+{
+ intRegFile.unserialize(cp, section);
+ floatRegFile.unserialize(cp, section);
+ miscRegFile.unserialize(cp, section);
+ UNSERIALIZE_SCALAR(pc);
+ UNSERIALIZE_SCALAR(npc);
+}
+
+void RegFile::changeContext(RegContextParam param, RegContextVal val)
+{
+ switch(param)
+ {
+ case CONTEXT_CWP:
+ intRegFile.setCWP(val);
+ break;
+ case CONTEXT_GLOBALS:
+ intRegFile.setGlobals(val);
+ break;
+ default:
+ panic("Tried to set illegal context parameter in the SPARC regfile.\n");
+ }
+}
+
+int SparcISA::InterruptLevel(uint64_t softint)
+{
+ if (softint & 0x10000 || softint & 0x1)
+ return 14;
+
+ int level = 14;
+ while (level >= 0 && !(1 << (level + 1) & softint))
+ level--;
+ if (1 << (level + 1) & softint)
+ return level;
+ return 0;
+}
+
+void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
+{
+
+ uint8_t tl = src->readMiscReg(MISCREG_TL);
+
+ // Read all the trap level dependent registers and save them off
+ for(int i = 1; i <= MaxTL; i++)
+ {
+ src->setMiscReg(MISCREG_TL, i);
+ dest->setMiscReg(MISCREG_TL, i);
+
+ dest->setMiscReg(MISCREG_TT, src->readMiscReg(MISCREG_TT));
+ dest->setMiscReg(MISCREG_TPC, src->readMiscReg(MISCREG_TPC));
+ dest->setMiscReg(MISCREG_TNPC, src->readMiscReg(MISCREG_TNPC));
+ dest->setMiscReg(MISCREG_TSTATE, src->readMiscReg(MISCREG_TSTATE));
+ }
+
+ // Save off the traplevel
+ dest->setMiscReg(MISCREG_TL, tl);
+ src->setMiscReg(MISCREG_TL, tl);
+
+
+ // ASRs
+ dest->setMiscReg(MISCREG_Y, src->readMiscReg(MISCREG_Y));
+ dest->setMiscReg(MISCREG_CCR, src->readMiscReg(MISCREG_CCR));
+ dest->setMiscReg(MISCREG_ASI, src->readMiscReg(MISCREG_ASI));
+ dest->setMiscReg(MISCREG_TICK, src->readMiscReg(MISCREG_TICK));
+ dest->setMiscReg(MISCREG_FPRS, src->readMiscReg(MISCREG_FPRS));
+ dest->setMiscReg(MISCREG_SOFTINT, src->readMiscReg(MISCREG_SOFTINT));
+ dest->setMiscReg(MISCREG_TICK_CMPR, src->readMiscReg(MISCREG_TICK_CMPR));
+ dest->setMiscReg(MISCREG_STICK, src->readMiscReg(MISCREG_STICK));
+ dest->setMiscReg(MISCREG_STICK_CMPR, src->readMiscReg(MISCREG_STICK_CMPR));
+
+ // Priv Registers
+ dest->setMiscReg(MISCREG_TICK, src->readMiscReg(MISCREG_TICK));
+ dest->setMiscReg(MISCREG_TBA, src->readMiscReg(MISCREG_TBA));
+ dest->setMiscReg(MISCREG_PSTATE, src->readMiscReg(MISCREG_PSTATE));
+ dest->setMiscReg(MISCREG_PIL, src->readMiscReg(MISCREG_PIL));
+ dest->setMiscReg(MISCREG_CWP, src->readMiscReg(MISCREG_CWP));
+ dest->setMiscReg(MISCREG_CANSAVE, src->readMiscReg(MISCREG_CANSAVE));
+ dest->setMiscReg(MISCREG_CANRESTORE, src->readMiscReg(MISCREG_CANRESTORE));
+ dest->setMiscReg(MISCREG_OTHERWIN, src->readMiscReg(MISCREG_OTHERWIN));
+ dest->setMiscReg(MISCREG_CLEANWIN, src->readMiscReg(MISCREG_CLEANWIN));
+ dest->setMiscReg(MISCREG_WSTATE, src->readMiscReg(MISCREG_WSTATE));
+ dest->setMiscReg(MISCREG_GL, src->readMiscReg(MISCREG_GL));
+
+ // Hyperprivilged registers
+ dest->setMiscReg(MISCREG_HPSTATE, src->readMiscReg(MISCREG_HPSTATE));
+ dest->setMiscReg(MISCREG_HINTP, src->readMiscReg(MISCREG_HINTP));
+ dest->setMiscReg(MISCREG_HTBA, src->readMiscReg(MISCREG_HTBA));
+ dest->setMiscReg(MISCREG_STRAND_STS_REG,
+ src->readMiscReg(MISCREG_STRAND_STS_REG));
+ dest->setMiscReg(MISCREG_HSTICK_CMPR,
+ src->readMiscReg(MISCREG_HSTICK_CMPR));
+
+ // FSR
+ dest->setMiscReg(MISCREG_FSR, src->readMiscReg(MISCREG_FSR));
+}
+
+void SparcISA::copyRegs(ThreadContext *src, ThreadContext *dest)
+{
+ // First loop through the integer registers.
+ for (int i = 0; i < TheISA::NumIntRegs; ++i) {
+ dest->setIntReg(i, src->readIntReg(i));
+ }
+
+ // Then loop through the floating point registers.
+ for (int i = 0; i < TheISA::NumFloatRegs; ++i) {
+ dest->setFloatRegBits(i, src->readFloatRegBits(i));
+ }
+
+ // Copy misc. registers
+ copyMiscRegs(src, dest);
+
+ // Lastly copy PC/NPC
+ dest->setPC(src->readPC());
+ dest->setNextPC(src->readNextPC());
+ dest->setNextNPC(src->readNextNPC());
+}
diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh
index cbeb3c7b9..500fbbba4 100644
--- a/src/arch/sparc/regfile.hh
+++ b/src/arch/sparc/regfile.hh
@@ -32,833 +32,84 @@
#ifndef __ARCH_SPARC_REGFILE_HH__
#define __ARCH_SPARC_REGFILE_HH__
-#include "arch/sparc/exceptions.hh"
#include "arch/sparc/faults.hh"
-#include "base/trace.hh"
-#include "sim/byteswap.hh"
-#include "cpu/cpuevent.hh"
+#include "arch/sparc/floatregfile.hh"
+#include "arch/sparc/intregfile.hh"
+#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/miscregfile.hh"
+#include "arch/sparc/types.hh"
#include "sim/host.hh"
+#include <string>
+
class Checkpoint;
namespace SparcISA
{
-
- typedef uint8_t RegIndex;
-
- // MAXTL - maximum trap level
- const int MaxPTL = 2;
- const int MaxTL = 6;
- const int MaxGL = 3;
- const int MaxPGL = 2;
-
- // NWINDOWS - number of register windows, can be 3 to 32
- const int NWindows = 32;
-
-
- const int AsrStart = 0;
- const int PrStart = 32;
- const int HprStart = 64;
- const int MiscStart = 96;
-
- const uint64_t Bit64 = (1ULL << 63);
-
- class IntRegFile
+ class RegFile
{
protected:
- static const int FrameOffsetBits = 3;
- static const int FrameNumBits = 2;
-
- static const int RegsPerFrame = 1 << FrameOffsetBits;
- static const int FrameNumMask =
- (FrameNumBits == sizeof(int)) ?
- (unsigned int)(-1) :
- (1 << FrameNumBits) - 1;
- static const int FrameOffsetMask =
- (FrameOffsetBits == sizeof(int)) ?
- (unsigned int)(-1) :
- (1 << FrameOffsetBits) - 1;
-
- IntReg regGlobals[MaxGL][RegsPerFrame];
- IntReg regSegments[2 * NWindows][RegsPerFrame];
-
- enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames};
-
- IntReg * regView[NumFrames];
-
- static const int RegGlobalOffset = 0;
- static const int FrameOffset = MaxGL * RegsPerFrame;
- int offset[NumFrames];
+ Addr pc; // Program Counter
+ Addr npc; // Next Program Counter
+ Addr nnpc;
public:
+ Addr readPC();
+ void setPC(Addr val);
- int flattenIndex(int reg)
- {
- int flatIndex = offset[reg >> FrameOffsetBits]
- | (reg & FrameOffsetMask);
- DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex);
- return flatIndex;
- }
-
- void clear()
- {
- int x;
- for (x = 0; x < MaxGL; x++)
- memset(regGlobals[x], 0, sizeof(regGlobals[x]));
- for(int x = 0; x < 2 * NWindows; x++)
- bzero(regSegments[x], sizeof(regSegments[x]));
- }
-
- IntRegFile()
- {
- offset[Globals] = 0;
- regView[Globals] = regGlobals[0];
- setCWP(0);
- clear();
- }
-
- IntReg readReg(int intReg)
- {
- IntReg val =
- regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask];
- DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val);
- return val;
- }
-
- Fault setReg(int intReg, const IntReg &val)
- {
- if(intReg)
- DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val);
- regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val;
- return NoFault;
- }
-
- //This doesn't effect the actual CWP register.
- //It's purpose is to adjust the view of the register file
- //to what it would be if CWP = cwp.
- void setCWP(int cwp)
- {
- int index = ((NWindows - cwp) % NWindows) * 2;
- offset[Outputs] = FrameOffset + (index * RegsPerFrame);
- offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame);
- offset[Inputs] = FrameOffset +
- (((index+2) % (NWindows * 2)) * RegsPerFrame);
- regView[Outputs] = regSegments[index];
- regView[Locals] = regSegments[index+1];
- regView[Inputs] = regSegments[(index+2) % (NWindows * 2)];
-
- DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp);
- }
-
- void setGlobals(int gl)
- {
-
- DPRINTF(Sparc, "Now using %d globals", gl);
-
- regView[Globals] = regGlobals[gl];
- offset[Globals] = RegGlobalOffset + gl * RegsPerFrame;
- }
-
- void serialize(std::ostream &os);
-
- void unserialize(Checkpoint *cp, const std::string &section);
- };
-
- typedef float float32_t;
- typedef double float64_t;
- //FIXME long double refers to a 10 byte float, rather than a
- //16 byte float as required. This data type may have to be emulated.
- typedef double float128_t;
+ Addr readNextPC();
+ void setNextPC(Addr val);
- class FloatRegFile
- {
- public:
- static const int SingleWidth = 32;
- static const int DoubleWidth = 64;
- static const int QuadWidth = 128;
+ Addr readNextNPC();
+ void setNextNPC(Addr val);
protected:
-
- //Since the floating point registers overlap each other,
- //A generic storage space is used. The float to be returned is
- //pulled from the appropriate section of this region.
- char regSpace[SingleWidth / 8 * NumFloatRegs];
+ IntRegFile intRegFile; // integer register file
+ FloatRegFile floatRegFile; // floating point register file
+ MiscRegFile miscRegFile; // control register file
public:
- void clear()
- {
- bzero(regSpace, sizeof(regSpace));
- }
-
- FloatReg readReg(int floatReg, int width)
- {
- //In each of these cases, we have to copy the value into a temporary
- //variable. This is because we may otherwise try to access an
- //unaligned portion of memory.
- switch(width)
- {
- case SingleWidth:
- float32_t result32;
- memcpy(&result32, regSpace + 4 * floatReg, width);
- return htog(result32);
- case DoubleWidth:
- float64_t result64;
- memcpy(&result64, regSpace + 4 * floatReg, width);
- return htog(result64);
- case QuadWidth:
- float128_t result128;
- memcpy(&result128, regSpace + 4 * floatReg, width);
- return htog(result128);
- default:
- panic("Attempted to read a %d bit floating point register!", width);
- }
- }
-
- FloatRegBits readRegBits(int floatReg, int width)
- {
- //In each of these cases, we have to copy the value into a temporary
- //variable. This is because we may otherwise try to access an
- //unaligned portion of memory.
- switch(width)
- {
- case SingleWidth:
- uint32_t result32;
- memcpy(&result32, regSpace + 4 * floatReg, width);
- return htog(result32);
- case DoubleWidth:
- uint64_t result64;
- memcpy(&result64, regSpace + 4 * floatReg, width);
- return htog(result64);
- case QuadWidth:
- uint64_t result128;
- memcpy(&result128, regSpace + 4 * floatReg, width);
- return htog(result128);
- default:
- panic("Attempted to read a %d bit floating point register!", width);
- }
- }
-
- Fault setReg(int floatReg, const FloatReg &val, int width)
- {
- //In each of these cases, we have to copy the value into a temporary
- //variable. This is because we may otherwise try to access an
- //unaligned portion of memory.
-
- uint32_t result32;
- uint64_t result64;
- switch(width)
- {
- case SingleWidth:
- result32 = gtoh((uint32_t)val);
- memcpy(regSpace + 4 * floatReg, &result32, width);
- break;
- case DoubleWidth:
- result64 = gtoh((uint64_t)val);
- memcpy(regSpace + 4 * floatReg, &result64, width);
- break;
- case QuadWidth:
- panic("Quad width FP not implemented.");
- break;
- default:
- panic("Attempted to read a %d bit floating point register!", width);
- }
- return NoFault;
- }
-
- Fault setRegBits(int floatReg, const FloatRegBits &val, int width)
- {
- //In each of these cases, we have to copy the value into a temporary
- //variable. This is because we may otherwise try to access an
- //unaligned portion of memory.
- uint32_t result32;
- uint64_t result64;
- switch(width)
- {
- case SingleWidth:
- result32 = gtoh((uint32_t)val);
- memcpy(regSpace + 4 * floatReg, &result32, width);
- break;
- case DoubleWidth:
- result64 = gtoh((uint64_t)val);
- memcpy(regSpace + 4 * floatReg, &result64, width);
- break;
- case QuadWidth:
- panic("Quad width FP not implemented.");
- break;
- default:
- panic("Attempted to read a %d bit floating point register!", width);
- }
- return NoFault;
- }
+ void clear();
- void serialize(std::ostream &os);
+ int FlattenIntIndex(int reg);
- void unserialize(Checkpoint *cp, const std::string &section);
- };
+ MiscReg readMiscReg(int miscReg);
- enum MiscRegIndex
- {
- /** Ancillary State Registers */
- MISCREG_Y = AsrStart + 0,
- MISCREG_CCR = AsrStart + 2,
- MISCREG_ASI = AsrStart + 3,
- MISCREG_TICK = AsrStart + 4,
- MISCREG_PC = AsrStart + 5,
- MISCREG_FPRS = AsrStart + 6,
- MISCREG_PCR = AsrStart + 16,
- MISCREG_PIC = AsrStart + 17,
- MISCREG_GSR = AsrStart + 19,
- MISCREG_SOFTINT_SET = AsrStart + 20,
- MISCREG_SOFTINT_CLR = AsrStart + 21,
- MISCREG_SOFTINT = AsrStart + 22,
- MISCREG_TICK_CMPR = AsrStart + 23,
- MISCREG_STICK = AsrStart + 24,
- MISCREG_STICK_CMPR = AsrStart + 25,
-
- /** Privilged Registers */
- MISCREG_TPC = PrStart + 0,
- MISCREG_TNPC = PrStart + 1,
- MISCREG_TSTATE = PrStart + 2,
- MISCREG_TT = PrStart + 3,
- MISCREG_PRIVTICK = PrStart + 4,
- MISCREG_TBA = PrStart + 5,
- MISCREG_PSTATE = PrStart + 6,
- MISCREG_TL = PrStart + 7,
- MISCREG_PIL = PrStart + 8,
- MISCREG_CWP = PrStart + 9,
- MISCREG_CANSAVE = PrStart + 10,
- MISCREG_CANRESTORE = PrStart + 11,
- MISCREG_CLEANWIN = PrStart + 12,
- MISCREG_OTHERWIN = PrStart + 13,
- MISCREG_WSTATE = PrStart + 14,
- MISCREG_GL = PrStart + 16,
-
- /** Hyper privileged registers */
- MISCREG_HPSTATE = HprStart + 0,
- MISCREG_HTSTATE = HprStart + 1,
- MISCREG_HINTP = HprStart + 3,
- MISCREG_HTBA = HprStart + 5,
- MISCREG_HVER = HprStart + 6,
- MISCREG_STRAND_STS_REG = HprStart + 16,
- MISCREG_HSTICK_CMPR = HprStart + 31,
-
- /** Floating Point Status Register */
- MISCREG_FSR = MiscStart + 0
+ MiscReg readMiscRegWithEffect(int miscReg,
+ Fault &fault, ThreadContext *tc);
- };
+ Fault setMiscReg(int miscReg, const MiscReg &val);
- // The control registers, broken out into fields
- class MiscRegFile
- {
- private:
-
- /* ASR Registers */
- union {
- uint64_t y; // Y (used in obsolete multiplication)
- struct {
- uint64_t value:32; // The actual value stored in y
- uint64_t :32; // reserved bits
- } yFields;
- };
- union {
- uint8_t ccr; // Condition Code Register
- struct {
- union {
- uint8_t icc:4; // 32-bit condition codes
- struct {
- uint8_t c:1; // Carry
- uint8_t v:1; // Overflow
- uint8_t z:1; // Zero
- uint8_t n:1; // Negative
- } iccFields;
- };
- union {
- uint8_t xcc:4; // 64-bit condition codes
- struct {
- uint8_t c:1; // Carry
- uint8_t v:1; // Overflow
- uint8_t z:1; // Zero
- uint8_t n:1; // Negative
- } xccFields;
- };
- } ccrFields;
- };
- uint8_t asi; // Address Space Identifier
- union {
- uint64_t tick; // Hardware clock-tick counter
- struct {
- int64_t counter:63; // Clock-tick count
- uint64_t npt:1; // Non-priveleged trap
- } tickFields;
- };
- union {
- uint8_t fprs; // Floating-Point Register State
- struct {
- uint8_t dl:1; // Dirty lower
- uint8_t du:1; // Dirty upper
- uint8_t fef:1; // FPRS enable floating-Point
- } fprsFields;
- };
- union {
- uint64_t softint;
- struct {
- uint64_t tm:1;
- uint64_t int_level:14;
- uint64_t sm:1;
- } softintFields;
- };
- union {
- uint64_t tick_cmpr; // Hardware tick compare registers
- struct {
- uint64_t tick_cmpr:63; // Clock-tick count
- uint64_t int_dis:1; // Non-priveleged trap
- } tick_cmprFields;
- };
- union {
- uint64_t stick; // Hardware clock-tick counter
- struct {
- int64_t :63; // Not used, storage in SparcSystem
- uint64_t npt:1; // Non-priveleged trap
- } stickFields;
- };
- union {
- uint64_t stick_cmpr; // Hardware tick compare registers
- struct {
- uint64_t tick_cmpr:63; // Clock-tick count
- uint64_t int_dis:1; // Non-priveleged trap
- } stick_cmprFields;
- };
-
-
- /* Privileged Registers */
- uint64_t tpc[MaxTL]; // Trap Program Counter (value from
- // previous trap level)
- uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from
- // previous trap level)
- union {
- uint64_t tstate[MaxTL]; // Trap State
- struct {
- //Values are from previous trap level
- uint64_t cwp:5; // Current Window Pointer
- uint64_t :3; // Reserved bits
- uint64_t pstate:13; // Process State
- uint64_t :3; // Reserved bits
- uint64_t asi:8; // Address Space Identifier
- uint64_t ccr:8; // Condition Code Register
- uint64_t gl:8; // Global level
- } tstateFields[MaxTL];
- };
- uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured
- // on the previous level)
- uint64_t tba; // Trap Base Address
-
- union {
- uint16_t pstate; // Process State Register
- struct {
- uint16_t :1; // reserved
- uint16_t ie:1; // Interrupt enable
- uint16_t priv:1; // Privelege mode
- uint16_t am:1; // Address mask
- uint16_t pef:1; // PSTATE enable floating-point
- uint16_t :1; // reserved2
- uint16_t mm:2; // Memory Model
- uint16_t tle:1; // Trap little-endian
- uint16_t cle:1; // Current little-endian
- } pstateFields;
- };
- uint8_t tl; // Trap Level
- uint8_t pil; // Process Interrupt Register
- uint8_t cwp; // Current Window Pointer
- uint8_t cansave; // Savable windows
- uint8_t canrestore; // Restorable windows
- uint8_t cleanwin; // Clean windows
- uint8_t otherwin; // Other windows
- union {
- uint8_t wstate; // Window State
- struct {
- uint8_t normal:3; // Bits TT<4:2> are set to on a normal
- // register window trap
- uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin"
- // register window trap
- } wstateFields;
- };
- uint8_t gl; // Global level register
-
-
- /** Hyperprivileged Registers */
- union {
- uint64_t hpstate; // Hyperprivileged State Register
- struct {
- uint8_t tlz: 1;
- uint8_t :1;
- uint8_t hpriv:1;
- uint8_t :2;
- uint8_t red:1;
- uint8_t :4;
- uint8_t ibe:1;
- uint8_t id:1;
- } hpstateFields;
- };
-
- uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register
- uint64_t hintp;
- uint64_t htba; // Hyperprivileged Trap Base Address register
- union {
- uint64_t hstick_cmpr; // Hardware tick compare registers
- struct {
- uint64_t tick_cmpr:63; // Clock-tick count
- uint64_t int_dis:1; // Non-priveleged trap
- } hstick_cmprFields;
- };
-
- uint64_t strandStatusReg; // Per strand status register
-
-
- /** Floating point misc registers. */
- union {
- uint64_t fsr; // Floating-Point State Register
- struct {
- union {
- uint64_t cexc:5; // Current excpetion
- struct {
- uint64_t nxc:1; // Inexact
- uint64_t dzc:1; // Divide by zero
- uint64_t ufc:1; // Underflow
- uint64_t ofc:1; // Overflow
- uint64_t nvc:1; // Invalid operand
- } cexcFields;
- };
- union {
- uint64_t aexc:5; // Accrued exception
- struct {
- uint64_t nxc:1; // Inexact
- uint64_t dzc:1; // Divide by zero
- uint64_t ufc:1; // Underflow
- uint64_t ofc:1; // Overflow
- uint64_t nvc:1; // Invalid operand
- } aexcFields;
- };
- uint64_t fcc0:2; // Floating-Point condtion codes
- uint64_t :1; // Reserved bits
- uint64_t qne:1; // Deferred trap queue not empty
- // with no queue, it should read 0
- uint64_t ftt:3; // Floating-Point trap type
- uint64_t ver:3; // Version (of the FPU)
- uint64_t :2; // Reserved bits
- uint64_t ns:1; // Nonstandard floating point
- union {
- uint64_t tem:5; // Trap Enable Mask
- struct {
- uint64_t nxm:1; // Inexact
- uint64_t dzm:1; // Divide by zero
- uint64_t ufm:1; // Underflow
- uint64_t ofm:1; // Overflow
- uint64_t nvm:1; // Invalid operand
- } temFields;
- };
- uint64_t :2; // Reserved bits
- uint64_t rd:2; // Rounding direction
- uint64_t fcc1:2; // Floating-Point condition codes
- uint64_t fcc2:2; // Floating-Point condition codes
- uint64_t fcc3:2; // Floating-Point condition codes
- uint64_t :26; // Reserved bits
- } fsrFields;
- };
-
- // These need to check the int_dis field and if 0 then
- // set appropriate bit in softint and checkinterrutps on the cpu
-#if FULL_SYSTEM
- /** Process a tick compare event and generate an interrupt on the cpu if
- * appropriate. */
- void processTickCompare(ThreadContext *tc);
- void processSTickCompare(ThreadContext *tc);
- void processHSTickCompare(ThreadContext *tc);
-
- typedef CpuEventWrapper<MiscRegFile,
- &MiscRegFile::processTickCompare> TickCompareEvent;
- TickCompareEvent *tickCompare;
-
- typedef CpuEventWrapper<MiscRegFile,
- &MiscRegFile::processSTickCompare> STickCompareEvent;
- STickCompareEvent *sTickCompare;
-
- typedef CpuEventWrapper<MiscRegFile,
- &MiscRegFile::processHSTickCompare> HSTickCompareEvent;
- HSTickCompareEvent *hSTickCompare;
-
- /** Fullsystem only register version of ReadRegWithEffect() */
- MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc);
- /** Fullsystem only register version of SetRegWithEffect() */
- Fault setFSRegWithEffect(int miscReg, const MiscReg &val,
+ Fault setMiscRegWithEffect(int miscReg, const MiscReg &val,
ThreadContext * tc);
-#endif
- public:
- void reset()
- {
- pstateFields.pef = 0; //No FPU
- //pstateFields.pef = 1; //FPU
-#if FULL_SYSTEM
- //For SPARC, when a system is first started, there is a power
- //on reset Trap which sets the processor into the following state.
- //Bits that aren't set aren't defined on startup.
- tl = MaxTL;
- gl = MaxGL;
-
- tickFields.counter = 0; //The TICK register is unreadable bya
- tickFields.npt = 1; //The TICK register is unreadable by by !priv
-
- softint = 0; // Clear all the soft interrupt bits
- tick_cmprFields.int_dis = 1; // disable timer compare interrupts
- tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
- stickFields.npt = 1; //The TICK register is unreadable by by !priv
- stick_cmprFields.int_dis = 1; // disable timer compare interrupts
- stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
-
-
- tt[tl] = power_on_reset;
- pstate = 0; // fields 0 but pef
- pstateFields.pef = 1;
-
- hpstate = 0;
- hpstateFields.red = 1;
- hpstateFields.hpriv = 1;
- hpstateFields.tlz = 0; // this is a guess
-
- hintp = 0; // no interrupts pending
- hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
- hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
-
-#else
-/* //This sets up the initial state of the processor for usermode processes
- pstateFields.priv = 0; //Process runs in user mode
- pstateFields.ie = 1; //Interrupts are enabled
- fsrFields.rd = 0; //Round to nearest
- fsrFields.tem = 0; //Floating point traps not enabled
- fsrFields.ns = 0; //Non standard mode off
- fsrFields.qne = 0; //Floating point queue is empty
- fsrFields.aexc = 0; //No accrued exceptions
- fsrFields.cexc = 0; //No current exceptions
-
- //Register window management registers
- otherwin = 0; //No windows contain info from other programs
- canrestore = 0; //There are no windows to pop
- cansave = MaxTL - 2; //All windows are available to save into
- cleanwin = MaxTL;*/
-#endif
- }
-
- MiscRegFile()
- {
- reset();
- }
-
- /** read a value out of an either an SE or FS IPR. No checking is done
- * about SE vs. FS as this is mostly used to copy the regfile. Thus more
- * register are copied that are necessary for FS. However this prevents
- * a bunch of ifdefs and is rarely called so is not performance
- * criticial. */
- MiscReg readReg(int miscReg);
-
- /** Read a value from an IPR. Only the SE iprs are here and the rest
- * are are readFSRegWithEffect (which is called by readRegWithEffect()).
- * Checking is done for permission based on state bits in the miscreg
- * file. */
- MiscReg readRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc);
-
- /** write a value into an either an SE or FS IPR. No checking is done
- * about SE vs. FS as this is mostly used to copy the regfile. Thus more
- * register are copied that are necessary for FS. However this prevents
- * a bunch of ifdefs and is rarely called so is not performance
- * criticial.*/
- Fault setReg(int miscReg, const MiscReg &val);
-
- /** Write a value into an IPR. Only the SE iprs are here and the rest
- * are are setFSRegWithEffect (which is called by setRegWithEffect()).
- * Checking is done for permission based on state bits in the miscreg
- * file. */
- Fault setRegWithEffect(int miscReg,
- const MiscReg &val, ThreadContext * tc);
-
- void serialize(std::ostream & os);
-
- void unserialize(Checkpoint * cp, const std::string & section);
-
- void copyMiscRegs(ThreadContext * tc);
-
- bool isHyperPriv() { return hpstateFields.hpriv; }
- bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; }
- bool isNonPriv() { return !isPriv(); }
- };
+ FloatReg readFloatReg(int floatReg, int width);
- typedef union
- {
- IntReg intreg;
- FloatReg fpreg;
- MiscReg ctrlreg;
- } AnyReg;
+ FloatReg readFloatReg(int floatReg);
- class RegFile
- {
- protected:
- Addr pc; // Program Counter
- Addr npc; // Next Program Counter
- Addr nnpc;
-
- public:
- Addr readPC()
- {
- return pc;
- }
-
- void setPC(Addr val)
- {
- pc = val;
- }
-
- Addr readNextPC()
- {
- return npc;
- }
-
- void setNextPC(Addr val)
- {
- npc = val;
- }
-
- Addr readNextNPC()
- {
- return nnpc;
- }
-
- void setNextNPC(Addr val)
- {
- nnpc = val;
- }
-
- protected:
- IntRegFile intRegFile; // integer register file
- FloatRegFile floatRegFile; // floating point register file
- MiscRegFile miscRegFile; // control register file
+ FloatRegBits readFloatRegBits(int floatReg, int width);
- public:
+ FloatRegBits readFloatRegBits(int floatReg);
- void clear()
- {
- intRegFile.clear();
- floatRegFile.clear();
- }
+ Fault setFloatReg(int floatReg, const FloatReg &val, int width);
- int FlattenIntIndex(int reg)
- {
- return intRegFile.flattenIndex(reg);
- }
+ Fault setFloatReg(int floatReg, const FloatReg &val);
- MiscReg readMiscReg(int miscReg)
- {
- return miscRegFile.readReg(miscReg);
- }
+ Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width);
- MiscReg readMiscRegWithEffect(int miscReg,
- Fault &fault, ThreadContext *tc)
- {
- return miscRegFile.readRegWithEffect(miscReg, fault, tc);
- }
+ Fault setFloatRegBits(int floatReg, const FloatRegBits &val);
- Fault setMiscReg(int miscReg, const MiscReg &val)
- {
- return miscRegFile.setReg(miscReg, val);
- }
+ IntReg readIntReg(int intReg);
- Fault setMiscRegWithEffect(int miscReg, const MiscReg &val,
- ThreadContext * tc)
- {
- return miscRegFile.setRegWithEffect(miscReg, val, tc);
- }
-
- FloatReg readFloatReg(int floatReg, int width)
- {
- return floatRegFile.readReg(floatReg, width);
- }
-
- FloatReg readFloatReg(int floatReg)
- {
- //Use the "natural" width of a single float
- return floatRegFile.readReg(floatReg, FloatRegFile::SingleWidth);
- }
-
- FloatRegBits readFloatRegBits(int floatReg, int width)
- {
- return floatRegFile.readRegBits(floatReg, width);
- }
-
- FloatRegBits readFloatRegBits(int floatReg)
- {
- //Use the "natural" width of a single float
- return floatRegFile.readRegBits(floatReg,
- FloatRegFile::SingleWidth);
- }
-
- Fault setFloatReg(int floatReg, const FloatReg &val, int width)
- {
- return floatRegFile.setReg(floatReg, val, width);
- }
-
- Fault setFloatReg(int floatReg, const FloatReg &val)
- {
- //Use the "natural" width of a single float
- return setFloatReg(floatReg, val, FloatRegFile::SingleWidth);
- }
-
- Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
- {
- return floatRegFile.setRegBits(floatReg, val, width);
- }
-
- Fault setFloatRegBits(int floatReg, const FloatRegBits &val)
- {
- //Use the "natural" width of a single float
- return floatRegFile.setRegBits(floatReg, val,
- FloatRegFile::SingleWidth);
- }
-
- IntReg readIntReg(int intReg)
- {
- return intRegFile.readReg(intReg);
- }
-
- Fault setIntReg(int intReg, const IntReg &val)
- {
- return intRegFile.setReg(intReg, val);
- }
+ Fault setIntReg(int intReg, const IntReg &val);
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
public:
- enum ContextParam
- {
- CONTEXT_CWP,
- CONTEXT_GLOBALS
- };
- typedef int ContextVal;
-
- void changeContext(ContextParam param, ContextVal val)
- {
- switch(param)
- {
- case CONTEXT_CWP:
- intRegFile.setCWP(val);
- break;
- case CONTEXT_GLOBALS:
- intRegFile.setGlobals(val);
- break;
- default:
- panic("Tried to set illegal context parameter in the SPARC regfile.\n");
- }
- }
+ void changeContext(RegContextParam param, RegContextVal val);
};
void copyRegs(ThreadContext *src, ThreadContext *dest);
diff --git a/src/arch/sparc/solaris/solaris.cc b/src/arch/sparc/solaris/solaris.cc
index c588925b0..c53caa72a 100644
--- a/src/arch/sparc/solaris/solaris.cc
+++ b/src/arch/sparc/solaris/solaris.cc
@@ -30,6 +30,8 @@
#include "arch/sparc/solaris/solaris.hh"
+#include <fcntl.h>
+
// open(2) flags translation table
OpenFlagTransTable SparcSolaris::openFlagTable[] = {
#ifdef _MSC_VER
diff --git a/src/arch/sparc/stacktrace.hh b/src/arch/sparc/stacktrace.hh
index d12aee211..54d3d17be 100644
--- a/src/arch/sparc/stacktrace.hh
+++ b/src/arch/sparc/stacktrace.hh
@@ -28,8 +28,8 @@
* Authors: Nathan Binkert
*/
-#ifndef __ARCH_ALPHA_STACKTRACE_HH__
-#define __ARCH_ALPHA_STACKTRACE_HH__
+#ifndef __ARCH_SPARC_STACKTRACE_HH__
+#define __ARCH_SPARC_STACKTRACE_HH__
#include "base/trace.hh"
#include "cpu/static_inst.hh"
@@ -118,4 +118,4 @@ StackTrace::trace(ThreadContext *tc, StaticInstPtr inst)
return true;
}
-#endif // __ARCH_ALPHA_STACKTRACE_HH__
+#endif // __ARCH_SPARC_STACKTRACE_HH__
diff --git a/src/arch/sparc/syscallreturn.hh b/src/arch/sparc/syscallreturn.hh
new file mode 100644
index 000000000..d850f4b65
--- /dev/null
+++ b/src/arch/sparc/syscallreturn.hh
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ */
+
+#ifndef __ARCH_SPARC_SYSCALLRETURN_HH__
+#define __ARCH_SPARC_SYSCALLRETURN_HH__
+
+#include <inttypes.h>
+
+#include "arch/sparc/regfile.hh"
+
+class SyscallReturn
+{
+ public:
+ template <class T>
+ SyscallReturn(T v, bool s)
+ {
+ retval = (uint64_t)v;
+ success = s;
+ }
+
+ template <class T>
+ SyscallReturn(T v)
+ {
+ success = (v >= 0);
+ retval = (uint64_t)v;
+ }
+
+ ~SyscallReturn() {}
+
+ SyscallReturn& operator=(const SyscallReturn& s)
+ {
+ retval = s.retval;
+ success = s.success;
+ return *this;
+ }
+
+ bool successful() { return success; }
+ uint64_t value() { return retval; }
+
+ private:
+ uint64_t retval;
+ bool success;
+};
+
+namespace SparcISA
+{
+ static inline void setSyscallReturn(SyscallReturn return_value,
+ RegFile *regs)
+ {
+ // check for error condition. SPARC syscall convention is to
+ // indicate success/failure in reg the carry bit of the ccr
+ // and put the return value itself in the standard return value reg ().
+ if (return_value.successful()) {
+ // no error, clear XCC.C
+ regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) & 0xEF);
+ regs->setIntReg(ReturnValueReg, return_value.value());
+ } else {
+ // got an error, set XCC.C
+ regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) | 0x10);
+ regs->setIntReg(ReturnValueReg, return_value.value());
+ }
+ }
+};
+
+#endif
diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc
index e197e7918..63cbbe057 100644
--- a/src/arch/sparc/system.cc
+++ b/src/arch/sparc/system.cc
@@ -141,6 +141,7 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
Param<std::string> kernel;
Param<std::string> reset_bin;
@@ -161,6 +162,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem)
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
INIT_PARAM(physmem, "phsyical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings),
INIT_PARAM(kernel, "file that contains the kernel code"),
INIT_PARAM(reset_bin, "file that contains the reset code"),
INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"),
@@ -183,6 +186,7 @@ CREATE_SIM_OBJECT(SparcSystem)
p->name = getInstanceName();
p->boot_cpu_frequency = boot_cpu_frequency;
p->physmem = physmem;
+ p->mem_mode = mem_mode;
p->kernel_path = kernel;
p->reset_bin = reset_bin;
p->hypervisor_bin = hypervisor_bin;
diff --git a/src/arch/sparc/types.hh b/src/arch/sparc/types.hh
new file mode 100644
index 000000000..88fb24153
--- /dev/null
+++ b/src/arch/sparc/types.hh
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2003-2005 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: Gabe Black
+ */
+
+#ifndef __ARCH_SPARC_TYPES_HH__
+#define __ARCH_SPARC_TYPES_HH__
+
+#include <inttypes.h>
+
+namespace SparcISA
+{
+ typedef uint32_t MachInst;
+ typedef uint64_t ExtMachInst;
+
+ typedef uint64_t IntReg;
+ typedef uint64_t MiscReg;
+ typedef double FloatReg;
+ typedef uint64_t FloatRegBits;
+ typedef union
+ {
+ IntReg intReg;
+ FloatReg fpreg;
+ MiscReg ctrlreg;
+ } AnyReg;
+
+ enum RegContextParam
+ {
+ CONTEXT_CWP,
+ CONTEXT_GLOBALS
+ };
+
+ typedef int RegContextVal;
+
+ typedef uint8_t RegIndex;
+}
+
+#endif
diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc
index b89d48663..6493ddfd5 100644
--- a/src/arch/sparc/ua2005.cc
+++ b/src/arch/sparc/ua2005.cc
@@ -37,7 +37,7 @@ SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
int64_t time;
SparcSystem *sys;
switch (miscReg) {
- /** Full system only ASRs */
+ /* Full system only ASRs */
case MISCREG_SOFTINT:
if (isNonPriv())
return new PrivilegedOpcode;
@@ -94,7 +94,7 @@ SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
sTickCompare.schedule(time * Clock::Int::ns);
return NoFault;
- /** Fullsystem only Priv registers. */
+ /* Fullsystem only Priv registers. */
case MISCREG_PIL:
if (FULL_SYSTEM) {
setReg(miscReg, val);
@@ -104,7 +104,7 @@ SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
} else
panic("PIL not implemented for syscall emulation\n");
- /** Hyper privileged registers */
+ /* Hyper privileged registers */
case MISCREG_HPSTATE:
case MISCREG_HINTP:
setReg(miscReg, val);
@@ -147,7 +147,7 @@ MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext * tc)
{
switch (miscReg) {
- /** Privileged registers. */
+ /* Privileged registers. */
case MISCREG_SOFTINT:
if (isNonPriv()) {
fault = new PrivilegedOpcode;
@@ -177,7 +177,7 @@ MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ThreadContext * tc)
return readReg(miscReg);
- /** Hyper privileged registers */
+ /* Hyper privileged registers */
case MISCREG_HPSTATE:
case MISCREG_HINTP:
return readReg(miscReg);
diff --git a/src/base/chunk_generator.hh b/src/base/chunk_generator.hh
index e9d5355ca..e8238464b 100644
--- a/src/base/chunk_generator.hh
+++ b/src/base/chunk_generator.hh
@@ -72,7 +72,7 @@ class ChunkGenerator
public:
/**
* Constructor.
- * @param startAddr The starting address of the region.
+ * @param _startAddr The starting address of the region.
* @param totalSize The total size of the region.
* @param _chunkSize The size/alignment of chunks into which
* the region should be decomposed.
diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc
index 00d218b76..2ca0d4f4a 100644
--- a/src/base/loader/elf_object.cc
+++ b/src/base/loader/elf_object.cc
@@ -153,8 +153,38 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
} // while sections
}
+ ElfObject * result = new ElfObject(fname, fd, len, data, arch, opSys);
+
+ //The number of headers in the file
+ result->_programHeaderCount = ehdr.e_phnum;
+ //Record the size of each entry
+ result->_programHeaderSize = ehdr.e_phentsize;
+ if(result->_programHeaderCount) //If there is a program header table
+ {
+ //Figure out the virtual address of the header table in the
+ //final memory image. We use the program headers themselves
+ //to translate from a file offset to the address in the image.
+ GElf_Phdr phdr;
+ uint64_t e_phoff = ehdr.e_phoff;
+ result->_programHeaderTable = 0;
+ for(int hdrnum = 0; hdrnum < result->_programHeaderCount; hdrnum++)
+ {
+ gelf_getphdr(elf, hdrnum, &phdr);
+ //Check if we've found the segment with the headers in it
+ if(phdr.p_offset <= e_phoff &&
+ phdr.p_offset + phdr.p_filesz > e_phoff)
+ {
+ result->_programHeaderTable = phdr.p_vaddr + e_phoff;
+ break;
+ }
+ }
+ }
+ else
+ result->_programHeaderTable = 0;
+
+
elf_end(elf);
- return new ElfObject(fname, fd, len, data, arch, opSys);
+ return result;
}
}
diff --git a/src/base/loader/elf_object.hh b/src/base/loader/elf_object.hh
index 46dbfe37b..9755426b4 100644
--- a/src/base/loader/elf_object.hh
+++ b/src/base/loader/elf_object.hh
@@ -37,6 +37,12 @@ class ElfObject : public ObjectFile
{
protected:
+ //These values are provided to a linux process by the kernel, so we
+ //need to keep them around.
+ Addr _programHeaderTable;
+ uint16_t _programHeaderSize;
+ uint16_t _programHeaderCount;
+
/// Helper functions for loadGlobalSymbols() and loadLocalSymbols().
bool loadSomeSymbols(SymbolTable *symtab, int binding);
@@ -52,6 +58,9 @@ class ElfObject : public ObjectFile
static ObjectFile *tryFile(const std::string &fname, int fd,
size_t len, uint8_t *data);
+ Addr programHeaderTable() {return _programHeaderTable;}
+ uint16_t programHeaderSize() {return _programHeaderSize;}
+ uint16_t programHeaderCount() {return _programHeaderCount;}
};
#endif // __ELF_OBJECT_HH__
diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh
index 55ff0c86f..184c0a996 100644
--- a/src/base/loader/symtab.hh
+++ b/src/base/loader/symtab.hh
@@ -104,11 +104,11 @@ class SymbolTable
/// Find the nearest symbol equal to or less than the supplied
/// address (e.g., the label for the enclosing function).
- /// @param address The address to look up.
- /// @param symbol Return reference for symbol string.
- /// @param sym_address Return reference for symbol address.
- /// @param next_sym_address Address of following symbol (for
- /// determining valid range of symbol).
+ /// @param addr The address to look up.
+ /// @param symbol Return reference for symbol string.
+ /// @param symaddr Return reference for symbol address.
+ /// @param nextaddr Address of following symbol (for
+ /// determining valid range of symbol).
/// @retval True if a symbol was found.
bool
findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr,
@@ -126,7 +126,7 @@ class SymbolTable
}
/// Overload for findNearestSymbol() for callers who don't care
- /// about next_sym_address.
+ /// about nextaddr.
bool
findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr) const
{
diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh
index 90b53e53f..8c3ce7572 100644
--- a/src/base/remote_gdb.hh
+++ b/src/base/remote_gdb.hh
@@ -33,6 +33,7 @@
#include <map>
+#include "arch/types.hh"
#include "base/kgdb.h"
#include "cpu/pc_event.hh"
#include "base/pollevent.hh"
diff --git a/src/cpu/SConscript b/src/cpu/SConscript
index bc4ec7923..2bb9a2399 100644
--- a/src/cpu/SConscript
+++ b/src/cpu/SConscript
@@ -71,7 +71,8 @@ virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) c
# Generate a temporary CPU list, including the CheckerCPU if
# it's enabled. This isn't used for anything else other than StaticInst
# headers.
-temp_cpu_list = env['CPU_MODELS']
+temp_cpu_list = env['CPU_MODELS'][:]
+
if env['USE_CHECKER']:
temp_cpu_list.append('CheckerCPU')
@@ -113,6 +114,9 @@ CheckerSupportedCPUList = ['O3CPU', 'OzoneCPU']
#
#################################################################
+# Keep a list of CPU models that support SMT
+env['SMT_CPU_MODELS'] = []
+
sources = []
need_simple_base = False
@@ -156,6 +160,8 @@ if 'O3CPU' in env['CPU_MODELS']:
''')
if env['USE_CHECKER']:
sources += Split('o3/checker_builder.cc')
+ else:
+ env['SMT_CPU_MODELS'].append('O3CPU') # Checker doesn't support SMT right now
if 'OzoneCPU' in env['CPU_MODELS']:
need_bp_unit = True
diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh
index 9cc61f74c..40611abe6 100644
--- a/src/cpu/base_dyn_inst.hh
+++ b/src/cpu/base_dyn_inst.hh
@@ -215,6 +215,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
*/
Addr nextPC;
+ /** Next non-speculative NPC. Target PC for Mips or Sparc. */
+ Addr nextNPC;
+
/** Predicted next PC. */
Addr predPC;
@@ -275,6 +278,11 @@ class BaseDynInst : public FastAlloc, public RefCounted
*/
Addr readNextPC() { return nextPC; }
+ /** Returns the next NPC. This could be the speculative next NPC if it is
+ * called prior to the actual branch target being calculated.
+ */
+ Addr readNextNPC() { return nextNPC; }
+
/** Set the predicted target of this current instruction. */
void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
@@ -282,11 +290,20 @@ class BaseDynInst : public FastAlloc, public RefCounted
Addr readPredTarg() { return predPC; }
/** Returns whether the instruction was predicted taken or not. */
- bool predTaken() { return predPC != (PC + sizeof(MachInst)); }
+ bool predTaken()
+#if THE_ISA == ALPHA_ISA
+ { return predPC != (PC + sizeof(MachInst)); }
+#else
+ { return predPC != (nextPC + sizeof(MachInst)); }
+#endif
/** Returns whether the instruction mispredicted. */
- bool mispredicted() { return predPC != nextPC; }
-
+ bool mispredicted()
+#if THE_ISA == ALPHA_ISA
+ { return predPC != nextPC; }
+#else
+ { return predPC != nextNPC; }
+#endif
//
// Instruction types. Forward checks to StaticInst object.
//
@@ -308,6 +325,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
bool isCondCtrl() const { return staticInst->isCondCtrl(); }
bool isUncondCtrl() const { return staticInst->isUncondCtrl(); }
+ bool isCondDelaySlot() const { return staticInst->isCondDelaySlot(); }
bool isThreadSync() const { return staticInst->isThreadSync(); }
bool isSerializing() const { return staticInst->isSerializing(); }
bool isSerializeBefore() const
@@ -545,6 +563,12 @@ class BaseDynInst : public FastAlloc, public RefCounted
nextPC = val;
}
+ /** Set the next NPC of this instruction (the target in Mips or Sparc).*/
+ void setNextNPC(uint64_t val)
+ {
+ nextNPC = val;
+ }
+
/** Sets the ASID. */
void setASID(short addr_space_id) { asid = addr_space_id; }
diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh
index 91424faad..f2109e88d 100644
--- a/src/cpu/base_dyn_inst_impl.hh
+++ b/src/cpu/base_dyn_inst_impl.hh
@@ -36,15 +36,12 @@
#include "base/cprintf.hh"
#include "base/trace.hh"
-#include "arch/faults.hh"
+#include "sim/faults.hh"
#include "cpu/exetrace.hh"
#include "mem/request.hh"
#include "cpu/base_dyn_inst.hh"
-using namespace std;
-using namespace TheISA;
-
#define NOHASH
#ifndef NOHASH
@@ -65,7 +62,7 @@ my_hash_t thishash;
#endif
template <class Impl>
-BaseDynInst<Impl>::BaseDynInst(ExtMachInst machInst, Addr inst_PC,
+BaseDynInst<Impl>::BaseDynInst(TheISA::ExtMachInst machInst, Addr inst_PC,
Addr pred_PC, InstSeqNum seq_num,
ImplCPU *cpu)
: staticInst(machInst), traceData(NULL), cpu(cpu)
@@ -73,7 +70,8 @@ BaseDynInst<Impl>::BaseDynInst(ExtMachInst machInst, Addr inst_PC,
seqNum = seq_num;
PC = inst_PC;
- nextPC = PC + sizeof(MachInst);
+ nextPC = PC + sizeof(TheISA::MachInst);
+ nextNPC = nextPC + sizeof(TheISA::MachInst);
predPC = pred_PC;
initVars();
@@ -249,7 +247,7 @@ void
BaseDynInst<Impl>::dump()
{
cprintf("T%d : %#08d `", threadNumber, PC);
- cout << staticInst->disassemble(PC);
+ std::cout << staticInst->disassemble(PC);
cprintf("'\n");
}
diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh
index a508c56ba..6d6ae1e0a 100644
--- a/src/cpu/checker/cpu.hh
+++ b/src/cpu/checker/cpu.hh
@@ -170,7 +170,7 @@ class CheckerCPU : public BaseCPU
virtual Counter totalInstructions() const
{
- return numInst - startNumInst;
+ return 0;
}
// number of simulated loads
diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh
index c035e92ac..8c0186dae 100644
--- a/src/cpu/checker/thread_context.hh
+++ b/src/cpu/checker/thread_context.hh
@@ -31,6 +31,7 @@
#ifndef __CPU_CHECKER_THREAD_CONTEXT_HH__
#define __CPU_CHECKER_THREAD_CONTEXT_HH__
+#include "arch/types.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/simple_thread.hh"
#include "cpu/thread_context.hh"
@@ -295,8 +296,8 @@ class CheckerThreadContext : public ThreadContext
Counter readFuncExeInst() { return actualTC->readFuncExeInst(); }
#endif
- void changeRegFileContext(RegFile::ContextParam param,
- RegFile::ContextVal val)
+ void changeRegFileContext(TheISA::RegContextParam param,
+ TheISA::RegContextVal val)
{
actualTC->changeRegFileContext(param, val);
checkerTC->changeRegFileContext(param, val);
diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc
index 7fdad5113..748f66d37 100644
--- a/src/cpu/exetrace.cc
+++ b/src/cpu/exetrace.cc
@@ -34,6 +34,7 @@
#include <fstream>
#include <iomanip>
+#include "arch/regfile.hh"
#include "base/loader/symtab.hh"
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
@@ -42,7 +43,7 @@
#include "sim/system.hh"
using namespace std;
-
+using namespace TheISA;
////////////////////////////////////////////////////////////////////////
//
@@ -53,7 +54,43 @@ using namespace std;
void
Trace::InstRecord::dump(ostream &outs)
{
- if (flags[INTEL_FORMAT]) {
+ if (flags[PRINT_REG_DELTA])
+ {
+ outs << "PC = 0x" << setbase(16)
+ << setfill('0')
+ << setw(16) << PC << endl;
+ outs << setbase(10)
+ << setfill(' ')
+ << setw(0);
+ /*
+ int numSources = staticInst->numSrcRegs();
+ int numDests = staticInst->numDestRegs();
+ outs << "Sources:";
+ for(int x = 0; x < numSources; x++)
+ {
+ int sourceNum = staticInst->srcRegIdx(x);
+ if(sourceNum < FP_Base_DepTag)
+ outs << " " << getIntRegName(sourceNum);
+ else if(sourceNum < Ctrl_Base_DepTag)
+ outs << " " << getFloatRegName(sourceNum - FP_Base_DepTag);
+ else
+ outs << " " << getMiscRegName(sourceNum - Ctrl_Base_DepTag);
+ }
+ outs << endl;
+ outs << "Destinations:";
+ for(int x = 0; x < numDests; x++)
+ {
+ int destNum = staticInst->destRegIdx(x);
+ if(destNum < FP_Base_DepTag)
+ outs << " " << getIntRegName(destNum);
+ else if(destNum < Ctrl_Base_DepTag)
+ outs << " " << getFloatRegName(destNum - FP_Base_DepTag);
+ else
+ outs << " " << getMiscRegName(destNum - Ctrl_Base_DepTag);
+ }
+ outs << endl;*/
+ }
+ else if (flags[INTEL_FORMAT]) {
#if FULL_SYSTEM
bool is_trace_system = (cpu->system->name() == trace_system);
#else
@@ -196,6 +233,8 @@ Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
"print fetch sequence number", false);
Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
"print correct-path sequence number", false);
+Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta",
+ "print which registers changed to what", false);
Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
"Use symbols for the PC if available", true);
Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
@@ -222,6 +261,7 @@ Trace::InstRecord::setParams()
flags[PRINT_INT_REGS] = exe_trace_print_iregs;
flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq;
flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq;
+ flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta;
flags[PC_SYMBOL] = exe_trace_pc_symbol;
flags[INTEL_FORMAT] = exe_trace_intel_format;
trace_system = exe_trace_system;
diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh
index 95f8b449c..8cc98b777 100644
--- a/src/cpu/exetrace.hh
+++ b/src/cpu/exetrace.hh
@@ -147,6 +147,7 @@ class InstRecord : public Record
PRINT_INT_REGS,
PRINT_FETCH_SEQ,
PRINT_CP_SEQ,
+ PRINT_REG_DELTA,
PC_SYMBOL,
INTEL_FORMAT,
NUM_BITS
diff --git a/src/cpu/o3/2bit_local_pred.hh b/src/cpu/o3/2bit_local_pred.hh
index 0a2a71d3e..954b86b4c 100644
--- a/src/cpu/o3/2bit_local_pred.hh
+++ b/src/cpu/o3/2bit_local_pred.hh
@@ -31,9 +31,8 @@
#ifndef __CPU_O3_2BIT_LOCAL_PRED_HH__
#define __CPU_O3_2BIT_LOCAL_PRED_HH__
-// For Addr type.
-#include "arch/isa_traits.hh"
#include "cpu/o3/sat_counter.hh"
+#include "sim/host.hh"
#include <vector>
diff --git a/src/cpu/o3/SConscript b/src/cpu/o3/SConscript
index e65d41411..afbd4c533 100755
--- a/src/cpu/o3/SConscript
+++ b/src/cpu/o3/SConscript
@@ -52,21 +52,19 @@ if env['TARGET_ISA'] == 'alpha':
alpha/cpu_builder.cc
''')
elif env['TARGET_ISA'] == 'mips':
- sys.exit('O3 CPU does not support MIPS')
- #sources += Split('''
- # mips/dyn_inst.cc
- # mips/cpu.cc
- # mips/thread_context.cc
- # mips/cpu_builder.cc
- # ''')
+ sources += Split('''
+ mips/dyn_inst.cc
+ mips/cpu.cc
+ mips/thread_context.cc
+ mips/cpu_builder.cc
+ ''')
elif env['TARGET_ISA'] == 'sparc':
- sys.exit('O3 CPU does not support MIPS')
- #sources += Split('''
- # sparc/dyn_inst.cc
- # sparc/cpu.cc
- # sparc/thread_context.cc
- # sparc/cpu_builder.cc
- # ''')
+ sources += Split('''
+ sparc/dyn_inst.cc
+ sparc/cpu.cc
+ sparc/thread_context.cc
+ sparc/cpu_builder.cc
+ ''')
else:
sys.exit('O3 CPU does not support the \'%s\' ISA' % env['TARGET_ISA'])
diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh
index b961341d5..9d97f9701 100644
--- a/src/cpu/o3/alpha/cpu.hh
+++ b/src/cpu/o3/alpha/cpu.hh
@@ -31,7 +31,8 @@
#ifndef __CPU_O3_ALPHA_CPU_HH__
#define __CPU_O3_ALPHA_CPU_HH__
-#include "arch/isa_traits.hh"
+#include "arch/regfile.hh"
+#include "arch/types.hh"
#include "cpu/thread_context.hh"
#include "cpu/o3/cpu.hh"
#include "sim/byteswap.hh"
diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh
index 0473e60c2..b7362fad9 100644
--- a/src/cpu/o3/alpha/cpu_impl.hh
+++ b/src/cpu/o3/alpha/cpu_impl.hh
@@ -31,6 +31,7 @@
#include "config/use_checker.hh"
#include "arch/alpha/faults.hh"
+#include "arch/alpha/isa_traits.hh"
#include "base/cprintf.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
@@ -53,8 +54,6 @@
#include "sim/system.hh"
#endif
-using namespace TheISA;
-
template <class Impl>
AlphaO3CPU<Impl>::AlphaO3CPU(Params *params)
#if FULL_SYSTEM
@@ -191,14 +190,14 @@ AlphaO3CPU<Impl>::regStats()
template <class Impl>
-MiscReg
+TheISA::MiscReg
AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
{
return this->regFile.readMiscReg(misc_reg, tid);
}
template <class Impl>
-MiscReg
+TheISA::MiscReg
AlphaO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
unsigned tid)
{
@@ -300,6 +299,7 @@ template <class Impl>
void
AlphaO3CPU<Impl>::processInterrupts()
{
+ using namespace TheISA;
// Check for interrupts here. For now can copy the code that
// exists within isa_fullsys_traits.hh. Also assume that thread 0
// is the one that handles the interrupts.
@@ -411,12 +411,12 @@ AlphaO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
// return value itself in the standard return value reg (v0).
if (return_value.successful()) {
// no error
- this->setArchIntReg(SyscallSuccessReg, 0, tid);
- this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
+ this->setArchIntReg(TheISA::SyscallSuccessReg, 0, tid);
+ this->setArchIntReg(TheISA::ReturnValueReg, return_value.value(), tid);
} else {
// got an error, return details
- this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
- this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);
+ this->setArchIntReg(TheISA::SyscallSuccessReg, (IntReg) -1, tid);
+ this->setArchIntReg(TheISA::ReturnValueReg, -return_value.value(), tid);
}
}
#endif
diff --git a/src/cpu/o3/alpha/thread_context.hh b/src/cpu/o3/alpha/thread_context.hh
index ad52b0d2e..70a09940f 100644
--- a/src/cpu/o3/alpha/thread_context.hh
+++ b/src/cpu/o3/alpha/thread_context.hh
@@ -26,9 +26,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
- * Korey Sewell
*/
+#include "arch/alpha/types.hh"
#include "cpu/o3/thread_context.hh"
template <class Impl>
@@ -65,8 +65,8 @@ class AlphaTC : public O3ThreadContext<Impl>
panic("Alpha has no NextNPC!");
}
- virtual void changeRegFileContext(TheISA::RegFile::ContextParam param,
- TheISA::RegFile::ContextVal val)
+ virtual void changeRegFileContext(TheISA::RegContextParam param,
+ TheISA::RegContextVal val)
{ panic("Not supported on Alpha!"); }
diff --git a/src/cpu/o3/bpred_unit.hh b/src/cpu/o3/bpred_unit.hh
index 2c0a39565..3c4c8e478 100644
--- a/src/cpu/o3/bpred_unit.hh
+++ b/src/cpu/o3/bpred_unit.hh
@@ -31,8 +31,6 @@
#ifndef __CPU_O3_BPRED_UNIT_HH__
#define __CPU_O3_BPRED_UNIT_HH__
-// For Addr type.
-#include "arch/isa_traits.hh"
#include "base/statistics.hh"
#include "cpu/inst_seq.hh"
@@ -41,6 +39,8 @@
#include "cpu/o3/ras.hh"
#include "cpu/o3/tournament_pred.hh"
+#include "sim/host.hh"
+
#include <list>
/**
diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh
index 0da02145b..e4e656632 100644
--- a/src/cpu/o3/bpred_unit_impl.hh
+++ b/src/cpu/o3/bpred_unit_impl.hh
@@ -28,15 +28,11 @@
* Authors: Kevin Lim
*/
-#include <list>
-#include <vector>
-
+#include "arch/types.hh"
#include "base/trace.hh"
#include "base/traceflags.hh"
#include "cpu/o3/bpred_unit.hh"
-using namespace std;
-
template<class Impl>
BPredUnit<Impl>::BPredUnit(Params *params)
: BTB(params->BTBEntries,
@@ -159,7 +155,7 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid)
void *bp_history = NULL;
if (inst->isUncondCtrl()) {
- DPRINTF(Fetch, "BranchPred: [tid:%i] Unconditional control.\n", tid);
+ DPRINTF(Fetch, "BranchPred: [tid:%i]: Unconditional control.\n", tid);
pred_taken = true;
// Tell the BP there was an unconditional branch.
BPUncond(bp_history);
@@ -201,15 +197,20 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid)
++BTBLookups;
if (inst->isCall()) {
- RAS[tid].push(PC + sizeof(MachInst));
+#if THE_ISA == ALPHA_ISA
+ Addr ras_pc = PC + sizeof(MachInst); // Next PC
+#else
+ Addr ras_pc = PC + (2 * sizeof(MachInst)); // Next Next PC
+#endif
+ RAS[tid].push(ras_pc);
// Record that it was a call so that the top RAS entry can
// be popped off if the speculation is incorrect.
predict_record.wasCall = true;
- DPRINTF(Fetch, "BranchPred: [tid:%i] Instruction %#x was a call"
+ DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x was a call"
", adding %#x to the RAS.\n",
- tid, inst->readPC(), PC + sizeof(MachInst));
+ tid, inst->readPC(), ras_pc);
}
if (BTB.valid(PC, tid)) {
@@ -242,7 +243,7 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid)
predHist[tid].push_front(predict_record);
- DPRINTF(Fetch, "[tid:%i] predHist.size(): %i\n", tid, predHist[tid].size());
+ DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n", tid, predHist[tid].size());
return pred_taken;
}
@@ -251,8 +252,8 @@ template <class Impl>
void
BPredUnit<Impl>::update(const InstSeqNum &done_sn, unsigned tid)
{
- DPRINTF(Fetch, "BranchPred: [tid:%i]: Commiting branches until sequence"
- "number %lli.\n", tid, done_sn);
+ DPRINTF(Fetch, "BranchPred: [tid:%i]: Commiting branches until "
+ "[sn:%lli].\n", tid, done_sn);
while (!predHist[tid].empty() &&
predHist[tid].back().seqNum <= done_sn) {
diff --git a/src/cpu/o3/btb.cc b/src/cpu/o3/btb.cc
index 01640f4d1..93d6ee768 100644
--- a/src/cpu/o3/btb.cc
+++ b/src/cpu/o3/btb.cc
@@ -32,8 +32,6 @@
#include "base/trace.hh"
#include "cpu/o3/btb.hh"
-using namespace TheISA;
-
DefaultBTB::DefaultBTB(unsigned _numEntries,
unsigned _tagBits,
unsigned _instShiftAmt)
diff --git a/src/cpu/o3/btb.hh b/src/cpu/o3/btb.hh
index dfa3b7b06..3c4899e89 100644
--- a/src/cpu/o3/btb.hh
+++ b/src/cpu/o3/btb.hh
@@ -31,9 +31,8 @@
#ifndef __CPU_O3_BTB_HH__
#define __CPU_O3_BTB_HH__
-// For Addr type.
-#include "arch/isa_traits.hh"
#include "base/misc.hh"
+#include "sim/host.hh"
class DefaultBTB
{
diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh
index bf1bd08e8..aa58fc20e 100644
--- a/src/cpu/o3/comm.hh
+++ b/src/cpu/o3/comm.hh
@@ -33,8 +33,7 @@
#include <vector>
-#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
+#include "sim/faults.hh"
#include "cpu/inst_seq.hh"
#include "sim/host.hh"
@@ -88,6 +87,7 @@ struct DefaultIEWDefaultCommit {
bool squash[Impl::MaxThreads];
bool branchMispredict[Impl::MaxThreads];
bool branchTaken[Impl::MaxThreads];
+ bool condDelaySlotBranch[Impl::MaxThreads];
uint64_t mispredPC[Impl::MaxThreads];
uint64_t nextPC[Impl::MaxThreads];
InstSeqNum squashedSeqNum[Impl::MaxThreads];
@@ -113,6 +113,7 @@ struct TimeBufStruct {
uint64_t branchAddr;
InstSeqNum doneSeqNum;
+ InstSeqNum bdelayDoneSeqNum;
// @todo: Might want to package this kind of branch stuff into a single
// struct as it is used pretty frequently.
@@ -165,6 +166,9 @@ struct TimeBufStruct {
// retired or squashed sequence number.
InstSeqNum doneSeqNum;
+ InstSeqNum bdelayDoneSeqNum;
+ bool squashDelaySlot;
+
//Just in case we want to do a commit/squash on a cycle
//(necessary for multiple ROBs?)
bool commitInsts;
diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh
index 956b6ec3e..7575783f7 100644
--- a/src/cpu/o3/commit.hh
+++ b/src/cpu/o3/commit.hh
@@ -32,7 +32,6 @@
#ifndef __CPU_O3_COMMIT_HH__
#define __CPU_O3_COMMIT_HH__
-#include "arch/faults.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/exetrace.hh"
@@ -165,6 +164,9 @@ class DefaultCommit
/** Sets the pointer to the IEW stage. */
void setIEWStage(IEW *iew_stage);
+ /** Skid buffer between rename and commit. */
+ std::queue<DynInstPtr> skidBuffer;
+
/** The pointer to the IEW stage. Used solely to ensure that
* various events (traps, interrupts, syscalls) do not occur until
* all stores have written back.
@@ -256,6 +258,9 @@ class DefaultCommit
/** Gets instructions from rename and inserts them into the ROB. */
void getInsts();
+ /** Insert all instructions from rename into skidBuffer */
+ void skidInsert();
+
/** Marks completed instructions using information sent from IEW. */
void markCompletedInsts();
@@ -286,13 +291,11 @@ class DefaultCommit
/** Sets the next PC of a specific thread. */
void setNextPC(uint64_t val, unsigned tid) { nextPC[tid] = val; }
-#if THE_ISA != ALPHA_ISA
/** Reads the next NPC of a specific thread. */
- uint64_t readNextPC(unsigned tid) { return nextNPC[tid]; }
+ uint64_t readNextNPC(unsigned tid) { return nextNPC[tid]; }
/** Sets the next NPC of a specific thread. */
- void setNextPC(uint64_t val, unsigned tid) { nextNPC[tid] = val; }
-#endif
+ void setNextNPC(uint64_t val, unsigned tid) { nextNPC[tid] = val; }
private:
/** Time buffer interface. */
@@ -397,10 +400,8 @@ class DefaultCommit
/** The next PC of each thread. */
Addr nextPC[Impl::MaxThreads];
-#if THE_ISA != ALPHA_ISA
/** The next NPC of each thread. */
Addr nextNPC[Impl::MaxThreads];
-#endif
/** The sequence number of the youngest valid instruction in the ROB. */
InstSeqNum youngestSeqNum[Impl::MaxThreads];
diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index 904af1071..f200f5f18 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
+ * Korey Sewell
*/
#include "config/full_system.hh"
@@ -44,8 +45,6 @@
#include "cpu/checker/cpu.hh"
#endif
-using namespace std;
-
template <class Impl>
DefaultCommit<Impl>::TrapEvent::TrapEvent(DefaultCommit<Impl> *_commit,
unsigned _tid)
@@ -86,7 +85,7 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
{
_status = Active;
_nextStatus = Inactive;
- string policy = params->smtCommitPolicy;
+ std::string policy = params->smtCommitPolicy;
//Convert string to lowercase
std::transform(policy.begin(), policy.end(), policy.begin(),
@@ -120,7 +119,7 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
changedROBNumEntries[i] = false;
trapSquash[i] = false;
tcSquash[i] = false;
- PC[i] = nextPC[i] = 0;
+ PC[i] = nextPC[i] = nextNPC[i] = 0;
}
}
@@ -235,7 +234,7 @@ DefaultCommit<Impl>::setCPU(O3CPU *cpu_ptr)
template <class Impl>
void
-DefaultCommit<Impl>::setThreads(vector<Thread *> &threads)
+DefaultCommit<Impl>::setThreads(std::vector<Thread *> &threads)
{
thread = threads;
}
@@ -296,7 +295,7 @@ DefaultCommit<Impl>::setIEWStage(IEW *iew_stage)
template<class Impl>
void
-DefaultCommit<Impl>::setActiveThreads(list<unsigned> *at_ptr)
+DefaultCommit<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
DPRINTF(Commit, "Commit: Setting active threads list pointer.\n");
activeThreads = at_ptr;
@@ -390,7 +389,7 @@ void
DefaultCommit<Impl>::updateStatus()
{
// reset ROB changed variable
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
changedROBNumEntries[tid] = false;
@@ -419,7 +418,7 @@ DefaultCommit<Impl>::setNextStatus()
{
int squashes = 0;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
@@ -442,7 +441,7 @@ template <class Impl>
bool
DefaultCommit<Impl>::changedROBEntries()
{
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
@@ -569,7 +568,7 @@ DefaultCommit<Impl>::tick()
if ((*activeThreads).size() <= 0)
return;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
// Check if any of the threads are done squashing. Change the
// status if they are done.
@@ -687,7 +686,7 @@ DefaultCommit<Impl>::commit()
// Check for any possible squashes, handle them first
////////////////////////////////////
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
@@ -723,14 +722,48 @@ DefaultCommit<Impl>::commit()
// then use one older sequence number.
InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
- if (fromIEW->includeSquashInst[tid] == true)
- squashed_inst--;
+#if THE_ISA != ALPHA_ISA
+ InstSeqNum bdelay_done_seq_num;
+ bool squash_bdelay_slot;
+
+ if (fromIEW->branchMispredict[tid]) {
+ if (fromIEW->branchTaken[tid] &&
+ fromIEW->condDelaySlotBranch[tid]) {
+ DPRINTF(Commit, "[tid:%i]: Cond. delay slot branch"
+ "mispredicted as taken. Squashing after previous "
+ "inst, [sn:%i]\n",
+ tid, squashed_inst);
+ bdelay_done_seq_num = squashed_inst;
+ squash_bdelay_slot = true;
+ } else {
+ DPRINTF(Commit, "[tid:%i]: Branch Mispredict. Squashing "
+ "after delay slot [sn:%i]\n", tid, squashed_inst+1);
+ bdelay_done_seq_num = squashed_inst + 1;
+ squash_bdelay_slot = false;
+ }
+ } else {
+ bdelay_done_seq_num = squashed_inst;
+ }
+#endif
+ if (fromIEW->includeSquashInst[tid] == true) {
+ squashed_inst--;
+#if THE_ISA != ALPHA_ISA
+ bdelay_done_seq_num--;
+#endif
+ }
// All younger instructions will be squashed. Set the sequence
// number as the youngest instruction in the ROB.
youngestSeqNum[tid] = squashed_inst;
+#if THE_ISA == ALPHA_ISA
rob->squash(squashed_inst, tid);
+ toIEW->commitInfo[tid].squashDelaySlot = true;
+#else
+ rob->squash(bdelay_done_seq_num, tid);
+ toIEW->commitInfo[tid].squashDelaySlot = squash_bdelay_slot;
+ toIEW->commitInfo[tid].bdelayDoneSeqNum = bdelay_done_seq_num;
+#endif
changedROBNumEntries[tid] = true;
toIEW->commitInfo[tid].doneSeqNum = squashed_inst;
@@ -766,6 +799,10 @@ DefaultCommit<Impl>::commit()
// Try to commit any instructions.
commitInsts();
+ } else {
+#if THE_ISA != ALPHA_ISA
+ skidInsert();
+#endif
}
//Check for any activity
@@ -840,6 +877,7 @@ DefaultCommit<Impl>::commitInsts()
} else {
PC[tid] = head_inst->readPC();
nextPC[tid] = head_inst->readNextPC();
+ nextNPC[tid] = head_inst->readNextNPC();
// Increment the total number of non-speculative instructions
// executed.
@@ -868,7 +906,13 @@ DefaultCommit<Impl>::commitInsts()
}
PC[tid] = nextPC[tid];
+#if THE_ISA == ALPHA_ISA
nextPC[tid] = nextPC[tid] + sizeof(TheISA::MachInst);
+#else
+ nextPC[tid] = nextNPC[tid];
+ nextNPC[tid] = nextNPC[tid] + sizeof(TheISA::MachInst);
+#endif
+
#if FULL_SYSTEM
int count = 0;
Addr oldpc;
@@ -996,6 +1040,12 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
// Check if the instruction caused a fault. If so, trap.
Fault inst_fault = head_inst->getFault();
+ // DTB will sometimes need the machine instruction for when
+ // faults happen. So we will set it here, prior to the DTB
+ // possibly needing it for its fault.
+ thread[tid]->setInst(
+ static_cast<TheISA::MachInst>(head_inst->staticInst->machInst));
+
if (inst_fault != NoFault) {
head_inst->setCompleted();
DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
@@ -1018,12 +1068,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
// execution doesn't generate extra squashes.
thread[tid]->inSyscall = true;
- // DTB will sometimes need the machine instruction for when
- // faults happen. So we will set it here, prior to the DTB
- // possibly needing it for its fault.
- thread[tid]->setInst(
- static_cast<TheISA::MachInst>(head_inst->staticInst->machInst));
-
// Execute the trap. Although it's slightly unrealistic in
// terms of timing (as it doesn't wait for the full timing of
// the trap event to complete before updating state), it's
@@ -1069,12 +1113,39 @@ template <class Impl>
void
DefaultCommit<Impl>::getInsts()
{
+ DPRINTF(Commit, "Getting instructions from Rename stage.\n");
+
+#if THE_ISA == ALPHA_ISA
+ // Read any renamed instructions and place them into the ROB.
+ int insts_to_process = std::min((int)renameWidth, fromRename->size);
+#else
// Read any renamed instructions and place them into the ROB.
- int insts_to_process = min((int)renameWidth, fromRename->size);
+ int insts_to_process = std::min((int)renameWidth,
+ (int)(fromRename->size + skidBuffer.size()));
+ int rename_idx = 0;
- for (int inst_num = 0; inst_num < insts_to_process; ++inst_num)
- {
- DynInstPtr inst = fromRename->insts[inst_num];
+ DPRINTF(Commit, "%i insts available to process. Rename Insts:%i "
+ "SkidBuffer Insts:%i\n", insts_to_process, fromRename->size,
+ skidBuffer.size());
+#endif
+
+
+ for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
+ DynInstPtr inst;
+
+#if THE_ISA == ALPHA_ISA
+ inst = fromRename->insts[inst_num];
+#else
+ // Get insts from skidBuffer or from Rename
+ if (skidBuffer.size() > 0) {
+ DPRINTF(Commit, "Grabbing skidbuffer inst.\n");
+ inst = skidBuffer.front();
+ skidBuffer.pop();
+ } else {
+ DPRINTF(Commit, "Grabbing rename inst.\n");
+ inst = fromRename->insts[rename_idx++];
+ }
+#endif
int tid = inst->threadNumber;
if (!inst->isSquashed() &&
@@ -1095,6 +1166,53 @@ DefaultCommit<Impl>::getInsts()
inst->readPC(), inst->seqNum, tid);
}
}
+
+#if THE_ISA != ALPHA_ISA
+ if (rename_idx < fromRename->size) {
+ DPRINTF(Commit,"Placing Rename Insts into skidBuffer.\n");
+
+ for (;
+ rename_idx < fromRename->size;
+ rename_idx++) {
+ DynInstPtr inst = fromRename->insts[rename_idx];
+ int tid = inst->threadNumber;
+
+ if (!inst->isSquashed()) {
+ DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ",
+ "skidBuffer.\n", inst->readPC(), inst->seqNum, tid);
+ skidBuffer.push(inst);
+ } else {
+ DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
+ "squashed, skipping.\n",
+ inst->readPC(), inst->seqNum, tid);
+ }
+ }
+ }
+#endif
+
+}
+
+template <class Impl>
+void
+DefaultCommit<Impl>::skidInsert()
+{
+ DPRINTF(Commit, "Attempting to any instructions from rename into "
+ "skidBuffer.\n");
+
+ for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) {
+ DynInstPtr inst = fromRename->insts[inst_num];
+ int tid = inst->threadNumber;
+
+ if (!inst->isSquashed()) {
+ DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ",
+ "skidBuffer.\n", inst->readPC(), inst->seqNum, tid);
+ skidBuffer.push(inst);
+ } else {
+ DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "
+ "squashed, skipping.\n",
+ inst->readPC(), inst->seqNum, tid);
+ }
+ }
}
template <class Impl>
@@ -1124,7 +1242,7 @@ template <class Impl>
bool
DefaultCommit<Impl>::robDoneSquashing()
{
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
@@ -1221,8 +1339,8 @@ template<class Impl>
int
DefaultCommit<Impl>::roundRobin()
{
- list<unsigned>::iterator pri_iter = priority_list.begin();
- list<unsigned>::iterator end = priority_list.end();
+ std::list<unsigned>::iterator pri_iter = priority_list.begin();
+ std::list<unsigned>::iterator end = priority_list.end();
while (pri_iter != end) {
unsigned tid = *pri_iter;
@@ -1252,7 +1370,7 @@ DefaultCommit<Impl>::oldestReady()
unsigned oldest = 0;
bool first = true;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index 7d2727401..af032132e 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -441,7 +441,7 @@ FullO3CPU<Impl>::tick()
if (!tickEvent.scheduled()) {
if (_status == SwitchedOut ||
- getState() == SimObject::DrainedTiming) {
+ getState() == SimObject::Drained) {
// increment stat
lastRunningCycle = curTick;
} else if (!activityRec.active()) {
@@ -577,39 +577,19 @@ void
FullO3CPU<Impl>::suspendContext(int tid)
{
DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
- unscheduleTickEvent();
+ deactivateThread(tid);
+ if (activeThreads.size() == 0)
+ unscheduleTickEvent();
_status = Idle;
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
- }
-*/
}
template <class Impl>
void
FullO3CPU<Impl>::haltContext(int tid)
{
- DPRINTF(O3CPU,"[tid:%i]: Halting Thread Context", tid);
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
-
- removeThread(tid);
- }
-*/
+ //For now, this is the same as deallocate
+ DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
+ deallocateContext(tid, 1);
}
template <class Impl>
@@ -687,11 +667,12 @@ FullO3CPU<Impl>::removeThread(unsigned tid)
}
// Squash Throughout Pipeline
- fetch.squash(0,tid);
+ InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum;
+ fetch.squash(0, squash_seq_num, true, tid);
decode.squash(tid);
- rename.squash(tid);
+ rename.squash(squash_seq_num, tid);
iew.squash(tid);
- commit.rob->squash(commit.rob->readHeadInst(tid)->seqNum, tid);
+ commit.rob->squash(squash_seq_num, tid);
assert(iew.ldstQueue.getCount(tid) == 0);
@@ -765,7 +746,8 @@ template <class Impl>
void
FullO3CPU<Impl>::serialize(std::ostream &os)
{
- SERIALIZE_ENUM(_status);
+ SimObject::State so_state = SimObject::getState();
+ SERIALIZE_ENUM(so_state);
BaseCPU::serialize(os);
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
@@ -786,7 +768,8 @@ template <class Impl>
void
FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
{
- UNSERIALIZE_ENUM(_status);
+ SimObject::State so_state;
+ UNSERIALIZE_ENUM(so_state);
BaseCPU::unserialize(cp, section);
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
@@ -803,7 +786,7 @@ FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
}
template <class Impl>
-bool
+unsigned int
FullO3CPU<Impl>::drain(Event *drain_event)
{
drainCount = 0;
@@ -815,7 +798,7 @@ FullO3CPU<Impl>::drain(Event *drain_event)
// Wake the CPU and record activity so everything can drain out if
// the CPU was not able to immediately drain.
- if (getState() != SimObject::DrainedTiming) {
+ if (getState() != SimObject::Drained) {
// A bit of a hack...set the drainEvent after all the drain()
// calls have been made, that way if all of the stages drain
// immediately, the signalDrained() function knows not to call
@@ -825,9 +808,9 @@ FullO3CPU<Impl>::drain(Event *drain_event)
wakeCPU();
activityRec.activity();
- return false;
+ return 1;
} else {
- return true;
+ return 0;
}
}
@@ -835,19 +818,21 @@ template <class Impl>
void
FullO3CPU<Impl>::resume()
{
+ assert(system->getMemoryMode() == System::Timing);
fetch.resume();
decode.resume();
rename.resume();
iew.resume();
commit.resume();
+ changeState(SimObject::Running);
+
if (_status == SwitchedOut || _status == Idle)
return;
if (!tickEvent.scheduled())
tickEvent.schedule(curTick);
_status = Running;
- changeState(SimObject::Timing);
}
template <class Impl>
@@ -858,7 +843,7 @@ FullO3CPU<Impl>::signalDrained()
if (tickEvent.scheduled())
tickEvent.squash();
- changeState(SimObject::DrainedTiming);
+ changeState(SimObject::Drained);
if (drainEvent) {
drainEvent->process();
@@ -1063,7 +1048,8 @@ template <class Impl>
void
FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
+ int idx = reg_idx + TheISA::FP_Base_DepTag;
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
regFile.setFloatReg(phys_reg, val);
}
@@ -1072,7 +1058,8 @@ template <class Impl>
void
FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
+ int idx = reg_idx + TheISA::FP_Base_DepTag;
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
regFile.setFloatReg(phys_reg, val, 64);
}
@@ -1081,7 +1068,8 @@ template <class Impl>
void
FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
+ int idx = reg_idx + TheISA::FP_Base_DepTag;
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
regFile.setFloatRegBits(phys_reg, val);
}
@@ -1114,7 +1102,6 @@ FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
commit.setNextPC(val, tid);
}
-#if THE_ISA != ALPHA_ISA
template <class Impl>
uint64_t
FullO3CPU<Impl>::readNextNPC(unsigned tid)
@@ -1124,11 +1111,10 @@ FullO3CPU<Impl>::readNextNPC(unsigned tid)
template <class Impl>
void
-FullO3CPU<Impl>::setNextNNPC(uint64_t val,unsigned tid)
+FullO3CPU<Impl>::setNextNPC(uint64_t val,unsigned tid)
{
commit.setNextNPC(val, tid);
}
-#endif
template <class Impl>
typename FullO3CPU<Impl>::ListIt
@@ -1178,7 +1164,9 @@ FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
template <class Impl>
void
-FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
+FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid,
+ bool squash_delay_slot,
+ const InstSeqNum &delay_slot_seq_num)
{
DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
" list.\n", tid);
@@ -1209,6 +1197,12 @@ FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
while (inst_it != end_it) {
assert(!instList.empty());
+#if THE_ISA != ALPHA_ISA
+ if(!squash_delay_slot &&
+ delay_slot_seq_num >= (*inst_it)->seqNum) {
+ break;
+ }
+#endif
squashInstIt(inst_it, tid);
inst_it--;
diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh
index 2fbd013ac..7e18571f1 100644
--- a/src/cpu/o3/cpu.hh
+++ b/src/cpu/o3/cpu.hh
@@ -38,7 +38,7 @@
#include <set>
#include <vector>
-#include "arch/isa_traits.hh"
+#include "arch/types.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "config/full_system.hh"
@@ -330,7 +330,7 @@ class FullO3CPU : public BaseO3CPU
/** Starts draining the CPU's pipeline of all instructions in
* order to stop all memory accesses. */
- virtual bool drain(Event *drain_event);
+ virtual unsigned int drain(Event *drain_event);
/** Resumes execution after a drain. */
virtual void resume();
@@ -449,8 +449,10 @@ class FullO3CPU : public BaseO3CPU
*/
void removeFrontInst(DynInstPtr &inst);
- /** Remove all instructions that are not currently in the ROB. */
- void removeInstsNotInROB(unsigned tid);
+ /** Remove all instructions that are not currently in the ROB.
+ * There's also an option to not squash delay slot instructions.*/
+ void removeInstsNotInROB(unsigned tid, bool squash_delay_slot,
+ const InstSeqNum &delay_slot_seq_num);
/** Remove all instructions younger than the given sequence number. */
void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid);
diff --git a/src/cpu/o3/decode.hh b/src/cpu/o3/decode.hh
index 7f5ecbc26..4a845e670 100644
--- a/src/cpu/o3/decode.hh
+++ b/src/cpu/o3/decode.hh
@@ -276,6 +276,19 @@ class DefaultDecode
/** Maximum size of the skid buffer. */
unsigned skidBufferMax;
+ /** SeqNum of Squashing Branch Delay Instruction (used for MIPS)*/
+ Addr bdelayDoneSeqNum[Impl::MaxThreads];
+
+ /** Instruction used for squashing branch (used for MIPS)*/
+ DynInstPtr squashInst[Impl::MaxThreads];
+
+ /** Tells when their is a pending delay slot inst. to send
+ * to rename. If there is, then wait squash after the next
+ * instruction (used for MIPS).
+ */
+ bool squashAfterDelaySlot[Impl::MaxThreads];
+
+
/** Stat for total number of idle cycles. */
Stats::Scalar<> decodeIdleCycles;
/** Stat for total number of blocked cycles. */
diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh
index 8b851c032..160845378 100644
--- a/src/cpu/o3/decode_impl.hh
+++ b/src/cpu/o3/decode_impl.hh
@@ -30,8 +30,6 @@
#include "cpu/o3/decode.hh"
-using namespace std;
-
template<class Impl>
DefaultDecode<Impl>::DefaultDecode(Params *params)
: renameToDecodeDelay(params->renameToDecodeDelay),
@@ -50,6 +48,8 @@ DefaultDecode<Impl>::DefaultDecode(Params *params)
stalls[i].rename = false;
stalls[i].iew = false;
stalls[i].commit = false;
+
+ squashAfterDelaySlot[i] = false;
}
// @todo: Make into a parameter
@@ -158,7 +158,7 @@ DefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
template<class Impl>
void
-DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr)
+DefaultDecode<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
DPRINTF(Decode, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
@@ -278,13 +278,25 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
// Send back mispredict information.
toFetch->decodeInfo[tid].branchMispredict = true;
- toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
toFetch->decodeInfo[tid].predIncorrect = true;
+ toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;
toFetch->decodeInfo[tid].squash = true;
toFetch->decodeInfo[tid].nextPC = inst->branchTarget();
+#if THE_ISA == ALPHA_ISA
toFetch->decodeInfo[tid].branchTaken =
inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst));
+ InstSeqNum squash_seq_num = inst->seqNum;
+#else
+ toFetch->decodeInfo[tid].branchTaken = inst->readNextNPC() !=
+ (inst->readNextPC() + sizeof(TheISA::MachInst));
+
+ toFetch->decodeInfo[tid].bdelayDoneSeqNum = bdelayDoneSeqNum[tid];
+ squashAfterDelaySlot[tid] = false;
+
+ InstSeqNum squash_seq_num = bdelayDoneSeqNum[tid];
+#endif
+
// Might have to tell fetch to unblock.
if (decodeStatus[tid] == Blocked ||
decodeStatus[tid] == Unblocking) {
@@ -296,7 +308,7 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
for (int i=0; i<fromFetch->size; i++) {
if (fromFetch->insts[i]->threadNumber == tid &&
- fromFetch->insts[i]->seqNum > inst->seqNum) {
+ fromFetch->insts[i]->seqNum > squash_seq_num) {
fromFetch->insts[i]->setSquashed();
}
}
@@ -304,15 +316,35 @@ DefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid)
// Clear the instruction list and skid buffer in case they have any
// insts in them.
while (!insts[tid].empty()) {
+
+#if THE_ISA != ALPHA_ISA
+ if (insts[tid].front()->seqNum <= squash_seq_num) {
+ DPRINTF(Decode, "[tid:%i]: Cannot remove incoming decode "
+ "instructions before delay slot [sn:%i]. %i insts"
+ "left in decode.\n", tid, squash_seq_num,
+ insts[tid].size());
+ break;
+ }
+#endif
insts[tid].pop();
}
while (!skidBuffer[tid].empty()) {
+
+#if THE_ISA != ALPHA_ISA
+ if (skidBuffer[tid].front()->seqNum <= squash_seq_num) {
+ DPRINTF(Decode, "[tid:%i]: Cannot remove skidBuffer "
+ "instructions before delay slot [sn:%i]. %i insts"
+ "left in decode.\n", tid, squash_seq_num,
+ insts[tid].size());
+ break;
+ }
+#endif
skidBuffer[tid].pop();
}
// Squash instructions up until this one
- cpu->removeInstsUntil(inst->seqNum, tid);
+ cpu->removeInstsUntil(squash_seq_num, tid);
}
template<class Impl>
@@ -392,7 +424,7 @@ template<class Impl>
bool
DefaultDecode<Impl>::skidsEmpty()
{
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
if (!skidBuffer[*threads++].empty())
@@ -408,7 +440,7 @@ DefaultDecode<Impl>::updateStatus()
{
bool any_unblocking = false;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
threads = (*activeThreads).begin();
@@ -565,7 +597,7 @@ DefaultDecode<Impl>::tick()
toRenameIndex = 0;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
sortInsts();
@@ -611,7 +643,7 @@ DefaultDecode<Impl>::decode(bool &status_change, unsigned tid)
// will allow, as long as it is not currently blocked.
if (decodeStatus[tid] == Running ||
decodeStatus[tid] == Idle) {
- DPRINTF(Decode, "[tid:%u] Not blocked, so attempting to run "
+ DPRINTF(Decode, "[tid:%u]: Not blocked, so attempting to run "
"stage.\n",tid);
decodeInsts(tid);
@@ -710,6 +742,9 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
// Ensure that if it was predicted as a branch, it really is a
// branch.
if (inst->predTaken() && !inst->isControl()) {
+ DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n",inst->predPC,
+ inst->nextPC + 4);
+
panic("Instruction predicted as a branch!");
++decodeControlMispred;
@@ -730,12 +765,43 @@ DefaultDecode<Impl>::decodeInsts(unsigned tid)
// Might want to set some sort of boolean and just do
// a check at the end
+#if THE_ISA == ALPHA_ISA
squash(inst, inst->threadNumber);
inst->setPredTarg(inst->branchTarget());
-
break;
+#else
+ // If mispredicted as taken, then ignore delay slot
+ // instruction... else keep delay slot and squash
+ // after it is sent to rename
+ if (inst->predTaken() && inst->isCondDelaySlot()) {
+ DPRINTF(Decode, "[tid:%i]: Conditional delay slot inst."
+ "[sn:%i] PC %#x mispredicted as taken.\n", tid,
+ inst->seqNum, inst->PC);
+ bdelayDoneSeqNum[tid] = inst->seqNum;
+ squash(inst, inst->threadNumber);
+ inst->setPredTarg(inst->branchTarget());
+ break;
+ } else {
+ DPRINTF(Decode, "[tid:%i]: Misprediction detected at "
+ "[sn:%i] PC %#x, will squash after delay slot "
+ "inst. is sent to Rename\n",
+ tid, inst->seqNum, inst->PC);
+ bdelayDoneSeqNum[tid] = inst->seqNum + 1;
+ squashAfterDelaySlot[tid] = true;
+ squashInst[tid] = inst;
+ continue;
+ }
+#endif
}
}
+
+ if (squashAfterDelaySlot[tid]) {
+ assert(!inst->isSquashed());
+ squash(squashInst[tid], squashInst[tid]->threadNumber);
+ squashInst[tid]->setPredTarg(squashInst[tid]->branchTarget());
+ assert(!inst->isSquashed());
+ break;
+ }
}
// If we didn't process all instructions, then we will need to block
diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh
index a2cdf2dba..279513493 100644
--- a/src/cpu/o3/dyn_inst.hh
+++ b/src/cpu/o3/dyn_inst.hh
@@ -34,12 +34,19 @@
#include "arch/isa_specific.hh"
#if THE_ISA == ALPHA_ISA
-template <class Impl>
-class AlphaDynInst;
-
-struct AlphaSimpleImpl;
-
-typedef AlphaDynInst<AlphaSimpleImpl> O3DynInst;
+ template <class Impl> class AlphaDynInst;
+ struct AlphaSimpleImpl;
+ typedef AlphaDynInst<AlphaSimpleImpl> O3DynInst;
+#elif THE_ISA == MIPS_ISA
+ template <class Impl> class MipsDynInst;
+ struct MipsSimpleImpl;
+ typedef MipsDynInst<MipsSimpleImpl> O3DynInst;
+#elif THE_ISA == SPARC_ISA
+ template <class Impl> class SparcDynInst;
+ struct SparcSimpleImpl;
+ typedef SparcDynInst<SparcSimpleImpl> O3DynInst;
+#else
+ #error "O3DynInst not defined for this ISA"
#endif
#endif // __CPU_O3_DYN_INST_HH__
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index 85654cebc..1a2ca32a4 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -106,6 +106,7 @@ class DefaultFetch
virtual void recvRetry();
};
+
public:
/** Overall fetch status. Used to determine if the CPU can
* deschedule itsef due to a lack of activity.
@@ -218,9 +219,10 @@ class DefaultFetch
* @param next_PC Next PC variable passed in by reference. It is
* expected to be set to the current PC; it will be updated with what
* the next PC will be.
+ * @param next_NPC Used for ISAs which use delay slots.
* @return Whether or not a branch was predicted as taken.
*/
- bool lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC);
+ bool lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, Addr &next_NPC);
/**
* Fetches the cache line that contains fetch_PC. Returns any
@@ -255,7 +257,8 @@ class DefaultFetch
* remove any instructions that are not in the ROB. The source of this
* squash should be the commit stage.
*/
- void squash(const Addr &new_PC, unsigned tid);
+ void squash(const Addr &new_PC, const InstSeqNum &seq_num,
+ bool squash_delay_slot, unsigned tid);
/** Ticks the fetch stage, processing all inputs signals and fetching
* as many instructions as possible.
@@ -340,14 +343,12 @@ class DefaultFetch
/** Per-thread next PC. */
Addr nextPC[Impl::MaxThreads];
-#if THE_ISA != ALPHA_ISA
/** Per-thread next Next PC.
* This is not a real register but is used for
* architectures that use a branch-delay slot.
* (such as MIPS or Sparc)
*/
Addr nextNPC[Impl::MaxThreads];
-#endif
/** Memory request used to access cache. */
RequestPtr memReq[Impl::MaxThreads];
@@ -360,6 +361,19 @@ class DefaultFetch
/** Tracks how many instructions has been fetched this cycle. */
int numInst;
+ /** Tracks delay slot information for threads in ISAs which use
+ * delay slots;
+ */
+ struct DelaySlotInfo {
+ InstSeqNum delaySlotSeqNum;
+ InstSeqNum branchSeqNum;
+ int numInsts;
+ Addr targetAddr;
+ bool targetReady;
+ };
+
+ DelaySlotInfo delaySlotInfo[Impl::MaxThreads];
+
/** Source of possible stalls. */
struct Stalls {
bool decode;
@@ -404,6 +418,12 @@ class DefaultFetch
/** The cache line being fetched. */
uint8_t *cacheData[Impl::MaxThreads];
+ /** The PC of the cacheline that has been loaded. */
+ Addr cacheDataPC[Impl::MaxThreads];
+
+ /** Whether or not the cache data is valid. */
+ bool cacheDataValid[Impl::MaxThreads];
+
/** Size of instructions. */
int instSize;
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 39a13f9f8..990db88ac 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -51,9 +51,6 @@
#include <algorithm>
-using namespace std;
-using namespace TheISA;
-
template<class Impl>
Tick
DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt)
@@ -118,7 +115,7 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
// Set fetch stage's status to inactive.
_status = Inactive;
- string policy = params->smtFetchPolicy;
+ std::string policy = params->smtFetchPolicy;
// Convert string to lowercase
std::transform(policy.begin(), policy.end(), policy.begin(),
@@ -162,15 +159,22 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
// Create space to store a cache line.
cacheData[tid] = new uint8_t[cacheBlkSize];
+ cacheDataPC[tid] = 0;
+ cacheDataValid[tid] = false;
+
+ delaySlotInfo[tid].branchSeqNum = -1;
+ delaySlotInfo[tid].numInsts = 0;
+ delaySlotInfo[tid].targetAddr = 0;
+ delaySlotInfo[tid].targetReady = false;
- stalls[tid].decode = 0;
- stalls[tid].rename = 0;
- stalls[tid].iew = 0;
- stalls[tid].commit = 0;
+ stalls[tid].decode = false;
+ stalls[tid].rename = false;
+ stalls[tid].iew = false;
+ stalls[tid].commit = false;
}
// Get the size of an instruction.
- instSize = sizeof(MachInst);
+ instSize = sizeof(TheISA::MachInst);
}
template <class Impl>
@@ -286,6 +290,9 @@ DefaultFetch<Impl>::setCPU(O3CPU *cpu_ptr)
}
#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();
@@ -307,7 +314,7 @@ DefaultFetch<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer)
template<class Impl>
void
-DefaultFetch<Impl>::setActiveThreads(list<unsigned> *at_ptr)
+DefaultFetch<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
DPRINTF(Fetch, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
@@ -358,6 +365,7 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt)
}
memcpy(cacheData[tid], pkt->getPtr<uint8_t *>(), cacheBlkSize);
+ cacheDataValid[tid] = true;
if (!drainPending) {
// Wake up the CPU (if it went to sleep and was waiting on
@@ -423,6 +431,10 @@ DefaultFetch<Impl>::takeOverFrom()
nextPC[i] = cpu->readNextPC(i);
#if THE_ISA != ALPHA_ISA
nextNPC[i] = cpu->readNextNPC(i);
+ delaySlotInfo[i].branchSeqNum = -1;
+ delaySlotInfo[i].numInsts = 0;
+ delaySlotInfo[i].targetAddr = 0;
+ delaySlotInfo[i].targetReady = false;
#endif
fetchStatus[i] = Running;
}
@@ -471,7 +483,8 @@ DefaultFetch<Impl>::switchToInactive()
template <class Impl>
bool
-DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC)
+DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC,
+ Addr &next_NPC)
{
// Do branch prediction check here.
// A bit of a misnomer...next_PC is actually the current PC until
@@ -479,12 +492,54 @@ DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC)
bool predict_taken;
if (!inst->isControl()) {
+#if THE_ISA == ALPHA_ISA
next_PC = next_PC + instSize;
inst->setPredTarg(next_PC);
+#else
+ Addr cur_PC = next_PC;
+ next_PC = cur_PC + instSize; //next_NPC;
+ next_NPC = cur_PC + (2 * instSize);//next_NPC + instSize;
+ inst->setPredTarg(next_NPC);
+#endif
return false;
}
- predict_taken = branchPred.predict(inst, next_PC, inst->threadNumber);
+ int tid = inst->threadNumber;
+#if THE_ISA == ALPHA_ISA
+ predict_taken = branchPred.predict(inst, next_PC, tid);
+#else
+ Addr pred_PC = next_PC;
+ predict_taken = branchPred.predict(inst, pred_PC, tid);
+
+ if (predict_taken) {
+ DPRINTF(Fetch, "[tid:%i]: Branch predicted to be true.\n", tid);
+ } else {
+ DPRINTF(Fetch, "[tid:%i]: Branch predicted to be false.\n", tid);
+ }
+
+ if (predict_taken) {
+ next_PC = next_NPC;
+ next_NPC = pred_PC;
+
+ // Update delay slot info
+ ++delaySlotInfo[tid].numInsts;
+ delaySlotInfo[tid].targetAddr = pred_PC;
+ DPRINTF(Fetch, "[tid:%i]: %i delay slot inst(s) to process.\n", tid,
+ delaySlotInfo[tid].numInsts);
+ } else { // !predict_taken
+ if (inst->isCondDelaySlot()) {
+ next_PC = pred_PC;
+ // The delay slot is skipped here if there is on
+ // prediction
+ } else {
+ next_PC = next_NPC;
+ // No need to declare a delay slot here since
+ // there is no for the pred. target to jump
+ }
+
+ next_NPC = next_NPC + instSize;
+ }
+#endif
++fetchedBranches;
@@ -519,6 +574,11 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
// Align the fetch PC so it's at the start of a cache block.
fetch_PC = icacheBlockAlignPC(fetch_PC);
+ // If we've already got the block, no need to try to fetch it again.
+ if (cacheDataValid[tid] && fetch_PC == cacheDataPC[tid]) {
+ return true;
+ }
+
// Setup the memReq to do a read of the first instruction's address.
// Set the appropriate read size and flags as well.
// Build request here.
@@ -550,7 +610,10 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
// Build packet here.
PacketPtr data_pkt = new Packet(mem_req,
Packet::ReadReq, Packet::Broadcast);
- data_pkt->dataDynamic(new uint8_t[cacheBlkSize]);
+ data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]);
+
+ cacheDataPC[tid] = fetch_PC;
+ cacheDataValid[tid] = false;
DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
@@ -595,6 +658,7 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid)
PC[tid] = new_PC;
nextPC[tid] = new_PC + instSize;
+ nextNPC[tid] = new_PC + (2 * instSize);
// Clear the icache miss if it's outstanding.
if (fetchStatus[tid] == IcacheWaitResponse) {
@@ -628,6 +692,14 @@ DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC,
doSquash(new_PC, tid);
+#if THE_ISA != ALPHA_ISA
+ if (seq_num <= delaySlotInfo[tid].branchSeqNum) {
+ delaySlotInfo[tid].numInsts = 0;
+ delaySlotInfo[tid].targetAddr = 0;
+ delaySlotInfo[tid].targetReady = false;
+ }
+#endif
+
// Tell the CPU to remove any instructions that are in flight between
// fetch and decode.
cpu->removeInstsUntil(seq_num, tid);
@@ -664,7 +736,7 @@ typename DefaultFetch<Impl>::FetchStatus
DefaultFetch<Impl>::updateFetchStatus()
{
//Check Running
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
@@ -701,21 +773,33 @@ DefaultFetch<Impl>::updateFetchStatus()
template <class Impl>
void
-DefaultFetch<Impl>::squash(const Addr &new_PC, unsigned tid)
+DefaultFetch<Impl>::squash(const Addr &new_PC, const InstSeqNum &seq_num,
+ bool squash_delay_slot, unsigned tid)
{
DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid);
doSquash(new_PC, tid);
+#if THE_ISA == ALPHA_ISA
+ // Tell the CPU to remove any instructions that are not in the ROB.
+ cpu->removeInstsNotInROB(tid, true, 0);
+#else
+ if (seq_num <= delaySlotInfo[tid].branchSeqNum) {
+ delaySlotInfo[tid].numInsts = 0;
+ delaySlotInfo[tid].targetAddr = 0;
+ delaySlotInfo[tid].targetReady = false;
+ }
+
// Tell the CPU to remove any instructions that are not in the ROB.
- cpu->removeInstsNotInROB(tid);
+ cpu->removeInstsNotInROB(tid, squash_delay_slot, seq_num);
+#endif
}
template <class Impl>
void
DefaultFetch<Impl>::tick()
{
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
bool status_change = false;
wroteToTimeBuffer = false;
@@ -817,8 +901,16 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid)
DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash "
"from commit.\n",tid);
+#if THE_ISA == ALPHA_ISA
+ InstSeqNum doneSeqNum = fromCommit->commitInfo[tid].doneSeqNum;
+#else
+ InstSeqNum doneSeqNum = fromCommit->commitInfo[tid].bdelayDoneSeqNum;
+#endif
// In any case, squash.
- squash(fromCommit->commitInfo[tid].nextPC,tid);
+ squash(fromCommit->commitInfo[tid].nextPC,
+ doneSeqNum,
+ fromCommit->commitInfo[tid].squashDelaySlot,
+ tid);
// Also check if there's a mispredict that happened.
if (fromCommit->commitInfo[tid].branchMispredict) {
@@ -865,9 +957,15 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid)
}
if (fetchStatus[tid] != Squashing) {
+
+#if THE_ISA == ALPHA_ISA
+ InstSeqNum doneSeqNum = fromDecode->decodeInfo[tid].doneSeqNum;
+#else
+ InstSeqNum doneSeqNum = fromDecode->decodeInfo[tid].bdelayDoneSeqNum;
+#endif
// Squash unless we're already squashing
squashFromDecode(fromDecode->decodeInfo[tid].nextPC,
- fromDecode->decodeInfo[tid].doneSeqNum,
+ doneSeqNum,
tid);
return true;
@@ -973,6 +1071,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
}
Addr next_PC = fetch_PC;
+ Addr next_NPC = next_PC + instSize;
InstSeqNum inst_seq;
MachInst inst;
ExtMachInst ext_inst;
@@ -991,10 +1090,13 @@ DefaultFetch<Impl>::fetch(bool &status_change)
// ended this fetch block.
bool predicted_branch = false;
+ // Need to keep track of whether or not a delay slot
+ // instruction has been fetched
+
for (;
offset < cacheBlkSize &&
numInst < fetchWidth &&
- !predicted_branch;
+ (!predicted_branch || delaySlotInfo[tid].numInsts > 0);
++numInst) {
// Get a sequence number.
@@ -1004,7 +1106,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
assert(offset <= cacheBlkSize - instSize);
// Get the instruction from the array of the cache line.
- inst = gtoh(*reinterpret_cast<MachInst *>
+ inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
(&cacheData[tid][offset]));
ext_inst = TheISA::makeExtMI(inst, fetch_PC);
@@ -1031,7 +1133,8 @@ DefaultFetch<Impl>::fetch(bool &status_change)
instruction->staticInst,
instruction->readPC(),tid);
- predicted_branch = lookupAndUpdateNextPC(instruction, next_PC);
+ predicted_branch = lookupAndUpdateNextPC(instruction, next_PC,
+ next_NPC);
// Add instruction to the CPU's list of instructions.
instruction->setInstListIt(cpu->addInst(instruction));
@@ -1057,7 +1160,41 @@ DefaultFetch<Impl>::fetch(bool &status_change)
break;
}
- offset+= instSize;
+ offset += instSize;
+
+#if THE_ISA != ALPHA_ISA
+ if (predicted_branch) {
+ delaySlotInfo[tid].branchSeqNum = inst_seq;
+
+ DPRINTF(Fetch, "[tid:%i]: Delay slot branch set to [sn:%i]\n",
+ tid, inst_seq);
+ continue;
+ } else if (delaySlotInfo[tid].numInsts > 0) {
+ --delaySlotInfo[tid].numInsts;
+
+ // It's OK to set PC to target of branch
+ if (delaySlotInfo[tid].numInsts == 0) {
+ delaySlotInfo[tid].targetReady = true;
+
+ // Break the looping condition
+ predicted_branch = true;
+ }
+
+ DPRINTF(Fetch, "[tid:%i]: %i delay slot inst(s) left to"
+ " process.\n", tid, delaySlotInfo[tid].numInsts);
+ }
+#endif
+ }
+
+ if (offset >= cacheBlkSize) {
+ DPRINTF(Fetch, "[tid:%i]: Done fetching, reached the end of cache "
+ "block.\n", tid);
+ } else if (numInst >= fetchWidth) {
+ DPRINTF(Fetch, "[tid:%i]: Done fetching, reached fetch bandwidth "
+ "for this cycle.\n", tid);
+ } else if (predicted_branch && delaySlotInfo[tid].numInsts <= 0) {
+ DPRINTF(Fetch, "[tid:%i]: Done fetching, predicted branch "
+ "instruction encountered.\n", tid);
}
}
@@ -1068,18 +1205,26 @@ DefaultFetch<Impl>::fetch(bool &status_change)
// Now that fetching is completed, update the PC to signify what the next
// cycle will be.
if (fault == NoFault) {
- DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n",tid, next_PC);
-
#if THE_ISA == ALPHA_ISA
+ DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n",tid, next_PC);
PC[tid] = next_PC;
nextPC[tid] = next_PC + instSize;
#else
- PC[tid] = next_PC;
- nextPC[tid] = next_PC + instSize;
- nextPC[tid] = next_PC + instSize;
+ if (delaySlotInfo[tid].targetReady &&
+ delaySlotInfo[tid].numInsts == 0) {
+ // Set PC to target
+ PC[tid] = delaySlotInfo[tid].targetAddr; //next_PC
+ nextPC[tid] = next_PC + instSize; //next_NPC
+ nextNPC[tid] = next_PC + (2 * instSize);
+
+ delaySlotInfo[tid].targetReady = false;
+ } else {
+ PC[tid] = next_PC;
+ nextPC[tid] = next_NPC;
+ nextNPC[tid] = next_NPC + instSize;
+ }
- thread->setNextPC(thread->readNextNPC());
- thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
+ DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n", tid, PC[tid]);
#endif
} else {
// We shouldn't be in an icache miss and also have a fault (an ITB
@@ -1123,9 +1268,9 @@ DefaultFetch<Impl>::fetch(bool &status_change)
fetchStatus[tid] = TrapPending;
status_change = true;
- warn("cycle %lli: fault (%d) detected @ PC %08p", curTick, fault, PC[tid]);
+ warn("cycle %lli: fault (%s) detected @ PC %08p", curTick, fault->name(), PC[tid]);
#else // !FULL_SYSTEM
- warn("cycle %lli: fault (%d) detected @ PC %08p", curTick, fault, PC[tid]);
+ warn("cycle %lli: fault (%s) detected @ PC %08p", curTick, fault->name(), PC[tid]);
#endif // FULL_SYSTEM
}
}
@@ -1202,8 +1347,8 @@ template<class Impl>
int
DefaultFetch<Impl>::roundRobin()
{
- list<unsigned>::iterator pri_iter = priorityList.begin();
- list<unsigned>::iterator end = priorityList.end();
+ std::list<unsigned>::iterator pri_iter = priorityList.begin();
+ std::list<unsigned>::iterator end = priorityList.end();
int high_pri;
@@ -1232,9 +1377,9 @@ template<class Impl>
int
DefaultFetch<Impl>::iqCount()
{
- priority_queue<unsigned> PQ;
+ std::priority_queue<unsigned> PQ;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
@@ -1262,10 +1407,10 @@ template<class Impl>
int
DefaultFetch<Impl>::lsqCount()
{
- priority_queue<unsigned> PQ;
+ std::priority_queue<unsigned> PQ;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
@@ -1293,7 +1438,7 @@ template<class Impl>
int
DefaultFetch<Impl>::branchCount()
{
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
panic("Branch Count Fetch policy unimplemented\n");
return *threads;
}
diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh
index fb9afde54..76fa008ee 100644
--- a/src/cpu/o3/iew.hh
+++ b/src/cpu/o3/iew.hh
@@ -31,11 +31,12 @@
#ifndef __CPU_O3_IEW_HH__
#define __CPU_O3_IEW_HH__
+#include "config/full_system.hh"
+
#include <queue>
#include "base/statistics.hh"
#include "base/timebuf.hh"
-#include "config/full_system.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/scoreboard.hh"
#include "cpu/o3/lsq.hh"
@@ -215,7 +216,7 @@ class DefaultIEW
if (++wbOutstanding == wbMax)
ableToIssue = false;
DPRINTF(IEW, "wbOutstanding: %i\n", wbOutstanding);
-#if DEBUG
+#ifdef DEBUG
wbList.insert(sn);
#endif
}
@@ -225,13 +226,13 @@ class DefaultIEW
if (wbOutstanding-- == wbMax)
ableToIssue = true;
DPRINTF(IEW, "wbOutstanding: %i\n", wbOutstanding);
-#if DEBUG
+#ifdef DEBUG
assert(wbList.find(sn) != wbList.end());
wbList.erase(sn);
#endif
}
-#if DEBUG
+#ifdef DEBUG
std::set<InstSeqNum> wbList;
void dumpWb()
@@ -404,6 +405,9 @@ class DefaultIEW
/** Records if there is a fetch redirect on this cycle for each thread. */
bool fetchRedirect[Impl::MaxThreads];
+ /** Keeps track of the last valid branch delay slot instss for threads */
+ InstSeqNum bdelayDoneSeqNum[Impl::MaxThreads];
+
/** Used to track if all instructions have been dispatched this cycle.
* If they have not, then blocking must have occurred, and the instructions
* would already be added to the skid buffer.
diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
index 684ae2295..cdc36c6c3 100644
--- a/src/cpu/o3/iew_impl.hh
+++ b/src/cpu/o3/iew_impl.hh
@@ -38,8 +38,6 @@
#include "cpu/o3/fu_pool.hh"
#include "cpu/o3/iew.hh"
-using namespace std;
-
template<class Impl>
DefaultIEW<Impl>::DefaultIEW(Params *params)
: issueToExecQueue(params->backComSize, params->forwardComSize),
@@ -73,6 +71,7 @@ DefaultIEW<Impl>::DefaultIEW(Params *params)
dispatchStatus[i] = Running;
stalls[i].commit = false;
fetchRedirect[i] = false;
+ bdelayDoneSeqNum[i] = 0;
}
wbMax = wbWidth * params->wbDepth;
@@ -335,7 +334,7 @@ DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
template<class Impl>
void
-DefaultIEW<Impl>::setActiveThreads(list<unsigned> *at_ptr)
+DefaultIEW<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
DPRINTF(IEW, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
@@ -428,13 +427,31 @@ DefaultIEW<Impl>::squash(unsigned tid)
instQueue.squash(tid);
// Tell the LDSTQ to start squashing.
+#if THE_ISA == ALPHA_ISA
ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
-
+#else
+ ldstQueue.squash(fromCommit->commitInfo[tid].bdelayDoneSeqNum, tid);
+#endif
updatedQueues = true;
// Clear the skid buffer in case it has any data in it.
- while (!skidBuffer[tid].empty()) {
+ DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n",
+ tid, fromCommit->commitInfo[tid].bdelayDoneSeqNum);
+ while (!skidBuffer[tid].empty()) {
+#if THE_ISA != ALPHA_ISA
+ if (skidBuffer[tid].front()->seqNum <=
+ fromCommit->commitInfo[tid].bdelayDoneSeqNum) {
+ DPRINTF(IEW, "[tid:%i]: Cannot remove skidbuffer instructions "
+ "that occur before delay slot [sn:%i].\n",
+ fromCommit->commitInfo[tid].bdelayDoneSeqNum,
+ tid);
+ break;
+ } else {
+ DPRINTF(IEW, "[tid:%i]: Removing instruction [sn:%i] from "
+ "skidBuffer.\n", tid, skidBuffer[tid].front()->seqNum);
+ }
+#endif
if (skidBuffer[tid].front()->isLoad() ||
skidBuffer[tid].front()->isStore() ) {
toRename->iewInfo[tid].dispatchedToLSQ++;
@@ -445,6 +462,8 @@ DefaultIEW<Impl>::squash(unsigned tid)
skidBuffer[tid].pop();
}
+ bdelayDoneSeqNum[tid] = fromCommit->commitInfo[tid].bdelayDoneSeqNum;
+
emptyRenameInsts(tid);
}
@@ -458,10 +477,26 @@ DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid)
toCommit->squash[tid] = true;
toCommit->squashedSeqNum[tid] = inst->seqNum;
toCommit->mispredPC[tid] = inst->readPC();
- toCommit->nextPC[tid] = inst->readNextPC();
toCommit->branchMispredict[tid] = true;
+
+#if THE_ISA == ALPHA_ISA
toCommit->branchTaken[tid] = inst->readNextPC() !=
(inst->readPC() + sizeof(TheISA::MachInst));
+ toCommit->nextPC[tid] = inst->readNextPC();
+#else
+ bool branch_taken = inst->readNextNPC() !=
+ (inst->readNextPC() + sizeof(TheISA::MachInst));
+
+ toCommit->branchTaken[tid] = branch_taken;
+
+ toCommit->condDelaySlotBranch[tid] = inst->isCondDelaySlot();
+
+ if (inst->isCondDelaySlot() && branch_taken) {
+ toCommit->nextPC[tid] = inst->readNextPC();
+ } else {
+ toCommit->nextPC[tid] = inst->readNextNPC();
+ }
+#endif
toCommit->includeSquashInst[tid] = false;
@@ -626,7 +661,7 @@ DefaultIEW<Impl>::skidCount()
{
int max=0;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned thread_count = skidBuffer[*threads++].size();
@@ -641,7 +676,7 @@ template<class Impl>
bool
DefaultIEW<Impl>::skidsEmpty()
{
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
if (!skidBuffer[*threads++].empty())
@@ -657,7 +692,7 @@ DefaultIEW<Impl>::updateStatus()
{
bool any_unblocking = false;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
threads = (*activeThreads).begin();
@@ -825,9 +860,11 @@ DefaultIEW<Impl>::sortInsts()
{
int insts_from_rename = fromRename->size;
#ifdef DEBUG
+#if THE_ISA == ALPHA_ISA
for (int i = 0; i < numThreads; i++)
assert(insts[i].empty());
#endif
+#endif
for (int i = 0; i < insts_from_rename; ++i) {
insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]);
}
@@ -837,7 +874,23 @@ template <class Impl>
void
DefaultIEW<Impl>::emptyRenameInsts(unsigned tid)
{
+ DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions until "
+ "[sn:%i].\n", tid, bdelayDoneSeqNum[tid]);
+
while (!insts[tid].empty()) {
+
+#if THE_ISA != ALPHA_ISA
+ if (insts[tid].front()->seqNum <= bdelayDoneSeqNum[tid]) {
+ DPRINTF(IEW, "[tid:%i]: Done removing, cannot remove instruction"
+ " that occurs at or before delay slot [sn:%i].\n",
+ tid, bdelayDoneSeqNum[tid]);
+ break;
+ } else {
+ DPRINTF(IEW, "[tid:%i]: Removing incoming rename instruction "
+ "[sn:%i].\n", tid, insts[tid].front()->seqNum);
+ }
+#endif
+
if (insts[tid].front()->isLoad() ||
insts[tid].front()->isStore() ) {
toRename->iewInfo[tid].dispatchedToLSQ++;
@@ -1120,7 +1173,7 @@ DefaultIEW<Impl>::dispatchInsts(unsigned tid)
}
if (!insts_to_dispatch.empty()) {
- DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n");
+ DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n", tid);
block(tid);
toRename->iewUnblock[tid] = false;
}
@@ -1140,13 +1193,13 @@ DefaultIEW<Impl>::printAvailableInsts()
{
int inst = 0;
- cout << "Available Instructions: ";
+ std::cout << "Available Instructions: ";
while (fromIssue->insts[inst]) {
- if (inst%3==0) cout << "\n\t";
+ if (inst%3==0) std::cout << "\n\t";
- cout << "PC: " << fromIssue->insts[inst]->readPC()
+ std::cout << "PC: " << fromIssue->insts[inst]->readPC()
<< " TN: " << fromIssue->insts[inst]->threadNumber
<< " SN: " << fromIssue->insts[inst]->seqNum << " | ";
@@ -1154,7 +1207,7 @@ DefaultIEW<Impl>::printAvailableInsts()
}
- cout << "\n";
+ std::cout << "\n";
}
template <class Impl>
@@ -1164,7 +1217,7 @@ DefaultIEW<Impl>::executeInsts()
wbNumInst = 0;
wbCycle = 0;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
@@ -1263,9 +1316,13 @@ DefaultIEW<Impl>::executeInsts()
fetchRedirect[tid] = true;
DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
+#if THE_ISA == ALPHA_ISA
DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
inst->nextPC);
-
+#else
+ DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
+ inst->nextNPC);
+#endif
// If incorrect, then signal the ROB that it must be squashed.
squashDueToBranch(inst, tid);
@@ -1384,7 +1441,7 @@ DefaultIEW<Impl>::tick()
// Free function units marked as being freed this cycle.
fuPool->processFreeUnits();
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
// Check stall and squash signals, dispatch any instructions.
while (threads != (*activeThreads).end()) {
diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh
index 4c69ca384..d745faf7b 100644
--- a/src/cpu/o3/inst_queue.hh
+++ b/src/cpu/o3/inst_queue.hh
@@ -26,7 +26,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
- * Korey Sewell
*/
#ifndef __CPU_O3_INST_QUEUE_HH__
diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh
index 36e0842be..e7991662b 100644
--- a/src/cpu/o3/inst_queue_impl.hh
+++ b/src/cpu/o3/inst_queue_impl.hh
@@ -37,8 +37,6 @@
#include "cpu/o3/fu_pool.hh"
#include "cpu/o3/inst_queue.hh"
-using namespace std;
-
template <class Impl>
InstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
int fu_idx,
@@ -100,7 +98,7 @@ InstructionQueue<Impl>::InstructionQueue(Params *params)
resetState();
- string policy = params->smtIQPolicy;
+ std::string policy = params->smtIQPolicy;
//Convert string to lowercase
std::transform(policy.begin(), policy.end(), policy.begin(),
@@ -279,7 +277,7 @@ InstructionQueue<Impl>::regStats()
;
for (int i=0; i<Num_OpClasses; ++i) {
- stringstream subname;
+ std::stringstream subname;
subname << opClassStrings[i] << "_delay";
issueDelayDist.subname(i, subname.str());
}
@@ -359,7 +357,7 @@ InstructionQueue<Impl>::resetState()
template <class Impl>
void
-InstructionQueue<Impl>::setActiveThreads(list<unsigned> *at_ptr)
+InstructionQueue<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
DPRINTF(IQ, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
@@ -421,8 +419,8 @@ InstructionQueue<Impl>::resetEntries()
if (iqPolicy != Dynamic || numThreads > 1) {
int active_threads = (*activeThreads).size();
- list<unsigned>::iterator threads = (*activeThreads).begin();
- list<unsigned>::iterator list_end = (*activeThreads).end();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator list_end = (*activeThreads).end();
while (threads != list_end) {
if (iqPolicy == Partitioned) {
@@ -993,7 +991,11 @@ InstructionQueue<Impl>::squash(unsigned tid)
// Read instruction sequence number of last instruction out of the
// time buffer.
+#if THE_ISA == ALPHA_ISA
squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;
+#else
+ squashedSeqNum[tid] = fromCommit->commitInfo[tid].bdelayDoneSeqNum;
+#endif
// Call doSquash if there are insts in the IQ
if (count[tid] > 0) {
diff --git a/src/cpu/o3/isa_specific.hh b/src/cpu/o3/isa_specific.hh
index f8a9dd8cc..4937589e3 100755
--- a/src/cpu/o3/isa_specific.hh
+++ b/src/cpu/o3/isa_specific.hh
@@ -35,6 +35,11 @@
#include "cpu/o3/alpha/impl.hh"
#include "cpu/o3/alpha/params.hh"
#include "cpu/o3/alpha/dyn_inst.hh"
+#elif THE_ISA == MIPS_ISA
+ #include "cpu/o3/mips/cpu.hh"
+ #include "cpu/o3/mips/impl.hh"
+ #include "cpu/o3/mips/params.hh"
+ #include "cpu/o3/mips/dyn_inst.hh"
#else
- #error "O3CPU doesnt support this ISA"
+ #error "ISA-specific header files O3CPU not defined ISA"
#endif
diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh
index d5890950f..190734dc2 100644
--- a/src/cpu/o3/lsq.hh
+++ b/src/cpu/o3/lsq.hh
@@ -70,7 +70,7 @@ class LSQ {
* to work. For now it just returns the port from one of the
* threads.
*/
- Port *getDcachePort() { return thread[0].getDcachePort(); }
+ Port *getDcachePort() { return &dcachePort; }
/** Sets the pointer to the list of active threads. */
void setActiveThreads(std::list<unsigned> *at_ptr);
@@ -258,6 +258,15 @@ class LSQ {
bool willWB(unsigned tid)
{ return thread[tid].willWB(); }
+ /** Returns if the cache is currently blocked. */
+ bool cacheBlocked()
+ { return retryTid != -1; }
+
+ /** Sets the retry thread id, indicating that one of the LSQUnits
+ * tried to access the cache but the cache was blocked. */
+ void setRetryTid(int tid)
+ { retryTid = tid; }
+
/** Debugging function to print out all instructions. */
void dumpInsts();
/** Debugging function to print out instructions from a specific thread. */
@@ -274,7 +283,49 @@ class LSQ {
template <class T>
Fault write(RequestPtr req, T &data, int store_idx);
- private:
+ /** DcachePort class for this LSQ. Handles doing the
+ * communication with the cache/memory.
+ */
+ class DcachePort : public Port
+ {
+ protected:
+ /** Pointer to LSQ. */
+ LSQ *lsq;
+
+ public:
+ /** Default constructor. */
+ DcachePort(LSQ *_lsq)
+ : lsq(_lsq)
+ { }
+
+ protected:
+ /** Atomic version of receive. Panics. */
+ virtual Tick recvAtomic(PacketPtr pkt);
+
+ /** Functional version of receive. Panics. */
+ virtual void recvFunctional(PacketPtr pkt);
+
+ /** Receives status change. Other than range changing, panics. */
+ virtual void recvStatusChange(Status status);
+
+ /** Returns the address ranges of this device. */
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+ { resp.clear(); snoop.clear(); }
+
+ /** Timing version of receive. Handles writing back and
+ * completing the load or store that has returned from
+ * memory. */
+ virtual bool recvTiming(PacketPtr pkt);
+
+ /** Handles doing a retry of the previous send. */
+ virtual void recvRetry();
+ };
+
+ /** D-cache port. */
+ DcachePort dcachePort;
+
+ protected:
/** The LSQ policy for SMT mode. */
LSQPolicy lsqPolicy;
@@ -303,6 +354,10 @@ class LSQ {
/** Number of Threads. */
unsigned numThreads;
+
+ /** The thread id of the LSQ Unit that is currently waiting for a
+ * retry. */
+ int retryTid;
};
template <class Impl>
diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh
index 89fd1a71d..db2c253e1 100644
--- a/src/cpu/o3/lsq_impl.hh
+++ b/src/cpu/o3/lsq_impl.hh
@@ -29,23 +29,66 @@
*/
#include <algorithm>
+#include <list>
#include <string>
#include "cpu/o3/lsq.hh"
-using namespace std;
+template <class Impl>
+Tick
+LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
+{
+ panic("O3CPU model does not work with atomic mode!");
+ return curTick;
+}
+
+template <class Impl>
+void
+LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
+{
+ panic("O3CPU doesn't expect recvFunctional callback!");
+}
+
+template <class Impl>
+void
+LSQ<Impl>::DcachePort::recvStatusChange(Status status)
+{
+ if (status == RangeChange)
+ return;
+
+ panic("O3CPU doesn't expect recvStatusChange callback!");
+}
+
+template <class Impl>
+bool
+LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
+{
+ lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt);
+ return true;
+}
+
+template <class Impl>
+void
+LSQ<Impl>::DcachePort::recvRetry()
+{
+ lsq->thread[lsq->retryTid].recvRetry();
+ // Speculatively clear the retry Tid. This will get set again if
+ // the LSQUnit was unable to complete its access.
+ lsq->retryTid = -1;
+}
template <class Impl>
LSQ<Impl>::LSQ(Params *params)
- : LQEntries(params->LQEntries), SQEntries(params->SQEntries),
- numThreads(params->numberOfThreads)
+ : dcachePort(this), LQEntries(params->LQEntries),
+ SQEntries(params->SQEntries), numThreads(params->numberOfThreads),
+ retryTid(-1)
{
DPRINTF(LSQ, "Creating LSQ object.\n");
//**********************************************/
//************ Handle SMT Parameters ***********/
//**********************************************/
- string policy = params->smtLSQPolicy;
+ std::string policy = params->smtLSQPolicy;
//Convert string to lowercase
std::transform(policy.begin(), policy.end(), policy.begin(),
@@ -94,7 +137,8 @@ LSQ<Impl>::LSQ(Params *params)
//Initialize LSQs
for (int tid=0; tid < numThreads; tid++) {
- thread[tid].init(params, maxLQEntries, maxSQEntries, tid);
+ thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid);
+ thread[tid].setDcachePort(&dcachePort);
}
}
@@ -118,7 +162,7 @@ LSQ<Impl>::regStats()
template<class Impl>
void
-LSQ<Impl>::setActiveThreads(list<unsigned> *at_ptr)
+LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
activeThreads = at_ptr;
assert(activeThreads != 0);
@@ -130,6 +174,8 @@ LSQ<Impl>::setCPU(O3CPU *cpu_ptr)
{
cpu = cpu_ptr;
+ dcachePort.setName(name());
+
for (int tid=0; tid < numThreads; tid++) {
thread[tid].setCPU(cpu_ptr);
}
@@ -182,8 +228,8 @@ LSQ<Impl>::resetEntries()
if (lsqPolicy != Dynamic || numThreads > 1) {
int active_threads = (*activeThreads).size();
- list<unsigned>::iterator threads = (*activeThreads).begin();
- list<unsigned>::iterator list_end = (*activeThreads).end();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator list_end = (*activeThreads).end();
int maxEntries;
@@ -221,7 +267,7 @@ template<class Impl>
void
LSQ<Impl>::tick()
{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -270,7 +316,7 @@ template<class Impl>
void
LSQ<Impl>::writebackStores()
{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -289,7 +335,7 @@ bool
LSQ<Impl>::violation()
{
/* Answers: Does Anybody Have a Violation?*/
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -306,7 +352,7 @@ LSQ<Impl>::getCount()
{
unsigned total = 0;
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -322,7 +368,7 @@ LSQ<Impl>::numLoads()
{
unsigned total = 0;
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -338,7 +384,7 @@ LSQ<Impl>::numStores()
{
unsigned total = 0;
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -354,7 +400,7 @@ LSQ<Impl>::numLoadsReady()
{
unsigned total = 0;
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -370,7 +416,7 @@ LSQ<Impl>::numFreeEntries()
{
unsigned total = 0;
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -394,7 +440,7 @@ template<class Impl>
bool
LSQ<Impl>::isFull()
{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -421,7 +467,7 @@ template<class Impl>
bool
LSQ<Impl>::lqFull()
{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -448,7 +494,7 @@ template<class Impl>
bool
LSQ<Impl>::sqFull()
{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -475,7 +521,7 @@ template<class Impl>
bool
LSQ<Impl>::isStalled()
{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -500,7 +546,7 @@ template<class Impl>
bool
LSQ<Impl>::hasStoresToWB()
{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
if ((*activeThreads).empty())
return false;
@@ -518,7 +564,7 @@ template<class Impl>
bool
LSQ<Impl>::willWB()
{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
@@ -533,7 +579,7 @@ template<class Impl>
void
LSQ<Impl>::dumpInsts()
{
- list<unsigned>::iterator active_threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator active_threads = (*activeThreads).begin();
while (active_threads != (*activeThreads).end()) {
unsigned tid = *active_threads++;
diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh
index 4d7a8350b..512b5a63c 100644
--- a/src/cpu/o3/lsq_unit.hh
+++ b/src/cpu/o3/lsq_unit.hh
@@ -64,6 +64,7 @@ class LSQUnit {
typedef typename Impl::O3CPU O3CPU;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::CPUPol::IEW IEW;
+ typedef typename Impl::CPUPol::LSQ LSQ;
typedef typename Impl::CPUPol::IssueStruct IssueStruct;
public:
@@ -71,17 +72,12 @@ class LSQUnit {
LSQUnit();
/** Initializes the LSQ unit with the specified number of entries. */
- void init(Params *params, unsigned maxLQEntries,
+ void init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
unsigned maxSQEntries, unsigned id);
/** Returns the name of the LSQ unit. */
std::string name() const;
- /** Returns the dcache port.
- * @todo: Remove this once the port moves up to the LSQ level.
- */
- Port *getDcachePort() { return dcachePort; }
-
/** Registers statistics. */
void regStats();
@@ -92,6 +88,10 @@ class LSQUnit {
void setIEW(IEW *iew_ptr)
{ iewStage = iew_ptr; }
+ /** Sets the pointer to the dcache port. */
+ void setDcachePort(Port *dcache_port)
+ { dcachePort = dcache_port; }
+
/** Switches out LSQ unit. */
void switchOut();
@@ -211,6 +211,9 @@ class LSQUnit {
!storeQueue[storeWBIdx].completed &&
!isStoreBlocked; }
+ /** Handles doing the retry. */
+ void recvRetry();
+
private:
/** Writes back the instruction, sending it to IEW. */
void writeback(DynInstPtr &inst, PacketPtr pkt);
@@ -221,9 +224,6 @@ class LSQUnit {
/** Completes the store at the specified index. */
void completeStore(int store_idx);
- /** Handles doing the retry. */
- void recvRetry();
-
/** Increments the given store index (circular queue). */
inline void incrStIdx(int &store_idx);
/** Decrements the given store index (circular queue). */
@@ -244,54 +244,11 @@ class LSQUnit {
/** Pointer to the IEW stage. */
IEW *iewStage;
- /** Pointer to memory object. */
- MemObject *mem;
+ /** Pointer to the LSQ. */
+ LSQ *lsq;
- /** DcachePort class for this LSQ Unit. Handles doing the
- * communication with the cache/memory.
- * @todo: Needs to be moved to the LSQ level and have some sort
- * of arbitration.
- */
- class DcachePort : public Port
- {
- protected:
- /** Pointer to CPU. */
- O3CPU *cpu;
- /** Pointer to LSQ. */
- LSQUnit *lsq;
-
- public:
- /** Default constructor. */
- DcachePort(O3CPU *_cpu, LSQUnit *_lsq)
- : Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq)
- { }
-
- protected:
- /** Atomic version of receive. Panics. */
- virtual Tick recvAtomic(PacketPtr pkt);
-
- /** Functional version of receive. Panics. */
- virtual void recvFunctional(PacketPtr pkt);
-
- /** Receives status change. Other than range changing, panics. */
- virtual void recvStatusChange(Status status);
-
- /** Returns the address ranges of this device. */
- virtual void getDeviceAddressRanges(AddrRangeList &resp,
- AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); }
-
- /** Timing version of receive. Handles writing back and
- * completing the load or store that has returned from
- * memory. */
- virtual bool recvTiming(PacketPtr pkt);
-
- /** Handles doing a retry of the previous send. */
- virtual void recvRetry();
- };
-
- /** Pointer to the D-cache. */
- DcachePort *dcachePort;
+ /** Pointer to the dcache port. Used only for sending. */
+ Port *dcachePort;
/** Derived class to hold any sender state the LSQ needs. */
class LSQSenderState : public Packet::SenderState
@@ -644,6 +601,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
// Tell IQ/mem dep unit that this instruction will need to be
// rescheduled eventually
iewStage->rescheduleMemInst(load_inst);
+ iewStage->decrWb(load_inst->seqNum);
++lsqRescheduledLoads;
// Do not generate a writeback event as this instruction is not
@@ -658,7 +616,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
}
// If there's no forwarding case, then go access memory
- DPRINTF(LSQUnit, "Doing functional access for inst [sn:%lli] PC %#x\n",
+ DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n",
load_inst->seqNum, load_inst->readPC());
assert(!load_inst->memData);
@@ -666,9 +624,6 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
++usedPorts;
- DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
- load_inst->readPC());
-
PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
data_pkt->dataStatic(load_inst->memData);
@@ -678,8 +633,18 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
state->inst = load_inst;
data_pkt->senderState = state;
- // if we have a cache, do cache access too
- if (!dcachePort->sendTiming(data_pkt)) {
+ // if we the cache is not blocked, do cache access
+ if (!lsq->cacheBlocked()) {
+ if (!dcachePort->sendTiming(data_pkt)) {
+ // If the access didn't succeed, tell the LSQ by setting
+ // the retry thread id.
+ lsq->setRetryTid(lsqID);
+ }
+ }
+
+ // If the cache was blocked, or has become blocked due to the access,
+ // handle it.
+ if (lsq->cacheBlocked()) {
++lsqCacheBlocked;
// There's an older load that's already going to squash.
if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index 8e951534f..4f5dbbf1c 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -31,6 +31,7 @@
#include "config/use_checker.hh"
+#include "cpu/o3/lsq.hh"
#include "cpu/o3/lsq_unit.hh"
#include "base/str.hh"
#include "mem/packet.hh"
@@ -96,46 +97,6 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
}
template <class Impl>
-Tick
-LSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
-{
- panic("O3CPU model does not work with atomic mode!");
- return curTick;
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
-{
- panic("O3CPU doesn't expect recvFunctional callback!");
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::DcachePort::recvStatusChange(Status status)
-{
- if (status == RangeChange)
- return;
-
- panic("O3CPU doesn't expect recvStatusChange callback!");
-}
-
-template <class Impl>
-bool
-LSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt)
-{
- lsq->completeDataAccess(pkt);
- return true;
-}
-
-template <class Impl>
-void
-LSQUnit<Impl>::DcachePort::recvRetry()
-{
- lsq->recvRetry();
-}
-
-template <class Impl>
LSQUnit<Impl>::LSQUnit()
: loads(0), stores(0), storesToWB(0), stalled(false),
isStoreBlocked(false), isLoadBlocked(false),
@@ -145,13 +106,15 @@ LSQUnit<Impl>::LSQUnit()
template<class Impl>
void
-LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
+LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
unsigned maxSQEntries, unsigned id)
{
DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
switchedOut = false;
+ lsq = lsq_ptr;
+
lsqID = id;
// Add 1 for the sentinel entry (they are circular queues).
@@ -168,8 +131,6 @@ LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
usedPorts = 0;
cachePorts = params->cachePorts;
- mem = params->mem;
-
memDepViolator = NULL;
blockedLoadSeqNum = 0;
@@ -180,7 +141,6 @@ void
LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr)
{
cpu = cpu_ptr;
- dcachePort = new DcachePort(cpu, this);
#if USE_CHECKER
if (cpu->checker) {
@@ -588,7 +548,7 @@ LSQUnit<Impl>::writebackStores()
storeQueue[storeWBIdx].canWB &&
usedPorts < cachePorts) {
- if (isStoreBlocked) {
+ if (isStoreBlocked || lsq->cacheBlocked()) {
DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
" is blocked!\n");
break;
@@ -830,6 +790,7 @@ LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt)
// Squashed instructions do not need to complete their access.
if (inst->isSquashed()) {
+ iewStage->decrWb(inst->seqNum);
assert(!inst->isStore());
++lsqIgnoredResponses;
return;
@@ -911,6 +872,7 @@ LSQUnit<Impl>::recvRetry()
} else {
// Still blocked!
++lsqCacheBlocked;
+ lsq->setRetryTid(lsqID);
}
} else if (isLoadBlocked) {
DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "
diff --git a/src/cpu/o3/mips/cpu.cc b/src/cpu/o3/mips/cpu.cc
new file mode 100755
index 000000000..420f460b2
--- /dev/null
+++ b/src/cpu/o3/mips/cpu.cc
@@ -0,0 +1,39 @@
+/*
+ * 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: Kevin Lim
+ * Korey Sewell
+ */
+
+#include "cpu/o3/mips/impl.hh"
+#include "cpu/o3/mips/cpu_impl.hh"
+#include "cpu/o3/mips/dyn_inst.hh"
+
+// Force instantiation of MipsO3CPU for all the implemntations that are
+// needed. Consider merging this and mips_dyn_inst.cc, and maybe all
+// classes that depend on a certain impl, into one file (mips_impl.cc?).
+template class MipsO3CPU<MipsSimpleImpl>;
diff --git a/src/cpu/o3/mips/cpu.hh b/src/cpu/o3/mips/cpu.hh
new file mode 100755
index 000000000..bf04b9f69
--- /dev/null
+++ b/src/cpu/o3/mips/cpu.hh
@@ -0,0 +1,149 @@
+/*
+ * 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: Kevin Lim
+ * Korey Sewell
+ */
+
+#ifndef __CPU_O3_MIPS_CPU_HH__
+#define __CPU_O3_MIPS_CPU_HH__
+
+#include "arch/mips/regfile.hh"
+#include "arch/mips/syscallreturn.hh"
+#include "cpu/thread_context.hh"
+#include "cpu/o3/cpu.hh"
+#include "sim/byteswap.hh"
+#include "sim/faults.hh"
+
+class EndQuiesceEvent;
+namespace Kernel {
+ class Statistics;
+};
+
+class TranslatingPort;
+
+/**
+ * MipsO3CPU class. Derives from the FullO3CPU class, and
+ * implements all ISA and implementation specific functions of the
+ * CPU. This is the CPU class that is used for the SimObjects, and is
+ * what is given to the DynInsts. Most of its state exists in the
+ * FullO3CPU; the state is has is mainly for ISA specific
+ * functionality.
+ */
+template <class Impl>
+class MipsO3CPU : public FullO3CPU<Impl>
+{
+ public:
+ typedef O3ThreadState<Impl> ImplState;
+ typedef O3ThreadState<Impl> Thread;
+ typedef typename Impl::Params Params;
+
+ /** Constructs an MipsO3CPU with the given parameters. */
+ MipsO3CPU(Params *params);
+
+ /** Registers statistics. */
+ void regStats();
+
+ /** Translates instruction requestion in syscall emulation mode. */
+ Fault translateInstReq(RequestPtr &req, Thread *thread)
+ {
+ return thread->getProcessPtr()->pTable->translate(req);
+ }
+
+ /** Translates data read request in syscall emulation mode. */
+ Fault translateDataReadReq(RequestPtr &req, Thread *thread)
+ {
+ return thread->getProcessPtr()->pTable->translate(req);
+ }
+
+ /** Translates data write request in syscall emulation mode. */
+ Fault translateDataWriteReq(RequestPtr &req, Thread *thread)
+ {
+ return thread->getProcessPtr()->pTable->translate(req);
+ }
+
+ /** Reads a miscellaneous register. */
+ TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid);
+
+ /** Reads a misc. register, including any side effects the read
+ * might have as defined by the architecture.
+ */
+ TheISA::MiscReg readMiscRegWithEffect(int misc_reg,
+ Fault &fault, unsigned tid);
+
+ /** Sets a miscellaneous register. */
+ Fault setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid);
+
+ /** Sets a misc. register, including any side effects the write
+ * might have as defined by the architecture.
+ */
+ Fault setMiscRegWithEffect(int misc_reg,
+ const TheISA::MiscReg &val, unsigned tid);
+
+ /** Initiates a squash of all in-flight instructions for a given
+ * thread. The source of the squash is an external update of
+ * state through the TC.
+ */
+ void squashFromTC(unsigned tid);
+
+ /** Traps to handle given fault. */
+ void trap(Fault fault, unsigned tid);
+
+ /** Executes a syscall.
+ * @todo: Determine if this needs to be virtual.
+ */
+ void syscall(int64_t callnum, int tid);
+ /** Gets a syscall argument. */
+ TheISA::IntReg getSyscallArg(int i, int tid);
+
+ /** Used to shift args for indirect syscall. */
+ void setSyscallArg(int i, TheISA::IntReg val, int tid);
+
+ /** Sets the return value of a syscall. */
+ void setSyscallReturn(SyscallReturn return_value, int tid);
+
+ /** CPU read function, forwards read to LSQ. */
+ template <class T>
+ Fault read(RequestPtr &req, T &data, int load_idx)
+ {
+ return this->iew.ldstQueue.read(req, data, load_idx);
+ }
+
+ /** CPU write function, forwards write to LSQ. */
+ template <class T>
+ Fault write(RequestPtr &req, T &data, int store_idx)
+ {
+ return this->iew.ldstQueue.write(req, data, store_idx);
+ }
+
+ Addr lockAddr;
+
+ /** Temporary fix for the lock flag, works in the UP case. */
+ bool lockFlag;
+};
+
+#endif // __CPU_O3_MIPS_CPU_HH__
diff --git a/src/cpu/o3/mips/cpu_builder.cc b/src/cpu/o3/mips/cpu_builder.cc
new file mode 100644
index 000000000..f1c3b33a5
--- /dev/null
+++ b/src/cpu/o3/mips/cpu_builder.cc
@@ -0,0 +1,394 @@
+/*
+ * 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: Kevin Lim
+ * Korey Sewell
+ */
+
+#include <string>
+
+#include "cpu/base.hh"
+#include "cpu/o3/mips/cpu.hh"
+#include "cpu/o3/mips/impl.hh"
+#include "cpu/o3/mips/params.hh"
+#include "cpu/o3/fu_pool.hh"
+#include "sim/builder.hh"
+
+class DerivO3CPU : public MipsO3CPU<MipsSimpleImpl>
+{
+ public:
+ DerivO3CPU(MipsSimpleParams *p)
+ : MipsO3CPU<MipsSimpleImpl>(p)
+ { }
+};
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
+
+Param<int> clock;
+Param<int> numThreads;
+Param<int> activity;
+
+SimObjectVectorParam<Process *> workload;
+
+SimObjectParam<MemObject *> mem;
+
+SimObjectParam<BaseCPU *> checker;
+
+Param<Counter> max_insts_any_thread;
+Param<Counter> max_insts_all_threads;
+Param<Counter> max_loads_any_thread;
+Param<Counter> max_loads_all_threads;
+
+Param<unsigned> cachePorts;
+
+Param<unsigned> decodeToFetchDelay;
+Param<unsigned> renameToFetchDelay;
+Param<unsigned> iewToFetchDelay;
+Param<unsigned> commitToFetchDelay;
+Param<unsigned> fetchWidth;
+
+Param<unsigned> renameToDecodeDelay;
+Param<unsigned> iewToDecodeDelay;
+Param<unsigned> commitToDecodeDelay;
+Param<unsigned> fetchToDecodeDelay;
+Param<unsigned> decodeWidth;
+
+Param<unsigned> iewToRenameDelay;
+Param<unsigned> commitToRenameDelay;
+Param<unsigned> decodeToRenameDelay;
+Param<unsigned> renameWidth;
+
+Param<unsigned> commitToIEWDelay;
+Param<unsigned> renameToIEWDelay;
+Param<unsigned> issueToExecuteDelay;
+Param<unsigned> dispatchWidth;
+Param<unsigned> issueWidth;
+Param<unsigned> wbWidth;
+Param<unsigned> wbDepth;
+SimObjectParam<FUPool *> fuPool;
+
+Param<unsigned> iewToCommitDelay;
+Param<unsigned> renameToROBDelay;
+Param<unsigned> commitWidth;
+Param<unsigned> squashWidth;
+Param<Tick> trapLatency;
+
+Param<unsigned> backComSize;
+Param<unsigned> forwardComSize;
+
+Param<std::string> predType;
+Param<unsigned> localPredictorSize;
+Param<unsigned> localCtrBits;
+Param<unsigned> localHistoryTableSize;
+Param<unsigned> localHistoryBits;
+Param<unsigned> globalPredictorSize;
+Param<unsigned> globalCtrBits;
+Param<unsigned> globalHistoryBits;
+Param<unsigned> choicePredictorSize;
+Param<unsigned> choiceCtrBits;
+
+Param<unsigned> BTBEntries;
+Param<unsigned> BTBTagSize;
+
+Param<unsigned> RASSize;
+
+Param<unsigned> LQEntries;
+Param<unsigned> SQEntries;
+Param<unsigned> LFSTSize;
+Param<unsigned> SSITSize;
+
+Param<unsigned> numPhysIntRegs;
+Param<unsigned> numPhysFloatRegs;
+Param<unsigned> numIQEntries;
+Param<unsigned> numROBEntries;
+
+Param<unsigned> smtNumFetchingThreads;
+Param<std::string> smtFetchPolicy;
+Param<std::string> smtLSQPolicy;
+Param<unsigned> smtLSQThreshold;
+Param<std::string> smtIQPolicy;
+Param<unsigned> smtIQThreshold;
+Param<std::string> smtROBPolicy;
+Param<unsigned> smtROBThreshold;
+Param<std::string> smtCommitPolicy;
+
+Param<unsigned> instShiftAmt;
+
+Param<bool> defer_registration;
+
+Param<bool> function_trace;
+Param<Tick> function_trace_start;
+
+END_DECLARE_SIM_OBJECT_PARAMS(DerivO3CPU)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
+
+ INIT_PARAM(clock, "clock speed"),
+ INIT_PARAM(numThreads, "number of HW thread contexts"),
+ INIT_PARAM_DFLT(activity, "Initial activity count", 0),
+
+ INIT_PARAM(workload, "Processes to run"),
+
+ INIT_PARAM(mem, "Memory"),
+
+ INIT_PARAM_DFLT(checker, "Checker CPU", NULL),
+
+ INIT_PARAM_DFLT(max_insts_any_thread,
+ "Terminate when any thread reaches this inst count",
+ 0),
+ INIT_PARAM_DFLT(max_insts_all_threads,
+ "Terminate when all threads have reached"
+ "this inst count",
+ 0),
+ INIT_PARAM_DFLT(max_loads_any_thread,
+ "Terminate when any thread reaches this load count",
+ 0),
+ INIT_PARAM_DFLT(max_loads_all_threads,
+ "Terminate when all threads have reached this load"
+ "count",
+ 0),
+
+ INIT_PARAM_DFLT(cachePorts, "Cache Ports", 200),
+
+ INIT_PARAM(decodeToFetchDelay, "Decode to fetch delay"),
+ INIT_PARAM(renameToFetchDelay, "Rename to fetch delay"),
+ INIT_PARAM(iewToFetchDelay, "Issue/Execute/Writeback to fetch"
+ "delay"),
+ INIT_PARAM(commitToFetchDelay, "Commit to fetch delay"),
+ INIT_PARAM(fetchWidth, "Fetch width"),
+ INIT_PARAM(renameToDecodeDelay, "Rename to decode delay"),
+ INIT_PARAM(iewToDecodeDelay, "Issue/Execute/Writeback to decode"
+ "delay"),
+ INIT_PARAM(commitToDecodeDelay, "Commit to decode delay"),
+ INIT_PARAM(fetchToDecodeDelay, "Fetch to decode delay"),
+ INIT_PARAM(decodeWidth, "Decode width"),
+
+ INIT_PARAM(iewToRenameDelay, "Issue/Execute/Writeback to rename"
+ "delay"),
+ INIT_PARAM(commitToRenameDelay, "Commit to rename delay"),
+ INIT_PARAM(decodeToRenameDelay, "Decode to rename delay"),
+ INIT_PARAM(renameWidth, "Rename width"),
+
+ INIT_PARAM(commitToIEWDelay, "Commit to "
+ "Issue/Execute/Writeback delay"),
+ INIT_PARAM(renameToIEWDelay, "Rename to "
+ "Issue/Execute/Writeback delay"),
+ INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
+ "to the IEW stage)"),
+ INIT_PARAM(dispatchWidth, "Dispatch width"),
+ INIT_PARAM(issueWidth, "Issue width"),
+ INIT_PARAM(wbWidth, "Writeback width"),
+ INIT_PARAM(wbDepth, "Writeback depth (number of cycles it can buffer)"),
+ INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL),
+
+ INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
+ "delay"),
+ INIT_PARAM(renameToROBDelay, "Rename to reorder buffer delay"),
+ INIT_PARAM(commitWidth, "Commit width"),
+ INIT_PARAM(squashWidth, "Squash width"),
+ INIT_PARAM_DFLT(trapLatency, "Number of cycles before the trap is handled", 6),
+
+ INIT_PARAM(backComSize, "Time buffer size for backwards communication"),
+ INIT_PARAM(forwardComSize, "Time buffer size for forward communication"),
+
+ INIT_PARAM(predType, "Type of branch predictor ('local', 'tournament')"),
+ INIT_PARAM(localPredictorSize, "Size of local predictor"),
+ INIT_PARAM(localCtrBits, "Bits per counter"),
+ INIT_PARAM(localHistoryTableSize, "Size of local history table"),
+ INIT_PARAM(localHistoryBits, "Bits for the local history"),
+ INIT_PARAM(globalPredictorSize, "Size of global predictor"),
+ INIT_PARAM(globalCtrBits, "Bits per counter"),
+ INIT_PARAM(globalHistoryBits, "Bits of history"),
+ INIT_PARAM(choicePredictorSize, "Size of choice predictor"),
+ INIT_PARAM(choiceCtrBits, "Bits of choice counters"),
+
+ INIT_PARAM(BTBEntries, "Number of BTB entries"),
+ INIT_PARAM(BTBTagSize, "Size of the BTB tags, in bits"),
+
+ INIT_PARAM(RASSize, "RAS size"),
+
+ INIT_PARAM(LQEntries, "Number of load queue entries"),
+ INIT_PARAM(SQEntries, "Number of store queue entries"),
+ INIT_PARAM(LFSTSize, "Last fetched store table size"),
+ INIT_PARAM(SSITSize, "Store set ID table size"),
+
+ INIT_PARAM(numPhysIntRegs, "Number of physical integer registers"),
+ INIT_PARAM(numPhysFloatRegs, "Number of physical floating point "
+ "registers"),
+ INIT_PARAM(numIQEntries, "Number of instruction queue entries"),
+ INIT_PARAM(numROBEntries, "Number of reorder buffer entries"),
+
+ INIT_PARAM_DFLT(smtNumFetchingThreads, "SMT Number of Fetching Threads", 1),
+ INIT_PARAM_DFLT(smtFetchPolicy, "SMT Fetch Policy", "SingleThread"),
+ INIT_PARAM_DFLT(smtLSQPolicy, "SMT LSQ Sharing Policy", "Partitioned"),
+ INIT_PARAM_DFLT(smtLSQThreshold,"SMT LSQ Threshold", 100),
+ INIT_PARAM_DFLT(smtIQPolicy, "SMT IQ Policy", "Partitioned"),
+ INIT_PARAM_DFLT(smtIQThreshold, "SMT IQ Threshold", 100),
+ INIT_PARAM_DFLT(smtROBPolicy, "SMT ROB Sharing Policy", "Partitioned"),
+ INIT_PARAM_DFLT(smtROBThreshold,"SMT ROB Threshold", 100),
+ INIT_PARAM_DFLT(smtCommitPolicy,"SMT Commit Fetch Policy", "RoundRobin"),
+
+ INIT_PARAM(instShiftAmt, "Number of bits to shift instructions by"),
+ INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
+
+ INIT_PARAM(function_trace, "Enable function trace"),
+ INIT_PARAM(function_trace_start, "Cycle to start function trace")
+
+END_INIT_SIM_OBJECT_PARAMS(DerivO3CPU)
+
+CREATE_SIM_OBJECT(DerivO3CPU)
+{
+ DerivO3CPU *cpu;
+
+ // In non-full-system mode, we infer the number of threads from
+ // the workload if it's not explicitly specified.
+ int actual_num_threads =
+ (numThreads.isValid() && numThreads >= workload.size()) ?
+ numThreads : workload.size();
+
+ if (workload.size() == 0) {
+ fatal("Must specify at least one workload!");
+ }
+
+ MipsSimpleParams *params = new MipsSimpleParams;
+
+ params->clock = clock;
+
+ params->name = getInstanceName();
+ params->numberOfThreads = actual_num_threads;
+ params->activity = activity;
+
+ params->workload = workload;
+
+ params->mem = mem;
+
+ params->checker = checker;
+
+ params->max_insts_any_thread = max_insts_any_thread;
+ params->max_insts_all_threads = max_insts_all_threads;
+ params->max_loads_any_thread = max_loads_any_thread;
+ params->max_loads_all_threads = max_loads_all_threads;
+
+ //
+ // Caches
+ //
+ params->cachePorts = cachePorts;
+
+ params->decodeToFetchDelay = decodeToFetchDelay;
+ params->renameToFetchDelay = renameToFetchDelay;
+ params->iewToFetchDelay = iewToFetchDelay;
+ params->commitToFetchDelay = commitToFetchDelay;
+ params->fetchWidth = fetchWidth;
+
+ params->renameToDecodeDelay = renameToDecodeDelay;
+ params->iewToDecodeDelay = iewToDecodeDelay;
+ params->commitToDecodeDelay = commitToDecodeDelay;
+ params->fetchToDecodeDelay = fetchToDecodeDelay;
+ params->decodeWidth = decodeWidth;
+
+ params->iewToRenameDelay = iewToRenameDelay;
+ params->commitToRenameDelay = commitToRenameDelay;
+ params->decodeToRenameDelay = decodeToRenameDelay;
+ params->renameWidth = renameWidth;
+
+ params->commitToIEWDelay = commitToIEWDelay;
+ params->renameToIEWDelay = renameToIEWDelay;
+ params->issueToExecuteDelay = issueToExecuteDelay;
+ params->dispatchWidth = dispatchWidth;
+ params->issueWidth = issueWidth;
+ params->wbWidth = wbWidth;
+ params->wbDepth = wbDepth;
+ params->fuPool = fuPool;
+
+ params->iewToCommitDelay = iewToCommitDelay;
+ params->renameToROBDelay = renameToROBDelay;
+ params->commitWidth = commitWidth;
+ params->squashWidth = squashWidth;
+ params->trapLatency = trapLatency;
+
+ params->backComSize = backComSize;
+ params->forwardComSize = forwardComSize;
+
+ params->predType = predType;
+ params->localPredictorSize = localPredictorSize;
+ params->localCtrBits = localCtrBits;
+ params->localHistoryTableSize = localHistoryTableSize;
+ params->localHistoryBits = localHistoryBits;
+ params->globalPredictorSize = globalPredictorSize;
+ params->globalCtrBits = globalCtrBits;
+ params->globalHistoryBits = globalHistoryBits;
+ params->choicePredictorSize = choicePredictorSize;
+ params->choiceCtrBits = choiceCtrBits;
+
+ params->BTBEntries = BTBEntries;
+ params->BTBTagSize = BTBTagSize;
+
+ params->RASSize = RASSize;
+
+ params->LQEntries = LQEntries;
+ params->SQEntries = SQEntries;
+
+ params->SSITSize = SSITSize;
+ params->LFSTSize = LFSTSize;
+
+ params->numPhysIntRegs = numPhysIntRegs;
+ params->numPhysFloatRegs = numPhysFloatRegs;
+ params->numIQEntries = numIQEntries;
+ params->numROBEntries = numROBEntries;
+
+ params->smtNumFetchingThreads = smtNumFetchingThreads;
+
+ // Default smtFetchPolicy to "RoundRobin", if necessary.
+ std::string round_robin_policy = "RoundRobin";
+ std::string single_thread = "SingleThread";
+
+ if (actual_num_threads > 1 && single_thread.compare(smtFetchPolicy) == 0)
+ params->smtFetchPolicy = round_robin_policy;
+ else
+ params->smtFetchPolicy = smtFetchPolicy;
+
+ params->smtIQPolicy = smtIQPolicy;
+ params->smtLSQPolicy = smtLSQPolicy;
+ params->smtLSQThreshold = smtLSQThreshold;
+ params->smtROBPolicy = smtROBPolicy;
+ params->smtROBThreshold = smtROBThreshold;
+ params->smtCommitPolicy = smtCommitPolicy;
+
+ params->instShiftAmt = 2;
+
+ params->deferRegistration = defer_registration;
+
+ params->functionTrace = function_trace;
+ params->functionTraceStart = function_trace_start;
+
+ cpu = new DerivO3CPU(params);
+
+ return cpu;
+}
+
+REGISTER_SIM_OBJECT("DerivO3CPU", DerivO3CPU)
+
diff --git a/src/cpu/o3/mips/cpu_impl.hh b/src/cpu/o3/mips/cpu_impl.hh
new file mode 100644
index 000000000..e08741626
--- /dev/null
+++ b/src/cpu/o3/mips/cpu_impl.hh
@@ -0,0 +1,250 @@
+/*
+ * 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: Kevin Lim
+ * Korey Sewell
+ */
+
+#include "config/use_checker.hh"
+
+#include "arch/mips/faults.hh"
+#include "base/cprintf.hh"
+#include "base/statistics.hh"
+#include "base/timebuf.hh"
+#include "cpu/checker/thread_context.hh"
+#include "sim/sim_events.hh"
+#include "sim/stats.hh"
+
+#include "cpu/o3/mips/cpu.hh"
+#include "cpu/o3/mips/params.hh"
+#include "cpu/o3/mips/thread_context.hh"
+#include "cpu/o3/comm.hh"
+#include "cpu/o3/thread_state.hh"
+
+template <class Impl>
+MipsO3CPU<Impl>::MipsO3CPU(Params *params)
+ : FullO3CPU<Impl>(params)
+{
+ DPRINTF(O3CPU, "Creating MipsO3CPU object.\n");
+
+ // Setup any thread state.
+ this->thread.resize(this->numThreads);
+
+ for (int i = 0; i < this->numThreads; ++i) {
+ if (i < params->workload.size()) {
+ DPRINTF(O3CPU, "Workload[%i] process is %#x",
+ i, this->thread[i]);
+ this->thread[i] = new Thread(this, i, params->workload[i],
+ i, params->mem);
+
+ this->thread[i]->setStatus(ThreadContext::Suspended);
+
+
+ /* Use this port to for syscall emulation writes to memory. */
+ Port *mem_port;
+ TranslatingPort *trans_port;
+ trans_port = new TranslatingPort(csprintf("%s-%d-funcport",
+ name(), i),
+ params->workload[i]->pTable,
+ false);
+ mem_port = params->mem->getPort("functional");
+ mem_port->setPeer(trans_port);
+ trans_port->setPeer(mem_port);
+ this->thread[i]->setMemPort(trans_port);
+
+ //usedTids[i] = true;
+ //threadMap[i] = i;
+ } else {
+ //Allocate Empty thread so M5 can use later
+ //when scheduling threads to CPU
+ Process* dummy_proc = NULL;
+
+ this->thread[i] = new Thread(this, i, dummy_proc, i, params->mem);
+ //usedTids[i] = false;
+ }
+
+ ThreadContext *tc;
+
+ // Setup the TC that will serve as the interface to the threads/CPU.
+ MipsTC<Impl> *mips_tc =
+ new MipsTC<Impl>;
+
+ tc = mips_tc;
+
+ // If we're using a checker, then the TC should be the
+ // CheckerThreadContext.
+#if USE_CHECKER
+ if (params->checker) {
+ tc = new CheckerThreadContext<MipsTC<Impl> >(
+ mips_tc, this->checker);
+ }
+#endif
+
+ mips_tc->cpu = this;
+ mips_tc->thread = this->thread[i];
+
+ // Give the thread the TC.
+ this->thread[i]->tc = tc;
+
+ // Add the TC to the CPU's list of TC's.
+ this->threadContexts.push_back(tc);
+ }
+
+ for (int i=0; i < this->numThreads; i++) {
+ 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;
+}
+
+template <class Impl>
+void
+MipsO3CPU<Impl>::regStats()
+{
+ // Register stats for everything that has stats.
+ this->fullCPURegStats();
+ this->fetch.regStats();
+ this->decode.regStats();
+ this->rename.regStats();
+ this->iew.regStats();
+ this->commit.regStats();
+}
+
+
+template <class Impl>
+MiscReg
+MipsO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
+{
+ return this->regFile.readMiscReg(misc_reg, tid);
+}
+
+template <class Impl>
+MiscReg
+MipsO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
+ unsigned tid)
+{
+ return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
+}
+
+template <class Impl>
+Fault
+MipsO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
+{
+ return this->regFile.setMiscReg(misc_reg, val, tid);
+}
+
+template <class Impl>
+Fault
+MipsO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
+ unsigned tid)
+{
+ return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
+}
+
+template <class Impl>
+void
+MipsO3CPU<Impl>::squashFromTC(unsigned tid)
+{
+ this->thread[tid]->inSyscall = true;
+ this->commit.generateTCEvent(tid);
+}
+
+template <class Impl>
+void
+MipsO3CPU<Impl>::trap(Fault fault, unsigned tid)
+{
+ // Pass the thread's TC into the invoke method.
+ fault->invoke(this->threadContexts[tid]);
+}
+
+#if !FULL_SYSTEM
+
+template <class Impl>
+void
+MipsO3CPU<Impl>::syscall(int64_t callnum, int tid)
+{
+ DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
+
+ DPRINTF(Activity,"Activity: syscall() called.\n");
+
+ // Temporarily increase this by one to account for the syscall
+ // instruction.
+ ++(this->thread[tid]->funcExeInst);
+
+ // Execute the actual syscall.
+ this->thread[tid]->syscall(callnum);
+
+ // Decrease funcExeInst by one as the normal commit will handle
+ // incrementing it.
+ --(this->thread[tid]->funcExeInst);
+
+ DPRINTF(O3CPU, "[tid:%i] Register 2 is %i ", tid, this->readIntReg(2));
+}
+
+template <class Impl>
+TheISA::IntReg
+MipsO3CPU<Impl>::getSyscallArg(int i, int tid)
+{
+ return this->readArchIntReg(MipsISA::ArgumentReg0 + i, tid);
+}
+
+template <class Impl>
+void
+MipsO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
+{
+ this->setArchIntReg(MipsISA::ArgumentReg0 + i, val, tid);
+}
+
+template <class Impl>
+void
+MipsO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
+{
+ // check for error condition.
+ if (return_value.successful()) {
+ // no error
+ this->setArchIntReg(TheISA::SyscallSuccessReg, 0, tid);
+ this->setArchIntReg(TheISA::ReturnValueReg, return_value.value(), tid);
+ } else {
+ // got an error, return details
+ this->setArchIntReg(TheISA::SyscallSuccessReg,
+ (TheISA::IntReg) -1, tid);
+ this->setArchIntReg(TheISA::ReturnValueReg, -return_value.value(), tid);
+ }
+}
+#endif
diff --git a/src/cpu/o3/mips/dyn_inst.cc b/src/cpu/o3/mips/dyn_inst.cc
new file mode 100755
index 000000000..216aa7d2c
--- /dev/null
+++ b/src/cpu/o3/mips/dyn_inst.cc
@@ -0,0 +1,37 @@
+/*
+ * 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: Kevin Lim
+ * Korey Sewell
+ */
+
+#include "cpu/o3/mips/dyn_inst_impl.hh"
+#include "cpu/o3/mips/impl.hh"
+
+// Force instantiation of MipsDynInst for all the implementations that
+// are needed.
+template class MipsDynInst<MipsSimpleImpl>;
diff --git a/src/cpu/o3/mips/dyn_inst.hh b/src/cpu/o3/mips/dyn_inst.hh
new file mode 100755
index 000000000..06bdfcec4
--- /dev/null
+++ b/src/cpu/o3/mips/dyn_inst.hh
@@ -0,0 +1,282 @@
+/*
+ * 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: Kevin Lim
+ * Korey Sewell
+ */
+
+#ifndef __CPU_O3_MIPS_DYN_INST_HH__
+#define __CPU_O3_MIPS_DYN_INST_HH__
+
+#include "arch/isa_traits.hh"
+#include "cpu/base_dyn_inst.hh"
+#include "cpu/inst_seq.hh"
+#include "cpu/o3/mips/cpu.hh"
+#include "cpu/o3/mips/impl.hh"
+
+class Packet;
+
+/**
+ * Mostly implementation & ISA specific MipsDynInst. As with most
+ * other classes in the new CPU model, it is templated on the Impl to
+ * allow for passing in of all types, such as the CPU type and the ISA
+ * type. The MipsDynInst serves as the primary interface to the CPU
+ * for instructions that are executing.
+ */
+template <class Impl>
+class MipsDynInst : public BaseDynInst<Impl>
+{
+ public:
+ /** Typedef for the CPU. */
+ typedef typename Impl::O3CPU O3CPU;
+
+ /** Binary machine instruction type. */
+ typedef TheISA::MachInst MachInst;
+ /** Extended machine instruction type. */
+ typedef TheISA::ExtMachInst ExtMachInst;
+ /** Logical register index type. */
+ typedef TheISA::RegIndex RegIndex;
+ /** Integer register index type. */
+ typedef TheISA::IntReg IntReg;
+ typedef TheISA::FloatReg FloatReg;
+ typedef TheISA::FloatRegBits FloatRegBits;
+ /** Misc register index type. */
+ typedef TheISA::MiscReg MiscReg;
+
+ enum {
+ MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
+ MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
+ };
+
+ public:
+ /** BaseDynInst constructor given a binary instruction. */
+ MipsDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
+ O3CPU *cpu);
+
+ /** BaseDynInst constructor given a static inst pointer. */
+ MipsDynInst(StaticInstPtr &_staticInst);
+
+ /** Executes the instruction.*/
+ Fault execute();
+
+ /** Initiates the access. Only valid for memory operations. */
+ Fault initiateAcc();
+
+ /** Completes the access. Only valid for memory operations. */
+ Fault completeAcc(Packet *pkt);
+
+ private:
+ /** Initializes variables. */
+ void initVars();
+
+ public:
+ /** Reads a miscellaneous register. */
+ MiscReg readMiscReg(int misc_reg)
+ {
+ return this->cpu->readMiscReg(misc_reg, this->threadNumber);
+ }
+
+ /** Reads a misc. register, including any side-effects the read
+ * might have as defined by the architecture.
+ */
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ {
+ return this->cpu->readMiscRegWithEffect(misc_reg, fault,
+ this->threadNumber);
+ }
+
+ /** Sets a misc. register. */
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
+ {
+ this->instResult.integer = val;
+ return this->cpu->setMiscReg(misc_reg, val, this->threadNumber);
+ }
+
+ /** Sets a misc. register, including any side-effects the write
+ * might have as defined by the architecture.
+ */
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+ {
+ return this->cpu->setMiscRegWithEffect(misc_reg, val,
+ this->threadNumber);
+ }
+
+ /** Calls a syscall. */
+ void syscall(int64_t callnum);
+
+ private:
+ /** Physical register index of the destination registers of this
+ * instruction.
+ */
+ PhysRegIndex _destRegIdx[MaxInstDestRegs];
+
+ /** Physical register index of the source registers of this
+ * instruction.
+ */
+ PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
+
+ /** Physical register index of the previous producers of the
+ * architected destinations.
+ */
+ PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
+
+ public:
+
+ // The register accessor methods provide the index of the
+ // instruction's operand (e.g., 0 or 1), not the architectural
+ // register index, to simplify the implementation of register
+ // renaming. We find the architectural register index by indexing
+ // into the instruction's own operand index table. Note that a
+ // raw pointer to the StaticInst is provided instead of a
+ // ref-counted StaticInstPtr to redice overhead. This is fine as
+ // long as these methods don't copy the pointer into any long-term
+ // storage (which is pretty hard to imagine they would have reason
+ // to do).
+
+ uint64_t readIntReg(const StaticInst *si, int idx)
+ {
+ return this->cpu->readIntReg(_srcRegIdx[idx]);
+ }
+
+ FloatReg readFloatReg(const StaticInst *si, int idx, int width)
+ {
+ return this->cpu->readFloatReg(_srcRegIdx[idx], width);
+ }
+
+ FloatReg readFloatReg(const StaticInst *si, int idx)
+ {
+ return this->cpu->readFloatReg(_srcRegIdx[idx]);
+ }
+
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
+ {
+ return this->cpu->readFloatRegBits(_srcRegIdx[idx], width);
+ }
+
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
+ {
+ return this->cpu->readFloatRegBits(_srcRegIdx[idx]);
+ }
+
+ /** @todo: Make results into arrays so they can handle multiple dest
+ * registers.
+ */
+ void setIntReg(const StaticInst *si, int idx, uint64_t val)
+ {
+ this->cpu->setIntReg(_destRegIdx[idx], val);
+ BaseDynInst<Impl>::setIntReg(si, idx, val);
+ }
+
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
+ {
+ this->cpu->setFloatReg(_destRegIdx[idx], val, width);
+ BaseDynInst<Impl>::setFloatReg(si, idx, val, width);
+ }
+
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val)
+ {
+ this->cpu->setFloatReg(_destRegIdx[idx], val);
+ BaseDynInst<Impl>::setFloatReg(si, idx, val);
+ }
+
+ void setFloatRegBits(const StaticInst *si, int idx,
+ FloatRegBits val, int width)
+ {
+ this->cpu->setFloatRegBits(_destRegIdx[idx], val, width);
+ BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
+ }
+
+ void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
+ {
+ this->cpu->setFloatRegBits(_destRegIdx[idx], val);
+ BaseDynInst<Impl>::setFloatRegBits(si, idx, val);
+ }
+
+ /** Returns the physical register index of the i'th destination
+ * register.
+ */
+ PhysRegIndex renamedDestRegIdx(int idx) const
+ {
+ return _destRegIdx[idx];
+ }
+
+ /** Returns the physical register index of the i'th source register. */
+ PhysRegIndex renamedSrcRegIdx(int idx) const
+ {
+ return _srcRegIdx[idx];
+ }
+
+ /** Returns the physical register index of the previous physical register
+ * that remapped to the same logical register index.
+ */
+ PhysRegIndex prevDestRegIdx(int idx) const
+ {
+ return _prevDestRegIdx[idx];
+ }
+
+ /** Renames a destination register to a physical register. Also records
+ * the previous physical register that the logical register mapped to.
+ */
+ void renameDestReg(int idx,
+ PhysRegIndex renamed_dest,
+ PhysRegIndex previous_rename)
+ {
+ _destRegIdx[idx] = renamed_dest;
+ _prevDestRegIdx[idx] = previous_rename;
+ }
+
+ /** Renames a source logical register to the physical register which
+ * has/will produce that logical register's result.
+ * @todo: add in whether or not the source register is ready.
+ */
+ void renameSrcReg(int idx, PhysRegIndex renamed_src)
+ {
+ _srcRegIdx[idx] = renamed_src;
+ }
+
+ public:
+ /** Calculates EA part of a memory instruction. Currently unused,
+ * though it may be useful in the future if we want to split
+ * memory operations into EA calculation and memory access parts.
+ */
+ Fault calcEA()
+ {
+ return this->staticInst->eaCompInst()->execute(this, this->traceData);
+ }
+
+ /** Does the memory access part of a memory instruction. Currently unused,
+ * though it may be useful in the future if we want to split
+ * memory operations into EA calculation and memory access parts.
+ */
+ Fault memAccess()
+ {
+ return this->staticInst->memAccInst()->execute(this, this->traceData);
+ }
+};
+
+#endif // __CPU_O3_MIPS_DYN_INST_HH__
+
diff --git a/src/cpu/o3/mips/dyn_inst_impl.hh b/src/cpu/o3/mips/dyn_inst_impl.hh
new file mode 100755
index 000000000..57dec1ccf
--- /dev/null
+++ b/src/cpu/o3/mips/dyn_inst_impl.hh
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2004-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: Kevin Lim
+ */
+
+#include "cpu/o3/mips/dyn_inst.hh"
+
+template <class Impl>
+MipsDynInst<Impl>::MipsDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC,
+ InstSeqNum seq_num, O3CPU *cpu)
+ : BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu)
+{
+ initVars();
+}
+
+template <class Impl>
+MipsDynInst<Impl>::MipsDynInst(StaticInstPtr &_staticInst)
+ : BaseDynInst<Impl>(_staticInst)
+{
+ initVars();
+}
+
+template <class Impl>
+void
+MipsDynInst<Impl>::initVars()
+{
+ // Make sure to have the renamed register entries set to the same
+ // as the normal register entries. It will allow the IQ to work
+ // without any modifications.
+ for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
+ _destRegIdx[i] = this->staticInst->destRegIdx(i);
+ }
+
+ for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
+ _srcRegIdx[i] = this->staticInst->srcRegIdx(i);
+ this->_readySrcRegIdx[i] = 0;
+ }
+}
+
+template <class Impl>
+Fault
+MipsDynInst<Impl>::execute()
+{
+ // @todo: Pretty convoluted way to avoid squashing from happening
+ // when using the TC during an instruction's execution
+ // (specifically for instructions that have side-effects that use
+ // the TC). Fix this.
+ bool in_syscall = this->thread->inSyscall;
+ this->thread->inSyscall = true;
+
+ this->fault = this->staticInst->execute(this, this->traceData);
+
+ this->thread->inSyscall = in_syscall;
+
+ return this->fault;
+}
+
+template <class Impl>
+Fault
+MipsDynInst<Impl>::initiateAcc()
+{
+ // @todo: Pretty convoluted way to avoid squashing from happening
+ // when using the TC during an instruction's execution
+ // (specifically for instructions that have side-effects that use
+ // the TC). Fix this.
+ bool in_syscall = this->thread->inSyscall;
+ this->thread->inSyscall = true;
+
+ this->fault = this->staticInst->initiateAcc(this, this->traceData);
+
+ this->thread->inSyscall = in_syscall;
+
+ return this->fault;
+}
+
+template <class Impl>
+Fault
+MipsDynInst<Impl>::completeAcc(Packet *pkt)
+{
+ this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
+
+ return this->fault;
+}
+
+template <class Impl>
+void
+MipsDynInst<Impl>::syscall(int64_t callnum)
+{
+ this->cpu->syscall(callnum, this->threadNumber);
+}
+
diff --git a/src/cpu/o3/mips/impl.hh b/src/cpu/o3/mips/impl.hh
new file mode 100644
index 000000000..ac7181a19
--- /dev/null
+++ b/src/cpu/o3/mips/impl.hh
@@ -0,0 +1,93 @@
+/*
+ * 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: Kevin Lim
+ * Korey Sewell
+ */
+
+#ifndef __CPU_O3_MIPS_IMPL_HH__
+#define __CPU_O3_MIPS_IMPL_HH__
+
+#include "arch/mips/isa_traits.hh"
+
+#include "cpu/o3/mips/params.hh"
+#include "cpu/o3/cpu_policy.hh"
+
+
+// Forward declarations.
+template <class Impl>
+class MipsDynInst;
+
+template <class Impl>
+class MipsO3CPU;
+
+/** Implementation specific struct that defines several key types to the
+ * CPU, the stages within the CPU, the time buffers, and the DynInst.
+ * The struct defines the ISA, the CPU policy, the specific DynInst, the
+ * specific O3CPU, and all of the structs from the time buffers to do
+ * communication.
+ * This is one of the key things that must be defined for each hardware
+ * specific CPU implementation.
+ */
+struct MipsSimpleImpl
+{
+ /** The type of MachInst. */
+ typedef TheISA::MachInst MachInst;
+
+ /** The CPU policy to be used, which defines all of the CPU stages. */
+ typedef SimpleCPUPolicy<MipsSimpleImpl> CPUPol;
+
+ /** The DynInst type to be used. */
+ typedef MipsDynInst<MipsSimpleImpl> DynInst;
+
+ /** The refcounted DynInst pointer to be used. In most cases this is
+ * what should be used, and not DynInst *.
+ */
+ typedef RefCountingPtr<DynInst> DynInstPtr;
+
+ /** The O3CPU type to be used. */
+ typedef MipsO3CPU<MipsSimpleImpl> O3CPU;
+
+ /** Same typedef, but for CPUType. BaseDynInst may not always use
+ * an O3 CPU, so it's clearer to call it CPUType instead in that
+ * case.
+ */
+ typedef O3CPU CPUType;
+
+ /** The Params to be passed to each stage. */
+ typedef MipsSimpleParams Params;
+
+ enum {
+ MaxWidth = 8,
+ MaxThreads = 4
+ };
+};
+
+/** The O3Impl to be used. */
+typedef MipsSimpleImpl O3CPUImpl;
+
+#endif // __CPU_O3_MIPS_IMPL_HH__
diff --git a/src/cpu/o3/mips/params.hh b/src/cpu/o3/mips/params.hh
new file mode 100644
index 000000000..d1ac62e21
--- /dev/null
+++ b/src/cpu/o3/mips/params.hh
@@ -0,0 +1,63 @@
+/*
+ * 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: Kevin Lim
+ * Korey Sewell
+ */
+
+#ifndef __CPU_O3_MIPS_PARAMS_HH__
+#define __CPU_O3_MIPS_PARAMS_HH__
+
+#include "cpu/o3/cpu.hh"
+#include "cpu/o3/params.hh"
+
+//Forward declarations
+//class MipsDTB;
+//class MipsITB;
+class MemObject;
+class Process;
+class System;
+
+/**
+ * This file defines the parameters that will be used for the MipsO3CPU.
+ * This must be defined externally so that the Impl can have a params class
+ * defined that it can pass to all of the individual stages.
+ */
+
+class MipsSimpleParams : public O3Params
+{
+ public:
+ MipsSimpleParams() {}
+
+#if FULL_SYSTEM
+ //Full System Paramater Objects place here
+ MipsITB *itb;
+ MipsDTB *dtb;
+#endif
+};
+
+#endif // __CPU_O3_MIPS_PARAMS_HH__
diff --git a/src/cpu/o3/mips/thread_context.cc b/src/cpu/o3/mips/thread_context.cc
new file mode 100755
index 000000000..0061a2a63
--- /dev/null
+++ b/src/cpu/o3/mips/thread_context.cc
@@ -0,0 +1,36 @@
+/*
+ * 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: Kevin Lim
+ * Korey Sewell
+ */
+
+#include "cpu/o3/thread_context.hh"
+#include "cpu/o3/thread_context_impl.hh"
+
+template class O3ThreadContext<MipsSimpleImpl>;
+
diff --git a/src/cpu/o3/mips/thread_context.hh b/src/cpu/o3/mips/thread_context.hh
new file mode 100644
index 000000000..26b1e2e7f
--- /dev/null
+++ b/src/cpu/o3/mips/thread_context.hh
@@ -0,0 +1,68 @@
+/*
+ * 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: Kevin Lim
+ * Korey Sewell
+ */
+
+#include "arch/mips/types.hh"
+#include "cpu/o3/thread_context.hh"
+
+template <class Impl>
+class MipsTC : public O3ThreadContext<Impl>
+{
+ public:
+ virtual uint64_t readNextNPC()
+ {
+ return this->cpu->readNextNPC(this->thread->readTid());
+ }
+
+ virtual void setNextNPC(uint64_t val)
+ {
+ this->cpu->setNextNPC(val, this->thread->readTid());
+ }
+
+ virtual void changeRegFileContext(TheISA::RegContextParam param,
+ TheISA::RegContextVal val)
+ { panic("Not supported on Mips!"); }
+
+ /** This function exits the thread context in the CPU and returns
+ * 1 if the CPU has no more active threads (meaning it's OK to exit);
+ * Used in syscall-emulation mode when a thread executes the 'exit'
+ * syscall.
+ */
+ virtual int exit()
+ {
+ this->deallocate();
+
+ // If there are still threads executing in the system
+ if (this->cpu->numActiveThreads())
+ return 0; // don't exit simulation
+ else
+ return 1; // exit simulation
+ }
+};
diff --git a/src/cpu/o3/ras.hh b/src/cpu/o3/ras.hh
index 5c8a93285..97846ed16 100644
--- a/src/cpu/o3/ras.hh
+++ b/src/cpu/o3/ras.hh
@@ -31,8 +31,7 @@
#ifndef __CPU_O3_RAS_HH__
#define __CPU_O3_RAS_HH__
-// For Addr type.
-#include "arch/isa_traits.hh"
+#include "sim/host.hh"
#include <vector>
/** Return address stack class, implements a simple RAS. */
diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh
index b6677b4b1..512cf0721 100644
--- a/src/cpu/o3/regfile.hh
+++ b/src/cpu/o3/regfile.hh
@@ -33,11 +33,11 @@
#define __CPU_O3_REGFILE_HH__
#include "arch/isa_traits.hh"
-#include "arch/faults.hh"
#include "arch/types.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
#include "cpu/o3/comm.hh"
+#include "sim/faults.hh"
#if FULL_SYSTEM
#include "kern/kernel_stats.hh"
diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh
index 034087feb..ba26a01dd 100644
--- a/src/cpu/o3/rename.hh
+++ b/src/cpu/o3/rename.hh
@@ -76,6 +76,7 @@ class DefaultRename
// using a list instead of a queue. (Most other stages use a
// queue)
typedef std::list<DynInstPtr> InstQueue;
+ typedef typename std::list<DynInstPtr>::iterator ListIt;
public:
/** Overall rename status. Used to determine if the CPU can
@@ -170,7 +171,7 @@ class DefaultRename
void takeOverFrom();
/** Squashes all instructions in a thread. */
- void squash(unsigned tid);
+ void squash(const InstSeqNum &squash_seq_num, unsigned tid);
/** Ticks rename, which processes all input signals and attempts to rename
* as many instructions as possible.
@@ -222,7 +223,7 @@ class DefaultRename
bool unblock(unsigned tid);
/** Executes actual squash, removing squashed instructions. */
- void doSquash(unsigned tid);
+ void doSquash(const InstSeqNum &squash_seq_num, unsigned tid);
/** Removes a committed instruction's rename history. */
void removeFromHistory(InstSeqNum inst_seq_num, unsigned tid);
diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh
index 805a72808..892eb12cf 100644
--- a/src/cpu/o3/rename_impl.hh
+++ b/src/cpu/o3/rename_impl.hh
@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
+ * Korey Sewell
*/
#include <list>
@@ -33,8 +34,6 @@
#include "config/full_system.hh"
#include "cpu/o3/rename.hh"
-using namespace std;
-
template <class Impl>
DefaultRename<Impl>::DefaultRename(Params *params)
: iewToRenameDelay(params->iewToRenameDelay),
@@ -222,7 +221,7 @@ DefaultRename<Impl>::initStage()
template<class Impl>
void
-DefaultRename<Impl>::setActiveThreads(list<unsigned> *at_ptr)
+DefaultRename<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
DPRINTF(Rename, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
@@ -271,7 +270,8 @@ DefaultRename<Impl>::switchOut()
{
// Clear any state, fix up the rename map.
for (int i = 0; i < numThreads; i++) {
- typename list<RenameHistory>::iterator hb_it = historyBuffer[i].begin();
+ typename std::list<RenameHistory>::iterator hb_it =
+ historyBuffer[i].begin();
while (!historyBuffer[i].empty()) {
assert(hb_it != historyBuffer[i].end());
@@ -318,7 +318,7 @@ DefaultRename<Impl>::takeOverFrom()
template <class Impl>
void
-DefaultRename<Impl>::squash(unsigned tid)
+DefaultRename<Impl>::squash(const InstSeqNum &squash_seq_num, unsigned tid)
{
DPRINTF(Rename, "[tid:%u]: Squashing instructions.\n",tid);
@@ -341,19 +341,55 @@ DefaultRename<Impl>::squash(unsigned tid)
unsigned squashCount = 0;
for (int i=0; i<fromDecode->size; i++) {
- if (fromDecode->insts[i]->threadNumber == tid) {
+ if (fromDecode->insts[i]->threadNumber == tid &&
+ fromDecode->insts[i]->seqNum > squash_seq_num) {
fromDecode->insts[i]->setSquashed();
wroteToTimeBuffer = true;
squashCount++;
}
+
}
+ // Clear the instruction list and skid buffer in case they have any
+ // insts in them. Since we support multiple ISAs, we cant just:
+ // "insts[tid].clear();" or "skidBuffer[tid].clear()" since there is
+ // a possible delay slot inst for different architectures
+ // insts[tid].clear();
+#if THE_ISA == ALPHA_ISA
insts[tid].clear();
+#else
+ DPRINTF(Rename, "[tid:%i] Squashing incoming decode instructions until "
+ "[sn:%i].\n",tid, squash_seq_num);
+ ListIt ilist_it = insts[tid].begin();
+ while (ilist_it != insts[tid].end()) {
+ if ((*ilist_it)->seqNum > squash_seq_num) {
+ (*ilist_it)->setSquashed();
+ DPRINTF(Rename, "Squashing incoming decode instruction, "
+ "[tid:%i] [sn:%i] PC %08p.\n", tid, (*ilist_it)->seqNum, (*ilist_it)->PC);
+ }
+ ilist_it++;
+ }
+#endif
// Clear the skid buffer in case it has any data in it.
+ // See comments above.
+ // skidBuffer[tid].clear();
+#if THE_ISA == ALPHA_ISA
skidBuffer[tid].clear();
-
- doSquash(tid);
+#else
+ DPRINTF(Rename, "[tid:%i] Squashing incoming skidbuffer instructions "
+ "until [sn:%i].\n", tid, squash_seq_num);
+ ListIt slist_it = skidBuffer[tid].begin();
+ while (slist_it != skidBuffer[tid].end()) {
+ if ((*slist_it)->seqNum > squash_seq_num) {
+ (*slist_it)->setSquashed();
+ DPRINTF(Rename, "Squashing skidbuffer instruction, [tid:%i] [sn:%i]"
+ "PC %08p.\n", tid, (*slist_it)->seqNum, (*slist_it)->PC);
+ }
+ slist_it++;
+ }
+#endif
+ doSquash(squash_seq_num, tid);
}
template <class Impl>
@@ -370,7 +406,7 @@ DefaultRename<Impl>::tick()
sortInsts();
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
// Check stall and squash signals.
while (threads != (*activeThreads).end()) {
@@ -572,7 +608,7 @@ DefaultRename<Impl>::renameInsts(unsigned tid)
if (inst->isSquashed()) {
DPRINTF(Rename, "[tid:%u]: instruction %i with PC %#x is "
"squashed, skipping.\n",
- tid, inst->seqNum, inst->threadNumber,inst->readPC());
+ tid, inst->seqNum, inst->readPC());
++renameSquashedInsts;
@@ -707,9 +743,11 @@ DefaultRename<Impl>::sortInsts()
{
int insts_from_decode = fromDecode->size;
#ifdef DEBUG
+#if THE_ISA == ALPHA_ISA
for (int i=0; i < numThreads; i++)
assert(insts[i].empty());
#endif
+#endif
for (int i = 0; i < insts_from_decode; ++i) {
DynInstPtr inst = fromDecode->insts[i];
insts[inst->threadNumber].push_back(inst);
@@ -720,7 +758,7 @@ template<class Impl>
bool
DefaultRename<Impl>::skidsEmpty()
{
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
if (!skidBuffer[*threads++].empty())
@@ -736,7 +774,7 @@ DefaultRename<Impl>::updateStatus()
{
bool any_unblocking = false;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
threads = (*activeThreads).begin();
@@ -824,11 +862,10 @@ DefaultRename<Impl>::unblock(unsigned tid)
template <class Impl>
void
-DefaultRename<Impl>::doSquash(unsigned tid)
+DefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, unsigned tid)
{
- typename list<RenameHistory>::iterator hb_it = historyBuffer[tid].begin();
-
- InstSeqNum squashed_seq_num = fromCommit->commitInfo[tid].doneSeqNum;
+ typename std::list<RenameHistory>::iterator hb_it =
+ historyBuffer[tid].begin();
// After a syscall squashes everything, the history buffer may be empty
// but the ROB may still be squashing instructions.
@@ -866,7 +903,8 @@ DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, unsigned tid)
"history buffer %u (size=%i), until [sn:%lli].\n",
tid, tid, historyBuffer[tid].size(), inst_seq_num);
- typename list<RenameHistory>::iterator hb_it = historyBuffer[tid].end();
+ typename std::list<RenameHistory>::iterator hb_it =
+ historyBuffer[tid].end();
--hb_it;
@@ -963,8 +1001,9 @@ DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst,unsigned tid)
historyBuffer[tid].push_front(hb_entry);
- DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer, "
- "[sn:%lli].\n",tid,
+ DPRINTF(Rename, "[tid:%u]: Adding instruction to history buffer "
+ "(size=%i), [sn:%lli].\n",tid,
+ historyBuffer[tid].size(),
(*historyBuffer[tid].begin()).instSeqNum);
// Tell the instruction to rename the appropriate destination
@@ -1143,7 +1182,13 @@ DefaultRename<Impl>::checkSignalsAndUpdate(unsigned tid)
DPRINTF(Rename, "[tid:%u]: Squashing instructions due to squash from "
"commit.\n", tid);
- squash(tid);
+#if THE_ISA == ALPHA_ISA
+ InstSeqNum squashed_seq_num = fromCommit->commitInfo[tid].doneSeqNum;
+#else
+ InstSeqNum squashed_seq_num = fromCommit->commitInfo[tid].bdelayDoneSeqNum;
+#endif
+
+ squash(squashed_seq_num, tid);
return true;
}
@@ -1258,7 +1303,7 @@ template <class Impl>
void
DefaultRename<Impl>::dumpHistory()
{
- typename list<RenameHistory>::iterator buf_it;
+ typename std::list<RenameHistory>::iterator buf_it;
for (int i = 0; i < numThreads; i++) {
diff --git a/src/cpu/o3/rename_map.hh b/src/cpu/o3/rename_map.hh
index c4c90c99a..896c66f3e 100644
--- a/src/cpu/o3/rename_map.hh
+++ b/src/cpu/o3/rename_map.hh
@@ -40,8 +40,7 @@
#include <vector>
#include "cpu/o3/free_list.hh"
-//For RegIndex
-#include "arch/isa_traits.hh"
+#include "arch/types.hh"
class SimpleRenameMap
{
diff --git a/src/cpu/o3/rob_impl.hh b/src/cpu/o3/rob_impl.hh
index 1b9f666b8..fab114a74 100644
--- a/src/cpu/o3/rob_impl.hh
+++ b/src/cpu/o3/rob_impl.hh
@@ -32,11 +32,11 @@
#include "config/full_system.hh"
#include "cpu/o3/rob.hh"
-using namespace std;
+#include <list>
template <class Impl>
ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
- string _smtROBPolicy, unsigned _smtROBThreshold,
+ std::string _smtROBPolicy, unsigned _smtROBThreshold,
unsigned _numThreads)
: numEntries(_numEntries),
squashWidth(_squashWidth),
@@ -49,7 +49,7 @@ ROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
threadEntries[tid] = 0;
}
- string policy = _smtROBPolicy;
+ std::string policy = _smtROBPolicy;
//Convert string to lowercase
std::transform(policy.begin(), policy.end(), policy.begin(),
@@ -118,7 +118,7 @@ ROB<Impl>::setCPU(O3CPU *cpu_ptr)
template <class Impl>
void
-ROB<Impl>::setActiveThreads(list<unsigned> *at_ptr)
+ROB<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
DPRINTF(ROB, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
@@ -157,8 +157,8 @@ ROB<Impl>::resetEntries()
if (robPolicy != Dynamic || numThreads > 1) {
int active_threads = (*activeThreads).size();
- list<unsigned>::iterator threads = (*activeThreads).begin();
- list<unsigned>::iterator list_end = (*activeThreads).end();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator list_end = (*activeThreads).end();
while (threads != list_end) {
if (robPolicy == Partitioned) {
@@ -318,7 +318,7 @@ bool
ROB<Impl>::canCommit()
{
//@todo: set ActiveThreads through ROB or CPU
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
@@ -432,7 +432,7 @@ ROB<Impl>::updateHead()
bool first_valid = true;
// @todo: set ActiveThreads through ROB or CPU
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned thread_num = *threads++;
@@ -472,7 +472,7 @@ ROB<Impl>::updateTail()
tail = instList[0].end();
bool first_valid = true;
- list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = (*activeThreads).begin();
while (threads != (*activeThreads).end()) {
unsigned tid = *threads++;
diff --git a/src/cpu/o3/scoreboard.hh b/src/cpu/o3/scoreboard.hh
index f8e4df3b7..eefff1d8b 100644
--- a/src/cpu/o3/scoreboard.hh
+++ b/src/cpu/o3/scoreboard.hh
@@ -35,7 +35,6 @@
#include <iostream>
#include <utility>
#include <vector>
-#include "arch/alpha/isa_traits.hh"
#include "base/trace.hh"
#include "base/traceflags.hh"
#include "cpu/o3/comm.hh"
diff --git a/src/cpu/o3/store_set.hh b/src/cpu/o3/store_set.hh
index f5a44a1ac..f9f7637d0 100644
--- a/src/cpu/o3/store_set.hh
+++ b/src/cpu/o3/store_set.hh
@@ -36,8 +36,8 @@
#include <utility>
#include <vector>
-#include "arch/isa_traits.hh"
#include "cpu/inst_seq.hh"
+#include "sim/host.hh"
struct ltseqnum {
bool operator()(const InstSeqNum &lhs, const InstSeqNum &rhs) const
diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh
index df8d1a6d8..9ca02b9f3 100755
--- a/src/cpu/o3/thread_context.hh
+++ b/src/cpu/o3/thread_context.hh
@@ -26,12 +26,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
- * Korey Sewell
*/
#ifndef __CPU_O3_THREAD_CONTEXT_HH__
#define __CPU_O3_THREAD_CONTEXT_HH__
+#include "cpu/thread_context.hh"
#include "cpu/o3/isa_specific.hh"
class EndQuiesceEvent;
diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh
index bf8cbf850..a4546e669 100755
--- a/src/cpu/o3/thread_context_impl.hh
+++ b/src/cpu/o3/thread_context_impl.hh
@@ -32,8 +32,6 @@
#include "cpu/o3/thread_context.hh"
#include "cpu/quiesce_event.hh"
-using namespace TheISA;
-
#if FULL_SYSTEM
template <class Impl>
VirtualPort *
@@ -285,7 +283,7 @@ O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc)
}
// Copy the misc regs.
- copyMiscRegs(tc, this);
+ TheISA::copyMiscRegs(tc, this);
// Then finally set the PC and the next PC.
cpu->setPC(tc->readPC(), tid);
@@ -308,7 +306,7 @@ O3ThreadContext<Impl>::readIntReg(int reg_idx)
}
template <class Impl>
-FloatReg
+TheISA::FloatReg
O3ThreadContext<Impl>::readFloatReg(int reg_idx, int width)
{
switch(width) {
@@ -323,14 +321,14 @@ O3ThreadContext<Impl>::readFloatReg(int reg_idx, int width)
}
template <class Impl>
-FloatReg
+TheISA::FloatReg
O3ThreadContext<Impl>::readFloatReg(int reg_idx)
{
return cpu->readArchFloatRegSingle(reg_idx, thread->readTid());
}
template <class Impl>
-FloatRegBits
+TheISA::FloatRegBits
O3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width)
{
DPRINTF(Fault, "Reading floatint register through the TC!\n");
@@ -338,7 +336,7 @@ O3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width)
}
template <class Impl>
-FloatRegBits
+TheISA::FloatRegBits
O3ThreadContext<Impl>::readFloatRegBits(int reg_idx)
{
return cpu->readArchFloatRegInt(reg_idx, thread->readTid());
diff --git a/src/cpu/o3/thread_state.hh b/src/cpu/o3/thread_state.hh
index 1c8105204..b6f2e14c0 100644
--- a/src/cpu/o3/thread_state.hh
+++ b/src/cpu/o3/thread_state.hh
@@ -31,8 +31,6 @@
#ifndef __CPU_O3_THREAD_STATE_HH__
#define __CPU_O3_THREAD_STATE_HH__
-#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
#include "cpu/thread_context.hh"
#include "cpu/thread_state.hh"
diff --git a/src/cpu/o3/tournament_pred.hh b/src/cpu/o3/tournament_pred.hh
index 92402adc6..66b4aaae2 100644
--- a/src/cpu/o3/tournament_pred.hh
+++ b/src/cpu/o3/tournament_pred.hh
@@ -31,9 +31,8 @@
#ifndef __CPU_O3_TOURNAMENT_PRED_HH__
#define __CPU_O3_TOURNAMENT_PRED_HH__
-// For Addr type.
-#include "arch/isa_traits.hh"
#include "cpu/o3/sat_counter.hh"
+#include "sim/host.hh"
#include <vector>
/**
diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh
index f58b81990..80f18434c 100644
--- a/src/cpu/ozone/cpu_impl.hh
+++ b/src/cpu/ozone/cpu_impl.hh
@@ -47,6 +47,7 @@
#include "arch/faults.hh"
#include "arch/alpha/osfpal.hh"
#include "arch/alpha/tlb.hh"
+#include "arch/alpha/types.hh"
#include "arch/vtophys.hh"
#include "base/callback.hh"
//#include "base/remote_gdb.hh"
diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh
index 67691d416..75ac464ec 100644
--- a/src/cpu/ozone/dyn_inst.hh
+++ b/src/cpu/ozone/dyn_inst.hh
@@ -32,6 +32,7 @@
#define __CPU_OZONE_DYN_INST_HH__
#include "arch/isa_traits.hh"
+#include "arch/types.hh"
#include "config/full_system.hh"
#include "cpu/base_dyn_inst.hh"
#include "cpu/inst_seq.hh"
diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh
index bad902c2a..ba0d70417 100644
--- a/src/cpu/ozone/dyn_inst_impl.hh
+++ b/src/cpu/ozone/dyn_inst_impl.hh
@@ -29,13 +29,10 @@
*/
#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
#include "config/full_system.hh"
#include "cpu/ozone/dyn_inst.hh"
#include "kern/kernel_stats.hh"
-using namespace TheISA;
-
template <class Impl>
OzoneDynInst<Impl>::OzoneDynInst(OzoneCPU *cpu)
: BaseDynInst<Impl>(0, 0, 0, 0, cpu)
diff --git a/src/cpu/ozone/ea_list.hh b/src/cpu/ozone/ea_list.hh
index 64882632c..d9e9d701f 100644
--- a/src/cpu/ozone/ea_list.hh
+++ b/src/cpu/ozone/ea_list.hh
@@ -35,8 +35,8 @@
#include <list>
#include <utility>
-#include "arch/isa_traits.hh"
#include "cpu/inst_seq.hh"
+#include "sim/host.hh"
/**
* Simple class to hold onto a list of pairs, each pair having a memory
diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh
index 9da937320..c9c5a869b 100644
--- a/src/cpu/ozone/front_end_impl.hh
+++ b/src/cpu/ozone/front_end_impl.hh
@@ -32,6 +32,7 @@
#include "arch/faults.hh"
#include "arch/isa_traits.hh"
+#include "arch/utility.hh"
#include "base/statistics.hh"
#include "cpu/thread_context.hh"
#include "cpu/exetrace.hh"
diff --git a/src/cpu/ozone/inorder_back_end_impl.hh b/src/cpu/ozone/inorder_back_end_impl.hh
index cbb73364e..701fc0ee9 100644
--- a/src/cpu/ozone/inorder_back_end_impl.hh
+++ b/src/cpu/ozone/inorder_back_end_impl.hh
@@ -29,12 +29,10 @@
*/
#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
+#include "arch/types.hh"
#include "cpu/ozone/inorder_back_end.hh"
#include "cpu/ozone/thread_state.hh"
-using namespace TheISA;
-
template <class Impl>
InorderBackEnd<Impl>::InorderBackEnd(Params *params)
: squashPending(false),
diff --git a/src/cpu/ozone/lsq_unit.hh b/src/cpu/ozone/lsq_unit.hh
index 1b5340e55..38c1c09a2 100644
--- a/src/cpu/ozone/lsq_unit.hh
+++ b/src/cpu/ozone/lsq_unit.hh
@@ -36,7 +36,7 @@
#include <algorithm>
#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
+#include "arch/types.hh"
#include "config/full_system.hh"
#include "base/hashmap.hh"
#include "cpu/inst_seq.hh"
diff --git a/src/cpu/ozone/lsq_unit_impl.hh b/src/cpu/ozone/lsq_unit_impl.hh
index f8cb18634..ee0804036 100644
--- a/src/cpu/ozone/lsq_unit_impl.hh
+++ b/src/cpu/ozone/lsq_unit_impl.hh
@@ -28,7 +28,7 @@
* Authors: Kevin Lim
*/
-#include "arch/isa_traits.hh"
+#include "arch/faults.hh"
#include "base/str.hh"
#include "cpu/ozone/lsq_unit.hh"
diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh
index 2eb09d01a..9a21a9d01 100644
--- a/src/cpu/ozone/lw_lsq.hh
+++ b/src/cpu/ozone/lw_lsq.hh
@@ -37,7 +37,7 @@
#include <algorithm>
#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
+#include "arch/types.hh"
#include "config/full_system.hh"
#include "base/hashmap.hh"
#include "cpu/inst_seq.hh"
diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh
index 88e9c218f..7eef4b11f 100644
--- a/src/cpu/ozone/lw_lsq_impl.hh
+++ b/src/cpu/ozone/lw_lsq_impl.hh
@@ -30,7 +30,7 @@
#include "config/use_checker.hh"
-#include "arch/isa_traits.hh"
+#include "arch/faults.hh"
#include "base/str.hh"
#include "cpu/ozone/lw_lsq.hh"
#include "cpu/checker/cpu.hh"
diff --git a/src/cpu/ozone/null_predictor.hh b/src/cpu/ozone/null_predictor.hh
index a98c89d69..0751338b7 100644
--- a/src/cpu/ozone/null_predictor.hh
+++ b/src/cpu/ozone/null_predictor.hh
@@ -31,8 +31,8 @@
#ifndef __CPU_OZONE_NULL_PREDICTOR_HH__
#define __CPU_OZONE_NULL_PREDICTOR_HH__
-#include "arch/isa_traits.hh"
#include "cpu/inst_seq.hh"
+#include "sim/host.hh"
template <class Impl>
class NullPredictor
diff --git a/src/cpu/ozone/ozone_impl.hh b/src/cpu/ozone/ozone_impl.hh
index 503675738..2271cd68a 100644
--- a/src/cpu/ozone/ozone_impl.hh
+++ b/src/cpu/ozone/ozone_impl.hh
@@ -31,7 +31,6 @@
#ifndef __CPU_OZONE_OZONE_IMPL_HH__
#define __CPU_OZONE_OZONE_IMPL_HH__
-#include "arch/alpha/isa_traits.hh"
#include "cpu/o3/bpred_unit.hh"
#include "cpu/ozone/front_end.hh"
#include "cpu/ozone/inst_queue.hh"
diff --git a/src/cpu/ozone/simple_impl.hh b/src/cpu/ozone/simple_impl.hh
index 3199d8d8a..42002180b 100644
--- a/src/cpu/ozone/simple_impl.hh
+++ b/src/cpu/ozone/simple_impl.hh
@@ -31,7 +31,6 @@
#ifndef __CPU_OZONE_SIMPLE_IMPL_HH__
#define __CPU_OZONE_SIMPLE_IMPL_HH__
-#include "arch/isa_traits.hh"
#include "cpu/o3/bpred_unit.hh"
#include "cpu/ozone/cpu.hh"
#include "cpu/ozone/front_end.hh"
diff --git a/src/cpu/ozone/thread_state.hh b/src/cpu/ozone/thread_state.hh
index ef4b1429d..8234cf938 100644
--- a/src/cpu/ozone/thread_state.hh
+++ b/src/cpu/ozone/thread_state.hh
@@ -32,7 +32,8 @@
#define __CPU_OZONE_THREAD_STATE_HH__
#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
+#include "arch/types.hh"
+#include "arch/regfile.hh"
#include "cpu/thread_context.hh"
#include "cpu/thread_state.hh"
#include "sim/process.hh"
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index 12bfdeb9b..c396f5033 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -33,6 +33,7 @@
#include "cpu/simple/atomic.hh"
#include "mem/packet_impl.hh"
#include "sim/builder.hh"
+#include "sim/system.hh"
using namespace std;
using namespace TheISA;
@@ -158,18 +159,31 @@ AtomicSimpleCPU::~AtomicSimpleCPU()
void
AtomicSimpleCPU::serialize(ostream &os)
{
- SERIALIZE_ENUM(_status);
- BaseSimpleCPU::serialize(os);
+ SimObject::State so_state = SimObject::getState();
+ SERIALIZE_ENUM(so_state);
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
+ BaseSimpleCPU::serialize(os);
}
void
AtomicSimpleCPU::unserialize(Checkpoint *cp, const string &section)
{
- UNSERIALIZE_ENUM(_status);
- BaseSimpleCPU::unserialize(cp, section);
+ SimObject::State so_state;
+ UNSERIALIZE_ENUM(so_state);
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
+ BaseSimpleCPU::unserialize(cp, section);
+}
+
+void
+AtomicSimpleCPU::resume()
+{
+ assert(system->getMemoryMode() == System::Atomic);
+ changeState(SimObject::Running);
+ if (thread->status() == ThreadContext::Active) {
+ if (!tickEvent.scheduled())
+ tickEvent.schedule(curTick);
+ }
}
void
@@ -451,11 +465,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
SimObjectParam<MemObject *> mem;
+ SimObjectParam<System *> system;
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<System *> system;
Param<int> cpu_id;
Param<Tick> profile;
#else
@@ -483,11 +497,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
INIT_PARAM(max_loads_all_threads,
"terminate when all threads have reached this load count"),
INIT_PARAM(mem, "memory"),
+ INIT_PARAM(system, "system object"),
#if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(dtb, "Data TLB"),
- INIT_PARAM(system, "system object"),
INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM(profile, ""),
#else
@@ -520,11 +534,11 @@ CREATE_SIM_OBJECT(AtomicSimpleCPU)
params->width = width;
params->simulate_stalls = simulate_stalls;
params->mem = mem;
+ params->system = system;
#if FULL_SYSTEM
params->itb = itb;
params->dtb = dtb;
- params->system = system;
params->cpu_id = cpu_id;
params->profile = profile;
#else
diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh
index 179b4a721..b602af558 100644
--- a/src/cpu/simple/atomic.hh
+++ b/src/cpu/simple/atomic.hh
@@ -126,6 +126,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
+ virtual void resume();
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index a50541189..801c96c88 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -26,10 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
- * Korey Sewell
*/
#include "arch/utility.hh"
+#include "arch/faults.hh"
#include "base/cprintf.hh"
#include "base/inifile.hh"
#include "base/loader/symtab.hh"
@@ -55,10 +55,10 @@
#include "sim/sim_events.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
+#include "sim/system.hh"
#if FULL_SYSTEM
#include "base/remote_gdb.hh"
-#include "sim/system.hh"
#include "arch/tlb.hh"
#include "arch/stacktrace.hh"
#include "arch/vtophys.hh"
@@ -178,8 +178,8 @@ void
BaseSimpleCPU::serialize(ostream &os)
{
BaseCPU::serialize(os);
- SERIALIZE_SCALAR(inst);
- nameOut(os, csprintf("%s.xc", name()));
+// SERIALIZE_SCALAR(inst);
+ nameOut(os, csprintf("%s.xc.0", name()));
thread->serialize(os);
}
@@ -187,8 +187,8 @@ void
BaseSimpleCPU::unserialize(Checkpoint *cp, const string &section)
{
BaseCPU::unserialize(cp, section);
- UNSERIALIZE_SCALAR(inst);
- thread->unserialize(cp, csprintf("%s.xc", section));
+// UNSERIALIZE_SCALAR(inst);
+ thread->unserialize(cp, csprintf("%s.xc.0", section));
}
void
@@ -455,6 +455,7 @@ BaseSimpleCPU::advancePC(Fault fault)
#else
thread->setNextPC(thread->readNextNPC());
thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
+ assert(thread->readNextPC() != thread->readNextNPC());
#endif
}
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index e55301c6b..5c1654f7e 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -33,6 +33,7 @@
#include "cpu/simple/timing.hh"
#include "mem/packet_impl.hh"
#include "sim/builder.hh"
+#include "sim/system.hh"
using namespace std;
using namespace TheISA;
@@ -84,14 +85,22 @@ TimingSimpleCPU::CpuPort::recvStatusChange(Status status)
panic("TimingSimpleCPU doesn't expect recvStatusChange callback!");
}
+
+void
+TimingSimpleCPU::CpuPort::TickEvent::schedule(Packet *_pkt, Tick t)
+{
+ pkt = _pkt;
+ Event::schedule(t);
+}
+
TimingSimpleCPU::TimingSimpleCPU(Params *p)
- : BaseSimpleCPU(p), icachePort(this), dcachePort(this)
+ : BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock)
{
_status = Idle;
ifetch_pkt = dcache_pkt = NULL;
drainEvent = NULL;
fetchEvent = NULL;
- state = SimObject::Timing;
+ changeState(SimObject::Running);
}
@@ -102,29 +111,31 @@ TimingSimpleCPU::~TimingSimpleCPU()
void
TimingSimpleCPU::serialize(ostream &os)
{
- SERIALIZE_ENUM(_status);
+ SimObject::State so_state = SimObject::getState();
+ SERIALIZE_ENUM(so_state);
BaseSimpleCPU::serialize(os);
}
void
TimingSimpleCPU::unserialize(Checkpoint *cp, const string &section)
{
- UNSERIALIZE_ENUM(_status);
+ SimObject::State so_state;
+ UNSERIALIZE_ENUM(so_state);
BaseSimpleCPU::unserialize(cp, section);
}
-bool
+unsigned int
TimingSimpleCPU::drain(Event *drain_event)
{
// TimingSimpleCPU is ready to drain if it's not waiting for
// an access to complete.
if (status() == Idle || status() == Running || status() == SwitchedOut) {
- changeState(SimObject::DrainedTiming);
- return true;
+ changeState(SimObject::Drained);
+ return 0;
} else {
changeState(SimObject::Draining);
drainEvent = drain_event;
- return false;
+ return 1;
}
}
@@ -134,7 +145,9 @@ TimingSimpleCPU::resume()
if (_status != SwitchedOut && _status != Idle) {
// Delete the old event if it existed.
if (fetchEvent) {
- assert(!fetchEvent->scheduled());
+ if (fetchEvent->scheduled())
+ fetchEvent->deschedule();
+
delete fetchEvent;
}
@@ -142,12 +155,9 @@ TimingSimpleCPU::resume()
new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false);
fetchEvent->schedule(curTick);
}
-}
-void
-TimingSimpleCPU::setMemoryMode(State new_mode)
-{
- assert(new_mode == SimObject::Timing);
+ assert(system->getMemoryMode() == System::Timing);
+ changeState(SimObject::Running);
}
void
@@ -460,11 +470,26 @@ TimingSimpleCPU::completeIfetch(Packet *pkt)
}
}
+void
+TimingSimpleCPU::IcachePort::ITickEvent::process()
+{
+ cpu->completeIfetch(pkt);
+}
bool
TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt)
{
- cpu->completeIfetch(pkt);
+ // These next few lines could be replaced with something faster
+ // who knows what though
+ Tick time = pkt->req->getTime();
+ while (time < curTick)
+ time += lat;
+
+ if (time == curTick)
+ cpu->completeIfetch(pkt);
+ else
+ tickEvent.schedule(pkt, time);
+
return true;
}
@@ -514,18 +539,32 @@ void
TimingSimpleCPU::completeDrain()
{
DPRINTF(Config, "Done draining\n");
- changeState(SimObject::DrainedTiming);
+ changeState(SimObject::Drained);
drainEvent->process();
}
bool
TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt)
{
- cpu->completeDataAccess(pkt);
+ Tick time = pkt->req->getTime();
+ while (time < curTick)
+ time += lat;
+
+ if (time == curTick)
+ cpu->completeDataAccess(pkt);
+ else
+ tickEvent.schedule(pkt, time);
+
return true;
}
void
+TimingSimpleCPU::DcachePort::DTickEvent::process()
+{
+ cpu->completeDataAccess(pkt);
+}
+
+void
TimingSimpleCPU::DcachePort::recvRetry()
{
// we shouldn't get a retry unless we have a packet that we're
@@ -551,11 +590,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU)
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
SimObjectParam<MemObject *> mem;
+ SimObjectParam<System *> system;
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<System *> system;
Param<int> cpu_id;
Param<Tick> profile;
#else
@@ -583,11 +622,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU)
INIT_PARAM(max_loads_all_threads,
"terminate when all threads have reached this load count"),
INIT_PARAM(mem, "memory"),
+ INIT_PARAM(system, "system object"),
#if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(dtb, "Data TLB"),
- INIT_PARAM(system, "system object"),
INIT_PARAM(cpu_id, "processor ID"),
INIT_PARAM(profile, ""),
#else
@@ -618,11 +657,11 @@ CREATE_SIM_OBJECT(TimingSimpleCPU)
params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start;
params->mem = mem;
+ params->system = system;
#if FULL_SYSTEM
params->itb = itb;
params->dtb = dtb;
- params->system = system;
params->cpu_id = cpu_id;
params->profile = profile;
#else
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index 0a3f91e6c..d03fa4bc0 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -74,11 +74,12 @@ class TimingSimpleCPU : public BaseSimpleCPU
{
protected:
TimingSimpleCPU *cpu;
+ Tick lat;
public:
- CpuPort(const std::string &_name, TimingSimpleCPU *_cpu)
- : Port(_name), cpu(_cpu)
+ CpuPort(const std::string &_name, TimingSimpleCPU *_cpu, Tick _lat)
+ : Port(_name), cpu(_cpu), lat(_lat)
{ }
protected:
@@ -92,14 +93,26 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
{ resp.clear(); snoop.clear(); }
+
+ struct TickEvent : public Event
+ {
+ Packet *pkt;
+ TimingSimpleCPU *cpu;
+
+ TickEvent(TimingSimpleCPU *_cpu)
+ :Event(&mainEventQueue), cpu(_cpu) {}
+ const char *description() { return "Timing CPU clock event"; }
+ void schedule(Packet *_pkt, Tick t);
+ };
+
};
class IcachePort : public CpuPort
{
public:
- IcachePort(TimingSimpleCPU *_cpu)
- : CpuPort(_cpu->name() + "-iport", _cpu)
+ IcachePort(TimingSimpleCPU *_cpu, Tick _lat)
+ : CpuPort(_cpu->name() + "-iport", _cpu, _lat), tickEvent(_cpu)
{ }
protected:
@@ -107,14 +120,26 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual bool recvTiming(Packet *pkt);
virtual void recvRetry();
+
+ struct ITickEvent : public TickEvent
+ {
+
+ ITickEvent(TimingSimpleCPU *_cpu)
+ : TickEvent(_cpu) {}
+ void process();
+ const char *description() { return "Timing CPU clock event"; }
+ };
+
+ ITickEvent tickEvent;
+
};
class DcachePort : public CpuPort
{
public:
- DcachePort(TimingSimpleCPU *_cpu)
- : CpuPort(_cpu->name() + "-dport", _cpu)
+ DcachePort(TimingSimpleCPU *_cpu, Tick _lat)
+ : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu)
{ }
protected:
@@ -122,6 +147,17 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual bool recvTiming(Packet *pkt);
virtual void recvRetry();
+
+ struct DTickEvent : public TickEvent
+ {
+ DTickEvent(TimingSimpleCPU *_cpu)
+ : TickEvent(_cpu) {}
+ void process();
+ const char *description() { return "Timing CPU clock event"; }
+ };
+
+ DTickEvent tickEvent;
+
};
IcachePort icachePort;
@@ -137,9 +173,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
- virtual bool drain(Event *drain_event);
+ virtual unsigned int drain(Event *drain_event);
virtual void resume();
- virtual void setMemoryMode(State new_mode);
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc
index af1db2ff2..5f86cf2b7 100644
--- a/src/cpu/simple_thread.cc
+++ b/src/cpu/simple_thread.cc
@@ -196,6 +196,7 @@ SimpleThread::copyState(ThreadContext *oldContext)
#if !FULL_SYSTEM
funcExeInst = oldContext->readFuncExeInst();
#endif
+ inst = oldContext->getInst();
}
void
diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh
index d36853db4..242cfd0e1 100644
--- a/src/cpu/simple_thread.hh
+++ b/src/cpu/simple_thread.hh
@@ -449,8 +449,8 @@ class SimpleThread : public ThreadState
}
#endif
- void changeRegFileContext(RegFile::ContextParam param,
- RegFile::ContextVal val)
+ void changeRegFileContext(TheISA::RegContextParam param,
+ TheISA::RegContextVal val)
{
regs.changeContext(param, val);
}
diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh
index ea1a65148..578d14191 100644
--- a/src/cpu/static_inst.hh
+++ b/src/cpu/static_inst.hh
@@ -34,14 +34,16 @@
#include <bitset>
#include <string>
+#include "arch/isa_traits.hh"
+#include "sim/faults.hh"
#include "base/bitfield.hh"
#include "base/hashmap.hh"
#include "base/misc.hh"
#include "base/refcnt.hh"
#include "cpu/op_class.hh"
#include "cpu/o3/dyn_inst.hh"
+#include "sim/faults.hh"
#include "sim/host.hh"
-#include "arch/isa_traits.hh"
// forward declarations
struct AlphaSimpleImpl;
@@ -214,6 +216,7 @@ class StaticInstBase : public RefCounted
bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
bool isCondCtrl() const { return flags[IsCondControl]; }
bool isUncondCtrl() const { return flags[IsUncondControl]; }
+ bool isCondDelaySlot() const { return flags[IsCondDelaySlot]; }
bool isThreadSync() const { return flags[IsThreadSync]; }
bool isSerializing() const { return flags[IsSerializing] ||
diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh
index e019e22bc..73046097d 100644
--- a/src/cpu/thread_context.hh
+++ b/src/cpu/thread_context.hh
@@ -31,6 +31,9 @@
#ifndef __CPU_THREAD_CONTEXT_HH__
#define __CPU_THREAD_CONTEXT_HH__
+#include "arch/types.hh"
+#include "arch/regfile.hh"
+#include "arch/syscallreturn.hh"
#include "config/full_system.hh"
#include "mem/request.hh"
#include "sim/faults.hh"
@@ -254,8 +257,8 @@ class ThreadContext
virtual int exit() { return 1; };
#endif
- virtual void changeRegFileContext(RegFile::ContextParam param,
- RegFile::ContextVal val) = 0;
+ virtual void changeRegFileContext(TheISA::RegContextParam param,
+ TheISA::RegContextVal val) = 0;
};
/**
@@ -438,8 +441,8 @@ class ProxyThreadContext : public ThreadContext
Counter readFuncExeInst() { return actualTC->readFuncExeInst(); }
#endif
- void changeRegFileContext(RegFile::ContextParam param,
- RegFile::ContextVal val)
+ void changeRegFileContext(TheISA::RegContextParam param,
+ TheISA::RegContextVal val)
{
actualTC->changeRegFileContext(param, val);
}
diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh
index b03a2e2bb..6e985054f 100644
--- a/src/cpu/thread_state.hh
+++ b/src/cpu/thread_state.hh
@@ -31,7 +31,7 @@
#ifndef __CPU_THREAD_STATE_HH__
#define __CPU_THREAD_STATE_HH__
-#include "arch/isa_traits.hh"
+#include "arch/types.hh"
#include "cpu/thread_context.hh"
#if !FULL_SYSTEM
diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc
index 5ffc02d34..e8d7f4817 100644
--- a/src/dev/ide_ctrl.cc
+++ b/src/dev/ide_ctrl.cc
@@ -756,6 +756,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
Param<Tick> pio_latency;
+ Param<Tick> config_latency;
SimObjectVectorParam<IdeDisk *> disks;
END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
@@ -769,6 +770,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"),
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
+ INIT_PARAM(config_latency, "Number of cycles for a config read or write"),
INIT_PARAM(disks, "IDE disks attached to this controller")
END_INIT_SIM_OBJECT_PARAMS(IdeController)
@@ -784,6 +786,7 @@ CREATE_SIM_OBJECT(IdeController)
params->deviceNum = pci_dev;
params->functionNum = pci_func;
params->pio_delay = pio_latency;
+ params->config_delay = config_latency;
params->disks = disks;
return new IdeController(params);
}
diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc
index dc78021f8..12564ddd0 100644
--- a/src/dev/ide_disk.cc
+++ b/src/dev/ide_disk.cc
@@ -318,7 +318,7 @@ IdeDisk::doDmaTransfer()
panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
dmaState, devState);
- if (ctrl->dmaPending()) {
+ if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
} else
@@ -398,8 +398,7 @@ IdeDisk::doDmaRead()
curPrd.getByteCount(), TheISA::PageBytes);
}
- if (ctrl->dmaPending()) {
- panic("shouldn't be reentant??");
+ if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
} else if (!dmaReadCG->done()) {
@@ -474,8 +473,7 @@ IdeDisk::doDmaWrite()
dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(),
curPrd.getByteCount(), TheISA::PageBytes);
}
- if (ctrl->dmaPending()) {
- panic("shouldn't be reentant??");
+ if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
return;
} else if (!dmaWriteCG->done()) {
diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc
index cb4850108..b51a93190 100644
--- a/src/dev/io_device.cc
+++ b/src/dev/io_device.cc
@@ -32,10 +32,11 @@
#include "base/trace.hh"
#include "dev/io_device.hh"
#include "sim/builder.hh"
+#include "sim/system.hh"
-PioPort::PioPort(PioDevice *dev, Platform *p, std::string pname)
- : Port(dev->name() + pname), device(dev), platform(p)
+PioPort::PioPort(PioDevice *dev, System *s, std::string pname)
+ : SimpleTimingPort(dev->name() + pname), device(dev), sys(s)
{ }
@@ -59,38 +60,6 @@ PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
}
-void
-PioPort::recvRetry()
-{
- bool result = true;
- while (result && transmitList.size()) {
- result = Port::sendTiming(transmitList.front());
- if (result)
- transmitList.pop_front();
- }
-}
-
-void
-PioPort::SendEvent::process()
-{
- if (port->Port::sendTiming(packet))
- return;
-
- port->transmitList.push_back(packet);
-}
-
-void
-PioPort::resendNacked(Packet *pkt) {
- pkt->reinitNacked();
- if (transmitList.size()) {
- transmitList.push_front(pkt);
- } else {
- if (!Port::sendTiming(pkt))
- transmitList.push_front(pkt);
- }
-};
-
-
bool
PioPort::recvTiming(Packet *pkt)
{
@@ -119,6 +88,19 @@ PioDevice::init()
pioPort->sendStatusChange(Port::RangeChange);
}
+
+unsigned int
+PioDevice::drain(Event *de)
+{
+ unsigned int count;
+ count = pioPort->drain(de);
+ if (count)
+ changeState(Draining);
+ else
+ changeState(Drained);
+ return count;
+}
+
void
BasicPioDevice::addressRanges(AddrRangeList &range_list)
{
@@ -128,8 +110,9 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list)
}
-DmaPort::DmaPort(DmaDevice *dev, Platform *p)
- : Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0)
+DmaPort::DmaPort(DmaDevice *dev, System *s)
+ : Port(dev->name() + "-dmaport"), device(dev), sys(s), pendingCount(0),
+ actionInProgress(0), drainEvent(NULL)
{ }
bool
@@ -159,6 +142,11 @@ DmaPort::recvTiming(Packet *pkt)
}
delete pkt->req;
delete pkt;
+
+ if (pendingCount == 0 && drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
+ }
} else {
panic("Got packet without sender state... huh?\n");
}
@@ -170,6 +158,29 @@ DmaDevice::DmaDevice(Params *p)
: PioDevice(p), dmaPort(NULL)
{ }
+
+unsigned int
+DmaDevice::drain(Event *de)
+{
+ unsigned int count;
+ count = pioPort->drain(de) + dmaPort->drain(de);
+ if (count)
+ changeState(Draining);
+ else
+ changeState(Drained);
+ return count;
+}
+
+unsigned int
+DmaPort::drain(Event *de)
+{
+ if (pendingCount == 0)
+ return 0;
+ drainEvent = de;
+ return 1;
+}
+
+
void
DmaPort::recvRetry()
{
@@ -195,6 +206,8 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
{
assert(event);
+ assert(device->getState() == SimObject::Running);
+
DmaReqState *reqState = new DmaReqState(event, this, size);
for (ChunkGenerator gen(addr, size, peerBlockSize());
@@ -212,51 +225,54 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
pendingCount++;
sendDma(pkt);
}
+
}
void
DmaPort::sendDma(Packet *pkt, bool front)
{
- // some kind of selction between access methods
- // more work is going to have to be done to make
- // switching actually work
- /* MemState state = device->platform->system->memState;
-
- if (state == Timing) { */
- DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
- pkt, pkt->getAddr());
- if (transmitList.size() || !sendTiming(pkt)) {
- if (front)
- transmitList.push_front(pkt);
- else
- transmitList.push_back(pkt);
- DPRINTF(DMA, "-- Failed: queued\n");
- } else {
- DPRINTF(DMA, "-- Done\n");
- }
- /* } else if (state == Atomic) {
- sendAtomic(pkt);
- if (pkt->senderState) {
- DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
- assert(state);
- state->completionEvent->schedule(curTick + (pkt->time -
- pkt->req->getTime()) +1);
- delete state;
- }
- pendingCount--;
- assert(pendingCount >= 0);
- delete pkt->req;
- delete pkt;
-
- } else if (state == Functional) {
- sendFunctional(pkt);
- // Is this correct???
- completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime);
- completionEvent == NULL;
+ // some kind of selction between access methods
+ // more work is going to have to be done to make
+ // switching actually work
+
+ System::MemoryMode state = sys->getMemoryMode();
+ if (state == System::Timing) {
+ DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
+ pkt, pkt->getAddr());
+ if (transmitList.size() || !sendTiming(pkt)) {
+ if (front)
+ transmitList.push_front(pkt);
+ else
+ transmitList.push_back(pkt);
+ DPRINTF(DMA, "-- Failed: queued\n");
+ } else {
+ DPRINTF(DMA, "-- Done\n");
+ }
+ } else if (state == System::Atomic) {
+ Tick lat;
+ lat = sendAtomic(pkt);
+ assert(pkt->senderState);
+ DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
+ assert(state);
+
+ state->numBytes += pkt->req->getSize();
+ if (state->totBytes == state->numBytes) {
+ state->completionEvent->schedule(curTick + lat);
+ delete state;
+ delete pkt->req;
+ }
+ pendingCount--;
+ assert(pendingCount >= 0);
+ delete pkt;
+
+ if (pendingCount == 0 && drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
+ }
+
} else
panic("Unknown memory command state.");
- */
}
DmaDevice::~DmaDevice()
diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh
index 40edf6875..710b22b2c 100644
--- a/src/dev/io_device.hh
+++ b/src/dev/io_device.hh
@@ -37,6 +37,7 @@
#include "mem/packet_impl.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
+#include "mem/tport.hh"
class Platform;
class PioDevice;
@@ -48,25 +49,17 @@ class System;
* sensitive to an address range use. The port takes all the memory
* access types and roles them into one read() and write() call that the device
* must respond to. The device must also provide the addressRanges() function
- * with which it returns the address ranges it is interested in. An extra
- * sendTiming() function is implemented which takes an delay. In this way the
- * device can immediatly call sendTiming(pkt, time) after processing a request
- * and the request will be handled by the port even if the port bus the device
- * connects to is blocked.
- */
-class PioPort : public Port
+ * with which it returns the address ranges it is interested in. */
+
+class PioPort : public SimpleTimingPort
{
protected:
/** The device that this port serves. */
PioDevice *device;
- /** The platform that device/port are in. This is used to select which mode
+ /** The system that device/port are in. This is used to select which mode
* we are currently operating in. */
- Platform *platform;
-
- /** A list of outgoing timing response packets that haven't been serviced
- * yet. */
- std::list<Packet*> transmitList;
+ System *sys;
/** The current status of the peer(bus) that we are connected to. */
Status peerStatus;
@@ -82,42 +75,9 @@ class PioPort : public Port
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
- void resendNacked(Packet *pkt);
-
- /**
- * This class is used to implemented sendTiming() with a delay. When a delay
- * is requested a new event is created. When the event time expires it
- * attempts to send the packet. If it cannot, the packet is pushed onto the
- * transmit list to be sent when recvRetry() is called. */
- class SendEvent : public Event
- {
- PioPort *port;
- Packet *packet;
-
- SendEvent(PioPort *p, Packet *pkt, Tick t)
- : Event(&mainEventQueue), port(p), packet(pkt)
- { schedule(curTick + t); }
-
- virtual void process();
-
- virtual const char *description()
- { return "Future scheduled sendTiming event"; }
-
- friend class PioPort;
- };
-
- /** Schedule a sendTiming() event to be called in the future. */
- void sendTiming(Packet *pkt, Tick time)
- { new PioPort::SendEvent(this, pkt, time); }
-
- /** This function is notification that the device should attempt to send a
- * packet again. */
- virtual void recvRetry();
-
public:
- PioPort(PioDevice *dev, Platform *p, std::string pname = "-pioport");
+ PioPort(PioDevice *dev, System *s, std::string pname = "-pioport");
- friend class PioPort::SendEvent;
};
@@ -147,13 +107,20 @@ class DmaPort : public Port
DmaDevice *device;
std::list<Packet*> transmitList;
- /** The platform that device/port are in. This is used to select which mode
+ /** The system that device/port are in. This is used to select which mode
* we are currently operating in. */
- Platform *platform;
+ System *sys;
/** Number of outstanding packets the dma port has. */
int pendingCount;
+ /** If a dmaAction is in progress. */
+ int actionInProgress;
+
+ /** If we need to drain, keep the drain event around until we're done
+ * here.*/
+ Event *drainEvent;
+
virtual bool recvTiming(Packet *pkt);
virtual Tick recvAtomic(Packet *pkt)
{ panic("dma port shouldn't be used for pio access."); }
@@ -171,13 +138,14 @@ class DmaPort : public Port
void sendDma(Packet *pkt, bool front = false);
public:
- DmaPort(DmaDevice *dev, Platform *p);
+ DmaPort(DmaDevice *dev, System *s);
void dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
uint8_t *data = NULL);
bool dmaPending() { return pendingCount > 0; }
+ unsigned int drain(Event *de);
};
/**
@@ -196,6 +164,8 @@ class PioDevice : public MemObject
* transaction we should perform. */
Platform *platform;
+ System *sys;
+
/** The pioPort that handles the requests for us and provides us requests
* that it sees. */
PioPort *pioPort;
@@ -240,20 +210,22 @@ class PioDevice : public MemObject
const Params *params() const { return _params; }
PioDevice(Params *p)
- : MemObject(p->name), platform(p->platform), pioPort(NULL),
- _params(p)
+ : MemObject(p->name), platform(p->platform), sys(p->system),
+ pioPort(NULL), _params(p)
{}
virtual ~PioDevice();
virtual void init();
+ virtual unsigned int drain(Event *de);
+
virtual Port *getPort(const std::string &if_name, int idx = -1)
{
if (if_name == "pio") {
if (pioPort != NULL)
panic("pio port already connected to.");
- pioPort = new PioPort(this, params()->platform);
+ pioPort = new PioPort(this, sys);
return pioPort;
} else
return NULL;
@@ -287,7 +259,7 @@ class BasicPioDevice : public PioDevice
{}
/** return the address ranges that this device responds to.
- * @params range_list range list to populate with ranges
+ * @param range_list range list to populate with ranges
*/
void addressRanges(AddrRangeList &range_list);
@@ -310,17 +282,19 @@ class DmaDevice : public PioDevice
bool dmaPending() { return dmaPort->dmaPending(); }
+ virtual unsigned int drain(Event *de);
+
virtual Port *getPort(const std::string &if_name, int idx = -1)
{
if (if_name == "pio") {
if (pioPort != NULL)
panic("pio port already connected to.");
- pioPort = new PioPort(this, params()->platform);
+ pioPort = new PioPort(this, sys);
return pioPort;
} else if (if_name == "dma") {
if (dmaPort != NULL)
panic("dma port already connected to.");
- dmaPort = new DmaPort(this, params()->platform);
+ dmaPort = new DmaPort(this, sys);
return dmaPort;
} else
return NULL;
diff --git a/src/dev/isa_fake.hh b/src/dev/isa_fake.hh
index a7a469e17..5166882f8 100644
--- a/src/dev/isa_fake.hh
+++ b/src/dev/isa_fake.hh
@@ -65,14 +65,14 @@ class IsaFake : public BasicPioDevice
/**
* This read always returns -1.
- * @param req The memory request.
+ * @param pkt The memory request.
* @param data Where to put the data.
*/
virtual Tick read(Packet *pkt);
/**
* All writes are simply ignored.
- * @param req The memory request.
+ * @param pkt The memory request.
* @param data the data to not write.
*/
virtual Tick write(Packet *pkt);
diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc
index 179a2c62d..704afcf7d 100644
--- a/src/dev/ns_gige.cc
+++ b/src/dev/ns_gige.cc
@@ -1377,7 +1377,7 @@ NSGigE::doRxDmaRead()
assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
rxDmaState = dmaReading;
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
rxDmaState = dmaReadWaiting;
else
dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
@@ -1408,7 +1408,7 @@ NSGigE::doRxDmaWrite()
assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
rxDmaState = dmaWriting;
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
rxDmaState = dmaWriteWaiting;
else
dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
@@ -1826,7 +1826,7 @@ NSGigE::doTxDmaRead()
assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
txDmaState = dmaReading;
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
txDmaState = dmaReadWaiting;
else
dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
@@ -1857,7 +1857,7 @@ NSGigE::doTxDmaWrite()
assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
txDmaState = dmaWriting;
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
txDmaState = dmaWriteWaiting;
else
dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
@@ -2406,6 +2406,20 @@ NSGigE::recvPacket(EthPacketPtr packet)
return true;
}
+
+void
+NSGigE::resume()
+{
+ SimObject::resume();
+
+ // During drain we could have left the state machines in a waiting state and
+ // they wouldn't get out until some other event occured to kick them.
+ // This way they'll get out immediately
+ txKick();
+ rxKick();
+}
+
+
//=====================================================================
//
//
@@ -2801,6 +2815,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
Param<Tick> pio_latency;
+ Param<Tick> config_latency;
Param<Tick> clock;
Param<bool> dma_desc_free;
@@ -2834,6 +2849,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"),
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
+ INIT_PARAM(config_latency, "Number of cycles for a config read or write"),
INIT_PARAM(clock, "State machine cycle time"),
INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"),
@@ -2871,6 +2887,7 @@ CREATE_SIM_OBJECT(NSGigE)
params->deviceNum = pci_dev;
params->functionNum = pci_func;
params->pio_delay = pio_latency;
+ params->config_delay = config_latency;
params->clock = clock;
params->dma_desc_free = dma_desc_free;
diff --git a/src/dev/ns_gige.hh b/src/dev/ns_gige.hh
index ea7243777..080c0b1f3 100644
--- a/src/dev/ns_gige.hh
+++ b/src/dev/ns_gige.hh
@@ -391,6 +391,8 @@ class NSGigE : public PciDev
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
+ virtual void resume();
+
public:
void regStats();
diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc
index 62a7324ad..e81e0d1ee 100644
--- a/src/dev/pcidev.cc
+++ b/src/dev/pcidev.cc
@@ -56,8 +56,8 @@ using namespace std;
PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid,
int funcid, Platform *p)
- : PioPort(dev,p,"-pciconf"), device(dev), busId(busid), deviceId(devid),
- functionId(funcid)
+ : PioPort(dev,p->system,"-pciconf"), device(dev), platform(p),
+ busId(busid), deviceId(devid), functionId(funcid)
{
configAddr = platform->calcConfigAddr(busId, deviceId, functionId);
}
@@ -132,6 +132,18 @@ PciDev::init()
PioDevice::init();
}
+unsigned int
+PciDev::drain(Event *de)
+{
+ unsigned int count;
+ count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de);
+ if (count)
+ changeState(Draining);
+ else
+ changeState(Drained);
+ return count;
+}
+
Tick
PciDev::readConfig(Packet *pkt)
{
diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh
index 20ab9364a..847fb07d0 100644
--- a/src/dev/pcidev.hh
+++ b/src/dev/pcidev.hh
@@ -95,6 +95,8 @@ class PciDev : public DmaDevice
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
+ Platform *platform;
+
int busId;
int deviceId;
int functionId;
@@ -249,6 +251,9 @@ class PciDev : public DmaDevice
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ virtual unsigned int drain(Event *de);
+
virtual Port *getPort(const std::string &if_name, int idx = -1)
{
if (if_name == "config") {
diff --git a/src/dev/platform.cc b/src/dev/platform.cc
index 8546b7805..07288249c 100644
--- a/src/dev/platform.cc
+++ b/src/dev/platform.cc
@@ -29,6 +29,7 @@
* Nathan Binkert
*/
+#include "base/misc.hh"
#include "dev/platform.hh"
#include "sim/builder.hh"
#include "sim/sim_exit.hh"
diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc
index dddda1f1c..40bf29c87 100644
--- a/src/dev/sinic.cc
+++ b/src/dev/sinic.cc
@@ -921,7 +921,7 @@ Device::rxKick()
break;
case rxBeginCopy:
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
goto exit;
rxDmaAddr = params()->platform->pciToDma(
@@ -1109,7 +1109,7 @@ Device::txKick()
break;
case txBeginCopy:
- if (dmaPending())
+ if (dmaPending() || getState() != Running)
goto exit;
txDmaAddr = params()->platform->pciToDma(
@@ -1287,6 +1287,18 @@ Device::recvPacket(EthPacketPtr packet)
return true;
}
+void
+Device::resume()
+{
+ SimObject::resume();
+
+ // During drain we could have left the state machines in a waiting state and
+ // they wouldn't get out until some other event occured to kick them.
+ // This way they'll get out immediately
+ txKick();
+ rxKick();
+}
+
//=====================================================================
//
//
@@ -1627,6 +1639,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
Param<Tick> pio_latency;
+ Param<Tick> config_latency;
Param<Tick> intr_delay;
Param<Tick> clock;
@@ -1669,6 +1682,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"),
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
+ INIT_PARAM(config_latency, "Number of cycles for a config read or write"),
INIT_PARAM(intr_delay, "Interrupt Delay"),
INIT_PARAM(clock, "State machine cycle time"),
@@ -1713,6 +1727,7 @@ CREATE_SIM_OBJECT(Device)
params->deviceNum = pci_dev;
params->functionNum = pci_func;
params->pio_delay = pio_latency;
+ params->config_delay = config_latency;
params->intr_delay = intr_delay;
params->clock = clock;
diff --git a/src/dev/sinic.hh b/src/dev/sinic.hh
index f6c229039..eece4ba6b 100644
--- a/src/dev/sinic.hh
+++ b/src/dev/sinic.hh
@@ -266,6 +266,7 @@ class Device : public Base
public:
virtual Tick read(Packet *pkt);
virtual Tick write(Packet *pkt);
+ virtual void resume();
void prepareIO(int cpu, int index);
void prepareRead(int cpu, int index);
diff --git a/src/dev/tsunami.hh b/src/dev/tsunami.hh
index 8bb66e914..6fbfac851 100644
--- a/src/dev/tsunami.hh
+++ b/src/dev/tsunami.hh
@@ -83,7 +83,8 @@ class Tsunami : public Platform
/**
* Constructor for the Tsunami Class.
* @param name name of the object
- * @param intrctrl pointer to the interrupt controller
+ * @param s system the object belongs to
+ * @param intctrl pointer to the interrupt controller
*/
Tsunami(const std::string &name, System *s, IntrControl *intctrl);
diff --git a/src/dev/tsunami_io.hh b/src/dev/tsunami_io.hh
index ee25bbdfd..9084a1be8 100644
--- a/src/dev/tsunami_io.hh
+++ b/src/dev/tsunami_io.hh
@@ -126,12 +126,14 @@ class TsunamiIO : public BasicPioDevice
/**
* Serialize this object to the given output stream.
+ * @param base The base name of the counter object.
* @param os The stream to serialize to.
*/
void serialize(const std::string &base, std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
+ * @param base The base name of the counter object.
* @param cp The checkpoint use.
* @param section The section name of this object
*/
@@ -221,12 +223,14 @@ class TsunamiIO : public BasicPioDevice
/**
* Serialize this object to the given output stream.
- * @param os The stream to serialize to.
+ * @param base The base name of the counter object.
+ * @param os The stream to serialize to.
*/
void serialize(const std::string &base, std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
+ * @param base The base name of the counter object.
* @param cp The checkpoint use.
* @param section The section name of this object
*/
@@ -254,12 +258,14 @@ class TsunamiIO : public BasicPioDevice
/**
* Serialize this object to the given output stream.
+ * @param base The base name of the counter object.
* @param os The stream to serialize to.
*/
void serialize(const std::string &base, std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
+ * @param base The base name of the counter object.
* @param cp The checkpoint use.
* @param section The section name of this object
*/
diff --git a/src/doxygen/footer.html b/src/doxygen/footer.html
new file mode 100644
index 000000000..6ef5293de
--- /dev/null
+++ b/src/doxygen/footer.html
@@ -0,0 +1,5 @@
+<hr size="1"><address style="align: right;"><small>
+Generated on $datetime for $projectname by <a href="http://www.doxygen.org/index.html"> doxygen</a> $doxygenversion</small></address>
+
+</body>
+</html>
diff --git a/src/doxygen/stl.hh b/src/doxygen/stl.hh
new file mode 100644
index 000000000..fd9f68140
--- /dev/null
+++ b/src/doxygen/stl.hh
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2003-2005 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: Erik Hallnor
+ * Nathan Binkert
+ */
+
+/**
+ * @file
+ * Dummy definitions of STL classes to pick up relationships in doxygen.
+ */
+
+namespace std {
+
+/** STL vector class*/
+template <class T> class vector {
+ public:
+ /** Dummy Item */
+ T item;
+};
+
+/** STL deque class */
+template <class T> class deque {
+ public:
+ /** Dummy Item */
+ T item;
+};
+
+/** STL list class */
+template <class T> class list {
+ public:
+ /** Dummy Item */
+ T item;
+};
+
+/** STL pair class */
+template <class X, class Y> class pair {
+ public:
+ /** Dummy Item */
+ X item1;
+ /** Dummy Item */
+ Y item2;
+};
+
+}
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc
index 29ea2e12f..9c14e7ee2 100644
--- a/src/mem/bridge.cc
+++ b/src/mem/bridge.cc
@@ -31,7 +31,8 @@
*/
/**
- * @file Definition of a simple bus bridge without buffering.
+ * @file
+ * Definition of a simple bus bridge without buffering.
*/
#include <algorithm>
diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh
index b3525d3e0..2ab9799c7 100644
--- a/src/mem/bridge.hh
+++ b/src/mem/bridge.hh
@@ -30,7 +30,8 @@
*/
/**
- * @file Decleration of a simple bus bridge object with no buffering
+ * @file
+ * Declaration of a simple bus bridge object with no buffering
*/
#ifndef __MEM_BRIDGE_HH__
@@ -49,7 +50,7 @@
class Bridge : public MemObject
{
protected:
- /** Decleration of the buses port type, one will be instantiated for each
+ /** Declaration of the buses port type, one will be instantiated for each
of the interfaces connecting to the bus. */
class BridgePort : public Port
{
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index 31271106b..b945f93b3 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -29,7 +29,8 @@
*/
/**
- * @file Definition of a bus object.
+ * @file
+ * Definition of a bus object.
*/
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 3a2896886..cd25fab2c 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -30,7 +30,8 @@
*/
/**
- * @file Decleration of a bus object.
+ * @file
+ * Declaration of a bus object.
*/
#ifndef __MEM_BUS_HH__
@@ -97,7 +98,7 @@ class Bus : public MemObject
void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id);
- /** Decleration of the buses port type, one will be instantiated for each
+ /** Declaration of the buses port type, one will be instantiated for each
of the interfaces connecting to the bus. */
class BusPort : public Port
{
diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh
index 823465769..9fb790cee 100644
--- a/src/mem/cache/base_cache.hh
+++ b/src/mem/cache/base_cache.hh
@@ -490,7 +490,7 @@ class BaseCache : public MemObject
/**
* Send a response to the slave interface.
- * @param req The request being responded to.
+ * @param pkt The request being responded to.
* @param time The time the response is ready.
*/
void respond(Packet *pkt, Tick time)
@@ -503,7 +503,7 @@ class BaseCache : public MemObject
/**
* Send a reponse to the slave interface and calculate miss latency.
- * @param req The request to respond to.
+ * @param pkt The request to respond to.
* @param time The time the response is ready.
*/
void respondToMiss(Packet *pkt, Tick time)
@@ -519,7 +519,7 @@ class BaseCache : public MemObject
/**
* Suppliess the data if cache to cache transfers are enabled.
- * @param req The bus transaction to fulfill.
+ * @param pkt The bus transaction to fulfill.
*/
void respondToSnoop(Packet *pkt)
{
diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh
index ec5b800a8..a26d91709 100644
--- a/src/mem/cache/cache.hh
+++ b/src/mem/cache/cache.hh
@@ -159,7 +159,7 @@ class Cache : public BaseCache
/**
* Performs the access specified by the request.
- * @param req The request to perform.
+ * @param pkt The request to perform.
* @return The result of the access.
*/
bool access(Packet * &pkt);
@@ -172,26 +172,26 @@ class Cache : public BaseCache
/**
* Was the request was sent successfully?
- * @param req The request.
+ * @param pkt The request.
* @param success True if the request was sent successfully.
*/
virtual void sendResult(Packet * &pkt, bool success);
/**
* Handles a response (cache line fill/write ack) from the bus.
- * @param req The request being responded to.
+ * @param pkt The request being responded to.
*/
void handleResponse(Packet * &pkt);
/**
* Start handling a copy transaction.
- * @param req The copy request to perform.
+ * @param pkt The copy request to perform.
*/
void startCopy(Packet * &pkt);
/**
* Handle a delayed copy transaction.
- * @param req The delayed copy request to continue.
+ * @param pkt The delayed copy request to continue.
* @param addr The address being responded to.
* @param blk The block of the current response.
* @param mshr The mshr being handled.
@@ -206,7 +206,7 @@ class Cache : public BaseCache
/**
* Snoops bus transactions to maintain coherence.
- * @param req The current bus transaction.
+ * @param pkt The current bus transaction.
*/
void snoop(Packet * &pkt);
@@ -221,9 +221,9 @@ class Cache : public BaseCache
void invalidateBlk(Addr addr, int asid);
/**
- * Aquash all requests associated with specified thread.
+ * Squash all requests associated with specified thread.
* intended for use by I-cache.
- * @param req->getThreadNum()ber The thread to squash.
+ * @param threadNum The thread to squash.
*/
void squash(int threadNum)
{
@@ -246,7 +246,7 @@ class Cache : public BaseCache
* time of completion. This function can either update the hierarchy state
* or just perform the access wherever the data is found depending on the
* state of the update flag.
- * @param req The memory request to satisfy
+ * @param pkt The memory request to satisfy
* @param update If true, update the hierarchy, otherwise just perform the
* request.
* @return The estimated completion time.
@@ -257,7 +257,7 @@ class Cache : public BaseCache
* Snoop for the provided request in the cache and return the estimated
* time of completion.
* @todo Can a snoop probe not change state?
- * @param req The memory request to satisfy
+ * @param pkt The memory request to satisfy
* @param update If true, update the hierarchy, otherwise just perform the
* request.
* @return The estimated completion time.
diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh
index 67e65d25b..a75c9611d 100644
--- a/src/mem/cache/cache_blk.hh
+++ b/src/mem/cache/cache_blk.hh
@@ -38,6 +38,8 @@
#include "sim/root.hh" // for Tick
#include "arch/isa_traits.hh" // for Addr
+#include <iostream>
+
/**
* Cache block status bit assignments
*/
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index db012920f..b215960c4 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -53,8 +53,6 @@
#include "sim/sim_events.hh" // for SimExitEvent
-using namespace std;
-
template<class TagStore, class Buffering, class Coherence>
bool
Cache<TagStore,Buffering,Coherence>::
@@ -501,7 +499,7 @@ Cache<TagStore,Buffering,Coherence>::probe(Packet * &pkt, bool update)
MSHR* mshr = missQueue->findMSHR(blk_addr, pkt->req->getAsid());
// There can be many matching outstanding writes.
- vector<MSHR*> writes;
+ std::vector<MSHR*> writes;
missQueue->findWrites(blk_addr, pkt->req->getAsid(), writes);
if (!update) {
diff --git a/src/mem/cache/coherence/coherence_protocol.hh b/src/mem/cache/coherence/coherence_protocol.hh
index 21351ace4..b5d7d80aa 100644
--- a/src/mem/cache/coherence/coherence_protocol.hh
+++ b/src/mem/cache/coherence/coherence_protocol.hh
@@ -85,7 +85,7 @@ class CoherenceProtocol : public SimObject
/**
* Return the proper state given the current state and the bus response.
- * @param req The bus response.
+ * @param pkt The bus response.
* @param oldState The current block state.
* @return The new state.
*/
@@ -95,7 +95,7 @@ class CoherenceProtocol : public SimObject
/**
* Handle snooped bus requests.
* @param cache The cache that snooped the request.
- * @param req The snooped bus request.
+ * @param pkt The snooped bus request.
* @param blk The cache block corresponding to the request, if any.
* @param mshr The MSHR corresponding to the request, if any.
* @param new_state The new coherence state of the block.
diff --git a/src/mem/cache/coherence/simple_coherence.hh b/src/mem/cache/coherence/simple_coherence.hh
index ca9d18beb..71d8f36f4 100644
--- a/src/mem/cache/coherence/simple_coherence.hh
+++ b/src/mem/cache/coherence/simple_coherence.hh
@@ -96,7 +96,7 @@ class SimpleCoherence
/**
* Return the proper state given the current state and the bus response.
- * @param req The bus response.
+ * @param pkt The bus response.
* @param current The current block state.
* @return The new state.
*/
@@ -107,7 +107,7 @@ class SimpleCoherence
/**
* Handle snooped bus requests.
- * @param req The snooped bus request.
+ * @param pkt The snooped bus request.
* @param blk The cache block corresponding to the request, if any.
* @param mshr The MSHR corresponding to the request, if any.
* @param new_state Return the new state for the block.
diff --git a/src/mem/cache/coherence/uni_coherence.hh b/src/mem/cache/coherence/uni_coherence.hh
index 764bf6276..27b6c7fb5 100644
--- a/src/mem/cache/coherence/uni_coherence.hh
+++ b/src/mem/cache/coherence/uni_coherence.hh
@@ -88,7 +88,7 @@ class UniCoherence
/**
* Just return readable and writeable.
- * @param req The bus response.
+ * @param pkt The bus response.
* @param current The current block state.
* @return The new state.
*/
@@ -116,7 +116,7 @@ class UniCoherence
/**
* Handle snooped bus requests.
- * @param req The snooped bus request.
+ * @param pkt The snooped bus request.
* @param blk The cache block corresponding to the request, if any.
* @param mshr The MSHR corresponding to the request, if any.
* @param new_state The new coherence state of the block.
diff --git a/src/mem/cache/miss/blocking_buffer.cc b/src/mem/cache/miss/blocking_buffer.cc
index 10d53b109..2f61e8a54 100644
--- a/src/mem/cache/miss/blocking_buffer.cc
+++ b/src/mem/cache/miss/blocking_buffer.cc
@@ -40,8 +40,6 @@
#include "sim/eventq.hh" // for Event declaration.
#include "mem/request.hh"
-using namespace TheISA;
-
/**
* @todo Move writebacks into shared BaseBuffer class.
*/
diff --git a/src/mem/cache/miss/blocking_buffer.hh b/src/mem/cache/miss/blocking_buffer.hh
index 39a06a377..a6261f62c 100644
--- a/src/mem/cache/miss/blocking_buffer.hh
+++ b/src/mem/cache/miss/blocking_buffer.hh
@@ -107,7 +107,7 @@ public:
/**
* Handle a cache miss properly. Requests the bus and marks the cache as
* blocked.
- * @param req The request that missed in the cache.
+ * @param pkt The request that missed in the cache.
* @param blk_size The block size of the cache.
* @param time The time the miss is detected.
*/
@@ -128,43 +128,43 @@ public:
}
/**
- * Selects a outstanding request to service.
- * @return The request to service, NULL if none found.
+ * Selects a outstanding pktuest to service.
+ * @return The pktuest to service, NULL if none found.
*/
Packet * getPacket();
/**
* Set the command to the given bus command.
- * @param req The request to update.
+ * @param pkt The request to update.
* @param cmd The bus command to use.
*/
void setBusCmd(Packet * &pkt, Packet::Command cmd);
/**
* Restore the original command in case of a bus transmission error.
- * @param req The request to reset.
+ * @param pkt The request to reset.
*/
void restoreOrigCmd(Packet * &pkt);
/**
- * Marks a request as in service (sent on the bus). This can have side
+ * Marks a pktuest as in service (sent on the bus). This can have side
* effect since storage for no response commands is deallocated once they
* are successfully sent.
- * @param req The request that was sent on the bus.
+ * @param pkt The request that was sent on the bus.
*/
void markInService(Packet * &pkt);
/**
- * Frees the resources of the request and unblock the cache.
- * @param req The request that has been satisfied.
- * @param time The time when the request is satisfied.
+ * Frees the resources of the pktuest and unblock the cache.
+ * @param pkt The request that has been satisfied.
+ * @param time The time when the pktuest is satisfied.
*/
void handleResponse(Packet * &pkt, Tick time);
/**
- * Removes all outstanding requests for a given thread number. If a request
+ * Removes all outstanding pktuests for a given thread number. If a request
* has been sent to the bus, this function removes all of its targets.
- * @param req->getThreadNum()ber The thread number of the requests to squash.
+ * @param threadNum The thread number of the requests to squash.
*/
void squash(int threadNum);
@@ -220,14 +220,14 @@ public:
int size, uint8_t *data, bool compressed);
/**
- * Perform a writeback request.
- * @param req The writeback request.
+ * Perform a writeback pktuest.
+ * @param pkt The writeback request.
*/
void doWriteback(Packet * &pkt);
/**
- * Returns true if there are outstanding requests.
- * @return True if there are outstanding requests.
+ * Returns true if there are outstanding pktuests.
+ * @return True if there are outstanding pktuests.
*/
bool havePending()
{
@@ -237,7 +237,7 @@ public:
/**
* Add a target to the given MSHR. This assumes it is in the miss queue.
* @param mshr The mshr to add a target to.
- * @param req The target to add.
+ * @param pkt The target to add.
*/
void addTarget(MSHR *mshr, Packet * &pkt)
{
diff --git a/src/mem/cache/miss/miss_queue.hh b/src/mem/cache/miss/miss_queue.hh
index b88b7038c..c558df956 100644
--- a/src/mem/cache/miss/miss_queue.hh
+++ b/src/mem/cache/miss/miss_queue.hh
@@ -77,7 +77,7 @@ class MissQueue
/** The block size of the parent cache. */
int blkSize;
- /** Increasing order number assigned to each incoming request. */
+ /** Increasing order number assigned to each incoming pktuest. */
uint64_t order;
bool prefetchMiss;
@@ -164,7 +164,7 @@ class MissQueue
/**
* Allocate a new MSHR to handle the provided miss.
- * @param req The miss to buffer.
+ * @param pkt The miss to buffer.
* @param size The number of bytes to fetch.
* @param time The time the miss occurs.
* @return A pointer to the new MSHR.
@@ -173,7 +173,7 @@ class MissQueue
/**
* Allocate a new WriteBuffer to handle the provided write.
- * @param req The write to handle.
+ * @param pkt The write to handle.
* @param size The number of bytes to write.
* @param time The time the write occurs.
* @return A pointer to the new write buffer.
@@ -212,9 +212,9 @@ class MissQueue
void setPrefetcher(BasePrefetcher *_prefetcher);
/**
- * Handle a cache miss properly. Either allocate an MSHR for the request,
+ * Handle a cache miss properly. Either allocate an MSHR for the pktuest,
* or forward it through the write buffer.
- * @param req The request that missed in the cache.
+ * @param pkt The request that missed in the cache.
* @param blk_size The block size of the cache.
* @param time The time the miss is detected.
*/
@@ -232,43 +232,43 @@ class MissQueue
Packet * &target);
/**
- * Selects a outstanding request to service.
- * @return The request to service, NULL if none found.
+ * Selects a outstanding pktuest to service.
+ * @return The pktuest to service, NULL if none found.
*/
Packet * getPacket();
/**
* Set the command to the given bus command.
- * @param req The request to update.
+ * @param pkt The request to update.
* @param cmd The bus command to use.
*/
void setBusCmd(Packet * &pkt, Packet::Command cmd);
/**
* Restore the original command in case of a bus transmission error.
- * @param req The request to reset.
+ * @param pkt The request to reset.
*/
void restoreOrigCmd(Packet * &pkt);
/**
- * Marks a request as in service (sent on the bus). This can have side
+ * Marks a pktuest as in service (sent on the bus). This can have side
* effect since storage for no response commands is deallocated once they
* are successfully sent.
- * @param req The request that was sent on the bus.
+ * @param pkt The request that was sent on the bus.
*/
void markInService(Packet * &pkt);
/**
- * Collect statistics and free resources of a satisfied request.
- * @param req The request that has been satisfied.
- * @param time The time when the request is satisfied.
+ * Collect statistics and free resources of a satisfied pktuest.
+ * @param pkt The request that has been satisfied.
+ * @param time The time when the pktuest is satisfied.
*/
void handleResponse(Packet * &pkt, Tick time);
/**
- * Removes all outstanding requests for a given thread number. If a request
+ * Removes all outstanding pktuests for a given thread number. If a request
* has been sent to the bus, this function removes all of its targets.
- * @param req->getThreadNum()ber The thread number of the requests to squash.
+ * @param threadNum The thread number of the requests to squash.
*/
void squash(int threadNum);
@@ -313,21 +313,21 @@ class MissQueue
int size, uint8_t *data, bool compressed);
/**
- * Perform the given writeback request.
- * @param req The writeback request.
+ * Perform the given writeback pktuest.
+ * @param pkt The writeback request.
*/
void doWriteback(Packet * &pkt);
/**
- * Returns true if there are outstanding requests.
- * @return True if there are outstanding requests.
+ * Returns true if there are outstanding pktuests.
+ * @return True if there are outstanding pktuests.
*/
bool havePending();
/**
* Add a target to the given MSHR. This assumes it is in the miss queue.
* @param mshr The mshr to add a target to.
- * @param req The target to add.
+ * @param pkt The target to add.
*/
void addTarget(MSHR *mshr, Packet * &pkt)
{
diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh
index 167aa26cd..ad2865973 100644
--- a/src/mem/cache/miss/mshr.hh
+++ b/src/mem/cache/miss/mshr.hh
@@ -44,7 +44,7 @@ class MSHR;
/**
* Miss Status and handling Register. This class keeps all the information
- * needed to handle a cache miss including a list of target requests.
+ * needed to handle a cache miss including a list of target pktuests.
*/
class MSHR {
public:
@@ -63,15 +63,15 @@ class MSHR {
Addr addr;
/** Adress space id of the miss. */
short asid;
- /** True if the request has been sent to the bus. */
+ /** True if the pktuest has been sent to the bus. */
bool inService;
/** Thread number of the miss. */
int threadNum;
- /** The request that is forwarded to the next level of the hierarchy. */
+ /** The pktuest that is forwarded to the next level of the hierarchy. */
Packet * pkt;
/** The number of currently allocated targets. */
short ntargets;
- /** The original requesting command. */
+ /** The original pktuesting command. */
Packet::Command originalCmd;
/** Order number of assigned by the miss queue. */
uint64_t order;
@@ -88,24 +88,24 @@ class MSHR {
Iterator allocIter;
private:
- /** List of all requests that match the address */
+ /** List of all pktuests that match the address */
TargetList targets;
public:
/**
* Allocate a miss to this MSHR.
- * @param cmd The requesting command.
+ * @param cmd The pktuesting command.
* @param addr The address of the miss.
* @param asid The address space id of the miss.
- * @param size The number of bytes to request.
- * @param req The original miss.
+ * @param size The number of bytes to pktuest.
+ * @param pkt The original miss.
*/
void allocate(Packet::Command cmd, Addr addr, int asid, int size,
Packet * &pkt);
/**
- * Allocate this MSHR as a buffer for the given request.
- * @param target The memory request to buffer.
+ * Allocate this MSHR as a buffer for the given pktuest.
+ * @param target The memory pktuest to buffer.
*/
void allocateAsBuffer(Packet * &target);
@@ -115,7 +115,7 @@ public:
void deallocate();
/**
- * Add a request to the list of targets.
+ * Add a pktuest to the list of targets.
* @param target The target.
*/
void allocateTarget(Packet * &target);
diff --git a/src/mem/cache/miss/mshr_queue.hh b/src/mem/cache/miss/mshr_queue.hh
index a67f1b9a6..02b6a026d 100644
--- a/src/mem/cache/miss/mshr_queue.hh
+++ b/src/mem/cache/miss/mshr_queue.hh
@@ -39,7 +39,7 @@
#include "mem/cache/miss/mshr.hh"
/**
- * A Class for maintaining a list of pending and allocated memory requests.
+ * A Class for maintaining a list of pending and allocated memory pktuests.
*/
class MSHRQueue {
private:
@@ -55,7 +55,7 @@ class MSHRQueue {
// Parameters
/**
* The total number of MSHRs in this queue. This number is set as the
- * number of MSHRs requested plus (numReserve - 1). This allows for
+ * number of MSHRs pktuested plus (numReserve - 1). This allows for
* the same number of effective MSHRs while still maintaining the reserve.
*/
const int numMSHRs;
@@ -103,16 +103,16 @@ class MSHRQueue {
bool findMatches(Addr addr, int asid, std::vector<MSHR*>& matches) const;
/**
- * Find any pending requests that overlap the given request.
- * @param req The request to find.
+ * Find any pending pktuests that overlap the given request.
+ * @param pkt The request to find.
* @return A pointer to the earliest matching MSHR.
*/
MSHR* findPending(Packet * &pkt) const;
/**
- * Allocates a new MSHR for the request and size. This places the request
+ * Allocates a new MSHR for the pktuest and size. This places the request
* as the first target in the MSHR.
- * @param req The request to handle.
+ * @param pkt The request to handle.
* @param size The number in bytes to fetch from memory.
* @return The a pointer to the MSHR allocated.
*
@@ -121,12 +121,12 @@ class MSHRQueue {
MSHR* allocate(Packet * &pkt, int size = 0);
/**
- * Allocate a read request for the given address, and places the given
+ * Allocate a read pktuest for the given address, and places the given
* target on the target list.
* @param addr The address to fetch.
* @param asid The address space for the fetch.
- * @param size The number of bytes to request.
- * @param target The first target for the request.
+ * @param size The number of bytes to pktuest.
+ * @param target The first target for the pktuest.
* @return Pointer to the new MSHR.
*/
MSHR* allocateFetch(Addr addr, int asid, int size, Packet * &target);
@@ -135,7 +135,7 @@ class MSHRQueue {
* Allocate a target list for the given address.
* @param addr The address to fetch.
* @param asid The address space for the fetch.
- * @param size The number of bytes to request.
+ * @param size The number of bytes to pktuest.
* @return Pointer to the new MSHR.
*/
MSHR* allocateTargetList(Addr addr, int asid, int size);
@@ -151,7 +151,7 @@ class MSHRQueue {
* Allocates a target to the given MSHR. Used to keep track of the number
* of outstanding targets.
* @param mshr The MSHR to allocate the target to.
- * @param req The target request.
+ * @param pkt The target request.
*/
void allocateTarget(MSHR* mshr, Packet * &pkt)
{
@@ -181,22 +181,22 @@ class MSHRQueue {
void markInService(MSHR* mshr);
/**
- * Mark an in service mshr as pending, used to resend a request.
+ * Mark an in service mshr as pending, used to resend a pktuest.
* @param mshr The MSHR to resend.
* @param cmd The command to resend.
*/
void markPending(MSHR* mshr, Packet::Command cmd);
/**
- * Squash outstanding requests with the given thread number. If a request
+ * Squash outstanding pktuests with the given thread number. If a request
* is in service, just squashes the targets.
- * @param req->getThreadNum()ber The thread to squash.
+ * @param threadNum The thread to squash.
*/
void squash(int threadNum);
/**
* Returns true if the pending list is not empty.
- * @return True if there are outstanding requests.
+ * @return True if there are outstanding pktuests.
*/
bool havePending() const
{
@@ -213,8 +213,8 @@ class MSHRQueue {
}
/**
- * Returns the request at the head of the pendingList.
- * @return The next request to service.
+ * Returns the pktuest at the head of the pendingList.
+ * @return The next pktuest to service.
*/
Packet * getReq() const
{
diff --git a/src/mem/cache/prefetch/tagged_prefetcher_impl.hh b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh
index db5c94820..e554b3cec 100644
--- a/src/mem/cache/prefetch/tagged_prefetcher_impl.hh
+++ b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh
@@ -33,6 +33,7 @@
* Describes a tagged prefetcher based on template policies.
*/
+#include "arch/isa_traits.hh"
#include "mem/cache/prefetch/tagged_prefetcher.hh"
template <class TagStore, class Buffering>
diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh
index 566e36c27..444954917 100644
--- a/src/mem/cache/tags/fa_lru.hh
+++ b/src/mem/cache/tags/fa_lru.hh
@@ -193,7 +193,7 @@ public:
/**
* Find the block in the cache and update the replacement data. Returns
* the access latency and the in cache flags as a side effect
- * @param req The req whose block to find
+ * @param pkt The req whose block to find
* @param lat The latency of the access.
* @param inCache The FALRUBlk::inCache flags.
* @return Pointer to the cache block.
@@ -210,7 +210,7 @@ public:
/**
* Find a replacement block for the address provided.
- * @param req The request to a find a replacement candidate for.
+ * @param pkt The request to a find a replacement candidate for.
* @param writebacks List for any writebacks to be performed.
* @param compress_blocks List of blocks to compress, for adaptive comp.
* @return The block to place the replacement in.
@@ -328,7 +328,7 @@ public:
* @param source The block aligned source address.
* @param dest The block aligned destination adddress.
* @param asid The address space ID.
- * @param writebacks List for any generated writeback requests.
+ * @param writebacks List for any generated writeback pktuests.
*/
void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks)
{
diff --git a/src/mem/cache/tags/iic.hh b/src/mem/cache/tags/iic.hh
index 6628f7e7a..514d16bdd 100644
--- a/src/mem/cache/tags/iic.hh
+++ b/src/mem/cache/tags/iic.hh
@@ -454,7 +454,7 @@ class IIC : public BaseTags
/**
* Find the block and update the replacement data. This call also returns
* the access latency as a side effect.
- * @param req The req whose block to find
+ * @param pkt The req whose block to find
* @param lat The access latency.
* @return A pointer to the block found, if any.
*/
@@ -470,7 +470,7 @@ class IIC : public BaseTags
/**
* Find a replacement block for the address provided.
- * @param req The request to a find a replacement candidate for.
+ * @param pkt The request to a find a replacement candidate for.
* @param writebacks List for any writebacks to be performed.
* @param compress_blocks List of blocks to compress, for adaptive comp.
* @return The block to place the replacement in.
@@ -502,14 +502,14 @@ class IIC : public BaseTags
* @param source The block-aligned source address.
* @param dest The block-aligned destination address.
* @param asid The address space DI.
- * @param writebacks List for any generated writeback requests.
+ * @param writebacks List for any generated writeback pktuests.
*/
void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks);
/**
* If a block is currently marked copy on write, copy it before writing.
- * @param req The write request.
- * @param writebacks List for any generated writeback requests.
+ * @param pkt The write request.
+ * @param writebacks List for any generated writeback pktuests.
*/
void fixCopy(Packet * &pkt, PacketList &writebacks);
diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh
index 437244660..8f0f3ae27 100644
--- a/src/mem/cache/tags/lru.hh
+++ b/src/mem/cache/tags/lru.hh
@@ -170,7 +170,7 @@ public:
/**
* Finds the given address in the cache and update replacement data.
* Returns the access latency as a side effect.
- * @param req The request whose block to find.
+ * @param pkt The request whose block to find.
* @param lat The access latency.
* @return Pointer to the cache block if found.
*/
@@ -196,7 +196,7 @@ public:
/**
* Find a replacement block for the address provided.
- * @param req The request to a find a replacement candidate for.
+ * @param pkt The request to a find a replacement candidate for.
* @param writebacks List for any writebacks to be performed.
* @param compress_blocks List of blocks to compress, for adaptive comp.
* @return The block to place the replacement in.
@@ -307,7 +307,7 @@ public:
* @param source The block-aligned source address.
* @param dest The block-aligned destination address.
* @param asid The address space DI.
- * @param writebacks List for any generated writeback requests.
+ * @param writebacks List for any generated writeback pktuests.
*/
void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks);
diff --git a/src/mem/cache/tags/split.hh b/src/mem/cache/tags/split.hh
index 5e0340269..25180a02b 100644
--- a/src/mem/cache/tags/split.hh
+++ b/src/mem/cache/tags/split.hh
@@ -71,13 +71,13 @@ class Split : public BaseTags
Addr blkMask;
- /** Number of NIC requests that hit in the NIC partition */
+ /** Number of NIC pktuests that hit in the NIC partition */
Stats::Scalar<> NR_NP_hits;
- /** Number of NIC requests that hit in the CPU partition */
+ /** Number of NIC pktuests that hit in the CPU partition */
Stats::Scalar<> NR_CP_hits;
- /** Number of CPU requests that hit in the NIC partition */
+ /** Number of CPU pktuests that hit in the NIC partition */
Stats::Scalar<> CR_NP_hits;
- /** Number of CPU requests that hit in the CPU partition */
+ /** Number of CPU pktuests that hit in the CPU partition */
Stats::Scalar<> CR_CP_hits;
/** The number of nic replacements (i.e. misses) */
Stats::Scalar<> nic_repl;
@@ -203,7 +203,7 @@ class Split : public BaseTags
/**
* Finds the given address in the cache and update replacement data.
* Returns the access latency as a side effect.
- * @param req The memory request whose block to find
+ * @param pkt The memory request whose block to find
* @param lat The access latency.
* @return Pointer to the cache block if found.
*/
@@ -219,7 +219,7 @@ class Split : public BaseTags
/**
* Find a replacement block for the address provided.
- * @param req The request to a find a replacement candidate for.
+ * @param pkt The request to a find a replacement candidate for.
* @param writebacks List for any writebacks to be performed.
* @param compress_blocks List of blocks to compress, for adaptive comp.
* @return The block to place the replacement in.
@@ -315,7 +315,7 @@ class Split : public BaseTags
* @param source The block-aligned source address.
* @param dest The block-aligned destination address.
* @param asid The address space DI.
- * @param writebacks List for any generated writeback requests.
+ * @param writebacks List for any generated writeback pktuests.
*/
void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks);
diff --git a/src/mem/cache/tags/split_blk.hh b/src/mem/cache/tags/split_blk.hh
index f38516180..64d903579 100644
--- a/src/mem/cache/tags/split_blk.hh
+++ b/src/mem/cache/tags/split_blk.hh
@@ -47,7 +47,7 @@ class SplitBlk : public CacheBlk {
bool isTouched;
/** Has this block been used after being brought in? (for LIFO partition) */
bool isUsed;
- /** is this blk a NIC block? (i.e. requested by the NIC) */
+ /** is this blk a NIC block? (i.e. pktuested by the NIC) */
bool isNIC;
/** timestamp of the arrival of this block into the cache */
Tick ts;
diff --git a/src/mem/cache/tags/split_lifo.hh b/src/mem/cache/tags/split_lifo.hh
index dfcaa0b67..52956b192 100644
--- a/src/mem/cache/tags/split_lifo.hh
+++ b/src/mem/cache/tags/split_lifo.hh
@@ -203,7 +203,7 @@ public:
/**
* Finds the given address in the cache and update replacement data.
* Returns the access latency as a side effect.
- * @param req The req whose block to find
+ * @param pkt The req whose block to find
* @param lat The access latency.
* @return Pointer to the cache block if found.
*/
@@ -219,7 +219,7 @@ public:
/**
* Find a replacement block for the address provided.
- * @param req The request to a find a replacement candidate for.
+ * @param pkt The request to a find a replacement candidate for.
* @param writebacks List for any writebacks to be performed.
* @param compress_blocks List of blocks to compress, for adaptive comp.
* @return The block to place the replacement in.
@@ -330,7 +330,7 @@ public:
* @param source The block-aligned source address.
* @param dest The block-aligned destination address.
* @param asid The address space DI.
- * @param writebacks List for any generated writeback requests.
+ * @param writebacks List for any generated writeback pktuests.
*/
void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks);
diff --git a/src/mem/cache/tags/split_lru.hh b/src/mem/cache/tags/split_lru.hh
index 03886b1d8..6d370c5dd 100644
--- a/src/mem/cache/tags/split_lru.hh
+++ b/src/mem/cache/tags/split_lru.hh
@@ -186,7 +186,7 @@ public:
/**
* Finds the given address in the cache and update replacement data.
* Returns the access latency as a side effect.
- * @param req The req whose block to find.
+ * @param pkt The req whose block to find.
* @param lat The access latency.
* @return Pointer to the cache block if found.
*/
@@ -202,7 +202,7 @@ public:
/**
* Find a replacement block for the address provided.
- * @param req The request to a find a replacement candidate for.
+ * @param pkt The request to a find a replacement candidate for.
* @param writebacks List for any writebacks to be performed.
* @param compress_blocks List of blocks to compress, for adaptive comp.
* @return The block to place the replacement in.
@@ -313,7 +313,7 @@ public:
* @param source The block-aligned source address.
* @param dest The block-aligned destination address.
* @param asid The address space DI.
- * @param writebacks List for any generated writeback requests.
+ * @param writebacks List for any generated writeback pktuests.
*/
void doCopy(Addr source, Addr dest, int asid, PacketList &writebacks);
diff --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh
index c81ea03d8..d12eeffe0 100644
--- a/src/mem/mem_object.hh
+++ b/src/mem/mem_object.hh
@@ -30,7 +30,7 @@
/**
* @file
- * Base Memory Object decleration.
+ * Base Memory Object declaration.
*/
#ifndef __MEM_MEM_OBJECT_HH__
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index 534db0077..83b4006e2 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -39,7 +39,7 @@
#define __MEM_PACKET_HH__
#include "mem/request.hh"
-#include "arch/isa_traits.hh"
+#include "sim/host.hh"
#include "sim/root.hh"
#include <list>
diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc
index a34a0393a..2b460306f 100644
--- a/src/mem/page_table.cc
+++ b/src/mem/page_table.cc
@@ -64,7 +64,7 @@ PageTable::~PageTable()
}
Fault
-PageTable::page_check(Addr addr, int size) const
+PageTable::page_check(Addr addr, int64_t size) const
{
if (size < sizeof(uint64_t)) {
if (!isPowerOf2(size)) {
@@ -92,7 +92,7 @@ PageTable::page_check(Addr addr, int size) const
void
-PageTable::allocate(Addr vaddr, int size)
+PageTable::allocate(Addr vaddr, int64_t size)
{
// starting address must be page aligned
assert(pageOffset(vaddr) == 0);
diff --git a/src/mem/page_table.hh b/src/mem/page_table.hh
index 494c0ce9a..fce063280 100644
--- a/src/mem/page_table.hh
+++ b/src/mem/page_table.hh
@@ -38,6 +38,7 @@
#include <string>
+#include "sim/faults.hh"
#include "arch/isa_traits.hh"
#include "base/hashmap.hh"
#include "base/trace.hh"
@@ -48,7 +49,7 @@
class System;
/**
- * Page Table Decleration.
+ * Page Table Declaration.
*/
class PageTable
{
@@ -76,9 +77,9 @@ class PageTable
Addr pageAlign(Addr a) { return (a & ~offsetMask); }
Addr pageOffset(Addr a) { return (a & offsetMask); }
- Fault page_check(Addr addr, int size) const;
+ Fault page_check(Addr addr, int64_t size) const;
- void allocate(Addr vaddr, int size);
+ void allocate(Addr vaddr, int64_t size);
/**
* Translate function
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index 2d66602ab..291c70d8c 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ron Dreslinski
+ * Ali Saidi
*/
#include <sys/types.h>
@@ -52,24 +53,6 @@
using namespace std;
using namespace TheISA;
-PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet *pkt, MemoryPort* _m)
- : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m)
-{
-
- this->setFlags(AutoDelete);
-}
-
-void
-PhysicalMemory::MemResponseEvent::process()
-{
- memoryPort->sendTiming(pkt);
-}
-
-const char *
-PhysicalMemory::MemResponseEvent::description()
-{
- return "Physical Memory Timing Access respnse event";
-}
PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
: MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
@@ -124,27 +107,8 @@ PhysicalMemory::deviceBlockSize()
return 0;
}
-bool
-PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort)
-{
- doFunctionalAccess(pkt);
-
- // turn packet around to go back to requester
- pkt->makeTimingResponse();
- MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
- response->schedule(curTick + lat);
-
- return true;
-}
Tick
-PhysicalMemory::doAtomicAccess(Packet *pkt)
-{
- doFunctionalAccess(pkt);
- return lat;
-}
-
-void
PhysicalMemory::doFunctionalAccess(Packet *pkt)
{
assert(pkt->getAddr() + pkt->getSize() < pmem_size);
@@ -170,6 +134,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
}
pkt->result = Packet::Success;
+ return lat;
}
Port *
@@ -195,7 +160,7 @@ PhysicalMemory::recvStatusChange(Port::Status status)
PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
PhysicalMemory *_memory)
- : Port(_name), memory(_memory)
+ : SimpleTimingPort(_name), memory(_memory)
{ }
void
@@ -228,13 +193,20 @@ PhysicalMemory::MemoryPort::deviceBlockSize()
bool
PhysicalMemory::MemoryPort::recvTiming(Packet *pkt)
{
- return memory->doTimingAccess(pkt, this);
+ assert(pkt->result != Packet::Nacked);
+
+ Tick latency = memory->doFunctionalAccess(pkt);
+
+ pkt->makeTimingResponse();
+ sendTiming(pkt, latency);
+
+ return true;
}
Tick
PhysicalMemory::MemoryPort::recvAtomic(Packet *pkt)
{
- return memory->doAtomicAccess(pkt);
+ return memory->doFunctionalAccess(pkt);
}
void
@@ -243,7 +215,16 @@ PhysicalMemory::MemoryPort::recvFunctional(Packet *pkt)
memory->doFunctionalAccess(pkt);
}
-
+unsigned int
+PhysicalMemory::drain(Event *de)
+{
+ int count = port->drain(de);
+ if (count)
+ changeState(Draining);
+ else
+ changeState(Drained);
+ return count;
+}
void
PhysicalMemory::serialize(ostream &os)
diff --git a/src/mem/physical.hh b/src/mem/physical.hh
index 50fa75ed3..b549c1f8b 100644
--- a/src/mem/physical.hh
+++ b/src/mem/physical.hh
@@ -37,7 +37,7 @@
#include "base/range.hh"
#include "mem/mem_object.hh"
#include "mem/packet.hh"
-#include "mem/port.hh"
+#include "mem/tport.hh"
#include "sim/eventq.hh"
#include <map>
#include <string>
@@ -47,7 +47,7 @@
//
class PhysicalMemory : public MemObject
{
- class MemoryPort : public Port
+ class MemoryPort : public SimpleTimingPort
{
PhysicalMemory *memory;
@@ -74,16 +74,6 @@ class PhysicalMemory : public MemObject
int numPorts;
- struct MemResponseEvent : public Event
- {
- Packet *pkt;
- MemoryPort *memoryPort;
-
- MemResponseEvent(Packet *pkt, MemoryPort *memoryPort);
- void process();
- const char *description();
- };
-
private:
// prevent copying of a MainMemory object
PhysicalMemory(const PhysicalMemory &specmem);
@@ -110,13 +100,10 @@ class PhysicalMemory : public MemObject
void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
virtual Port *getPort(const std::string &if_name, int idx = -1);
void virtual init();
+ unsigned int drain(Event *de);
- // fast back-door memory access for vtophys(), remote gdb, etc.
- // uint64_t phys_read_qword(Addr addr) const;
private:
- bool doTimingAccess(Packet *pkt, MemoryPort *memoryPort);
- Tick doAtomicAccess(Packet *pkt);
- void doFunctionalAccess(Packet *pkt);
+ Tick doFunctionalAccess(Packet *pkt);
void recvStatusChange(Port::Status status);
diff --git a/src/mem/port.cc b/src/mem/port.cc
index bec9d2274..17924b759 100644
--- a/src/mem/port.cc
+++ b/src/mem/port.cc
@@ -29,7 +29,8 @@
*/
/**
- * @file Port object definitions.
+ * @file
+ * Port object definitions.
*/
#include "base/chunk_generator.hh"
diff --git a/src/mem/port.hh b/src/mem/port.hh
index 17b1f4a00..42e369205 100644
--- a/src/mem/port.hh
+++ b/src/mem/port.hh
@@ -30,7 +30,7 @@
/**
* @file
- * Port Object Decleration. Ports are used to interface memory objects to
+ * Port Object Declaration. Ports are used to interface memory objects to
* each other. They will always come in pairs, and we refer to the other
* port object as the peer. These are used to make the design more
* modular so that a specific interface between every type of objcet doesn't
diff --git a/src/mem/port_impl.hh b/src/mem/port_impl.hh
index e9a159293..b7980bdd2 100644
--- a/src/mem/port_impl.hh
+++ b/src/mem/port_impl.hh
@@ -28,8 +28,6 @@
* Authors: Ali Saidi
*/
-#include "arch/isa_specific.hh"
-#include "arch/isa_traits.hh"
#include "mem/port.hh"
#include "sim/byteswap.hh"
@@ -37,7 +35,7 @@ template <typename T>
void
FunctionalPort::writeHtoG(Addr addr, T d)
{
- d = TheISA::htog(d);
+ d = htog(d);
writeBlob(addr, (uint8_t*)&d, sizeof(T));
}
@@ -48,6 +46,6 @@ FunctionalPort::readGtoH(Addr addr)
{
T d;
readBlob(addr, (uint8_t*)&d, sizeof(T));
- return TheISA::gtoh(d);
+ return gtoh(d);
}
diff --git a/src/mem/request.hh b/src/mem/request.hh
index a1524f807..457310298 100644
--- a/src/mem/request.hh
+++ b/src/mem/request.hh
@@ -31,14 +31,16 @@
*/
/**
- * @file Decleration of a request, the overall memory request consisting of
+ * @file
+ * Declaration of a request, the overall memory request consisting of
the parts of the request that are persistent throughout the transaction.
*/
#ifndef __MEM_REQUEST_HH__
#define __MEM_REQUEST_HH__
-#include "arch/isa_traits.hh"
+#include "sim/host.hh"
+#include "sim/root.hh"
class Request;
diff --git a/src/mem/tport.cc b/src/mem/tport.cc
new file mode 100644
index 000000000..90cf68f02
--- /dev/null
+++ b/src/mem/tport.cc
@@ -0,0 +1,82 @@
+/*
+ * 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: Ali Saidi
+ */
+
+#include "mem/tport.hh"
+
+void
+SimpleTimingPort::recvRetry()
+{
+ bool result = true;
+ while (result && transmitList.size()) {
+ result = Port::sendTiming(transmitList.front());
+ if (result)
+ transmitList.pop_front();
+ }
+ if (transmitList.size() == 0 && drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
+ }
+}
+
+void
+SimpleTimingPort::SendEvent::process()
+{
+ port->outTiming--;
+ assert(port->outTiming >= 0);
+ if (port->Port::sendTiming(packet))
+ if (port->transmitList.size() == 0 && port->drainEvent) {
+ port->drainEvent->process();
+ port->drainEvent = NULL;
+ }
+ return;
+
+ port->transmitList.push_back(packet);
+}
+
+void
+SimpleTimingPort::resendNacked(Packet *pkt) {
+ pkt->reinitNacked();
+ if (transmitList.size()) {
+ transmitList.push_front(pkt);
+ } else {
+ if (!Port::sendTiming(pkt))
+ transmitList.push_front(pkt);
+ }
+};
+
+
+unsigned int
+SimpleTimingPort::drain(Event *de)
+{
+ if (outTiming == 0 && transmitList.size() == 0)
+ return 0;
+ drainEvent = de;
+ return 1;
+}
diff --git a/src/mem/tport.hh b/src/mem/tport.hh
new file mode 100644
index 000000000..5473e945e
--- /dev/null
+++ b/src/mem/tport.hh
@@ -0,0 +1,134 @@
+/*
+ * 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: Ali Saidi
+ */
+
+/**
+ * @file
+ * Implement a port which adds simple support of a sendTiming() function that
+ * takes a delay. In this way the * device can immediatly call
+ * sendTiming(pkt, time) after processing a request and the request will be
+ * handled by the port even if the port bus the device connects to is blocked.
+ */
+
+/** recvTiming and drain should be implemented something like this when this
+ * class is used.
+
+bool
+PioPort::recvTiming(Packet *pkt)
+{
+ if (pkt->result == Packet::Nacked) {
+ resendNacked(pkt);
+ } else {
+ Tick latency = device->recvAtomic(pkt);
+ // turn packet around to go back to requester
+ pkt->makeTimingResponse();
+ sendTiming(pkt, latency);
+ }
+ return true;
+}
+
+PioDevice::drain(Event *de)
+{
+ unsigned int count;
+ count = SimpleTimingPort->drain(de);
+ if (count)
+ changeState(Draining);
+ else
+ changeState(Drained);
+ return count;
+}
+*/
+
+#ifndef __MEM_TPORT_HH__
+#define __MEM_TPORT_HH__
+
+#include "mem/port.hh"
+#include "sim/eventq.hh"
+#include <list>
+#include <string>
+
+class SimpleTimingPort : public Port
+{
+ protected:
+ /** A list of outgoing timing response packets that haven't been serviced
+ * yet. */
+ std::list<Packet*> transmitList;
+ /**
+ * This class is used to implemented sendTiming() with a delay. When a delay
+ * is requested a new event is created. When the event time expires it
+ * attempts to send the packet. If it cannot, the packet is pushed onto the
+ * transmit list to be sent when recvRetry() is called. */
+ class SendEvent : public Event
+ {
+ SimpleTimingPort *port;
+ Packet *packet;
+
+ SendEvent(SimpleTimingPort *p, Packet *pkt, Tick t)
+ : Event(&mainEventQueue), port(p), packet(pkt)
+ { setFlags(AutoDelete); schedule(curTick + t); }
+
+ virtual void process();
+
+ virtual const char *description()
+ { return "Future scheduled sendTiming event"; }
+
+ friend class SimpleTimingPort;
+ };
+
+
+ /** Number of timing requests that are emulating the device timing before
+ * attempting to end up on the bus.
+ */
+ int outTiming;
+
+ /** If we need to drain, keep the drain event around until we're done
+ * here.*/
+ Event *drainEvent;
+
+ /** Schedule a sendTiming() event to be called in the future. */
+ void sendTiming(Packet *pkt, Tick time)
+ { outTiming++; new SimpleTimingPort::SendEvent(this, pkt, time); }
+
+ /** This function is notification that the device should attempt to send a
+ * packet again. */
+ virtual void recvRetry();
+
+ void resendNacked(Packet *pkt);
+ public:
+
+ SimpleTimingPort(std::string pname)
+ : Port(pname), outTiming(0), drainEvent(NULL)
+ {}
+
+ unsigned int drain(Event *de);
+
+ friend class SimpleTimingPort::SendEvent;
+};
+
+#endif // __MEM_TPORT_HH__
diff --git a/src/mem/vport.cc b/src/mem/vport.cc
index cd297bb8e..8030c5a15 100644
--- a/src/mem/vport.cc
+++ b/src/mem/vport.cc
@@ -29,7 +29,8 @@
*/
/**
- * @file Port object definitions.
+ * @file
+ * Port object definitions.
*/
#include "base/chunk_generator.hh"
diff --git a/src/mem/vport.hh b/src/mem/vport.hh
index 697c8e5f3..c83836258 100644
--- a/src/mem/vport.hh
+++ b/src/mem/vport.hh
@@ -30,7 +30,7 @@
/**
* @file
- * Virtual Port Object Decleration. These ports incorporate some translation
+ * Virtual Port Object Declaration. These ports incorporate some translation
* into their access methods. Thus you can use one to read and write data
* to/from virtual addresses.
*/
diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py
index 3d0e3defa..950d605df 100644
--- a/src/python/m5/__init__.py
+++ b/src/python/m5/__init__.py
@@ -44,6 +44,11 @@ def panic(string):
print >>sys.stderr, 'panic:', string
sys.exit(1)
+def makeList(objOrList):
+ if isinstance(objOrList, list):
+ return objOrList
+ return [objOrList]
+
# Prepend given directory to system module search path. We may not
# need this anymore if we can structure our config library more like a
# Python package.
diff --git a/src/python/m5/config.py b/src/python/m5/config.py
index 8291e1e1b..df4b74cbd 100644
--- a/src/python/m5/config.py
+++ b/src/python/m5/config.py
@@ -547,8 +547,7 @@ class SimObject(object):
count = 0
# ParamContexts don't serialize
if isinstance(self, SimObject) and not isinstance(self, ParamContext):
- if not self._ccObject.drain(drain_event):
- count = 1
+ count += self._ccObject.drain(drain_event)
if recursive:
for child in self._children.itervalues():
count += child.startDrain(drain_event, True)
@@ -561,7 +560,7 @@ class SimObject(object):
child.resume()
def changeTiming(self, mode):
- if isinstance(self, SimObject) and not isinstance(self, ParamContext):
+ if isinstance(self, System):
self._ccObject.setMemoryMode(mode)
for child in self._children.itervalues():
child.changeTiming(mode)
@@ -666,7 +665,8 @@ class BaseProxy(object):
result, done = self.find(obj)
if not done:
- raise AttributeError, "Can't resolve proxy '%s' from '%s'" % \
+ raise AttributeError, \
+ "Can't resolve proxy '%s' from '%s'" % \
(self.path(), base.path())
if isinstance(result, BaseProxy):
diff --git a/src/python/m5/main.py b/src/python/m5/main.py
index 904b241ca..e296453db 100644
--- a/src/python/m5/main.py
+++ b/src/python/m5/main.py
@@ -119,6 +119,8 @@ add_option('-d', "--outdir", metavar="DIR", default=".",
help="Set the output directory to DIR [Default: %default]")
add_option('-i', "--interactive", action="store_true", default=False,
help="Invoke the interactive interpreter after running the script")
+add_option("--pdb", action="store_true", default=False,
+ help="Invoke the python debugger before running the script")
add_option('-p', "--path", metavar="PATH[:PATH]", action='append', split=':',
help="Prepend PATH to the system path when invoking the script")
add_option('-q', "--quiet", action="count", default=0,
@@ -175,12 +177,14 @@ bool_option("print-fetch-seq", default=False,
help="Print fetch sequence numbers in trace output")
bool_option("print-cpseq", default=False,
help="Print correct path sequence numbers in trace output")
+#bool_option("print-reg-delta", default=False,
+# help="Print which registers changed to what in trace output")
options = attrdict()
arguments = []
def usage(exitcode=None):
- print parser.help
+ parser.print_help()
if exitcode is not None:
sys.exit(exitcode)
@@ -244,9 +248,15 @@ def main():
print "M5 compiled %s" % cc_main.cvar.compileDate;
print "M5 started %s" % datetime.now().ctime()
print "M5 executing on %s" % socket.gethostname()
+ print "command line:",
+ for argv in sys.argv:
+ print argv,
+ print
# check to make sure we can find the listed script
if not arguments or not os.path.isfile(arguments[0]):
+ if arguments and not os.path.isfile(arguments[0]):
+ print "Script %s not found" % arguments[0]
usage(2)
# tell C++ about output directory
@@ -282,12 +292,25 @@ def main():
objects.ExecutionTrace.print_iregs = options.print_iregs
objects.ExecutionTrace.print_fetchseq = options.print_fetch_seq
objects.ExecutionTrace.print_cpseq = options.print_cpseq
+ #objects.ExecutionTrace.print_reg_delta = options.print_reg_delta
- scope = { '__file__' : sys.argv[0] }
sys.argv = arguments
sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path
- exec("import readline", scope)
- execfile(sys.argv[0], scope)
+
+ scope = { '__file__' : sys.argv[0] }
+
+ # we want readline if we're doing anything interactive
+ if options.interactive or options.pdb:
+ exec("import readline", scope)
+
+ # if pdb was requested, execfile the thing under pdb, otherwise,
+ # just do the execfile normally
+ if options.pdb:
+ from pdb import Pdb
+ debugger = Pdb()
+ debugger.run('execfile("%s")' % sys.argv[0], scope)
+ else:
+ execfile(sys.argv[0], scope)
# once the script is done
if options.interactive:
diff --git a/src/python/m5/objects/BaseCPU.py b/src/python/m5/objects/BaseCPU.py
index 2e78578df..5bf98be9c 100644
--- a/src/python/m5/objects/BaseCPU.py
+++ b/src/python/m5/objects/BaseCPU.py
@@ -6,10 +6,10 @@ class BaseCPU(SimObject):
abstract = True
mem = Param.MemObject("memory")
+ system = Param.System(Parent.any, "system object")
if build_env['FULL_SYSTEM']:
dtb = Param.AlphaDTB("Data TLB")
itb = Param.AlphaITB("Instruction TLB")
- system = Param.System(Parent.any, "system object")
cpu_id = Param.Int(-1, "CPU identifier")
else:
workload = VectorParam.Process("processes to run")
diff --git a/src/python/m5/objects/Device.py b/src/python/m5/objects/Device.py
index 222f750da..f72c8e73f 100644
--- a/src/python/m5/objects/Device.py
+++ b/src/python/m5/objects/Device.py
@@ -12,7 +12,7 @@ class BasicPioDevice(PioDevice):
type = 'BasicPioDevice'
abstract = True
pio_addr = Param.Addr("Device Address")
- pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
+ pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
class DmaDevice(PioDevice):
type = 'DmaDevice'
diff --git a/src/python/m5/objects/DiskImage.py b/src/python/m5/objects/DiskImage.py
index 70d8b2e45..a98b35a4f 100644
--- a/src/python/m5/objects/DiskImage.py
+++ b/src/python/m5/objects/DiskImage.py
@@ -10,6 +10,6 @@ class RawDiskImage(DiskImage):
class CowDiskImage(DiskImage):
type = 'CowDiskImage'
- child = Param.DiskImage("child image")
+ child = Param.DiskImage(RawDiskImage(read_only=True),
+ "child image")
table_size = Param.Int(65536, "initial table size")
- image_file = ''
diff --git a/src/python/m5/objects/Ethernet.py b/src/python/m5/objects/Ethernet.py
index 418670592..fb641bf80 100644
--- a/src/python/m5/objects/Ethernet.py
+++ b/src/python/m5/objects/Ethernet.py
@@ -1,7 +1,7 @@
from m5 import build_env
from m5.config import *
from Device import DmaDevice
-from Pci import PciDevice
+from Pci import PciDevice, PciConfigData
class EtherInt(SimObject):
type = 'EtherInt'
@@ -68,6 +68,8 @@ class EtherDevBase(PciDevice):
clock = Param.Clock('0ns', "State machine processor frequency")
+ config_latency = Param.Latency('20ns', "Config read or write latency")
+
dma_read_delay = Param.Latency('0us', "fixed delay for dma reads")
dma_read_factor = Param.Latency('0us', "multiplier for dma reads")
dma_write_delay = Param.Latency('0us', "fixed delay for dma writes")
@@ -84,6 +86,26 @@ class EtherDevBase(PciDevice):
tx_thread = Param.Bool(False, "dedicated kernel threads for receive")
rss = Param.Bool(False, "Receive Side Scaling")
+class NSGigEPciData(PciConfigData):
+ VendorID = 0x100B
+ DeviceID = 0x0022
+ Status = 0x0290
+ SubClassCode = 0x00
+ ClassCode = 0x02
+ ProgIF = 0x00
+ BAR0 = 0x00000001
+ BAR1 = 0x00000000
+ BAR2 = 0x00000000
+ BAR3 = 0x00000000
+ BAR4 = 0x00000000
+ BAR5 = 0x00000000
+ MaximumLatency = 0x34
+ MinimumGrant = 0xb0
+ InterruptLine = 0x1e
+ InterruptPin = 0x01
+ BAR0Size = '256B'
+ BAR1Size = '4kB'
+
class NSGigE(EtherDevBase):
type = 'NSGigE'
@@ -91,11 +113,32 @@ class NSGigE(EtherDevBase):
dma_desc_free = Param.Bool(False, "DMA of Descriptors is free")
dma_no_allocate = Param.Bool(True, "Should we allocate cache on read")
+ configdata = NSGigEPciData()
+
class NSGigEInt(EtherInt):
type = 'NSGigEInt'
device = Param.NSGigE("Ethernet device of this interface")
+class SinicPciData(PciConfigData):
+ VendorID = 0x1291
+ DeviceID = 0x1293
+ Status = 0x0290
+ SubClassCode = 0x00
+ ClassCode = 0x02
+ ProgIF = 0x00
+ BAR0 = 0x00000000
+ BAR1 = 0x00000000
+ BAR2 = 0x00000000
+ BAR3 = 0x00000000
+ BAR4 = 0x00000000
+ BAR5 = 0x00000000
+ MaximumLatency = 0x34
+ MinimumGrant = 0xb0
+ InterruptLine = 0x1e
+ InterruptPin = 0x01
+ BAR0Size = '64kB'
+
class Sinic(EtherDevBase):
type = 'Sinic'
@@ -111,6 +154,8 @@ class Sinic(EtherDevBase):
delay_copy = Param.Bool(False, "Delayed copy transmit")
virtual_addr = Param.Bool(False, "Virtual addressing")
+ configdata = SinicPciData()
+
class SinicInt(EtherInt):
type = 'SinicInt'
device = Param.Sinic("Ethernet device of this interface")
diff --git a/src/python/m5/objects/Ide.py b/src/python/m5/objects/Ide.py
index 9ee578177..a8bd4ac5a 100644
--- a/src/python/m5/objects/Ide.py
+++ b/src/python/m5/objects/Ide.py
@@ -1,8 +1,31 @@
from m5.config import *
-from Pci import PciDevice
+from Pci import PciDevice, PciConfigData
class IdeID(Enum): vals = ['master', 'slave']
+class IdeControllerPciData(PciConfigData):
+ VendorID = 0x8086
+ DeviceID = 0x7111
+ Command = 0x0
+ Status = 0x280
+ Revision = 0x0
+ ClassCode = 0x01
+ SubClassCode = 0x01
+ ProgIF = 0x85
+ BAR0 = 0x00000001
+ BAR1 = 0x00000001
+ BAR2 = 0x00000001
+ BAR3 = 0x00000001
+ BAR4 = 0x00000001
+ BAR5 = 0x00000001
+ InterruptLine = 0x1f
+ InterruptPin = 0x01
+ BAR0Size = '8B'
+ BAR1Size = '4B'
+ BAR2Size = '8B'
+ BAR3Size = '4B'
+ BAR4Size = '16B'
+
class IdeDisk(SimObject):
type = 'IdeDisk'
delay = Param.Latency('1us', "Fixed disk delay in microseconds")
@@ -12,3 +35,7 @@ class IdeDisk(SimObject):
class IdeController(PciDevice):
type = 'IdeController'
disks = VectorParam.IdeDisk("IDE disks attached to this controller")
+
+ config_latency = Param.Latency('20ns', "Config read or write latency")
+
+ configdata =IdeControllerPciData()
diff --git a/src/python/m5/objects/O3CPU.py b/src/python/m5/objects/O3CPU.py
index d6bc454ad..41208929a 100644
--- a/src/python/m5/objects/O3CPU.py
+++ b/src/python/m5/objects/O3CPU.py
@@ -1,91 +1,101 @@
from m5 import build_env
from m5.config import *
from BaseCPU import BaseCPU
+from Checker import O3Checker
class DerivO3CPU(BaseCPU):
type = 'DerivO3CPU'
- activity = Param.Unsigned("Initial count")
- numThreads = Param.Unsigned("number of HW thread contexts")
-
- checker = Param.BaseCPU(NULL, "checker")
+ activity = Param.Unsigned(0, "Initial count")
+ numThreads = Param.Unsigned(1, "number of HW thread contexts")
+
+ if build_env['USE_CHECKER']:
+ if not build_env['FULL_SYSTEM']:
+ checker = Param.BaseCPU(O3Checker(workload=Parent.workload,
+ exitOnError=True,
+ warnOnlyOnLoadError=False),
+ "checker")
+ else:
+ checker = Param.BaseCPU(O3Checker(exitOnError=True, warnOnlyOnLoadError=False), "checker")
+ checker.itb = Parent.itb
+ checker.dtb = Parent.dtb
cachePorts = Param.Unsigned("Cache Ports")
icache_port = Port("Instruction Port")
dcache_port = Port("Data Port")
- decodeToFetchDelay = Param.Unsigned("Decode to fetch delay")
- renameToFetchDelay = Param.Unsigned("Rename to fetch delay")
- iewToFetchDelay = Param.Unsigned("Issue/Execute/Writeback to fetch "
- "delay")
- commitToFetchDelay = Param.Unsigned("Commit to fetch delay")
- fetchWidth = Param.Unsigned("Fetch width")
+ decodeToFetchDelay = Param.Unsigned(1, "Decode to fetch delay")
+ renameToFetchDelay = Param.Unsigned(1 ,"Rename to fetch delay")
+ iewToFetchDelay = Param.Unsigned(1, "Issue/Execute/Writeback to fetch "
+ "delay")
+ commitToFetchDelay = Param.Unsigned(1, "Commit to fetch delay")
+ fetchWidth = Param.Unsigned(8, "Fetch width")
- renameToDecodeDelay = Param.Unsigned("Rename to decode delay")
- iewToDecodeDelay = Param.Unsigned("Issue/Execute/Writeback to decode "
+ renameToDecodeDelay = Param.Unsigned(1, "Rename to decode delay")
+ iewToDecodeDelay = Param.Unsigned(1, "Issue/Execute/Writeback to decode "
"delay")
- commitToDecodeDelay = Param.Unsigned("Commit to decode delay")
- fetchToDecodeDelay = Param.Unsigned("Fetch to decode delay")
- decodeWidth = Param.Unsigned("Decode width")
+ commitToDecodeDelay = Param.Unsigned(1, "Commit to decode delay")
+ fetchToDecodeDelay = Param.Unsigned(1, "Fetch to decode delay")
+ decodeWidth = Param.Unsigned(8, "Decode width")
- iewToRenameDelay = Param.Unsigned("Issue/Execute/Writeback to rename "
+ iewToRenameDelay = Param.Unsigned(1, "Issue/Execute/Writeback to rename "
"delay")
- commitToRenameDelay = Param.Unsigned("Commit to rename delay")
- decodeToRenameDelay = Param.Unsigned("Decode to rename delay")
- renameWidth = Param.Unsigned("Rename width")
+ commitToRenameDelay = Param.Unsigned(1, "Commit to rename delay")
+ decodeToRenameDelay = Param.Unsigned(1, "Decode to rename delay")
+ renameWidth = Param.Unsigned(8, "Rename width")
- commitToIEWDelay = Param.Unsigned("Commit to "
+ commitToIEWDelay = Param.Unsigned(1, "Commit to "
"Issue/Execute/Writeback delay")
- renameToIEWDelay = Param.Unsigned("Rename to "
+ renameToIEWDelay = Param.Unsigned(2, "Rename to "
"Issue/Execute/Writeback delay")
- issueToExecuteDelay = Param.Unsigned("Issue to execute delay (internal "
+ issueToExecuteDelay = Param.Unsigned(1, "Issue to execute delay (internal "
"to the IEW stage)")
- dispatchWidth = Param.Unsigned("Dispatch width")
- issueWidth = Param.Unsigned("Issue width")
- wbWidth = Param.Unsigned("Writeback width")
- wbDepth = Param.Unsigned("Writeback depth")
- fuPool = Param.FUPool(NULL, "Functional Unit pool")
+ dispatchWidth = Param.Unsigned(8, "Dispatch width")
+ issueWidth = Param.Unsigned(8, "Issue width")
+ wbWidth = Param.Unsigned(8, "Writeback width")
+ wbDepth = Param.Unsigned(1, "Writeback depth")
+ fuPool = Param.FUPool("Functional Unit pool")
- iewToCommitDelay = Param.Unsigned("Issue/Execute/Writeback to commit "
+ iewToCommitDelay = Param.Unsigned(1, "Issue/Execute/Writeback to commit "
"delay")
- renameToROBDelay = Param.Unsigned("Rename to reorder buffer delay")
- commitWidth = Param.Unsigned("Commit width")
- squashWidth = Param.Unsigned("Squash width")
- trapLatency = Param.Tick("Trap latency")
- fetchTrapLatency = Param.Tick("Fetch trap latency")
-
- backComSize = Param.Unsigned("Time buffer size for backwards communication")
- forwardComSize = Param.Unsigned("Time buffer size for forward communication")
-
- predType = Param.String("Branch predictor type ('local', 'tournament')")
- localPredictorSize = Param.Unsigned("Size of local predictor")
- localCtrBits = Param.Unsigned("Bits per counter")
- localHistoryTableSize = Param.Unsigned("Size of local history table")
- localHistoryBits = Param.Unsigned("Bits for the local history")
- globalPredictorSize = Param.Unsigned("Size of global predictor")
- globalCtrBits = Param.Unsigned("Bits per counter")
- globalHistoryBits = Param.Unsigned("Bits of history")
- choicePredictorSize = Param.Unsigned("Size of choice predictor")
- choiceCtrBits = Param.Unsigned("Bits of choice counters")
-
- BTBEntries = Param.Unsigned("Number of BTB entries")
- BTBTagSize = Param.Unsigned("Size of the BTB tags, in bits")
-
- RASSize = Param.Unsigned("RAS size")
-
- LQEntries = Param.Unsigned("Number of load queue entries")
- SQEntries = Param.Unsigned("Number of store queue entries")
- LFSTSize = Param.Unsigned("Last fetched store table size")
- SSITSize = Param.Unsigned("Store set ID table size")
-
- numRobs = Param.Unsigned("Number of Reorder Buffers");
-
- numPhysIntRegs = Param.Unsigned("Number of physical integer registers")
- numPhysFloatRegs = Param.Unsigned("Number of physical floating point "
- "registers")
- numIQEntries = Param.Unsigned("Number of instruction queue entries")
- numROBEntries = Param.Unsigned("Number of reorder buffer entries")
-
- instShiftAmt = Param.Unsigned("Number of bits to shift instructions by")
+ renameToROBDelay = Param.Unsigned(1, "Rename to reorder buffer delay")
+ commitWidth = Param.Unsigned(8, "Commit width")
+ squashWidth = Param.Unsigned(8, "Squash width")
+ trapLatency = Param.Tick(13, "Trap latency")
+ fetchTrapLatency = Param.Tick(1, "Fetch trap latency")
+
+ backComSize = Param.Unsigned(5, "Time buffer size for backwards communication")
+ forwardComSize = Param.Unsigned(5, "Time buffer size for forward communication")
+
+ predType = Param.String("tournament", "Branch predictor type ('local', 'tournament')")
+ localPredictorSize = Param.Unsigned(2048, "Size of local predictor")
+ localCtrBits = Param.Unsigned(2, "Bits per counter")
+ localHistoryTableSize = Param.Unsigned(2048, "Size of local history table")
+ localHistoryBits = Param.Unsigned(11, "Bits for the local history")
+ globalPredictorSize = Param.Unsigned(8192, "Size of global predictor")
+ globalCtrBits = Param.Unsigned(2, "Bits per counter")
+ globalHistoryBits = Param.Unsigned(4096, "Bits of history")
+ choicePredictorSize = Param.Unsigned(8192, "Size of choice predictor")
+ choiceCtrBits = Param.Unsigned(2, "Bits of choice counters")
+
+ BTBEntries = Param.Unsigned(4096, "Number of BTB entries")
+ BTBTagSize = Param.Unsigned(16, "Size of the BTB tags, in bits")
+
+ RASSize = Param.Unsigned(16, "RAS size")
+
+ LQEntries = Param.Unsigned(32, "Number of load queue entries")
+ SQEntries = Param.Unsigned(32, "Number of store queue entries")
+ LFSTSize = Param.Unsigned(1024, "Last fetched store table size")
+ SSITSize = Param.Unsigned(1024, "Store set ID table size")
+
+ numRobs = Param.Unsigned(1, "Number of Reorder Buffers");
+
+ numPhysIntRegs = Param.Unsigned(256, "Number of physical integer registers")
+ numPhysFloatRegs = Param.Unsigned(256, "Number of physical floating point "
+ "registers")
+ numIQEntries = Param.Unsigned(64, "Number of instruction queue entries")
+ numROBEntries = Param.Unsigned(192, "Number of reorder buffer entries")
+
+ instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by")
function_trace = Param.Bool(False, "Enable function trace")
function_trace_start = Param.Tick(0, "Cycle to start function trace")
diff --git a/src/python/m5/objects/Pci.py b/src/python/m5/objects/Pci.py
index 29014bb37..cc0d1cf4a 100644
--- a/src/python/m5/objects/Pci.py
+++ b/src/python/m5/objects/Pci.py
@@ -52,7 +52,7 @@ class PciDevice(DmaDevice):
pci_bus = Param.Int("PCI bus")
pci_dev = Param.Int("PCI device number")
pci_func = Param.Int("PCI function code")
- pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
+ pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
configdata = Param.PciConfigData(Parent.any, "PCI Config data")
class PciFake(PciDevice):
diff --git a/src/python/m5/objects/Root.py b/src/python/m5/objects/Root.py
index 373475a7a..33dd22620 100644
--- a/src/python/m5/objects/Root.py
+++ b/src/python/m5/objects/Root.py
@@ -7,7 +7,7 @@ from Debug import Debug
class Root(SimObject):
type = 'Root'
- clock = Param.RootClock('200MHz', "tick frequency")
+ clock = Param.RootClock('1THz', "tick frequency")
max_tick = Param.Tick('0', "maximum simulation ticks (0 = infinite)")
progress_interval = Param.Tick('0',
"print a progress message every n ticks (0 = never)")
diff --git a/src/python/m5/objects/System.py b/src/python/m5/objects/System.py
index 9a1e1d690..386f39277 100644
--- a/src/python/m5/objects/System.py
+++ b/src/python/m5/objects/System.py
@@ -1,9 +1,12 @@
from m5 import build_env
from m5.config import *
+class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing']
+
class System(SimObject):
type = 'System'
physmem = Param.PhysicalMemory(Parent.any, "phsyical memory")
+ mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
if build_env['FULL_SYSTEM']:
boot_cpu_frequency = Param.Frequency(Self.cpu[0].clock.frequency,
"boot processor frequency")
diff --git a/src/python/m5/objects/Tsunami.py b/src/python/m5/objects/Tsunami.py
index 4613571d8..0b5ff9e7d 100644
--- a/src/python/m5/objects/Tsunami.py
+++ b/src/python/m5/objects/Tsunami.py
@@ -1,11 +1,10 @@
from m5.config import *
from Device import BasicPioDevice
from Platform import Platform
-
-class Tsunami(Platform):
- type = 'Tsunami'
-# pciconfig = Param.PciConfigAll("PCI configuration")
- system = Param.System(Parent.any, "system")
+from AlphaConsole import AlphaConsole
+from Uart import Uart8250
+from Pci import PciConfigAll
+from BadDevice import BadDevice
class TsunamiCChip(BasicPioDevice):
type = 'TsunamiCChip'
@@ -25,3 +24,71 @@ class TsunamiIO(BasicPioDevice):
class TsunamiPChip(BasicPioDevice):
type = 'TsunamiPChip'
tsunami = Param.Tsunami(Parent.any, "Tsunami")
+
+class Tsunami(Platform):
+ type = 'Tsunami'
+ system = Param.System(Parent.any, "system")
+
+ cchip = TsunamiCChip(pio_addr=0x801a0000000)
+ pchip = TsunamiPChip(pio_addr=0x80180000000)
+ pciconfig = PciConfigAll()
+ fake_sm_chip = IsaFake(pio_addr=0x801fc000370)
+
+ fake_uart1 = IsaFake(pio_addr=0x801fc0002f8)
+ fake_uart2 = IsaFake(pio_addr=0x801fc0003e8)
+ fake_uart3 = IsaFake(pio_addr=0x801fc0002e8)
+ fake_uart4 = IsaFake(pio_addr=0x801fc0003f0)
+
+ fake_ppc = IsaFake(pio_addr=0x801fc0003bc)
+
+ fake_OROM = IsaFake(pio_addr=0x800000a0000, pio_size=0x60000)
+
+ fake_pnp_addr = IsaFake(pio_addr=0x801fc000279)
+ fake_pnp_write = IsaFake(pio_addr=0x801fc000a79)
+ fake_pnp_read0 = IsaFake(pio_addr=0x801fc000203)
+ fake_pnp_read1 = IsaFake(pio_addr=0x801fc000243)
+ fake_pnp_read2 = IsaFake(pio_addr=0x801fc000283)
+ fake_pnp_read3 = IsaFake(pio_addr=0x801fc0002c3)
+ fake_pnp_read4 = IsaFake(pio_addr=0x801fc000303)
+ fake_pnp_read5 = IsaFake(pio_addr=0x801fc000343)
+ fake_pnp_read6 = IsaFake(pio_addr=0x801fc000383)
+ fake_pnp_read7 = IsaFake(pio_addr=0x801fc0003c3)
+
+ fake_ata0 = IsaFake(pio_addr=0x801fc0001f0)
+ fake_ata1 = IsaFake(pio_addr=0x801fc000170)
+
+ fb = BadDevice(pio_addr=0x801fc0003d0, devicename='FrameBuffer')
+ io = TsunamiIO(pio_addr=0x801fc000000)
+ uart = Uart8250(pio_addr=0x801fc0003f8)
+ console = AlphaConsole(pio_addr=0x80200000000, disk=Parent.simple_disk)
+
+ # Attach I/O devices to specified bus object. Can't do this
+ # earlier, since the bus object itself is typically defined at the
+ # System level.
+ def attachIO(self, bus):
+ self.cchip.pio = bus.port
+ self.pchip.pio = bus.port
+ self.pciconfig.pio = bus.default
+ self.fake_sm_chip.pio = bus.port
+ self.fake_uart1.pio = bus.port
+ self.fake_uart2.pio = bus.port
+ self.fake_uart3.pio = bus.port
+ self.fake_uart4.pio = bus.port
+ self.fake_ppc.pio = bus.port
+ self.fake_OROM.pio = bus.port
+ self.fake_pnp_addr.pio = bus.port
+ self.fake_pnp_write.pio = bus.port
+ self.fake_pnp_read0.pio = bus.port
+ self.fake_pnp_read1.pio = bus.port
+ self.fake_pnp_read2.pio = bus.port
+ self.fake_pnp_read3.pio = bus.port
+ self.fake_pnp_read4.pio = bus.port
+ self.fake_pnp_read5.pio = bus.port
+ self.fake_pnp_read6.pio = bus.port
+ self.fake_pnp_read7.pio = bus.port
+ self.fake_ata0.pio = bus.port
+ self.fake_ata1.pio = bus.port
+ self.fb.pio = bus.port
+ self.io.pio = bus.port
+ self.uart.pio = bus.port
+ self.console.pio = bus.port
diff --git a/src/sim/byteswap.hh b/src/sim/byteswap.hh
index f1f244150..7648b8fcd 100644
--- a/src/sim/byteswap.hh
+++ b/src/sim/byteswap.hh
@@ -25,7 +25,8 @@
* (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: Ali Saidi
+ * Authors: Gabe Black
+ * Ali Saidi
* Nathan Binkert
*/
diff --git a/src/sim/main.cc b/src/sim/main.cc
index d0725ab37..4ea8c4138 100644
--- a/src/sim/main.cc
+++ b/src/sim/main.cc
@@ -215,7 +215,7 @@ loadIniFile(PyObject *_resolveFunc)
configStream = simout.find("config.out");
// The configuration database is now complete; start processing it.
- inifile.load("config.ini");
+ inifile.load(simout.resolve("config.ini"));
// Initialize statistics database
Stats::InitSimStats();
diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh
index 5e5b7d95f..4a83b93e0 100644
--- a/src/sim/pseudo_inst.hh
+++ b/src/sim/pseudo_inst.hh
@@ -30,10 +30,8 @@
class ThreadContext;
-//We need the "Tick" data type from here
+//We need the "Tick" and "Addr" data types from here
#include "sim/host.hh"
-//We need the "Addr" data type from here
-#include "arch/isa_traits.hh"
namespace AlphaPseudo
{
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
index a0278dba0..d12b06b7a 100644
--- a/src/sim/sim_object.cc
+++ b/src/sim/sim_object.cc
@@ -72,7 +72,7 @@ SimObject::SimObject(Params *p)
doRecordEvent = !Stats::event_ignore.match(name());
simObjectList.push_back(this);
- state = Atomic;
+ state = Running;
}
//
@@ -88,7 +88,7 @@ SimObject::SimObject(const string &_name)
doRecordEvent = !Stats::event_ignore.match(name());
simObjectList.push_back(this);
- state = Atomic;
+ state = Running;
}
void
@@ -269,38 +269,23 @@ SimObject::recordEvent(const std::string &stat)
Stats::recordEvent(stat);
}
-bool
+unsigned int
SimObject::drain(Event *drain_event)
{
- if (state != DrainedAtomic && state != Atomic) {
- panic("Must implement your own drain function if it is to be used "
- "in timing mode!");
- }
- state = DrainedAtomic;
- return true;
+ state = Drained;
+ return 0;
}
void
SimObject::resume()
{
- if (state == DrainedAtomic) {
- state = Atomic;
- } else if (state == DrainedTiming) {
- state = Timing;
- }
+ state = Running;
}
void
SimObject::setMemoryMode(State new_mode)
{
- assert(new_mode == Timing || new_mode == Atomic);
- if (state == DrainedAtomic && new_mode == Timing) {
- state = DrainedTiming;
- } else if (state == DrainedTiming && new_mode == Atomic) {
- state = DrainedAtomic;
- } else {
- state = new_mode;
- }
+ panic("setMemoryMode() should only be called on systems");
}
void
diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh
index 7ecc00958..38f2bdd23 100644
--- a/src/sim/sim_object.hh
+++ b/src/sim/sim_object.hh
@@ -60,16 +60,15 @@ class SimObject : public Serializable, protected StartupCallback
};
enum State {
- Atomic,
- Timing,
+ Running,
Draining,
- DrainedAtomic,
- DrainedTiming
+ Drained
};
+ private:
+ State state;
protected:
Params *_params;
- State state;
void changeState(State new_state) { state = new_state; }
@@ -116,8 +115,10 @@ class SimObject : public Serializable, protected StartupCallback
// Methods to drain objects in order to take checkpoints
// Or switch from timing -> atomic memory model
- // Drain returns false if the SimObject cannot drain immediately.
- virtual bool drain(Event *drain_event);
+ // Drain returns 0 if the simobject can drain immediately or
+ // the number of times the drain_event's process function will be called
+ // before the object will be done draining. Normally this should be 1
+ virtual unsigned int drain(Event *drain_event);
virtual void resume();
virtual void setMemoryMode(State new_mode);
virtual void switchOut();
diff --git a/src/sim/system.cc b/src/sim/system.cc
index 89e7b8542..ad70b9b03 100644
--- a/src/sim/system.cc
+++ b/src/sim/system.cc
@@ -63,7 +63,7 @@ System::System(Params *p)
#else
page_ptr(0),
#endif
- _params(p)
+ memoryMode(p->mem_mode), _params(p)
{
// add self to global system list
systemList.push_back(this);
@@ -143,6 +143,14 @@ int rgdb_wait = -1;
#endif // FULL_SYSTEM
+
+void
+System::setMemoryMode(MemoryMode mode)
+{
+ assert(getState() == Drained);
+ memoryMode = mode;
+}
+
int
System::registerThreadContext(ThreadContext *tc, int id)
{
@@ -249,6 +257,9 @@ printSystems()
System::printSystems();
}
+const char *System::MemoryModeStrings[3] = {"invalid", "atomic",
+ "timing"};
+
#if FULL_SYSTEM
// In full system mode, only derived classes (e.g. AlphaLinuxSystem)
@@ -261,12 +272,15 @@ DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(System)
SimObjectParam<PhysicalMemory *> physmem;
+ SimpleEnumParam<System::MemoryMode> mem_mode;
END_DECLARE_SIM_OBJECT_PARAMS(System)
BEGIN_INIT_SIM_OBJECT_PARAMS(System)
- INIT_PARAM(physmem, "physical memory")
+ INIT_PARAM(physmem, "physical memory"),
+ INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)",
+ System::MemoryModeStrings)
END_INIT_SIM_OBJECT_PARAMS(System)
@@ -275,6 +289,7 @@ CREATE_SIM_OBJECT(System)
System::Params *p = new System::Params;
p->name = getInstanceName();
p->physmem = physmem;
+ p->mem_mode = mem_mode;
return new System(p);
}
diff --git a/src/sim/system.hh b/src/sim/system.hh
index 059dc92dc..c138d2ee4 100644
--- a/src/sim/system.hh
+++ b/src/sim/system.hh
@@ -39,6 +39,7 @@
#include "base/loader/symtab.hh"
#include "base/misc.hh"
#include "base/statistics.hh"
+#include "config/full_system.hh"
#include "cpu/pc_event.hh"
#include "mem/port.hh"
#include "sim/sim_object.hh"
@@ -61,6 +62,23 @@ class RemoteGDB;
class System : public SimObject
{
public:
+ enum MemoryMode {
+ Invalid=0,
+ Atomic,
+ Timing
+ };
+
+ static const char *MemoryModeStrings[3];
+
+
+ MemoryMode getMemoryMode() { assert(memoryMode); return memoryMode; }
+
+ /** Change the memory mode of the system. This should only be called by the
+ * python!!
+ * @param mode Mode to change to (atomic/timing)
+ */
+ void setMemoryMode(MemoryMode mode);
+
PhysicalMemory *physmem;
PCEventQueue pcEventQueue;
@@ -108,6 +126,8 @@ class System : public SimObject
protected:
+ MemoryMode memoryMode;
+
#if FULL_SYSTEM
/**
* Fix up an address used to match PCs for hooking simulator
@@ -153,6 +173,7 @@ class System : public SimObject
{
std::string name;
PhysicalMemory *physmem;
+ MemoryMode mem_mode;
#if FULL_SYSTEM
Tick boot_cpu_frequency;