diff options
Diffstat (limited to 'src')
371 files changed, 19916 insertions, 6642 deletions
diff --git a/src/SConscript b/src/SConscript index 74bed9a7e..5efd2f794 100644 --- a/src/SConscript +++ b/src/SConscript @@ -30,187 +30,27 @@ import os import sys -from os.path import isfile, join as joinpath + +from os.path import join as joinpath # This file defines how to build a particular configuration of M5 # based on variable settings in the 'env' build environment. -# Import build environment variable from SConstruct. -Import('env') - -################################################### -# -# Define needed sources. -# -################################################### - -# Base sources used by all configurations. - -base_sources = Split(''' - base/annotate.cc - base/circlebuf.cc - base/cprintf.cc - base/fast_alloc.cc - base/fifo_buffer.cc - base/hostinfo.cc - base/hybrid_pred.cc - base/inifile.cc - base/intmath.cc - base/match.cc - base/misc.cc - base/output.cc - base/pollevent.cc - base/range.cc - base/random.cc - base/remote_gdb.cc - base/sat_counter.cc - base/socket.cc - base/statistics.cc - base/str.cc - base/time.cc - base/trace.cc - base/traceflags.cc - base/userinfo.cc - base/compression/lzss_compression.cc - base/loader/aout_object.cc - base/loader/ecoff_object.cc - base/loader/elf_object.cc - base/loader/raw_object.cc - base/loader/object_file.cc - base/loader/symtab.cc - base/stats/events.cc - base/stats/statdb.cc - base/stats/visit.cc - base/stats/text.cc - - cpu/activity.cc - cpu/base.cc - cpu/cpuevent.cc - cpu/exetrace.cc - cpu/func_unit.cc - cpu/op_class.cc - cpu/pc_event.cc - cpu/quiesce_event.cc - cpu/static_inst.cc - cpu/simple_thread.cc - cpu/thread_state.cc - - mem/bridge.cc - mem/bus.cc - mem/dram.cc - mem/mem_object.cc - mem/packet.cc - mem/physical.cc - mem/port.cc - mem/tport.cc - - mem/cache/base_cache.cc - mem/cache/cache.cc - mem/cache/coherence/coherence_protocol.cc - mem/cache/coherence/uni_coherence.cc - mem/cache/miss/blocking_buffer.cc - mem/cache/miss/miss_buffer.cc - mem/cache/miss/miss_queue.cc - mem/cache/miss/mshr.cc - mem/cache/miss/mshr_queue.cc - mem/cache/prefetch/base_prefetcher.cc - mem/cache/prefetch/ghb_prefetcher.cc - mem/cache/prefetch/stride_prefetcher.cc - mem/cache/prefetch/tagged_prefetcher.cc - mem/cache/tags/base_tags.cc - mem/cache/tags/fa_lru.cc - mem/cache/tags/iic.cc - mem/cache/tags/lru.cc - mem/cache/tags/repl/gen.cc - mem/cache/tags/repl/repl.cc - mem/cache/tags/split.cc - mem/cache/tags/split_lifo.cc - mem/cache/tags/split_lru.cc - - mem/cache/cache_builder.cc - - python/swig/init.cc - python/swig/debug_wrap.cc - python/swig/main_wrap.cc - python/swig/event_wrap.cc - python/swig/pyevent.cc - - sim/builder.cc - sim/debug.cc - sim/eventq.cc - sim/faults.cc - sim/main.cc - sim/param.cc - sim/root.cc - sim/serialize.cc - sim/sim_events.cc - sim/sim_object.cc - sim/startup.cc - sim/stat_context.cc - sim/stat_control.cc - sim/system.cc - sim/trace_context.cc - ''') - -trace_reader_sources = Split(''' - cpu/trace/reader/mem_trace_reader.cc - cpu/trace/reader/ibm_reader.cc - cpu/trace/reader/itx_reader.cc - cpu/trace/reader/m5_reader.cc - cpu/trace/opt_cpu.cc - cpu/trace/trace_cpu.cc - ''') - - - -# MySql sources -mysql_sources = Split(''' - base/mysql.cc - base/stats/mysql.cc - ''') - -# Full-system sources -full_system_sources = Split(''' - base/crc.cc - base/inet.cc - - cpu/intr_control.cc - cpu/profile.cc - - dev/uart.cc - dev/uart8250.cc +Import('*') - mem/vport.cc - - sim/pseudo_inst.cc - ''') - #dev/sinic.cc - #dev/i8254xGBe.cc - -if env['TARGET_ISA'] == 'alpha': - full_system_sources += Split(''' - kern/tru64/dump_mbuf.cc - kern/tru64/printf.cc - kern/tru64/tru64_events.cc - kern/tru64/tru64_syscalls.cc - ''') - -# Syscall emulation (non-full-system) sources -syscall_emulation_sources = Split(''' - mem/translating_port.cc - mem/page_table.cc - sim/process.cc - sim/syscall_emul.cc - ''') - -#if env['TARGET_ISA'] == 'alpha': -# syscall_emulation_sources += Split(''' -# kern/tru64/tru64.cc -# ''') +sources = [] +def Source(*args): + for arg in args: + if isinstance(arg, (list, tuple)): + # Recurse to load a list + Source(*arg) + elif isinstance(arg, str): + sources.extend([ File(f) for f in Split(arg) ]) + else: + sources.append(File(arg)) -memtest_sources = Split(''' - cpu/memtest/memtest.cc - ''') +Export('env') +Export('Source') # Include file paths are rooted in this directory. SCons will # automatically expand '.' to refer to both the source directory and @@ -221,52 +61,23 @@ env.Append(CPPPATH=Dir('.')) # Add a flag defining what THE_ISA should be for all compilation env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) -arch_sources = SConscript(os.path.join('arch', 'SConscript'), exports = 'env') - -cpu_sources = SConscript(os.path.join('cpu', 'SConscript'), exports = 'env') - -if env['FULL_SYSTEM']: - dev_sources = SConscript(os.path.join('dev', 'SConscript'), - exports = 'env') - full_system_sources += dev_sources - - kern_sources = SConscript(os.path.join('kern', 'SConscript'), - exports = 'env') - full_system_sources += kern_sources - -# Set up complete list of sources based on configuration. -sources = base_sources + arch_sources + cpu_sources - -# encumbered should be last because we're adding to some of the other groups -if isfile(joinpath(env['SRCDIR'], 'encumbered/SConscript')): - sources += SConscript('encumbered/SConscript', exports = 'env') - - -if env['FULL_SYSTEM']: - sources += full_system_sources -else: - sources += syscall_emulation_sources - -if env['USE_MYSQL']: - sources += mysql_sources +# Walk the tree and execute all SConscripts +scripts = [] +srcdir = env['SRCDIR'] +for root, dirs, files in os.walk(srcdir, topdown=True): + if root == srcdir: + # we don't want to recurse back into this SConscript + continue + + if 'SConscript' in files: + # strip off the srcdir part since scons will try to find the + # script in the build directory + base = root[len(srcdir) + 1:] + SConscript(joinpath(base, 'SConscript')) for opt in env.ExportOptions: env.ConfigFile(opt) -################################################### -# -# Special build rules. -# -################################################### - -# base/traceflags.{cc,hh} are generated from base/traceflags.py. -# $TARGET.base will expand to "<build-dir>/base/traceflags". -env.Command(Split('base/traceflags.hh base/traceflags.cc'), - 'base/traceflags.py', - 'python $SOURCE $TARGET.base') - -SConscript('python/SConscript', exports = ['env']) - # This function adds the specified sources to the given build # environment, and returns a list of all the corresponding SCons # Object nodes (including an extra one for date.cc). We explicitly diff --git a/src/arch/SConscript b/src/arch/SConscript index 74be5f8d1..0ac25b6c7 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -28,13 +28,9 @@ # # Authors: Steve Reinhardt -import os.path, sys +import sys -# Import build environment variable from SConstruct. -Import('env') - -# Right now there are no source files immediately in this directory -sources = [] +Import('*') ################################################################# # @@ -55,6 +51,7 @@ isa_switch_hdrs = Split(''' locked_mem.hh mmaped_ipr.hh process.hh + predecoder.hh regfile.hh remote_gdb.hh stacktrace.hh @@ -66,7 +63,7 @@ isa_switch_hdrs = Split(''' ''') # Set up this directory to support switching headers -env.make_switching_dir('arch', isa_switch_hdrs, env) +make_switching_dir('arch', isa_switch_hdrs, env) ################################################################# # @@ -100,7 +97,7 @@ execfile(cpu_models_file.srcnode().abspath) # Several files are generated from the ISA description. # We always get the basic decoder and header file. -isa_desc_gen_files = Split('decoder.cc decoder.hh') +isa_desc_gen_files = [ 'decoder.cc', 'decoder.hh' ] # We also get an execute file for each selected CPU model. isa_desc_gen_files += [CpuModel.dict[cpu].filename for cpu in env['CPU_MODELS']] @@ -128,14 +125,3 @@ else: emitter = isa_desc_emitter) env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder }) - -# -# Now include other ISA-specific sources from the ISA subdirectories. -# - -isa = env['TARGET_ISA'] # someday this may be a list of ISAs - -# Let the target architecture define what additional sources it needs -sources += SConscript(os.path.join(isa, 'SConscript'), exports = 'env') - -Return('sources') diff --git a/src/arch/alpha/SConscript b/src/arch/alpha/SConscript index addd49884..61611e9f6 100644 --- a/src/arch/alpha/SConscript +++ b/src/arch/alpha/SConscript @@ -29,76 +29,45 @@ # Authors: Gabe Black # Steve Reinhardt -import os -import sys -from os.path import isdir +Import('*') -# This file defines how to build a particular configuration of M5 -# based on variable settings in the 'env' build environment. +if env['TARGET_ISA'] == 'alpha': + Source('faults.cc') + Source('floatregfile.cc') + Source('intregfile.cc') + Source('miscregfile.cc') + Source('regfile.cc') + Source('remote_gdb.cc') -# Import build environment variable from SConstruct. -Import('env') + if env['FULL_SYSTEM']: + Source('arguments.cc') + Source('ev5.cc') + Source('idle_event.cc') + Source('ipr.cc') + Source('kernel_stats.cc') + Source('osfpal.cc') + Source('pagetable.cc') + Source('stacktrace.cc') + Source('system.cc') + Source('tlb.cc') + Source('vtophys.cc') -################################################### -# -# Define needed sources. -# -################################################### - -# Base sources used by all configurations. -base_sources = Split(''' - faults.cc - floatregfile.cc - intregfile.cc - miscregfile.cc - regfile.cc - remote_gdb.cc - ''') - -# Full-system sources -full_system_sources = Split(''' - arguments.cc - ev5.cc - freebsd/system.cc - idle_event.cc - ipr.cc - kernel_stats.cc - linux/system.cc - osfpal.cc - pagetable.cc - stacktrace.cc - system.cc - tlb.cc - tru64/system.cc - vtophys.cc - ''') - - -# Syscall emulation (non-full-system) sources -syscall_emulation_sources = Split(''' - linux/linux.cc - linux/process.cc - tru64/tru64.cc - tru64/process.cc - process.cc - ''') - -# Set up complete list of sources based on configuration. -sources = base_sources + Source('freebsd/system.cc') + Source('linux/system.cc') + Source('tru64/system.cc') -if env['FULL_SYSTEM']: - sources += full_system_sources -else: - sources += syscall_emulation_sources + else: + Source('process.cc') -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] + Source('linux/linux.cc') + Source('linux/process.cc') -# Add in files generated by the ISA description. -isa_desc_files = env.ISADesc('isa/main.isa') -# Only non-header files need to be compiled. -isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')] -sources += isa_desc_sources + Source('tru64/tru64.cc') + Source('tru64/process.cc') -Return('sources') + # Add in files generated by the ISA description. + isa_desc_files = env.ISADesc('isa/main.isa') + # Only non-header files need to be compiled. + for f in isa_desc_files: + if not f.path.endswith('.hh'): + Source(f) diff --git a/src/arch/alpha/SConsopts b/src/arch/alpha/SConsopts new file mode 100644 index 000000000..633eeb06f --- /dev/null +++ b/src/arch/alpha/SConsopts @@ -0,0 +1,37 @@ +# -*- mode:python -*- + +# Copyright (c) 2004-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 + +Import('*') + +all_isa_list.append('alpha') + +# Alpha can be compiled with Turbolaser support instead of Tsunami +sticky_opts.Add(BoolOption('ALPHA_TLASER', + 'Model Alpha TurboLaser platform (vs. Tsunami)', False)) diff --git a/src/arch/alpha/arguments.hh b/src/arch/alpha/arguments.hh index c44181a8d..4dba4901f 100644 --- a/src/arch/alpha/arguments.hh +++ b/src/arch/alpha/arguments.hh @@ -35,6 +35,7 @@ #include "arch/alpha/vtophys.hh" #include "base/refcnt.hh" +#include "mem/vport.hh" #include "sim/host.hh" class ThreadContext; diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 8d13511ac..ec5090eb8 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -62,7 +62,7 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId) AlphaISA::AlphaFault *reset = new AlphaISA::ResetFault; - tc->setPC(tc->readMiscReg(IPR_PAL_BASE) + reset->vect()); + tc->setPC(tc->readMiscRegNoEffect(IPR_PAL_BASE) + reset->vect()); tc->setNextPC(tc->readPC() + sizeof(MachInst)); delete reset; @@ -76,12 +76,12 @@ void AlphaISA::initIPRs(ThreadContext *tc, int cpuId) { for (int i = 0; i < NumInternalProcRegs; ++i) { - tc->setMiscReg(i, 0); + tc->setMiscRegNoEffect(i, 0); } - tc->setMiscReg(IPR_PAL_BASE, PalBase); - tc->setMiscReg(IPR_MCSR, 0x6); - tc->setMiscReg(IPR_PALtemp16, cpuId); + tc->setMiscRegNoEffect(IPR_PAL_BASE, PalBase); + tc->setMiscRegNoEffect(IPR_MCSR, 0x6); + tc->setMiscRegNoEffect(IPR_PALtemp16, cpuId); } @@ -94,13 +94,13 @@ AlphaISA::processInterrupts(CPU *cpu) int ipl = 0; int summary = 0; - if (cpu->readMiscReg(IPR_ASTRR)) + if (cpu->readMiscRegNoEffect(IPR_ASTRR)) panic("asynchronous traps not implemented\n"); - if (cpu->readMiscReg(IPR_SIRR)) { + if (cpu->readMiscRegNoEffect(IPR_SIRR)) { for (int i = INTLEVEL_SOFTWARE_MIN; i < INTLEVEL_SOFTWARE_MAX; i++) { - if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { + if (cpu->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) { // See table 4-19 of the 21164 hardware reference ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; summary |= (ULL(1) << i); @@ -121,12 +121,12 @@ AlphaISA::processInterrupts(CPU *cpu) } } - if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) { - cpu->setMiscReg(IPR_ISR, summary); - cpu->setMiscReg(IPR_INTID, ipl); + if (ipl && ipl > cpu->readMiscRegNoEffect(IPR_IPLR)) { + cpu->setMiscRegNoEffect(IPR_ISR, summary); + cpu->setMiscRegNoEffect(IPR_INTID, ipl); cpu->trap(new InterruptFault); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - cpu->readMiscReg(IPR_IPLR), ipl, summary); + cpu->readMiscRegNoEffect(IPR_IPLR), ipl, summary); } } @@ -148,7 +148,7 @@ SimpleThread::hwrei() if (!(readPC() & 0x3)) return new UnimplementedOpcodeFault; - setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR)); + setNextPC(readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR)); if (!misspeculating()) { if (kernelStats) @@ -554,7 +554,7 @@ void AlphaISA::copyIprs(ThreadContext *src, ThreadContext *dest) { for (int i = 0; i < NumInternalProcRegs; ++i) { - dest->setMiscReg(i, src->readMiscReg(i)); + dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i)); } } diff --git a/src/arch/alpha/faults.cc b/src/arch/alpha/faults.cc index 5efcf92e4..149729351 100644 --- a/src/arch/alpha/faults.cc +++ b/src/arch/alpha/faults.cc @@ -59,12 +59,6 @@ FaultName ArithmeticFault::_name = "arith"; FaultVect ArithmeticFault::_vect = 0x0501; FaultStat ArithmeticFault::_count; -#if !FULL_SYSTEM -FaultName PageTableFault::_name = "page_table_fault"; -FaultVect PageTableFault::_vect = 0x0000; -FaultStat PageTableFault::_count; -#endif - FaultName InterruptFault::_name = "interrupt"; FaultVect InterruptFault::_vect = 0x0101; FaultStat InterruptFault::_count; @@ -126,15 +120,15 @@ void AlphaFault::invoke(ThreadContext * tc) // exception restart address if (setRestartAddress() || !(tc->readPC() & 0x3)) - tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, tc->readPC()); + tc->setMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, tc->readPC()); if (skipFaultingInstruction()) { // traps... skip faulting instruction. - tc->setMiscReg(AlphaISA::IPR_EXC_ADDR, - tc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4); + tc->setMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, + tc->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR) + 4); } - tc->setPC(tc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect()); + tc->setPC(tc->readMiscRegNoEffect(AlphaISA::IPR_PAL_BASE) + vect()); tc->setNextPC(tc->readPC() + sizeof(MachInst)); } @@ -154,17 +148,17 @@ void DtbFault::invoke(ThreadContext * tc) if (!tc->misspeculating() && !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) { // set VA register with faulting address - tc->setMiscReg(AlphaISA::IPR_VA, vaddr); + tc->setMiscRegNoEffect(AlphaISA::IPR_VA, vaddr); // set MM_STAT register flags - tc->setMiscReg(AlphaISA::IPR_MM_STAT, + tc->setMiscRegNoEffect(AlphaISA::IPR_MM_STAT, (((EV5::Opcode(tc->getInst()) & 0x3f) << 11) | ((EV5::Ra(tc->getInst()) & 0x1f) << 6) | (flags & 0x3f))); // set VA_FORM register with faulting formatted address - tc->setMiscReg(AlphaISA::IPR_VA_FORM, - tc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3)); + tc->setMiscRegNoEffect(AlphaISA::IPR_VA_FORM, + tc->readMiscRegNoEffect(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3)); } AlphaFault::invoke(tc); @@ -173,41 +167,15 @@ void DtbFault::invoke(ThreadContext * tc) void ItbFault::invoke(ThreadContext * tc) { if (!tc->misspeculating()) { - tc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc); - tc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM, - tc->readMiscReg(AlphaISA::IPR_IVPTBR) | + tc->setMiscRegNoEffect(AlphaISA::IPR_ITB_TAG, pc); + tc->setMiscRegNoEffect(AlphaISA::IPR_IFAULT_VA_FORM, + tc->readMiscRegNoEffect(AlphaISA::IPR_IVPTBR) | (AlphaISA::VAddr(pc).vpn() << 3)); } AlphaFault::invoke(tc); } -#else //!FULL_SYSTEM - -void PageTableFault::invoke(ThreadContext *tc) -{ - Process *p = tc->getProcessPtr(); - - // address is higher than the stack region or in the current stack region - if (vaddr > p->stack_base || vaddr > p->stack_min) - FaultBase::invoke(tc); - - // We've accessed the next page - if (vaddr > p->stack_min - PageBytes) { - DPRINTF(Stack, - "Increasing stack %#x:%#x to %#x:%#x because of access to %#x", - p->stack_min, p->stack_base, p->stack_min - PageBytes, - p->stack_base, vaddr); - p->stack_min -= PageBytes; - if (p->stack_base - p->stack_min > 8*1024*1024) - fatal("Over max stack size for one thread\n"); - p->pTable->allocate(p->stack_min, PageBytes); - } else { - warn("Page fault on address %#x\n", vaddr); - FaultBase::invoke(tc); - } -} - #endif } // namespace AlphaISA diff --git a/src/arch/alpha/faults.hh b/src/arch/alpha/faults.hh index e2c3441e9..6342122c2 100644 --- a/src/arch/alpha/faults.hh +++ b/src/arch/alpha/faults.hh @@ -85,29 +85,6 @@ class AlignmentFault : public AlphaFault bool isAlignmentFault() {return true;} }; -#if !FULL_SYSTEM -class PageTableFault : public AlphaFault -{ - private: - Addr vaddr; - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - PageTableFault(Addr va) - : vaddr(va) {} - FaultName name() {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; - -static inline Fault genPageTableFault(Addr va) -{ - return new PageTableFault(va); -} -#endif - static inline Fault genMachineCheckFault() { return new MachineCheckFault; diff --git a/src/arch/alpha/idle_event.cc b/src/arch/alpha/idle_event.cc index 0f6806319..f0f1eab7a 100644 --- a/src/arch/alpha/idle_event.cc +++ b/src/arch/alpha/idle_event.cc @@ -40,6 +40,6 @@ IdleStartEvent::process(ThreadContext *tc) { if (tc->getKernelStats()) tc->getKernelStats()->setIdleProcess( - tc->readMiscReg(AlphaISA::IPR_PALtemp23), tc); + tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23), tc); remove(); } diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index a522dec6c..6453edf97 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -34,6 +34,7 @@ #include "arch/alpha/faults.hh" #include "arch/alpha/isa_traits.hh" +#include "base/compiler.hh" #include "cpu/thread_context.hh" namespace AlphaISA @@ -52,11 +53,6 @@ namespace AlphaISA newInfoSet = false; } - void post(int int_type) - { - // sparc only - } - void post(int int_num, int index) { DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); @@ -116,13 +112,13 @@ namespace AlphaISA int ipl = 0; int summary = 0; - if (tc->readMiscReg(IPR_ASTRR)) + if (tc->readMiscRegNoEffect(IPR_ASTRR)) panic("asynchronous traps not implemented\n"); - if (tc->readMiscReg(IPR_SIRR)) { + if (tc->readMiscRegNoEffect(IPR_SIRR)) { for (int i = INTLEVEL_SOFTWARE_MIN; i < INTLEVEL_SOFTWARE_MAX; i++) { - if (tc->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { + if (tc->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) { // See table 4-19 of 21164 hardware reference ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; summary |= (ULL(1) << i); @@ -142,12 +138,12 @@ namespace AlphaISA } } - if (ipl && ipl > tc->readMiscReg(IPR_IPLR)) { + if (ipl && ipl > tc->readMiscRegNoEffect(IPR_IPLR)) { newIpl = ipl; newSummary = summary; newInfoSet = true; DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - tc->readMiscReg(IPR_IPLR), ipl, summary); + tc->readMiscRegNoEffect(IPR_IPLR), ipl, summary); return new InterruptFault; } else { @@ -158,11 +154,17 @@ namespace AlphaISA void updateIntrInfo(ThreadContext *tc) { assert(newInfoSet); - tc->setMiscReg(IPR_ISR, newSummary); - tc->setMiscReg(IPR_INTID, newIpl); + tc->setMiscRegNoEffect(IPR_ISR, newSummary); + tc->setMiscRegNoEffect(IPR_INTID, newIpl); newInfoSet = false; } + uint64_t get_vec(int int_num) + { + panic("Shouldn't be called for Alpha\n"); + M5_DUMMY_RETURN + } + private: bool newInfoSet; int newIpl; diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 03c8cc29e..af1a91a62 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -84,6 +84,9 @@ decode OPCODE default Unknown::unknown() { uint64_t tmp = write_result; // see stq_c Ra = (tmp == 0 || tmp == 1) ? tmp : Ra; + if (tmp == 1) { + xc->setStCondFailures(0); + } }}, mem_flags = LOCKED, inst_flags = IsStoreConditional); 0x2f: stq_c({{ Mem.uq = Ra; }}, {{ @@ -96,6 +99,12 @@ decode OPCODE default Unknown::unknown() { // mailbox access, and we don't update the // result register at all. Ra = (tmp == 0 || tmp == 1) ? tmp : Ra; + if (tmp == 1) { + // clear failure counter... this is + // non-architectural and for debugging + // only. + xc->setStCondFailures(0); + } }}, mem_flags = LOCKED, inst_flags = IsStoreConditional); } @@ -629,7 +638,7 @@ decode OPCODE default Unknown::unknown() { /* Rb is a fake dependency so here is a fun way to get * the parser to understand that. */ - Ra = xc->readMiscRegWithEffect(AlphaISA::IPR_CC) + (Rb & 0); + Ra = xc->readMiscReg(AlphaISA::IPR_CC) + (Rb & 0); #else Ra = curTick; @@ -681,7 +690,7 @@ decode OPCODE default Unknown::unknown() { 0x00: CallPal::call_pal({{ if (!palValid || (palPriv - && xc->readMiscRegWithEffect(AlphaISA::IPR_ICM) != AlphaISA::mode_kernel)) { + && xc->readMiscReg(AlphaISA::IPR_ICM) != AlphaISA::mode_kernel)) { // invalid pal function code, or attempt to do privileged // PAL call in non-kernel mode fault = new UnimplementedOpcodeFault; @@ -692,8 +701,8 @@ decode OPCODE default Unknown::unknown() { bool dopal = xc->simPalCheck(palFunc); if (dopal) { - xc->setMiscRegWithEffect(AlphaISA::IPR_EXC_ADDR, NPC); - NPC = xc->readMiscRegWithEffect(AlphaISA::IPR_PAL_BASE) + palOffset; + xc->setMiscReg(AlphaISA::IPR_EXC_ADDR, NPC); + NPC = xc->readMiscReg(AlphaISA::IPR_PAL_BASE) + palOffset; } } }}, IsNonSpeculative); @@ -753,7 +762,7 @@ decode OPCODE default Unknown::unknown() { miscRegIndex >= NumInternalProcRegs) fault = new UnimplementedOpcodeFault; else - Ra = xc->readMiscRegWithEffect(miscRegIndex); + Ra = xc->readMiscReg(miscRegIndex); }}, IsIprAccess); } } @@ -768,7 +777,7 @@ decode OPCODE default Unknown::unknown() { miscRegIndex >= NumInternalProcRegs) fault = new UnimplementedOpcodeFault; else - xc->setMiscRegWithEffect(miscRegIndex, Ra); + xc->setMiscReg(miscRegIndex, Ra); if (traceData) { traceData->setData(Ra); } }}, IsIprAccess); } @@ -783,19 +792,19 @@ decode OPCODE default Unknown::unknown() { // M5 special opcodes use the reserved 0x01 opcode space 0x01: decode M5FUNC { 0x00: arm({{ - AlphaPseudo::arm(xc->tcBase()); + PseudoInst::arm(xc->tcBase()); }}, IsNonSpeculative); 0x01: quiesce({{ - AlphaPseudo::quiesce(xc->tcBase()); + PseudoInst::quiesce(xc->tcBase()); }}, IsNonSpeculative, IsQuiesce); 0x02: quiesceNs({{ - AlphaPseudo::quiesceNs(xc->tcBase(), R16); + PseudoInst::quiesceNs(xc->tcBase(), R16); }}, IsNonSpeculative, IsQuiesce); 0x03: quiesceCycles({{ - AlphaPseudo::quiesceCycles(xc->tcBase(), R16); + PseudoInst::quiesceCycles(xc->tcBase(), R16); }}, IsNonSpeculative, IsQuiesce, IsUnverifiable); 0x04: quiesceTime({{ - R0 = AlphaPseudo::quiesceTime(xc->tcBase()); + R0 = PseudoInst::quiesceTime(xc->tcBase()); }}, IsNonSpeculative, IsUnverifiable); 0x10: ivlb({{ warn_once("Obsolete M5 instruction ivlb encountered.\n"); @@ -804,47 +813,47 @@ decode OPCODE default Unknown::unknown() { warn_once("Obsolete M5 instruction ivlb encountered.\n"); }}); 0x20: m5exit_old({{ - AlphaPseudo::m5exit_old(xc->tcBase()); + PseudoInst::m5exit_old(xc->tcBase()); }}, No_OpClass, IsNonSpeculative); 0x21: m5exit({{ - AlphaPseudo::m5exit(xc->tcBase(), R16); + PseudoInst::m5exit(xc->tcBase(), R16); }}, No_OpClass, IsNonSpeculative); 0x31: loadsymbol({{ - AlphaPseudo::loadsymbol(xc->tcBase()); + PseudoInst::loadsymbol(xc->tcBase()); }}, No_OpClass, IsNonSpeculative); 0x30: initparam({{ Ra = xc->tcBase()->getCpuPtr()->system->init_param; }}); 0x40: resetstats({{ - AlphaPseudo::resetstats(xc->tcBase(), R16, R17); + PseudoInst::resetstats(xc->tcBase(), R16, R17); }}, IsNonSpeculative); 0x41: dumpstats({{ - AlphaPseudo::dumpstats(xc->tcBase(), R16, R17); + PseudoInst::dumpstats(xc->tcBase(), R16, R17); }}, IsNonSpeculative); 0x42: dumpresetstats({{ - AlphaPseudo::dumpresetstats(xc->tcBase(), R16, R17); + PseudoInst::dumpresetstats(xc->tcBase(), R16, R17); }}, IsNonSpeculative); 0x43: m5checkpoint({{ - AlphaPseudo::m5checkpoint(xc->tcBase(), R16, R17); + PseudoInst::m5checkpoint(xc->tcBase(), R16, R17); }}, IsNonSpeculative); 0x50: m5readfile({{ - R0 = AlphaPseudo::readfile(xc->tcBase(), R16, R17, R18); + R0 = PseudoInst::readfile(xc->tcBase(), R16, R17, R18); }}, IsNonSpeculative); 0x51: m5break({{ - AlphaPseudo::debugbreak(xc->tcBase()); + PseudoInst::debugbreak(xc->tcBase()); }}, IsNonSpeculative); 0x52: m5switchcpu({{ - AlphaPseudo::switchcpu(xc->tcBase()); + PseudoInst::switchcpu(xc->tcBase()); }}, IsNonSpeculative); 0x53: m5addsymbol({{ - AlphaPseudo::addsymbol(xc->tcBase(), R16, R17); + PseudoInst::addsymbol(xc->tcBase(), R16, R17); }}, IsNonSpeculative); 0x54: m5panic({{ panic("M5 panic instruction called at pc=%#x.", xc->readPC()); }}, IsNonSpeculative); 0x55: m5anBegin({{ - AlphaPseudo::anBegin(xc->tcBase(), R16); + PseudoInst::anBegin(xc->tcBase(), R16); }}, IsNonSpeculative); 0x56: m5anWait({{ - AlphaPseudo::anWait(xc->tcBase(), R16, R17); + PseudoInst::anWait(xc->tcBase(), R16, R17); }}, IsNonSpeculative); } } diff --git a/src/arch/alpha/isa/fp.isa b/src/arch/alpha/isa/fp.isa index c845ea442..a350aa05f 100644 --- a/src/arch/alpha/isa/fp.isa +++ b/src/arch/alpha/isa/fp.isa @@ -46,7 +46,7 @@ output exec {{ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) { Fault fault = NoFault; // dummy... this ipr access should not fault - if (!EV5::ICSR_FPE(xc->readMiscRegWithEffect(AlphaISA::IPR_ICSR))) { + if (!EV5::ICSR_FPE(xc->readMiscReg(AlphaISA::IPR_ICSR))) { fault = new FloatEnableFault; } return fault; @@ -229,7 +229,7 @@ def template FloatingPointExecute {{ %(code)s; } else { fesetround(getC99RoundingMode( - xc->readMiscReg(AlphaISA::MISCREG_FPCR))); + xc->readMiscRegNoEffect(AlphaISA::MISCREG_FPCR))); %(code)s; fesetround(FE_TONEAREST); } diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index c0bdd2c05..fe0daf772 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -350,6 +350,41 @@ def template StoreMemAccExecute {{ { Addr EA; Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreCondMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; uint64_t write_result = 0; %(fp_enable_check)s; @@ -386,6 +421,40 @@ def template StoreExecute {{ { Addr EA; Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreCondExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; uint64_t write_result = 0; %(fp_enable_check)s; @@ -475,7 +544,7 @@ def template StoreCondCompleteAcc {{ %(fp_enable_check)s; %(op_dest_decl)s; - uint64_t write_result = pkt->req->getScResult(); + uint64_t write_result = pkt->req->getExtraData(); if (fault == NoFault) { %(postacc_code)s; @@ -614,10 +683,8 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, # select templates - # define aliases... most StoreCond templates are the same as the - # corresponding Store templates (only CompleteAcc is different). - StoreCondMemAccExecute = StoreMemAccExecute - StoreCondExecute = StoreExecute + # The InitiateAcc template is the same for StoreCond templates as the + # corresponding Store template.. StoreCondInitiateAcc = StoreInitiateAcc memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') diff --git a/src/arch/alpha/kernel_stats.cc b/src/arch/alpha/kernel_stats.cc index 6fc3cb72f..13dc95af7 100644 --- a/src/arch/alpha/kernel_stats.cc +++ b/src/arch/alpha/kernel_stats.cc @@ -150,7 +150,7 @@ Statistics::changeMode(cpu_mode newmode, ThreadContext *tc) void Statistics::mode(cpu_mode newmode, ThreadContext *tc) { - Addr pcbb = tc->readMiscReg(AlphaISA::IPR_PALtemp23); + Addr pcbb = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23); if (newmode == kernel && pcbb == idleProcess) newmode = idle; diff --git a/src/arch/alpha/linux/linux.hh b/src/arch/alpha/linux/linux.hh index 09988bab2..84c04ebc3 100644 --- a/src/arch/alpha/linux/linux.hh +++ b/src/arch/alpha/linux/linux.hh @@ -96,15 +96,15 @@ class AlphaLinux : public Linux //@{ /// ioctl() command codes. - static const unsigned TIOCGETP = 0x40067408; - static const unsigned TIOCSETP = 0x80067409; - static const unsigned TIOCSETN = 0x8006740a; - static const unsigned TIOCSETC = 0x80067411; - static const unsigned TIOCGETC = 0x40067412; - static const unsigned FIONREAD = 0x4004667f; - static const unsigned TIOCISATTY = 0x2000745e; - static const unsigned TIOCGETS = 0x402c7413; - static const unsigned TIOCGETA = 0x40127417; + static const unsigned TIOCGETP_ = 0x40067408; + static const unsigned TIOCSETP_ = 0x80067409; + static const unsigned TIOCSETN_ = 0x8006740a; + static const unsigned TIOCSETC_ = 0x80067411; + static const unsigned TIOCGETC_ = 0x40067412; + static const unsigned FIONREAD_ = 0x4004667f; + static const unsigned TIOCISATTY_ = 0x2000745e; + static const unsigned TIOCGETS_ = 0x402c7413; + static const unsigned TIOCGETA_ = 0x40127417; //@} /// For table(). diff --git a/src/arch/alpha/linux/process.hh b/src/arch/alpha/linux/process.hh index 2076f6339..cb22f521b 100644 --- a/src/arch/alpha/linux/process.hh +++ b/src/arch/alpha/linux/process.hh @@ -53,9 +53,6 @@ class AlphaLinuxProcess : public AlphaLiveProcess virtual SyscallDesc* getDesc(int callnum); - /// The target system's hostname. - static const char *hostname; - /// Array of syscall descriptors, indexed by call number. static SyscallDesc syscallDescs[]; diff --git a/src/arch/alpha/locked_mem.hh b/src/arch/alpha/locked_mem.hh index 52fe24173..df66b92bc 100644 --- a/src/arch/alpha/locked_mem.hh +++ b/src/arch/alpha/locked_mem.hh @@ -35,6 +35,14 @@ * @file * * ISA-specific helper functions for locked memory accesses. + * + * Note that these functions are not embedded in the ISA description + * because they operate on the *physical* address rather than the + * virtual address. In the current M5 design, the physical address is + * not accessible from the ISA description, only from the CPU model. + * Thus the CPU is responsible for calling back to the ISA (here) + * after the address translation has been performed to allow the ISA + * to do these manipulations based on the physical address. */ #include "arch/alpha/miscregfile.hh" @@ -48,8 +56,8 @@ template <class XC> inline void handleLockedRead(XC *xc, Request *req) { - xc->setMiscReg(MISCREG_LOCKADDR, req->getPaddr() & ~0xf); - xc->setMiscReg(MISCREG_LOCKFLAG, true); + xc->setMiscRegNoEffect(MISCREG_LOCKADDR, req->getPaddr() & ~0xf); + xc->setMiscRegNoEffect(MISCREG_LOCKFLAG, true); } @@ -60,16 +68,16 @@ handleLockedWrite(XC *xc, Request *req) if (req->isUncacheable()) { // Funky Turbolaser mailbox access...don't update // result register (see stq_c in decoder.isa) - req->setScResult(2); + req->setExtraData(2); } else { // standard store conditional - bool lock_flag = xc->readMiscReg(MISCREG_LOCKFLAG); - Addr lock_addr = xc->readMiscReg(MISCREG_LOCKADDR); + bool lock_flag = xc->readMiscRegNoEffect(MISCREG_LOCKFLAG); + Addr lock_addr = xc->readMiscRegNoEffect(MISCREG_LOCKADDR); if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) { // Lock flag not set or addr mismatch in CPU; // don't even bother sending to memory system - req->setScResult(0); - xc->setMiscReg(MISCREG_LOCKFLAG, false); + req->setExtraData(0); + xc->setMiscRegNoEffect(MISCREG_LOCKFLAG, false); // the rest of this code is not architectural; // it's just a debugging aid to help detect // livelock by warning on long sequences of failed diff --git a/src/arch/alpha/miscregfile.cc b/src/arch/alpha/miscregfile.cc index 67f6c98e4..1af97adcf 100644 --- a/src/arch/alpha/miscregfile.cc +++ b/src/arch/alpha/miscregfile.cc @@ -61,7 +61,7 @@ namespace AlphaISA } MiscReg - MiscRegFile::readReg(int misc_reg) + MiscRegFile::readRegNoEffect(int misc_reg) { switch(misc_reg) { case MISCREG_FPCR: @@ -87,7 +87,7 @@ namespace AlphaISA } MiscReg - MiscRegFile::readRegWithEffect(int misc_reg, ThreadContext *tc) + MiscRegFile::readReg(int misc_reg, ThreadContext *tc) { switch(misc_reg) { case MISCREG_FPCR: @@ -112,7 +112,7 @@ namespace AlphaISA } void - MiscRegFile::setReg(int misc_reg, const MiscReg &val) + MiscRegFile::setRegNoEffect(int misc_reg, const MiscReg &val) { switch(misc_reg) { case MISCREG_FPCR: @@ -143,7 +143,7 @@ namespace AlphaISA } void - MiscRegFile::setRegWithEffect(int misc_reg, const MiscReg &val, + MiscRegFile::setReg(int misc_reg, const MiscReg &val, ThreadContext *tc) { switch(misc_reg) { diff --git a/src/arch/alpha/miscregfile.hh b/src/arch/alpha/miscregfile.hh index 31b3e59b3..aea702849 100644 --- a/src/arch/alpha/miscregfile.hh +++ b/src/arch/alpha/miscregfile.hh @@ -75,18 +75,18 @@ namespace AlphaISA #endif } - MiscReg readReg(int misc_reg); + MiscReg readRegNoEffect(int misc_reg); - MiscReg readRegWithEffect(int misc_reg, ThreadContext *tc); + MiscReg readReg(int misc_reg, ThreadContext *tc); //These functions should be removed once the simplescalar cpu model //has been replaced. int getInstAsid(); int getDataAsid(); - void setReg(int misc_reg, const MiscReg &val); + void setRegNoEffect(int misc_reg, const MiscReg &val); - void setRegWithEffect(int misc_reg, const MiscReg &val, + void setReg(int misc_reg, const MiscReg &val, ThreadContext *tc); void clear() diff --git a/src/arch/alpha/predecoder.hh b/src/arch/alpha/predecoder.hh new file mode 100644 index 000000000..650f2bfa2 --- /dev/null +++ b/src/arch/alpha/predecoder.hh @@ -0,0 +1,108 @@ +/* + * 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: Gabe Black + */ + +#ifndef __ARCH_ALPHA_PREDECODER_HH__ +#define __ARCH_ALPHA_PREDECODER_HH__ + +#include "arch/alpha/types.hh" +#include "base/misc.hh" +#include "config/full_system.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace AlphaISA +{ + class Predecoder + { + protected: + ThreadContext * tc; + //The pc of the current instruction + Addr fetchPC; + //The extended machine instruction being generated + ExtMachInst ext_inst; + + public: + Predecoder(ThreadContext * _tc) : tc(_tc) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process() + { + } + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr pc, Addr off, MachInst inst) + { + fetchPC = pc; + assert(off == 0); + ext_inst = inst; +#if FULL_SYSTEM + if (pc && 0x1) + ext_inst|=(static_cast<ExtMachInst>(pc & 0x1) << 32); +#endif + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(fetchPC + sizeof(machInst), 0, machInst); + } + + bool needMoreBytes() + { + return true; + } + + bool extMachInstReady() + { + return true; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + return ext_inst; + } + }; +}; + +#endif // __ARCH_ALPHA_PREDECODER_HH__ diff --git a/src/arch/alpha/regfile.cc b/src/arch/alpha/regfile.cc index 92e1b07df..3b42ca9bc 100644 --- a/src/arch/alpha/regfile.cc +++ b/src/arch/alpha/regfile.cc @@ -85,14 +85,14 @@ namespace AlphaISA void copyMiscRegs(ThreadContext *src, ThreadContext *dest) { - dest->setMiscReg(AlphaISA::MISCREG_FPCR, - src->readMiscReg(AlphaISA::MISCREG_FPCR)); - dest->setMiscReg(AlphaISA::MISCREG_UNIQ, - src->readMiscReg(AlphaISA::MISCREG_UNIQ)); - dest->setMiscReg(AlphaISA::MISCREG_LOCKFLAG, - src->readMiscReg(AlphaISA::MISCREG_LOCKFLAG)); - dest->setMiscReg(AlphaISA::MISCREG_LOCKADDR, - src->readMiscReg(AlphaISA::MISCREG_LOCKADDR)); + dest->setMiscRegNoEffect(AlphaISA::MISCREG_FPCR, + src->readMiscRegNoEffect(AlphaISA::MISCREG_FPCR)); + dest->setMiscRegNoEffect(AlphaISA::MISCREG_UNIQ, + src->readMiscRegNoEffect(AlphaISA::MISCREG_UNIQ)); + dest->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, + src->readMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG)); + dest->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKADDR, + src->readMiscRegNoEffect(AlphaISA::MISCREG_LOCKADDR)); #if FULL_SYSTEM copyIprs(src, dest); diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh index 54372da36..b93707181 100644 --- a/src/arch/alpha/regfile.hh +++ b/src/arch/alpha/regfile.hh @@ -106,25 +106,25 @@ namespace AlphaISA miscRegFile.clear(); } - MiscReg readMiscReg(int miscReg) + MiscReg readMiscRegNoEffect(int miscReg) { - return miscRegFile.readReg(miscReg); + return miscRegFile.readRegNoEffect(miscReg); } - MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc) + MiscReg readMiscReg(int miscReg, ThreadContext *tc) { - return miscRegFile.readRegWithEffect(miscReg, tc); + return miscRegFile.readReg(miscReg, tc); } - void setMiscReg(int miscReg, const MiscReg &val) + void setMiscRegNoEffect(int miscReg, const MiscReg &val) { - miscRegFile.setReg(miscReg, val); + miscRegFile.setRegNoEffect(miscReg, val); } - void setMiscRegWithEffect(int miscReg, const MiscReg &val, + void setMiscReg(int miscReg, const MiscReg &val, ThreadContext * tc) { - miscRegFile.setRegWithEffect(miscReg, val, tc); + miscRegFile.setReg(miscReg, val, tc); } FloatReg readFloatReg(int floatReg) diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc index 4637bd7a6..a68e5218e 100644 --- a/src/arch/alpha/remote_gdb.cc +++ b/src/arch/alpha/remote_gdb.cc @@ -187,7 +187,7 @@ RemoteGDB::acc(Addr va, size_t len) if (AlphaISA::PcPAL(va) || va < 0x10000) return true; - Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20); + Addr ptbr = context->readMiscRegNoEffect(AlphaISA::IPR_PALtemp20); TheISA::PageTableEntry pte = TheISA::kernel_pte_lookup(context->getPhysPort(), ptbr, va); if (!pte.valid()) { DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va); diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc index c4612e156..c16498e72 100644 --- a/src/arch/alpha/stacktrace.cc +++ b/src/arch/alpha/stacktrace.cc @@ -146,7 +146,7 @@ namespace AlphaISA { tc = _tc; - bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + bool usermode = (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; Addr pc = tc->readNextPC(); bool kernel = tc->getSystemPtr()->kernelStart <= pc && @@ -219,22 +219,22 @@ namespace AlphaISA bool StackTrace::isEntry(Addr addr) { - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp12)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp7)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp11)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp21)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp9)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp2)) return true; return false; diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index c21bf94f5..3ab65e664 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -46,8 +46,7 @@ using namespace std; using namespace EV5; -namespace AlphaISA -{ +namespace AlphaISA { /////////////////////////////////////////////////////////////////////// // // Alpha TLB @@ -116,10 +115,11 @@ TLB::checkCacheability(RequestPtr &req) #if ALPHA_TLASER - if (req->getPaddr() & PAddrUncachedBit39) { + if (req->getPaddr() & PAddrUncachedBit39) #else - if (req->getPaddr() & PAddrUncachedBit43) { + if (req->getPaddr() & PAddrUncachedBit43) #endif + { // IPR memory space not implemented if (PAddrIprSpace(req->getPaddr())) { return new UnimpFault("IPR memory space not implemented!"); @@ -312,13 +312,14 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) const // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5 // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6 #if ALPHA_TLASER - if ((MCSR_SP(tc->readMiscReg(IPR_MCSR)) & 2) && - VAddrSpaceEV5(req->getVaddr()) == 2) { + if ((MCSR_SP(tc->readMiscRegNoEffect(IPR_MCSR)) & 2) && + VAddrSpaceEV5(req->getVaddr()) == 2) #else - if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { + if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) #endif + { // only valid in kernel mode - if (ICM_CM(tc->readMiscReg(IPR_ICM)) != + if (ICM_CM(tc->readMiscRegNoEffect(IPR_ICM)) != mode_kernel) { acv++; return new ItbAcvFault(req->getVaddr()); @@ -336,7 +337,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) const } else { // not a physical address: need to look up pte - int asn = DTB_ASN_ASN(tc->readMiscReg(IPR_DTB_ASN)); + int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN)); PTE *pte = lookup(VAddr(req->getVaddr()).vpn(), asn); @@ -351,7 +352,7 @@ ITB::translate(RequestPtr &req, ThreadContext *tc) const // check permissions for this access if (!(pte->xre & - (1 << ICM_CM(tc->readMiscReg(IPR_ICM))))) { + (1 << ICM_CM(tc->readMiscRegNoEffect(IPR_ICM))))) { // instruction access fault acv++; return new ItbAcvFault(req->getVaddr()); @@ -452,7 +453,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const Addr pc = tc->readPC(); mode_type mode = - (mode_type)DTB_CM_CM(tc->readMiscReg(IPR_DTB_CM)); + (mode_type)DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)); /** @@ -468,7 +469,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const if (PcPAL(pc)) { mode = (req->getFlags() & ALTMODE) ? (mode_type)ALT_MODE_AM( - tc->readMiscReg(IPR_ALT_MODE)) + tc->readMiscRegNoEffect(IPR_ALT_MODE)) : mode_kernel; } @@ -486,14 +487,15 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const // Check for "superpage" mapping #if ALPHA_TLASER - if ((MCSR_SP(tc->readMiscReg(IPR_MCSR)) & 2) && - VAddrSpaceEV5(req->getVaddr()) == 2) { + if ((MCSR_SP(tc->readMiscRegNoEffect(IPR_MCSR)) & 2) && + VAddrSpaceEV5(req->getVaddr()) == 2) #else - if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) { + if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) #endif + { // only valid in kernel mode - if (DTB_CM_CM(tc->readMiscReg(IPR_DTB_CM)) != + if (DTB_CM_CM(tc->readMiscRegNoEffect(IPR_DTB_CM)) != mode_kernel) { if (write) { write_acv++; } else { read_acv++; } uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) | @@ -517,7 +519,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) const else read_accesses++; - int asn = DTB_ASN_ASN(tc->readMiscReg(IPR_DTB_ASN)); + int asn = DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN)); // not a physical address: need to look up pte PTE *pte = lookup(VAddr(req->getVaddr()).vpn(), @@ -592,6 +594,8 @@ TLB::index(bool advance) return *pte; } +/* end namespace AlphaISA */ } + DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", TLB) BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB) @@ -633,4 +637,3 @@ CREATE_SIM_OBJECT(DTB) } REGISTER_SIM_OBJECT("AlphaDTB", DTB) -} diff --git a/src/arch/alpha/tru64/tru64.hh b/src/arch/alpha/tru64/tru64.hh index f0711b995..90e5f12dc 100644 --- a/src/arch/alpha/tru64/tru64.hh +++ b/src/arch/alpha/tru64/tru64.hh @@ -91,15 +91,15 @@ class AlphaTru64 : public Tru64 //@{ /// ioctl() command codes. - static const unsigned TIOCGETP = 0x40067408; - static const unsigned TIOCSETP = 0x80067409; - static const unsigned TIOCSETN = 0x8006740a; - static const unsigned TIOCSETC = 0x80067411; - static const unsigned TIOCGETC = 0x40067412; - static const unsigned FIONREAD = 0x4004667f; - static const unsigned TIOCISATTY = 0x2000745e; - static const unsigned TIOCGETS = 0x402c7413; - static const unsigned TIOCGETA = 0x40127417; + static const unsigned TIOCGETP_ = 0x40067408; + static const unsigned TIOCSETP_ = 0x80067409; + static const unsigned TIOCSETN_ = 0x8006740a; + static const unsigned TIOCSETC_ = 0x80067411; + static const unsigned TIOCGETC_ = 0x40067412; + static const unsigned FIONREAD_ = 0x4004667f; + static const unsigned TIOCISATTY_ = 0x2000745e; + static const unsigned TIOCGETS_ = 0x402c7413; + static const unsigned TIOCGETA_ = 0x40127417; //@} //@{ diff --git a/src/arch/alpha/types.hh b/src/arch/alpha/types.hh index ae42552d8..6433ea3ca 100644 --- a/src/arch/alpha/types.hh +++ b/src/arch/alpha/types.hh @@ -42,6 +42,7 @@ namespace AlphaISA typedef uint8_t RegIndex; typedef uint64_t IntReg; + typedef uint64_t LargestRead; // floating point register file entry type typedef double FloatReg; diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh index 9a06cc2a4..c20394a92 100644 --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -45,20 +45,7 @@ namespace AlphaISA static inline bool inUserMode(ThreadContext *tc) { - return (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; - } - - static inline ExtMachInst - makeExtMI(MachInst inst, Addr 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 + return (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; } inline bool isCallerSaveIntegerRegister(unsigned int reg) { @@ -123,6 +110,9 @@ namespace AlphaISA // Alpha IPR register accessors inline bool PcPAL(Addr addr) { return addr & 0x3; } + inline void startupCPU(ThreadContext *tc, int cpuId) { + tc->activate(0); + } #if FULL_SYSTEM //////////////////////////////////////////////////////////////////////// diff --git a/src/arch/alpha/vtophys.cc b/src/arch/alpha/vtophys.cc index fd8f781e4..6ffbea181 100644 --- a/src/arch/alpha/vtophys.cc +++ b/src/arch/alpha/vtophys.cc @@ -88,7 +88,7 @@ Addr AlphaISA::vtophys(ThreadContext *tc, Addr addr) { AlphaISA::VAddr vaddr = addr; - Addr ptbr = tc->readMiscReg(AlphaISA::IPR_PALtemp20); + Addr ptbr = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp20); Addr paddr = 0; //@todo Andrew couldn't remember why he commented some of this code //so I put it back in. Perhaps something to do with gdb debugging? @@ -113,54 +113,3 @@ AlphaISA::vtophys(ThreadContext *tc, Addr addr) return paddr; } - -void -AlphaISA::CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) -{ - uint8_t *dst = (uint8_t *)dest; - VirtualPort *vp = tc->getVirtPort(tc); - - vp->readBlob(src, dst, cplen); - - tc->delVirtPort(vp); - -} - -void -AlphaISA::CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) -{ - uint8_t *src = (uint8_t *)source; - VirtualPort *vp = tc->getVirtPort(tc); - - vp->writeBlob(dest, src, cplen); - - tc->delVirtPort(vp); -} - -void -AlphaISA::CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) -{ - int len = 0; - char *start = dst; - VirtualPort *vp = tc->getVirtPort(tc); - - do { - vp->readBlob(vaddr++, (uint8_t*)dst++, 1); - } while (len < maxlen && start[len++] != 0 ); - - tc->delVirtPort(vp); - dst[len] = 0; -} - -void -AlphaISA::CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) -{ - VirtualPort *vp = tc->getVirtPort(tc); - for (ChunkGenerator gen(vaddr, strlen(src), AlphaISA::PageBytes); !gen.done(); - gen.next()) - { - vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size()); - src += gen.size(); - } - tc->delVirtPort(vp); -} diff --git a/src/arch/alpha/vtophys.hh b/src/arch/alpha/vtophys.hh index 32b999c37..bd2ee8468 100644 --- a/src/arch/alpha/vtophys.hh +++ b/src/arch/alpha/vtophys.hh @@ -47,11 +47,6 @@ namespace AlphaISA { 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); - }; #endif // __ARCH_ALPHA_VTOPHYS_H__ diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index 07ae72cb8..f3981a6eb 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -81,12 +81,12 @@ tokens = reserved + ( # code literal 'CODELIT', - # ( ) [ ] { } < > , ; : :: * + # ( ) [ ] { } < > , ; . : :: * 'LPAREN', 'RPAREN', 'LBRACKET', 'RBRACKET', 'LBRACE', 'RBRACE', 'LESS', 'GREATER', 'EQUALS', - 'COMMA', 'SEMI', 'COLON', 'DBLCOLON', + 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON', 'ASTERISK', # C preprocessor directives @@ -113,6 +113,7 @@ t_GREATER = r'\>' t_EQUALS = r'=' t_COMMA = r',' t_SEMI = r';' +t_DOT = r'\.' t_COLON = r':' t_DBLCOLON = r'::' t_ASTERISK = r'\*' @@ -261,6 +262,7 @@ def p_defs_and_outputs_1(t): def p_def_or_output(t): '''def_or_output : def_format | def_bitfield + | def_bitfield_struct | def_template | def_operand_types | def_operands @@ -363,6 +365,23 @@ def p_def_bitfield_1(t): hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) t[0] = GenCode(header_output = hash_define) +# alternate form for structure member: 'def bitfield <ID> <ID>' +def p_def_bitfield_struct(t): + 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' + if (t[2] != ''): + error(t.lineno(1), 'error: structure bitfields are always unsigned.') + expr = 'machInst.%s' % t[5] + hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) + t[0] = GenCode(header_output = hash_define) + +def p_id_with_dot_0(t): + 'id_with_dot : ID' + t[0] = t[1] + +def p_id_with_dot_1(t): + 'id_with_dot : ID DOT id_with_dot' + t[0] = t[1] + t[2] + t[3] + def p_opt_signed_0(t): 'opt_signed : SIGNED' t[0] = t[1] @@ -1124,6 +1143,12 @@ def buildOperandTypeMap(userDict, lineno): ctype = 'float' elif size == 64: ctype = 'double' + elif desc == 'twin64 int': + is_signed = 0 + ctype = 'Twin64_t' + elif desc == 'twin32 int': + is_signed = 0 + ctype = 'Twin32_t' if ctype == '': error(lineno, 'Unrecognized type description "%s" in userDict') operandTypeMap[ext] = (size, ctype, is_signed) @@ -1156,7 +1181,10 @@ class Operand(object): # template must be careful not to use it if it doesn't apply. if self.isMem(): self.mem_acc_size = self.makeAccSize() - self.mem_acc_type = self.ctype + if self.ctype in ['Twin32_t', 'Twin64_t']: + self.mem_acc_type = 'Twin' + else: + self.mem_acc_type = 'uint' # Finalize additional fields (primarily code fields). This step # is done separately since some of these fields may depend on the @@ -1359,7 +1387,7 @@ class ControlRegOperand(Operand): bit_select = 0 if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to read control register as FP') - base = 'xc->readMiscRegOperandWithEffect(this, %s)' % self.src_reg_idx + base = 'xc->readMiscRegOperand(this, %s)' % self.src_reg_idx if self.size == self.dflt_size: return '%s = %s;\n' % (self.base_name, base) else: @@ -1369,7 +1397,7 @@ class ControlRegOperand(Operand): def makeWrite(self): if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to write control register as FP') - wb = 'xc->setMiscRegOperandWithEffect(this, %s, %s);\n' % \ + wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \ (self.dest_reg_idx, self.base_name) wb += 'if (traceData) { traceData->setData(%s); }' % \ self.base_name @@ -1386,6 +1414,9 @@ class MemOperand(Operand): # Note that initializations in the declarations are solely # to avoid 'uninitialized variable' errors from the compiler. # Declare memory data variable. + if self.ctype in ['Twin32_t','Twin64_t']: + return "%s %s; %s.a = 0; %s.b = 0;\n" % (self.ctype, self.base_name, + self.base_name, self.base_name) c = '%s %s = 0;\n' % (self.ctype, self.base_name) return c diff --git a/src/arch/isa_specific.hh b/src/arch/isa_specific.hh index 181e81302..c241e5c62 100644 --- a/src/arch/isa_specific.hh +++ b/src/arch/isa_specific.hh @@ -32,22 +32,23 @@ #define __ARCH_ISA_SPECIFIC_HH__ //This file provides a mechanism for other source code to bring in -//files from the ISA being compiled with +//files from the ISA being compiled in. -//These are constants so you can selective compile code based on the isa -//To use them, do something like +//These are constants so you can selectively compile code based on the isa. +//To use them, do something like: // //#if THE_ISA == YOUR_FAVORITE_ISA // conditional_code //#endif // -//Note that this is how this file sets up the other isa "hooks" +//Note that this is how this file sets up the TheISA macro. //These macros have numerical values because otherwise the preprocessor //would treat them as 0 in comparisons. #define ALPHA_ISA 21064 #define SPARC_ISA 42 #define MIPS_ISA 34000 +#define X86_ISA 8086 //These tell the preprocessor where to find the files of a particular //ISA, and set the "TheISA" macro for use elsewhere. @@ -57,6 +58,8 @@ #define TheISA SparcISA #elif THE_ISA == MIPS_ISA #define TheISA MipsISA +#elif THE_ISA == X86_ISA + #define TheISA X86ISA #else #error "THE_ISA not set" #endif diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript index 8353bcde7..f959951b3 100644 --- a/src/arch/mips/SConscript +++ b/src/arch/mips/SConscript @@ -30,54 +30,25 @@ # Steve Reinhardt # Korey Sewell -import os -import sys -from os.path import isdir - -# Import build environment variable from SConstruct. -Import('env') - -################################################### -# -# Define needed sources. -# -################################################### - -# Base sources used by all configurations. -base_sources = Split(''' - faults.cc - isa_traits.cc - utility.cc - ''') - -# Full-system sources -full_system_sources = Split(''' - #Insert Full-System Files Here - ''') - -# Syscall emulation (non-full-system) sources -syscall_emulation_sources = Split(''' - linux/linux.cc - linux/process.cc - process.cc - ''') - -# Set up complete list of sources based on configuration. -sources = base_sources - -if env['FULL_SYSTEM']: - sources += full_system_sources -else: - sources += syscall_emulation_sources - -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] - -# Add in files generated by the ISA description. -isa_desc_files = env.ISADesc('isa/main.isa') -# Only non-header files need to be compiled. -isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')] -sources += isa_desc_sources - -Return('sources') +Import('*') + +if env['TARGET_ISA'] == 'mips': + Source('faults.cc') + Source('isa_traits.cc') + Source('utility.cc') + + if env['FULL_SYSTEM']: + #Insert Full-System Files Here + pass + else: + Source('process.cc') + + Source('linux/linux.cc') + Source('linux/process.cc') + + # Add in files generated by the ISA description. + isa_desc_files = env.ISADesc('isa/main.isa') + # Only non-header files need to be compiled. + for f in isa_desc_files: + if not f.path.endswith('.hh'): + Source(f) diff --git a/src/arch/mips/SConsopts b/src/arch/mips/SConsopts new file mode 100644 index 000000000..744fc9cca --- /dev/null +++ b/src/arch/mips/SConsopts @@ -0,0 +1,33 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +all_isa_list.append('mips') diff --git a/src/arch/mips/faults.cc b/src/arch/mips/faults.cc index 2a8ab1df5..c9e6aa75b 100644 --- a/src/arch/mips/faults.cc +++ b/src/arch/mips/faults.cc @@ -58,12 +58,6 @@ FaultName ArithmeticFault::_name = "arith"; FaultVect ArithmeticFault::_vect = 0x0501; FaultStat ArithmeticFault::_count; -#if !FULL_SYSTEM -FaultName PageTableFault::_name = "page_table_fault"; -FaultVect PageTableFault::_vect = 0x0000; -FaultStat PageTableFault::_count; -#endif - FaultName InterruptFault::_name = "interrupt"; FaultVect InterruptFault::_vect = 0x0101; FaultStat InterruptFault::_count; @@ -112,25 +106,5 @@ FaultName IntegerOverflowFault::_name = "intover"; FaultVect IntegerOverflowFault::_vect = 0x0501; FaultStat IntegerOverflowFault::_count; -void PageTableFault::invoke(ThreadContext *tc) -{ - Process *p = tc->getProcessPtr(); - - // address is higher than the stack region or in the current stack region - if (vaddr > p->stack_base || vaddr > p->stack_min) - FaultBase::invoke(tc); - - // We've accessed the next page - if (vaddr > p->stack_min - PageBytes) { - p->stack_min -= PageBytes; - if (p->stack_base - p->stack_min > 8*1024*1024) - fatal("Over max stack size for one thread\n"); - p->pTable->allocate(p->stack_min, PageBytes); - warn("Increasing stack size by one page."); - } else { - FaultBase::invoke(tc); - } -} - } // namespace MipsISA diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh index 9d2c5df32..86c742413 100644 --- a/src/arch/mips/faults.hh +++ b/src/arch/mips/faults.hh @@ -80,30 +80,6 @@ class AlignmentFault : public MipsFault bool isAlignmentFault() {return true;} }; -#if !FULL_SYSTEM -class PageTableFault : public MipsFault -{ - private: - Addr vaddr; - static FaultName _name; - static FaultVect _vect; - static FaultStat _count; - public: - PageTableFault(Addr va) - : vaddr(va) {} - FaultName name() {return _name;} - FaultVect vect() {return _vect;} - FaultStat & countStat() {return _count;} - void invoke(ThreadContext * tc); -}; - -static inline Fault genPageTableFault(Addr va) -{ - return new PageTableFault(va); -} -#endif - - static inline Fault genMachineCheckFault() { return new MachineCheckFault; diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index 99c9e1604..b5d1df4fc 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -289,8 +289,8 @@ decode OPCODE_HI default Unknown::unknown() { 0x0: decode RS_MSB { 0x0: decode RS { format CP0Control { - 0x0: mfc0({{ Rt = xc->readMiscReg(RD << 5 | SEL); }}); - 0x4: mtc0({{ xc->setMiscReg(RD << 5 | SEL, Rt); }}); + 0x0: mfc0({{ Rt = xc->readMiscRegNoEffect(RD << 5 | SEL); }}); + 0x4: mtc0({{ xc->setMiscRegNoEffect(RD << 5 | SEL, Rt); }}); } format MipsMT { @@ -1093,6 +1093,9 @@ 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; + if (tmp == 1) { + xc->setStCondFailures(0); + } }}, mem_flags=LOCKED, inst_flags = IsStoreConditional); format StoreMemory { diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa index fccda2775..df80e7a1f 100644 --- a/src/arch/mips/isa/formats/mem.isa +++ b/src/arch/mips/isa/formats/mem.isa @@ -325,6 +325,41 @@ def template StoreMemAccExecute {{ { Addr EA; Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreCondMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; uint64_t write_result = 0; %(fp_enable_check)s; @@ -361,6 +396,40 @@ def template StoreExecute {{ { Addr EA; Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, NULL); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreCondExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; uint64_t write_result = 0; %(fp_enable_check)s; @@ -449,7 +518,7 @@ def template StoreCondCompleteAcc {{ %(fp_enable_check)s; %(op_dest_decl)s; - uint64_t write_result = pkt->req->getScResult(); + uint64_t write_result = pkt->req->getExtraData(); if (fault == NoFault) { %(postacc_code)s; diff --git a/src/arch/mips/isa/formats/util.isa b/src/arch/mips/isa/formats/util.isa index ec524113d..884e6f727 100644 --- a/src/arch/mips/isa/formats/util.isa +++ b/src/arch/mips/isa/formats/util.isa @@ -66,10 +66,8 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, # select templates - # define aliases... most StoreCond templates are the same as the - # corresponding Store templates (only CompleteAcc is different). - StoreCondMemAccExecute = StoreMemAccExecute - StoreCondExecute = StoreExecute + # The InitiateAcc template is the same for StoreCond templates as the + # corresponding Store template.. StoreCondInitiateAcc = StoreInitiateAcc memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') diff --git a/src/arch/mips/linux/linux.hh b/src/arch/mips/linux/linux.hh index f85935bb9..a20221e9b 100644 --- a/src/arch/mips/linux/linux.hh +++ b/src/arch/mips/linux/linux.hh @@ -91,15 +91,15 @@ class MipsLinux : public Linux //@{ /// ioctl() command codes. - static const unsigned TIOCGETP = 0x7408; - static const unsigned TIOCSETP = 0x7409; - static const unsigned TIOCSETN = 0x740a; - static const unsigned TIOCSETC = 0x7411; - static const unsigned TIOCGETC = 0x7412; - static const unsigned FIONREAD = 0x467f; - static const unsigned TIOCISATTY = 0x5480; - static const unsigned TIOCGETS = 0x7413; - static const unsigned TIOCGETA = 0x7417; + static const unsigned TIOCGETP_ = 0x7408; + static const unsigned TIOCSETP_ = 0x7409; + static const unsigned TIOCSETN_ = 0x740a; + static const unsigned TIOCSETC_ = 0x7411; + static const unsigned TIOCGETC_ = 0x7412; + static const unsigned FIONREAD_ = 0x467f; + static const unsigned TIOCISATTY_ = 0x5480; + static const unsigned TIOCGETS_ = 0x7413; + static const unsigned TIOCGETA_ = 0x7417; //@} /// For table(). diff --git a/src/arch/mips/predecoder.hh b/src/arch/mips/predecoder.hh new file mode 100644 index 000000000..a25cce8a7 --- /dev/null +++ b/src/arch/mips/predecoder.hh @@ -0,0 +1,100 @@ +/* + * 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: Gabe Black + */ + +#ifndef __ARCH_MIPS_PREDECODER_HH__ +#define __ARCH_MIPS_PREDECODER_HH__ + +#include "arch/mips/types.hh" +#include "base/misc.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace MipsISA +{ + class Predecoder + { + protected: + ThreadContext * tc; + //The extended machine instruction being generated + ExtMachInst emi; + + public: + Predecoder(ThreadContext * _tc) : tc(_tc) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process() + { + } + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr currPC, Addr off, MachInst inst) + { + assert(off == 0); + emi = inst; + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(0, 0, machInst); + } + + bool needMoreBytes() + { + return true; + } + + bool extMachInstReady() + { + return true; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + return emi; + } + }; +}; + +#endif // __ARCH_MIPS_PREDECODER_HH__ diff --git a/src/arch/mips/regfile/misc_regfile.hh b/src/arch/mips/regfile/misc_regfile.hh index 368925e00..53ee09512 100644 --- a/src/arch/mips/regfile/misc_regfile.hh +++ b/src/arch/mips/regfile/misc_regfile.hh @@ -215,22 +215,22 @@ namespace MipsISA void copyMiscRegs(ThreadContext *tc); - MiscReg readReg(int misc_reg) + MiscReg readRegNoEffect(int misc_reg) { return miscRegFile[misc_reg]; } - MiscReg readRegWithEffect(int misc_reg, ThreadContext *tc) + MiscReg readReg(int misc_reg, ThreadContext *tc) { return miscRegFile[misc_reg]; } - void setReg(int misc_reg, const MiscReg &val) + void setRegNoEffect(int misc_reg, const MiscReg &val) { miscRegFile[misc_reg] = val; } - void setRegWithEffect(int misc_reg, const MiscReg &val, + void setReg(int misc_reg, const MiscReg &val, ThreadContext *tc) { miscRegFile[misc_reg] = val; diff --git a/src/arch/mips/regfile/regfile.hh b/src/arch/mips/regfile/regfile.hh index 7b57b31f5..387fbd5c8 100644 --- a/src/arch/mips/regfile/regfile.hh +++ b/src/arch/mips/regfile/regfile.hh @@ -57,25 +57,25 @@ namespace MipsISA bzero(&miscRegFile, sizeof(miscRegFile)); } - MiscReg readMiscReg(int miscReg) + MiscReg readMiscRegNoEffect(int miscReg) { - return miscRegFile.readReg(miscReg); + return miscRegFile.readRegNoEffect(miscReg); } - MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc) + MiscReg readMiscReg(int miscReg, ThreadContext *tc) { - return miscRegFile.readRegWithEffect(miscReg, tc); + return miscRegFile.readReg(miscReg, tc); } - void setMiscReg(int miscReg, const MiscReg &val) + void setMiscRegNoEffect(int miscReg, const MiscReg &val) { - miscRegFile.setReg(miscReg, val); + miscRegFile.setRegNoEffect(miscReg, val); } - void setMiscRegWithEffect(int miscReg, const MiscReg &val, + void setMiscReg(int miscReg, const MiscReg &val, ThreadContext * tc) { - miscRegFile.setRegWithEffect(miscReg, val, tc); + miscRegFile.setReg(miscReg, val, tc); } FloatRegVal readFloatReg(int floatReg) diff --git a/src/arch/mips/types.hh b/src/arch/mips/types.hh index d4fa296fd..fc45ea253 100644 --- a/src/arch/mips/types.hh +++ b/src/arch/mips/types.hh @@ -40,6 +40,8 @@ namespace MipsISA typedef uint8_t RegIndex; typedef uint32_t IntReg; + typedef uint64_t LargestRead; + // floating point register file entry type typedef uint32_t FloatReg32; diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh index 56689ba4d..12db1de57 100644 --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2003-2005 The Regents of The University of Michigan + * Copyright (c) 2007 MIPS Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,6 +28,7 @@ * * Authors: Nathan Binkert * Steve Reinhardt + * Korey Sewell */ #ifndef __ARCH_MIPS_UTILITY_HH__ @@ -86,17 +88,9 @@ namespace MipsISA { return 0; } - static inline ExtMachInst - makeExtMI(MachInst inst, ThreadContext * xc) { -#if FULL_SYSTEM - ExtMachInst ext_inst = inst; - if (xc->readPC() && 0x1) - return ext_inst|=(static_cast<ExtMachInst>(xc->readPC() & 0x1) << 32); - else - return ext_inst; -#else - return ExtMachInst(inst); -#endif + inline void startupCPU(ThreadContext *tc, int cpuId) + { + tc->activate(0); } }; diff --git a/src/arch/sparc/SConscript b/src/arch/sparc/SConscript index 555bfba3d..e342c79cf 100644 --- a/src/arch/sparc/SConscript +++ b/src/arch/sparc/SConscript @@ -29,65 +29,38 @@ # Authors: Gabe Black # Steve Reinhardt -import os -import sys -from os.path import isdir +Import('*') -# Import build environment variable from SConstruct. -Import('env') +if env['TARGET_ISA'] == 'sparc': + Source('asi.cc') + Source('faults.cc') + Source('floatregfile.cc') + Source('intregfile.cc') + Source('miscregfile.cc') + Source('regfile.cc') + Source('remote_gdb.cc') -################################################### -# -# Define needed sources. -# -################################################### - -# Base sources used by all configurations. -base_sources = Split(''' - asi.cc - faults.cc - floatregfile.cc - intregfile.cc - miscregfile.cc - regfile.cc - remote_gdb.cc - ''') - -# Full-system sources -full_system_sources = Split(''' - arguments.cc - pagetable.cc - stacktrace.cc - system.cc - tlb.cc - ua2005.cc - vtophys.cc - ''') - -# Syscall emulation (non-full-system) sources -syscall_emulation_sources = Split(''' - linux/linux.cc - linux/process.cc - process.cc - solaris/process.cc - solaris/solaris.cc - ''') - -sources = base_sources - -if env['FULL_SYSTEM']: - sources += full_system_sources -else: - sources += syscall_emulation_sources + if env['FULL_SYSTEM']: + Source('arguments.cc') + Source('pagetable.cc') + Source('stacktrace.cc') + Source('system.cc') + Source('tlb.cc') + Source('ua2005.cc') + Source('vtophys.cc') + else: + Source('process.cc') -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] + Source('linux/linux.cc') + Source('linux/process.cc') + Source('linux/syscalls.cc') -# Add in files generated by the ISA description. -isa_desc_files = env.ISADesc('isa/main.isa') -# Only non-header files need to be compiled. -isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')] -sources += isa_desc_sources + Source('solaris/process.cc') + Source('solaris/solaris.cc') -Return('sources') + # Add in files generated by the ISA description. + isa_desc_files = env.ISADesc('isa/main.isa') + # Only non-header files need to be compiled. + for f in isa_desc_files: + if not f.path.endswith('.hh'): + Source(f) diff --git a/src/arch/sparc/SConsopts b/src/arch/sparc/SConsopts new file mode 100644 index 000000000..c35606281 --- /dev/null +++ b/src/arch/sparc/SConsopts @@ -0,0 +1,33 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +all_isa_list.append('sparc') diff --git a/src/arch/sparc/arguments.hh b/src/arch/sparc/arguments.hh index 8f925dd25..5596f7408 100644 --- a/src/arch/sparc/arguments.hh +++ b/src/arch/sparc/arguments.hh @@ -33,9 +33,9 @@ #include <assert.h> -#include "arch/sparc/vtophys.hh" #include "base/refcnt.hh" #include "sim/host.hh" +#include "mem/vport.hh" class ThreadContext; diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc index 3d553955f..254635bff 100644 --- a/src/arch/sparc/asi.cc +++ b/src/arch/sparc/asi.cc @@ -247,7 +247,8 @@ namespace SparcISA bool AsiIsCmt(ASI asi) { return - (asi == ASI_CMT_PER_STRAND); + (asi == ASI_CMT_PER_STRAND) || + (asi == ASI_CMT_SHARED); } bool AsiIsQueue(ASI asi) @@ -294,7 +295,9 @@ namespace SparcISA bool AsiIsReg(ASI asi) { - return AsiIsMmu(asi) || AsiIsScratchPad(asi) | AsiIsSparcError(asi); + return AsiIsMmu(asi) || AsiIsScratchPad(asi) || + AsiIsSparcError(asi) || AsiIsInterrupt(asi) + || AsiIsCmt(asi); } bool AsiIsSparcError(ASI asi) diff --git a/src/arch/sparc/asi.hh b/src/arch/sparc/asi.hh index 166c3867e..eba2d518f 100644 --- a/src/arch/sparc/asi.hh +++ b/src/arch/sparc/asi.hh @@ -115,6 +115,7 @@ namespace SparcISA ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1 = 0x3E, ASI_IMMU_CTXT_NONZERO_CONFIG = 0x3F, ASI_STREAM_MA = 0x40, + ASI_CMT_SHARED = 0x41, //0x41 implementation dependent ASI_SPARC_BIST_CONTROL = 0x42, ASI_INST_MASK_REG = 0x42, diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index a6f4343ae..88c086090 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -208,6 +208,10 @@ template<> SparcFaultBase::FaultVals {"trap_level_zero", 0x05F, 202, {H, H, SH}}; template<> SparcFaultBase::FaultVals + SparcFault<InterruptVector>::vals = + {"interrupt_vector", 0x060, 2630, {H, H, H}}; + +template<> SparcFaultBase::FaultVals SparcFault<PAWatchpoint>::vals = {"PA_watchpoint", 0x061, 1209, {H, H, H}}; @@ -263,12 +267,6 @@ template<> SparcFaultBase::FaultVals SparcFault<TrapInstruction>::vals = {"trap_instruction", 0x100, 1602, {P, P, H}}; -#if !FULL_SYSTEM -template<> SparcFaultBase::FaultVals - SparcFault<PageTableFault>::vals = - {"page_table_fault", 0x0000, 0, {SH, SH, SH}}; -#endif - /** * This causes the thread context to enter RED state. This causes the side * effects which go with entering RED state because of a trap. @@ -278,17 +276,17 @@ void enterREDState(ThreadContext *tc) { //@todo Disable the mmu? //@todo Disable watchpoints? - MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); + MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); //HPSTATE.red = 1 HPSTATE |= (1 << 5); //HPSTATE.hpriv = 1 HPSTATE |= (1 << 2); - tc->setMiscRegWithEffect(MISCREG_HPSTATE, HPSTATE); + tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); //PSTATE.priv is set to 1 here. The manual says it should be 0, but //Legion sets it to 1. - MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); + MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); PSTATE |= (1 << 2); - tc->setMiscRegWithEffect(MISCREG_PSTATE, PSTATE); + tc->setMiscReg(MISCREG_PSTATE, PSTATE); } /** @@ -298,17 +296,17 @@ void enterREDState(ThreadContext *tc) void doREDFault(ThreadContext *tc, TrapType tt) { - MiscReg TL = tc->readMiscReg(MISCREG_TL); - MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); - MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); - MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); - //MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL); + MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE); + MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); + MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); + //MiscReg CCR = tc->readMiscRegNoEffect(MISCREG_CCR); MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); - MiscReg ASI = tc->readMiscReg(MISCREG_ASI); - MiscReg CWP = tc->readMiscReg(MISCREG_CWP); - //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); - MiscReg CANSAVE = tc->readMiscReg(NumIntArchRegs + 3); - MiscReg GL = tc->readMiscReg(MISCREG_GL); + MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI); + MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP); + //MiscReg CANSAVE = tc->readMiscRegNoEffect(MISCREG_CANSAVE); + MiscReg CANSAVE = tc->readMiscRegNoEffect(NumIntArchRegs + 3); + MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL); MiscReg PC = tc->readPC(); MiscReg NPC = tc->readNextPC(); @@ -331,25 +329,25 @@ void doREDFault(ThreadContext *tc, TrapType tt) replaceBits(TSTATE, 4, 0, CWP); //Write back TSTATE - tc->setMiscReg(MISCREG_TSTATE, TSTATE); + tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE); //set TPC to PC - tc->setMiscReg(MISCREG_TPC, PC); + tc->setMiscRegNoEffect(MISCREG_TPC, PC); //set TNPC to NPC - tc->setMiscReg(MISCREG_TNPC, NPC); + tc->setMiscRegNoEffect(MISCREG_TNPC, NPC); //set HTSTATE.hpstate to hpstate - tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); + tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE); //TT = trap type; - tc->setMiscReg(MISCREG_TT, tt); + tc->setMiscRegNoEffect(MISCREG_TT, tt); //Update GL - tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); + tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL)); PSTATE = mbits(PSTATE, 2, 2); // just save the priv bit PSTATE |= (1 << 4); //set PSTATE.pef to 1 - tc->setMiscReg(MISCREG_PSTATE, PSTATE); + tc->setMiscRegNoEffect(MISCREG_PSTATE, PSTATE); //set HPSTATE.red to 1 HPSTATE |= (1 << 5); @@ -359,7 +357,7 @@ void doREDFault(ThreadContext *tc, TrapType tt) HPSTATE &= ~(1 << 10); //set HPSTATE.tlz to 0 HPSTATE &= ~(1 << 0); - tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); + tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE); bool changedCWP = true; if(tt == 0x24) @@ -374,7 +372,7 @@ void doREDFault(ThreadContext *tc, TrapType tt) if(changedCWP) { CWP = (CWP + NWindows) % NWindows; - tc->setMiscRegWithEffect(MISCREG_CWP, CWP); + tc->setMiscReg(MISCREG_CWP, CWP); } } @@ -385,17 +383,17 @@ void doREDFault(ThreadContext *tc, TrapType tt) void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) { - MiscReg TL = tc->readMiscReg(MISCREG_TL); - MiscReg TSTATE = tc->readMiscReg(MISCREG_TSTATE); - MiscReg PSTATE = tc->readMiscReg(MISCREG_PSTATE); - MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); - //MiscReg CCR = tc->readMiscReg(MISCREG_CCR); + MiscReg TL = tc->readMiscRegNoEffect(MISCREG_TL); + MiscReg TSTATE = tc->readMiscRegNoEffect(MISCREG_TSTATE); + MiscReg PSTATE = tc->readMiscRegNoEffect(MISCREG_PSTATE); + MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); + //MiscReg CCR = tc->readMiscRegNoEffect(MISCREG_CCR); MiscReg CCR = tc->readIntReg(NumIntArchRegs + 2); - MiscReg ASI = tc->readMiscReg(MISCREG_ASI); - MiscReg CWP = tc->readMiscReg(MISCREG_CWP); - //MiscReg CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + MiscReg ASI = tc->readMiscRegNoEffect(MISCREG_ASI); + MiscReg CWP = tc->readMiscRegNoEffect(MISCREG_CWP); + //MiscReg CANSAVE = tc->readMiscRegNoEffect(MISCREG_CANSAVE); MiscReg CANSAVE = tc->readIntReg(NumIntArchRegs + 3); - MiscReg GL = tc->readMiscReg(MISCREG_GL); + MiscReg GL = tc->readMiscRegNoEffect(MISCREG_GL); MiscReg PC = tc->readPC(); MiscReg NPC = tc->readNextPC(); @@ -406,7 +404,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) //Increment the trap level TL++; - tc->setMiscReg(MISCREG_TL, TL); + tc->setMiscRegNoEffect(MISCREG_TL, TL); //Save off state @@ -422,24 +420,24 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) replaceBits(TSTATE, 4, 0, CWP); //Write back TSTATE - tc->setMiscReg(MISCREG_TSTATE, TSTATE); + tc->setMiscRegNoEffect(MISCREG_TSTATE, TSTATE); //set TPC to PC - tc->setMiscReg(MISCREG_TPC, PC); + tc->setMiscRegNoEffect(MISCREG_TPC, PC); //set TNPC to NPC - tc->setMiscReg(MISCREG_TNPC, NPC); + tc->setMiscRegNoEffect(MISCREG_TNPC, NPC); //set HTSTATE.hpstate to hpstate - tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); + tc->setMiscRegNoEffect(MISCREG_HTSTATE, HPSTATE); //TT = trap type; - tc->setMiscReg(MISCREG_TT, tt); + tc->setMiscRegNoEffect(MISCREG_TT, tt); //Update the global register level if (!gotoHpriv) - tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxPGL)); + tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxPGL)); else - tc->setMiscRegWithEffect(MISCREG_GL, min<int>(GL+1, MaxGL)); + tc->setMiscReg(MISCREG_GL, min<int>(GL+1, MaxGL)); //PSTATE.mm is unchanged PSTATE |= (1 << 4); //PSTATE.pef = whether or not an fpu is present @@ -456,12 +454,12 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) HPSTATE |= (1 << 2); //HPSTATE.hpriv = 1 HPSTATE &= ~(1 << 10); //HPSTATE.ibe = 0 //HPSTATE.tlz is unchanged - tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); + tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE); } else { // we are going to priv PSTATE |= (1 << 2); //PSTATE.priv = 1 replaceBits(PSTATE, 9, 9, PSTATE >> 8); //PSTATE.cle = PSTATE.tle } - tc->setMiscReg(MISCREG_PSTATE, PSTATE); + tc->setMiscRegNoEffect(MISCREG_PSTATE, PSTATE); bool changedCWP = true; @@ -477,7 +475,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) if (changedCWP) { CWP = (CWP + NWindows) % NWindows; - tc->setMiscRegWithEffect(MISCREG_CWP, CWP); + tc->setMiscReg(MISCREG_CWP, CWP); } } @@ -491,14 +489,14 @@ void getREDVector(MiscReg TT, Addr & PC, Addr & NPC) void getHyperVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT) { - Addr HTBA = tc->readMiscReg(MISCREG_HTBA); + Addr HTBA = tc->readMiscRegNoEffect(MISCREG_HTBA); PC = (HTBA & ~mask(14)) | ((TT << 5) & mask(14)); NPC = PC + sizeof(MachInst); } void getPrivVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT, MiscReg TL) { - Addr TBA = tc->readMiscReg(MISCREG_TBA); + Addr TBA = tc->readMiscRegNoEffect(MISCREG_TBA); PC = (TBA & ~mask(15)) | (TL > 1 ? (1 << 14) : 0) | ((TT << 5) & mask(14)); @@ -515,10 +513,10 @@ void SparcFaultBase::invoke(ThreadContext * tc) //We can refer to this to see what the trap level -was-, but something //in the middle could change it in the regfile out from under us. - MiscReg tl = tc->readMiscReg(MISCREG_TL); - MiscReg tt = tc->readMiscReg(MISCREG_TT); - MiscReg pstate = tc->readMiscReg(MISCREG_PSTATE); - MiscReg hpstate = tc->readMiscReg(MISCREG_HPSTATE); + MiscReg tl = tc->readMiscRegNoEffect(MISCREG_TL); + MiscReg tt = tc->readMiscRegNoEffect(MISCREG_TT); + MiscReg pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); + MiscReg hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); Addr PC, NPC; @@ -567,15 +565,15 @@ void PowerOnReset::invoke(ThreadContext * tc) //on reset Trap which sets the processor into the following state. //Bits that aren't set aren't defined on startup. - tc->setMiscReg(MISCREG_TL, MaxTL); - tc->setMiscReg(MISCREG_TT, trapType()); - tc->setMiscRegWithEffect(MISCREG_GL, MaxGL); + tc->setMiscRegNoEffect(MISCREG_TL, MaxTL); + tc->setMiscRegNoEffect(MISCREG_TT, trapType()); + tc->setMiscReg(MISCREG_GL, MaxGL); //Turn on pef and priv, set everything else to 0 - tc->setMiscReg(MISCREG_PSTATE, (1 << 4) | (1 << 2)); + tc->setMiscRegNoEffect(MISCREG_PSTATE, (1 << 4) | (1 << 2)); //Turn on red and hpriv, set everything else to 0 - MiscReg HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); + MiscReg HPSTATE = tc->readMiscRegNoEffect(MISCREG_HPSTATE); //HPSTATE.red = 1 HPSTATE |= (1 << 5); //HPSTATE.hpriv = 1 @@ -584,10 +582,10 @@ void PowerOnReset::invoke(ThreadContext * tc) HPSTATE &= ~(1 << 10); //HPSTATE.tlz = 0 HPSTATE &= ~(1 << 0); - tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); + tc->setMiscRegNoEffect(MISCREG_HPSTATE, HPSTATE); //The tick register is unreadable by nonprivileged software - tc->setMiscReg(MISCREG_TICK, 1ULL << 63); + tc->setMiscRegNoEffect(MISCREG_TICK, 1ULL << 63); //Enter RED state. We do this last so that the actual state preserved in //the trap stack is the state from before this fault. @@ -605,7 +603,7 @@ void PowerOnReset::invoke(ThreadContext * tc) // Clear all the soft interrupt bits softint = 0; // disable timer compare interrupts, reset tick_cmpr - tc->setMiscReg(MISCREG_ + tc->setMiscRegNoEffect(MISCREG_ tick_cmprFields.int_dis = 1; tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing stickFields.npt = 1; //The TICK register is unreadable by by !priv @@ -656,26 +654,24 @@ void FillNNormal::invoke(ThreadContext *tc) tc->setNextNPC(fillStart + 2*sizeof(MachInst)); } -void PageTableFault::invoke(ThreadContext *tc) +void TrapInstruction::invoke(ThreadContext *tc) { + //In SE, this mechanism is how the process requests a service from the + //operating system. We'll get the process object from the thread context + //and let it service the request. + Process *p = tc->getProcessPtr(); - // We've accessed the next page of the stack, so extend the stack - // to cover it. - if(vaddr < p->stack_min && vaddr >= p->stack_min - PageBytes) - { - p->stack_min -= PageBytes; - if(p->stack_base - p->stack_min > 8*1024*1024) - fatal("Over max stack size for one thread\n"); - p->pTable->allocate(p->stack_min, PageBytes); - warn("Increasing stack size by one page."); - } - // Otherwise, we have an unexpected page fault. Report that fact, - // and what address was accessed to cause the fault. - else - { - panic("Page table fault when accessing virtual address %#x\n", vaddr); - } + SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); + assert(lp); + + lp->handleTrap(_n, tc); + + //We need to explicitly advance the pc, since that's not done for us + //on a faulting instruction + tc->setPC(tc->readNextPC()); + tc->setNextPC(tc->readNextNPC()); + tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst)); } #endif diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh index 3c0d9674f..10ef89279 100644 --- a/src/arch/sparc/faults.hh +++ b/src/arch/sparc/faults.hh @@ -193,6 +193,8 @@ class HstickMatch : public SparcFault<HstickMatch> {}; class TrapLevelZero : public SparcFault<TrapLevelZero> {}; +class InterruptVector : public SparcFault<InterruptVector> {}; + class PAWatchpoint : public SparcFault<PAWatchpoint> {}; class VAWatchpoint : public SparcFault<VAWatchpoint> {}; @@ -246,26 +248,13 @@ class FillNOther : public EnumeratedFault<FillNOther> class TrapInstruction : public EnumeratedFault<TrapInstruction> { - public: TrapInstruction(uint32_t n) : EnumeratedFault<TrapInstruction>(n) {;} -}; - + //In SE, trap instructions are requesting services from the OS. #if !FULL_SYSTEM -class PageTableFault : public SparcFault<PageTableFault> -{ - private: - Addr vaddr; - public: - PageTableFault(Addr va) : vaddr(va) {} void invoke(ThreadContext * tc); -}; - -static inline Fault genPageTableFault(Addr va) -{ - return new PageTableFault(va); -} #endif +}; static inline Fault genMachineCheckFault() { diff --git a/src/arch/sparc/handlers.hh b/src/arch/sparc/handlers.hh new file mode 100644 index 000000000..ce5b69427 --- /dev/null +++ b/src/arch/sparc/handlers.hh @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2003-2004 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_HANDLERS_HH__ +#define __ARCH_SPARC_HANDLERS_HH__ + +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/types.hh" +#include "sim/byteswap.hh" + +namespace SparcISA { + +//We only use 19 instructions for the trap handlers, but there would be +//space for 32 in a real SPARC trap table. +const int numFillInsts = 32; +const int numSpillInsts = 32; + +const MachInst fillHandler64[numFillInsts] = +{ + htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0xe0dba7ff), //ldxa [%sp + BIAS + (0*8)] %asi, %l0 + htog(0xe2dba807), //ldxa [%sp + BIAS + (1*8)] %asi, %l1 + htog(0xe4dba80f), //ldxa [%sp + BIAS + (2*8)] %asi, %l2 + htog(0xe6dba817), //ldxa [%sp + BIAS + (3*8)] %asi, %l3 + htog(0xe8dba81f), //ldxa [%sp + BIAS + (4*8)] %asi, %l4 + htog(0xeadba827), //ldxa [%sp + BIAS + (5*8)] %asi, %l5 + htog(0xecdba82f), //ldxa [%sp + BIAS + (6*8)] %asi, %l6 + htog(0xeedba837), //ldxa [%sp + BIAS + (7*8)] %asi, %l7 + htog(0xf0dba83f), //ldxa [%sp + BIAS + (8*8)] %asi, %i0 + htog(0xf2dba847), //ldxa [%sp + BIAS + (9*8)] %asi, %i1 + htog(0xf4dba84f), //ldxa [%sp + BIAS + (10*8)] %asi, %i2 + htog(0xf6dba857), //ldxa [%sp + BIAS + (11*8)] %asi, %i3 + htog(0xf8dba85f), //ldxa [%sp + BIAS + (12*8)] %asi, %i4 + htog(0xfadba867), //ldxa [%sp + BIAS + (13*8)] %asi, %i5 + htog(0xfcdba86f), //ldxa [%sp + BIAS + (14*8)] %asi, %i6 + htog(0xfedba877), //ldxa [%sp + BIAS + (15*8)] %asi, %i7 + htog(0x83880000), //restored + htog(0x83F00000), //retry + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000) //illtrap +}; + +const MachInst fillHandler32[numFillInsts] = +{ + htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0xe083a000), //lduwa [%sp + (0*4)] %asi, %l0 + htog(0xe283a004), //lduwa [%sp + (1*4)] %asi, %l1 + htog(0xe483a008), //lduwa [%sp + (2*4)] %asi, %l2 + htog(0xe683a00c), //lduwa [%sp + (3*4)] %asi, %l3 + htog(0xe883a010), //lduwa [%sp + (4*4)] %asi, %l4 + htog(0xea83a014), //lduwa [%sp + (5*4)] %asi, %l5 + htog(0xec83a018), //lduwa [%sp + (6*4)] %asi, %l6 + htog(0xee83a01c), //lduwa [%sp + (7*4)] %asi, %l7 + htog(0xf083a020), //lduwa [%sp + (8*4)] %asi, %i0 + htog(0xf283a024), //lduwa [%sp + (9*4)] %asi, %i1 + htog(0xf483a028), //lduwa [%sp + (10*4)] %asi, %i2 + htog(0xf683a02c), //lduwa [%sp + (11*4)] %asi, %i3 + htog(0xf883a030), //lduwa [%sp + (12*4)] %asi, %i4 + htog(0xfa83a034), //lduwa [%sp + (13*4)] %asi, %i5 + htog(0xfc83a038), //lduwa [%sp + (14*4)] %asi, %i6 + htog(0xfe83a03c), //lduwa [%sp + (15*4)] %asi, %i7 + htog(0x83880000), //restored + htog(0x83F00000), //retry + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000) //illtrap +}; + +const MachInst spillHandler64[numSpillInsts] = +{ + htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0xe0f3a7ff), //stxa %l0, [%sp + BIAS + (0*8)] %asi + htog(0xe2f3a807), //stxa %l1, [%sp + BIAS + (1*8)] %asi + htog(0xe4f3a80f), //stxa %l2, [%sp + BIAS + (2*8)] %asi + htog(0xe6f3a817), //stxa %l3, [%sp + BIAS + (3*8)] %asi + htog(0xe8f3a81f), //stxa %l4, [%sp + BIAS + (4*8)] %asi + htog(0xeaf3a827), //stxa %l5, [%sp + BIAS + (5*8)] %asi + htog(0xecf3a82f), //stxa %l6, [%sp + BIAS + (6*8)] %asi + htog(0xeef3a837), //stxa %l7, [%sp + BIAS + (7*8)] %asi + htog(0xf0f3a83f), //stxa %i0, [%sp + BIAS + (8*8)] %asi + htog(0xf2f3a847), //stxa %i1, [%sp + BIAS + (9*8)] %asi + htog(0xf4f3a84f), //stxa %i2, [%sp + BIAS + (10*8)] %asi + htog(0xf6f3a857), //stxa %i3, [%sp + BIAS + (11*8)] %asi + htog(0xf8f3a85f), //stxa %i4, [%sp + BIAS + (12*8)] %asi + htog(0xfaf3a867), //stxa %i5, [%sp + BIAS + (13*8)] %asi + htog(0xfcf3a86f), //stxa %i6, [%sp + BIAS + (14*8)] %asi + htog(0xfef3a877), //stxa %i7, [%sp + BIAS + (15*8)] %asi + htog(0x81880000), //saved + htog(0x83F00000), //retry + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000) //illtrap +}; + +const MachInst spillHandler32[numSpillInsts] = +{ + htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0xe0a3a000), //stwa %l0, [%sp + (0*4)] %asi + htog(0xe2a3a004), //stwa %l1, [%sp + (1*4)] %asi + htog(0xe4a3a008), //stwa %l2, [%sp + (2*4)] %asi + htog(0xe6a3a00c), //stwa %l3, [%sp + (3*4)] %asi + htog(0xe8a3a010), //stwa %l4, [%sp + (4*4)] %asi + htog(0xeaa3a014), //stwa %l5, [%sp + (5*4)] %asi + htog(0xeca3a018), //stwa %l6, [%sp + (6*4)] %asi + htog(0xeea3a01c), //stwa %l7, [%sp + (7*4)] %asi + htog(0xf0a3a020), //stwa %i0, [%sp + (8*4)] %asi + htog(0xf2a3a024), //stwa %i1, [%sp + (9*4)] %asi + htog(0xf4a3a028), //stwa %i2, [%sp + (10*4)] %asi + htog(0xf6a3a02c), //stwa %i3, [%sp + (11*4)] %asi + htog(0xf8a3a030), //stwa %i4, [%sp + (12*4)] %asi + htog(0xfaa3a034), //stwa %i5, [%sp + (13*4)] %asi + htog(0xfca3a038), //stwa %i6, [%sp + (14*4)] %asi + htog(0xfea3a03c), //stwa %i7, [%sp + (15*4)] %asi + htog(0x81880000), //saved + htog(0x83F00000), //retry + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000) //illtrap +}; + +} // namespace SparcISA +#endif // __ARCH_SPARC_HANDLERS_HH__ diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh index dc3b235fe..4ad3385fb 100644 --- a/src/arch/sparc/interrupts.hh +++ b/src/arch/sparc/interrupts.hh @@ -24,82 +24,86 @@ * 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 + * Lisa Hsu */ #ifndef __ARCH_SPARC_INTERRUPT_HH__ #define __ARCH_SPARC_INTERRUPT_HH__ #include "arch/sparc/faults.hh" +#include "arch/sparc/isa_traits.hh" #include "cpu/thread_context.hh" namespace SparcISA { -enum interrupts_t { - trap_level_zero, - hstick_match, - interrupt_vector, - cpu_mondo, - dev_mondo, - resumable_error, - soft_interrupt, - num_interrupt_types -}; - class Interrupts { private: - bool interrupts[num_interrupt_types]; - int numPosted; + uint64_t interrupts[NumInterruptTypes]; + uint64_t intStatus; public: Interrupts() { - for (int i = 0; i < num_interrupt_types; ++i) { - interrupts[i] = false; - } - numPosted = 0; + clear_all(); } - void post(int int_type) + int InterruptLevel(uint64_t softint) { - if (int_type < 0 || int_type >= num_interrupt_types) - panic("posting unknown interrupt!\n"); - if (interrupts[int_type] == false) { - interrupts[int_type] = true; - ++numPosted; - } + if (softint & 0x10000 || softint & 0x1) + return 14; + + int level = 15; + while (level > 0 && !(1 << level & softint)) + level--; + if (1 << level & softint) + return level; + return 0; } void post(int int_num, int index) { + DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); + assert(int_num >= 0 && int_num < NumInterruptTypes); + assert(index >= 0 && index < 64); + interrupts[int_num] |= ULL(1) << index; + intStatus |= ULL(1) << int_num; } void clear(int int_num, int index) { + DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); + assert(int_num >= 0 && int_num < NumInterruptTypes); + assert(index >= 0 && index < 64); + interrupts[int_num] &= ~(ULL(1) << index); + if (!interrupts[int_num]) + intStatus &= ~(ULL(1) << int_num); } void clear_all() { - + for (int i = 0; i < NumInterruptTypes; ++i) { + interrupts[i] = 0; + } + intStatus = 0; } bool check_interrupts(ThreadContext * tc) const { - if (numPosted) - return true; - else - return false; + return intStatus; } Fault getInterrupt(ThreadContext * tc) { - int hpstate = tc->readMiscReg(MISCREG_HPSTATE); - int pstate = tc->readMiscReg(MISCREG_PSTATE); + int hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); + int pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); bool ie = pstate & PSTATE::ie; // THESE ARE IN ORDER OF PRIORITY @@ -109,84 +113,45 @@ class Interrupts // in the right order of processing if (hpstate & HPSTATE::hpriv) { if (ie) { - if (interrupts[hstick_match]) { - if (tc->readMiscReg(MISCREG_HINTP) & 1) { - interrupts[hstick_match] = false; - --numPosted; - return new HstickMatch; - } - } - if (interrupts[interrupt_vector]) { - interrupts[interrupt_vector] = false; - --numPosted; - //HAVEN'T IMPLed THIS YET - return NoFault; + if (interrupts[IT_HINTP]) { + // This will be cleaned by a HINTP write + return new HstickMatch; } - } else { - if (interrupts[hstick_match]) { - return NoFault; + if (interrupts[IT_INT_VEC]) { + // this will be cleared by an ASI read (or write) + return new InterruptVector; } - } } else { - if (interrupts[trap_level_zero]) { - if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) { - interrupts[trap_level_zero] = false; - --numPosted; + if (interrupts[IT_TRAP_LEVEL_ZERO]) { + // this is cleared by deasserting HPSTATE::tlz return new TrapLevelZero; - } } - if (interrupts[hstick_match]) { - if (tc->readMiscReg(MISCREG_HINTP) & 1) { - interrupts[hstick_match] = false; - --numPosted; - return new HstickMatch; - } + // HStick matches always happen in priv mode (ie doesn't matter) + if (interrupts[IT_HINTP]) { + return new HstickMatch; + } + if (interrupts[IT_INT_VEC]) { + // this will be cleared by an ASI read (or write) + return new InterruptVector; } if (ie) { - if (interrupts[cpu_mondo]) { - interrupts[cpu_mondo] = false; - --numPosted; + if (interrupts[IT_CPU_MONDO]) { return new CpuMondo; } - if (interrupts[dev_mondo]) { - interrupts[dev_mondo] = false; - --numPosted; + if (interrupts[IT_DEV_MONDO]) { return new DevMondo; } - if (interrupts[soft_interrupt]) { - int il = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT)); - // it seems that interrupt vectors are right in - // the middle of interrupt levels with regard to - // priority, so have to check - if ((il < 6) && - interrupts[interrupt_vector]) { - // may require more details here since there - // may be lots of interrupts embedded in an - // platform interrupt vector - interrupts[interrupt_vector] = false; - --numPosted; - //HAVEN'T IMPLed YET - return NoFault; - } else { - if (il > tc->readMiscReg(MISCREG_PIL)) { - uint64_t si = tc->readMiscReg(MISCREG_SOFTINT); - uint64_t more = si & ~(1 << (il + 1)); - if (!InterruptLevel(more)) { - interrupts[soft_interrupt] = false; - --numPosted; - } - return new InterruptLevelN(il); - } - } + if (interrupts[IT_SOFT_INT]) { + return new + InterruptLevelN(InterruptLevel(interrupts[IT_SOFT_INT])); } - if (interrupts[resumable_error]) { - interrupts[resumable_error] = false; - --numPosted; + + if (interrupts[IT_RES_ERROR]) { return new ResumableError; } - } - } + } // !hpriv && ie + } // !hpriv return NoFault; } @@ -195,16 +160,22 @@ class Interrupts } + uint64_t get_vec(int int_num) + { + assert(int_num >= 0 && int_num < NumInterruptTypes); + return interrupts[int_num]; + } + void serialize(std::ostream &os) { - SERIALIZE_ARRAY(interrupts,num_interrupt_types); - SERIALIZE_SCALAR(numPosted); + SERIALIZE_ARRAY(interrupts,NumInterruptTypes); + SERIALIZE_SCALAR(intStatus); } void unserialize(Checkpoint *cp, const std::string §ion) { - UNSERIALIZE_ARRAY(interrupts,num_interrupt_types); - UNSERIALIZE_SCALAR(numPosted); + UNSERIALIZE_ARRAY(interrupts,NumInterruptTypes); + UNSERIALIZE_SCALAR(intStatus); } }; } // namespace SPARC_ISA diff --git a/src/arch/sparc/intregfile.hh b/src/arch/sparc/intregfile.hh index 665c7aa31..83ef1d17b 100644 --- a/src/arch/sparc/intregfile.hh +++ b/src/arch/sparc/intregfile.hh @@ -82,7 +82,7 @@ namespace SparcISA IntReg * regView[NumFrames]; static const int RegGlobalOffset = 0; - static const int FrameOffset = MaxGL * RegsPerFrame; + static const int FrameOffset = (MaxGL + 1) * RegsPerFrame; int offset[NumFrames]; public: diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa index 693cc6876..bba63f407 100644 --- a/src/arch/sparc/isa/base.isa +++ b/src/arch/sparc/isa/base.isa @@ -492,8 +492,8 @@ output exec {{ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc) { Fault fault = NoFault; // dummy... this ipr access should not fault - if (xc->readMiscRegWithEffect(MISCREG_PSTATE) & PSTATE::pef && - xc->readMiscRegWithEffect(MISCREG_FPRS) & 0x4) + if (xc->readMiscReg(MISCREG_PSTATE) & PSTATE::pef && + xc->readMiscReg(MISCREG_FPRS) & 0x4) return NoFault; else return new FpDisabled; diff --git a/src/arch/sparc/isa/bitfields.isa b/src/arch/sparc/isa/bitfields.isa index e75680d2b..afa8f88a2 100644 --- a/src/arch/sparc/isa/bitfields.isa +++ b/src/arch/sparc/isa/bitfields.isa @@ -54,6 +54,7 @@ def bitfield FCN <29:25>; def bitfield I <13>; def bitfield IMM_ASI <12:5>; def bitfield IMM22 <21:0>; +def bitfield M5FUNC <15:7>; def bitfield MMASK <3:0>; def bitfield OP <31:30>; def bitfield OP2 <24:22>; diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index fb606c7cc..556bb4bca 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -185,25 +185,25 @@ decode OP default Unknown::unknown() }}, ',a'); } default: decode BPCC { - 0x0: fbpcc0(22, {{ + 0x0: fbpfcc0(19, {{ if(passesFpCondition(Fsr<11:10>, COND2)) NNPC = xc->readPC() + disp; else handle_annul }}); - 0x1: fbpcc1(22, {{ + 0x1: fbpfcc1(19, {{ if(passesFpCondition(Fsr<33:32>, COND2)) NNPC = xc->readPC() + disp; else handle_annul }}); - 0x2: fbpcc2(22, {{ + 0x2: fbpfcc2(19, {{ if(passesFpCondition(Fsr<35:34>, COND2)) NNPC = xc->readPC() + disp; else handle_annul }}); - 0x3: fbpcc3(22, {{ + 0x3: fbpfcc3(19, {{ if(passesFpCondition(Fsr<37:36>, COND2)) NNPC = xc->readPC() + disp; else @@ -426,19 +426,22 @@ decode OP default Unknown::unknown() {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}} ); 0x24: mulscc({{ - int64_t resTemp, multiplicand = Rs2_or_imm13; - int32_t multiplier = Rs1<31:0>; int32_t savedLSB = Rs1<0:>; - multiplier = multiplier<31:1> | - ((Ccr<3:3> ^ Ccr<1:1>) << 32); - if(!Y<0:>) - multiplicand = 0; - Rd = resTemp = multiplicand + multiplier; + + //Step 1 + int64_t multiplicand = Rs2_or_imm13; + //Step 2 + int32_t partialP = Rs1<31:1> | + ((Ccr<3:3> ^ Ccr<1:1>) << 31); + //Step 3 + int32_t added = Y<0:> ? multiplicand : 0; + Rd = partialP + added; + //Steps 4 & 5 Y = Y<31:1> | (savedLSB << 31);}}, - {{((multiplicand<31:0> + multiplier<31:0>)<32:0>)}}, - {{multiplicand<31:> == multiplier<31:> && multiplier<31:> != resTemp<31:>}}, - {{((multiplicand >> 1) + (multiplier >> 1) + (multiplicand & multiplier & 0x1))<63:>}}, - {{multiplicand<63:> == multiplier<63:> && multiplier<63:> != resTemp<63:>}} + {{((partialP<31:0> + added<31:0>)<32:0>)}}, + {{partialP<31:> == added<31:> && added<31:> != Rd<31:>}}, + {{((partialP >> 1) + (added >> 1) + (partialP & added & 0x1))<63:>}}, + {{partialP<63:> == added<63:> && partialP<63:> != Rd<63:>}} ); } format IntOp @@ -472,8 +475,8 @@ decode OP default Unknown::unknown() }}); //7-14 should cause an illegal instruction exception 0x0F: decode I { - 0x0: Nop::stbar({{/*stuff*/}}); - 0x1: Nop::membar({{/*stuff*/}}); + 0x0: Nop::stbar({{/*stuff*/}}, IsWriteBarrier, MemWriteOp); + 0x1: Nop::membar({{/*stuff*/}}, IsMemBarrier, MemReadOp); } 0x10: Priv::rdpcr({{Rd = Pcr;}}); 0x11: PrivCheck::rdpic({{Rd = Pic;}}, {{Pcr<0:>}}); @@ -620,10 +623,6 @@ decode OP default Unknown::unknown() }}); 0x19: Priv::wrstick_cmpr({{StickCmpr = Rs1 ^ Rs2_or_imm13;}}); 0x1A: Priv::wrstrand_sts_reg({{ - if(Pstate<2:> && !Hpstate<2:>) - StrandStsReg = StrandStsReg<63:1> | - (Rs1 ^ Rs2_or_imm13)<0:>; - else StrandStsReg = Rs1 ^ Rs2_or_imm13; }}); //0x1A is supposed to be reserved, but it writes the strand @@ -820,6 +819,58 @@ decode OP default Unknown::unknown() } 0x35: decode OPF{ format FpBasic{ + 0x01: fmovs_fcc0({{ + if(passesFpCondition(Fsr<11:10>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x02: fmovd_fcc0({{ + if(passesFpCondition(Fsr<11:10>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x03: FpUnimpl::fmovq_fcc0(); + 0x25: fmovrsz({{ + if(Rs1 == 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x26: fmovrdz({{ + if(Rs1 == 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x27: FpUnimpl::fmovrqz(); + 0x41: fmovs_fcc1({{ + if(passesFpCondition(Fsr<33:32>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x42: fmovd_fcc1({{ + if(passesFpCondition(Fsr<33:32>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x43: FpUnimpl::fmovq_fcc1(); + 0x45: fmovrslez({{ + if(Rs1 <= 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x46: fmovrdlez({{ + if(Rs1 <= 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x47: FpUnimpl::fmovrqlez(); 0x51: fcmps({{ uint8_t fcc; if(isnan(Frs1s) || isnan(Frs2s)) @@ -878,6 +929,110 @@ decode OP default Unknown::unknown() Fsr = insertBits(Fsr, firstbit +1, firstbit, fcc); }}); 0x57: FpUnimpl::fcmpeq(); + 0x65: fmovrslz({{ + if(Rs1 < 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x66: fmovrdlz({{ + if(Rs1 < 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x67: FpUnimpl::fmovrqlz(); + 0x81: fmovs_fcc2({{ + if(passesFpCondition(Fsr<35:34>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x82: fmovd_fcc2({{ + if(passesFpCondition(Fsr<35:34>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x83: FpUnimpl::fmovq_fcc2(); + 0xA5: fmovrsnz({{ + if(Rs1 != 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0xA6: fmovrdnz({{ + if(Rs1 != 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0xA7: FpUnimpl::fmovrqnz(); + 0xC1: fmovs_fcc3({{ + if(passesFpCondition(Fsr<37:36>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0xC2: fmovd_fcc3({{ + if(passesFpCondition(Fsr<37:36>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0xC3: FpUnimpl::fmovq_fcc3(); + 0xC5: fmovrsgz({{ + if(Rs1 > 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0xC6: fmovrdgz({{ + if(Rs1 > 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0xC7: FpUnimpl::fmovrqgz(); + 0xE5: fmovrsgez({{ + if(Rs1 >= 0) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0xE6: fmovrdgez({{ + if(Rs1 >= 0) + Frd = Frs2; + else + Frd = Frd; + }}); + 0xE7: FpUnimpl::fmovrqgez(); + 0x101: fmovs_icc({{ + if(passesCondition(Ccr<3:0>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x102: fmovd_icc({{ + if(passesCondition(Ccr<3:0>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x103: FpUnimpl::fmovq_icc(); + 0x181: fmovs_xcc({{ + if(passesCondition(Ccr<7:4>, COND4)) + Frds = Frs2s; + else + Frds = Frds; + }}); + 0x182: fmovd_xcc({{ + if(passesCondition(Ccr<7:4>, COND4)) + Frd = Frs2; + else + Frd = Frd; + }}); + 0x183: FpUnimpl::fmovq_xcc(); default: FailUnimpl::fpop2(); } } @@ -1009,7 +1164,25 @@ decode OP default Unknown::unknown() 0x80: Trap::shutdown({{fault = new IllegalInstruction;}}); 0x81: FailUnimpl::siam(); } - 0x37: Trap::impdep2({{fault = new IllegalInstruction;}}); + // M5 special opcodes use the reserved IMPDEP2A opcode space + 0x37: decode M5FUNC { +#if FULL_SYSTEM + format BasicOperate { + // we have 7 bits of space here to play with... + 0x21: m5exit({{PseudoInst::m5exit(xc->tcBase(), O0); + }}, No_OpClass, IsNonSpeculative); + 0x50: m5readfile({{ + O0 = PseudoInst::readfile(xc->tcBase(), O0, O1, O2); + }}, IsNonSpeculative); + 0x51: m5break({{PseudoInst::debugbreak(xc->tcBase()); + }}, IsNonSpeculative); + 0x54: m5panic({{ + panic("M5 panic instruction called at pc=%#x.", xc->readPC()); + }}, No_OpClass, IsNonSpeculative); + } +#endif + default: Trap::impdep2({{fault = new IllegalInstruction;}}); + } 0x38: Branch::jmpl({{ Addr target = Rs1 + Rs2_or_imm13; if(target & 0x3) @@ -1053,31 +1226,22 @@ decode OP default Unknown::unknown() 0x0: Trap::tcci({{ if(passesCondition(Ccr<3:0>, COND2)) { -#if FULL_SYSTEM int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2); DPRINTF(Sparc, "The trap number is %d\n", lTrapNum); fault = new TrapInstruction(lTrapNum); -#else - DPRINTF(Sparc, "The syscall number is %d\n", R1); - xc->syscall(R1); -#endif } }}, IsSerializeAfter, IsNonSpeculative); 0x2: Trap::tccx({{ if(passesCondition(Ccr<7:4>, COND2)) { -#if FULL_SYSTEM int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2); DPRINTF(Sparc, "The trap number is %d\n", lTrapNum); fault = new TrapInstruction(lTrapNum); -#else - DPRINTF(Sparc, "The syscall number is %d\n", R1); - xc->syscall(R1); -#endif } }}, IsSerializeAfter, IsNonSpeculative); } - 0x3B: Nop::flush({{/*Instruction memory flush*/}}); + 0x3B: Nop::flush({{/*Instruction memory flush*/}}, IsWriteBarrier, + MemWriteOp); 0x3C: save({{ if(Cansave == 0) { @@ -1151,16 +1315,18 @@ decode OP default Unknown::unknown() 0x01: ldub({{Rd = Mem.ub;}}); 0x02: lduh({{Rd = Mem.uhw;}}); 0x03: ldtw({{ - uint64_t val = Mem.udw; - RdLow = val<31:0>; - RdHigh = val<63:32>; + RdLow = (Mem.tuw).a; + RdHigh = (Mem.tuw).b; }}); } format Store { 0x04: stw({{Mem.uw = Rd.sw;}}); 0x05: stb({{Mem.ub = Rd.sb;}}); 0x06: sth({{Mem.uhw = Rd.shw;}}); - 0x07: sttw({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}}); + 0x07: sttw({{ + (Mem.tuw).a = RdLow<31:0>; + (Mem.tuw).b = RdHigh<31:0>; + }}); } format Load { 0x08: ldsw({{Rd = (int32_t)Mem.sw;}}); @@ -1168,15 +1334,17 @@ decode OP default Unknown::unknown() 0x0A: ldsh({{Rd = (int16_t)Mem.shw;}}); 0x0B: ldx({{Rd = (int64_t)Mem.sdw;}}); } - 0x0D: LoadStore::ldstub( - {{uReg0 = Mem.ub;}}, - {{Rd.ub = uReg0; - Mem.ub = 0xFF;}}); + 0x0D: Swap::ldstub({{Mem.ub = 0xFF;}}, + {{ + uint8_t tmp = mem_data; + Rd.ub = tmp; + }}, MEM_SWAP); 0x0E: Store::stx({{Mem.udw = Rd}}); - 0x0F: LoadStore::swap( - {{ uReg0 = Mem.uw}}, - {{ Mem.uw = Rd.uw; - Rd.uw = uReg0;}}); + 0x0F: Swap::swap({{Mem.uw = Rd.uw}}, + {{ + uint32_t tmp = mem_data; + Rd.uw = tmp; + }}, MEM_SWAP); format LoadAlt { 0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}}); 0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}}); @@ -1184,38 +1352,63 @@ decode OP default Unknown::unknown() 0x13: decode EXT_ASI { //ASI_LDTD_AIUP 0x22: TwinLoad::ldtx_aiup( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTD_AIUS 0x23: TwinLoad::ldtx_aius( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_QUAD_LDD 0x24: TwinLoad::ldtx_quad_ldd( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTX_REAL 0x26: TwinLoad::ldtx_real( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); - //ASI_LDTX_N - 0x27: TwinLoad::ldtx_n( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); - //ASI_LDTX_L - 0x2C: TwinLoad::ldtx_l( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_N + 0x27: TwinLoad::ldtx_n( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_AIUP_L + 0x2A: TwinLoad::ldtx_aiup_l( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_AIUS_L + 0x2B: TwinLoad::ldtx_aius_l( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_L + 0x2C: TwinLoad::ldtx_l( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTX_REAL_L 0x2E: TwinLoad::ldtx_real_l( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTX_N_L 0x2F: TwinLoad::ldtx_n_l( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTX_P 0xE2: TwinLoad::ldtx_p( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); //ASI_LDTX_S 0xE3: TwinLoad::ldtx_s( - {{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}}); + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_PL + 0xEA: TwinLoad::ldtx_pl( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); + //ASI_LDTX_SL + 0xEB: TwinLoad::ldtx_sl( + {{RdLow.udw = (Mem.tudw).a; + RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}}); default: ldtwa({{ - uint64_t val = Mem.udw; - RdLow = val<31:0>; - RdHigh = val<63:32>; + RdLow = (Mem.tuw).a; + RdHigh = (Mem.tuw).b; }}, {{EXT_ASI}}); } } @@ -1223,7 +1416,10 @@ decode OP default Unknown::unknown() 0x14: stwa({{Mem.uw = Rd;}}, {{EXT_ASI}}); 0x15: stba({{Mem.ub = Rd;}}, {{EXT_ASI}}); 0x16: stha({{Mem.uhw = Rd;}}, {{EXT_ASI}}); - 0x17: sttwa({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{EXT_ASI}}); + 0x17: sttwa({{ + (Mem.tuw).a = RdLow<31:0>; + (Mem.tuw).b = RdHigh<31:0>; + }}, {{EXT_ASI}}); } format LoadAlt { 0x18: ldswa({{Rd = (int32_t)Mem.sw;}}, {{EXT_ASI}}); @@ -1231,15 +1427,18 @@ decode OP default Unknown::unknown() 0x1A: ldsha({{Rd = (int16_t)Mem.shw;}}, {{EXT_ASI}}); 0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}, {{EXT_ASI}}); } - 0x1D: LoadStoreAlt::ldstuba( - {{uReg0 = Mem.ub;}}, - {{Rd.ub = uReg0; - Mem.ub = 0xFF;}}, {{EXT_ASI}}); + 0x1D: SwapAlt::ldstuba({{Mem.ub = 0xFF;}}, + {{ + uint8_t tmp = mem_data; + Rd.ub = tmp; + }}, {{EXT_ASI}}, MEM_SWAP); 0x1E: StoreAlt::stxa({{Mem.udw = Rd}}, {{EXT_ASI}}); - 0x1F: LoadStoreAlt::swapa( - {{ uReg0 = Mem.uw}}, - {{ Mem.uw = Rd.uw; - Rd.uw = uReg0;}}, {{EXT_ASI}}); + 0x1F: SwapAlt::swapa({{Mem.uw = Rd.uw}}, + {{ + uint32_t tmp = mem_data; + Rd.uw = tmp; + }}, {{EXT_ASI}}, MEM_SWAP); + format Trap { 0x20: Load::ldf({{Frds.uw = Mem.uw;}}); 0x21: decode RD { @@ -1438,21 +1637,17 @@ decode OP default Unknown::unknown() {{fault = new DataAccessException;}}); } } - 0x3C: Cas::casa( - {{uReg0 = Mem.uw;}}, - {{if(Rs2.uw == uReg0) - Mem.uw = Rd.uw; - else - storeCond = false; - Rd.uw = uReg0;}}, {{EXT_ASI}}); + 0x3C: CasAlt::casa({{ + mem_data = htog(Rs2.uw); + Mem.uw = Rd.uw;}}, + {{ + uint32_t tmp = mem_data; + Rd.uw = tmp; + }}, {{EXT_ASI}}, MEM_SWAP_COND); 0x3D: Nop::prefetcha({{ }}); - 0x3E: Cas::casxa( - {{uReg0 = Mem.udw;}}, - {{if(Rs2 == uReg0) - Mem.udw = Rd; - else - storeCond = false; - Rd = uReg0;}}, {{EXT_ASI}}); + 0x3E: CasAlt::casxa({{mem_data = gtoh(Rs2); + Mem.udw = Rd.udw; }}, + {{ Rd.udw = mem_data; }}, {{EXT_ASI}}, MEM_SWAP_COND); } } } diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index 5cd3ab598..f5ab940bb 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -40,7 +40,7 @@ output header {{ { protected: // Constructor - Branch(const char *mnem, MachInst _machInst, OpClass __opClass) : + Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass) { } @@ -56,7 +56,7 @@ output header {{ { protected: // Constructor - BranchDisp(const char *mnem, MachInst _machInst, + BranchDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : Branch(mnem, _machInst, __opClass) { @@ -76,7 +76,7 @@ output header {{ { protected: // Constructor - BranchNBits(const char *mnem, MachInst _machInst, + BranchNBits(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : BranchDisp(mnem, _machInst, __opClass) { @@ -91,7 +91,7 @@ output header {{ { protected: // Constructor - BranchSplit(const char *mnem, MachInst _machInst, + BranchSplit(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : BranchDisp(mnem, _machInst, __opClass) { @@ -107,7 +107,7 @@ output header {{ { protected: // Constructor - BranchImm13(const char *mnem, MachInst _machInst, OpClass __opClass) : + BranchImm13(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : Branch(mnem, _machInst, __opClass), imm(sext<13>(SIMM13)) { } diff --git a/src/arch/sparc/isa/formats/mem/basicmem.isa b/src/arch/sparc/isa/formats/mem/basicmem.isa index 1d9075a57..751262811 100644 --- a/src/arch/sparc/isa/formats/mem/basicmem.isa +++ b/src/arch/sparc/isa/formats/mem/basicmem.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -52,22 +52,20 @@ def template MemDeclare {{ }}; let {{ - def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags): + def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags, postacc_code = ''): addrCalcReg = 'EA = Rs1 + Rs2;' addrCalcImm = 'EA = Rs1 + imm;' iop = InstObjParams(name, Name, 'Mem', - {"code": code, "fault_check": faultCode, - "ea_code": addrCalcReg}, - opt_flags) + {"code": code, "postacc_code" : postacc_code, + "fault_check": faultCode, "ea_code": addrCalcReg}, opt_flags) iop_imm = InstObjParams(name, Name + "Imm", 'MemImm', - {"code": code, "fault_check": faultCode, - "ea_code": addrCalcImm}, - opt_flags) + {"code": code, "postacc_code" : postacc_code, + "fault_check": faultCode, "ea_code": addrCalcImm}, opt_flags) header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm) decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm) decode_block = ROrImmDecode.subst(iop) - exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm, - execute, faultCode, name, name + "Imm", + exec_output = doDualSplitExecute(code, postacc_code, addrCalcReg, + addrCalcImm, execute, faultCode, name, name + "Imm", Name, Name + "Imm", asi, opt_flags) return (header_output, decoder_output, exec_output, decode_block) }}; @@ -103,3 +101,13 @@ def format Store(code, *opt_flags) {{ decode_block) = doMemFormat(code, StoreFuncs, '', name, Name, 0, opt_flags) }}; + +def format TwinLoad(code, asi, *opt_flags) {{ + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, LoadFuncs, + AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck, + name, Name, asi, opt_flags) +}}; + diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa index 9795d2342..499685a5c 100644 --- a/src/arch/sparc/isa/formats/mem/blockmem.isa +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -91,65 +91,6 @@ output header {{ }; }}; -output header {{ - - class TwinMem : public SparcMacroInst - { - protected: - - // Constructor - // We make the assumption that all block memory operations - // Will take 8 instructions to execute - TwinMem(const char *mnem, ExtMachInst _machInst) : - SparcMacroInst(mnem, _machInst, No_OpClass, 2) - {} - }; - - class TwinMemImm : public BlockMem - { - protected: - - // Constructor - TwinMemImm(const char *mnem, ExtMachInst _machInst) : - BlockMem(mnem, _machInst) - {} - }; - - class TwinMemMicro : public SparcMicroInst - { - protected: - - // Constructor - TwinMemMicro(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, int8_t _offset) : - SparcMicroInst(mnem, _machInst, __opClass), - offset(_offset) - {} - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - - const int8_t offset; - }; - - class TwinMemImmMicro : public BlockMemMicro - { - protected: - - // Constructor - TwinMemImmMicro(const char *mnem, ExtMachInst _machInst, - OpClass __opClass, int8_t _offset) : - BlockMemMicro(mnem, _machInst, __opClass, _offset), - imm(sext<13>(SIMM13)) - {} - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - - const int32_t imm; - }; -}}; - output decoder {{ std::string BlockMemMicro::generateDisassembly(Addr pc, const SymbolTable *symtab) const @@ -208,64 +149,6 @@ output decoder {{ }}; -output decoder {{ - std::string TwinMemMicro::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - bool load = flags[IsLoad]; - bool save = flags[IsStore]; - - printMnemonic(response, mnemonic); - if(save) - { - printReg(response, _srcRegIdx[0]); - ccprintf(response, ", "); - } - ccprintf(response, "[ "); - printReg(response, _srcRegIdx[!save ? 0 : 1]); - ccprintf(response, " + "); - printReg(response, _srcRegIdx[!save ? 1 : 2]); - ccprintf(response, " ]"); - if(load) - { - ccprintf(response, ", "); - printReg(response, _destRegIdx[0]); - } - - return response.str(); - } - - std::string TwinMemImmMicro::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - bool load = flags[IsLoad]; - bool save = flags[IsStore]; - - printMnemonic(response, mnemonic); - if(save) - { - printReg(response, _srcRegIdx[1]); - ccprintf(response, ", "); - } - ccprintf(response, "[ "); - printReg(response, _srcRegIdx[0]); - if(imm >= 0) - ccprintf(response, " + 0x%x ]", imm); - else - ccprintf(response, " + -0x%x ]", -imm); - if(load) - { - ccprintf(response, ", "); - printReg(response, _destRegIdx[0]); - } - - return response.str(); - } - -}}; - def template BlockMemDeclare {{ /** * Static instruction class for a block memory operation @@ -359,39 +242,6 @@ def template BlockMemDeclare {{ }; }}; -def template TwinMemDeclare {{ - /** - * Static instruction class for a block memory operation - */ - class %(class_name)s : public %(base_class)s - { - public: - //Constructor - %(class_name)s(ExtMachInst machInst); - - protected: - class %(class_name)s_0 : public %(base_class)sMicro - { - public: - //Constructor - %(class_name)s_0(ExtMachInst machInst); - %(BasicExecDeclare)s - %(InitiateAccDeclare)s - %(CompleteAccDeclare)s - }; - - class %(class_name)s_1 : public %(base_class)sMicro - { - public: - //Constructor - %(class_name)s_1(ExtMachInst machInst); - %(BasicExecDeclare)s - %(InitiateAccDeclare)s - %(CompleteAccDeclare)s - }; - }; -}}; - // Basic instruction class constructor template. def template BlockMemConstructor {{ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) @@ -409,17 +259,6 @@ def template BlockMemConstructor {{ } }}; -// Basic instruction class constructor template. -def template TwinMemConstructor {{ - inline %(class_name)s::%(class_name)s(ExtMachInst machInst) - : %(base_class)s("%(mnemonic)s", machInst) - { - %(constructor)s; - microOps[0] = new %(class_name)s_0(machInst); - microOps[1] = new %(class_name)s_1(machInst); - } -}}; - def template BlockMemMicroConstructor {{ inline %(class_name)s:: %(class_name)s_%(micro_pc)s:: @@ -467,47 +306,7 @@ let {{ decoder_output += BlockMemMicroConstructor.subst(iop) decoder_output += BlockMemMicroConstructor.subst(iop_imm) exec_output += doDualSplitExecute( - pcedCode, addrCalcReg, addrCalcImm, execute, faultCode, - makeMicroName(name, microPc), - makeMicroName(name + "Imm", microPc), - makeMicroName(Name, microPc), - makeMicroName(Name + "Imm", microPc), - asi, opt_flags); - faultCode = '' - return (header_output, decoder_output, exec_output, decode_block) - - def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags): - addrCalcReg = 'EA = Rs1 + Rs2 + offset;' - addrCalcImm = 'EA = Rs1 + imm + offset;' - iop = InstObjParams(name, Name, 'TwinMem', code, opt_flags) - iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', code, opt_flags) - header_output = TwinMemDeclare.subst(iop) + TwinMemDeclare.subst(iop_imm) - decoder_output = TwinMemConstructor.subst(iop) + TwinMemConstructor.subst(iop_imm) - decode_block = ROrImmDecode.subst(iop) - matcher = re.compile(r'RdTwin') - exec_output = '' - for microPc in range(2): - flag_code = '' - pcedCode = '' - if (microPc == 1): - flag_code = "flags[IsLastMicroOp] = true;" - pcedCode = "RdLow = uReg0;\n" - pcedCode += matcher.sub("RdHigh", code) - else: - flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;" - pcedCode = matcher.sub("uReg0", code) - iop = InstObjParams(name, Name, 'TwinMem', - {"code": pcedCode, "ea_code": addrCalcReg, - "fault_check": faultCode, "micro_pc": microPc, - "set_flags": flag_code}, opt_flags) - iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', - {"code": pcedCode, "ea_code": addrCalcImm, - "fault_check": faultCode, "micro_pc": microPc, - "set_flags": flag_code}, opt_flags) - decoder_output += BlockMemMicroConstructor.subst(iop) - decoder_output += BlockMemMicroConstructor.subst(iop_imm) - exec_output += doDualSplitExecute( - pcedCode, addrCalcReg, addrCalcImm, LoadFuncs, faultCode, + pcedCode, '', addrCalcReg, addrCalcImm, execute, faultCode, makeMicroName(name, microPc), makeMicroName(name + "Imm", microPc), makeMicroName(Name, microPc), @@ -515,7 +314,6 @@ let {{ asi, opt_flags); faultCode = '' return (header_output, decoder_output, exec_output, decode_block) - }}; def format BlockLoad(code, asi, *opt_flags) {{ @@ -541,11 +339,3 @@ def format BlockStore(code, asi, *opt_flags) {{ decode_block) = doBlockMemFormat(code, faultCode, StoreFuncs, name, Name, asi, opt_flags) }}; - -def format TwinLoad(code, asi, *opt_flags) {{ - faultCode = AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck - (header_output, - decoder_output, - exec_output, - decode_block) = doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags) -}}; diff --git a/src/arch/sparc/isa/formats/mem/mem.isa b/src/arch/sparc/isa/formats/mem/mem.isa index fedece2b8..db45e226d 100644 --- a/src/arch/sparc/isa/formats/mem/mem.isa +++ b/src/arch/sparc/isa/formats/mem/mem.isa @@ -1,4 +1,4 @@ -// Copyright (c) 2006 The Regents of The University of Michigan +// Copyright (c) 2006-2007 The Regents of The University of Michigan // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -42,4 +42,4 @@ ##include "blockmem.isa" //Include the load/store and cas memory format -##include "loadstore.isa" +##include "swap.isa" diff --git a/src/arch/sparc/isa/formats/mem/swap.isa b/src/arch/sparc/isa/formats/mem/swap.isa new file mode 100644 index 000000000..818597a84 --- /dev/null +++ b/src/arch/sparc/isa/formats/mem/swap.isa @@ -0,0 +1,183 @@ +// Copyright (c) 2007 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 + +//This template provides the execute functions for a swap +def template SwapExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + //This is to support the conditional store in cas instructions. + //It should be optomized out in all the others + bool storeCond = true; + Addr EA; + %(fp_enable_check)s; + %(op_decl)s; + uint64_t mem_data; + + %(op_rd)s; + %(ea_code)s; + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); + %(fault_check)s; + if(fault == NoFault) + { + %(code)s; + } + if(storeCond && fault == NoFault) + { + fault = xc->write((uint%(mem_acc_size)s_t)Mem, + EA, %(asi_val)s, &mem_data); + } + if(fault == NoFault) + { + //Handle the swapping + %(postacc_code)s; + } + if(fault == NoFault) + { + //Write the resulting state to the execution context + %(op_wb)s; + } + + return fault; + } +}}; + + +def template SwapInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + Fault fault = NoFault; + Addr EA; + %(fp_enable_check)s; + uint64_t mem_data = 0; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); + %(fault_check)s; + + if(fault == NoFault) + { + %(code)s; + } + if(fault == NoFault) + { + fault = xc->write((uint%(mem_acc_size)s_t)Mem, + EA, %(asi_val)s, &mem_data); + } + return fault; + } +}}; + + + +def template SwapCompleteAcc {{ + Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc, + Trace::InstRecord * traceData) const + { + Fault fault = NoFault; + %(op_decl)s; + + uint64_t mem_data = pkt->get<uint%(mem_acc_size)s_t>(); + + if(fault == NoFault) + { + //Handle the swapping + %(postacc_code)s; + } + if(fault == NoFault) + { + //Write the resulting state to the execution context + %(op_wb)s; + } + + return fault; + } +}}; + +let {{ + SwapFuncs = [SwapExecute, SwapInitiateAcc, SwapCompleteAcc] +}}; + + +def format Swap(code, postacc_code, mem_flags, *opt_flags) {{ + mem_flags = makeList(mem_flags) + flags = string.join(mem_flags, '|') + + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, SwapFuncs, '', name, Name, flags, + opt_flags, postacc_code) +}}; + +def format SwapAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{ + mem_flags = makeList(mem_flags) + mem_flags.append(asi) + flags = string.join(mem_flags, '|') + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, SwapFuncs, AlternateASIPrivFaultCheck, + name, Name, flags, opt_flags, postacc_code) +}}; + + +let {{ + def doCasFormat(code, execute, faultCode, name, Name, asi, opt_flags, postacc_code = ''): + addrCalcReg = 'EA = Rs1;' + iop = InstObjParams(name, Name, 'Mem', + {"code": code, "postacc_code" : postacc_code, + "fault_check": faultCode, "ea_code": addrCalcReg}, opt_flags) + header_output = MemDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + microParams = {"code": code, "postacc_code" : postacc_code, + "ea_code" : addrCalcReg, "fault_check" : faultCode} + exec_output = doSplitExecute(execute, name, Name, asi, opt_flags, + microParams); + return (header_output, decoder_output, exec_output, decode_block) +}}; + + +def format CasAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{ + mem_flags = makeList(mem_flags) + mem_flags.append(asi) + flags = string.join(mem_flags, '|') + (header_output, + decoder_output, + exec_output, + decode_block) = doCasFormat(code, SwapFuncs, AlternateASIPrivFaultCheck, + name, Name, flags, opt_flags, postacc_code) +}}; + + diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index dbaabdca4..dfe937371 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -149,7 +149,7 @@ def template LoadExecute {{ %(fault_check)s; if(fault == NoFault) { - fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s); + fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, %(asi_val)s); } if(fault == NoFault) { @@ -179,7 +179,7 @@ def template LoadInitiateAcc {{ %(fault_check)s; if(fault == NoFault) { - fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s); + fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, %(asi_val)s); } return fault; } @@ -224,7 +224,7 @@ def template StoreExecute {{ } if(storeCond && fault == NoFault) { - fault = xc->write((uint%(mem_acc_size)s_t)Mem, + fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, EA, %(asi_val)s, 0); } if(fault == NoFault) @@ -246,6 +246,7 @@ def template StoreInitiateAcc {{ Addr EA; %(fp_enable_check)s; %(op_decl)s; + %(op_rd)s; %(ea_code)s; DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA); @@ -256,7 +257,7 @@ def template StoreInitiateAcc {{ } if(storeCond && fault == NoFault) { - fault = xc->write((uint%(mem_acc_size)s_t)Mem, + fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, EA, %(asi_val)s, 0); } if(fault == NoFault) @@ -290,6 +291,7 @@ def template CompleteAccDeclare {{ let {{ LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc] StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc] + # The LSB can be zero, since it's really the MSB in doubles and quads # and we're dealing with doubles BlockAlignmentFaultCheck = ''' @@ -337,14 +339,14 @@ let {{ return execf.subst(iop) + initf.subst(iop) + compf.subst(iop) - def doDualSplitExecute(code, eaRegCode, eaImmCode, execute, + def doDualSplitExecute(code, postacc_code, eaRegCode, eaImmCode, execute, faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags): executeCode = '' for (eaCode, name, Name) in ( (eaRegCode, nameReg, NameReg), (eaImmCode, nameImm, NameImm)): - microParams = {"code": code, "ea_code": eaCode, - "fault_check": faultCode} + microParams = {"code": code, "postacc_code" : postacc_code, + "ea_code": eaCode, "fault_check": faultCode} executeCode += doSplitExecute(execute, name, Name, asi, opt_flags, microParams) return executeCode diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index d2ef67154..05e9e8731 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -70,10 +70,15 @@ output exec {{ #include <ieeefp.h> #endif +#if FULL_SYSTEM +#include "sim/pseudo_inst.hh" +#endif + #include <limits> #include <cmath> #include "arch/sparc/asi.hh" +#include "base/bigint.hh" #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 140055010..038919bd1 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -37,6 +37,8 @@ def operand_types {{ 'uw' : ('unsigned int', 32), 'sdw' : ('signed int', 64), 'udw' : ('unsigned int', 64), + 'tudw' : ('twin64 int', 64), + 'tuw' : ('twin32 int', 32), 'sf' : ('float', 32), 'df' : ('float', 64), 'qf' : ('float', 128) @@ -99,6 +101,12 @@ def operands {{ 'R1': ('IntReg', 'udw', '1', None, 7), 'R15': ('IntReg', 'udw', '15', 'IsInteger', 8), 'R16': ('IntReg', 'udw', '16', None, 9), + 'O0': ('IntReg', 'udw', '8', 'IsInteger', 10), + 'O1': ('IntReg', 'udw', '9', 'IsInteger', 11), + 'O2': ('IntReg', 'udw', '10', 'IsInteger', 12), + 'O3': ('IntReg', 'udw', '11', 'IsInteger', 13), + 'O4': ('IntReg', 'udw', '12', 'IsInteger', 14), + 'O5': ('IntReg', 'udw', '13', 'IsInteger', 15), # Control registers # 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 40), diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 64ae6abd8..d0b8827f3 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -87,6 +87,11 @@ namespace SparcISA const int LogVMPageSize = 13; const int VMPageSize = (1 << LogVMPageSize); + // real address virtual mapping + // sort of like alpha super page, but less frequently used + const Addr SegKPMEnd = ULL(0xfffffffc00000000); + const Addr SegKPMBase = ULL(0xfffffac000000000); + //Why does both the previous set of constants and this one exist? const int PageShift = 13; const int PageBytes = 1ULL << PageShift; @@ -108,6 +113,18 @@ namespace SparcISA const Addr PAddrImplMask = ULL(0x000000FFFFFFFFFF); const Addr BytesInPageMask = ULL(0x1FFF); + enum InterruptTypes + { + IT_TRAP_LEVEL_ZERO, + IT_HINTP, + IT_INT_VEC, + IT_CPU_MONDO, + IT_DEV_MONDO, + IT_RES_ERROR, + IT_SOFT_INT, + NumInterruptTypes + }; + #endif } diff --git a/src/arch/sparc/linux/linux.hh b/src/arch/sparc/linux/linux.hh index fefd27197..f396eb5cd 100644 --- a/src/arch/sparc/linux/linux.hh +++ b/src/arch/sparc/linux/linux.hh @@ -79,4 +79,32 @@ class SparcLinux : public Linux static const unsigned TGT_MAP_ANONYMOUS = 0x20; }; +class Sparc32Linux : public SparcLinux +{ + public: + + typedef struct { + uint64_t st_dev; + uint64_t st_ino; + uint32_t st_mode; + uint32_t st_nlink; + uint32_t st_uid; + uint32_t st_gid; + uint64_t st_rdev; + uint8_t __pad3[8]; + int64_t st_size; + int32_t st_blksize; + uint8_t __pad4[8]; + int64_t st_blocks; + uint64_t st_atimeX; + uint64_t st_atime_nsec; + uint64_t st_mtimeX; + uint64_t st_mtime_nsec; + uint64_t st_ctimeX; + uint64_t st_ctime_nsec; + uint32_t __unused4; + uint32_t __unused5; + } tgt_stat64; +}; + #endif diff --git a/src/arch/sparc/linux/process.cc b/src/arch/sparc/linux/process.cc index 565975fe0..9e3f74075 100644 --- a/src/arch/sparc/linux/process.cc +++ b/src/arch/sparc/linux/process.cc @@ -44,373 +44,89 @@ using namespace std; using namespace SparcISA; - -/// Target uname() handler. -static SyscallReturn -unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, - ThreadContext *tc) +SyscallDesc* +SparcLinuxProcess::getDesc(int callnum) { - TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0)); - - strcpy(name->sysname, "Linux"); - strcpy(name->nodename, "m5.eecs.umich.edu"); - strcpy(name->release, "2.4.20"); - strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); - strcpy(name->machine, "sparc"); - - name.copyOut(tc->getMemPort()); - - return 0; + if (callnum < 0 || callnum > Num_Syscall_Descs) + return NULL; + return &syscallDescs[callnum]; } - -SyscallReturn SparcISA::getresuidFunc(SyscallDesc *desc, int num, - LiveProcess *p, ThreadContext *tc) +SyscallDesc* +SparcLinuxProcess::getDesc32(int callnum) { - const IntReg id = htog(100); - Addr ruid = tc->getSyscallArg(0); - Addr euid = tc->getSyscallArg(1); - Addr suid = tc->getSyscallArg(2); - //Handle the EFAULT case - //Set the ruid - if(ruid) - { - BufferArg ruidBuff(ruid, sizeof(IntReg)); - memcpy(ruidBuff.bufferPtr(), &id, sizeof(IntReg)); - ruidBuff.copyOut(tc->getMemPort()); - } - //Set the euid - if(euid) - { - BufferArg euidBuff(euid, sizeof(IntReg)); - memcpy(euidBuff.bufferPtr(), &id, sizeof(IntReg)); - euidBuff.copyOut(tc->getMemPort()); - } - //Set the suid - if(suid) - { - BufferArg suidBuff(suid, sizeof(IntReg)); - memcpy(suidBuff.bufferPtr(), &id, sizeof(IntReg)); - suidBuff.copyOut(tc->getMemPort()); - } - return 0; + if (callnum < 0 || callnum > Num_Syscall32_Descs) + return NULL; + return &syscall32Descs[callnum]; } -SyscallDesc SparcLinuxProcess::syscallDescs[] = { - /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc), - /* 1 */ SyscallDesc("exit", exitFunc), - /* 2 */ SyscallDesc("fork", unimplementedFunc), - /* 3 */ SyscallDesc("read", readFunc), - /* 4 */ SyscallDesc("write", writeFunc), - /* 5 */ SyscallDesc("open", openFunc<SparcLinux>), - /* 6 */ SyscallDesc("close", closeFunc), - /* 7 */ SyscallDesc("wait4", unimplementedFunc), - /* 8 */ SyscallDesc("creat", unimplementedFunc), - /* 9 */ SyscallDesc("link", unimplementedFunc), - /* 10 */ SyscallDesc("unlink", unlinkFunc), - /* 11 */ SyscallDesc("execv", unimplementedFunc), - /* 12 */ SyscallDesc("chdir", unimplementedFunc), - /* 13 */ SyscallDesc("chown", chownFunc), - /* 14 */ SyscallDesc("mknod", unimplementedFunc), - /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>), - /* 16 */ SyscallDesc("lchown", unimplementedFunc), - /* 17 */ SyscallDesc("brk", obreakFunc), - /* 18 */ SyscallDesc("perfctr", unimplementedFunc), - /* 19 */ SyscallDesc("lseek", lseekFunc), - /* 20 */ SyscallDesc("getpid", getpidFunc), - /* 21 */ SyscallDesc("capget", unimplementedFunc), - /* 22 */ SyscallDesc("capset", unimplementedFunc), - /* 23 */ SyscallDesc("setuid", setuidFunc), - /* 24 */ SyscallDesc("getuid", getuidFunc), - /* 25 */ SyscallDesc("time", unimplementedFunc), - /* 26 */ SyscallDesc("ptrace", unimplementedFunc), - /* 27 */ SyscallDesc("alarm", unimplementedFunc), - /* 28 */ SyscallDesc("sigaltstack", unimplementedFunc), - /* 29 */ SyscallDesc("pause", unimplementedFunc), - /* 30 */ SyscallDesc("utime", unimplementedFunc), - /* 31 */ SyscallDesc("lchown32", unimplementedFunc), - /* 32 */ SyscallDesc("fchown32", unimplementedFunc), - /* 33 */ SyscallDesc("access", unimplementedFunc), - /* 34 */ SyscallDesc("nice", unimplementedFunc), - /* 35 */ SyscallDesc("chown32", unimplementedFunc), - /* 36 */ SyscallDesc("sync", unimplementedFunc), - /* 37 */ SyscallDesc("kill", unimplementedFunc), - /* 38 */ SyscallDesc("stat", unimplementedFunc), - /* 39 */ SyscallDesc("sendfile", unimplementedFunc), - /* 40 */ SyscallDesc("lstat", unimplementedFunc), - /* 41 */ SyscallDesc("dup", unimplementedFunc), - /* 42 */ SyscallDesc("pipe", pipePseudoFunc), - /* 43 */ SyscallDesc("times", unimplementedFunc), - /* 44 */ SyscallDesc("getuid32", unimplementedFunc), - /* 45 */ SyscallDesc("umount2", unimplementedFunc), - /* 46 */ SyscallDesc("setgid", unimplementedFunc), - /* 47 */ SyscallDesc("getgid", getgidFunc), - /* 48 */ SyscallDesc("signal", unimplementedFunc), - /* 49 */ SyscallDesc("geteuid", geteuidFunc), - /* 50 */ SyscallDesc("getegid", getegidFunc), - /* 51 */ SyscallDesc("acct", unimplementedFunc), - /* 52 */ SyscallDesc("memory_ordering", unimplementedFunc), - /* 53 */ SyscallDesc("getgid32", unimplementedFunc), - /* 54 */ SyscallDesc("ioctl", unimplementedFunc), - /* 55 */ SyscallDesc("reboot", unimplementedFunc), - /* 56 */ SyscallDesc("mmap2", unimplementedFunc), - /* 57 */ SyscallDesc("symlink", unimplementedFunc), - /* 58 */ SyscallDesc("readlink", unimplementedFunc), - /* 59 */ SyscallDesc("execve", unimplementedFunc), - /* 60 */ SyscallDesc("umask", unimplementedFunc), - /* 61 */ SyscallDesc("chroot", unimplementedFunc), - /* 62 */ SyscallDesc("fstat", fstatFunc<SparcLinux>), - /* 63 */ SyscallDesc("fstat64", unimplementedFunc), - /* 64 */ SyscallDesc("getpagesize", unimplementedFunc), - /* 65 */ SyscallDesc("msync", unimplementedFunc), - /* 66 */ SyscallDesc("vfork", unimplementedFunc), - /* 67 */ SyscallDesc("pread64", unimplementedFunc), - /* 68 */ SyscallDesc("pwrite64", unimplementedFunc), - /* 69 */ SyscallDesc("geteuid32", unimplementedFunc), - /* 70 */ SyscallDesc("getdgid32", unimplementedFunc), - /* 71 */ SyscallDesc("mmap", mmapFunc<SparcLinux>), - /* 72 */ SyscallDesc("setreuid32", unimplementedFunc), - /* 73 */ SyscallDesc("munmap", munmapFunc), - /* 74 */ SyscallDesc("mprotect", unimplementedFunc), - /* 75 */ SyscallDesc("madvise", unimplementedFunc), - /* 76 */ SyscallDesc("vhangup", unimplementedFunc), - /* 77 */ SyscallDesc("truncate64", unimplementedFunc), - /* 78 */ SyscallDesc("mincore", unimplementedFunc), - /* 79 */ SyscallDesc("getgroups", unimplementedFunc), - /* 80 */ SyscallDesc("setgroups", unimplementedFunc), - /* 81 */ SyscallDesc("getpgrp", unimplementedFunc), - /* 82 */ SyscallDesc("setgroups32", unimplementedFunc), - /* 83 */ SyscallDesc("setitimer", unimplementedFunc), - /* 84 */ SyscallDesc("ftruncate64", unimplementedFunc), - /* 85 */ SyscallDesc("swapon", unimplementedFunc), - /* 86 */ SyscallDesc("getitimer", unimplementedFunc), - /* 87 */ SyscallDesc("setuid32", unimplementedFunc), - /* 88 */ SyscallDesc("sethostname", unimplementedFunc), - /* 89 */ SyscallDesc("setgid32", unimplementedFunc), - /* 90 */ SyscallDesc("dup2", unimplementedFunc), - /* 91 */ SyscallDesc("setfsuid32", unimplementedFunc), - /* 92 */ SyscallDesc("fcntl", unimplementedFunc), - /* 93 */ SyscallDesc("select", unimplementedFunc), - /* 94 */ SyscallDesc("setfsgid32", unimplementedFunc), - /* 95 */ SyscallDesc("fsync", unimplementedFunc), - /* 96 */ SyscallDesc("setpriority", unimplementedFunc), - /* 97 */ SyscallDesc("socket", unimplementedFunc), - /* 98 */ SyscallDesc("connect", unimplementedFunc), - /* 99 */ SyscallDesc("accept", unimplementedFunc), - /* 100 */ SyscallDesc("getpriority", unimplementedFunc), - /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc), - /* 102 */ SyscallDesc("rt_sigaction", ignoreFunc), - /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), - /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc), - /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), - /* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), - /* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), - /* 108 */ SyscallDesc("setresuid", unimplementedFunc), - /* 109 */ SyscallDesc("getresuid", getresuidFunc), - /* 110 */ SyscallDesc("setresgid", unimplementedFunc), - /* 111 */ SyscallDesc("getresgid", unimplementedFunc), - /* 112 */ SyscallDesc("setregid32", unimplementedFunc), - /* 113 */ SyscallDesc("recvmsg", unimplementedFunc), - /* 114 */ SyscallDesc("sendmsg", unimplementedFunc), - /* 115 */ SyscallDesc("getgroups32", unimplementedFunc), - /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc), - /* 117 */ SyscallDesc("getrusage", unimplementedFunc), - /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), - /* 119 */ SyscallDesc("getcwd", unimplementedFunc), - /* 120 */ SyscallDesc("readv", unimplementedFunc), - /* 121 */ SyscallDesc("writev", unimplementedFunc), - /* 122 */ SyscallDesc("settimeofday", unimplementedFunc), - /* 123 */ SyscallDesc("fchown", unimplementedFunc), - /* 124 */ SyscallDesc("fchmod", unimplementedFunc), - /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), - /* 126 */ SyscallDesc("setreuid", unimplementedFunc), - /* 127 */ SyscallDesc("setregid", unimplementedFunc), - /* 128 */ SyscallDesc("rename", unimplementedFunc), - /* 129 */ SyscallDesc("truncate", unimplementedFunc), - /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), - /* 131 */ SyscallDesc("flock", unimplementedFunc), - /* 132 */ SyscallDesc("lstat64", unimplementedFunc), - /* 133 */ SyscallDesc("sendto", unimplementedFunc), - /* 134 */ SyscallDesc("shutdown", unimplementedFunc), - /* 135 */ SyscallDesc("socketpair", unimplementedFunc), - /* 136 */ SyscallDesc("mkdir", unimplementedFunc), - /* 137 */ SyscallDesc("rmdir", unimplementedFunc), - /* 138 */ SyscallDesc("utimes", unimplementedFunc), - /* 139 */ SyscallDesc("stat64", unimplementedFunc), - /* 140 */ SyscallDesc("sendfile64", unimplementedFunc), - /* 141 */ SyscallDesc("getpeername", unimplementedFunc), - /* 142 */ SyscallDesc("futex", unimplementedFunc), - /* 143 */ SyscallDesc("gettid", unimplementedFunc), - /* 144 */ SyscallDesc("getrlimit", unimplementedFunc), - /* 145 */ SyscallDesc("setrlimit", unimplementedFunc), - /* 146 */ SyscallDesc("pivot_root", unimplementedFunc), - /* 147 */ SyscallDesc("prctl", unimplementedFunc), - /* 148 */ SyscallDesc("pciconfig_read", unimplementedFunc), - /* 149 */ SyscallDesc("pciconfig_write", unimplementedFunc), - /* 150 */ SyscallDesc("getsockname", unimplementedFunc), - /* 151 */ SyscallDesc("inotify_init", unimplementedFunc), - /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc), - /* 153 */ SyscallDesc("poll", unimplementedFunc), - /* 154 */ SyscallDesc("getdents64", unimplementedFunc), - /* 155 */ SyscallDesc("fcntl64", unimplementedFunc), - /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), - /* 157 */ SyscallDesc("statfs", unimplementedFunc), - /* 158 */ SyscallDesc("fstatfs", unimplementedFunc), - /* 159 */ SyscallDesc("umount", unimplementedFunc), - /* 160 */ SyscallDesc("sched_set_affinity", unimplementedFunc), - /* 161 */ SyscallDesc("sched_get_affinity", unimplementedFunc), - /* 162 */ SyscallDesc("getdomainname", unimplementedFunc), - /* 163 */ SyscallDesc("setdomainname", unimplementedFunc), - /* 164 */ SyscallDesc("utrap_install", unimplementedFunc), - /* 165 */ SyscallDesc("quotactl", unimplementedFunc), - /* 166 */ SyscallDesc("set_tid_address", unimplementedFunc), - /* 167 */ SyscallDesc("mount", unimplementedFunc), - /* 168 */ SyscallDesc("ustat", unimplementedFunc), - /* 169 */ SyscallDesc("setxattr", unimplementedFunc), - /* 170 */ SyscallDesc("lsetxattr", unimplementedFunc), - /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc), - /* 172 */ SyscallDesc("getxattr", unimplementedFunc), - /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc), - /* 174 */ SyscallDesc("getdents", unimplementedFunc), - /* 175 */ SyscallDesc("setsid", unimplementedFunc), - /* 176 */ SyscallDesc("fchdir", unimplementedFunc), - /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc), - /* 178 */ SyscallDesc("listxattr", unimplementedFunc), - /* 179 */ SyscallDesc("llistxattr", unimplementedFunc), - /* 180 */ SyscallDesc("flistxattr", unimplementedFunc), - /* 181 */ SyscallDesc("removexattr", unimplementedFunc), - /* 182 */ SyscallDesc("lremovexattr", unimplementedFunc), - /* 183 */ SyscallDesc("sigpending", unimplementedFunc), - /* 184 */ SyscallDesc("query_module", unimplementedFunc), - /* 185 */ SyscallDesc("setpgid", unimplementedFunc), - /* 186 */ SyscallDesc("fremovexattr", unimplementedFunc), - /* 187 */ SyscallDesc("tkill", unimplementedFunc), - /* 188 */ SyscallDesc("exit_group", exitFunc), - /* 189 */ SyscallDesc("uname", unameFunc), - /* 190 */ SyscallDesc("init_module", unimplementedFunc), - /* 191 */ SyscallDesc("personality", unimplementedFunc), - /* 192 */ SyscallDesc("remap_file_pages", unimplementedFunc), - /* 193 */ SyscallDesc("epoll_create", unimplementedFunc), - /* 194 */ SyscallDesc("epoll_ctl", unimplementedFunc), - /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc), - /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc), - /* 197 */ SyscallDesc("getppid", getppidFunc), - /* 198 */ SyscallDesc("sigaction", ignoreFunc), - /* 199 */ SyscallDesc("sgetmask", unimplementedFunc), - /* 200 */ SyscallDesc("ssetmask", unimplementedFunc), - /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc), - /* 202 */ SyscallDesc("oldlstat", unimplementedFunc), - /* 203 */ SyscallDesc("uselib", unimplementedFunc), - /* 204 */ SyscallDesc("readdir", unimplementedFunc), - /* 205 */ SyscallDesc("readahead", unimplementedFunc), - /* 206 */ SyscallDesc("socketcall", unimplementedFunc), - /* 207 */ SyscallDesc("syslog", unimplementedFunc), - /* 208 */ SyscallDesc("lookup_dcookie", unimplementedFunc), - /* 209 */ SyscallDesc("fadvise64", unimplementedFunc), - /* 210 */ SyscallDesc("fadvise64_64", unimplementedFunc), - /* 211 */ SyscallDesc("tgkill", unimplementedFunc), - /* 212 */ SyscallDesc("waitpid", unimplementedFunc), - /* 213 */ SyscallDesc("swapoff", unimplementedFunc), - /* 214 */ SyscallDesc("sysinfo", unimplementedFunc), - /* 215 */ SyscallDesc("ipc", unimplementedFunc), - /* 216 */ SyscallDesc("sigreturn", unimplementedFunc), - /* 217 */ SyscallDesc("clone", unimplementedFunc), - /* 218 */ SyscallDesc("ioprio_get", unimplementedFunc), - /* 219 */ SyscallDesc("adjtimex", unimplementedFunc), - /* 220 */ SyscallDesc("sigprocmask", unimplementedFunc), - /* 221 */ SyscallDesc("create_module", unimplementedFunc), - /* 222 */ SyscallDesc("delete_module", unimplementedFunc), - /* 223 */ SyscallDesc("get_kernel_syms", unimplementedFunc), - /* 224 */ SyscallDesc("getpgid", unimplementedFunc), - /* 225 */ SyscallDesc("bdflush", unimplementedFunc), - /* 226 */ SyscallDesc("sysfs", unimplementedFunc), - /* 227 */ SyscallDesc("afs_syscall", unimplementedFunc), - /* 228 */ SyscallDesc("setfsuid", unimplementedFunc), - /* 229 */ SyscallDesc("setfsgid", unimplementedFunc), - /* 230 */ SyscallDesc("_newselect", unimplementedFunc), - /* 231 */ SyscallDesc("time", unimplementedFunc), - /* 232 */ SyscallDesc("oldstat", unimplementedFunc), - /* 233 */ SyscallDesc("stime", unimplementedFunc), - /* 234 */ SyscallDesc("statfs64", unimplementedFunc), - /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc), - /* 236 */ SyscallDesc("_llseek", unimplementedFunc), - /* 237 */ SyscallDesc("mlock", unimplementedFunc), - /* 238 */ SyscallDesc("munlock", unimplementedFunc), - /* 239 */ SyscallDesc("mlockall", unimplementedFunc), - /* 240 */ SyscallDesc("munlockall", unimplementedFunc), - /* 241 */ SyscallDesc("sched_setparam", unimplementedFunc), - /* 242 */ SyscallDesc("sched_getparam", unimplementedFunc), - /* 243 */ SyscallDesc("sched_setscheduler", unimplementedFunc), - /* 244 */ SyscallDesc("sched_getscheduler", unimplementedFunc), - /* 245 */ SyscallDesc("sched_yield", unimplementedFunc), - /* 246 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), - /* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), - /* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), - /* 249 */ SyscallDesc("nanosleep", unimplementedFunc), - /* 250 */ SyscallDesc("mremap", unimplementedFunc), - /* 251 */ SyscallDesc("_sysctl", unimplementedFunc), - /* 252 */ SyscallDesc("getsid", unimplementedFunc), - /* 253 */ SyscallDesc("fdatasync", unimplementedFunc), - /* 254 */ SyscallDesc("nfsservctl", unimplementedFunc), - /* 255 */ SyscallDesc("aplib", unimplementedFunc), - /* 256 */ SyscallDesc("clock_settime", unimplementedFunc), - /* 257 */ SyscallDesc("clock_gettime", unimplementedFunc), - /* 258 */ SyscallDesc("clock_getres", unimplementedFunc), - /* 259 */ SyscallDesc("clock_nanosleep", unimplementedFunc), - /* 260 */ SyscallDesc("sched_getaffinity", unimplementedFunc), - /* 261 */ SyscallDesc("sched_setaffinity", unimplementedFunc), - /* 262 */ SyscallDesc("timer_settime", unimplementedFunc), - /* 263 */ SyscallDesc("timer_gettime", unimplementedFunc), - /* 264 */ SyscallDesc("timer_getoverrun", unimplementedFunc), - /* 265 */ SyscallDesc("timer_delete", unimplementedFunc), - /* 266 */ SyscallDesc("timer_create", unimplementedFunc), - /* 267 */ SyscallDesc("vserver", unimplementedFunc), - /* 268 */ SyscallDesc("io_setup", unimplementedFunc), - /* 269 */ SyscallDesc("io_destroy", unimplementedFunc), - /* 270 */ SyscallDesc("io_submit", unimplementedFunc), - /* 271 */ SyscallDesc("io_cancel", unimplementedFunc), - /* 272 */ SyscallDesc("io_getevents", unimplementedFunc), - /* 273 */ SyscallDesc("mq_open", unimplementedFunc), - /* 274 */ SyscallDesc("mq_unlink", unimplementedFunc), - /* 275 */ SyscallDesc("mq_timedsend", unimplementedFunc), - /* 276 */ SyscallDesc("mq_timedreceive", unimplementedFunc), - /* 277 */ SyscallDesc("mq_notify", unimplementedFunc), - /* 278 */ SyscallDesc("mq_getsetattr", unimplementedFunc), - /* 279 */ SyscallDesc("waitid", unimplementedFunc), - /* 280 */ SyscallDesc("sys_setaltroot", unimplementedFunc), - /* 281 */ SyscallDesc("add_key", unimplementedFunc), - /* 282 */ SyscallDesc("request_key", unimplementedFunc), - /* 283 */ SyscallDesc("keyctl", unimplementedFunc) -}; - -SparcLinuxProcess::SparcLinuxProcess(const std::string &name, - ObjectFile *objFile, - System * system, - int stdin_fd, - int stdout_fd, - int stderr_fd, - std::vector<std::string> &argv, - std::vector<std::string> &envp, - const std::string &cwd, - uint64_t _uid, uint64_t _euid, - uint64_t _gid, uint64_t _egid, - uint64_t _pid, uint64_t _ppid) - : SparcLiveProcess(name, objFile, system, - stdin_fd, stdout_fd, stderr_fd, argv, envp, cwd, - _uid, _euid, _gid, _egid, _pid, _ppid), - Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) +SparcLinuxProcess::SparcLinuxProcess() : + Num_Syscall_Descs(284), //sizeof(syscallDescs) / sizeof(SyscallDesc)), + Num_Syscall32_Descs(299) //sizeof(syscall32Descs) / sizeof(SyscallDesc)) { // The sparc syscall table must be <= 284 entries because that is all there // is space for. assert(Num_Syscall_Descs <= 284); + // The sparc 32 bit syscall table bust be <= 299 entries because that is + // all there is space for. + assert(Num_Syscall_Descs <= 299); } +Sparc32LinuxProcess::Sparc32LinuxProcess(const std::string &name, + ObjectFile *objFile, + System * system, + int stdin_fd, + int stdout_fd, + int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid) + : Sparc32LiveProcess(name, objFile, system, + stdin_fd, stdout_fd, stderr_fd, argv, envp, cwd, + _uid, _euid, _gid, _egid, _pid, _ppid) +{} +void Sparc32LinuxProcess::handleTrap(int trapNum, ThreadContext *tc) +{ + switch(trapNum) + { + case 0x10: //Linux 32 bit syscall trap + tc->syscall(tc->readIntReg(1)); + break; + default: + SparcLiveProcess::handleTrap(trapNum, tc); + } +} -SyscallDesc* -SparcLinuxProcess::getDesc(int callnum) +Sparc64LinuxProcess::Sparc64LinuxProcess(const std::string &name, + ObjectFile *objFile, + System * system, + int stdin_fd, + int stdout_fd, + int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid) + : Sparc64LiveProcess(name, objFile, system, + stdin_fd, stdout_fd, stderr_fd, argv, envp, cwd, + _uid, _euid, _gid, _egid, _pid, _ppid) +{} + +void Sparc64LinuxProcess::handleTrap(int trapNum, ThreadContext *tc) { - if (callnum < 0 || callnum > Num_Syscall_Descs) - return NULL; - return &syscallDescs[callnum]; + switch(trapNum) + { + //case 0x10: //Linux 32 bit syscall trap + case 0x6d: //Linux 64 bit syscall trap + tc->syscall(tc->readIntReg(1)); + break; + default: + SparcLiveProcess::handleTrap(trapNum, tc); + } } diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh index e212de973..6c7f30a43 100644 --- a/src/arch/sparc/linux/process.hh +++ b/src/arch/sparc/linux/process.hh @@ -38,12 +38,34 @@ namespace SparcISA { +//This contains all of the common elements of a SPARC Linux process which +//are not shared by other operating systems. The rest come from the common +//SPARC process class. +class SparcLinuxProcess +{ + public: + SparcLinuxProcess(); + + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; + + /// Array of 32 bit compatibility syscall descriptors, + /// indexed by call number. + static SyscallDesc syscall32Descs[]; + + SyscallDesc* getDesc(int callnum); + SyscallDesc* getDesc32(int callnum); + + const int Num_Syscall_Descs; + const int Num_Syscall32_Descs; +}; + /// A process with emulated SPARC/Linux syscalls. -class SparcLinuxProcess : public SparcLiveProcess +class Sparc32LinuxProcess : public SparcLinuxProcess, public Sparc32LiveProcess { public: /// Constructor. - SparcLinuxProcess(const std::string &name, + Sparc32LinuxProcess(const std::string &name, ObjectFile *objFile, System * system, int stdin_fd, int stdout_fd, int stderr_fd, @@ -54,19 +76,40 @@ class SparcLinuxProcess : public SparcLiveProcess uint64_t _gid, uint64_t _egid, uint64_t _pid, uint64_t _ppid); - virtual SyscallDesc* getDesc(int callnum); + SyscallDesc* getDesc(int callnum) + { + return SparcLinuxProcess::getDesc32(callnum); + } - /// The target system's hostname. - static const char *hostname; + void handleTrap(int trapNum, ThreadContext *tc); +}; - /// Array of syscall descriptors, indexed by call number. - static SyscallDesc syscallDescs[]; +/// A process with emulated 32 bit SPARC/Linux syscalls. +class Sparc64LinuxProcess : public SparcLinuxProcess, public Sparc64LiveProcess +{ + public: + /// Constructor. + Sparc64LinuxProcess(const std::string &name, + ObjectFile *objFile, + System * system, + int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid); - const int Num_Syscall_Descs; + SyscallDesc* getDesc(int callnum) + { + return SparcLinuxProcess::getDesc(callnum); + } + + void handleTrap(int trapNum, ThreadContext *tc); }; SyscallReturn getresuidFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); } // namespace SparcISA -#endif // __ALPHA_LINUX_PROCESS_HH__ +#endif // __SPARC_LINUX_PROCESS_HH__ diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc new file mode 100644 index 000000000..03c8bafe2 --- /dev/null +++ b/src/arch/sparc/linux/syscalls.cc @@ -0,0 +1,681 @@ +/* + * 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 + */ + +#include "arch/sparc/linux/process.hh" +#include "arch/sparc/syscallreturn.hh" +#include "sim/syscall_emul.hh" + +class LiveProcess; +class ThreadContext; + +namespace SparcISA { + +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0)); + + strcpy(name->sysname, "Linux"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "2.6.12-9-sparc64"); + strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); + strcpy(name->machine, "sparc"); + + name.copyOut(tc->getMemPort()); + + return 0; +} + + +SyscallReturn getresuidFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc) +{ + const IntReg id = htog(100); + Addr ruid = tc->getSyscallArg(0); + Addr euid = tc->getSyscallArg(1); + Addr suid = tc->getSyscallArg(2); + //Handle the EFAULT case + //Set the ruid + if(ruid) + { + BufferArg ruidBuff(ruid, sizeof(IntReg)); + memcpy(ruidBuff.bufferPtr(), &id, sizeof(IntReg)); + ruidBuff.copyOut(tc->getMemPort()); + } + //Set the euid + if(euid) + { + BufferArg euidBuff(euid, sizeof(IntReg)); + memcpy(euidBuff.bufferPtr(), &id, sizeof(IntReg)); + euidBuff.copyOut(tc->getMemPort()); + } + //Set the suid + if(suid) + { + BufferArg suidBuff(suid, sizeof(IntReg)); + memcpy(suidBuff.bufferPtr(), &id, sizeof(IntReg)); + suidBuff.copyOut(tc->getMemPort()); + } + return 0; +} + +SyscallDesc SparcLinuxProcess::syscall32Descs[] = { + /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc), + /* 1 */ SyscallDesc("exit", exitFunc), //32 bit + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), + /* 4 */ SyscallDesc("write", writeFunc), + /* 5 */ SyscallDesc("open", openFunc<Sparc32Linux>), //32 bit + /* 6 */ SyscallDesc("close", closeFunc), + /* 7 */ SyscallDesc("wait4", unimplementedFunc), //32 bit + /* 8 */ SyscallDesc("creat", unimplementedFunc), //32 bit + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unlinkFunc), + /* 11 */ SyscallDesc("execv", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("chown", chownFunc), //32 bit + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", unimplementedFunc), + /* 16 */ SyscallDesc("lchown", unimplementedFunc), //32 bit + /* 17 */ SyscallDesc("brk", obreakFunc), + /* 18 */ SyscallDesc("perfctr", unimplementedFunc), //32 bit + /* 19 */ SyscallDesc("lseek", lseekFunc), //32 bit + /* 20 */ SyscallDesc("getpid", getpidFunc), + /* 21 */ SyscallDesc("capget", unimplementedFunc), + /* 22 */ SyscallDesc("capset", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", setuidFunc), //32 bit + /* 24 */ SyscallDesc("getuid", getuidFunc), //32 bit + /* 25 */ SyscallDesc("time", unimplementedFunc), + /* 26 */ SyscallDesc("ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("alarm", unimplementedFunc), + /* 28 */ SyscallDesc("sigaltstack", unimplementedFunc), //32 bit + /* 29 */ SyscallDesc("pause", unimplementedFunc), //32 bit + /* 30 */ SyscallDesc("utime", unimplementedFunc), + /* 31 */ SyscallDesc("lchown32", unimplementedFunc), + /* 32 */ SyscallDesc("fchown32", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), //32 bit + /* 34 */ SyscallDesc("nice", unimplementedFunc), //32 bit + /* 35 */ SyscallDesc("chown32", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", unimplementedFunc), //32 bit + /* 38 */ SyscallDesc("stat", unimplementedFunc), + /* 39 */ SyscallDesc("sendfile", unimplementedFunc), //32 bit + /* 40 */ SyscallDesc("lstat", unimplementedFunc), + /* 41 */ SyscallDesc("dup", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", pipePseudoFunc), + /* 43 */ SyscallDesc("times", ignoreFunc), + /* 44 */ SyscallDesc("getuid32", unimplementedFunc), + /* 45 */ SyscallDesc("umount2", unimplementedFunc), //32 bit + /* 46 */ SyscallDesc("setgid", unimplementedFunc), //32 bit + /* 47 */ SyscallDesc("getgid", getgidFunc), //32 bit + /* 48 */ SyscallDesc("signal", unimplementedFunc), //32 bit + /* 49 */ SyscallDesc("geteuid", geteuidFunc), //32 bit + /* 50 */ SyscallDesc("getegid", getegidFunc), //32 bit + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("memory_ordering", unimplementedFunc), + /* 53 */ SyscallDesc("getgid32", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", unimplementedFunc), + /* 55 */ SyscallDesc("reboot", unimplementedFunc), //32 bit + /* 56 */ SyscallDesc("mmap2", unimplementedFunc), //32 bit + /* 57 */ SyscallDesc("symlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", unimplementedFunc), //32 bit + /* 59 */ SyscallDesc("execve", unimplementedFunc), //32 bit + /* 60 */ SyscallDesc("umask", unimplementedFunc), //32 bit + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("fstat", unimplementedFunc), + /* 63 */ SyscallDesc("fstat64", fstat64Func<Sparc32Linux>), + /* 64 */ SyscallDesc("getpagesize", unimplementedFunc), + /* 65 */ SyscallDesc("msync", unimplementedFunc), //32 bit + /* 66 */ SyscallDesc("vfork", unimplementedFunc), + /* 67 */ SyscallDesc("pread64", unimplementedFunc), //32 bit + /* 68 */ SyscallDesc("pwrite64", unimplementedFunc), //32 bit + /* 69 */ SyscallDesc("geteuid32", unimplementedFunc), + /* 70 */ SyscallDesc("getegid32", unimplementedFunc), + /* 71 */ SyscallDesc("mmap", mmapFunc<Sparc32Linux>), + /* 72 */ SyscallDesc("setreuid32", unimplementedFunc), + /* 73 */ SyscallDesc("munmap", munmapFunc), + /* 74 */ SyscallDesc("mprotect", unimplementedFunc), + /* 75 */ SyscallDesc("madvise", unimplementedFunc), + /* 76 */ SyscallDesc("vhangup", unimplementedFunc), + /* 77 */ SyscallDesc("truncate64", unimplementedFunc), //32 bit + /* 78 */ SyscallDesc("mincore", unimplementedFunc), + /* 79 */ SyscallDesc("getgroups", unimplementedFunc), //32 bit + /* 80 */ SyscallDesc("setgroups", unimplementedFunc), //32 bit + /* 81 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 82 */ SyscallDesc("setgroups32", unimplementedFunc), //32 bit + /* 83 */ SyscallDesc("setitimer", unimplementedFunc), //32 bit + /* 84 */ SyscallDesc("ftruncate64", unimplementedFunc), //32 bit + /* 85 */ SyscallDesc("swapon", unimplementedFunc), //32 bit + /* 86 */ SyscallDesc("getitimer", unimplementedFunc), //32 bit + /* 87 */ SyscallDesc("setuid32", unimplementedFunc), + /* 88 */ SyscallDesc("sethostname", unimplementedFunc), //32 bit + /* 89 */ SyscallDesc("setgid32", unimplementedFunc), + /* 90 */ SyscallDesc("dup2", unimplementedFunc), + /* 91 */ SyscallDesc("setfsuid32", unimplementedFunc), + /* 92 */ SyscallDesc("fcntl", unimplementedFunc), + /* 93 */ SyscallDesc("select", unimplementedFunc), //32 bit + /* 94 */ SyscallDesc("setfsgid32", unimplementedFunc), + /* 95 */ SyscallDesc("fsync", unimplementedFunc), + /* 96 */ SyscallDesc("setpriority", unimplementedFunc), //32 bit + /* 97 */ SyscallDesc("socket", unimplementedFunc), + /* 98 */ SyscallDesc("connect", unimplementedFunc), + /* 99 */ SyscallDesc("accept", unimplementedFunc), + /* 100 */ SyscallDesc("getpriority", unimplementedFunc), //32 bit + /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc), //32 bit + /* 102 */ SyscallDesc("rt_sigaction", ignoreFunc), //32 bit + /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), //32 bit + /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc), //32 bit + /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), //32 bit + /* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 108 */ SyscallDesc("setresuid32", unimplementedFunc), + /* 109 */ SyscallDesc("getresuid32", getresuidFunc), + /* 110 */ SyscallDesc("setresgid32", unimplementedFunc), + /* 111 */ SyscallDesc("getresgid32", unimplementedFunc), + /* 112 */ SyscallDesc("setregid32", unimplementedFunc), + /* 113 */ SyscallDesc("revcmsg", unimplementedFunc), + /* 114 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 115 */ SyscallDesc("getgroups32", unimplementedFunc), //32 bit + /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc), //32 bit + /* 117 */ SyscallDesc("getrusage", unimplementedFunc), //32 bit + /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 119 */ SyscallDesc("getcwd", unimplementedFunc), + /* 120 */ SyscallDesc("readv", unimplementedFunc), + /* 121 */ SyscallDesc("writev", unimplementedFunc), + /* 122 */ SyscallDesc("settimeofday", unimplementedFunc), //32 bit + /* 123 */ SyscallDesc("fchown", unimplementedFunc), //32 bit + /* 124 */ SyscallDesc("fchmod", unimplementedFunc), + /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 126 */ SyscallDesc("setreuid", unimplementedFunc), //32 bit + /* 127 */ SyscallDesc("setregid", unimplementedFunc), //32 bit + /* 128 */ SyscallDesc("rename", renameFunc), + /* 129 */ SyscallDesc("truncate", unimplementedFunc), + /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 131 */ SyscallDesc("flock", unimplementedFunc), + /* 132 */ SyscallDesc("lstat64", unimplementedFunc), + /* 133 */ SyscallDesc("sendto", unimplementedFunc), + /* 134 */ SyscallDesc("shutdown", unimplementedFunc), + /* 135 */ SyscallDesc("socketpair", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", unimplementedFunc), //32 bit + /* 137 */ SyscallDesc("rmdir", unimplementedFunc), + /* 138 */ SyscallDesc("utimes", unimplementedFunc), //32 bit + /* 139 */ SyscallDesc("stat64", unimplementedFunc), + /* 140 */ SyscallDesc("sendfile64", unimplementedFunc), //32 bit + /* 141 */ SyscallDesc("getpeername", unimplementedFunc), + /* 142 */ SyscallDesc("futex", unimplementedFunc), //32 bit + /* 143 */ SyscallDesc("gettid", unimplementedFunc), + /* 144 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 145 */ SyscallDesc("setrlimit", unimplementedFunc), + /* 146 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 147 */ SyscallDesc("prctl", unimplementedFunc), //32 bit + /* 148 */ SyscallDesc("pciconfig_read", unimplementedFunc), + /* 149 */ SyscallDesc("pciconfig_write", unimplementedFunc), + /* 150 */ SyscallDesc("getsockname", unimplementedFunc), + /* 151 */ SyscallDesc("inotify_init", unimplementedFunc), + /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc), + /* 153 */ SyscallDesc("poll", unimplementedFunc), + /* 154 */ SyscallDesc("getdents64", unimplementedFunc), + /* 155 */ SyscallDesc("fcntl64", unimplementedFunc), + /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), + /* 157 */ SyscallDesc("statfs", unimplementedFunc), + /* 158 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 159 */ SyscallDesc("umount", unimplementedFunc), + /* 160 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 161 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 162 */ SyscallDesc("getdomainname", unimplementedFunc), //32 bit + /* 163 */ SyscallDesc("setdomainname", unimplementedFunc), //32 bit + /* 164 */ SyscallDesc("ni_syscall", unimplementedFunc), + /* 165 */ SyscallDesc("quotactl", unimplementedFunc), + /* 166 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 167 */ SyscallDesc("mount", unimplementedFunc), + /* 168 */ SyscallDesc("ustat", unimplementedFunc), + /* 169 */ SyscallDesc("setxattr", unimplementedFunc), //32 bit + /* 170 */ SyscallDesc("lsetxattr", unimplementedFunc), //32 bit + /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc), //32 bit + /* 172 */ SyscallDesc("getxattr", unimplementedFunc), + /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 174 */ SyscallDesc("getdents", unimplementedFunc), + /* 175 */ SyscallDesc("setsid", unimplementedFunc), + /* 176 */ SyscallDesc("fchdir", unimplementedFunc), + /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc), //32 bit + /* 178 */ SyscallDesc("listxattr", unimplementedFunc), + /* 179 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 180 */ SyscallDesc("flistxattr", unimplementedFunc), //32 bit + /* 181 */ SyscallDesc("removexattr", unimplementedFunc), + /* 182 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 183 */ SyscallDesc("sigpending", unimplementedFunc), + /* 184 */ SyscallDesc("query_module", unimplementedFunc), + /* 185 */ SyscallDesc("setpgid", unimplementedFunc), //32 bit + /* 186 */ SyscallDesc("fremovexattr", unimplementedFunc), //32 bit + /* 187 */ SyscallDesc("tkill", unimplementedFunc), //32 bit + /* 188 */ SyscallDesc("exit_group", exitFunc), //32 bit + /* 189 */ SyscallDesc("uname", unameFunc), + /* 190 */ SyscallDesc("init_module", unimplementedFunc), //32 bit + /* 191 */ SyscallDesc("personality", unimplementedFunc), + /* 192 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 193 */ SyscallDesc("epoll_create", unimplementedFunc), //32 bit + /* 194 */ SyscallDesc("epoll_ctl", unimplementedFunc), //32 bit + /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc), //32 bit + /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc), //32 bit + /* 197 */ SyscallDesc("getppid", getppidFunc), + /* 198 */ SyscallDesc("sigaction", unimplementedFunc), //32 bit + /* 199 */ SyscallDesc("sgetmask", unimplementedFunc), + /* 200 */ SyscallDesc("ssetmask", unimplementedFunc), + /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 202 */ SyscallDesc("oldlstat", unimplementedFunc), + /* 203 */ SyscallDesc("uselib", unimplementedFunc), + /* 204 */ SyscallDesc("readdir", unimplementedFunc), + /* 205 */ SyscallDesc("readahead", unimplementedFunc), //32 bit + /* 206 */ SyscallDesc("socketcall", unimplementedFunc), //32 bit + /* 207 */ SyscallDesc("syslog", unimplementedFunc), //32 bit + /* 208 */ SyscallDesc("lookup_dcookie", unimplementedFunc), //32 bit + /* 209 */ SyscallDesc("fadvise64", unimplementedFunc), //32 bit + /* 210 */ SyscallDesc("fadvise64_64", unimplementedFunc), //32 bit + /* 211 */ SyscallDesc("tgkill", unimplementedFunc), //32 bit + /* 212 */ SyscallDesc("waitpid", unimplementedFunc), //32 bit + /* 213 */ SyscallDesc("swapoff", unimplementedFunc), + /* 214 */ SyscallDesc("sysinfo", unimplementedFunc), //32 bit + /* 215 */ SyscallDesc("ipc", unimplementedFunc), //32 bit + /* 216 */ SyscallDesc("sigreturn", unimplementedFunc), //32 bit + /* 217 */ SyscallDesc("clone", unimplementedFunc), + /* 218 */ SyscallDesc("ioprio_get", unimplementedFunc), //32 bit + /* 219 */ SyscallDesc("adjtimex", unimplementedFunc), //32 bit + /* 220 */ SyscallDesc("sigprocmask", unimplementedFunc), //32 bit + /* 221 */ SyscallDesc("create_module", unimplementedFunc), + /* 222 */ SyscallDesc("delete_module", unimplementedFunc), //32 bit + /* 223 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 224 */ SyscallDesc("getpgid", unimplementedFunc), //32 bit + /* 225 */ SyscallDesc("bdflush", unimplementedFunc), //32 bit + /* 226 */ SyscallDesc("sysfs", unimplementedFunc), //32 bit + /* 227 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 228 */ SyscallDesc("setfsuid", unimplementedFunc), //32 bit + /* 229 */ SyscallDesc("setfsgid", unimplementedFunc), //32 bit + /* 230 */ SyscallDesc("_newselect", unimplementedFunc), //32 bit + /* 231 */ SyscallDesc("time", ignoreFunc), + /* 232 */ SyscallDesc("oldstat", unimplementedFunc), + /* 233 */ SyscallDesc("stime", unimplementedFunc), + /* 234 */ SyscallDesc("statfs64", unimplementedFunc), + /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc), + /* 236 */ SyscallDesc("_llseek", _llseekFunc), + /* 237 */ SyscallDesc("mlock", unimplementedFunc), + /* 238 */ SyscallDesc("munlock", unimplementedFunc), + /* 239 */ SyscallDesc("mlockall", unimplementedFunc), //32 bit + /* 240 */ SyscallDesc("munlockall", unimplementedFunc), + /* 241 */ SyscallDesc("sched_setparam", unimplementedFunc), //32 bit + /* 242 */ SyscallDesc("sched_getparam", unimplementedFunc), //32 bit + /* 243 */ SyscallDesc("sched_setscheduler", unimplementedFunc), //32 bit + /* 244 */ SyscallDesc("sched_getscheduler", unimplementedFunc), //32 bit + /* 245 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 246 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), //32 bit + /* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), //32 bit + /* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), //32 bit + /* 249 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 250 */ SyscallDesc("mremap", unimplementedFunc), //32 bit + /* 251 */ SyscallDesc("_sysctl", unimplementedFunc), //32 bit + /* 252 */ SyscallDesc("getsid", unimplementedFunc), //32 bit + /* 253 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 254 */ SyscallDesc("nfsservctl", unimplementedFunc), //32 bit + /* 255 */ SyscallDesc("aplib", unimplementedFunc), + /* 256 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 257 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 258 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 259 */ SyscallDesc("clock_nanosleep", unimplementedFunc), //32 bit + /* 260 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 261 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 262 */ SyscallDesc("timer_settime", unimplementedFunc), //32 bit + /* 263 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 264 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 265 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 266 */ SyscallDesc("timer_create", unimplementedFunc), + /* 267 */ SyscallDesc("vserver", unimplementedFunc), + /* 268 */ SyscallDesc("io_setup", unimplementedFunc), + /* 269 */ SyscallDesc("io_destroy", unimplementedFunc), + /* 270 */ SyscallDesc("io_submit", unimplementedFunc), //32 bit + /* 271 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 272 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 273 */ SyscallDesc("mq_open", unimplementedFunc), //32 bit + /* 274 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 275 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 276 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 277 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 278 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 279 */ SyscallDesc("waitid", unimplementedFunc), + /* 280 */ SyscallDesc("sys_setaltroot", unimplementedFunc), + /* 281 */ SyscallDesc("add_key", unimplementedFunc), + /* 282 */ SyscallDesc("request_key", unimplementedFunc), + /* 283 */ SyscallDesc("keyctl", unimplementedFunc), + /* 284 */ SyscallDesc("openat", unimplementedFunc), + /* 285 */ SyscallDesc("mkdirat", unimplementedFunc), + /* 286 */ SyscallDesc("mknodat", unimplementedFunc), + /* 287 */ SyscallDesc("fchownat", unimplementedFunc), + /* 288 */ SyscallDesc("futimesat", unimplementedFunc), + /* 289 */ SyscallDesc("fstatat64", unimplementedFunc), + /* 290 */ SyscallDesc("unlinkat", unimplementedFunc), + /* 291 */ SyscallDesc("renameat", unimplementedFunc), + /* 292 */ SyscallDesc("linkat", unimplementedFunc), + /* 293 */ SyscallDesc("symlinkat", unimplementedFunc), + /* 294 */ SyscallDesc("readlinkat", unimplementedFunc), + /* 295 */ SyscallDesc("fchmodat", unimplementedFunc), + /* 296 */ SyscallDesc("faccessat", unimplementedFunc), + /* 297 */ SyscallDesc("pselect6", unimplementedFunc), + /* 298 */ SyscallDesc("ppoll", unimplementedFunc), + /* 299 */ SyscallDesc("unshare", unimplementedFunc) +}; + +SyscallDesc SparcLinuxProcess::syscallDescs[] = { + /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc), + /* 1 */ SyscallDesc("exit", exitFunc), + /* 2 */ SyscallDesc("fork", unimplementedFunc), + /* 3 */ SyscallDesc("read", readFunc), + /* 4 */ SyscallDesc("write", writeFunc), + /* 5 */ SyscallDesc("open", openFunc<SparcLinux>), + /* 6 */ SyscallDesc("close", closeFunc), + /* 7 */ SyscallDesc("wait4", unimplementedFunc), + /* 8 */ SyscallDesc("creat", unimplementedFunc), + /* 9 */ SyscallDesc("link", unimplementedFunc), + /* 10 */ SyscallDesc("unlink", unlinkFunc), + /* 11 */ SyscallDesc("execv", unimplementedFunc), + /* 12 */ SyscallDesc("chdir", unimplementedFunc), + /* 13 */ SyscallDesc("chown", chownFunc), + /* 14 */ SyscallDesc("mknod", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>), + /* 16 */ SyscallDesc("lchown", unimplementedFunc), + /* 17 */ SyscallDesc("brk", obreakFunc), + /* 18 */ SyscallDesc("perfctr", unimplementedFunc), + /* 19 */ SyscallDesc("lseek", lseekFunc), + /* 20 */ SyscallDesc("getpid", getpidFunc), + /* 21 */ SyscallDesc("capget", unimplementedFunc), + /* 22 */ SyscallDesc("capset", unimplementedFunc), + /* 23 */ SyscallDesc("setuid", setuidFunc), + /* 24 */ SyscallDesc("getuid", getuidFunc), + /* 25 */ SyscallDesc("time", unimplementedFunc), + /* 26 */ SyscallDesc("ptrace", unimplementedFunc), + /* 27 */ SyscallDesc("alarm", unimplementedFunc), + /* 28 */ SyscallDesc("sigaltstack", unimplementedFunc), + /* 29 */ SyscallDesc("pause", unimplementedFunc), + /* 30 */ SyscallDesc("utime", unimplementedFunc), + /* 31 */ SyscallDesc("lchown32", unimplementedFunc), + /* 32 */ SyscallDesc("fchown32", unimplementedFunc), + /* 33 */ SyscallDesc("access", unimplementedFunc), + /* 34 */ SyscallDesc("nice", unimplementedFunc), + /* 35 */ SyscallDesc("chown32", unimplementedFunc), + /* 36 */ SyscallDesc("sync", unimplementedFunc), + /* 37 */ SyscallDesc("kill", unimplementedFunc), + /* 38 */ SyscallDesc("stat", unimplementedFunc), + /* 39 */ SyscallDesc("sendfile", unimplementedFunc), + /* 40 */ SyscallDesc("lstat", unimplementedFunc), + /* 41 */ SyscallDesc("dup", unimplementedFunc), + /* 42 */ SyscallDesc("pipe", pipePseudoFunc), + /* 43 */ SyscallDesc("times", ignoreFunc), + /* 44 */ SyscallDesc("getuid32", unimplementedFunc), + /* 45 */ SyscallDesc("umount2", unimplementedFunc), + /* 46 */ SyscallDesc("setgid", unimplementedFunc), + /* 47 */ SyscallDesc("getgid", getgidFunc), + /* 48 */ SyscallDesc("signal", unimplementedFunc), + /* 49 */ SyscallDesc("geteuid", geteuidFunc), + /* 50 */ SyscallDesc("getegid", getegidFunc), + /* 51 */ SyscallDesc("acct", unimplementedFunc), + /* 52 */ SyscallDesc("memory_ordering", unimplementedFunc), + /* 53 */ SyscallDesc("getgid32", unimplementedFunc), + /* 54 */ SyscallDesc("ioctl", unimplementedFunc), + /* 55 */ SyscallDesc("reboot", unimplementedFunc), + /* 56 */ SyscallDesc("mmap2", unimplementedFunc), + /* 57 */ SyscallDesc("symlink", unimplementedFunc), + /* 58 */ SyscallDesc("readlink", unimplementedFunc), + /* 59 */ SyscallDesc("execve", unimplementedFunc), + /* 60 */ SyscallDesc("umask", unimplementedFunc), + /* 61 */ SyscallDesc("chroot", unimplementedFunc), + /* 62 */ SyscallDesc("fstat", fstatFunc<SparcLinux>), + /* 63 */ SyscallDesc("fstat64", unimplementedFunc), + /* 64 */ SyscallDesc("getpagesize", unimplementedFunc), + /* 65 */ SyscallDesc("msync", unimplementedFunc), + /* 66 */ SyscallDesc("vfork", unimplementedFunc), + /* 67 */ SyscallDesc("pread64", unimplementedFunc), + /* 68 */ SyscallDesc("pwrite64", unimplementedFunc), + /* 69 */ SyscallDesc("geteuid32", unimplementedFunc), + /* 70 */ SyscallDesc("getegid32", unimplementedFunc), + /* 71 */ SyscallDesc("mmap", mmapFunc<SparcLinux>), + /* 72 */ SyscallDesc("setreuid32", unimplementedFunc), + /* 73 */ SyscallDesc("munmap", munmapFunc), + /* 74 */ SyscallDesc("mprotect", unimplementedFunc), + /* 75 */ SyscallDesc("madvise", unimplementedFunc), + /* 76 */ SyscallDesc("vhangup", unimplementedFunc), + /* 77 */ SyscallDesc("truncate64", unimplementedFunc), + /* 78 */ SyscallDesc("mincore", unimplementedFunc), + /* 79 */ SyscallDesc("getgroups", unimplementedFunc), + /* 80 */ SyscallDesc("setgroups", unimplementedFunc), + /* 81 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 82 */ SyscallDesc("setgroups32", unimplementedFunc), + /* 83 */ SyscallDesc("setitimer", unimplementedFunc), + /* 84 */ SyscallDesc("ftruncate64", unimplementedFunc), + /* 85 */ SyscallDesc("swapon", unimplementedFunc), + /* 86 */ SyscallDesc("getitimer", unimplementedFunc), + /* 87 */ SyscallDesc("setuid32", unimplementedFunc), + /* 88 */ SyscallDesc("sethostname", unimplementedFunc), + /* 89 */ SyscallDesc("setgid32", unimplementedFunc), + /* 90 */ SyscallDesc("dup2", unimplementedFunc), + /* 91 */ SyscallDesc("setfsuid32", unimplementedFunc), + /* 92 */ SyscallDesc("fcntl", unimplementedFunc), + /* 93 */ SyscallDesc("select", unimplementedFunc), + /* 94 */ SyscallDesc("setfsgid32", unimplementedFunc), + /* 95 */ SyscallDesc("fsync", unimplementedFunc), + /* 96 */ SyscallDesc("setpriority", unimplementedFunc), + /* 97 */ SyscallDesc("socket", unimplementedFunc), + /* 98 */ SyscallDesc("connect", unimplementedFunc), + /* 99 */ SyscallDesc("accept", unimplementedFunc), + /* 100 */ SyscallDesc("getpriority", unimplementedFunc), + /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc), + /* 102 */ SyscallDesc("rt_sigaction", ignoreFunc), + /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), + /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc), + /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), + /* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 108 */ SyscallDesc("setresuid", unimplementedFunc), + /* 109 */ SyscallDesc("getresuid", getresuidFunc), + /* 110 */ SyscallDesc("setresgid", unimplementedFunc), + /* 111 */ SyscallDesc("getresgid", unimplementedFunc), + /* 112 */ SyscallDesc("setregid32", unimplementedFunc), + /* 113 */ SyscallDesc("recvmsg", unimplementedFunc), + /* 114 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 115 */ SyscallDesc("getgroups32", unimplementedFunc), + /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc), + /* 117 */ SyscallDesc("getrusage", unimplementedFunc), + /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 119 */ SyscallDesc("getcwd", unimplementedFunc), + /* 120 */ SyscallDesc("readv", unimplementedFunc), + /* 121 */ SyscallDesc("writev", unimplementedFunc), + /* 122 */ SyscallDesc("settimeofday", unimplementedFunc), + /* 123 */ SyscallDesc("fchown", unimplementedFunc), + /* 124 */ SyscallDesc("fchmod", unimplementedFunc), + /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 126 */ SyscallDesc("setreuid", unimplementedFunc), + /* 127 */ SyscallDesc("setregid", unimplementedFunc), + /* 128 */ SyscallDesc("rename", renameFunc), + /* 129 */ SyscallDesc("truncate", unimplementedFunc), + /* 130 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 131 */ SyscallDesc("flock", unimplementedFunc), + /* 132 */ SyscallDesc("lstat64", unimplementedFunc), + /* 133 */ SyscallDesc("sendto", unimplementedFunc), + /* 134 */ SyscallDesc("shutdown", unimplementedFunc), + /* 135 */ SyscallDesc("socketpair", unimplementedFunc), + /* 136 */ SyscallDesc("mkdir", unimplementedFunc), + /* 137 */ SyscallDesc("rmdir", unimplementedFunc), + /* 138 */ SyscallDesc("utimes", unimplementedFunc), + /* 139 */ SyscallDesc("stat64", unimplementedFunc), + /* 140 */ SyscallDesc("sendfile64", unimplementedFunc), + /* 141 */ SyscallDesc("getpeername", unimplementedFunc), + /* 142 */ SyscallDesc("futex", unimplementedFunc), + /* 143 */ SyscallDesc("gettid", unimplementedFunc), + /* 144 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 145 */ SyscallDesc("setrlimit", unimplementedFunc), + /* 146 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 147 */ SyscallDesc("prctl", unimplementedFunc), + /* 148 */ SyscallDesc("pciconfig_read", unimplementedFunc), + /* 149 */ SyscallDesc("pciconfig_write", unimplementedFunc), + /* 150 */ SyscallDesc("getsockname", unimplementedFunc), + /* 151 */ SyscallDesc("inotify_init", unimplementedFunc), + /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc), + /* 153 */ SyscallDesc("poll", unimplementedFunc), + /* 154 */ SyscallDesc("getdents64", unimplementedFunc), + /* 155 */ SyscallDesc("fcntl64", unimplementedFunc), + /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), + /* 157 */ SyscallDesc("statfs", unimplementedFunc), + /* 158 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 159 */ SyscallDesc("umount", unimplementedFunc), + /* 160 */ SyscallDesc("sched_set_affinity", unimplementedFunc), + /* 161 */ SyscallDesc("sched_get_affinity", unimplementedFunc), + /* 162 */ SyscallDesc("getdomainname", unimplementedFunc), + /* 163 */ SyscallDesc("setdomainname", unimplementedFunc), + /* 164 */ SyscallDesc("utrap_install", unimplementedFunc), + /* 165 */ SyscallDesc("quotactl", unimplementedFunc), + /* 166 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 167 */ SyscallDesc("mount", unimplementedFunc), + /* 168 */ SyscallDesc("ustat", unimplementedFunc), + /* 169 */ SyscallDesc("setxattr", unimplementedFunc), + /* 170 */ SyscallDesc("lsetxattr", unimplementedFunc), + /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc), + /* 172 */ SyscallDesc("getxattr", unimplementedFunc), + /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 174 */ SyscallDesc("getdents", unimplementedFunc), + /* 175 */ SyscallDesc("setsid", unimplementedFunc), + /* 176 */ SyscallDesc("fchdir", unimplementedFunc), + /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc), + /* 178 */ SyscallDesc("listxattr", unimplementedFunc), + /* 179 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 180 */ SyscallDesc("flistxattr", unimplementedFunc), + /* 181 */ SyscallDesc("removexattr", unimplementedFunc), + /* 182 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 183 */ SyscallDesc("sigpending", unimplementedFunc), + /* 184 */ SyscallDesc("query_module", unimplementedFunc), + /* 185 */ SyscallDesc("setpgid", unimplementedFunc), + /* 186 */ SyscallDesc("fremovexattr", unimplementedFunc), + /* 187 */ SyscallDesc("tkill", unimplementedFunc), + /* 188 */ SyscallDesc("exit_group", exitFunc), + /* 189 */ SyscallDesc("uname", unameFunc), + /* 190 */ SyscallDesc("init_module", unimplementedFunc), + /* 191 */ SyscallDesc("personality", unimplementedFunc), + /* 192 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 193 */ SyscallDesc("epoll_create", unimplementedFunc), + /* 194 */ SyscallDesc("epoll_ctl", unimplementedFunc), + /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc), + /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc), + /* 197 */ SyscallDesc("getppid", getppidFunc), + /* 198 */ SyscallDesc("sigaction", ignoreFunc), + /* 199 */ SyscallDesc("sgetmask", unimplementedFunc), + /* 200 */ SyscallDesc("ssetmask", unimplementedFunc), + /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc), + /* 202 */ SyscallDesc("oldlstat", unimplementedFunc), + /* 203 */ SyscallDesc("uselib", unimplementedFunc), + /* 204 */ SyscallDesc("readdir", unimplementedFunc), + /* 205 */ SyscallDesc("readahead", unimplementedFunc), + /* 206 */ SyscallDesc("socketcall", unimplementedFunc), + /* 207 */ SyscallDesc("syslog", unimplementedFunc), + /* 208 */ SyscallDesc("lookup_dcookie", unimplementedFunc), + /* 209 */ SyscallDesc("fadvise64", unimplementedFunc), + /* 210 */ SyscallDesc("fadvise64_64", unimplementedFunc), + /* 211 */ SyscallDesc("tgkill", unimplementedFunc), + /* 212 */ SyscallDesc("waitpid", unimplementedFunc), + /* 213 */ SyscallDesc("swapoff", unimplementedFunc), + /* 214 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 215 */ SyscallDesc("ipc", unimplementedFunc), + /* 216 */ SyscallDesc("sigreturn", unimplementedFunc), + /* 217 */ SyscallDesc("clone", unimplementedFunc), + /* 218 */ SyscallDesc("ioprio_get", unimplementedFunc), + /* 219 */ SyscallDesc("adjtimex", unimplementedFunc), + /* 220 */ SyscallDesc("sigprocmask", unimplementedFunc), + /* 221 */ SyscallDesc("create_module", unimplementedFunc), + /* 222 */ SyscallDesc("delete_module", unimplementedFunc), + /* 223 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 224 */ SyscallDesc("getpgid", unimplementedFunc), + /* 225 */ SyscallDesc("bdflush", unimplementedFunc), + /* 226 */ SyscallDesc("sysfs", unimplementedFunc), + /* 227 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 228 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 229 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 230 */ SyscallDesc("_newselect", unimplementedFunc), + /* 231 */ SyscallDesc("time", ignoreFunc), + /* 232 */ SyscallDesc("oldstat", unimplementedFunc), + /* 233 */ SyscallDesc("stime", unimplementedFunc), + /* 234 */ SyscallDesc("statfs64", unimplementedFunc), + /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc), + /* 236 */ SyscallDesc("_llseek", _llseekFunc), + /* 237 */ SyscallDesc("mlock", unimplementedFunc), + /* 238 */ SyscallDesc("munlock", unimplementedFunc), + /* 239 */ SyscallDesc("mlockall", unimplementedFunc), + /* 240 */ SyscallDesc("munlockall", unimplementedFunc), + /* 241 */ SyscallDesc("sched_setparam", unimplementedFunc), + /* 242 */ SyscallDesc("sched_getparam", unimplementedFunc), + /* 243 */ SyscallDesc("sched_setscheduler", unimplementedFunc), + /* 244 */ SyscallDesc("sched_getscheduler", unimplementedFunc), + /* 245 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 246 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), + /* 247 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), + /* 248 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), + /* 249 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 250 */ SyscallDesc("mremap", unimplementedFunc), + /* 251 */ SyscallDesc("_sysctl", unimplementedFunc), + /* 252 */ SyscallDesc("getsid", unimplementedFunc), + /* 253 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 254 */ SyscallDesc("nfsservctl", unimplementedFunc), + /* 255 */ SyscallDesc("aplib", unimplementedFunc), + /* 256 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 257 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 258 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 259 */ SyscallDesc("clock_nanosleep", unimplementedFunc), + /* 260 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 261 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 262 */ SyscallDesc("timer_settime", unimplementedFunc), + /* 263 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 264 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 265 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 266 */ SyscallDesc("timer_create", unimplementedFunc), + /* 267 */ SyscallDesc("vserver", unimplementedFunc), + /* 268 */ SyscallDesc("io_setup", unimplementedFunc), + /* 269 */ SyscallDesc("io_destroy", unimplementedFunc), + /* 270 */ SyscallDesc("io_submit", unimplementedFunc), + /* 271 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 272 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 273 */ SyscallDesc("mq_open", unimplementedFunc), + /* 274 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 275 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 276 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 277 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 278 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 279 */ SyscallDesc("waitid", unimplementedFunc), + /* 280 */ SyscallDesc("sys_setaltroot", unimplementedFunc), + /* 281 */ SyscallDesc("add_key", unimplementedFunc), + /* 282 */ SyscallDesc("request_key", unimplementedFunc), + /* 283 */ SyscallDesc("keyctl", unimplementedFunc) +}; + +} // namespace SparcISA diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 8b612e8b4..5bd572d38 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -54,7 +54,15 @@ string SparcISA::getMiscRegName(RegIndex index) "wstate",*/ "gl", "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg", "hstick_cmpr", - "fsr"}; + "fsr", "prictx", "secctx", "partId", "lsuCtrlReg", "itbTsbC0Ps0", + "itbTsbC0Ps1", "iTlbC0Cnfg", "itbTsbCXPs0", "itbTsbCXPs1", + "iTlbCXCnfg","iTlbSfsr", "iTlbTagAcs", "dtbTsbC0Ps0", + "dtbTsbC0Ps1", "dTlbC0Cnfg", "dtbTsbCXPs0", "dtbTsbCXPs1", + "dTlbCXCnfg","dTlbSfsr", "dTlbSfar", "dTlbTagAcs", + "scratch0", "scratch1", "scratch2", "scratch3", "scratch4", + "scratch5", "scratch6", "scratch7", "cpuMondoHead", "cpuMondoTail", + "devMondoHead", "devMondoTail", "resErrorHead", "resErrorTail", + "nresErrorHead", "nresErrorTail", "TlbData" }; return miscRegName[index]; } @@ -132,7 +140,7 @@ void MiscRegFile::clear() #endif } -MiscReg MiscRegFile::readReg(int miscReg) +MiscReg MiscRegFile::readRegNoEffect(int miscReg) { switch (miscReg) { case MISCREG_TLB_DATA: @@ -223,8 +231,6 @@ MiscReg MiscRegFile::readReg(int miscReg) return hintp; 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: @@ -317,7 +323,7 @@ MiscReg MiscRegFile::readReg(int miscReg) } } -MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) +MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) { switch (miscReg) { // tick and stick are aliased to each other in niagra @@ -360,7 +366,7 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) case MISCREG_QUEUE_NRES_ERROR_TAIL: #if FULL_SYSTEM case MISCREG_HPSTATE: - return readFSRegWithEffect(miscReg, tc); + return readFSReg(miscReg, tc); #else case MISCREG_HPSTATE: //HPSTATE is special because because sometimes in privilege checks for instructions @@ -372,10 +378,10 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) #endif } - return readReg(miscReg); + return readRegNoEffect(miscReg); } -void MiscRegFile::setReg(int miscReg, const MiscReg &val) +void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val) { switch (miscReg) { // case MISCREG_Y: @@ -602,13 +608,12 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val) case MISCREG_QUEUE_NRES_ERROR_TAIL: nres_error_tail = val; break; - default: panic("Miscellaneous register %d not implemented\n", miscReg); } } -void MiscRegFile::setRegWithEffect(int miscReg, +void MiscRegFile::setReg(int miscReg, const MiscReg &val, ThreadContext * tc) { MiscReg new_val = val; @@ -633,9 +638,20 @@ void MiscRegFile::setRegWithEffect(int miscReg, return; case MISCREG_TL: tl = val; +#if FULL_SYSTEM + if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv)) + tc->getCpuPtr()->post_interrupt(IT_TRAP_LEVEL_ZERO,0); + else + tc->getCpuPtr()->clear_interrupt(IT_TRAP_LEVEL_ZERO,0); +#endif return; case MISCREG_CWP: - new_val = val > NWindows ? NWindows - 1 : val; + new_val = val >= NWindows ? NWindows - 1 : val; + if (val >= NWindows) { + new_val = NWindows - 1; + warn("Attempted to set the CWP to %d with NWindows = %d\n", + val, NWindows); + } tc->changeRegFileContext(CONTEXT_CWP, new_val); break; case MISCREG_GL: @@ -663,7 +679,7 @@ void MiscRegFile::setRegWithEffect(int miscReg, case MISCREG_QUEUE_NRES_ERROR_TAIL: #if FULL_SYSTEM case MISCREG_HPSTATE: - setFSRegWithEffect(miscReg, val, tc); + setFSReg(miscReg, val, tc); return; #else case MISCREG_HPSTATE: @@ -673,7 +689,7 @@ void MiscRegFile::setRegWithEffect(int miscReg, panic("Accessing Fullsystem register %s to %#x in SE mode\n", getMiscRegName(miscReg), val); #endif } - setReg(miscReg, new_val); + setRegNoEffect(miscReg, new_val); } void MiscRegFile::serialize(std::ostream & os) diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 66c9f17df..867f959e1 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -39,6 +39,8 @@ #include <string> +class Checkpoint; + namespace SparcISA { //These functions map register indices to names @@ -161,6 +163,23 @@ namespace SparcISA const static int ie = 0x2; }; + struct STS { + const static int st_idle = 0x00; + const static int st_wait = 0x01; + const static int st_halt = 0x02; + const static int st_run = 0x05; + const static int st_spec_run = 0x07; + const static int st_spec_rdy = 0x13; + const static int st_ready = 0x19; + const static int active = 0x01; + const static int speculative = 0x04; + const static int shft_id = 8; + const static int shft_fsm0 = 31; + const static int shft_fsm1 = 26; + const static int shft_fsm2 = 21; + const static int shft_fsm3 = 16; + }; + const int NumMiscArchRegs = MISCREG_NUMMISCREGS; const int NumMiscRegs = MISCREG_NUMMISCREGS; @@ -255,9 +274,11 @@ namespace SparcISA // 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 - void setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext *tc); - MiscReg readFSRegWithEffect(int miscReg, ThreadContext * tc); + void setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc); + MiscReg readFSReg(int miscReg, ThreadContext * tc); + + // Update interrupt state on softint or pil change + void checkSoftInt(ThreadContext *tc); /** Process a tick compare event and generate an interrupt on the cpu if * appropriate. */ @@ -286,13 +307,13 @@ namespace SparcISA clear(); } - MiscReg readReg(int miscReg); + MiscReg readRegNoEffect(int miscReg); - MiscReg readRegWithEffect(int miscReg, ThreadContext *tc); + MiscReg readReg(int miscReg, ThreadContext *tc); - void setReg(int miscReg, const MiscReg &val); + void setRegNoEffect(int miscReg, const MiscReg &val); - void setRegWithEffect(int miscReg, + void setReg(int miscReg, const MiscReg &val, ThreadContext * tc); int getInstAsid() diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh index fc01e82da..980225052 100644 --- a/src/arch/sparc/pagetable.hh +++ b/src/arch/sparc/pagetable.hh @@ -45,6 +45,22 @@ struct VAddr VAddr(Addr a) { panic("not implemented yet."); } }; +class TteTag +{ + private: + uint64_t entry; + bool populated; + + public: + TteTag() : entry(0), populated(false) {} + TteTag(uint64_t e) : entry(e), populated(true) {} + const TteTag &operator=(uint64_t e) { populated = true; + entry = e; return *this; } + bool valid() const {assert(populated); return !bits(entry,62,62); } + Addr va() const {assert(populated); return bits(entry,41,0); } +}; + + class PageTableEntry { public: @@ -110,13 +126,14 @@ class PageTableEntry entry4u = e; return *this; } const PageTableEntry &operator=(const PageTableEntry &e) - { populated = true; entry4u = e.entry4u; return *this; } + { populated = true; entry4u = e.entry4u; type = e.type; return *this; } bool valid() const { return bits(entry4u,63,63) && populated; } uint8_t _size() const { assert(populated); return bits(entry4u, 62,61) | bits(entry4u, 48,48) << 2; } Addr size() const { assert(_size() < 6); return pageSizes[_size()]; } + Addr sizeMask() const { assert(_size() < 6); return pageSizes[_size()]-1;} bool ie() const { return bits(entry4u, 59,59); } Addr pfn() const { assert(populated); return bits(entry4u,39,13); } Addr paddr() const { assert(populated); return mbits(entry4u, 39,13);} @@ -127,6 +144,8 @@ class PageTableEntry bool writable() const { assert(populated); return bits(entry4u,1,1); } bool nofault() const { assert(populated); return bits(entry4u,60,60); } bool sideffect() const { assert(populated); return bits(entry4u,3,3); } + Addr paddrMask() const { assert(populated); + return mbits(entry4u, 39,13) & ~sizeMask(); } }; struct TlbRange { diff --git a/src/arch/sparc/predecoder.hh b/src/arch/sparc/predecoder.hh new file mode 100644 index 000000000..4a8c9dc4a --- /dev/null +++ b/src/arch/sparc/predecoder.hh @@ -0,0 +1,113 @@ +/* + * 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: Gabe Black + */ + +#ifndef __ARCH_SPARC_PREDECODER_HH__ +#define __ARCH_SPARC_PREDECODER_HH__ + +#include "arch/sparc/types.hh" +#include "base/misc.hh" +#include "cpu/thread_context.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace SparcISA +{ + class Predecoder + { + protected: + ThreadContext * tc; + //The extended machine instruction being generated + ExtMachInst emi; + + public: + Predecoder(ThreadContext * _tc) : tc(_tc) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process() + { + } + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr currPC, Addr off, MachInst inst) + { + assert(off == 0); + + emi = inst; + //The I bit, bit 13, is used to figure out where the ASI + //should come from. Use that in the ExtMachInst. This is + //slightly redundant, but it removes the need to put a condition + //into all the execute functions + if(inst & (1 << 13)) + emi |= (static_cast<ExtMachInst>( + tc->readMiscRegNoEffect(MISCREG_ASI)) + << (sizeof(MachInst) * 8)); + else + emi |= (static_cast<ExtMachInst>(bits(inst, 12, 5)) + << (sizeof(MachInst) * 8)); + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(0, 0, machInst); + } + + bool needMoreBytes() + { + return true; + } + + bool extMachInstReady() + { + return true; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + return emi; + } + }; +}; + +#endif // __ARCH_SPARC_PREDECODER_HH__ diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 1e639b9a5..e4774ab54 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -30,6 +30,7 @@ */ #include "arch/sparc/asi.hh" +#include "arch/sparc/handlers.hh" #include "arch/sparc/isa_traits.hh" #include "arch/sparc/process.hh" #include "arch/sparc/types.hh" @@ -59,14 +60,6 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile, brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); brk_point = roundUp(brk_point, VMPageSize); - // Set up stack. On SPARC Linux, stack goes from the top of memory - // downward, less the hole for the kernel address space. - stack_base = (Addr)0x80000000000ULL; - - // Set up region for mmaps. Tru64 seems to start just above 0 and - // grow up from there. - mmap_start = mmap_end = 0xfffff80000000000ULL; - // Set pointer for next thread stack. Reserve 8M for main stack. next_thread_stack_base = stack_base - (8 * 1024 * 1024); @@ -75,136 +68,118 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile, spillStart = 0; } +void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc) +{ + switch(trapNum) + { + case 0x03: //Flush window trap + warn("Ignoring request to flush register windows.\n"); + break; + default: + panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum); + } +} + void -SparcLiveProcess::startup() +Sparc32LiveProcess::startup() { - argsInit(sizeof(IntReg), VMPageSize); + argsInit(32 / 8, VMPageSize); //From the SPARC ABI //The process runs in user mode - threadContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE, 0x02); + threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02); //Setup default FP state - threadContexts[0]->setMiscReg(MISCREG_FSR, 0); + threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0); - threadContexts[0]->setMiscReg(MISCREG_TICK, 0); + threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0); // /* * Register window management registers */ //No windows contain info from other programs - //threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0); + //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0); threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0); //There are no windows to pop - //threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0); + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0); threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0); //All windows are available to save into - //threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2); + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2); threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2); //All windows are "clean" - //threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows); + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows); threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows); //Start with register window 0 - threadContexts[0]->setMiscReg(MISCREG_CWP, 0); + threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0); //Always use spill and fill traps 0 - //threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0); + //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0); threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0); //Set the trap level to 0 - threadContexts[0]->setMiscReg(MISCREG_TL, 0); + threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0); //Set the ASI register to something fixed - threadContexts[0]->setMiscReg(MISCREG_ASI, ASI_PRIMARY); + threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); } -m5_auxv_t buildAuxVect(int64_t type, int64_t val) +void +Sparc64LiveProcess::startup() { - m5_auxv_t result; - result.a_type = TheISA::htog(type); - result.a_val = TheISA::htog(val); - return result; -} + argsInit(sizeof(IntReg), VMPageSize); + + //From the SPARC ABI + + //The process runs in user mode + threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02); + + //Setup default FP state + threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0); + + threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0); + // + /* + * Register window management registers + */ -//We only use 19 instructions for the trap handlers, but there would be -//space for 32 in a real SPARC trap table. -const int numFillInsts = 32; -const int numSpillInsts = 32; + //No windows contain info from other programs + //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0); + //There are no windows to pop + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0); + //All windows are available to save into + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2); + threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2); + //All windows are "clean" + //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows); + threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows); + //Start with register window 0 + threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0); + //Always use spill and fill traps 0 + //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0); + threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0); + //Set the trap level to 0 + threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0); + //Set the ASI register to something fixed + threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); +} -MachInst fillHandler[numFillInsts] = +M5_32_auxv_t::M5_32_auxv_t(int32_t type, int32_t val) { - htog(0x87802018), //wr %g0, ASI_AIUP, %asi - htog(0xe0dba7ff), //ldxa [%sp + BIAS + (0*8)] %asi, %l0 - htog(0xe2dba807), //ldxa [%sp + BIAS + (1*8)] %asi, %l1 - htog(0xe4dba80f), //ldxa [%sp + BIAS + (2*8)] %asi, %l2 - htog(0xe6dba817), //ldxa [%sp + BIAS + (3*8)] %asi, %l3 - htog(0xe8dba81f), //ldxa [%sp + BIAS + (4*8)] %asi, %l4 - htog(0xeadba827), //ldxa [%sp + BIAS + (5*8)] %asi, %l5 - htog(0xecdba82f), //ldxa [%sp + BIAS + (6*8)] %asi, %l6 - htog(0xeedba837), //ldxa [%sp + BIAS + (7*8)] %asi, %l7 - htog(0xf0dba83f), //ldxa [%sp + BIAS + (8*8)] %asi, %i0 - htog(0xf2dba847), //ldxa [%sp + BIAS + (9*8)] %asi, %i1 - htog(0xf4dba84f), //ldxa [%sp + BIAS + (10*8)] %asi, %i2 - htog(0xf6dba857), //ldxa [%sp + BIAS + (11*8)] %asi, %i3 - htog(0xf8dba85f), //ldxa [%sp + BIAS + (12*8)] %asi, %i4 - htog(0xfadba867), //ldxa [%sp + BIAS + (13*8)] %asi, %i5 - htog(0xfcdba86f), //ldxa [%sp + BIAS + (14*8)] %asi, %i6 - htog(0xfedba877), //ldxa [%sp + BIAS + (15*8)] %asi, %i7 - htog(0x83880000), //restored - htog(0x83F00000), //retry - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000) //illtrap -}; - -MachInst spillHandler[numSpillInsts] = + a_type = TheISA::htog(type); + a_val = TheISA::htog(val); +} + +M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val) { - htog(0x87802018), //wr %g0, ASI_AIUP, %asi - htog(0xe0f3a7ff), //stxa %l0, [%sp + BIAS + (0*8)] %asi - htog(0xe2f3a807), //stxa %l1, [%sp + BIAS + (1*8)] %asi - htog(0xe4f3a80f), //stxa %l2, [%sp + BIAS + (2*8)] %asi - htog(0xe6f3a817), //stxa %l3, [%sp + BIAS + (3*8)] %asi - htog(0xe8f3a81f), //stxa %l4, [%sp + BIAS + (4*8)] %asi - htog(0xeaf3a827), //stxa %l5, [%sp + BIAS + (5*8)] %asi - htog(0xecf3a82f), //stxa %l6, [%sp + BIAS + (6*8)] %asi - htog(0xeef3a837), //stxa %l7, [%sp + BIAS + (7*8)] %asi - htog(0xf0f3a83f), //stxa %i0, [%sp + BIAS + (8*8)] %asi - htog(0xf2f3a847), //stxa %i1, [%sp + BIAS + (9*8)] %asi - htog(0xf4f3a84f), //stxa %i2, [%sp + BIAS + (10*8)] %asi - htog(0xf6f3a857), //stxa %i3, [%sp + BIAS + (11*8)] %asi - htog(0xf8f3a85f), //stxa %i4, [%sp + BIAS + (12*8)] %asi - htog(0xfaf3a867), //stxa %i5, [%sp + BIAS + (13*8)] %asi - htog(0xfcf3a86f), //stxa %i6, [%sp + BIAS + (14*8)] %asi - htog(0xfef3a877), //stxa %i7, [%sp + BIAS + (15*8)] %asi - htog(0x81880000), //saved - htog(0x83F00000), //retry - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000), //illtrap - htog(0x00000000) //illtrap -}; + a_type = TheISA::htog(type); + a_val = TheISA::htog(val); +} void -SparcLiveProcess::argsInit(int intSize, int pageSize) +Sparc64LiveProcess::argsInit(int intSize, int pageSize) { + typedef M5_64_auxv_t auxv_t; Process::startup(); string filename; @@ -265,34 +240,34 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) if(elfObject) { //Bits which describe the system hardware capabilities - auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap)); + auxv.push_back(auxv_t(SPARC_AT_HWCAP, hwcap)); //The system page size - auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); + auxv.push_back(auxv_t(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)); + auxv.push_back(auxv_t(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())); + auxv.push_back(auxv_t(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())); + auxv.push_back(auxv_t(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())); + auxv.push_back(auxv_t(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)); + auxv.push_back(auxv_t(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)); + auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0)); //The entry point to the program - auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entryPoint())); + auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint())); //Different user and group IDs - auxv.push_back(buildAuxVect(SPARC_AT_UID, uid())); - auxv.push_back(buildAuxVect(SPARC_AT_EUID, euid())); - auxv.push_back(buildAuxVect(SPARC_AT_GID, gid())); - auxv.push_back(buildAuxVect(SPARC_AT_EGID, egid())); + auxv.push_back(auxv_t(SPARC_AT_UID, uid())); + auxv.push_back(auxv_t(SPARC_AT_EUID, euid())); + auxv.push_back(auxv_t(SPARC_AT_GID, gid())); + auxv.push_back(auxv_t(SPARC_AT_EGID, egid())); //Whether to enable "secure mode" in the executable - auxv.push_back(buildAuxVect(SPARC_AT_SECURE, 0)); + auxv.push_back(auxv_t(SPARC_AT_SECURE, 0)); } //Figure out how big the initial stack needs to be @@ -419,8 +394,8 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) int spillSize = sizeof(MachInst) * numSpillInsts; fillStart = stack_base; spillStart = fillStart + fillSize; - initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler, fillSize); - initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler, spillSize); + initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler64, fillSize); + initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler64, spillSize); //Set up the thread context to start running the process threadContexts[0]->setIntReg(ArgumentReg0, argc); @@ -437,3 +412,231 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) // num_processes++; } + +void +Sparc32LiveProcess::argsInit(int intSize, int pageSize) +{ + typedef M5_32_auxv_t auxv_t; + Process::startup(); + + string filename; + if(argv.size() < 1) + filename = ""; + else + filename = argv[0]; + + //Even though this is a 32 bit process, the ABI says we still need to + //maintain double word alignment of the stack pointer. + Addr alignmentMask = ~(8 - 1); + + // load object file into target memory + objFile->loadSections(initVirtMem); + + //These are the auxilliary vector types + enum auxTypes + { + SPARC_AT_HWCAP = 16, + SPARC_AT_PAGESZ = 6, + SPARC_AT_CLKTCK = 17, + SPARC_AT_PHDR = 3, + SPARC_AT_PHENT = 4, + SPARC_AT_PHNUM = 5, + SPARC_AT_BASE = 7, + SPARC_AT_FLAGS = 8, + SPARC_AT_ENTRY = 9, + SPARC_AT_UID = 11, + SPARC_AT_EUID = 12, + SPARC_AT_GID = 13, + SPARC_AT_EGID = 14, + SPARC_AT_SECURE = 23 + }; + + enum hardwareCaps + { + M5_HWCAP_SPARC_FLUSH = 1, + M5_HWCAP_SPARC_STBAR = 2, + M5_HWCAP_SPARC_SWAP = 4, + M5_HWCAP_SPARC_MULDIV = 8, + M5_HWCAP_SPARC_V9 = 16, + //This one should technically only be set + //if there is a cheetah or cheetah_plus tlb, + //but we'll use it all the time + M5_HWCAP_SPARC_ULTRA3 = 32 + }; + + const int64_t hwcap = + M5_HWCAP_SPARC_FLUSH | + M5_HWCAP_SPARC_STBAR | + M5_HWCAP_SPARC_SWAP | + M5_HWCAP_SPARC_MULDIV | + M5_HWCAP_SPARC_V9 | + M5_HWCAP_SPARC_ULTRA3; + + + //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(auxv_t(SPARC_AT_HWCAP, hwcap)); + //The system page size + auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); + //Defined to be 100 in the kernel source. + //Frequency at which times() increments + auxv.push_back(auxv_t(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(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable())); + // This is the size of a program header entry from the elf file. + auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize())); + // This is the number of program headers from the original elf file. + auxv.push_back(auxv_t(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(auxv_t(SPARC_AT_BASE, 0)); + //This is hardwired to 0 in the elf loading code in the kernel + auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0)); + //The entry point to the program + auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint())); + //Different user and group IDs + auxv.push_back(auxv_t(SPARC_AT_UID, uid())); + auxv.push_back(auxv_t(SPARC_AT_EUID, euid())); + auxv.push_back(auxv_t(SPARC_AT_GID, gid())); + auxv.push_back(auxv_t(SPARC_AT_EGID, egid())); + //Whether to enable "secure mode" in the executable + auxv.push_back(auxv_t(SPARC_AT_SECURE, 0)); + } + + //Figure out how big the initial stack needs to be + + // The unaccounted for 8 byte 0 at the top of the stack + int mysterious_size = 8; + + //This is the name of the file which is present on the initial stack + //It's purpose is to let the user space linker examine the original file. + int file_name_size = filename.size() + 1; + + int env_data_size = 0; + for (int i = 0; i < envp.size(); ++i) { + env_data_size += envp[i].size() + 1; + } + int arg_data_size = 0; + for (int i = 0; i < argv.size(); ++i) { + arg_data_size += argv[i].size() + 1; + } + + //The info_block - This seems to need an pad for some reason. + int info_block_size = + (mysterious_size + + file_name_size + + env_data_size + + arg_data_size + intSize); + + //Each auxilliary vector is two 4 byte words + int aux_array_size = intSize * 2 * (auxv.size() + 1); + + int envp_array_size = intSize * (envp.size() + 1); + int argv_array_size = intSize * (argv.size() + 1); + + int argc_size = intSize; + int window_save_size = intSize * 16; + + int space_needed = + info_block_size + + aux_array_size + + envp_array_size + + argv_array_size + + argc_size + + window_save_size; + + stack_min = stack_base - space_needed; + stack_min &= alignmentMask; + stack_size = stack_base - stack_min; + + // map memory + pTable->allocate(roundDown(stack_min, pageSize), + roundUp(stack_size, pageSize)); + + // map out initial stack contents + uint32_t window_save_base = stack_min; + uint32_t argc_base = window_save_base + window_save_size; + uint32_t argv_array_base = argc_base + argc_size; + uint32_t envp_array_base = argv_array_base + argv_array_size; + uint32_t auxv_array_base = envp_array_base + envp_array_size; + //The info block is pushed up against the top of the stack, while + //the rest of the initial stack frame is aligned to an 8 byte boudary. + uint32_t arg_data_base = stack_base - info_block_size + intSize; + uint32_t env_data_base = arg_data_base + arg_data_size; + uint32_t file_name_base = env_data_base + env_data_size; + uint32_t mysterious_base = file_name_base + file_name_size; + + DPRINTF(Sparc, "The addresses of items on the initial stack:\n"); + DPRINTF(Sparc, "0x%x - file name\n", file_name_base); + DPRINTF(Sparc, "0x%x - env data\n", env_data_base); + DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base); + DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base); + DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base); + DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base); + DPRINTF(Sparc, "0x%x - argc \n", argc_base); + DPRINTF(Sparc, "0x%x - window save\n", window_save_base); + DPRINTF(Sparc, "0x%x - stack min\n", stack_min); + + // write contents to stack + + // figure out argc + uint32_t argc = argv.size(); + uint32_t guestArgc = TheISA::htog(argc); + + //Write out the mysterious 0 + uint64_t mysterious_zero = 0; + initVirtMem->writeBlob(mysterious_base, + (uint8_t*)&mysterious_zero, mysterious_size); + + //Write the file name + initVirtMem->writeString(file_name_base, filename.c_str()); + + //Copy the aux stuff + for(int x = 0; x < auxv.size(); x++) + { + initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize, + (uint8_t*)&(auxv[x].a_type), intSize); + initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize, + (uint8_t*)&(auxv[x].a_val), intSize); + } + //Write out the terminating zeroed auxilliary vector + const uint64_t zero = 0; + initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(), + (uint8_t*)&zero, 2 * intSize); + + copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); + copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); + + initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); + + //Stuff the trap handlers into the processes address space. + //Since the stack grows down and is the highest area in the processes + //address space, we can put stuff above it and stay out of the way. + int fillSize = sizeof(MachInst) * numFillInsts; + int spillSize = sizeof(MachInst) * numSpillInsts; + fillStart = stack_base; + spillStart = fillStart + fillSize; + initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler32, fillSize); + initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler32, spillSize); + + //Set up the thread context to start running the process + //threadContexts[0]->setIntReg(ArgumentReg0, argc); + //threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base); + threadContexts[0]->setIntReg(StackPointerReg, stack_min); + + uint32_t prog_entry = objFile->entryPoint(); + threadContexts[0]->setPC(prog_entry); + threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); + threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst))); + + //Align the "stack_min" to a page boundary. + stack_min = roundDown(stack_min, pageSize); + +// num_processes++; +} diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index 1cf7ec224..2512441c6 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -39,27 +39,13 @@ class ObjectFile; class System; -typedef struct -{ - int64_t a_type; - union { - int64_t a_val; - Addr a_ptr; - Addr a_fcn; - }; -} m5_auxv_t; - class SparcLiveProcess : public LiveProcess { protected: - static const Addr StackBias = 2047; - //The locations of the fill and spill handlers Addr fillStart, spillStart; - std::vector<m5_auxv_t> auxv; - SparcLiveProcess(const std::string &nm, ObjectFile *objFile, System *_system, int stdin_fd, int stdout_fd, int stderr_fd, std::vector<std::string> &argv, @@ -69,11 +55,10 @@ class SparcLiveProcess : public LiveProcess uint64_t _gid, uint64_t _egid, uint64_t _pid, uint64_t _ppid); - void startup(); - public: - void argsInit(int intSize, int pageSize); + //Handles traps which request services from the operating system + virtual void handleTrap(int trapNum, ThreadContext *tc); Addr readFillStart() { return fillStart; } @@ -83,4 +68,107 @@ class SparcLiveProcess : public LiveProcess }; +struct M5_32_auxv_t +{ + int32_t a_type; + union { + int32_t a_val; + int32_t a_ptr; + int32_t a_fcn; + }; + + M5_32_auxv_t() + {} + + M5_32_auxv_t(int32_t type, int32_t val); +}; + +class Sparc32LiveProcess : public SparcLiveProcess +{ + protected: + + std::vector<M5_32_auxv_t> auxv; + + Sparc32LiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid) : + SparcLiveProcess(nm, objFile, _system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, + _uid, _euid, _gid, _egid, _pid, _ppid) + { + // Set up stack. On SPARC Linux, stack goes from the top of memory + // downward, less the hole for the kernel address space. + stack_base = (Addr)0xf0000000ULL; + + // Set up region for mmaps. + mmap_start = mmap_end = 0x70000000; + } + + void startup(); + + public: + + void argsInit(int intSize, int pageSize); + +}; + +struct M5_64_auxv_t +{ + int64_t a_type; + union { + int64_t a_val; + int64_t a_ptr; + int64_t a_fcn; + }; + + M5_64_auxv_t() + {} + + M5_64_auxv_t(int64_t type, int64_t val); +}; + +class Sparc64LiveProcess : public SparcLiveProcess +{ + protected: + + static const Addr StackBias = 2047; + + std::vector<M5_64_auxv_t> auxv; + + Sparc64LiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid) : + SparcLiveProcess(nm, objFile, _system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, + _uid, _euid, _gid, _egid, _pid, _ppid) + { + // Set up stack. On SPARC Linux, stack goes from the top of memory + // downward, less the hole for the kernel address space. + stack_base = (Addr)0x80000000000ULL; + + // Set up region for mmaps. Tru64 seems to start just above 0 and + // grow up from there. + mmap_start = mmap_end = 0xfffff80000000000ULL; + } + + void startup(); + + public: + + void argsInit(int intSize, int pageSize); + +}; + #endif // __SPARC_PROCESS_HH__ diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index 827e22c31..667b1f002 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -75,25 +75,25 @@ void RegFile::clear() miscRegFile.clear(); } -MiscReg RegFile::readMiscReg(int miscReg) +MiscReg RegFile::readMiscRegNoEffect(int miscReg) { - return miscRegFile.readReg(miscReg); + return miscRegFile.readRegNoEffect(miscReg); } -MiscReg RegFile::readMiscRegWithEffect(int miscReg, ThreadContext *tc) +MiscReg RegFile::readMiscReg(int miscReg, ThreadContext *tc) { - return miscRegFile.readRegWithEffect(miscReg, tc); + return miscRegFile.readReg(miscReg, tc); } -void RegFile::setMiscReg(int miscReg, const MiscReg &val) +void RegFile::setMiscRegNoEffect(int miscReg, const MiscReg &val) { - miscRegFile.setReg(miscReg, val); + miscRegFile.setRegNoEffect(miscReg, val); } -void RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val, +void RegFile::setMiscReg(int miscReg, const MiscReg &val, ThreadContext * tc) { - miscRegFile.setRegWithEffect(miscReg, val, tc); + miscRegFile.setReg(miscReg, val, tc); } FloatReg RegFile::readFloatReg(int floatReg, int width) @@ -153,8 +153,8 @@ void RegFile::setIntReg(int intReg, const IntReg &val) int SparcISA::flattenIntIndex(ThreadContext * tc, int reg) { - int gl = tc->readMiscReg(MISCREG_GL); - int cwp = tc->readMiscReg(MISCREG_CWP); + int gl = tc->readMiscRegNoEffect(MISCREG_GL); + int cwp = tc->readMiscRegNoEffect(MISCREG_CWP); //DPRINTF(Sparc, "Global Level = %d, Current Window Pointer = %d\n", gl, cwp); int newReg; //The total number of global registers @@ -254,162 +254,149 @@ void RegFile::changeContext(RegContextParam param, RegContextVal val) } } -int SparcISA::InterruptLevel(uint64_t softint) -{ - if (softint & 0x10000 || softint & 0x1) - return 14; - - int level = 15; - while (level > 0 && !(1 << level & softint)) - level--; - if (1 << level & softint) - return level; - return 0; -} - void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) { - uint8_t tl = src->readMiscReg(MISCREG_TL); + uint8_t tl = src->readMiscRegNoEffect(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); + src->setMiscRegNoEffect(MISCREG_TL, i); + dest->setMiscRegNoEffect(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)); + dest->setMiscRegNoEffect(MISCREG_TT, src->readMiscRegNoEffect(MISCREG_TT)); + dest->setMiscRegNoEffect(MISCREG_TPC, src->readMiscRegNoEffect(MISCREG_TPC)); + dest->setMiscRegNoEffect(MISCREG_TNPC, src->readMiscRegNoEffect(MISCREG_TNPC)); + dest->setMiscRegNoEffect(MISCREG_TSTATE, src->readMiscRegNoEffect(MISCREG_TSTATE)); } // Save off the traplevel - dest->setMiscReg(MISCREG_TL, tl); - src->setMiscReg(MISCREG_TL, tl); + dest->setMiscRegNoEffect(MISCREG_TL, tl); + src->setMiscRegNoEffect(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)); +// dest->setMiscRegNoEffect(MISCREG_Y, src->readMiscRegNoEffect(MISCREG_Y)); +// dest->setMiscRegNoEffect(MISCREG_CCR, src->readMiscRegNoEffect(MISCREG_CCR)); + dest->setMiscRegNoEffect(MISCREG_ASI, src->readMiscRegNoEffect(MISCREG_ASI)); + dest->setMiscRegNoEffect(MISCREG_TICK, src->readMiscRegNoEffect(MISCREG_TICK)); + dest->setMiscRegNoEffect(MISCREG_FPRS, src->readMiscRegNoEffect(MISCREG_FPRS)); + dest->setMiscRegNoEffect(MISCREG_SOFTINT, src->readMiscRegNoEffect(MISCREG_SOFTINT)); + dest->setMiscRegNoEffect(MISCREG_TICK_CMPR, src->readMiscRegNoEffect(MISCREG_TICK_CMPR)); + dest->setMiscRegNoEffect(MISCREG_STICK, src->readMiscRegNoEffect(MISCREG_STICK)); + dest->setMiscRegNoEffect(MISCREG_STICK_CMPR, src->readMiscRegNoEffect(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)); + dest->setMiscRegNoEffect(MISCREG_TICK, src->readMiscRegNoEffect(MISCREG_TICK)); + dest->setMiscRegNoEffect(MISCREG_TBA, src->readMiscRegNoEffect(MISCREG_TBA)); + dest->setMiscRegNoEffect(MISCREG_PSTATE, src->readMiscRegNoEffect(MISCREG_PSTATE)); + dest->setMiscRegNoEffect(MISCREG_PIL, src->readMiscRegNoEffect(MISCREG_PIL)); + dest->setMiscRegNoEffect(MISCREG_CWP, src->readMiscRegNoEffect(MISCREG_CWP)); +// dest->setMiscRegNoEffect(MISCREG_CANSAVE, src->readMiscRegNoEffect(MISCREG_CANSAVE)); +// dest->setMiscRegNoEffect(MISCREG_CANRESTORE, src->readMiscRegNoEffect(MISCREG_CANRESTORE)); +// dest->setMiscRegNoEffect(MISCREG_OTHERWIN, src->readMiscRegNoEffect(MISCREG_OTHERWIN)); +// dest->setMiscRegNoEffect(MISCREG_CLEANWIN, src->readMiscRegNoEffect(MISCREG_CLEANWIN)); +// dest->setMiscRegNoEffect(MISCREG_WSTATE, src->readMiscRegNoEffect(MISCREG_WSTATE)); + dest->setMiscRegNoEffect(MISCREG_GL, src->readMiscRegNoEffect(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)); + dest->setMiscRegNoEffect(MISCREG_HPSTATE, src->readMiscRegNoEffect(MISCREG_HPSTATE)); + dest->setMiscRegNoEffect(MISCREG_HINTP, src->readMiscRegNoEffect(MISCREG_HINTP)); + dest->setMiscRegNoEffect(MISCREG_HTBA, src->readMiscRegNoEffect(MISCREG_HTBA)); + dest->setMiscRegNoEffect(MISCREG_STRAND_STS_REG, + src->readMiscRegNoEffect(MISCREG_STRAND_STS_REG)); + dest->setMiscRegNoEffect(MISCREG_HSTICK_CMPR, + src->readMiscRegNoEffect(MISCREG_HSTICK_CMPR)); // FSR - dest->setMiscReg(MISCREG_FSR, src->readMiscReg(MISCREG_FSR)); + dest->setMiscRegNoEffect(MISCREG_FSR, src->readMiscRegNoEffect(MISCREG_FSR)); //Strand Status Register - dest->setMiscReg(MISCREG_STRAND_STS_REG, - src->readMiscReg(MISCREG_STRAND_STS_REG)); + dest->setMiscRegNoEffect(MISCREG_STRAND_STS_REG, + src->readMiscRegNoEffect(MISCREG_STRAND_STS_REG)); // MMU Registers - dest->setMiscReg(MISCREG_MMU_P_CONTEXT, - src->readMiscReg(MISCREG_MMU_P_CONTEXT)); - dest->setMiscReg(MISCREG_MMU_S_CONTEXT, - src->readMiscReg(MISCREG_MMU_S_CONTEXT)); - dest->setMiscReg(MISCREG_MMU_PART_ID, - src->readMiscReg(MISCREG_MMU_PART_ID)); - dest->setMiscReg(MISCREG_MMU_LSU_CTRL, - src->readMiscReg(MISCREG_MMU_LSU_CTRL)); - - dest->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0, - src->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0)); - dest->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1, - src->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1)); - dest->setMiscReg(MISCREG_MMU_ITLB_C0_CONFIG, - src->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG)); - dest->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0, - src->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0)); - dest->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1, - src->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1)); - dest->setMiscReg(MISCREG_MMU_ITLB_CX_CONFIG, - src->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); - dest->setMiscReg(MISCREG_MMU_ITLB_SFSR, - src->readMiscReg(MISCREG_MMU_ITLB_SFSR)); - dest->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, - src->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS)); - - dest->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0, - src->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0)); - dest->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1, - src->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1)); - dest->setMiscReg(MISCREG_MMU_DTLB_C0_CONFIG, - src->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG)); - dest->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0, - src->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0)); - dest->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1, - src->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1)); - dest->setMiscReg(MISCREG_MMU_DTLB_CX_CONFIG, - src->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); - dest->setMiscReg(MISCREG_MMU_DTLB_SFSR, - src->readMiscReg(MISCREG_MMU_DTLB_SFSR)); - dest->setMiscReg(MISCREG_MMU_DTLB_SFAR, - src->readMiscReg(MISCREG_MMU_DTLB_SFAR)); - dest->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, - src->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS)); + dest->setMiscRegNoEffect(MISCREG_MMU_P_CONTEXT, + src->readMiscRegNoEffect(MISCREG_MMU_P_CONTEXT)); + dest->setMiscRegNoEffect(MISCREG_MMU_S_CONTEXT, + src->readMiscRegNoEffect(MISCREG_MMU_S_CONTEXT)); + dest->setMiscRegNoEffect(MISCREG_MMU_PART_ID, + src->readMiscRegNoEffect(MISCREG_MMU_PART_ID)); + dest->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, + src->readMiscRegNoEffect(MISCREG_MMU_LSU_CTRL)); + + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_C0_CONFIG, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_C0_CONFIG)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_CX_CONFIG, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_CX_CONFIG)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_SFSR, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_SFSR)); + dest->setMiscRegNoEffect(MISCREG_MMU_ITLB_TAG_ACCESS, + src->readMiscRegNoEffect(MISCREG_MMU_ITLB_TAG_ACCESS)); + + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_C0_CONFIG, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_C0_CONFIG)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_CX_CONFIG, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_CX_CONFIG)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_SFSR, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_SFSR)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_SFAR, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_SFAR)); + dest->setMiscRegNoEffect(MISCREG_MMU_DTLB_TAG_ACCESS, + src->readMiscRegNoEffect(MISCREG_MMU_DTLB_TAG_ACCESS)); // Scratchpad Registers - dest->setMiscReg(MISCREG_SCRATCHPAD_R0, - src->readMiscReg(MISCREG_SCRATCHPAD_R0)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R1, - src->readMiscReg(MISCREG_SCRATCHPAD_R1)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R2, - src->readMiscReg(MISCREG_SCRATCHPAD_R2)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R3, - src->readMiscReg(MISCREG_SCRATCHPAD_R3)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R4, - src->readMiscReg(MISCREG_SCRATCHPAD_R4)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R5, - src->readMiscReg(MISCREG_SCRATCHPAD_R5)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R6, - src->readMiscReg(MISCREG_SCRATCHPAD_R6)); - dest->setMiscReg(MISCREG_SCRATCHPAD_R7, - src->readMiscReg(MISCREG_SCRATCHPAD_R7)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R0, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R0)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R1, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R1)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R2, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R2)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R3, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R3)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R4, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R4)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R5, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R5)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R6, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R6)); + dest->setMiscRegNoEffect(MISCREG_SCRATCHPAD_R7, + src->readMiscRegNoEffect(MISCREG_SCRATCHPAD_R7)); // Queue Registers - dest->setMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD, - src->readMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD)); - dest->setMiscReg(MISCREG_QUEUE_CPU_MONDO_TAIL, - src->readMiscReg(MISCREG_QUEUE_CPU_MONDO_TAIL)); - dest->setMiscReg(MISCREG_QUEUE_DEV_MONDO_HEAD, - src->readMiscReg(MISCREG_QUEUE_DEV_MONDO_HEAD)); - dest->setMiscReg(MISCREG_QUEUE_DEV_MONDO_TAIL, - src->readMiscReg(MISCREG_QUEUE_DEV_MONDO_TAIL)); - dest->setMiscReg(MISCREG_QUEUE_RES_ERROR_HEAD, - src->readMiscReg(MISCREG_QUEUE_RES_ERROR_HEAD)); - dest->setMiscReg(MISCREG_QUEUE_RES_ERROR_TAIL, - src->readMiscReg(MISCREG_QUEUE_RES_ERROR_TAIL)); - dest->setMiscReg(MISCREG_QUEUE_NRES_ERROR_HEAD, - src->readMiscReg(MISCREG_QUEUE_NRES_ERROR_HEAD)); - dest->setMiscReg(MISCREG_QUEUE_NRES_ERROR_TAIL, - src->readMiscReg(MISCREG_QUEUE_NRES_ERROR_TAIL)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_CPU_MONDO_HEAD, + src->readMiscRegNoEffect(MISCREG_QUEUE_CPU_MONDO_HEAD)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_CPU_MONDO_TAIL, + src->readMiscRegNoEffect(MISCREG_QUEUE_CPU_MONDO_TAIL)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_DEV_MONDO_HEAD, + src->readMiscRegNoEffect(MISCREG_QUEUE_DEV_MONDO_HEAD)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_DEV_MONDO_TAIL, + src->readMiscRegNoEffect(MISCREG_QUEUE_DEV_MONDO_TAIL)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_RES_ERROR_HEAD, + src->readMiscRegNoEffect(MISCREG_QUEUE_RES_ERROR_HEAD)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_RES_ERROR_TAIL, + src->readMiscRegNoEffect(MISCREG_QUEUE_RES_ERROR_TAIL)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_NRES_ERROR_HEAD, + src->readMiscRegNoEffect(MISCREG_QUEUE_NRES_ERROR_HEAD)); + dest->setMiscRegNoEffect(MISCREG_QUEUE_NRES_ERROR_TAIL, + src->readMiscRegNoEffect(MISCREG_QUEUE_NRES_ERROR_TAIL)); } void SparcISA::copyRegs(ThreadContext *src, ThreadContext *dest) diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index d9af0757c..f3e253f7e 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -73,13 +73,13 @@ namespace SparcISA int FlattenIntIndex(int reg); - MiscReg readMiscReg(int miscReg); + MiscReg readMiscRegNoEffect(int miscReg); - MiscReg readMiscRegWithEffect(int miscReg, ThreadContext *tc); + MiscReg readMiscReg(int miscReg, ThreadContext *tc); - void setMiscReg(int miscReg, const MiscReg &val); + void setMiscRegNoEffect(int miscReg, const MiscReg &val); - void setMiscRegWithEffect(int miscReg, const MiscReg &val, + void setMiscReg(int miscReg, const MiscReg &val, ThreadContext * tc); int instAsid() @@ -126,8 +126,6 @@ namespace SparcISA void copyMiscRegs(ThreadContext *src, ThreadContext *dest); - int InterruptLevel(uint64_t softint); - } // namespace SparcISA #endif diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc index 21c4a468c..85b0c03a3 100644 --- a/src/arch/sparc/remote_gdb.cc +++ b/src/arch/sparc/remote_gdb.cc @@ -138,7 +138,7 @@ using namespace std; using namespace TheISA; RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) - : BaseRemoteGDB(_system, c, NumGDBRegs) + : BaseRemoteGDB(_system, c, NumGDBRegs), nextBkpt(0) {} /////////////////////////////////////////////////////////// @@ -152,7 +152,9 @@ RemoteGDB::acc(Addr va, size_t len) //@Todo In NetBSD, this function checks if all addresses //from va to va + len have valid page mape entries. Not //sure how this will work for other OSes or in general. - return true; + if (va) + return true; + return false; } /////////////////////////////////////////////////////////// @@ -165,10 +167,37 @@ RemoteGDB::getregs() { memset(gdbregs.regs, 0, gdbregs.size); - gdbregs.regs[RegPc] = context->readPC(); - gdbregs.regs[RegNpc] = context->readNextPC(); - for(int x = RegG0; x <= RegI0 + 7; x++) - gdbregs.regs[x] = context->readIntReg(x - RegG0); + if (context->readMiscReg(MISCREG_PSTATE) & + PSTATE::am) { + uint32_t *regs; + regs = (uint32_t*)gdbregs.regs; + regs[Reg32Pc] = htobe((uint32_t)context->readPC()); + regs[Reg32Npc] = htobe((uint32_t)context->readNextPC()); + for(int x = RegG0; x <= RegI0 + 7; x++) + regs[x] = htobe((uint32_t)context->readIntReg(x - RegG0)); + + regs[Reg32Y] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 1)); + regs[Reg32Psr] = htobe((uint32_t)context->readMiscReg(MISCREG_PSTATE)); + regs[Reg32Fsr] = htobe((uint32_t)context->readMiscReg(MISCREG_FSR)); + regs[Reg32Csr] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2)); + } else { + gdbregs.regs[RegPc] = htobe(context->readPC()); + gdbregs.regs[RegNpc] = htobe(context->readNextPC()); + for(int x = RegG0; x <= RegI0 + 7; x++) + gdbregs.regs[x] = htobe(context->readIntReg(x - RegG0)); + + gdbregs.regs[RegFsr] = htobe(context->readMiscReg(MISCREG_FSR)); + gdbregs.regs[RegFprs] = htobe(context->readMiscReg(MISCREG_FPRS)); + gdbregs.regs[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1)); + gdbregs.regs[RegState] = htobe( + context->readMiscReg(MISCREG_CWP) | + context->readMiscReg(MISCREG_PSTATE) << 8 | + context->readMiscReg(MISCREG_ASI) << 24 | + context->readIntReg(NumIntArchRegs + 2) << 32); + } + + DPRINTF(GDBRead, "PC=%#x\n", gdbregs.regs[RegPc]); + //Floating point registers are left at 0 in netbsd //All registers other than the pc, npc and int regs //are ignored as well. @@ -193,12 +222,13 @@ RemoteGDB::setregs() void RemoteGDB::clearSingleStep() { - warn("SPARC single stepping not implemented, " - "but clearSingleStep called\n"); + if (nextBkpt) + clearTempBreakpoint(nextBkpt); } void RemoteGDB::setSingleStep() { - panic("SPARC single stepping not implemented.\n"); + nextBkpt = context->readNextPC(); + setTempBreakpoint(nextBkpt); } diff --git a/src/arch/sparc/remote_gdb.hh b/src/arch/sparc/remote_gdb.hh index e4b66b783..dbdf810c4 100644 --- a/src/arch/sparc/remote_gdb.hh +++ b/src/arch/sparc/remote_gdb.hh @@ -28,12 +28,12 @@ * Authors: Nathan Binkert */ -#ifndef __ARCH_ALPHA_REMOTE_GDB_HH__ -#define __ARCH_ALPHA_REMOTE_GDB_HH__ +#ifndef __ARCH_SPARC_REMOTE_GDB_HH__ +#define __ARCH_SPARC_REMOTE_GDB_HH__ #include <map> -#include "arch/types.hh" +#include "arch/sparc/types.hh" #include "base/remote_gdb.hh" #include "cpu/pc_event.hh" #include "base/pollevent.hh" @@ -50,15 +50,12 @@ namespace SparcISA enum RegisterConstants { RegG0 = 0, RegO0 = 8, RegL0 = 16, RegI0 = 24, - RegF0 = 32, RegF32 = 64, - RegPc = 80, RegNpc, RegCcr, RegFsr, RegFprs, RegY, RegAsi, - RegVer, RegTick, RegPil, RegPstate, - RegTstate, RegTba, RegTl, RegTt, RegTpc, RegTnpc, RegWstate, - RegCwp, RegCansave, RegCanrestore, RegCleanwin, RegOtherwin, - RegAsr16 = 103, - RegIcc = 119, RegXcc, - RegFcc0 = 121, - NumGDBRegs + RegF0 = 32, + RegPc = 64, RegNpc, RegState, RegFsr, RegFprs, RegY, + /*RegState contains data in same format as tstate */ + Reg32Y = 64, Reg32Psr = 65, Reg32Tbr = 66, Reg32Pc = 67, + Reg32Npc = 68, Reg32Fsr = 69, Reg32Csr = 70, + NumGDBRegs = RegY }; public: @@ -72,7 +69,9 @@ namespace SparcISA void clearSingleStep(); void setSingleStep(); + + Addr nextBkpt; }; } -#endif /* __ARCH_ALPHA_REMOTE_GDB_H__ */ +#endif /* __ARCH_SPARC_REMOTE_GDB_H__ */ diff --git a/src/arch/sparc/stacktrace.cc b/src/arch/sparc/stacktrace.cc index 2eb697bf2..2d7991267 100644 --- a/src/arch/sparc/stacktrace.cc +++ b/src/arch/sparc/stacktrace.cc @@ -146,7 +146,7 @@ namespace SparcISA #if 0 tc = _tc; - bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + bool usermode = (tc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; Addr pc = tc->readNextPC(); bool kernel = tc->getSystemPtr()->kernelStart <= pc && @@ -221,22 +221,22 @@ namespace SparcISA StackTrace::isEntry(Addr addr) { #if 0 - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp12)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp7)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp11)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp21)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp9)) return true; - if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2)) + if (addr == tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp2)) return true; #endif return false; diff --git a/src/arch/sparc/syscallreturn.hh b/src/arch/sparc/syscallreturn.hh index d92b12790..cf13fc3e8 100644 --- a/src/arch/sparc/syscallreturn.hh +++ b/src/arch/sparc/syscallreturn.hh @@ -49,13 +49,13 @@ namespace SparcISA // no error, clear XCC.C tc->setIntReg(NumIntArchRegs + 2, tc->readIntReg(NumIntArchRegs + 2) & 0xEE); - //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) & 0xEE); + //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) & 0xEE); tc->setIntReg(ReturnValueReg, return_value.value()); } else { // got an error, set XCC.C tc->setIntReg(NumIntArchRegs + 2, tc->readIntReg(NumIntArchRegs + 2) | 0x11); - //tc->setMiscReg(MISCREG_CCR, tc->readMiscReg(MISCREG_CCR) | 0x11); + //tc->setMiscRegNoEffect(MISCREG_CCR, tc->readMiscRegNoEffect(MISCREG_CCR) | 0x11); tc->setIntReg(ReturnValueReg, -return_value.value()); } } diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index 293f667d6..09266fd6e 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -40,11 +40,11 @@ #include "mem/packet_access.hh" #include "mem/request.hh" #include "sim/builder.hh" +#include "sim/system.hh" /* @todo remove some of the magic constants. -- ali * */ -namespace SparcISA -{ +namespace SparcISA { TLB::TLB(const std::string &name, int s) : SimObject(name), size(s), usedEntries(0), lastReplaced(0), @@ -204,7 +204,8 @@ insertAllLocked: TlbEntry* -TLB::lookup(Addr va, int partition_id, bool real, int context_id) +TLB::lookup(Addr va, int partition_id, bool real, int context_id, bool + update_used) { MapIter i; TlbRange tr; @@ -230,7 +231,10 @@ TLB::lookup(Addr va, int partition_id, bool real, int context_id) t = i->second; DPRINTF(TLB, "TLB: Valid entry found pa: %#x size: %#x\n", t->pte.paddr(), t->pte.size()); - if (!t->used) { + + // Update the used bits only if this is a real access (not a fake one from + // virttophys() + if (!t->used && update_used) { t->used = true; usedEntries++; if (usedEntries == size) { @@ -392,7 +396,7 @@ TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, bool se, FaultTypes ft, int asi) { uint64_t sfsr; - sfsr = tc->readMiscReg(reg); + sfsr = tc->readMiscRegNoEffect(reg); if (sfsr & 0x1) sfsr = 0x3; @@ -406,7 +410,7 @@ TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct, sfsr |= 1 << 6; sfsr |= ft << 7; sfsr |= asi << 16; - tc->setMiscRegWithEffect(reg, sfsr); + tc->setMiscReg(reg, sfsr); } void @@ -415,7 +419,7 @@ TLB::writeTagAccess(ThreadContext *tc, int reg, Addr va, int context) DPRINTF(TLB, "TLB: Writing Tag Access: va: %#X ctx: %#X value: %#X\n", va, context, mbits(va, 63,13) | mbits(context,12,0)); - tc->setMiscRegWithEffect(reg, mbits(va, 63,13) | mbits(context,12,0)); + tc->setMiscReg(reg, mbits(va, 63,13) | mbits(context,12,0)); } void @@ -440,7 +444,7 @@ DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n", a, (int)write, ct, ft, asi); TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR, a); + tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a); } void @@ -454,7 +458,7 @@ DTB::writeTagAccess(ThreadContext *tc, Addr va, int context) Fault ITB::translate(RequestPtr &req, ThreadContext *tc) { - uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA); + uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); Addr vaddr = req->getVaddr(); TlbEntry *e; @@ -568,7 +572,7 @@ Fault DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) { /* @todo this could really use some profiling and fixing to make it faster! */ - uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA); + uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); Addr vaddr = req->getVaddr(); Addr size = req->getSize(); ASI asi; @@ -592,21 +596,36 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) // Be fast if we can! if (cacheValid && cacheState == tlbdata) { - if (cacheEntry[0] && cacheAsi[0] == asi && cacheEntry[0]->range.va < vaddr + size && - cacheEntry[0]->range.va + cacheEntry[0]->range.size > vaddr && - (!write || cacheEntry[0]->pte.writable())) { - req->setPaddr(cacheEntry[0]->pte.paddr() & ~(cacheEntry[0]->pte.size()-1) | - vaddr & cacheEntry[0]->pte.size()-1 ); - return NoFault; - } - if (cacheEntry[1] && cacheAsi[1] == asi && cacheEntry[1]->range.va < vaddr + size && - cacheEntry[1]->range.va + cacheEntry[1]->range.size > vaddr && - (!write || cacheEntry[1]->pte.writable())) { - req->setPaddr(cacheEntry[1]->pte.paddr() & ~(cacheEntry[1]->pte.size()-1) | - vaddr & cacheEntry[1]->pte.size()-1 ); - return NoFault; - } - } + + + + if (cacheEntry[0]) { + TlbEntry *ce = cacheEntry[0]; + Addr ce_va = ce->range.va; + if (cacheAsi[0] == asi && + ce_va < vaddr + size && ce_va + ce->range.size > vaddr && + (!write || ce->pte.writable())) { + req->setPaddr(ce->pte.paddrMask() | vaddr & ce->pte.sizeMask()); + if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) + req->setFlags(req->getFlags() | UNCACHEABLE); + DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); + return NoFault; + } // if matched + } // if cache entry valid + if (cacheEntry[1]) { + TlbEntry *ce = cacheEntry[1]; + Addr ce_va = ce->range.va; + if (cacheAsi[1] == asi && + ce_va < vaddr + size && ce_va + ce->range.size > vaddr && + (!write || ce->pte.writable())) { + req->setPaddr(ce->pte.paddrMask() | vaddr & ce->pte.sizeMask()); + if (ce->pte.sideffect() || (ce->pte.paddr() >> 39) & 1) + req->setFlags(req->getFlags() | UNCACHEABLE); + DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); + return NoFault; + } // if matched + } // if cache entry valid + } bool red = bits(tlbdata,1,1); bool priv = bits(tlbdata,2,2); @@ -673,9 +692,12 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (AsiIsPartialStore(asi)) panic("Partial Store ASIs not supported\n"); - if (AsiIsInterrupt(asi)) - panic("Interrupt ASIs not supported\n"); + if (AsiIsCmt(asi)) + panic("Cmt ASI registers not implmented\n"); + + if (AsiIsInterrupt(asi)) + goto handleIntRegAccess; if (AsiIsMmu(asi)) goto handleMmuRegAccess; if (AsiIsScratchPad(asi)) @@ -752,7 +774,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) } - if (e->pte.sideffect()) + if (e->pte.sideffect() || (e->pte.paddr() >> 39) & 1) req->setFlags(req->getFlags() | UNCACHEABLE); // cache translation date for next translation @@ -775,7 +797,25 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) vaddr & e->pte.size()-1); DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr()); return NoFault; + /** Normal flow ends here. */ +handleIntRegAccess: + if (!hpriv) { + writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + if (priv) + return new DataAccessException; + else + return new PrivilegedAction; + } + + if (asi == ASI_SWVR_UDB_INTR_W && !write || + asi == ASI_SWVR_UDB_INTR_R && write) { + writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + return new DataAccessException; + } + + goto regAccessOk; + handleScratchRegAccess: if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) { @@ -797,13 +837,11 @@ handleQueueRegAccess: handleSparcErrorRegAccess: if (!hpriv) { - if (priv) { - writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + if (priv) return new DataAccessException; - } else { - writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi); + else return new PrivilegedAction; - } } goto regAccessOk; @@ -821,8 +859,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) { Addr va = pkt->getAddr(); ASI asi = (ASI)pkt->req->getAsi(); - uint64_t temp, data; - uint64_t tsbtemp, cnftemp; + uint64_t temp; DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n", (uint32_t)pkt->req->getAsi(), pkt->getAddr()); @@ -830,90 +867,90 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) switch (asi) { case ASI_LSU_CONTROL_REG: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL)); + pkt->set(tc->readMiscReg(MISCREG_MMU_LSU_CTRL)); break; case ASI_MMU: switch (va) { case 0x8: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT)); + pkt->set(tc->readMiscReg(MISCREG_MMU_P_CONTEXT)); break; case 0x10: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT)); + pkt->set(tc->readMiscReg(MISCREG_MMU_S_CONTEXT)); break; default: goto doMmuReadError; } break; case ASI_QUEUE: - pkt->set(tc->readMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + + pkt->set(tc->readMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD + (va >> 4) - 0x3c)); break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0)); break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1)); break; case ASI_DMMU_CTXT_ZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG)); break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0)); break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1)); break; case ASI_IMMU_CTXT_ZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG)); break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0)); break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1)); break; case ASI_DMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0)); break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1)); break; case ASI_IMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); break; case ASI_SPARC_ERROR_STATUS_REG: pkt->set((uint64_t)0); break; case ASI_HYP_SCRATCHPAD: case ASI_SCRATCHPAD: - pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3))); + pkt->set(tc->readMiscReg(MISCREG_SCRATCHPAD_R0 + (va >> 3))); break; case ASI_IMMU: switch (va) { case 0x0: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); + temp = tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS); pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); break; case 0x18: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_SFSR)); break; case 0x30: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS)); + pkt->set(tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS)); break; default: goto doMmuReadError; @@ -922,86 +959,65 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) case ASI_DMMU: switch (va) { case 0x0: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); + temp = tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS); pkt->set(bits(temp,63,22) | bits(temp,12,0) << 48); break; case 0x18: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_SFSR)); break; case 0x20: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_SFAR)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_SFAR)); break; case 0x30: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS)); + pkt->set(tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS)); break; case 0x80: - pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID)); + pkt->set(tc->readMiscReg(MISCREG_MMU_PART_ID)); break; default: goto doMmuReadError; } break; case ASI_DMMU_TSB_PS0_PTR_REG: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); - if (bits(temp,12,0) == 0) { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG); - } else { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG); - } - data = mbits(tsbtemp,63,13); - data |= temp >> (9 + bits(cnftemp,2,0) * 3) & - mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); - pkt->set(data); + pkt->set(MakeTsbPtr(Ps0, + tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG))); break; case ASI_DMMU_TSB_PS1_PTR_REG: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); - if (bits(temp,12,0) == 0) { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG); - } else { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG); - } - data = mbits(tsbtemp,63,13); - if (bits(tsbtemp,12,12)) - data |= ULL(1) << (13+bits(tsbtemp,3,0)); - data |= temp >> (9 + bits(cnftemp,10,8) * 3) & - mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); - pkt->set(data); + pkt->set(MakeTsbPtr(Ps1, + tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG))); break; case ASI_IMMU_TSB_PS0_PTR_REG: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); - if (bits(temp,12,0) == 0) { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG); - } else { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG); - } - data = mbits(tsbtemp,63,13); - data |= temp >> (9 + bits(cnftemp,2,0) * 3) & - mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); - pkt->set(data); + pkt->set(MakeTsbPtr(Ps0, + tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG))); break; case ASI_IMMU_TSB_PS1_PTR_REG: - temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); - if (bits(temp,12,0) == 0) { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG); - } else { - tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1); - cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG); - } - data = mbits(tsbtemp,63,13); - if (bits(tsbtemp,12,12)) - data |= ULL(1) << (13+bits(tsbtemp,3,0)); - data |= temp >> (9 + bits(cnftemp,10,8) * 3) & - mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4); - pkt->set(data); + pkt->set(MakeTsbPtr(Ps1, + tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG))); + break; + case ASI_SWVR_INTR_RECEIVE: + pkt->set(tc->getCpuPtr()->get_interrupts(IT_INT_VEC)); + break; + case ASI_SWVR_UDB_INTR_R: + temp = findMsbSet(tc->getCpuPtr()->get_interrupts(IT_INT_VEC)); + tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, temp); + pkt->set(temp); break; - default: doMmuReadError: panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n", @@ -1035,15 +1051,15 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) switch (asi) { case ASI_LSU_CONTROL_REG: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data); + tc->setMiscReg(MISCREG_MMU_LSU_CTRL, data); break; case ASI_MMU: switch (va) { case 0x8: - tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data); + tc->setMiscReg(MISCREG_MMU_P_CONTEXT, data); break; case 0x10: - tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data); + tc->setMiscReg(MISCREG_MMU_S_CONTEXT, data); break; default: goto doMmuWriteError; @@ -1051,56 +1067,56 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) break; case ASI_QUEUE: assert(mbits(data,13,6) == data); - tc->setMiscRegWithEffect(MISCREG_QUEUE_CPU_MONDO_HEAD + + tc->setMiscReg(MISCREG_QUEUE_CPU_MONDO_HEAD + (va >> 4) - 0x3c, data); break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data); + tc->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0, data); break; case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data); + tc->setMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1, data); break; case ASI_DMMU_CTXT_ZERO_CONFIG: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data); + tc->setMiscReg(MISCREG_MMU_DTLB_C0_CONFIG, data); break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data); + tc->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0, data); break; case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data); + tc->setMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1, data); break; case ASI_IMMU_CTXT_ZERO_CONFIG: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data); + tc->setMiscReg(MISCREG_MMU_ITLB_C0_CONFIG, data); break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data); + tc->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0, data); break; case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data); + tc->setMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1, data); break; case ASI_DMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data); + tc->setMiscReg(MISCREG_MMU_DTLB_CX_CONFIG, data); break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data); + tc->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0, data); break; case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data); + tc->setMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1, data); break; case ASI_IMMU_CTXT_NONZERO_CONFIG: assert(va == 0); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data); + tc->setMiscReg(MISCREG_MMU_ITLB_CX_CONFIG, data); break; case ASI_SPARC_ERROR_EN_REG: case ASI_SPARC_ERROR_STATUS_REG: @@ -1108,16 +1124,16 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) break; case ASI_HYP_SCRATCHPAD: case ASI_SCRATCHPAD: - tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); + tc->setMiscReg(MISCREG_SCRATCHPAD_R0 + (va >> 3), data); break; case ASI_IMMU: switch (va) { case 0x18: - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_SFSR, data); + tc->setMiscReg(MISCREG_MMU_ITLB_SFSR, data); break; case 0x30: sext<59>(bits(data, 59,0)); - tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS, data); + tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS, data); break; default: goto doMmuWriteError; @@ -1127,10 +1143,10 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) entry_insert = bits(va, 8,3); case ASI_ITLB_DATA_IN_REG: assert(entry_insert != -1 || mbits(va,10,9) == va); - ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS); + ta_insert = tc->readMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS); va_insert = mbits(ta_insert, 63,13); ct_insert = mbits(ta_insert, 12,0); - part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); + part_insert = tc->readMiscReg(MISCREG_MMU_PART_ID); real_insert = bits(va, 9,9); pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : PageTableEntry::sun4u); @@ -1141,10 +1157,10 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) entry_insert = bits(va, 8,3); case ASI_DTLB_DATA_IN_REG: assert(entry_insert != -1 || mbits(va,10,9) == va); - ta_insert = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS); + ta_insert = tc->readMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS); va_insert = mbits(ta_insert, 63,13); ct_insert = mbits(ta_insert, 12,0); - part_insert = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); + part_insert = tc->readMiscReg(MISCREG_MMU_PART_ID); real_insert = bits(va, 9,9); pte.populate(data, bits(va,10,10) ? PageTableEntry::sun4v : PageTableEntry::sun4u); @@ -1153,10 +1169,10 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) case ASI_IMMU_DEMAP: ignore = false; ctx_id = -1; - part_id = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); + part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); switch (bits(va,5,4)) { case 0: - ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT); + ctx_id = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); break; case 1: ignore = true; @@ -1188,14 +1204,14 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) case ASI_DMMU: switch (va) { case 0x18: - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_SFSR, data); + tc->setMiscReg(MISCREG_MMU_DTLB_SFSR, data); break; case 0x30: sext<59>(bits(data, 59,0)); - tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS, data); + tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS, data); break; case 0x80: - tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data); + tc->setMiscReg(MISCREG_MMU_PART_ID, data); break; default: goto doMmuWriteError; @@ -1204,13 +1220,13 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) case ASI_DMMU_DEMAP: ignore = false; ctx_id = -1; - part_id = tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID); + part_id = tc->readMiscReg(MISCREG_MMU_PART_ID); switch (bits(va,5,4)) { case 0: - ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT); + ctx_id = tc->readMiscReg(MISCREG_MMU_P_CONTEXT); break; case 1: - ctx_id = tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT); + ctx_id = tc->readMiscReg(MISCREG_MMU_S_CONTEXT); break; case 3: ctx_id = 0; @@ -1235,7 +1251,19 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) panic("Invalid type for IMMU demap\n"); } break; - default: + case ASI_SWVR_INTR_RECEIVE: + int msb; + // clear all the interrupts that aren't set in the write + while(tc->getCpuPtr()->get_interrupts(IT_INT_VEC) & data) { + msb = findMsbSet(tc->getCpuPtr()->get_interrupts(IT_INT_VEC) & data); + tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, msb); + } + break; + case ASI_SWVR_UDB_INTR_W: + tc->getSystemPtr()->threadContexts[bits(data,12,8)]->getCpuPtr()-> + post_interrupt(bits(data,5,0),0); + break; + default: doMmuWriteError: panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n", (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data); @@ -1245,6 +1273,64 @@ doMmuWriteError: } void +DTB::GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs) +{ + uint64_t tag_access = mbits(addr,63,13) | mbits(ctx,12,0); + ptrs[0] = MakeTsbPtr(Ps0, tag_access, + tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); + ptrs[1] = MakeTsbPtr(Ps1, tag_access, + tc->readMiscReg(MISCREG_MMU_DTLB_C0_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_DTLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_DTLB_CX_CONFIG)); + ptrs[2] = MakeTsbPtr(Ps0, tag_access, + tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS0), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); + ptrs[3] = MakeTsbPtr(Ps1, tag_access, + tc->readMiscReg(MISCREG_MMU_ITLB_C0_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_ITLB_C0_CONFIG), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_TSB_PS1), + tc->readMiscReg(MISCREG_MMU_ITLB_CX_CONFIG)); +} + + + + + +uint64_t +DTB::MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb, + uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config) +{ + uint64_t tsb; + uint64_t config; + + if (bits(tag_access, 12,0) == 0) { + tsb = c0_tsb; + config = c0_config; + } else { + tsb = cX_tsb; + config = cX_config; + } + + uint64_t ptr = mbits(tsb,63,13); + bool split = bits(tsb,12,12); + int tsb_size = bits(tsb,3,0); + int page_size = (ps == Ps0) ? bits(config, 2,0) : bits(config,10,8); + + if (ps == Ps1 && split) + ptr |= ULL(1) << (13 + tsb_size); + ptr |= (tag_access >> (9 + page_size * 3)) & mask(12+tsb_size, 4); + + return ptr; +} + + +void TLB::serialize(std::ostream &os) { SERIALIZE_SCALAR(size); @@ -1298,6 +1384,9 @@ TLB::unserialize(Checkpoint *cp, const std::string §ion) } } +/* end namespace SparcISA */ } + +using namespace SparcISA; DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB) @@ -1340,4 +1429,3 @@ CREATE_SIM_OBJECT(DTB) } REGISTER_SIM_OBJECT("SparcDTB", DTB) -} diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index 34e5f5feb..b5f02c62e 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -78,17 +78,25 @@ class TLB : public SimObject Nucleus = 2 }; - + enum TsbPageSize { + Ps0, + Ps1 + }; + public: /** lookup an entry in the TLB based on the partition id, and real bit if * real is true or the partition id, and context id if real is false. * @param va the virtual address not shifted (e.g. bottom 13 bits are 0) * @param paritition_id partition this entry is for * @param real is this a real->phys or virt->phys translation * @param context_id if this is virt->phys what context + * @param update_used should ew update the used bits in the entries on not + * useful if we are trying to do a va->pa without mucking with any state for + * a debug read for example. * @return A pointer to a tlb entry */ - TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0); - + TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0, + bool update_used = true); + protected: /** Insert a PTE into the TLB. */ void insert(Addr vpn, int partition_id, int context_id, bool real, const PageTableEntry& PTE, int entry = -1); @@ -163,12 +171,17 @@ class DTB : public TLB Fault translate(RequestPtr &req, ThreadContext *tc, bool write); Tick doMmuRegRead(ThreadContext *tc, Packet *pkt); Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt); + void GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs); private: void writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct, bool se, FaultTypes ft, int asi); void writeTagAccess(ThreadContext *tc, Addr va, int context); + uint64_t MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb, + uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config); + + TlbEntry *cacheEntry[2]; ASI cacheAsi[2]; }; diff --git a/src/arch/sparc/types.hh b/src/arch/sparc/types.hh index 88fb24153..15386adca 100644 --- a/src/arch/sparc/types.hh +++ b/src/arch/sparc/types.hh @@ -32,6 +32,7 @@ #define __ARCH_SPARC_TYPES_HH__ #include <inttypes.h> +#include "base/bigint.hh" namespace SparcISA { @@ -39,6 +40,7 @@ namespace SparcISA typedef uint64_t ExtMachInst; typedef uint64_t IntReg; + typedef Twin64_t LargestRead; typedef uint64_t MiscReg; typedef double FloatReg; typedef uint64_t FloatRegBits; diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index ecb63bb9a..48e97a531 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -26,106 +26,181 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "arch/sparc/kernel_stats.hh" #include "arch/sparc/miscregfile.hh" #include "base/bitfield.hh" #include "base/trace.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" +#include "sim/system.hh" using namespace SparcISA; + +void +MiscRegFile::checkSoftInt(ThreadContext *tc) +{ + // If PIL < 14, copy over the tm and sm bits + if (pil < 14 && softint & 0x10000) + tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,16); + else + tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,16); + if (pil < 14 && softint & 0x1) + tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,0); + else + tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,0); + + // Copy over any of the other bits that are set + for (int bit = 15; bit > 0; --bit) { + if (1 << bit & softint && bit > pil) + tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,bit); + else + tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,bit); + } +} + + void -MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, - ThreadContext *tc) +MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc) { int64_t time; switch (miscReg) { /* Full system only ASRs */ case MISCREG_SOFTINT: - setReg(miscReg, val);; + setRegNoEffect(miscReg, val);; + checkSoftInt(tc); break; - case MISCREG_SOFTINT_CLR: - return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc); + return setReg(MISCREG_SOFTINT, ~val & softint, tc); case MISCREG_SOFTINT_SET: - tc->getCpuPtr()->post_interrupt(soft_interrupt); - return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc); + return setReg(MISCREG_SOFTINT, val | softint, tc); case MISCREG_TICK_CMPR: if (tickCompare == NULL) tickCompare = new TickCompareEvent(this, tc); - setReg(miscReg, val); - if ((tick_cmpr & mask(63)) && tickCompare->scheduled()) + setRegNoEffect(miscReg, val); + if ((tick_cmpr & ~mask(63)) && tickCompare->scheduled()) tickCompare->deschedule(); time = (tick_cmpr & mask(63)) - (tick & mask(63)); - if (!(tick_cmpr & ~mask(63)) && time > 0) + if (!(tick_cmpr & ~mask(63)) && time > 0) { + if (tickCompare->scheduled()) + tickCompare->deschedule(); tickCompare->schedule(time * tc->getCpuPtr()->cycles(1)); + } panic("writing to TICK compare register %#X\n", val); break; case MISCREG_STICK_CMPR: if (sTickCompare == NULL) sTickCompare = new STickCompareEvent(this, tc); - setReg(miscReg, val); + setRegNoEffect(miscReg, val); if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled()) sTickCompare->deschedule(); time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) - tc->getCpuPtr()->instCount(); - if (!(stick_cmpr & ~mask(63)) && time > 0) + if (!(stick_cmpr & ~mask(63)) && time > 0) { + if (sTickCompare->scheduled()) + sTickCompare->deschedule(); sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick); + } DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val); break; case MISCREG_PSTATE: - setReg(miscReg, val); + setRegNoEffect(miscReg, val); case MISCREG_PIL: - setReg(miscReg, val); + setRegNoEffect(miscReg, val); + checkSoftInt(tc); break; case MISCREG_HVER: panic("Shouldn't be writing HVER\n"); case MISCREG_HINTP: - setReg(miscReg, val); + setRegNoEffect(miscReg, val); + if (hintp) + tc->getCpuPtr()->post_interrupt(IT_HINTP,0); + else + tc->getCpuPtr()->clear_interrupt(IT_HINTP,0); + break; case MISCREG_HTBA: // clear lower 7 bits on writes. - setReg(miscReg, val & ULL(~0x7FFF)); + setRegNoEffect(miscReg, val & ULL(~0x7FFF)); break; case MISCREG_QUEUE_CPU_MONDO_HEAD: case MISCREG_QUEUE_CPU_MONDO_TAIL: + setRegNoEffect(miscReg, val); + if (cpu_mondo_head != cpu_mondo_tail) + tc->getCpuPtr()->post_interrupt(IT_CPU_MONDO,0); + else + tc->getCpuPtr()->clear_interrupt(IT_CPU_MONDO,0); + break; case MISCREG_QUEUE_DEV_MONDO_HEAD: case MISCREG_QUEUE_DEV_MONDO_TAIL: + setRegNoEffect(miscReg, val); + if (dev_mondo_head != dev_mondo_tail) + tc->getCpuPtr()->post_interrupt(IT_DEV_MONDO,0); + else + tc->getCpuPtr()->clear_interrupt(IT_DEV_MONDO,0); + break; case MISCREG_QUEUE_RES_ERROR_HEAD: case MISCREG_QUEUE_RES_ERROR_TAIL: + setRegNoEffect(miscReg, val); + if (res_error_head != res_error_tail) + tc->getCpuPtr()->post_interrupt(IT_RES_ERROR,0); + else + tc->getCpuPtr()->clear_interrupt(IT_RES_ERROR,0); + break; case MISCREG_QUEUE_NRES_ERROR_HEAD: case MISCREG_QUEUE_NRES_ERROR_TAIL: - setReg(miscReg, val); - //do something to post mondo interrupt + setRegNoEffect(miscReg, val); + // This one doesn't have an interrupt to report to the guest OS break; case MISCREG_HSTICK_CMPR: if (hSTickCompare == NULL) hSTickCompare = new HSTickCompareEvent(this, tc); - setReg(miscReg, val); + setRegNoEffect(miscReg, val); if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled()) hSTickCompare->deschedule(); time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - tc->getCpuPtr()->instCount(); - if (!(hstick_cmpr & ~mask(63)) && time > 0) + if (!(hstick_cmpr & ~mask(63)) && time > 0) { + if (hSTickCompare->scheduled()) + hSTickCompare->deschedule(); hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1)); + } DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val); break; case MISCREG_HPSTATE: // T1000 spec says impl. dependent val must always be 1 - setReg(miscReg, val | HPSTATE::id); + setRegNoEffect(miscReg, val | HPSTATE::id); +#if FULL_SYSTEM + if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv)) + tc->getCpuPtr()->post_interrupt(IT_TRAP_LEVEL_ZERO,0); + else + tc->getCpuPtr()->clear_interrupt(IT_TRAP_LEVEL_ZERO,0); +#endif break; case MISCREG_HTSTATE: + setRegNoEffect(miscReg, val); + break; + case MISCREG_STRAND_STS_REG: - setReg(miscReg, val); + if (bits(val,2,2)) + panic("No support for setting spec_en bit\n"); + setRegNoEffect(miscReg, bits(val,0,0)); + if (!bits(val,0,0)) { + DPRINTF(Quiesce, "Cpu executed quiescing instruction\n"); + // Time to go to sleep + tc->suspend(); + if (tc->getKernelStats()) + tc->getKernelStats()->quiesce(); + } break; default: @@ -134,8 +209,10 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, } MiscReg -MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc) +MiscRegFile::readFSReg(int miscReg, ThreadContext * tc) { + uint64_t temp; + switch (miscReg) { /* Privileged registers. */ case MISCREG_QUEUE_CPU_MONDO_HEAD: @@ -153,15 +230,52 @@ MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc) case MISCREG_HPSTATE: case MISCREG_HINTP: case MISCREG_HTSTATE: - case MISCREG_STRAND_STS_REG: case MISCREG_HSTICK_CMPR: - return readReg(miscReg) ; + return readRegNoEffect(miscReg) ; case MISCREG_HTBA: - return readReg(miscReg) & ULL(~0x7FFF); + return readRegNoEffect(miscReg) & ULL(~0x7FFF); case MISCREG_HVER: - return NWindows | MaxTL << 8 | MaxGL << 16; + // XXX set to match Legion + return ULL(0x3e) << 48 | + ULL(0x23) << 32 | + ULL(0x20) << 24 | + //MaxGL << 16 | XXX For some reason legion doesn't set GL + MaxTL << 8 | + (NWindows -1) << 0; + case MISCREG_STRAND_STS_REG: + System *sys; + int x; + sys = tc->getSystemPtr(); + + temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative); + // Check that the CPU array is fully populated (by calling getNumCPus()) + assert(sys->getNumCPUs() > tc->readCpuId()); + + temp |= tc->readCpuId() << STS::shft_id; + + for (x = tc->readCpuId() & ~3; x < sys->threadContexts.size(); x++) { + switch (sys->threadContexts[x]->status()) { + case ThreadContext::Active: + temp |= STS::st_run << (STS::shft_fsm0 - + ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1))); + break; + case ThreadContext::Suspended: + // should this be idle? + temp |= STS::st_idle << (STS::shft_fsm0 - + ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1))); + break; + case ThreadContext::Halted: + temp |= STS::st_halt << (STS::shft_fsm0 - + ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1))); + break; + default: + panic("What state are we in?!\n"); + } // switch + } // for + + return temp; default: panic("Invalid read to FS misc register\n"); } @@ -194,12 +308,11 @@ MiscRegFile::processSTickCompare(ThreadContext *tc) tc->getCpuPtr()->instCount(); assert(ticks >= 0 && "stick compare missed interrupt cycle"); - if (ticks == 0) { + if (ticks == 0 || tc->status() == ThreadContext::Suspended) { DPRINTF(Timer, "STick compare cycle reached at %#x\n", (stick_cmpr & mask(63))); - if (!(tc->readMiscReg(MISCREG_STICK_CMPR) & (ULL(1) << 63))) { - tc->getCpuPtr()->post_interrupt(soft_interrupt); - setRegWithEffect(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc); + if (!(tc->readMiscRegNoEffect(MISCREG_STICK_CMPR) & (ULL(1) << 63))) { + setReg(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc); } } else sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick); @@ -212,19 +325,22 @@ MiscRegFile::processHSTickCompare(ThreadContext *tc) // we're actually at the correct cycle or we need to wait a little while // more int ticks; + if ( tc->status() == ThreadContext::Halted || + tc->status() == ThreadContext::Unallocated) + return; + ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) - tc->getCpuPtr()->instCount(); assert(ticks >= 0 && "hstick compare missed interrupt cycle"); - if (ticks == 0) { + if (ticks == 0 || tc->status() == ThreadContext::Suspended) { DPRINTF(Timer, "HSTick compare cycle reached at %#x\n", (stick_cmpr & mask(63))); - if (!(tc->readMiscReg(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) { - setRegWithEffect(MISCREG_HINTP, 1, tc); - tc->getCpuPtr()->post_interrupt(hstick_match); + if (!(tc->readMiscRegNoEffect(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) { + setReg(MISCREG_HINTP, 1, tc); } // Need to do something to cause interrupt to happen here !!! @todo } else - sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick); + hSTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick); } diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index 3c8bdcd01..1458231f2 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -44,24 +44,8 @@ namespace SparcISA static inline bool inUserMode(ThreadContext *tc) { - return !(tc->readMiscReg(MISCREG_PSTATE & (1 << 2)) || - tc->readMiscReg(MISCREG_HPSTATE & (1 << 2))); - } - - inline ExtMachInst - makeExtMI(MachInst inst, ThreadContext * xc) { - ExtMachInst emi = (MachInst) inst; - //The I bit, bit 13, is used to figure out where the ASI - //should come from. Use that in the ExtMachInst. This is - //slightly redundant, but it removes the need to put a condition - //into all the execute functions - if(inst & (1 << 13)) - emi |= (static_cast<ExtMachInst>(xc->readMiscReg(MISCREG_ASI)) - << (sizeof(MachInst) * 8)); - else - emi |= (static_cast<ExtMachInst>(bits(inst, 12, 5)) - << (sizeof(MachInst) * 8)); - return emi; + return !(tc->readMiscRegNoEffect(MISCREG_PSTATE & (1 << 2)) || + tc->readMiscRegNoEffect(MISCREG_HPSTATE & (1 << 2))); } inline bool isCallerSaveIntegerRegister(unsigned int reg) { @@ -112,7 +96,20 @@ namespace SparcISA inline void initCPU(ThreadContext *tc, int cpuId) { static Fault por = new PowerOnReset(); - por->invoke(tc); + if (cpuId == 0) + por->invoke(tc); + + } + + inline void startupCPU(ThreadContext *tc, int cpuId) + { +#if FULL_SYSTEM + // Other CPUs will get activated by IPIs + if (cpuId == 0) + tc->activate(0); +#else + tc->activate(0); +#endif } } // namespace SparcISA diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc index 429126b70..9a93950d2 100644 --- a/src/arch/sparc/vtophys.cc +++ b/src/arch/sparc/vtophys.cc @@ -25,14 +25,14 @@ * (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 - * Ali Saidi + * Authors: Ali Saidi */ #include <string> #include "arch/sparc/vtophys.hh" +#include "arch/sparc/tlb.hh" +#include "base/compiler.hh" #include "base/chunk_generator.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" @@ -42,37 +42,83 @@ using namespace std; namespace SparcISA { - PageTableEntry kernel_pte_lookup(FunctionalPort *mem, - Addr ptbr, VAddr vaddr) - { - PageTableEntry pte(4); - return pte; - } - Addr vtophys(Addr vaddr) { - return vaddr; + // In SPARC it's almost always impossible to turn a VA->PA w/o a context + // The only times we can kinda do it are if we have a SegKPM mapping + // and can find the real address in the tlb or we have a physical + // adddress already (beacuse we are looking at the hypervisor) + // Either case is rare, so we'll just panic. + + panic("vtophys() without context on SPARC largly worthless\n"); + M5_DUMMY_RETURN } Addr vtophys(ThreadContext *tc, Addr addr) { - return addr; - } + // Here we have many options and are really implementing something like + // a fill handler to find the address since there isn't a multilevel + // table for us to walk around. + // + // 1. We are currently hyperpriv, return the address unmodified + // 2. The mmu is off return(ra->pa) + // 3. We are currently priv, use ctx0* tsbs to find the page + // 4. We are not priv, use ctxN0* tsbs to find the page + // For all accesses we check the tlbs first since it's possible that + // long standing pages (e.g. locked kernel mappings) won't be in the tsb + uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA); + bool hpriv = bits(tlbdata,0,0); + //bool priv = bits(tlbdata,2,2); + bool addr_mask = bits(tlbdata,3,3); + bool data_real = !bits(tlbdata,5,5); + bool inst_real = !bits(tlbdata,4,4); + bool ctx_zero = bits(tlbdata,18,16) > 0; + int part_id = bits(tlbdata,15,8); + int pri_context = bits(tlbdata,47,32); + //int sec_context = bits(tlbdata,63,48); - void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) - { - } + FunctionalPort *mem = tc->getPhysPort(); + ITB* itb = tc->getITBPtr(); + DTB* dtb = tc->getDTBPtr(); + TlbEntry* tbe; + PageTableEntry pte; + Addr tsbs[4]; + Addr va_tag; + TteTag ttetag; - void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) - { - } + if (hpriv) + return addr; - void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) - { - } + if (addr_mask) + addr = addr & VAddrAMask; - void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) - { + tbe = dtb->lookup(addr, part_id, data_real, ctx_zero ? 0 : pri_context , false); + if (tbe) goto foundtbe; + + tbe = itb->lookup(addr, part_id, inst_real, ctx_zero ? 0 : pri_context, false); + if (tbe) goto foundtbe; + + // We didn't find it in the tlbs, so lets look at the TSBs + dtb->GetTsbPtr(tc, addr, ctx_zero ? 0 : pri_context, tsbs); + va_tag = bits(addr, 63, 22); + for (int x = 0; x < 4; x++) { + ttetag = betoh(mem->read<uint64_t>(tsbs[x])); + if (ttetag.valid() && ttetag.va() == va_tag) { + pte.populate(betoh(mem->read<uint64_t>(tsbs[x]) + sizeof(uint64_t)), + PageTableEntry::sun4v); // I think it's sun4v at least! + DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TTE\n", addr, + pte.paddrMask() | addr & pte.sizeMask()); + goto foundpte; + } + } + panic("couldn't translate %#x\n", addr); + +foundtbe: + pte = tbe->pte; + DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TLB\n", addr, + pte.paddrMask() | addr & pte.sizeMask()); +foundpte: + return pte.paddrMask() | addr & pte.sizeMask(); } } diff --git a/src/arch/sparc/vtophys.hh b/src/arch/sparc/vtophys.hh index 66679a565..f55967b53 100644 --- a/src/arch/sparc/vtophys.hh +++ b/src/arch/sparc/vtophys.hh @@ -46,11 +46,6 @@ kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, SparcISA::VAddr 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); - }; #endif // __ARCH_SPARC_VTOPHYS_H__ diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript new file mode 100644 index 000000000..2e2c5b006 --- /dev/null +++ b/src/arch/x86/SConscript @@ -0,0 +1,111 @@ +# -*- mode:python -*- + +# Copyright (c) 2005-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: Gabe Black + +# Copyright (c) 2007 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. Redistributions +# in binary form must reproduce the above copyright notice, this list of +# conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. Neither the name of +# the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +Import('*') +if env['TARGET_ISA'] == 'x86': + Source('floatregfile.cc') + Source('intregfile.cc') + Source('miscregfile.cc') + Source('predecoder.cc') + Source('predecoder_tables.cc') + Source('regfile.cc') + Source('remote_gdb.cc') + + if env['FULL_SYSTEM']: + # Full-system sources + pass + else: + Source('process.cc') + + Source('linux/linux.cc') + Source('linux/process.cc') + Source('linux/syscalls.cc') + + # Add in files generated by the ISA description. + isa_desc_files = env.ISADesc('isa/main.isa') + # Only non-header files need to be compiled. + for f in isa_desc_files: + if not f.path.endswith('.hh'): + Source(f) diff --git a/src/arch/x86/SConsopts b/src/arch/x86/SConsopts new file mode 100644 index 000000000..d8b7cbed1 --- /dev/null +++ b/src/arch/x86/SConsopts @@ -0,0 +1,60 @@ +# -*- mode:python -*- + +# Copyright (c) 2007 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. Redistributions +# in binary form must reproduce the above copyright notice, this list of +# conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. Neither the name of +# the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Gabe Black + +Import('*') + +all_isa_list.append('x86') diff --git a/src/arch/x86/arguments.hh b/src/arch/x86/arguments.hh new file mode 100644 index 000000000..e645766bf --- /dev/null +++ b/src/arch/x86/arguments.hh @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_ARGUMENTS_HH__ +#define __ARCH_X86_ARGUMENTS_HH__ + +#error X86 is not yet supported! + +namespace X86ISA +{ +}; + +#endif // __ARCH_X86_ARGUMENTS_HH__ diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh new file mode 100644 index 000000000..6d89c273a --- /dev/null +++ b/src/arch/x86/faults.hh @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_FAULTS_HH__ +#define __ARCH_X86_FAULTS_HH__ + +#include "base/misc.hh" +#include "sim/faults.hh" + +namespace X86ISA +{ + class X86Fault : public FaultBase + { + void invoke(ThreadContext * tc) + { + panic("X86 faults are not implemented!"); + } + }; + + static inline Fault genPageTableFault(Addr va) + { + panic("Page table fault not implemented in x86!\n"); + } + + static inline Fault genMachineCheckFault() + { + panic("Machine check fault not implemented in x86!\n"); + } + + static inline Fault genAlignmentFault() + { + panic("Alignment fault not implemented (or for the most part existant) in x86!\n"); + } +}; + +#endif // __ARCH_X86_FAULTS_HH__ diff --git a/src/arch/x86/floatregfile.cc b/src/arch/x86/floatregfile.cc new file mode 100644 index 000000000..515ed0958 --- /dev/null +++ b/src/arch/x86/floatregfile.cc @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2003-2007 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 + */ + +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/floatregfile.hh" +#include "sim/serialize.hh" + +#include <string.h> + +using namespace X86ISA; +using namespace std; + +class Checkpoint; + +string X86ISA::getFloatRegName(RegIndex index) +{ + static std::string floatRegName[NumFloatRegs] = + {"mmx0", "mmx1", "mmx2", "mmx3", "mmx4", "mmx5", "mmx6", "mmx7", + "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"}; + return floatRegName[index]; +} + +void FloatRegFile::clear() +{ + memset(q, 0, sizeof(FloatReg) * NumFloatRegs); +} + +FloatReg FloatRegFile::readReg(int floatReg, int width) +{ + panic("Floating point not implemented for x86!\n"); +} + +FloatRegBits FloatRegFile::readRegBits(int floatReg, int width) +{ + panic("Floating point not implemented for x86!\n"); +} + +Fault FloatRegFile::setReg(int floatReg, const FloatReg &val, int width) +{ + panic("Floating point not implemented for x86!\n"); +} + +Fault FloatRegFile::setRegBits(int floatReg, const FloatRegBits &val, int width) +{ + panic("Floating point not implemented for x86!\n"); +} + +void FloatRegFile::serialize(std::ostream &os) +{ + SERIALIZE_ARRAY(q, NumFloatRegs); +} + +void FloatRegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY(q, NumFloatRegs); +} + diff --git a/src/arch/x86/floatregfile.hh b/src/arch/x86/floatregfile.hh new file mode 100644 index 000000000..18371280d --- /dev/null +++ b/src/arch/x86/floatregfile.hh @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2003-2007 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 + */ + +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_FLOATREGFILE_HH__ +#define __ARCH_X86_FLOATREGFILE_HH__ + +#include <string> + +#include "arch/x86/faults.hh" +#include "arch/x86/types.hh" +#include "arch/x86/x86_traits.hh" + +class Checkpoint; + +namespace X86ISA +{ + std::string getFloatRegName(RegIndex); + + const int NumFloatArchRegs = NumMMXRegs + NumXMMRegs; + const int NumFloatRegs = NumFloatArchRegs; + + class FloatRegFile + { + public: + static const int SingleWidth = 32; + static const int DoubleWidth = 64; + static const int QuadWidth = 128; + + protected: + union + { + uint64_t q[NumFloatRegs]; + double d[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 §ion); + }; +} + +#endif //__ARCH_X86_FLOATREGFILE_HH__ diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh new file mode 100644 index 000000000..3f33b8d85 --- /dev/null +++ b/src/arch/x86/interrupts.hh @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_INTERRUPTS_HH__ +#define __ARCH_X86_INTERRUPTS_HH__ + +#error X86 is not yet supported! + +namespace X86ISA +{ +}; + +#endif // __ARCH_X86_INTERRUPTS_HH__ diff --git a/src/arch/x86/intregfile.cc b/src/arch/x86/intregfile.cc new file mode 100644 index 000000000..15e86d88b --- /dev/null +++ b/src/arch/x86/intregfile.cc @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2003-2007 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 + */ + +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/intregfile.hh" +#include "base/misc.hh" +#include "sim/serialize.hh" + +#include <string.h> + +using namespace X86ISA; +using namespace std; + +class Checkpoint; + +string X86ISA::getIntRegName(RegIndex index) +{ + //These might appear to be out of order, but they match + //the encoding for the registers. Who knows why the indexes + //are out of order + static std::string intRegName[NumIntArchRegs] = + {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}; + return intRegName[index]; +} + +int IntRegFile::flattenIndex(int reg) +{ + return reg; +} + +void IntRegFile::clear() +{ + memset(regs, 0, sizeof(IntReg) * NumIntRegs); +} + +IntReg IntRegFile::readReg(int intReg) +{ + return regs[intReg]; +} + +void IntRegFile::setReg(int intReg, const IntReg &val) +{ + regs[intReg] = val; +} + +void IntRegFile::serialize(std::ostream &os) +{ + SERIALIZE_ARRAY(regs, NumIntRegs); +} + +void IntRegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ARRAY(regs, NumIntRegs); +} diff --git a/src/arch/x86/intregfile.hh b/src/arch/x86/intregfile.hh new file mode 100644 index 000000000..f7b03f0f0 --- /dev/null +++ b/src/arch/x86/intregfile.hh @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2003-2007 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 + */ + +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_INTREGFILE_HH__ +#define __ARCH_X86_INTREGFILE_HH__ + +#include "arch/x86/intregs.hh" +#include "arch/x86/types.hh" +#include "arch/x86/x86_traits.hh" + +#include <string> + +class Checkpoint; + +namespace X86ISA +{ + class Regfile; + + //This function translates integer register file indices into names + std::string getIntRegName(RegIndex); + + const int NumIntArchRegs = NUM_INTREGS; + const int NumIntRegs = NumIntArchRegs + NumMicroIntRegs; + + class IntRegFile + { + protected: + IntReg regs[NumIntRegs]; + + public: + + int flattenIndex(int reg); + + void clear(); + + IntReg readReg(int intReg); + + void setReg(int intReg, const IntReg &val); + + void serialize(std::ostream &os); + + void unserialize(Checkpoint *cp, const std::string §ion); + }; +} + +#endif //__ARCH_X86_INTREGFILE__ diff --git a/src/arch/x86/intregs.hh b/src/arch/x86/intregs.hh new file mode 100644 index 000000000..ed801cc48 --- /dev/null +++ b/src/arch/x86/intregs.hh @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_INTREGS_HH__ +#define __ARCH_X86_INTREGS_HH__ + +namespace X86ISA +{ + enum IntRegIndex + { + INTREG_RAX, + INTREG_RCX, + INTREG_RDX, + INTREG_RBX, + INTREG_RSP, + INTREG_RBP, + INTREG_RSI, + INTREG_RDI, + INTREG_R8W, + INTREG_R9W, + INTREG_R10W, + INTREG_R11W, + INTREG_R12W, + INTREG_R13W, + INTREG_R14W, + INTREG_R15W, + NUM_INTREGS + }; +}; + +#endif // __ARCH_X86_INTERRUPTS_HH__ diff --git a/src/arch/x86/isa/base.isa b/src/arch/x86/isa/base.isa new file mode 100644 index 000000000..4776f7a7e --- /dev/null +++ b/src/arch/x86/isa/base.isa @@ -0,0 +1,181 @@ +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Base class for sparc instructions, and some support functions +// + +output header {{ + + /** + * Base class for all X86 static instructions. + */ + class X86StaticInst : public StaticInst + { + protected: + // Constructor. + X86StaticInst(const char *mnem, + ExtMachInst _machInst, OpClass __opClass) + : StaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, + 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; + }; +}}; + +output decoder {{ + + inline void printMnemonic(std::ostream &os, const char * mnemonic) + { + ccprintf(os, "\t%s ", mnemonic); + } + + void + X86StaticInst::printSrcReg(std::ostream &os, int reg) const + { + if(_numSrcRegs > reg) + printReg(os, _srcRegIdx[reg]); + } + + void + X86StaticInst::printDestReg(std::ostream &os, int reg) const + { + if(_numDestRegs > reg) + printReg(os, _destRegIdx[reg]); + } + + void + X86StaticInst::printReg(std::ostream &os, int reg) const + { + if (reg < FP_Base_DepTag) { + //FIXME These should print differently depending on the + //mode etc, but for now this will get the point across + switch (reg) { + case INTREG_RAX: + ccprintf(os, "rax"); + break; + case INTREG_RBX: + ccprintf(os, "rbx"); + break; + case INTREG_RCX: + ccprintf(os, "rcx"); + break; + case INTREG_RDX: + ccprintf(os, "rdx"); + break; + case INTREG_RSP: + ccprintf(os, "rsp"); + break; + case INTREG_RBP: + ccprintf(os, "rbp"); + break; + case INTREG_RSI: + ccprintf(os, "rsi"); + break; + case INTREG_RDI: + ccprintf(os, "rdi"); + break; + case INTREG_R8W: + ccprintf(os, "r8"); + break; + case INTREG_R9W: + ccprintf(os, "r9"); + break; + case INTREG_R10W: + ccprintf(os, "r10"); + break; + case INTREG_R11W: + ccprintf(os, "r11"); + break; + case INTREG_R12W: + ccprintf(os, "r12"); + break; + case INTREG_R13W: + ccprintf(os, "r13"); + break; + case INTREG_R14W: + ccprintf(os, "r14"); + break; + case INTREG_R15W: + ccprintf(os, "r15"); + break; + } + } else if (reg < Ctrl_Base_DepTag) { + ccprintf(os, "%%f%d", reg - FP_Base_DepTag); + } else { + switch (reg - Ctrl_Base_DepTag) { + default: + ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag); + } + } + } + + std::string X86StaticInst::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream ss; + + printMnemonic(ss, mnemonic); + + return ss.str(); + } +}}; diff --git a/src/arch/x86/isa/bitfields.isa b/src/arch/x86/isa/bitfields.isa new file mode 100644 index 000000000..fff324caa --- /dev/null +++ b/src/arch/x86/isa/bitfields.isa @@ -0,0 +1,87 @@ +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Bitfield definitions. +// + +//Prefixes +def bitfield REX rex; +def bitfield LEGACY legacy; + +// Pieces of the opcode +def bitfield OPCODE_NUM opcode.num; +def bitfield OPCODE_PREFIXA opcode.prefixA; +def bitfield OPCODE_PREFIXB opcode.prefixB; +def bitfield OPCODE_OP opcode.op; +//The top 5 bits of the opcode tend to split the instructions into groups +def bitfield OPCODE_OP_TOP5 opcode.op.top5; +def bitfield OPCODE_OP_BOTTOM3 opcode.op.bottom3; + +// Immediate fields +def bitfield IMMEDIATE immediate; +def bitfield DISPLACEMENT displacement; + +//Modifier bytes +def bitfield MODRM modRM; +def bitfield MODRM_MOD modRM.mod; +def bitfield MODRM_REG modRM.reg; +def bitfield MODRM_RM modRM.rm; + +def bitfield SIB sib; +def bitfield SIB_SCALE sib.scale; +def bitfield SIB_INDEX sib.index; +def bitfield SIB_BASE sib.base; diff --git a/src/arch/x86/isa/decoder/decoder.isa b/src/arch/x86/isa/decoder/decoder.isa new file mode 100644 index 000000000..20f31f882 --- /dev/null +++ b/src/arch/x86/isa/decoder/decoder.isa @@ -0,0 +1,89 @@ +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// The actual decoder specification +// + +decode OPCODE_NUM default Unknown::unknown() +{ + 0x0: M5InternalError::error( + {{"Saw an ExtMachInst with zero opcode bytes!"}}); + //1 byte opcodes + ##include "one_byte_opcodes.isa" + //2 byte opcodes + ##include "two_byte_opcodes.isa" + //3 byte opcodes + 0x3: decode OPCODE_PREFIXA { + 0xF0: decode OPCODE_PREFIXB { + //We don't handle these properly in the predecoder yet, so there's + //no reason to implement them for now. + 0x38: decode OPCODE_OP { + default: FailUnimpl::sseThreeEight(); + } + 0x3A: decode OPCODE_OP { + default: FailUnimpl::sseThreeA(); + } + 0xF0: decode OPCODE_OP { + default: FailUnimpl::threednow(); + } + default: M5InternalError::error( + {{"Unexpected second opcode byte in three byte opcode!"}}); + } + default: M5InternalError::error( + {{"Unexpected first opcode byte in three byte opcode!"}}); + } +} diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa new file mode 100644 index 000000000..c56a8bf92 --- /dev/null +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -0,0 +1,398 @@ +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Decode the one byte opcodes +// + +0x1: decode OPCODE_OP_TOP5 { + format WarnUnimpl { + 0x00: decode OPCODE_OP_BOTTOM3 { + 0x6: push_ES(); + 0x7: pop_ES(); + default: MultiOp::add( + {{out1 = in1 + in2}}, + OPCODE_OP_BOTTOM3, + [[Eb,Gb],[Ev,Gv], + [Gb,Eb],[Gv,Ev], + [Al,Ib],[rAx,Iz]]); + } + 0x01: decode OPCODE_OP_BOTTOM3 { + 0x0: or_Eb_Gb(); + 0x1: or_Ev_Gv(); + 0x2: or_Gb_Eb(); + 0x3: or_Gv_Ev(); + 0x4: or_Al_Ib(); + 0x5: or_rAX_Iz(); + 0x6: push_CS(); + //Any time this is seen, it should generate a two byte opcode + 0x7: M5InternalError::error( + {{"Saw a one byte opcode whose value was 0x0F!"}}); + } + 0x02: decode OPCODE_OP_BOTTOM3 { + 0x0: adc_Eb_Gb(); + 0x1: adc_Ev_Gv(); + 0x2: adc_Gb_Eb(); + 0x3: adc_Gv_Ev(); + 0x4: adc_Al_Ib(); + 0x5: adc_rAX_Iz(); + 0x6: push_SS(); + 0x7: pop_SS(); + } + 0x03: decode OPCODE_OP_BOTTOM3 { + 0x0: sbb_Eb_Gb(); + 0x1: sbb_Ev_Gv(); + 0x2: sbb_Gb_Eb(); + 0x3: sbb_Gv_Ev(); + 0x4: sbb_Al_Ib(); + 0x5: sbb_rAX_Iz(); + 0x6: push_DS(); + 0x7: pop_DS(); + } + 0x04: decode OPCODE_OP_BOTTOM3 { + 0x0: and_Eb_Gb(); + 0x1: and_Ev_Gv(); + 0x2: and_Gb_Eb(); + 0x3: and_Gv_Ev(); + 0x4: and_Al_Ib(); + 0x5: and_rAX_Iz(); + 0x6: M5InternalError::error( + {{"Tried to execute the ES segment override prefix!"}}); + 0x7: daa(); + } + 0x05: decode OPCODE_OP_BOTTOM3 { + 0x0: sub_Eb_Gb(); + 0x1: sub_Ev_Gv(); + 0x2: sub_Gb_Eb(); + 0x3: sub_Gv_Ev(); + 0x4: sub_Al_Ib(); + 0x5: sub_rAX_Iz(); + 0x6: M5InternalError::error( + {{"Tried to execute the CS segment override prefix!"}}); + 0x7: das(); + } + 0x06: decode OPCODE_OP_BOTTOM3 { + 0x0: xor_Eb_Gb(); + 0x1: xor_Ev_Gv(); + 0x2: xor_Gb_Eb(); + 0x3: xor_Gv_Ev(); + 0x4: xor_Al_Ib(); + 0x5: xor_rAX_Iz(); + 0x6: M5InternalError::error( + {{"Tried to execute the SS segment override prefix!"}}); + 0x7: aaa(); + } + 0x07: decode OPCODE_OP_BOTTOM3 { + 0x0: cmp_Eb_Gb(); + 0x1: cmp_Ev_Gv(); + 0x2: cmp_Gb_Eb(); + 0x3: cmp_Gv_Ev(); + 0x4: cmp_Al_Ib(); + 0x5: cmp_rAX_Iz(); + 0x6: M5InternalError::error( + {{"Tried to execute the DS segment override prefix!"}}); + 0x7: aas(); + } + 0x08: decode OPCODE_OP_BOTTOM3 { + 0x0: inc_eAX(); + 0x1: inc_eCX(); + 0x2: inc_eDX(); + 0x3: inc_eBX(); + 0x4: inc_eSP(); + 0x5: inc_eBP(); + 0x6: inc_eSI(); + 0x7: inc_eDI(); + } + 0x09: decode OPCODE_OP_BOTTOM3 { + 0x0: dec_eAX(); + 0x1: dec_eCX(); + 0x2: dec_eDX(); + 0x3: dec_eBX(); + 0x4: dec_eSP(); + 0x5: dec_eBP(); + 0x6: dec_eSI(); + 0x7: dec_eDI(); + } + 0x0A: decode OPCODE_OP_BOTTOM3 { + 0x0: push_rAX(); + 0x1: push_rCX(); + 0x2: push_rDX(); + 0x3: push_rBX(); + 0x4: push_rSP(); + 0x5: push_rBP(); + 0x6: push_rSI(); + 0x7: push_rDI(); + } + 0x0B: decode OPCODE_OP_BOTTOM3 { + 0x0: pop_rAX(); + 0x1: pop_rCX(); + 0x2: pop_rDX(); + 0x3: pop_rBX(); + 0x4: pop_rSP(); + 0x5: pop_rBP(); + 0x6: pop_rSI(); + 0x7: pop_rDI(); + } + 0x0C: decode OPCODE_OP_BOTTOM3 { + 0x0: pusha(); + 0x1: popa(); + 0x2: bound_Gv_Ma(); + 0x3: arpl_Ew_Gw(); + 0x4: M5InternalError::error( + {{"Tried to execute the FS segment override prefix!"}}); + 0x5: M5InternalError::error( + {{"Tried to execute the GS segment override prefix!"}}); + 0x6: M5InternalError::error( + {{"Tried to execute the operand size override prefix!"}}); + 0x7: M5InternalError::error( + {{"Tried to execute the DS address size override prefix!"}}); + } + 0x0D: decode OPCODE_OP_BOTTOM3 { + 0x0: push_Iz(); + 0x1: imul_Gv_Ev_Iz(); + 0x2: push_Ib(); + 0x3: imul_Gv_Ev_Ib(); + 0x4: ins_Yb_Dx(); + 0x5: ins_Yz_Dx(); + 0x6: outs_Dx_Xb(); + 0x7: outs_Dx_Xz(); + } + 0x0E: decode OPCODE_OP_BOTTOM3 { + 0x0: jo_Jb(); + 0x1: jno_Jb(); + 0x2: jb_Jb(); + 0x3: jnb_Jb(); + 0x4: jz_Jb(); + 0x5: jnz_Jb(); + 0x6: jbe_Jb(); + 0x7: jnbe_Jb(); + } + 0x0F: decode OPCODE_OP_BOTTOM3 { + 0x0: js_Jb(); + 0x1: jns_Jb(); + 0x2: jp_Jb(); + 0x3: jnp_Jb(); + 0x4: jl_Jb(); + 0x5: jnl_Jb(); + 0x6: jle_Jb(); + 0x7: jnke_Jb(); + } + 0x10: decode OPCODE_OP_BOTTOM3 { + 0x0: group1_Eb_Ib(); + 0x1: group1_Ev_Iz(); + 0x2: group1_Eb_Ib(); + 0x3: group1_Ev_Ib(); + 0x4: test_Eb_Gb(); + 0x5: test_Ev_Gv(); + 0x6: xchg_Eb_Gb(); + 0x7: xchg_Ev_Gv(); + } + 0x11: decode OPCODE_OP_BOTTOM3 { + 0x0: mov_Eb_Gb(); + 0x1: mov_Ev_Gv(); + 0x2: mov_Gb_Eb(); + 0x3: mov_Gv_Ev(); + 0x4: mov_MwRv_Sw(); + 0x5: lea_Gv_M(); + 0x6: mov_Sw_MwRv(); + 0x7: group10_Ev(); //Make sure this is Ev + } + 0x12: decode OPCODE_OP_BOTTOM3 { + 0x0: nop_or_pause(); //Check for repe prefix + 0x1: xchg_rCX_rAX(); + 0x2: xchg_rDX_rAX(); + 0x3: xchg_rVX_rAX(); + 0x4: xchg_rSP_rAX(); + 0x5: xchg_rBP_rAX(); + 0x6: xchg_rSI_rAX(); + 0x7: xchg_rDI_rAX(); + } + 0x13: decode OPCODE_OP_BOTTOM3 { + 0x0: cbw_or_cwde_or_cdqe_rAX(); + 0x1: cwd_or_cdq_or_cqo_rAX_rDX(); + 0x2: call_Ap(); + 0x3: fwait(); //aka wait + 0x4: pushf_Fv(); + 0x5: popf_Fv(); + 0x6: sahf(); + 0x7: lahf(); + } + 0x14: decode OPCODE_OP_BOTTOM3 { + 0x0: mov_Al_Ob(); + 0x1: mov_rAX_Ov(); + 0x2: mov_Ob_Al(); + 0x3: mov_Ov_rAX(); + 0x4: movs_Yb_Xb(); + 0x5: movs_Yv_Xv(); + 0x6: cmps_Yb_Xb(); + 0x7: cmps_Yv_Xv(); + } + 0x15: decode OPCODE_OP_BOTTOM3 { + 0x0: test_Al_Ib(); + 0x1: test_rAX_Iz(); + 0x2: stos_Yb_Al(); + 0x3: stos_Yv_rAX(); + 0x4: lods_Al_Xb(); + 0x5: lods_rAX_Xv(); + 0x6: scas_Yb_Al(); + 0x7: scas_Yv_rAX(); + } + 0x16: decode OPCODE_OP_BOTTOM3 { + 0x0: mov_Al_Ib(); + 0x1: mov_Cl_Ib(); + 0x2: mov_Dl_Ib(); + 0x3: mov_Bl_Ib(); + 0x4: mov_Ah_Ib(); + 0x5: mov_Ch_Ib(); + 0x6: mov_Dh_Ib(); + 0x7: mov_Bh_Ib(); + } + 0x17: decode OPCODE_OP_BOTTOM3 { + 0x0: mov_rAX_Iv(); + 0x1: mov_rCX_Iv(); + 0x2: mov_rDX_Iv(); + 0x3: mov_rBX_Iv(); + 0x4: mov_rSP_Iv(); + 0x5: mov_rBP_Iv(); + 0x6: mov_rSI_Iv(); + 0x7: mov_rDI_Iv(); + } + 0x18: decode OPCODE_OP_BOTTOM3 { + 0x0: group2_Eb_Ib(); + 0x1: group2_Ev_Ib(); + 0x2: ret_near_Iw(); + 0x3: ret_near(); + 0x4: les_Gz_Mp(); + 0x5: lds_Gz_Mp(); + 0x6: group12_Eb_Ib(); + 0x7: group12_Ev_Iz(); + } + 0x19: decode OPCODE_OP_BOTTOM3 { + 0x0: enter_Iw_Ib(); + 0x1: leave(); + 0x2: ret_far_Iw(); + 0x3: ret_far(); + 0x4: int3(); + 0x5: int_Ib(); + 0x6: into(); + 0x7: iret(); + } + 0x1A: decode OPCODE_OP_BOTTOM3 { + 0x0: group2_Eb_1(); + 0x1: group2_Ev_1(); + 0x2: group2_Eb_Cl(); + 0x3: group2_Ev_Cl(); + 0x4: aam_Ib(); + 0x5: aad_Ib(); + 0x6: salc(); + 0x7: xlat(); + } + 0x1B: decode OPCODE_OP_BOTTOM3 { + 0x0: esc0(); + 0x1: esc1(); + 0x2: esc2(); + 0x3: esc3(); + 0x4: esc4(); + 0x5: esc5(); + 0x6: esc6(); + 0x7: esc7(); + } + 0x1C: decode OPCODE_OP_BOTTOM3 { + 0x0: loopne_Jb(); + 0x1: loope_Jb(); + 0x2: loop_Jb(); + 0x3: jcxz_or_jecx_or_jrcx(); + 0x4: in_Al_Ib(); + 0x5: in_eAX_Ib(); + 0x6: out_Ib_Al(); + 0x7: out_Ib_eAX(); + } + 0x1D: decode OPCODE_OP_BOTTOM3 { + 0x0: call_Jz(); + 0x1: jmp_Jz(); + 0x2: jmp_Ap(); + 0x3: jmp_Jb(); + 0x4: in_Al_Dx(); + 0x5: in_eAX_Dx(); + 0x6: out_Dx_Al(); + 0x7: out_Dx_eAX(); + } + 0x1E: decode OPCODE_OP_BOTTOM3 { + 0x0: M5InternalError::error( + {{"Tried to execute the lock prefix!"}}); + 0x1: int1(); + 0x2: M5InternalError::error( + {{"Tried to execute the repne prefix!"}}); + 0x3: M5InternalError::error( + {{"Tried to execute the rep/repe prefix!"}}); + 0x4: hlt(); + 0x5: cmc(); + 0x6: group3_Eb(); + 0x7: group3_Ev(); + } + 0x1F: decode OPCODE_OP_BOTTOM3 { + 0x0: clc(); + 0x1: stc(); + 0x2: cli(); + 0x3: sti(); + 0x4: cld(); + 0x5: std(); + 0x6: group4(); + 0x7: group5(); + } + } + default: FailUnimpl::oneByteOps(); +} diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa new file mode 100644 index 000000000..f05c33bdb --- /dev/null +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -0,0 +1,393 @@ +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Decode the two byte opcodes +// +0x2: decode OPCODE_PREFIXA { + 0xF0: decode OPCODE_OP_TOP5 { + format WarnUnimpl { + 0x00: decode OPCODE_OP_BOTTOM3 { + 0x00: group6(); + 0x01: group7(); + 0x02: lar_Gv_Ew(); + 0x03: lsl_Gv_Ew(); + //sandpile.org doesn't seem to know what this is... ? + 0x04: loadall_or_reset_or_hang(); + //sandpile.org says (AMD) after syscall, so I might want to check + //if that means amd64 or AMD machines + 0x05: loadall_or_syscall(); + 0x06: clts(); + //sandpile.org says (AMD) after sysret, so I might want to check + //if that means amd64 or AMD machines + 0x07: loadall_or_sysret(); + } + 0x01: decode OPCODE_OP_BOTTOM3 { + 0x0: holderholder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x02: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x03: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x04: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x05: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x06: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x07: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x08: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x09: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x0A: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x0B: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x0C: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x0D: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x0E: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x0F: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x10: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x11: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x12: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x13: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x14: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x15: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x16: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x17: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x18: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x19: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x1A: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x1B: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x1C: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x1D: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x1E: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + 0x1F: decode OPCODE_OP_BOTTOM3 { + 0x0: holder(); + 0x1: holder(); + 0x2: holder(); + 0x3: holder(); + 0x4: holder(); + 0x5: holder(); + 0x6: holder(); + 0x7: holder(); + } + default: FailUnimpl::twoByteOps(); + } + } + default: M5InternalError::error( + {{"Unexpected first opcode byte in two byte opcode!"}}); +} diff --git a/src/arch/x86/isa/formats/basic.isa b/src/arch/x86/isa/formats/basic.isa new file mode 100644 index 000000000..ea224d638 --- /dev/null +++ b/src/arch/x86/isa/formats/basic.isa @@ -0,0 +1,158 @@ +// Copyright (c) 2007 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 + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +// Declarations for execute() methods. +def template BasicExecDeclare {{ + Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + +// Definitions of execute methods that panic. +def template BasicExecPanic {{ + Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const + { + panic("Execute method called when it shouldn't!"); + M5_DUMMY_RETURN + } +}}; + +// Basic instruction class declaration template. +def template BasicDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + public: + // Constructor. + %(class_name)s(ExtMachInst machInst); + %(BasicExecDeclare)s + }; +}}; + +// Basic instruction class constructor template. +def template BasicConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + } +}}; + +// Basic instruction class execute method template. +def template BasicExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if(fault == NoFault) + { + %(op_wb)s; + } + return fault; + } +}}; + +// Basic decode template. +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', code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/src/arch/x86/isa/formats/error.isa b/src/arch/x86/isa/formats/error.isa new file mode 100644 index 000000000..8ac2ea44d --- /dev/null +++ b/src/arch/x86/isa/formats/error.isa @@ -0,0 +1,77 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// "Format" which really indicates an internal error. This is a more +// significant problem for x86 than for other ISAs because of it's complex +// ExtMachInst type. +// + +def template ErrorDecode {{ + { + panic("X86 decoder internal error: '%%s' %%s", + %(message)s, machInst); + } +}}; + +def format M5InternalError(error_message) {{ + iop = InstObjParams(name, 'M5InternalError') + iop.message = error_message + decode_block = ErrorDecode.subst(iop) +}}; + diff --git a/src/arch/x86/isa/formats/formats.isa b/src/arch/x86/isa/formats/formats.isa new file mode 100644 index 000000000..d763c05bc --- /dev/null +++ b/src/arch/x86/isa/formats/formats.isa @@ -0,0 +1,100 @@ +// Copyright (c) 2007 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 + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//Include the basic format +//Templates from this format are used later +##include "basic.isa" + +//Include the "unknown" format +##include "unknown.isa" + +//Include the "unimp" format +##include "unimp.isa" + +//Include a format to signal m5 internal errors. This is used to indicate a +//malfunction of the decode mechanism. +##include "error.isa" + +//Include a format which implements a batch of instructions which do the same +//thing on a variety of inputs +##include "multi.isa" diff --git a/src/arch/x86/isa/formats/multi.isa b/src/arch/x86/isa/formats/multi.isa new file mode 100644 index 000000000..3e80f9cfb --- /dev/null +++ b/src/arch/x86/isa/formats/multi.isa @@ -0,0 +1,106 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Instructions that do the same thing to multiple sets of arguments. +// + +output header {{ +}}; + +output decoder {{ +}}; + +output exec {{ +}}; + +let {{ + multiops = {} +}}; + +def format MultiOp(code, switchVal, opTags, *opt_flags) {{ + # Loads and stores that bring in and write out values from the + # instructions. These are determined by the input and output tags, + # and the resulting instruction will have the right number of micro ops, + # or could be implemented as an atomic macro op. + instNames = [] + for tagSet in opTags: + loads = [] + stores = [] + postfix = '' + for tag in tagSet: + postfix += '_' + tag + gather_inputs = '' + if len(loads) + len(stores) == 0: + # If there are no loads or stores, make this a single instruction. + iop = InstObjParams(name, Name + postfix, 'X86StaticInst', + {"code": code, "gather_inputs": gather_inputs}, + opt_flags) + else: + # Build up a macro op. We'll punt on this for now + pass + + decodeBlob = 'switch(%s) {\n' % switchVal + counter = 0 + for inst in instNames: + decodeBlob += '%d: return (X86StaticInst *)(new %s(machInst));\n' % \ + (counter, inst) + counter += 1 + decodeBlob += '}\n' + # decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; diff --git a/src/arch/x86/isa/formats/unimp.isa b/src/arch/x86/isa/formats/unimp.isa new file mode 100644 index 000000000..12fa8387b --- /dev/null +++ b/src/arch/x86/isa/formats/unimp.isa @@ -0,0 +1,174 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Unimplemented instructions +// + +output header {{ + /** + * Static instruction class for unimplemented instructions that + * cause simulator termination. Note that these are recognized + * (legal) instructions that the simulator does not support; the + * 'Unknown' class is used for unrecognized/illegal instructions. + * This is a leaf class. + */ + class FailUnimplemented : public X86StaticInst + { + public: + /// Constructor + FailUnimplemented(const char *_mnemonic, ExtMachInst _machInst) + : X86StaticInst(_mnemonic, _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for unimplemented instructions that cause a warning + * to be printed (but do not terminate simulation). This + * implementation is a little screwy in that it will print a + * warning for each instance of a particular unimplemented machine + * instruction, not just for each unimplemented opcode. Should + * probably make the 'warned' flag a static member of the derived + * class. + */ + class WarnUnimplemented : public X86StaticInst + { + private: + /// Have we warned on this instruction yet? + mutable bool warned; + + public: + /// Constructor + WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst) + : X86StaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + FailUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } + + std::string + WarnUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return csprintf("%-10s", mnemonic); +#else + return csprintf("%-10s (unimplemented)", mnemonic); +#endif + } +}}; + +output exec {{ + Fault + FailUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unimplemented instruction '%s' %s", + mnemonic, machInst); + return NoFault; + } + + Fault + WarnUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (!warned) { + warn("instruction '%s' unimplemented\n", mnemonic); + warned = true; + } + + return NoFault; + } +}}; + + +def format FailUnimpl() {{ + iop = InstObjParams(name, 'FailUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +def format WarnUnimpl() {{ + iop = InstObjParams(name, 'WarnUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + diff --git a/src/arch/x86/isa/formats/unknown.isa b/src/arch/x86/isa/formats/unknown.isa new file mode 100644 index 000000000..43ddc20c1 --- /dev/null +++ b/src/arch/x86/isa/formats/unknown.isa @@ -0,0 +1,130 @@ +// Copyright (c) 2007 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 + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Unknown instructions +// + +output header {{ + /** + * Class for Unknown/Illegal instructions + */ + class Unknown : public StaticInst + { + public: + + // Constructor + Unknown(ExtMachInst _machInst) : + StaticInst("unknown", _machInst, No_OpClass) + { + } + + %(BasicExecDeclare)s + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + }; +}}; + +output decoder {{ + std::string Unknown::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return "Unknown instruction"; + } +}}; + +output exec {{ + Fault Unknown::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + warn("No instructions are implemented for X86!\n"); + return NoFault; + } +}}; + +def format Unknown() {{ + decode_block = 'return new Unknown(machInst);\n' +}}; diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa new file mode 100644 index 000000000..65e735b03 --- /dev/null +++ b/src/arch/x86/isa/includes.isa @@ -0,0 +1,143 @@ +// Copyright (c) 2007 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 + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// Output include file directives. +// + +output header {{ +#include <cstring> +#include <sstream> +#include <iostream> + +#include "arch/x86/faults.hh" +#include "arch/x86/isa_traits.hh" +#include "arch/x86/regfile.hh" +#include "base/misc.hh" +#include "cpu/static_inst.hh" +#include "mem/packet.hh" +#include "mem/request.hh" // some constructors use MemReq flags +}}; + +output decoder {{ +#include "base/cprintf.hh" +#include "base/loader/symtab.hh" +#include "cpu/thread_context.hh" // for Jump::branchTarget() +#include "mem/packet.hh" + +#if defined(linux) || defined(__APPLE__) +#include <fenv.h> +#endif +#include <algorithm> + +using namespace X86ISA; +}}; + +output exec {{ +#if defined(linux) || defined(__APPLE__) +#include <fenv.h> +#endif + +#if defined(__sun) || defined (__OpenBSD__) +#include <ieeefp.h> +#endif + +#if FULL_SYSTEM +#include "sim/pseudo_inst.hh" +#endif + +#include <limits> + +#include <cmath> +#include "base/bigint.hh" +#include "cpu/base.hh" +#include "cpu/exetrace.hh" +#include "sim/sim_exit.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +using namespace X86ISA; +using namespace std; +}}; + diff --git a/src/arch/x86/isa/main.isa b/src/arch/x86/isa/main.isa new file mode 100644 index 000000000..146f714a7 --- /dev/null +++ b/src/arch/x86/isa/main.isa @@ -0,0 +1,88 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +//////////////////////////////////////////////////////////////////// +// +// X86 ISA description file. +// +//////////////////////////////////////////////////////////////////// + +//Include the C++ include directives +##include "includes.isa" + +//////////////////////////////////////////////////////////////////// +// +// Namespace statement. Everything below this line will be in the +// SparcISAInst namespace. +// + +namespace X86ISA; + +//Include the bitfield definitions +##include "bitfields.isa" + +//Include the operand_types and operand definitions +##include "operands.isa" + +//Include the base class for x86 instructions, and some support code +##include "base.isa" + +//Include the definitions for the instruction formats +##include "formats/formats.isa" + +//Include the decoder definition +##include "decoder/decoder.isa" diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa new file mode 100644 index 000000000..20376f38f --- /dev/null +++ b/src/arch/x86/isa/operands.isa @@ -0,0 +1,102 @@ +// Copyright (c) 2007 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 + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. Redistributions +// in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. Neither the name of +// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Authors: Gabe Black + +def operand_types {{ + 'sb' : ('signed int', 8), + 'ub' : ('unsigned int', 8), + 'sw' : ('signed int', 16), + 'uw' : ('unsigned int', 16), + 'sdw' : ('signed int', 32), + 'udw' : ('unsigned int', 32), + 'sqw' : ('signed int', 64), + 'uqw' : ('unsigned int', 64), + 'sf' : ('float', 32), + 'df' : ('float', 64), + 'qf' : ('float', 128) +}}; + +def operands {{ + # This is just copied from SPARC, because having no operands confuses + # the parser. + 'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1) +}}; diff --git a/src/arch/x86/isa_traits.hh b/src/arch/x86/isa_traits.hh new file mode 100644 index 000000000..5a625f741 --- /dev/null +++ b/src/arch/x86/isa_traits.hh @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_ISATRAITS_HH__ +#define __ARCH_X86_ISATRAITS_HH__ + +#include "arch/x86/intregs.hh" +#include "arch/x86/types.hh" +#include "arch/x86/x86_traits.hh" + +class StaticInstPtr; + +namespace LittleEndianGuest {} + +namespace X86ISA +{ + //This makes sure the little endian version of certain functions + //are used. + using namespace LittleEndianGuest; + + // X86 does not have a delay slot +#define ISA_HAS_DELAY_SLOT 0 + + // X86 NOP (XCHG rAX, rAX) + //XXX This needs to be set to an intermediate instruction struct + //which encodes this instruction + + // These enumerate all the registers for dependence tracking. + enum DependenceTags { + //The number of microcode registers needs to be added to this + FP_Base_DepTag = 16, + Ctrl_Base_DepTag = + FP_Base_DepTag + + //mmx/x87 registers + 8 + + //xmm registers + 16 + }; + + // semantically meaningful register indices + //There is no such register in X86 + const int ZeroReg = 0; + const int StackPointerReg = INTREG_RSP; + //X86 doesn't seem to have a link register + const int ReturnAddressReg = 0; + const int ReturnValueReg = INTREG_RAX; + const int FramePointerReg = INTREG_RBP; + const int ArgumentReg0 = INTREG_RDI; + const int ArgumentReg1 = INTREG_RSI; + const int ArgumentReg2 = INTREG_RDX; + const int ArgumentReg3 = INTREG_RCX; + const int ArgumentReg4 = INTREG_R8W; + const int ArgumentReg5 = INTREG_R9W; + + // Some OS syscalls use a second register (rdx) to return a second + // value + const int SyscallPseudoReturnReg = INTREG_RDX; + + //XXX These numbers are bogus + const int MaxInstSrcRegs = 10; + const int MaxInstDestRegs = 10; + + //4k. This value is not constant on x86. + const int LogVMPageSize = 12; + const int VMPageSize = (1 << LogVMPageSize); + + const int PageShift = 13; + const int PageBytes = 1ULL << PageShift; + + const int BranchPredAddrShiftAmt = 0; + + StaticInstPtr decodeInst(ExtMachInst); +}; + +#endif // __ARCH_X86_ISATRAITS_HH__ diff --git a/src/arch/x86/kernel_stats.hh b/src/arch/x86/kernel_stats.hh new file mode 100644 index 000000000..8cd80073e --- /dev/null +++ b/src/arch/x86/kernel_stats.hh @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_KERNELSTATS_HH__ +#define __ARCH_X86_KERNELSTATS_HH__ + +#error X86 is not yet supported! + +namespace X86ISA +{ +}; + +#endif // __ARCH_X86_KERNELSTATS_HH__ diff --git a/src/arch/x86/linux/linux.cc b/src/arch/x86/linux/linux.cc new file mode 100644 index 000000000..59754d7b3 --- /dev/null +++ b/src/arch/x86/linux/linux.cc @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/linux/linux.hh" +#include <fcntl.h> + +// open(2) flags translation table +OpenFlagTransTable X86Linux::openFlagTable[] = { +#ifdef _MSC_VER + { TGT_O_RDONLY, _O_RDONLY }, + { TGT_O_WRONLY, _O_WRONLY }, + { TGT_O_RDWR, _O_RDWR }, + { TGT_O_APPEND, _O_APPEND }, + { TGT_O_CREAT, _O_CREAT }, + { TGT_O_TRUNC, _O_TRUNC }, + { TGT_O_EXCL, _O_EXCL }, +#ifdef _O_NONBLOCK + { TGT_O_NONBLOCK, _O_NONBLOCK }, +#endif +#ifdef _O_NOCTTY + { TGT_O_NOCTTY, _O_NOCTTY }, +#endif +#ifdef _O_SYNC + { TGT_O_SYNC, _O_SYNC }, +#endif +#else /* !_MSC_VER */ + { TGT_O_RDONLY, O_RDONLY }, + { TGT_O_WRONLY, O_WRONLY }, + { TGT_O_RDWR, O_RDWR }, + { TGT_O_APPEND, O_APPEND }, + { TGT_O_CREAT, O_CREAT }, + { TGT_O_TRUNC, O_TRUNC }, + { TGT_O_EXCL, O_EXCL }, + { TGT_O_NONBLOCK, O_NONBLOCK }, + { TGT_O_NOCTTY, O_NOCTTY }, +#ifdef O_SYNC + { TGT_O_SYNC, O_SYNC }, +#endif +#endif /* _MSC_VER */ +}; + +const int X86Linux::NUM_OPEN_FLAGS = + (sizeof(X86Linux::openFlagTable)/sizeof(X86Linux::openFlagTable[0])); + diff --git a/src/arch/x86/linux/linux.hh b/src/arch/x86/linux/linux.hh new file mode 100644 index 000000000..a276d4c0c --- /dev/null +++ b/src/arch/x86/linux/linux.hh @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_LINUX_LINUX_HH__ +#define __ARCH_X86_LINUX_LINUX_HH__ + +#include "kern/linux/linux.hh" + +class X86Linux : public Linux +{ + public: + + typedef struct { + uint32_t st_dev; + char __pad1[4]; + uint64_t st_ino; + uint32_t st_mode; + uint16_t st_nlink; + uint32_t st_uid; + uint32_t st_gid; + uint32_t st_rdev; + char __pad2[4]; + int64_t st_size; + int64_t st_atimeX; + int64_t st_mtimeX; + int64_t st_ctimeX; + int64_t st_blksize; + int64_t st_blocks; + uint64_t __unused4[2]; + } tgt_stat; + + static OpenFlagTransTable openFlagTable[]; + + static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY + static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY + static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR + static const int TGT_O_NONBLOCK = 0x00004000; //!< O_NONBLOCK + static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND + static const int TGT_O_CREAT = 0x00000200; //!< O_CREAT + static const int TGT_O_TRUNC = 0x00000400; //!< O_TRUNC + static const int TGT_O_EXCL = 0x00000800; //!< O_EXCL + static const int TGT_O_NOCTTY = 0x00008000; //!< O_NOCTTY + static const int TGT_O_SYNC = 0x00002000; //!< O_SYNC +// static const int TGT_O_DRD = 0x00010000; //!< O_DRD +// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO +// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE +// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC +// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC + + static const int NUM_OPEN_FLAGS; + + static const unsigned TGT_MAP_ANONYMOUS = 0x20; +}; + +#endif diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc new file mode 100644 index 000000000..9ef591a1c --- /dev/null +++ b/src/arch/x86/linux/process.cc @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/isa_traits.hh" +#include "arch/x86/linux/process.hh" +#include "arch/x86/regfile.hh" + +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "kern/linux/linux.hh" + +#include "sim/process.hh" +#include "sim/syscall_emul.hh" + +using namespace std; +using namespace X86ISA; + +SyscallDesc* +X86LinuxProcess::getDesc(int callnum) +{ + if (callnum < 0 || callnum > Num_Syscall_Descs) + return NULL; + return &syscallDescs[callnum]; +} + +X86LinuxProcess::X86LinuxProcess(const std::string &name, + ObjectFile *objFile, + System * system, + int stdin_fd, + int stdout_fd, + int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid) + : X86LiveProcess(name, objFile, system, + stdin_fd, stdout_fd, stderr_fd, argv, envp, cwd, + _uid, _euid, _gid, _egid, _pid, _ppid), + Num_Syscall_Descs(273) +{} + +void X86LinuxProcess::handleTrap(int trapNum, ThreadContext *tc) +{ + switch(trapNum) + { + //This implementation is from SPARC + case 0x10: //Linux 32 bit syscall trap + tc->syscall(tc->readIntReg(1)); + break; + default: + X86LiveProcess::handleTrap(trapNum, tc); + } +} diff --git a/src/arch/x86/linux/process.hh b/src/arch/x86/linux/process.hh new file mode 100644 index 000000000..7e7236f0d --- /dev/null +++ b/src/arch/x86/linux/process.hh @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __X86_LINUX_PROCESS_HH__ +#define __X86_LINUX_PROCESS_HH__ + +#include "sim/process.hh" +#include "arch/x86/linux/linux.hh" +#include "arch/x86/syscallreturn.hh" +#include "arch/x86/process.hh" + +namespace X86ISA { + +/// A process with emulated x86/Linux syscalls. +class X86LinuxProcess : public X86LiveProcess +{ + public: + /// Constructor. + X86LinuxProcess(const std::string &name, + ObjectFile *objFile, + System * system, + int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid); + + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; + + SyscallDesc* getDesc(int callnum); + + const int Num_Syscall_Descs; + + void handleTrap(int trapNum, ThreadContext *tc); +}; + +} // namespace X86ISA +#endif // __X86_LINUX_PROCESS_HH__ diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc new file mode 100644 index 000000000..809784635 --- /dev/null +++ b/src/arch/x86/linux/syscalls.cc @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/linux/process.hh" +#include "kern/linux/linux.hh" +#include "sim/syscall_emul.hh" + +using namespace X86ISA; + +/// Target uname() handler. +static SyscallReturn +unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0)); + + strcpy(name->sysname, "Linux"); + strcpy(name->nodename, "m5.eecs.umich.edu"); + strcpy(name->release, "2.6.12"); + strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); + strcpy(name->machine, "x86_64"); + + name.copyOut(tc->getMemPort()); + + return 0; +} + +SyscallDesc X86LinuxProcess::syscallDescs[] = { + /* 0 */ SyscallDesc("read", unimplementedFunc), + /* 1 */ SyscallDesc("write", unimplementedFunc), + /* 2 */ SyscallDesc("open", unimplementedFunc), + /* 3 */ SyscallDesc("close", unimplementedFunc), + /* 4 */ SyscallDesc("stat", unimplementedFunc), + /* 5 */ SyscallDesc("fstat", unimplementedFunc), + /* 6 */ SyscallDesc("lstat", unimplementedFunc), + /* 7 */ SyscallDesc("poll", unimplementedFunc), + /* 8 */ SyscallDesc("lseek", unimplementedFunc), + /* 9 */ SyscallDesc("mmap", unimplementedFunc), + /* 10 */ SyscallDesc("mprotect", unimplementedFunc), + /* 11 */ SyscallDesc("munmap", unimplementedFunc), + /* 12 */ SyscallDesc("brk", unimplementedFunc), + /* 13 */ SyscallDesc("rt_sigaction", unimplementedFunc), + /* 14 */ SyscallDesc("rt_sigprocmask", unimplementedFunc), + /* 15 */ SyscallDesc("rt_sigreturn", unimplementedFunc), + /* 16 */ SyscallDesc("ioctl", unimplementedFunc), + /* 17 */ SyscallDesc("pread64", unimplementedFunc), + /* 18 */ SyscallDesc("pwrite64", unimplementedFunc), + /* 19 */ SyscallDesc("readv", unimplementedFunc), + /* 20 */ SyscallDesc("writev", unimplementedFunc), + /* 21 */ SyscallDesc("access", unimplementedFunc), + /* 22 */ SyscallDesc("pipe", unimplementedFunc), + /* 23 */ SyscallDesc("select", unimplementedFunc), + /* 24 */ SyscallDesc("sched_yield", unimplementedFunc), + /* 25 */ SyscallDesc("mremap", unimplementedFunc), + /* 26 */ SyscallDesc("msync", unimplementedFunc), + /* 27 */ SyscallDesc("mincore", unimplementedFunc), + /* 28 */ SyscallDesc("madvise", unimplementedFunc), + /* 29 */ SyscallDesc("shmget", unimplementedFunc), + /* 30 */ SyscallDesc("shmat", unimplementedFunc), + /* 31 */ SyscallDesc("shmctl", unimplementedFunc), + /* 32 */ SyscallDesc("dup", unimplementedFunc), + /* 33 */ SyscallDesc("dup2", unimplementedFunc), + /* 34 */ SyscallDesc("pause", unimplementedFunc), + /* 35 */ SyscallDesc("nanosleep", unimplementedFunc), + /* 36 */ SyscallDesc("getitimer", unimplementedFunc), + /* 37 */ SyscallDesc("alarm", unimplementedFunc), + /* 38 */ SyscallDesc("setitimer", unimplementedFunc), + /* 39 */ SyscallDesc("getpid", unimplementedFunc), + /* 40 */ SyscallDesc("sendfile", unimplementedFunc), + /* 41 */ SyscallDesc("socket", unimplementedFunc), + /* 42 */ SyscallDesc("connect", unimplementedFunc), + /* 43 */ SyscallDesc("accept", unimplementedFunc), + /* 44 */ SyscallDesc("sendto", unimplementedFunc), + /* 45 */ SyscallDesc("recvfrom", unimplementedFunc), + /* 46 */ SyscallDesc("sendmsg", unimplementedFunc), + /* 47 */ SyscallDesc("recvmsg", unimplementedFunc), + /* 48 */ SyscallDesc("shutdown", unimplementedFunc), + /* 49 */ SyscallDesc("bind", unimplementedFunc), + /* 50 */ SyscallDesc("listen", unimplementedFunc), + /* 51 */ SyscallDesc("getsockname", unimplementedFunc), + /* 52 */ SyscallDesc("getpeername", unimplementedFunc), + /* 53 */ SyscallDesc("socketpair", unimplementedFunc), + /* 54 */ SyscallDesc("setsockopt", unimplementedFunc), + /* 55 */ SyscallDesc("getsockopt", unimplementedFunc), + /* 56 */ SyscallDesc("clone", unimplementedFunc), + /* 57 */ SyscallDesc("fork", unimplementedFunc), + /* 58 */ SyscallDesc("vfork", unimplementedFunc), + /* 59 */ SyscallDesc("execve", unimplementedFunc), + /* 60 */ SyscallDesc("exit", unimplementedFunc), + /* 61 */ SyscallDesc("wait4", unimplementedFunc), + /* 62 */ SyscallDesc("kill", unimplementedFunc), + /* 63 */ SyscallDesc("uname", unameFunc), + /* 64 */ SyscallDesc("semget", unimplementedFunc), + /* 65 */ SyscallDesc("semop", unimplementedFunc), + /* 66 */ SyscallDesc("semctl", unimplementedFunc), + /* 67 */ SyscallDesc("shmdt", unimplementedFunc), + /* 68 */ SyscallDesc("msgget", unimplementedFunc), + /* 69 */ SyscallDesc("msgsnd", unimplementedFunc), + /* 70 */ SyscallDesc("msgrcv", unimplementedFunc), + /* 71 */ SyscallDesc("msgctl", unimplementedFunc), + /* 72 */ SyscallDesc("fcntl", unimplementedFunc), + /* 73 */ SyscallDesc("flock", unimplementedFunc), + /* 74 */ SyscallDesc("fsync", unimplementedFunc), + /* 75 */ SyscallDesc("fdatasync", unimplementedFunc), + /* 76 */ SyscallDesc("truncate", unimplementedFunc), + /* 77 */ SyscallDesc("ftruncate", unimplementedFunc), + /* 78 */ SyscallDesc("getdents", unimplementedFunc), + /* 79 */ SyscallDesc("getcwd", unimplementedFunc), + /* 80 */ SyscallDesc("chdir", unimplementedFunc), + /* 81 */ SyscallDesc("fchdir", unimplementedFunc), + /* 82 */ SyscallDesc("rename", unimplementedFunc), + /* 83 */ SyscallDesc("mkdir", unimplementedFunc), + /* 84 */ SyscallDesc("rmdir", unimplementedFunc), + /* 85 */ SyscallDesc("creat", unimplementedFunc), + /* 86 */ SyscallDesc("link", unimplementedFunc), + /* 87 */ SyscallDesc("unlink", unimplementedFunc), + /* 88 */ SyscallDesc("symlink", unimplementedFunc), + /* 89 */ SyscallDesc("readlink", unimplementedFunc), + /* 90 */ SyscallDesc("chmod", unimplementedFunc), + /* 91 */ SyscallDesc("fchmod", unimplementedFunc), + /* 92 */ SyscallDesc("chown", unimplementedFunc), + /* 93 */ SyscallDesc("fchown", unimplementedFunc), + /* 94 */ SyscallDesc("lchown", unimplementedFunc), + /* 95 */ SyscallDesc("umask", unimplementedFunc), + /* 96 */ SyscallDesc("gettimeofday", unimplementedFunc), + /* 97 */ SyscallDesc("getrlimit", unimplementedFunc), + /* 98 */ SyscallDesc("getrusage", unimplementedFunc), + /* 99 */ SyscallDesc("sysinfo", unimplementedFunc), + /* 100 */ SyscallDesc("times", unimplementedFunc), + /* 101 */ SyscallDesc("ptrace", unimplementedFunc), + /* 102 */ SyscallDesc("getuid", unimplementedFunc), + /* 103 */ SyscallDesc("syslog", unimplementedFunc), + /* 104 */ SyscallDesc("getgid", unimplementedFunc), + /* 105 */ SyscallDesc("setuid", unimplementedFunc), + /* 106 */ SyscallDesc("setgid", unimplementedFunc), + /* 107 */ SyscallDesc("geteuid", unimplementedFunc), + /* 108 */ SyscallDesc("getegid", unimplementedFunc), + /* 109 */ SyscallDesc("setpgid", unimplementedFunc), + /* 110 */ SyscallDesc("getppid", unimplementedFunc), + /* 111 */ SyscallDesc("getpgrp", unimplementedFunc), + /* 112 */ SyscallDesc("setsid", unimplementedFunc), + /* 113 */ SyscallDesc("setreuid", unimplementedFunc), + /* 114 */ SyscallDesc("setregid", unimplementedFunc), + /* 115 */ SyscallDesc("getgroups", unimplementedFunc), + /* 116 */ SyscallDesc("setgroups", unimplementedFunc), + /* 117 */ SyscallDesc("setresuid", unimplementedFunc), + /* 118 */ SyscallDesc("getresuid", unimplementedFunc), + /* 119 */ SyscallDesc("setresgid", unimplementedFunc), + /* 120 */ SyscallDesc("getresgid", unimplementedFunc), + /* 121 */ SyscallDesc("getpgid", unimplementedFunc), + /* 122 */ SyscallDesc("setfsuid", unimplementedFunc), + /* 123 */ SyscallDesc("setfsgid", unimplementedFunc), + /* 124 */ SyscallDesc("getsid", unimplementedFunc), + /* 125 */ SyscallDesc("capget", unimplementedFunc), + /* 126 */ SyscallDesc("capset", unimplementedFunc), + /* 127 */ SyscallDesc("rt_sigpending", unimplementedFunc), + /* 128 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc), + /* 129 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc), + /* 130 */ SyscallDesc("rt_sigsuspend", unimplementedFunc), + /* 131 */ SyscallDesc("sigaltstack", unimplementedFunc), + /* 132 */ SyscallDesc("utime", unimplementedFunc), + /* 133 */ SyscallDesc("mknod", unimplementedFunc), + /* 134 */ SyscallDesc("uselib", unimplementedFunc), + /* 135 */ SyscallDesc("personality", unimplementedFunc), + /* 136 */ SyscallDesc("ustat", unimplementedFunc), + /* 137 */ SyscallDesc("statfs", unimplementedFunc), + /* 138 */ SyscallDesc("fstatfs", unimplementedFunc), + /* 139 */ SyscallDesc("sysfs", unimplementedFunc), + /* 140 */ SyscallDesc("getpriority", unimplementedFunc), + /* 141 */ SyscallDesc("setpriority", unimplementedFunc), + /* 142 */ SyscallDesc("sched_setparam", unimplementedFunc), + /* 143 */ SyscallDesc("sched_getparam", unimplementedFunc), + /* 144 */ SyscallDesc("sched_setscheduler", unimplementedFunc), + /* 145 */ SyscallDesc("sched_getscheduler", unimplementedFunc), + /* 146 */ SyscallDesc("sched_get_priority_max", unimplementedFunc), + /* 147 */ SyscallDesc("sched_get_priority_min", unimplementedFunc), + /* 148 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc), + /* 149 */ SyscallDesc("mlock", unimplementedFunc), + /* 150 */ SyscallDesc("munlock", unimplementedFunc), + /* 151 */ SyscallDesc("mlockall", unimplementedFunc), + /* 152 */ SyscallDesc("munlockall", unimplementedFunc), + /* 153 */ SyscallDesc("vhangup", unimplementedFunc), + /* 154 */ SyscallDesc("modify_ldt", unimplementedFunc), + /* 155 */ SyscallDesc("pivot_root", unimplementedFunc), + /* 156 */ SyscallDesc("_sysctl", unimplementedFunc), + /* 157 */ SyscallDesc("prctl", unimplementedFunc), + /* 158 */ SyscallDesc("arch_prctl", unimplementedFunc), + /* 159 */ SyscallDesc("adjtimex", unimplementedFunc), + /* 160 */ SyscallDesc("setrlimit", unimplementedFunc), + /* 161 */ SyscallDesc("chroot", unimplementedFunc), + /* 162 */ SyscallDesc("sync", unimplementedFunc), + /* 163 */ SyscallDesc("acct", unimplementedFunc), + /* 164 */ SyscallDesc("settimeofday", unimplementedFunc), + /* 165 */ SyscallDesc("mount", unimplementedFunc), + /* 166 */ SyscallDesc("umount2", unimplementedFunc), + /* 167 */ SyscallDesc("swapon", unimplementedFunc), + /* 168 */ SyscallDesc("swapoff", unimplementedFunc), + /* 169 */ SyscallDesc("reboot", unimplementedFunc), + /* 170 */ SyscallDesc("sethostname", unimplementedFunc), + /* 171 */ SyscallDesc("setdomainname", unimplementedFunc), + /* 172 */ SyscallDesc("iopl", unimplementedFunc), + /* 173 */ SyscallDesc("ioperm", unimplementedFunc), + /* 174 */ SyscallDesc("create_module", unimplementedFunc), + /* 175 */ SyscallDesc("init_module", unimplementedFunc), + /* 176 */ SyscallDesc("delete_module", unimplementedFunc), + /* 177 */ SyscallDesc("get_kernel_syms", unimplementedFunc), + /* 178 */ SyscallDesc("query_module", unimplementedFunc), + /* 179 */ SyscallDesc("quotactl", unimplementedFunc), + /* 180 */ SyscallDesc("nfsservctl", unimplementedFunc), + /* 181 */ SyscallDesc("getpmsg", unimplementedFunc), + /* 182 */ SyscallDesc("putpmsg", unimplementedFunc), + /* 183 */ SyscallDesc("afs_syscall", unimplementedFunc), + /* 184 */ SyscallDesc("tuxcall", unimplementedFunc), + /* 185 */ SyscallDesc("security", unimplementedFunc), + /* 186 */ SyscallDesc("gettid", unimplementedFunc), + /* 187 */ SyscallDesc("readahead", unimplementedFunc), + /* 188 */ SyscallDesc("setxattr", unimplementedFunc), + /* 189 */ SyscallDesc("lsetxattr", unimplementedFunc), + /* 190 */ SyscallDesc("fsetxattr", unimplementedFunc), + /* 191 */ SyscallDesc("getxattr", unimplementedFunc), + /* 192 */ SyscallDesc("lgetxattr", unimplementedFunc), + /* 193 */ SyscallDesc("fgetxattr", unimplementedFunc), + /* 194 */ SyscallDesc("listxattr", unimplementedFunc), + /* 195 */ SyscallDesc("llistxattr", unimplementedFunc), + /* 196 */ SyscallDesc("flistxattr", unimplementedFunc), + /* 197 */ SyscallDesc("removexattr", unimplementedFunc), + /* 198 */ SyscallDesc("lremovexattr", unimplementedFunc), + /* 199 */ SyscallDesc("fremovexattr", unimplementedFunc), + /* 200 */ SyscallDesc("tkill", unimplementedFunc), + /* 201 */ SyscallDesc("time", unimplementedFunc), + /* 202 */ SyscallDesc("futex", unimplementedFunc), + /* 203 */ SyscallDesc("sched_setaffinity", unimplementedFunc), + /* 204 */ SyscallDesc("sched_getaffinity", unimplementedFunc), + /* 205 */ SyscallDesc("set_thread_area", unimplementedFunc), + /* 206 */ SyscallDesc("io_setup", unimplementedFunc), + /* 207 */ SyscallDesc("io_destroy", unimplementedFunc), + /* 208 */ SyscallDesc("io_getevents", unimplementedFunc), + /* 209 */ SyscallDesc("io_submit", unimplementedFunc), + /* 210 */ SyscallDesc("io_cancel", unimplementedFunc), + /* 211 */ SyscallDesc("get_thread_area", unimplementedFunc), + /* 212 */ SyscallDesc("lookup_dcookie", unimplementedFunc), + /* 213 */ SyscallDesc("epoll_create", unimplementedFunc), + /* 214 */ SyscallDesc("epoll_ctl_old", unimplementedFunc), + /* 215 */ SyscallDesc("epoll_wait_old", unimplementedFunc), + /* 216 */ SyscallDesc("remap_file_pages", unimplementedFunc), + /* 217 */ SyscallDesc("getdents64", unimplementedFunc), + /* 218 */ SyscallDesc("set_tid_address", unimplementedFunc), + /* 219 */ SyscallDesc("restart_syscall", unimplementedFunc), + /* 220 */ SyscallDesc("semtimedop", unimplementedFunc), + /* 221 */ SyscallDesc("fadvise64", unimplementedFunc), + /* 222 */ SyscallDesc("timer_create", unimplementedFunc), + /* 223 */ SyscallDesc("timer_settime", unimplementedFunc), + /* 224 */ SyscallDesc("timer_gettime", unimplementedFunc), + /* 225 */ SyscallDesc("timer_getoverrun", unimplementedFunc), + /* 226 */ SyscallDesc("timer_delete", unimplementedFunc), + /* 227 */ SyscallDesc("clock_settime", unimplementedFunc), + /* 228 */ SyscallDesc("clock_gettime", unimplementedFunc), + /* 229 */ SyscallDesc("clock_getres", unimplementedFunc), + /* 230 */ SyscallDesc("clock_nanosleep", unimplementedFunc), + /* 231 */ SyscallDesc("exit_group", unimplementedFunc), + /* 232 */ SyscallDesc("epoll_wait", unimplementedFunc), + /* 233 */ SyscallDesc("epoll_ctl", unimplementedFunc), + /* 234 */ SyscallDesc("tgkill", unimplementedFunc), + /* 235 */ SyscallDesc("utimes", unimplementedFunc), + /* 236 */ SyscallDesc("vserver", unimplementedFunc), + /* 237 */ SyscallDesc("mbind", unimplementedFunc), + /* 238 */ SyscallDesc("set_mempolicy", unimplementedFunc), + /* 239 */ SyscallDesc("get_mempolicy", unimplementedFunc), + /* 240 */ SyscallDesc("mq_open", unimplementedFunc), + /* 241 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 242 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 243 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 244 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 245 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 246 */ SyscallDesc("kexec_load", unimplementedFunc), + /* 247 */ SyscallDesc("waitid", unimplementedFunc), + /* 248 */ SyscallDesc("add_key", unimplementedFunc), + /* 249 */ SyscallDesc("request_key", unimplementedFunc), + /* 250 */ SyscallDesc("keyctl", unimplementedFunc), + /* 251 */ SyscallDesc("ioprio_set", unimplementedFunc), + /* 252 */ SyscallDesc("ioprio_get", unimplementedFunc), + /* 253 */ SyscallDesc("inotify_init", unimplementedFunc), + /* 254 */ SyscallDesc("inotify_add_watch", unimplementedFunc), + /* 255 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), + /* 256 */ SyscallDesc("migrate_pages", unimplementedFunc), + /* 257 */ SyscallDesc("openat", unimplementedFunc), + /* 258 */ SyscallDesc("mkdirat", unimplementedFunc), + /* 259 */ SyscallDesc("mknodat", unimplementedFunc), + /* 260 */ SyscallDesc("fchownat", unimplementedFunc), + /* 261 */ SyscallDesc("futimesat", unimplementedFunc), + /* 262 */ SyscallDesc("newfstatat", unimplementedFunc), + /* 263 */ SyscallDesc("unlinkat", unimplementedFunc), + /* 264 */ SyscallDesc("renameat", unimplementedFunc), + /* 265 */ SyscallDesc("linkat", unimplementedFunc), + /* 266 */ SyscallDesc("symlinkat", unimplementedFunc), + /* 267 */ SyscallDesc("readlinkat", unimplementedFunc), + /* 268 */ SyscallDesc("fchmodat", unimplementedFunc), + /* 269 */ SyscallDesc("faccessat", unimplementedFunc), + /* 270 */ SyscallDesc("pselect6", unimplementedFunc), + /* 271 */ SyscallDesc("ppoll", unimplementedFunc), + /* 272 */ SyscallDesc("unshare", unimplementedFunc) +}; diff --git a/src/arch/x86/locked_mem.hh b/src/arch/x86/locked_mem.hh new file mode 100644 index 000000000..e1d289ee9 --- /dev/null +++ b/src/arch/x86/locked_mem.hh @@ -0,0 +1,58 @@ +/* + * 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: Steve Reinhardt + */ + +#ifndef __ARCH_X86_LOCKEDMEM_HH__ +#define __ARCH_X86_LOCKEDMEM_HH__ + +/** + * @file + * + * ISA-specific helper functions for locked memory accesses. + */ + +#include "mem/request.hh" + +namespace X86ISA +{ + template <class XC> + inline void + handleLockedRead(XC *xc, Request *req) + { + } + + template <class XC> + inline bool + handleLockedWrite(XC *xc, Request *req) + { + return true; + } +}; + +#endif // __ARCH_X86_LOCKEDMEM_HH__ diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc new file mode 100644 index 000000000..14ba3c7cc --- /dev/null +++ b/src/arch/x86/miscregfile.cc @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2003-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: Gabe Black + */ + +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/miscregfile.hh" + +using namespace X86ISA; +using namespace std; + +class Checkpoint; + +//These functions map register indices to names +string X86ISA::getMiscRegName(RegIndex index) +{ + panic("No misc registers in x86 yet!\n"); +} + +void MiscRegFile::clear() +{ + //When there are actually misc regs implemented, this will clear them +} + +MiscReg MiscRegFile::readRegNoEffect(int miscReg) +{ + panic("No misc registers in x86 yet!\n"); +} + +MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) +{ + panic("No misc registers in x86 yet!\n"); +} + +void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val) +{ + panic("No misc registers in x86 yet!\n"); +} + +void MiscRegFile::setReg(int miscReg, + const MiscReg &val, ThreadContext * tc) +{ + panic("No misc registers in x86 yet!\n"); +} + +void MiscRegFile::serialize(std::ostream & os) +{ + panic("No misc registers in x86 yet!\n"); +} + +void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) +{ + panic("No misc registers in x86 yet!\n"); +} diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh new file mode 100644 index 000000000..10acb97a4 --- /dev/null +++ b/src/arch/x86/miscregfile.hh @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2003-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: Gabe Black + */ + +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_MISCREGFILE_HH__ +#define __ARCH_X86_MISCREGFILE_HH__ + +#include "arch/x86/faults.hh" +#include "arch/x86/types.hh" + +#include <string> + +class Checkpoint; + +namespace X86ISA +{ + std::string getMiscRegName(RegIndex); + + //These will have to be updated in the future. + const int NumMiscArchRegs = 0; + const int NumMiscRegs = 0; + + class MiscRegFile + { + public: + void clear(); + + MiscRegFile() + { + clear(); + } + + MiscReg readRegNoEffect(int miscReg); + + MiscReg readReg(int miscReg, ThreadContext *tc); + + void setRegNoEffect(int miscReg, const MiscReg &val); + + void setReg(int miscReg, + const MiscReg &val, ThreadContext *tc); + + void serialize(std::ostream & os); + + void unserialize(Checkpoint * cp, const std::string §ion); + + void copyMiscRegs(ThreadContext * tc); + }; +} + +#endif //__ARCH_X86_MISCREGFILE_HH__ diff --git a/src/arch/x86/mmaped_ipr.hh b/src/arch/x86/mmaped_ipr.hh new file mode 100644 index 000000000..a33a3f4f0 --- /dev/null +++ b/src/arch/x86/mmaped_ipr.hh @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_MMAPEDIPR_HH__ +#define __ARCH_X86_MMAPEDIPR_HH__ + +/** + * @file + * + * ISA-specific helper functions for memory mapped IPR accesses. + */ + +#include "config/full_system.hh" +#include "cpu/thread_context.hh" +#include "mem/packet.hh" + +namespace X86ISA +{ + inline Tick + handleIprRead(ThreadContext *xc, Packet *pkt) + { +#if !FULL_SYSTEM + panic("Shouldn't have a memory mapped register in SE\n"); +#endif + } + + inline Tick + handleIprWrite(ThreadContext *xc, Packet *pkt) + { +#if !FULL_SYSTEM + panic("Shouldn't have a memory mapped register in SE\n"); +#endif + } +}; + +#endif // __ARCH_X86_MMAPEDIPR_HH__ diff --git a/src/arch/x86/pagetable.hh b/src/arch/x86/pagetable.hh new file mode 100644 index 000000000..8ca179c86 --- /dev/null +++ b/src/arch/x86/pagetable.hh @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_PAGETABLE_HH__ +#define __ARCH_X86_PAGETABLE_HH__ + +#include "sim/host.hh" +#include "base/misc.hh" + +namespace X86ISA +{ + struct VAddr + { + VAddr(Addr a) { panic("not implemented yet."); } + }; + + class PageTableEntry + { + }; +} + +#endif diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc new file mode 100644 index 000000000..fbed4fe41 --- /dev/null +++ b/src/arch/x86/predecoder.cc @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/predecoder.hh" +#include "base/misc.hh" +#include "base/trace.hh" +#include "sim/host.hh" + +namespace X86ISA +{ + void Predecoder::process() + { + //This function drives the predecoder state machine. + + //Some sanity checks. You shouldn't try to process more bytes if + //there aren't any, and you shouldn't overwrite an already + //predecoder ExtMachInst. + assert(!outOfBytes); + assert(!emiIsReady); + + //While there's still something to do... + while(!emiIsReady && !outOfBytes) + { + uint8_t nextByte = getNextByte(); + switch(state) + { + case PrefixState: + state = doPrefixState(nextByte); + break; + case OpcodeState: + state = doOpcodeState(nextByte); + break; + case ModRMState: + state = doModRMState(nextByte); + break; + case SIBState: + state = doSIBState(nextByte); + break; + case DisplacementState: + state = doDisplacementState(); + break; + case ImmediateState: + state = doImmediateState(); + break; + case ErrorState: + panic("Went to the error state in the predecoder.\n"); + default: + panic("Unrecognized state! %d\n", state); + } + } + } + + //Either get a prefix and record it in the ExtMachInst, or send the + //state machine on to get the opcode(s). + Predecoder::State Predecoder::doPrefixState(uint8_t nextByte) + { + uint8_t prefix = Prefixes[nextByte]; + State nextState = PrefixState; + if(prefix) + consumeByte(); + switch(prefix) + { + //Operand size override prefixes + case OperandSizeOverride: + DPRINTF(Predecoder, "Found operand size override prefix.\n"); + break; + case AddressSizeOverride: + DPRINTF(Predecoder, "Found address size override prefix.\n"); + break; + //Segment override prefixes + case CSOverride: + DPRINTF(Predecoder, "Found cs segment override.\n"); + break; + case DSOverride: + DPRINTF(Predecoder, "Found ds segment override.\n"); + break; + case ESOverride: + DPRINTF(Predecoder, "Found es segment override.\n"); + break; + case FSOverride: + DPRINTF(Predecoder, "Found fs segment override.\n"); + break; + case GSOverride: + DPRINTF(Predecoder, "Found gs segment override.\n"); + break; + case SSOverride: + DPRINTF(Predecoder, "Found ss segment override.\n"); + break; + case Lock: + DPRINTF(Predecoder, "Found lock prefix.\n"); + break; + case Rep: + DPRINTF(Predecoder, "Found rep prefix.\n"); + break; + case Repne: + DPRINTF(Predecoder, "Found repne prefix.\n"); + break; + case RexPrefix: + DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte); + emi.rex = nextByte; + break; + case 0: + emi.opcode.num = 0; + nextState = OpcodeState; + break; + default: + panic("Unrecognized prefix %#x\n", nextByte); + } + return nextState; + } + + //Load all the opcodes (currently up to 2) and then figure out + //what immediate and/or ModRM is needed. + Predecoder::State Predecoder::doOpcodeState(uint8_t nextByte) + { + State nextState = ErrorState; + emi.opcode.num++; + //We can't handle 3+ byte opcodes right now + assert(emi.opcode.num < 3); + consumeByte(); + if(emi.opcode.num == 1 && nextByte == 0x0f) + { + nextState = OpcodeState; + DPRINTF(Predecoder, "Found two byte opcode.\n"); + emi.opcode.prefixA = nextByte; + } + else if(emi.opcode.num == 2 && + (nextByte == 0x0f || + (nextByte & 0xf8) == 0x38)) + { + panic("Three byte opcodes aren't yet supported!\n"); + nextState = OpcodeState; + DPRINTF(Predecoder, "Found three byte opcode.\n"); + emi.opcode.prefixB = nextByte; + } + else + { + DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte); + emi.opcode.op = nextByte; + + //Prepare for any immediate/displacement we might need + immediateCollected = 0; + emi.immediate = 0; + displacementCollected = 0; + emi.displacement = 0; + + //Figure out how big of an immediate we'll retreive based + //on the opcode. + int immType = ImmediateType[ + emi.opcode.num - 1][nextByte]; + if(0) //16 bit mode + immediateSize = ImmediateTypeToSize[0][immType]; + else if(!(emi.rex & 0x4)) //32 bit mode + immediateSize = ImmediateTypeToSize[1][immType]; + else //64 bit mode + immediateSize = ImmediateTypeToSize[2][immType]; + + //Determine what to expect next + if (UsesModRM[emi.opcode.num - 1][nextByte]) { + nextState = ModRMState; + } else if(immediateSize) { + nextState = ImmediateState; + } else { + emiIsReady = true; + nextState = PrefixState; + } + } + return nextState; + } + + //Get the ModRM byte and determine what displacement, if any, there is. + //Also determine whether or not to get the SIB byte, displacement, or + //immediate next. + Predecoder::State Predecoder::doModRMState(uint8_t nextByte) + { + State nextState = ErrorState; + emi.modRM = nextByte; + DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte); + if (0) {//FIXME in 16 bit mode + //figure out 16 bit displacement size + if(nextByte & 0xC7 == 0x06 || + nextByte & 0xC0 == 0x80) + displacementSize = 2; + else if(nextByte & 0xC0 == 0x40) + displacementSize = 1; + else + displacementSize = 0; + } else { + //figure out 32/64 bit displacement size + if(nextByte & 0xC7 == 0x05 || + nextByte & 0xC0 == 0x80) + displacementSize = 4; + else if(nextByte & 0xC0 == 0x40) + displacementSize = 2; + else + displacementSize = 0; + } + //If there's an SIB, get that next. + //There is no SIB in 16 bit mode. + if(nextByte & 0x7 == 4 && + nextByte & 0xC0 != 0xC0) { + // && in 32/64 bit mode) + nextState = SIBState; + } else if(displacementSize) { + nextState = DisplacementState; + } else if(immediateSize) { + nextState = ImmediateState; + } else { + emiIsReady = true; + nextState = PrefixState; + } + //The ModRM byte is consumed no matter what + consumeByte(); + return nextState; + } + + //Get the SIB byte. We don't do anything with it at this point, other + //than storing it in the ExtMachInst. Determine if we need to get a + //displacement or immediate next. + Predecoder::State Predecoder::doSIBState(uint8_t nextByte) + { + State nextState = ErrorState; + emi.sib = nextByte; + DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte); + consumeByte(); + if(displacementSize) { + nextState = DisplacementState; + } else if(immediateSize) { + nextState = ImmediateState; + } else { + emiIsReady = true; + nextState = PrefixState; + } + return nextState; + } + + //Gather up the displacement, or at least as much of it + //as we can get. + Predecoder::State Predecoder::doDisplacementState() + { + State nextState = ErrorState; + + getImmediate(displacementCollected, + emi.displacement, + displacementSize); + + DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n", + displacementSize, displacementCollected); + + if(displacementSize == displacementCollected) { + //Sign extend the displacement + switch(displacementSize) + { + case 1: + emi.displacement = sext<8>(emi.displacement); + break; + case 2: + emi.displacement = sext<16>(emi.displacement); + break; + case 4: + emi.displacement = sext<32>(emi.displacement); + break; + default: + panic("Undefined displacement size!\n"); + } + DPRINTF(Predecoder, "Collected displacement %#x.\n", + emi.displacement); + if(immediateSize) { + nextState = ImmediateState; + } else { + emiIsReady = true; + nextState = PrefixState; + } + } + else + nextState = DisplacementState; + return nextState; + } + + //Gather up the immediate, or at least as much of it + //as we can get + Predecoder::State Predecoder::doImmediateState() + { + State nextState = ErrorState; + + getImmediate(immediateCollected, + emi.immediate, + immediateSize); + + DPRINTF(Predecoder, "Collecting %d byte immediate, got %d bytes.\n", + immediateSize, immediateCollected); + + if(immediateSize == immediateCollected) + { + DPRINTF(Predecoder, "Collected immediate %#x.\n", + emi.immediate); + emiIsReady = true; + nextState = PrefixState; + } + else + nextState = ImmediateState; + return nextState; + } +} diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh new file mode 100644 index 000000000..1df17d6d2 --- /dev/null +++ b/src/arch/x86/predecoder.hh @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_PREDECODER_HH__ +#define __ARCH_X86_PREDECODER_HH__ + +#include "arch/x86/types.hh" +#include "base/bitfield.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace X86ISA +{ + class Predecoder + { + private: + //These are defined and documented in predecoder_tables.cc + static const uint8_t Prefixes[256]; + static const uint8_t UsesModRM[2][256]; + static const uint8_t ImmediateType[2][256]; + static const uint8_t ImmediateTypeToSize[3][10]; + + protected: + ThreadContext * tc; + //The bytes to be predecoded + MachInst fetchChunk; + //The pc of the start of fetchChunk + Addr basePC; + //The offset into fetchChunk of current processing + int offset; + //The extended machine instruction being generated + ExtMachInst emi; + + inline uint8_t getNextByte() + { + return (fetchChunk >> (offset * 8)) & 0xff; + } + + void getImmediate(int &collected, uint64_t ¤t, int size) + { + //Figure out how many bytes we still need to get for the + //immediate. + int toGet = size - collected; + //Figure out how many bytes are left in our "buffer" + int remaining = sizeof(MachInst) - offset; + //Get as much as we need, up to the amount available. + toGet = toGet > remaining ? remaining : toGet; + + //Shift the bytes we want to be all the way to the right + uint64_t partialDisp = fetchChunk >> (offset * 8); + //Mask off what we don't want + partialDisp &= mask(toGet * 8); + //Shift it over to overlay with our displacement. + partialDisp <<= (displacementCollected * 8); + //Put it into our displacement + current |= partialDisp; + //Update how many bytes we've collected. + collected += toGet; + consumeBytes(toGet); + } + + inline void consumeByte() + { + offset++; + assert(offset <= sizeof(MachInst)); + if(offset == sizeof(MachInst)) + outOfBytes = true; + } + + inline void consumeBytes(int numBytes) + { + offset += numBytes; + assert(offset <= sizeof(MachInst)); + if(offset == sizeof(MachInst)) + outOfBytes = true; + } + + //State machine state + protected: + //Whether or not we're out of bytes + bool outOfBytes; + //Whether we've completed generating an ExtMachInst + bool emiIsReady; + //The size of the displacement value + int displacementSize; + int displacementCollected; + //The size of the immediate value + int immediateSize; + int immediateCollected; + + enum State { + PrefixState, + OpcodeState, + ModRMState, + SIBState, + DisplacementState, + ImmediateState, + //We should never get to this state. Getting here is an error. + ErrorState + }; + + State state; + + //Functions to handle each of the states + State doPrefixState(uint8_t); + State doOpcodeState(uint8_t); + State doModRMState(uint8_t); + State doSIBState(uint8_t); + State doDisplacementState(); + State doImmediateState(); + + public: + Predecoder(ThreadContext * _tc) : + tc(_tc), basePC(0), offset(0), + outOfBytes(true), emiIsReady(false), + state(PrefixState) + {} + + ThreadContext * getTC() + { + return tc; + } + + void setTC(ThreadContext * _tc) + { + tc = _tc; + } + + void process(); + + //Use this to give data to the predecoder. This should be used + //when there is control flow. + void moreBytes(Addr currPC, Addr off, MachInst data) + { + basePC = currPC; + offset = off; + fetchChunk = data; + assert(off < sizeof(MachInst)); + outOfBytes = false; + process(); + } + + //Use this to give data to the predecoder. This should be used + //when instructions are executed in order. + void moreBytes(MachInst machInst) + { + moreBytes(basePC + sizeof(machInst), 0, machInst); + } + + bool needMoreBytes() + { + return outOfBytes; + } + + bool extMachInstReady() + { + return emiIsReady; + } + + //This returns a constant reference to the ExtMachInst to avoid a copy + const ExtMachInst & getExtMachInst() + { + assert(emiIsReady); + emiIsReady = false; + return emi; + } + }; +}; + +#endif // __ARCH_X86_PREDECODER_HH__ diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc new file mode 100644 index 000000000..f233ad234 --- /dev/null +++ b/src/arch/x86/predecoder_tables.cc @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/predecoder.hh" +#include "arch/x86/types.hh" + +namespace X86ISA +{ + const uint8_t CS = CSOverride; + const uint8_t DS = DSOverride; + const uint8_t ES = ESOverride; + const uint8_t FS = FSOverride; + const uint8_t GS = GSOverride; + const uint8_t SS = SSOverride; + + const uint8_t OO = OperandSizeOverride; + const uint8_t AO = AddressSizeOverride; + const uint8_t LO = Lock; + const uint8_t RE = Rep; + const uint8_t RN = Repne; + const uint8_t RX = RexPrefix; + + //This table identifies whether a byte is a prefix, and if it is, + //which prefix it is. + const uint8_t Predecoder::Prefixes[256] = + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 1*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 2*/ 0 , 0 , 0 , 0 , 0 , 0 , ES, 0 , 0 , 0 , 0 , 0 , 0 , 0 , CS, 0, +/* 3*/ 0 , 0 , 0 , 0 , 0 , 0 , SS, 0 , 0 , 0 , 0 , 0 , 0 , 0 , DS, 0, +/* 4*/ RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, RX, +/* 5*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 6*/ 0 , 0 , 0 , 0 , FS, GS, OO, AO, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 7*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 8*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 9*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* A*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* B*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* C*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* D*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* E*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* F*/ LO, 0 , RN, RE, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 + }; + + //This table identifies whether a particular opcode uses the ModRM byte + const uint8_t Predecoder::UsesModRM[2][256] = + {//For one byte instructions + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 1 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 2 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 3 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0, +/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 6 */ 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0, +/* 7 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 8 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* A */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* C */ 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* D */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 + }, + //For two byte instructions + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1, +/* 1 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 2 */ 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 4 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 5 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 6 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* 7 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1, +/* 8 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* 9 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* A */ 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1, +/* B */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1, +/* C */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, +/* D */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* E */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, +/* F */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 + } + }; + + enum ImmediateTypes { + NoImm, + NI = NoImm, + ByteImm, + BY = ByteImm, + WordImm, + WO = WordImm, + DWordImm, + DW = DWordImm, + QWordImm, + QW = QWordImm, + OWordImm, + OW = OWordImm, + VWordImm, + VW = VWordImm, + ZWordImm, + ZW = ZWordImm, + Pointer, + PO = Pointer, + //The enter instruction takes -2- immediates for a total of 3 bytes + Enter, + EN = Enter + }; + + const uint8_t Predecoder::ImmediateTypeToSize[3][10] = + { +// noimm byte word dword qword oword vword zword enter + {0, 1, 2, 4, 8, 16, 2, 2, 3, 4}, //16 bit + {0, 1, 2, 4, 8, 16, 4, 4, 3, 6}, //32 bit + {0, 1, 2, 4, 8, 16, 4, 8, 3, 0} //64 bit + }; + + //This table determines the immediate type. The first index is the + //number of bytes in the instruction, and the second is the meaningful + //byte of the opcode. I didn't use the NI constant here for the sake + //of clarity. + const uint8_t Predecoder::ImmediateType[2][256] = + {//For one byte instructions + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , +/* 1 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , +/* 2 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , +/* 3 */ 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , +/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 6 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, ZW, BY, BY, 0 , 0 , 0 , 0 , +/* 7 */ BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, BY, +/* 8 */ BY, ZW, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* A */ BY, VW, BY, VW, 0 , 0 , 0 , 0 , BY, ZW, 0 , 0 , 0 , 0 , 0 , 0 , +/* B */ BY, BY, BY, BY, BY, BY, BY, BY, VW, VW, VW, VW, VW, VW, VW, VW, +/* C */ BY, BY, WO, 0 , 0 , 0 , BY, ZW, EN, 0 , WO, 0 , 0 , BY, 0 , 0 , +/* D */ 0 , 0 , 0 , 0 , BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* E */ BY, BY, BY, BY, BY, BY, BY, BY, ZW, ZW, PO, BY, 0 , 0 , 0 , 0 , +/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 + }, + //For two byte instructions + { //LSB +// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F +/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 2 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 4 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 5 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 6 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 7 */ BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* 8 */ ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, ZW, +/* 9 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* A */ 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY, 0 , 0 , 0 , +/* B */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ZW, 0 , BY, 0 , 0 , 0 , 0 , 0 , +/* C */ 0 , 0 , BY, 0 , BY, BY, BY, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* D */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* E */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , +/* F */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 + } + }; +} diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc new file mode 100644 index 000000000..e6d1e4921 --- /dev/null +++ b/src/arch/x86/process.cc @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2003-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: Gabe Black + * Ali Saidi + */ + +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/isa_traits.hh" +#include "arch/x86/process.hh" +#include "arch/x86/types.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" +#include "mem/translating_port.hh" +#include "sim/system.hh" + +using namespace std; +using namespace X86ISA; + +M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val) +{ + a_type = TheISA::htog(type); + a_val = TheISA::htog(val); +} + +X86LiveProcess::X86LiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid) + : LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, _uid, _euid, _gid, _egid, _pid, _ppid) +{ + brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); + brk_point = roundUp(brk_point, VMPageSize); + + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); + + // Set up stack. On SPARC Linux, stack goes from the top of memory + // downward, less the hole for the kernel address space. + stack_base = (Addr)0x80000000000ULL; + + // Set up region for mmaps. Tru64 seems to start just above 0 and + // grow up from there. + mmap_start = mmap_end = 0xfffff80000000000ULL; +} + +void X86LiveProcess::handleTrap(int trapNum, ThreadContext *tc) +{ + switch(trapNum) + { + default: + panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum); + } +} + +void +X86LiveProcess::startup() +{ + argsInit(sizeof(IntReg), VMPageSize); + + //The AMD64 abi says that only rsp and rdx are defined at process + //startup. rsp will be set by argsInit, and I don't understand what + //rdx should be set to. The other floating point and integer registers + //will be zeroed by the register file constructors, but control registers + //should be initialized here. Since none of those are implemented, there + //isn't anything here. +} + +void +X86LiveProcess::argsInit(int intSize, int pageSize) +{ + typedef M5_64_auxv_t auxv_t; + Process::startup(); + + string filename; + if(argv.size() < 1) + filename = ""; + else + filename = argv[0]; + + Addr alignmentMask = ~(intSize - 1); + + // load object file into target memory + objFile->loadSections(initVirtMem); + + //These are the auxilliary vector types + enum auxTypes + { + X86_AT_NULL = 0, + X86_AT_IGNORE = 1, + X86_AT_EXECFD = 2, + X86_AT_PHDR = 3, + X86_AT_PHENT = 4, + X86_AT_PHNUM = 5, + X86_AT_PAGESZ = 6, + X86_AT_BASE = 7, + X86_AT_FLAGS = 8, + X86_AT_ENTRY = 9, + X86_AT_NOTELF = 10, + X86_AT_UID = 11, + X86_AT_EUID = 12, + X86_AT_GID = 13, + X86_AT_EGID = 14 + }; + + //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(auxv_t(SPARC_AT_HWCAP, hwcap)); + //The system page size + auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize)); + //Defined to be 100 in the kernel source. + //Frequency at which times() increments + auxv.push_back(auxv_t(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(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable())); + // This is the size of a program header entry from the elf file. + auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize())); + // This is the number of program headers from the original elf file. + auxv.push_back(auxv_t(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(auxv_t(SPARC_AT_BASE, 0)); + //This is hardwired to 0 in the elf loading code in the kernel + auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0)); + //The entry point to the program + auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint())); + //Different user and group IDs + auxv.push_back(auxv_t(SPARC_AT_UID, uid())); + auxv.push_back(auxv_t(SPARC_AT_EUID, euid())); + auxv.push_back(auxv_t(SPARC_AT_GID, gid())); + auxv.push_back(auxv_t(SPARC_AT_EGID, egid())); + //Whether to enable "secure mode" in the executable + auxv.push_back(auxv_t(SPARC_AT_SECURE, 0));*/ + } + + //Figure out how big the initial stack needs to be + + // The unaccounted for 0 at the top of the stack + int mysterious_size = intSize; + + //This is the name of the file which is present on the initial stack + //It's purpose is to let the user space linker examine the original file. + int file_name_size = filename.size() + 1; + + int env_data_size = 0; + for (int i = 0; i < envp.size(); ++i) { + env_data_size += envp[i].size() + 1; + } + int arg_data_size = 0; + for (int i = 0; i < argv.size(); ++i) { + arg_data_size += argv[i].size() + 1; + } + + //The info_block needs to be padded so it's size is a multiple of the + //alignment mask. Also, it appears that there needs to be at least some + //padding, so if the size is already a multiple, we need to increase it + //anyway. + int info_block_size = + (file_name_size + + env_data_size + + arg_data_size + + intSize) & alignmentMask; + + int info_block_padding = + info_block_size - + file_name_size - + env_data_size - + arg_data_size; + + //Each auxilliary vector is two 8 byte words + int aux_array_size = intSize * 2 * (auxv.size() + 1); + + int envp_array_size = intSize * (envp.size() + 1); + int argv_array_size = intSize * (argv.size() + 1); + + int argc_size = intSize; + int window_save_size = intSize * 16; + + int space_needed = + mysterious_size + + info_block_size + + aux_array_size + + envp_array_size + + argv_array_size + + argc_size + + window_save_size; + + stack_min = stack_base - space_needed; + stack_min &= alignmentMask; + stack_size = stack_base - stack_min; + + // map memory + pTable->allocate(roundDown(stack_min, pageSize), + roundUp(stack_size, pageSize)); + + // map out initial stack contents + Addr mysterious_base = stack_base - mysterious_size; + Addr file_name_base = mysterious_base - file_name_size; + Addr env_data_base = file_name_base - env_data_size; + Addr arg_data_base = env_data_base - arg_data_size; + Addr auxv_array_base = arg_data_base - aux_array_size - info_block_padding; + Addr envp_array_base = auxv_array_base - envp_array_size; + Addr argv_array_base = envp_array_base - argv_array_size; + Addr argc_base = argv_array_base - argc_size; +#ifndef NDEBUG + // only used in DPRINTF + Addr window_save_base = argc_base - window_save_size; +#endif + + DPRINTF(X86, "The addresses of items on the initial stack:\n"); + DPRINTF(X86, "0x%x - file name\n", file_name_base); + DPRINTF(X86, "0x%x - env data\n", env_data_base); + DPRINTF(X86, "0x%x - arg data\n", arg_data_base); + DPRINTF(X86, "0x%x - auxv array\n", auxv_array_base); + DPRINTF(X86, "0x%x - envp array\n", envp_array_base); + DPRINTF(X86, "0x%x - argv array\n", argv_array_base); + DPRINTF(X86, "0x%x - argc \n", argc_base); + DPRINTF(X86, "0x%x - window save\n", window_save_base); + DPRINTF(X86, "0x%x - stack min\n", stack_min); + + // write contents to stack + + // figure out argc + uint64_t argc = argv.size(); + uint64_t guestArgc = TheISA::htog(argc); + + //Write out the mysterious 0 + uint64_t mysterious_zero = 0; + initVirtMem->writeBlob(mysterious_base, + (uint8_t*)&mysterious_zero, mysterious_size); + + //Write the file name + initVirtMem->writeString(file_name_base, filename.c_str()); + + //Copy the aux stuff + for(int x = 0; x < auxv.size(); x++) + { + initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize, + (uint8_t*)&(auxv[x].a_type), intSize); + initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize, + (uint8_t*)&(auxv[x].a_val), intSize); + } + //Write out the terminating zeroed auxilliary vector + const uint64_t zero = 0; + initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(), + (uint8_t*)&zero, 2 * intSize); + + copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); + copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); + + initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); + + //Set up the thread context to start running the process + threadContexts[0]->setIntReg(ArgumentReg0, argc); + threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base); + threadContexts[0]->setIntReg(StackPointerReg, stack_min); + + Addr prog_entry = objFile->entryPoint(); + threadContexts[0]->setPC(prog_entry); + threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); + + //Align the "stack_min" to a page boundary. + stack_min = roundDown(stack_min, pageSize); + +// num_processes++; +} diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh new file mode 100644 index 000000000..a2fa258c8 --- /dev/null +++ b/src/arch/x86/process.hh @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_PROCESS_HH__ +#define __ARCH_X86_PROCESS_HH__ + +#include <string> +#include <vector> +#include "sim/process.hh" + +namespace X86ISA +{ + struct M5_64_auxv_t + { + int64_t a_type; + union { + int64_t a_val; + int64_t a_ptr; + int64_t a_fcn; + }; + + M5_64_auxv_t() + {} + + M5_64_auxv_t(int64_t type, int64_t val); + }; + + class X86LiveProcess : public LiveProcess + { + protected: + std::vector<M5_64_auxv_t> auxv; + + X86LiveProcess(const std::string &nm, ObjectFile *objFile, + System *_system, + int stdin_fd, int stdout_fd, int stderr_fd, + std::vector<std::string> &argv, + std::vector<std::string> &envp, + const std::string &cwd, + uint64_t _uid, uint64_t _euid, + uint64_t _gid, uint64_t _egid, + uint64_t _pid, uint64_t _ppid); + + void startup(); + + public: + + //Handles traps which request services from the operating system + virtual void handleTrap(int trapNum, ThreadContext *tc); + + void argsInit(int intSize, int pageSize); + }; +} + +#endif // __ARCH_X86_PROCESS_HH__ diff --git a/src/arch/x86/regfile.cc b/src/arch/x86/regfile.cc new file mode 100644 index 000000000..568eb1d94 --- /dev/null +++ b/src/arch/x86/regfile.cc @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2003-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: Gabe Black + */ + +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#include "arch/x86/regfile.hh" +#include "sim/serialize.hh" +#include "cpu/thread_context.hh" + +class Checkpoint; + +using namespace X86ISA; +using namespace std; + +//RegFile class methods +Addr RegFile::readPC() +{ + return rip; +} + +void RegFile::setPC(Addr val) +{ + rip = val; +} + +Addr RegFile::readNextPC() +{ + return nextRip; +} + +void RegFile::setNextPC(Addr val) +{ + nextRip = val; +} + +Addr RegFile::readNextNPC() +{ + return nextRip + sizeof(MachInst); +} + +void RegFile::setNextNPC(Addr val) +{ } + +void RegFile::clear() +{ + floatRegFile.clear(); + intRegFile.clear(); + miscRegFile.clear(); +} + +MiscReg RegFile::readMiscRegNoEffect(int miscReg) +{ + return miscRegFile.readRegNoEffect(miscReg); +} + +MiscReg RegFile::readMiscReg(int miscReg, ThreadContext *tc) +{ + return miscRegFile.readReg(miscReg, tc); +} + +void RegFile::setMiscRegNoEffect(int miscReg, const MiscReg &val) +{ + miscRegFile.setRegNoEffect(miscReg, val); +} + +void RegFile::setMiscReg(int miscReg, const MiscReg &val, + ThreadContext * tc) +{ + miscRegFile.setReg(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); +} + +void RegFile::setFloatReg(int floatReg, const FloatReg &val, int width) +{ + floatRegFile.setReg(floatReg, val, width); +} + +void RegFile::setFloatReg(int floatReg, const FloatReg &val) +{ + //Use the "natural" width of a single float + setFloatReg(floatReg, val, FloatRegFile::SingleWidth); +} + +void RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val, int width) +{ + floatRegFile.setRegBits(floatReg, val, width); +} + +void RegFile::setFloatRegBits(int floatReg, const FloatRegBits &val) +{ + //Use the "natural" width of a single float + floatRegFile.setRegBits(floatReg, val, FloatRegFile::SingleWidth); +} + +IntReg RegFile::readIntReg(int intReg) +{ + return intRegFile.readReg(intReg); +} + +void RegFile::setIntReg(int intReg, const IntReg &val) +{ + intRegFile.setReg(intReg, val); +} + +int X86ISA::flattenIntIndex(ThreadContext * tc, int reg) +{ + //For right now, don't do any flattening + return reg; +} + +void RegFile::serialize(std::ostream &os) +{ + intRegFile.serialize(os); + floatRegFile.serialize(os); + miscRegFile.serialize(os); + SERIALIZE_SCALAR(rip); + SERIALIZE_SCALAR(nextRip); +} + +void RegFile::unserialize(Checkpoint *cp, const std::string §ion) +{ + intRegFile.unserialize(cp, section); + floatRegFile.unserialize(cp, section); + miscRegFile.unserialize(cp, section); + UNSERIALIZE_SCALAR(rip); + UNSERIALIZE_SCALAR(nextRip); +} + +void RegFile::changeContext(RegContextParam param, RegContextVal val) +{ + panic("changeContext not implemented for x86!\n"); +} + +void X86ISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest) +{ + panic("copyMiscRegs not implemented for x86!\n"); +} + +void X86ISA::copyRegs(ThreadContext *src, ThreadContext *dest) +{ + panic("copyRegs not implemented for x86!\n"); + //copy int regs + //copy float regs + copyMiscRegs(src, dest); + + dest->setPC(src->readPC()); + dest->setNextPC(src->readNextPC()); +} diff --git a/src/arch/x86/regfile.hh b/src/arch/x86/regfile.hh new file mode 100644 index 000000000..d4425b04c --- /dev/null +++ b/src/arch/x86/regfile.hh @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_REGFILE_HH__ +#define __ARCH_X86_REGFILE_HH__ + +#include "arch/x86/floatregfile.hh" +#include "arch/x86/intregfile.hh" +#include "arch/x86/isa_traits.hh" +#include "arch/x86/miscregfile.hh" +#include "arch/x86/types.hh" +#include "sim/host.hh" + +#include <string> + +class Checkpoint; + +namespace X86ISA +{ + class RegFile + { + protected: + Addr rip; //Program Counter + Addr nextRip; //Next Program Counter + + public: + Addr readPC(); + void setPC(Addr val); + + Addr readNextPC(); + void setNextPC(Addr val); + + Addr readNextNPC(); + void setNextNPC(Addr val); + + protected: + IntRegFile intRegFile; // integer register file + FloatRegFile floatRegFile; // floating point register file + MiscRegFile miscRegFile; // control register file + + public: + + void clear(); + + int FlattenIntIndex(int reg); + + MiscReg readMiscRegNoEffect(int miscReg); + + MiscReg readMiscReg(int miscReg, ThreadContext *tc); + + void setMiscRegNoEffect(int miscReg, const MiscReg &val); + + void setMiscReg(int miscReg, const MiscReg &val, + ThreadContext * tc); + + int instAsid() + { + //XXX This doesn't make sense in x86 + return 0; + } + + int dataAsid() + { + //XXX This doesn't make sense in x86 + return 0; + } + + FloatReg readFloatReg(int floatReg, int width); + + FloatReg readFloatReg(int floatReg); + + FloatRegBits readFloatRegBits(int floatReg, int width); + + FloatRegBits readFloatRegBits(int floatReg); + + void setFloatReg(int floatReg, const FloatReg &val, int width); + + void setFloatReg(int floatReg, const FloatReg &val); + + void setFloatRegBits(int floatReg, const FloatRegBits &val, int width); + + void setFloatRegBits(int floatReg, const FloatRegBits &val); + + IntReg readIntReg(int intReg); + + void setIntReg(int intReg, const IntReg &val); + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + public: + + void changeContext(RegContextParam param, RegContextVal val); + }; + + int flattenIntIndex(ThreadContext * tc, int reg); + + void copyRegs(ThreadContext *src, ThreadContext *dest); + + void copyMiscRegs(ThreadContext *src, ThreadContext *dest); + + int InterruptLevel(uint64_t softint); + +}; // namespace X86ISA + +#endif // __ARCH_X86_REGFILE_HH__ diff --git a/src/arch/x86/remote_gdb.cc b/src/arch/x86/remote_gdb.cc new file mode 100644 index 000000000..5ab0ec3fb --- /dev/null +++ b/src/arch/x86/remote_gdb.cc @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratories. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94 + */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $ + * + * Taken from NetBSD + * + * "Stub" to allow remote cpu to debug over a serial line using gdb. + */ + +#include <sys/signal.h> + +#include <string> +#include <unistd.h> + +#include "arch/vtophys.hh" +#include "arch/x86/remote_gdb.hh" +#include "base/remote_gdb.hh" +#include "base/socket.hh" +#include "base/trace.hh" +#include "config/full_system.hh" +#include "cpu/thread_context.hh" + +using namespace std; +using namespace TheISA; + +RemoteGDB::RemoteGDB(System *_system, ThreadContext *c) + : BaseRemoteGDB(_system, c, NumGDBRegs) +{} + +bool RemoteGDB::acc(Addr va, size_t len) +{ + panic("Remote gdb acc not implemented in x86!\n"); +} + +void RemoteGDB::getregs() +{ + panic("Remote gdb getregs not implemented in x86!\n"); +} + +void RemoteGDB::setregs() +{ + panic("Remote gdb setregs not implemented in x86!\n"); +} + +void RemoteGDB::clearSingleStep() +{ + panic("Remote gdb clearSingleStep not implemented in x86!\n"); +} + +void RemoteGDB::setSingleStep() +{ + panic("Remoge gdb setSingleStep not implemented in x86!\n"); +} diff --git a/src/arch/x86/remote_gdb.hh b/src/arch/x86/remote_gdb.hh new file mode 100644 index 000000000..e21250875 --- /dev/null +++ b/src/arch/x86/remote_gdb.hh @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_REMOTEGDB_HH__ +#define __ARCH_X86_REMOTEGDB_HH__ + +#include "arch/x86/types.hh" +#include "base/remote_gdb.hh" + +class System; +class ThreadContext; + +namespace X86ISA +{ + class RemoteGDB : public BaseRemoteGDB + { + protected: + enum RegisterContants + { + NumGDBRegs + //XXX fill this in + }; + + public: + RemoteGDB(System *system, ThreadContext *context); + + bool acc(Addr addr, size_t len); + + protected: + void getregs(); + void setregs(); + + void clearSingleStep(); + void setSingleStep(); + + Addr nextBkpt; + }; +} + +#endif // __ARCH_X86_REMOTEGDB_HH__ diff --git a/src/arch/x86/stacktrace.hh b/src/arch/x86/stacktrace.hh new file mode 100644 index 000000000..854fb397c --- /dev/null +++ b/src/arch/x86/stacktrace.hh @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __ARCH_X86_STACKTRACE_HH__ +#define __ARCH_X86_STACKTRACE_HH__ + +#include "base/trace.hh" +#include "cpu/static_inst.hh" + +class ThreadContext; +namespace X86ISA +{ + class StackTrace; + + class ProcessInfo + { + private: + ThreadContext *tc; + + int thread_info_size; + int task_struct_size; + int task_off; + int pid_off; + int name_off; + + public: + ProcessInfo(ThreadContext *_tc); + + Addr task(Addr ksp) const; + int pid(Addr ksp) const; + std::string name(Addr ksp) const; + }; + + class StackTrace + { + private: + ThreadContext *tc; + std::vector<Addr> stack; + + private: + bool isEntry(Addr addr); + bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); + bool decodeSave(MachInst inst, int ®, int &disp); + bool decodeStack(MachInst inst, int &disp); + + void trace(ThreadContext *tc, bool is_call); + + public: + StackTrace(); + StackTrace(ThreadContext *tc, StaticInstPtr inst); + ~StackTrace(); + + void clear() + { + tc = 0; + stack.clear(); + } + + bool valid() const { return tc != NULL; } + bool trace(ThreadContext *tc, StaticInstPtr inst); + + public: + const std::vector<Addr> &getstack() const { return stack; } + + static const int user = 1; + static const int console = 2; + static const int unknown = 3; + +#if TRACING_ON + private: + void dump(); + + public: + void dprintf() { if (DTRACE(Stack)) dump(); } +#else + public: + void dprintf() {} +#endif + }; + + inline bool + StackTrace::trace(ThreadContext *tc, StaticInstPtr inst) + { + if (!inst->isCall() && !inst->isReturn()) + return false; + + if (valid()) + clear(); + + trace(tc, !inst->isReturn()); + return true; + } +} + +#endif // __ARCH_X86_STACKTRACE_HH__ diff --git a/src/arch/x86/syscallreturn.hh b/src/arch/x86/syscallreturn.hh new file mode 100644 index 000000000..9f0d20e2a --- /dev/null +++ b/src/arch/x86/syscallreturn.hh @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_SYSCALLRETURN_HH__ +#define __ARCH_X86_SYSCALLRETURN_HH__ + +#include "base/misc.hh" +#include "sim/syscallreturn.hh" + +class ThreadContext; + +namespace X86ISA +{ + static inline void setSyscallReturn(SyscallReturn return_value, + ThreadContext * tc) + { + panic("setSyscallReturn not implemented!\n"); + } +}; + +#endif // __ARCH_X86_SYSCALLRETURN_HH__ diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh new file mode 100644 index 000000000..c19ce0b29 --- /dev/null +++ b/src/arch/x86/tlb.hh @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_TLB_HH__ +#define __ARCH_X86_TLB_HH__ + +#error X86 is not yet supported! + +namespace X86ISA +{ +}; + +#endif // __ARCH_X86_TLB_HH__ diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh new file mode 100644 index 000000000..ca4a15d24 --- /dev/null +++ b/src/arch/x86/types.hh @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_TYPES_HH__ +#define __ARCH_X86_TYPES_HH__ + +#include <inttypes.h> +#include <iostream> + +#include "base/bitfield.hh" +#include "base/cprintf.hh" + +namespace X86ISA +{ + //This really determines how many bytes are passed to the predecoder. + typedef uint64_t MachInst; + + enum Prefixes { + NoOverride = 0, + CSOverride = 1, + DSOverride = 2, + ESOverride = 3, + FSOverride = 4, + GSOverride = 5, + SSOverride = 6, + //The Rex prefix obviously doesn't fit in with the above, but putting + //it here lets us save double the space the enums take up. + RexPrefix = 7, + //There can be only one segment override, so they share the + //first 3 bits in the legacyPrefixes bitfield. + SegmentOverride = 0x7, + OperandSizeOverride = 8, + AddressSizeOverride = 16, + Lock = 32, + Rep = 64, + Repne = 128 + }; + + BitUnion8(ModRM) + Bitfield<7,6> mod; + Bitfield<5,3> reg; + Bitfield<2,0> rm; + EndBitUnion(ModRM) + + BitUnion8(Sib) + Bitfield<7,6> scale; + Bitfield<5,3> index; + Bitfield<2,0> base; + EndBitUnion(Sib) + + BitUnion8(Rex) + Bitfield<3> w; + Bitfield<2> r; + Bitfield<1> x; + Bitfield<0> b; + EndBitUnion(Rex) + + BitUnion8(Opcode) + Bitfield<7,3> top5; + Bitfield<2,0> bottom3; + EndBitUnion(Opcode) + + //The intermediate structure the x86 predecoder returns. + struct ExtMachInst + { + //Prefixes + uint8_t legacy; + Rex rex; + //This holds all of the bytes of the opcode + struct + { + //The number of bytes in this opcode. Right now, we ignore that + //this can be 3 in some cases + uint8_t num; + //The first byte detected in a 2+ byte opcode. Should be 0xF0. + uint8_t prefixA; + //The second byte detected in a 3+ byte opcode. Could be 0xF0 for + //3dnow instructions, or 0x38-0x3F for some SSE instructions. + uint8_t prefixB; + //The main opcode byte. The highest addressed byte in the opcode. + Opcode op; + } opcode; + //Modifier bytes + ModRM modRM; + uint8_t sib; + //Immediate fields + uint64_t immediate; + uint64_t displacement; + }; + + inline static std::ostream & + operator << (std::ostream & os, const ExtMachInst & emi) + { + ccprintf(os, "\n{\n\tleg = %#x,\n\trex = %#x,\n\t" + "op = {\n\t\tnum = %d,\n\t\top = %#x,\n\t\t" + "prefixA = %#x,\n\t\tprefixB = %#x\n\t},\n\t" + "modRM = %#x,\n\tsib = %#x,\n\t" + "immediate = %#x,\n\tdisplacement = %#x\n}\n", + emi.legacy, (uint8_t)emi.rex, + emi.opcode.num, emi.opcode.op, + emi.opcode.prefixA, emi.opcode.prefixB, + (uint8_t)emi.modRM, (uint8_t)emi.sib, + emi.immediate, emi.displacement); + return os; + } + + inline static bool + operator == (const ExtMachInst &emi1, const ExtMachInst &emi2) + { + //Since this is empty, it's always equal + return true; + } + + typedef uint64_t IntReg; + //XXX Should this be a 128 bit structure for XMM memory ops? + typedef uint64_t LargestRead; + typedef uint64_t MiscReg; + + //These floating point types are correct for mmx, but not + //technically for x87 (80 bits) or at all for xmm (128 bits) + typedef double FloatReg; + typedef uint64_t FloatRegBits; + typedef union + { + IntReg intReg; + FloatReg fpReg; + MiscReg ctrlReg; + } AnyReg; + + //XXX This is very hypothetical. X87 instructions would need to + //change their "context" constantly. It's also not clear how + //this would be handled as far as out of order execution. + //Maybe x87 instructions are in order? + enum RegContextParam + { + CONTEXT_X87_TOP + }; + + typedef int RegContextVal; + + typedef uint8_t RegIndex; +}; + +#endif // __ARCH_X86_TYPES_HH__ diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh new file mode 100644 index 000000000..d89e223de --- /dev/null +++ b/src/arch/x86/utility.hh @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_UTILITY_HH__ +#define __ARCH_X86_UTILITY_HH__ + +#include "arch/x86/types.hh" +#include "base/hashmap.hh" +#include "base/misc.hh" +#include "cpu/thread_context.hh" +#include "sim/host.hh" + +class ThreadContext; + +namespace __hash_namespace { + template<> + struct hash<X86ISA::ExtMachInst> { + size_t operator()(const X86ISA::ExtMachInst &emi) const { + //Because these are all the same, return 0 + return 0; + }; + }; +} + +namespace X86ISA +{ + static inline bool + inUserMode(ThreadContext *tc) + { + return false; + } + + inline bool isCallerSaveIntegerRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + inline bool isCalleeSaveIntegerRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + inline bool isCallerSaveFloatRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + inline bool isCalleeSaveFloatRegister(unsigned int reg) { + panic("register classification not implemented"); + return false; + } + + // Instruction address compression hooks + inline Addr realPCToFetchPC(const Addr &addr) + { + return addr; + } + + inline Addr fetchPCToRealPC(const Addr &addr) + { + return addr; + } + + // the size of "fetched" instructions (not necessarily the size + // of real instructions for PISA) + inline size_t fetchInstSize() + { + return sizeof(MachInst); + } + + /** + * Function to insure ISA semantics about 0 registers. + * @param tc The thread context. + */ + template <class TC> + void zeroRegisters(TC *tc); + + inline void initCPU(ThreadContext *tc, int cpuId) + { + panic("initCPU not implemented!\n"); + } + + inline void startupCPU(ThreadContext *tc, int cpuId) + { + tc->activate(0); + } +}; + +#endif // __ARCH_X86_UTILITY_HH__ diff --git a/src/arch/x86/vtophys.hh b/src/arch/x86/vtophys.hh new file mode 100644 index 000000000..00d0f9499 --- /dev/null +++ b/src/arch/x86/vtophys.hh @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_VTOPHYS_HH__ +#define __ARCH_X86_VTOPHYS_HH__ + +#include "arch/x86/isa_traits.hh" +#include "arch/x86/pagetable.hh" +#include "sim/host.hh" + +class ThreadContext; +class FunctionalPort; + +namespace X86ISA +{ + +PageTableEntry +kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, X86ISA::VAddr vaddr); + +Addr vtophys(Addr vaddr); +Addr vtophys(ThreadContext *tc, Addr vaddr); + +}; + +#endif // __ARCH_X86_VTOPHYS_HH__ diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh new file mode 100644 index 000000000..fa54c24e9 --- /dev/null +++ b/src/arch/x86/x86_traits.hh @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. Neither the name of + * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Gabe Black + */ + +#ifndef __ARCH_X86_X86TRAITS_HH__ +#define __ARCH_X86_X86TRAITS_HH__ + +namespace X86ISA +{ + //XXX This will definitely need to be something larger in the future. + const int NumMicroIntRegs = 0; + + const int NumMMXRegs = 8; + const int NumXMMRegs = 16; +} + +#endif //__ARCH_X86_X86TRAITS_HH__ diff --git a/src/base/SConscript b/src/base/SConscript new file mode 100644 index 000000000..788aa3e6f --- /dev/null +++ b/src/base/SConscript @@ -0,0 +1,83 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +# base/traceflags.{cc,hh} are generated from base/traceflags.py. +# $TARGET.base will expand to "<build-dir>/base/traceflags". +env.Command(['traceflags.hh', 'traceflags.cc'], 'traceflags.py', + 'python $SOURCE $TARGET.base') + +Source('annotate.cc') +Source('bigint.cc') +Source('circlebuf.cc') +Source('cprintf.cc') +Source('crc.cc') +Source('fast_alloc.cc') +Source('fifo_buffer.cc') +Source('hostinfo.cc') +Source('hybrid_pred.cc') +Source('inet.cc') +Source('inifile.cc') +Source('intmath.cc') +Source('match.cc') +Source('misc.cc') +Source('output.cc') +Source('pollevent.cc') +Source('random.cc') +Source('range.cc') +Source('remote_gdb.cc') +Source('sat_counter.cc') +Source('socket.cc') +Source('statistics.cc') +Source('str.cc') +Source('time.cc') +Source('trace.cc') +Source('traceflags.cc') +Source('userinfo.cc') + +Source('compression/lzss_compression.cc') + +Source('loader/aout_object.cc') +Source('loader/ecoff_object.cc') +Source('loader/elf_object.cc') +Source('loader/object_file.cc') +Source('loader/raw_object.cc') +Source('loader/symtab.cc') + +Source('stats/events.cc') +Source('stats/output.cc') +Source('stats/statdb.cc') +Source('stats/text.cc') +Source('stats/visit.cc') + +if env['USE_MYSQL']: + Source('mysql.cc') + Source('stats/mysql.cc') diff --git a/src/base/annotate.cc b/src/base/annotate.cc index ba2fb1788..de7eeed51 100644 --- a/src/base/annotate.cc +++ b/src/base/annotate.cc @@ -32,7 +32,7 @@ #include "base/callback.hh" #include "base/output.hh" #include "base/trace.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/sim_exit.hh" #include "sim/system.hh" diff --git a/src/base/bigint.cc b/src/base/bigint.cc new file mode 100644 index 000000000..ce9942c9c --- /dev/null +++ b/src/base/bigint.cc @@ -0,0 +1,47 @@ +/* + * 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: Gabe Black + */ + +#include "base/bigint.hh" + +#include <iostream> + +using namespace std; + +ostream & operator << (ostream & os, const Twin64_t & t) +{ + os << t.a << ", " << t.b; + return os; +} + +ostream & operator << (ostream & os, const Twin32_t & t) +{ + os << t.a << ", " << t.b; + return os; +} diff --git a/src/base/bigint.hh b/src/base/bigint.hh new file mode 100644 index 000000000..d60684231 --- /dev/null +++ b/src/base/bigint.hh @@ -0,0 +1,97 @@ +/* + * 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 "base/misc.hh" + +#include <iostream> + +#ifndef __BASE_BIGINT_HH__ +#define __BASE_BIGINT_HH__ +// Create a couple of large int types for atomic reads +struct m5_twin64_t { + uint64_t a; + uint64_t b; + m5_twin64_t() + {} + m5_twin64_t(const uint64_t x) + { + a = x; + b = x; + } + inline m5_twin64_t& operator=(const uint64_t x) + { + a = x; + b = x; + return *this; + } + + operator uint64_t() + { + panic("Tried to cram a twin64_t into an integer!\n"); + return a; + } +}; + +struct m5_twin32_t { + uint32_t a; + uint32_t b; + m5_twin32_t() + {} + m5_twin32_t(const uint32_t x) + { + a = x; + b = x; + } + inline m5_twin32_t& operator=(const uint32_t x) + { + a = x; + b = x; + return *this; + } + + operator uint32_t() + { + panic("Tried to cram a twin32_t into an integer!\n"); + return a; + } +}; + + +// This is for twin loads (two 64 bit values), not 1 128 bit value (as far as +// endian conversion is concerned! +typedef m5_twin64_t Twin64_t; +typedef m5_twin32_t Twin32_t; + +// Output operator overloads +std::ostream & operator << (std::ostream & os, const Twin64_t & t); +std::ostream & operator << (std::ostream & os, const Twin32_t & t); + +#endif // __BASE_BIGINT_HH__ + diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index 1fc0bad5d..69cce2245 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -44,6 +44,7 @@ mask(int nbits) } + /** * Extract the bitfield from position 'first' to 'last' (inclusive) * from 'val' and right justify it. MSB is numbered 63, LSB is 0. @@ -69,6 +70,12 @@ mbits(T val, int first, int last) return val & (mask(first+1) & ~mask(last)); } +inline uint64_t +mask(int first, int last) +{ + return mbits((uint64_t)-1LL, first, last); +} + /** * Sign-extend an N-bit value to 64 bits. */ @@ -105,4 +112,291 @@ replaceBits(T& val, int first, int last, B bit_val) val = insertBits(val, first, last, bit_val); } +/** + * Returns the bit position of the MSB that is set in the input + */ +inline +int +findMsbSet(uint64_t val) { + int msb = 0; + if (!val) + return 0; + if (bits(val, 63,32)) { msb += 32; val >>= 32; } + if (bits(val, 31,16)) { msb += 16; val >>= 16; } + if (bits(val, 15,8)) { msb += 8; val >>= 8; } + if (bits(val, 7,4)) { msb += 4; val >>= 4; } + if (bits(val, 3,2)) { msb += 2; val >>= 2; } + if (bits(val, 1,1)) { msb += 1; } + return msb; +} + +// The following implements the BitUnion system of defining bitfields +//on top of an underlying class. This is done through the pervasive use of +//both named and unnamed unions which all contain the same actual storage. +//Since they're unioned with each other, all of these storage locations +//overlap. This allows all of the bitfields to manipulate the same data +//without having to have access to each other. More details are provided with the +//individual components. + +//This namespace is for classes which implement the backend of the BitUnion +//stuff. Don't use any of these directly, except for the Bitfield classes in +//the *BitfieldTypes class(es). +namespace BitfieldBackend +{ + //A base class for all bitfields. It instantiates the actual storage, + //and provides getBits and setBits functions for manipulating it. The + //Data template parameter is type of the underlying storage. + template<class Data> + class BitfieldBase + { + protected: + Data __data; + + //This function returns a range of bits from the underlying storage. + //It relies on the "bits" function above. It's the user's + //responsibility to make sure that there is a properly overloaded + //version of this function for whatever type they want to overlay. + inline uint64_t + getBits(int first, int last) const + { + return bits(__data, first, last); + } + + //Similar to the above, but for settings bits with replaceBits. + inline void + setBits(int first, int last, uint64_t val) + { + replaceBits(__data, first, last, val); + } + }; + + //This class contains all the "regular" bitfield classes. It is inherited + //by all BitUnions which give them access to those types. + template<class Type> + class RegularBitfieldTypes + { + protected: + //This class implements ordinary bitfields, that is a span of bits + //who's msb is "first", and who's lsb is "last". + template<int first, int last=first> + class Bitfield : public BitfieldBase<Type> + { + public: + operator uint64_t () const + { + return this->getBits(first, last); + } + + uint64_t + operator=(const uint64_t _data) + { + this->setBits(first, last, _data); + return _data; + } + }; + + //A class which specializes the above so that it can only be read + //from. This is accomplished explicitly making sure the assignment + //operator is blocked. The conversion operator is carried through + //inheritance. This will unfortunately need to be copied into each + //bitfield type due to limitations with how templates work + template<int first, int last=first> + class BitfieldRO : public Bitfield<first, last> + { + private: + uint64_t + operator=(const uint64_t _data); + }; + + //Similar to the above, but only allows writing. + template<int first, int last=first> + class BitfieldWO : public Bitfield<first, last> + { + private: + operator uint64_t () const; + + public: + using Bitfield<first, last>::operator=; + }; + }; + + //This class contains all the "regular" bitfield classes. It is inherited + //by all BitUnions which give them access to those types. + template<class Type> + class SignedBitfieldTypes + { + protected: + //This class implements ordinary bitfields, that is a span of bits + //who's msb is "first", and who's lsb is "last". + template<int first, int last=first> + class SignedBitfield : public BitfieldBase<Type> + { + public: + operator int64_t () const + { + return sext<first - last + 1>(this->getBits(first, last)); + } + + int64_t + operator=(const int64_t _data) + { + this->setBits(first, last, _data); + return _data; + } + }; + + //A class which specializes the above so that it can only be read + //from. This is accomplished explicitly making sure the assignment + //operator is blocked. The conversion operator is carried through + //inheritance. This will unfortunately need to be copied into each + //bitfield type due to limitations with how templates work + template<int first, int last=first> + class SignedBitfieldRO : public SignedBitfield<first, last> + { + private: + int64_t + operator=(const int64_t _data); + }; + + //Similar to the above, but only allows writing. + template<int first, int last=first> + class SignedBitfieldWO : public SignedBitfield<first, last> + { + private: + operator int64_t () const; + + public: + int64_t operator=(const int64_t _data) + { + *((SignedBitfield<first, last> *)this) = _data; + return _data; + } + }; + }; + + template<class Type> + class BitfieldTypes : public RegularBitfieldTypes<Type>, + public SignedBitfieldTypes<Type> + {}; + + //When a BitUnion is set up, an underlying class is created which holds + //the actual union. This class then inherits from it, and provids the + //implementations for various operators. Setting things up this way + //prevents having to redefine these functions in every different BitUnion + //type. More operators could be implemented in the future, as the need + //arises. + template <class Type, class Base> + class BitUnionOperators : public Base + { + public: + operator Type () const + { + return Base::__data; + } + + Type + operator=(const Type & _data) + { + Base::__data = _data; + return _data; + } + + bool + operator<(const Base & base) const + { + return Base::__data < base.__data; + } + + bool + operator==(const Base & base) const + { + return Base::__data == base.__data; + } + }; +} + +//This macro is a backend for other macros that specialize it slightly. +//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and +//sticks the class which has the actual union in it, which +//BitfieldOperators above inherits from. Putting these classes in a special +//namespace ensures that there will be no collisions with other names as long +//as the BitUnion names themselves are all distinct and nothing else uses +//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself +//creates a typedef of the "type" parameter called __DataType. This allows +//the type to propagate outside of the macro itself in a controlled way. +//Finally, the base storage is defined which BitfieldOperators will refer to +//in the operators it defines. This macro is intended to be followed by +//bitfield definitions which will end up inside it's union. As explained +//above, these is overlayed the __data member in its entirety by each of the +//bitfields which are defined in the union, creating shared storage with no +//overhead. +#define __BitUnion(type, name) \ + namespace BitfieldUnderlyingClasses \ + { \ + class name; \ + } \ + class BitfieldUnderlyingClasses::name : \ + public BitfieldBackend::BitfieldTypes<type> \ + { \ + public: \ + typedef type __DataType; \ + union { \ + type __data;\ + +//This closes off the class and union started by the above macro. It is +//followed by a typedef which makes "name" refer to a BitfieldOperator +//class inheriting from the class and union just defined, which completes +//building up the type for the user. +#define EndBitUnion(name) \ + }; \ + }; \ + typedef BitfieldBackend::BitUnionOperators< \ + BitfieldUnderlyingClasses::name::__DataType, \ + BitfieldUnderlyingClasses::name> name; + +//This sets up a bitfield which has other bitfields nested inside of it. The +//__data member functions like the "underlying storage" of the top level +//BitUnion. Like everything else, it overlays with the top level storage, so +//making it a regular bitfield type makes the entire thing function as a +//regular bitfield when referred to by itself. +#define __SubBitUnion(fieldType, first, last, name) \ + class : public BitfieldBackend::BitfieldTypes<__DataType> \ + { \ + public: \ + union { \ + fieldType<first, last> __data; + +//This closes off the union created above and gives it a name. Unlike the top +//level BitUnion, we're interested in creating an object instead of a type. +//The operators are defined in the macro itself instead of a class for +//technical reasons. If someone determines a way to move them to one, please +//do so. +#define EndSubBitUnion(name) \ + }; \ + inline operator const __DataType () \ + { return __data; } \ + \ + inline const __DataType operator = (const __DataType & _data) \ + { __data = _data; } \ + } name; + +//Regular bitfields +//These define macros for read/write regular bitfield based subbitfields. +#define SubBitUnion(name, first, last) \ + __SubBitUnion(Bitfield, first, last, name) + +//Regular bitfields +//These define macros for read/write regular bitfield based subbitfields. +#define SignedSubBitUnion(name, first, last) \ + __SubBitUnion(SignedBitfield, first, last, name) + +//Use this to define an arbitrary type overlayed with bitfields. +#define BitUnion(type, name) __BitUnion(type, name) + +//Use this to define conveniently sized values overlayed with bitfields. +#define BitUnion64(name) __BitUnion(uint64_t, name) +#define BitUnion32(name) __BitUnion(uint32_t, name) +#define BitUnion16(name) __BitUnion(uint16_t, name) +#define BitUnion8(name) __BitUnion(uint8_t, name) + #endif // __BASE_BITFIELD_HH__ diff --git a/src/base/cprintf.cc b/src/base/cprintf.cc index dd8ce858b..d4ba9ca21 100644 --- a/src/base/cprintf.cc +++ b/src/base/cprintf.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2002-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,232 +39,247 @@ using namespace std; namespace cp { -ArgList::~ArgList() +Print::Print(std::ostream &stream, const std::string &format) + : stream(stream), format(format.c_str()), ptr(format.c_str()) +{ + saved_flags = stream.flags(); + saved_fill = stream.fill(); + saved_precision = stream.precision(); +} + +Print::Print(std::ostream &stream, const char *format) + : stream(stream), format(format), ptr(format) +{ + saved_flags = stream.flags(); + saved_fill = stream.fill(); + saved_precision = stream.precision(); +} + +Print::~Print() { - while (!objects.empty()) { - delete objects.front(); - objects.pop_front(); - } } void -ArgList::dump(const string &format) +Print::process(Format &fmt) { - list_t::iterator iter = objects.begin(); - list_t::iterator end = objects.end(); - - const char *p = format.c_str(); - - stream->fill(' '); - stream->flags((ios::fmtflags)0); - - while (*p) { - switch (*p) { - case '%': { - if (p[1] == '%') { - *stream << '%'; - p += 2; - continue; - } - - Format fmt; - bool done = false; - bool end_number = false; - bool have_precision = false; - int number = 0; - - while (!done) { - ++p; - if (*p >= '0' && *p <= '9') { - if (end_number) - continue; - } else if (number > 0) - end_number = true; - - switch (*p) { - case 's': - fmt.format = Format::string; - done = true; - break; - - case 'c': - fmt.format = Format::character; - done = true; - break; - - case 'l': - continue; - - case 'p': - fmt.format = Format::integer; - fmt.base = Format::hex; - fmt.alternate_form = true; - done = true; - break; - - case 'X': - fmt.uppercase = true; - case 'x': - fmt.base = Format::hex; - fmt.format = Format::integer; - done = true; - break; - - case 'o': - fmt.base = Format::oct; - fmt.format = Format::integer; - done = true; - break; - - case 'd': - case 'i': - case 'u': - fmt.format = Format::integer; - done = true; - break; - - case 'G': - fmt.uppercase = true; - case 'g': - fmt.format = Format::floating; - fmt.float_format = Format::best; - done = true; - break; - - case 'E': - fmt.uppercase = true; - case 'e': - fmt.format = Format::floating; - fmt.float_format = Format::scientific; - done = true; - break; - - case 'f': - fmt.format = Format::floating; - fmt.float_format = Format::fixed; - done = true; - break; - - case 'n': - *stream << "we don't do %n!!!\n"; - done = true; - break; - - case '#': - fmt.alternate_form = true; - break; - - case '-': - fmt.flush_left = true; - break; - - case '+': - fmt.print_sign = true; - break; - - case ' ': - fmt.blank_space = true; - break; - - case '.': - fmt.width = number; - fmt.precision = 0; - have_precision = true; - number = 0; - end_number = false; - break; - - case '0': - if (number == 0) { - fmt.fill_zero = true; - break; - } - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - number = number * 10 + (*p - '0'); - break; - - case '%': - assert("we shouldn't get here"); - break; - - default: - done = true; - break; - } - - if (end_number) { - if (have_precision) - fmt.precision = number; - else - fmt.width = number; - - end_number = false; - number = 0; - } - } - - if (iter != end) - { - ios::fmtflags saved_flags = stream->flags(); - char old_fill = stream->fill(); - int old_precision = stream->precision(); - - (*iter)->process(*stream, fmt); - - stream->flags(saved_flags); - stream->fill(old_fill); - stream->precision(old_precision); - - ++iter; - } else { - *stream << "<missing arg for format>"; - } - - ++p; - } + size_t len; + + while (*ptr) { + switch (*ptr) { + case '%': + if (ptr[1] != '%') + goto processing; + + stream.put('%'); + ptr += 2; break; case '\n': - *stream << endl; - ++p; + stream << endl; + ++ptr; break; case '\r': - ++p; - if (*p != '\n') - *stream << endl; + ++ptr; + if (*ptr != '\n') + stream << endl; break; - default: { - size_t len = strcspn(p, "%\n\r\0"); - stream->write(p, len); - p += len; - } + default: + len = strcspn(ptr, "%\n\r\0"); + stream.write(ptr, len); + ptr += len; break; } } - while (iter != end) { - *stream << "<extra arg>"; - ++iter; + return; + + processing: + bool done = false; + bool end_number = false; + bool have_precision = false; + int number = 0; + + stream.fill(' '); + stream.flags((ios::fmtflags)0); + + while (!done) { + ++ptr; + if (*ptr >= '0' && *ptr <= '9') { + if (end_number) + continue; + } else if (number > 0) + end_number = true; + + switch (*ptr) { + case 's': + fmt.format = Format::string; + done = true; + break; + + case 'c': + fmt.format = Format::character; + done = true; + break; + + case 'l': + continue; + + case 'p': + fmt.format = Format::integer; + fmt.base = Format::hex; + fmt.alternate_form = true; + done = true; + break; + + case 'X': + fmt.uppercase = true; + case 'x': + fmt.base = Format::hex; + fmt.format = Format::integer; + done = true; + break; + + case 'o': + fmt.base = Format::oct; + fmt.format = Format::integer; + done = true; + break; + + case 'd': + case 'i': + case 'u': + fmt.format = Format::integer; + done = true; + break; + + case 'G': + fmt.uppercase = true; + case 'g': + fmt.format = Format::floating; + fmt.float_format = Format::best; + done = true; + break; + + case 'E': + fmt.uppercase = true; + case 'e': + fmt.format = Format::floating; + fmt.float_format = Format::scientific; + done = true; + break; + + case 'f': + fmt.format = Format::floating; + fmt.float_format = Format::fixed; + done = true; + break; + + case 'n': + stream << "we don't do %n!!!\n"; + done = true; + break; + + case '#': + fmt.alternate_form = true; + break; + + case '-': + fmt.flush_left = true; + break; + + case '+': + fmt.print_sign = true; + break; + + case ' ': + fmt.blank_space = true; + break; + + case '.': + fmt.width = number; + fmt.precision = 0; + have_precision = true; + number = 0; + end_number = false; + break; + + case '0': + if (number == 0) { + fmt.fill_zero = true; + break; + } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + number = number * 10 + (*ptr - '0'); + break; + + case '%': + assert("we shouldn't get here"); + break; + + default: + done = true; + break; + } + + if (end_number) { + if (have_precision) + fmt.precision = number; + else + fmt.width = number; + + end_number = false; + number = 0; + } } + + ++ptr; } -string -ArgList::dumpToString(const string &format) +void +Print::end_args() { - stringstream ss; + size_t len; - dump(ss, format); + while (*ptr) { + switch (*ptr) { + case '%': + if (ptr[1] != '%') + stream << "<extra arg>"; - return ss.str(); -} + stream.put('%'); + ptr += 2; + break; + case '\n': + stream << endl; + ++ptr; + break; + case '\r': + ++ptr; + if (*ptr != '\n') + stream << endl; + break; + + default: + len = strcspn(ptr, "%\n\r\0"); + stream.write(ptr, len); + ptr += len; + break; + } + } + + stream.flags(saved_flags); + stream.fill(saved_fill); + stream.precision(saved_precision); } + +/* end namespace cp */ } diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh index dd2256e69..cff73a228 100644 --- a/src/base/cprintf.hh +++ b/src/base/cprintf.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2002-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,142 +29,135 @@ * Steve Reinhardt */ -#ifndef __CPRINTF_HH__ -#define __CPRINTF_HH__ +#ifndef __BASE_CPRINTF_HH__ +#define __BASE_CPRINTF_HH__ +#include <ios> #include <iostream> #include <list> #include <string> +#include "base/varargs.hh" #include "base/cprintf_formats.hh" namespace cp { -class ArgList +#define CPRINTF_DECLARATION VARARGS_DECLARATION(cp::Print) +#define CPRINTF_DEFINITION VARARGS_DEFINITION(cp::Print) + +struct Print { - private: - class Base - { - public: - virtual ~Base() {} - virtual void process(std::ostream &out, Format &fmt) = 0; - }; + protected: + std::ostream &stream; + const char *format; + const char *ptr; + + std::ios::fmtflags saved_flags; + char saved_fill; + int saved_precision; + + void process(Format &fmt); + + public: + Print(std::ostream &stream, const std::string &format); + Print(std::ostream &stream, const char *format); + ~Print(); template <typename T> - class Node : public Base + void + add_arg(const T &data) { - public: - const T &data; - - public: - Node(const T &d) : data(d) {} - virtual void process(std::ostream &out, Format &fmt) { - switch (fmt.format) { - case Format::character: - format_char(out, data, fmt); - break; - - case Format::integer: - format_integer(out, data, fmt); - break; - - case Format::floating: - format_float(out, data, fmt); - break; - - case Format::string: - format_string(out, data, fmt); - break; - - default: - out << "<bad format>"; - break; - } - } - }; + Format fmt; + process(fmt); - typedef std::list<Base *> list_t; + switch (fmt.format) { + case Format::character: + format_char(stream, data, fmt); + break; - protected: - list_t objects; - std::ostream *stream; + case Format::integer: + format_integer(stream, data, fmt); + break; - public: - ArgList() : stream(&std::cout) {} - ~ArgList(); + case Format::floating: + format_float(stream, data, fmt); + break; - template<class T> - void append(const T &data) { - Base *obj = new ArgList::Node<T>(data); - objects.push_back(obj); - } + case Format::string: + format_string(stream, data, fmt); + break; - template<class T> - void prepend(const T &data) { - Base *obj = new ArgList::Node<T>(data); - objects.push_front(obj); + default: + stream << "<bad format>"; + break; + } } - void dump(const std::string &format); - void dump(std::ostream &strm, const std::string &fmt) - { stream = &strm; dump(fmt); } + void end_args(); +}; - std::string dumpToString(const std::string &format); +/* end namespace cp */ } - friend ArgList &operator<<(std::ostream &str, ArgList &list); -}; +typedef VarArgs::List<cp::Print> CPrintfArgsList; + +inline void +ccprintf(std::ostream &stream, const char *format, const CPrintfArgsList &args) +{ + cp::Print print(stream, format); + args.add_args(print); +} -template<class T> -inline ArgList & -operator,(ArgList &alist, const T &data) +inline void +ccprintf(std::ostream &stream, const char *format, CPRINTF_DECLARATION) { - alist.append(data); - return alist; + cp::Print print(stream, format); + VARARGS_ADDARGS(print); } -class ArgListNull { -}; +inline void +cprintf(const char *format, CPRINTF_DECLARATION) +{ + ccprintf(std::cout, format, VARARGS_ALLARGS); +} + +inline std::string +csprintf(const char *format, CPRINTF_DECLARATION) +{ + std::stringstream stream; + ccprintf(stream, format, VARARGS_ALLARGS); + return stream.str(); +} -inline ArgList & -operator,(ArgList &alist, ArgListNull) -{ return alist; } +/* + * functions again with std::string. We have both so we don't waste + * time converting const char * to std::string since we don't take + * advantage of it. + */ +inline void +ccprintf(std::ostream &stream, const std::string &format, + const CPrintfArgsList &args) +{ + ccprintf(stream, format.c_str(), args); +} -// -// cprintf(format, args, ...) prints to cout -// (analogous to printf()) -// inline void -__cprintf(const std::string &format, ArgList &args) -{ args.dump(format); delete &args; } -#define __cprintf__(format, ...) \ - cp::__cprintf(format, (*(new cp::ArgList), __VA_ARGS__)) -#define cprintf(...) \ - __cprintf__(__VA_ARGS__, cp::ArgListNull()) - -// -// ccprintf(stream, format, args, ...) prints to the specified stream -// (analogous to fprintf()) -// +ccprintf(std::ostream &stream, const std::string &format, CPRINTF_DECLARATION) +{ + ccprintf(stream, format.c_str(), VARARGS_ALLARGS); +} + inline void -__ccprintf(std::ostream &stream, const std::string &format, ArgList &args) -{ args.dump(stream, format); delete &args; } -#define __ccprintf__(stream, format, ...) \ - cp::__ccprintf(stream, format, (*(new cp::ArgList), __VA_ARGS__)) -#define ccprintf(stream, ...) \ - __ccprintf__(stream, __VA_ARGS__, cp::ArgListNull()) - -// -// csprintf(format, args, ...) returns a string -// (roughly analogous to sprintf()) -// -inline std::string -__csprintf(const std::string &format, ArgList &args) -{ std::string s = args.dumpToString(format); delete &args; return s; } -#define __csprintf__(format, ...) \ - cp::__csprintf(format, (*(new cp::ArgList), __VA_ARGS__)) -#define csprintf(...) \ - __csprintf__(__VA_ARGS__, cp::ArgListNull()) +cprintf(const std::string &format, CPRINTF_DECLARATION) +{ + ccprintf(std::cout, format.c_str(), VARARGS_ALLARGS); +} +inline std::string +csprintf(const std::string &format, CPRINTF_DECLARATION) +{ + std::stringstream stream; + ccprintf(stream, format.c_str(), VARARGS_ALLARGS); + return stream.str(); } #endif // __CPRINTF_HH__ diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh index 0af493217..4e8b2b09e 100644 --- a/src/base/cprintf_formats.hh +++ b/src/base/cprintf_formats.hh @@ -28,8 +28,8 @@ * Authors: Nathan Binkert */ -#ifndef __CPRINTF_FORMATS_HH__ -#define __CPRINTF_FORMATS_HH__ +#ifndef __BASE_CPRINTF_FORMATS_HH__ +#define __BASE_CPRINTF_FORMATS_HH__ #include <sstream> #include <ostream> diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index d59affe85..8f157da28 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -78,12 +78,23 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) //just assume if it wasn't something else and it's 64 bit, that's //what it must be. if (ehdr.e_machine == EM_SPARC64 || - ehdr.e_machine == EM_SPARC || + (ehdr.e_machine == EM_SPARC && + ehdr.e_ident[EI_CLASS] == ELFCLASS64)|| ehdr.e_machine == EM_SPARCV9) { - arch = ObjectFile::SPARC; + arch = ObjectFile::SPARC64; + } else if (ehdr.e_machine == EM_SPARC32PLUS || + (ehdr.e_machine == EM_SPARC && + ehdr.e_ident[EI_CLASS] == ELFCLASS32)) { + arch = ObjectFile::SPARC32; } else if (ehdr.e_machine == EM_MIPS && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { arch = ObjectFile::Mips; + } else if (ehdr.e_machine == EM_X86_64 && + ehdr.e_ident[EI_CLASS] == ELFCLASS64) { + //In the future, we might want to differentiate between 32 bit + //and 64 bit x86 processes in case there are differences in their + //initial stack frame. + arch = ObjectFile::X86; } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { arch = ObjectFile::Alpha; } else { diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh index 18e6482be..4b44a6e22 100644 --- a/src/base/loader/object_file.hh +++ b/src/base/loader/object_file.hh @@ -47,8 +47,10 @@ class ObjectFile enum Arch { UnknownArch, Alpha, - SPARC, - Mips + SPARC64, + SPARC32, + Mips, + X86 }; enum OpSys { diff --git a/src/base/misc.cc b/src/base/misc.cc index 991a33736..afb48ca80 100644 --- a/src/base/misc.cc +++ b/src/base/misc.cc @@ -36,91 +36,99 @@ #include "base/misc.hh" #include "base/output.hh" #include "base/trace.hh" +#include "base/varargs.hh" #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; void -__panic(const string &format, cp::ArgList &args, const char *func, - const char *file, int line) +__panic(const char *func, const char *file, int line, const char *fmt, + CPRINTF_DEFINITION) { - string fmt = "panic: " + format; - switch (fmt[fmt.size() - 1]) { + string format = "panic: "; + format += fmt; + switch (format[format.size() - 1]) { case '\n': case '\r': break; default: - fmt += "\n"; + format += "\n"; } - fmt += " @ cycle %d\n[%s:%s, line %d]\n"; + format += " @ cycle %d\n[%s:%s, line %d]\n"; - args.append(curTick); - args.append(func); - args.append(file); - args.append(line); - args.dump(cerr, fmt); + CPrintfArgsList args(VARARGS_ALLARGS); - delete &args; + args.push_back(curTick); + args.push_back(func); + args.push_back(file); + args.push_back(line); + + ccprintf(cerr, format.c_str(), args); abort(); } void -__fatal(const string &format, cp::ArgList &args, const char *func, - const char *file, int line) +__fatal(const char *func, const char *file, int line, const char *fmt, + CPRINTF_DEFINITION) { - string fmt = "fatal: " + format; + CPrintfArgsList args(VARARGS_ALLARGS); + string format = "fatal: "; + format += fmt; - switch (fmt[fmt.size() - 1]) { + switch (format[format.size() - 1]) { case '\n': case '\r': break; default: - fmt += "\n"; + format += "\n"; } - fmt += " @ cycle %d\n[%s:%s, line %d]\n"; - fmt += "Memory Usage: %ld KBytes\n"; + format += " @ cycle %d\n[%s:%s, line %d]\n"; + format += "Memory Usage: %ld KBytes\n"; - args.append(curTick); - args.append(func); - args.append(file); - args.append(line); - args.append(memUsage()); - args.dump(cerr, fmt); + args.push_back(curTick); + args.push_back(func); + args.push_back(file); + args.push_back(line); + args.push_back(memUsage()); - delete &args; + ccprintf(cerr, format.c_str(), args); exit(1); } void -__warn(const string &format, cp::ArgList &args, const char *func, - const char *file, int line) +__warn(const char *func, const char *file, int line, const char *fmt, + CPRINTF_DEFINITION) { - string fmt = "warn: " + format; + string format = "warn: "; + format += fmt; - switch (fmt[fmt.size() - 1]) { + switch (format[format.size() - 1]) { case '\n': case '\r': break; default: - fmt += "\n"; + format += "\n"; } #ifdef VERBOSE_WARN - fmt += " @ cycle %d\n[%s:%s, line %d]\n"; - args.append(curTick); - args.append(func); - args.append(file); - args.append(line); + format += " @ cycle %d\n[%s:%s, line %d]\n"; #endif - args.dump(cerr, fmt); - if (simout.isFile(*outputStream)) - args.dump(*outputStream, fmt); + CPrintfArgsList args(VARARGS_ALLARGS); + +#ifdef VERBOSE_WARN + args.push_back(curTick); + args.push_back(func); + args.push_back(file); + args.push_back(line); +#endif - delete &args; + ccprintf(cerr, format.c_str(), args); + if (simout.isFile(*outputStream)) + ccprintf(*outputStream, format.c_str(), args); } diff --git a/src/base/misc.hh b/src/base/misc.hh index c12c2fe20..1509ea2d2 100644 --- a/src/base/misc.hh +++ b/src/base/misc.hh @@ -32,9 +32,11 @@ #ifndef __MISC_HH__ #define __MISC_HH__ -#include <assert.h> +#include <cassert> + #include "base/compiler.hh" #include "base/cprintf.hh" +#include "base/varargs.hh" #if defined(__SUNPRO_CC) #define __FUNCTION__ "how to fix me?" @@ -47,14 +49,20 @@ // calls abort which can dump core or enter the debugger. // // -void __panic(const std::string&, cp::ArgList &, const char*, const char*, int) - M5_ATTR_NORETURN; -#define __panic__(format, ...) \ - __panic(format, (*(new cp::ArgList), __VA_ARGS__), \ - __FUNCTION__ , __FILE__, __LINE__) -#define panic(...) \ - __panic__(__VA_ARGS__, cp::ArgListNull()) +void __panic(const char *func, const char *file, int line, const char *format, + CPRINTF_DECLARATION) M5_ATTR_NORETURN; +void __panic(const char *func, const char *file, int line, + const std::string &format, CPRINTF_DECLARATION) +M5_ATTR_NORETURN; + +inline void +__panic(const char *func, const char *file, int line, + const std::string &format, CPRINTF_DEFINITION) +{ + __panic(func, file, line, format.c_str(), VARARGS_ALLARGS); +} M5_PRAGMA_NORETURN(__panic) +#define panic(...) __panic(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) // // This implements a cprintf based fatal() function. fatal() should @@ -64,34 +72,43 @@ M5_PRAGMA_NORETURN(__panic) // "normal" exit with an error code, as opposed to abort() like // panic() does. // -void __fatal(const std::string&, cp::ArgList &, const char*, const char*, int) +void __fatal(const char *func, const char *file, int line, const char *format, + CPRINTF_DECLARATION) M5_ATTR_NORETURN; +void __fatal(const char *func, const char *file, int line, + const std::string &format, CPRINTF_DECLARATION) M5_ATTR_NORETURN; -#define __fatal__(format, ...) \ - __fatal(format, (*(new cp::ArgList), __VA_ARGS__), \ - __FUNCTION__ , __FILE__, __LINE__) -#define fatal(...) \ - __fatal__(__VA_ARGS__, cp::ArgListNull()) + +inline void +__fatal(const char *func, const char *file, int line, + const std::string &format, CPRINTF_DEFINITION) +{ + __fatal(func, file, line, format.c_str(), VARARGS_ALLARGS); +} M5_PRAGMA_NORETURN(__fatal) +#define fatal(...) __fatal(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) // // This implements a cprintf based warn // -void __warn(const std::string&, cp::ArgList &, const char*, const char*, int); -#define __warn__(format, ...) \ - __warn(format, (*(new cp::ArgList), __VA_ARGS__), \ - __FUNCTION__ , __FILE__, __LINE__) -#define warn(...) \ - __warn__(__VA_ARGS__, cp::ArgListNull()) +void __warn(const char *func, const char *file, int line, const char *format, + CPRINTF_DECLARATION); +inline void +__warn(const char *func, const char *file, int line, const std::string &format, + CPRINTF_DECLARATION) +{ + __warn(func, file, line, format, VARARGS_ALLARGS); +} +#define warn(...) __warn(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) // Only print the warning message the first time it is seen. This // doesn't check the warning string itself, it just only lets one // warning come from the statement. So, even if the arguments change // and that would have resulted in a different warning message, // subsequent messages would still be supressed. -#define warn_once(...) do { \ +#define warn_once(...) do { \ static bool once = false; \ if (!once) { \ - __warn__(__VA_ARGS__, cp::ArgListNull()); \ + warn(__VA_ARGS__); \ once = true; \ } \ } while (0) @@ -99,10 +116,10 @@ void __warn(const std::string&, cp::ArgList &, const char*, const char*, int); // // assert() that prints out the current cycle // -#define m5_assert(TEST) \ - if (!(TEST)) { \ - std::cerr << "Assertion failure, curTick = " << curTick << std::endl; \ - } \ - assert(TEST); +#define m5_assert(TEST) do { \ + if (!(TEST)) \ + ccprintf(std::cerr, "Assertion failure, curTick = %d\n", curTick); \ + assert(TEST); \ +} while (0) #endif // __MISC_HH__ diff --git a/src/base/pollevent.cc b/src/base/pollevent.cc index 32724b74d..331b5eac6 100644 --- a/src/base/pollevent.cc +++ b/src/base/pollevent.cc @@ -42,7 +42,7 @@ #include "sim/host.hh" #include "base/misc.hh" #include "base/pollevent.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/serialize.hh" using namespace std; diff --git a/src/base/pollevent.hh b/src/base/pollevent.hh index 5b84650cb..ecaeb94ce 100644 --- a/src/base/pollevent.hh +++ b/src/base/pollevent.hh @@ -33,7 +33,7 @@ #include <vector> #include <poll.h> -#include "sim/root.hh" +#include "sim/core.hh" class Checkpoint; class PollQueue; diff --git a/src/base/random.cc b/src/base/random.cc index 0ccedcb00..ceab337d9 100644 --- a/src/base/random.cc +++ b/src/base/random.cc @@ -40,38 +40,20 @@ #include <cstdlib> #include <cmath> - -#include "sim/param.hh" #include "base/random.hh" -#include "base/trace.hh" using namespace std; -class RandomContext : public ParamContext -{ - public: - RandomContext(const string &_iniSection) - : ::ParamContext(_iniSection) {} - ~RandomContext() {} - - void checkParams(); -}; - -RandomContext paramContext("random"); - -Param<unsigned> -seed(¶mContext, "seed", "seed to random number generator", 1); - -void -RandomContext::checkParams() +uint32_t +getInt32() { - ::srand48(seed); + return mrand48() & 0xffffffff; } -long -getLong() +double +getDouble() { - return mrand48(); + return drand48(); } double @@ -105,21 +87,3 @@ getUniformPos(uint64_t min, uint64_t max) return (uint64_t)m5round(r); } - - -// idea for generating a double from erand48 -double -getDouble() -{ - union { - uint32_t _long[2]; - uint16_t _short[4]; - }; - - _long[0] = mrand48(); - _long[1] = mrand48(); - - return ldexp((double) _short[0], -48) + - ldexp((double) _short[1], -32) + - ldexp((double) _short[2], -16); -} diff --git a/src/base/random.hh b/src/base/random.hh index 40d62da7f..0cd88728d 100644 --- a/src/base/random.hh +++ b/src/base/random.hh @@ -34,7 +34,7 @@ #include "sim/host.hh" -long getLong(); +uint32_t getUInt32(); double getDouble(); double m5random(double r); uint64_t getUniformPos(uint64_t min, uint64_t max); @@ -46,7 +46,7 @@ struct Random; template<> struct Random<int8_t> { static int8_t get() - { return getLong() & (int8_t)-1; } + { return getUInt32() & (int8_t)-1; } static int8_t uniform(int8_t min, int8_t max) { return getUniform(min, max); } @@ -55,7 +55,7 @@ template<> struct Random<int8_t> template<> struct Random<uint8_t> { static uint8_t get() - { return getLong() & (uint8_t)-1; } + { return getUInt32() & (uint8_t)-1; } static uint8_t uniform(uint8_t min, uint8_t max) { return getUniformPos(min, max); } @@ -64,7 +64,7 @@ template<> struct Random<uint8_t> template<> struct Random<int16_t> { static int16_t get() - { return getLong() & (int16_t)-1; } + { return getUInt32() & (int16_t)-1; } static int16_t uniform(int16_t min, int16_t max) { return getUniform(min, max); } @@ -73,7 +73,7 @@ template<> struct Random<int16_t> template<> struct Random<uint16_t> { static uint16_t get() - { return getLong() & (uint16_t)-1; } + { return getUInt32() & (uint16_t)-1; } static uint16_t uniform(uint16_t min, uint16_t max) { return getUniformPos(min, max); } @@ -82,7 +82,7 @@ template<> struct Random<uint16_t> template<> struct Random<int32_t> { static int32_t get() - { return (int32_t)getLong(); } + { return (int32_t)getUInt32(); } static int32_t uniform(int32_t min, int32_t max) { return getUniform(min, max); } @@ -91,7 +91,7 @@ template<> struct Random<int32_t> template<> struct Random<uint32_t> { static uint32_t get() - { return (uint32_t)getLong(); } + { return (uint32_t)getUInt32(); } static uint32_t uniform(uint32_t min, uint32_t max) { return getUniformPos(min, max); } @@ -100,7 +100,7 @@ template<> struct Random<uint32_t> template<> struct Random<int64_t> { static int64_t get() - { return (int64_t)getLong() << 32 || (uint64_t)getLong(); } + { return (int64_t)getUInt32() << 32 || (uint64_t)getUInt32(); } static int64_t uniform(int64_t min, int64_t max) { return getUniform(min, max); } @@ -109,7 +109,7 @@ template<> struct Random<int64_t> template<> struct Random<uint64_t> { static uint64_t get() - { return (uint64_t)getLong() << 32 || (uint64_t)getLong(); } + { return (uint64_t)getUInt32() << 32 || (uint64_t)getUInt32(); } static uint64_t uniform(uint64_t min, uint64_t max) { return getUniformPos(min, max); } diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 2b1b327e5..761b30c2b 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -70,7 +70,7 @@ class Callback; -/** The current simulated cycle. */ +/** The current simulated tick. */ extern Tick curTick; /* A namespace for all of the Statistics */ @@ -598,9 +598,9 @@ struct StatStor }; /** - * Templatized storage and interface to a per-cycle average stat. This keeps - * a current count and updates a total (count * cycles) when this count - * changes. This allows the quick calculation of a per cycle count of the item + * Templatized storage and interface to a per-tick average stat. This keeps + * a current count and updates a total (count * ticks) when this count + * changes. This allows the quick calculation of a per tick count of the item * being watched. This is good for keeping track of residencies in structures * among other things. */ @@ -613,9 +613,9 @@ struct AvgStor private: /** The current count. */ Counter current; - /** The total count for all cycles. */ + /** The total count for all tick. */ mutable Result total; - /** The cycle that current last changed. */ + /** The tick that current last changed. */ mutable Tick last; public: @@ -1563,7 +1563,7 @@ struct FancyStor }; /** - * Templatized storage for distribution that calculates per cycle mean and + * Templatized storage for distribution that calculates per tick mean and * variance. */ struct AvgFancy @@ -2280,7 +2280,7 @@ class Value : public Wrap<Value, ValueBase, ScalarStatData> }; /** - * A stat that calculates the per cycle average of a value. + * A stat that calculates the per tick average of a value. * @sa Stat, ScalarBase, AvgStor */ template<int N = 0> @@ -2417,7 +2417,7 @@ class StandardDeviation }; /** - * Calculates the per cycle mean and variance of the samples. + * Calculates the per tick mean and variance of the samples. * @sa Stat, DistBase, AvgFancy */ template<int N = 0> @@ -2839,6 +2839,7 @@ class Temp */ void check(); +void dump(); void reset(); void registerResetCallback(Callback *cb); diff --git a/src/base/stats/events.cc b/src/base/stats/events.cc index 6ecc5434c..dc56fe75f 100644 --- a/src/base/stats/events.cc +++ b/src/base/stats/events.cc @@ -31,20 +31,8 @@ #include <vector> #include "base/stats/events.hh" - -#if USE_MYSQL -#include "base/cprintf.hh" -#include "base/misc.hh" -#include "base/mysql.hh" -#include "base/stats/mysql.hh" -#include "base/stats/mysql_run.hh" -#include "base/str.hh" -#endif - -#include "base/match.hh" +#include "base/stats/output.hh" #include "sim/host.hh" -#include "sim/sim_object.hh" -#include "sim/root.hh" using namespace std; @@ -52,118 +40,21 @@ namespace Stats { Tick EventStart = ULL(0x7fffffffffffffff); -ObjectMatch event_ignore; +extern list<Output *> OutputList; #if USE_MYSQL -class InsertEvent -{ - private: - char *query; - int size; - bool first; - static const int maxsize = 1024*1024; - - typedef map<string, uint32_t> event_map_t; - event_map_t events; - - MySQL::Connection &mysql; - uint16_t run; - - public: - InsertEvent() - : mysql(MySqlDB.conn()), run(MySqlDB.run()) - { - query = new char[maxsize + 1]; - size = 0; - first = true; - flush(); - } - ~InsertEvent() - { - flush(); - } - - void flush(); - void insert(const string &stat); -}; - void -InsertEvent::insert(const string &stat) +__event(const string &event) { - assert(mysql.connected()); - - event_map_t::iterator i = events.find(stat); - uint32_t event; - if (i == events.end()) { - mysql.query( - csprintf("SELECT en_id " - "from event_names " - "where en_name=\"%s\"", - stat)); - - MySQL::Result result = mysql.store_result(); - if (!result) - panic("could not get a run\n%s\n", mysql.error); - - assert(result.num_fields() == 1); - MySQL::Row row = result.fetch_row(); - if (row) { - if (!to_number(row[0], event)) - panic("invalid event id: %s\n", row[0]); - } else { - mysql.query( - csprintf("INSERT INTO " - "event_names(en_name)" - "values(\"%s\")", - stat)); - - if (mysql.error) - panic("could not get a run\n%s\n", mysql.error); - - event = mysql.insert_id(); - } - } else { - event = (*i).second; + list<Output *>::iterator i = OutputList.begin(); + list<Output *>::iterator end = OutputList.end(); + for (; i != end; ++i) { + Output *output = *i; + if (!output->valid()) + continue; + + output->event(event); } - - if (size + 1024 > maxsize) - flush(); - - if (!first) { - query[size++] = ','; - query[size] = '\0'; - } - - first = false; - - size += sprintf(query + size, "(%u,%u,%llu)", - event, run, (unsigned long long)curTick); -} - -void -InsertEvent::flush() -{ - static const char query_header[] = "INSERT INTO " - "events(ev_event, ev_run, ev_tick)" - "values"; - - if (size) { - MySQL::Connection &mysql = MySqlDB.conn(); - assert(mysql.connected()); - mysql.query(query); - } - - query[0] = '\0'; - size = sizeof(query_header); - first = true; - memcpy(query, query_header, size); -} - -void -__event(const string &stat) -{ - static InsertEvent event; - event.insert(stat); } #endif diff --git a/src/base/stats/events.hh b/src/base/stats/events.hh index b09b91c7c..8ba9cece5 100644 --- a/src/base/stats/events.hh +++ b/src/base/stats/events.hh @@ -42,11 +42,10 @@ extern Tick EventStart; #if USE_MYSQL void __event(const std::string &stat); -bool MySqlConnected(); +#else +inline void __event(const std::string &stat) {} #endif -bool ignoreEvent(const std::string &name); - inline void recordEvent(const std::string &stat) { @@ -55,12 +54,7 @@ recordEvent(const std::string &stat) DPRINTF(StatEvents, "Statistics Event: %s\n", stat); -#if USE_MYSQL - if (!MySqlConnected()) - return; - __event(stat); -#endif } /* namespace Stats */ } diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index 0fb31f4ce..39a687fff 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -43,20 +43,13 @@ #include "base/stats/statdb.hh" #include "base/stats/types.hh" #include "base/str.hh" +#include "base/userinfo.hh" #include "sim/host.hh" using namespace std; namespace Stats { -MySqlRun MySqlDB; - -bool -MySqlConnected() -{ - return MySqlDB.connected(); -} - void MySqlRun::connect(const string &host, const string &user, const string &passwd, const string &db, const string &name, const string &sample, @@ -196,9 +189,9 @@ SetupStat::init() } unsigned -SetupStat::setup() +SetupStat::setup(MySqlRun *run) { - MySQL::Connection &mysql = MySqlDB.conn(); + MySQL::Connection &mysql = run->conn(); stringstream insert; ccprintf(insert, @@ -301,7 +294,8 @@ SetupStat::setup() return statid; } -InsertData::InsertData() +InsertData::InsertData(MySqlRun *_run) + : run(_run) { query = new char[maxsize + 1]; size = 0; @@ -317,7 +311,7 @@ void InsertData::flush() { if (size) { - MySQL::Connection &mysql = MySqlDB.conn(); + MySQL::Connection &mysql = run->conn(); assert(mysql.connected()); mysql.query(query); if (mysql.error) @@ -349,10 +343,97 @@ InsertData::insert() first = false; size += sprintf(query + size, "(%u,%d,%d,%u,%llu,\"%f\")", - stat, x, y, MySqlDB.run(), (unsigned long long)tick, + stat, x, y, run->run(), (unsigned long long)tick, data); } +InsertEvent::InsertEvent(MySqlRun *_run) + : run(_run) +{ + query = new char[maxsize + 1]; + size = 0; + first = true; + flush(); +} + +InsertEvent::~InsertEvent() +{ + flush(); +} + +void +InsertEvent::insert(const string &stat) +{ + MySQL::Connection &mysql = run->conn(); + assert(mysql.connected()); + + event_map_t::iterator i = events.find(stat); + uint32_t event; + if (i == events.end()) { + mysql.query( + csprintf("SELECT en_id " + "from event_names " + "where en_name=\"%s\"", + stat)); + + MySQL::Result result = mysql.store_result(); + if (!result) + panic("could not get a run\n%s\n", mysql.error); + + assert(result.num_fields() == 1); + MySQL::Row row = result.fetch_row(); + if (row) { + if (!to_number(row[0], event)) + panic("invalid event id: %s\n", row[0]); + } else { + mysql.query( + csprintf("INSERT INTO " + "event_names(en_name)" + "values(\"%s\")", + stat)); + + if (mysql.error) + panic("could not get a run\n%s\n", mysql.error); + + event = mysql.insert_id(); + } + } else { + event = (*i).second; + } + + if (size + 1024 > maxsize) + flush(); + + if (!first) { + query[size++] = ','; + query[size] = '\0'; + } + + first = false; + + size += sprintf(query + size, "(%u,%u,%llu)", + event, run->run(), (unsigned long long)curTick); +} + +void +InsertEvent::flush() +{ + static const char query_header[] = "INSERT INTO " + "events(ev_event, ev_run, ev_tick)" + "values"; + + MySQL::Connection &mysql = run->conn(); + assert(mysql.connected()); + + if (size) + mysql.query(query); + + query[0] = '\0'; + size = sizeof(query_header); + first = true; + memcpy(query, query_header, size); +} + struct InsertSubData { uint16_t stat; @@ -361,13 +442,13 @@ struct InsertSubData string name; string descr; - void setup(); + void setup(MySqlRun *run); }; void -InsertSubData::setup() +InsertSubData::setup(MySqlRun *run) { - MySQL::Connection &mysql = MySqlDB.conn(); + MySQL::Connection &mysql = run->conn(); assert(mysql.connected()); stringstream insert; ccprintf(insert, @@ -383,47 +464,27 @@ InsertSubData::setup() panic("could not commit transaction\n%s\n", mysql.error); } -void -InsertFormula(uint16_t stat, const string &formula) -{ - MySQL::Connection &mysql = MySqlDB.conn(); - assert(mysql.connected()); - stringstream insert_formula; - ccprintf(insert_formula, - "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")", - stat, formula); +MySql::MySql() + : run(new MySqlRun), newdata(run), newevent(run) +{} - mysql.query(insert_formula); -// if (mysql.error) -// panic("could not insert formula\n%s\n", mysql.error); - - stringstream insert_ref; - ccprintf(insert_ref, - "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)", - stat, MySqlDB.run()); - - mysql.query(insert_ref); -// if (mysql.error) -// panic("could not insert formula reference\n%s\n", mysql.error); - - if (mysql.commit()) - panic("could not commit transaction\n%s\n", mysql.error); +MySql::~MySql() +{ + delete run; } void -UpdatePrereq(uint16_t stat, uint16_t prereq) +MySql::connect(const string &host, const string &user, const string &passwd, + const string &db, const string &name, const string &sample, + const string &project) { - MySQL::Connection &mysql = MySqlDB.conn(); - assert(mysql.connected()); - stringstream update; - ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d", - prereq, stat); - mysql.query(update); - if (mysql.error) - panic("could not update prereq\n%s\n", mysql.error); + run->connect(host, user, passwd, db, name, sample, project); +} - if (mysql.commit()) - panic("could not commit transaction\n%s\n", mysql.error); +bool +MySql::connected() const +{ + return run->connected(); } void @@ -434,7 +495,7 @@ MySql::configure() */ using namespace Database; - MySQL::Connection &mysql = MySqlDB.conn(); + MySQL::Connection &mysql = run->conn(); stat_list_t::const_iterator i, end = stats().end(); for (i = stats().begin(); i != end; ++i) { @@ -444,11 +505,20 @@ MySql::configure() for (i = stats().begin(); i != end; ++i) { StatData *data = *i; if (data->prereq) { + // update the prerequisite uint16_t stat_id = find(data->id); uint16_t prereq_id = find(data->prereq->id); assert(stat_id && prereq_id); - UpdatePrereq(stat_id, prereq_id); + stringstream update; + ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d", + prereq_id, stat_id); + mysql.query(update); + if (mysql.error) + panic("could not update prereq\n%s\n", mysql.error); + + if (mysql.commit()) + panic("could not commit transaction\n%s\n", mysql.error); } } @@ -483,7 +553,7 @@ MySql::configure(const ScalarData &data) if (!configure(data, "SCALAR")) return; - insert(data.id, stat.setup()); + insert(data.id, stat.setup(run)); } void @@ -492,7 +562,7 @@ MySql::configure(const VectorData &data) if (!configure(data, "VECTOR")) return; - uint16_t statid = stat.setup(); + uint16_t statid = stat.setup(run); if (!data.subnames.empty()) { InsertSubData subdata; @@ -504,7 +574,7 @@ MySql::configure(const VectorData &data) subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i]; if (!subdata.name.empty() || !subdata.descr.empty()) - subdata.setup(); + subdata.setup(run); } } @@ -523,7 +593,7 @@ MySql::configure(const DistData &data) stat.max = data.data.max; stat.bktsize = data.data.bucket_size; } - insert(data.id, stat.setup()); + insert(data.id, stat.setup(run)); } void @@ -539,7 +609,7 @@ MySql::configure(const VectorDistData &data) stat.bktsize = data.data[0].bucket_size; } - uint16_t statid = stat.setup(); + uint16_t statid = stat.setup(run); if (!data.subnames.empty()) { InsertSubData subdata; @@ -550,7 +620,7 @@ MySql::configure(const VectorDistData &data) subdata.name = data.subnames[i]; subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i]; if (!subdata.name.empty() || !subdata.descr.empty()) - subdata.setup(); + subdata.setup(run); } } @@ -563,7 +633,7 @@ MySql::configure(const Vector2dData &data) if (!configure(data, "VECTOR2D")) return; - uint16_t statid = stat.setup(); + uint16_t statid = stat.setup(run); if (!data.subnames.empty()) { InsertSubData subdata; @@ -574,7 +644,7 @@ MySql::configure(const Vector2dData &data) subdata.name = data.subnames[i]; subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i]; if (!subdata.name.empty() || !subdata.descr.empty()) - subdata.setup(); + subdata.setup(run); } } @@ -587,7 +657,7 @@ MySql::configure(const Vector2dData &data) subdata.y = i; subdata.name = data.y_subnames[i]; if (!subdata.name.empty()) - subdata.setup(); + subdata.setup(run); } } @@ -597,15 +667,41 @@ MySql::configure(const Vector2dData &data) void MySql::configure(const FormulaData &data) { + MySQL::Connection &mysql = run->conn(); + assert(mysql.connected()); + configure(data, "FORMULA"); - insert(data.id, stat.setup()); - InsertFormula(find(data.id), data.str()); + insert(data.id, stat.setup(run)); + + uint16_t stat = find(data.id); + string formula = data.str(); + + stringstream insert_formula; + ccprintf(insert_formula, + "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")", + stat, formula); + + mysql.query(insert_formula); +// if (mysql.error) +// panic("could not insert formula\n%s\n", mysql.error); + + stringstream insert_ref; + ccprintf(insert_ref, + "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)", + stat, run->run()); + + mysql.query(insert_ref); +// if (mysql.error) +// panic("could not insert formula reference\n%s\n", mysql.error); + + if (mysql.commit()) + panic("could not commit transaction\n%s\n", mysql.error); } bool MySql::valid() const { - return MySqlDB.connected(); + return run->connected(); } void @@ -620,7 +716,7 @@ MySql::output() // store sample # newdata.tick = curTick; - MySQL::Connection &mysql = MySqlDB.conn(); + MySQL::Connection &mysql = run->conn(); Database::stat_list_t::const_iterator i, end = Database::stats().end(); for (i = Database::stats().begin(); i != end; ++i) { @@ -634,6 +730,13 @@ MySql::output() } void +MySql::event(const std::string &event) +{ + newevent.insert(event); +} + + +void MySql::output(const ScalarData &data) { if (!(data.flags & print)) @@ -825,4 +928,20 @@ MySql::visit(const FormulaData &data) output(data); } -/* namespace Stats */ } +bool +initMySQL(string host, string user, string password, string database, + string project, string name, string sample) +{ + extern list<Output *> OutputList; + static MySql mysql; + + if (mysql.connected()) + return false; + + mysql.connect(host, user, password, database, name, sample, project); + OutputList.push_back(&mysql); + + return true; +} + +/* end namespace Stats */ } diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh index 50f7d9e97..0ce381c2f 100644 --- a/src/base/stats/mysql.hh +++ b/src/base/stats/mysql.hh @@ -35,14 +35,13 @@ #include <string> #include "base/stats/output.hh" +#include "config/use_mysql.hh" namespace MySQL { class Connection; } namespace Stats { class DistDataData; class MySqlRun; -bool MySqlConnected(); -extern MySqlRun MySqlDB; struct SetupStat { @@ -63,7 +62,7 @@ struct SetupStat uint16_t size; void init(); - unsigned setup(); + unsigned setup(MySqlRun *run); }; class InsertData @@ -85,18 +84,43 @@ class InsertData int16_t y; public: - InsertData(); + InsertData(MySqlRun *_run); ~InsertData(); void flush(); void insert(); }; +class InsertEvent +{ + private: + char *query; + int size; + bool first; + static const int maxsize = 1024*1024; + + typedef std::map<std::string, uint32_t> event_map_t; + event_map_t events; + + MySqlRun *run; + + public: + InsertEvent(MySqlRun *_run); + ~InsertEvent(); + + void flush(); + void insert(const std::string &stat); +}; + class MySql : public Output { protected: + MySqlRun *run; /* Hide the implementation so we don't have a + #include mess */ + SetupStat stat; InsertData newdata; + InsertEvent newevent; std::list<FormulaData *> formulas; bool configured; @@ -116,6 +140,17 @@ class MySql : public Output assert(i != idmap.end()); return (*i).second; } + + public: + MySql(); + ~MySql(); + + void connect(const std::string &host, const std::string &user, + const std::string &passwd, const std::string &db, + const std::string &name, const std::string &sample, + const std::string &project); + bool connected() const; + public: // Implement Visit virtual void visit(const ScalarData &data); @@ -129,6 +164,9 @@ class MySql : public Output virtual bool valid() const; virtual void output(); + // Implement Event Output + virtual void event(const std::string &event); + protected: // Output helper void output(const DistDataData &data); @@ -149,6 +187,20 @@ class MySql : public Output void configure(const FormulaData &data); }; +bool initMySQL(std::string host, std::string database, std::string user, + std::string passwd, std::string project, std::string name, + std::string sample); + +#if !USE_MYSQL +inline bool +initMySQL(std::string host, std::string user, std::string password, + std::string database, std::string project, std::string name, + std::string sample) +{ + return false; +} +#endif + /* namespace Stats */ } #endif // __BASE_STATS_MYSQL_HH__ diff --git a/src/base/stats/output.cc b/src/base/stats/output.cc new file mode 100644 index 000000000..9f2b91c77 --- /dev/null +++ b/src/base/stats/output.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2004-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 + */ + +#include <list> + +#include "base/stats/output.hh" +#include "sim/eventq.hh" +#include "sim/host.hh" + +using namespace std; + +namespace Stats { + +Tick lastDump(0); +list<Output *> OutputList; + +void +dump() +{ + assert(lastDump <= curTick); + if (lastDump == curTick) + return; + lastDump = curTick; + + list<Output *>::iterator i = OutputList.begin(); + list<Output *>::iterator end = OutputList.end(); + for (; i != end; ++i) { + Output *output = *i; + if (!output->valid()) + continue; + + output->output(); + } +} + +/* namespace Stats */ } + +void +debugDumpStats() +{ + Stats::dump(); +} + diff --git a/src/base/stats/output.hh b/src/base/stats/output.hh index 4fe93791f..c7ffcaade 100644 --- a/src/base/stats/output.hh +++ b/src/base/stats/output.hh @@ -42,6 +42,7 @@ struct Output : public Visit inline void operator()() { output(); } virtual void output() = 0; virtual bool valid() const = 0; + virtual void event(const std::string &event) = 0; }; /* namespace Stats */ } diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc index ae0d65537..a018c4837 100644 --- a/src/base/stats/text.cc +++ b/src/base/stats/text.cc @@ -251,6 +251,7 @@ VectorPrint::operator()(std::ostream &stream) const ScalarPrint print; print.name = name; print.desc = desc; + print.compat = compat; print.precision = precision; print.descriptions = descriptions; print.flags = flags; @@ -725,4 +726,25 @@ Text::visit(const FormulaData &data) visit((const VectorData &)data); } +bool +initText(const string &filename, bool desc, bool compat) +{ + static Text text; + static bool connected = false; + + if (connected) + return false; + + extern list<Output *> OutputList; + + text.open(*simout.find(filename)); + text.descriptions = desc; + text.compat = compat; + OutputList.push_back(&text); + connected = true; + + return true; +} + + /* namespace Stats */ } diff --git a/src/base/stats/text.hh b/src/base/stats/text.hh index b3faf5ad5..781d1083d 100644 --- a/src/base/stats/text.hh +++ b/src/base/stats/text.hh @@ -34,6 +34,7 @@ #include <iosfwd> #include <string> +#include "base/output.hh" #include "base/stats/output.hh" namespace Stats { @@ -71,8 +72,13 @@ class Text : public Output // Implement Output virtual bool valid() const; virtual void output(); + + // Implement Event Output + virtual void event(const std::string &event) {} }; +bool initText(const std::string &filename, bool desc=true, bool compat=true); + /* namespace Stats */ } #endif // __BASE_STATS_TEXT_HH__ diff --git a/src/base/trace.cc b/src/base/trace.cc index 9fa615f4d..0a7e6e833 100644 --- a/src/base/trace.cc +++ b/src/base/trace.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2001-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,14 +37,17 @@ #include <vector> #include "base/misc.hh" -#include "base/trace.hh" +#include "base/output.hh" #include "base/str.hh" +#include "base/trace.hh" +#include "base/varargs.hh" using namespace std; namespace Trace { const string DefaultName("global"); FlagVec flags(NumFlags, false); +bool enabled = false; // // This variable holds the output stream for debug information. Other @@ -53,151 +56,74 @@ FlagVec flags(NumFlags, false); // output. // ostream *dprintf_stream = &cerr; - -ObjectMatch ignore; - -Log theLog; - -Log::Log() +ostream & +output() { - size = 0; - buffer = NULL; + return *dprintf_stream; } - void -Log::init(int _size) +setOutput(const string &filename) { - if (buffer != NULL) { - fatal("Trace::Log::init called twice!"); - } - - size = _size; - - buffer = new Record *[size]; - - for (int i = 0; i < size; ++i) { - buffer[i] = NULL; - } - - nextRecPtr = &buffer[0]; - wrapRecPtr = &buffer[size]; + dprintf_stream = simout.find(filename); } +ObjectMatch ignore; -Log::~Log() +void +dprintf(Tick when, const std::string &name, const char *format, + CPRINTF_DEFINITION) { - for (int i = 0; i < size; ++i) { - delete buffer[i]; - } - - delete [] buffer; -} + if (!name.empty() && ignore.match(name)) + return; + std::ostream &os = *dprintf_stream; -void -Log::append(Record *rec) -{ - // dump record to output stream if there's one open - if (dprintf_stream != NULL) { - rec->dump(*dprintf_stream); - } else { - rec->dump(cout); - } + string fmt = ""; + CPrintfArgsList args(VARARGS_ALLARGS); - // no buffering: justget rid of it now - if (buffer == NULL) { - delete rec; - return; + if (!name.empty()) { + fmt = "%s: " + fmt; + args.push_front(name); } - Record *oldRec = *nextRecPtr; - - if (oldRec != NULL) { - // log has wrapped: overwrite - delete oldRec; + if (when != (Tick)-1) { + fmt = "%7d: " + fmt; + args.push_front(when); } - *nextRecPtr = rec; + fmt += format; - if (++nextRecPtr == wrapRecPtr) { - nextRecPtr = &buffer[0]; - } + ccprintf(os, fmt.c_str(), args); + os.flush(); } - void -Log::dump(ostream &os) +dump(Tick when, const std::string &name, const void *d, int len) { - if (buffer == NULL) { + if (!name.empty() && ignore.match(name)) return; - } - - Record **bufPtr = nextRecPtr; - - if (*bufPtr == NULL) { - // next record slot is empty: log must not be full yet. - // start dumping from beginning of buffer - bufPtr = buffer; - } - do { - Record *rec = *bufPtr; - - rec->dump(os); - - if (++bufPtr == wrapRecPtr) { - bufPtr = &buffer[0]; - } - } while (bufPtr != nextRecPtr); -} - -PrintfRecord::~PrintfRecord() -{ - delete &args; -} + std::ostream &os = *dprintf_stream; -void -PrintfRecord::dump(ostream &os) -{ string fmt = ""; + CPrintfArgsList args; if (!name.empty()) { fmt = "%s: " + fmt; - args.prepend(name); + args.push_front(name); } - if (cycle != (Tick)-1) { + if (when != (Tick)-1) { fmt = "%7d: " + fmt; - args.prepend(cycle); + args.push_front(when); } - fmt += format; - - args.dump(os, fmt); - os.flush(); -} - -DataRecord::DataRecord(Tick _cycle, const string &_name, - const void *_data, int _len) - : Record(_cycle), name(_name), len(_len) -{ - data = new uint8_t[len]; - memcpy(data, _data, len); -} - -DataRecord::~DataRecord() -{ - delete [] data; -} - -void -DataRecord::dump(ostream &os) -{ + const char *data = static_cast<const char *>(d); int c, i, j; - for (i = 0; i < len; i += 16) { - ccprintf(os, "%d: %s: %08x ", cycle, name, i); + ccprintf(os, fmt, args); + ccprintf(os, "%08x ", i); c = len - i; if (c > 16) c = 16; @@ -213,8 +139,7 @@ DataRecord::dump(ostream &os) for (j = 0; j < c; j++) { int ch = data[i + j] & 0x7f; - ccprintf(os, - "%c", (char)(isprint(ch) ? ch : ' ')); + ccprintf(os, "%c", (char)(isprint(ch) ? ch : ' ')); } ccprintf(os, "\n"); @@ -223,126 +148,64 @@ DataRecord::dump(ostream &os) break; } } -} // namespace Trace -// -// Returns the current output stream for debug information. As a -// wrapper around Trace::dprintf_stream, this handles cases where debug -// information is generated in the process of parsing .ini options, -// before we process the option that sets up the debug output stream -// itself. -// -std::ostream & -DebugOut() -{ - return *Trace::dprintf_stream; -} - -///////////////////////////////////////////// -// -// C-linkage functions for invoking from gdb -// -///////////////////////////////////////////// - -// -// Dump trace buffer to specified file (cout if NULL) -// -void -dumpTrace(const char *filename) -{ - if (filename != NULL) { - ofstream out(filename); - Trace::theLog.dump(out); - out.close(); - } - else { - Trace::theLog.dump(cout); - } -} - - -// -// Turn on/off trace output to cerr. Typically used when trace output -// is only going to circular buffer, but you want to see what's being -// sent there as you step through some code in gdb. This uses the -// same facility as the "trace to file" feature, and will print error -// messages rather than clobbering an existing ostream pointer. -// -void -echoTrace(bool on) -{ - if (on) { - if (Trace::dprintf_stream != NULL) { - cerr << "Already echoing trace to a file... go do a 'tail -f'" - << " on that file instead." << endl; - } else { - Trace::dprintf_stream = &cerr; - } - } else { - if (Trace::dprintf_stream != &cerr) { - cerr << "Not echoing trace to cerr." << endl; - } else { - Trace::dprintf_stream = NULL; - } - } -} - -void -printTraceFlags() -{ - using namespace Trace; - for (int i = 0; i < numFlagStrings; ++i) - if (flags[i]) - cprintf("%s\n", flagStrings[i]); -} - -void -tweakTraceFlag(const char *string, bool value) +bool +changeFlag(const char *s, bool value) { using namespace Trace; - std::string str(string); + std::string str(s); for (int i = 0; i < numFlagStrings; ++i) { if (str != flagStrings[i]) continue; - int idx = i; - - if (idx < NumFlags) { - flags[idx] = value; + if (i < NumFlags) { + flags[i] = value; } else { - idx -= NumFlags; - if (idx >= NumCompoundFlags) { - ccprintf(cerr, "Invalid compound flag"); - return; - } - - const Flags *flagVec = compoundFlags[idx]; + i -= NumFlags; + const Flags *flagVec = compoundFlags[i]; for (int j = 0; flagVec[j] != -1; ++j) { - if (flagVec[j] >= NumFlags) { - ccprintf(cerr, "Invalid compound flag"); - return; - } - flags[flagVec[j]] = value; + if (flagVec[j] < NumFlags) + flags[flagVec[j]] = value; } } - cprintf("flag %s was %s\n", string, value ? "set" : "cleared"); - return; + return true; } - cprintf("could not find flag %s\n", string); + // the flag was not found. + return false; +} + +void +dumpStatus() +{ + using namespace Trace; + for (int i = 0; i < numFlagStrings; ++i) { + if (flags[i]) + cprintf("%s\n", flagStrings[i]); + } } +/* namespace Trace */ } + + +// add a set of functions that can easily be invoked from gdb void setTraceFlag(const char *string) { - tweakTraceFlag(string, true); + Trace::changeFlag(string, true); } void clearTraceFlag(const char *string) { - tweakTraceFlag(string, false); + Trace::changeFlag(string, false); +} + +void +dumpTraceStatus() +{ + Trace::dumpStatus(); } diff --git a/src/base/trace.hh b/src/base/trace.hh index a46643159..c1b506187 100644 --- a/src/base/trace.hh +++ b/src/base/trace.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2001-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,125 +32,35 @@ #ifndef __BASE_TRACE_HH__ #define __BASE_TRACE_HH__ +#include <string> #include <vector> #include "base/cprintf.hh" #include "base/match.hh" -#include "sim/host.hh" -#include "sim/root.hh" - #include "base/traceflags.hh" +#include "sim/host.hh" +#include "sim/core.hh" namespace Trace { - typedef std::vector<bool> FlagVec; +std::ostream &output(); +void setOutput(const std::string &filename); - extern FlagVec flags; +extern bool enabled; +typedef std::vector<bool> FlagVec; +extern FlagVec flags; +inline bool IsOn(int t) { return flags[t]; } +bool changeFlag(const char *str, bool value); +void dumpStatus(); -#if TRACING_ON - const bool On = true; -#else - const bool On = false; -#endif - - inline bool - IsOn(int t) - { - return flags[t]; - - } - - void dump(const uint8_t *data, int count); - - class Record - { - protected: - Tick cycle; - - Record(Tick _cycle) - : cycle(_cycle) - { - } - - public: - virtual ~Record() {} - - virtual void dump(std::ostream &) = 0; - }; - - class PrintfRecord : public Record - { - private: - const char *format; - const std::string &name; - cp::ArgList &args; - - public: - PrintfRecord(const char *_format, cp::ArgList &_args, - Tick cycle, const std::string &_name) - : Record(cycle), format(_format), name(_name), args(_args) - { - } - - virtual ~PrintfRecord(); - - virtual void dump(std::ostream &); - }; - - class DataRecord : public Record - { - private: - const std::string &name; - uint8_t *data; - int len; - - public: - DataRecord(Tick cycle, const std::string &name, - const void *_data, int _len); - virtual ~DataRecord(); - - virtual void dump(std::ostream &); - }; - - class Log - { - private: - int size; // number of records in log - Record **buffer; // array of 'size' Record ptrs (circular buf) - Record **nextRecPtr; // next slot to use in buffer - Record **wrapRecPtr; // &buffer[size], for quick wrap check - - public: - - Log(); - ~Log(); - - void init(int _size); - - void append(Record *); // append trace record to log - void dump(std::ostream &); // dump contents to stream - }; - - extern Log theLog; - - extern ObjectMatch ignore; - - inline void - dprintf(const char *format, cp::ArgList &args, Tick cycle, - const std::string &name) - { - if (name.empty() || !ignore.match(name)) - theLog.append(new Trace::PrintfRecord(format, args, cycle, name)); - } - - inline void - dataDump(Tick cycle, const std::string &name, const void *data, int len) - { - theLog.append(new Trace::DataRecord(cycle, name, data, len)); - } - - extern const std::string DefaultName; -}; +extern ObjectMatch ignore; +extern const std::string DefaultName; + +void dprintf(Tick when, const std::string &name, const char *format, + CPRINTF_DECLARATION); +void dump(Tick when, const std::string &name, const void *data, int len); + +/* namespace Trace */ } // This silly little class allows us to wrap a string in a functor // object so that we can give a name() that DPRINTF will like @@ -162,7 +72,6 @@ struct StringWrap }; inline const std::string &name() { return Trace::DefaultName; } -std::ostream &DebugOut(); // // DPRINTF is a debugging trace facility that allows one to @@ -176,50 +85,44 @@ std::ostream &DebugOut(); #if TRACING_ON -#define DTRACE(x) (Trace::IsOn(Trace::x)) - -#define DCOUT(x) if (Trace::IsOn(Trace::x)) DebugOut() +#define DTRACE(x) (Trace::IsOn(Trace::x) && Trace::enabled) -#define DDUMP(x, data, count) \ -do { \ - if (Trace::IsOn(Trace::x)) \ - Trace::dataDump(curTick, name(), data, count); \ +#define DDUMP(x, data, count) do { \ + if (DTRACE(x)) \ + Trace::dump(curTick, name(), data, count); \ } while (0) -#define __dprintf(cycle, name, format, ...) \ - Trace::dprintf(format, (*(new cp::ArgList), __VA_ARGS__), cycle, name) +#define DPRINTF(x, ...) do { \ + if (DTRACE(x)) \ + Trace::dprintf(curTick, name(), __VA_ARGS__); \ +} while (0) -#define DPRINTF(x, ...) \ -do { \ - if (Trace::IsOn(Trace::x)) \ - __dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \ +#define DPRINTFR(x, ...) do { \ + if (DTRACE(x)) \ + Trace::dprintf((Tick)-1, std::string(), __VA_ARGS__); \ } while (0) -#define DPRINTFR(x, ...) \ -do { \ - if (Trace::IsOn(Trace::x)) \ - __dprintf((Tick)-1, std::string(), __VA_ARGS__, cp::ArgListNull()); \ +#define DDUMPN(data, count) do { \ + Trace::dump(curTick, name(), data, count); \ } while (0) -#define DPRINTFN(...) \ -do { \ - __dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \ +#define DPRINTFN(...) do { \ + Trace::dprintf(curTick, name(), __VA_ARGS__); \ } while (0) -#define DPRINTFNR(...) \ -do { \ - __dprintf((Tick)-1, string(), __VA_ARGS__, cp::ArgListNull()); \ +#define DPRINTFNR(...) do { \ + Trace::dprintf((Tick)-1, string(), __VA_ARGS__); \ } while (0) #else // !TRACING_ON #define DTRACE(x) (false) -#define DCOUT(x) if (0) DebugOut() +#define DDUMP(x, data, count) do {} while (0) #define DPRINTF(x, ...) do {} while (0) #define DPRINTFR(...) do {} while (0) +#define DDUMPN(data, count) do {} while (0) #define DPRINTFN(...) do {} while (0) #define DPRINTFNR(...) do {} while (0) -#define DDUMP(x, data, count) do {} while (0) #endif // TRACING_ON diff --git a/src/base/traceflags.py b/src/base/traceflags.py index c06399f81..e57bfa350 100644 --- a/src/base/traceflags.py +++ b/src/base/traceflags.py @@ -29,19 +29,7 @@ # Authors: Nathan Binkert # Steve Reinhardt -# -# This file generates the header and source files for the flags -# that control the tracing facility. -# - -import sys - -if len(sys.argv) != 2: - print "%s: Need argument (basename of cc/hh files)" % sys.argv[0] - sys.exit(1) - -hhfilename = sys.argv[1] + '.hh' -ccfilename = sys.argv[1] + '.cc' +__all__ = [ 'allFlags', 'baseFlags', 'compoundFlagsMap', 'compoundFlags' ] # # The list of trace flags that can be used to condition DPRINTFs etc. @@ -89,6 +77,20 @@ baseFlags = [ 'EthernetPIO', 'EthernetSM', 'Event', + 'ExecEnable', + 'ExecCPSeq', + 'ExecEffAddr', + 'ExecFetchSeq', + 'ExecIntRegs', + 'ExecIntel', + 'ExecLegion', + 'ExecOpClass', + 'ExecRegDelta', + 'ExecResult', + 'ExecSpeculative', + 'ExecSymbol', + 'ExecThread', + 'ExecTicks', 'FE', 'Fault', 'Fetch', @@ -114,7 +116,7 @@ baseFlags = [ 'ISP', 'IdeCtrl', 'IdeDisk', - 'InstExec', + 'Iob', 'Interrupt', 'LLSC', 'LSQ', @@ -135,6 +137,7 @@ baseFlags = [ 'PciConfigAll', 'Pipeline', 'Printf', + 'Predecoder', 'Quiesce', 'ROB', 'Regs', @@ -167,6 +170,7 @@ baseFlags = [ 'VtoPhys', 'WriteBarrier', 'Writeback', + 'X86', ] # @@ -178,111 +182,119 @@ baseFlags = [ # following the existing examples. # compoundFlagMap = { - 'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv', 'GDBExtra' ], - 'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ], - 'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ], - 'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ], - 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ], - 'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ], - 'O3CPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', 'O3CPU', 'Activity','Scoreboard','Writeback'], - 'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU'], - 'All' : baseFlags + 'All' : baseFlags, + 'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ], + 'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', + 'EthernetData' , 'EthernetDesc', 'EthernetIntr', + 'EthernetSM', 'EthernetCksum' ], + 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', + 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ], + 'Exec' : [ 'ExecEnable', 'ExecTicks', 'ExecOpClass', + 'ExecThread', 'ExecEffAddr', 'ExecResult', + 'ExecSymbol' ], + 'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', + 'GDBRecv', 'GDBExtra' ], + 'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ], + 'O3CPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', + 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', + 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', + 'O3CPU', 'Activity','Scoreboard','Writeback' ], + 'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU' ], + 'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ] } -############################################################# -# -# Everything below this point generates the appropriate C++ -# declarations and definitions for the trace flags. If you are simply -# adding or modifying flag definitions, you should not have to change -# anything below. -# - -import sys - # extract just the compound flag names into a list compoundFlags = [] compoundFlags.extend(compoundFlagMap.keys()) compoundFlags.sort() -# -# First generate the header file. This defines the Flag enum -# and some extern declarations for the .cc file. -# -try: - hhfile = file(hhfilename, 'w') -except IOError, e: - sys.exit("can't open %s: %s" % (hhfilename, e)) - -# file header boilerplate -print >>hhfile, ''' -/* - * DO NOT EDIT THIS FILE! - * - * Automatically generated from traceflags.py - */ +allFlags = frozenset(baseFlags + compoundFlags) -#ifndef __BASE_TRACE_FLAGS_HH__ -#define __BASE_TRACE_FLAGS_HH__ - -namespace Trace { - -enum Flags { -''', - -# Generate the enum. Base flags come first, then compound flags. -idx = 0 -for flag in baseFlags: - print >>hhfile, ' %s = %d,' % (flag, idx) - idx += 1 - -numBaseFlags = idx -print >>hhfile, ' NumFlags = %d,' % idx - -# put a comment in here to separate base from compound flags -print >>hhfile, ''' - // The remaining enum values are *not* valid indices for Trace::flags. - // They are "compound" flags, which correspond to sets of base - // flags, and are used only by TraceParamContext::setFlags(). -''', - -for flag in compoundFlags: - print >>hhfile, ' %s = %d,' % (flag, idx) - idx += 1 - -numCompoundFlags = idx - numBaseFlags -print >>hhfile, ' NumCompoundFlags = %d' % numCompoundFlags - -# trailer boilerplate -print >>hhfile, '''\ -}; // enum Flags - -// Array of strings for SimpleEnumParam -extern const char *flagStrings[]; -extern const int numFlagStrings; - -// Array of arraay pointers: for each compound flag, gives the list of -// base flags to set. Inidividual flag arrays are terminated by -1. -extern const Flags *compoundFlags[]; - -/* namespace Trace */ } - -#endif // __BASE_TRACE_FLAGS_HH__ -''', - -hhfile.close() - -# -# -# Print out .cc file with array definitions. +############################################################# # +# Everything below this point generates the appropriate C++ +# declarations and definitions for the trace flags. If you are simply +# adding or modifying flag definitions, you should not have to change +# anything below. # -try: - ccfile = file(ccfilename, 'w') -except OSError, e: - sys.exit("can't open %s: %s" % (ccfilename, e)) - -# file header -print >>ccfile, ''' +def gen_hh(filename): + # + # First generate the header file. This defines the Flag enum + # and some extern declarations for the .cc file. + # + try: + hhfile = file(filename, 'w') + except IOError, e: + sys.exit("can't open %s: %s" % (hhfilename, e)) + + # file header boilerplate + print >>hhfile, ''' + /* + * DO NOT EDIT THIS FILE! + * + * Automatically generated from traceflags.py + */ + + #ifndef __BASE_TRACE_FLAGS_HH__ + #define __BASE_TRACE_FLAGS_HH__ + + namespace Trace { + + enum Flags { + ''', + + # Generate the enum. Base flags come first, then compound flags. + idx = 0 + for flag in baseFlags: + print >>hhfile, ' %s = %d,' % (flag, idx) + idx += 1 + + numBaseFlags = idx + print >>hhfile, ' NumFlags = %d,' % idx + + # put a comment in here to separate base from compound flags + print >>hhfile, ''' + // The remaining enum values are *not* valid indices for Trace::flags. + // They are "compound" flags, which correspond to sets of base + // flags, and are used by changeFlag. + ''', + + for flag in compoundFlags: + print >>hhfile, ' %s = %d,' % (flag, idx) + idx += 1 + + numCompoundFlags = idx - numBaseFlags + print >>hhfile, ' NumCompoundFlags = %d' % numCompoundFlags + + # trailer boilerplate + print >>hhfile, '''\ + }; // enum Flags + + // Array of strings for SimpleEnumParam + extern const char *flagStrings[]; + extern const int numFlagStrings; + + // Array of arraay pointers: for each compound flag, gives the list of + // base flags to set. Inidividual flag arrays are terminated by -1. + extern const Flags *compoundFlags[]; + + /* namespace Trace */ } + + #endif // __BASE_TRACE_FLAGS_HH__ + \n''', + + hhfile.close() + +def gen_cc(filename): + '''Print out .cc file with array definitions.''' + + try: + ccfile = file(filename, 'w') + except OSError, e: + sys.exit("can't open %s: %s" % (ccfilename, e)) + + # file header + print >>ccfile, ''' /* * DO NOT EDIT THIS FILE! * @@ -297,45 +309,57 @@ const char *Trace::flagStrings[] = { ''', -# The string array is used by SimpleEnumParam to map the strings -# provided by the user to enum values. -for flag in baseFlags: - print >>ccfile, ' "%s",' % flag + # The string array is used by SimpleEnumParam to map the strings + # provided by the user to enum values. + for flag in baseFlags: + print >>ccfile, ' "%s",' % flag -for flag in compoundFlags: - print >>ccfile, ' "%s",' % flag + for flag in compoundFlags: + print >>ccfile, ' "%s",' % flag -print >>ccfile, '};\n' + print >>ccfile, '};\n' -numFlagStrings = len(baseFlags) + len(compoundFlags); + numFlagStrings = len(baseFlags) + len(compoundFlags); -print >>ccfile, 'const int Trace::numFlagStrings = %d;' % numFlagStrings -print >>ccfile + print >>ccfile, 'const int Trace::numFlagStrings = %d;' % numFlagStrings + print >>ccfile -# -# Now define the individual compound flag arrays. There is an array -# for each compound flag listing the component base flags. -# + # + # Now define the individual compound flag arrays. There is an array + # for each compound flag listing the component base flags. + # -for flag in compoundFlags: - flags = compoundFlagMap[flag] - flags.append('(Flags)-1') - print >>ccfile, 'static const Flags %sMap[] =' % flag - print >>ccfile, '{ %s };' % (', '.join(flags)) - print >>ccfile + for flag in compoundFlags: + flags = compoundFlagMap[flag] + flags.append('(Flags)-1') + print >>ccfile, 'static const Flags %sMap[] =' % flag + print >>ccfile, '{ %s };' % (', '.join(flags)) + print >>ccfile -# -# Finally the compoundFlags[] array maps the compound flags -# to their individual arrays/ -# -print >>ccfile, 'const Flags *Trace::compoundFlags[] =' -print >>ccfile, '{' + # + # Finally the compoundFlags[] array maps the compound flags + # to their individual arrays/ + # + print >>ccfile, 'const Flags *Trace::compoundFlags[] =' + print >>ccfile, '{' + + for flag in compoundFlags: + print >>ccfile, ' %sMap,' % flag + + # file trailer + print >>ccfile, '};' + + ccfile.close() -for flag in compoundFlags: - print >>ccfile, ' %sMap,' % flag +if __name__ == '__main__': + # This file generates the header and source files for the flags + # that control the tracing facility. -# file trailer -print >>ccfile, '};' + import sys -ccfile.close() + if len(sys.argv) != 2: + print "%s: Need argument (basename of cc/hh files)" % sys.argv[0] + sys.exit(1) + gen_hh(sys.argv[1] + '.hh') + gen_cc(sys.argv[1] + '.cc') diff --git a/src/base/varargs.hh b/src/base/varargs.hh new file mode 100644 index 000000000..2ba8c240a --- /dev/null +++ b/src/base/varargs.hh @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __BASE_VARARGS_HH__ +#define __BASE_VARARGS_HH__ + +#include "base/refcnt.hh" + +#define VARARGS_DECLARATION(receiver) \ + VarArgs::Argument<receiver> a01 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a02 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a03 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a04 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a05 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a06 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a07 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a08 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a09 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a10 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a11 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a12 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a13 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a14 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a15 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a16 = VarArgs::Null() + +#define VARARGS_DEFINITION(receiver) \ + VarArgs::Argument<receiver> a01, \ + VarArgs::Argument<receiver> a02, \ + VarArgs::Argument<receiver> a03, \ + VarArgs::Argument<receiver> a04, \ + VarArgs::Argument<receiver> a05, \ + VarArgs::Argument<receiver> a06, \ + VarArgs::Argument<receiver> a07, \ + VarArgs::Argument<receiver> a08, \ + VarArgs::Argument<receiver> a09, \ + VarArgs::Argument<receiver> a10, \ + VarArgs::Argument<receiver> a11, \ + VarArgs::Argument<receiver> a12, \ + VarArgs::Argument<receiver> a13, \ + VarArgs::Argument<receiver> a14, \ + VarArgs::Argument<receiver> a15, \ + VarArgs::Argument<receiver> a16 + +#define VARARGS_ALLARGS \ + a01, a02, a03, a04, a05, a06, a07, a08, \ + a09, a10, a11, a12, a13, a14, a15, a16 + +#define VARARGS_ADDARGS(receiver) do { \ + do { \ + if (!a01) break; \ + a01.add_arg(receiver); \ + if (!a02) break; \ + a02.add_arg(receiver); \ + if (!a03) break; \ + a03.add_arg(receiver); \ + if (!a04) break; \ + a04.add_arg(receiver); \ + if (!a05) break; \ + a05.add_arg(receiver); \ + if (!a06) break; \ + a06.add_arg(receiver); \ + if (!a07) break; \ + a07.add_arg(receiver); \ + if (!a08) break; \ + a08.add_arg(receiver); \ + if (!a09) break; \ + a09.add_arg(receiver); \ + if (!a10) break; \ + a10.add_arg(receiver); \ + if (!a11) break; \ + a11.add_arg(receiver); \ + if (!a12) break; \ + a12.add_arg(receiver); \ + if (!a13) break; \ + a13.add_arg(receiver); \ + if (!a14) break; \ + a14.add_arg(receiver); \ + if (!a15) break; \ + a15.add_arg(receiver); \ + if (!a16) break; \ + a16.add_arg(receiver); \ + } while (0); \ + receiver.end_args(); \ +} while (0) + +namespace VarArgs { + +struct Null {}; + +template <typename T> +struct Traits +{ + enum { enabled = true }; +}; + +template <> +struct Traits<Null> +{ + enum { enabled = false }; +}; + +template <class RECV> +struct Base : public RefCounted +{ + virtual void add_arg(RECV &receiver) const = 0; +}; + +template <typename T, class RECV> +struct Any : public Base<RECV> +{ + const T &argument; + + Any(const T &arg) : argument(arg) {} + + virtual void + add_arg(RECV &receiver) const + { + receiver.add_arg(argument); + } +}; + +template <class RECV> +struct Argument : public RefCountingPtr<Base<RECV> > +{ + typedef RefCountingPtr<Base<RECV> > Base; + + Argument() { } + Argument(const Null &null) { } + template <typename T> + Argument(const T& arg) : Base(new Any<T, RECV>(arg)) { } + + void + add_arg(RECV &receiver) const + { + if (this->data) + this->data->add_arg(receiver); + } +}; + +template<class RECV> +class List +{ + public: + typedef Argument<RECV> Argument; + typedef std::list<Argument> list; + typedef typename list::iterator iterator; + typedef typename list::const_iterator const_iterator; + typedef typename list::size_type size_type; + + protected: + list l; + + public: + List() {} + List(Argument a01, Argument a02, Argument a03, Argument a04, + Argument a05, Argument a06, Argument a07, Argument a08, + Argument a09, Argument a10, Argument a11, Argument a12, + Argument a13, Argument a14, Argument a15, Argument a16) + { + if (!a01) return; + l.push_back(a01); + if (!a02) return; + l.push_back(a02); + if (!a03) return; + l.push_back(a03); + if (!a04) return; + l.push_back(a04); + if (!a05) return; + l.push_back(a05); + if (!a06) return; + l.push_back(a06); + if (!a07) return; + l.push_back(a07); + if (!a08) return; + l.push_back(a08); + if (!a09) return; + l.push_back(a09); + if (!a10) return; + l.push_back(a10); + if (!a11) return; + l.push_back(a11); + if (!a12) return; + l.push_back(a12); + if (!a13) return; + l.push_back(a13); + if (!a14) return; + l.push_back(a14); + if (!a15) return; + l.push_back(a15); + if (!a16) return; + l.push_back(a16); + } + + size_type size() const { return l.size(); } + bool empty() const { return l.empty(); } + + iterator begin() { return l.begin(); } + const_iterator begin() const { return l.begin(); } + + iterator end() { return l.end(); } + const_iterator end() const { return l.end(); } + + void + push_back(const Argument &arg) + { + if (arg) + l.push_back(arg); + } + + void + push_front(const Argument &arg) + { + if (arg) + l.push_front(arg); + } + + template <typename T> + void + push_back(const T &arg) + { + if (Traits<T>::enabled) + l.push_back(arg); + } + + template <typename T> + void + push_front(const T &arg) + { + if (Traits<T>::enabled) + l.push_front(arg); + } + + Argument& front() { return l.front(); } + const Argument& front() const { return l.front(); } + Argument& back() { return l.back(); } + const Argument& back() const { return l.back(); } + + void erase(iterator position) { return l.erase(position); } + void erase(iterator first, iterator last) { return l.erase(first, last); } + void clear() { return l.clear(); } + void pop_front() { return l.pop_front(); } + void pop_back() { return l.pop_back(); } + void reverse() { l.reverse(); } + + /* + * Functions specific to variable arguments + */ + void + add_args(RECV &recv) const + { + const_iterator i = l.begin(); + const_iterator end = l.end(); + while (i != end) { + i->add_arg(recv); + ++i; + } + + recv.end_args(); + } +}; + +/* end namespace VarArgs */ } + +#endif /* __BASE_VARARGS_HH__ */ diff --git a/src/cpu/SConscript b/src/cpu/SConscript index 4d4b7574c..1c2278f6f 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -28,11 +28,7 @@ # # Authors: Steve Reinhardt -import os -import os.path - -# Import build environment variable from SConstruct. -Import('env') +Import('*') ################################################################# # @@ -107,89 +103,24 @@ env.Depends('static_inst_exec_sigs.hh', Value(env['CPU_MODELS'])) # and one of these are not being used. CheckerSupportedCPUList = ['O3CPU', 'OzoneCPU'] -################################################################# -# -# Include CPU-model-specific files based on set of models -# specified in CPU_MODELS build option. -# -################################################################# - -# Keep a list of CPU models that support SMT -env['SMT_CPU_MODELS'] = [] - -sources = [] - -need_simple_base = False -if 'AtomicSimpleCPU' in env['CPU_MODELS']: - need_simple_base = True - sources += Split('simple/atomic.cc') - -if 'TimingSimpleCPU' in env['CPU_MODELS']: - need_simple_base = True - sources += Split('simple/timing.cc') - -if need_simple_base: - sources += Split('simple/base.cc') - -if 'FastCPU' in env['CPU_MODELS']: - sources += Split('fast/cpu.cc') - -need_bp_unit = False -if 'O3CPU' in env['CPU_MODELS']: - need_bp_unit = True - sources += SConscript('o3/SConscript', exports = 'env') - sources += Split(''' - o3/base_dyn_inst.cc - o3/bpred_unit.cc - o3/commit.cc - o3/decode.cc - o3/fetch.cc - o3/free_list.cc - o3/fu_pool.cc - o3/cpu.cc - o3/iew.cc - o3/inst_queue.cc - o3/lsq_unit.cc - o3/lsq.cc - o3/mem_dep_unit.cc - o3/rename.cc - o3/rename_map.cc - o3/rob.cc - o3/scoreboard.cc - o3/store_set.cc - ''') - sources += Split('memtest/memtest.cc') - 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 - sources += Split(''' - ozone/base_dyn_inst.cc - ozone/bpred_unit.cc - ozone/cpu.cc - ozone/cpu_builder.cc - ozone/dyn_inst.cc - ozone/front_end.cc - ozone/lw_back_end.cc - ozone/lw_lsq.cc - ozone/rename_table.cc - ''') - if env['USE_CHECKER']: - sources += Split('ozone/checker_builder.cc') - -if need_bp_unit: - sources += Split(''' - o3/2bit_local_pred.cc - o3/btb.cc - o3/ras.cc - o3/tournament_pred.cc - ''') +Source('activity.cc') +Source('base.cc') +Source('cpuevent.cc') +Source('exetrace.cc') +Source('func_unit.cc') +Source('op_class.cc') +Source('pc_event.cc') +Source('quiesce_event.cc') +Source('static_inst.cc') +Source('simple_thread.cc') +Source('thread_state.cc') + +if env['FULL_SYSTEM']: + Source('intr_control.cc') + Source('profile.cc') if env['USE_CHECKER']: - sources += Split('checker/cpu.cc') + Source('checker/cpu.cc') checker_supports = False for i in CheckerSupportedCPUList: if i in env['CPU_MODELS']: @@ -198,16 +129,5 @@ if env['USE_CHECKER']: print "Checker only supports CPU models", for i in CheckerSupportedCPUList: print i, - print ", please set USE_CHECKER=False or use one of those CPU models" + print ", please set USE_CHECKER=False or use one of those CPU models" Exit(1) - - -# FullCPU sources are included from src/SConscript since they're not -# below this point in the file hierarchy. - -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] - -Return('sources') - diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 03110630c..4dccee0d3 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -63,7 +63,7 @@ int maxThreadsPerCPU = 1; CPUProgressEvent::CPUProgressEvent(EventQueue *q, Tick ival, BaseCPU *_cpu) - : Event(q, Event::Stat_Event_Pri), interval(ival), + : Event(q, Event::Progress_Event_Pri), interval(ival), lastNumInst(0), cpu(_cpu) { if (interval) @@ -320,7 +320,7 @@ BaseCPU::switchOut() } void -BaseCPU::takeOverFrom(BaseCPU *oldCPU) +BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) { assert(threadContexts.size() == oldCPU->threadContexts.size()); @@ -353,6 +353,26 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) // if (profileEvent) // profileEvent->schedule(curTick); #endif + + // Connect new CPU to old CPU's memory only if new CPU isn't + // connected to anything. Also connect old CPU's memory to new + // CPU. + Port *peer; + if (ic->getPeer() == NULL) { + peer = oldCPU->getPort("icache_port")->getPeer(); + ic->setPeer(peer); + } else { + peer = ic->getPeer(); + } + peer->setPeer(ic); + + if (dc->getPeer() == NULL) { + peer = oldCPU->getPort("dcache_port")->getPeer(); + dc->setPeer(peer); + } else { + peer = dc->getPeer(); + } + peer->setPeer(dc); } @@ -373,12 +393,6 @@ BaseCPU::ProfileEvent::process() } void -BaseCPU::post_interrupt(int int_type) -{ - interrupts.post(int_type); -} - -void BaseCPU::post_interrupt(int int_num, int index) { interrupts.post(int_num, index); @@ -396,6 +410,11 @@ BaseCPU::clear_interrupts() interrupts.clear_all(); } +uint64_t +BaseCPU::get_interrupts(int int_num) +{ + return interrupts.get_vec(int_num); +} void BaseCPU::serialize(std::ostream &os) diff --git a/src/cpu/base.hh b/src/cpu/base.hh index a1265b748..4d8300186 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -34,11 +34,11 @@ #include <vector> +#include "arch/isa_traits.hh" #include "base/statistics.hh" #include "config/full_system.hh" #include "sim/eventq.hh" #include "mem/mem_object.hh" -#include "arch/isa_traits.hh" #if FULL_SYSTEM #include "arch/interrupts.hh" @@ -50,6 +50,11 @@ class ThreadContext; class System; class Port; +namespace TheISA +{ + class Predecoder; +} + class CPUProgressEvent : public Event { protected: @@ -102,10 +107,10 @@ class BaseCPU : public MemObject TheISA::Interrupts interrupts; public: - virtual void post_interrupt(int int_type); virtual void post_interrupt(int int_num, int index); virtual void clear_interrupt(int int_num, int index); virtual void clear_interrupts(); + virtual uint64_t get_interrupts(int int_num); bool check_interrupts(ThreadContext * tc) const { return interrupts.check_interrupts(tc); } @@ -125,6 +130,7 @@ class BaseCPU : public MemObject protected: std::vector<ThreadContext *> threadContexts; + std::vector<TheISA::Predecoder *> predecoders; public: @@ -196,7 +202,7 @@ class BaseCPU : public MemObject /// Take over execution from the given CPU. Used for warm-up and /// sampling. - virtual void takeOverFrom(BaseCPU *); + virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc); /** * Number of threads we're actually simulating (<= SMT_MAX_THREADS). diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index d6cd9409b..a6af98d66 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -244,7 +244,7 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) !(unverifiedReq->isUncacheable()) && (!(unverifiedReq->isLocked()) || ((unverifiedReq->isLocked()) && - unverifiedReq->getScResult() == 1))) { + unverifiedReq->getExtraData() == 1))) { T inst_data; /* // This code would work if the LSQ allowed for snooping. @@ -269,7 +269,7 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) // doesn't check if the SC should succeed or fail, it just checks the // value. if (res && unverifiedReq->scResultValid()) - *res = unverifiedReq->getScResult(); + *res = unverifiedReq->getExtraData(); return NoFault; } diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 3e08193ee..7b3628986 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -298,27 +298,27 @@ class CheckerCPU : public BaseCPU thread->setNextPC(val); } - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg) { - return thread->readMiscReg(misc_reg); + return thread->readMiscRegNoEffect(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) + MiscReg readMiscReg(int misc_reg) { - return thread->readMiscRegWithEffect(misc_reg); + return thread->readMiscReg(misc_reg); } - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { result.integer = val; miscRegIdxs.push(misc_reg); - return thread->setMiscReg(misc_reg, val); + return thread->setMiscRegNoEffect(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val) { miscRegIdxs.push(misc_reg); - return thread->setMiscRegWithEffect(misc_reg, val); + return thread->setMiscReg(misc_reg, val); } void recordPCChange(uint64_t val) { changedPC = true; newPC = val; } diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 56e13dd1e..f3f8a0bb3 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -386,13 +386,13 @@ Checker<DynInstPtr>::validateExecution(DynInstPtr &inst) int misc_reg_idx = miscRegIdxs.front(); miscRegIdxs.pop(); - if (inst->tcBase()->readMiscReg(misc_reg_idx) != - thread->readMiscReg(misc_reg_idx)) { + if (inst->tcBase()->readMiscRegNoEffect(misc_reg_idx) != + thread->readMiscRegNoEffect(misc_reg_idx)) { warn("%lli: Misc reg idx %i (side effect) does not match! " "Inst: %#x, checker: %#x", curTick, misc_reg_idx, - inst->tcBase()->readMiscReg(misc_reg_idx), - thread->readMiscReg(misc_reg_idx)); + inst->tcBase()->readMiscRegNoEffect(misc_reg_idx), + thread->readMiscRegNoEffect(misc_reg_idx)); handleError(inst); } } @@ -432,7 +432,7 @@ Checker<DynInstPtr>::copyResult(DynInstPtr &inst) } else if (idx < TheISA::Fpcr_DepTag) { thread->setFloatRegBits(idx, inst->readIntResult()); } else { - thread->setMiscReg(idx, inst->readIntResult()); + thread->setMiscRegNoEffect(idx, inst->readIntResult()); } } diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index cf36d8392..3b4d21e13 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -248,11 +248,17 @@ class CheckerThreadContext : public ThreadContext checkerCPU->recordNextPCChange(val); } + MiscReg readMiscRegNoEffect(int misc_reg) + { return actualTC->readMiscRegNoEffect(misc_reg); } + MiscReg readMiscReg(int misc_reg) { return actualTC->readMiscReg(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) - { return actualTC->readMiscRegWithEffect(misc_reg); } + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) + { + checkerTC->setMiscRegNoEffect(misc_reg, val); + actualTC->setMiscRegNoEffect(misc_reg, val); + } void setMiscReg(int misc_reg, const MiscReg &val) { @@ -260,12 +266,6 @@ class CheckerThreadContext : public ThreadContext actualTC->setMiscReg(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) - { - checkerTC->setMiscRegWithEffect(misc_reg, val); - actualTC->setMiscRegWithEffect(misc_reg, val); - } - unsigned readStCondFailures() { return actualTC->readStCondFailures(); } diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh index edccd747f..2b9fe4bcf 100644 --- a/src/cpu/exec_context.hh +++ b/src/cpu/exec_context.hh @@ -100,18 +100,18 @@ class ExecContext { void setNextNPC(uint64_t val); /** Reads a miscellaneous register. */ - MiscReg readMiscReg(int misc_reg); + MiscReg readMiscRegNoEffect(int misc_reg); /** Reads a miscellaneous register, handling any architectural * side effects due to reading that register. */ - MiscReg readMiscRegWithEffect(int misc_reg); + MiscReg readMiscReg(int misc_reg); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const MiscReg &val); + void setMiscRegNoEffect(int misc_reg, const MiscReg &val); /** Sets a miscellaneous register, handling any architectural * side effects due to writing that register. */ - void setMiscRegWithEffect(int misc_reg, const MiscReg &val); + void setMiscReg(int misc_reg, const MiscReg &val); /** Records the effective address of the instruction. Only valid * for memory ops. */ diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 5108d7338..c568b1439 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -31,14 +31,17 @@ * Steve Raasch */ +#include <errno.h> #include <fstream> #include <iomanip> #include <sys/ipc.h> #include <sys/shm.h> +#include "arch/predecoder.hh" #include "arch/regfile.hh" #include "arch/utility.hh" #include "base/loader/symtab.hh" +#include "base/socket.hh" #include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" @@ -64,6 +67,28 @@ static bool wasMicro = false; namespace Trace { SharedData *shared_data = NULL; +ListenSocket *cosim_listener = NULL; + +void +setupSharedData() +{ + int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777); + if (shmfd < 0) + fatal("Couldn't get shared memory fd. Is Legion running?"); + + shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND); + if (shared_data == (SharedData*)-1) + fatal("Couldn't allocate shared memory"); + + if (shared_data->flags != OWN_M5) + fatal("Shared memory has invalid owner"); + + if (shared_data->version != VERSION) + fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION, + shared_data->version); + + // step legion forward one cycle so we can get register values + shared_data->flags = OWN_LEGION; } //////////////////////////////////////////////////////////////////////// @@ -123,12 +148,101 @@ inline void printLevelHeader(ostream & os, int level) #endif void -Trace::InstRecord::dump(ostream &outs) +Trace::InstRecord::dump() { + ostream &outs = Trace::output(); + DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst); - if (flags[PRINT_REG_DELTA]) + bool diff = true; + if (IsOn(ExecRegDelta)) { + diff = false; +#ifndef NDEBUG #if THE_ISA == SPARC_ISA + static int fd = 0; + //Don't print what happens for each micro-op, just print out + //once at the last op, and for regular instructions. + if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) + { + if(!cosim_listener) + { + int port = 8000; + cosim_listener = new ListenSocket(); + while(!cosim_listener->listen(port, true)) + { + DPRINTF(GDBMisc, "Can't bind port %d\n", port); + port++; + } + ccprintf(cerr, "Listening for cosimulator on port %d\n", port); + fd = cosim_listener->accept(); + } + char prefix[] = "goli"; + for(int p = 0; p < 4; p++) + { + for(int i = 0; i < 8; i++) + { + uint64_t regVal; + int res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + uint64_t realRegVal = thread->readIntReg(p * 8 + i); + if((regVal & 0xffffffffULL) != (realRegVal & 0xffffffffULL)) + { + DPRINTF(ExecRegDelta, "Register %s%d should be %#x but is %#x.\n", prefix[p], i, regVal, realRegVal); + diff = true; + } + //ccprintf(outs, "%s%d m5 = %#x statetrace = %#x\n", prefix[p], i, realRegVal, regVal); + } + } + /*for(int f = 0; f <= 62; f+=2) + { + uint64_t regVal; + int res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + uint64_t realRegVal = thread->readFloatRegBits(f, 64); + if(regVal != realRegVal) + { + DPRINTF(ExecRegDelta, "Register f%d should be %#x but is %#x.\n", f, regVal, realRegVal); + } + }*/ + uint64_t regVal; + int res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + uint64_t realRegVal = thread->readNextPC(); + if(regVal != realRegVal) + { + DPRINTF(ExecRegDelta, "Register pc should be %#x but is %#x.\n", regVal, realRegVal); + diff = true; + } + res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + realRegVal = thread->readNextNPC(); + if(regVal != realRegVal) + { + DPRINTF(ExecRegDelta, "Register npc should be %#x but is %#x.\n", regVal, realRegVal); + diff = true; + } + res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + realRegVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2); + if((regVal & 0xF) != (realRegVal & 0xF)) + { + DPRINTF(ExecRegDelta, "Register ccr should be %#x but is %#x.\n", regVal, realRegVal); + diff = true; + } + } +#endif +#endif +#if 0 //THE_ISA == SPARC_ISA //Don't print what happens for each micro-op, just print out //once at the last op, and for regular instructions. if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) @@ -148,14 +262,14 @@ Trace::InstRecord::dump(ostream &outs) outs << "PC = " << thread->readNextPC(); outs << " NPC = " << thread->readNextNPC(); newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2); - //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR); + //newVal = thread->readMiscRegNoEffect(SparcISA::MISCREG_CCR); if(newVal != ccr) { outs << " CCR = " << newVal; ccr = newVal; } newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1); - //newVal = thread->readMiscReg(SparcISA::MISCREG_Y); + //newVal = thread->readMiscRegNoEffect(SparcISA::MISCREG_Y); if(newVal != y) { outs << " Y = " << newVal; @@ -187,34 +301,26 @@ Trace::InstRecord::dump(ostream &outs) } #endif } - else if (flags[INTEL_FORMAT]) { -#if FULL_SYSTEM - bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system); -#else - bool is_trace_system = true; -#endif - if (is_trace_system) { - ccprintf(outs, "%7d ) ", cycle); - outs << "0x" << hex << PC << ":\t"; - if (staticInst->isLoad()) { - outs << "<RD 0x" << hex << addr; - outs << ">"; - } else if (staticInst->isStore()) { - outs << "<WR 0x" << hex << addr; - outs << ">"; - } - outs << endl; + if(!diff) { + } else if (IsOn(ExecIntel)) { + ccprintf(outs, "%7d ) ", when); + outs << "0x" << hex << PC << ":\t"; + if (staticInst->isLoad()) { + ccprintf(outs, "<RD %#x>", addr); + } else if (staticInst->isStore()) { + ccprintf(outs, "<WR %#x>", addr); } + outs << endl; } else { - if (flags[PRINT_CYCLE]) - ccprintf(outs, "%7d: ", cycle); + if (IsOn(ExecTicks)) + ccprintf(outs, "%7d: ", when); outs << thread->getCpuPtr()->name() << " "; - if (flags[TRACE_MISSPEC]) + if (IsOn(ExecSpeculative)) outs << (misspeculating ? "-" : "+") << " "; - if (flags[PRINT_THREAD_NUM]) + if (IsOn(ExecThread)) outs << "T" << thread->getThreadNum() << " : "; @@ -222,7 +328,7 @@ Trace::InstRecord::dump(ostream &outs) Addr sym_addr; if (debugSymbolTable && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr) - && flags[PC_SYMBOL]) { + && IsOn(ExecSymbol)) { if (PC != sym_addr) sym_str += csprintf("+%d", PC - sym_addr); outs << "@" << sym_str << " : "; @@ -248,11 +354,11 @@ Trace::InstRecord::dump(ostream &outs) outs << " : "; - if (flags[PRINT_OP_CLASS]) { + if (IsOn(ExecOpClass)) { outs << opClassStrings[staticInst->opClass()] << " : "; } - if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) { + if (IsOn(ExecResult) && data_status != DataInvalid) { outs << " D="; #if 0 if (data_status == DataDouble) @@ -264,10 +370,10 @@ Trace::InstRecord::dump(ostream &outs) #endif } - if (flags[PRINT_EFF_ADDR] && addr_valid) + if (IsOn(ExecEffAddr) && addr_valid) outs << " A=0x" << hex << addr; - if (flags[PRINT_INT_REGS] && regs_valid) { + if (IsOn(ExecIntRegs) && regs_valid) { for (int i = 0; i < TheISA::NumIntRegs;) for (int j = i + 1; i <= j; i++) ccprintf(outs, "r%02d = %#018x%s", i, @@ -276,10 +382,10 @@ Trace::InstRecord::dump(ostream &outs) outs << "\n"; } - if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid) + if (IsOn(ExecFetchSeq) && fetch_seq_valid) outs << " FetchSeq=" << dec << fetch_seq; - if (flags[PRINT_CP_SEQ] && cp_seq_valid) + if (IsOn(ExecCPSeq) && cp_seq_valid) outs << " CPSeq=" << dec << cp_seq; // @@ -288,8 +394,9 @@ Trace::InstRecord::dump(ostream &outs) outs << endl; } #if THE_ISA == SPARC_ISA && FULL_SYSTEM + static TheISA::Predecoder predecoder(NULL); // Compare - if (flags[LEGION_LOCKSTEP]) + if (IsOn(ExecLegion)) { bool compared = false; bool diffPC = false; @@ -321,10 +428,13 @@ Trace::InstRecord::dump(ostream &outs) bool diffTlb = false; Addr m5Pc, lgnPc; + if (!shared_data) + setupSharedData(); + // We took a trap on a micro-op... if (wasMicro && !staticInst->isMicroOp()) { - // let's skip comparing this cycle + // let's skip comparing this tick while (!compared) if (shared_data->flags == OWN_M5) { shared_data->flags = OWN_LEGION; @@ -370,30 +480,30 @@ Trace::InstRecord::dump(ostream &outs) diffFpRegs = true; } } - uint64_t oldTl = thread->readMiscReg(MISCREG_TL); + uint64_t oldTl = thread->readMiscRegNoEffect(MISCREG_TL); if (oldTl != shared_data->tl) diffTl = true; for (int i = 1; i <= MaxTL; i++) { - thread->setMiscReg(MISCREG_TL, i); - if (thread->readMiscReg(MISCREG_TPC) != + thread->setMiscRegNoEffect(MISCREG_TL, i); + if (thread->readMiscRegNoEffect(MISCREG_TPC) != shared_data->tpc[i-1]) diffTpc = true; - if (thread->readMiscReg(MISCREG_TNPC) != + if (thread->readMiscRegNoEffect(MISCREG_TNPC) != shared_data->tnpc[i-1]) diffTnpc = true; - if (thread->readMiscReg(MISCREG_TSTATE) != + if (thread->readMiscRegNoEffect(MISCREG_TSTATE) != shared_data->tstate[i-1]) diffTstate = true; - if (thread->readMiscReg(MISCREG_TT) != + if (thread->readMiscRegNoEffect(MISCREG_TT) != shared_data->tt[i-1]) diffTt = true; - if (thread->readMiscReg(MISCREG_HTSTATE) != + if (thread->readMiscRegNoEffect(MISCREG_HTSTATE) != shared_data->htstate[i-1]) diffHtstate = true; } - thread->setMiscReg(MISCREG_TL, oldTl); + thread->setMiscRegNoEffect(MISCREG_TL, oldTl); - if(shared_data->tba != thread->readMiscReg(MISCREG_TBA)) + if(shared_data->tba != thread->readMiscRegNoEffect(MISCREG_TBA)) diffTba = true; //When the hpstate register is read by an instruction, //legion has bit 11 set. When it's in storage, it doesn't. @@ -401,50 +511,50 @@ Trace::InstRecord::dump(ostream &outs) //of the registers like that, the bit is always set to 1 and //we just don't compare it. It's not supposed to matter //anyway. - if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE)) + if((shared_data->hpstate | (1 << 11)) != thread->readMiscRegNoEffect(MISCREG_HPSTATE)) diffHpstate = true; - if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA)) + if(shared_data->htba != thread->readMiscRegNoEffect(MISCREG_HTBA)) diffHtba = true; - if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE)) + if(shared_data->pstate != thread->readMiscRegNoEffect(MISCREG_PSTATE)) diffPstate = true; - //if(shared_data->y != thread->readMiscReg(MISCREG_Y)) + //if(shared_data->y != thread->readMiscRegNoEffect(MISCREG_Y)) if(shared_data->y != thread->readIntReg(NumIntArchRegs + 1)) diffY = true; - if(shared_data->fsr != thread->readMiscReg(MISCREG_FSR)) { + if(shared_data->fsr != thread->readMiscRegNoEffect(MISCREG_FSR)) { diffFsr = true; if (mbits(shared_data->fsr, 63,10) == - mbits(thread->readMiscReg(MISCREG_FSR), 63,10)) { - thread->setMiscReg(MISCREG_FSR, shared_data->fsr); + mbits(thread->readMiscRegNoEffect(MISCREG_FSR), 63,10)) { + thread->setMiscRegNoEffect(MISCREG_FSR, shared_data->fsr); diffFsr = false; } } - //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR)) + //if(shared_data->ccr != thread->readMiscRegNoEffect(MISCREG_CCR)) if(shared_data->ccr != thread->readIntReg(NumIntArchRegs + 2)) diffCcr = true; - if(shared_data->gl != thread->readMiscReg(MISCREG_GL)) + if(shared_data->gl != thread->readMiscRegNoEffect(MISCREG_GL)) diffGl = true; - if(shared_data->asi != thread->readMiscReg(MISCREG_ASI)) + if(shared_data->asi != thread->readMiscRegNoEffect(MISCREG_ASI)) diffAsi = true; - if(shared_data->pil != thread->readMiscReg(MISCREG_PIL)) + if(shared_data->pil != thread->readMiscRegNoEffect(MISCREG_PIL)) diffPil = true; - if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP)) + if(shared_data->cwp != thread->readMiscRegNoEffect(MISCREG_CWP)) diffCwp = true; - //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE)) + //if(shared_data->cansave != thread->readMiscRegNoEffect(MISCREG_CANSAVE)) if(shared_data->cansave != thread->readIntReg(NumIntArchRegs + 3)) diffCansave = true; //if(shared_data->canrestore != - // thread->readMiscReg(MISCREG_CANRESTORE)) + // thread->readMiscRegNoEffect(MISCREG_CANRESTORE)) if(shared_data->canrestore != thread->readIntReg(NumIntArchRegs + 4)) diffCanrestore = true; - //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN)) + //if(shared_data->otherwin != thread->readMiscRegNoEffect(MISCREG_OTHERWIN)) if(shared_data->otherwin != thread->readIntReg(NumIntArchRegs + 6)) diffOtherwin = true; - //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN)) + //if(shared_data->cleanwin != thread->readMiscRegNoEffect(MISCREG_CLEANWIN)) if(shared_data->cleanwin != thread->readIntReg(NumIntArchRegs + 5)) diffCleanwin = true; @@ -539,9 +649,13 @@ Trace::InstRecord::dump(ostream &outs) << staticInst->disassemble(m5Pc, debugSymbolTable) << endl; + predecoder.setTC(thread); + predecoder.moreBytes(m5Pc, 0, shared_data->instruction); + + assert(predecoder.extMachInstRead()); + StaticInstPtr legionInst = - StaticInst::decode(makeExtMI(shared_data->instruction, - thread)); + StaticInst::decode(predecoder.getExtMachInst()); outs << setfill(' ') << setw(15) << " Legion Inst: " << "0x" << setw(8) << setfill('0') << hex @@ -552,78 +666,78 @@ Trace::InstRecord::dump(ostream &outs) printSectionHeader(outs, "General State"); printColumnLabels(outs); printRegPair(outs, "HPstate", - thread->readMiscReg(MISCREG_HPSTATE), + thread->readMiscRegNoEffect(MISCREG_HPSTATE), shared_data->hpstate | (1 << 11)); printRegPair(outs, "Htba", - thread->readMiscReg(MISCREG_HTBA), + thread->readMiscRegNoEffect(MISCREG_HTBA), shared_data->htba); printRegPair(outs, "Pstate", - thread->readMiscReg(MISCREG_PSTATE), + thread->readMiscRegNoEffect(MISCREG_PSTATE), shared_data->pstate); printRegPair(outs, "Y", - //thread->readMiscReg(MISCREG_Y), + //thread->readMiscRegNoEffect(MISCREG_Y), thread->readIntReg(NumIntArchRegs + 1), shared_data->y); printRegPair(outs, "FSR", - thread->readMiscReg(MISCREG_FSR), + thread->readMiscRegNoEffect(MISCREG_FSR), shared_data->fsr); printRegPair(outs, "Ccr", - //thread->readMiscReg(MISCREG_CCR), + //thread->readMiscRegNoEffect(MISCREG_CCR), thread->readIntReg(NumIntArchRegs + 2), shared_data->ccr); printRegPair(outs, "Tl", - thread->readMiscReg(MISCREG_TL), + thread->readMiscRegNoEffect(MISCREG_TL), shared_data->tl); printRegPair(outs, "Gl", - thread->readMiscReg(MISCREG_GL), + thread->readMiscRegNoEffect(MISCREG_GL), shared_data->gl); printRegPair(outs, "Asi", - thread->readMiscReg(MISCREG_ASI), + thread->readMiscRegNoEffect(MISCREG_ASI), shared_data->asi); printRegPair(outs, "Pil", - thread->readMiscReg(MISCREG_PIL), + thread->readMiscRegNoEffect(MISCREG_PIL), shared_data->pil); printRegPair(outs, "Cwp", - thread->readMiscReg(MISCREG_CWP), + thread->readMiscRegNoEffect(MISCREG_CWP), shared_data->cwp); printRegPair(outs, "Cansave", - //thread->readMiscReg(MISCREG_CANSAVE), + //thread->readMiscRegNoEffect(MISCREG_CANSAVE), thread->readIntReg(NumIntArchRegs + 3), shared_data->cansave); printRegPair(outs, "Canrestore", - //thread->readMiscReg(MISCREG_CANRESTORE), + //thread->readMiscRegNoEffect(MISCREG_CANRESTORE), thread->readIntReg(NumIntArchRegs + 4), shared_data->canrestore); printRegPair(outs, "Otherwin", - //thread->readMiscReg(MISCREG_OTHERWIN), + //thread->readMiscRegNoEffect(MISCREG_OTHERWIN), thread->readIntReg(NumIntArchRegs + 6), shared_data->otherwin); printRegPair(outs, "Cleanwin", - //thread->readMiscReg(MISCREG_CLEANWIN), + //thread->readMiscRegNoEffect(MISCREG_CLEANWIN), thread->readIntReg(NumIntArchRegs + 5), shared_data->cleanwin); outs << endl; for (int i = 1; i <= MaxTL; i++) { printLevelHeader(outs, i); printColumnLabels(outs); - thread->setMiscReg(MISCREG_TL, i); + thread->setMiscRegNoEffect(MISCREG_TL, i); printRegPair(outs, "Tpc", - thread->readMiscReg(MISCREG_TPC), + thread->readMiscRegNoEffect(MISCREG_TPC), shared_data->tpc[i-1]); printRegPair(outs, "Tnpc", - thread->readMiscReg(MISCREG_TNPC), + thread->readMiscRegNoEffect(MISCREG_TNPC), shared_data->tnpc[i-1]); printRegPair(outs, "Tstate", - thread->readMiscReg(MISCREG_TSTATE), + thread->readMiscRegNoEffect(MISCREG_TSTATE), shared_data->tstate[i-1]); printRegPair(outs, "Tt", - thread->readMiscReg(MISCREG_TT), + thread->readMiscRegNoEffect(MISCREG_TT), shared_data->tt[i-1]); printRegPair(outs, "Htstate", - thread->readMiscReg(MISCREG_HTSTATE), + thread->readMiscRegNoEffect(MISCREG_HTSTATE), shared_data->htstate[i-1]); } - thread->setMiscReg(MISCREG_TL, oldTl); + thread->setMiscRegNoEffect(MISCREG_TL, oldTl); outs << endl; printSectionHeader(outs, "General Purpose Registers"); @@ -684,110 +798,4 @@ Trace::InstRecord::dump(ostream &outs) #endif } - -vector<bool> Trace::InstRecord::flags(NUM_BITS); -string Trace::InstRecord::trace_system; - -//////////////////////////////////////////////////////////////////////// -// -// Parameter space for per-cycle execution address tracing options. -// Derive from ParamContext so we can override checkParams() function. -// -class ExecutionTraceParamContext : public ParamContext -{ - public: - ExecutionTraceParamContext(const string &_iniSection) - : ParamContext(_iniSection) - { - } - - void checkParams(); // defined at bottom of file -}; - -ExecutionTraceParamContext exeTraceParams("exetrace"); - -Param<bool> exe_trace_spec(&exeTraceParams, "speculative", - "capture speculative instructions", true); - -Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle", - "print cycle number", true); -Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass", - "print op class", true); -Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread", - "print thread number", true); -Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr", - "print effective address", true); -Param<bool> exe_trace_print_data(&exeTraceParams, "print_data", - "print result data", true); -Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs", - "print all integer regs", false); -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", - "print trace in intel compatible format", false); -Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep", - "Compare sim state to legion state every cycle", - false); -Param<string> exe_trace_system(&exeTraceParams, "trace_system", - "print trace of which system (client or server)", - "client"); - - -// -// Helper function for ExecutionTraceParamContext::checkParams() just -// to get us into the InstRecord namespace -// -void -Trace::InstRecord::setParams() -{ - flags[TRACE_MISSPEC] = exe_trace_spec; - - flags[PRINT_CYCLE] = exe_trace_print_cycle; - flags[PRINT_OP_CLASS] = exe_trace_print_opclass; - flags[PRINT_THREAD_NUM] = exe_trace_print_thread; - flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr; - flags[PRINT_EFF_ADDR] = exe_trace_print_data; - 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; - flags[LEGION_LOCKSTEP] = exe_trace_legion_lockstep; - trace_system = exe_trace_system; - - // If were going to be in lockstep with Legion - // Setup shared memory, and get otherwise ready - if (flags[LEGION_LOCKSTEP]) { - int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777); - if (shmfd < 0) - fatal("Couldn't get shared memory fd. Is Legion running?"); - - shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND); - if (shared_data == (SharedData*)-1) - fatal("Couldn't allocate shared memory"); - - if (shared_data->flags != OWN_M5) - fatal("Shared memory has invalid owner"); - - if (shared_data->version != VERSION) - fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION, - shared_data->version); - - // step legion forward one cycle so we can get register values - shared_data->flags = OWN_LEGION; - } -} - -void -ExecutionTraceParamContext::checkParams() -{ - Trace::InstRecord::setParams(); -} - +/* namespace Trace */ } diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index a825f6a82..8c0fa22cb 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -36,22 +36,24 @@ #include <fstream> #include <vector> -#include "sim/host.hh" -#include "cpu/inst_seq.hh" // for InstSeqNum #include "base/trace.hh" -#include "cpu/thread_context.hh" +#include "cpu/inst_seq.hh" // for InstSeqNum #include "cpu/static_inst.hh" +#include "cpu/thread_context.hh" +#include "sim/host.hh" class ThreadContext; namespace Trace { -class InstRecord : public Record +class InstRecord { protected: typedef TheISA::IntRegFile IntRegFile; + Tick when; + // The following fields are initialized by the constructor and // thus guaranteed to be valid. ThreadContext *thread; @@ -95,10 +97,10 @@ class InstRecord : public Record bool regs_valid; public: - InstRecord(Tick _cycle, ThreadContext *_thread, + InstRecord(Tick _when, ThreadContext *_thread, const StaticInstPtr &_staticInst, Addr _pc, bool spec) - : Record(_cycle), thread(_thread), + : when(_when), thread(_thread), staticInst(_staticInst), PC(_pc), misspeculating(spec) { @@ -110,12 +112,12 @@ class InstRecord : public Record cp_seq_valid = false; } - virtual ~InstRecord() { } - - virtual void dump(std::ostream &outs); + ~InstRecord() { } void setAddr(Addr a) { addr = a; addr_valid = true; } + void setData(Twin64_t d) { data.as_int = d.a; data_status = DataInt64; } + void setData(Twin32_t d) { data.as_int = d.a; data_status = DataInt32; } void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; } void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; } void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; } @@ -136,31 +138,7 @@ class InstRecord : public Record void setRegs(const IntRegFile ®s); - void finalize() { theLog.append(this); } - - enum InstExecFlagBits { - TRACE_MISSPEC = 0, - PRINT_CYCLE, - PRINT_OP_CLASS, - PRINT_THREAD_NUM, - PRINT_RESULT_DATA, - PRINT_EFF_ADDR, - PRINT_INT_REGS, - PRINT_FETCH_SEQ, - PRINT_CP_SEQ, - PRINT_REG_DELTA, - PC_SYMBOL, - INTEL_FORMAT, - LEGION_LOCKSTEP, - NUM_BITS - }; - - static std::vector<bool> flags; - static std::string trace_system; - - static void setParams(); - - static bool traceMisspec() { return flags[TRACE_MISSPEC]; } + void dump(); }; @@ -174,22 +152,22 @@ InstRecord::setRegs(const IntRegFile ®s) regs_valid = true; } -inline -InstRecord * -getInstRecord(Tick cycle, ThreadContext *tc, - const StaticInstPtr staticInst, +inline InstRecord * +getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst, Addr pc) { - if (DTRACE(InstExec) && - (InstRecord::traceMisspec() || !tc->misspeculating())) { - return new InstRecord(cycle, tc, staticInst, pc, - tc->misspeculating()); - } + if (!IsOn(ExecEnable)) + return NULL; - return NULL; -} + if (!Trace::enabled) + return NULL; + if (!IsOn(ExecSpeculative) && tc->misspeculating()) + return NULL; + return new InstRecord(when, tc, staticInst, pc, tc->misspeculating()); } +/* namespace Trace */ } + #endif // __EXETRACE_HH__ diff --git a/src/cpu/intr_control.cc b/src/cpu/intr_control.cc index 4cbc86891..be0f6599b 100644 --- a/src/cpu/intr_control.cc +++ b/src/cpu/intr_control.cc @@ -40,18 +40,14 @@ using namespace std; -IntrControl::IntrControl(const string &name, BaseCPU *c) - : SimObject(name), cpu(c) +IntrControl::IntrControl(const string &name, System *s) + : SimObject(name), sys(s) {} -/* @todo - *Fix the cpu sim object parameter to be a system pointer - *instead, to avoid some extra dereferencing - */ void IntrControl::post(int int_num, int index) { - std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts; + std::vector<ThreadContext *> &tcvec = sys->threadContexts; BaseCPU *temp = tcvec[0]->getCpuPtr(); temp->post_interrupt(int_num, index); } @@ -59,7 +55,7 @@ IntrControl::post(int int_num, int index) void IntrControl::post(int cpu_id, int int_num, int index) { - std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts; + std::vector<ThreadContext *> &tcvec = sys->threadContexts; BaseCPU *temp = tcvec[cpu_id]->getCpuPtr(); temp->post_interrupt(int_num, index); } @@ -67,7 +63,7 @@ IntrControl::post(int cpu_id, int int_num, int index) void IntrControl::clear(int int_num, int index) { - std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts; + std::vector<ThreadContext *> &tcvec = sys->threadContexts; BaseCPU *temp = tcvec[0]->getCpuPtr(); temp->clear_interrupt(int_num, index); } @@ -75,26 +71,26 @@ IntrControl::clear(int int_num, int index) void IntrControl::clear(int cpu_id, int int_num, int index) { - std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts; + std::vector<ThreadContext *> &tcvec = sys->threadContexts; BaseCPU *temp = tcvec[cpu_id]->getCpuPtr(); temp->clear_interrupt(int_num, index); } BEGIN_DECLARE_SIM_OBJECT_PARAMS(IntrControl) - SimObjectParam<BaseCPU *> cpu; + SimObjectParam<System *> sys; END_DECLARE_SIM_OBJECT_PARAMS(IntrControl) BEGIN_INIT_SIM_OBJECT_PARAMS(IntrControl) - INIT_PARAM(cpu, "the cpu") + INIT_PARAM(sys, "the system we are part of") END_INIT_SIM_OBJECT_PARAMS(IntrControl) CREATE_SIM_OBJECT(IntrControl) { - return new IntrControl(getInstanceName(), cpu); + return new IntrControl(getInstanceName(), sys); } REGISTER_SIM_OBJECT("IntrControl", IntrControl) diff --git a/src/cpu/intr_control.hh b/src/cpu/intr_control.hh index 2e3f9e038..c6f75abf0 100644 --- a/src/cpu/intr_control.hh +++ b/src/cpu/intr_control.hh @@ -42,8 +42,8 @@ class IntrControl : public SimObject { public: - BaseCPU *cpu; - IntrControl(const std::string &name, BaseCPU *c); + System *sys; + IntrControl(const std::string &name, System *s); void clear(int int_num, int index = 0); void post(int int_num, int index = 0); diff --git a/src/cpu/memtest/SConscript b/src/cpu/memtest/SConscript new file mode 100644 index 000000000..7b4d6d2c5 --- /dev/null +++ b/src/cpu/memtest/SConscript @@ -0,0 +1,34 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +if 'O3CPU' in env['CPU_MODELS']: + Source('memtest.cc') diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc index 180f41541..607cf1066 100644 --- a/src/cpu/memtest/memtest.cc +++ b/src/cpu/memtest/memtest.cc @@ -226,8 +226,8 @@ MemTest::completeRequest(PacketPtr pkt) assert(removeAddr != outstandingAddrs.end()); outstandingAddrs.erase(removeAddr); - switch (pkt->cmd) { - case Packet::ReadResp: + switch (pkt->cmd.toInt()) { + case MemCmd::ReadResp: if (memcmp(pkt_data, data, pkt->getSize()) != 0) { cerr << name() << ": on read of 0x" << hex << req->getPaddr() @@ -254,7 +254,7 @@ MemTest::completeRequest(PacketPtr pkt) exitSimLoop("Maximum number of loads reached!"); break; - case Packet::WriteResp: + case MemCmd::WriteResp: numWritesStat++; break; /* @@ -369,7 +369,7 @@ MemTest::tick() //This means we assume CPU does write forwarding to reads that alias something //in the cpu store buffer. if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) { - delete result; + delete [] result; delete req; return; } @@ -389,7 +389,7 @@ MemTest::tick() << dec << curTick << endl; } - PacketPtr pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); + PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); pkt->dataDynamicArray(new uint8_t[req->getSize()]); MemTestSenderState *state = new MemTestSenderState(result); pkt->senderState = state; @@ -429,7 +429,7 @@ MemTest::tick() << dec << curTick << endl; } */ - PacketPtr pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); + PacketPtr pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast); uint8_t *pkt_data = new uint8_t[req->getSize()]; pkt->dataDynamicArray(pkt_data); memcpy(pkt_data, &data, req->getSize()); diff --git a/src/cpu/o3/SConscript b/src/cpu/o3/SConscript index afbd4c533..bb1dfb613 100755 --- a/src/cpu/o3/SConscript +++ b/src/cpu/o3/SConscript @@ -26,52 +26,56 @@ # (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: Nathan Binkert -import os -import os.path import sys -# Import build environment variable from SConstruct. -Import('env') +Import('*') +if 'O3CPU' in env['CPU_MODELS']: + Source('base_dyn_inst.cc') + Source('bpred_unit.cc') + Source('commit.cc') + Source('cpu.cc') + Source('decode.cc') + Source('fetch.cc') + Source('free_list.cc') + Source('fu_pool.cc') + Source('iew.cc') + Source('inst_queue.cc') + Source('lsq.cc') + Source('lsq_unit.cc') + Source('mem_dep_unit.cc') + Source('rename.cc') + Source('rename_map.cc') + Source('rob.cc') + Source('scoreboard.cc') + Source('store_set.cc') -################################################################# -# -# Include ISA-specific files for the O3 CPU-model -# -################################################################# - -sources = [] - -if env['TARGET_ISA'] == 'alpha': - sources += Split(''' - alpha/dyn_inst.cc - alpha/cpu.cc - alpha/thread_context.cc - alpha/cpu_builder.cc - ''') -elif env['TARGET_ISA'] == 'mips': - sources += Split(''' - mips/dyn_inst.cc - mips/cpu.cc - mips/thread_context.cc - mips/cpu_builder.cc - ''') -elif env['TARGET_ISA'] == 'sparc': - 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']) - + if env['TARGET_ISA'] == 'alpha': + Source('alpha/cpu.cc') + Source('alpha/cpu_builder.cc') + Source('alpha/dyn_inst.cc') + Source('alpha/thread_context.cc') + elif env['TARGET_ISA'] == 'mips': + Source('mips/cpu.cc') + Source('mips/cpu_builder.cc') + Source('mips/dyn_inst.cc') + Source('mips/thread_context.cc') + elif env['TARGET_ISA'] == 'sparc': + Source('sparc/cpu.cc') + Source('sparc/cpu_builder.cc') + Source('sparc/dyn_inst.cc') + Source('sparc/thread_context.cc') + else: + sys.exit('O3 CPU does not support the \'%s\' ISA' % env['TARGET_ISA']) -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] + if env['USE_CHECKER']: + Source('checker_builder.cc') -Return('sources') +if 'O3CPU' in env['CPU_MODELS'] or 'OzoneCPU' in env['CPU_MODELS']: + Source('2bit_local_pred.cc') + Source('btb.cc') + Source('ras.cc') + Source('tournament_pred.cc') diff --git a/src/cpu/o3/SConsopts b/src/cpu/o3/SConsopts new file mode 100644 index 000000000..040352e6a --- /dev/null +++ b/src/cpu/o3/SConsopts @@ -0,0 +1,34 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +all_cpu_list.append('O3CPU') +default_cpus.append('O3CPU') diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh index 4a2086296..676893098 100644 --- a/src/cpu/o3/alpha/cpu.hh +++ b/src/cpu/o3/alpha/cpu.hh @@ -106,21 +106,21 @@ class AlphaO3CPU : public FullO3CPU<Impl> #endif /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscRegNoEffect(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, unsigned tid); + TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val, + void setMiscRegNoEffect(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. */ - void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val, + void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); /** Initiates a squash of all in-flight instructions for a given diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh index 7799d8f05..304ee6c38 100644 --- a/src/cpu/o3/alpha/cpu_impl.hh +++ b/src/cpu/o3/alpha/cpu_impl.hh @@ -155,32 +155,32 @@ AlphaO3CPU<Impl>::regStats() template <class Impl> TheISA::MiscReg -AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) +AlphaO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid) { - return this->regFile.readMiscReg(misc_reg, tid); + return this->regFile.readMiscRegNoEffect(misc_reg, tid); } template <class Impl> TheISA::MiscReg -AlphaO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid) +AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) { - return this->regFile.readMiscRegWithEffect(misc_reg, tid); + return this->regFile.readMiscReg(misc_reg, tid); } template <class Impl> void -AlphaO3CPU<Impl>::setMiscReg(int misc_reg, const TheISA::MiscReg &val, +AlphaO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid) { - this->regFile.setMiscReg(misc_reg, val, tid); + this->regFile.setMiscRegNoEffect(misc_reg, val, tid); } template <class Impl> void -AlphaO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, +AlphaO3CPU<Impl>::setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid) { - this->regFile.setMiscRegWithEffect(misc_reg, val, tid); + this->regFile.setMiscReg(misc_reg, val, tid); } template <class Impl> @@ -210,7 +210,7 @@ Fault AlphaO3CPU<Impl>::hwrei(unsigned tid) { // Need to clear the lock flag upon returning from an interrupt. - this->setMiscReg(AlphaISA::MISCREG_LOCKFLAG, false, tid); + this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); this->thread[tid]->kernelStats->hwrei(); diff --git a/src/cpu/o3/alpha/dyn_inst.hh b/src/cpu/o3/alpha/dyn_inst.hh index 603a1b52d..20759d849 100644 --- a/src/cpu/o3/alpha/dyn_inst.hh +++ b/src/cpu/o3/alpha/dyn_inst.hh @@ -95,39 +95,39 @@ class AlphaDynInst : public BaseDynInst<Impl> public: /** Reads a miscellaneous register. */ - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg) { - return this->cpu->readMiscReg(misc_reg, this->threadNumber); + return this->cpu->readMiscRegNoEffect(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) + MiscReg readMiscReg(int misc_reg) { - return this->cpu->readMiscRegWithEffect(misc_reg, this->threadNumber); + return this->cpu->readMiscReg(misc_reg, this->threadNumber); } /** Sets a misc. register. */ - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { this->instResult.integer = val; - return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); + return this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber); } /** Sets a misc. register, including any side-effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val) { - return this->cpu->setMiscRegWithEffect(misc_reg, val, + return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); } /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) + TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) { - return this->cpu->readMiscReg( + return this->cpu->readMiscRegNoEffect( si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, this->threadNumber); } @@ -135,18 +135,18 @@ class AlphaDynInst : public BaseDynInst<Impl> /** Reads a misc. register, including any side-effects the read * might have as defined by the architecture. */ - TheISA::MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) { - return this->cpu->readMiscRegWithEffect( + return this->cpu->readMiscReg( si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, this->threadNumber); } /** Sets a misc. register. */ - void setMiscRegOperand(const StaticInst * si, int idx, const MiscReg &val) + void setMiscRegOperandNoEffect(const StaticInst * si, int idx, const MiscReg &val) { this->instResult.integer = val; - return this->cpu->setMiscReg( + return this->cpu->setMiscRegNoEffect( si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, val, this->threadNumber); } @@ -154,10 +154,10 @@ class AlphaDynInst : public BaseDynInst<Impl> /** Sets a misc. register, including any side-effects the write * might have as defined by the architecture. */ - void setMiscRegOperandWithEffect(const StaticInst *si, int idx, + void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val) { - return this->cpu->setMiscRegWithEffect( + return this->cpu->setMiscReg( si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, val, this->threadNumber); } diff --git a/src/cpu/o3/alpha/dyn_inst_impl.hh b/src/cpu/o3/alpha/dyn_inst_impl.hh index 50cdec408..fdce1ade5 100644 --- a/src/cpu/o3/alpha/dyn_inst_impl.hh +++ b/src/cpu/o3/alpha/dyn_inst_impl.hh @@ -118,7 +118,7 @@ AlphaDynInst<Impl>::hwrei() return new AlphaISA::UnimplementedOpcodeFault; // Set the next PC based on the value of the EXC_ADDR IPR. - this->setNextPC(this->cpu->readMiscReg(AlphaISA::IPR_EXC_ADDR, + this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, this->threadNumber)); // Tell CPU to clear any state it needs to if a hwrei is taken. diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index b42a6f523..c17c8836d 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -1148,7 +1148,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) if (head_inst->traceData) { head_inst->traceData->setFetchSeq(head_inst->seqNum); head_inst->traceData->setCPSeq(thread[tid]->numInst); - head_inst->traceData->finalize(); + head_inst->traceData->dump(); + delete head_inst->traceData; head_inst->traceData = NULL; } diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index f9e094d75..354e3c490 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -45,7 +45,7 @@ #include "cpu/o3/isa_specific.hh" #include "cpu/o3/cpu.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/stat_control.hh" #if USE_CHECKER @@ -557,12 +557,6 @@ template <class Impl> void FullO3CPU<Impl>::activateContext(int tid, int delay) { -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - threadContexts[tid]->connectMemPorts(); -#endif - // Needs to set each stage to running as well. if (delay){ DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " @@ -781,6 +775,18 @@ FullO3CPU<Impl>::activateWhenReady(int tid) } } +#if FULL_SYSTEM +template <class Impl> +void +FullO3CPU<Impl>::updateMemPorts() +{ + // Update all ThreadContext's memory ports (Functional/Virtual + // Ports) + for (int i = 0; i < thread.size(); ++i) + thread[i]->connectMemPorts(); +} +#endif + template <class Impl> void FullO3CPU<Impl>::serialize(std::ostream &os) @@ -941,7 +947,7 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) activityRec.reset(); - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort()); fetch.takeOverFrom(); decode.takeOverFrom(); @@ -978,25 +984,6 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) } if (!tickEvent.scheduled()) tickEvent.schedule(nextCycle()); - - Port *peer; - Port *icachePort = fetch.getIcachePort(); - if (icachePort->getPeer() == NULL) { - peer = oldCPU->getPort("icache_port")->getPeer(); - icachePort->setPeer(peer); - } else { - peer = icachePort->getPeer(); - } - peer->setPeer(icachePort); - - Port *dcachePort = iew.getDcachePort(); - if (dcachePort->getPeer() == NULL) { - peer = oldCPU->getPort("dcache_port")->getPeer(); - dcachePort->setPeer(peer); - } else { - peer = dcachePort->getPeer(); - } - peer->setPeer(dcachePort); } template <class Impl> diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index b47c2a494..0ab20ba2a 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -361,6 +361,10 @@ class FullO3CPU : public BaseO3CPU { return globalSeqNum++; } #if FULL_SYSTEM + /** Update the Virt and Phys ports of all ThreadContexts to + * reflect change in memory connections. */ + void updateMemPorts(); + /** Check if this address is a valid instruction address. */ bool validInstAddr(Addr addr) { return true; } diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 279513493..c37f8007e 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -45,6 +45,10 @@ template <class Impl> class SparcDynInst; struct SparcSimpleImpl; typedef SparcDynInst<SparcSimpleImpl> O3DynInst; +#elif THE_ISA == X86_ISA + template <class Impl> class X86DynInst; + struct X86SimpleImpl; + typedef X86DynInst<X86SimpleImpl> O3DynInst; #else #error "O3DynInst not defined for this ISA" #endif diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 8347ed775..da7ce00f5 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -33,6 +33,7 @@ #define __CPU_O3_FETCH_HH__ #include "arch/utility.hh" +#include "arch/predecoder.hh" #include "base/statistics.hh" #include "base/timebuf.hh" #include "cpu/pc_event.hh" @@ -338,6 +339,9 @@ class DefaultFetch /** BPredUnit. */ BPredUnit branchPred; + /** Predecoder. */ + TheISA::Predecoder predecoder; + /** Per-thread fetch PC. */ Addr PC[Impl::MaxThreads]; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index a8727a425..663cd3142 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -40,7 +40,7 @@ #include "mem/request.hh" #include "sim/byteswap.hh" #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" #if FULL_SYSTEM #include "arch/tlb.hh" @@ -103,6 +103,7 @@ DefaultFetch<Impl>::IcachePort::recvRetry() template<class Impl> DefaultFetch<Impl>::DefaultFetch(Params *params) : branchPred(params), + predecoder(NULL), decodeToFetchDelay(params->decodeToFetchDelay), renameToFetchDelay(params->renameToFetchDelay), iewToFetchDelay(params->iewToFetchDelay), @@ -602,7 +603,7 @@ 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); + MemCmd::ReadReq, Packet::Broadcast); data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]); cacheDataPC[tid] = block_PC; @@ -1119,13 +1120,10 @@ DefaultFetch<Impl>::fetch(bool &status_change) inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *> (&cacheData[tid][offset])); -#if THE_ISA == ALPHA_ISA - ext_inst = TheISA::makeExtMI(inst, fetch_PC); -#elif THE_ISA == SPARC_ISA - ext_inst = TheISA::makeExtMI(inst, cpu->thread[tid]->getTC()); -#elif THE_ISA == MIPS_ISA - ext_inst = TheISA::makeExtMI(inst, cpu->thread[tid]->getTC()); -#endif + predecoder.setTC(cpu->thread[tid]->getTC()); + predecoder.moreBytes(fetch_PC, 0, inst); + + ext_inst = predecoder.getExtMachInst(); // Create a new DynInst from the instruction fetched. DynInstPtr instruction = new DynInst(ext_inst, diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 87bf60dfa..79e03d4bf 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -32,7 +32,7 @@ #include <limits> #include <vector> -#include "sim/root.hh" +#include "sim/core.hh" #include "cpu/o3/fu_pool.hh" #include "cpu/o3/inst_queue.hh" diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index e68085cfd..80f53a726 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -300,6 +300,8 @@ class LSQ { bool snoopRangeSent; + virtual void setPeer(Port *port); + protected: /** Atomic version of receive. Panics. */ virtual Tick recvAtomic(PacketPtr pkt); @@ -327,6 +329,11 @@ class LSQ { /** D-cache port. */ DcachePort dcachePort; +#if FULL_SYSTEM + /** Tell the CPU to update the Phys and Virt ports. */ + void updateMemPorts() { cpu->updateMemPorts(); } +#endif + protected: /** The LSQ policy for SMT mode. */ LSQPolicy lsqPolicy; diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index fb738f7c9..d4994fcb7 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -34,6 +34,19 @@ #include "cpu/o3/lsq.hh" +template<class Impl> +void +LSQ<Impl>::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + lsq->updateMemPorts(); +#endif +} + template <class Impl> Tick LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 704d2183d..1b10843f5 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -583,7 +583,8 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx) "addr %#x, data %#x\n", store_idx, req->getVaddr(), data); - PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); + PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq, + Packet::Broadcast); data_pkt->dataStatic(load_inst->memData); WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this); @@ -653,7 +654,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx) // if we the cache is not blocked, do cache access if (!lsq->cacheBlocked()) { PacketPtr data_pkt = - new Packet(req, Packet::ReadReq, Packet::Broadcast); + new Packet(req, MemCmd::ReadReq, Packet::Broadcast); data_pkt->dataStatic(load_inst->memData); LSQSenderState *state = new LSQSenderState; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index ed331386b..e70c960b3 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -656,7 +656,8 @@ LSQUnit<Impl>::writebackStores() (sizeof(TheISA::IntReg) - req->getSize()) : 0), req->getSize()); - PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); + PacketPtr data_pkt = new Packet(req, MemCmd::WriteReq, + Packet::Broadcast); data_pkt->dataStatic(inst->memData); LSQSenderState *state = new LSQSenderState; diff --git a/src/cpu/o3/mips/cpu.hh b/src/cpu/o3/mips/cpu.hh index 7e6268cdf..0361c1814 100755 --- a/src/cpu/o3/mips/cpu.hh +++ b/src/cpu/o3/mips/cpu.hh @@ -87,20 +87,20 @@ class MipsO3CPU : public FullO3CPU<Impl> } /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscRegNoEffect(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, unsigned tid); + TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); + void setMiscRegNoEffect(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. */ - void setMiscRegWithEffect(int misc_reg, + void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); /** Initiates a squash of all in-flight instructions for a given diff --git a/src/cpu/o3/mips/cpu_impl.hh b/src/cpu/o3/mips/cpu_impl.hh index e7dbd3aba..317fd748e 100644 --- a/src/cpu/o3/mips/cpu_impl.hh +++ b/src/cpu/o3/mips/cpu_impl.hh @@ -135,31 +135,31 @@ MipsO3CPU<Impl>::regStats() template <class Impl> MiscReg -MipsO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) +MipsO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid) { - return this->regFile.readMiscReg(misc_reg, tid); + return this->regFile.readMiscRegNoEffect(misc_reg, tid); } template <class Impl> MiscReg -MipsO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid) +MipsO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) { - return this->regFile.readMiscRegWithEffect(misc_reg, tid); + return this->regFile.readMiscReg(misc_reg, tid); } template <class Impl> void -MipsO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +MipsO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid) { - this->regFile.setMiscReg(misc_reg, val, tid); + this->regFile.setMiscRegNoEffect(misc_reg, val, tid); } template <class Impl> void -MipsO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val, +MipsO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) { - this->regFile.setMiscRegWithEffect(misc_reg, val, tid); + this->regFile.setMiscReg(misc_reg, val, tid); } template <class Impl> diff --git a/src/cpu/o3/mips/dyn_inst.hh b/src/cpu/o3/mips/dyn_inst.hh index f53530908..366b4bb23 100755 --- a/src/cpu/o3/mips/dyn_inst.hh +++ b/src/cpu/o3/mips/dyn_inst.hh @@ -93,32 +93,32 @@ class MipsDynInst : public BaseDynInst<Impl> public: /** Reads a miscellaneous register. */ - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg) { - return this->cpu->readMiscReg(misc_reg, this->threadNumber); + return this->cpu->readMiscRegNoEffect(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) + MiscReg readMiscReg(int misc_reg) { - return this->cpu->readMiscRegWithEffect(misc_reg, this->threadNumber); + return this->cpu->readMiscReg(misc_reg, this->threadNumber); } /** Sets a misc. register. */ - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { this->instResult.integer = val; - this->cpu->setMiscReg(misc_reg, val, this->threadNumber); + this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber); } /** Sets a misc. register, including any side-effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val) { - return this->cpu->setMiscRegWithEffect(misc_reg, val, + return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); } diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index 598af123e..c4f8f3a9f 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -225,26 +225,26 @@ class PhysRegFile floatRegFile[reg_idx].q = val; } - MiscReg readMiscReg(int misc_reg, unsigned thread_id) + MiscReg readMiscRegNoEffect(int misc_reg, unsigned thread_id) { - return miscRegs[thread_id].readReg(misc_reg); + return miscRegs[thread_id].readRegNoEffect(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg, unsigned thread_id) + MiscReg readMiscReg(int misc_reg, unsigned thread_id) { - return miscRegs[thread_id].readRegWithEffect(misc_reg, + return miscRegs[thread_id].readReg(misc_reg, cpu->tcBase(thread_id)); } - void setMiscReg(int misc_reg, const MiscReg &val, unsigned thread_id) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned thread_id) { - miscRegs[thread_id].setReg(misc_reg, val); + miscRegs[thread_id].setRegNoEffect(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val, + void setMiscReg(int misc_reg, const MiscReg &val, unsigned thread_id) { - miscRegs[thread_id].setRegWithEffect(misc_reg, val, + miscRegs[thread_id].setReg(misc_reg, val, cpu->tcBase(thread_id)); } diff --git a/src/cpu/o3/sparc/cpu.hh b/src/cpu/o3/sparc/cpu.hh index 08ebd2710..7b932e429 100644 --- a/src/cpu/o3/sparc/cpu.hh +++ b/src/cpu/o3/sparc/cpu.hh @@ -106,20 +106,20 @@ class SparcO3CPU : public FullO3CPU<Impl> #endif /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscRegNoEffect(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, unsigned tid); + TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); + void setMiscRegNoEffect(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. */ - void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val, + void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); /** Initiates a squash of all in-flight instructions for a given diff --git a/src/cpu/o3/sparc/cpu_impl.hh b/src/cpu/o3/sparc/cpu_impl.hh index c039a8fec..a425a8a56 100644 --- a/src/cpu/o3/sparc/cpu_impl.hh +++ b/src/cpu/o3/sparc/cpu_impl.hh @@ -153,32 +153,32 @@ SparcO3CPU<Impl>::regStats() template <class Impl> TheISA::MiscReg -SparcO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) +SparcO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid) { - return this->regFile.readMiscReg(misc_reg, tid); + return this->regFile.readMiscRegNoEffect(misc_reg, tid); } template <class Impl> TheISA::MiscReg -SparcO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid) +SparcO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) { - return this->regFile.readMiscRegWithEffect(misc_reg, tid); + return this->regFile.readMiscReg(misc_reg, tid); } template <class Impl> void -SparcO3CPU<Impl>::setMiscReg(int misc_reg, +SparcO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, const SparcISA::MiscReg &val, unsigned tid) { - this->regFile.setMiscReg(misc_reg, val, tid); + this->regFile.setMiscRegNoEffect(misc_reg, val, tid); } template <class Impl> void -SparcO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, +SparcO3CPU<Impl>::setMiscReg(int misc_reg, const SparcISA::MiscReg &val, unsigned tid) { - this->regFile.setMiscRegWithEffect(misc_reg, val, tid); + this->regFile.setMiscReg(misc_reg, val, tid); } template <class Impl> diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh index 4314488b5..72242b161 100644 --- a/src/cpu/o3/sparc/dyn_inst.hh +++ b/src/cpu/o3/sparc/dyn_inst.hh @@ -77,39 +77,39 @@ class SparcDynInst : public BaseDynInst<Impl> public: /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscReg(int misc_reg) + TheISA::MiscReg readMiscRegNoEffect(int misc_reg) { - return this->cpu->readMiscReg(misc_reg, this->threadNumber); + return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber); } /** Reads a misc. register, including any side-effects the read * might have as defined by the architecture. */ - TheISA::MiscReg readMiscRegWithEffect(int misc_reg) + TheISA::MiscReg readMiscReg(int misc_reg) { - return this->cpu->readMiscRegWithEffect(misc_reg, this->threadNumber); + return this->cpu->readMiscReg(misc_reg, this->threadNumber); } /** Sets a misc. register. */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val) { this->instResult.integer = val; - return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); + return this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber); } /** Sets a misc. register, including any side-effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val) + void setMiscReg(int misc_reg, const TheISA::MiscReg &val) { - return this->cpu->setMiscRegWithEffect(misc_reg, val, + return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); } /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) + TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) { - return this->cpu->readMiscReg( + return this->cpu->readMiscRegNoEffect( si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, this->threadNumber); } @@ -117,19 +117,19 @@ class SparcDynInst : public BaseDynInst<Impl> /** Reads a misc. register, including any side-effects the read * might have as defined by the architecture. */ - TheISA::MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) { - return this->cpu->readMiscRegWithEffect( + return this->cpu->readMiscReg( si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, this->threadNumber); } /** Sets a misc. register. */ - void setMiscRegOperand(const StaticInst * si, + void setMiscRegOperandNoEffect(const StaticInst * si, int idx, const TheISA::MiscReg &val) { this->instResult.integer = val; - return this->cpu->setMiscReg( + return this->cpu->setMiscRegNoEffect( si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, val, this->threadNumber); } @@ -137,10 +137,10 @@ class SparcDynInst : public BaseDynInst<Impl> /** Sets a misc. register, including any side-effects the write * might have as defined by the architecture. */ - void setMiscRegOperandWithEffect( + void setMiscRegOperand( const StaticInst *si, int idx, const TheISA::MiscReg &val) { - return this->cpu->setMiscRegWithEffect( + return this->cpu->setMiscReg( si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, val, this->threadNumber); } diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 4987d6eb4..93638673b 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -206,20 +206,20 @@ class O3ThreadContext : public ThreadContext virtual void setNextPC(uint64_t val); /** Reads a miscellaneous register. */ - virtual MiscReg readMiscReg(int misc_reg) - { return cpu->readMiscReg(misc_reg, thread->readTid()); } + virtual MiscReg readMiscRegNoEffect(int misc_reg) + { return cpu->readMiscRegNoEffect(misc_reg, thread->readTid()); } /** Reads a misc. register, including any side-effects the * read might have as defined by the architecture. */ - virtual MiscReg readMiscRegWithEffect(int misc_reg) - { return cpu->readMiscRegWithEffect(misc_reg, thread->readTid()); } + virtual MiscReg readMiscReg(int misc_reg) + { return cpu->readMiscReg(misc_reg, thread->readTid()); } /** Sets a misc. register. */ - virtual void setMiscReg(int misc_reg, const MiscReg &val); + virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val); /** Sets a misc. register, including any side-effects the * write might have as defined by the architecture. */ - virtual void setMiscRegWithEffect(int misc_reg, const MiscReg &val); + virtual void setMiscReg(int misc_reg, const MiscReg &val); /** Returns the number of consecutive store conditional failures. */ // @todo: Figure out where these store cond failures should go. diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index af98fa1f5..a145e046e 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -103,7 +103,7 @@ void O3ThreadContext<Impl>::delVirtPort(VirtualPort *vp) { if (vp != thread->getVirtPort()) { - delete vp->getPeer(); + vp->removeConn(); delete vp; } } @@ -442,9 +442,9 @@ O3ThreadContext<Impl>::setNextPC(uint64_t val) template <class Impl> void -O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) +O3ThreadContext<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { - cpu->setMiscReg(misc_reg, val, thread->readTid()); + cpu->setMiscRegNoEffect(misc_reg, val, thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { @@ -454,10 +454,10 @@ O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) template <class Impl> void -O3ThreadContext<Impl>::setMiscRegWithEffect(int misc_reg, +O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) { - cpu->setMiscRegWithEffect(misc_reg, val, thread->readTid()); + cpu->setMiscReg(misc_reg, val, thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { diff --git a/src/cpu/ozone/SConscript b/src/cpu/ozone/SConscript new file mode 100644 index 000000000..4a040684a --- /dev/null +++ b/src/cpu/ozone/SConscript @@ -0,0 +1,45 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +if 'OzoneCPU' in env['CPU_MODELS']: + need_bp_unit = True + Source('base_dyn_inst.cc') + Source('bpred_unit.cc') + Source('cpu.cc') + Source('cpu_builder.cc') + Source('dyn_inst.cc') + Source('front_end.cc') + Source('lw_back_end.cc') + Source('lw_lsq.cc') + Source('rename_table.cc') + if env['USE_CHECKER']: + Source('checker_builder.cc') diff --git a/src/cpu/ozone/SConsopts b/src/cpu/ozone/SConsopts new file mode 100644 index 000000000..341644dcd --- /dev/null +++ b/src/cpu/ozone/SConsopts @@ -0,0 +1,33 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +all_cpu_list.append('OzoneCPU') diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index baea7a546..2432df55e 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -235,14 +235,14 @@ class OzoneCPU : public BaseCPU public: // ISA stuff: + MiscReg readMiscRegNoEffect(int misc_reg); + MiscReg readMiscReg(int misc_reg); - MiscReg readMiscRegWithEffect(int misc_reg); + void setMiscRegNoEffect(int misc_reg, const MiscReg &val); void setMiscReg(int misc_reg, const MiscReg &val); - void setMiscRegWithEffect(int misc_reg, const MiscReg &val); - unsigned readStCondFailures() { return thread->storeCondFailures; } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index a854de8de..d78162243 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -748,7 +748,7 @@ template <class Impl> void OzoneCPU<Impl>::OzoneTC::delVirtPort(VirtualPort *vp) { - delete vp->getPeer(); + vp->removeConn(); delete vp; } #endif @@ -1089,24 +1089,24 @@ OzoneCPU<Impl>::OzoneTC::setNextPC(Addr val) template <class Impl> TheISA::MiscReg -OzoneCPU<Impl>::OzoneTC::readMiscReg(int misc_reg) +OzoneCPU<Impl>::OzoneTC::readMiscRegNoEffect(int misc_reg) { - return thread->miscRegFile.readReg(misc_reg); + return thread->miscRegFile.readRegNoEffect(misc_reg); } template <class Impl> TheISA::MiscReg -OzoneCPU<Impl>::OzoneTC::readMiscRegWithEffect(int misc_reg) +OzoneCPU<Impl>::OzoneTC::readMiscReg(int misc_reg) { - return thread->miscRegFile.readRegWithEffect(misc_reg, this); + return thread->miscRegFile.readReg(misc_reg, this); } template <class Impl> void -OzoneCPU<Impl>::OzoneTC::setMiscReg(int misc_reg, const MiscReg &val) +OzoneCPU<Impl>::OzoneTC::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { // Needs to setup a squash event unless we're in syscall mode - thread->miscRegFile.setReg(misc_reg, val); + thread->miscRegFile.setRegNoEffect(misc_reg, val); if (!thread->inSyscall) { cpu->squashFromTC(); @@ -1115,10 +1115,10 @@ OzoneCPU<Impl>::OzoneTC::setMiscReg(int misc_reg, const MiscReg &val) template <class Impl> void -OzoneCPU<Impl>::OzoneTC::setMiscRegWithEffect(int misc_reg, const MiscReg &val) +OzoneCPU<Impl>::OzoneTC::setMiscReg(int misc_reg, const MiscReg &val) { // Needs to setup a squash event unless we're in syscall mode - thread->miscRegFile.setRegWithEffect(misc_reg, val, this); + thread->miscRegFile.setReg(misc_reg, val, this); if (!thread->inSyscall) { cpu->squashFromTC(); diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh index 88f96b14b..e138cbe13 100644 --- a/src/cpu/ozone/dyn_inst.hh +++ b/src/cpu/ozone/dyn_inst.hh @@ -231,14 +231,14 @@ class OzoneDynInst : public BaseDynInst<Impl> public: // ISA stuff + MiscReg readMiscRegNoEffect(int misc_reg); + MiscReg readMiscReg(int misc_reg); - MiscReg readMiscRegWithEffect(int misc_reg); + void setMiscRegNoEffect(int misc_reg, const MiscReg &val); void setMiscReg(int misc_reg, const MiscReg &val); - void setMiscRegWithEffect(int misc_reg, const MiscReg &val); - #if FULL_SYSTEM Fault hwrei(); void trap(Fault fault); diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index 05a66d77a..8519917f5 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -219,31 +219,31 @@ OzoneDynInst<Impl>::clearMemDependents() template <class Impl> TheISA::MiscReg -OzoneDynInst<Impl>::readMiscReg(int misc_reg) +OzoneDynInst<Impl>::readMiscRegNoEffect(int misc_reg) { - return this->thread->readMiscReg(misc_reg); + return this->thread->readMiscRegNoEffect(misc_reg); } template <class Impl> TheISA::MiscReg -OzoneDynInst<Impl>::readMiscRegWithEffect(int misc_reg) +OzoneDynInst<Impl>::readMiscReg(int misc_reg) { - return this->thread->readMiscRegWithEffect(misc_reg); + return this->thread->readMiscReg(misc_reg); } template <class Impl> void -OzoneDynInst<Impl>::setMiscReg(int misc_reg, const MiscReg &val) +OzoneDynInst<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { this->setIntResult(val); - this->thread->setMiscReg(misc_reg, val); + this->thread->setMiscRegNoEffect(misc_reg, val); } template <class Impl> void -OzoneDynInst<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val) +OzoneDynInst<Impl>::setMiscReg(int misc_reg, const MiscReg &val) { - this->thread->setMiscRegWithEffect(misc_reg, val); + this->thread->setMiscReg(misc_reg, val); } #if FULL_SYSTEM @@ -255,7 +255,7 @@ OzoneDynInst<Impl>::hwrei() if (!(this->readPC() & 0x3)) return new AlphaISA::UnimplementedOpcodeFault; - this->setNextPC(this->thread->readMiscReg(AlphaISA::IPR_EXC_ADDR)); + this->setNextPC(this->thread->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR)); this->cpu->hwrei(); diff --git a/src/cpu/ozone/inorder_back_end_impl.hh b/src/cpu/ozone/inorder_back_end_impl.hh index 84f935a72..8d7ebb60e 100644 --- a/src/cpu/ozone/inorder_back_end_impl.hh +++ b/src/cpu/ozone/inorder_back_end_impl.hh @@ -89,13 +89,13 @@ InorderBackEnd<Impl>::checkInterrupts() int summary = 0; - if (thread->readMiscReg(IPR_ASTRR)) + if (thread->readMiscRegNoEffect(IPR_ASTRR)) panic("asynchronous traps not implemented\n"); - if (thread->readMiscReg(IPR_SIRR)) { + if (thread->readMiscRegNoEffect(IPR_SIRR)) { for (int i = INTLEVEL_SOFTWARE_MIN; i < INTLEVEL_SOFTWARE_MAX; i++) { - if (thread->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { + if (thread->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) { // See table 4-19 of the 21164 hardware reference ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; summary |= (ULL(1) << i); @@ -116,14 +116,14 @@ InorderBackEnd<Impl>::checkInterrupts() } } - if (ipl && ipl > thread->readMiscReg(IPR_IPLR)) { + if (ipl && ipl > thread->readMiscRegNoEffect(IPR_IPLR)) { thread->inSyscall = true; - thread->setMiscReg(IPR_ISR, summary); - thread->setMiscReg(IPR_INTID, ipl); + thread->setMiscRegNoEffect(IPR_ISR, summary); + thread->setMiscRegNoEffect(IPR_INTID, ipl); Fault(new InterruptFault)->invoke(xc); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - thread->readMiscReg(IPR_IPLR), ipl, summary); + thread->readMiscRegNoEffect(IPR_IPLR), ipl, summary); // May need to go 1 inst prior squashPending = true; diff --git a/src/cpu/ozone/inst_queue_impl.hh b/src/cpu/ozone/inst_queue_impl.hh index 84f2b2a19..ea9d03c0d 100644 --- a/src/cpu/ozone/inst_queue_impl.hh +++ b/src/cpu/ozone/inst_queue_impl.hh @@ -38,7 +38,7 @@ #include <vector> -#include "sim/root.hh" +#include "sim/core.hh" #include "cpu/ozone/inst_queue.hh" #if 0 diff --git a/src/cpu/ozone/lw_back_end_impl.hh b/src/cpu/ozone/lw_back_end_impl.hh index a181c93f4..c0a9cad24 100644 --- a/src/cpu/ozone/lw_back_end_impl.hh +++ b/src/cpu/ozone/lw_back_end_impl.hh @@ -1193,7 +1193,7 @@ LWBackEnd<Impl>::commitInst(int inst_num) #if FULL_SYSTEM if (thread->profile) { // bool usermode = -// (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; +// (xc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; // thread->profilePC = usermode ? 1 : inst->readPC(); thread->profilePC = inst->readPC(); ProfileNode *node = thread->profile->consume(thread->getTC(), diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index ee1968626..f26b06453 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -605,12 +605,12 @@ OzoneLWLSQ<Impl>::writebackStores() // @todo: Remove this SC hack once the memory system handles it. if (req->isLocked()) { if (req->isUncacheable()) { - req->setScResult(2); + req->setExtraData(2); } else { if (cpu->lockFlag) { - req->setScResult(1); + req->setExtraData(1); } else { - req->setScResult(0); + req->setExtraData(0); // Hack: Instantly complete this store. completeDataAccess(data_pkt); --sq_it; diff --git a/src/cpu/ozone/thread_state.hh b/src/cpu/ozone/thread_state.hh index a71795851..53776e7d9 100644 --- a/src/cpu/ozone/thread_state.hh +++ b/src/cpu/ozone/thread_state.hh @@ -115,24 +115,24 @@ struct OzoneThreadState : public ThreadState { ThreadContext *getTC() { return tc; } - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg) { - return miscRegFile.readReg(misc_reg); + return miscRegFile.readRegNoEffect(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) + MiscReg readMiscReg(int misc_reg) { - return miscRegFile.readRegWithEffect(misc_reg, tc); + return miscRegFile.readReg(misc_reg, tc); } - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { - miscRegFile.setReg(misc_reg, val); + miscRegFile.setRegNoEffect(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val) { - miscRegFile.setRegWithEffect(misc_reg, val, tc); + miscRegFile.setReg(misc_reg, val, tc); } uint64_t readPC() diff --git a/src/cpu/pc_event.cc b/src/cpu/pc_event.cc index fca357fe3..438218df2 100644 --- a/src/cpu/pc_event.cc +++ b/src/cpu/pc_event.cc @@ -40,7 +40,7 @@ #include "cpu/thread_context.hh" #include "cpu/pc_event.hh" #include "sim/debug.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/system.hh" using namespace std; @@ -138,14 +138,12 @@ BreakPCEvent::process(ThreadContext *tc) } #if FULL_SYSTEM -extern "C" void sched_break_pc_sys(System *sys, Addr addr) { new BreakPCEvent(&sys->pcEventQueue, "debug break", addr, true); } -extern "C" void sched_break_pc(Addr addr) { diff --git a/src/cpu/simple/SConscript b/src/cpu/simple/SConscript new file mode 100644 index 000000000..9a6a80473 --- /dev/null +++ b/src/cpu/simple/SConscript @@ -0,0 +1,43 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +need_simple_base = False +if 'AtomicSimpleCPU' in env['CPU_MODELS']: + need_simple_base = True + Source('atomic.cc') + +if 'TimingSimpleCPU' in env['CPU_MODELS']: + need_simple_base = True + Source('timing.cc') + +if need_simple_base: + Source('base.cc') diff --git a/src/cpu/simple/SConsopts b/src/cpu/simple/SConsopts new file mode 100644 index 000000000..32dbda1a5 --- /dev/null +++ b/src/cpu/simple/SConsopts @@ -0,0 +1,34 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +all_cpu_list.extend(('AtomicSimpleCPU', 'TimingSimpleCPU')) +default_cpus.extend(('AtomicSimpleCPU', 'TimingSimpleCPU')) diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 3b3536e44..6f69b5ac4 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -31,6 +31,7 @@ #include "arch/locked_mem.hh" #include "arch/mmaped_ipr.hh" #include "arch/utility.hh" +#include "base/bigint.hh" #include "cpu/exetrace.hh" #include "cpu/simple/atomic.hh" #include "mem/packet.hh" @@ -125,6 +126,17 @@ AtomicSimpleCPU::CpuPort::recvRetry() panic("AtomicSimpleCPU doesn't expect recvRetry callback!"); } +void +AtomicSimpleCPU::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + cpu->tcBase()->connectMemPorts(); +#endif +} AtomicSimpleCPU::AtomicSimpleCPU(Params *p) : BaseSimpleCPU(p), tickEvent(this), @@ -138,18 +150,20 @@ AtomicSimpleCPU::AtomicSimpleCPU(Params *p) ifetch_req = new Request(); ifetch_req->setThreadContext(p->cpu_id, 0); // Add thread ID if we add MT - ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); + ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); ifetch_pkt->dataStatic(&inst); data_read_req = new Request(); data_read_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too - data_read_pkt = new Packet(data_read_req, Packet::ReadReq, + data_read_pkt = new Packet(data_read_req, MemCmd::ReadReq, Packet::Broadcast); data_read_pkt->dataStatic(&dataReg); data_write_req = new Request(); data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too - data_write_pkt = new Packet(data_write_req, Packet::WriteReq, + data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq, + Packet::Broadcast); + data_swap_pkt = new Packet(data_write_req, MemCmd::SwapReq, Packet::Broadcast); } @@ -208,7 +222,7 @@ AtomicSimpleCPU::switchOut() void AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) { - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); assert(!tickEvent.scheduled()); @@ -239,12 +253,6 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay) notIdleFraction++; -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - tc->connectMemPorts(); -#endif - //Make sure ticks are still on multiples of cycles tickEvent.schedule(nextCycle(curTick + cycles(delay))); _status = Running; @@ -318,6 +326,14 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) template Fault +AtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); + +template +Fault +AtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); + +template +Fault AtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); template @@ -363,10 +379,15 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { // use the CPU's statically allocated write request and packet objects Request *req = data_write_req; - PacketPtr pkt = data_write_pkt; + PacketPtr pkt; req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); + if (req->isSwap()) + pkt = data_swap_pkt; + else + pkt = data_write_pkt; + if (traceData) { traceData->setAddr(addr); } @@ -381,6 +402,11 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) if (req->isLocked()) { do_access = TheISA::handleLockedWrite(thread, req); } + if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); + } + if (do_access) { pkt->reinitFromRequest(); @@ -401,15 +427,11 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) #endif } - if (req->isLocked()) { - uint64_t scResult = req->getScResult(); - if (scResult != 0) { - // clear failure counter - thread->setStCondFailures(0); - } - if (res) { - *res = req->getScResult(); - } + if (req->isSwap()) { + assert(res); + *res = pkt->get<T>(); + } else if (res) { + *res = req->getExtraData(); } } @@ -424,6 +446,17 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) #ifndef DOXYGEN_SHOULD_SKIP_THIS + +template +Fault +AtomicSimpleCPU::write(Twin32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +AtomicSimpleCPU::write(Twin64_t data, Addr addr, + unsigned flags, uint64_t *res); + template Fault AtomicSimpleCPU::write(uint64_t data, Addr addr, @@ -483,17 +516,28 @@ AtomicSimpleCPU::tick() Fault fault = setupFetchRequest(ifetch_req); if (fault == NoFault) { - ifetch_pkt->reinitFromRequest(); + Tick icache_latency = 0; + bool icache_access = false; + dcache_access = false; // assume no dcache access - Tick icache_latency = icachePort.sendAtomic(ifetch_pkt); - // ifetch_req is initialized to read the instruction directly - // into the CPU object's inst field. + //Fetch more instruction memory if necessary + if(predecoder.needMoreBytes()) + { + icache_access = true; + ifetch_pkt->reinitFromRequest(); + + icache_latency = icachePort.sendAtomic(ifetch_pkt); + // ifetch_req is initialized to read the instruction directly + // into the CPU object's inst field. + } - dcache_access = false; // assume no dcache access preExecute(); - fault = curStaticInst->execute(this, traceData); - postExecute(); + if(curStaticInst) + { + fault = curStaticInst->execute(this, traceData); + postExecute(); + } // @todo remove me after debugging with legion done if (curStaticInst && (!curStaticInst->isMicroOp() || @@ -501,7 +545,8 @@ AtomicSimpleCPU::tick() instCnt++; if (simulate_stalls) { - Tick icache_stall = icache_latency - cycles(1); + Tick icache_stall = + icache_access ? icache_latency - cycles(1) : 0; Tick dcache_stall = dcache_access ? dcache_latency - cycles(1) : 0; Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1); @@ -512,8 +557,8 @@ AtomicSimpleCPU::tick() } } - - advancePC(fault); + if(predecoder.needMoreBytes()) + advancePC(fault); } if (_status != Idle) diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 42c7bf23a..ad4aa4708 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -81,9 +81,6 @@ class AtomicSimpleCPU : public BaseSimpleCPU class CpuPort : public Port { - - AtomicSimpleCPU *cpu; - public: CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu) @@ -94,6 +91,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU protected: + AtomicSimpleCPU *cpu; + virtual bool recvTiming(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt); @@ -110,7 +109,17 @@ class AtomicSimpleCPU : public BaseSimpleCPU }; CpuPort icachePort; - CpuPort dcachePort; + + class DcachePort : public CpuPort + { + public: + DcachePort(const std::string &_name, AtomicSimpleCPU *_cpu) + : CpuPort(_name, _cpu) + { } + + virtual void setPeer(Port *port); + }; + DcachePort dcachePort; Request *ifetch_req; PacketPtr ifetch_pkt; @@ -118,6 +127,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU PacketPtr data_read_pkt; Request *data_write_req; PacketPtr data_write_pkt; + PacketPtr data_swap_pkt; bool dcache_access; Tick dcache_latency; diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index b8d1f3bed..877dc5bd4 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -70,7 +70,7 @@ using namespace std; using namespace TheISA; BaseSimpleCPU::BaseSimpleCPU(Params *p) - : BaseCPU(p), thread(NULL) + : BaseCPU(p), thread(NULL), predecoder(NULL) { #if FULL_SYSTEM thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); @@ -301,7 +301,7 @@ BaseSimpleCPU::post_interrupt(int int_num, int index) BaseCPU::post_interrupt(int_num, index); if (thread->status() == ThreadContext::Suspended) { - DPRINTF(IPI,"Suspended Processor awoke\n"); + DPRINTF(Quiesce,"Suspended Processor awoke\n"); thread->activate(); } } @@ -367,16 +367,23 @@ BaseSimpleCPU::preExecute() inst = gtoh(inst); //If we're not in the middle of a macro instruction if (!curMacroStaticInst) { -#if THE_ISA == ALPHA_ISA - StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->readPC())); -#elif THE_ISA == SPARC_ISA - StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC())); -#elif THE_ISA == MIPS_ISA - //Mips doesn't do anything in it's MakeExtMI function right now, - //so it won't be called. - StaticInstPtr instPtr = StaticInst::decode(inst); -#endif - if (instPtr->isMacroOp()) { + StaticInstPtr instPtr = NULL; + + //Predecode, ie bundle up an ExtMachInst + //This should go away once the constructor can be set up properly + predecoder.setTC(thread->getTC()); + //If more fetch data is needed, pass it in. + if(predecoder.needMoreBytes()) + predecoder.moreBytes(thread->readPC(), 0, inst); + else + predecoder.process(); + //If an instruction is ready, decode it + if (predecoder.extMachInstReady()) + instPtr = StaticInst::decode(predecoder.getExtMachInst()); + + //If we decoded an instruction and it's microcoded, start pulling + //out micro ops + if (instPtr && instPtr->isMacroOp()) { curMacroStaticInst = instPtr; curStaticInst = curMacroStaticInst-> fetchMicroOp(thread->readMicroPC()); @@ -389,17 +396,19 @@ BaseSimpleCPU::preExecute() fetchMicroOp(thread->readMicroPC()); } + //If we decoded an instruction this "tick", record information about it. + if(curStaticInst) + { + traceData = Trace::getInstRecord(curTick, tc, curStaticInst, + thread->readPC()); - traceData = Trace::getInstRecord(curTick, tc, curStaticInst, - thread->readPC()); - - DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n", - curStaticInst->getName(), curStaticInst->getOpcode(), - curStaticInst->machInst); + DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", + curStaticInst->getName(), curStaticInst->machInst); #if FULL_SYSTEM - thread->setInst(inst); + thread->setInst(inst); #endif // FULL_SYSTEM + } } void @@ -409,7 +418,8 @@ BaseSimpleCPU::postExecute() if (thread->profile) { bool usermode = TheISA::inUserMode(tc); thread->profilePC = usermode ? 1 : thread->readPC(); - ProfileNode *node = thread->profile->consume(tc, inst); + StaticInstPtr si(inst); + ProfileNode *node = thread->profile->consume(tc, si); if (node) thread->profileNode = node; } @@ -427,7 +437,9 @@ BaseSimpleCPU::postExecute() traceFunctions(thread->readPC()); if (traceData) { - traceData->finalize(); + traceData->dump(); + delete traceData; + traceData = NULL; } } @@ -440,9 +452,9 @@ BaseSimpleCPU::advancePC(Fault fault) fault->invoke(tc); thread->setMicroPC(0); thread->setNextMicroPC(1); - } else { + } else if (predecoder.needMoreBytes()) { //If we're at the last micro op for this instruction - if (curStaticInst->isLastMicroOp()) { + if (curStaticInst && curStaticInst->isLastMicroOp()) { //We should be working with a macro op assert(curMacroStaticInst); //Close out this macro op, and clean up the @@ -461,13 +473,9 @@ BaseSimpleCPU::advancePC(Fault fault) } else { // go to the next instruction thread->setPC(thread->readNextPC()); -#if ISA_HAS_DELAY_SLOT thread->setNextPC(thread->readNextNPC()); thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); assert(thread->readNextPC() != thread->readNextNPC()); -#else - thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); -#endif } } diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index c4853b916..787259c96 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -33,6 +33,7 @@ #ifndef __CPU_SIMPLE_BASE_HH__ #define __CPU_SIMPLE_BASE_HH__ +#include "arch/predecoder.hh" #include "base/statistics.hh" #include "config/full_system.hh" #include "cpu/base.hh" @@ -63,6 +64,10 @@ class Process; class RemoteGDB; class GDBListener; +namespace TheISA +{ + class Predecoder; +} class ThreadContext; class Checkpoint; @@ -74,7 +79,6 @@ namespace Trace { class BaseSimpleCPU : public BaseCPU { protected: - typedef TheISA::MachInst MachInst; typedef TheISA::MiscReg MiscReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; @@ -122,10 +126,13 @@ class BaseSimpleCPU : public BaseCPU #endif // current instruction - MachInst inst; + TheISA::MachInst inst; + + // The predecoder + TheISA::Predecoder predecoder; // Static data storage - TheISA::IntReg dataReg; + TheISA::LargestRead dataReg; StaticInstPtr curStaticInst; StaticInstPtr curMacroStaticInst; @@ -284,14 +291,19 @@ class BaseSimpleCPU : public BaseCPU void setNextPC(uint64_t val) { thread->setNextPC(val); } void setNextNPC(uint64_t val) { thread->setNextNPC(val); } + MiscReg readMiscRegNoEffect(int misc_reg) + { + return thread->readMiscRegNoEffect(misc_reg); + } + MiscReg readMiscReg(int misc_reg) { return thread->readMiscReg(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { - return thread->readMiscRegWithEffect(misc_reg); + return thread->setMiscRegNoEffect(misc_reg, val); } void setMiscReg(int misc_reg, const MiscReg &val) @@ -299,9 +311,10 @@ class BaseSimpleCPU : public BaseCPU return thread->setMiscReg(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) { - return thread->setMiscRegWithEffect(misc_reg, val); + int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->readMiscRegNoEffect(reg_idx); } MiscReg readMiscRegOperand(const StaticInst *si, int idx) @@ -310,23 +323,25 @@ class BaseSimpleCPU : public BaseCPU return thread->readMiscReg(reg_idx); } - MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + void setMiscRegOperandNoEffect(const StaticInst *si, int idx, const MiscReg &val) { - int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; - return thread->readMiscRegWithEffect(reg_idx); + int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->setMiscRegNoEffect(reg_idx, val); } - void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val) + void setMiscRegOperand( + const StaticInst *si, int idx, const MiscReg &val) { int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; return thread->setMiscReg(reg_idx, val); } - void setMiscRegOperandWithEffect( - const StaticInst *si, int idx, const MiscReg &val) - { - int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; - return thread->setMiscRegWithEffect(reg_idx, val); + unsigned readStCondFailures() { + return thread->readStCondFailures(); + } + + void setStCondFailures(unsigned sc_failures) { + thread->setStCondFailures(sc_failures); } #if FULL_SYSTEM diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index dfffb0b1f..45da7c3eb 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -30,6 +30,7 @@ #include "arch/locked_mem.hh" #include "arch/utility.hh" +#include "base/bigint.hh" #include "cpu/exetrace.hh" #include "cpu/simple/timing.hh" #include "mem/packet.hh" @@ -193,7 +194,7 @@ TimingSimpleCPU::switchOut() void TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) { - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); // if any of this CPU's ThreadContexts are active, mark the CPU as // running and schedule its tick event. @@ -208,23 +209,6 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) if (_status != Running) { _status = Idle; } - - Port *peer; - if (icachePort.getPeer() == NULL) { - peer = oldCPU->getPort("icache_port")->getPeer(); - icachePort.setPeer(peer); - } else { - peer = icachePort.getPeer(); - } - peer->setPeer(&icachePort); - - if (dcachePort.getPeer() == NULL) { - peer = oldCPU->getPort("dcache_port")->getPeer(); - dcachePort.setPeer(peer); - } else { - peer = dcachePort.getPeer(); - } - peer->setPeer(&dcachePort); } @@ -239,12 +223,6 @@ TimingSimpleCPU::activateContext(int thread_num, int delay) notIdleFraction++; _status = Running; -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - tc->connectMemPorts(); -#endif - // kick things off by initiating the fetch of the next instruction fetchEvent = new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false); @@ -286,7 +264,7 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // Now do the access. if (fault == NoFault) { PacketPtr pkt = - new Packet(req, Packet::ReadReq, Packet::Broadcast); + new Packet(req, MemCmd::ReadReq, Packet::Broadcast); pkt->dataDynamic<T>(new T); if (!dcachePort.sendTiming(pkt)) { @@ -297,14 +275,14 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // memory system takes ownership of packet dcache_pkt = NULL; } + + // This will need a new way to tell if it has a dcache attached. + if (req->isUncacheable()) + recordEvent("Uncached Read"); } else { delete req; } - // This will need a new way to tell if it has a dcache attached. - if (req->isUncacheable()) - recordEvent("Uncached Read"); - return fault; } @@ -312,6 +290,14 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) template Fault +TimingSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); + +template +Fault +TimingSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); + +template +Fault TimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); template @@ -359,13 +345,20 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), cpu_id, /* thread ID */ 0); + if (traceData) { + traceData->setAddr(req->getVaddr()); + } + // translate to physical address Fault fault = thread->translateDataWriteReq(req); // Now do the access. if (fault == NoFault) { assert(dcache_pkt == NULL); - dcache_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); + if (req->isSwap()) + dcache_pkt = new Packet(req, MemCmd::SwapReq, Packet::Broadcast); + else + dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast); dcache_pkt->allocate(); dcache_pkt->set(data); @@ -374,6 +367,10 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) if (req->isLocked()) { do_access = TheISA::handleLockedWrite(thread, req); } + if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); + } if (do_access) { if (!dcachePort.sendTiming(dcache_pkt)) { @@ -384,13 +381,13 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) dcache_pkt = NULL; } } + // This will need a new way to tell if it's hooked up to a cache or not. + if (req->isUncacheable()) + recordEvent("Uncached Write"); } else { delete req; } - // This will need a new way to tell if it's hooked up to a cache or not. - if (req->isUncacheable()) - recordEvent("Uncached Write"); // If the write needs to have a fault on the access, consider calling // changeStatus() and changing it to "bad addr write" or something. @@ -401,6 +398,16 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) #ifndef DOXYGEN_SHOULD_SKIP_THIS template Fault +TimingSimpleCPU::write(Twin32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +TimingSimpleCPU::write(Twin64_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault TimingSimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); @@ -454,7 +461,7 @@ TimingSimpleCPU::fetch() ifetch_req->setThreadContext(cpu_id, /* thread ID */ 0); Fault fault = setupFetchRequest(ifetch_req); - ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); + ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); ifetch_pkt->dataStatic(&inst); if (fault == NoFault) { @@ -629,6 +636,18 @@ TimingSimpleCPU::completeDrain() drainEvent->process(); } +void +TimingSimpleCPU::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + cpu->tcBase()->connectMemPorts(); +#endif +} + bool TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) { diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index abcb224bf..ef062d24a 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -144,6 +144,8 @@ class TimingSimpleCPU : public BaseSimpleCPU : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu) { } + virtual void setPeer(Port *port); + protected: virtual bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 13d0e2e29..39f31782b 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -305,7 +305,7 @@ void SimpleThread::delVirtPort(VirtualPort *vp) { if (vp != virtPort) { - delete vp->getPeer(); + vp->removeConn(); delete vp; } } diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index f2f79c070..824914ad0 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -350,24 +350,24 @@ class SimpleThread : public ThreadState regs.setNextNPC(val); } - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg) { - return regs.readMiscReg(misc_reg); + return regs.readMiscRegNoEffect(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) + MiscReg readMiscReg(int misc_reg) { - return regs.readMiscRegWithEffect(misc_reg, tc); + return regs.readMiscReg(misc_reg, tc); } - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { - return regs.setMiscReg(misc_reg, val); + return regs.setMiscRegNoEffect(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val) { - return regs.setMiscRegWithEffect(misc_reg, val, tc); + return regs.setMiscReg(misc_reg, val, tc); } unsigned readStCondFailures() { return storeCondFailures; } diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc index cb4a7cdf7..64fcc0580 100644 --- a/src/cpu/static_inst.cc +++ b/src/cpu/static_inst.cc @@ -31,7 +31,7 @@ #include <iostream> #include "cpu/static_inst.hh" -#include "sim/root.hh" +#include "sim/core.hh" StaticInstPtr StaticInst::nullStaticInstPtr; diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 416c8ab56..a58ac85d6 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -35,6 +35,7 @@ #include <string> #include "arch/isa_traits.hh" +#include "arch/utility.hh" #include "sim/faults.hh" #include "base/bitfield.hh" #include "base/hashmap.hh" @@ -439,9 +440,6 @@ class StaticInst : public StaticInstBase //This is defined as inline below. static StaticInstPtr decode(ExtMachInst mach_inst); - /// Return opcode of machine instruction - uint32_t getOpcode() { return bits(machInst, 31, 26);} - /// Return name of machine instruction std::string getName() { return mnemonic; } }; @@ -474,7 +472,7 @@ class StaticInstPtr : public RefCountingPtr<StaticInst> /// Construct directly from machine instruction. /// Calls StaticInst::decode(). - StaticInstPtr(TheISA::ExtMachInst mach_inst) + explicit StaticInstPtr(TheISA::ExtMachInst mach_inst) : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst)) { } diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 16e491fd3..05c409c95 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -226,14 +226,14 @@ class ThreadContext virtual void setNextNPC(uint64_t val) = 0; + virtual MiscReg readMiscRegNoEffect(int misc_reg) = 0; + virtual MiscReg readMiscReg(int misc_reg) = 0; - virtual MiscReg readMiscRegWithEffect(int misc_reg) = 0; + virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val) = 0; virtual void setMiscReg(int misc_reg, const MiscReg &val) = 0; - virtual void setMiscRegWithEffect(int misc_reg, const MiscReg &val) = 0; - // Also not necessarily the best location for these two. Hopefully will go // away once we decide upon where st cond failures goes. virtual unsigned readStCondFailures() = 0; @@ -254,6 +254,8 @@ class ThreadContext // Same with st cond failures. virtual Counter readFuncExeInst() = 0; + virtual void syscall(int64_t callnum) = 0; + // 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 calls the exit syscall. @@ -410,18 +412,18 @@ class ProxyThreadContext : public ThreadContext void setNextNPC(uint64_t val) { actualTC->setNextNPC(val); } + MiscReg readMiscRegNoEffect(int misc_reg) + { return actualTC->readMiscRegNoEffect(misc_reg); } + MiscReg readMiscReg(int misc_reg) { return actualTC->readMiscReg(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) - { return actualTC->readMiscRegWithEffect(misc_reg); } + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) + { return actualTC->setMiscRegNoEffect(misc_reg, val); } void setMiscReg(int misc_reg, const MiscReg &val) { return actualTC->setMiscReg(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) - { return actualTC->setMiscRegWithEffect(misc_reg, val); } - unsigned readStCondFailures() { return actualTC->readStCondFailures(); } @@ -441,6 +443,9 @@ class ProxyThreadContext : public ThreadContext void setSyscallReturn(SyscallReturn return_value) { actualTC->setSyscallReturn(return_value); } + void syscall(int64_t callnum) + { actualTC->syscall(callnum); } + Counter readFuncExeInst() { return actualTC->readFuncExeInst(); } #endif diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 93dd1e2eb..4b65ca4b8 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -125,7 +125,10 @@ ThreadState::connectPhysPort() // @todo: For now this disregards any older port that may have // already existed. Fix this memory leak once the bus port IDs // for functional ports is resolved. - physPort = new FunctionalPort(csprintf("%s-%d-funcport", + if (physPort) + physPort->removeConn(); + else + physPort = new FunctionalPort(csprintf("%s-%d-funcport", baseCpu->name(), tid)); connectToMemFunc(physPort); } @@ -136,7 +139,10 @@ ThreadState::connectVirtPort() // @todo: For now this disregards any older port that may have // already existed. Fix this memory leak once the bus port IDs // for functional ports is resolved. - virtPort = new VirtualPort(csprintf("%s-%d-vport", + if (virtPort) + virtPort->removeConn(); + else + virtPort = new VirtualPort(csprintf("%s-%d-vport", baseCpu->name(), tid)); connectToMemFunc(virtPort); } diff --git a/src/cpu/trace/SConscript b/src/cpu/trace/SConscript new file mode 100644 index 000000000..f166b2f23 --- /dev/null +++ b/src/cpu/trace/SConscript @@ -0,0 +1,40 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +if False: + Source('opt_cpu.cc') + Source('trace_cpu.cc') + + Source('reader/mem_trace_reader.cc') + Source('reader/ibm_reader.cc') + Source('reader/itx_reader.cc') + Source('reader/m5_reader.cc') diff --git a/src/dev/SConscript b/src/dev/SConscript index 951bc29d1..ea529b536 100644 --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -29,51 +29,29 @@ # Authors: Steve Reinhardt # Gabe Black -import os.path, sys - -# Import build environment variable from SConstruct. -Import('env') - -# Right now there are no source files immediately in this directory -sources = [] - -# -# Now include other ISA-specific sources from the ISA subdirectories. -# - -isa = env['TARGET_ISA'] # someday this may be a list of ISAs - -# -# These source files can be used by any architecture -# - -sources += Split(''' - baddev.cc - disk_image.cc - etherbus.cc - etherdump.cc - etherint.cc - etherlink.cc - etherpkt.cc - ethertap.cc - ide_ctrl.cc - ide_disk.cc - io_device.cc - isa_fake.cc - ns_gige.cc - pciconfigall.cc - pcidev.cc - pktfifo.cc - platform.cc - simconsole.cc - simple_disk.cc - ''') - -# Let the target architecture define what additional sources it needs -sources += SConscript(os.path.join(isa, 'SConscript'), exports = 'env') - -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] - -Return('sources') +Import('*') + +if env['FULL_SYSTEM']: + Source('baddev.cc') + Source('disk_image.cc') + Source('etherbus.cc') + Source('etherdump.cc') + Source('etherint.cc') + Source('etherlink.cc') + Source('etherpkt.cc') + Source('ethertap.cc') + Source('i8254xGBe.cc') + Source('ide_ctrl.cc') + Source('ide_disk.cc') + Source('io_device.cc') + Source('isa_fake.cc') + Source('ns_gige.cc') + Source('pciconfigall.cc') + Source('pcidev.cc') + Source('pktfifo.cc') + Source('platform.cc') + Source('simconsole.cc') + Source('simple_disk.cc') + #Source('sinic.cc') + Source('uart.cc') + Source('uart8250.cc') diff --git a/src/dev/alpha/SConscript b/src/dev/alpha/SConscript index fb0e626d3..c985fdd9f 100644 --- a/src/dev/alpha/SConscript +++ b/src/dev/alpha/SConscript @@ -29,40 +29,11 @@ # Authors: Steve Reinhardt # Gabe Black -import os.path, sys +Import('*') -# Import build environment variable from SConstruct. -Import('env') - -sources = Split(''' - console.cc - tsunami.cc - tsunami_cchip.cc - tsunami_io.cc - tsunami_pchip.cc - ''') -# baddev.cc -# disk_image.cc -# etherbus.cc -# etherdump.cc -# etherint.cc -# etherlink.cc -# etherpkt.cc -# ethertap.cc -# ide_ctrl.cc -# ide_disk.cc -# io_device.cc -# isa_fake.cc -# ns_gige.cc -# pciconfigall.cc -# pcidev.cc -# pktfifo.cc -# platform.cc -# simconsole.cc -# simple_disk.cc - -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] - -Return('sources') +if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'alpha': + Source('console.cc') + Source('tsunami.cc') + Source('tsunami_cchip.cc') + Source('tsunami_io.cc') + Source('tsunami_pchip.cc') diff --git a/src/dev/alpha/tsunami_cchip.cc b/src/dev/alpha/tsunami_cchip.cc index 15c47984b..118160adf 100644 --- a/src/dev/alpha/tsunami_cchip.cc +++ b/src/dev/alpha/tsunami_cchip.cc @@ -372,7 +372,7 @@ TsunamiCChip::write(PacketPtr pkt) void TsunamiCChip::clearIPI(uint64_t ipintr) { - int numcpus = tsunami->intrctrl->cpu->system->threadContexts.size(); + int numcpus = sys->threadContexts.size(); assert(numcpus <= Tsunami::Max_CPUs); if (ipintr) { @@ -398,7 +398,7 @@ TsunamiCChip::clearIPI(uint64_t ipintr) void TsunamiCChip::clearITI(uint64_t itintr) { - int numcpus = tsunami->intrctrl->cpu->system->threadContexts.size(); + int numcpus = sys->threadContexts.size(); assert(numcpus <= Tsunami::Max_CPUs); if (itintr) { @@ -418,7 +418,7 @@ TsunamiCChip::clearITI(uint64_t itintr) void TsunamiCChip::reqIPI(uint64_t ipreq) { - int numcpus = tsunami->intrctrl->cpu->system->threadContexts.size(); + int numcpus = sys->threadContexts.size(); assert(numcpus <= Tsunami::Max_CPUs); if (ipreq) { @@ -445,7 +445,7 @@ TsunamiCChip::reqIPI(uint64_t ipreq) void TsunamiCChip::postRTC() { - int size = tsunami->intrctrl->cpu->system->threadContexts.size(); + int size = sys->threadContexts.size(); assert(size <= Tsunami::Max_CPUs); for (int i = 0; i < size; i++) { @@ -463,7 +463,7 @@ void TsunamiCChip::postDRIR(uint32_t interrupt) { uint64_t bitvector = ULL(1) << interrupt; - uint64_t size = tsunami->intrctrl->cpu->system->threadContexts.size(); + uint64_t size = sys->threadContexts.size(); assert(size <= Tsunami::Max_CPUs); drir |= bitvector; @@ -481,7 +481,7 @@ void TsunamiCChip::clearDRIR(uint32_t interrupt) { uint64_t bitvector = ULL(1) << interrupt; - uint64_t size = tsunami->intrctrl->cpu->system->threadContexts.size(); + uint64_t size = sys->threadContexts.size(); assert(size <= Tsunami::Max_CPUs); if (drir & bitvector) diff --git a/src/dev/alpha/tsunamireg.h b/src/dev/alpha/tsunamireg.h index d603972be..a2742e36d 100644 --- a/src/dev/alpha/tsunamireg.h +++ b/src/dev/alpha/tsunamireg.h @@ -136,15 +136,6 @@ /* Added for keyboard accesses */ #define TSDEV_KBD 0x64 -/* Added for ATA PCI DMA */ -#define ATA_PCI_DMA 0x00 -#define ATA_PCI_DMA2 0x02 -#define ATA_PCI_DMA3 0x16 -#define ATA_PCI_DMA4 0x17 -#define ATA_PCI_DMA5 0x1a -#define ATA_PCI_DMA6 0x11 -#define ATA_PCI_DMA7 0x14 - #define TSDEV_RTC_ADDR 0x70 #define TSDEV_RTC_DATA 0x71 @@ -155,18 +146,6 @@ #define TSUNAMI_PCI0_IO TSUNAMI_UNCACHABLE_BIT + PCHIP_PCI0_IO -// UART Defines -#define UART_IER_RDI 0x01 -#define UART_IER_THRI 0x02 -#define UART_IER_RLSI 0x04 - - -#define UART_LSR_TEMT 0x40 -#define UART_LSR_THRE 0x20 -#define UART_LSR_DR 0x01 - -#define UART_MCR_LOOP 0x10 - // System Control PortB Status Bits #define PORTB_SPKR_HIGH 0x20 diff --git a/src/dev/etherbus.cc b/src/dev/etherbus.cc index 348bb818a..cedb3cd4d 100644 --- a/src/dev/etherbus.cc +++ b/src/dev/etherbus.cc @@ -43,7 +43,7 @@ #include "dev/etherint.hh" #include "dev/etherpkt.hh" #include "sim/builder.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/dev/etherdump.cc b/src/dev/etherdump.cc index 0c986cc21..04463f3ee 100644 --- a/src/dev/etherdump.cc +++ b/src/dev/etherdump.cc @@ -41,7 +41,7 @@ #include "base/output.hh" #include "dev/etherdump.hh" #include "sim/builder.hh" -#include "sim/root.hh" +#include "sim/core.hh" using std::string; diff --git a/src/dev/etherlink.cc b/src/dev/etherlink.cc index cd3812270..5d30e1744 100644 --- a/src/dev/etherlink.cc +++ b/src/dev/etherlink.cc @@ -47,7 +47,7 @@ #include "sim/builder.hh" #include "sim/serialize.hh" #include "sim/system.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 7fc68f4e7..d6449f6c5 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -35,7 +35,13 @@ * other MACs with slight modifications. */ + +/* + * @todo really there are multiple dma engines.. we should implement them. + */ + #include "base/inet.hh" +#include "base/trace.hh" #include "dev/i8254xGBe.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" @@ -43,32 +49,37 @@ #include "sim/stats.hh" #include "sim/system.hh" +#include <algorithm> + using namespace iGbReg; +using namespace Net; IGbE::IGbE(Params *p) - : PciDev(p), etherInt(NULL) + : PciDev(p), etherInt(NULL), useFlowControl(p->use_flow_control), + rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false), + txTick(false), rdtrEvent(this), radvEvent(this), tadvEvent(this), + tidvEvent(this), tickEvent(this), interEvent(this), + rxDescCache(this, name()+".TxDesc", p->rx_desc_cache_size), + txDescCache(this, name()+".RxDesc", p->tx_desc_cache_size), clock(p->clock) { // Initialized internal registers per Intel documentation - regs.tctl.reg = 0; - regs.rctl.reg = 0; - regs.ctrl.reg = 0; - regs.ctrl.fd = 1; - regs.ctrl.lrst = 1; - regs.ctrl.speed = 2; - regs.ctrl.frcspd = 1; - regs.sts.reg = 0; - regs.eecd.reg = 0; - regs.eecd.fwe = 1; - regs.eecd.ee_type = 1; - regs.eerd.reg = 0; - regs.icd.reg = 0; - regs.imc.reg = 0; - regs.rctl.reg = 0; - regs.tctl.reg = 0; - regs.manc.reg = 0; - - regs.pba.rxa = 0x30; - regs.pba.txa = 0x10; + // All registers intialized to 0 by per register constructor + regs.ctrl.fd(1); + regs.ctrl.lrst(1); + regs.ctrl.speed(2); + regs.ctrl.frcspd(1); + regs.sts.speed(3); // Say we're 1000Mbps + regs.sts.fd(1); // full duplex + regs.eecd.fwe(1); + regs.eecd.ee_type(1); + regs.imr = 0; + regs.iam = 0; + regs.rxdctl.gran(1); + regs.rxdctl.wthresh(1); + regs.fcrth(1); + + regs.pba.rxa(0x30); + regs.pba.txa(0x10); eeOpBits = 0; eeAddrBits = 0; @@ -78,8 +89,20 @@ IGbE::IGbE(Params *p) // clear all 64 16 bit words of the eeprom memset(&flash, 0, EEPROM_SIZE*2); + //We'll need to instert the MAC address into the flash + flash[0] = 0xA4A4; + flash[1] = 0xB6B6; + flash[2] = 0xC8C8; + + uint16_t csum = 0; + for (int x = 0; x < EEPROM_SIZE; x++) + csum += flash[x]; + // Magic happy checksum value - flash[0] = 0xBABA; + flash[EEPROM_SIZE-1] = htobe((uint16_t)(EEPROM_CSUM - csum)); + + rxFifo.clear(); + txFifo.clear(); } @@ -124,47 +147,129 @@ IGbE::read(PacketPtr pkt) switch (daddr) { - case CTRL: - pkt->set<uint32_t>(regs.ctrl.reg); - break; - case STATUS: - pkt->set<uint32_t>(regs.sts.reg); - break; - case EECD: - pkt->set<uint32_t>(regs.eecd.reg); - break; - case EERD: - pkt->set<uint32_t>(regs.eerd.reg); - break; - case ICR: - pkt->set<uint32_t>(regs.icd.reg); - break; - case IMC: - pkt->set<uint32_t>(regs.imc.reg); - break; - case RCTL: - pkt->set<uint32_t>(regs.rctl.reg); - break; - case TCTL: - pkt->set<uint32_t>(regs.tctl.reg); - break; - case PBA: - pkt->set<uint32_t>(regs.pba.reg); - break; - case WUC: - case LEDCTL: - pkt->set<uint32_t>(0); // We don't care, so just return 0 - break; - case MANC: - pkt->set<uint32_t>(regs.manc.reg); - break; + case REG_CTRL: + pkt->set<uint32_t>(regs.ctrl()); + break; + case REG_STATUS: + pkt->set<uint32_t>(regs.sts()); + break; + case REG_EECD: + pkt->set<uint32_t>(regs.eecd()); + break; + case REG_EERD: + pkt->set<uint32_t>(regs.eerd()); + break; + case REG_CTRL_EXT: + pkt->set<uint32_t>(regs.ctrl_ext()); + break; + case REG_MDIC: + pkt->set<uint32_t>(regs.mdic()); + break; + case REG_ICR: + pkt->set<uint32_t>(regs.icr()); + if (regs.icr.int_assert()) + regs.imr &= regs.iam; + if (regs.imr == 0 || (regs.icr.int_assert() && regs.ctrl_ext.iame())) { + regs.icr(0); + cpuClearInt(); + } + break; + case REG_ITR: + pkt->set<uint32_t>(regs.itr()); + break; + case REG_RCTL: + pkt->set<uint32_t>(regs.rctl()); + break; + case REG_FCTTV: + pkt->set<uint32_t>(regs.fcttv()); + break; + case REG_TCTL: + pkt->set<uint32_t>(regs.tctl()); + break; + case REG_PBA: + pkt->set<uint32_t>(regs.pba()); + break; + case REG_WUC: + case REG_LEDCTL: + pkt->set<uint32_t>(0); // We don't care, so just return 0 + break; + case REG_FCRTL: + pkt->set<uint32_t>(regs.fcrtl()); + break; + case REG_FCRTH: + pkt->set<uint32_t>(regs.fcrth()); + break; + case REG_RDBAL: + pkt->set<uint32_t>(regs.rdba.rdbal()); + break; + case REG_RDBAH: + pkt->set<uint32_t>(regs.rdba.rdbah()); + break; + case REG_RDLEN: + pkt->set<uint32_t>(regs.rdlen()); + break; + case REG_RDH: + pkt->set<uint32_t>(regs.rdh()); + break; + case REG_RDT: + pkt->set<uint32_t>(regs.rdt()); + break; + case REG_RDTR: + pkt->set<uint32_t>(regs.rdtr()); + if (regs.rdtr.fpd()) { + rxDescCache.writeback(0); + postInterrupt(IT_RXT); + regs.rdtr.fpd(0); + } + if (regs.rdtr.delay()) { + Tick t = regs.rdtr.delay() * Clock::Int::ns * 1024; + if (rdtrEvent.scheduled()) + rdtrEvent.reschedule(curTick + t); + else + rdtrEvent.schedule(curTick + t); + } + break; + case REG_RADV: + pkt->set<uint32_t>(regs.radv()); + break; + case REG_TDBAL: + pkt->set<uint32_t>(regs.tdba.tdbal()); + break; + case REG_TDBAH: + pkt->set<uint32_t>(regs.tdba.tdbah()); + break; + case REG_TDLEN: + pkt->set<uint32_t>(regs.tdlen()); + break; + case REG_TDH: + pkt->set<uint32_t>(regs.tdh()); + break; + case REG_TDT: + pkt->set<uint32_t>(regs.tdt()); + break; + case REG_TIDV: + pkt->set<uint32_t>(regs.tidv()); + break; + case REG_TXDCTL: + pkt->set<uint32_t>(regs.txdctl()); + break; + case REG_TADV: + pkt->set<uint32_t>(regs.tadv()); + break; + case REG_RXCSUM: + pkt->set<uint32_t>(regs.rxcsum()); + break; + case REG_MANC: + pkt->set<uint32_t>(regs.manc()); + break; default: - if (!(daddr >= VFTA && daddr < (VFTA + VLAN_FILTER_TABLE_SIZE)*4) && - !(daddr >= RAL && daddr < (RAL + RCV_ADDRESS_TABLE_SIZE)*4) && - !(daddr >= MTA && daddr < (MTA + MULTICAST_TABLE_SIZE)*4)) - pkt->set<uint32_t>(0); - else - panic("Read request to unknown register number: %#x\n", daddr); + if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) && + !(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) && + !(daddr >= REG_MTA && daddr < (REG_MTA + MULTICAST_TABLE_SIZE*4)) && + !(daddr >= REG_CRCERRS && daddr < (REG_CRCERRS + STATS_REGS_SIZE))) + panic("Read request to unknown register number: %#x\n", daddr); + else + pkt->set<uint32_t>(0); }; pkt->result = Packet::Success; @@ -194,93 +299,253 @@ IGbE::write(PacketPtr pkt) /// uint32_t val = pkt->get<uint32_t>(); + Regs::RCTL oldrctl; + Regs::TCTL oldtctl; + switch (daddr) { - case CTRL: - regs.ctrl.reg = val; - break; - case STATUS: - regs.sts.reg = val; - break; - case EECD: - int oldClk; - oldClk = regs.eecd.sk; - regs.eecd.reg = val; - // See if this is a eeprom access and emulate accordingly - if (!oldClk && regs.eecd.sk) { - if (eeOpBits < 8) { - eeOpcode = eeOpcode << 1 | regs.eecd.din; - eeOpBits++; - } else if (eeAddrBits < 8 && eeOpcode == EEPROM_READ_OPCODE_SPI) { - eeAddr = eeAddr << 1 | regs.eecd.din; - eeAddrBits++; - } else if (eeDataBits < 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) { - assert(eeAddr>>1 < EEPROM_SIZE); - DPRINTF(EthernetEEPROM, "EEPROM bit read: %d word: %#X\n", - flash[eeAddr>>1] >> eeDataBits & 0x1, flash[eeAddr>>1]); - regs.eecd.dout = (flash[eeAddr>>1] >> (15-eeDataBits)) & 0x1; - eeDataBits++; - } else if (eeDataBits < 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI) { - regs.eecd.dout = 0; - eeDataBits++; - } else - panic("What's going on with eeprom interface? opcode:" - " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode, - (uint32_t)eeOpBits, (uint32_t)eeAddr, - (uint32_t)eeAddrBits, (uint32_t)eeDataBits); - - // Reset everything for the next command - if ((eeDataBits == 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) || + case REG_CTRL: + regs.ctrl = val; + if (regs.ctrl.tfce()) + warn("TX Flow control enabled, should implement\n"); + if (regs.ctrl.rfce()) + warn("RX Flow control enabled, should implement\n"); + break; + case REG_CTRL_EXT: + regs.ctrl_ext = val; + break; + case REG_STATUS: + regs.sts = val; + break; + case REG_EECD: + int oldClk; + oldClk = regs.eecd.sk(); + regs.eecd = val; + // See if this is a eeprom access and emulate accordingly + if (!oldClk && regs.eecd.sk()) { + if (eeOpBits < 8) { + eeOpcode = eeOpcode << 1 | regs.eecd.din(); + eeOpBits++; + } else if (eeAddrBits < 8 && eeOpcode == EEPROM_READ_OPCODE_SPI) { + eeAddr = eeAddr << 1 | regs.eecd.din(); + eeAddrBits++; + } else if (eeDataBits < 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) { + assert(eeAddr>>1 < EEPROM_SIZE); + DPRINTF(EthernetEEPROM, "EEPROM bit read: %d word: %#X\n", + flash[eeAddr>>1] >> eeDataBits & 0x1, flash[eeAddr>>1]); + regs.eecd.dout((flash[eeAddr>>1] >> (15-eeDataBits)) & 0x1); + eeDataBits++; + } else if (eeDataBits < 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI) { + regs.eecd.dout(0); + eeDataBits++; + } else + panic("What's going on with eeprom interface? opcode:" + " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode, + (uint32_t)eeOpBits, (uint32_t)eeAddr, + (uint32_t)eeAddrBits, (uint32_t)eeDataBits); + + // Reset everything for the next command + if ((eeDataBits == 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) || (eeDataBits == 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI)) { - eeOpBits = 0; - eeAddrBits = 0; - eeDataBits = 0; + eeOpBits = 0; + eeAddrBits = 0; + eeDataBits = 0; eeOpcode = 0; - eeAddr = 0; - } + eeAddr = 0; + } DPRINTF(EthernetEEPROM, "EEPROM: opcode: %#X:%d addr: %#X:%d\n", - (uint32_t)eeOpcode, (uint32_t) eeOpBits, - (uint32_t)eeAddr>>1, (uint32_t)eeAddrBits); + (uint32_t)eeOpcode, (uint32_t) eeOpBits, + (uint32_t)eeAddr>>1, (uint32_t)eeAddrBits); if (eeOpBits == 8 && !(eeOpcode == EEPROM_READ_OPCODE_SPI || - eeOpcode == EEPROM_RDSR_OPCODE_SPI )) - panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode, - (uint32_t)eeOpBits); - - - } - // If driver requests eeprom access, immediately give it to it - regs.eecd.ee_gnt = regs.eecd.ee_req; - break; - case EERD: - regs.eerd.reg = val; - break; - case ICR: - regs.icd.reg = val; - break; - case IMC: - regs.imc.reg = val; - break; - case RCTL: - regs.rctl.reg = val; - break; - case TCTL: - regs.tctl.reg = val; - break; - case PBA: - regs.pba.rxa = val; - regs.pba.txa = 64 - regs.pba.rxa; - break; - case WUC: - case LEDCTL: - ; // We don't care, so don't store anything - break; - case MANC: - regs.manc.reg = val; - break; + eeOpcode == EEPROM_RDSR_OPCODE_SPI )) + panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode, + (uint32_t)eeOpBits); + + + } + // If driver requests eeprom access, immediately give it to it + regs.eecd.ee_gnt(regs.eecd.ee_req()); + break; + case REG_EERD: + regs.eerd = val; + break; + case REG_MDIC: + regs.mdic = val; + if (regs.mdic.i()) + panic("No support for interrupt on mdic complete\n"); + if (regs.mdic.phyadd() != 1) + panic("No support for reading anything but phy\n"); + DPRINTF(Ethernet, "%s phy address %x\n", regs.mdic.op() == 1 ? "Writing" + : "Reading", regs.mdic.regadd()); + switch (regs.mdic.regadd()) { + case PHY_PSTATUS: + regs.mdic.data(0x796D); // link up + break; + case PHY_PID: + regs.mdic.data(0x02A8); + break; + case PHY_EPID: + regs.mdic.data(0x0380); + break; + case PHY_GSTATUS: + regs.mdic.data(0x7C00); + break; + case PHY_EPSTATUS: + regs.mdic.data(0x3000); + break; + case PHY_AGC: + regs.mdic.data(0x180); // some random length + break; + default: + regs.mdic.data(0); + warn("Accessing unknown phy register %d\n", regs.mdic.regadd()); + } + regs.mdic.r(1); + break; + case REG_ICR: + if (regs.icr.int_assert()) + regs.imr &= regs.iam; + + regs.icr = ~bits(val,30,0) & regs.icr(); + // if no more bits are set clear the int_asserted bit + if (!bits(regs.icr(),31,31)) + cpuClearInt(); + + break; + case REG_ITR: + regs.itr = val; + break; + case REG_ICS: + postInterrupt((IntTypes)val); + break; + case REG_IMS: + regs.imr |= val; + chkInterrupt(); + break; + case REG_IMC: + regs.imr &= ~val; + chkInterrupt(); + break; + case REG_IAM: + regs.iam = val; + break; + case REG_RCTL: + oldrctl = regs.rctl; + regs.rctl = val; + if (regs.rctl.rst()) { + rxDescCache.reset(); + rxFifo.clear(); + regs.rctl.rst(0); + } + if (regs.rctl.en()) + rxTick = true; + if ((rxTick || txTick) && !tickEvent.scheduled()) + tickEvent.schedule(curTick + cycles(1)); + break; + case REG_FCTTV: + regs.fcttv = val; + break; + case REG_TCTL: + regs.tctl = val; + oldtctl = regs.tctl; + regs.tctl = val; + if (regs.tctl.en()) + txTick = true; + if ((rxTick || txTick) && !tickEvent.scheduled()) + tickEvent.schedule(curTick + cycles(1)); + if (regs.tctl.en() && !oldtctl.en()) { + txDescCache.reset(); + } + break; + case REG_PBA: + regs.pba.rxa(val); + regs.pba.txa(64 - regs.pba.rxa()); + break; + case REG_WUC: + case REG_LEDCTL: + case REG_FCAL: + case REG_FCAH: + case REG_FCT: + case REG_VET: + case REG_AIFS: + case REG_TIPG: + ; // We don't care, so don't store anything + break; + case REG_FCRTL: + regs.fcrtl = val; + break; + case REG_FCRTH: + regs.fcrth = val; + break; + case REG_RDBAL: + regs.rdba.rdbal( val & ~mask(4)); + rxDescCache.areaChanged(); + break; + case REG_RDBAH: + regs.rdba.rdbah(val); + rxDescCache.areaChanged(); + break; + case REG_RDLEN: + regs.rdlen = val & ~mask(7); + rxDescCache.areaChanged(); + break; + case REG_RDH: + regs.rdh = val; + rxDescCache.areaChanged(); + break; + case REG_RDT: + regs.rdt = val; + rxTick = true; + if ((rxTick || txTick) && !tickEvent.scheduled()) + tickEvent.schedule(curTick + cycles(1)); + break; + case REG_RDTR: + regs.rdtr = val; + break; + case REG_RADV: + regs.radv = val; + break; + case REG_TDBAL: + regs.tdba.tdbal( val & ~mask(4)); + txDescCache.areaChanged(); + break; + case REG_TDBAH: + regs.tdba.tdbah(val); + txDescCache.areaChanged(); + break; + case REG_TDLEN: + regs.tdlen = val & ~mask(7); + txDescCache.areaChanged(); + break; + case REG_TDH: + regs.tdh = val; + txDescCache.areaChanged(); + break; + case REG_TDT: + regs.tdt = val; + txTick = true; + if ((rxTick || txTick) && !tickEvent.scheduled()) + tickEvent.schedule(curTick + cycles(1)); + break; + case REG_TIDV: + regs.tidv = val; + break; + case REG_TXDCTL: + regs.txdctl = val; + break; + case REG_TADV: + regs.tadv = val; + break; + case REG_RXCSUM: + regs.rxcsum = val; + break; + case REG_MANC: + regs.manc = val; + break; default: - if (!(daddr >= VFTA && daddr < (VFTA + VLAN_FILTER_TABLE_SIZE)*4) && - !(daddr >= RAL && daddr < (RAL + RCV_ADDRESS_TABLE_SIZE)*4) && - !(daddr >= MTA && daddr < (MTA + MULTICAST_TABLE_SIZE)*4)) + if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) && + !(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) && + !(daddr >= REG_MTA && daddr < (REG_MTA + MULTICAST_TABLE_SIZE*4))) panic("Write request to unknown register number: %#x\n", daddr); }; @@ -288,18 +553,585 @@ IGbE::write(PacketPtr pkt) return pioDelay; } +void +IGbE::postInterrupt(IntTypes t, bool now) +{ + // Interrupt is already pending + if (t & regs.icr()) + return; + + if (regs.icr() & regs.imr) + { + // already in an interrupt state, set new int and done + regs.icr = regs.icr() | t; + } else { + regs.icr = regs.icr() | t; + if (regs.itr.interval() == 0 || now) { + if (now) { + if (interEvent.scheduled()) + interEvent.deschedule(); + } + cpuPostInt(); + } else { + DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n", + Clock::Int::ns * 256 * regs.itr.interval()); + assert(!interEvent.scheduled()); + interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval()); + } + } +} + +void +IGbE::cpuPostInt() +{ + if (rdtrEvent.scheduled()) { + regs.icr.rxt0(1); + rdtrEvent.deschedule(); + } + if (radvEvent.scheduled()) { + regs.icr.rxt0(1); + radvEvent.deschedule(); + } + if (tadvEvent.scheduled()) { + regs.icr.txdw(1); + tadvEvent.deschedule(); + } + if (tidvEvent.scheduled()) { + regs.icr.txdw(1); + tidvEvent.deschedule(); + } + + regs.icr.int_assert(1); + DPRINTF(EthernetIntr, "EINT: Posting interrupt to CPU now. Vector %#x\n", + regs.icr()); + intrPost(); +} + +void +IGbE::cpuClearInt() +{ + regs.icr.int_assert(0); + DPRINTF(EthernetIntr, "EINT: Clearing interrupt to CPU now. Vector %#x\n", + regs.icr()); + intrClear(); +} + +void +IGbE::chkInterrupt() +{ + // Check if we need to clear the cpu interrupt + if (!(regs.icr() & regs.imr)) + cpuClearInt(); + + // Check if we need to set the cpu interupt + postInterrupt(IT_NONE); +} + + +IGbE::RxDescCache::RxDescCache(IGbE *i, const std::string n, int s) + : DescCache<RxDesc>(i, n, s), pktDone(false), pktEvent(this) + +{ +} bool -IGbE::ethRxPkt(EthPacketPtr packet) +IGbE::RxDescCache::writePacket(EthPacketPtr packet) { - panic("Need to implemenet\n"); + // We shouldn't have to deal with any of these yet + assert(packet->length < igbe->regs.rctl.descSize()); + + if (!unusedCache.size()) + return false; + + pktPtr = packet; + + igbe->dmaWrite(unusedCache.front()->buf, packet->length, &pktEvent, packet->data); + return true; +} + +void +IGbE::RxDescCache::pktComplete() +{ + assert(unusedCache.size()); + RxDesc *desc; + desc = unusedCache.front(); + + desc->len = pktPtr->length; + // no support for anything but starting at 0 + assert(igbe->regs.rxcsum.pcss() == 0); + + DPRINTF(EthernetDesc, "RxDesc: Packet written to memory updating Descriptor\n"); + + uint8_t status = RXDS_DD | RXDS_EOP; + uint8_t err = 0; + IpPtr ip(pktPtr); + if (ip) { + if (igbe->regs.rxcsum.ipofld()) { + DPRINTF(EthernetDesc, "RxDesc: Checking IP checksum\n"); + status |= RXDS_IPCS; + desc->csum = cksum(ip); + if (cksum(ip) != 0) { + err |= RXDE_IPE; + DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n"); + } + } + TcpPtr tcp(ip); + if (tcp && igbe->regs.rxcsum.tuofld()) { + DPRINTF(EthernetDesc, "RxDesc: Checking TCP checksum\n"); + status |= RXDS_TCPCS; + desc->csum = cksum(tcp); + if (cksum(tcp) != 0) { + DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n"); + err |= RXDE_TCPE; + } + } + + UdpPtr udp(ip); + if (udp && igbe->regs.rxcsum.tuofld()) { + DPRINTF(EthernetDesc, "RxDesc: Checking UDP checksum\n"); + status |= RXDS_UDPCS; + desc->csum = cksum(udp); + if (cksum(tcp) != 0) { + DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n"); + err |= RXDE_TCPE; + } + } + } // if ip + + desc->status = status; + desc->errors = err; + + // No vlan support at this point... just set it to 0 + desc->vlan = 0; + + // Deal with the rx timer interrupts + if (igbe->regs.rdtr.delay()) { + DPRINTF(EthernetSM, "RXS: Scheduling DTR for %d\n", + igbe->regs.rdtr.delay() * igbe->intClock()); + if (igbe->rdtrEvent.scheduled()) + igbe->rdtrEvent.reschedule(curTick + igbe->regs.rdtr.delay() * + igbe->intClock()); + else + igbe->rdtrEvent.schedule(curTick + igbe->regs.rdtr.delay() * + igbe->intClock()); + } + + if (igbe->regs.radv.idv() && igbe->regs.rdtr.delay()) { + DPRINTF(EthernetSM, "RXS: Scheduling ADV for %d\n", + igbe->regs.radv.idv() * igbe->intClock()); + if (!igbe->radvEvent.scheduled()) + igbe->radvEvent.schedule(curTick + igbe->regs.radv.idv() * + igbe->intClock()); + } + + // If the packet is small enough, interrupt appropriately + if (pktPtr->length <= igbe->regs.rsrpd.idv()) + igbe->postInterrupt(IT_SRPD); + + DPRINTF(EthernetDesc, "RxDesc: Processing of this descriptor complete\n"); + unusedCache.pop_front(); + usedCache.push_back(desc); + pktPtr = NULL; + enableSm(); + pktDone = true; +} + +void +IGbE::RxDescCache::enableSm() +{ + igbe->rxTick = true; + if ((igbe->rxTick || igbe->txTick) && !igbe->tickEvent.scheduled()) + igbe->tickEvent.schedule((curTick/igbe->cycles(1)) * igbe->cycles(1) + + igbe->cycles(1)); +} + +bool +IGbE::RxDescCache::packetDone() +{ + if (pktDone) { + pktDone = false; + return true; + } + return false; +} + +///////////////////////////////////// IGbE::TxDesc ///////////////////////////////// + +IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s) + : DescCache<TxDesc>(i,n, s), pktDone(false), isTcp(false), pktWaiting(false), + pktEvent(this) + +{ +} + +int +IGbE::TxDescCache::getPacketSize() +{ + assert(unusedCache.size()); + + TxDesc *desc; + + DPRINTF(EthernetDesc, "TxDesc: Starting processing of descriptor\n"); + + while (unusedCache.size() && TxdOp::isContext(unusedCache.front())) { + DPRINTF(EthernetDesc, "TxDesc: Got context descriptor type... skipping\n"); + + // I think we can just ignore these for now? + desc = unusedCache.front(); + // is this going to be a tcp or udp packet? + isTcp = TxdOp::tcp(desc) ? true : false; + + // make sure it's ipv4 + assert(TxdOp::ip(desc)); + + TxdOp::setDd(desc); + unusedCache.pop_front(); + usedCache.push_back(desc); + } + + if (!unusedCache.size()) + return -1; + + DPRINTF(EthernetDesc, "TxDesc: Next TX packet is %d bytes\n", + TxdOp::getLen(unusedCache.front())); + + return TxdOp::getLen(unusedCache.front()); +} + +void +IGbE::TxDescCache::getPacketData(EthPacketPtr p) +{ + assert(unusedCache.size()); + + TxDesc *desc; + desc = unusedCache.front(); + + assert((TxdOp::isLegacy(desc) || TxdOp::isData(desc)) && TxdOp::getLen(desc)); + + pktPtr = p; + + pktWaiting = true; + + DPRINTF(EthernetDesc, "TxDesc: Starting DMA of packet\n"); + igbe->dmaRead(TxdOp::getBuf(desc), TxdOp::getLen(desc), &pktEvent, p->data); + + +} + +void +IGbE::TxDescCache::pktComplete() +{ + + TxDesc *desc; + assert(unusedCache.size()); + assert(pktPtr); + + DPRINTF(EthernetDesc, "TxDesc: DMA of packet complete\n"); + + desc = unusedCache.front(); + assert((TxdOp::isLegacy(desc) || TxdOp::isData(desc)) && TxdOp::getLen(desc)); + + // no support for vlans + assert(!TxdOp::vle(desc)); + + // we alway report status + assert(TxdOp::rs(desc)); + + // we only support single packet descriptors at this point + assert(TxdOp::eop(desc)); + + // set that this packet is done + TxdOp::setDd(desc); + + // Checksums are only ofloaded for new descriptor types + if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) { + DPRINTF(EthernetDesc, "TxDesc: Calculating checksums for packet\n"); + IpPtr ip(pktPtr); + if (TxdOp::ixsm(desc)) { + ip->sum(0); + ip->sum(cksum(ip)); + DPRINTF(EthernetDesc, "TxDesc: Calculated IP checksum\n"); + } + if (TxdOp::txsm(desc)) { + if (isTcp) { + TcpPtr tcp(ip); + tcp->sum(0); + tcp->sum(cksum(tcp)); + DPRINTF(EthernetDesc, "TxDesc: Calculated TCP checksum\n"); + } else { + UdpPtr udp(ip); + udp->sum(0); + udp->sum(cksum(udp)); + DPRINTF(EthernetDesc, "TxDesc: Calculated UDP checksum\n"); + } + } + } + + if (TxdOp::ide(desc)) { + // Deal with the rx timer interrupts + DPRINTF(EthernetDesc, "TxDesc: Descriptor had IDE set\n"); + if (igbe->regs.tidv.idv()) { + DPRINTF(EthernetDesc, "TxDesc: setting tidv\n"); + if (igbe->tidvEvent.scheduled()) + igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() * + igbe->intClock()); + else + igbe->tidvEvent.schedule(curTick + igbe->regs.tidv.idv() * + igbe->intClock()); + } + + if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) { + DPRINTF(EthernetDesc, "TxDesc: setting tadv\n"); + if (!igbe->tadvEvent.scheduled()) + igbe->tadvEvent.schedule(curTick + igbe->regs.tadv.idv() * + igbe->intClock()); + } + } + + unusedCache.pop_front(); + usedCache.push_back(desc); + pktDone = true; + pktWaiting = false; + pktPtr = NULL; + + DPRINTF(EthernetDesc, "TxDesc: Descriptor Done\n"); +} + +bool +IGbE::TxDescCache::packetAvailable() +{ + if (pktDone) { + pktDone = false; + return true; + } + return false; +} + +void +IGbE::TxDescCache::enableSm() +{ + igbe->txTick = true; + if ((igbe->rxTick || igbe->txTick) && !igbe->tickEvent.scheduled()) + igbe->tickEvent.schedule((curTick/igbe->cycles(1)) * igbe->cycles(1) + + igbe->cycles(1)); +} + + + + +///////////////////////////////////// IGbE ///////////////////////////////// + +void +IGbE::txStateMachine() +{ + if (!regs.tctl.en()) { + txTick = false; + DPRINTF(EthernetSM, "TXS: RX disabled, stopping ticking\n"); + return; + } + + if (txPacket && txDescCache.packetAvailable()) { + bool success; + DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n"); + success = txFifo.push(txPacket); + assert(success); + txPacket = NULL; + return; + } + + // Only support descriptor granularity + assert(regs.txdctl.gran()); + if (regs.txdctl.lwthresh() && txDescCache.descLeft() < (regs.txdctl.lwthresh() * 8)) { + DPRINTF(EthernetSM, "TXS: LWTHRESH caused posting of TXDLOW\n"); + postInterrupt(IT_TXDLOW); + } + + if (!txPacket) { + txPacket = new EthPacketData(16384); + } + + if (!txDescCache.packetWaiting()) { + if (txDescCache.descLeft() == 0) { + DPRINTF(EthernetSM, "TXS: No descriptors left in ring, forcing writeback\n"); + txDescCache.writeback(0); + DPRINTF(EthernetSM, "TXS: No descriptors left, stopping ticking\n"); + txTick = false; + } + + if (!(txDescCache.descUnused())) { + DPRINTF(EthernetSM, "TXS: No descriptors available in cache, stopping ticking\n"); + txTick = false; + DPRINTF(EthernetSM, "TXS: No descriptors left, fetching\n"); + txDescCache.fetchDescriptors(); + return; + } + + int size; + size = txDescCache.getPacketSize(); + if (size > 0 && rxFifo.avail() > size) { + DPRINTF(EthernetSM, "TXS: Reserving %d bytes in FIFO and begining DMA of next packet\n"); + rxFifo.reserve(size); + txDescCache.getPacketData(txPacket); + } else { + DPRINTF(EthernetSM, "TXS: No packets to get, writing back used descriptors\n"); + txDescCache.writeback(0); + } + + return; + } +} + +bool +IGbE::ethRxPkt(EthPacketPtr pkt) +{ + DPRINTF(Ethernet, "RxFIFO: Receiving pcakte from wire\n"); + if (!regs.rctl.en()) { + DPRINTF(Ethernet, "RxFIFO: RX not enabled, dropping\n"); + return true; + } + + // restart the state machines if they are stopped + rxTick = true; + if ((rxTick || txTick) && !tickEvent.scheduled()) { + DPRINTF(EthernetSM, "RXS: received packet into fifo, starting ticking\n"); + tickEvent.schedule(curTick/cycles(1) + cycles(1)); + } + + if (!rxFifo.push(pkt)) { + DPRINTF(Ethernet, "RxFIFO: Packet won't fit in fifo... dropped\n"); + postInterrupt(IT_RXO, true); + return false; + } + return true; +} + + +void +IGbE::rxStateMachine() +{ + if (!regs.rctl.en()) { + rxTick = false; + DPRINTF(EthernetSM, "RXS: RX disabled, stopping ticking\n"); + return; + } + + // If the packet is done check for interrupts/descriptors/etc + if (rxDescCache.packetDone()) { + DPRINTF(EthernetSM, "RXS: Packet completed DMA to memory\n"); + int descLeft = rxDescCache.descLeft(); + switch (regs.rctl.rdmts()) { + case 2: if (descLeft > .125 * regs.rdlen()) break; + case 1: if (descLeft > .250 * regs.rdlen()) break; + case 0: if (descLeft > .500 * regs.rdlen()) break; + DPRINTF(Ethernet, "RXS: Interrupting (RXDMT) because of descriptors left\n"); + postInterrupt(IT_RXDMT); + break; + } + + if (descLeft == 0) { + DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing writeback\n"); + rxDescCache.writeback(0); + DPRINTF(EthernetSM, "RXS: No descriptors left, stopping ticking\n"); + rxTick = false; + } + + // only support descriptor granulaties + assert(regs.rxdctl.gran()); + + if (regs.rxdctl.wthresh() >= rxDescCache.descUsed()) { + DPRINTF(EthernetSM, "RXS: Writing back because WTHRESH >= descUsed\n"); + rxDescCache.writeback(cacheBlockSize()-1); + } + + if ((rxDescCache.descUnused() < regs.rxdctl.pthresh()) && + ((rxDescCache.descLeft() - rxDescCache.descUnused()) > regs.rxdctl.hthresh())) { + DPRINTF(EthernetSM, "RXS: Fetching descriptors because descUnused < PTHRESH\n"); + rxDescCache.fetchDescriptors(); + } + + if (rxDescCache.descUnused() == 0) { + DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n"); + rxTick = false; + DPRINTF(EthernetSM, "RXS: Fetching descriptors because none available\n"); + rxDescCache.fetchDescriptors(); + } + return; + } + + if (!rxDescCache.descUnused()) { + DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n"); + rxTick = false; + DPRINTF(EthernetSM, "RXS: No descriptors available, fetching\n"); + rxDescCache.fetchDescriptors(); + return; + } + + if (rxFifo.empty()) { + DPRINTF(EthernetSM, "RXS: RxFIFO empty, stopping ticking\n"); + rxTick = false; + return; + } + + EthPacketPtr pkt; + pkt = rxFifo.front(); + + DPRINTF(EthernetSM, "RXS: Writing packet into memory\n"); + if (!rxDescCache.writePacket(pkt)) { + return; + } + + DPRINTF(EthernetSM, "RXS: Removing packet from FIFO\n"); + rxFifo.pop(); + DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n"); + rxTick = false; } +void +IGbE::txWire() +{ + if (txFifo.empty()) { + return; + } + + txTick = true; + + if (etherInt->sendPacket(txFifo.front())) { + DPRINTF(Ethernet, "TxFIFO: Successful transmit, bytes in fifo: %d\n", + txFifo.avail()); + txFifo.pop(); + } + + if (txFifo.empty()) { + postInterrupt(IT_TXQE); + DPRINTF(Ethernet, "TxFIFO: Empty, posting interruppt\n"); + } +} + +void +IGbE::tick() +{ + DPRINTF(EthernetSM, "IGbE: -------------- Cycle -------------- "); + + if (rxTick) + rxStateMachine(); + + if (txTick) { + txStateMachine(); + txWire(); + } + + if (rxTick || txTick) + tickEvent.schedule(curTick + cycles(1)); +} void IGbE::ethTxDone() { - panic("Need to implemenet\n"); + // restart the state machines if they are stopped + txTick = true; + if ((rxTick || txTick) && !tickEvent.scheduled()) + tickEvent.schedule(curTick/cycles(1) + cycles(1)); + DPRINTF(Ethernet, "TxFIFO: Transmission complete\n"); } void diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index ce4007263..d7d20ae50 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -35,6 +35,9 @@ #ifndef __DEV_I8254XGBE_HH__ #define __DEV_I8254XGBE_HH__ +#include <deque> +#include <string> + #include "base/inet.hh" #include "base/statistics.hh" #include "dev/etherint.hh" @@ -50,22 +53,434 @@ class IGbE : public PciDev { private: IGbEInt *etherInt; + + // device registers iGbReg::Regs regs; + + // eeprom data, status and control bits int eeOpBits, eeAddrBits, eeDataBits; uint8_t eeOpcode, eeAddr; - uint16_t flash[iGbReg::EEPROM_SIZE]; + // cached parameters from params struct + Tick tickRate; + bool useFlowControl; + + // packet fifos + PacketFifo rxFifo; + PacketFifo txFifo; + + // Packet that we are currently putting into the txFifo + EthPacketPtr txPacket; + + // Should to Rx/Tx State machine tick? + bool rxTick; + bool txTick; + + // Event and function to deal with RDTR timer expiring + void rdtrProcess() { postInterrupt(iGbReg::IT_RXDMT, true); } + //friend class EventWrapper<IGbE, &IGbE::rdtrProcess>; + EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent; + + // Event and function to deal with RADV timer expiring + void radvProcess() { postInterrupt(iGbReg::IT_RXDMT, true); } + //friend class EventWrapper<IGbE, &IGbE::radvProcess>; + EventWrapper<IGbE, &IGbE::radvProcess> radvEvent; + + // Event and function to deal with TADV timer expiring + void tadvProcess() { postInterrupt(iGbReg::IT_TXDW, true); } + //friend class EventWrapper<IGbE, &IGbE::tadvProcess>; + EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent; + + // Event and function to deal with TIDV timer expiring + void tidvProcess() { postInterrupt(iGbReg::IT_TXDW, true); }; + //friend class EventWrapper<IGbE, &IGbE::tidvProcess>; + EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent; + + // Main event to tick the device + void tick(); + //friend class EventWrapper<IGbE, &IGbE::tick>; + EventWrapper<IGbE, &IGbE::tick> tickEvent; + + + void rxStateMachine(); + void txStateMachine(); + void txWire(); + + /** Write an interrupt into the interrupt pending register and check mask + * and interrupt limit timer before sending interrupt to CPU + * @param t the type of interrupt we are posting + * @param now should we ignore the interrupt limiting timer + */ + void postInterrupt(iGbReg::IntTypes t, bool now = false); + + /** Check and see if changes to the mask register have caused an interrupt + * to need to be sent or perhaps removed an interrupt cause. + */ + void chkInterrupt(); + + /** Send an interrupt to the cpu + */ + void cpuPostInt(); + // Event to moderate interrupts + EventWrapper<IGbE, &IGbE::cpuPostInt> interEvent; + + /** Clear the interupt line to the cpu + */ + void cpuClearInt(); + + Tick intClock() { return Clock::Int::ns * 1024; } + + template<class T> + class DescCache + { + protected: + virtual Addr descBase() const = 0; + virtual long descHead() const = 0; + virtual long descTail() const = 0; + virtual long descLen() const = 0; + virtual void updateHead(long h) = 0; + virtual void enableSm() = 0; + + std::deque<T*> usedCache; + std::deque<T*> unusedCache; + + T *fetchBuf; + T *wbBuf; + + // Pointer to the device we cache for + IGbE *igbe; + + // Name of this descriptor cache + std::string _name; + + // How far we've cached + int cachePnt; + + // The size of the descriptor cache + int size; + + // How many descriptors we are currently fetching + int curFetching; + + // How many descriptors we are currently writing back + int wbOut; + + // if the we wrote back to the end of the descriptor ring and are going + // to have to wrap and write more + bool moreToWb; + + // What the alignment is of the next descriptor writeback + Addr wbAlignment; + + /** The packet that is currently being dmad to memory if any + */ + EthPacketPtr pktPtr; + + public: + DescCache(IGbE *i, const std::string n, int s) + : igbe(i), _name(n), cachePnt(0), size(s), curFetching(0), wbOut(0), + pktPtr(NULL), fetchEvent(this), wbEvent(this) + { + fetchBuf = new T[size]; + wbBuf = new T[size]; + } + + virtual ~DescCache() + { + reset(); + } + + std::string name() { return _name; } + + /** If the address/len/head change when we've got descriptors that are + * dirty that is very bad. This function checks that we don't and if we + * do panics. + */ + void areaChanged() + { + if (usedCache.size() > 0 || unusedCache.size() > 0) + panic("Descriptor Address, Length or Head changed. Bad\n"); + } + + void writeback(Addr aMask) + { + int curHead = descHead(); + int max_to_wb = usedCache.size() + curHead; + + DPRINTF(EthernetDesc, "Writing back descriptors head: %d tail: " + "%d len: %d cachePnt: %d max_to_wb: %d descleft: %d\n", + curHead, descTail(), descLen(), cachePnt, max_to_wb, + descLeft()); + + // Check if this writeback is less restrictive that the previous + // and if so setup another one immediately following it + if (wbOut && (aMask < wbAlignment)) { + moreToWb = true; + wbAlignment = aMask; + DPRINTF(EthernetDesc, "Writing back already in process, returning\n"); + return; + } + + + moreToWb = false; + wbAlignment = aMask; + + if (max_to_wb > descLen()) { + max_to_wb = descLen() - curHead; + moreToWb = true; + // this is by definition aligned correctly + } else if (aMask != 0) { + // align the wb point to the mask + max_to_wb = max_to_wb & ~(aMask>>4); + } + + DPRINTF(EthernetDesc, "Writing back %d descriptors\n", max_to_wb); + + if (max_to_wb <= 0 || wbOut) + return; + + wbOut = max_to_wb - curHead; + + for (int x = 0; x < wbOut; x++) + memcpy(&wbBuf[x], usedCache[x], sizeof(T)); + + for (int x = 0; x < wbOut; x++) { + assert(usedCache.size()); + delete usedCache[0]; + usedCache.pop_front(); + }; + + igbe->dmaWrite(descBase() + curHead * sizeof(T), wbOut * sizeof(T), + &wbEvent, (uint8_t*)wbBuf); + } + + /** Fetch a chunk of descriptors into the descriptor cache. + * Calls fetchComplete when the memory system returns the data + */ + void fetchDescriptors() + { + size_t max_to_fetch = cachePnt - descTail(); + if (max_to_fetch < 0) + max_to_fetch = descLen() - cachePnt; + + max_to_fetch = std::min(max_to_fetch, (size - usedCache.size() - + unusedCache.size())); + + DPRINTF(EthernetDesc, "Fetching descriptors head: %d tail: " + "%d len: %d cachePnt: %d max_to_wb: %d descleft: %d\n", + descHead(), descTail(), descLen(), cachePnt, + max_to_fetch, descLeft()); + + // Nothing to do + if (max_to_fetch == 0 || curFetching) + return; + + // So we don't have two descriptor fetches going on at once + curFetching = max_to_fetch; + + igbe->dmaRead(descBase() + cachePnt * sizeof(T), + curFetching * sizeof(T), &fetchEvent, (uint8_t*)fetchBuf); + } + + + /** Called by event when dma to read descriptors is completed + */ + void fetchComplete() + { + T *newDesc; + for (int x = 0; x < curFetching; x++) { + newDesc = new T; + memcpy(newDesc, &fetchBuf[x], sizeof(T)); + unusedCache.push_back(newDesc); + } + +#ifndef NDEBUG + int oldCp = cachePnt; +#endif + + cachePnt += curFetching; + if (cachePnt > descLen()) + cachePnt -= descLen(); + + DPRINTF(EthernetDesc, "Fetching complete cachePnt %d -> %d\n", + oldCp, cachePnt); + + enableSm(); + + } + + EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent; + + /** Called by event when dma to writeback descriptors is completed + */ + void wbComplete() + { + long curHead = descHead(); +#ifndef NDEBUG + long oldHead = curHead; +#endif + + curHead += wbOut; + wbOut = 0; + + if (curHead > descLen()) + curHead = 0; + + // Update the head + updateHead(curHead); + + DPRINTF(EthernetDesc, "Writeback complete cachePnt %d -> %d\n", + oldHead, curHead); + + // If we still have more to wb, call wb now + if (moreToWb) { + DPRINTF(EthernetDesc, "Writeback has more todo\n"); + writeback(wbAlignment); + } + } + + + EventWrapper<DescCache, &DescCache::wbComplete> wbEvent; + + /* Return the number of descriptors left in the ring, so the device has + * a way to figure out if it needs to interrupt. + */ + int descLeft() const + { + int left = unusedCache.size(); + if (cachePnt - descTail() >= 0) + left += (cachePnt - descTail()); + else + left += (descLen() - cachePnt); + + return left; + } + + /* Return the number of descriptors used and not written back. + */ + int descUsed() const { return usedCache.size(); } + + /* Return the number of cache unused descriptors we have. */ + int descUnused() const {return unusedCache.size(); } + + /* Get into a state where the descriptor address/head/etc colud be + * changed */ + void reset() + { + DPRINTF(EthernetDesc, "Reseting descriptor cache\n"); + for (int x = 0; x < usedCache.size(); x++) + delete usedCache[x]; + for (int x = 0; x < unusedCache.size(); x++) + delete unusedCache[x]; + + usedCache.clear(); + unusedCache.clear(); + } + + }; + + + class RxDescCache : public DescCache<iGbReg::RxDesc> + { + protected: + virtual Addr descBase() const { return igbe->regs.rdba(); } + virtual long descHead() const { return igbe->regs.rdh(); } + virtual long descLen() const { return igbe->regs.rdlen() >> 4; } + virtual long descTail() const { return igbe->regs.rdt(); } + virtual void updateHead(long h) { igbe->regs.rdh(h); } + virtual void enableSm(); + + bool pktDone; + + public: + RxDescCache(IGbE *i, std::string n, int s); + + /** Write the given packet into the buffer(s) pointed to by the + * descriptor and update the book keeping. Should only be called when + * there are no dma's pending. + * @param packet ethernet packet to write + * @return if the packet could be written (there was a free descriptor) + */ + bool writePacket(EthPacketPtr packet); + /** Called by event when dma to write packet is completed + */ + void pktComplete(); + + /** Check if the dma on the packet has completed. + */ + + bool packetDone(); + + EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent; + + }; + friend class RxDescCache; + + RxDescCache rxDescCache; + + class TxDescCache : public DescCache<iGbReg::TxDesc> + { + protected: + virtual Addr descBase() const { return igbe->regs.tdba(); } + virtual long descHead() const { return igbe->regs.tdh(); } + virtual long descTail() const { return igbe->regs.tdt(); } + virtual long descLen() const { return igbe->regs.tdlen() >> 4; } + virtual void updateHead(long h) { igbe->regs.tdh(h); } + virtual void enableSm(); + + bool pktDone; + bool isTcp; + bool pktWaiting; + + public: + TxDescCache(IGbE *i, std::string n, int s); + + /** Tell the cache to DMA a packet from main memory into its buffer and + * return the size the of the packet to reserve space in tx fifo. + * @return size of the packet + */ + int getPacketSize(); + void getPacketData(EthPacketPtr p); + + /** Ask if the packet has been transfered so the state machine can give + * it to the fifo. + * @return packet available in descriptor cache + */ + bool packetAvailable(); + + /** Ask if we are still waiting for the packet to be transfered. + * @return packet still in transit. + */ + bool packetWaiting() { return pktWaiting; } + + /** Called by event when dma to write packet is completed + */ + void pktComplete(); + EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent; + + }; + friend class TxDescCache; + + TxDescCache txDescCache; public: struct Params : public PciDev::Params { - ; + bool use_flow_control; + int rx_fifo_size; + int tx_fifo_size; + int rx_desc_cache_size; + int tx_desc_cache_size; + Tick clock; }; IGbE(Params *params); ~IGbE() {;} + Tick clock; + inline Tick cycles(int numCycles) const { return numCycles * clock; } + virtual Tick read(PacketPtr pkt); virtual Tick write(PacketPtr pkt); @@ -76,6 +491,7 @@ class IGbE : public PciDev void setEthInt(IGbEInt *i) { assert(!etherInt); etherInt = i; } + const Params *params() const {return (const Params *)_params; } virtual void serialize(std::ostream &os); diff --git a/src/dev/i8254xGBe_defs.hh b/src/dev/i8254xGBe_defs.hh index ae0925356..d9648a7c2 100644 --- a/src/dev/i8254xGBe_defs.hh +++ b/src/dev/i8254xGBe_defs.hh @@ -31,433 +31,570 @@ /* @file * Register and structure descriptions for Intel's 8254x line of gigabit ethernet controllers. */ +#include "base/bitfield.hh" namespace iGbReg { -const uint32_t CTRL = 0x00000; //* -const uint32_t STATUS = 0x00008; //* -const uint32_t EECD = 0x00010; //* -const uint32_t EERD = 0x00014; //* -const uint32_t CTRL_EXT = 0x00018; -const uint32_t PBA = 0x01000; -const uint32_t ICR = 0x000C0; //* -const uint32_t ITR = 0x000C4; -const uint32_t ICS = 0x000C8; -const uint32_t IMS = 0x000D0; -const uint32_t IMC = 0x000D8; //* -const uint32_t RCTL = 0x00100; //* -const uint32_t RDBAL = 0x02800; -const uint32_t RDBAH = 0x02804; -const uint32_t RDLEN = 0x02808; -const uint32_t RDH = 0x02810; -const uint32_t RDT = 0x02818; -const uint32_t RDTR = 0x02820; -const uint32_t RADV = 0x0282C; -const uint32_t RSRPD = 0x02C00; -const uint32_t TCTL = 0x00400; //* -const uint32_t TDBAL = 0x03800; -const uint32_t TDBAH = 0x03804; -const uint32_t TDLEN = 0x03808; -const uint32_t TDH = 0x03810; -const uint32_t THT = 0x03818; -const uint32_t TIDV = 0x03820; -const uint32_t TXDMAC = 0x03000; -const uint32_t TXDCTL = 0x03828; -const uint32_t TADV = 0x0282C; -const uint32_t TSPMT = 0x03830; -const uint32_t RXDCTL = 0x02828; -const uint32_t RXCSUM = 0x05000; -const uint32_t MANC = 0x05820;//* + +// Registers used by the Intel GbE NIC +const uint32_t REG_CTRL = 0x00000; +const uint32_t REG_STATUS = 0x00008; +const uint32_t REG_EECD = 0x00010; +const uint32_t REG_EERD = 0x00014; +const uint32_t REG_CTRL_EXT = 0x00018; +const uint32_t REG_MDIC = 0x00020; +const uint32_t REG_FCAL = 0x00028; +const uint32_t REG_FCAH = 0x0002C; +const uint32_t REG_FCT = 0x00030; +const uint32_t REG_VET = 0x00038; +const uint32_t REG_PBA = 0x01000; +const uint32_t REG_ICR = 0x000C0; +const uint32_t REG_ITR = 0x000C4; +const uint32_t REG_ICS = 0x000C8; +const uint32_t REG_IMS = 0x000D0; +const uint32_t REG_IMC = 0x000D8; +const uint32_t REG_IAM = 0x000E0; +const uint32_t REG_RCTL = 0x00100; +const uint32_t REG_FCTTV = 0x00170; +const uint32_t REG_TIPG = 0x00410; +const uint32_t REG_AIFS = 0x00458; +const uint32_t REG_LEDCTL = 0x00e00; +const uint32_t REG_FCRTL = 0x02160; +const uint32_t REG_FCRTH = 0x02168; +const uint32_t REG_RDBAL = 0x02800; +const uint32_t REG_RDBAH = 0x02804; +const uint32_t REG_RDLEN = 0x02808; +const uint32_t REG_RDH = 0x02810; +const uint32_t REG_RDT = 0x02818; +const uint32_t REG_RDTR = 0x02820; +const uint32_t REG_RXDCTL = 0x02828; +const uint32_t REG_RADV = 0x0282C; +const uint32_t REG_TCTL = 0x00400; +const uint32_t REG_TDBAL = 0x03800; +const uint32_t REG_TDBAH = 0x03804; +const uint32_t REG_TDLEN = 0x03808; +const uint32_t REG_TDH = 0x03810; +const uint32_t REG_TDT = 0x03818; +const uint32_t REG_TIDV = 0x03820; +const uint32_t REG_TXDCTL = 0x03828; +const uint32_t REG_TADV = 0x0382C; +const uint32_t REG_CRCERRS = 0x04000; +const uint32_t REG_RXCSUM = 0x05000; +const uint32_t REG_MTA = 0x05200; +const uint32_t REG_RAL = 0x05400; +const uint32_t REG_RAH = 0x05404; +const uint32_t REG_VFTA = 0x05600; + +const uint32_t REG_WUC = 0x05800; +const uint32_t REG_MANC = 0x05820; const uint8_t EEPROM_READ_OPCODE_SPI = 0x03; const uint8_t EEPROM_RDSR_OPCODE_SPI = 0x05; const uint8_t EEPROM_SIZE = 64; +const uint16_t EEPROM_CSUM = 0xBABA; + +const uint8_t VLAN_FILTER_TABLE_SIZE = 128; +const uint8_t RCV_ADDRESS_TABLE_SIZE = 16; +const uint8_t MULTICAST_TABLE_SIZE = 128; +const uint32_t STATS_REGS_SIZE = 0x124; + + +// Registers in that are accessed in the PHY +const uint8_t PHY_PSTATUS = 0x1; +const uint8_t PHY_PID = 0x2; +const uint8_t PHY_EPID = 0x3; +const uint8_t PHY_GSTATUS = 10; +const uint8_t PHY_EPSTATUS = 15; +const uint8_t PHY_AGC = 18; + +// Receive Descriptor Status Flags +const uint8_t RXDS_PIF = 0x80; +const uint8_t RXDS_IPCS = 0x40; +const uint8_t RXDS_TCPCS = 0x20; +const uint8_t RXDS_UDPCS = 0x10; +const uint8_t RXDS_VP = 0x08; +const uint8_t RXDS_IXSM = 0x04; +const uint8_t RXDS_EOP = 0x02; +const uint8_t RXDS_DD = 0x01; +// Receive Descriptor Error Flags +const uint8_t RXDE_RXE = 0x80; +const uint8_t RXDE_IPE = 0x40; +const uint8_t RXDE_TCPE = 0x20; +const uint8_t RXDE_SEQ = 0x04; +const uint8_t RXDE_SE = 0x02; +const uint8_t RXDE_CE = 0x01; + +// Interrupt types +enum IntTypes +{ + IT_NONE = 0x00000, //dummy value + IT_TXDW = 0x00001, + IT_TXQE = 0x00002, + IT_LSC = 0x00004, + IT_RXSEQ = 0x00008, + IT_RXDMT = 0x00010, + IT_RXO = 0x00040, + IT_RXT = 0x00080, + IT_MADC = 0x00200, + IT_RXCFG = 0x00400, + IT_GPI0 = 0x02000, + IT_GPI1 = 0x04000, + IT_TXDLOW = 0x08000, + IT_SRPD = 0x10000, + IT_ACK = 0x20000 +}; + +// Receive Descriptor struct struct RxDesc { Addr buf; uint16_t len; uint16_t csum; - union { - uint8_t status; - struct { // these may be in the worng order - uint8_t dd:1; // descriptor done (hw is done when 1) - uint8_t eop:1; // end of packet - uint8_t xism:1; // ignore checksum - uint8_t vp:1; // packet is vlan packet - uint8_t rsv:1; // reserved - uint8_t tcpcs:1; // TCP checksum done - uint8_t ipcs:1; // IP checksum done - uint8_t pif:1; // passed in-exact filter - } st; - }; - union { - uint8_t errors; - struct { - uint8_t ce:1; // crc error or alignment error - uint8_t se:1; // symbol error - uint8_t seq:1; // sequence error - uint8_t rsv:1; // reserved - uint8_t cxe:1; // carrier extension error - uint8_t tcpe:1; // tcp checksum error - uint8_t ipe:1; // ip checksum error - uint8_t rxe:1; // PX data error - } er; - }; - union { - uint16_t special; - struct { - uint16_t vlan:12; //vlan id - uint16_t cfi:1; // canocial form id - uint16_t pri:3; // user priority - } sp; - }; + uint8_t status; + uint8_t errors; + uint16_t vlan; }; -union TxDesc { - uint8_t data[16]; - struct { - Addr buf; - uint16_t len; - uint8_t cso; - union { - uint8_t command; - struct { - uint8_t eop:1; // end of packet - uint8_t ifcs:1; // insert crc - uint8_t ic:1; // insert checksum - uint8_t rs:1; // report status - uint8_t rps:1; // report packet sent - uint8_t dext:1; // extension - uint8_t vle:1; // vlan enable - uint8_t ide:1; // interrupt delay enable - } cmd; - }; - union { - uint8_t status:4; - struct { - uint8_t dd:1; // descriptor done - uint8_t ec:1; // excess collisions - uint8_t lc:1; // late collision - uint8_t tu:1; // transmit underrun - } st; - }; - uint8_t reserved:4; - uint8_t css; - union { - uint16_t special; - struct { - uint16_t vlan:12; //vlan id - uint16_t cfi:1; // canocial form id - uint16_t pri:3; // user priority - } sp; - }; - } legacy; - - // Type 0000 descriptor - struct { - uint8_t ipcss; - uint8_t ipcso; - uint16_t ipcse; - uint8_t tucss; - uint8_t tucso; - uint16_t tucse; - uint32_t paylen:20; - uint8_t dtype:4; - union { - uint8_t tucommand; - struct { - uint8_t tcp:1; // tcp/udp - uint8_t ip:1; // ip ipv4/ipv6 - uint8_t tse:1; // tcp segment enbale - uint8_t rs:1; // report status - uint8_t rsv0:1; // reserved - uint8_t dext:1; // descriptor extension - uint8_t rsv1:1; // reserved - uint8_t ide:1; // interrupt delay enable - } tucmd; - }; - union { - uint8_t status:4; - struct { - uint8_t dd:1; - uint8_t rsvd:3; - } sta; - }; - uint8_t reserved:4; - uint8_t hdrlen; - uint16_t mss; - } t0; - - // Type 0001 descriptor - struct { - Addr buf; - uint32_t dtalen:20; - uint8_t dtype:4; - union { - uint8_t dcommand; - struct { - uint8_t eop:1; // end of packet - uint8_t ifcs:1; // insert crc - uint8_t tse:1; // segmentation enable - uint8_t rs:1; // report status - uint8_t rps:1; // report packet sent - uint8_t dext:1; // extension - uint8_t vle:1; // vlan enable - uint8_t ide:1; // interrupt delay enable - } dcmd; - }; - union { - uint8_t status:4; - struct { - uint8_t dd:1; // descriptor done - uint8_t ec:1; // excess collisions - uint8_t lc:1; // late collision - uint8_t tu:1; // transmit underrun - } sta; - }; - union { - uint8_t pktopts; - struct { - uint8_t ixsm:1; // insert ip checksum - uint8_t txsm:1; // insert tcp checksum - }; - }; - union { - uint16_t special; - struct { - uint16_t vlan:12; //vlan id - uint16_t cfi:1; // canocial form id - uint16_t pri:3; // user priority - } sp; - }; - } t1; - - // Junk to test descriptor type! - struct { - uint64_t junk; - uint32_t junk1:20; - uint8_t dtype; - uint8_t junk2:5; - uint8_t dext:1; - uint8_t junk3:2; - uint8_t junk4:4; - uint32_t junk5; - } type; +struct TxDesc { + uint64_t d1; + uint64_t d2; }; +namespace TxdOp { +const uint8_t TXD_CNXT = 0x0; +const uint8_t TXD_DATA = 0x0; + +bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); } +uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); } +bool isContext(TxDesc *d) { return !isLegacy(d) && getType(d) == TXD_CNXT; } +bool isData(TxDesc *d) { return !isLegacy(d) && getType(d) == TXD_DATA; } + +Addr getBuf(TxDesc *d) { assert(isLegacy(d) || isData(d)); return d->d1; } +Addr getLen(TxDesc *d) { if (isLegacy(d)) return bits(d->d2,15,0); else return bits(d->d2, 19,0); } +void setDd(TxDesc *d) +{ + replaceBits(d->d1, 35, 32, 1); +} + +bool ide(TxDesc *d) { return bits(d->d2, 31,31); } +bool vle(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 30,30); } +bool rs(TxDesc *d) { return bits(d->d2, 28,28); } +bool ic(TxDesc *d) { assert(isLegacy(d) || isData(d)); return isLegacy(d) && bits(d->d2, 27,27); } +bool tse(TxDesc *d) { return (isData(d) || isContext(d)) && bits(d->d2, 27,27); } +bool ifcs(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 26,26); } +bool eop(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 25,25); } +bool ip(TxDesc *d) { assert(isContext(d)); return bits(d->d2, 26,26); } +bool tcp(TxDesc *d) { assert(isContext(d)); return bits(d->d2, 25,25); } + +uint8_t getCso(TxDesc *d) { assert(isLegacy(d)); return bits(d->d2, 23,16); } +uint8_t getCss(TxDesc *d) { assert(isLegacy(d)); return bits(d->d2, 47,40); } + +bool ixsm(TxDesc *d) { return isData(d) && bits(d->d2, 40,40); } +bool txsm(TxDesc *d) { return isData(d) && bits(d->d2, 41,41); } + +int tucse(TxDesc *d) { assert(isContext(d)); return bits(d->d1,63,48); } +int tucso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,47,40); } +int tucss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,39,32); } +int ipcse(TxDesc *d) { assert(isContext(d)); return bits(d->d1,31,16); } +int ipcso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,15,8); } +int ipcss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,7,0); } +int mss(TxDesc *d) { assert(isContext(d)); return bits(d->d2,63,48); } +int hdrlen(TxDesc *d) { assert(isContext(d)); return bits(d->d2,47,40); } +} // namespace TxdOp + + +#define ADD_FIELD32(NAME, OFFSET, BITS) \ + inline uint32_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \ + inline void NAME(uint32_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); } + +#define ADD_FIELD64(NAME, OFFSET, BITS) \ + inline uint64_t NAME() { return bits(_data, OFFSET+BITS-1, OFFSET); } \ + inline void NAME(uint64_t d) { replaceBits(_data, OFFSET+BITS-1, OFFSET,d); } + struct Regs { - union { // 0x0000 CTRL Register - uint32_t reg; - struct { - uint8_t fd:1; // full duplex - uint8_t bem:1; // big endian mode - uint8_t pcipr:1; // PCI priority - uint8_t lrst:1; // link reset - uint8_t tme:1; // test mode enable - uint8_t asde:1; // Auto-speed detection - uint8_t slu:1; // Set link up - uint8_t ilos:1; // invert los-of-signal - uint8_t speed:2; // speed selection bits - uint8_t be32:1; // big endian mode 32 - uint8_t frcspd:1; // force speed - uint8_t frcdpx:1; // force duplex - uint8_t duden:1; // dock/undock enable - uint8_t dudpol:1; // dock/undock polarity - uint8_t fphyrst:1; // force phy reset - uint8_t extlen:1; // external link status enable - uint8_t rsvd:1; // reserved - uint8_t sdp0d:1; // software controlled pin data - uint8_t sdp1d:1; // software controlled pin data - uint8_t sdp2d:1; // software controlled pin data - uint8_t sdp3d:1; // software controlled pin data - uint8_t sdp0i:1; // software controlled pin dir - uint8_t sdp1i:1; // software controlled pin dir - uint8_t sdp2i:1; // software controlled pin dir - uint8_t sdp3i:1; // software controlled pin dir - uint8_t rst:1; // reset - uint8_t rfce:1; // receive flow control enable - uint8_t tfce:1; // transmit flow control enable - uint8_t rte:1; // routing tag enable - uint8_t vme:1; // vlan enable - uint8_t phyrst:1; // phy reset - } ; - } ctrl; - - union { // 0x0008 STATUS - uint32_t reg; - struct { - uint8_t fd:1; // full duplex - uint8_t lu:1; // link up - uint8_t func:2; // function id - uint8_t txoff:1; // transmission paused - uint8_t tbimode:1; // tbi mode - uint8_t speed:2; // link speed - uint8_t asdv:2; // auto speed detection value - uint8_t mtxckok:1; // mtx clock running ok - uint8_t pci66:1; // In 66Mhz pci slot - uint8_t bus64:1; // in 64 bit slot - uint8_t pcix:1; // Pci mode - uint8_t pcixspd:1; // pci x speed - uint8_t reserved; // reserved - } ; - } sts; - - union { // 0x0010 EECD - uint32_t reg; - struct { - uint8_t sk:1; // clack input to the eeprom - uint8_t cs:1; // chip select to eeprom - uint8_t din:1; // data input to eeprom - uint8_t dout:1; // data output bit - uint8_t fwe:2; // flash write enable - uint8_t ee_req:1; // request eeprom access - uint8_t ee_gnt:1; // grant eeprom access - uint8_t ee_pres:1; // eeprom present - uint8_t ee_size:1; // eeprom size - uint8_t ee_sz1:1; // eeprom size - uint8_t rsvd:2; // reserved - uint8_t ee_type:1; // type of eeprom - } ; - } eecd; - - union { // 0x0014 EERD - uint32_t reg; - struct { - uint8_t start:1; // start read - uint8_t done:1; // done read - uint16_t addr:14; // address - uint16_t data; // data - }; - } eerd; - - union { // 0x00C0 ICR - uint32_t reg; - struct { - uint8_t txdw:1; // tx descr witten back - uint8_t txqe:1; // tx queue empty - uint8_t lsc:1; // link status change - uint8_t rxseq:1; // rcv sequence error - uint8_t rxdmt0:1; // rcv descriptor min thresh - uint8_t rsvd1:1; // reserved - uint8_t rxo:1; // receive overrunn - uint8_t rxt0:1; // receiver timer interrupt - uint8_t rsvd2:1; // reserved - uint8_t mdac:1; // mdi/o access complete - uint8_t rxcfg:1; // recv /c/ ordered sets - uint8_t rsvd3:1; // reserved - uint8_t phyint:1; // phy interrupt - uint8_t gpi1:1; // gpi int 1 - uint8_t gpi2:1; // gpi int 2 - uint8_t txdlow:1; // transmit desc low thresh - uint8_t srpd:1; // small receive packet detected - uint16_t rsvd4:15; // reserved - } ; - } icd; - - union { // 0x00C0 IMC - uint32_t reg; - struct { - uint8_t txdw:1; // tx descr witten back - uint8_t txqe:1; // tx queue empty - uint8_t lsc:1; // link status change - uint8_t rxseq:1; // rcv sequence error - uint8_t rxdmt0:1; // rcv descriptor min thresh - uint8_t rsvd1:1; // reserved - uint8_t rxo:1; // receive overrunn - uint8_t rxt0:1; // receiver timer interrupt - uint8_t rsvd2:1; // reserved - uint8_t mdac:1; // mdi/o access complete - uint8_t rxcfg:1; // recv /c/ ordered sets - uint8_t rsvd3:1; // reserved - uint8_t phyint:1; // phy interrupt - uint8_t gpi1:1; // gpi int 1 - uint8_t gpi2:1; // gpi int 2 - uint8_t txdlow:1; // transmit desc low thresh - uint8_t srpd:1; // small receive packet detected - uint16_t rsvd4:15; // reserved - } ; - } imc; - - union { // 0x0100 RCTL - uint32_t reg; - struct { - uint8_t rst:1; // Reset - uint8_t en:1; // Enable - uint8_t sbp:1; // Store bad packets - uint8_t upe:1; // Unicast Promiscuous enabled - uint8_t mpe:1; // Multicast promiscuous enabled - uint8_t lpe:1; // long packet reception enabled - uint8_t lbm:2; // - uint8_t rdmts:2; // - uint8_t rsvd:2; // - uint8_t mo:2; // - uint8_t mdr:1; // - uint8_t bam:1; // - uint8_t bsize:2; // - uint8_t vpe:1; // - uint8_t cfien:1; // - uint8_t cfi:1; // - uint8_t rsvd2:1; // - uint8_t dpf:1; // discard pause frames - uint8_t pmcf:1; // pass mac control frames - uint8_t rsvd3:1; // reserved - uint8_t bsex:1; // buffer size extension - uint8_t secrc:1; // strip ethernet crc from incoming packet - uint8_t rsvd1:5; // reserved - } ; - } rctl; - - union { // 0x0400 TCTL - uint32_t reg; - struct { - uint8_t rst:1; // Reset - uint8_t en:1; // Enable - uint8_t bce:1; // busy check enable - uint8_t psp:1; // pad short packets - uint8_t ct:8; // collision threshold - uint16_t cold:10; // collision distance - uint8_t swxoff:1; // software xoff transmission - uint8_t pbe:1; // packet burst enable - uint8_t rtlc:1; // retransmit late collisions - uint8_t nrtu:1; // on underrun no TX - uint8_t mulr:1; // multiple request - uint8_t rsvd:5; // reserved - } ; - } tctl; - - union { // 0x5820 MANC - uint32_t reg; - struct { - uint8_t smbus:1; // SMBus enabled ##### - uint8_t asf:1; // ASF enabled ##### - uint8_t ronforce:1; // reset of force - uint8_t rsvd:5; // reserved - uint8_t rmcp1:1; // rcmp1 filtering - uint8_t rmcp2:1; // rcmp2 filtering - uint8_t ipv4:1; // enable ipv4 - uint8_t ipv6:1; // enable ipv6 - uint8_t snap:1; // accept snap - uint8_t arp:1; // filter arp ##### - uint8_t neighbor:1; // neighbor discovery - uint8_t arp_resp:1; // arp response - uint8_t tcorst:1; // tco reset happened - uint8_t rcvtco:1; // receive tco enabled ###### - uint8_t blkphyrst:1;// block phy resets ######## - uint8_t rcvall:1; // receive all - uint8_t macaddrfltr:1; // mac address filtering ###### - uint8_t mng2host:1; // mng2 host packets ####### - uint8_t ipaddrfltr:1; // ip address filtering - uint8_t xsumfilter:1; // checksum filtering - uint8_t brfilter:1; // broadcast filtering - uint8_t smbreq:1; // smb request - uint8_t smbgnt:1; // smb grant - uint8_t smbclkin:1; // smbclkin - uint8_t smbdatain:1; // smbdatain - uint8_t smbdataout:1; // smb data out - uint8_t smbclkout:1; // smb clock out - uint8_t rsvd2:2; - }; - } manc; + template<class T> + struct Reg { + T _data; + T operator()() { return _data; } + const Reg<T> &operator=(T d) { _data = d; return *this;} + bool operator==(T d) { return d == _data; } + void operator()(T d) { _data = d; } + Reg() { _data = 0; } + }; + + struct CTRL : public Reg<uint32_t> { // 0x0000 CTRL Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(fd,0,1); // full duplex + ADD_FIELD32(bem,1,1); // big endian mode + ADD_FIELD32(pcipr,2,1); // PCI priority + ADD_FIELD32(lrst,3,1); // link reset + ADD_FIELD32(tme,4,1); // test mode enable + ADD_FIELD32(asde,5,1); // Auto-speed detection + ADD_FIELD32(slu,6,1); // Set link up + ADD_FIELD32(ilos,7,1); // invert los-of-signal + ADD_FIELD32(speed,8,2); // speed selection bits + ADD_FIELD32(be32,10,1); // big endian mode 32 + ADD_FIELD32(frcspd,11,1); // force speed + ADD_FIELD32(frcdpx,12,1); // force duplex + ADD_FIELD32(duden,13,1); // dock/undock enable + ADD_FIELD32(dudpol,14,1); // dock/undock polarity + ADD_FIELD32(fphyrst,15,1); // force phy reset + ADD_FIELD32(extlen,16,1); // external link status enable + ADD_FIELD32(rsvd,17,1); // reserved + ADD_FIELD32(sdp0d,18,1); // software controlled pin data + ADD_FIELD32(sdp1d,19,1); // software controlled pin data + ADD_FIELD32(sdp2d,20,1); // software controlled pin data + ADD_FIELD32(sdp3d,21,1); // software controlled pin data + ADD_FIELD32(sdp0i,22,1); // software controlled pin dir + ADD_FIELD32(sdp1i,23,1); // software controlled pin dir + ADD_FIELD32(sdp2i,24,1); // software controlled pin dir + ADD_FIELD32(sdp3i,25,1); // software controlled pin dir + ADD_FIELD32(rst,26,1); // reset + ADD_FIELD32(rfce,27,1); // receive flow control enable + ADD_FIELD32(tfce,28,1); // transmit flow control enable + ADD_FIELD32(rte,29,1); // routing tag enable + ADD_FIELD32(vme,30,1); // vlan enable + ADD_FIELD32(phyrst,31,1); // phy reset + }; + CTRL ctrl; + + struct STATUS : public Reg<uint32_t> { // 0x0008 STATUS Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(fd,0,1); // full duplex + ADD_FIELD32(lu,1,1); // link up + ADD_FIELD32(func,2,2); // function id + ADD_FIELD32(txoff,4,1); // transmission paused + ADD_FIELD32(tbimode,5,1); // tbi mode + ADD_FIELD32(speed,6,2); // link speed + ADD_FIELD32(asdv,8,2); // auto speed detection value + ADD_FIELD32(mtxckok,10,1); // mtx clock running ok + ADD_FIELD32(pci66,11,1); // In 66Mhz pci slot + ADD_FIELD32(bus64,12,1); // in 64 bit slot + ADD_FIELD32(pcix,13,1); // Pci mode + ADD_FIELD32(pcixspd,14,2); // pci x speed + }; + STATUS sts; + + struct EECD : public Reg<uint32_t> { // 0x0010 EECD Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(sk,0,1); // clack input to the eeprom + ADD_FIELD32(cs,1,1); // chip select to eeprom + ADD_FIELD32(din,2,1); // data input to eeprom + ADD_FIELD32(dout,3,1); // data output bit + ADD_FIELD32(fwe,4,2); // flash write enable + ADD_FIELD32(ee_req,6,1); // request eeprom access + ADD_FIELD32(ee_gnt,7,1); // grant eeprom access + ADD_FIELD32(ee_pres,8,1); // eeprom present + ADD_FIELD32(ee_size,9,1); // eeprom size + ADD_FIELD32(ee_sz1,10,1); // eeprom size + ADD_FIELD32(rsvd,11,2); // reserved + ADD_FIELD32(ee_type,13,1); // type of eeprom + } ; + EECD eecd; + + struct EERD : public Reg<uint32_t> { // 0x0014 EERD Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(start,0,1); // start read + ADD_FIELD32(done,4,1); // done read + ADD_FIELD32(addr,8,8); // address + ADD_FIELD32(data,16,16); // data + }; + EERD eerd; + + struct CTRL_EXT : public Reg<uint32_t> { // 0x0018 CTRL_EXT Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(gpi_en,0,4); // enable interrupts from gpio + ADD_FIELD32(phyint,5,1); // reads the phy internal int status + ADD_FIELD32(sdp2_data,6,1); // data from gpio sdp + ADD_FIELD32(spd3_data,7,1); // data frmo gpio sdp + ADD_FIELD32(spd2_iodir,10,1); // direction of sdp2 + ADD_FIELD32(spd3_iodir,11,1); // direction of sdp2 + ADD_FIELD32(asdchk,12,1); // initiate auto-speed-detection + ADD_FIELD32(eerst,13,1); // reset the eeprom + ADD_FIELD32(spd_byps,15,1); // bypass speed select + ADD_FIELD32(ro_dis,17,1); // disable relaxed memory ordering + ADD_FIELD32(vreg,21,1); // power down the voltage regulator + ADD_FIELD32(link_mode,22,2); // interface to talk to the link + ADD_FIELD32(iame, 27,1); // interrupt acknowledge auto-mask ?? + ADD_FIELD32(drv_loaded, 28,1);// driver is loaded and incharge of device + ADD_FIELD32(timer_clr, 29,1); // clear interrupt timers after IMS clear ?? + }; + CTRL_EXT ctrl_ext; + + struct MDIC : public Reg<uint32_t> { // 0x0020 MDIC Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(data,0,16); // data + ADD_FIELD32(regadd,16,5); // register address + ADD_FIELD32(phyadd,21,5); // phy addresses + ADD_FIELD32(op,26,2); // opcode + ADD_FIELD32(r,28,1); // ready + ADD_FIELD32(i,29,1); // interrupt + ADD_FIELD32(e,30,1); // error + }; + MDIC mdic; + + struct ICR : public Reg<uint32_t> { // 0x00C0 ICR Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(txdw,0,1) // tx descr witten back + ADD_FIELD32(txqe,1,1) // tx queue empty + ADD_FIELD32(lsc,2,1) // link status change + ADD_FIELD32(rxseq,3,1) // rcv sequence error + ADD_FIELD32(rxdmt0,4,1) // rcv descriptor min thresh + ADD_FIELD32(rsvd1,5,1) // reserved + ADD_FIELD32(rxo,6,1) // receive overrunn + ADD_FIELD32(rxt0,7,1) // receiver timer interrupt + ADD_FIELD32(mdac,9,1) // mdi/o access complete + ADD_FIELD32(rxcfg,10,1) // recv /c/ ordered sets + ADD_FIELD32(phyint,12,1) // phy interrupt + ADD_FIELD32(gpi1,13,1) // gpi int 1 + ADD_FIELD32(gpi2,14,1) // gpi int 2 + ADD_FIELD32(txdlow,15,1) // transmit desc low thresh + ADD_FIELD32(srpd,16,1) // small receive packet detected + ADD_FIELD32(ack,17,1); // receive ack frame + ADD_FIELD32(int_assert, 31,0); // interrupt caused a system interrupt + }; + ICR icr; + + uint32_t imr; // register that contains the current interrupt mask + + struct ITR : public Reg<uint32_t> { // 0x00C4 ITR Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(interval, 0,16); // minimum inter-interrutp inteval + // specified in 256ns interrupts + }; + ITR itr; + + // When CTRL_EXT.IAME and the ICR.INT_ASSERT is 1 an ICR read or write + // causes the IAM register contents to be written into the IMC + // automatically clearing all interrupts that have a bit in the IAM set + uint32_t iam; + + struct RCTL : public Reg<uint32_t> { // 0x0100 RCTL Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(rst,0,1); // Reset + ADD_FIELD32(en,1,1); // Enable + ADD_FIELD32(sbp,2,1); // Store bad packets + ADD_FIELD32(upe,3,1); // Unicast Promiscuous enabled + ADD_FIELD32(mpe,4,1); // Multicast promiscuous enabled + ADD_FIELD32(lpe,5,1); // long packet reception enabled + ADD_FIELD32(lbm,6,2); // + ADD_FIELD32(rdmts,8,2); // + ADD_FIELD32(mo,12,2); // + ADD_FIELD32(mdr,14,1); // + ADD_FIELD32(bam,15,1); // + ADD_FIELD32(bsize,16,2); // + ADD_FIELD32(vfe,18,1); // + ADD_FIELD32(cfien,19,1); // + ADD_FIELD32(cfi,20,1); // + ADD_FIELD32(dpf,22,1); // discard pause frames + ADD_FIELD32(pmcf,23,1); // pass mac control frames + ADD_FIELD32(bsex,25,1); // buffer size extension + ADD_FIELD32(secrc,26,1); // strip ethernet crc from incoming packet + int descSize() + { + switch(bsize()) { + case 0: return bsex() ? 2048 : -1; + case 1: return bsex() ? 1024 : 16384; + case 2: return bsex() ? 512 : 8192; + case 3: return bsex() ? 256 : 4096; + default: + return -1; + } + } + }; + RCTL rctl; + + struct FCTTV : public Reg<uint32_t> { // 0x0170 FCTTV + using Reg<uint32_t>::operator=; + ADD_FIELD32(ttv,0,16); // Transmit Timer Value + }; + FCTTV fcttv; + + struct TCTL : public Reg<uint32_t> { // 0x0400 TCTL Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(rst,0,1); // Reset + ADD_FIELD32(en,1,1); // Enable + ADD_FIELD32(bce,2,1); // busy check enable + ADD_FIELD32(psp,3,1); // pad short packets + ADD_FIELD32(ct,4,8); // collision threshold + ADD_FIELD32(cold,12,10); // collision distance + ADD_FIELD32(swxoff,22,1); // software xoff transmission + ADD_FIELD32(pbe,23,1); // packet burst enable + ADD_FIELD32(rtlc,24,1); // retransmit late collisions + ADD_FIELD32(nrtu,25,1); // on underrun no TX + ADD_FIELD32(mulr,26,1); // multiple request + }; + TCTL tctl; + + struct PBA : public Reg<uint32_t> { // 0x1000 PBA Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(rxa,0,16); + ADD_FIELD32(txa,16,16); + }; + PBA pba; + + struct FCRTL : public Reg<uint32_t> { // 0x2160 FCRTL Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(rtl,3,28); // make this bigger than the spec so we can have + // a larger buffer + ADD_FIELD32(xone, 31,1); + }; + FCRTL fcrtl; + + struct FCRTH : public Reg<uint32_t> { // 0x2168 FCRTL Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(rth,3,13); // make this bigger than the spec so we can have + //a larger buffer + ADD_FIELD32(xfce, 31,1); + }; + FCRTH fcrth; + + struct RDBA : public Reg<uint64_t> { // 0x2800 RDBA Register + using Reg<uint64_t>::operator=; + ADD_FIELD64(rdbal,4,28); // base address of rx descriptor ring + ADD_FIELD64(rdbah,32,32); // base address of rx descriptor ring + }; + RDBA rdba; + + struct RDLEN : public Reg<uint32_t> { // 0x2808 RDLEN Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(len,7,13); // number of bytes in the descriptor buffer + }; + RDLEN rdlen; + + struct RDH : public Reg<uint32_t> { // 0x2810 RDH Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(rdh,0,16); // head of the descriptor ring + }; + RDH rdh; + + struct RDT : public Reg<uint32_t> { // 0x2818 RDT Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(rdt,0,16); // tail of the descriptor ring + }; + RDT rdt; + + struct RDTR : public Reg<uint32_t> { // 0x2820 RDTR Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(delay,0,16); // receive delay timer + ADD_FIELD32(fpd, 31,1); // flush partial descriptor block ?? + }; + RDTR rdtr; + + struct RXDCTL : public Reg<uint32_t> { // 0x2828 RXDCTL Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(pthresh,0,6); // prefetch threshold, less that this + // consider prefetch + ADD_FIELD32(hthresh,8,6); // number of descriptors in host mem to + // consider prefetch + ADD_FIELD32(wthresh,16,6); // writeback threshold + ADD_FIELD32(gran,24,1); // granularity 0 = desc, 1 = cacheline + }; + RXDCTL rxdctl; + + struct RADV : public Reg<uint32_t> { // 0x282C RADV Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(idv,0,16); // absolute interrupt delay + }; + RADV radv; + + struct RSRPD : public Reg<uint32_t> { // 0x2C00 RSRPD Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(idv,0,12); // size to interrutp on small packets + }; + RSRPD rsrpd; + + struct TDBA : public Reg<uint64_t> { // 0x3800 TDBAL Register + using Reg<uint64_t>::operator=; + ADD_FIELD64(tdbal,4,28); // base address of transmit descriptor ring + ADD_FIELD64(tdbah,32,32); // base address of transmit descriptor ring + }; + TDBA tdba; + + struct TDLEN : public Reg<uint32_t> { // 0x3808 TDLEN Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(len,7,13); // number of bytes in the descriptor buffer + }; + TDLEN tdlen; + + struct TDH : public Reg<uint32_t> { // 0x3810 TDH Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(tdh,0,16); // head of the descriptor ring + }; + TDH tdh; + + struct TDT : public Reg<uint32_t> { // 0x3818 TDT Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(tdt,0,16); // tail of the descriptor ring + }; + TDT tdt; + + struct TIDV : public Reg<uint32_t> { // 0x3820 TIDV Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(idv,0,16); // interrupt delay + }; + TIDV tidv; + + struct TXDCTL : public Reg<uint32_t> { // 0x3828 TXDCTL Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(pthresh, 0,6); // if number of descriptors control has is + // below this number, a prefetch is considered + ADD_FIELD32(hthresh,8,8); // number of valid descriptors is host memory + // before a prefetch is considered + ADD_FIELD32(wthresh,16,6); // number of descriptors to keep until + // writeback is considered + ADD_FIELD32(gran, 24,1); // granulatiry of above values (0 = cacheline, + // 1 == desscriptor) + ADD_FIELD32(lwthresh,25,7); // xmit descriptor low thresh, interrupt + // below this level + }; + TXDCTL txdctl; + + struct TADV : public Reg<uint32_t> { // 0x382C TADV Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(idv,0,16); // absolute interrupt delay + }; + TADV tadv; + + struct RXCSUM : public Reg<uint32_t> { // 0x5000 RXCSUM Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(pcss,0,8); + ADD_FIELD32(ipofld,8,1); + ADD_FIELD32(tuofld,9,1); + }; + RXCSUM rxcsum; + + struct MANC : public Reg<uint32_t> { // 0x5820 MANC Register + using Reg<uint32_t>::operator=; + ADD_FIELD32(smbus,0,1); // SMBus enabled ##### + ADD_FIELD32(asf,1,1); // ASF enabled ##### + ADD_FIELD32(ronforce,2,1); // reset of force + ADD_FIELD32(rsvd,3,5); // reserved + ADD_FIELD32(rmcp1,8,1); // rcmp1 filtering + ADD_FIELD32(rmcp2,9,1); // rcmp2 filtering + ADD_FIELD32(ipv4,10,1); // enable ipv4 + ADD_FIELD32(ipv6,11,1); // enable ipv6 + ADD_FIELD32(snap,12,1); // accept snap + ADD_FIELD32(arp,13,1); // filter arp ##### + ADD_FIELD32(neighbor,14,1); // neighbor discovery + ADD_FIELD32(arp_resp,15,1); // arp response + ADD_FIELD32(tcorst,16,1); // tco reset happened + ADD_FIELD32(rcvtco,17,1); // receive tco enabled ###### + ADD_FIELD32(blkphyrst,18,1);// block phy resets ######## + ADD_FIELD32(rcvall,19,1); // receive all + ADD_FIELD32(macaddrfltr,20,1); // mac address filtering ###### + ADD_FIELD32(mng2host,21,1); // mng2 host packets ####### + ADD_FIELD32(ipaddrfltr,22,1); // ip address filtering + ADD_FIELD32(xsumfilter,23,1); // checksum filtering + ADD_FIELD32(brfilter,24,1); // broadcast filtering + ADD_FIELD32(smbreq,25,1); // smb request + ADD_FIELD32(smbgnt,26,1); // smb grant + ADD_FIELD32(smbclkin,27,1); // smbclkin + ADD_FIELD32(smbdatain,28,1); // smbdatain + ADD_FIELD32(smbdataout,29,1); // smb data out + ADD_FIELD32(smbclkout,30,1); // smb clock out + }; + MANC manc; }; }; // iGbReg namespace diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc index 5083c9c8d..9fa0cedde 100644 --- a/src/dev/ide_disk.cc +++ b/src/dev/ide_disk.cc @@ -48,7 +48,7 @@ #include "dev/alpha/tsunami_pchip.hh" #include "sim/builder.hh" #include "sim/sim_object.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "arch/isa_traits.hh" using namespace std; diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index c56eba267..cd7a5296a 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -132,6 +132,7 @@ class DmaPort : public Port bool dmaPending() { return pendingCount > 0; } + int cacheBlockSize() { return peerBlockSize(); } unsigned int drain(Event *de); }; @@ -256,15 +257,22 @@ class DmaDevice : public PioDevice virtual ~DmaDevice(); void dmaWrite(Addr addr, int size, Event *event, uint8_t *data) - { dmaPort->dmaAction(Packet::WriteInvalidateReq, addr, size, event, data) ; } + { + dmaPort->dmaAction(MemCmd::WriteInvalidateReq, + addr, size, event, data); + } - void dmaRead(Addr addr, int size, Event *event, uint8_t *data = NULL) - { dmaPort->dmaAction(Packet::ReadReq, addr, size, event, data); } + void dmaRead(Addr addr, int size, Event *event, uint8_t *data) + { + dmaPort->dmaAction(MemCmd::ReadReq, addr, size, event, data); + } bool dmaPending() { return dmaPort->dmaPending(); } virtual unsigned int drain(Event *de); + int cacheBlockSize() { return dmaPort->cacheBlockSize(); } + virtual Port *getPort(const std::string &if_name, int idx = -1) { if (if_name == "pio") { diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index 74f9d88d1..86f56b62e 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -92,28 +92,30 @@ NSGigE::NSGigE(Params *p) : PciDev(p), ioEnable(false), txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), - txXferLen(0), rxXferLen(0), clock(p->clock), - txState(txIdle), txEnable(false), CTDD(false), + txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false), + clock(p->clock), + txState(txIdle), txEnable(false), CTDD(false), txHalt(false), txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), - rxEnable(false), CRDD(false), rxPktBytes(0), + rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false), rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), - eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this), + eepromState(eepromStart), eepromClk(false), eepromBitsToRx(0), + eepromOpcode(0), eepromAddress(0), eepromData(0), + dmaReadDelay(p->dma_read_delay), dmaWriteDelay(p->dma_write_delay), + dmaReadFactor(p->dma_read_factor), dmaWriteFactor(p->dma_write_factor), + rxDmaData(NULL), rxDmaAddr(0), rxDmaLen(0), + txDmaData(NULL), txDmaAddr(0), txDmaLen(0), + rxDmaReadEvent(this), rxDmaWriteEvent(this), txDmaReadEvent(this), txDmaWriteEvent(this), dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), txDelay(p->tx_delay), rxDelay(p->rx_delay), rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this), - txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), - acceptMulticast(false), acceptUnicast(false), + txEvent(this), rxFilterEnable(p->rx_filter), + acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false), acceptPerfect(false), acceptArp(false), multicastHashEnable(false), - intrTick(0), cpuPendingIntr(false), + intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false), intrEvent(0), interface(0) { - intrDelay = p->intr_delay; - dmaReadDelay = p->dma_read_delay; - dmaWriteDelay = p->dma_write_delay; - dmaReadFactor = p->dma_read_factor; - dmaWriteFactor = p->dma_write_factor; regsReset(); memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index 1c2465dd1..f906e69cf 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -51,7 +51,7 @@ #include "sim/builder.hh" #include "sim/byteswap.hh" #include "sim/param.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/dev/platform.hh b/src/dev/platform.hh index 1940dcad6..aceec0970 100644 --- a/src/dev/platform.hh +++ b/src/dev/platform.hh @@ -55,9 +55,6 @@ class Platform : public SimObject /** Pointer to the interrupt controller */ IntrControl *intrctrl; - /** Pointer to the UART, set by the uart */ - Uart *uart; - /** Pointer to the system for info about the memory system. */ System *system; diff --git a/src/dev/simconsole.cc b/src/dev/simconsole.cc index 77aafd9fa..c6ff9c1c6 100644 --- a/src/dev/simconsole.cc +++ b/src/dev/simconsole.cc @@ -56,17 +56,31 @@ using namespace std; -//////////////////////////////////////////////////////////////////////// -// -// -SimConsole::Event::Event(SimConsole *c, int fd, int e) +/* + * Poll event for the listen socket + */ +SimConsole::ListenEvent::ListenEvent(SimConsole *c, int fd, int e) : PollEvent(fd, e), cons(c) { } void -SimConsole::Event::process(int revent) +SimConsole::ListenEvent::process(int revent) +{ + cons->accept(); +} + +/* + * Poll event for the data socket + */ +SimConsole::DataEvent::DataEvent(SimConsole *c, int fd, int e) + : PollEvent(fd, e), cons(c) +{ +} + +void +SimConsole::DataEvent::process(int revent) { if (revent & POLLIN) cons->data(); @@ -74,41 +88,76 @@ SimConsole::Event::process(int revent) cons->detach(); } -SimConsole::SimConsole(const string &name, ostream *os, int num) - : SimObject(name), event(NULL), number(num), in_fd(-1), out_fd(-1), - listener(NULL), txbuf(16384), rxbuf(16384), outfile(os) +/* + * SimConsole code + */ +SimConsole::SimConsole(const string &name, ostream *os, int num, int port) + : SimObject(name), listenEvent(NULL), dataEvent(NULL), number(num), + data_fd(-1), txbuf(16384), rxbuf(16384), outfile(os) #if TRACING_ON == 1 , linebuf(16384) #endif { if (outfile) outfile->setf(ios::unitbuf); + + if (port) + listen(port); } SimConsole::~SimConsole() { - close(); + if (data_fd != -1) + ::close(data_fd); + + if (listenEvent) + delete listenEvent; + + if (dataEvent) + delete dataEvent; } +/////////////////////////////////////////////////////////////////////// +// socket creation and console attach +// + void -SimConsole::close() +SimConsole::listen(int port) { - if (in_fd != -1) - ::close(in_fd); + while (!listener.listen(port, true)) { + DPRINTF(Console, + ": can't bind address console port %d inuse PID %d\n", + port, getpid()); + port++; + } - if (out_fd != in_fd && out_fd != -1) - ::close(out_fd); + int p1, p2; + p2 = name().rfind('.') - 1; + p1 = name().rfind('.', p2); + ccprintf(cerr, "Listening for %s connection on port %d\n", + name().substr(p1+1,p2-p1), port); + + listenEvent = new ListenEvent(this, listener.getfd(), POLLIN); + pollQueue.schedule(listenEvent); } void -SimConsole::attach(int in, int out, ConsoleListener *l) +SimConsole::accept() { - in_fd = in; - out_fd = out; - listener = l; + if (!listener.islistening()) + panic("%s: cannot accept a connection if not listening!", name()); - event = new Event(this, in, POLLIN); - pollQueue.schedule(event); + int fd = listener.accept(true); + if (data_fd != -1) { + char message[] = "console already attached!\n"; + ::write(fd, message, sizeof(message)); + ::close(fd); + return; + } + + data_fd = fd; + dataEvent = new DataEvent(this, data_fd, POLLIN); + pollQueue.schedule(dataEvent); stringstream stream; ccprintf(stream, "==== m5 slave console: Console %d ====", number); @@ -119,26 +168,23 @@ SimConsole::attach(int in, int out, ConsoleListener *l) write((const uint8_t *)stream.str().c_str(), stream.str().size()); - DPRINTFN("attach console %d\n", number); - txbuf.readall(out); + txbuf.readall(data_fd); } void SimConsole::detach() { - close(); - in_fd = -1; - out_fd = -1; - - pollQueue.remove(event); - - if (listener) { - listener->add(this); - listener = NULL; + if (data_fd != -1) { + ::close(data_fd); + data_fd = -1; } + pollQueue.remove(dataEvent); + delete dataEvent; + dataEvent = NULL; + DPRINTFN("detach console %d\n", number); } @@ -159,12 +205,12 @@ SimConsole::data() size_t SimConsole::read(uint8_t *buf, size_t len) { - if (in_fd < 0) + if (data_fd < 0) panic("Console not properly attached.\n"); size_t ret; do { - ret = ::read(in_fd, buf, len); + ret = ::read(data_fd, buf, len); } while (ret == -1 && errno == EINTR); @@ -183,12 +229,12 @@ SimConsole::read(uint8_t *buf, size_t len) size_t SimConsole::write(const uint8_t *buf, size_t len) { - if (out_fd < 0) + if (data_fd < 0) panic("Console not properly attached.\n"); size_t ret; for (;;) { - ret = ::write(out_fd, buf, len); + ret = ::write(data_fd, buf, len); if (ret >= 0) break; @@ -268,7 +314,7 @@ SimConsole::out(char c) txbuf.write(c); - if (out_fd >= 0) + if (data_fd >= 0) write(c); if (outfile) @@ -279,23 +325,11 @@ SimConsole::out(char c) } - -void -SimConsole::serialize(ostream &os) -{ -} - -void -SimConsole::unserialize(Checkpoint *cp, const std::string §ion) -{ -} - - BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimConsole) - SimObjectParam<ConsoleListener *> listener; SimObjectParam<IntrControl *> intr_control; Param<string> output; + Param<int> port; Param<bool> append_name; Param<int> number; @@ -303,9 +337,9 @@ END_DECLARE_SIM_OBJECT_PARAMS(SimConsole) BEGIN_INIT_SIM_OBJECT_PARAMS(SimConsole) - INIT_PARAM(listener, "console listener"), INIT_PARAM(intr_control, "interrupt controller"), INIT_PARAM(output, "file to dump output to"), + INIT_PARAM(port, ""), INIT_PARAM_DFLT(append_name, "append name() to filename", true), INIT_PARAM_DFLT(number, "console number", 0) @@ -322,95 +356,7 @@ CREATE_SIM_OBJECT(SimConsole) stream = simout.find(filename); } - SimConsole *console = new SimConsole(getInstanceName(), stream, number); - ((ConsoleListener *)listener)->add(console); - - return console; + return new SimConsole(getInstanceName(), stream, number, port); } REGISTER_SIM_OBJECT("SimConsole", SimConsole) - -//////////////////////////////////////////////////////////////////////// -// -// - -ConsoleListener::ConsoleListener(const string &name) - : SimObject(name), event(NULL) -{} - -ConsoleListener::~ConsoleListener() -{ - if (event) - delete event; -} - -void -ConsoleListener::Event::process(int revent) -{ - listener->accept(); -} - -/////////////////////////////////////////////////////////////////////// -// socket creation and console attach -// - -void -ConsoleListener::listen(int port) -{ - while (!listener.listen(port, true)) { - DPRINTF(Console, - ": can't bind address console port %d inuse PID %d\n", - port, getpid()); - port++; - } - - ccprintf(cerr, "Listening for console connection on port %d\n", port); - - event = new Event(this, listener.getfd(), POLLIN); - pollQueue.schedule(event); -} - -void -ConsoleListener::add(SimConsole *cons) -{ ConsoleList.push_back(cons);} - -void -ConsoleListener::accept() -{ - if (!listener.islistening()) - panic("%s: cannot accept a connection if not listening!", name()); - - int sfd = listener.accept(true); - if (sfd != -1) { - iter_t i = ConsoleList.begin(); - iter_t end = ConsoleList.end(); - if (i == end) { - close(sfd); - } else { - (*i)->attach(sfd, this); - i = ConsoleList.erase(i); - } - } -} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener) - - Param<int> port; - -END_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener) - -BEGIN_INIT_SIM_OBJECT_PARAMS(ConsoleListener) - - INIT_PARAM_DFLT(port, "listen port", 3456) - -END_INIT_SIM_OBJECT_PARAMS(ConsoleListener) - -CREATE_SIM_OBJECT(ConsoleListener) -{ - ConsoleListener *listener = new ConsoleListener(getInstanceName()); - listener->listen(port); - - return listener; -} - -REGISTER_SIM_OBJECT("ConsoleListener", ConsoleListener) diff --git a/src/dev/simconsole.hh b/src/dev/simconsole.hh index ec99c6028..18a193493 100644 --- a/src/dev/simconsole.hh +++ b/src/dev/simconsole.hh @@ -53,30 +53,47 @@ class SimConsole : public SimObject Uart *uart; protected: - class Event : public PollEvent + class ListenEvent : public PollEvent { protected: SimConsole *cons; public: - Event(SimConsole *c, int fd, int e); + ListenEvent(SimConsole *c, int fd, int e); void process(int revent); }; - friend class Event; - Event *event; + friend class ListenEvent; + ListenEvent *listenEvent; + + class DataEvent : public PollEvent + { + protected: + SimConsole *cons; + + public: + DataEvent(SimConsole *c, int fd, int e); + void process(int revent); + }; + + friend class DataEvent; + DataEvent *dataEvent; protected: int number; - int in_fd; - int out_fd; - ConsoleListener *listener; + int data_fd; public: - SimConsole(const std::string &name, std::ostream *os, int num); + SimConsole(const std::string &name, std::ostream *os, int num, int port); ~SimConsole(); protected: + ListenSocket listener; + + void listen(int port); + void accept(); + + protected: CircleBuf txbuf; CircleBuf rxbuf; std::ostream *outfile; @@ -88,17 +105,13 @@ class SimConsole : public SimObject /////////////////////// // Terminal Interface - void attach(int fd, ConsoleListener *l = NULL) { attach(fd, fd, l); } - void attach(int in, int out, ConsoleListener *l = NULL); - void detach(); - void data(); - void close(); void read(uint8_t &c) { read(&c, 1); } size_t read(uint8_t *buf, size_t len); void write(uint8_t c) { write(&c, 1); } size_t write(const uint8_t *buf, size_t len); + void detach(); public: ///////////////// @@ -126,43 +139,6 @@ class SimConsole : public SimObject //Ask the console if data is available bool dataAvailable() { return !rxbuf.empty(); } - - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); -}; - -class ConsoleListener : public SimObject -{ - protected: - class Event : public PollEvent - { - protected: - ConsoleListener *listener; - - public: - Event(ConsoleListener *l, int fd, int e) - : PollEvent(fd, e), listener(l) {} - void process(int revent); - }; - - friend class Event; - Event *event; - - typedef std::list<SimConsole *> list_t; - typedef list_t::iterator iter_t; - list_t ConsoleList; - - protected: - ListenSocket listener; - - public: - ConsoleListener(const std::string &name); - ~ConsoleListener(); - - void add(SimConsole *cons); - - void accept(); - void listen(int port); }; #endif // __CONSOLE_HH__ diff --git a/src/dev/sparc/SConscript b/src/dev/sparc/SConscript index 44b082b68..8511b16fb 100644 --- a/src/dev/sparc/SConscript +++ b/src/dev/sparc/SConscript @@ -29,21 +29,10 @@ # Authors: Steve Reinhardt # Gabe Black -import os.path, sys +Import('*') -# Import build environment variable from SConstruct. -Import('env') - -sources = [] - -sources += Split(''' - dtod.cc - t1000.cc - mm_disk.cc - ''') - -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] - -Return('sources') +if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'sparc': + Source('dtod.cc') + Source('iob.cc') + Source('t1000.cc') + Source('mm_disk.cc') diff --git a/src/dev/sparc/iob.cc b/src/dev/sparc/iob.cc new file mode 100644 index 000000000..e686e51f7 --- /dev/null +++ b/src/dev/sparc/iob.cc @@ -0,0 +1,402 @@ +/* + * 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 + * This device implemetns the niagara I/O bridge chip. It manages incomming + * interrupts and posts them to the CPU when needed. It holds mask registers and + * various status registers for CPUs to check what interrupts are pending as + * well as facilities to send IPIs to other cpus. + */ + +#include <cstring> + +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/faults.hh" +#include "base/trace.hh" +#include "cpu/intr_control.hh" +#include "dev/sparc/iob.hh" +#include "dev/platform.hh" +#include "mem/port.hh" +#include "mem/packet_access.hh" +#include "sim/builder.hh" +#include "sim/faults.hh" +#include "sim/system.hh" + +Iob::Iob(Params *p) + : PioDevice(p), ic(p->platform->intrctrl) +{ + iobManAddr = ULL(0x9800000000); + iobManSize = ULL(0x0100000000); + iobJBusAddr = ULL(0x9F00000000); + iobJBusSize = ULL(0x0100000000); + assert (params()->system->threadContexts.size() <= MaxNiagaraProcs); + // Get the interrupt controller from the platform + ic = platform->intrctrl; + + for (int x = 0; x < NumDeviceIds; ++x) { + intMan[x].cpu = 0; + intMan[x].vector = 0; + intCtl[x].mask = true; + intCtl[x].pend = false; + } + +} + +Tick +Iob::read(PacketPtr pkt) +{ + assert(pkt->result == Packet::Unknown); + + if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize) + readIob(pkt); + else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize) + readJBus(pkt); + else + panic("Invalid address reached Iob\n"); + + pkt->result = Packet::Success; + return pioDelay; +} + +void +Iob::readIob(PacketPtr pkt) +{ + Addr accessAddr = pkt->getAddr() - iobManAddr; + int index; + uint64_t data; + + if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) { + index = (accessAddr - IntManAddr) >> 3; + data = intMan[index].cpu << 8 | intMan[index].vector << 0; + pkt->set(data); + return; + } + + if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) { + index = (accessAddr - IntManAddr) >> 3; + data = intCtl[index].mask ? 1 << 2 : 0 | + intCtl[index].pend ? 1 << 0 : 0; + pkt->set(data); + return; + } + + if (accessAddr == JIntVecAddr) { + pkt->set(jIntVec); + return; + } + + panic("Read to unknown IOB offset 0x%x\n", accessAddr); +} + +void +Iob::readJBus(PacketPtr pkt) +{ + Addr accessAddr = pkt->getAddr() - iobJBusAddr; + int cpuid = pkt->req->getCpuNum(); + int index; + uint64_t data; + + + + + if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) { + index = (accessAddr - JIntData0Addr) >> 3; + pkt->set(jBusData0[index]); + return; + } + + if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) { + index = (accessAddr - JIntData1Addr) >> 3; + pkt->set(jBusData1[index]); + return; + } + + if (accessAddr == JIntDataA0Addr) { + pkt->set(jBusData0[cpuid]); + return; + } + + if (accessAddr == JIntDataA1Addr) { + pkt->set(jBusData1[cpuid]); + return; + } + + if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) { + index = (accessAddr - JIntBusyAddr) >> 3; + data = jIntBusy[index].busy ? 1 << 5 : 0 | + jIntBusy[index].source; + pkt->set(data); + return; + } + if (accessAddr == JIntABusyAddr) { + data = jIntBusy[cpuid].busy ? 1 << 5 : 0 | + jIntBusy[cpuid].source; + pkt->set(data); + return; + }; + + panic("Read to unknown JBus offset 0x%x\n", accessAddr); +} + +Tick +Iob::write(PacketPtr pkt) +{ + if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize) + writeIob(pkt); + else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize) + writeJBus(pkt); + else + panic("Invalid address reached Iob\n"); + + + pkt->result = Packet::Success; + return pioDelay; +} + +void +Iob::writeIob(PacketPtr pkt) +{ + Addr accessAddr = pkt->getAddr() - iobManAddr; + int index; + uint64_t data; + + if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) { + index = (accessAddr - IntManAddr) >> 3; + data = pkt->get<uint64_t>(); + intMan[index].cpu = bits(data,12,8); + intMan[index].vector = bits(data,5,0); + DPRINTF(Iob, "Wrote IntMan %d cpu %d, vec %d\n", index, + intMan[index].cpu, intMan[index].vector); + return; + } + + if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) { + index = (accessAddr - IntManAddr) >> 3; + data = pkt->get<uint64_t>(); + intCtl[index].mask = bits(data,2,2); + if (bits(data,1,1)) + intCtl[index].pend = false; + DPRINTF(Iob, "Wrote IntCtl %d pend %d cleared %d\n", index, + intCtl[index].pend, bits(data,2,2)); + return; + } + + if (accessAddr == JIntVecAddr) { + jIntVec = bits(pkt->get<uint64_t>(), 5,0); + DPRINTF(Iob, "Wrote jIntVec %d\n", jIntVec); + return; + } + + if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) { + Type type; + int cpu_id; + int vector; + index = (accessAddr - IntManAddr) >> 3; + data = pkt->get<uint64_t>(); + type = (Type)bits(data,17,16); + cpu_id = bits(data, 12,8); + vector = bits(data,5,0); + generateIpi(type,cpu_id, vector); + return; + } + + panic("Write to unknown IOB offset 0x%x\n", accessAddr); +} + +void +Iob::writeJBus(PacketPtr pkt) +{ + Addr accessAddr = pkt->getAddr() - iobJBusAddr; + int cpuid = pkt->req->getCpuNum(); + int index; + uint64_t data; + + if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) { + index = (accessAddr - JIntBusyAddr) >> 3; + data = pkt->get<uint64_t>(); + jIntBusy[index].busy = bits(data,5,5); + DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", index, + jIntBusy[index].busy); + return; + } + if (accessAddr == JIntABusyAddr) { + data = pkt->get<uint64_t>(); + jIntBusy[cpuid].busy = bits(data,5,5); + DPRINTF(Iob, "Wrote jIntBusy index %d busy: %d\n", cpuid, + jIntBusy[cpuid].busy); + return; + }; + + panic("Write to unknown JBus offset 0x%x\n", accessAddr); +} + +void +Iob::receiveDeviceInterrupt(DeviceId devid) +{ + assert(devid < NumDeviceIds); + if (intCtl[devid].mask) + return; + intCtl[devid].mask = true; + intCtl[devid].pend = true; + DPRINTF(Iob, "Receiving Device interrupt: %d for cpu %d vec %d\n", + devid, intMan[devid].cpu, intMan[devid].vector); + ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector); +} + + +void +Iob::generateIpi(Type type, int cpu_id, int vector) +{ + SparcISA::SparcFault<SparcISA::PowerOnReset> *por = new SparcISA::PowerOnReset(); + if (cpu_id >= sys->getNumCPUs()) + return; + + switch (type) { + case 0: // interrupt + DPRINTF(Iob, "Generating interrupt because of I/O write to cpu: %d vec %d\n", + cpu_id, vector); + ic->post(cpu_id, SparcISA::IT_INT_VEC, vector); + break; + case 1: // reset + warn("Sending reset to CPU: %d\n", cpu_id); + if (vector != por->trapType()) + panic("Don't know how to set non-POR reset to cpu\n"); + por->invoke(sys->threadContexts[cpu_id]); + sys->threadContexts[cpu_id]->activate(); + break; + case 2: // idle -- this means stop executing and don't wake on interrupts + DPRINTF(Iob, "Idling CPU because of I/O write cpu: %d\n", cpu_id); + sys->threadContexts[cpu_id]->halt(); + break; + case 3: // resume + DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id); + sys->threadContexts[cpu_id]->activate(); + break; + default: + panic("Invalid type to generate ipi\n"); + } +} + +bool +Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1) +{ + // If we are already dealing with an interrupt for that cpu we can't deal + // with another one right now... come back later + if (jIntBusy[cpu_id].busy) + return false; + + DPRINTF(Iob, "Receiving jBus interrupt: %d for cpu %d vec %d\n", + source, cpu_id, jIntVec); + + jIntBusy[cpu_id].busy = true; + jIntBusy[cpu_id].source = source; + jBusData0[cpu_id] = d0; + jBusData1[cpu_id] = d1; + + ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec); + return true; +} + +void +Iob::addressRanges(AddrRangeList &range_list) +{ + range_list.clear(); + range_list.push_back(RangeSize(iobManAddr, iobManSize)); + range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize)); +} + + +void +Iob::serialize(std::ostream &os) +{ + + SERIALIZE_SCALAR(jIntVec); + SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs); + SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs); + for (int x = 0; x < NumDeviceIds; x++) { + nameOut(os, csprintf("%s.Int%d", name(), x)); + paramOut(os, "cpu", intMan[x].cpu); + paramOut(os, "vector", intMan[x].vector); + paramOut(os, "mask", intCtl[x].mask); + paramOut(os, "pend", intCtl[x].pend); + }; + for (int x = 0; x < MaxNiagaraProcs; x++) { + nameOut(os, csprintf("%s.jIntBusy%d", name(), x)); + paramOut(os, "busy", jIntBusy[x].busy); + paramOut(os, "source", jIntBusy[x].source); + }; +} + +void +Iob::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(jIntVec); + UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs); + UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs); + for (int x = 0; x < NumDeviceIds; x++) { + paramIn(cp, csprintf("%s.Int%d", name(), x), "cpu", intMan[x].cpu); + paramIn(cp, csprintf("%s.Int%d", name(), x), "vector", intMan[x].vector); + paramIn(cp, csprintf("%s.Int%d", name(), x), "mask", intCtl[x].mask); + paramIn(cp, csprintf("%s.Int%d", name(), x), "pend", intCtl[x].pend); + }; + for (int x = 0; x < MaxNiagaraProcs; x++) { + paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "busy", jIntBusy[x].busy); + paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "source", jIntBusy[x].source); + }; +} + + + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(Iob) + Param<Tick> pio_latency; + SimObjectParam<Platform *> platform; + SimObjectParam<System *> system; +END_DECLARE_SIM_OBJECT_PARAMS(Iob) + +BEGIN_INIT_SIM_OBJECT_PARAMS(Iob) + + INIT_PARAM(pio_latency, "Programmed IO latency"), + INIT_PARAM(platform, "platform"), + INIT_PARAM(system, "system object") + +END_INIT_SIM_OBJECT_PARAMS(Iob) + +CREATE_SIM_OBJECT(Iob) +{ + Iob::Params *p = new Iob::Params; + p->name = getInstanceName(); + p->pio_delay = pio_latency; + p->platform = platform; + p->system = system; + return new Iob(p); +} + +REGISTER_SIM_OBJECT("Iob", Iob) diff --git a/src/dev/sparc/iob.hh b/src/dev/sparc/iob.hh new file mode 100644 index 000000000..c05c4f2ef --- /dev/null +++ b/src/dev/sparc/iob.hh @@ -0,0 +1,153 @@ +/* + * 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 + * This device implements the niagara I/O Bridge chip. The device manages + * internal (ipi) and external (serial, pci via jbus). + */ + +#ifndef __DEV_SPARC_IOB_HH__ +#define __DEV_SPARC_IOB_HH__ + +#include "base/range.hh" +#include "dev/io_device.hh" +#include "dev/disk_image.hh" + +class IntrControl; + +const int MaxNiagaraProcs = 32; +// IOB Managment Addresses +const Addr IntManAddr = 0x0000; +const Addr IntManSize = 0x0020; +const Addr IntCtlAddr = 0x0400; +const Addr IntCtlSize = 0x0020; +const Addr JIntVecAddr = 0x0A00; +const Addr IntVecDisAddr = 0x0800; +const Addr IntVecDisSize = 0x0100; + + +// IOB Control Addresses +const Addr JIntData0Addr = 0x0400; +const Addr JIntData1Addr = 0x0500; +const Addr JIntDataA0Addr = 0x0600; +const Addr JIntDataA1Addr = 0x0700; +const Addr JIntBusyAddr = 0x0900; +const Addr JIntBusySize = 0x0100; +const Addr JIntABusyAddr = 0x0B00; + + +// IOB Masks +const uint64_t IntManMask = 0x01F3F; +const uint64_t IntCtlMask = 0x00006; +const uint64_t JIntVecMask = 0x0003F; +const uint64_t IntVecDis = 0x31F3F; +const uint64_t JIntBusyMask = 0x0003F; + + +class Iob : public PioDevice +{ + private: + IntrControl *ic; + Addr iobManAddr; + Addr iobManSize; + Addr iobJBusAddr; + Addr iobJBusSize; + Tick pioDelay; + + enum DeviceId { + Interal = 0, + Error = 1, + SSI = 2, + Reserved = 3, + NumDeviceIds + }; + + struct IntMan { + int cpu; + int vector; + }; + + struct IntCtl { + bool mask; + bool pend; + }; + + struct IntBusy { + bool busy; + int source; + }; + + enum Type { + Interrupt, + Reset, + Idle, + Resume + }; + + IntMan intMan[NumDeviceIds]; + IntCtl intCtl[NumDeviceIds]; + uint64_t jIntVec; + uint64_t jBusData0[MaxNiagaraProcs]; + uint64_t jBusData1[MaxNiagaraProcs]; + IntBusy jIntBusy[MaxNiagaraProcs]; + + void writeIob(PacketPtr pkt); + void writeJBus(PacketPtr pkt); + void readIob(PacketPtr pkt); + void readJBus(PacketPtr pkt); + + + public: + struct Params : public PioDevice::Params + { + Tick pio_delay; + }; + protected: + const Params *params() const { return (const Params*)_params; } + + public: + Iob(Params *p); + + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); + void generateIpi(Type type, int cpu_id, int vector); + void receiveDeviceInterrupt(DeviceId devid); + bool receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1); + + + void addressRanges(AddrRangeList &range_list); + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + +}; + +#endif //__DEV_SPARC_IOB_HH__ + diff --git a/src/dev/sparc/mm_disk.cc b/src/dev/sparc/mm_disk.cc index b8cabd0cf..81c5c589a 100644 --- a/src/dev/sparc/mm_disk.cc +++ b/src/dev/sparc/mm_disk.cc @@ -45,7 +45,7 @@ #include "sim/system.hh" MmDisk::MmDisk(Params *p) - : BasicPioDevice(p), image(p->image), curSector((uint64_t)-1), dirty(false) + : BasicPioDevice(p), image(p->image), curSector((off_t)-1), dirty(false) { std::memset(&diskData, 0, SectorSize); pioSize = image->size() * SectorSize; diff --git a/src/dev/uart.cc b/src/dev/uart.cc index f769b720b..1c781f76d 100644 --- a/src/dev/uart.cc +++ b/src/dev/uart.cc @@ -47,7 +47,6 @@ Uart::Uart(Params *p) // set back pointers cons->uart = this; - platform->uart = this; } DEFINE_SIM_OBJECT_CLASS_NAME("Uart", Uart) diff --git a/src/dev/uart8250.hh b/src/dev/uart8250.hh index a0620c7e0..c28200592 100644 --- a/src/dev/uart8250.hh +++ b/src/dev/uart8250.hh @@ -35,7 +35,6 @@ #ifndef __DEV_UART8250_HH__ #define __DEV_UART8250_HH__ -#include "dev/alpha/tsunamireg.h" #include "base/range.hh" #include "dev/io_device.hh" #include "dev/uart.hh" @@ -54,6 +53,18 @@ const uint8_t IIR_TXID = 0x02; /* Tx Data */ const uint8_t IIR_RXID = 0x04; /* Rx Data */ const uint8_t IIR_LINE = 0x06; /* Rx Line Status (highest priority)*/ +const uint8_t UART_IER_RDI = 0x01; +const uint8_t UART_IER_THRI = 0x02; +const uint8_t UART_IER_RLSI = 0x04; + + +const uint8_t UART_LSR_TEMT = 0x40; +const uint8_t UART_LSR_THRE = 0x20; +const uint8_t UART_LSR_DR = 0x01; + +const uint8_t UART_MCR_LOOP = 0x10; + + class SimConsole; class Platform; diff --git a/src/kern/SConscript b/src/kern/SConscript index 12df28836..eec8012a7 100644 --- a/src/kern/SConscript +++ b/src/kern/SConscript @@ -28,21 +28,18 @@ # # Authors: Steve Reinhardt -import os.path, sys +Import('*') -# Import build environment variable from SConstruct. -Import('env') +if env['FULL_SYSTEM']: + Source('kernel_stats.cc') + Source('system_events.cc') -sources = Split(''' - kernel_stats.cc - system_events.cc - linux/events.cc - linux/linux_syscalls.cc - linux/printk.cc - ''') + Source('linux/events.cc') + Source('linux/linux_syscalls.cc') + Source('linux/printk.cc') -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] - -Return('sources') + if env['TARGET_ISA'] == 'alpha': + Source('tru64/dump_mbuf.cc') + Source('tru64/printf.cc') + Source('tru64/tru64_events.cc') + Source('tru64/tru64_syscalls.cc') diff --git a/src/kern/linux/printk.cc b/src/kern/linux/printk.cc index ea3d59f19..0e9fd6620 100644 --- a/src/kern/linux/printk.cc +++ b/src/kern/linux/printk.cc @@ -41,11 +41,12 @@ using namespace std; void Printk(TheISA::Arguments args) { + std::ostream &out = Trace::output(); char *p = (char *)args++; - ios::fmtflags saved_flags = DebugOut().flags(); - char old_fill = DebugOut().fill(); - int old_precision = DebugOut().precision(); + ios::fmtflags saved_flags = out.flags(); + char old_fill = out.fill(); + int old_precision = out.precision(); while (*p) { switch (*p) { @@ -118,53 +119,53 @@ Printk(TheISA::Arguments args) case 'P': case 'p': { if (hexnum) - DebugOut() << hex; + out << hex; if (octal) - DebugOut() << oct; + out << oct; if (format) { if (!zero) - DebugOut().setf(ios::showbase); + out.setf(ios::showbase); else { if (hexnum) { - DebugOut() << "0x"; + out << "0x"; width -= 2; } else if (octal) { - DebugOut() << "0"; + out << "0"; width -= 1; } } } if (zero) - DebugOut().fill('0'); + out.fill('0'); if (width > 0) - DebugOut().width(width); + out.width(width); if (leftjustify && !zero) - DebugOut().setf(ios::left); + out.setf(ios::left); if (sign) { if (islong) - DebugOut() << (int64_t)args; + out << (int64_t)args; else - DebugOut() << (int32_t)args; + out << (int32_t)args; } else { if (islong) - DebugOut() << (uint64_t)args; + out << (uint64_t)args; else - DebugOut() << (uint32_t)args; + out << (uint32_t)args; } if (zero) - DebugOut().fill(' '); + out.fill(' '); if (width > 0) - DebugOut().width(0); + out.width(0); - DebugOut() << dec; + out << dec; ++args; } @@ -176,11 +177,11 @@ Printk(TheISA::Arguments args) s = "<NULL>"; if (width > 0) - DebugOut().width(width); + out.width(width); if (leftjustify) - DebugOut().setf(ios::left); + out.setf(ios::left); - DebugOut() << s; + out << s; ++args; } break; @@ -201,7 +202,7 @@ Printk(TheISA::Arguments args) while (width-- > 0) { char c = (char)(num & mask); if (c) - DebugOut() << c; + out << c; num >>= 8; } @@ -211,7 +212,7 @@ Printk(TheISA::Arguments args) case 'b': { uint64_t n = (uint64_t)args++; char *s = (char *)args++; - DebugOut() << s << ": " << n; + out << s << ": " << n; } break; case 'n': @@ -233,32 +234,32 @@ Printk(TheISA::Arguments args) } break; case '%': - DebugOut() << '%'; + out << '%'; break; } ++p; } break; case '\n': - DebugOut() << endl; + out << endl; ++p; break; case '\r': ++p; if (*p != '\n') - DebugOut() << endl; + out << endl; break; default: { size_t len = strcspn(p, "%\n\r\0"); - DebugOut().write(p, len); + out.write(p, len); p += len; } } } - DebugOut().flags(saved_flags); - DebugOut().fill(old_fill); - DebugOut().precision(old_precision); + out.flags(saved_flags); + out.fill(old_fill); + out.precision(old_precision); } diff --git a/src/kern/tru64/dump_mbuf.cc b/src/kern/tru64/dump_mbuf.cc index 22d2228f0..5ccfbca5d 100644 --- a/src/kern/tru64/dump_mbuf.cc +++ b/src/kern/tru64/dump_mbuf.cc @@ -50,6 +50,7 @@ void DumpMbuf(Arguments args) { ThreadContext *tc = args.getThreadContext(); + StringWrap name(tc->getSystemPtr()->name()); Addr addr = (Addr)args; struct mbuf m; @@ -57,16 +58,14 @@ DumpMbuf(Arguments args) int count = m.m_pkthdr.len; - ccprintf(DebugOut(), "m=%#lx, m->m_pkthdr.len=%#d\n", addr, - m.m_pkthdr.len); + DPRINTFN("m=%#lx, m->m_pkthdr.len=%#d\n", addr, m.m_pkthdr.len); while (count > 0) { - ccprintf(DebugOut(), "m=%#lx, m->m_data=%#lx, m->m_len=%d\n", + DPRINTFN("m=%#lx, m->m_data=%#lx, m->m_len=%d\n", addr, m.m_data, m.m_len); char *buffer = new char[m.m_len]; CopyOut(tc, buffer, m.m_data, m.m_len); - Trace::dataDump(curTick, tc->getSystemPtr()->name(), (uint8_t *)buffer, - m.m_len); + DDUMPN((uint8_t *)buffer, m.m_len); delete [] buffer; count -= m.m_len; diff --git a/src/kern/tru64/printf.cc b/src/kern/tru64/printf.cc index 2c767c4d2..4245ac6d0 100644 --- a/src/kern/tru64/printf.cc +++ b/src/kern/tru64/printf.cc @@ -44,11 +44,13 @@ namespace tru64 { void Printf(TheISA::Arguments args) { + std::ostream &out = Trace::output(); + char *p = (char *)args++; - ios::fmtflags saved_flags = DebugOut().flags(); - char old_fill = DebugOut().fill(); - int old_precision = DebugOut().precision(); + ios::fmtflags saved_flags = out.flags(); + char old_fill = out.fill(); + int old_precision = out.precision(); while (*p) { switch (*p) { @@ -121,53 +123,53 @@ Printf(TheISA::Arguments args) case 'P': case 'p': { if (hexnum) - DebugOut() << hex; + out << hex; if (octal) - DebugOut() << oct; + out << oct; if (format) { if (!zero) - DebugOut().setf(ios::showbase); + out.setf(ios::showbase); else { if (hexnum) { - DebugOut() << "0x"; + out << "0x"; width -= 2; } else if (octal) { - DebugOut() << "0"; + out << "0"; width -= 1; } } } if (zero) - DebugOut().fill('0'); + out.fill('0'); if (width > 0) - DebugOut().width(width); + out.width(width); if (leftjustify && !zero) - DebugOut().setf(ios::left); + out.setf(ios::left); if (sign) { if (islong) - DebugOut() << (int64_t)args; + out << (int64_t)args; else - DebugOut() << (int32_t)args; + out << (int32_t)args; } else { if (islong) - DebugOut() << (uint64_t)args; + out << (uint64_t)args; else - DebugOut() << (uint32_t)args; + out << (uint32_t)args; } if (zero) - DebugOut().fill(' '); + out.fill(' '); if (width > 0) - DebugOut().width(0); + out.width(0); - DebugOut() << dec; + out << dec; ++args; } @@ -179,11 +181,11 @@ Printf(TheISA::Arguments args) s = "<NULL>"; if (width > 0) - DebugOut().width(width); + out.width(width); if (leftjustify) - DebugOut().setf(ios::left); + out.setf(ios::left); - DebugOut() << s; + out << s; ++args; } break; @@ -204,7 +206,7 @@ Printf(TheISA::Arguments args) while (width-- > 0) { char c = (char)(num & mask); if (c) - DebugOut() << c; + out << c; num >>= 8; } @@ -214,7 +216,7 @@ Printf(TheISA::Arguments args) case 'b': { uint64_t n = (uint64_t)args++; char *s = (char *)args++; - DebugOut() << s << ": " << n; + out << s << ": " << n; } break; case 'n': @@ -236,33 +238,33 @@ Printf(TheISA::Arguments args) } break; case '%': - DebugOut() << '%'; + out << '%'; break; } ++p; } break; case '\n': - DebugOut() << endl; + out << endl; ++p; break; case '\r': ++p; if (*p != '\n') - DebugOut() << endl; + out << endl; break; default: { size_t len = strcspn(p, "%\n\r\0"); - DebugOut().write(p, len); + out.write(p, len); p += len; } } } - DebugOut().flags(saved_flags); - DebugOut().fill(old_fill); - DebugOut().precision(old_precision); + out.flags(saved_flags); + out.fill(old_fill); + out.precision(old_precision); } } // namespace Tru64 diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index 82db34bf6..b94276035 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -56,7 +56,7 @@ class Tru64 {}; #include <unistd.h> #include "cpu/base.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/syscall_emul.hh" typedef struct stat global_stat; @@ -511,7 +511,7 @@ class Tru64 : public OperatingSystem tc->setFloatRegBits(i, htog(sc->sc_fpregs[i])); } - tc->setMiscReg(AlphaISA::MISCREG_FPCR, htog(sc->sc_fpcr)); + tc->setMiscRegNoEffect(AlphaISA::MISCREG_FPCR, htog(sc->sc_fpcr)); return 0; } @@ -653,7 +653,7 @@ class Tru64 : public OperatingSystem ssp->nxm_sysevent = htog(0); if (i == 0) { - uint64_t uniq = tc->readMiscReg(AlphaISA::MISCREG_UNIQ); + uint64_t uniq = tc->readMiscRegNoEffect(AlphaISA::MISCREG_UNIQ); ssp->nxm_u.pth_id = htog(uniq + gtoh(attrp->nxm_uniq_offset)); ssp->nxm_u.nxm_active = htog(uniq | 1); } @@ -693,7 +693,7 @@ class Tru64 : public OperatingSystem tc->setIntReg(TheISA::ArgumentReg0, gtoh(attrp->registers.a0)); tc->setIntReg(27/*t12*/, gtoh(attrp->registers.pc)); tc->setIntReg(TheISA::StackPointerReg, gtoh(attrp->registers.sp)); - tc->setMiscReg(AlphaISA::MISCREG_UNIQ, uniq_val); + tc->setMiscRegNoEffect(AlphaISA::MISCREG_UNIQ, uniq_val); tc->setPC(gtoh(attrp->registers.pc)); tc->setNextPC(gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst)); diff --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc index 851b3a526..0ad89f8bd 100644 --- a/src/kern/tru64/tru64_events.cc +++ b/src/kern/tru64/tru64_events.cc @@ -79,7 +79,8 @@ void PrintfEvent::process(ThreadContext *tc) { if (DTRACE(Printf)) { - DebugOut() << curTick << ": " << tc->getCpuPtr()->name() << ": "; + StringWrap name(tc->getSystemPtr()->name()); + DPRINTFN(""); Arguments args(tc); tru64::Printf(args); @@ -90,8 +91,10 @@ void DebugPrintfEvent::process(ThreadContext *tc) { if (DTRACE(DebugPrintf)) { - if (!raw) - DebugOut() << curTick << ": " << tc->getCpuPtr()->name() << ": "; + if (!raw) { + StringWrap name(tc->getSystemPtr()->name()); + DPRINTFN(""); + } Arguments args(tc); tru64::Printf(args); diff --git a/src/mem/SConscript b/src/mem/SConscript new file mode 100644 index 000000000..61fb766d6 --- /dev/null +++ b/src/mem/SConscript @@ -0,0 +1,46 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +Source('bridge.cc') +Source('bus.cc') +Source('dram.cc') +Source('mem_object.cc') +Source('packet.cc') +Source('physical.cc') +Source('port.cc') +Source('tport.cc') + +if env['FULL_SYSTEM']: + Source('vport.cc') +else: + Source('page_table.cc') + Source('translating_port.cc') diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 401dc0186..6e6ba2380 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -34,6 +34,8 @@ */ +#include <limits> + #include "base/misc.hh" #include "base/trace.hh" #include "mem/bus.hh" @@ -52,20 +54,30 @@ Bus::getPort(const std::string &if_name, int idx) } // if_name ignored? forced to be empty? - int id = interfaces.size(); + int id = maxId++; + assert(maxId < std::numeric_limits<typeof(maxId)>::max()); BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id); - interfaces.push_back(bp); + interfaces[id] = bp; return bp; } +void +Bus::deletePortRefs(Port *p) +{ + BusPort *bp = dynamic_cast<BusPort*>(p); + if (bp == NULL) + panic("Couldn't convert Port* to BusPort*\n"); + interfaces.erase(bp->getId()); +} + /** Get the ranges of anyone other buses that we are connected to. */ void Bus::init() { - std::vector<BusPort*>::iterator intIter; + m5::hash_map<short,BusPort*>::iterator intIter; for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) - (*intIter)->sendStatusChange(Port::RangeChange); + intIter->second->sendStatusChange(Port::RangeChange); } Bus::BusFreeEvent::BusFreeEvent(Bus *_bus) : Event(&mainEventQueue), bus(_bus) @@ -184,12 +196,13 @@ Bus::recvTiming(PacketPtr pkt) } } else { //Snoop didn't succeed - DPRINTF(Bus, "Adding a retry to RETRY list %i\n", pktPort); + DPRINTF(Bus, "Adding a retry to RETRY list %d\n", + pktPort->getId()); addToRetryList(pktPort); return false; } } else { - assert(dest >= 0 && dest < interfaces.size()); + assert(dest >= 0 && dest < maxId); assert(dest != pkt->getSrc()); // catch infinite loops port = interfaces[dest]; } @@ -201,7 +214,8 @@ Bus::recvTiming(PacketPtr pkt) // Packet was successfully sent. Return true. // Also take care of retries if (inRetry) { - DPRINTF(Bus, "Remove retry from list %i\n", retryList.front()); + DPRINTF(Bus, "Remove retry from list %d\n", + retryList.front()->getId()); retryList.front()->onRetryList(false); retryList.pop_front(); inRetry = false; @@ -210,7 +224,8 @@ Bus::recvTiming(PacketPtr pkt) } // Packet not successfully sent. Leave or put it on the retry list. - DPRINTF(Bus, "Adding a retry to RETRY list %i\n", pktPort); + DPRINTF(Bus, "Adding a retry to RETRY list %d\n", + pktPort->getId()); addToRetryList(pktPort); return false; } @@ -436,7 +451,6 @@ Bus::recvStatusChange(Port::Status status, int id) { AddrRangeList ranges; AddrRangeList snoops; - int x; AddrRangeIter iter; assert(status == Port::RangeChange && @@ -458,7 +472,7 @@ Bus::recvStatusChange(Port::Status status, int id) } } else { - assert((id < interfaces.size() && id >= 0) || id == defaultId); + assert((id < maxId && id >= 0) || id == defaultId); Port *port = interfaces[id]; range_map<Addr,int>::iterator portIter; std::vector<DevMap>::iterator snoopIter; @@ -503,9 +517,11 @@ Bus::recvStatusChange(Port::Status status, int id) // tell all our peers that our address range has changed. // Don't tell the device that caused this change, it already knows - for (x = 0; x < interfaces.size(); x++) - if (x != id) - interfaces[x]->sendStatusChange(Port::RangeChange); + m5::hash_map<short,BusPort*>::iterator intIter; + + for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) + if (intIter->first != id) + intIter->second->sendStatusChange(Port::RangeChange); if (id != defaultId && defaultPort) defaultPort->sendStatusChange(Port::RangeChange); diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 0ad4aad60..6706b6c77 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -42,6 +42,7 @@ #include <inttypes.h> #include "base/range.hh" +#include "base/hashmap.hh" #include "base/range_map.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" @@ -156,6 +157,8 @@ class Bus : public MemObject void onRetryList(bool newVal) { _onRetryList = newVal; } + int getId() { return id; } + protected: /** When reciving a timing request from the peer port (at id), @@ -210,9 +213,12 @@ class Bus : public MemObject bool inRetry; + /** max number of bus ids we've handed out so far */ + short maxId; + /** An array of pointers to the peer port interfaces connected to this bus.*/ - std::vector<BusPort*> interfaces; + m5::hash_map<short,BusPort*> interfaces; /** An array of pointers to ports that retry should be called on because the * original send failed for whatever reason.*/ @@ -250,6 +256,7 @@ class Bus : public MemObject /** A function used to return the port associated with this bus object. */ virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual void deletePortRefs(Port *p); virtual void init(); @@ -259,7 +266,7 @@ class Bus : public MemObject bool responder_set) : MemObject(n), busId(bus_id), clock(_clock), width(_width), tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false), - defaultPort(NULL), responderSet(responder_set) + maxId(0), defaultPort(NULL), responderSet(responder_set) { //Both the width and clock period must be positive if (width <= 0) diff --git a/src/mem/cache/SConscript b/src/mem/cache/SConscript new file mode 100644 index 000000000..7150719ad --- /dev/null +++ b/src/mem/cache/SConscript @@ -0,0 +1,35 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +Source('base_cache.cc') +Source('cache.cc') +Source('cache_builder.cc') diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc index d9e6c5e1f..ed665dafb 100644 --- a/src/mem/cache/base_cache.cc +++ b/src/mem/cache/base_cache.cc @@ -356,7 +356,7 @@ BaseCache::CacheEvent::process() const char * BaseCache::CacheEvent::description() { - return "timing event\n"; + return "BaseCache timing event"; } void @@ -370,17 +370,12 @@ BaseCache::init() void BaseCache::regStats() { - Request temp_req((Addr) NULL, 4, 0); - Packet::Command temp_cmd = Packet::ReadReq; - Packet temp_pkt(&temp_req, temp_cmd, 0); //@todo FIx command strings so this isn't neccessary - temp_pkt.allocate(); //Temp allocate, all need data - using namespace Stats; // Hit statistics - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); hits[access_idx] .init(maxThreadsPerCPU) @@ -395,20 +390,20 @@ BaseCache::regStats() .desc("number of demand (read+write) hits") .flags(total) ; - demandHits = hits[Packet::ReadReq] + hits[Packet::WriteReq]; + demandHits = hits[MemCmd::ReadReq] + hits[MemCmd::WriteReq]; overallHits .name(name() + ".overall_hits") .desc("number of overall hits") .flags(total) ; - overallHits = demandHits + hits[Packet::SoftPFReq] + hits[Packet::HardPFReq] - + hits[Packet::Writeback]; + overallHits = demandHits + hits[MemCmd::SoftPFReq] + hits[MemCmd::HardPFReq] + + hits[MemCmd::Writeback]; // Miss statistics - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); misses[access_idx] .init(maxThreadsPerCPU) @@ -423,20 +418,20 @@ BaseCache::regStats() .desc("number of demand (read+write) misses") .flags(total) ; - demandMisses = misses[Packet::ReadReq] + misses[Packet::WriteReq]; + demandMisses = misses[MemCmd::ReadReq] + misses[MemCmd::WriteReq]; overallMisses .name(name() + ".overall_misses") .desc("number of overall misses") .flags(total) ; - overallMisses = demandMisses + misses[Packet::SoftPFReq] + - misses[Packet::HardPFReq] + misses[Packet::Writeback]; + overallMisses = demandMisses + misses[MemCmd::SoftPFReq] + + misses[MemCmd::HardPFReq] + misses[MemCmd::Writeback]; // Miss latency statistics - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); missLatency[access_idx] .init(maxThreadsPerCPU) @@ -451,20 +446,20 @@ BaseCache::regStats() .desc("number of demand (read+write) miss cycles") .flags(total) ; - demandMissLatency = missLatency[Packet::ReadReq] + missLatency[Packet::WriteReq]; + demandMissLatency = missLatency[MemCmd::ReadReq] + missLatency[MemCmd::WriteReq]; overallMissLatency .name(name() + ".overall_miss_latency") .desc("number of overall miss cycles") .flags(total) ; - overallMissLatency = demandMissLatency + missLatency[Packet::SoftPFReq] + - missLatency[Packet::HardPFReq]; + overallMissLatency = demandMissLatency + missLatency[MemCmd::SoftPFReq] + + missLatency[MemCmd::HardPFReq]; // access formulas - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); accesses[access_idx] .name(name() + "." + cstr + "_accesses") @@ -490,9 +485,9 @@ BaseCache::regStats() overallAccesses = overallHits + overallMisses; // miss rate formulas - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); missRate[access_idx] .name(name() + "." + cstr + "_miss_rate") @@ -518,9 +513,9 @@ BaseCache::regStats() overallMissRate = overallMisses / overallAccesses; // miss latency formulas - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); avgMissLatency[access_idx] .name(name() + "." + cstr + "_avg_miss_latency") diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh index c10d98e8e..ee871c1c4 100644 --- a/src/mem/cache/base_cache.hh +++ b/src/mem/cache/base_cache.hh @@ -200,14 +200,14 @@ class BaseCache : public MemObject */ /** Number of hits per thread for each type of command. @sa Packet::Command */ - Stats::Vector<> hits[NUM_MEM_CMDS]; + Stats::Vector<> hits[MemCmd::NUM_MEM_CMDS]; /** Number of hits for demand accesses. */ Stats::Formula demandHits; /** Number of hit for all accesses. */ Stats::Formula overallHits; /** Number of misses per thread for each type of command. @sa Packet::Command */ - Stats::Vector<> misses[NUM_MEM_CMDS]; + Stats::Vector<> misses[MemCmd::NUM_MEM_CMDS]; /** Number of misses for demand accesses. */ Stats::Formula demandMisses; /** Number of misses for all accesses. */ @@ -217,28 +217,28 @@ class BaseCache : public MemObject * Total number of cycles per thread/command spent waiting for a miss. * Used to calculate the average miss latency. */ - Stats::Vector<> missLatency[NUM_MEM_CMDS]; + Stats::Vector<> missLatency[MemCmd::NUM_MEM_CMDS]; /** Total number of cycles spent waiting for demand misses. */ Stats::Formula demandMissLatency; /** Total number of cycles spent waiting for all misses. */ Stats::Formula overallMissLatency; /** The number of accesses per command and thread. */ - Stats::Formula accesses[NUM_MEM_CMDS]; + Stats::Formula accesses[MemCmd::NUM_MEM_CMDS]; /** The number of demand accesses. */ Stats::Formula demandAccesses; /** The number of overall accesses. */ Stats::Formula overallAccesses; /** The miss rate per command and thread. */ - Stats::Formula missRate[NUM_MEM_CMDS]; + Stats::Formula missRate[MemCmd::NUM_MEM_CMDS]; /** The miss rate of all demand accesses. */ Stats::Formula demandMissRate; /** The miss rate for all accesses. */ Stats::Formula overallMissRate; /** The average miss latency per command and thread. */ - Stats::Formula avgMissLatency[NUM_MEM_CMDS]; + Stats::Formula avgMissLatency[MemCmd::NUM_MEM_CMDS]; /** The average miss latency for demand misses. */ Stats::Formula demandAvgMissLatency; /** The average miss latency for all misses. */ @@ -535,7 +535,7 @@ class BaseCache : public MemObject } } else { - if (pkt->cmd != Packet::UpgradeReq) + if (pkt->cmd != MemCmd::UpgradeReq) { delete pkt->req; delete pkt; @@ -594,7 +594,7 @@ class BaseCache : public MemObject } } else { - if (pkt->cmd != Packet::UpgradeReq) + if (pkt->cmd != MemCmd::UpgradeReq) { delete pkt->req; delete pkt; diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 26dab2179..722ce216b 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -331,6 +331,7 @@ class Cache : public BaseCache Cache(const std::string &_name, Params ¶ms); virtual Port *getPort(const std::string &if_name, int idx = -1); + virtual void deletePortRefs(Port *p); virtual void recvStatusChange(Port::Status status, bool isCpuSide); diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh index 7b999e4b1..fa00a0f5a 100644 --- a/src/mem/cache/cache_blk.hh +++ b/src/mem/cache/cache_blk.hh @@ -37,7 +37,7 @@ #include <list> -#include "sim/root.hh" // for Tick +#include "sim/core.hh" // for Tick #include "arch/isa_traits.hh" // for Addr #include "mem/request.hh" @@ -249,7 +249,7 @@ class CacheBlk } } - req->setScResult(success ? 1 : 0); + req->setExtraData(success ? 1 : 0); clearLoadLocks(); return success; } else { diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 08e226343..fc4660269 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -90,7 +90,7 @@ Cache(const std::string &_name, coherence->setCache(this); prefetcher->setCache(this); invalidateReq = new Request((Addr) NULL, blkSize, 0); - invalidatePkt = new Packet(invalidateReq, Packet::InvalidateReq, 0); + invalidatePkt = new Packet(invalidateReq, MemCmd::InvalidateReq, 0); } template<class TagStore, class Coherence> @@ -206,7 +206,7 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat, // complete miss (no matching block) if (pkt->req->isLocked() && pkt->isWrite()) { // miss on store conditional... just give up now - pkt->req->setScResult(0); + pkt->req->setExtraData(0); pkt->flags |= SATISFIED; } } @@ -239,7 +239,7 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt, target->flags |= SATISFIED; - if (target->cmd == Packet::InvalidateReq) { + if (target->cmd == MemCmd::InvalidateReq) { tags->invalidateBlk(blk); blk = NULL; } @@ -316,7 +316,7 @@ Cache<TagStore,Coherence>::handleFill(BlkType *blk, MSHR * mshr, Tick completion_time = tags->getHitLatency() + transfer_offset ? pkt->finishTime : pkt->firstWordTime; - if (target->cmd == Packet::InvalidateReq) { + if (target->cmd == MemCmd::InvalidateReq) { //Mark the blk as invalid now, if it hasn't been already if (blk) { tags->invalidateBlk(blk); @@ -430,7 +430,7 @@ Cache<TagStore,Coherence>::writebackBlk(BlkType *blk) Request *writebackReq = new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0); - PacketPtr writeback = new Packet(writebackReq, Packet::Writeback, -1); + PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback, -1); writeback->allocate(); std::memcpy(writeback->getPtr<uint8_t>(),blk->data,blkSize); @@ -560,11 +560,11 @@ Cache<TagStore,Coherence>::access(PacketPtr &pkt) /** @todo make the fast write alloc (wh64) work with coherence. */ /** @todo Do we want to do fast writes for writebacks as well? */ if (!blk && pkt->getSize() >= blkSize && coherence->allowFastWrites() && - (pkt->cmd == Packet::WriteReq - || pkt->cmd == Packet::WriteInvalidateReq) ) { + (pkt->cmd == MemCmd::WriteReq + || pkt->cmd == MemCmd::WriteInvalidateReq) ) { // not outstanding misses, can do this MSHR* outstanding_miss = missQueue->findMSHR(pkt->getAddr()); - if (pkt->cmd == Packet::WriteInvalidateReq || !outstanding_miss) { + if (pkt->cmd == MemCmd::WriteInvalidateReq || !outstanding_miss) { if (outstanding_miss) { warn("WriteInv doing a fastallocate" "with an outstanding miss to the same address\n"); @@ -575,8 +575,10 @@ Cache<TagStore,Coherence>::access(PacketPtr &pkt) } } while (!writebacks.empty()) { - missQueue->doWriteback(writebacks.front()); + PacketPtr wbPkt = writebacks.front(); + missQueue->doWriteback(wbPkt); writebacks.pop_front(); + delete wbPkt; } DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(), pkt->getAddr(), @@ -586,12 +588,7 @@ Cache<TagStore,Coherence>::access(PacketPtr &pkt) // Hit hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; // clear dirty bit if write through - if (pkt->needsResponse()) - respond(pkt, curTick+lat); - if (pkt->cmd == Packet::Writeback) { - //Signal that you can kill the pkt/req - pkt->flags |= SATISFIED; - } + respond(pkt, curTick+lat); return true; } @@ -609,14 +606,14 @@ Cache<TagStore,Coherence>::access(PacketPtr &pkt) if (pkt->flags & SATISFIED) { // happens when a store conditional fails because it missed // the cache completely - if (pkt->needsResponse()) - respond(pkt, curTick+lat); + respond(pkt, curTick+lat); } else { missQueue->handleMiss(pkt, size, curTick + hitLatency); } - if (pkt->cmd == Packet::Writeback) { + if (!pkt->needsResponse()) { //Need to clean up the packet on a writeback miss, but leave the request + //for the next level. delete pkt; } @@ -632,11 +629,11 @@ Cache<TagStore,Coherence>::getPacket() PacketPtr pkt = missQueue->getPacket(); if (pkt) { if (!pkt->req->isUncacheable()) { - if (pkt->cmd == Packet::HardPFReq) - misses[Packet::HardPFReq][0/*pkt->req->getThreadNum()*/]++; + if (pkt->cmd == MemCmd::HardPFReq) + misses[MemCmd::HardPFReq][0/*pkt->req->getThreadNum()*/]++; BlkType *blk = tags->findBlock(pkt->getAddr()); - Packet::Command cmd = coherence->getBusCmd(pkt->cmd, - (blk)? blk->status : 0); + MemCmd cmd = + coherence->getBusCmd(pkt->cmd, (blk) ? blk->status : 0); missQueue->setBusCmd(pkt, cmd); } } @@ -655,7 +652,7 @@ Cache<TagStore,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr, if (success && !(SIGNAL_NACK_HACK)) { //Remember if it was an upgrade because writeback MSHR's are removed //in Mark in Service - bool upgrade = (mshr->pkt && mshr->pkt->cmd == Packet::UpgradeReq); + bool upgrade = (mshr->pkt && mshr->pkt->cmd == MemCmd::UpgradeReq); missQueue->markInService(mshr->pkt, mshr); @@ -726,8 +723,10 @@ Cache<TagStore,Coherence>::handleResponse(PacketPtr &pkt) blk = handleFill(blk, (MSHR*)pkt->senderState, new_state, writebacks, pkt); while (!writebacks.empty()) { - missQueue->doWriteback(writebacks.front()); - writebacks.pop_front(); + PacketPtr wbPkt = writebacks.front(); + missQueue->doWriteback(wbPkt); + writebacks.pop_front(); + delete wbPkt; } } missQueue->handleResponse(pkt, curTick + hitLatency); @@ -780,8 +779,8 @@ Cache<TagStore,Coherence>::snoop(PacketPtr &pkt) if (mshr) { if (mshr->inService) { if ((mshr->pkt->isInvalidate() || !mshr->pkt->isCacheFill()) - && (pkt->cmd != Packet::InvalidateReq - && pkt->cmd != Packet::WriteInvalidateReq)) { + && (pkt->cmd != MemCmd::InvalidateReq + && pkt->cmd != MemCmd::WriteInvalidateReq)) { //If the outstanding request was an invalidate //(upgrade,readex,..) Then we need to ACK the request //until we get the data Also NACK if the outstanding @@ -987,11 +986,11 @@ Cache<TagStore,Coherence>::probe(PacketPtr &pkt, bool update, panic("Atomic access ran into outstanding MSHR's or WB's!"); } if (!pkt->req->isUncacheable() /*Uncacheables just go through*/ - && (pkt->cmd != Packet::Writeback)/*Writebacks on miss fall through*/) { + && (pkt->cmd != MemCmd::Writeback)/*Writebacks on miss fall through*/) { // Fetch the cache block to fill BlkType *blk = tags->findBlock(pkt->getAddr()); - Packet::Command temp_cmd = coherence->getBusCmd(pkt->cmd, - (blk)? blk->status : 0); + MemCmd temp_cmd = + coherence->getBusCmd(pkt->cmd, (blk) ? blk->status : 0); PacketPtr busPkt = new Packet(pkt->req,temp_cmd, -1, blkSize); @@ -1045,8 +1044,10 @@ return 0; // There was a cache hit. // Handle writebacks if needed while (!writebacks.empty()){ - memSidePort->sendAtomic(writebacks.front()); + PacketPtr wbPkt = writebacks.front(); + memSidePort->sendAtomic(wbPkt); writebacks.pop_front(); + delete wbPkt; } hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; @@ -1105,7 +1106,7 @@ Cache<TagStore,Coherence>::getPort(const std::string &if_name, int idx) } else if (if_name == "functional") { - return new CpuSidePort(name() + "-cpu_side_port", this); + return new CpuSidePort(name() + "-cpu_side_funcport", this); } else if (if_name == "cpu_side") { @@ -1126,6 +1127,15 @@ Cache<TagStore,Coherence>::getPort(const std::string &if_name, int idx) else panic("Port name %s unrecognized\n", if_name); } +template<class TagStore, class Coherence> +void +Cache<TagStore,Coherence>::deletePortRefs(Port *p) +{ + if (cpuSidePort == p || memSidePort == p) + panic("Can only delete functional ports\n"); + // nothing else to do +} + template<class TagStore, class Coherence> bool @@ -1152,7 +1162,7 @@ Cache<TagStore,Coherence>::CpuSidePort::recvTiming(PacketPtr pkt) } if (pkt->isWrite() && (pkt->req->isLocked())) { - pkt->req->setScResult(1); + pkt->req->setExtraData(1); } myCache()->access(pkt); return true; diff --git a/src/mem/cache/coherence/SConscript b/src/mem/cache/coherence/SConscript new file mode 100644 index 000000000..03a2d85d7 --- /dev/null +++ b/src/mem/cache/coherence/SConscript @@ -0,0 +1,35 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +Source('coherence_protocol.cc') +Source('uni_coherence.cc') + diff --git a/src/mem/cache/coherence/coherence_protocol.cc b/src/mem/cache/coherence/coherence_protocol.cc index 3d7721805..e8520401d 100644 --- a/src/mem/cache/coherence/coherence_protocol.cc +++ b/src/mem/cache/coherence/coherence_protocol.cc @@ -47,7 +47,7 @@ using namespace std; CoherenceProtocol::StateTransition::StateTransition() - : busCmd(Packet::InvalidCmd), newState(-1), snoopFunc(invalidTransition) + : busCmd(MemCmd::InvalidCmd), newState(-1), snoopFunc(invalidTransition) { } @@ -59,132 +59,132 @@ CoherenceProtocol::regStats() // requestCount and snoopCount arrays, most of these are invalid, // so we just select the interesting ones to print here. - requestCount[Invalid][Packet::ReadReq] + requestCount[Invalid][MemCmd::ReadReq] .name(name() + ".read_invalid") .desc("read misses to invalid blocks") ; - requestCount[Invalid][Packet::WriteReq] + requestCount[Invalid][MemCmd::WriteReq] .name(name() +".write_invalid") .desc("write misses to invalid blocks") ; - requestCount[Invalid][Packet::SoftPFReq] + requestCount[Invalid][MemCmd::SoftPFReq] .name(name() +".swpf_invalid") .desc("soft prefetch misses to invalid blocks") ; - requestCount[Invalid][Packet::HardPFReq] + requestCount[Invalid][MemCmd::HardPFReq] .name(name() +".hwpf_invalid") .desc("hard prefetch misses to invalid blocks") ; - requestCount[Shared][Packet::WriteReq] + requestCount[Shared][MemCmd::WriteReq] .name(name() + ".write_shared") .desc("write misses to shared blocks") ; - requestCount[Owned][Packet::WriteReq] + requestCount[Owned][MemCmd::WriteReq] .name(name() + ".write_owned") .desc("write misses to owned blocks") ; - snoopCount[Shared][Packet::ReadReq] + snoopCount[Shared][MemCmd::ReadReq] .name(name() + ".snoop_read_shared") .desc("read snoops on shared blocks") ; - snoopCount[Shared][Packet::ReadExReq] + snoopCount[Shared][MemCmd::ReadExReq] .name(name() + ".snoop_readex_shared") .desc("readEx snoops on shared blocks") ; - snoopCount[Shared][Packet::UpgradeReq] + snoopCount[Shared][MemCmd::UpgradeReq] .name(name() + ".snoop_upgrade_shared") .desc("upgradee snoops on shared blocks") ; - snoopCount[Modified][Packet::ReadReq] + snoopCount[Modified][MemCmd::ReadReq] .name(name() + ".snoop_read_modified") .desc("read snoops on modified blocks") ; - snoopCount[Modified][Packet::ReadExReq] + snoopCount[Modified][MemCmd::ReadExReq] .name(name() + ".snoop_readex_modified") .desc("readEx snoops on modified blocks") ; - snoopCount[Owned][Packet::ReadReq] + snoopCount[Owned][MemCmd::ReadReq] .name(name() + ".snoop_read_owned") .desc("read snoops on owned blocks") ; - snoopCount[Owned][Packet::ReadExReq] + snoopCount[Owned][MemCmd::ReadExReq] .name(name() + ".snoop_readex_owned") .desc("readEx snoops on owned blocks") ; - snoopCount[Owned][Packet::UpgradeReq] + snoopCount[Owned][MemCmd::UpgradeReq] .name(name() + ".snoop_upgrade_owned") .desc("upgrade snoops on owned blocks") ; - snoopCount[Exclusive][Packet::ReadReq] + snoopCount[Exclusive][MemCmd::ReadReq] .name(name() + ".snoop_read_exclusive") .desc("read snoops on exclusive blocks") ; - snoopCount[Exclusive][Packet::ReadExReq] + snoopCount[Exclusive][MemCmd::ReadExReq] .name(name() + ".snoop_readex_exclusive") .desc("readEx snoops on exclusive blocks") ; - snoopCount[Shared][Packet::InvalidateReq] + snoopCount[Shared][MemCmd::InvalidateReq] .name(name() + ".snoop_inv_shared") .desc("Invalidate snoops on shared blocks") ; - snoopCount[Owned][Packet::InvalidateReq] + snoopCount[Owned][MemCmd::InvalidateReq] .name(name() + ".snoop_inv_owned") .desc("Invalidate snoops on owned blocks") ; - snoopCount[Exclusive][Packet::InvalidateReq] + snoopCount[Exclusive][MemCmd::InvalidateReq] .name(name() + ".snoop_inv_exclusive") .desc("Invalidate snoops on exclusive blocks") ; - snoopCount[Modified][Packet::InvalidateReq] + snoopCount[Modified][MemCmd::InvalidateReq] .name(name() + ".snoop_inv_modified") .desc("Invalidate snoops on modified blocks") ; - snoopCount[Invalid][Packet::InvalidateReq] + snoopCount[Invalid][MemCmd::InvalidateReq] .name(name() + ".snoop_inv_invalid") .desc("Invalidate snoops on invalid blocks") ; - snoopCount[Shared][Packet::WriteInvalidateReq] + snoopCount[Shared][MemCmd::WriteInvalidateReq] .name(name() + ".snoop_writeinv_shared") .desc("WriteInvalidate snoops on shared blocks") ; - snoopCount[Owned][Packet::WriteInvalidateReq] + snoopCount[Owned][MemCmd::WriteInvalidateReq] .name(name() + ".snoop_writeinv_owned") .desc("WriteInvalidate snoops on owned blocks") ; - snoopCount[Exclusive][Packet::WriteInvalidateReq] + snoopCount[Exclusive][MemCmd::WriteInvalidateReq] .name(name() + ".snoop_writeinv_exclusive") .desc("WriteInvalidate snoops on exclusive blocks") ; - snoopCount[Modified][Packet::WriteInvalidateReq] + snoopCount[Modified][MemCmd::WriteInvalidateReq] .name(name() + ".snoop_writeinv_modified") .desc("WriteInvalidate snoops on modified blocks") ; - snoopCount[Invalid][Packet::WriteInvalidateReq] + snoopCount[Invalid][MemCmd::WriteInvalidateReq] .name(name() + ".snoop_writeinv_invalid") .desc("WriteInvalidate snoops on invalid blocks") ; @@ -278,11 +278,13 @@ CoherenceProtocol::CoherenceProtocol(const string &name, } // set up a few shortcuts to save typing & visual clutter - typedef Packet P; - StateTransition (&tt)[stateMax+1][NUM_MEM_CMDS] = transitionTable; + typedef MemCmd MC; + StateTransition (&tt)[stateMax+1][MC::NUM_MEM_CMDS] = transitionTable; - P::Command writeToSharedCmd = doUpgrades ? P::UpgradeReq : P::ReadExReq; - P::Command writeToSharedResp = doUpgrades ? P::UpgradeReq : P::ReadExResp; + MC::Command writeToSharedCmd = + doUpgrades ? MC::UpgradeReq : MC::ReadExReq; + MC::Command writeToSharedResp = + doUpgrades ? MC::UpgradeReq : MC::ReadExResp; // Note that all transitions by default cause a panic. // Override the valid transitions with the appropriate actions here. @@ -290,34 +292,34 @@ CoherenceProtocol::CoherenceProtocol(const string &name, // // ----- incoming requests: specify outgoing bus request ----- // - tt[Invalid][P::ReadReq].onRequest(P::ReadReq); + tt[Invalid][MC::ReadReq].onRequest(MC::ReadReq); // we only support write allocate right now - tt[Invalid][P::WriteReq].onRequest(P::ReadExReq); - tt[Shared][P::WriteReq].onRequest(writeToSharedCmd); + tt[Invalid][MC::WriteReq].onRequest(MC::ReadExReq); + tt[Shared][MC::WriteReq].onRequest(writeToSharedCmd); if (hasOwned) { - tt[Owned][P::WriteReq].onRequest(writeToSharedCmd); + tt[Owned][MC::WriteReq].onRequest(writeToSharedCmd); } // Prefetching causes a read - tt[Invalid][P::SoftPFReq].onRequest(P::ReadReq); - tt[Invalid][P::HardPFReq].onRequest(P::ReadReq); + tt[Invalid][MC::SoftPFReq].onRequest(MC::ReadReq); + tt[Invalid][MC::HardPFReq].onRequest(MC::ReadReq); // // ----- on response to given request: specify new state ----- // - tt[Invalid][P::ReadExResp].onResponse(Modified); + tt[Invalid][MC::ReadExResp].onResponse(Modified); tt[Shared][writeToSharedResp].onResponse(Modified); // Go to Exclusive state on read response if we have one (will // move into shared if the shared line is asserted in the // getNewState function) // // originally had this as: - // tt[Invalid][P::ReadResp].onResponse(hasExclusive ? Exclusive: Shared); + // tt[Invalid][MC::ReadResp].onResponse(hasExclusive ? Exclusive: Shared); // ...but for some reason that caused a link error... if (hasExclusive) { - tt[Invalid][P::ReadResp].onResponse(Exclusive); + tt[Invalid][MC::ReadResp].onResponse(Exclusive); } else { - tt[Invalid][P::ReadResp].onResponse(Shared); + tt[Invalid][MC::ReadResp].onResponse(Shared); } if (hasOwned) { tt[Owned][writeToSharedResp].onResponse(Modified); @@ -326,58 +328,58 @@ CoherenceProtocol::CoherenceProtocol(const string &name, // // ----- bus snoop transition functions ----- // - tt[Invalid][P::ReadReq].onSnoop(nullTransition); - tt[Invalid][P::ReadExReq].onSnoop(nullTransition); - tt[Invalid][P::InvalidateReq].onSnoop(invalidateTrans); - tt[Invalid][P::WriteInvalidateReq].onSnoop(invalidateTrans); - tt[Shared][P::ReadReq].onSnoop(hasExclusive + tt[Invalid][MC::ReadReq].onSnoop(nullTransition); + tt[Invalid][MC::ReadExReq].onSnoop(nullTransition); + tt[Invalid][MC::InvalidateReq].onSnoop(invalidateTrans); + tt[Invalid][MC::WriteInvalidateReq].onSnoop(invalidateTrans); + tt[Shared][MC::ReadReq].onSnoop(hasExclusive ? assertShared : nullTransition); - tt[Shared][P::ReadExReq].onSnoop(invalidateTrans); - tt[Shared][P::InvalidateReq].onSnoop(invalidateTrans); - tt[Shared][P::WriteInvalidateReq].onSnoop(invalidateTrans); + tt[Shared][MC::ReadExReq].onSnoop(invalidateTrans); + tt[Shared][MC::InvalidateReq].onSnoop(invalidateTrans); + tt[Shared][MC::WriteInvalidateReq].onSnoop(invalidateTrans); if (doUpgrades) { - tt[Invalid][P::UpgradeReq].onSnoop(nullTransition); - tt[Shared][P::UpgradeReq].onSnoop(invalidateTrans); + tt[Invalid][MC::UpgradeReq].onSnoop(nullTransition); + tt[Shared][MC::UpgradeReq].onSnoop(invalidateTrans); } - tt[Modified][P::ReadExReq].onSnoop(supplyAndInvalidateTrans); - tt[Modified][P::ReadReq].onSnoop(hasOwned + tt[Modified][MC::ReadExReq].onSnoop(supplyAndInvalidateTrans); + tt[Modified][MC::ReadReq].onSnoop(hasOwned ? supplyAndGotoOwnedTrans : supplyAndGotoSharedTrans); - tt[Modified][P::InvalidateReq].onSnoop(invalidateTrans); - tt[Modified][P::WriteInvalidateReq].onSnoop(invalidateTrans); + tt[Modified][MC::InvalidateReq].onSnoop(invalidateTrans); + tt[Modified][MC::WriteInvalidateReq].onSnoop(invalidateTrans); if (hasExclusive) { - tt[Exclusive][P::ReadReq].onSnoop(assertShared); - tt[Exclusive][P::ReadExReq].onSnoop(invalidateTrans); - tt[Exclusive][P::InvalidateReq].onSnoop(invalidateTrans); - tt[Exclusive][P::WriteInvalidateReq].onSnoop(invalidateTrans); + tt[Exclusive][MC::ReadReq].onSnoop(assertShared); + tt[Exclusive][MC::ReadExReq].onSnoop(invalidateTrans); + tt[Exclusive][MC::InvalidateReq].onSnoop(invalidateTrans); + tt[Exclusive][MC::WriteInvalidateReq].onSnoop(invalidateTrans); } if (hasOwned) { - tt[Owned][P::ReadReq].onSnoop(supplyAndGotoOwnedTrans); - tt[Owned][P::ReadExReq].onSnoop(supplyAndInvalidateTrans); - tt[Owned][P::UpgradeReq].onSnoop(invalidateTrans); - tt[Owned][P::InvalidateReq].onSnoop(invalidateTrans); - tt[Owned][P::WriteInvalidateReq].onSnoop(invalidateTrans); + tt[Owned][MC::ReadReq].onSnoop(supplyAndGotoOwnedTrans); + tt[Owned][MC::ReadExReq].onSnoop(supplyAndInvalidateTrans); + tt[Owned][MC::UpgradeReq].onSnoop(invalidateTrans); + tt[Owned][MC::InvalidateReq].onSnoop(invalidateTrans); + tt[Owned][MC::WriteInvalidateReq].onSnoop(invalidateTrans); } // @todo add in hardware prefetch to this list } -Packet::Command -CoherenceProtocol::getBusCmd(Packet::Command cmdIn, CacheBlk::State state, +MemCmd +CoherenceProtocol::getBusCmd(MemCmd cmdIn, CacheBlk::State state, MSHR *mshr) { state &= stateMask; - int cmd_idx = (int) cmdIn; + int cmd_idx = cmdIn.toInt(); assert(0 <= state && state <= stateMax); - assert(0 <= cmd_idx && cmd_idx < NUM_MEM_CMDS); + assert(0 <= cmd_idx && cmd_idx < MemCmd::NUM_MEM_CMDS); - Packet::Command cmdOut = transitionTable[state][cmd_idx].busCmd; + MemCmd::Command cmdOut = transitionTable[state][cmd_idx].busCmd; - assert(cmdOut != Packet::InvalidCmd); + assert(cmdOut != MemCmd::InvalidCmd); ++requestCount[state][cmd_idx]; @@ -392,7 +394,7 @@ CoherenceProtocol::getNewState(PacketPtr &pkt, CacheBlk::State oldState) int cmd_idx = pkt->cmdToIndex(); assert(0 <= state && state <= stateMax); - assert(0 <= cmd_idx && cmd_idx < NUM_MEM_CMDS); + assert(0 <= cmd_idx && cmd_idx < MemCmd::NUM_MEM_CMDS); CacheBlk::State newState = transitionTable[state][cmd_idx].newState; @@ -425,7 +427,7 @@ CoherenceProtocol::handleBusRequest(BaseCache *cache, PacketPtr &pkt, int cmd_idx = pkt->cmdToIndex(); assert(0 <= state && state <= stateMax); - assert(0 <= cmd_idx && cmd_idx < NUM_MEM_CMDS); + assert(0 <= cmd_idx && cmd_idx < MemCmd::NUM_MEM_CMDS); // assert(mshr == NULL); // can't currently handle outstanding requests //Check first if MSHR, and also insure, if there is one, that it is not in service diff --git a/src/mem/cache/coherence/coherence_protocol.hh b/src/mem/cache/coherence/coherence_protocol.hh index 481277523..775bc807a 100644 --- a/src/mem/cache/coherence/coherence_protocol.hh +++ b/src/mem/cache/coherence/coherence_protocol.hh @@ -80,8 +80,8 @@ class CoherenceProtocol : public SimObject * @param mshr The MSHR matching the request. * @return The proper bus command, as determined by the protocol. */ - Packet::Command getBusCmd(Packet::Command cmd, CacheBlk::State status, - MSHR *mshr = NULL); + MemCmd getBusCmd(MemCmd cmd, CacheBlk::State status, + MSHR *mshr = NULL); /** * Return the proper state given the current state and the bus response. @@ -235,7 +235,7 @@ class CoherenceProtocol : public SimObject * The table of all possible transitions, organized by starting state and * request command. */ - StateTransition transitionTable[stateMax+1][NUM_MEM_CMDS]; + StateTransition transitionTable[stateMax+1][MemCmd::NUM_MEM_CMDS]; /** * @addtogroup CoherenceStatistics @@ -244,11 +244,11 @@ class CoherenceProtocol : public SimObject /** * State accesses from parent cache. */ - Stats::Scalar<> requestCount[stateMax+1][NUM_MEM_CMDS]; + Stats::Scalar<> requestCount[stateMax+1][MemCmd::NUM_MEM_CMDS]; /** * State accesses from snooped requests. */ - Stats::Scalar<> snoopCount[stateMax+1][NUM_MEM_CMDS]; + Stats::Scalar<> snoopCount[stateMax+1][MemCmd::NUM_MEM_CMDS]; /** * @} */ diff --git a/src/mem/cache/coherence/simple_coherence.hh b/src/mem/cache/coherence/simple_coherence.hh index a1fd33080..1c89c703a 100644 --- a/src/mem/cache/coherence/simple_coherence.hh +++ b/src/mem/cache/coherence/simple_coherence.hh @@ -131,7 +131,7 @@ class SimpleCoherence //Got rid of, there could be an MSHR, but it can't be in service if (blk != NULL) { - if (pkt->cmd != Packet::Writeback) { + if (pkt->cmd != MemCmd::Writeback) { return protocol->handleBusRequest(cache, pkt, blk, mshr, new_state); } @@ -148,9 +148,10 @@ class SimpleCoherence * @param state The current state of the cache block. * @return The proper bus command, as determined by the protocol. */ - Packet::Command getBusCmd(Packet::Command &cmd, CacheBlk::State state) + MemCmd getBusCmd(MemCmd cmd, + CacheBlk::State state) { - if (cmd == Packet::Writeback) return Packet::Writeback; + if (cmd == MemCmd::Writeback) return MemCmd::Writeback; return protocol->getBusCmd(cmd, state); } diff --git a/src/mem/cache/coherence/uni_coherence.cc b/src/mem/cache/coherence/uni_coherence.cc index ea615d70a..6061c89c3 100644 --- a/src/mem/cache/coherence/uni_coherence.cc +++ b/src/mem/cache/coherence/uni_coherence.cc @@ -99,19 +99,19 @@ UniCoherence::propogateInvalidate(PacketPtr pkt, bool isTiming) if (isTiming) { // Forward to other caches Request* req = new Request(pkt->req->getPaddr(), pkt->getSize(), 0); - PacketPtr tmp = new Packet(req, Packet::InvalidateReq, -1); + PacketPtr tmp = new Packet(req, MemCmd::InvalidateReq, -1); cshrs.allocate(tmp); cache->setSlaveRequest(Request_Coherence, curTick); if (cshrs.isFull()) cache->setBlockedForSnoop(Blocked_Coherence); } else { - PacketPtr tmp = new Packet(pkt->req, Packet::InvalidateReq, -1); + PacketPtr tmp = new Packet(pkt->req, MemCmd::InvalidateReq, -1); cache->cpuSidePort->sendAtomic(tmp); delete tmp; } /**/ -/* PacketPtr tmp = new Packet(pkt->req, Packet::InvalidateReq, -1); +/* PacketPtr tmp = new Packet(pkt->req, MemCmd::InvalidateReq, -1); cache->cpuSidePort->sendFunctional(tmp); delete tmp; */ @@ -119,7 +119,7 @@ UniCoherence::propogateInvalidate(PacketPtr pkt, bool isTiming) if (pkt->isRead()) { /*For now we will see if someone above us has the data by doing a functional access on reads. Fix this later */ - PacketPtr tmp = new Packet(pkt->req, Packet::ReadReq, -1); + PacketPtr tmp = new Packet(pkt->req, MemCmd::ReadReq, -1); tmp->allocate(); cache->cpuSidePort->sendFunctional(tmp); bool hit = (tmp->result == Packet::Success); diff --git a/src/mem/cache/coherence/uni_coherence.hh b/src/mem/cache/coherence/uni_coherence.hh index 9a4aacdec..9efb4e192 100644 --- a/src/mem/cache/coherence/uni_coherence.hh +++ b/src/mem/cache/coherence/uni_coherence.hh @@ -77,13 +77,13 @@ class UniCoherence * @return The proper bus command, as determined by the protocol. * @todo Make changes so writebacks don't get here. */ - Packet::Command getBusCmd(Packet::Command &cmd, CacheBlk::State state) + MemCmd getBusCmd(MemCmd cmd, CacheBlk::State state) { - if (cmd == Packet::HardPFReq && state) + if (cmd == MemCmd::HardPFReq && state) warn("Trying to issue a prefetch to a block we already have\n"); - if (cmd == Packet::Writeback) - return Packet::Writeback; - return Packet::ReadReq; + if (cmd == MemCmd::Writeback) + return MemCmd::Writeback; + return MemCmd::ReadReq; } /** @@ -96,7 +96,7 @@ class UniCoherence { if (pkt->senderState) //Blocking Buffers don't get mshrs { - if (((MSHR *)(pkt->senderState))->originalCmd == Packet::HardPFReq) { + if (((MSHR *)(pkt->senderState))->originalCmd == MemCmd::HardPFReq) { DPRINTF(HWPrefetch, "Marking a hardware prefetch as such in the state\n"); return BlkHWPrefetched | BlkValid | BlkWritable; } diff --git a/src/mem/cache/miss/SConscript b/src/mem/cache/miss/SConscript new file mode 100644 index 000000000..0f81a2570 --- /dev/null +++ b/src/mem/cache/miss/SConscript @@ -0,0 +1,37 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +Source('blocking_buffer.cc') +Source('miss_buffer.cc') +Source('miss_queue.cc') +Source('mshr.cc') +Source('mshr_queue.cc') diff --git a/src/mem/cache/miss/blocking_buffer.cc b/src/mem/cache/miss/blocking_buffer.cc index a1af88341..e8ff26880 100644 --- a/src/mem/cache/miss/blocking_buffer.cc +++ b/src/mem/cache/miss/blocking_buffer.cc @@ -90,7 +90,7 @@ BlockingBuffer::getPacket() } void -BlockingBuffer::setBusCmd(PacketPtr &pkt, Packet::Command cmd) +BlockingBuffer::setBusCmd(PacketPtr &pkt, MemCmd cmd) { MSHR *mshr = (MSHR*) pkt->senderState; mshr->originalCmd = pkt->cmd; @@ -189,7 +189,7 @@ BlockingBuffer::doWriteback(Addr addr, { // Generate request Request * req = new Request(addr, size, 0); - PacketPtr pkt = new Packet(req, Packet::Writeback, -1); + PacketPtr pkt = new Packet(req, MemCmd::Writeback, -1); pkt->allocate(); if (data) { std::memcpy(pkt->getPtr<uint8_t>(), data, size); diff --git a/src/mem/cache/miss/blocking_buffer.hh b/src/mem/cache/miss/blocking_buffer.hh index 24386a249..86b24d539 100644 --- a/src/mem/cache/miss/blocking_buffer.hh +++ b/src/mem/cache/miss/blocking_buffer.hh @@ -104,7 +104,7 @@ public: * @param pkt The request to update. * @param cmd The bus command to use. */ - void setBusCmd(PacketPtr &pkt, Packet::Command cmd); + void setBusCmd(PacketPtr &pkt, MemCmd cmd); /** * Restore the original command in case of a bus transmission error. diff --git a/src/mem/cache/miss/miss_buffer.hh b/src/mem/cache/miss/miss_buffer.hh index 3e3080578..9a86db304 100644 --- a/src/mem/cache/miss/miss_buffer.hh +++ b/src/mem/cache/miss/miss_buffer.hh @@ -123,7 +123,7 @@ class MissBuffer * @param pkt The request to update. * @param cmd The bus command to use. */ - virtual void setBusCmd(PacketPtr &pkt, Packet::Command cmd) = 0; + virtual void setBusCmd(PacketPtr &pkt, MemCmd cmd) = 0; /** * Restore the original command in case of a bus transmission error. diff --git a/src/mem/cache/miss/miss_queue.cc b/src/mem/cache/miss/miss_queue.cc index 38c5ffa71..24ca9cfa2 100644 --- a/src/mem/cache/miss/miss_queue.cc +++ b/src/mem/cache/miss/miss_queue.cc @@ -67,17 +67,12 @@ MissQueue::regStats(const string &name) { MissBuffer::regStats(name); - Request temp_req((Addr) NULL, 4, 0); - Packet::Command temp_cmd = Packet::ReadReq; - Packet temp_pkt(&temp_req, temp_cmd, 0); //@todo FIx command strings so this isn't neccessary - temp_pkt.allocate(); - using namespace Stats; // MSHR hit statistics - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); mshr_hits[access_idx] .init(maxThreadsPerCPU) @@ -92,20 +87,20 @@ MissQueue::regStats(const string &name) .desc("number of demand (read+write) MSHR hits") .flags(total) ; - demandMshrHits = mshr_hits[Packet::ReadReq] + mshr_hits[Packet::WriteReq]; + demandMshrHits = mshr_hits[MemCmd::ReadReq] + mshr_hits[MemCmd::WriteReq]; overallMshrHits .name(name + ".overall_mshr_hits") .desc("number of overall MSHR hits") .flags(total) ; - overallMshrHits = demandMshrHits + mshr_hits[Packet::SoftPFReq] + - mshr_hits[Packet::HardPFReq]; + overallMshrHits = demandMshrHits + mshr_hits[MemCmd::SoftPFReq] + + mshr_hits[MemCmd::HardPFReq]; // MSHR miss statistics - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); mshr_misses[access_idx] .init(maxThreadsPerCPU) @@ -120,20 +115,20 @@ MissQueue::regStats(const string &name) .desc("number of demand (read+write) MSHR misses") .flags(total) ; - demandMshrMisses = mshr_misses[Packet::ReadReq] + mshr_misses[Packet::WriteReq]; + demandMshrMisses = mshr_misses[MemCmd::ReadReq] + mshr_misses[MemCmd::WriteReq]; overallMshrMisses .name(name + ".overall_mshr_misses") .desc("number of overall MSHR misses") .flags(total) ; - overallMshrMisses = demandMshrMisses + mshr_misses[Packet::SoftPFReq] + - mshr_misses[Packet::HardPFReq]; + overallMshrMisses = demandMshrMisses + mshr_misses[MemCmd::SoftPFReq] + + mshr_misses[MemCmd::HardPFReq]; // MSHR miss latency statistics - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); mshr_miss_latency[access_idx] .init(maxThreadsPerCPU) @@ -148,8 +143,8 @@ MissQueue::regStats(const string &name) .desc("number of demand (read+write) MSHR miss cycles") .flags(total) ; - demandMshrMissLatency = mshr_miss_latency[Packet::ReadReq] - + mshr_miss_latency[Packet::WriteReq]; + demandMshrMissLatency = mshr_miss_latency[MemCmd::ReadReq] + + mshr_miss_latency[MemCmd::WriteReq]; overallMshrMissLatency .name(name + ".overall_mshr_miss_latency") @@ -157,12 +152,12 @@ MissQueue::regStats(const string &name) .flags(total) ; overallMshrMissLatency = demandMshrMissLatency + - mshr_miss_latency[Packet::SoftPFReq] + mshr_miss_latency[Packet::HardPFReq]; + mshr_miss_latency[MemCmd::SoftPFReq] + mshr_miss_latency[MemCmd::HardPFReq]; // MSHR uncacheable statistics - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); mshr_uncacheable[access_idx] .init(maxThreadsPerCPU) @@ -177,14 +172,14 @@ MissQueue::regStats(const string &name) .desc("number of overall MSHR uncacheable misses") .flags(total) ; - overallMshrUncacheable = mshr_uncacheable[Packet::ReadReq] - + mshr_uncacheable[Packet::WriteReq] + mshr_uncacheable[Packet::SoftPFReq] - + mshr_uncacheable[Packet::HardPFReq]; + overallMshrUncacheable = mshr_uncacheable[MemCmd::ReadReq] + + mshr_uncacheable[MemCmd::WriteReq] + mshr_uncacheable[MemCmd::SoftPFReq] + + mshr_uncacheable[MemCmd::HardPFReq]; // MSHR miss latency statistics - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); mshr_uncacheable_lat[access_idx] .init(maxThreadsPerCPU) @@ -199,16 +194,16 @@ MissQueue::regStats(const string &name) .desc("number of overall MSHR uncacheable cycles") .flags(total) ; - overallMshrUncacheableLatency = mshr_uncacheable_lat[Packet::ReadReq] - + mshr_uncacheable_lat[Packet::WriteReq] - + mshr_uncacheable_lat[Packet::SoftPFReq] - + mshr_uncacheable_lat[Packet::HardPFReq]; + overallMshrUncacheableLatency = mshr_uncacheable_lat[MemCmd::ReadReq] + + mshr_uncacheable_lat[MemCmd::WriteReq] + + mshr_uncacheable_lat[MemCmd::SoftPFReq] + + mshr_uncacheable_lat[MemCmd::HardPFReq]; #if 0 // MSHR access formulas - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); mshrAccesses[access_idx] .name(name + "." + cstr + "_mshr_accesses") @@ -237,9 +232,9 @@ MissQueue::regStats(const string &name) #endif // MSHR miss rate formulas - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); mshrMissRate[access_idx] .name(name + "." + cstr + "_mshr_miss_rate") @@ -266,9 +261,9 @@ MissQueue::regStats(const string &name) overallMshrMissRate = overallMshrMisses / cache->overallAccesses; // mshrMiss latency formulas - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); avgMshrMissLatency[access_idx] .name(name + "." + cstr + "_avg_mshr_miss_latency") @@ -295,9 +290,9 @@ MissQueue::regStats(const string &name) overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses; // mshrUncacheable latency formulas - for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) { - Packet::Command cmd = (Packet::Command)access_idx; - const string &cstr = temp_pkt.cmdIdxToString(cmd); + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); avgMshrUncacheableLatency[access_idx] .name(name + "." + cstr + "_avg_mshr_uncacheable_latency") @@ -351,7 +346,7 @@ MissQueue::allocateMiss(PacketPtr &pkt, int size, Tick time) if (mq.isFull()) { cache->setBlocked(Blocked_NoMSHRs); } - if (pkt->cmd != Packet::HardPFReq) { + if (pkt->cmd != MemCmd::HardPFReq) { //If we need to request the bus (not on HW prefetch), do so cache->setMasterRequest(Request_MSHR, time); } @@ -500,17 +495,17 @@ MissQueue::getPacket() } void -MissQueue::setBusCmd(PacketPtr &pkt, Packet::Command cmd) +MissQueue::setBusCmd(PacketPtr &pkt, MemCmd cmd) { assert(pkt->senderState != 0); MSHR * mshr = (MSHR*)pkt->senderState; mshr->originalCmd = pkt->cmd; - if (cmd == Packet::UpgradeReq || cmd == Packet::InvalidateReq) { + if (cmd == MemCmd::UpgradeReq || cmd == MemCmd::InvalidateReq) { pkt->flags |= NO_ALLOCATE; pkt->flags &= ~CACHE_LINE_FILL; } else if (!pkt->req->isUncacheable() && !pkt->isNoAllocate() && - (cmd & (1 << 6)/*NeedsResponse*/)) { + cmd.needsResponse()) { pkt->flags |= CACHE_LINE_FILL; } if (pkt->isCacheFill() || pkt->isNoAllocate()) @@ -552,7 +547,7 @@ MissQueue::markInService(PacketPtr &pkt, MSHR* mshr) if (!mq.havePending()){ cache->clearMasterRequest(Request_MSHR); } - if (mshr->originalCmd == Packet::HardPFReq) { + if (mshr->originalCmd == MemCmd::HardPFReq) { DPRINTF(HWPrefetch, "%s:Marking a HW_PF in service\n", cache->name()); //Also clear pending if need be @@ -576,7 +571,7 @@ void MissQueue::handleResponse(PacketPtr &pkt, Tick time) { MSHR* mshr = (MSHR*)pkt->senderState; - if (((MSHR*)(pkt->senderState))->originalCmd == Packet::HardPFReq) { + if (((MSHR*)(pkt->senderState))->originalCmd == MemCmd::HardPFReq) { DPRINTF(HWPrefetch, "%s:Handling the response to a HW_PF\n", cache->name()); } @@ -589,7 +584,7 @@ MissQueue::handleResponse(PacketPtr &pkt, Tick time) BlockedCause cause = NUM_BLOCKED_CAUSES; if (pkt->isCacheFill() && !pkt->isNoAllocate()) { - mshr_miss_latency[mshr->originalCmd][0/*pkt->req->getThreadNum()*/] += + mshr_miss_latency[mshr->originalCmd.toInt()][0/*pkt->req->getThreadNum()*/] += curTick - pkt->time; // targets were handled in the cache tags if (mshr == noTargetMSHR) { @@ -601,7 +596,7 @@ MissQueue::handleResponse(PacketPtr &pkt, Tick time) if (mshr->hasTargets()) { // Didn't satisfy all the targets, need to resend - Packet::Command cmd = mshr->getTarget()->cmd; + MemCmd cmd = mshr->getTarget()->cmd; mshr->pkt->setDest(Packet::Broadcast); mshr->pkt->result = Packet::Unknown; mshr->pkt->req = mshr->getTarget()->req; @@ -619,7 +614,7 @@ MissQueue::handleResponse(PacketPtr &pkt, Tick time) } } else { if (pkt->req->isUncacheable()) { - mshr_uncacheable_lat[pkt->cmd][0/*pkt->req->getThreadNum()*/] += + mshr_uncacheable_lat[pkt->cmd.toInt()][0/*pkt->req->getThreadNum()*/] += curTick - pkt->time; } if (mshr->hasTargets() && pkt->req->isUncacheable()) { @@ -714,7 +709,7 @@ MissQueue::doWriteback(Addr addr, { // Generate request Request * req = new Request(addr, size, 0); - PacketPtr pkt = new Packet(req, Packet::Writeback, -1); + PacketPtr pkt = new Packet(req, MemCmd::Writeback, -1); pkt->allocate(); if (data) { memcpy(pkt->getPtr<uint8_t>(), data, size); diff --git a/src/mem/cache/miss/miss_queue.hh b/src/mem/cache/miss/miss_queue.hh index 1f9bb1e0c..d3560ff36 100644 --- a/src/mem/cache/miss/miss_queue.hh +++ b/src/mem/cache/miss/miss_queue.hh @@ -77,59 +77,59 @@ class MissQueue : public MissBuffer * @{ */ /** Number of misses that hit in the MSHRs per command and thread. */ - Stats::Vector<> mshr_hits[NUM_MEM_CMDS]; + Stats::Vector<> mshr_hits[MemCmd::NUM_MEM_CMDS]; /** Demand misses that hit in the MSHRs. */ Stats::Formula demandMshrHits; /** Total number of misses that hit in the MSHRs. */ Stats::Formula overallMshrHits; /** Number of misses that miss in the MSHRs, per command and thread. */ - Stats::Vector<> mshr_misses[NUM_MEM_CMDS]; + Stats::Vector<> mshr_misses[MemCmd::NUM_MEM_CMDS]; /** Demand misses that miss in the MSHRs. */ Stats::Formula demandMshrMisses; /** Total number of misses that miss in the MSHRs. */ Stats::Formula overallMshrMisses; /** Number of misses that miss in the MSHRs, per command and thread. */ - Stats::Vector<> mshr_uncacheable[NUM_MEM_CMDS]; + Stats::Vector<> mshr_uncacheable[MemCmd::NUM_MEM_CMDS]; /** Total number of misses that miss in the MSHRs. */ Stats::Formula overallMshrUncacheable; /** Total cycle latency of each MSHR miss, per command and thread. */ - Stats::Vector<> mshr_miss_latency[NUM_MEM_CMDS]; + Stats::Vector<> mshr_miss_latency[MemCmd::NUM_MEM_CMDS]; /** Total cycle latency of demand MSHR misses. */ Stats::Formula demandMshrMissLatency; /** Total cycle latency of overall MSHR misses. */ Stats::Formula overallMshrMissLatency; /** Total cycle latency of each MSHR miss, per command and thread. */ - Stats::Vector<> mshr_uncacheable_lat[NUM_MEM_CMDS]; + Stats::Vector<> mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS]; /** Total cycle latency of overall MSHR misses. */ Stats::Formula overallMshrUncacheableLatency; /** The total number of MSHR accesses per command and thread. */ - Stats::Formula mshrAccesses[NUM_MEM_CMDS]; + Stats::Formula mshrAccesses[MemCmd::NUM_MEM_CMDS]; /** The total number of demand MSHR accesses. */ Stats::Formula demandMshrAccesses; /** The total number of MSHR accesses. */ Stats::Formula overallMshrAccesses; /** The miss rate in the MSHRs pre command and thread. */ - Stats::Formula mshrMissRate[NUM_MEM_CMDS]; + Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS]; /** The demand miss rate in the MSHRs. */ Stats::Formula demandMshrMissRate; /** The overall miss rate in the MSHRs. */ Stats::Formula overallMshrMissRate; /** The average latency of an MSHR miss, per command and thread. */ - Stats::Formula avgMshrMissLatency[NUM_MEM_CMDS]; + Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS]; /** The average latency of a demand MSHR miss. */ Stats::Formula demandAvgMshrMissLatency; /** The average overall latency of an MSHR miss. */ Stats::Formula overallAvgMshrMissLatency; /** The average latency of an MSHR miss, per command and thread. */ - Stats::Formula avgMshrUncacheableLatency[NUM_MEM_CMDS]; + Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS]; /** The average overall latency of an MSHR miss. */ Stats::Formula overallAvgMshrUncacheableLatency; @@ -220,7 +220,7 @@ class MissQueue : public MissBuffer * @param pkt The request to update. * @param cmd The bus command to use. */ - void setBusCmd(PacketPtr &pkt, Packet::Command cmd); + void setBusCmd(PacketPtr &pkt, MemCmd cmd); /** * Restore the original command in case of a bus transmission error. diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc index fc520b4b4..74dad658b 100644 --- a/src/mem/cache/miss/mshr.cc +++ b/src/mem/cache/miss/mshr.cc @@ -39,7 +39,7 @@ #include <vector> #include "mem/cache/miss/mshr.hh" -#include "sim/root.hh" // for curTick +#include "sim/core.hh" // for curTick #include "sim/host.hh" #include "base/misc.hh" #include "mem/cache/cache.hh" @@ -54,7 +54,7 @@ MSHR::MSHR() } void -MSHR::allocate(Packet::Command cmd, Addr _addr, int size, +MSHR::allocate(MemCmd cmd, Addr _addr, int size, PacketPtr &target) { addr = _addr; @@ -148,7 +148,7 @@ MSHR::allocateTarget(PacketPtr &target) */ if (!inService && target->isWrite()) { - pkt->cmd = Packet::WriteReq; + pkt->cmd = MemCmd::WriteReq; } } diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh index 281ea9d49..d0410acda 100644 --- a/src/mem/cache/miss/mshr.hh +++ b/src/mem/cache/miss/mshr.hh @@ -72,7 +72,7 @@ class MSHR { /** The number of currently allocated targets. */ short ntargets; /** The original requesting command. */ - Packet::Command originalCmd; + MemCmd originalCmd; /** Order number of assigned by the miss queue. */ uint64_t order; @@ -100,7 +100,7 @@ public: * @param size The number of bytes to request. * @param pkt The original miss. */ - void allocate(Packet::Command cmd, Addr addr, int size, + void allocate(MemCmd cmd, Addr addr, int size, PacketPtr &pkt); /** diff --git a/src/mem/cache/miss/mshr_queue.cc b/src/mem/cache/miss/mshr_queue.cc index 6cb62429d..add11dfe7 100644 --- a/src/mem/cache/miss/mshr_queue.cc +++ b/src/mem/cache/miss/mshr_queue.cc @@ -136,7 +136,7 @@ MSHRQueue::allocateFetch(Addr addr, int size, PacketPtr &target) MSHR *mshr = freeList.front(); assert(mshr->getNumTargets() == 0); freeList.pop_front(); - mshr->allocate(Packet::ReadReq, addr, size, target); + mshr->allocate(MemCmd::ReadReq, addr, size, target); mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); mshr->readyIter = pendingList.insert(pendingList.end(), mshr); @@ -151,7 +151,7 @@ MSHRQueue::allocateTargetList(Addr addr, int size) assert(mshr->getNumTargets() == 0); freeList.pop_front(); PacketPtr dummy; - mshr->allocate(Packet::ReadReq, addr, size, dummy); + mshr->allocate(MemCmd::ReadReq, addr, size, dummy); mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); mshr->inService = true; ++inServiceMSHRs; @@ -196,7 +196,7 @@ void MSHRQueue::markInService(MSHR* mshr) { //assert(mshr == pendingList.front()); - if (!mshr->pkt->needsResponse() && !(mshr->pkt->cmd == Packet::UpgradeReq)) { + if (!mshr->pkt->needsResponse() && !(mshr->pkt->cmd == MemCmd::UpgradeReq)) { assert(mshr->getNumTargets() == 0); deallocate(mshr); return; @@ -209,7 +209,7 @@ MSHRQueue::markInService(MSHR* mshr) } void -MSHRQueue::markPending(MSHR* mshr, Packet::Command cmd) +MSHRQueue::markPending(MSHR* mshr, MemCmd cmd) { //assert(mshr->readyIter == NULL); mshr->pkt->cmd = cmd; diff --git a/src/mem/cache/miss/mshr_queue.hh b/src/mem/cache/miss/mshr_queue.hh index ec2ddae8a..5069db661 100644 --- a/src/mem/cache/miss/mshr_queue.hh +++ b/src/mem/cache/miss/mshr_queue.hh @@ -185,7 +185,7 @@ class MSHRQueue { * @param mshr The MSHR to resend. * @param cmd The command to resend. */ - void markPending(MSHR* mshr, Packet::Command cmd); + void markPending(MSHR* mshr, MemCmd cmd); /** * Squash outstanding requests with the given thread number. If a request diff --git a/src/mem/cache/prefetch/SConscript b/src/mem/cache/prefetch/SConscript new file mode 100644 index 000000000..8a7f1232c --- /dev/null +++ b/src/mem/cache/prefetch/SConscript @@ -0,0 +1,37 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +Source('base_prefetcher.cc') +Source('ghb_prefetcher.cc') +Source('stride_prefetcher.cc') +Source('tagged_prefetcher.cc') + diff --git a/src/mem/cache/prefetch/base_prefetcher.cc b/src/mem/cache/prefetch/base_prefetcher.cc index 4254800b1..44daf75e1 100644 --- a/src/mem/cache/prefetch/base_prefetcher.cc +++ b/src/mem/cache/prefetch/base_prefetcher.cc @@ -200,7 +200,7 @@ BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) //create a prefetch memreq Request * prefetchReq = new Request(*addr, blkSize, 0); PacketPtr prefetch; - prefetch = new Packet(prefetchReq, Packet::HardPFReq, -1); + prefetch = new Packet(prefetchReq, MemCmd::HardPFReq, -1); prefetch->allocate(); prefetch->req->setThreadContext(pkt->req->getCpuNum(), pkt->req->getThreadNum()); diff --git a/src/mem/cache/tags/SConscript b/src/mem/cache/tags/SConscript new file mode 100644 index 000000000..baf71f687 --- /dev/null +++ b/src/mem/cache/tags/SConscript @@ -0,0 +1,42 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +Source('base_tags.cc') +Source('fa_lru.cc') +Source('iic.cc') +Source('lru.cc') +Source('split.cc') +Source('split_lifo.cc') +Source('split_lru.cc') + +Source('repl/gen.cc') +Source('repl/repl.cc') diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc index e547e112e..9c802d0dc 100644 --- a/src/mem/cache/tags/iic.cc +++ b/src/mem/cache/tags/iic.cc @@ -42,7 +42,7 @@ #include "mem/cache/base_cache.hh" #include "mem/cache/tags/iic.hh" #include "base/intmath.hh" -#include "sim/root.hh" // for curTick +#include "sim/core.hh" // for curTick #include "base/trace.hh" // for DPRINTF @@ -372,7 +372,8 @@ IIC::freeReplacementBlock(PacketList & writebacks) */ Request *writebackReq = new Request(regenerateBlkAddr(tag_ptr->tag, 0), blkSize, 0); - PacketPtr writeback = new Packet(writebackReq, Packet::Writeback, -1); + PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback, + -1); writeback->allocate(); memcpy(writeback->getPtr<uint8_t>(), tag_ptr->data, blkSize); diff --git a/src/mem/cache/tags/lru.cc b/src/mem/cache/tags/lru.cc index 102bb3506..8e8779774 100644 --- a/src/mem/cache/tags/lru.cc +++ b/src/mem/cache/tags/lru.cc @@ -38,7 +38,7 @@ #include "mem/cache/base_cache.hh" #include "base/intmath.hh" #include "mem/cache/tags/lru.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/mem/cache/tags/split_lifo.cc b/src/mem/cache/tags/split_lifo.cc index 792ff8fa7..d71d1a3ef 100644 --- a/src/mem/cache/tags/split_lifo.cc +++ b/src/mem/cache/tags/split_lifo.cc @@ -38,7 +38,7 @@ #include "mem/cache/base_cache.hh" #include "base/intmath.hh" #include "mem/cache/tags/split_lifo.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "base/trace.hh" using namespace std; diff --git a/src/mem/cache/tags/split_lru.cc b/src/mem/cache/tags/split_lru.cc index c37d72cb7..7227fb5c1 100644 --- a/src/mem/cache/tags/split_lru.cc +++ b/src/mem/cache/tags/split_lru.cc @@ -38,7 +38,7 @@ #include "mem/cache/base_cache.hh" #include "base/intmath.hh" #include "mem/cache/tags/split_lru.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc index d4d3fd283..ef31cf999 100644 --- a/src/mem/mem_object.cc +++ b/src/mem/mem_object.cc @@ -35,5 +35,10 @@ MemObject::MemObject(const std::string &name) : SimObject(name) { } +void +MemObject::deletePortRefs(Port *p) +{ + panic("This object does not support port deletion\n"); +} DEFINE_SIM_OBJECT_CLASS_NAME("MemObject", MemObject) diff --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh index d12eeffe0..ec6fa2b2a 100644 --- a/src/mem/mem_object.hh +++ b/src/mem/mem_object.hh @@ -51,6 +51,10 @@ class MemObject : public SimObject public: /** Additional function to return the Port of a memory object. */ virtual Port *getPort(const std::string &if_name, int idx = -1) = 0; + + /** Tell object that this port is about to disappear, so it should remove it + * from any structures that it's keeping it in. */ + virtual void deletePortRefs(Port *p) ; }; #endif //__MEM_MEM_OBJECT_HH__ diff --git a/src/mem/packet.cc b/src/mem/packet.cc index 44805236c..14d08db1b 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -41,68 +41,68 @@ #include "base/trace.hh" #include "mem/packet.hh" -static const std::string ReadReqString("ReadReq"); -static const std::string WriteReqString("WriteReq"); -static const std::string WriteReqNoAckString("WriteReqNoAck|Writeback"); -static const std::string ReadRespString("ReadResp"); -static const std::string WriteRespString("WriteResp"); -static const std::string SoftPFReqString("SoftPFReq"); -static const std::string SoftPFRespString("SoftPFResp"); -static const std::string HardPFReqString("HardPFReq"); -static const std::string HardPFRespString("HardPFResp"); -static const std::string InvalidateReqString("InvalidateReq"); -static const std::string WriteInvalidateReqString("WriteInvalidateReq"); -static const std::string WriteInvalidateRespString("WriteInvalidateResp"); -static const std::string UpgradeReqString("UpgradeReq"); -static const std::string ReadExReqString("ReadExReq"); -static const std::string ReadExRespString("ReadExResp"); -static const std::string OtherCmdString("<other>"); +// The one downside to bitsets is that static initializers can get ugly. +#define SET1(a1) (1 << (a1)) +#define SET2(a1, a2) (SET1(a1) | SET1(a2)) +#define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3)) +#define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4)) +#define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5)) +#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6)) -const std::string & -Packet::cmdString() const +const MemCmd::CommandInfo +MemCmd::commandInfo[] = { - switch (cmd) { - case ReadReq: return ReadReqString; - case WriteReq: return WriteReqString; - case WriteReqNoAck: return WriteReqNoAckString; - case ReadResp: return ReadRespString; - case WriteResp: return WriteRespString; - case SoftPFReq: return SoftPFReqString; - case SoftPFResp: return SoftPFRespString; - case HardPFReq: return HardPFReqString; - case HardPFResp: return HardPFRespString; - case InvalidateReq: return InvalidateReqString; - case WriteInvalidateReq:return WriteInvalidateReqString; - case WriteInvalidateResp:return WriteInvalidateRespString; - case UpgradeReq: return UpgradeReqString; - case ReadExReq: return ReadExReqString; - case ReadExResp: return ReadExRespString; - default: return OtherCmdString; - } -} + /* InvalidCmd */ + { 0, InvalidCmd, "InvalidCmd" }, + /* ReadReq */ + { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" }, + /* WriteReq */ + { SET4(IsWrite, IsRequest, NeedsResponse, HasData), + WriteResp, "WriteReq" }, + /* WriteReqNoAck */ + { SET3(IsWrite, IsRequest, HasData), InvalidCmd, "WriteReqNoAck" }, + /* ReadResp */ + { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" }, + /* WriteResp */ + { SET2(IsWrite, IsResponse), InvalidCmd, "WriteResp" }, + /* Writeback */ + { SET3(IsWrite, IsRequest, HasData), InvalidCmd, "Writeback" }, + /* SoftPFReq */ + { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse), + SoftPFResp, "SoftPFReq" }, + /* HardPFReq */ + { SET4(IsRead, IsRequest, IsHWPrefetch, NeedsResponse), + HardPFResp, "HardPFReq" }, + /* SoftPFResp */ + { SET4(IsRead, IsResponse, IsSWPrefetch, HasData), + InvalidCmd, "SoftPFResp" }, + /* HardPFResp */ + { SET4(IsRead, IsResponse, IsHWPrefetch, HasData), + InvalidCmd, "HardPFResp" }, + /* InvalidateReq */ + { SET2(IsInvalidate, IsRequest), InvalidCmd, "InvalidateReq" }, + /* WriteInvalidateReq */ + { SET5(IsWrite, IsInvalidate, IsRequest, HasData, NeedsResponse), + WriteInvalidateResp, "WriteInvalidateReq" }, + /* WriteInvalidateResp */ + { SET5(IsWrite, IsInvalidate, IsRequest, NeedsResponse, IsResponse), + InvalidCmd, "WriteInvalidateResp" }, + /* UpgradeReq */ + { SET3(IsInvalidate, IsRequest, IsUpgrade), InvalidCmd, "UpgradeReq" }, + /* ReadExReq */ + { SET4(IsRead, IsInvalidate, IsRequest, NeedsResponse), + ReadExResp, "ReadExReq" }, + /* ReadExResp */ + { SET4(IsRead, IsInvalidate, IsResponse, HasData), + InvalidCmd, "ReadExResp" }, + /* SwapReq -- for Swap ldstub type operations */ + { SET4(IsReadWrite, IsRequest, HasData, NeedsResponse), + SwapResp, "SwapReq" }, + /* SwapResp -- for Swap ldstub type operations */ + { SET3(IsReadWrite, IsResponse, HasData), + InvalidCmd, "SwapResp" } +}; -const std::string & -Packet::cmdIdxToString(Packet::Command idx) -{ - switch (idx) { - case ReadReq: return ReadReqString; - case WriteReq: return WriteReqString; - case WriteReqNoAck: return WriteReqNoAckString; - case ReadResp: return ReadRespString; - case WriteResp: return WriteRespString; - case SoftPFReq: return SoftPFReqString; - case SoftPFResp: return SoftPFRespString; - case HardPFReq: return HardPFReqString; - case HardPFResp: return HardPFRespString; - case InvalidateReq: return InvalidateReqString; - case WriteInvalidateReq:return WriteInvalidateReqString; - case WriteInvalidateResp:return WriteInvalidateRespString; - case UpgradeReq: return UpgradeReqString; - case ReadExReq: return ReadExReqString; - case ReadExResp: return ReadExRespString; - default: return OtherCmdString; - } -} /** delete the data pointed to in the data pointer. Ok to call to matter how * data was allocted. */ @@ -149,9 +149,17 @@ fixDelayedResponsePacket(PacketPtr func, PacketPtr timing) bool result; if (timing->isRead() || timing->isWrite()) { - timing->toggleData(); + // Ugly hack to deal with the fact that we queue the requests + // and don't convert them to responses until we issue them on + // the bus. I tried to avoid this by converting packets to + // responses right away, but this breaks during snoops where a + // responder may do the conversion before other caches have + // done the snoop. Would work if we copied the packet instead + // of just hanging on to a pointer. + MemCmd oldCmd = timing->cmd; + timing->cmd = timing->cmd.responseCommand(); result = fixPacket(func, timing); - timing->toggleData(); + timing->cmd = oldCmd; } else { //Don't toggle if it isn't a read/write response @@ -171,11 +179,6 @@ fixPacket(PacketPtr func, PacketPtr timing) assert(!(funcStart > timingEnd || timingStart > funcEnd)); - if (DTRACE(FunctionalAccess)) { - DebugOut() << func; - DebugOut() << timing; - } - // this packet can't solve our problem, continue on if (!timing->hasData()) return true; @@ -241,9 +244,11 @@ operator<<(std::ostream &o, const Packet &p) if (p.isRead()) o << "Read "; if (p.isWrite()) - o << "Read "; + o << "Write "; + if (p.isReadWrite()) + o << "Read/Write "; if (p.isInvalidate()) - o << "Read "; + o << "Invalidate "; if (p.isRequest()) o << "Request "; if (p.isResponse()) diff --git a/src/mem/packet.hh b/src/mem/packet.hh index a4c003e8b..dc23e9f6d 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -40,12 +40,13 @@ #include <cassert> #include <list> +#include <bitset> #include "base/compiler.hh" #include "base/misc.hh" #include "mem/request.hh" #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" struct Packet; @@ -62,8 +63,118 @@ typedef std::list<PacketPtr> PacketList; #define NO_ALLOCATE (1 << 5) #define SNOOP_COMMIT (1 << 6) -//for now. @todo fix later -#define NUM_MEM_CMDS (1 << 11) + +class MemCmd +{ + public: + + /** List of all commands associated with a packet. */ + enum Command + { + InvalidCmd, + ReadReq, + WriteReq, + WriteReqNoAck, + ReadResp, + WriteResp, + Writeback, + SoftPFReq, + HardPFReq, + SoftPFResp, + HardPFResp, + InvalidateReq, + WriteInvalidateReq, + WriteInvalidateResp, + UpgradeReq, + ReadExReq, + ReadExResp, + SwapReq, + SwapResp, + NUM_MEM_CMDS + }; + + private: + /** List of command attributes. */ + enum Attribute + { + IsRead, + IsWrite, + IsPrefetch, + IsInvalidate, + IsRequest, + IsResponse, + NeedsResponse, + IsSWPrefetch, + IsHWPrefetch, + IsUpgrade, + HasData, + IsReadWrite, + NUM_COMMAND_ATTRIBUTES + }; + + /** Structure that defines attributes and other data associated + * with a Command. */ + struct CommandInfo { + /** Set of attribute flags. */ + const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes; + /** Corresponding response for requests; InvalidCmd if no + * response is applicable. */ + const Command response; + /** String representation (for printing) */ + const std::string str; + }; + + /** Array to map Command enum to associated info. */ + static const CommandInfo commandInfo[]; + + private: + + Command cmd; + + bool testCmdAttrib(MemCmd::Attribute attrib) const { + return commandInfo[cmd].attributes[attrib] != 0; + } + + public: + + bool isRead() const { return testCmdAttrib(IsRead); } + bool isWrite() const { return testCmdAttrib(IsWrite); } + bool isRequest() const { return testCmdAttrib(IsRequest); } + bool isResponse() const { return testCmdAttrib(IsResponse); } + bool needsResponse() const { return testCmdAttrib(NeedsResponse); } + bool isInvalidate() const { return testCmdAttrib(IsInvalidate); } + bool hasData() const { return testCmdAttrib(HasData); } + bool isReadWrite() const { return testCmdAttrib(IsReadWrite); } + + const Command responseCommand() const { + return commandInfo[cmd].response; + } + + /** Return the string to a cmd given by idx. */ + const std::string &toString() const { + return commandInfo[cmd].str; + } + + int toInt() const { return (int)cmd; } + + MemCmd(Command _cmd) + : cmd(_cmd) + { } + + MemCmd(int _cmd) + : cmd((Command)_cmd) + { } + + MemCmd() + : cmd(InvalidCmd) + { } + + bool operator==(MemCmd c2) { return (cmd == c2.cmd); } + bool operator!=(MemCmd c2) { return (cmd != c2.cmd); } + + friend class Packet; +}; + /** * A Packet is used to encapsulate a transfer between two objects in * the memory system (e.g., the L1 and L2 cache). (In contrast, a @@ -74,6 +185,9 @@ typedef std::list<PacketPtr> PacketList; class Packet { public: + + typedef MemCmd::Command Command; + /** Temporary FLAGS field until cache gets working, this should be in coherence/sender state. */ uint64_t flags; @@ -169,73 +283,28 @@ class Packet * to cast to the state appropriate to the sender. */ SenderState *senderState; - private: - /** List of command attributes. */ - // If you add a new CommandAttribute, make sure to increase NUM_MEM_CMDS - // as well. - enum CommandAttribute - { - IsRead = 1 << 0, - IsWrite = 1 << 1, - IsPrefetch = 1 << 2, - IsInvalidate = 1 << 3, - IsRequest = 1 << 4, - IsResponse = 1 << 5, - NeedsResponse = 1 << 6, - IsSWPrefetch = 1 << 7, - IsHWPrefetch = 1 << 8, - IsUpgrade = 1 << 9, - HasData = 1 << 10 - }; - public: - /** List of all commands associated with a packet. */ - enum Command - { - InvalidCmd = 0, - ReadReq = IsRead | IsRequest | NeedsResponse, - WriteReq = IsWrite | IsRequest | NeedsResponse | HasData, - WriteReqNoAck = IsWrite | IsRequest | HasData, - ReadResp = IsRead | IsResponse | NeedsResponse | HasData, - WriteResp = IsWrite | IsResponse | NeedsResponse, - Writeback = IsWrite | IsRequest | HasData, - SoftPFReq = IsRead | IsRequest | IsSWPrefetch | NeedsResponse, - HardPFReq = IsRead | IsRequest | IsHWPrefetch | NeedsResponse, - SoftPFResp = IsRead | IsResponse | IsSWPrefetch - | NeedsResponse | HasData, - HardPFResp = IsRead | IsResponse | IsHWPrefetch - | NeedsResponse | HasData, - InvalidateReq = IsInvalidate | IsRequest, - WriteInvalidateReq = IsWrite | IsInvalidate | IsRequest - | HasData | NeedsResponse, - WriteInvalidateResp = IsWrite | IsInvalidate | IsRequest - | NeedsResponse | IsResponse, - UpgradeReq = IsInvalidate | IsRequest | IsUpgrade, - ReadExReq = IsRead | IsInvalidate | IsRequest | NeedsResponse, - ReadExResp = IsRead | IsInvalidate | IsResponse - | NeedsResponse | HasData - }; + + /** The command field of the packet. */ + MemCmd cmd; /** Return the string name of the cmd field (for debugging and * tracing). */ - const std::string &cmdString() const; - - /** Reutrn the string to a cmd given by idx. */ - const std::string &cmdIdxToString(Command idx); + const std::string &cmdString() const { return cmd.toString(); } /** Return the index of this command. */ - inline int cmdToIndex() const { return (int) cmd; } + inline int cmdToIndex() const { return cmd.toInt(); } - /** The command field of the packet. */ - Command cmd; + public: - bool isRead() const { return (cmd & IsRead) != 0; } - bool isWrite() const { return (cmd & IsWrite) != 0; } - bool isRequest() const { return (cmd & IsRequest) != 0; } - bool isResponse() const { return (cmd & IsResponse) != 0; } - bool needsResponse() const { return (cmd & NeedsResponse) != 0; } - bool isInvalidate() const { return (cmd & IsInvalidate) != 0; } - bool hasData() const { return (cmd & HasData) != 0; } + bool isRead() const { return cmd.isRead(); } + bool isWrite() const { return cmd.isWrite(); } + bool isRequest() const { return cmd.isRequest(); } + bool isResponse() const { return cmd.isResponse(); } + bool needsResponse() const { return cmd.needsResponse(); } + bool isInvalidate() const { return cmd.isInvalidate(); } + bool hasData() const { return cmd.hasData(); } + bool isReadWrite() const { return cmd.isReadWrite(); } bool isCacheFill() const { return (flags & CACHE_LINE_FILL) != 0; } bool isNoAllocate() const { return (flags & NO_ALLOCATE) != 0; } @@ -269,13 +338,13 @@ class Packet Addr getOffset(int blkSize) const { return addr & (Addr)(blkSize - 1); } void addrOverride(Addr newAddr) { assert(addrSizeValid); addr = newAddr; } - void cmdOverride(Command newCmd) { cmd = newCmd; } + void cmdOverride(MemCmd newCmd) { cmd = newCmd; } /** Constructor. Note that a Request object must be constructed * first, but the Requests's physical address and size fields * need not be valid. The command and destination addresses * must be supplied. */ - Packet(Request *_req, Command _cmd, short _dest) + Packet(Request *_req, MemCmd _cmd, short _dest) : data(NULL), staticData(false), dynamicData(false), arrayData(false), addr(_req->paddr), size(_req->size), dest(_dest), addrSizeValid(_req->validPaddr), @@ -290,7 +359,7 @@ class Packet /** Alternate constructor if you are trying to create a packet with * a request that is for a whole block, not the address from the req. * this allows for overriding the size/addr of the req.*/ - Packet(Request *_req, Command _cmd, short _dest, int _blkSize) + Packet(Request *_req, MemCmd _cmd, short _dest, int _blkSize) : data(NULL), staticData(false), dynamicData(false), arrayData(false), addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize), dest(_dest), @@ -335,25 +404,11 @@ class Packet void makeTimingResponse() { assert(needsResponse()); assert(isRequest()); - int icmd = (int)cmd; - icmd &= ~(IsRequest); - icmd |= IsResponse; - if (isRead()) - icmd |= HasData; - if (isWrite()) - icmd &= ~HasData; - cmd = (Command)icmd; + cmd = cmd.responseCommand(); dest = src; srcValid = false; } - - void toggleData() { - int icmd = (int)cmd; - icmd ^= HasData; - cmd = (Command)icmd; - } - /** * Take a request packet and modify it in place to be suitable for * returning as a response to that request. @@ -362,14 +417,7 @@ class Packet { assert(needsResponse()); assert(isRequest()); - int icmd = (int)cmd; - icmd &= ~(IsRequest); - icmd |= IsResponse; - if (isRead()) - icmd |= HasData; - if (isWrite()) - icmd &= ~HasData; - cmd = (Command)icmd; + cmd = cmd.responseCommand(); } /** diff --git a/src/mem/packet_access.hh b/src/mem/packet_access.hh index aac0c3ae5..d1edd00aa 100644 --- a/src/mem/packet_access.hh +++ b/src/mem/packet_access.hh @@ -30,6 +30,7 @@ */ #include "arch/isa_traits.hh" +#include "base/bigint.hh" #include "mem/packet.hh" #include "sim/byteswap.hh" diff --git a/src/mem/page_table.cc b/src/mem/page_table.cc index fe8094b88..96bc23793 100644 --- a/src/mem/page_table.cc +++ b/src/mem/page_table.cc @@ -157,7 +157,7 @@ PageTable::translate(RequestPtr &req) assert(pageAlign(req->getVaddr() + req->getSize() - 1) == pageAlign(req->getVaddr())); if (!translate(req->getVaddr(), paddr)) { - return genPageTableFault(req->getVaddr()); + return Fault(new PageTableFault(req->getVaddr())); } req->setPaddr(paddr); return page_check(req->getPaddr(), req->getSize()); diff --git a/src/mem/physical.cc b/src/mem/physical.cc index eccd42bec..5d7d7382a 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -92,7 +92,7 @@ Addr PhysicalMemory::new_page() { Addr return_addr = pagePtr << LogVMPageSize; - return_addr += params()->addrRange.start; + return_addr += start(); ++pagePtr; return return_addr; @@ -187,7 +187,7 @@ PhysicalMemory::checkLockedAddrList(Request *req) } if (isLocked) { - req->setScResult(success ? 1 : 0); + req->setExtraData(success ? 1 : 0); } return success; @@ -196,16 +196,14 @@ PhysicalMemory::checkLockedAddrList(Request *req) void PhysicalMemory::doFunctionalAccess(PacketPtr pkt) { - assert(pkt->getAddr() >= params()->addrRange.start && - pkt->getAddr() + pkt->getSize() <= params()->addrRange.start + - params()->addrRange.size()); + assert(pkt->getAddr() >= start() && + pkt->getAddr() + pkt->getSize() <= start() + size()); if (pkt->isRead()) { if (pkt->req->isLocked()) { trackLoadLocked(pkt->req); } - memcpy(pkt->getPtr<uint8_t>(), - pmemAddr + pkt->getAddr() - params()->addrRange.start, + memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(), pkt->getSize()); #if TRACING_ON switch (pkt->getSize()) { @@ -233,8 +231,8 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt) } else if (pkt->isWrite()) { if (writeOK(pkt->req)) { - memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start, - pkt->getPtr<uint8_t>(), pkt->getSize()); + memcpy(pmemAddr + pkt->getAddr() - start(), pkt->getPtr<uint8_t>(), + pkt->getSize()); #if TRACING_ON switch (pkt->getSize()) { case sizeof(uint64_t): @@ -259,12 +257,75 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt) } #endif } - } - else if (pkt->isInvalidate()) { + } else if (pkt->isInvalidate()) { //upgrade or invalidate pkt->flags |= SATISFIED; - } - else { + } else if (pkt->isReadWrite()) { + IntReg overwrite_val; + bool overwrite_mem; + uint64_t condition_val64; + uint32_t condition_val32; + + assert(sizeof(IntReg) >= pkt->getSize()); + + overwrite_mem = true; + // keep a copy of our possible write value, and copy what is at the + // memory address into the packet + std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); + std::memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(), + pkt->getSize()); + + if (pkt->req->isCondSwap()) { + if (pkt->getSize() == sizeof(uint64_t)) { + condition_val64 = pkt->req->getExtraData(); + overwrite_mem = !std::memcmp(&condition_val64, pmemAddr + + pkt->getAddr() - start(), sizeof(uint64_t)); + } else if (pkt->getSize() == sizeof(uint32_t)) { + condition_val32 = (uint32_t)pkt->req->getExtraData(); + overwrite_mem = !std::memcmp(&condition_val32, pmemAddr + + pkt->getAddr() - start(), sizeof(uint32_t)); + } else + panic("Invalid size for conditional read/write\n"); + } + + if (overwrite_mem) + std::memcpy(pmemAddr + pkt->getAddr() - start(), + &overwrite_val, pkt->getSize()); + +#if TRACING_ON + switch (pkt->getSize()) { + case sizeof(uint64_t): + DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", + pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>()); + DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n", + overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't", + condition_val64, overwrite_mem ? "happened" : "didn't happen"); + break; + case sizeof(uint32_t): + DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", + pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>()); + DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n", + overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't", + condition_val32, overwrite_mem ? "happened" : "didn't happen"); + break; + case sizeof(uint16_t): + DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", + pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>()); + DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n", + overwrite_mem); + break; + case sizeof(uint8_t): + DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", + pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>()); + DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n", + overwrite_mem); + break; + default: + DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x\n", + pkt->getSize(), pkt->getAddr()); + } +#endif + } else { panic("unimplemented"); } @@ -315,7 +376,7 @@ PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop) { snoop.clear(); resp.clear(); - resp.push_back(RangeSize(params()->addrRange.start, + resp.push_back(RangeSize(start(), params()->addrRange.size())); } diff --git a/src/mem/physical.hh b/src/mem/physical.hh index af88bcaa0..f7200b502 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -131,7 +131,7 @@ class PhysicalMemory : public MemObject // no locked addrs: nothing to check, store_conditional fails bool isLocked = req->isLocked(); if (isLocked) { - req->setScResult(0); + req->setExtraData(0); } return !isLocked; // only do write if not an sc } else { @@ -148,6 +148,7 @@ class PhysicalMemory : public MemObject public: Addr new_page(); uint64_t size() { return params()->addrRange.size(); } + uint64_t start() { return params()->addrRange.start; } struct Params { diff --git a/src/mem/port.cc b/src/mem/port.cc index da719bbd9..e75e50e4d 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -36,6 +36,7 @@ #include "base/chunk_generator.hh" #include "base/trace.hh" +#include "mem/mem_object.hh" #include "mem/port.hh" void @@ -46,7 +47,16 @@ Port::setPeer(Port *port) } void -Port::blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd) +Port::removeConn() +{ + if (peer->getOwner()) + peer->getOwner()->deletePortRefs(peer); + delete peer; + peer = NULL; +} + +void +Port::blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd) { Request req; Packet pkt(&req, cmd, Packet::Broadcast); @@ -64,13 +74,13 @@ Port::blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd) void Port::writeBlob(Addr addr, uint8_t *p, int size) { - blobHelper(addr, p, size, Packet::WriteReq); + blobHelper(addr, p, size, MemCmd::WriteReq); } void Port::readBlob(Addr addr, uint8_t *p, int size) { - blobHelper(addr, p, size, Packet::ReadReq); + blobHelper(addr, p, size, MemCmd::ReadReq); } void @@ -80,7 +90,7 @@ Port::memsetBlob(Addr addr, uint8_t val, int size) uint8_t *buf = new uint8_t[size]; std::memset(buf, val, size); - blobHelper(addr, buf, size, Packet::WriteReq); + blobHelper(addr, buf, size, MemCmd::WriteReq); delete [] buf; } diff --git a/src/mem/port.hh b/src/mem/port.hh index 5e55225bf..6296b42ca 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -120,7 +120,7 @@ class Port { portName = name; } /** Function to set the pointer for the peer port. */ - void setPeer(Port *port); + virtual void setPeer(Port *port); /** Function to get the pointer to the peer port. */ Port *getPeer() { return peer; } @@ -131,6 +131,11 @@ class Port /** Function to return the owner of this port. */ MemObject *getOwner() { return owner; } + /** Inform the peer port to delete itself and notify it's owner about it's + * demise. */ + void removeConn(); + + protected: /** These functions are protected because they should only be @@ -245,7 +250,7 @@ class Port /** Internal helper function for read/writeBlob(). */ - void blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd); + void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd); }; /** A simple functional port that is only meant for one way communication to diff --git a/src/mem/request.hh b/src/mem/request.hh index de0512e1c..d2ebc91d3 100644 --- a/src/mem/request.hh +++ b/src/mem/request.hh @@ -40,7 +40,7 @@ #define __MEM_REQUEST_HH__ #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include <cassert> @@ -71,6 +71,10 @@ const uint32_t EVICT_NEXT = 0x20000; const uint32_t NO_ALIGN_FAULT = 0x40000; /** The request was an instruction read. */ const uint32_t INST_READ = 0x80000; +/** This request is for a memory swap. */ +const uint32_t MEM_SWAP = 0x100000; +const uint32_t MEM_SWAP_COND = 0x200000; + class Request { @@ -104,8 +108,9 @@ class Request /** The virtual address of the request. */ Addr vaddr; - /** The return value of store conditional. */ - uint64_t scResult; + /** Extra data for the request, such as the return value of + * store conditional or the compare value for a CAS. */ + uint64_t extraData; /** The cpu number (for statistics, typically). */ int cpuNum; @@ -120,7 +125,7 @@ class Request /** Whether or not the asid & vaddr are valid. */ bool validAsidVaddr; /** Whether or not the sc result is valid. */ - bool validScResult; + bool validExData; /** Whether or not the cpu number & thread ID are valid. */ bool validCpuAndThreadNums; /** Whether or not the pc is valid. */ @@ -130,7 +135,7 @@ class Request /** Minimal constructor. No fields are initialized. */ Request() : validPaddr(false), validAsidVaddr(false), - validScResult(false), validCpuAndThreadNums(false), validPC(false) + validExData(false), validCpuAndThreadNums(false), validPC(false) {} /** @@ -169,7 +174,7 @@ class Request validPaddr = true; validAsidVaddr = false; validPC = false; - validScResult = false; + validExData = false; mmapedIpr = false; } @@ -187,7 +192,7 @@ class Request validPaddr = false; validAsidVaddr = true; validPC = true; - validScResult = false; + validExData = false; mmapedIpr = false; } @@ -237,12 +242,12 @@ class Request void setMmapedIpr(bool r) { assert(validAsidVaddr); mmapedIpr = r; } /** Accessor function to check if sc result is valid. */ - bool scResultValid() { return validScResult; } + bool extraDataValid() { return validExData; } /** Accessor function for store conditional return value.*/ - uint64_t getScResult() { assert(validScResult); return scResult; } + uint64_t getExtraData() { assert(validExData); return extraData; } /** Accessor function for store conditional return value.*/ - void setScResult(uint64_t _scResult) - { scResult = _scResult; validScResult = true; } + void setExtraData(uint64_t _extraData) + { extraData = _extraData; validExData = true; } /** Accessor function for cpu number.*/ int getCpuNum() { assert(validCpuAndThreadNums); return cpuNum; } @@ -259,6 +264,12 @@ class Request bool isLocked() { return (getFlags() & LOCKED) != 0; } + bool isSwap() { return (getFlags() & MEM_SWAP || + getFlags() & MEM_SWAP_COND); } + + bool isCondSwap() { return (getFlags() & MEM_SWAP_COND) != 0; } + + friend class Packet; }; diff --git a/src/mem/tport.cc b/src/mem/tport.cc index c43c9aac0..b384a0444 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -68,7 +68,7 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) sendTiming(pkt, latency); } else { - if (pkt->cmd != Packet::UpgradeReq) + if (pkt->cmd != MemCmd::UpgradeReq) { delete pkt->req; delete pkt; diff --git a/src/mem/vport.cc b/src/mem/vport.cc index 8030c5a15..6cc4d9ca9 100644 --- a/src/mem/vport.cc +++ b/src/mem/vport.cc @@ -34,6 +34,7 @@ */ #include "base/chunk_generator.hh" +#include "cpu/thread_context.hh" #include "mem/vport.hh" void @@ -70,3 +71,53 @@ VirtualPort::writeBlob(Addr addr, uint8_t *p, int size) } } +void +CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) +{ + uint8_t *dst = (uint8_t *)dest; + VirtualPort *vp = tc->getVirtPort(tc); + + vp->readBlob(src, dst, cplen); + + tc->delVirtPort(vp); + +} + +void +CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) +{ + uint8_t *src = (uint8_t *)source; + VirtualPort *vp = tc->getVirtPort(tc); + + vp->writeBlob(dest, src, cplen); + + tc->delVirtPort(vp); +} + +void +CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) +{ + int len = 0; + char *start = dst; + VirtualPort *vp = tc->getVirtPort(tc); + + do { + vp->readBlob(vaddr++, (uint8_t*)dst++, 1); + } while (len < maxlen && start[len++] != 0 ); + + tc->delVirtPort(vp); + dst[len] = 0; +} + +void +CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) +{ + VirtualPort *vp = tc->getVirtPort(tc); + for (ChunkGenerator gen(vaddr, strlen(src), TheISA::PageBytes); !gen.done(); + gen.next()) + { + vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size()); + src += gen.size(); + } + tc->delVirtPort(vp); +} diff --git a/src/mem/vport.hh b/src/mem/vport.hh index c83836258..a8ceaa9fc 100644 --- a/src/mem/vport.hh +++ b/src/mem/vport.hh @@ -49,6 +49,7 @@ * simple address masking operation (such as alpha super page accesses). */ + class VirtualPort : public FunctionalPort { private: @@ -75,5 +76,11 @@ class VirtualPort : public FunctionalPort virtual void writeBlob(Addr addr, uint8_t *p, int size); }; + +void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen); +void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen); +void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen); +void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr); + #endif //__MEM_VPORT_HH__ diff --git a/src/python/SConscript b/src/python/SConscript index df1464809..6662c8a45 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -29,14 +29,14 @@ # Authors: Steve Reinhardt # Nathan Binkert -import os, os.path, re, sys -from zipfile import PyZipFile +import os +import zipfile # handy function for path joins def join(*args): return os.path.normpath(os.path.join(*args)) -Import('env') +Import('*') # This SConscript is in charge of collecting .py files and generating # a zip archive that is appended to the m5 binary. @@ -97,22 +97,59 @@ addPkg('m5') pyzip_files.append('m5/defines.py') pyzip_files.append('m5/info.py') pyzip_files.append(join(env['ROOT'], 'util/pbs/jobfile.py')) +pyzip_files.append(join(env['ROOT'], 'src/base/traceflags.py')) -def swig_it(basename): - env.Command(['swig/%s_wrap.cc' % basename, 'm5/internal/%s.py' % basename], - 'swig/%s.i' % basename, +swig_modules = [] +def swig_it(module): + env.Command(['swig/%s_wrap.cc' % module, 'm5/internal/%s.py' % module], + 'swig/%s.i' % module, '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' '-o ${TARGETS[0]} $SOURCES') - pyzip_dep_files.append('m5/internal/%s.py' % basename) + swig_modules.append(module) + Source('swig/%s_wrap.cc' % module) -swig_it('main') +Source('swig/init.cc') +Source('swig/pyevent.cc') +Source('swig/pyobject.cc') + +swig_it('core') swig_it('debug') swig_it('event') +swig_it('random') +swig_it('sim_object') +swig_it('stats') +swig_it('trace') + +# Automatically generate m5/internals/__init__.py +def MakeInternalsInit(target, source, env): + f = file(str(target[0]), 'w') + for m in swig_modules: + print >>f, 'import %s' % m + f.close() + +swig_py_files = [ 'm5/internal/%s.py' % m for m in swig_modules ] +env.Command('m5/internal/__init__.py', swig_py_files, MakeInternalsInit) +pyzip_dep_files.append('m5/internal/__init__.py') + +def MakeSwigInit(target, source, env): + f = file(str(target[0]), 'w') + print >>f, 'extern "C" {' + for m in swig_modules: + print >>f, ' void init_%s();' % m + print >>f, '}' + print >>f, 'void init_swig() {' + for m in swig_modules: + print >>f, ' init_%s();' % m + print >>f, '}' + f.close() + +swig_cc_files = [ 'swig/%s_wrap.cc' % m for m in swig_modules ] +env.Command('swig/init.cc', swig_cc_files, MakeSwigInit) # Action function to build the zip archive. Uses the PyZipFile module # included in the standard Python library. def buildPyZip(target, source, env): - pzf = PyZipFile(str(target[0]), 'w') + pzf = zipfile.PyZipFile(str(target[0]), 'w') for s in source: pzf.writepy(str(s)) diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 934358298..42266a80e 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -653,15 +653,13 @@ class SimObject(object): instanceDict[self.path()] = self - if hasattr(self, 'type') and not isinstance(self, ParamContext): + if hasattr(self, 'type'): print 'type=%s' % self.type child_names = self._children.keys() child_names.sort() - np_child_names = [c for c in child_names \ - if not isinstance(self._children[c], ParamContext)] - if len(np_child_names): - print 'children=%s' % ' '.join(np_child_names) + if len(child_names): + print 'children=%s' % ' '.join(child_names) param_names = self._params.keys() param_names.sort() @@ -695,7 +693,7 @@ class SimObject(object): def getCCObject(self): if not self._ccObject: self._ccObject = -1 # flag to catch cycles in recursion - self._ccObject = internal.main.createSimObject(self.path()) + self._ccObject = internal.sim_object.createSimObject(self.path()) elif self._ccObject == -1: raise RuntimeError, "%s: recursive call to getCCObject()" \ % self.path() @@ -711,8 +709,7 @@ class SimObject(object): def startDrain(self, drain_event, recursive): count = 0 - # ParamContexts don't serialize - if isinstance(self, SimObject) and not isinstance(self, ParamContext): + if isinstance(self, SimObject): count += self._ccObject.drain(drain_event) if recursive: for child in self._children.itervalues(): @@ -720,7 +717,7 @@ class SimObject(object): return count def resume(self): - if isinstance(self, SimObject) and not isinstance(self, ParamContext): + if isinstance(self, SimObject): self._ccObject.resume() for child in self._children.itervalues(): child.resume() @@ -730,13 +727,13 @@ class SimObject(object): # i don't know if there's a better way to do this - calling # setMemoryMode directly from self._ccObject results in calling # SimObject::setMemoryMode, not the System::setMemoryMode - system_ptr = internal.main.convertToSystemPtr(self._ccObject) + system_ptr = internal.sim_object.convertToSystemPtr(self._ccObject) system_ptr.setMemoryMode(mode) for child in self._children.itervalues(): child.changeTiming(mode) def takeOverFrom(self, old_cpu): - cpu_ptr = internal.main.convertToBaseCPUPtr(old_cpu._ccObject) + cpu_ptr = internal.sim_object.convertToBaseCPUPtr(old_cpu._ccObject) self._ccObject.takeOverFrom(cpu_ptr) # generate output file for 'dot' to display as a pretty graph. @@ -782,9 +779,6 @@ class SimObject(object): for c in self.children: c.outputDot(dot) -class ParamContext(SimObject): - pass - # Function to provide to C++ so it can look up instances based on paths def resolveSimObject(name): obj = instanceDict[name] @@ -793,7 +787,7 @@ def resolveSimObject(name): # __all__ defines the list of symbols that get exported when # 'from config import *' is invoked. Try to keep this reasonably # short to avoid polluting other namespaces. -__all__ = ['SimObject', 'ParamContext'] +__all__ = ['SimObject'] # see comment on imports at end of __init__.py. import proxy diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index f39cc670a..06dc92bc6 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -27,14 +27,16 @@ # Authors: Nathan Binkert # Steve Reinhardt -import atexit, os, sys +import atexit +import os +import sys # import the SWIG-wrapped main C++ functions import internal # import a few SWIG-wrapped items (those that are likely to be used # directly by user scripts) completely into this module for # convenience -from internal.main import simulate, SimLoopExitEvent +import event # import the m5 compile options import defines @@ -78,34 +80,72 @@ env.update(os.environ) # The final hook to generate .ini files. Called from the user script # once the config is built. def instantiate(root): - params.ticks_per_sec = float(root.clock.frequency) + # we need to fix the global frequency + ticks.fixGlobalFrequency() + root.unproxy_all() # ugly temporary hack to get output to config.ini sys.stdout = file(os.path.join(options.outdir, 'config.ini'), 'w') root.print_ini() sys.stdout.close() # close config.ini sys.stdout = sys.__stdout__ # restore to original - internal.main.loadIniFile(resolveSimObject) # load config.ini into C++ + + # load config.ini into C++ + internal.core.loadIniFile(resolveSimObject) + + # Initialize the global statistics + internal.stats.initSimStats() + + # Create the C++ sim objects and connect ports root.createCCObject() root.connectPorts() - internal.main.finalInit() - noDot = True # temporary until we fix dot - if not noDot: - dot = pydot.Dot() - instance.outputDot(dot) - dot.orientation = "portrait" - dot.size = "8.5,11" - dot.ranksep="equally" - dot.rank="samerank" - dot.write("config.dot") - dot.write_ps("config.ps") + + # Do a second pass to finish initializing the sim objects + internal.sim_object.initAll() + + # Do a third pass to initialize statistics + internal.sim_object.regAllStats() + + # Check to make sure that the stats package is properly initialized + internal.stats.check() + + # Reset to put the stats in a consistent state. + internal.stats.reset() + +def doDot(root): + dot = pydot.Dot() + instance.outputDot(dot) + dot.orientation = "portrait" + dot.size = "8.5,11" + dot.ranksep="equally" + dot.rank="samerank" + dot.write("config.dot") + dot.write_ps("config.ps") + +need_resume = [] +need_startup = True +def simulate(*args, **kwargs): + global need_resume, need_startup + + if need_startup: + internal.core.SimStartup() + need_startup = False + + for root in need_resume: + resume(root) + need_resume = [] + + return internal.event.simulate(*args, **kwargs) # Export curTick to user script. def curTick(): - return internal.main.cvar.curTick + return internal.core.cvar.curTick + +# Python exit handlers happen in reverse order. We want to dump stats last. +atexit.register(internal.stats.dump) # register our C++ exit callback function with Python -atexit.register(internal.main.doExitCleanup) +atexit.register(internal.core.doExitCleanup) # This loops until all objects have been fully drained. def doDrain(root): @@ -119,7 +159,7 @@ def doDrain(root): # be drained. def drain(root): all_drained = False - drain_event = internal.main.createCountedDrain() + drain_event = internal.event.createCountedDrain() unready_objects = root.startDrain(drain_event, True) # If we've got some objects that can't drain immediately, then simulate if unready_objects > 0: @@ -127,7 +167,7 @@ def drain(root): simulate() else: all_drained = True - internal.main.cleanupCountedDrain(drain_event) + internal.event.cleanupCountedDrain(drain_event) return all_drained def resume(root): @@ -135,32 +175,32 @@ def resume(root): def checkpoint(root, dir): if not isinstance(root, objects.Root): - raise TypeError, "Object is not a root object. Checkpoint must be called on a root object." + raise TypeError, "Checkpoint must be called on a root object." doDrain(root) print "Writing checkpoint" - internal.main.serializeAll(dir) + internal.sim_object.serializeAll(dir) resume(root) def restoreCheckpoint(root, dir): print "Restoring from checkpoint" - internal.main.unserializeAll(dir) - resume(root) + internal.sim_object.unserializeAll(dir) + need_resume.append(root) def changeToAtomic(system): - if not isinstance(system, objects.Root) and not isinstance(system, objects.System): - raise TypeError, "Object is not a root or system object. Checkpoint must be " - "called on a root object." + if not isinstance(system, (objects.Root, objects.System)): + raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \ + (type(system), objects.Root, objects.System) doDrain(system) print "Changing memory mode to atomic" - system.changeTiming(internal.main.SimObject.Atomic) + system.changeTiming(internal.sim_object.SimObject.Atomic) def changeToTiming(system): - if not isinstance(system, objects.Root) and not isinstance(system, objects.System): - raise TypeError, "Object is not a root or system object. Checkpoint must be " - "called on a root object." + if not isinstance(system, (objects.Root, objects.System)): + raise TypeError, "Parameter of type '%s'. Must be type %s or %s." % \ + (type(system), objects.Root, objects.System) doDrain(system) print "Changing memory mode to timing" - system.changeTiming(internal.main.SimObject.Timing) + system.changeTiming(internal.sim_object.SimObject.Timing) def switchCpus(cpuList): print "switching cpus" @@ -180,7 +220,7 @@ def switchCpus(cpuList): raise TypeError, "%s is not of type BaseCPU" % cpu # Drain all of the individual CPUs - drain_event = internal.main.createCountedDrain() + drain_event = internal.event.createCountedDrain() unready_cpus = 0 for old_cpu in old_cpus: unready_cpus += old_cpu.startDrain(drain_event, False) @@ -188,7 +228,7 @@ def switchCpus(cpuList): if unready_cpus > 0: drain_event.setCount(unready_cpus) simulate() - internal.main.cleanupCountedDrain(drain_event) + internal.event.cleanupCountedDrain(drain_event) # Now all of the CPUs are ready to be switched out for old_cpu in old_cpus: old_cpu._ccObject.switchOut() diff --git a/src/python/m5/convert.py b/src/python/m5/convert.py index 580a579bc..bb9e3e1f1 100644 --- a/src/python/m5/convert.py +++ b/src/python/m5/convert.py @@ -148,7 +148,7 @@ def toLatency(value): raise ValueError, "cannot convert '%s' to latency" % value -def toClockPeriod(value): +def anyToLatency(value): """result is a clock period""" if not isinstance(value, str): @@ -170,6 +170,27 @@ def toClockPeriod(value): raise ValueError, "cannot convert '%s' to clock period" % value +def anyToFrequency(value): + """result is a clock period""" + + if not isinstance(value, str): + raise TypeError, "wrong type '%s' should be str" % type(value) + + try: + val = toFrequency(value) + return val + except ValueError: + pass + + try: + val = toLatency(value) + if val != 0: + val = 1 / val + return val + except ValueError: + pass + + raise ValueError, "cannot convert '%s' to clock period" % value def toNetworkBandwidth(value): if not isinstance(value, str): diff --git a/src/python/m5/event.py b/src/python/m5/event.py new file mode 100644 index 000000000..2d6497464 --- /dev/null +++ b/src/python/m5/event.py @@ -0,0 +1,42 @@ +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +from internal.event import create +from internal.event import SimLoopExitEvent as SimExit + +class ProgressEvent(object): + def __init__(self, period): + self.period = int(period) + self.schedule() + + def schedule(self): + create(self, m5.curTick() + self.period) + + def __call__(self): + print "Progress! Time now %fs" % (m5.curTick()/1e12) + self.schedule() diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 5df6d03cf..1695ed75f 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -29,11 +29,7 @@ import code, optparse, os, socket, sys from datetime import datetime from attrdict import attrdict - -try: - import info -except ImportError: - info = None +import traceflags __all__ = [ 'options', 'arguments', 'main' ] @@ -45,6 +41,19 @@ The Regents of The University of Michigan All Rights Reserved ''' +def print_list(items, indent=4): + line = ' ' * indent + for i,item in enumerate(items): + if len(line) + len(item) > 76: + print line + line = ' ' * indent + + if i < len(items) - 1: + line += '%s, ' % item + else: + line += item + print line + # there's only one option parsing done, so make it global and add some # helper functions to make it work well. parser = optparse.OptionParser(usage=usage, version=version, @@ -140,50 +149,17 @@ add_option("--debug-break", metavar="TIME[,TIME]", action='append', split=',', # Tracing options set_group("Trace Options") +add_option("--trace-help", action='store_true', + help="Print help on trace flags") add_option("--trace-flags", metavar="FLAG[,FLAG]", action='append', split=',', - help="Sets the flags for tracing") -add_option("--trace-start", metavar="TIME", default='0s', - help="Start tracing at TIME (must have units)") -add_option("--trace-cycle", metavar="CYCLE", default='0', - help="Start tracing at CYCLE") + help="Sets the flags for tracing (-FLAG disables a flag)") +add_option("--trace-start", metavar="TIME", type='int', + help="Start tracing at TIME (must be in ticks)") add_option("--trace-file", metavar="FILE", default="cout", help="Sets the output file for tracing [Default: %default]") -add_option("--trace-circlebuf", metavar="SIZE", type="int", default=0, - help="If SIZE is non-zero, turn on the circular buffer with SIZE lines") -add_option("--no-trace-circlebuf", action="store_const", const=0, - dest='trace_circlebuf', help=optparse.SUPPRESS_HELP) -bool_option("trace-dumponexit", default=False, - help="Dump trace buffer on exit") add_option("--trace-ignore", metavar="EXPR", action='append', split=':', help="Ignore EXPR sim objects") -# Execution Trace options -set_group("Execution Trace Options") -bool_option("speculative", default=True, - help="Don't capture speculative instructions") -bool_option("print-cycle", default=True, - help="Don't print cycle numbers in trace output") -bool_option("print-symbol", default=True, - help="Disable PC symbols in trace output") -bool_option("print-opclass", default=True, - help="Don't print op class type in trace output") -bool_option("print-thread", default=True, - help="Don't print thread number in trace output") -bool_option("print-effaddr", default=True, - help="Don't print effective address in trace output") -bool_option("print-data", default=True, - help="Don't print result data in trace output") -bool_option("print-iregs", default=False, - help="Print fetch sequence numbers in trace output") -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") -bool_option("legion-lock", default=False, - help="Compare simulator state with Legion simulator every cycle") - options = attrdict() arguments = [] @@ -211,6 +187,9 @@ def parse_args(): return opts,args def main(): + import defines + import event + import info import internal parse_args() @@ -242,6 +221,19 @@ def main(): print info.RELEASE_NOTES print + if options.trace_help: + done = True + print "Base Flags:" + print_list(traceflags.baseFlags, indent=4) + print + print "Compound Flags:" + for flag in traceflags.compoundFlags: + if flag == 'All': + continue + print " %s:" % flag + print_list(traceflags.compoundFlagMap[flag], indent=8) + print + if done: sys.exit(0) @@ -249,7 +241,7 @@ def main(): print "M5 Simulator System" print brief_copyright print - print "M5 compiled %s" % internal.main.cvar.compileDate; + print "M5 compiled %s" % internal.core.cvar.compileDate; print "M5 started %s" % datetime.now().ctime() print "M5 executing on %s" % socket.gethostname() print "command line:", @@ -261,10 +253,11 @@ def main(): 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 - internal.main.setOutputDir(options.outdir) + internal.core.setOutputDir(options.outdir) # update the system path with elements from the -p option sys.path[0:0] = options.path @@ -272,34 +265,45 @@ def main(): import objects # set stats options - objects.Statistics.text_file = options.stats_file + internal.stats.initText(options.stats_file) # set debugging options for when in options.debug_break: internal.debug.schedBreakCycle(int(when)) - # set tracing options - objects.Trace.flags = options.trace_flags - objects.Trace.start = options.trace_start - objects.Trace.cycle = options.trace_cycle - objects.Trace.file = options.trace_file - objects.Trace.bufsize = options.trace_circlebuf - objects.Trace.dump_on_exit = options.trace_dumponexit - objects.Trace.ignore = options.trace_ignore - - # set execution trace options - objects.ExecutionTrace.speculative = options.speculative - objects.ExecutionTrace.print_cycle = options.print_cycle - objects.ExecutionTrace.pc_symbol = options.print_symbol - objects.ExecutionTrace.print_opclass = options.print_opclass - objects.ExecutionTrace.print_thread = options.print_thread - objects.ExecutionTrace.print_effaddr = options.print_effaddr - objects.ExecutionTrace.print_data = options.print_data - 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 - objects.ExecutionTrace.legion_lockstep = options.legion_lock + on_flags = [] + off_flags = [] + for flag in options.trace_flags: + off = False + if flag.startswith('-'): + flag = flag[1:] + off = True + if flag not in traceflags.allFlags: + print >>sys.stderr, "invalid trace flag '%s'" % flag + sys.exit(1) + + if off: + off_flags.append(flag) + else: + on_flags.append(flag) + + for flag in on_flags: + internal.trace.set(flag) + + for flag in off_flags: + internal.trace.clear(flag) + + if options.trace_start: + def enable_trace(): + internal.trace.cvar.enabled = True + event.create(enable_trace, int(options.trace_start)) + else: + internal.trace.cvar.enabled = True + + internal.trace.output(options.trace_file) + + for ignore in options.trace_ignore: + internal.trace.ignore(ignore) sys.argv = arguments sys.path = [ os.path.dirname(sys.argv[0]) ] + sys.path @@ -309,7 +313,7 @@ def main(): # we want readline if we're doing anything interactive if options.interactive or options.pdb: - exec("import readline", scope) + exec "import readline" in scope # if pdb was requested, execfile the thing under pdb, otherwise, # just do the execfile normally diff --git a/src/python/m5/objects/BaseCPU.py b/src/python/m5/objects/BaseCPU.py index 67a28a61e..986220c3f 100644 --- a/src/python/m5/objects/BaseCPU.py +++ b/src/python/m5/objects/BaseCPU.py @@ -47,8 +47,8 @@ class BaseCPU(SimObject): defer_registration = Param.Bool(False, "defer registration with system (for sampling)") - clock = Param.Clock(Parent.clock, "clock speed") - phase = Param.Latency("0ns", "clock phase") + clock = Param.Clock('1t', "clock speed") + phase = Param.Latency('0ns', "clock phase") _mem_ports = [] diff --git a/src/python/m5/objects/IntrControl.py b/src/python/m5/objects/IntrControl.py index a7cf5cc84..398ba47f9 100644 --- a/src/python/m5/objects/IntrControl.py +++ b/src/python/m5/objects/IntrControl.py @@ -3,4 +3,4 @@ from m5.params import * from m5.proxy import * class IntrControl(SimObject): type = 'IntrControl' - cpu = Param.BaseCPU(Parent.cpu[0], "the cpu") + sys = Param.System(Parent.any, "the system we are part of") diff --git a/src/python/m5/objects/PhysicalMemory.py b/src/python/m5/objects/PhysicalMemory.py index b8df6229e..c389e4a7f 100644 --- a/src/python/m5/objects/PhysicalMemory.py +++ b/src/python/m5/objects/PhysicalMemory.py @@ -8,7 +8,7 @@ class PhysicalMemory(MemObject): functional = Port("Functional Access Port") range = Param.AddrRange(AddrRange('128MB'), "Device Address") file = Param.String('', "memory mapped file") - latency = Param.Latency(Parent.clock, "latency of an access") + latency = Param.Latency('1t', "latency of an access") zero = Param.Bool(False, "zero initialize memory") class DRAMMemory(PhysicalMemory): diff --git a/src/python/m5/objects/Root.py b/src/python/m5/objects/Root.py index b6123f192..2b0e736e7 100644 --- a/src/python/m5/objects/Root.py +++ b/src/python/m5/objects/Root.py @@ -1,23 +1,6 @@ from m5.SimObject import SimObject from m5.params import * -from Serialize import Serialize -from Serialize import Statreset -from Statistics import Statistics -from Trace import Trace -from ExeTrace import ExecutionTrace class Root(SimObject): type = 'Root' - 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)") - output_file = Param.String('cout', "file to dump simulator output to") - checkpoint = Param.String('', "checkpoint file to load") -# stats = Param.Statistics(Statistics(), "statistics object") -# trace = Param.Trace(Trace(), "trace object") -# serialize = Param.Serialize(Serialize(), "checkpoint generation options") - stats = Statistics() - trace = Trace() - exetrace = ExecutionTrace() - serialize = Serialize() + dummy = Param.Int(0, "We don't support objects without params") diff --git a/src/python/m5/objects/SimConsole.py b/src/python/m5/objects/SimConsole.py index bdd7f246d..dfad18eb6 100644 --- a/src/python/m5/objects/SimConsole.py +++ b/src/python/m5/objects/SimConsole.py @@ -1,14 +1,11 @@ from m5.SimObject import SimObject from m5.params import * from m5.proxy import * -class ConsoleListener(SimObject): - type = 'ConsoleListener' - port = Param.TcpPort(3456, "listen port") class SimConsole(SimObject): type = 'SimConsole' append_name = Param.Bool(True, "append name() to filename") intr_control = Param.IntrControl(Parent.any, "interrupt controller") - listener = Param.ConsoleListener("console listener") + port = Param.TcpPort(3456, "listen port") number = Param.Int(0, "console number") output = Param.String('console', "file to dump output to") diff --git a/src/python/m5/objects/T1000.py b/src/python/m5/objects/T1000.py index 85c4db6df..0acfa0920 100644 --- a/src/python/m5/objects/T1000.py +++ b/src/python/m5/objects/T1000.py @@ -1,9 +1,9 @@ from m5.params import * from m5.proxy import * -from Device import BasicPioDevice, IsaFake, BadAddr +from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr from Uart import Uart8250 from Platform import Platform -from SimConsole import SimConsole, ConsoleListener +from SimConsole import SimConsole class MmDisk(BasicPioDevice): @@ -16,6 +16,10 @@ class DumbTOD(BasicPioDevice): time = Param.Time('01/01/2009', "System time to use ('Now' for real time)") pio_addr = 0xfff0c1fff8 +class Iob(PioDevice): + type = 'Iob' + pio_latency = Param.Latency('1ns', "Programed IO latency in simticks") + class T1000(Platform): type = 'T1000' @@ -28,9 +32,6 @@ class T1000(Platform): ret_data64=0x0000000000000000, update_data=False) #warn_access="Accessing Memory Banks -- Unimplemented!") - fake_iob = IsaFake(pio_addr=0x9800000000, pio_size=0x100000000) - #warn_access="Accessing IOB -- Unimplemented!") - fake_jbi = IsaFake(pio_addr=0x8000000000, pio_size=0x100000000) #warn_access="Accessing JBI -- Unimplemented!") @@ -69,20 +70,28 @@ class T1000(Platform): fake_ssi = IsaFake(pio_addr=0xff00000000, pio_size=0x10000000) #warn_access="Accessing SSI -- Unimplemented!") + hconsole = SimConsole() hvuart = Uart8250(pio_addr=0xfff0c2c000) htod = DumbTOD() + pconsole = SimConsole() puart0 = Uart8250(pio_addr=0x1f10000000) - console = SimConsole(listener = ConsoleListener()) + + iob = Iob() + # Attach I/O devices that are on chip + def attachOnChipIO(self, bus): + self.iob.pio = bus.port + self.htod.pio = bus.port + # 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.hvuart.sim_console = self.hconsole + self.puart0.sim_console = self.pconsole self.fake_clk.pio = bus.port self.fake_membnks.pio = bus.port - self.fake_iob.pio = bus.port - self.fake_jbi.pio = bus.port self.fake_l2_1.pio = bus.port self.fake_l2_2.pio = bus.port self.fake_l2_3.pio = bus.port @@ -92,6 +101,6 @@ class T1000(Platform): self.fake_l2esr_3.pio = bus.port self.fake_l2esr_4.pio = bus.port self.fake_ssi.pio = bus.port + self.fake_jbi.pio = bus.port self.puart0.pio = bus.port self.hvuart.pio = bus.port - self.htod.pio = bus.port diff --git a/src/python/m5/params.py b/src/python/m5/params.py index f8a9f9ddd..9892df97c 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -51,6 +51,7 @@ import sys import time import convert +import ticks from util import * # Dummy base class to identify types that are legitimate for SimObject @@ -360,6 +361,7 @@ class MemorySize(CheckedInt): self._check() class MemorySize32(CheckedInt): + cxx_type = 'uint32_t' size = 32 unsigned = True def __init__(self, value): @@ -632,47 +634,29 @@ class Enum(ParamValue): def __str__(self): return self.value -ticks_per_sec = None - # how big does a rounding error need to be before we warn about it? frequency_tolerance = 0.001 # 0.1% -# convert a floting-point # of ticks to integer, and warn if rounding -# discards too much precision -def tick_check(float_ticks): - if float_ticks == 0: - return 0 - int_ticks = int(round(float_ticks)) - err = (float_ticks - int_ticks) / float_ticks - if err > frequency_tolerance: - print >> sys.stderr, "Warning: rounding error > tolerance" - print >> sys.stderr, " %f rounded to %d" % (float_ticks, int_ticks) - #raise ValueError - return int_ticks - -def getLatency(value): - if isinstance(value, Latency) or isinstance(value, Clock): - return value.value - elif isinstance(value, Frequency) or isinstance(value, RootClock): - return 1 / value.value - elif isinstance(value, str): - try: - return convert.toLatency(value) - except ValueError: - try: - return 1 / convert.toFrequency(value) - except ValueError: - pass # fall through - raise ValueError, "Invalid Frequency/Latency value '%s'" % value - - -class Latency(NumericParamValue): +class TickParamValue(NumericParamValue): cxx_type = 'Tick' cxx_predecls = ['#include "sim/host.hh"'] swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + '%import "sim/host.hh"'] + +class Latency(TickParamValue): def __init__(self, value): - self.value = getLatency(value) + if isinstance(value, (Latency, Clock)): + self.ticks = value.ticks + self.value = value.value + elif isinstance(value, Frequency): + self.ticks = value.ticks + self.value = 1.0 / value.value + elif value.endswith('t'): + self.ticks = True + self.value = int(value[:-1]) + else: + self.ticks = False + self.value = convert.toLatency(value) def __getattr__(self, attr): if attr in ('latency', 'period'): @@ -683,15 +667,25 @@ class Latency(NumericParamValue): # convert latency to ticks def ini_str(self): - return str(tick_check(self.value * ticks_per_sec)) + if self.ticks or self.value == 0: + return '%d' % self.value + else: + return '%d' % (ticks.fromSeconds(self.value)) -class Frequency(NumericParamValue): - cxx_type = 'Tick' - cxx_predecls = ['#include "sim/host.hh"'] - swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + - '%import "sim/host.hh"'] +class Frequency(TickParamValue): def __init__(self, value): - self.value = 1 / getLatency(value) + if isinstance(value, (Latency, Clock)): + if value.value == 0: + self.value = 0 + else: + self.value = 1.0 / value.value + self.ticks = value.ticks + elif isinstance(value, Frequency): + self.value = value.value + self.ticks = value.ticks + else: + self.ticks = False + self.value = convert.toFrequency(value) def __getattr__(self, attr): if attr == 'frequency': @@ -700,30 +694,12 @@ class Frequency(NumericParamValue): return Latency(self) raise AttributeError, "Frequency object has no attribute '%s'" % attr - # convert frequency to ticks per period - def ini_str(self): - return self.period.ini_str() - -# Just like Frequency, except ini_str() is absolute # of ticks per sec (Hz). -# We can't inherit from Frequency because we don't want it to be directly -# assignable to a regular Frequency parameter. -class RootClock(ParamValue): - cxx_type = 'Tick' - cxx_predecls = ['#include "sim/host.hh"'] - swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + - '%import "sim/host.hh"'] - def __init__(self, value): - self.value = 1 / getLatency(value) - - def __getattr__(self, attr): - if attr == 'frequency': - return Frequency(self) - if attr in ('latency', 'period'): - return Latency(self) - raise AttributeError, "Frequency object has no attribute '%s'" % attr - + # convert latency to ticks def ini_str(self): - return str(tick_check(self.value)) + if self.ticks or self.value == 0: + return '%d' % self.value + else: + return '%d' % (ticks.fromSeconds(1.0 / self.value)) # A generic frequency and/or Latency value. Value is stored as a latency, # but to avoid ambiguity this object does not support numeric ops (* or /). @@ -734,7 +710,18 @@ class Clock(ParamValue): swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + '%import "sim/host.hh"'] def __init__(self, value): - self.value = getLatency(value) + if isinstance(value, (Latency, Clock)): + self.ticks = value.ticks + self.value = value.value + elif isinstance(value, Frequency): + self.ticks = value.ticks + self.value = 1.0 / value.value + elif value.endswith('t'): + self.ticks = True + self.value = int(value[:-1]) + else: + self.ticks = False + self.value = convert.anyToLatency(value) def __getattr__(self, attr): if attr == 'frequency': @@ -749,18 +736,23 @@ class Clock(ParamValue): class NetworkBandwidth(float,ParamValue): cxx_type = 'float' def __new__(cls, value): - val = convert.toNetworkBandwidth(value) / 8.0 + # convert to bits per second + val = convert.toNetworkBandwidth(value) return super(cls, NetworkBandwidth).__new__(cls, val) def __str__(self): return str(self.val) def ini_str(self): - return '%f' % (ticks_per_sec / float(self)) + # convert to seconds per byte + value = 8.0 / float(self) + # convert to ticks per byte + return '%f' % (ticks.fromSeconds(value)) class MemoryBandwidth(float,ParamValue): cxx_type = 'float' def __new__(self, value): + # we want the number of ticks per byte of data val = convert.toMemoryBandwidth(value) return super(cls, MemoryBandwidth).__new__(cls, val) @@ -768,7 +760,10 @@ class MemoryBandwidth(float,ParamValue): return str(self.val) def ini_str(self): - return '%f' % (ticks_per_sec / float(self)) + # convert to seconds per byte + value = 1.0 / float(self) + # convert to ticks per byte + return '%f' % (ticks.fromSeconds(value)) # # "Constants"... handy aliases for various values. @@ -894,9 +889,8 @@ class PortRef(object): if self.ccConnected: # already done this return peer = self.peer - internal.main.connectPorts(self.simobj.getCCObject(), self.name, - self.index, peer.simobj.getCCObject(), - peer.name, peer.index) + internal.sim_object.connectPorts(self.simobj.getCCObject(), self.name, + self.index, peer.simobj.getCCObject(), peer.name, peer.index) self.ccConnected = True peer.ccConnected = True @@ -1024,7 +1018,7 @@ __all__ = ['Param', 'VectorParam', 'Counter', 'Addr', 'Tick', 'Percent', 'TcpPort', 'UdpPort', 'EthernetAddr', 'MemorySize', 'MemorySize32', - 'Latency', 'Frequency', 'RootClock', 'Clock', + 'Latency', 'Frequency', 'Clock', 'NetworkBandwidth', 'MemoryBandwidth', 'Range', 'AddrRange', 'TickRange', 'MaxAddr', 'MaxTick', 'AllMemory', diff --git a/src/python/m5/stats.py b/src/python/m5/stats.py new file mode 100644 index 000000000..041a3f58d --- /dev/null +++ b/src/python/m5/stats.py @@ -0,0 +1,46 @@ +# Copyright (c) 2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +import internal + +from internal.stats import dump +from internal.stats import initSimStats +from internal.stats import reset +from internal.stats import StatEvent as event + +def initText(filename, desc=True, compat=True): + internal.stats.initText(filename, desc, compat) + +def initMySQL(host, database, user='', passwd='', project='test', name='test', + sample='0'): + if not user: + import getpass + user = getpass.getuser() + + internal.stats.initMySQL(host, database, user, passwd, project, name, + sample) diff --git a/src/python/m5/ticks.py b/src/python/m5/ticks.py new file mode 100644 index 000000000..e91b470ff --- /dev/null +++ b/src/python/m5/ticks.py @@ -0,0 +1,89 @@ +# Copyright (c) 2007 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +import sys + +import convert +import internal + +tps = 1.0e12 # default to 1 THz (1 Tick == 1 ps) +tps_fixed = False # once set to true, can't be changed + +# fix the global frequency and tell C++ about it +def fixGlobalFrequency(): + global tps, tps_fixed + if not tps_fixed: + tps_fixed = True + internal.core.setClockFrequency(int(tps)) + print "Global frequency set at %d ticks per second" % int(tps) + +def setGlobalFrequency(ticksPerSecond): + global tps, tps_fixed + + if tps_fixed: + raise AttributeError, \ + "Global frequency already fixed at %f ticks/s." % tps + + if isinstance(ticksPerSecond, (int, long)): + tps = ticksPerSecond + elif isinstance(ticksPerSecond, float): + tps = ticksPerSecond + elif isinstance(ticksPerSecond, str): + tps = round(convert.anyToFrequency(ticksPerSecond)) + else: + raise TypeError, \ + "wrong type '%s' for ticksPerSecond" % type(ticksPerSecond) + +# how big does a rounding error need to be before we warn about it? +frequency_tolerance = 0.001 # 0.1% + +def fromSeconds(value): + if not isinstance(value, float): + raise TypeError, "can't convert '%s' to type tick" % type(value) + + # once someone needs to convert to seconds, the global frequency + # had better be fixed + if not tps_fixed: + raise AttributeError, \ + "In order to do conversions, the global frequency must be fixed" + + if value == 0: + return 0 + + # convert the value from time to ticks + value *= tps + + int_value = int(round(value)) + err = (value - int_value) / value + if err > frequency_tolerance: + print >>sys.stderr, "Warning: rounding error > tolerance" + print >>sys.stderr, " %f rounded to %d" % (value, int_value) + return int_value + +__all__ = [ 'setGlobalFrequency', 'fixGlobalFrequency', 'fromSeconds', + 'frequency_tolerance' ] diff --git a/src/python/swig/core.i b/src/python/swig/core.i new file mode 100644 index 000000000..3edfa4c7e --- /dev/null +++ b/src/python/swig/core.i @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +%module core + +%{ +#include "python/swig/pyobject.hh" + +#include "sim/core.hh" +#include "sim/host.hh" +#include "sim/startup.hh" + +extern const char *compileDate; +%} + +%include "stdint.i" +%include "std_string.i" +%include "sim/host.hh" + +void setOutputDir(const std::string &dir); +void setOutputFile(const std::string &file); +void loadIniFile(PyObject *); +void SimStartup(); +void doExitCleanup(); + +char *compileDate; + +void setClockFrequency(Tick ticksPerSecond); + +%immutable curTick; +Tick curTick; + +%wrapper %{ +// fix up module name to reflect the fact that it's inside the m5 package +#undef SWIG_name +#define SWIG_name "m5.internal._core" +%} diff --git a/src/python/swig/event.i b/src/python/swig/event.i index 554c9fa0e..9a2093c99 100644 --- a/src/python/swig/event.i +++ b/src/python/swig/event.i @@ -33,19 +33,43 @@ %{ #include "python/swig/pyevent.hh" -inline void -create(PyObject *object, Tick when) -{ - new PythonEvent(object, when); -} +#include "sim/sim_events.hh" +#include "sim/sim_exit.hh" +#include "sim/simulate.hh" %} %include "stdint.i" +%include "std_string.i" %include "sim/host.hh" -%inline %{ -extern void create(PyObject *object, Tick when); -%} +void create(PyObject *object, Tick when); + +class Event; +class CountedDrainEvent : public Event { + public: + void setCount(int _count); +}; + +CountedDrainEvent *createCountedDrain(); +void cleanupCountedDrain(Event *drain_event); + +// minimal definition of SimExitEvent interface to wrap +class SimLoopExitEvent { + public: + std::string getCause(); + int getCode(); + SimLoopExitEvent(EventQueue *q, Tick _when, Tick _repeat, + const std::string &_cause, int c = 0); +}; + +%exception simulate { + $action + if (!result) { + return NULL; + } +} +SimLoopExitEvent *simulate(Tick num_cycles = MaxTick); +void exitSimLoop(const std::string &message, int exit_code); %wrapper %{ // fix up module name to reflect the fact that it's inside the m5 package diff --git a/src/python/swig/pyevent.cc b/src/python/swig/pyevent.cc index 6fb7d3f17..7f23b8874 100644 --- a/src/python/swig/pyevent.cc +++ b/src/python/swig/pyevent.cc @@ -31,6 +31,7 @@ #include <Python.h> #include "python/swig/pyevent.hh" +#include "sim/async.hh" PythonEvent::PythonEvent(PyObject *obj, Tick when, Priority priority) : Event(&mainEventQueue, priority), object(obj) @@ -52,9 +53,9 @@ PythonEvent::~PythonEvent() void PythonEvent::process() { - PyObject *result; - - result = PyObject_CallMethod(object, "process", ""); + PyObject *args = PyTuple_New(0); + PyObject *result = PyObject_Call(object, args, NULL); + Py_DECREF(args); if (result) { // Nothing to do just decrement the reference count @@ -62,5 +63,7 @@ PythonEvent::process() } else { // Somethign should be done to signal back to the main interpreter // that there's been an exception. + async_event = true; + async_exception = true; } } diff --git a/src/python/swig/pyevent.hh b/src/python/swig/pyevent.hh index 16af85a84..65e80e9e4 100644 --- a/src/python/swig/pyevent.hh +++ b/src/python/swig/pyevent.hh @@ -32,6 +32,7 @@ #define __PYTHON_SWIG_PYEVENT_HH__ #include "sim/eventq.hh" +#include "sim/sim_events.hh" class PythonEvent : public Event { @@ -45,4 +46,29 @@ class PythonEvent : public Event virtual void process(); }; +inline void +create(PyObject *object, Tick when) +{ + new PythonEvent(object, when); +} + +inline Event * +createCountedDrain() +{ + return new CountedDrainEvent(); +} + +inline void +cleanupCountedDrain(Event *counted_drain) +{ + CountedDrainEvent *event = + dynamic_cast<CountedDrainEvent *>(counted_drain); + if (event == NULL) { + fatal("Called cleanupCountedDrain() on an event that was not " + "a CountedDrainEvent."); + } + assert(event->getCount() == 0); + delete event; +} + #endif // __PYTHON_SWIG_PYEVENT_HH__ diff --git a/src/python/swig/pyobject.cc b/src/python/swig/pyobject.cc new file mode 100644 index 000000000..11141fa84 --- /dev/null +++ b/src/python/swig/pyobject.cc @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#include <Python.h> + +#include <string> + +#include "base/inifile.hh" +#include "base/output.hh" +#include "mem/mem_object.hh" +#include "mem/port.hh" +#include "sim/builder.hh" +#include "sim/sim_object.hh" + +using namespace std; + +/** + * Look up a MemObject port. Helper function for connectPorts(). + */ +Port * +lookupPort(SimObject *so, const std::string &name, int i) +{ + MemObject *mo = dynamic_cast<MemObject *>(so); + if (mo == NULL) { + warn("error casting SimObject %s to MemObject", so->name()); + return NULL; + } + + Port *p = mo->getPort(name, i); + if (p == NULL) + warn("error looking up port %s on object %s", name, so->name()); + return p; +} + + +/** + * Connect the described MemObject ports. Called from Python via SWIG. + */ +int +connectPorts(SimObject *o1, const std::string &name1, int i1, + SimObject *o2, const std::string &name2, int i2) +{ + Port *p1 = lookupPort(o1, name1, i1); + Port *p2 = lookupPort(o2, name2, i2); + + if (p1 == NULL || p2 == NULL) { + warn("connectPorts: port lookup error"); + return 0; + } + + p1->setPeer(p2); + p2->setPeer(p1); + + return 1; +} + +inline IniFile & +inifile() +{ + static IniFile inifile; + return inifile; +} + +SimObject * +createSimObject(const string &name) +{ + return SimObjectClass::createObject(inifile(), name); +} + +/** + * Pointer to the Python function that maps names to SimObjects. + */ +PyObject *resolveFunc = NULL; + +/** + * Convert a pointer to the Python object that SWIG wraps around a C++ + * SimObject pointer back to the actual C++ pointer. See main.i. + */ +extern "C" SimObject *convertSwigSimObjectPtr(PyObject *); + +SimObject * +resolveSimObject(const string &name) +{ + PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str()); + if (pyPtr == NULL) { + PyErr_Print(); + panic("resolveSimObject: failure on call to Python for %s", name); + } + + SimObject *simObj = convertSwigSimObjectPtr(pyPtr); + if (simObj == NULL) + panic("resolveSimObject: failure on pointer conversion for %s", name); + + return simObj; +} + +/** + * Load config.ini into C++ database. Exported to Python via SWIG; + * invoked from m5.instantiate(). + */ +void +loadIniFile(PyObject *_resolveFunc) +{ + resolveFunc = _resolveFunc; + configStream = simout.find("config.out"); + + // The configuration database is now complete; start processing it. + inifile().load(simout.resolve("config.ini")); +} + diff --git a/src/python/swig/pyobject.hh b/src/python/swig/pyobject.hh new file mode 100644 index 000000000..d8efc9149 --- /dev/null +++ b/src/python/swig/pyobject.hh @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#include <Python.h> + +#include "cpu/base.hh" +#include "sim/host.hh" +#include "sim/serialize.hh" +#include "sim/sim_object.hh" +#include "sim/system.hh" + +SimObject *createSimObject(const std::string &name); +extern "C" SimObject *convertSwigSimObjectPtr(PyObject *); +SimObject *resolveSimObject(const std::string &name); +void loadIniFile(PyObject *_resolveFunc); + + +/** + * Connect the described MemObject ports. Called from Python via SWIG. + */ +int connectPorts(SimObject *o1, const std::string &name1, int i1, + SimObject *o2, const std::string &name2, int i2); + +inline BaseCPU * +convertToBaseCPUPtr(SimObject *obj) +{ + BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj); + + if (ptr == NULL) + warn("Casting to BaseCPU pointer failed"); + return ptr; +} + +inline System * +convertToSystemPtr(SimObject *obj) +{ + System *ptr = dynamic_cast<System *>(obj); + + if (ptr == NULL) + warn("Casting to System pointer failed"); + return ptr; +} + +inline void +initAll() +{ + SimObject::initAll(); +} + +inline void +regAllStats() +{ + SimObject::regAllStats(); +} + +inline void +serializeAll(const std::string &cpt_dir) +{ + Serializable::serializeAll(cpt_dir); +} + +inline void +unserializeAll(const std::string &cpt_dir) +{ + Serializable::unserializeAll(cpt_dir); +} + diff --git a/src/python/swig/random.i b/src/python/swig/random.i new file mode 100644 index 000000000..657a59780 --- /dev/null +++ b/src/python/swig/random.i @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +%module random + +%include "stdint.i" + +%{ +#include <cstdlib> + +#include "sim/host.hh" + +inline void +seed(uint64_t seed) +{ + ::srand48(seed & ULL(0xffffffffffff)); +} +%} + +%inline %{ +extern void seed(uint64_t seed); +%} + +%wrapper %{ +// fix up module name to reflect the fact that it's inside the m5 package +#undef SWIG_name +#define SWIG_name "m5.internal._random" +%} diff --git a/src/python/swig/sim_object.i b/src/python/swig/sim_object.i new file mode 100644 index 000000000..b2af72c61 --- /dev/null +++ b/src/python/swig/sim_object.i @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +%module sim_object + +%{ +#include "python/swig/pyobject.hh" +%} + +// import these files for SWIG to wrap +%include "stdint.i" +%include "std_string.i" +%include "sim/host.hh" + +class BaseCPU; + +class SimObject { + public: + enum State { + Running, + Draining, + Drained + }; + + enum MemoryMode { + Invalid, + Atomic, + Timing + }; + + unsigned int drain(Event *drain_event); + void resume(); + void switchOut(); + void takeOverFrom(BaseCPU *cpu); + SimObject(const std::string &_name); +}; + +class System { + private: + System(); + public: + void setMemoryMode(SimObject::MemoryMode mode); +}; + +SimObject *createSimObject(const std::string &name); + +int connectPorts(SimObject *o1, const std::string &name1, int i1, + SimObject *o2, const std::string &name2, int i2); + +BaseCPU *convertToBaseCPUPtr(SimObject *obj); +System *convertToSystemPtr(SimObject *obj); + +void serializeAll(const std::string &cpt_dir); +void unserializeAll(const std::string &cpt_dir); + +void initAll(); +void regAllStats(); + +%wrapper %{ +// fix up module name to reflect the fact that it's inside the m5 package +#undef SWIG_name +#define SWIG_name "m5.internal._sim_object" + +// Convert a pointer to the Python object that SWIG wraps around a +// C++ SimObject pointer back to the actual C++ pointer. +SimObject * +convertSwigSimObjectPtr(PyObject *pyObj) +{ + SimObject *so; + if (SWIG_ConvertPtr(pyObj, (void **) &so, SWIGTYPE_p_SimObject, 0) == -1) + return NULL; + return so; +} +%} diff --git a/src/python/swig/stats.i b/src/python/swig/stats.i new file mode 100644 index 000000000..d36f82dbc --- /dev/null +++ b/src/python/swig/stats.i @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +%module stats + +%include "std_string.i" + +%{ +#include "base/statistics.hh" +#include "base/stats/mysql.hh" +#include "base/stats/text.hh" +#include "sim/stat_control.hh" +%} + +namespace Stats { +void initSimStats(); +void initText(const std::string &filename, bool desc=true, bool compat=true); +void initMySQL(std::string host, std::string database, std::string user, + std::string passwd, std::string project, std::string name, + std::string sample); + +void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0); + +void check(); +void dump(); +void reset(); + +/* namespace Stat */ } + +%wrapper %{ +// fix up module name to reflect the fact that it's inside the m5 package +#undef SWIG_name +#define SWIG_name "m5.internal._stats" +%} diff --git a/src/python/swig/trace.i b/src/python/swig/trace.i new file mode 100644 index 000000000..69b44c025 --- /dev/null +++ b/src/python/swig/trace.i @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +%module trace + +%{ +#include "base/trace.hh" +#include "sim/host.hh" + +inline void +output(const char *filename) +{ + Trace::setOutput(filename); +} + +inline void +set(const char *flag) +{ + Trace::changeFlag(flag, true); +} + +inline void +clear(const char *flag) +{ + Trace::changeFlag(flag, false); +} + +inline void +ignore(const char *expr) +{ + Trace::ignore.setExpression(expr); +} + +using Trace::enabled; +%} + +%inline %{ +extern void output(const char *string); +extern void set(const char *string); +extern void clear(const char *string); +extern void ignore(const char *expr); +extern bool enabled; +%} + +%wrapper %{ +// fix up module name to reflect the fact that it's inside the m5 package +#undef SWIG_name +#define SWIG_name "m5.internal._trace" +%} diff --git a/src/sim/SConscript b/src/sim/SConscript new file mode 100644 index 000000000..46dc2c8dd --- /dev/null +++ b/src/sim/SConscript @@ -0,0 +1,54 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +Source('async.cc') +Source('builder.cc') +Source('core.cc') +Source('debug.cc') +Source('eventq.cc') +Source('faults.cc') +Source('main.cc') +Source('param.cc') +Source('root.cc') +Source('serialize.cc') +Source('sim_events.cc') +Source('sim_object.cc') +Source('simulate.cc') +Source('startup.cc') +Source('stat_control.cc') +Source('system.cc') + +if env['FULL_SYSTEM']: + Source('pseudo_inst.cc') +else: + Source('process.cc') + Source('syscall_emul.cc') diff --git a/src/sim/async.cc b/src/sim/async.cc new file mode 100644 index 000000000..1a8e499f7 --- /dev/null +++ b/src/sim/async.cc @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2000-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 + */ + +volatile bool async_event = false; +volatile bool async_statdump = false; +volatile bool async_statreset = false; +volatile bool async_exit = false; +volatile bool async_io = false; +volatile bool async_alarm = false; +volatile bool async_exception = false; + diff --git a/src/sim/async.hh b/src/sim/async.hh index 50ae73040..932f975d2 100644 --- a/src/sim/async.hh +++ b/src/sim/async.hh @@ -43,10 +43,12 @@ /// @note See the PollQueue object (in pollevent.hh) for the use of async_io and async_alarm. //@{ extern volatile bool async_event; ///< Some asynchronous event has happened. -extern volatile bool async_dump; ///< Async request to dump stats. +extern volatile bool async_statdump; ///< Async request to dump stats. +extern volatile bool async_statreset; ///< Async request to reset stats. extern volatile bool async_exit; ///< Async request to exit simulator. extern volatile bool async_io; ///< Async I/O request (SIGIO). extern volatile bool async_alarm; ///< Async alarm event (SIGALRM). +extern volatile bool async_exception; ///< Python exception. //@} #endif // __ASYNC_HH__ diff --git a/src/sim/builder.cc b/src/sim/builder.cc index 9074cc899..532df36b1 100644 --- a/src/sim/builder.cc +++ b/src/sim/builder.cc @@ -35,12 +35,12 @@ #include "sim/builder.hh" #include "sim/host.hh" #include "sim/sim_object.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; SimObjectBuilder::SimObjectBuilder(const std::string &_iniSection) - : ParamContext(_iniSection, NoAutoInit) + : ParamContext(_iniSection) { } diff --git a/src/sim/byteswap.hh b/src/sim/byteswap.hh index cbc0b5088..062fc4513 100644 --- a/src/sim/byteswap.hh +++ b/src/sim/byteswap.hh @@ -37,6 +37,7 @@ #ifndef __SIM_BYTE_SWAP_HH__ #define __SIM_BYTE_SWAP_HH__ +#include "base/bigint.hh" #include "base/misc.hh" #include "sim/host.hh" @@ -109,7 +110,7 @@ swap_byte16(uint16_t x) // This function lets the compiler figure out how to call the // swap_byte functions above for different data types. Since the -// sizeof() values are known at compiel time, it should inline to a +// sizeof() values are known at compile time, it should inline to a // direct call to the right swap_byteNN() function. template <typename T> static inline T swap_byte(T x) { @@ -125,6 +126,22 @@ static inline T swap_byte(T x) { panic("Can't byte-swap values larger than 64 bits"); } +template<> +static inline Twin64_t swap_byte<Twin64_t>(Twin64_t x) +{ + x.a = swap_byte(x.a); + x.b = swap_byte(x.b); + return x; +} + +template<> +static inline Twin32_t swap_byte<Twin32_t>(Twin32_t x) +{ + x.a = swap_byte(x.a); + x.b = swap_byte(x.b); + return x; +} + //The conversion functions with fixed endianness on both ends don't need to //be in a namespace template <typename T> static inline T betole(T value) {return swap_byte(value);} diff --git a/src/sim/core.cc b/src/sim/core.cc new file mode 100644 index 000000000..c961e9eb8 --- /dev/null +++ b/src/sim/core.cc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#include <iostream> +#include <string> + +#include "base/callback.hh" +#include "base/output.hh" +#include "sim/core.hh" + +using namespace std; + +Tick curTick = 0; + +namespace Clock { +/// The simulated frequency of curTick. (In ticks per second) +Tick Frequency; + +namespace Float { +double s; +double ms; +double us; +double ns; +double ps; + +double Hz; +double kHz; +double MHz; +double GHZ; +/* namespace Float */ } + +namespace Int { +Tick s; +Tick ms; +Tick us; +Tick ns; +Tick ps; +/* namespace Float */ } + +/* namespace Clock */ } + +void +setClockFrequency(Tick ticksPerSecond) +{ + using namespace Clock; + Frequency = ticksPerSecond; + Float::s = static_cast<double>(Frequency); + Float::ms = Float::s / 1.0e3; + Float::us = Float::s / 1.0e6; + Float::ns = Float::s / 1.0e9; + Float::ps = Float::s / 1.0e12; + + Float::Hz = 1.0 / Float::s; + Float::kHz = 1.0 / Float::ms; + Float::MHz = 1.0 / Float::us; + Float::GHZ = 1.0 / Float::ns; + + Int::s = Frequency; + Int::ms = Int::s / 1000; + Int::us = Int::ms / 1000; + Int::ns = Int::us / 1000; + Int::ps = Int::ns / 1000; + +} + +void +setOutputDir(const string &dir) +{ + simout.setDirectory(dir); +} + +ostream *outputStream; +ostream *configStream; + +void +setOutputFile(const string &file) +{ + outputStream = simout.find(file); +} + +/** + * Queue of C++ callbacks to invoke on simulator exit. + */ +inline CallbackQueue & +exitCallbacks() +{ + static CallbackQueue theQueue; + return theQueue; +} + +/** + * Register an exit callback. + */ +void +registerExitCallback(Callback *callback) +{ + exitCallbacks().add(callback); +} + +/** + * Do C++ simulator exit processing. Exported to SWIG to be invoked + * when simulator terminates via Python's atexit mechanism. + */ +void +doExitCleanup() +{ + exitCallbacks().process(); + exitCallbacks().clear(); + + cout.flush(); +} + diff --git a/src/sim/core.hh b/src/sim/core.hh new file mode 100644 index 000000000..7360032c2 --- /dev/null +++ b/src/sim/core.hh @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __SIM_CORE_HH__ +#define __SIM_CORE_HH__ + +#include <string> + +#include "sim/host.hh" + +/// The universal simulation clock. +extern Tick curTick; +const Tick retryTime = 1000; + +namespace Clock { +/// The simulated frequency of curTick. +extern Tick Frequency; + +namespace Float { +extern double s; +extern double ms; +extern double us; +extern double ns; +extern double ps; + +extern double Hz; +extern double kHz; +extern double MHz; +extern double GHZ; +/* namespace Float */ } + +namespace Int { +extern Tick s; +extern Tick ms; +extern Tick us; +extern Tick ns; +extern Tick ps; +/* namespace Int */ } +/* namespace Clock */ } + +void setClockFrequency(Tick ticksPerSecond); + +/// Output stream for simulator messages (e.g., cprintf()). Also used +/// as default stream for tracing and DPRINTF() messages (unless +/// overridden with trace:file option). +extern std::ostream *outputStream; +void setOutputFile(const std::string &file); +void setOutputDir(const std::string &dir); + +/// Output stream for configuration dump. +extern std::ostream *configStream; + +struct Callback; +void registerExitCallback(Callback *callback); +void doExitCleanup(); + +#endif /* __SIM_CORE_HH__ */ diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 6ae838897..65e115256 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -41,7 +41,7 @@ #include "sim/eventq.hh" #include "base/trace.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; @@ -53,6 +53,10 @@ using namespace std; // EventQueue mainEventQueue("MainEventQueue"); +#ifndef NDEBUG +Counter Event::instanceCounter = 0; +#endif + void EventQueue::insert(Event *event) { @@ -218,7 +222,6 @@ EventQueue::dump() cprintf("============================================================\n"); } -extern "C" void dumpMainQueue() { diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index fa65b08af..a57e9077e 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -75,6 +75,18 @@ class Event : public Serializable, public FastAlloc friend class EventQueue; private: + +#ifndef NDEBUG + /// Global counter to generate unique IDs for Event instances + static Counter instanceCounter; + + /// This event's unique ID. We can also use pointer values for + /// this but they're not consistent across runs making debugging + /// more difficult. Thus we use a global counter value when + /// debugging. + Counter instanceId; +#endif // NDEBUG + /// queue to which this event belongs (though it may or may not be /// scheduled on this queue yet) EventQueue *queue; @@ -157,6 +169,9 @@ class Event : public Serializable, public FastAlloc /// everything else, but before exit. Stat_Event_Pri = 90, + /// Progress events come at the end. + Progress_Event_Pri = 95, + /// If we want to exit on this cycle, it's the very last thing /// we do. Sim_Exit_Pri = 100 @@ -173,12 +188,19 @@ class Event : public Serializable, public FastAlloc #endif annotated_value(0) { +#ifndef NDEBUG + instanceId = ++instanceCounter; +#endif } ~Event() {} virtual const std::string name() const { +#ifndef NDEBUG + return csprintf("Event_%d", instanceId); +#else return csprintf("Event_%x", (uintptr_t)this); +#endif } /// Determine if the current event is scheduled diff --git a/src/sim/faults.cc b/src/sim/faults.cc index cea35482a..b09bbc177 100644 --- a/src/sim/faults.cc +++ b/src/sim/faults.cc @@ -29,10 +29,13 @@ * Gabe Black */ +#include "arch/isa_traits.hh" #include "base/misc.hh" -#include "sim/faults.hh" #include "cpu/thread_context.hh" #include "cpu/base.hh" +#include "sim/faults.hh" +#include "sim/process.hh" +#include "mem/page_table.hh" #if !FULL_SYSTEM void FaultBase::invoke(ThreadContext * tc) @@ -53,3 +56,26 @@ void UnimpFault::invoke(ThreadContext * tc) { panic("Unimpfault: %s\n", panicStr.c_str()); } +#if !FULL_SYSTEM +void PageTableFault::invoke(ThreadContext *tc) +{ + Process *p = tc->getProcessPtr(); + + // We've accessed the next page of the stack, so extend the stack + // to cover it. + if(vaddr < p->stack_min && vaddr >= p->stack_min - TheISA::PageBytes) + { + p->stack_min -= TheISA::PageBytes; + if(p->stack_base - p->stack_min > 8*1024*1024) + fatal("Over max stack size for one thread\n"); + p->pTable->allocate(p->stack_min, TheISA::PageBytes); + warn("Increasing stack size by one page."); + } + // Otherwise, we have an unexpected page fault. Report that fact, + // and what address was accessed to cause the fault. + else + { + panic("Page table fault when accessing virtual address %#x\n", vaddr); + } +} +#endif diff --git a/src/sim/faults.hh b/src/sim/faults.hh index 00264d8fc..2f0b5af62 100644 --- a/src/sim/faults.hh +++ b/src/sim/faults.hh @@ -76,4 +76,16 @@ class UnimpFault : public FaultBase void invoke(ThreadContext * tc); }; +#if !FULL_SYSTEM +class PageTableFault : public FaultBase +{ + private: + Addr vaddr; + public: + FaultName name() {return "M5 page table fault";} + PageTableFault(Addr va) : vaddr(va) {} + void invoke(ThreadContext * tc); +}; +#endif + #endif // __FAULTS_HH__ diff --git a/src/sim/main.cc b/src/sim/main.cc index 04dbe1ef4..5bf4add4b 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -25,77 +25,39 @@ * (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 Raasch - * Nathan Binkert - * Steve Reinhardt + * Authors: Nathan Binkert */ -/// -/// @file sim/main.cc -/// -#include <Python.h> // must be before system headers... see Python docs - -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#include <libgen.h> -#include <stdlib.h> +#include <Python.h> #include <signal.h> -#include <getopt.h> -#include <list> +#include <iostream> #include <string> -#include <vector> -#include "base/callback.hh" -#include "base/inifile.hh" +#include "base/cprintf.hh" #include "base/misc.hh" -#include "base/output.hh" -#include "base/pollevent.hh" -#include "base/statistics.hh" -#include "base/str.hh" -#include "base/time.hh" #include "config/pythonhome.hh" -#include "cpu/base.hh" -#include "cpu/smt.hh" -#include "mem/mem_object.hh" -#include "mem/port.hh" #include "python/swig/init.hh" #include "sim/async.hh" -#include "sim/builder.hh" #include "sim/host.hh" -#include "sim/serialize.hh" -#include "sim/sim_events.hh" -#include "sim/sim_exit.hh" -#include "sim/sim_object.hh" -#include "sim/system.hh" -#include "sim/stat_control.hh" -#include "sim/stats.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; -// See async.h. -volatile bool async_event = false; -volatile bool async_dump = false; -volatile bool async_dumpreset = false; -volatile bool async_exit = false; -volatile bool async_io = false; -volatile bool async_alarm = false; - /// Stats signal handler. void dumpStatsHandler(int sigtype) { async_event = true; - async_dump = true; + async_statdump = true; } void dumprstStatsHandler(int sigtype) { async_event = true; - async_dumpreset = true; + async_statdump = true; + async_statreset = true; } /// Exit signal handler. @@ -110,12 +72,7 @@ exitNowHandler(int sigtype) void abortHandler(int sigtype) { - cerr << "Program aborted at cycle " << curTick << endl; - -#if TRACING_ON - // dump trace buffer, if there is one - Trace::theLog.dump(cerr); -#endif + ccprintf(cerr, "Program aborted at cycle %d\n", curTick); } int @@ -163,310 +120,3 @@ main(int argc, char **argv) // clean up Python intepreter. Py_Finalize(); } - - -void -setOutputDir(const string &dir) -{ - simout.setDirectory(dir); -} - - -IniFile inifile; - -SimObject * -createSimObject(const string &name) -{ - return SimObjectClass::createObject(inifile, name); -} - - -/** - * Pointer to the Python function that maps names to SimObjects. - */ -PyObject *resolveFunc = NULL; - -/** - * Convert a pointer to the Python object that SWIG wraps around a C++ - * SimObject pointer back to the actual C++ pointer. See main.i. - */ -extern "C" SimObject *convertSwigSimObjectPtr(PyObject *); - - -SimObject * -resolveSimObject(const string &name) -{ - PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str()); - if (pyPtr == NULL) { - PyErr_Print(); - panic("resolveSimObject: failure on call to Python for %s", name); - } - - SimObject *simObj = convertSwigSimObjectPtr(pyPtr); - if (simObj == NULL) - panic("resolveSimObject: failure on pointer conversion for %s", name); - - return simObj; -} - - -/** - * Load config.ini into C++ database. Exported to Python via SWIG; - * invoked from m5.instantiate(). - */ -void -loadIniFile(PyObject *_resolveFunc) -{ - resolveFunc = _resolveFunc; - configStream = simout.find("config.out"); - - // The configuration database is now complete; start processing it. - inifile.load(simout.resolve("config.ini")); - - // Initialize statistics database - Stats::InitSimStats(); -} - - -/** - * Look up a MemObject port. Helper function for connectPorts(). - */ -Port * -lookupPort(SimObject *so, const std::string &name, int i) -{ - MemObject *mo = dynamic_cast<MemObject *>(so); - if (mo == NULL) { - warn("error casting SimObject %s to MemObject", so->name()); - return NULL; - } - - Port *p = mo->getPort(name, i); - if (p == NULL) - warn("error looking up port %s on object %s", name, so->name()); - return p; -} - - -/** - * Connect the described MemObject ports. Called from Python via SWIG. - */ -int -connectPorts(SimObject *o1, const std::string &name1, int i1, - SimObject *o2, const std::string &name2, int i2) -{ - Port *p1 = lookupPort(o1, name1, i1); - Port *p2 = lookupPort(o2, name2, i2); - - if (p1 == NULL || p2 == NULL) { - warn("connectPorts: port lookup error"); - return 0; - } - - p1->setPeer(p2); - p2->setPeer(p1); - - return 1; -} - -/** - * Do final initialization steps after object construction but before - * start of simulation. - */ -void -finalInit() -{ - // Parse and check all non-config-hierarchy parameters. - ParamContext::parseAllContexts(inifile); - ParamContext::checkAllContexts(); - - // Echo all parameter settings to stats file as well. - ParamContext::showAllContexts(*configStream); - - // Do a second pass to finish initializing the sim objects - SimObject::initAll(); - - // Restore checkpointed state, if any. -#if 0 - configHierarchy.unserializeSimObjects(); -#endif - - SimObject::regAllStats(); - - // Check to make sure that the stats package is properly initialized - Stats::check(); - - // Reset to put the stats in a consistent state. - Stats::reset(); - - SimStartup(); -} - - -/** Simulate for num_cycles additional cycles. If num_cycles is -1 - * (the default), do not limit simulation; some other event must - * terminate the loop. Exported to Python via SWIG. - * @return The SimLoopExitEvent that caused the loop to exit. - */ -SimLoopExitEvent * -simulate(Tick num_cycles = MaxTick) -{ - warn("Entering event queue @ %d. Starting simulation...\n", curTick); - - if (num_cycles < 0) - fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); - else if (curTick + num_cycles < 0) //Overflow - num_cycles = MaxTick; - else - num_cycles = curTick + num_cycles; - - Event *limit_event = schedExitSimLoop("simulate() limit reached", - num_cycles); - - while (1) { - // there should always be at least one event (the SimLoopExitEvent - // we just scheduled) in the queue - assert(!mainEventQueue.empty()); - assert(curTick <= mainEventQueue.nextTick() && - "event scheduled in the past"); - - // forward current cycle to the time of the first event on the - // queue - curTick = mainEventQueue.nextTick(); - Event *exit_event = mainEventQueue.serviceOne(); - if (exit_event != NULL) { - // hit some kind of exit event; return to Python - // event must be subclass of SimLoopExitEvent... - SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); - if (se_event == NULL) - panic("Bogus exit event class!"); - - // if we didn't hit limit_event, delete it - if (se_event != limit_event) { - assert(limit_event->scheduled()); - limit_event->deschedule(); - delete limit_event; - } - - return se_event; - } - - if (async_event) { - async_event = false; - if (async_dump) { - async_dump = false; - - using namespace Stats; - SetupEvent(Dump, curTick); - } - - if (async_dumpreset) { - async_dumpreset = false; - - using namespace Stats; - SetupEvent(Dump | Reset, curTick); - } - - if (async_exit) { - async_exit = false; - exitSimLoop("user interrupt received"); - } - - if (async_io || async_alarm) { - async_io = false; - async_alarm = false; - pollQueue.service(); - } - } - } - - // not reached... only exit is return on SimLoopExitEvent -} - -Event * -createCountedDrain() -{ - return new CountedDrainEvent(); -} - -void -cleanupCountedDrain(Event *counted_drain) -{ - CountedDrainEvent *event = - dynamic_cast<CountedDrainEvent *>(counted_drain); - if (event == NULL) { - fatal("Called cleanupCountedDrain() on an event that was not " - "a CountedDrainEvent."); - } - assert(event->getCount() == 0); - delete event; -} - -void -serializeAll(const std::string &cpt_dir) -{ - Serializable::serializeAll(cpt_dir); -} - -void -unserializeAll(const std::string &cpt_dir) -{ - Serializable::unserializeAll(cpt_dir); -} - -/** - * Queue of C++ callbacks to invoke on simulator exit. - */ -CallbackQueue& -exitCallbacks() -{ - static CallbackQueue theQueue; - return theQueue; -} - -/** - * Register an exit callback. - */ -void -registerExitCallback(Callback *callback) -{ - exitCallbacks().add(callback); -} - -BaseCPU * -convertToBaseCPUPtr(SimObject *obj) -{ - BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj); - - if (ptr == NULL) - warn("Casting to BaseCPU pointer failed"); - return ptr; -} - -System * -convertToSystemPtr(SimObject *obj) -{ - System *ptr = dynamic_cast<System *>(obj); - - if (ptr == NULL) - warn("Casting to System pointer failed"); - return ptr; -} - - -/** - * Do C++ simulator exit processing. Exported to SWIG to be invoked - * when simulator terminates via Python's atexit mechanism. - */ -void -doExitCleanup() -{ - exitCallbacks().process(); - exitCallbacks().clear(); - - cout.flush(); - - ParamContext::cleanupAllContexts(); - - // print simulation stats - Stats::DumpNow(); -} diff --git a/src/sim/param.cc b/src/sim/param.cc index 5cc69b161..51d389f5a 100644 --- a/src/sim/param.cc +++ b/src/sim/param.cc @@ -583,30 +583,10 @@ SimObjectBaseParam::parse(const string &s, vector<SimObject *>&value) // //////////////////////////////////////////////////////////////////////// -list<ParamContext *> *ParamContext::ctxList = NULL; - -ParamContext::ParamContext(const string &_iniSection, InitPhase _initPhase) +ParamContext::ParamContext(const string &_iniSection) : iniFilePtr(NULL), // initialized on call to parseParams() - iniSection(_iniSection), paramList(NULL), - initPhase(_initPhase) -{ - // Put this context on global list for initialization - if (initPhase != NoAutoInit) { - if (ctxList == NULL) - ctxList = new list<ParamContext *>(); - - // keep list sorted by ascending initPhase values - list<ParamContext *>::iterator i = ctxList->begin(); - list<ParamContext *>::iterator end = ctxList->end(); - for (; i != end; ++i) { - if (initPhase <= (*i)->initPhase) { - // found where we want to insert - break; - } - } - // (fall through case: insert at end) - ctxList->insert(i, this); - } + iniSection(_iniSection), paramList(NULL) +{ } @@ -695,89 +675,6 @@ ParamContext::printErrorProlog(ostream &os) os << "Parameter error in section [" << iniSection << "]: " << endl; } -// -// static method: call parseParams() on all registered contexts -// -void -ParamContext::parseAllContexts(IniFile &iniFile) -{ - list<ParamContext *>::iterator iter; - - for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) { - ParamContext *pc = *iter; - - pc->parseParams(iniFile); - } -} - - -// -// static method: call checkParams() on all registered contexts -// -void -ParamContext::checkAllContexts() -{ - list<ParamContext *>::iterator iter; - - for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) { - ParamContext *pc = *iter; - - pc->checkParams(); - } -} - - -// -// static method: call showParams() on all registered contexts -// -void -ParamContext::showAllContexts(ostream &os) -{ - list<ParamContext *>::iterator iter; - - for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) { - ParamContext *pc = *iter; - - os << "[" << pc->iniSection << "]" << endl; - pc->showParams(os); - os << endl; - } -} - - -// -// static method: call cleanup() on all registered contexts -// -void -ParamContext::cleanupAllContexts() -{ - list<ParamContext *>::iterator iter; - - for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) { - ParamContext *pc = *iter; - - pc->cleanup(); - } -} - - -// -// static method: call describeParams() on all registered contexts -// -void -ParamContext::describeAllContexts(ostream &os) -{ - list<ParamContext *>::iterator iter; - - for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) { - ParamContext *pc = *iter; - - os << "[" << pc->iniSection << "]\n"; - pc->describeParams(os); - os << endl; - } -} - void parseTime(const std::vector<int> &time, struct tm *tm) { diff --git a/src/sim/param.hh b/src/sim/param.hh index 8a4670e27..dff0fa72d 100644 --- a/src/sim/param.hh +++ b/src/sim/param.hh @@ -50,12 +50,6 @@ class SimObject; // class ParamContext : protected StartupCallback { - private: - - // static list of all ParamContext objects, built as a side effect - // of the ParamContext constructor - static std::list<ParamContext *> *ctxList; - protected: // .ini file (database) for parameter lookup... initialized on call @@ -78,31 +72,10 @@ class ParamContext : protected StartupCallback public: - /// Initialization phases for ParamContext objects. - enum InitPhase { - NoAutoInit = -1, ///< Don't initialize at all... params - /// will be parsed later (used by - /// SimObjectBuilder, which parses - /// params in SimObject::create(). - OutputInitPhase = 0, ///< Output stream initialization - TraceInitPhase = 1, ///< Trace context initialization: - /// depends on output streams, but - /// needs to come before others so we - /// can use tracing in other - /// ParamContext init code - StatsInitPhase = 2, ///< Stats output initialization - DefaultInitPhase = 3 ///< Everything else - }; - - /// Records the initialization phase for this ParamContext. - InitPhase initPhase; - /// Constructor. /// @param _iniSection Name of .ini section corresponding to this context. /// @param _initPhase Initialization phase (see InitPhase). - ParamContext(const std::string &_iniSection, - InitPhase _initPhase = DefaultInitPhase); - + ParamContext(const std::string &_iniSection); virtual ~ParamContext() {} // add a parameter to the context... called from the parameter @@ -135,24 +108,6 @@ class ParamContext : protected StartupCallback // generate the name for this instance of this context (used as a // prefix to create unique names in resolveSimObject() virtual const std::string &getInstanceName() { return iniSection; } - - // Parse all parameters registered with all ParamContext objects. - static void parseAllContexts(IniFile &iniFile); - - // Check all parameters registered with all ParamContext objects. - // (calls checkParams() on each) - static void checkAllContexts(); - - // Print all parameter values on indicated ostream. - static void showAllContexts(std::ostream &os); - - // Clean up all registered ParamContext objects. (calls cleanup() - // on each) - static void cleanupAllContexts(); - - // print descriptions of all parameters registered with all - // ParamContext objects - static void describeAllContexts(std::ostream &os); }; diff --git a/src/sim/process.cc b/src/sim/process.cc index e5d868115..2b283c9d1 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -60,6 +60,8 @@ #include "arch/sparc/solaris/process.hh" #elif THE_ISA == MIPS_ISA #include "arch/mips/linux/process.hh" +#elif THE_ISA == X86_ISA +#include "arch/x86/linux/process.hh" #else #error "THE_ISA not set" #endif @@ -300,24 +302,6 @@ DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process) //////////////////////////////////////////////////////////////////////// -void -copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr, - TranslatingPort* memPort) -{ - Addr data_ptr_swap; - for (int i = 0; i < strings.size(); ++i) { - data_ptr_swap = htog(data_ptr); - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, sizeof(Addr)); - memPort->writeString(data_ptr, strings[i].c_str()); - array_ptr += sizeof(Addr); - data_ptr += strings[i].size() + 1; - } - // add NULL terminator - data_ptr = 0; - - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(Addr)); -} - LiveProcess::LiveProcess(const string &nm, ObjectFile *_objFile, System *_system, int stdin_fd, int stdout_fd, int stderr_fd, @@ -475,14 +459,23 @@ LiveProcess::create(const std::string &nm, System *system, int stdin_fd, fatal("Unknown/unsupported operating system."); } #elif THE_ISA == SPARC_ISA - if (objFile->getArch() != ObjectFile::SPARC) + if (objFile->getArch() != ObjectFile::SPARC64 && objFile->getArch() != ObjectFile::SPARC32) fatal("Object file architecture does not match compiled ISA (SPARC)."); switch (objFile->getOpSys()) { case ObjectFile::Linux: - process = new SparcLinuxProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp, cwd, - _uid, _euid, _gid, _egid, _pid, _ppid); + if (objFile->getArch() == ObjectFile::SPARC64) { + process = new Sparc64LinuxProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, + _uid, _euid, _gid, + _egid, _pid, _ppid); + } else { + process = new Sparc32LinuxProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, + _uid, _euid, _gid, + _egid, _pid, _ppid); + } break; @@ -495,6 +488,20 @@ LiveProcess::create(const std::string &nm, System *system, int stdin_fd, default: fatal("Unknown/unsupported operating system."); } +#elif THE_ISA == X86_ISA + if (objFile->getArch() != ObjectFile::X86) + fatal("Object file architecture does not match compiled ISA (x86)."); + switch (objFile->getOpSys()) { + case ObjectFile::Linux: + process = new X86LinuxProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, + _uid, _euid, _gid, + _egid, _pid, _ppid); + break; + default: + fatal("Unknown/unsupported operating system."); + } #elif THE_ISA == MIPS_ISA if (objFile->getArch() != ObjectFile::Mips) fatal("Object file architecture does not match compiled ISA (MIPS)."); diff --git a/src/sim/process.hh b/src/sim/process.hh index bf65c6e06..dd64fa607 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -41,9 +41,12 @@ #if !FULL_SYSTEM +#include <string> #include <vector> #include "base/statistics.hh" +#include "mem/translating_port.hh" +#include "sim/host.hh" #include "sim/sim_object.hh" class ThreadContext; @@ -57,9 +60,27 @@ namespace TheISA class RemoteGDB; } +//This needs to be templated for cases where 32 bit pointers are needed. +template<class AddrType> void -copyStringArray(std::vector<std::string> &strings, Addr array_ptr, - Addr data_ptr, TranslatingPort* memPort); +copyStringArray(std::vector<std::string> &strings, + AddrType array_ptr, AddrType data_ptr, + TranslatingPort* memPort) +{ + AddrType data_ptr_swap; + for (int i = 0; i < strings.size(); ++i) { + data_ptr_swap = htog(data_ptr); + memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, + sizeof(AddrType)); + memPort->writeString(data_ptr, strings[i].c_str()); + array_ptr += sizeof(AddrType); + data_ptr += strings[i].size() + 1; + } + // add NULL terminator + data_ptr = 0; + + memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType)); +} class Process : public SimObject { diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 4a8c0eb66..56a779674 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -32,6 +32,7 @@ #include <fcntl.h> #include <unistd.h> +#include <fstream> #include <string> #include "arch/vtophys.hh" @@ -54,7 +55,7 @@ using namespace std; using namespace Stats; using namespace TheISA; -namespace AlphaPseudo +namespace PseudoInst { void arm(ThreadContext *tc) @@ -199,8 +200,7 @@ namespace AlphaPseudo Tick when = curTick + delay * Clock::Int::ns; Tick repeat = period * Clock::Int::ns; - using namespace Stats; - SetupEvent(Reset, when, repeat); + Stats::StatEvent(false, true, when, repeat); } void @@ -213,8 +213,7 @@ namespace AlphaPseudo Tick when = curTick + delay * Clock::Int::ns; Tick repeat = period * Clock::Int::ns; - using namespace Stats; - SetupEvent(Dump, when, repeat); + Stats::StatEvent(true, false, when, repeat); } void @@ -254,8 +253,7 @@ namespace AlphaPseudo Tick when = curTick + delay * Clock::Int::ns; Tick repeat = period * Clock::Int::ns; - using namespace Stats; - SetupEvent(Dump|Reset, when, repeat); + Stats::StatEvent(true, true, when, repeat); } void diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index bc71a7e64..93021abad 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -33,7 +33,7 @@ class ThreadContext; //We need the "Tick" and "Addr" data types from here #include "sim/host.hh" -namespace AlphaPseudo +namespace PseudoInst { /** * @todo these externs are only here for a hack in fullCPU::takeOver... diff --git a/src/sim/root.cc b/src/sim/root.cc index 565b57269..f4743af0a 100644 --- a/src/sim/root.cc +++ b/src/sim/root.cc @@ -36,91 +36,24 @@ #include <vector> #include "base/misc.hh" -#include "base/output.hh" #include "sim/builder.hh" -#include "sim/host.hh" -#include "sim/sim_events.hh" -#include "sim/sim_exit.hh" #include "sim/sim_object.hh" -#include "sim/root.hh" - -using namespace std; - -Tick curTick = 0; -ostream *outputStream; -ostream *configStream; - -/// The simulated frequency of curTick. (This is only here for a short time) -Tick ticksPerSecond; - -namespace Clock { -/// The simulated frequency of curTick. (In ticks per second) -Tick Frequency; - -namespace Float { -double s; -double ms; -double us; -double ns; -double ps; - -double Hz; -double kHz; -double MHz; -double GHZ; -/* namespace Float */ } - -namespace Int { -Tick s; -Tick ms; -Tick us; -Tick ns; -Tick ps; -/* namespace Float */ } - -/* namespace Clock */ } - // Dummy Object -class Root : public SimObject +struct Root : public SimObject { - private: - Tick max_tick; - Tick progress_interval; - - public: - Root(const std::string &name, Tick maxtick, Tick pi) - : SimObject(name), max_tick(maxtick), progress_interval(pi) - {} - - virtual void startup(); + Root(const std::string &name) : SimObject(name) {} }; -void -Root::startup() -{ - if (max_tick != 0) - schedExitSimLoop("reached maximum cycle count", curTick + max_tick); - - if (progress_interval != 0) - new ProgressEvent(&mainEventQueue, progress_interval); -} - BEGIN_DECLARE_SIM_OBJECT_PARAMS(Root) - Param<Tick> clock; - Param<Tick> max_tick; - Param<Tick> progress_interval; - Param<string> output_file; + Param<int> dummy; // needed below END_DECLARE_SIM_OBJECT_PARAMS(Root) BEGIN_INIT_SIM_OBJECT_PARAMS(Root) - INIT_PARAM(clock, "tick frequency"), - INIT_PARAM(max_tick, "maximum simulation time"), - INIT_PARAM(progress_interval, "print a progress message"), - INIT_PARAM(output_file, "file to dump simulator output to") + INIT_PARAM(dummy, "") // All SimObjects must have params END_INIT_SIM_OBJECT_PARAMS(Root) @@ -132,29 +65,7 @@ CREATE_SIM_OBJECT(Root) created = true; - outputStream = simout.find(output_file); - Root *root = new Root(getInstanceName(), max_tick, progress_interval); - - using namespace Clock; - Frequency = clock; - Float::s = static_cast<double>(Frequency); - Float::ms = Float::s / 1.0e3; - Float::us = Float::s / 1.0e6; - Float::ns = Float::s / 1.0e9; - Float::ps = Float::s / 1.0e12; - - Float::Hz = 1.0 / Float::s; - Float::kHz = 1.0 / Float::ms; - Float::MHz = 1.0 / Float::us; - Float::GHZ = 1.0 / Float::ns; - - Int::s = Frequency; - Int::ms = Int::s / 1000; - Int::us = Int::ms / 1000; - Int::ns = Int::us / 1000; - Int::ps = Int::ns / 1000; - - return root; + return new Root(getInstanceName()); } REGISTER_SIM_OBJECT("Root", Root) diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index 1ff16976d..d32bb1142 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -407,36 +407,3 @@ Checkpoint::sectionExists(const std::string §ion) { return db->sectionExists(section); } - -/** Hacked stat reset event */ - -class StatresetParamContext : public ParamContext -{ - public: - StatresetParamContext(const string §ion); - ~StatresetParamContext(); - void startup(); -}; - -StatresetParamContext statParams("statsreset"); - -Param<Tick> reset_cycle(&statParams, "reset_cycle", - "Cycle to reset stats on", 0); - -StatresetParamContext::StatresetParamContext(const string §ion) - : ParamContext(section) -{ } - -StatresetParamContext::~StatresetParamContext() -{ -} - -void -StatresetParamContext::startup() -{ - if (reset_cycle > 0) { - Stats::SetupEvent(Stats::Reset, curTick + reset_cycle, 0); - cprintf("Stats reset event scheduled for %lli\n", - curTick + reset_cycle); - } -} diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc index 2ccc9dad2..a4457a11c 100644 --- a/src/sim/sim_events.cc +++ b/src/sim/sim_events.cc @@ -158,21 +158,3 @@ CheckSwapEvent::description() { return "check swap"; } - -// -// handle progress event: print message and reschedule -// -void -ProgressEvent::process() -{ - DPRINTFN("ProgressEvent\n"); - // reschedule for next interval - schedule(curTick + interval); -} - - -const char * -ProgressEvent::description() -{ - return "progress message"; -} diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh index e1576b38c..94e2540b1 100644 --- a/src/sim/sim_events.hh +++ b/src/sim/sim_events.hh @@ -125,23 +125,4 @@ class CheckSwapEvent : public Event virtual const char *description(); }; -// -// Progress event: print out cycle every so often so we know we're -// making forward progress. -// -class ProgressEvent : public Event -{ - protected: - Tick interval; - - public: - ProgressEvent(EventQueue *q, Tick ival) - : Event(q), interval(ival) - { schedule(curTick + interval); } - - void process(); // process event - - virtual const char *description(); -}; - #endif // __SIM_SIM_EVENTS_HH__ diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc index 8fc8fe58f..434fcffe6 100644 --- a/src/sim/sim_object.cc +++ b/src/sim/sim_object.cc @@ -56,10 +56,6 @@ using namespace std; // SimObject::SimObjectList SimObject::simObjectList; -namespace Stats { - extern ObjectMatch event_ignore; -} - // // SimObject constructor: used to maintain static simObjectList // @@ -70,7 +66,6 @@ SimObject::SimObject(Params *p) doDebugBreak = false; #endif - doRecordEvent = !Stats::event_ignore.match(name()); simObjectList.push_back(this); state = Running; } @@ -86,7 +81,6 @@ SimObject::SimObject(const string &_name) doDebugBreak = false; #endif - doRecordEvent = !Stats::event_ignore.match(name()); simObjectList.push_back(this); state = Running; } @@ -245,8 +239,7 @@ debugObjectBreak(const char *objs) void SimObject::recordEvent(const std::string &stat) { - if (doRecordEvent) - Stats::recordEvent(stat); + Stats::recordEvent(stat); } unsigned int diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh index 93802e247..536e761e5 100644 --- a/src/sim/sim_object.hh +++ b/src/sim/sim_object.hh @@ -136,7 +136,6 @@ class SimObject : public Serializable, protected StartupCallback #endif public: - bool doRecordEvent; void recordEvent(const std::string &stat); }; diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc new file mode 100644 index 000000000..55cbb50a9 --- /dev/null +++ b/src/sim/simulate.cc @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#include "base/misc.hh" +#include "base/pollevent.hh" +#include "sim/stat_control.hh" +#include "sim/async.hh" +#include "sim/eventq.hh" +#include "sim/host.hh" +#include "sim/sim_events.hh" +#include "sim/sim_exit.hh" +#include "sim/simulate.hh" + +/** Simulate for num_cycles additional cycles. If num_cycles is -1 + * (the default), do not limit simulation; some other event must + * terminate the loop. Exported to Python via SWIG. + * @return The SimLoopExitEvent that caused the loop to exit. + */ +SimLoopExitEvent * +simulate(Tick num_cycles) +{ + warn("Entering event queue @ %d. Starting simulation...\n", curTick); + + if (num_cycles < 0) + fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); + else if (curTick + num_cycles < 0) //Overflow + num_cycles = MaxTick; + else + num_cycles = curTick + num_cycles; + + Event *limit_event; + limit_event = schedExitSimLoop("simulate() limit reached", num_cycles); + + while (1) { + // there should always be at least one event (the SimLoopExitEvent + // we just scheduled) in the queue + assert(!mainEventQueue.empty()); + assert(curTick <= mainEventQueue.nextTick() && + "event scheduled in the past"); + + // forward current cycle to the time of the first event on the + // queue + curTick = mainEventQueue.nextTick(); + Event *exit_event = mainEventQueue.serviceOne(); + if (exit_event != NULL) { + // hit some kind of exit event; return to Python + // event must be subclass of SimLoopExitEvent... + SimLoopExitEvent *se_event; + se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); + + if (se_event == NULL) + panic("Bogus exit event class!"); + + // if we didn't hit limit_event, delete it + if (se_event != limit_event) { + assert(limit_event->scheduled()); + limit_event->deschedule(); + delete limit_event; + } + + return se_event; + } + + if (async_event) { + async_event = false; + if (async_statdump || async_statreset) { + async_statdump = false; + async_statreset = false; + + Stats::StatEvent(async_statdump, async_statreset); + } + + if (async_exit) { + async_exit = false; + exitSimLoop("user interrupt received"); + } + + if (async_io || async_alarm) { + async_io = false; + async_alarm = false; + pollQueue.service(); + } + + if (async_exception) { + async_exception = false; + return NULL; + } + } + } + + // not reached... only exit is return on SimLoopExitEvent +} + diff --git a/src/sim/simulate.hh b/src/sim/simulate.hh new file mode 100644 index 000000000..139bddb82 --- /dev/null +++ b/src/sim/simulate.hh @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#include "sim/host.hh" +#include "sim/sim_events.hh" + +SimLoopExitEvent *simulate(Tick num_cycles = MaxTick); diff --git a/src/sim/stat_control.cc b/src/sim/stat_control.cc index 3fad8beb5..228c83898 100644 --- a/src/sim/stat_control.cc +++ b/src/sim/stat_control.cc @@ -38,14 +38,9 @@ #include "base/callback.hh" #include "base/hostinfo.hh" #include "base/statistics.hh" -#include "base/str.hh" #include "base/time.hh" -#include "base/stats/output.hh" #include "cpu/base.hh" #include "sim/eventq.hh" -#include "sim/sim_object.hh" -#include "sim/stat_control.hh" -#include "sim/root.hh" using namespace std; @@ -63,11 +58,9 @@ namespace Stats { Time statTime(true); Tick startTick; -Tick lastDump(0); -class SimTicksReset : public Callback +struct SimTicksReset : public Callback { - public: void process() { statTime.set(); @@ -92,7 +85,7 @@ statElapsedTicks() SimTicksReset simTicksReset; void -InitSimStats() +initSimStats() { simInsts .functor(BaseCPU::numSimulatedInstructions) @@ -153,81 +146,40 @@ InitSimStats() registerResetCallback(&simTicksReset); } -class StatEvent : public Event +class _StatEvent : public Event { - protected: - int flags; + private: + bool dump; + bool reset; Tick repeat; public: - StatEvent(EventQueue *queue, int _flags, Tick _when, Tick _repeat); - virtual void process(); - virtual const char *description(); -}; - -StatEvent::StatEvent(EventQueue *queue, int _flags, Tick _when, Tick _repeat) - : Event(queue, Stat_Event_Pri), - flags(_flags), repeat(_repeat) -{ - setFlags(AutoDelete); - schedule(_when); -} - -const char * -StatEvent::description() -{ - return "Statistics dump and/or reset"; -} - -void -StatEvent::process() -{ - if (flags & Stats::Dump) - DumpNow(); - - if (flags & Stats::Reset) { - cprintf("Resetting stats at cycle %d!\n", curTick); - reset(); + _StatEvent(bool _dump, bool _reset, Tick _when, Tick _repeat) + : Event(&mainEventQueue, Stat_Event_Pri), dump(_dump), reset(_reset), + repeat(_repeat) + { + setFlags(AutoDelete); + schedule(_when); } - if (repeat) - schedule(curTick + repeat); -} + virtual void + process() + { + if (dump) + Stats::dump(); -list<Output *> OutputList; + if (reset) + Stats::reset(); -void -DumpNow() -{ - assert(lastDump <= curTick); - if (lastDump == curTick) - return; - lastDump = curTick; - - list<Output *>::iterator i = OutputList.begin(); - list<Output *>::iterator end = OutputList.end(); - for (; i != end; ++i) { - Output *output = *i; - if (!output->valid()) - continue; - - output->output(); + if (repeat) + new _StatEvent(dump, reset, curTick + repeat, repeat); } -} +}; void -SetupEvent(int flags, Tick when, Tick repeat, EventQueue *queue) +StatEvent(bool dump, bool reset, Tick when, Tick repeat) { - if (queue == NULL) - queue = &mainEventQueue; - - new StatEvent(queue, flags, when, repeat); + new _StatEvent(dump, reset, when, repeat); } /* namespace Stats */ } - -void debugDumpStats() -{ - Stats::DumpNow(); -} - diff --git a/src/sim/stat_control.hh b/src/sim/stat_control.hh index 67f7cc491..1efa2554e 100644 --- a/src/sim/stat_control.hh +++ b/src/sim/stat_control.hh @@ -31,25 +31,10 @@ #ifndef __SIM_STAT_CONTROL_HH__ #define __SIM_STAT_CONTROL_HH__ -#include <fstream> -#include <list> - -class EventQueue; - namespace Stats { -enum { - Reset = 0x1, - Dump = 0x2 -}; - -class Output; -extern std::list<Output *> OutputList; - -void DumpNow(); -void SetupEvent(int flags, Tick when, Tick repeat = 0, EventQueue *queue = NULL); - -void InitSimStats(); +void initSimStats(); +void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0); /* namespace Stats */ } diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index ab44c0a35..876f39e99 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -184,6 +184,39 @@ lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn +_llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) +{ + int fd = p->sim_fd(tc->getSyscallArg(0)); + uint64_t offset_high = tc->getSyscallArg(1); + uint32_t offset_low = tc->getSyscallArg(2); + Addr result_ptr = tc->getSyscallArg(3); + int whence = tc->getSyscallArg(4); + + uint64_t offset = (offset_high << 32) | offset_low; + + uint64_t result = lseek(fd, offset, whence); + result = TheISA::htog(result); + + if (result == (off_t)-1) { + //The seek failed. + return -errno; + } else { + //The seek succeeded. + //Copy "result" to "result_ptr" + //XXX We'll assume that the size of loff_t is 64 bits on the + //target platform + BufferArg result_buf(result_ptr, sizeof(result)); + memcpy(result_buf.bufferPtr(), &result, sizeof(result)); + result_buf.copyOut(tc->getMemPort()); + return 0; + } + + + return (result == (off_t)-1) ? -errno : result; +} + + +SyscallReturn munmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { // given that we don't really implement mmap, munmap is really easy diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 27356c9f1..a3d95b8ec 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -211,6 +211,10 @@ SyscallReturn writeFunc(SyscallDesc *desc, int num, SyscallReturn lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); +/// Target _llseek() handler. +SyscallReturn _llseekFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); + /// Target munmap() handler. SyscallReturn munmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); @@ -349,6 +353,8 @@ template <typename target_stat, typename host_stat> static void convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) { + using namespace TheISA; + if (fakeTTY) tgt->st_dev = 0xA; else @@ -377,7 +383,9 @@ convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) tgt->st_mtimeX = htog(tgt->st_mtimeX); tgt->st_ctimeX = host->st_ctime; tgt->st_ctimeX = htog(tgt->st_ctimeX); - tgt->st_blksize = host->st_blksize; + // Force the block size to be 8k. This helps to ensure buffered io works + // consistently across different hosts. + tgt->st_blksize = 0x2000; tgt->st_blksize = htog(tgt->st_blksize); tgt->st_blocks = host->st_blocks; tgt->st_blocks = htog(tgt->st_blocks); @@ -389,6 +397,8 @@ template <typename target_stat, typename host_stat64> static void convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) { + using namespace TheISA; + convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); #if defined(STAT_HAVE_NSEC) tgt->st_atime_nsec = host->st_atime_nsec; @@ -446,14 +456,14 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } switch (req) { - case OS::TIOCISATTY: - case OS::TIOCGETP: - case OS::TIOCSETP: - case OS::TIOCSETN: - case OS::TIOCSETC: - case OS::TIOCGETC: - case OS::TIOCGETS: - case OS::TIOCGETA: + case OS::TIOCISATTY_: + case OS::TIOCGETP_: + case OS::TIOCSETP_: + case OS::TIOCSETN_: + case OS::TIOCSETC_: + case OS::TIOCGETC_: + case OS::TIOCGETS_: + case OS::TIOCGETA_: return -ENOTTY; default: diff --git a/src/sim/system.cc b/src/sim/system.cc index f6febe4b1..2d0eaaf5b 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -33,6 +33,7 @@ #include "arch/isa_traits.hh" #include "arch/remote_gdb.hh" +#include "arch/utility.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" #include "base/trace.hh" @@ -142,6 +143,7 @@ System::~System() } int rgdb_wait = -1; +int rgdb_enable = true; void System::setMemoryMode(MemoryMode mode) @@ -152,7 +154,9 @@ System::setMemoryMode(MemoryMode mode) bool System::breakpoint() { - return remoteGDB[0]->breakpoint(); + if (remoteGDB.size()) + return remoteGDB[0]->breakpoint(); + return false; } int @@ -174,22 +178,24 @@ System::registerThreadContext(ThreadContext *tc, int id) threadContexts[id] = tc; numcpus++; - RemoteGDB *rgdb = new RemoteGDB(this, tc); - GDBListener *gdbl = new GDBListener(rgdb, 7000 + id); - gdbl->listen(); - /** - * Uncommenting this line waits for a remote debugger to connect - * to the simulator before continuing. - */ - if (rgdb_wait != -1 && rgdb_wait == id) - gdbl->accept(); + if (rgdb_enable) { + RemoteGDB *rgdb = new RemoteGDB(this, tc); + GDBListener *gdbl = new GDBListener(rgdb, 7000 + id); + gdbl->listen(); + /** + * Uncommenting this line waits for a remote debugger to + * connect to the simulator before continuing. + */ + if (rgdb_wait != -1 && rgdb_wait == id) + gdbl->accept(); + + if (remoteGDB.size() <= id) { + remoteGDB.resize(id + 1); + } - if (remoteGDB.size() <= id) { - remoteGDB.resize(id + 1); + remoteGDB[id] = rgdb; } - remoteGDB[id] = rgdb; - return id; } @@ -198,7 +204,7 @@ System::startup() { int i; for (i = 0; i < threadContexts.size(); i++) - threadContexts[i]->activate(0); + TheISA::startupCPU(threadContexts[i], i); } void @@ -210,7 +216,8 @@ System::replaceThreadContext(ThreadContext *tc, int id) } threadContexts[id] = tc; - remoteGDB[id]->replaceThreadContext(tc); + if (id < remoteGDB.size()) + remoteGDB[id]->replaceThreadContext(tc); } #if !FULL_SYSTEM diff --git a/src/unittest/Makefile b/src/unittest/Makefile index e22b80b48..e6a621a9e 100644 --- a/src/unittest/Makefile +++ b/src/unittest/Makefile @@ -56,6 +56,9 @@ circletest: unittest/circletest.cc base/circlebuf.cc cprintftest: unittest/cprintftest.cc base/cprintf.cc $(CXX) $(CCFLAGS) -o $@ $^ +cprintftime: unittest/cprintftime.cc base/cprintf.cc + $(CXX) $(CCFLAGS) -o $@ $^ + initest: unittest/initest.cc base/str.cc base/inifile.cc base/cprintf.cc $(CXX) $(CCFLAGS) -o $@ $^ diff --git a/src/unittest/cprintftime.cc b/src/unittest/cprintftime.cc new file mode 100644 index 000000000..f35e0aa25 --- /dev/null +++ b/src/unittest/cprintftime.cc @@ -0,0 +1,90 @@ +/* + * 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 + */ + +#include <iostream> +#include <list> +#include <string> +#include <sstream> + +#include "base/cprintf.hh" + +using namespace std; + +volatile int stop = false; + +void +handle_alarm(int signal) +{ + stop = true; +} + +void +do_test(int seconds) +{ + stop = false; + alarm(seconds); +} + +int +main() +{ + stringstream result; + int iterations = 0; + + signal(SIGALRM, handle_alarm); + + do_test(10); + while (!stop) { + stringstream result; + ccprintf(result, + "this is a %s of %d iterations %3.2f %#x\n", + "test", iterations, 51.934, &result); + + iterations += 1; + } + + cprintf("completed %d iterations of ccprintf in 10s, %f iterations/s\n", + iterations, iterations / 10.0); + + do_test(10); + while (!stop) { + char result[1024]; + sprintf(result, + "this is a %s of %d iterations %3.2f %#x\n", + "test", iterations, 51.934, &result); + + iterations += 1; + } + + cprintf("completed %d iterations of sprintf in 10s, %f iterations/s\n", + iterations, iterations / 10.0); + + return 0; +} |