diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2007-03-05 11:00:44 +0000 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2007-03-05 11:00:44 +0000 |
commit | 6a19b64de2044e5b166a9883be6531166cd69900 (patch) | |
tree | e463581d5611ac0a2223a292cc4d1231f3de6b1f /src | |
parent | 5498d5298577c07189ff3f7026eba5c1ee09cc1b (diff) | |
parent | ba042842c61339e33c0b684f9854e8fe818160fe (diff) | |
download | gem5-6a19b64de2044e5b166a9883be6531166cd69900.tar.xz |
Merge zizzer.eecs.umich.edu:/bk/newmem
into ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86
--HG--
extra : convert_revision : b585cea2221377eb2fceea8976c46a17c0034f51
Diffstat (limited to 'src')
55 files changed, 1831 insertions, 657 deletions
diff --git a/src/SConscript b/src/SConscript index c93605ff7..9d7248213 100644 --- a/src/SConscript +++ b/src/SConscript @@ -131,15 +131,19 @@ base_sources = Split(''' mem/cache/cache_builder.cc python/swig/init.cc + python/swig/core_wrap.cc python/swig/debug_wrap.cc - python/swig/main_wrap.cc python/swig/event_wrap.cc python/swig/random_wrap.cc + python/swig/sim_object_wrap.cc python/swig/stats_wrap.cc python/swig/trace_wrap.cc python/swig/pyevent.cc + python/swig/pyobject.cc + sim/async.cc sim/builder.cc + sim/core.cc sim/debug.cc sim/eventq.cc sim/faults.cc @@ -149,6 +153,7 @@ base_sources = Split(''' sim/serialize.cc sim/sim_events.cc sim/sim_object.cc + sim/simulate.cc sim/startup.cc sim/stat_control.cc sim/system.cc diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index a522dec6c..0500714ad 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); @@ -163,6 +159,12 @@ namespace AlphaISA 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/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/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/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/sparc/asi.cc b/src/arch/sparc/asi.cc index 3d553955f..d8cd84af5 100644 --- a/src/arch/sparc/asi.cc +++ b/src/arch/sparc/asi.cc @@ -294,7 +294,8 @@ namespace SparcISA bool AsiIsReg(ASI asi) { - return AsiIsMmu(asi) || AsiIsScratchPad(asi) | AsiIsSparcError(asi); + return AsiIsMmu(asi) || AsiIsScratchPad(asi) || + AsiIsSparcError(asi) || AsiIsInterrupt(asi); } bool AsiIsSparcError(ASI asi) diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 391dd7134..b1a6ae919 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}}; diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh index 5facc081d..0ba897e67 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> {}; diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh index dc3b235fe..3234002c5 100644 --- a/src/arch/sparc/interrupts.hh +++ b/src/arch/sparc/interrupts.hh @@ -24,76 +24,80 @@ * 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) @@ -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/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 1fbdd160d..d0b8827f3 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -113,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/process.cc b/src/arch/sparc/linux/process.cc index 9c7c0e643..10cde3af8 100644 --- a/src/arch/sparc/linux/process.cc +++ b/src/arch/sparc/linux/process.cc @@ -333,7 +333,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = { /* 233 */ SyscallDesc("stime", unimplementedFunc), /* 234 */ SyscallDesc("statfs64", unimplementedFunc), /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc), - /* 236 */ SyscallDesc("_llseek", unimplementedFunc), + /* 236 */ SyscallDesc("_llseek", _llseekFunc), /* 237 */ SyscallDesc("mlock", unimplementedFunc), /* 238 */ SyscallDesc("munlock", unimplementedFunc), /* 239 */ SyscallDesc("mlockall", unimplementedFunc), diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 9a69d3374..849eed1cc 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]; } @@ -608,7 +616,6 @@ 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); } @@ -639,6 +646,12 @@ 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; diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index 66c9f17df..4207de823 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -259,6 +259,9 @@ namespace SparcISA ThreadContext *tc); MiscReg readFSRegWithEffect(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. */ void processTickCompare(ThreadContext *tc); diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index d5a95e0c0..c3b833562 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -425,7 +425,9 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize) else filename = argv[0]; - Addr alignmentMask = ~(intSize - 1); + //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); @@ -525,21 +527,11 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize) 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. + //The info_block 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; + arg_data_size); //Each auxilliary vector is two 8 byte words int aux_array_size = intSize * 2 * (auxv.size() + 1); @@ -552,7 +544,6 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize) int space_needed = mysterious_size + - info_block_size + aux_array_size + envp_array_size + argv_array_size + @@ -568,18 +559,17 @@ Sparc32LiveProcess::argsInit(int intSize, int 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 + 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; + 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); @@ -619,8 +609,8 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize) initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(), (uint8_t*)&zero, 2 * intSize); - copyStringArray(envp, envp_array_base, env_data_base, initVirtMem, intSize); - copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem, 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); @@ -639,7 +629,7 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize) threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base); threadContexts[0]->setIntReg(StackPointerReg, stack_min); - Addr prog_entry = objFile->entryPoint(); + 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))); diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index 827e22c31..944b1f401 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -254,19 +254,6 @@ 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) { diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh index d9af0757c..9e0b3beb3 100644 --- a/src/arch/sparc/regfile.hh +++ b/src/arch/sparc/regfile.hh @@ -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/tlb.cc b/src/arch/sparc/tlb.cc index 2dca6d5e7..41d55158e 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -40,6 +40,7 @@ #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 * */ @@ -691,9 +692,9 @@ 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 (AsiIsInterrupt(asi)) + goto handleIntRegAccess; if (AsiIsMmu(asi)) goto handleMmuRegAccess; if (AsiIsScratchPad(asi)) @@ -793,7 +794,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)) { @@ -988,7 +1007,14 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt) tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1), tc->readMiscRegWithEffect(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", @@ -1222,7 +1248,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); diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index ecb63bb9a..5b13cd041 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -34,6 +34,30 @@ 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) @@ -43,23 +67,25 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, /* Full system only ASRs */ case MISCREG_SOFTINT: setReg(miscReg, val);; + checkSoftInt(tc); break; - case MISCREG_SOFTINT_CLR: return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc); case MISCREG_SOFTINT_SET: - tc->getCpuPtr()->post_interrupt(soft_interrupt); return setRegWithEffect(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()) + 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; @@ -71,8 +97,11 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, 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; @@ -81,6 +110,7 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, case MISCREG_PIL: setReg(miscReg, val); + checkSoftInt(tc); break; case MISCREG_HVER: @@ -88,6 +118,11 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, case MISCREG_HINTP: setReg(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. @@ -96,14 +131,32 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, case MISCREG_QUEUE_CPU_MONDO_HEAD: case MISCREG_QUEUE_CPU_MONDO_TAIL: + setReg(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: + setReg(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: + setReg(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 + // This one doesn't have an interrupt to report to the guest OS break; case MISCREG_HSTICK_CMPR: @@ -114,14 +167,23 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val, 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); +#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: case MISCREG_STRAND_STS_REG: @@ -198,7 +260,6 @@ MiscRegFile::processSTickCompare(ThreadContext *tc) 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); } } else @@ -221,10 +282,9 @@ MiscRegFile::processHSTickCompare(ThreadContext *tc) (stick_cmpr & mask(63))); if (!(tc->readMiscReg(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) { setRegWithEffect(MISCREG_HINTP, 1, tc); - tc->getCpuPtr()->post_interrupt(hstick_match); } // 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/base/bitfield.hh b/src/base/bitfield.hh index 0f1233677..83b9138b4 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -112,4 +112,29 @@ 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; +} + + + #endif // __BASE_BITFIELD_HH__ diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc index d4035986b..39a687fff 100644 --- a/src/base/stats/mysql.cc +++ b/src/base/stats/mysql.cc @@ -930,7 +930,7 @@ MySql::visit(const FormulaData &data) bool initMySQL(string host, string user, string password, string database, - string name, string sample, string project) + string project, string name, string sample) { extern list<Output *> OutputList; static MySql mysql; @@ -938,9 +938,6 @@ initMySQL(string host, string user, string password, string database, if (mysql.connected()) return false; - if (user.empty()) - user = username(); - mysql.connect(host, user, password, database, name, sample, project); OutputList.push_back(&mysql); diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh index 52f93ac61..0ce381c2f 100644 --- a/src/base/stats/mysql.hh +++ b/src/base/stats/mysql.hh @@ -187,15 +187,15 @@ 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 name = "test", - std::string sample = "0", std::string project = "test"); +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 name, std::string sample, - std::string project) + std::string database, std::string project, std::string name, + std::string sample) { return false; } diff --git a/src/cpu/base.cc b/src/cpu/base.cc index d5a023c59..104b3b6bb 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -372,12 +372,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); @@ -395,6 +389,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..d4213887d 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -102,10 +102,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); } 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/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/sparc/SConscript b/src/dev/sparc/SConscript index 44b082b68..4d63690c2 100644 --- a/src/dev/sparc/SConscript +++ b/src/dev/sparc/SConscript @@ -38,6 +38,7 @@ sources = [] sources += Split(''' dtod.cc + iob.cc t1000.cc mm_disk.cc ''') diff --git a/src/dev/sparc/iob.cc b/src/dev/sparc/iob.cc new file mode 100644 index 000000000..2cff02a99 --- /dev/null +++ b/src/dev/sparc/iob.cc @@ -0,0 +1,365 @@ +/* + * 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 "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/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); + 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; + return; + } + + if (accessAddr == JIntVecAddr) { + jIntVec = bits(pkt->get<uint64_t>(), 5,0); + 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); + return; + } + if (accessAddr == JIntABusyAddr) { + data = pkt->get<uint64_t>(); + jIntBusy[cpuid].busy = bits(data,5,5); + 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; + ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector); +} + + +void +Iob::generateIpi(Type type, int cpu_id, int vector) +{ + // Only handle interrupts for the moment... Cpu Idle/reset/resume will be + // later + if (type != 0) + return; + + assert(type == 0); + ic->post(cpu_id, SparcISA::IT_INT_VEC, vector); +} + +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; + + 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/python/SConscript b/src/python/SConscript index 8c7e47909..94db1a747 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -107,10 +107,11 @@ def swig_it(module): '-o ${TARGETS[0]} $SOURCES') swig_modules.append(module) -swig_it('main') +swig_it('core') swig_it('debug') swig_it('event') swig_it('random') +swig_it('sim_object') swig_it('stats') swig_it('trace') diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index ba79d3729..42266a80e 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -693,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() @@ -727,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. diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index f39cc670a..1c4a79020 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 +from internal.event import SimLoopExitEvent # import the m5 compile options import defines @@ -85,27 +87,60 @@ def instantiate(root): 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() + 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.event.cvar.curTick # register our C++ exit callback function with Python -atexit.register(internal.main.doExitCleanup) +atexit.register(internal.core.doExitCleanup) +atexit.register(internal.stats.dump) # This loops until all objects have been fully drained. def doDrain(root): @@ -119,7 +154,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 +162,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,16 +170,16 @@ 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): @@ -152,7 +187,7 @@ def changeToAtomic(system): "called on a root object." 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): @@ -160,7 +195,7 @@ def changeToTiming(system): "called on a root object." 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 +215,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 +223,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() @@ -198,6 +233,14 @@ def switchCpus(cpuList): new_cpu._ccObject.resume() index += 1 +def dumpStats(): + print 'Dumping stats' + internal.stats.dump() + +def resetStats(): + print 'Resetting stats' + internal.stats.reset() + # Since we have so many mutual imports in this package, we should: # 1. Put all intra-package imports at the *bottom* of the file, unless # they're absolutely needed before that (for top-level statements diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 37df884d0..54368b91e 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -240,7 +240,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:", @@ -256,7 +256,7 @@ def main(): 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 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/T1000.py b/src/python/m5/objects/T1000.py index aeca491c4..0acfa0920 100644 --- a/src/python/m5/objects/T1000.py +++ b/src/python/m5/objects/T1000.py @@ -1,6 +1,6 @@ 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 @@ -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!") @@ -76,6 +77,13 @@ class T1000(Platform): pconsole = SimConsole() puart0 = Uart8250(pio_addr=0x1f10000000) + 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. @@ -84,8 +92,6 @@ class T1000(Platform): 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 @@ -95,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..e71e1c3c5 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -894,9 +894,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 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/swig/core.i b/src/python/swig/core.i new file mode 100644 index 000000000..116890763 --- /dev/null +++ b/src/python/swig/core.i @@ -0,0 +1,57 @@ +/* + * 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 "std_string.i" + +void setOutputDir(const std::string &dir); +void loadIniFile(PyObject *); +void SimStartup(); +void doExitCleanup(); + +char *compileDate; + +%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..51d7d89f0 100644 --- a/src/python/swig/event.i +++ b/src/python/swig/event.i @@ -33,19 +33,48 @@ %{ #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); + +%immutable curTick; +Tick curTick; + +// 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); + +Tick curTick; %wrapper %{ // fix up module name to reflect the fact that it's inside the m5 package 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/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 index d6b39c2cb..d36f82dbc 100644 --- a/src/python/swig/stats.i +++ b/src/python/swig/stats.i @@ -42,12 +42,13 @@ 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 name = "test", - std::string sample = "0", std::string project = "test"); +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(); 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 6ee5eb46a..932f975d2 100644 --- a/src/sim/async.hh +++ b/src/sim/async.hh @@ -43,7 +43,8 @@ /// @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). diff --git a/src/sim/core.cc b/src/sim/core.cc new file mode 100644 index 000000000..24cc33da2 --- /dev/null +++ b/src/sim/core.cc @@ -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 + * Steve Reinhardt + */ + +#include <iostream> +#include <string> + +#include "base/callback.hh" +#include "base/output.hh" + +using namespace std; + +void +setOutputDir(const string &dir) +{ + simout.setDirectory(dir); +} + +/** + * 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..2ef21c4b6 --- /dev/null +++ b/src/sim/core.hh @@ -0,0 +1,40 @@ +/* + * 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 <Python.h> +#include <string> + +#include "base/callback.hh" + +void setOutputDir(const std::string &dir); + +void registerExitCallback(Callback *callback); +void doExitCleanup(); diff --git a/src/sim/main.cc b/src/sim/main.cc index 8e47ac6a0..0341b7d5f 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -25,79 +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/stats/output.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" 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; -volatile bool async_exception = 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. @@ -112,7 +72,7 @@ exitNowHandler(int sigtype) void abortHandler(int sigtype) { - cerr << "Program aborted at cycle " << curTick << endl; + ccprintf(cerr, "Program aborted at cycle %d\n", curTick); } int @@ -160,301 +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() -{ - // 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; - Stats::StatEvent(true, false); - } - - if (async_dumpreset) { - async_dumpreset = false; - Stats::StatEvent(true, true); - } - - 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 -} - -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(); - - // print simulation stats - Stats::dump(); -} diff --git a/src/sim/process.cc b/src/sim/process.cc index acc509a6f..b3ce182e5 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -300,24 +300,6 @@ DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process) //////////////////////////////////////////////////////////////////////// -void -copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr, - TranslatingPort* memPort, int ptr_size) -{ - 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, ptr_size); - memPort->writeString(data_ptr, strings[i].c_str()); - array_ptr += ptr_size; - data_ptr += strings[i].size() + 1; - } - // add NULL terminator - data_ptr = 0; - - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, ptr_size); -} - LiveProcess::LiveProcess(const string &nm, ObjectFile *_objFile, System *_system, int stdin_fd, int stdout_fd, int stderr_fd, diff --git a/src/sim/process.hh b/src/sim/process.hh index 1226db81b..dd64fa607 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -41,9 +41,11 @@ #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" @@ -58,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, int ptr_size = sizeof(Addr)); +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/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/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 f57bd5272..94ae8e3e6 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); @@ -448,14 +452,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: |