From: Gabe Black Date: Thu, 9 Mar 2006 23:35:28 +0000 (-0500) Subject: Hand merge. Stuff probably doesn't compile. X-Git-Tag: m5_2.0_beta1~207 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=872bbdfc33cb82bf32576db3a57d3055a04acbac;p=gem5.git Hand merge. Stuff probably doesn't compile. --HG-- rename : arch/alpha/isa_desc => arch/alpha/isa/main.isa rename : arch/alpha/alpha_linux_process.cc => arch/alpha/linux/process.cc rename : arch/alpha/alpha_linux_process.hh => arch/alpha/linux/process.hh rename : arch/alpha/alpha_tru64_process.cc => arch/alpha/tru64/process.cc rename : arch/alpha/alpha_tru64_process.hh => arch/alpha/tru64/process.hh rename : cpu/exec_context.cc => cpu/cpu_exec_context.cc rename : cpu/exec_context.hh => cpu/cpu_exec_context.hh extra : convert_revision : 7d1efcedd708815d985a951f6f010fbd83dc27e8 --- 872bbdfc33cb82bf32576db3a57d3055a04acbac diff --cc SConscript index 1c13a9307,8afac510b..3a141a7d2 --- a/SConscript +++ b/SConscript @@@ -84,9 -81,9 +81,9 @@@ base_sources = Split('' base/stats/text.cc cpu/base.cc - cpu/exec_context.cc - cpu/base_dyn_inst.cc + cpu/cpu_exec_context.cc cpu/exetrace.cc + cpu/op_class.cc cpu/pc_event.cc cpu/static_inst.cc cpu/sampler/sampler.cc @@@ -177,32 -204,6 +156,17 @@@ full_cpu_sources = Split('' encumbered/cpu/full/iq/standard/iq_standard.cc ''') - o3_cpu_sources = Split(''' - arch/alpha/alpha_o3_exec.cc - cpu/o3/2bit_local_pred.cc - cpu/o3/alpha_dyn_inst.cc - cpu/o3/alpha_cpu.cc - cpu/o3/alpha_cpu_builder.cc - cpu/o3/bpred_unit.cc - cpu/o3/btb.cc - cpu/o3/commit.cc - cpu/o3/decode.cc - cpu/o3/fetch.cc - cpu/o3/free_list.cc - cpu/o3/cpu.cc - cpu/o3/iew.cc - cpu/o3/inst_queue.cc - cpu/o3/ldstq.cc - cpu/o3/mem_dep_unit.cc - cpu/o3/ras.cc - cpu/o3/rename.cc - cpu/o3/rename_map.cc - cpu/o3/rob.cc - cpu/o3/sat_counter.cc - cpu/o3/store_set.cc - cpu/o3/tournament_pred.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 @@@ -266,9 -258,12 +221,9 @@@ full_system_sources = Split('' kern/tru64/printf.cc kern/tru64/tru64_events.cc kern/tru64/tru64_syscalls.cc - kern/tru64/tru64_system.cc mem/functional/memory_control.cc - mem/functional/physical.cc - - sim/system.cc + sim/pseudo_inst.cc ''') # turbolaser encumbered sources @@@ -293,51 -288,32 +248,39 @@@ turbolaser_sources = Split('' # Syscall emulation (non-full-system) sources syscall_emulation_sources = Split(''' - arch/alpha/alpha_common_syscall_emul.cc - arch/alpha/alpha_linux_process.cc - arch/alpha/alpha_tru64_process.cc - cpu/memtest/memtest.cc - encumbered/eio/eio.cc + encumbered/eio/exolex.cc encumbered/eio/libexo.cc + kern/linux/linux.cc + kern/tru64/tru64.cc sim/process.cc sim/syscall_emul.cc ''') +eio_sources = Split(''' + encumbered/eio/eio.cc + ''') + +memtest_sources = Split(''' + cpu/memtest/memtest.cc + ''') + - targetarch_files = Split(''' - alpha_common_syscall_emul.hh - alpha_linux_process.hh - alpha_memory.hh - alpha_tru64_process.hh - aout_machdep.h - arguments.hh - byte_swap.hh - ecoff_machdep.h - ev5.hh - faults.hh - isa_fullsys_traits.hh - isa_traits.hh - osfpal.hh - pseudo_inst.hh - stacktrace.hh - vptr.hh - vtophys.hh - ''') + # Add a flag defining what THE_ISA should be for all compilation + env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) - for f in targetarch_files: - env.Command('targetarch/' + f, 'arch/alpha/' + f, - '''echo '#include "arch/alpha/%s"' > $TARGET''' % f) + arch_sources = SConscript('arch/SConscript', + exports = 'env', duplicate = False) + cpu_sources = SConscript('cpu/SConscript', + exports = 'env', duplicate = False) + + # This is outside of cpu/SConscript since the source directory isn't + # underneath 'cpu'. + if 'FullCPU' in env['CPU_MODELS']: + cpu_sources += full_cpu_sources # Set up complete list of sources based on configuration. - sources = base_sources + simple_cpu_sources + sources = base_sources + arch_sources + cpu_sources if env['FULL_SYSTEM']: sources += full_system_sources diff --cc arch/alpha/isa/main.isa index 000000000,17c9989ab..d4c744fbc mode 000000,100644..100644 --- a/arch/alpha/isa/main.isa +++ b/arch/alpha/isa/main.isa @@@ -1,0 -1,448 +1,448 @@@ + // -*- mode:c++ -*- + + // 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. + + output header {{ + #include + #include + #include + + #include "config/ss_compatible_fp.hh" + #include "cpu/static_inst.hh" + #include "arch/alpha/faults.hh" -#include "mem/mem_req.hh" // some constructors use MemReq flags ++#include "mem/request.hh" // some constructors use MemReq flags + }}; + + output decoder {{ + #include "base/cprintf.hh" + #include "base/fenv.hh" + #include "base/loader/symtab.hh" + #include "config/ss_compatible_fp.hh" + #include "cpu/exec_context.hh" // for Jump::branchTarget() + + #include + + using namespace AlphaISA; + }}; + + output exec {{ + #include + + #if FULL_SYSTEM + #include "sim/pseudo_inst.hh" + #endif + #include "base/fenv.hh" + #include "config/ss_compatible_fp.hh" + #include "cpu/base.hh" + #include "cpu/exetrace.hh" + #include "sim/sim_exit.hh" + + using namespace AlphaISA; + }}; + + //////////////////////////////////////////////////////////////////// + // + // Namespace statement. Everything below this line will be in the + // AlphaISAInst namespace. + // + + + namespace AlphaISA; + + //////////////////////////////////////////////////////////////////// + // + // Bitfield definitions. + // + + // Universal (format-independent) fields + def bitfield PALMODE <32:32>; + def bitfield OPCODE <31:26>; + def bitfield RA <25:21>; + def bitfield RB <20:16>; + + // Memory format + def signed bitfield MEMDISP <15: 0>; // displacement + def bitfield MEMFUNC <15: 0>; // function code (same field, unsigned) + + // Memory-format jumps + def bitfield JMPFUNC <15:14>; // function code (disp<15:14>) + def bitfield JMPHINT <13: 0>; // tgt Icache idx hint (disp<13:0>) + + // Branch format + def signed bitfield BRDISP <20: 0>; // displacement + + // Integer operate format(s>; + def bitfield INTIMM <20:13>; // integer immediate (literal) + def bitfield IMM <12:12>; // immediate flag + def bitfield INTFUNC <11: 5>; // function code + def bitfield RC < 4: 0>; // dest reg + + // Floating-point operate format + def bitfield FA <25:21>; + def bitfield FB <20:16>; + def bitfield FP_FULLFUNC <15: 5>; // complete function code + def bitfield FP_TRAPMODE <15:13>; // trapping mode + def bitfield FP_ROUNDMODE <12:11>; // rounding mode + def bitfield FP_TYPEFUNC <10: 5>; // type+func: handiest for decoding + def bitfield FP_SRCTYPE <10: 9>; // source reg type + def bitfield FP_SHORTFUNC < 8: 5>; // short function code + def bitfield FP_SHORTFUNC_TOP2 <8:7>; // top 2 bits of short func code + def bitfield FC < 4: 0>; // dest reg + + // PALcode format + def bitfield PALFUNC <25: 0>; // function code + + // EV5 PAL instructions: + // HW_LD/HW_ST + def bitfield HW_LDST_PHYS <15>; // address is physical + def bitfield HW_LDST_ALT <14>; // use ALT_MODE IPR + def bitfield HW_LDST_WRTCK <13>; // HW_LD only: fault if no write acc + def bitfield HW_LDST_QUAD <12>; // size: 0=32b, 1=64b + def bitfield HW_LDST_VPTE <11>; // HW_LD only: is PTE fetch + def bitfield HW_LDST_LOCK <10>; // HW_LD only: is load locked + def bitfield HW_LDST_COND <10>; // HW_ST only: is store conditional + def signed bitfield HW_LDST_DISP <9:0>; // signed displacement + + // HW_REI + def bitfield HW_REI_TYP <15:14>; // type: stalling vs. non-stallingk + def bitfield HW_REI_MBZ <13: 0>; // must be zero + + // HW_MTPR/MW_MFPR + def bitfield HW_IPR_IDX <15:0>; // IPR index + + // M5 instructions + def bitfield M5FUNC <7:0>; + + def operand_types {{ + 'sb' : ('signed int', 8), + 'ub' : ('unsigned int', 8), + 'sw' : ('signed int', 16), + 'uw' : ('unsigned int', 16), + 'sl' : ('signed int', 32), + 'ul' : ('unsigned int', 32), + 'sq' : ('signed int', 64), + 'uq' : ('unsigned int', 64), + 'sf' : ('float', 32), + 'df' : ('float', 64) + }}; + + def operands {{ + # Int regs default to unsigned, but code should not count on this. + # For clarity, descriptions that depend on unsigned behavior should + # explicitly specify '.uq'. + 'Ra': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RA] : RA', + 'IsInteger', 1), + 'Rb': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RB] : RB', + 'IsInteger', 2), + 'Rc': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RC] : RC', + 'IsInteger', 3), + 'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1), + 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2), + 'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3), + 'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), + 'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4), + 'Runiq': ('ControlReg', 'uq', 'TheISA::Uniq_DepTag', None, 1), + 'FPCR': (' ControlReg', 'uq', 'TheISA::Fpcr_DepTag', None, 1), + # The next two are hacks for non-full-system call-pal emulation + 'R0': ('IntReg', 'uq', '0', None, 1), + 'R16': ('IntReg', 'uq', '16', None, 1), + 'R17': ('IntReg', 'uq', '17', None, 1), + 'R18': ('IntReg', 'uq', '18', None, 1) + }}; + + //////////////////////////////////////////////////////////////////// + // + // Basic instruction classes/templates/formats etc. + // + + output header {{ + // uncomment the following to get SimpleScalar-compatible disassembly + // (useful for diffing output traces). + // #define SS_COMPATIBLE_DISASSEMBLY + + /** + * Base class for all Alpha static instructions. + */ + class AlphaStaticInst : public StaticInst + { + protected: + + /// Make AlphaISA register dependence tags directly visible in + /// this class and derived classes. Maybe these should really + /// live here and not in the AlphaISA namespace. + enum DependenceTags { + FP_Base_DepTag = AlphaISA::FP_Base_DepTag, + Fpcr_DepTag = AlphaISA::Fpcr_DepTag, + Uniq_DepTag = AlphaISA::Uniq_DepTag, + Lock_Flag_DepTag = AlphaISA::Lock_Flag_DepTag, + Lock_Addr_DepTag = AlphaISA::Lock_Addr_DepTag, + IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag + }; + + /// Constructor. + AlphaStaticInst(const char *mnem, ExtMachInst _machInst, + OpClass __opClass) + : StaticInst(mnem, _machInst, __opClass) + { + } + + /// Print a register name for disassembly given the unique + /// dependence tag number (FP or int). + void printReg(std::ostream &os, int reg) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + }}; + + output decoder {{ + void + AlphaStaticInst::printReg(std::ostream &os, int reg) const + { + if (reg < FP_Base_DepTag) { + ccprintf(os, "r%d", reg); + } + else { + ccprintf(os, "f%d", reg - FP_Base_DepTag); + } + } + + std::string + AlphaStaticInst::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // just print the first two source regs... if there's + // a third one, it's a read-modify-write dest (Rc), + // e.g. for CMOVxx + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + if (_numSrcRegs > 1) { + ss << ","; + printReg(ss, _srcRegIdx[1]); + } + + // just print the first dest... if there's a second one, + // it's generally implicit + if (_numDestRegs > 0) { + if (_numSrcRegs > 0) + ss << ","; + printReg(ss, _destRegIdx[0]); + } + + return ss.str(); + } + }}; + + // Declarations for execute() methods. + def template BasicExecDeclare {{ + Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const; + }}; + + // 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, 'AlphaStaticInst', CodeBlock(code), flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) + }}; + + + + //////////////////////////////////////////////////////////////////// + // + // Nop + // + + output header {{ + /** + * Static instruction class for no-ops. This is a leaf class. + */ + class Nop : public AlphaStaticInst + { + /// Disassembly of original instruction. + const std::string originalDisassembly; + + public: + /// Constructor + Nop(const std::string _originalDisassembly, ExtMachInst _machInst) + : AlphaStaticInst("nop", _machInst, No_OpClass), + originalDisassembly(_originalDisassembly) + { + flags[IsNop] = true; + } + + ~Nop() { } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + %(BasicExecDeclare)s + }; + + /// Helper function for decoding nops. Substitute Nop object + /// for original inst passed in as arg (and delete latter). + static inline + AlphaStaticInst * + makeNop(AlphaStaticInst *inst) + { + AlphaStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst); + delete inst; + return nop; + } + }}; + + output decoder {{ + std::string Nop::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + #ifdef SS_COMPATIBLE_DISASSEMBLY + return originalDisassembly; + #else + return csprintf("%-10s (%s)", "nop", originalDisassembly); + #endif + } + }}; + + output exec {{ + Fault + Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const + { + return NoFault; + } + }}; + + // integer & FP operate instructions use Rc as dest, so check for + // Rc == 31 to detect nops + def template OperateNopCheckDecode {{ + { + AlphaStaticInst *i = new %(class_name)s(machInst); + if (RC == 31) { + i = makeNop(i); + } + return i; + } + }}; + + // Like BasicOperate format, but generates NOP if RC/FC == 31 + def format BasicOperateWithNopCheck(code, *opt_args) {{ + iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), + opt_args) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = OperateNopCheckDecode.subst(iop) + exec_output = BasicExecute.subst(iop) + }}; + + // Integer instruction templates, formats, etc. + ##include "m5/arch/alpha/isa/int.isa" + + // Floating-point instruction templates, formats, etc. + ##include "m5/arch/alpha/isa/fp.isa" + + // Memory instruction templates, formats, etc. + ##include "m5/arch/alpha/isa/mem.isa" + + // Branch/jump instruction templates, formats, etc. + ##include "m5/arch/alpha/isa/branch.isa" + + // PAL instruction templates, formats, etc. + ##include "m5/arch/alpha/isa/pal.isa" + + // Opcdec fault instruction templates, formats, etc. + ##include "m5/arch/alpha/isa/opcdec.isa" + + // Unimplemented instruction templates, formats, etc. + ##include "m5/arch/alpha/isa/unimp.isa" + + // Unknown instruction templates, formats, etc. + ##include "m5/arch/alpha/isa/unknown.isa" + + // Execution utility functions + ##include "m5/arch/alpha/isa/util.isa" + + // The actual decoder + ##include "m5/arch/alpha/isa/decoder.isa" diff --cc arch/alpha/linux/process.hh index 000000000,7de1b1ac1..2cabc3f76 mode 000000,100644..100644 --- a/arch/alpha/linux/process.hh +++ b/arch/alpha/linux/process.hh @@@ -1,0 -1,58 +1,59 @@@ + /* + * 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. + */ + + #ifndef __ALPHA_LINUX_PROCESS_HH__ + #define __ALPHA_LINUX_PROCESS_HH__ + + #include "sim/process.hh" + + + /// A process with emulated Alpha/Linux syscalls. + class AlphaLinuxProcess : public LiveProcess + { + public: + /// Constructor. + AlphaLinuxProcess(const std::string &name, + ObjectFile *objFile, ++ System *system, + int stdin_fd, int stdout_fd, int stderr_fd, + std::vector &argv, + std::vector &envp); + + 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[]; + + const int Num_Syscall_Descs; + }; + + + #endif // __ALPHA_LINUX_PROCESS_HH__ diff --cc arch/alpha/tru64/process.hh index 000000000,051760702..84abd54bf mode 000000,100644..100644 --- a/arch/alpha/tru64/process.hh +++ b/arch/alpha/tru64/process.hh @@@ -1,0 -1,58 +1,59 @@@ + /* + * 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. + */ + + #ifndef __ALPHA_TRU64_PROCESS_HH__ + #define __ALPHA_TRU64_PROCESS_HH__ + + #include "sim/process.hh" + + /// A process with emulated Alpha Tru64 syscalls. + class AlphaTru64Process : public LiveProcess + { + public: + /// Constructor. + AlphaTru64Process(const std::string &name, + ObjectFile *objFile, ++ System *system, + int stdin_fd, int stdout_fd, int stderr_fd, + std::vector &argv, + std::vector &envp); + + /// Array of syscall descriptors, indexed by call number. + static SyscallDesc syscallDescs[]; + + /// Array of mach syscall descriptors, indexed by call number. + static SyscallDesc machSyscallDescs[]; + + const int Num_Syscall_Descs; + const int Num_Mach_Syscall_Descs; + + virtual SyscallDesc* getDesc(int callnum); + }; + + + #endif // __ALPHA_TRU64_PROCESS_HH__ diff --cc base/loader/object_file.hh index 35ea11b54,1b44ae14f..08a51863e --- a/base/loader/object_file.hh +++ b/base/loader/object_file.hh @@@ -29,9 -29,11 +29,11 @@@ #ifndef __OBJECT_FILE_HH__ #define __OBJECT_FILE_HH__ - #include "targetarch/isa_traits.hh" // for Addr + #include + + #include "sim/host.hh" // for Addr -class FunctionalMemory; +class TranslatingPort; class SymbolTable; class ObjectFile diff --cc cpu/base.hh index c0e087f42,d9d5d2b88..0866b49a7 --- a/cpu/base.hh +++ b/cpu/base.hh @@@ -36,12 -36,15 +36,13 @@@ #include "cpu/sampler/sampler.hh" #include "sim/eventq.hh" #include "sim/sim_object.hh" - #include "targetarch/isa_traits.hh" + #include "arch/isa_traits.hh" -#if FULL_SYSTEM class System; + namespace Kernel { class Statistics; } -#endif - class BranchPred; class ExecContext; +class Port; class BaseCPU : public SimObject { diff --cc cpu/cpu_exec_context.cc index 000000000,b7238e73a..6ef42762d mode 000000,100644..100644 --- a/cpu/cpu_exec_context.cc +++ b/cpu/cpu_exec_context.cc @@@ -1,0 -1,298 +1,290 @@@ + /* + * 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 + * 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. + */ + + #include + + #include "cpu/base.hh" + #include "cpu/cpu_exec_context.hh" + #include "cpu/exec_context.hh" + + #if FULL_SYSTEM + #include "base/callback.hh" + #include "base/cprintf.hh" + #include "base/output.hh" + #include "base/trace.hh" + #include "cpu/profile.hh" + #include "kern/kernel_stats.hh" + #include "sim/serialize.hh" + #include "sim/sim_exit.hh" + #include "sim/system.hh" + #include "arch/stacktrace.hh" + #else + #include "sim/process.hh" ++#include "mem/translating_port.hh" + #endif + + using namespace std; + + // constructor + #if FULL_SYSTEM + CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, + AlphaITB *_itb, AlphaDTB *_dtb, - FunctionalMemory *_mem) ++ Memory *_mem) + : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), + cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb), + dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem), + profile(NULL), quiesceEvent(this), func_exe_inst(0), storeCondFailures(0) + { + proxy = new ProxyExecContext(this); + + memset(®s, 0, sizeof(RegFile)); + + if (cpu->params->profile) { + profile = new FunctionProfile(system->kernelSymtab); + Callback *cb = + new MakeCallback(this); + registerExitCallback(cb); + } + + // let's fill with a dummy node for now so we don't get a segfault + // on the first cycle when there's no node available. + static ProfileNode dummyNode; + profileNode = &dummyNode; + profilePC = 3; + } + #else + CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, - Process *_process, int _asid) ++ Process *_process, int _asid, Port *mem_port) + : _status(ExecContext::Unallocated), + cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), - lastSuspend(0), process(_process), mem(process->getMemory()), asid(_asid), - func_exe_inst(0), storeCondFailures(0) -{ - memset(®s, 0, sizeof(RegFile)); - proxy = new ProxyExecContext(this); -} - -CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, - FunctionalMemory *_mem, int _asid) - : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid), ++ lastSuspend(0), process(_process), asid(_asid), + func_exe_inst(0), storeCondFailures(0) + { ++ port = new TranslatingPort(mem_port, process->pTable); + memset(®s, 0, sizeof(RegFile)); + proxy = new ProxyExecContext(this); + } + + CPUExecContext::CPUExecContext(RegFile *regFile) + : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1), + func_exe_inst(0), storeCondFailures(0) + { + regs = *regFile; + proxy = new ProxyExecContext(this); + } + + #endif + + CPUExecContext::~CPUExecContext() + { + delete proxy; + } + + #if FULL_SYSTEM + void + CPUExecContext::dumpFuncProfile() + { + std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); + profile->dump(proxy, *os); + } + + CPUExecContext::EndQuiesceEvent::EndQuiesceEvent(CPUExecContext *_cpuXC) + : Event(&mainEventQueue), cpuXC(_cpuXC) + { + } + + void + CPUExecContext::EndQuiesceEvent::process() + { + cpuXC->activate(); + } + + const char* + CPUExecContext::EndQuiesceEvent::description() + { + return "End Quiesce Event."; + } + + void + CPUExecContext::profileClear() + { + if (profile) + profile->clear(); + } + + void + CPUExecContext::profileSample() + { + if (profile) + profile->sample(profileNode, profilePC); + } + + #endif + + void + CPUExecContext::takeOverFrom(ExecContext *oldContext) + { + // some things should already be set up - assert(mem == oldContext->getMemPtr()); + #if FULL_SYSTEM + assert(system == oldContext->getSystemPtr()); + #else + assert(process == oldContext->getProcessPtr()); + #endif + + // copy over functional state + _status = oldContext->status(); + copyArchRegs(oldContext); + cpu_id = oldContext->readCpuId(); + #if !FULL_SYSTEM + func_exe_inst = oldContext->readFuncExeInst(); + #endif + + storeCondFailures = 0; + + oldContext->setStatus(ExecContext::Unallocated); + } + + void + CPUExecContext::serialize(ostream &os) + { + SERIALIZE_ENUM(_status); + regs.serialize(os); + // thread_num and cpu_id are deterministic from the config + SERIALIZE_SCALAR(func_exe_inst); + SERIALIZE_SCALAR(inst); + + #if FULL_SYSTEM + Tick quiesceEndTick = 0; + if (quiesceEvent.scheduled()) + quiesceEndTick = quiesceEvent.when(); + SERIALIZE_SCALAR(quiesceEndTick); + + #endif + } + + + void + CPUExecContext::unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_ENUM(_status); + regs.unserialize(cp, section); + // thread_num and cpu_id are deterministic from the config + UNSERIALIZE_SCALAR(func_exe_inst); + UNSERIALIZE_SCALAR(inst); + + #if FULL_SYSTEM + Tick quiesceEndTick; + UNSERIALIZE_SCALAR(quiesceEndTick); + if (quiesceEndTick) + quiesceEvent.schedule(quiesceEndTick); + #endif + } + + + void + CPUExecContext::activate(int delay) + { + if (status() == ExecContext::Active) + return; + + lastActivate = curTick; + + _status = ExecContext::Active; + cpu->activateContext(thread_num, delay); + } + + void + CPUExecContext::suspend() + { + if (status() == ExecContext::Suspended) + return; + + lastActivate = curTick; + lastSuspend = curTick; + /* + #if FULL_SYSTEM + // Don't change the status from active if there are pending interrupts + if (cpu->check_interrupts()) { + assert(status() == ExecContext::Active); + return; + } + #endif + */ + _status = ExecContext::Suspended; + cpu->suspendContext(thread_num); + } + + void + CPUExecContext::deallocate() + { + if (status() == ExecContext::Unallocated) + return; + + _status = ExecContext::Unallocated; + cpu->deallocateContext(thread_num); + } + + void + CPUExecContext::halt() + { + if (status() == ExecContext::Halted) + return; + + _status = ExecContext::Halted; + cpu->haltContext(thread_num); + } + + + void + CPUExecContext::regStats(const string &name) + { + } + + void + CPUExecContext::copyArchRegs(ExecContext *xc) + { + // First loop through the integer registers. + for (int i = 0; i < AlphaISA::NumIntRegs; ++i) { + setIntReg(i, xc->readIntReg(i)); + } + + // Then loop through the floating point registers. + for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { + setFloatRegDouble(i, xc->readFloatRegDouble(i)); + setFloatRegInt(i, xc->readFloatRegInt(i)); + } + + // Copy misc. registers + regs.miscRegs.copyMiscRegs(xc); + + // Lastly copy PC/NPC + setPC(xc->readPC()); + setNextPC(xc->readNextPC()); + } + diff --cc cpu/cpu_exec_context.hh index 000000000,beaf67352..e17cfbb94 mode 000000,100644..100644 --- a/cpu/cpu_exec_context.hh +++ b/cpu/cpu_exec_context.hh @@@ -1,0 -1,530 +1,522 @@@ + /* + * 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 + * 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. + */ + + #ifndef __CPU_CPU_EXEC_CONTEXT_HH__ + #define __CPU_CPU_EXEC_CONTEXT_HH__ + + #include "arch/isa_traits.hh" + #include "config/full_system.hh" + #include "cpu/exec_context.hh" -#include "mem/functional/functional.hh" -#include "mem/mem_req.hh" ++#include "mem/physical.hh" ++#include "mem/request.hh" + #include "sim/byteswap.hh" + #include "sim/eventq.hh" + #include "sim/host.hh" + #include "sim/serialize.hh" + -// forward declaration: see functional_memory.hh -class FunctionalMemory; -class PhysicalMemory; + class BaseCPU; + + #if FULL_SYSTEM + + #include "sim/system.hh" + #include "arch/tlb.hh" + + class FunctionProfile; + class ProfileNode; + class MemoryController; + + #else // !FULL_SYSTEM + + #include "sim/process.hh" ++class TranslatingPort; + + #endif // FULL_SYSTEM + + // + // The CPUExecContext object represents a functional context for + // instruction execution. It incorporates everything required for + // architecture-level functional simulation of a single thread. + // + + class CPUExecContext + { + protected: + typedef TheISA::RegFile RegFile; + typedef TheISA::MachInst MachInst; + typedef TheISA::MiscRegFile MiscRegFile; + typedef TheISA::MiscReg MiscReg; + public: + typedef ExecContext::Status Status; + + private: + Status _status; + + public: + Status status() const { return _status; } + + void setStatus(Status newStatus) { _status = newStatus; } + + /// Set the status to Active. Optional delay indicates number of + /// cycles to wait before beginning execution. + void activate(int delay = 1); + + /// Set the status to Suspended. + void suspend(); + + /// Set the status to Unallocated. + void deallocate(); + + /// Set the status to Halted. + void halt(); + + protected: + RegFile regs; // correct-path register context + + public: + // pointer to CPU associated with this context + BaseCPU *cpu; + + ProxyExecContext *proxy; + + // Current instruction + MachInst inst; + + // Index of hardware thread context on the CPU that this represents. + int thread_num; + + // ID of this context w.r.t. the System or Process object to which + // it belongs. For full-system mode, this is the system CPU ID. + int cpu_id; + + Tick lastActivate; + Tick lastSuspend; + ++ System *system; ++ ++ /// Port that syscalls can use to access memory (provides translation step). ++ TranslatingPort *port; ++// Memory *mem; ++ + #if FULL_SYSTEM - FunctionalMemory *mem; + AlphaITB *itb; + AlphaDTB *dtb; - System *system; + + // the following two fields are redundant, since we can always + // look them up through the system pointer, but we'll leave them + // here for now for convenience + MemoryController *memctrl; - PhysicalMemory *physmem; ++// PhysicalMemory *physmem; + + FunctionProfile *profile; + ProfileNode *profileNode; + Addr profilePC; + void dumpFuncProfile(); + + /** Event for timing out quiesce instruction */ + struct EndQuiesceEvent : public Event + { + /** A pointer to the execution context that is quiesced */ + CPUExecContext *cpuXC; + + EndQuiesceEvent(CPUExecContext *_cpuXC); + + /** Event process to occur at interrupt*/ + virtual void process(); + + /** Event description */ + virtual const char *description(); + }; + EndQuiesceEvent quiesceEvent; + + Event *getQuiesceEvent() { return &quiesceEvent; } + + Tick readLastActivate() { return lastActivate; } + + Tick readLastSuspend() { return lastSuspend; } + + void profileClear(); + + void profileSample(); + + #else + Process *process; + - FunctionalMemory *mem; // functional storage for process address space - + // Address space ID. Note that this is used for TIMING cache + // simulation only; all functional memory accesses should use + // one of the FunctionalMemory pointers above. + short asid; + + #endif + + /** + * Temporary storage to pass the source address from copy_load to + * copy_store. + * @todo Remove this temporary when we have a better way to do it. + */ + Addr copySrcAddr; + /** + * Temp storage for the physical source address of a copy. + * @todo Remove this temporary when we have a better way to do it. + */ + Addr copySrcPhysAddr; + + + /* + * number of executed instructions, for matching with syscall trace + * points in EIO files. + */ + Counter func_exe_inst; + + // + // Count failed store conditionals so we can warn of apparent + // application deadlock situations. + unsigned storeCondFailures; + + // constructor: initialize context from given process structure + #if FULL_SYSTEM + CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system, + AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem); + #else - CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid); - CPUExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem, - int _asid); ++ CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, Port *mem_port); + // Constructor to use XC to pass reg file around. Not used for anything + // else. + CPUExecContext(RegFile *regFile); + #endif + virtual ~CPUExecContext(); + + virtual void takeOverFrom(ExecContext *oldContext); + + void regStats(const std::string &name); + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + BaseCPU *getCpuPtr() { return cpu; } + + ExecContext *getProxy() { return proxy; } + + int getThreadNum() { return thread_num; } + + #if FULL_SYSTEM + System *getSystemPtr() { return system; } + + PhysicalMemory *getPhysMemPtr() { return physmem; } + + AlphaITB *getITBPtr() { return itb; } + + AlphaDTB *getDTBPtr() { return dtb; } + + bool validInstAddr(Addr addr) { return true; } + bool validDataAddr(Addr addr) { return true; } + int getInstAsid() { return regs.instAsid(); } + int getDataAsid() { return regs.dataAsid(); } + - Fault translateInstReq(MemReqPtr &req) ++ Fault translateInstReq(CpuRequestPtr &req) + { + return itb->translate(req); + } + - Fault translateDataReadReq(MemReqPtr &req) ++ Fault translateDataReadReq(CpuRequestPtr &req) + { + return dtb->translate(req, false); + } + - Fault translateDataWriteReq(MemReqPtr &req) ++ Fault translateDataWriteReq(CpuRequestPtr &req) + { + return dtb->translate(req, true); + } + + #else + Process *getProcessPtr() { return process; } + + bool validInstAddr(Addr addr) + { return process->validInstAddr(addr); } + + bool validDataAddr(Addr addr) + { return process->validDataAddr(addr); } + + int getInstAsid() { return asid; } + int getDataAsid() { return asid; } + - Fault dummyTranslation(MemReqPtr &req) ++ Fault translateInstReq(CpuRequestPtr &req) + { -#if 0 - assert((req->vaddr >> 48 & 0xffff) == 0); -#endif - - // put the asid in the upper 16 bits of the paddr - req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); - req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; - return NoFault; ++ return process->pTable->translate(req); + } - Fault translateInstReq(MemReqPtr &req) - { - return dummyTranslation(req); - } - Fault translateDataReadReq(MemReqPtr &req) ++ ++ Fault translateDataReadReq(CpuRequestPtr &req) + { - return dummyTranslation(req); ++ return process->pTable->translate(req); + } - Fault translateDataWriteReq(MemReqPtr &req) ++ ++ Fault translateDataWriteReq(CpuRequestPtr &req) + { - return dummyTranslation(req); ++ return process->pTable->translate(req); + } + + #endif + ++/* + template - Fault read(MemReqPtr &req, T &data) ++ Fault read(CpuRequestPtr &req, T &data) + { + #if FULL_SYSTEM && defined(TARGET_ALPHA) + if (req->flags & LOCKED) { + req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr); + req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true); + } + #endif + + Fault error; - error = mem->read(req, data); ++ error = mem->prot_read(req->paddr, data, req->size); + data = LittleEndianGuest::gtoh(data); + return error; + } + + template - Fault write(MemReqPtr &req, T &data) ++ Fault write(CpuRequestPtr &req, T &data) + { + #if FULL_SYSTEM && defined(TARGET_ALPHA) + ExecContext *xc; + + // If this is a store conditional, act appropriately + if (req->flags & LOCKED) { + xc = req->xc; + + if (req->flags & UNCACHEABLE) { + // Don't update result register (see stq_c in isa_desc) + req->result = 2; + xc->setStCondFailures(0);//Needed? [RGD] + } else { + bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag); + Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag); + req->result = lock_flag; + if (!lock_flag || + ((lock_addr & ~0xf) != (req->paddr & ~0xf))) { + xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); + xc->setStCondFailures(xc->readStCondFailures() + 1); + if (((xc->readStCondFailures()) % 100000) == 0) { + std::cerr << "Warning: " + << xc->readStCondFailures() + << " consecutive store conditional failures " + << "on cpu " << req->xc->readCpuId() + << std::endl; + } + return NoFault; + } + else xc->setStCondFailures(0); + } + } + + // Need to clear any locked flags on other proccessors for + // this address. Only do this for succsful Store Conditionals + // and all other stores (WH64?). Unsuccessful Store + // Conditionals would have returned above, and wouldn't fall + // through. + for (int i = 0; i < system->execContexts.size(); i++){ + xc = system->execContexts[i]; + if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) == + (req->paddr & ~0xf)) { + xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); + } + } + + #endif - return mem->write(req, (T)LittleEndianGuest::htog(data)); ++ return mem->prot_write(req->paddr, (T)htog(data), req->size); + } - ++*/ + virtual bool misspeculating(); + + + MachInst getInst() { return inst; } + + void setInst(MachInst new_inst) + { + inst = new_inst; + } + - Fault instRead(MemReqPtr &req) ++ Fault instRead(CpuRequestPtr &req) + { - return mem->read(req, inst); ++ panic("instRead not implemented"); ++ // return funcPhysMem->read(req, inst); ++ return No_Fault; + } + + void setCpuId(int id) { cpu_id = id; } + + int readCpuId() { return cpu_id; } + + FunctionalMemory *getMemPtr() { return mem; } + + void copyArchRegs(ExecContext *xc); + + // + // New accessors for new decoder. + // + uint64_t readIntReg(int reg_idx) + { + return regs.intRegFile[reg_idx]; + } + + float readFloatRegSingle(int reg_idx) + { + return (float)regs.floatRegFile.d[reg_idx]; + } + + double readFloatRegDouble(int reg_idx) + { + return regs.floatRegFile.d[reg_idx]; + } + + uint64_t readFloatRegInt(int reg_idx) + { + return regs.floatRegFile.q[reg_idx]; + } + + void setIntReg(int reg_idx, uint64_t val) + { + regs.intRegFile[reg_idx] = val; + } + + void setFloatRegSingle(int reg_idx, float val) + { + regs.floatRegFile.d[reg_idx] = (double)val; + } + + void setFloatRegDouble(int reg_idx, double val) + { + regs.floatRegFile.d[reg_idx] = val; + } + + void setFloatRegInt(int reg_idx, uint64_t val) + { + regs.floatRegFile.q[reg_idx] = val; + } + + uint64_t readPC() + { + return regs.pc; + } + + void setPC(uint64_t val) + { + regs.pc = val; + } + + uint64_t readNextPC() + { + return regs.npc; + } + + void setNextPC(uint64_t val) + { + regs.npc = val; + } + + uint64_t readNextNPC() + { + return regs.nnpc; + } + + void setNextNPC(uint64_t val) + { + regs.nnpc = val; + } + + + MiscReg readMiscReg(int misc_reg) + { + return regs.miscRegs.readReg(misc_reg); + } + + MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) + { + return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy); + } + + Fault setMiscReg(int misc_reg, const MiscReg &val) + { + return regs.miscRegs.setReg(misc_reg, val); + } + + Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) + { + return regs.miscRegs.setRegWithEffect(misc_reg, val, proxy); + } + + unsigned readStCondFailures() { return storeCondFailures; } + + void setStCondFailures(unsigned sc_failures) + { storeCondFailures = sc_failures; } + + void clearArchRegs() { memset(®s, 0, sizeof(regs)); } + + #if FULL_SYSTEM + int readIntrFlag() { return regs.intrflag; } + void setIntrFlag(int val) { regs.intrflag = val; } + Fault hwrei(); + bool inPalMode() { return AlphaISA::PcPAL(regs.pc); } + bool simPalCheck(int palFunc); + #endif + + #if !FULL_SYSTEM + TheISA::IntReg getSyscallArg(int i) + { + return regs.intRegFile[TheISA::ArgumentReg0 + i]; + } + + // used to shift args for indirect syscall + void setSyscallArg(int i, TheISA::IntReg val) + { + regs.intRegFile[TheISA::ArgumentReg0 + i] = val; + } + + void setSyscallReturn(SyscallReturn return_value) + { + TheISA::setSyscallReturn(return_value, ®s); + } + + void syscall() + { + process->syscall(proxy); + } + + Counter readFuncExeInst() { return func_exe_inst; } + + void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; } + #endif + }; + + + // for non-speculative execution context, spec_mode is always false + inline bool + CPUExecContext::misspeculating() + { + return false; + } + + #endif // __CPU_CPU_EXEC_CONTEXT_HH__ diff --cc cpu/exetrace.cc index 5c7dc953c,84b5eacf7..ebb719b2c --- a/cpu/exetrace.cc +++ b/cpu/exetrace.cc @@@ -30,8 -30,10 +30,7 @@@ #include #include "sim/param.hh" -#include "encumbered/cpu/full/dyn_inst.hh" -#include "encumbered/cpu/full/spec_state.hh" -#include "encumbered/cpu/full/issue.hh" #include "cpu/exetrace.hh" - #include "cpu/exec_context.hh" #include "base/loader/symtab.hh" #include "cpu/base.hh" #include "cpu/static_inst.hh" diff --cc cpu/simple/cpu.cc index d8d4c3644,8db72b77e..fc70df662 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@@ -52,6 -53,9 +53,7 @@@ #include "cpu/smt.hh" #include "cpu/static_inst.hh" #include "kern/kernel_stats.hh" -#include "mem/base_mem.hh" -#include "mem/mem_interface.hh" + #include "sim/byteswap.hh" #include "sim/builder.hh" #include "sim/debug.hh" #include "sim/host.hh" @@@ -64,11 -68,11 +66,11 @@@ #include "mem/functional/memory_control.hh" #include "mem/functional/physical.hh" #include "sim/system.hh" - #include "targetarch/alpha_memory.hh" - #include "targetarch/stacktrace.hh" - #include "targetarch/vtophys.hh" + #include "arch/tlb.hh" + #include "arch/stacktrace.hh" + #include "arch/vtophys.hh" #else // !FULL_SYSTEM -#include "mem/functional/functional.hh" +#include "mem/memory.hh" #endif // FULL_SYSTEM using namespace std; @@@ -128,53 -133,26 +147,52 @@@ SimpleCPU::CpuPort::recvRetry( } SimpleCPU::SimpleCPU(Params *p) - : BaseCPU(p), tickEvent(this, p->width), cpuXC(NULL), - cacheCompletionEvent(this) + : BaseCPU(p), icachePort(this), - dcachePort(this), tickEvent(this, p->width), xc(NULL) ++ dcachePort(this), tickEvent(this, p->width), cpuXC(NULL) { _status = Idle; + + //Create Memory Ports (conect them up) + p->mem->addPort("DCACHE"); + dcachePort.setPeer(p->mem->getPort("DCACHE")); + (p->mem->getPort("DCACHE"))->setPeer(&dcachePort); + + p->mem->addPort("ICACHE"); + icachePort.setPeer(p->mem->getPort("ICACHE")); + (p->mem->getPort("ICACHE"))->setPeer(&icachePort); + #if FULL_SYSTEM - xc = new ExecContext(this, 0, p->system, p->itb, p->dtb, p->mem); - - // initialize CPU, including PC - TheISA::initCPU(&xc->regs); + cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem); - #else - xc = new ExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0, - cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, - /* asid */ 0); ++ cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0, + &dcachePort); #endif // !FULL_SYSTEM - xcProxy = cpuXC->getProxy(); - icacheInterface = p->icache_interface; - dcacheInterface = p->dcache_interface; ++ xcProxy = cpuXC->getProxy(); + - memReq = new MemReq(); - memReq->xc = xcProxy; - memReq->asid = 0; - memReq->data = new uint8_t[64]; +#if SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE + ifetch_req = new CpuRequest; + ifetch_req->asid = 0; + ifetch_req->size = sizeof(MachInst); + ifetch_pkt = new Packet; + ifetch_pkt->cmd = Read; + ifetch_pkt->data = (uint8_t *)&inst; + ifetch_pkt->req = ifetch_req; + ifetch_pkt->size = sizeof(MachInst); + + data_read_req = new CpuRequest; + data_read_req->asid = 0; + data_read_pkt = new Packet; + data_read_pkt->cmd = Read; + data_read_pkt->data = new uint8_t[8]; + data_read_pkt->req = data_read_req; + + data_write_req = new CpuRequest; + data_write_req->asid = 0; + data_write_pkt = new Packet; + data_write_pkt->cmd = Write; + data_write_pkt->req = data_write_req; +#endif numInst = 0; startNumInst = 0; @@@ -350,8 -317,10 +368,8 @@@ SimpleCPU::unserialize(Checkpoint *cp, BaseCPU::unserialize(cp, section); UNSERIALIZE_ENUM(_status); UNSERIALIZE_SCALAR(inst); - xc->unserialize(cp, csprintf("%s.xc", section)); + cpuXC->unserialize(cp, csprintf("%s.xc", section)); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); - cacheCompletionEvent - .unserialize(cp, csprintf("%s.cacheCompletionEvent", section)); } void @@@ -379,22 -347,19 +397,21 @@@ SimpleCPU::copySrcTranslate(Addr src memReq->reset(src & ~(blk_size - 1), blk_size); -- // translate to physical address - Fault fault = xc->translateDataReadReq(req); - - assert(fault != Alignment_Fault); - Fault fault = cpuXC->translateDataReadReq(memReq); ++ // translate to physical address Fault fault = cpuXC->translateDataReadReq(req); - if (fault == No_Fault) { - xc->copySrcAddr = src; - xc->copySrcPhysAddr = memReq->paddr + offset; + if (fault == NoFault) { + cpuXC->copySrcAddr = src; + cpuXC->copySrcPhysAddr = memReq->paddr + offset; } else { - xc->copySrcAddr = 0; - xc->copySrcPhysAddr = 0; + assert(!fault->isAlignmentFault()); + + cpuXC->copySrcAddr = 0; + cpuXC->copySrcPhysAddr = 0; } return fault; +#else + return No_Fault; +#endif } Fault @@@ -419,17 -383,15 +436,15 @@@ SimpleCPU::copy(Addr dest memReq->reset(dest & ~(blk_size -1), blk_size); // translate to physical address - Fault fault = xc->translateDataWriteReq(req); - - assert(fault != Alignment_Fault); - Fault fault = cpuXC->translateDataWriteReq(memReq); ++ Fault fault = cpuXC->translateDataWriteReq(req); - if (fault == No_Fault) { + if (fault == NoFault) { Addr dest_addr = memReq->paddr + offset; // Need to read straight from memory since we have more than 8 bytes. - memReq->paddr = xc->copySrcPhysAddr; - xc->mem->read(memReq, data); + memReq->paddr = cpuXC->copySrcPhysAddr; + cpuXC->mem->read(memReq, data); memReq->paddr = dest_addr; - xc->mem->write(memReq, data); + cpuXC->mem->write(memReq, data); if (dcacheInterface) { memReq->cmd = Copy; memReq->completionEvent = NULL; @@@ -441,11 -403,10 +456,14 @@@ dcacheInterface->access(memReq); } } + else + assert(!fault->isAlignmentFault()); + return fault; +#else + panic("copy not implemented"); + return No_Fault; +#endif } // precise architected memory state accessor macros @@@ -463,54 -420,16 +481,54 @@@ SimpleCPU::read(Addr addr, T &data, uns if (traceData) { traceData->setAddr(addr); } - return fault; + + // @todo: Figure out a way to create a Fault from the packet result. + return No_Fault; } - memReq->reset(addr, sizeof(T), flags); +// memReq->reset(addr, sizeof(T), flags); + +#if SIMPLE_CPU_MEM_TIMING + CpuRequest *data_read_req = new CpuRequest; +#endif + + data_read_req->vaddr = addr; + data_read_req->size = sizeof(T); + data_read_req->flags = flags; + data_read_req->time = curTick; // translate to physical address - Fault fault = xc->translateDataReadReq(data_read_req); - Fault fault = cpuXC->translateDataReadReq(memReq); ++ Fault fault = cpuXC->translateDataReadReq(data_read_req); + + // Now do the access. + if (fault == No_Fault) { +#if SIMPLE_CPU_MEM_TIMING + data_read_pkt = new Packet; + data_read_pkt->cmd = Read; + data_read_pkt->req = data_read_req; + data_read_pkt->data = new uint8_t[8]; +#endif + data_read_pkt->addr = data_read_req->paddr; + data_read_pkt->size = sizeof(T); - // if we have a cache, do cache access too - if (fault == NoFault && dcacheInterface) { + sendDcacheRequest(data_read_pkt); + +#if SIMPLE_CPU_MEM_IMMEDIATE + // Need to find a way to not duplicate code above. + + if (data_read_pkt->result == Success) { + memcpy(&data, data_read_pkt->data, sizeof(T)); + } + + if (traceData) { + traceData->setAddr(addr); + } + + // @todo: Figure out a way to create a Fault from the packet result. + return No_Fault; +#endif + } +/* memReq->cmd = Read; memReq->completionEvent = NULL; memReq->time = curTick; @@@ -527,18 -446,16 +545,17 @@@ _status = DcacheMissStall; } else { // do functional access - fault = xc->read(memReq, data); + fault = cpuXC->read(memReq, data); } - - } else if(fault == No_Fault) { + } else if(fault == NoFault) { // do functional access - fault = xc->read(memReq, data); + fault = cpuXC->read(memReq, data); } - - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) +*/ + // This will need a new way to tell if it has a dcache attached. + if (data_read_req->flags & UNCACHEABLE) recordEvent("Uncached Read"); return fault; @@@ -591,37 -508,16 +608,36 @@@ template reset(addr, sizeof(T), flags); + data_write_req->vaddr = addr; + data_write_req->time = curTick; + data_write_req->size = sizeof(T); + data_write_req->flags = flags; // translate to physical address - Fault fault = xc->translateDataWriteReq(data_write_req); - - Fault fault = cpuXC->translateDataWriteReq(memReq); ++ Fault fault = cpuXC->translateDataWriteReq(data_write_req); + // Now do the access. + if (fault == No_Fault) { +#if SIMPLE_CPU_MEM_TIMING + data_write_pkt = new Packet; + data_write_pkt->cmd = Write; + data_write_pkt->req = data_write_req; + data_write_pkt->data = new uint8_t[64]; + memcpy(data_write_pkt->data, &data, sizeof(T)); +#else + data_write_pkt->data = (uint8_t *)&data; +#endif + data_write_pkt->addr = data_write_req->paddr; + data_write_pkt->size = sizeof(T); + + sendDcacheRequest(data_write_pkt); + } +/* // do functional access - if (fault == No_Fault) - fault = xc->write(memReq, data); + if (fault == NoFault) + fault = cpuXC->write(memReq, data); - if (fault == No_Fault && dcacheInterface) { + if (fault == NoFault && dcacheInterface) { memReq->cmd = Write; memcpy(memReq->data,(uint8_t *)&data,memReq->size); memReq->completionEvent = NULL; @@@ -639,16 -535,13 +655,16 @@@ _status = DcacheMissStall; } } - +*/ - if (res && (fault == No_Fault)) + if (res && (fault == NoFault)) - *res = memReq->result; + *res = data_write_pkt->result; - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) + // This will need a new way to tell if it's hooked up to a cache or not. + if (data_write_req->flags & UNCACHEABLE) 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. return fault; } @@@ -924,12 -701,12 +940,12 @@@ SimpleCPU::tick( #endif // maintain $r0 semantics - xc->regs.intRegFile[ZeroReg] = 0; + cpuXC->setIntReg(ZeroReg, 0); #ifdef TARGET_ALPHA - xc->regs.floatRegFile.d[ZeroReg] = 0.0; + cpuXC->setFloatRegDouble(ZeroReg, 0.0); #endif // TARGET_ALPHA - if (status() == IcacheMissComplete) { + if (status() == IcacheAccessComplete) { // We've already fetched an instruction and were stalled on an // I-cache miss. No need to fetch it again. @@@ -946,36 -724,16 +962,36 @@@ #define IFETCH_FLAGS(pc) 0 #endif - memReq->cmd = Read; - memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t), - IFETCH_FLAGS(cpuXC->readPC())); +#if SIMPLE_CPU_MEM_TIMING + CpuRequest *ifetch_req = new CpuRequest(); + ifetch_req->size = sizeof(MachInst); +#endif - ifetch_req->vaddr = xc->regs.pc & ~3; - fault = cpuXC->translateInstReq(memReq); ++ ifetch_req->vaddr = cpuXC->readPC() & ~3; + ifetch_req->time = curTick; - if (fault == NoFault) - fault = cpuXC->mem->read(memReq, inst); +/* memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t), + IFETCH_FLAGS(xc->regs.pc)); +*/ + + fault = xc->translateInstReq(ifetch_req); + - if (fault == No_Fault) { ++ if (fault == NoFault) { +#if SIMPLE_CPU_MEM_TIMING + Packet *ifetch_pkt = new Packet; + ifetch_pkt->cmd = Read; + ifetch_pkt->data = (uint8_t *)&inst; + ifetch_pkt->req = ifetch_req; + ifetch_pkt->size = sizeof(MachInst); +#endif + ifetch_pkt->addr = ifetch_req->paddr; + sendIcacheRequest(ifetch_pkt); +#if SIMPLE_CPU_MEM_TIMING || SIMPLE_CPU_MEM_ATOMIC + return; +#endif +/* - if (icacheInterface && fault == No_Fault) { + if (icacheInterface && fault == NoFault) { memReq->completionEvent = NULL; memReq->time = curTick; diff --cc cpu/simple/cpu.hh index ca10134f7,4ab9a1c3e..fbfae950f --- a/cpu/simple/cpu.hh +++ b/cpu/simple/cpu.hh @@@ -64,45 -62,11 +65,48 @@@ namespace Trace class InstRecord; } + +// Set exactly one of these symbols to 1 to set the memory access +// model. Probably should make these template parameters, or even +// just fork the CPU models. +// +#define SIMPLE_CPU_MEM_TIMING 0 +#define SIMPLE_CPU_MEM_ATOMIC 0 +#define SIMPLE_CPU_MEM_IMMEDIATE 1 + + class SimpleCPU : public BaseCPU { + protected: + typedef TheISA::MachInst MachInst; + typedef TheISA::MiscReg MiscReg; + class CpuPort : public Port + { + + SimpleCPU *cpu; + + public: + + CpuPort(SimpleCPU *_cpu) + : cpu(_cpu) + { } + + protected: + + virtual bool recvTiming(Packet &pkt); + + virtual Tick recvAtomic(Packet &pkt); + + virtual void recvFunctional(Packet &pkt); + + virtual void recvStatusChange(Status status); + + virtual Packet *recvRetry(); + }; + + CpuPort icachePort; + CpuPort dcachePort; + public: // main simulation loop (one cycle) void tick(); @@@ -214,8 -179,22 +221,8 @@@ // the next switchover Sampler *sampler; - StaticInstPtr curStaticInst; + StaticInstPtr curStaticInst; - class CacheCompletionEvent : public Event - { - private: - SimpleCPU *cpu; - - public: - CacheCompletionEvent(SimpleCPU *_cpu); - - virtual void process(); - virtual const char *description(); - }; - - CacheCompletionEvent cacheCompletionEvent; - Status status() const { return _status; } virtual void activateContext(int thread_num, int delay); diff --cc cpu/static_inst.hh index 09eb7efbf,20116554e..2ed2fe61c --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@@ -34,9 -34,9 +34,9 @@@ #include "base/hashmap.hh" #include "base/refcnt.hh" -#include "encumbered/cpu/full/op_class.hh" +#include "cpu/op_class.hh" #include "sim/host.hh" - #include "targetarch/isa_traits.hh" + #include "arch/isa_traits.hh" // forward declarations struct AlphaSimpleImpl; diff --cc sim/process.cc index bb13bd35f,f02ca8bfd..70a92a604 --- a/sim/process.cc +++ b/sim/process.cc @@@ -48,14 -47,12 +49,13 @@@ #include "sim/fake_syscall.hh" #include "sim/process.hh" #include "sim/stats.hh" + #include "sim/syscall_emul.hh" +#include "sim/system.hh" - #ifdef TARGET_ALPHA - #include "arch/alpha/alpha_tru64_process.hh" - #include "arch/alpha/alpha_linux_process.hh" - #endif + #include "arch/process.hh" using namespace std; + using namespace TheISA; // // The purpose of this code is to fake the loader & syscall mechanism @@@ -245,11 -251,13 +245,13 @@@ DEFINE_SIM_OBJECT_CLASS_NAME("Process" static void copyStringArray(vector &strings, Addr array_ptr, Addr data_ptr, - FunctionalMemory *memory) + TranslatingPort* memPort) { + Addr data_ptr_swap; for (int i = 0; i < strings.size(); ++i) { - memPort->writeBlobFunctional(array_ptr, (uint8_t*)&data_ptr, sizeof(Addr)); + data_ptr_swap = htog(data_ptr); - memory->access(Write, array_ptr, &data_ptr_swap, sizeof(Addr)); - memory->writeString(data_ptr, strings[i].c_str()); ++ memPort->writeBlobFunctional(array_ptr, (uint8_t*)&data_ptr_swap, sizeof(Addr)); + memPort->writeStringFunctional(data_ptr, strings[i].c_str()); array_ptr += sizeof(Addr); data_ptr += strings[i].size() + 1; } @@@ -342,26 -338,36 +344,38 @@@ LiveProcess::startup( // write contents to stack uint64_t argc = argv.size(); + argc = htog(argc); - memory->access(Write, stack_min, &argc, sizeof(uint64_t)); + initVirtMem->writeBlobFunctional(stack_min, (uint8_t*)&argc, sizeof(uint64_t)); - copyStringArray(argv, argv_array_base, arg_data_base, memory); - copyStringArray(envp, envp_array_base, env_data_base, memory); + copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); + copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); - RegFile *init_regs = &(execContexts[0]->regs); - -- init_regs->intRegFile[ArgumentReg0] = argc; -- init_regs->intRegFile[ArgumentReg1] = argv_array_base; -- init_regs->intRegFile[StackPointerReg] = stack_min; -- init_regs->intRegFile[GlobalPointerReg] = objFile->globalPointer(); -- init_regs->pc = prog_entry; -- init_regs->npc = prog_entry + sizeof(MachInst); ++ execContexts[0]->setIntReg(ArgumentReg0, argc); ++ execContexts[0]->setIntReg(ArgumentReg1, argv_array_base); ++ execContexts[0]->setIntReg(StackPointerReg, stack_min); ++ execContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer()); ++ execContexts[0]->setPC(prog_entry); ++ execContexts[0]->setNextPC(prog_entry + sizeof(MachInst)); + + num_processes++; } + void + LiveProcess::syscall(ExecContext *xc) + { + num_syscalls++; + + int64_t callnum = xc->readIntReg(SyscallNumReg); + + SyscallDesc *desc = getDesc(callnum); + if (desc == NULL) + fatal("Syscall %d out of range", callnum); + + desc->doSyscall(callnum, this, xc); + } LiveProcess * -LiveProcess::create(const string &nm, +LiveProcess::create(const string &nm, System *system, int stdin_fd, int stdout_fd, int stderr_fd, string executable, vector &argv, vector &envp) @@@ -372,31 -378,13 +386,11 @@@ fatal("Can't load object file %s", executable); } - // check object type & set up syscall emulation pointer - if (objFile->getArch() == ObjectFile::Alpha) { - - switch (objFile->getOpSys()) { - case ObjectFile::Tru64: - process = new AlphaTru64Process(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp); - - break; - - case ObjectFile::Linux: - process = new AlphaLinuxProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp); - - break; - - default: - fatal("Unknown/unsupported operating system."); - } - } else { - fatal("Unknown object file architecture."); - } + // set up syscall emulation pointer for the current ISA - process = createProcess(nm, objFile, ++ process = createProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp); - delete objFile; - if (process == NULL) fatal("Unknown error creating process object."); diff --cc sim/process.hh index 8d8c9e676,3a48f128c..fc600fb06 --- a/sim/process.hh +++ b/sim/process.hh @@@ -40,27 -40,23 +40,33 @@@ #include + #include "arch/isa_traits.hh" -#include "sim/sim_object.hh" -#include "sim/stats.hh" #include "base/statistics.hh" #include "base/trace.hh" +#include "mem/memory.hh" +//#include "mem/mem_interface.hh" +#include "mem/page_table.hh" +#include "sim/sim_object.hh" +#include "sim/stats.hh" +#include "targetarch/isa_traits.hh" + class CPUExecContext; class ExecContext; -class FunctionalMemory; + class SyscallDesc; +class TranslatingPort; +class System; + class Process : public SimObject { + protected: + typedef TheISA::RegFile RegFile; + typedef TheISA::MachInst MachInst; public: + /// Pointer to object representing the system this process is + /// running on. + System *system; + // have we initialized an execution context from this process? If // yes, subsequent contexts are assumed to be for dynamically // created threads and are not initialized. diff --cc sim/syscall_emul.cc index 0cebee0e1,00168b025..1d0b3a375 --- a/sim/syscall_emul.cc +++ b/sim/syscall_emul.cc @@@ -191,7 -193,7 +193,7 @@@ unlinkFunc(SyscallDesc *desc, int num, { string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) ++ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return (TheISA::IntReg)-EFAULT; int result = unlink(path.c_str()); @@@ -203,12 -205,12 +205,12 @@@ renameFunc(SyscallDesc *desc, int num, { string old_name; - if (xc->port->readStringFunctional(old_name, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(old_name, xc->getSyscallArg(0)) != NoFault) ++ if (xc->port->readStringFunctional(old_name, xc->getSyscallArg(0)) != NoFault) return -EFAULT; string new_name; - if (xc->port->readStringFunctional(new_name, xc->getSyscallArg(1)) != No_Fault) - if (xc->getMemPtr()->readString(new_name, xc->getSyscallArg(1)) != NoFault) ++ if (xc->port->readStringFunctional(new_name, xc->getSyscallArg(1)) != NoFault) return -EFAULT; int64_t result = rename(old_name.c_str(), new_name.c_str()); @@@ -220,7 -222,7 +222,7 @@@ truncateFunc(SyscallDesc *desc, int num { string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) ++ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; off_t length = xc->getSyscallArg(1); @@@ -248,7 -250,7 +250,7 @@@ chownFunc(SyscallDesc *desc, int num, P { string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) ++ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; /* XXX endianess */ diff --cc sim/syscall_emul.hh index ed3b0fc8b,35129bcb4..25f8c6cb8 --- a/sim/syscall_emul.hh +++ b/sim/syscall_emul.hh @@@ -43,8 -46,8 +46,8 @@@ #include #include "base/intmath.hh" // for RoundUp -#include "mem/functional/functional.hh" +#include "mem/translating_port.hh" - #include "targetarch/isa_traits.hh" // for Addr + #include "arch/isa_traits.hh" // for Addr #include "base/trace.hh" #include "cpu/exec_context.hh" @@@ -315,7 -369,7 +370,7 @@@ openFunc(SyscallDesc *desc, int callnum { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) ++ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; if (path == "/dev/sysdev0") { @@@ -362,7 -416,7 +417,7 @@@ chmodFunc(SyscallDesc *desc, int callnu { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) ++ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) return -EFAULT; uint32_t mode = xc->getSyscallArg(1); @@@ -415,16 -469,16 +470,16 @@@ statFunc(SyscallDesc *desc, int callnum { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) - return -EFAULT; ++ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) + return -EFAULT; struct stat hostBuf; int result = stat(path.c_str(), &hostBuf); if (result < 0) - return errno; + return -errno; - OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf); + OS::copyOutStatBuf(xc->port, xc->getSyscallArg(1), &hostBuf); return 0; } @@@ -442,13 -496,18 +497,18 @@@ fstat64Func(SyscallDesc *desc, int call return -EBADF; } - struct stat64 hostBuf; + #if BSD_HOST + struct stat hostBuf; + int result = fstat(process->sim_fd(fd), &hostBuf); + #else + struct stat64 hostBuf; int result = fstat64(process->sim_fd(fd), &hostBuf); + #endif if (result < 0) - return errno; + return -errno; - OS::copyOutStat64Buf(xc->port, xc->getSyscallArg(1), &hostBuf); - OS::copyOutStat64Buf(xc->getMemPtr(), fd, xc->getSyscallArg(1), &hostBuf); ++ OS::copyOutStat64Buf(xc->port, fd, xc->getSyscallArg(1), &hostBuf); return 0; } @@@ -462,8 -521,8 +522,8 @@@ lstatFunc(SyscallDesc *desc, int callnu { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) - return -EFAULT; ++ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) + return -EFAULT; struct stat hostBuf; int result = lstat(path.c_str(), &hostBuf); @@@ -484,16 -543,21 +544,21 @@@ lstat64Func(SyscallDesc *desc, int call { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) - return -EFAULT; ++ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) + return -EFAULT; + #if BSD_HOST + struct stat hostBuf; + int result = lstat(path.c_str(), &hostBuf); + #else struct stat64 hostBuf; int result = lstat64(path.c_str(), &hostBuf); + #endif if (result < 0) return -errno; - OS::copyOutStat64Buf(xc->port, xc->getSyscallArg(1), &hostBuf); - OS::copyOutStat64Buf(xc->getMemPtr(), -1, xc->getSyscallArg(1), &hostBuf); ++ OS::copyOutStat64Buf(xc->port, -1, xc->getSyscallArg(1), &hostBuf); return 0; } @@@ -531,16 -594,16 +596,16 @@@ statfsFunc(SyscallDesc *desc, int calln { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) - return -EFAULT; ++ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) + return -EFAULT; struct statfs hostBuf; int result = statfs(path.c_str(), &hostBuf); if (result < 0) - return errno; + return -errno; - OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf); + OS::copyOutStatfsBuf(xc->port, xc->getSyscallArg(1), &hostBuf); return 0; } @@@ -561,9 -624,9 +626,9 @@@ fstatfsFunc(SyscallDesc *desc, int call int result = fstatfs(fd, &hostBuf); if (result < 0) - return errno; + return -errno; - OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf); + OS::copyOutStatfsBuf(xc->port, xc->getSyscallArg(1), &hostBuf); return 0; } @@@ -587,12 -650,12 +652,12 @@@ writevFunc(SyscallDesc *desc, int calln for (int i = 0; i < count; ++i) { typename OS::tgt_iovec tiov; - xc->getMemPtr()->access(Read, tiov_base + i*sizeof(typename OS::tgt_iovec), + xc->port->readBlobFunctional(tiov_base + i*sizeof(typename OS::tgt_iovec),(uint8_t*) &tiov, sizeof(typename OS::tgt_iovec)); - hiov[i].iov_len = tiov.iov_len; + hiov[i].iov_len = gtoh(tiov.iov_len); hiov[i].iov_base = new char [hiov[i].iov_len]; - xc->port->readBlobFunctional(tiov.iov_base, - xc->getMemPtr()->access(Read, gtoh(tiov.iov_base), - hiov[i].iov_base, hiov[i].iov_len); ++ xc->port->readBlobFunctional(gtoh(tiov.iov_base), + (uint8_t *)hiov[i].iov_base, hiov[i].iov_len); } int result = writev(process->sim_fd(fd), hiov, count); @@@ -660,19 -723,21 +725,21 @@@ getrlimitFunc(SyscallDesc *desc, int ca TypedBufferArg rlp(xc->getSyscallArg(1)); switch (resource) { - case OS::RLIMIT_STACK: - // max stack size in bytes: make up a number (2MB for now) - rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; - break; - - default: - std::cerr << "getrlimitFunc: unimplemented resource " << resource - << std::endl; - abort(); - break; + case OS::TGT_RLIMIT_STACK: + // max stack size in bytes: make up a number (2MB for now) + rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; + rlp->rlim_cur = htog(rlp->rlim_cur); + rlp->rlim_max = htog(rlp->rlim_max); + break; + + default: + std::cerr << "getrlimitFunc: unimplemented resource " << resource + << std::endl; + abort(); + break; } - rlp.copyOut(xc->getMemPtr()); + rlp.copyOut(xc->port); return 0; } @@@ -686,8 -751,10 +753,10 @@@ gettimeofdayFunc(SyscallDesc *desc, in getElapsedTime(tp->tv_sec, tp->tv_usec); tp->tv_sec += seconds_since_epoch; + tp->tv_sec = htog(tp->tv_sec); + tp->tv_usec = htog(tp->tv_usec); - tp.copyOut(xc->getMemPtr()); + tp.copyOut(xc->port); return 0; } @@@ -701,11 -768,11 +770,11 @@@ utimesFunc(SyscallDesc *desc, int calln { std::string path; - if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != No_Fault) - if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault) - return -EFAULT; ++ if (xc->port->readStringFunctional(path, xc->getSyscallArg(0)) != NoFault) + return -EFAULT; TypedBufferArg tp(xc->getSyscallArg(1)); - tp.copyIn(xc->getMemPtr()); + tp.copyIn(xc->port); struct timeval hostTimeval[2]; for (int i = 0; i < 2; ++i) diff --cc sim/system.cc index 07eb81c71,8820922c1..3ed7ed590 --- a/sim/system.cc +++ b/sim/system.cc @@@ -1,67 -1,32 +1,41 @@@ - /* - * 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. - */ - #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" -#include "base/remote_gdb.hh" #include "cpu/exec_context.hh" -#include "kern/kernel_stats.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" + #include "arch/vtophys.hh" +#include "mem/memory.hh" #include "sim/builder.hh" + #include "arch/isa_traits.hh" + #include "sim/byteswap.hh" #include "sim/system.hh" #include "base/trace.hh" +#if FULL_SYSTEM +#include "base/remote_gdb.hh" +#include "kern/kernel_stats.hh" +#include "mem/functional/memory_control.hh" +#include "targetarch/vtophys.hh" +#endif using namespace std; + using namespace TheISA; vector System::systemList; int System::numSystemsRunning = 0; System::System(Params *p) - : SimObject(p->name), memctrl(p->memctrl), physmem(p->physmem), - init_param(p->init_param), numcpus(0), _params(p) + : SimObject(p->name), physmem(p->physmem), numcpus(0), +#if FULL_SYSTEM + memctrl(p->memctrl), init_param(p->init_param), +#else + page_ptr(0), +#endif - params(p) ++ _params(p) { // add self to global system list systemList.push_back(this); +#if FULL_SYSTEM kernelSymtab = new SymbolTable; - consoleSymtab = new SymbolTable; - palSymtab = new SymbolTable; debugSymbolTable = new SymbolTable; /** @@@ -130,154 -63,22 +72,29 @@@ DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry); DPRINTF(Loader, "Kernel loaded...\n"); - Addr addr = 0; - #ifdef DEBUG - consolePanicEvent = addConsoleFuncEvent("panic"); - #endif - - /** - * Copy the osflags (kernel arguments) into the consoles - * memory. (Presently Linux does not use the console service - * routine to get these command line arguments, but Tru64 and - * others do.) - */ - if (consoleSymtab->findAddress("env_booted_osflags", addr)) { - Addr paddr = vtophys(physmem, addr); - char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t)); - - if (osflags) - strcpy(osflags, params->boot_osflags.c_str()); - } - - /** - * Set the hardware reset parameter block system type and revision - * information to Tsunami. - */ - if (consoleSymtab->findAddress("m5_rpb", addr)) { - Addr paddr = vtophys(physmem, addr); - char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t)); - - if (!hwrpb) - panic("could not translate hwrpb addr\n"); - - *(uint64_t*)(hwrpb+0x50) = htog(params->system_type); - *(uint64_t*)(hwrpb+0x58) = htog(params->system_rev); - } else - panic("could not find hwrpb\n"); - ++#if FULL_SYSTEM + kernelBinning = new Kernel::Binning(this); - +#endif // FULL_SYSTEM + // increment the number of running systms numSystemsRunning++; - - kernelBinning = new Kernel::Binning(this); } System::~System() { +#if FULL_SYSTEM delete kernelSymtab; - delete consoleSymtab; delete kernel; - delete console; - delete pal; delete kernelBinning; - - #ifdef DEBUG - delete consolePanicEvent; - #endif - - #endif // FULL_SYSTEM - } - - - /** - * This function fixes up addresses that are used to match PCs for - * hooking simulator events on to target function executions. - * - * Alpha binaries may have multiple global offset table (GOT) - * sections. A function that uses the GOT starts with a - * two-instruction prolog which sets the global pointer (gp == r29) to - * the appropriate GOT section. The proper gp value is calculated - * based on the function address, which must be passed by the caller - * in the procedure value register (pv aka t12 == r27). This sequence - * looks like the following: - * - * opcode Ra Rb offset - * ldah gp,X(pv) 09 29 27 X - * lda gp,Y(gp) 08 29 29 Y - * - * for some constant offsets X and Y. The catch is that the linker - * (or maybe even the compiler, I'm not sure) may recognize that the - * caller and callee are using the same GOT section, making this - * prolog redundant, and modify the call target to skip these - * instructions. If we check for execution of the first instruction - * of a function (the one the symbol points to) to detect when to skip - * it, we'll miss all these modified calls. It might work to - * unconditionally check for the third instruction, but not all - * functions have this prolog, and there's some chance that those - * first two instructions could have undesired consequences. So we do - * the Right Thing and pattern-match the first two instructions of the - * function to decide where to patch. - * - * Eventually this code should be moved into an ISA-specific file. - */ - Addr - System::fixFuncEventAddr(Addr addr) - { - #if FULL_SYSTEM - // mask for just the opcode, Ra, and Rb fields (not the offset) - const uint32_t inst_mask = 0xffff0000; - // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27 - const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16); - // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29 - const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16); - // instruction size - const int sz = sizeof(uint32_t); - - Addr paddr = vtophys(physmem, addr); - uint32_t i1 = *(uint32_t *)physmem->dma_addr(paddr, sz); - uint32_t i2 = *(uint32_t *)physmem->dma_addr(paddr+sz, sz); - - if ((i1 & inst_mask) == gp_ldah_pattern && - (i2 & inst_mask) == gp_lda_pattern) { - Addr new_addr = addr + 2*sz; - DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr); - return new_addr; - } else { - return addr; - } +#else + panic("System::fixFuncEventAddr needs to be rewritten " + "to work with syscall emulation"); +#endif // FULL_SYSTEM} } - +#if FULL_SYSTEM - void - System::setAlphaAccess(Addr access) - { - Addr addr = 0; - if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { - Addr paddr = vtophys(physmem, addr); - uint64_t *m5AlphaAccess = - (uint64_t *)physmem->dma_addr(paddr, sizeof(uint64_t)); - - if (!m5AlphaAccess) - panic("could not translate m5AlphaAccess addr\n"); - - *m5AlphaAccess = htog(EV5::Phys2K0Seg(access)); - } else - panic("could not find m5AlphaAccess\n"); - } - - bool - System::breakpoint() - { - return remoteGDB[0]->trap(ALPHA_KENTRY_INT); - } int rgdb_wait = -1; @@@ -372,9 -152,6 +187,7 @@@ System::serialize(ostream &os kernelBinning->serialize(os); kernelSymtab->serialize("kernel_symtab", os); - consoleSymtab->serialize("console_symtab", os); - palSymtab->serialize("pal_symtab", os); +#endif // FULL_SYSTEM } @@@ -385,9 -161,6 +198,7 @@@ System::unserialize(Checkpoint *cp, con kernelBinning->unserialize(cp, section); kernelSymtab->unserialize("kernel_symtab", cp, section); - consoleSymtab->unserialize("console_symtab", cp, section); - palSymtab->unserialize("pal_symtab", cp, section); +#endif // FULL_SYSTEM } void diff --cc sim/system.hh index 8922373cc,ea482a102..cbe876c42 --- a/sim/system.hh +++ b/sim/system.hh @@@ -104,18 -85,6 +92,13 @@@ class System : public SimObjec Kernel::Binning *kernelBinning; - #ifdef DEBUG - /** Event to halt the simulator if the console calls panic() */ - BreakPCEvent *consolePanicEvent; - #endif - +#else + + int page_ptr; + + +#endif // FULL_SYSTEM + protected: /** @@@ -150,27 -118,10 +133,13 @@@ return addFuncEvent(kernelSymtab, lbl); } - /** Add a function-based event to PALcode. */ - template - T *System::addPalFuncEvent(const char *lbl) - { - return addFuncEvent(palSymtab, lbl); - } - - /** Add a function-based event to the console code. */ - template - T *System::addConsoleFuncEvent(const char *lbl) - { - return addFuncEvent(consoleSymtab, lbl); - } +#endif - public: +#if FULL_SYSTEM std::vector remoteGDB; std::vector gdbListen; - bool breakpoint(); + virtual bool breakpoint() = 0; +#endif // FULL_SYSTEM public: struct Params @@@ -187,30 -136,21 +156,24 @@@ bool bin_int; std::string kernel_path; - std::string console_path; - std::string palcode; - std::string boot_osflags; - std::string readfile; - uint64_t system_type; - uint64_t system_rev; +#endif }; - Params *params; + protected: + Params *_params; + + public: System(Params *p); ~System(); void startup(); + const Params *params() const { return (const Params *)_params; } + public: + +#if FULL_SYSTEM - /** - * Set the m5AlphaAccess pointer in the console - */ - void setAlphaAccess(Addr access); - /** * Returns the addess the kernel starts at. * @return address the kernel starts at