diff options
36 files changed, 2611 insertions, 1279 deletions
diff --git a/SConscript b/SConscript index 2726bbf20..677a06d1f 100644 --- a/SConscript +++ b/SConscript @@ -143,7 +143,6 @@ base_sources = Split(''' encumbered/cpu/full/issue.cc encumbered/cpu/full/ls_queue.cc encumbered/cpu/full/machine_queue.cc - encumbered/cpu/full/pc_sample_profile.cc encumbered/cpu/full/pipetrace.cc encumbered/cpu/full/readyq.cc encumbered/cpu/full/reg_info.cc @@ -244,6 +243,7 @@ full_system_sources = Split(''' arch/alpha/ev5.cc arch/alpha/osfpal.cc arch/alpha/pseudo_inst.cc + arch/alpha/stacktrace.cc arch/alpha/vtophys.cc base/crc.cc @@ -251,6 +251,7 @@ full_system_sources = Split(''' base/remote_gdb.cc cpu/intr_control.cc + cpu/profile.cc dev/alpha_console.cc dev/baddev.cc @@ -348,6 +349,7 @@ targetarch_files = Split(''' isa_traits.hh osfpal.hh pseudo_inst.hh + stacktrace.hh vptr.hh vtophys.hh ''') diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh index cc6d81478..2570d12f0 100644 --- a/arch/alpha/isa_traits.hh +++ b/arch/alpha/isa_traits.hh @@ -73,8 +73,10 @@ class AlphaISA // the rest of these depend on the ABI StackPointerReg = 30, GlobalPointerReg = 29, + ProcedureValueReg = 27, ReturnAddressReg = 26, ReturnValueReg = 0, + FramePointerReg = 15, ArgumentReg0 = 16, ArgumentReg1 = 17, ArgumentReg2 = 18, diff --git a/arch/alpha/stacktrace.cc b/arch/alpha/stacktrace.cc new file mode 100644 index 000000000..fdad9d673 --- /dev/null +++ b/arch/alpha/stacktrace.cc @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string> + +#include "arch/alpha/isa_traits.hh" +#include "arch/alpha/stacktrace.hh" +#include "arch/alpha/vtophys.hh" +#include "base/bitfield.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/exec_context.hh" + +using namespace std; + +ProcessInfo::ProcessInfo(ExecContext *_xc) + : xc(_xc) +{ + Addr addr = 0; + + if (!xc->system->kernelSymtab->findAddress("thread_info_size", addr)) + panic("thread info not compiled into kernel\n"); + thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); + + if (!xc->system->kernelSymtab->findAddress("task_struct_size", addr)) + panic("thread info not compiled into kernel\n"); + task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); + + if (!xc->system->kernelSymtab->findAddress("thread_info_task", addr)) + panic("thread info not compiled into kernel\n"); + task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); + + if (!xc->system->kernelSymtab->findAddress("task_struct_pid", addr)) + panic("thread info not compiled into kernel\n"); + pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); + + if (!xc->system->kernelSymtab->findAddress("task_struct_comm", addr)) + panic("thread info not compiled into kernel\n"); + name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); +} + +Addr +ProcessInfo::task(Addr ksp) const +{ + Addr base = ksp & ~0x3fff; + if (base == ULL(0xfffffc0000000000)) + return 0; + + Addr task; + CopyOut(xc, &task, base + task_off, sizeof(task)); + return task; +} + +int +ProcessInfo::pid(Addr ksp) const +{ + Addr task = this->task(ksp); + if (!task) + return -1; + + uint16_t pid; + CopyOut(xc, &pid, task + pid_off, sizeof(pid)); + return pid; +} + +string +ProcessInfo::name(Addr ksp) const +{ + Addr task = this->task(ksp); + if (!task) + return "console"; + + char comm[256]; + CopyString(xc, comm, task + name_off, sizeof(comm)); + if (!comm[0]) + return "startup"; + + return comm; +} + +StackTrace::StackTrace(ExecContext *_xc, bool is_call) + : xc(_xc) +{ + bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0; + + Addr pc = xc->regs.npc; + bool kernel = xc->system->kernelStart <= pc && pc <= xc->system->kernelEnd; + + if (usermode) { + stack.push_back(1); + return; + } + + if (!kernel) { + stack.push_back(2); + return; + } + + SymbolTable *symtab = xc->system->allSymtab; + Addr ksp = xc->regs.intRegFile[TheISA::StackPointerReg]; + Addr bottom = ksp & ~0x3fff; + Addr addr; + + if (is_call) { + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find address %#x", pc); + + stack.push_back(addr); + pc = xc->regs.pc; + } + + Addr ra; + int size; + + while (ksp > bottom) { + if (!symtab->findNearestAddr(pc, addr)) + panic("could not find symbol for pc=%#x", pc); + assert(pc >= addr && "symbol botch: callpc < func"); + + stack.push_back(addr); + + if (isEntry(addr)) + return; + + if (decodePrologue(ksp, pc, addr, size, ra)) { + if (!ra) + return; + + pc = ra; + ksp += size; + } else { + stack.push_back(3); + return; + } + + bool kernel = xc->system->kernelStart <= pc && + pc <= xc->system->kernelEnd; + if (!kernel) + return; + } + + panic("unwinding too far"); +} + +StackTrace::~StackTrace() +{ +} + +bool +StackTrace::isEntry(Addr addr) +{ + if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp12]) + return true; + + if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp7]) + return true; + + if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp11]) + return true; + + if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp21]) + return true; + + if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp9]) + return true; + + if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp2]) + return true; + + return false; +} + +bool +StackTrace::decodeStack(MachInst inst, int &disp) +{ + // lda $sp, -disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == 30 + // RB<20:16> == 30 + // Disp<15:0> + const MachInst mem_mask = 0xffff0000; + const MachInst lda_pattern = 0x23de0000; + const MachInst lda_disp_mask = 0x0000ffff; + + // subq $sp, disp, $sp + // addq $sp, disp, $sp + // + // Opcode<31:26> == 0x10 + // RA<25:21> == 30 + // Lit<20:13> + // One<12> = 1 + // Func<11:5> == 0x20 (addq) + // Func<11:5> == 0x29 (subq) + // RC<4:0> == 30 + const MachInst intop_mask = 0xffe01fff; + const MachInst addq_pattern = 0x43c0141e; + const MachInst subq_pattern = 0x43c0153e; + const MachInst intop_disp_mask = 0x001fe000; + const int intop_disp_shift = 13; + + if ((inst & mem_mask) == lda_pattern) + disp = -sext<16>(inst & lda_disp_mask); + else if ((inst & intop_mask) == addq_pattern) + disp = -int((inst & intop_disp_mask) >> intop_disp_shift); + else if ((inst & intop_mask) == subq_pattern) + disp = int((inst & intop_disp_mask) >> intop_disp_shift); + else + return false; + + return true; +} + +bool +StackTrace::decodeSave(MachInst inst, int ®, int &disp) +{ + // lda $stq, disp($sp) + // + // Opcode<31:26> == 0x08 + // RA<25:21> == ? + // RB<20:16> == 30 + // Disp<15:0> + const MachInst stq_mask = 0xfc1f0000; + const MachInst stq_pattern = 0xb41e0000; + const MachInst stq_disp_mask = 0x0000ffff; + const MachInst reg_mask = 0x03e00000; + const int reg_shift = 21; + + if ((inst & stq_mask) == stq_pattern) { + reg = (inst & reg_mask) >> reg_shift; + disp = sext<16>(inst & stq_disp_mask); + } else { + return false; + } + + return true; +} + +/* + * Decode the function prologue for the function we're in, and note + * which registers are stored where, and how large the stack frame is. + */ +bool +StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, + int &size, Addr &ra) +{ + size = 0; + ra = 0; + + for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { + MachInst inst; + CopyOut(xc, (uint8_t *)&inst, pc, sizeof(MachInst)); + + int reg, disp; + if (decodeStack(inst, disp)) { + if (size) { + // panic("decoding frame size again"); + return true; + } + size += disp; + } else if (decodeSave(inst, reg, disp)) { + if (!ra && reg == ReturnAddressReg) { + CopyOut(xc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); + if (!ra) { + // panic("no return address value pc=%#x\n", pc); + return false; + } + } + } + } + + return true; +} + +#if TRACING_ON +void +StackTrace::dump() +{ + StringWrap name(xc->cpu->name()); + SymbolTable *symtab = xc->system->allSymtab; + + DPRINTFN("------ Stack ------\n"); + + string symbol; + for (int i = 0, size = stack.size(); i < size; ++i) { + Addr addr = stack[size - i - 1]; + if (addr == 1) + symbol = "user"; + else if (addr == 2) + symbol = "console"; + else if (addr == 3) + symbol = "unknown"; + else + symtab->findSymbol(addr, symbol); + + DPRINTFN("%#x: %s\n", addr, symbol); + } +} +#endif diff --git a/arch/alpha/stacktrace.hh b/arch/alpha/stacktrace.hh new file mode 100644 index 000000000..5a4741eba --- /dev/null +++ b/arch/alpha/stacktrace.hh @@ -0,0 +1,99 @@ +/* + * Copyright (c) 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. + */ + +#ifndef __ARCH_ALPHA_STACKTRACE_HH__ +#define __ARCH_ALPHA_STACKTRACE_HH__ + +#include "base/trace.hh" +#include "cpu/static_inst.hh" + +class ExecContext; +class StackTrace; +class SymbolTable; + +class ProcessInfo +{ + private: + ExecContext *xc; + + int thread_info_size; + int task_struct_size; + int task_off; + int pid_off; + int name_off; + + public: + ProcessInfo(ExecContext *_xc); + + Addr task(Addr ksp) const; + int pid(Addr ksp) const; + std::string name(Addr ksp) const; +}; + +class StackTrace +{ + private: + ExecContext *xc; + std::vector<Addr> stack; + + private: + bool isEntry(Addr addr); + bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra); + bool decodeSave(MachInst inst, int ®, int &disp); + bool decodeStack(MachInst inst, int &disp); + + public: + StackTrace(ExecContext *xc, bool is_call); + ~StackTrace(); + + public: + const std::vector<Addr> &getstack() const { return stack; } + static StackTrace *create(ExecContext *xc, StaticInstPtr<TheISA> inst); + +#if TRACING_ON + private: + void dump(); + + public: + void dprintf() { if (DTRACE(Stack)) dump(); } +#else + public: + void dprintf() {} +#endif +}; + +inline StackTrace * +StackTrace::create(ExecContext *xc, StaticInstPtr<TheISA> inst) +{ + if (!inst->isCall() && !inst->isReturn()) + return NULL; + + return new StackTrace(xc, !inst->isReturn()); +} + +#endif // __ARCH_ALPHA_STACKTRACE_HH__ diff --git a/arch/isa_parser.py b/arch/isa_parser.py index eaef4b798..8f4c6bce7 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -794,20 +794,19 @@ def defFormat(id, params, code, lineno): ############## # Stack: a simple stack object. Used for both formats (formatStack) -# and default cases (defaultStack). +# and default cases (defaultStack). Simply wraps a list to give more +# stack-like syntax and enable initialization with an argument list +# (as opposed to an argument that's a list). -class Stack: - def __init__(self, initItem): - self.stack = [ initItem ] +class Stack(list): + def __init__(self, *items): + list.__init__(self, items) def push(self, item): - self.stack.append(item); - - def pop(self): - return self.stack.pop() + self.append(item); def top(self): - return self.stack[-1] + return self[-1] # The global format stack. formatStack = Stack(NoFormat()) diff --git a/base/traceflags.py b/base/traceflags.py index a7d9ff9bf..d44d44681 100644 --- a/base/traceflags.py +++ b/base/traceflags.py @@ -140,7 +140,8 @@ baseFlags = [ 'FullCPU', 'CommitRate', 'OoOCPU', - 'HWPrefetch' + 'HWPrefetch', + 'Stack', ] # diff --git a/cpu/base.cc b/cpu/base.cc index 8d97bc330..a6e71c808 100644 --- a/cpu/base.cc +++ b/cpu/base.cc @@ -142,8 +142,19 @@ BaseCPU::BaseCPU(Params *p) e->schedule(p->functionTraceStart); } } +#if FULL_SYSTEM + profileEvent = NULL; + if (params->profile) + profileEvent = new ProfileEvent(this, params->profile); +#endif } +BaseCPU::Params::Params() +{ +#if FULL_SYSTEM + profile = false; +#endif +} void BaseCPU::enableFunctionTrace() @@ -163,6 +174,16 @@ BaseCPU::init() } void +BaseCPU::startup() +{ +#if FULL_SYSTEM + if (!params->deferRegistration && profileEvent) + profileEvent->schedule(curTick); +#endif +} + + +void BaseCPU::regStats() { using namespace Stats; @@ -231,11 +252,32 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) for (int i = 0; i < NumInterruptLevels; ++i) interrupts[i] = oldCPU->interrupts[i]; intstatus = oldCPU->intstatus; + + for (int i = 0; i < execContexts.size(); ++i) + execContexts[i]->profile->clear(); + + if (profileEvent) + profileEvent->schedule(curTick); #endif } #if FULL_SYSTEM +BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, int _interval) + : Event(&mainEventQueue), cpu(_cpu), interval(_interval) +{ } + +void +BaseCPU::ProfileEvent::process() +{ + for (int i = 0, size = cpu->execContexts.size(); i < size; ++i) { + ExecContext *xc = cpu->execContexts[i]; + xc->profile->sample(xc->profileNode, xc->profilePC); + } + + schedule(curTick + interval); +} + void BaseCPU::post_interrupt(int int_num, int index) { diff --git a/cpu/base.hh b/cpu/base.hh index b9617a730..914d06982 100644 --- a/cpu/base.hh +++ b/cpu/base.hh @@ -33,6 +33,7 @@ #include "base/statistics.hh" #include "config/full_system.hh" +#include "cpu/profile.hh" #include "cpu/sampler/sampler.hh" #include "sim/eventq.hh" #include "sim/sim_object.hh" @@ -76,6 +77,18 @@ class BaseCPU : public SimObject bool check_interrupts() const { return intstatus != 0; } uint64_t intr_status() const { return intstatus; } + + class ProfileEvent : public Event + { + private: + BaseCPU *cpu; + int interval; + + public: + ProfileEvent(BaseCPU *cpu, int interval); + void process(); + }; + ProfileEvent *profileEvent; #endif protected: @@ -113,7 +126,10 @@ class BaseCPU : public SimObject #if FULL_SYSTEM System *system; int cpu_id; + Tick profile; #endif + + Params(); }; const Params *params; @@ -122,6 +138,7 @@ class BaseCPU : public SimObject virtual ~BaseCPU(); virtual void init(); + virtual void startup(); virtual void regStats(); void registerExecContexts(); diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc index 91578bdf1..3fe951387 100644 --- a/cpu/exec_context.cc +++ b/cpu/exec_context.cc @@ -32,10 +32,15 @@ #include "cpu/exec_context.hh" #if FULL_SYSTEM +#include "base/callback.hh" #include "base/cprintf.hh" +#include "base/output.hh" +#include "cpu/profile.hh" #include "kern/kernel_stats.hh" #include "sim/serialize.hh" +#include "sim/sim_exit.hh" #include "sim/system.hh" +#include "targetarch/stacktrace.hh" #else #include "sim/process.hh" #endif @@ -51,10 +56,24 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem), kernelBinning(system->kernelBinning), bin(kernelBinning->bin), - fnbin(kernelBinning->fnbin), func_exe_inst(0), storeCondFailures(0) + fnbin(kernelBinning->fnbin), profile(NULL), + func_exe_inst(0), storeCondFailures(0) { kernelStats = new Kernel::Statistics(this); memset(®s, 0, sizeof(RegFile)); + + if (cpu->params->profile) { + profile = new FunctionProfile(system->allSymtab); + Callback *cb = + new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this); + registerExitCallback(cb); + } + + // let's fill with a dummy node for now so we don't get a segfault + // on the first cycle when there's no node available. + static ProfileNode dummyNode; + profileNode = &dummyNode; + profilePC = 3; } #else ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, @@ -83,6 +102,14 @@ ExecContext::~ExecContext() #endif } +#if FULL_SYSTEM +void +ExecContext::dumpFuncProfile() +{ + std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); + profile->dump(this, *os); +} +#endif void ExecContext::takeOverFrom(ExecContext *oldContext) @@ -106,15 +133,6 @@ ExecContext::takeOverFrom(ExecContext *oldContext) oldContext->_status = ExecContext::Unallocated; } -#if FULL_SYSTEM -void -ExecContext::execute(const StaticInstBase *inst) -{ - assert(kernelStats); - system->kernelBinning->execute(this, inst); -} -#endif - void ExecContext::serialize(ostream &os) { diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index 6a17951f9..6f38a6960 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -46,8 +46,9 @@ class BaseCPU; #include "sim/system.hh" #include "targetarch/alpha_memory.hh" +class FunctionProfile; +class ProfileNode; class MemoryController; -class StaticInstBase; namespace Kernel { class Binning; class Statistics; } #else // !FULL_SYSTEM @@ -138,7 +139,11 @@ class ExecContext Kernel::Statistics *kernelStats; bool bin; bool fnbin; - void execute(const StaticInstBase *inst); + + FunctionProfile *profile; + ProfileNode *profileNode; + Addr profilePC; + void dumpFuncProfile(); #else Process *process; diff --git a/cpu/profile.cc b/cpu/profile.cc new file mode 100644 index 000000000..b17a3c74e --- /dev/null +++ b/cpu/profile.cc @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string> + +#include "base/bitfield.hh" +#include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/exec_context.hh" +#include "cpu/profile.hh" + +using namespace std; + +ProfileNode::ProfileNode() + : count(0) +{ } + +void +ProfileNode::dump(const string &symbol, uint64_t id, const SymbolTable *symtab, + ostream &os) const +{ + ccprintf(os, "%#x %s %d ", id, symbol, count); + ChildList::const_iterator i, end = children.end(); + for (i = children.begin(); i != end; ++i) { + const ProfileNode &node = i->second; + ccprintf(os, "%#x ", (intptr_t)&node); + } + + ccprintf(os, "\n"); + + for (i = children.begin(); i != end; ++i) { + Addr addr = i->first; + string symbol; + if (addr == 1) + symbol = "user"; + else if (addr == 2) + symbol = "console"; + else if (addr == 3) + symbol = "unknown"; + else if (!symtab->findSymbol(addr, symbol)) + panic("could not find symbol for address %#x\n", addr); + + const ProfileNode &node = i->second; + node.dump(symbol, (intptr_t)&node, symtab, os); + } +} + +void +ProfileNode::clear() +{ + count = 0; + ChildList::iterator i, end = children.end(); + for (i = children.begin(); i != end; ++i) { + ProfileNode &node = i->second; + node.clear(); + } + +} + +FunctionProfile::FunctionProfile(const SymbolTable *_symtab) + : symtab(_symtab) +{ +} + +FunctionProfile::~FunctionProfile() +{ +} + +ProfileNode * +FunctionProfile::consume(const StackTrace *trace) +{ + const vector<Addr> &stack = trace->getstack(); + ProfileNode *current = ⊤ + for (int i = 0, size = stack.size(); i < size; ++i) + current = ¤t->children[stack[size - i - 1]]; + + return current; +} + +void +FunctionProfile::clear() +{ + top.clear(); + pc_count.clear(); +} + +void +FunctionProfile::dump(ExecContext *xc, ostream &os) const +{ + ccprintf(os, ">>>PC data\n"); + map<Addr, Counter>::const_iterator i, end = pc_count.end(); + for (i = pc_count.begin(); i != end; ++i) { + Addr pc = i->first; + Counter count = i->second; + + std::string symbol; + if (pc == 1) + ccprintf(os, "user %d\n", count); + else if (symtab->findSymbol(pc, symbol) && !symbol.empty()) + ccprintf(os, "%s %d\n", symbol, count); + else + ccprintf(os, "%#x %d\n", pc, count); + } + + ccprintf(os, ">>>function data\n"); + top.dump("top", 0, symtab, os); +} + +void +FunctionProfile::sample(ProfileNode *node, Addr pc) +{ + node->count++; + + Addr symaddr; + if (symtab->findNearestAddr(pc, symaddr)) { + pc_count[symaddr]++; + } else { + // record PC even if we don't have a symbol to avoid + // silently biasing the histogram + pc_count[pc]++; + } +} diff --git a/cpu/profile.hh b/cpu/profile.hh new file mode 100644 index 000000000..9da170eb4 --- /dev/null +++ b/cpu/profile.hh @@ -0,0 +1,74 @@ +/* + * Copyright (c) 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. + */ + +#ifndef __CPU_PROFILE_HH__ +#define __CPU_PROFILE_HH__ + +#include <map> + +#include "cpu/static_inst.hh" +#include "sim/host.hh" +#include "targetarch/stacktrace.hh" + +class ProfileNode +{ + private: + friend class FunctionProfile; + + typedef std::map<Addr, ProfileNode> ChildList; + ChildList children; + + public: + int count; + + public: + ProfileNode(); + + void dump(const std::string &symbol, uint64_t id, + const SymbolTable *symtab, std::ostream &os) const; + void clear(); +}; + +class FunctionProfile +{ + private: + const SymbolTable *symtab; + ProfileNode top; + std::map<Addr, Counter> pc_count; + + public: + FunctionProfile(const SymbolTable *symtab); + ~FunctionProfile(); + + ProfileNode *consume(const StackTrace *trace); + void clear(); + void dump(ExecContext *xc, std::ostream &out) const; + void sample(ProfileNode *node, Addr pc); +}; + +#endif // __CPU_PROFILE_HH__ diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc index 1bd5547e7..8f7534e16 100644 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@ -50,6 +50,7 @@ #include "cpu/simple/cpu.hh" #include "cpu/smt.hh" #include "cpu/static_inst.hh" +#include "kern/kernel_stats.hh" #include "mem/base_mem.hh" #include "mem/mem_interface.hh" #include "sim/builder.hh" @@ -65,6 +66,7 @@ #include "mem/functional/physical.hh" #include "sim/system.hh" #include "targetarch/alpha_memory.hh" +#include "targetarch/stacktrace.hh" #include "targetarch/vtophys.hh" #else // !FULL_SYSTEM #include "mem/functional/functional.hh" @@ -753,8 +755,21 @@ SimpleCPU::tick() fault = curStaticInst->execute(this, traceData); #if FULL_SYSTEM - if (xc->fnbin) - xc->execute(curStaticInst.get()); + if (xc->fnbin) { + assert(xc->kernelStats); + system->kernelBinning->execute(xc, inst); + } + + if (xc->profile) { + bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0; + xc->profilePC = usermode ? 1 : xc->regs.pc; + StackTrace *trace = StackTrace::create(xc, inst); + if (trace) { + xc->profileNode = xc->profile->consume(trace); + trace->dprintf(); + delete trace; + } + } #endif if (curStaticInst->isMemRef()) { @@ -806,7 +821,6 @@ SimpleCPU::tick() tickEvent.schedule(curTick + cycles(1)); } - //////////////////////////////////////////////////////////////////////// // // SimpleCPU Simulation Object @@ -824,6 +838,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) SimObjectParam<FunctionalMemory *> mem; SimObjectParam<System *> system; Param<int> cpu_id; + Param<Tick> profile; #else SimObjectParam<Process *> workload; #endif // FULL_SYSTEM @@ -856,6 +871,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) INIT_PARAM(mem, "memory"), INIT_PARAM(system, "system object"), INIT_PARAM(cpu_id, "processor ID"), + INIT_PARAM(profile, ""), #else INIT_PARAM(workload, "processes to run"), #endif // FULL_SYSTEM @@ -894,6 +910,7 @@ CREATE_SIM_OBJECT(SimpleCPU) params->mem = mem; params->system = system; params->cpu_id = cpu_id; + params->profile = profile; #else params->process = workload; #endif diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc index d67c6cf95..0537c344a 100644 --- a/dev/ns_gige.cc +++ b/dev/ns_gige.cc @@ -127,7 +127,7 @@ NSGigE::NSGigE(Params *p) p->header_bus, 1, p->dma_no_allocate); } else if (p->payload_bus) { - pioInterface = newPioInterface(name() + ".pio2", p->hier, + pioInterface = newPioInterface(name() + ".pio", p->hier, p->payload_bus, this, &NSGigE::cacheAccess); @@ -771,7 +771,9 @@ NSGigE::read(MemReqPtr &req, uint8_t *data) break; case M5REG: - reg = params()->m5reg; + reg = 0; + if (params()->dedicated) + reg |= M5REG_DEDICATED; break; default: @@ -2529,20 +2531,17 @@ NSGigE::recvPacket(PacketPtr packet) if (!rxEnable) { DPRINTF(Ethernet, "receive disabled...packet dropped\n"); - interface->recvDone(); return true; } if (!rxFilterEnable) { DPRINTF(Ethernet, "receive packet filtering disabled . . . packet dropped\n"); - interface->recvDone(); return true; } if (rxFilter(packet)) { DPRINTF(Ethernet, "packet filtered...dropped\n"); - interface->recvDone(); return true; } @@ -2565,7 +2564,6 @@ NSGigE::recvPacket(PacketPtr packet) } rxFifo.push(packet); - interface->recvDone(); rxKick(); return true; @@ -2982,69 +2980,77 @@ REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) - Param<Addr> addr; Param<Tick> clock; - Param<Tick> tx_delay; - Param<Tick> rx_delay; - Param<Tick> intr_delay; + + Param<Addr> addr; SimObjectParam<MemoryController *> mmu; SimObjectParam<PhysicalMemory *> physmem; - Param<bool> rx_filter; - Param<string> hardware_address; + SimObjectParam<PciConfigAll *> configspace; + SimObjectParam<PciConfigData *> configdata; + SimObjectParam<Platform *> platform; + Param<uint32_t> pci_bus; + Param<uint32_t> pci_dev; + Param<uint32_t> pci_func; + + SimObjectParam<HierParams *> hier; SimObjectParam<Bus*> io_bus; SimObjectParam<Bus*> payload_bus; - SimObjectParam<HierParams *> hier; - Param<Tick> pio_latency; Param<bool> dma_desc_free; Param<bool> dma_data_free; Param<Tick> dma_read_delay; Param<Tick> dma_write_delay; Param<Tick> dma_read_factor; Param<Tick> dma_write_factor; - SimObjectParam<PciConfigAll *> configspace; - SimObjectParam<PciConfigData *> configdata; - SimObjectParam<Platform *> platform; - Param<uint32_t> pci_bus; - Param<uint32_t> pci_dev; - Param<uint32_t> pci_func; - Param<uint32_t> tx_fifo_size; - Param<uint32_t> rx_fifo_size; - Param<uint32_t> m5reg; Param<bool> dma_no_allocate; + Param<Tick> pio_latency; + Param<Tick> intr_delay; + + Param<Tick> rx_delay; + Param<Tick> tx_delay; + Param<uint32_t> rx_fifo_size; + Param<uint32_t> tx_fifo_size; + + Param<bool> rx_filter; + Param<string> hardware_address; + Param<bool> dedicated; END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) - INIT_PARAM(addr, "Device Address"), INIT_PARAM(clock, "State machine processor frequency"), - INIT_PARAM(tx_delay, "Transmit Delay"), - INIT_PARAM(rx_delay, "Receive Delay"), - INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), + + INIT_PARAM(addr, "Device Address"), INIT_PARAM(mmu, "Memory Controller"), INIT_PARAM(physmem, "Physical Memory"), - INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), - INIT_PARAM(hardware_address, "Ethernet Hardware Address"), - INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL), - INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false), - INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false), - INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), - INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), - INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), - INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), INIT_PARAM(configspace, "PCI Configspace"), INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(platform, "Platform"), INIT_PARAM(pci_bus, "PCI bus"), INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), - INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072), - INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072), - INIT_PARAM(m5reg, "m5 register"), - INIT_PARAM_DFLT(dma_no_allocate, "Should DMA reads allocate cache lines", true) + + INIT_PARAM(hier, "Hierarchy global variables"), + INIT_PARAM(io_bus, "The IO Bus to attach to for headers"), + INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"), + INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"), + INIT_PARAM(dma_data_free, "DMA of Data is free"), + INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), + INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), + INIT_PARAM(dma_read_factor, "multiplier for dma reads"), + INIT_PARAM(dma_write_factor, "multiplier for dma writes"), + INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"), + INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), + INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), + + INIT_PARAM(rx_delay, "Receive Delay"), + INIT_PARAM(tx_delay, "Transmit Delay"), + INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), + INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), + + INIT_PARAM(rx_filter, "Enable Receive Filter"), + INIT_PARAM(hardware_address, "Ethernet Hardware Address"), + INIT_PARAM(dedicated, "dedicate a kernel thread to the driver") END_INIT_SIM_OBJECT_PARAMS(NSGigE) @@ -3054,7 +3060,11 @@ CREATE_SIM_OBJECT(NSGigE) NSGigE::Params *params = new NSGigE::Params; params->name = getInstanceName(); + + params->clock = clock; + params->mmu = mmu; + params->pmem = physmem; params->configSpace = configspace; params->configData = configdata; params->plat = platform; @@ -3062,27 +3072,28 @@ CREATE_SIM_OBJECT(NSGigE) params->deviceNum = pci_dev; params->functionNum = pci_func; - params->clock = clock; - params->intr_delay = intr_delay; - params->pmem = physmem; - params->tx_delay = tx_delay; - params->rx_delay = rx_delay; params->hier = hier; params->header_bus = io_bus; params->payload_bus = payload_bus; - params->pio_latency = pio_latency; params->dma_desc_free = dma_desc_free; params->dma_data_free = dma_data_free; params->dma_read_delay = dma_read_delay; params->dma_write_delay = dma_write_delay; params->dma_read_factor = dma_read_factor; params->dma_write_factor = dma_write_factor; + params->dma_no_allocate = dma_no_allocate; + params->pio_latency = pio_latency; + params->intr_delay = intr_delay; + + params->rx_delay = rx_delay; + params->tx_delay = tx_delay; + params->rx_fifo_size = rx_fifo_size; + params->tx_fifo_size = tx_fifo_size; + params->rx_filter = rx_filter; params->eaddr = hardware_address; - params->tx_fifo_size = tx_fifo_size; - params->rx_fifo_size = rx_fifo_size; - params->m5reg = m5reg; - params->dma_no_allocate = dma_no_allocate; + params->dedicated = dedicated; + return new NSGigE(params); } diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh index 111003432..a04b52fe9 100644 --- a/dev/ns_gige.hh +++ b/dev/ns_gige.hh @@ -385,7 +385,7 @@ class NSGigE : public PciDev Net::EthAddr eaddr; uint32_t tx_fifo_size; uint32_t rx_fifo_size; - uint32_t m5reg; + bool dedicated; bool dma_no_allocate; }; diff --git a/dev/ns_gige_reg.h b/dev/ns_gige_reg.h index 54ffb9075..f919ff086 100644 --- a/dev/ns_gige_reg.h +++ b/dev/ns_gige_reg.h @@ -304,6 +304,10 @@ #define TANAR_FULL_DUP 0x00000020 #define TANAR_UNUSED 0x00000E1F +/* M5 control register */ +#define M5REG_RESERVED 0xfffffffe +#define M5REG_DEDICATED 0x00000001 + struct ns_desc32 { uint32_t link; /* link field to next descriptor in linked list */ uint32_t bufptr; /* pointer to the first fragment or buffer */ diff --git a/dev/sinic.cc b/dev/sinic.cc index 1914367bd..1a1456e5f 100644 --- a/dev/sinic.cc +++ b/dev/sinic.cc @@ -77,7 +77,7 @@ const char *TxStateStrings[] = // Sinic PCI Device // Base::Base(Params *p) - : PciDev(p), rxEnable(false), txEnable(false), cycleTime(p->cycle_time), + : PciDev(p), rxEnable(false), txEnable(false), clock(p->clock), intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false), cpuPendingIntr(false), intrEvent(0), interface(NULL) { @@ -94,8 +94,8 @@ Device::Device(Params *p) reset(); if (p->io_bus) { - pioInterface = newPioInterface(p->name, p->hier, p->io_bus, this, - &Device::cacheAccess); + pioInterface = newPioInterface(p->name + ".pio", p->hier, p->io_bus, + this, &Device::cacheAccess); pioLatency = p->pio_latency * p->io_bus->clockRate; @@ -108,7 +108,8 @@ Device::Device(Params *p) p->io_bus, 1, p->dma_no_allocate); } else if (p->payload_bus) { - pioInterface = newPioInterface(p->name, p->hier, p->payload_bus, this, + pioInterface = newPioInterface(p->name + ".pio", p->hier, + p->payload_bus, this, &Device::cacheAccess); pioLatency = p->pio_latency * p->payload_bus->clockRate; @@ -315,9 +316,26 @@ Device::writeConfig(int offset, int size, const uint8_t *data) } } +void +Device::prepareRead() +{ + using namespace Regs; + + // update rx registers + regs.RxDone = set_RxDone_Packets(regs.RxDone, rxFifo.packets()); + regs.RxWait = regs.RxDone; + + // update tx regsiters + regs.TxDone = set_TxDone_Packets(regs.TxDone, txFifo.packets()); + regs.TxDone = set_TxDone_Full(regs.TxDone, + txFifo.avail() < regs.TxMaxCopy); + regs.TxDone = set_TxDone_Low(regs.TxDone, + txFifo.size() < regs.TxFifoMark); + regs.TxWait = regs.TxDone; +} + /** - * This reads the device registers, which are detailed in the NS83820 - * spec sheet + * I/O read of device register */ Fault Device::read(MemReqPtr &req, uint8_t *data) @@ -327,118 +345,115 @@ Device::read(MemReqPtr &req, uint8_t *data) //The mask is to give you only the offset into the device register file Addr daddr = req->paddr & 0xfff; - if (Regs::regSize(daddr) == 0) - panic("invalid address: da=%#x pa=%#x va=%#x size=%d", + if (!regValid(daddr)) + panic("invalid register: da=%#x pa=%#x va=%#x size=%d", daddr, req->paddr, req->vaddr, req->size); - if (req->size != Regs::regSize(daddr)) - panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d", - Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); - - DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d\n", - Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); - - uint32_t ®32 = *(uint32_t *)data; - uint64_t ®64 = *(uint64_t *)data; + const Regs::Info &info = regInfo(daddr); + if (!info.read) + panic("reading write only register: %s: da=%#x pa=%#x va=%#x size=%d", + info.name, daddr, req->paddr, req->vaddr, req->size); - switch (daddr) { - case Regs::Config: - reg32 = regs.Config; - break; + if (req->size != info.size) + panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d", + info.name, daddr, req->paddr, req->vaddr, req->size); - case Regs::RxMaxCopy: - reg32 = regs.RxMaxCopy; - break; + prepareRead(); - case Regs::TxMaxCopy: - reg32 = regs.TxMaxCopy; - break; + uint64_t value = 0; + if (req->size == 4) { + uint32_t ® = *(uint32_t *)data; + reg = regData32(daddr); + value = reg; + } - case Regs::RxThreshold: - reg32 = regs.RxThreshold; - break; + if (req->size == 8) { + uint64_t ® = *(uint64_t *)data; + reg = regData64(daddr); + value = reg; + } - case Regs::TxThreshold: - reg32 = regs.TxThreshold; - break; + DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d val=%#x\n", + info.name, daddr, req->paddr, req->vaddr, req->size, value); - case Regs::IntrStatus: - reg32 = regs.IntrStatus; + // reading the interrupt status register has the side effect of + // clearing it + if (daddr == Regs::IntrStatus) devIntrClear(); - break; - case Regs::IntrMask: - reg32 = regs.IntrMask; - break; + return No_Fault; +} - case Regs::RxData: - reg64 = regs.RxData; - break; +/** + * IPR read of device register + */ +Fault +Device::iprRead(Addr daddr, uint64_t &result) +{ + if (!regValid(daddr)) + panic("invalid address: da=%#x", daddr); - case Regs::RxDone: - case Regs::RxWait: - reg64 = Regs::set_RxDone_FifoLen(regs.RxDone, - min(rxFifo.packets(), 255)); - break; + const Regs::Info &info = regInfo(daddr); + if (!info.read) + panic("reading write only register %s: da=%#x", info.name, daddr); - case Regs::TxData: - reg64 = regs.TxData; - break; + DPRINTF(EthernetPIO, "read reg=%s da=%#x\n", info.name, daddr); - case Regs::TxDone: - case Regs::TxWait: - reg64 = Regs::set_TxDone_FifoLen(regs.TxDone, - min(txFifo.packets(), 255)); - break; + prepareRead(); - case Regs::HwAddr: - reg64 = params()->eaddr; - break; + if (info.size == 4) + result = regData32(daddr); - default: - panic("reading write only register %s: da=%#x pa=%#x va=%#x size=%d", - Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); - } + if (info.size == 8) + result = regData64(daddr); - DPRINTF(EthernetPIO, "read reg=%s done val=%#x\n", Regs::regName(daddr), - Regs::regSize(daddr) == 4 ? reg32 : reg64); + DPRINTF(EthernetPIO, "IPR read reg=%s da=%#x val=%#x\n", + info.name, result); return No_Fault; } +/** + * I/O write of device register + */ Fault Device::write(MemReqPtr &req, const uint8_t *data) { assert(config.command & PCI_CMD_MSE); + + //The mask is to give you only the offset into the device register file Addr daddr = req->paddr & 0xfff; - if (Regs::regSize(daddr) == 0) + if (!regValid(daddr)) panic("invalid address: da=%#x pa=%#x va=%#x size=%d", daddr, req->paddr, req->vaddr, req->size); - if (req->size != Regs::regSize(daddr)) - panic("invalid size: reg=%s da=%#x pa=%#x va=%#x size=%d", - Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); + const Regs::Info &info = regInfo(daddr); + if (!info.write) + panic("writing read only register %s: da=%#x", info.name, daddr); + + if (req->size != info.size) + panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d", + info.name, daddr, req->paddr, req->vaddr, req->size); uint32_t reg32 = *(uint32_t *)data; uint64_t reg64 = *(uint64_t *)data; DPRINTF(EthernetPIO, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n", - Regs::regName(daddr), Regs::regSize(daddr) == 4 ? reg32 : reg64, - daddr, req->paddr, req->vaddr, req->size); - + info.name, info.size == 4 ? reg32 : reg64, daddr, req->paddr, + req->vaddr, req->size); switch (daddr) { case Regs::Config: changeConfig(reg32); break; - case Regs::RxThreshold: - regs.RxThreshold = reg32; + case Regs::Command: + command(reg32); break; - case Regs::TxThreshold: - regs.TxThreshold = reg32; + case Regs::IntrStatus: + devIntrClear(regs.IntrStatus & reg32); break; case Regs::IntrMask: @@ -447,9 +462,10 @@ Device::write(MemReqPtr &req, const uint8_t *data) case Regs::RxData: if (rxState != rxIdle) - panic("receive machine busy with another request!"); + panic("receive machine busy with another request! rxState=%s", + RxStateStrings[rxState]); - regs.RxDone = 0; + regs.RxDone = Regs::RxDone_Busy; regs.RxData = reg64; if (rxEnable) { rxState = rxFifoBlock; @@ -459,19 +475,16 @@ Device::write(MemReqPtr &req, const uint8_t *data) case Regs::TxData: if (txState != txIdle) - panic("transmit machine busy with another request!"); + panic("transmit machine busy with another request! txState=%s", + TxStateStrings[txState]); - regs.TxDone = 0; + regs.TxDone = Regs::TxDone_Busy; regs.TxData = reg64; if (txEnable) { txState = txFifoBlock; txKick(); } break; - - default: - panic("writing read only register %s: da=%#x pa=%#x va=%#x size=%d", - Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); } return No_Fault; @@ -489,9 +502,25 @@ Device::devIntrPost(uint32_t interrupts) "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n", interrupts, regs.IntrStatus, regs.IntrMask); - if ((regs.IntrStatus & regs.IntrMask)) { + interrupts = regs.IntrStatus & regs.IntrMask; + + // Intr_RxHigh is special, we only signal it if we've emptied the fifo + // and then filled it above the high watermark + if (rxEmpty) + rxEmpty = false; + else + interrupts &= ~Regs::Intr_RxHigh; + + // Intr_TxLow is special, we only signal it if we've filled up the fifo + // and then dropped below the low watermark + if (txFull) + txFull = false; + else + interrupts &= ~Regs::Intr_TxLow; + + if (interrupts) { Tick when = curTick; - if ((regs.IntrStatus & regs.IntrMask & Regs::Intr_NoDelay) == 0) + if ((interrupts & Regs::Intr_NoDelay) == 0) when += intrDelay; cpuIntrPost(when); } @@ -627,12 +656,6 @@ Device::changeConfig(uint32_t newconf) regs.Config = newconf; - if ((changed & Regs::Config_Reset)) { - assert(regs.Config & Regs::Config_Reset); - reset(); - regs.Config &= ~Regs::Config_Reset; - } - if ((changed & Regs::Config_IntEn)) { cpuIntrEnable = regs.Config & Regs::Config_IntEn; if (cpuIntrEnable) { @@ -657,19 +680,39 @@ Device::changeConfig(uint32_t newconf) } void +Device::command(uint32_t command) +{ + if (command & Regs::Command_Reset) + reset(); +} + +void Device::reset() { using namespace Regs; + memset(®s, 0, sizeof(regs)); + + regs.Config = 0; + if (params()->dedicated) + regs.Config |= Config_Thread; + regs.IntrMask = Intr_RxHigh | Intr_RxDMA | Intr_TxLow; regs.RxMaxCopy = params()->rx_max_copy; regs.TxMaxCopy = params()->tx_max_copy; - regs.IntrMask = Intr_TxFifo | Intr_RxFifo | Intr_RxData; + regs.RxMaxIntr = params()->rx_max_intr; + regs.RxFifoSize = params()->rx_fifo_size; + regs.TxFifoSize = params()->tx_fifo_size; + regs.RxFifoMark = params()->rx_fifo_threshold; + regs.TxFifoMark = params()->tx_fifo_threshold; + regs.HwAddr = params()->eaddr; rxState = rxIdle; txState = txIdle; rxFifo.clear(); txFifo.clear(); + rxEmpty = false; + txFull = false; } void @@ -680,13 +723,18 @@ Device::rxDmaCopy() physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", rxDmaAddr, rxDmaLen); - DDUMP(EthernetDMA, rxDmaData, rxDmaLen); + DDUMP(EthernetData, rxDmaData, rxDmaLen); } void Device::rxDmaDone() { rxDmaCopy(); + + // If the transmit state machine has a pending DMA, let it go first + if (txState == txBeginCopy) + txKick(); + rxKick(); } @@ -706,6 +754,8 @@ Device::rxKick() switch (rxState) { case rxIdle: if (rxPioRequest) { + DPRINTF(EthernetPIO, "rxIdle: PIO waiting responding at %d\n", + curTick + pioLatency); pioInterface->respond(rxPioRequest, curTick); rxPioRequest = 0; } @@ -761,20 +811,20 @@ Device::rxKick() break; case rxBeginCopy: + if (dmaInterface && dmaInterface->busy()) + goto exit; + rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(regs.RxData)); rxDmaLen = min<int>(Regs::get_RxData_Len(regs.RxData), rxPktBytes); rxDmaData = rxPacketBufPtr; + rxState = rxCopy; if (dmaInterface) { - if (!dmaInterface->busy()) { - dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, - curTick, &rxDmaEvent, true); - rxState = rxCopy; - } + dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, + curTick, &rxDmaEvent, true); goto exit; } - rxState = rxCopy; if (dmaWriteDelay != 0 || dmaWriteFactor != 0) { Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; Tick start = curTick + dmaWriteDelay + factor; @@ -802,7 +852,7 @@ Device::rxKick() } regs.RxDone |= Regs::RxDone_Complete; - devIntrPost(Regs::Intr_RxData); + devIntrPost(Regs::Intr_RxDMA); rxState = rxIdle; break; @@ -831,13 +881,18 @@ Device::txDmaCopy() physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", txDmaAddr, txDmaLen); - DDUMP(EthernetDMA, txDmaData, txDmaLen); + DDUMP(EthernetData, txDmaData, txDmaLen); } void Device::txDmaDone() { txDmaCopy(); + + // If the receive state machine has a pending DMA, let it go first + if (rxState == rxBeginCopy) + rxKick(); + txKick(); } @@ -849,6 +904,7 @@ Device::transmit() return; } + uint32_t interrupts; PacketPtr packet = txFifo.front(); if (!interface->sendPacket(packet)) { DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n", @@ -857,7 +913,6 @@ Device::transmit() } txFifo.pop(); - #if TRACING_ON if (DTRACE(Ethernet)) { IpPtr ip(packet); @@ -872,17 +927,17 @@ Device::transmit() } #endif - DDUMP(Ethernet, packet->data, packet->length); + DDUMP(EthernetData, packet->data, packet->length); txBytes += packet->length; txPackets++; DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n", txFifo.avail()); - if (txFifo.size() <= params()->tx_fifo_threshold) - devIntrPost(Regs::Intr_TxFifo); - - devIntrPost(Regs::Intr_TxDone); + interrupts = Regs::Intr_TxPacket; + if (txFifo.size() < regs.TxFifoMark) + interrupts |= Regs::Intr_TxLow; + devIntrPost(interrupts); reschedule: if (!txFifo.empty() && !txEvent.scheduled()) { @@ -907,6 +962,8 @@ Device::txKick() switch (txState) { case txIdle: if (txPioRequest) { + DPRINTF(EthernetPIO, "txIdle: PIO waiting responding at %d\n", + curTick + pioLatency); pioInterface->respond(txPioRequest, curTick + pioLatency); txPioRequest = 0; } @@ -929,21 +986,20 @@ Device::txKick() break; case txBeginCopy: + if (dmaInterface && dmaInterface->busy()) + goto exit; + txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(regs.TxData)); txDmaLen = Regs::get_TxData_Len(regs.TxData); txDmaData = txPacketBufPtr; + txState = txCopy; if (dmaInterface) { - if (!dmaInterface->busy()) { - dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, - curTick, &txDmaEvent, true); - txState = txCopy; - } - + dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, + curTick, &txDmaEvent, true); goto exit; } - txState = txCopy; if (dmaReadDelay != 0 || dmaReadFactor != 0) { Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; Tick start = curTick + dmaReadDelay + factor; @@ -987,12 +1043,16 @@ Device::txKick() } } txFifo.push(txPacket); + if (txFifo.avail() < regs.TxMaxCopy) { + devIntrPost(Regs::Intr_TxFull); + txFull = true; + } txPacket = 0; transmit(); } regs.TxDone = txDmaLen | Regs::TxDone_Complete; - devIntrPost(Regs::Intr_TxData); + devIntrPost(Regs::Intr_TxDMA); txState = txIdle; break; @@ -1085,18 +1145,16 @@ Device::recvPacket(PacketPtr packet) if (!rxEnable) { DPRINTF(Ethernet, "receive disabled...packet dropped\n"); - interface->recvDone(); return true; } if (rxFilter(packet)) { DPRINTF(Ethernet, "packet filtered...dropped\n"); - interface->recvDone(); return true; } - if (rxFifo.size() >= params()->rx_fifo_threshold) - devIntrPost(Regs::Intr_RxFifo); + if (rxFifo.size() >= regs.RxFifoMark) + devIntrPost(Regs::Intr_RxHigh); if (!rxFifo.push(packet)) { DPRINTF(Ethernet, @@ -1104,8 +1162,7 @@ Device::recvPacket(PacketPtr packet) return false; } - interface->recvDone(); - devIntrPost(Regs::Intr_RxDone); + devIntrPost(Regs::Intr_RxPacket); rxKick(); return true; } @@ -1163,22 +1220,23 @@ Device::serialize(ostream &os) // Serialize the PciDev base class Base::serialize(os); - if (rxDmaEvent.scheduled()) - rxDmaCopy(); + if (rxState == rxCopy) + panic("can't serialize with an in flight dma request rxState=%s", + RxStateStrings[rxState]); - if (txDmaEvent.scheduled()) - txDmaCopy(); + if (txState == txCopy) + panic("can't serialize with an in flight dma request txState=%s", + TxStateStrings[txState]); /* * Serialize the device registers */ SERIALIZE_SCALAR(regs.Config); - SERIALIZE_SCALAR(regs.RxMaxCopy); - SERIALIZE_SCALAR(regs.TxMaxCopy); - SERIALIZE_SCALAR(regs.RxThreshold); - SERIALIZE_SCALAR(regs.TxThreshold); SERIALIZE_SCALAR(regs.IntrStatus); SERIALIZE_SCALAR(regs.IntrMask); + SERIALIZE_SCALAR(regs.RxMaxCopy); + SERIALIZE_SCALAR(regs.TxMaxCopy); + SERIALIZE_SCALAR(regs.RxMaxIntr); SERIALIZE_SCALAR(regs.RxData); SERIALIZE_SCALAR(regs.RxDone); SERIALIZE_SCALAR(regs.TxData); @@ -1189,6 +1247,7 @@ Device::serialize(ostream &os) */ int rxState = this->rxState; SERIALIZE_SCALAR(rxState); + SERIALIZE_SCALAR(rxEmpty); rxFifo.serialize("rxFifo", os); bool rxPacketExists = rxPacket; SERIALIZE_SCALAR(rxPacketExists); @@ -1205,6 +1264,7 @@ Device::serialize(ostream &os) */ int txState = this->txState; SERIALIZE_SCALAR(txState); + SERIALIZE_SCALAR(txFull); txFifo.serialize("txFifo", os); bool txPacketExists = txPacket; SERIALIZE_SCALAR(txPacketExists); @@ -1233,12 +1293,11 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) * Unserialize the device registers */ UNSERIALIZE_SCALAR(regs.Config); - UNSERIALIZE_SCALAR(regs.RxMaxCopy); - UNSERIALIZE_SCALAR(regs.TxMaxCopy); - UNSERIALIZE_SCALAR(regs.RxThreshold); - UNSERIALIZE_SCALAR(regs.TxThreshold); UNSERIALIZE_SCALAR(regs.IntrStatus); UNSERIALIZE_SCALAR(regs.IntrMask); + UNSERIALIZE_SCALAR(regs.RxMaxCopy); + UNSERIALIZE_SCALAR(regs.TxMaxCopy); + UNSERIALIZE_SCALAR(regs.RxMaxIntr); UNSERIALIZE_SCALAR(regs.RxData); UNSERIALIZE_SCALAR(regs.RxDone); UNSERIALIZE_SCALAR(regs.TxData); @@ -1249,6 +1308,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) */ int rxState; UNSERIALIZE_SCALAR(rxState); + UNSERIALIZE_SCALAR(rxEmpty); this->rxState = (RxState) rxState; rxFifo.unserialize("rxFifo", cp, section); bool rxPacketExists; @@ -1269,6 +1329,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) */ int txState; UNSERIALIZE_SCALAR(txState); + UNSERIALIZE_SCALAR(txFull); this->txState = (TxState) txState; txFifo.unserialize("txFifo", cp, section); bool txPacketExists; @@ -1310,15 +1371,19 @@ Device::cacheAccess(MemReqPtr &req) Tick when = curTick + pioLatency; switch (daddr) { - case Regs::RxDone: + case Regs::RxWait: if (rxState != rxIdle) { + DPRINTF(EthernetPIO, "rxState=%s (not idle)... waiting\n", + TxStateStrings[txState]); rxPioRequest = req; when = 0; } break; - case Regs::TxDone: + case Regs::TxWait: if (txState != txIdle) { + DPRINTF(EthernetPIO, "txState=%s (not idle)... waiting\n", + TxStateStrings[txState]); txPioRequest = req; when = 0; } @@ -1360,71 +1425,83 @@ REGISTER_SIM_OBJECT("SinicInt", Interface) BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) + Param<Tick> clock; + Param<Addr> addr; - Param<Tick> cycle_time; - Param<Tick> tx_delay; - Param<Tick> rx_delay; - Param<Tick> intr_delay; SimObjectParam<MemoryController *> mmu; SimObjectParam<PhysicalMemory *> physmem; - Param<bool> rx_filter; - Param<string> hardware_address; - SimObjectParam<Bus*> io_bus; - SimObjectParam<Bus*> payload_bus; - SimObjectParam<HierParams *> hier; - Param<Tick> pio_latency; SimObjectParam<PciConfigAll *> configspace; SimObjectParam<PciConfigData *> configdata; SimObjectParam<Platform *> platform; Param<uint32_t> pci_bus; Param<uint32_t> pci_dev; Param<uint32_t> pci_func; + + SimObjectParam<HierParams *> hier; + SimObjectParam<Bus*> io_bus; + SimObjectParam<Bus*> payload_bus; + Param<Tick> dma_read_delay; + Param<Tick> dma_read_factor; + Param<Tick> dma_write_delay; + Param<Tick> dma_write_factor; + Param<bool> dma_no_allocate; + Param<Tick> pio_latency; + Param<Tick> intr_delay; + + Param<Tick> rx_delay; + Param<Tick> tx_delay; Param<uint32_t> rx_max_copy; Param<uint32_t> tx_max_copy; + Param<uint32_t> rx_max_intr; Param<uint32_t> rx_fifo_size; Param<uint32_t> tx_fifo_size; Param<uint32_t> rx_fifo_threshold; Param<uint32_t> tx_fifo_threshold; - Param<Tick> dma_read_delay; - Param<Tick> dma_read_factor; - Param<Tick> dma_write_delay; - Param<Tick> dma_write_factor; - Param<bool> dma_no_allocate; + + Param<bool> rx_filter; + Param<string> hardware_address; + Param<bool> dedicated; END_DECLARE_SIM_OBJECT_PARAMS(Device) BEGIN_INIT_SIM_OBJECT_PARAMS(Device) + INIT_PARAM(clock, "State machine cycle time"), + INIT_PARAM(addr, "Device Address"), - INIT_PARAM(cycle_time, "State machine cycle time"), - INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000), - INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000), - INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0), INIT_PARAM(mmu, "Memory Controller"), INIT_PARAM(physmem, "Physical Memory"), - INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), - INIT_PARAM(hardware_address, "Ethernet Hardware Address"), - INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL), - INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), - INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), INIT_PARAM(configspace, "PCI Configspace"), INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(platform, "Platform"), INIT_PARAM(pci_bus, "PCI bus"), INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_func, "PCI function code"), - INIT_PARAM_DFLT(rx_max_copy, "rx max copy", 16*1024), - INIT_PARAM_DFLT(tx_max_copy, "rx max copy", 16*1024), - INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 64*1024), - INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 64*1024), - INIT_PARAM_DFLT(rx_fifo_threshold, "max size in bytes of rxFifo", 48*1024), - INIT_PARAM_DFLT(tx_fifo_threshold, "max size in bytes of txFifo", 16*1024), - INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), - INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), - INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), - INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), - INIT_PARAM_DFLT(dma_no_allocate, "Should we allocat on read in cache", true) + + INIT_PARAM(hier, "Hierarchy global variables"), + INIT_PARAM(io_bus, "The IO Bus to attach to for headers"), + INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"), + INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), + INIT_PARAM(dma_read_factor, "multiplier for dma reads"), + INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), + INIT_PARAM(dma_write_factor, "multiplier for dma writes"), + INIT_PARAM(dma_no_allocate, "Should we allocat on read in cache"), + INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), + INIT_PARAM(intr_delay, "Interrupt Delay"), + + INIT_PARAM(rx_delay, "Receive Delay"), + INIT_PARAM(tx_delay, "Transmit Delay"), + INIT_PARAM(rx_max_copy, "rx max copy"), + INIT_PARAM(tx_max_copy, "rx max copy"), + INIT_PARAM(rx_max_intr, "rx max intr"), + INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), + INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), + INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"), + INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"), + + INIT_PARAM(rx_filter, "Enable Receive Filter"), + INIT_PARAM(hardware_address, "Ethernet Hardware Address"), + INIT_PARAM(dedicated, "dedicate a kernel thread to the driver") END_INIT_SIM_OBJECT_PARAMS(Device) @@ -1432,36 +1509,45 @@ END_INIT_SIM_OBJECT_PARAMS(Device) CREATE_SIM_OBJECT(Device) { Device::Params *params = new Device::Params; + params->name = getInstanceName(); - params->intr_delay = intr_delay; - params->physmem = physmem; - params->cycle_time = cycle_time; - params->tx_delay = tx_delay; - params->rx_delay = rx_delay; + + params->clock = clock; + params->mmu = mmu; - params->hier = hier; - params->io_bus = io_bus; - params->payload_bus = payload_bus; - params->pio_latency = pio_latency; + params->physmem = physmem; params->configSpace = configspace; params->configData = configdata; params->plat = platform; params->busNum = pci_bus; params->deviceNum = pci_dev; params->functionNum = pci_func; - params->rx_filter = rx_filter; - params->eaddr = hardware_address; + + params->hier = hier; + params->io_bus = io_bus; + params->payload_bus = payload_bus; + params->dma_read_delay = dma_read_delay; + params->dma_read_factor = dma_read_factor; + params->dma_write_delay = dma_write_delay; + params->dma_write_factor = dma_write_factor; + params->dma_no_allocate = dma_no_allocate; + params->pio_latency = pio_latency; + params->intr_delay = intr_delay; + + params->tx_delay = tx_delay; + params->rx_delay = rx_delay; params->rx_max_copy = rx_max_copy; params->tx_max_copy = tx_max_copy; + params->rx_max_intr = rx_max_intr; params->rx_fifo_size = rx_fifo_size; params->tx_fifo_size = tx_fifo_size; params->rx_fifo_threshold = rx_fifo_threshold; params->tx_fifo_threshold = tx_fifo_threshold; - params->dma_read_delay = dma_read_delay; - params->dma_read_factor = dma_read_factor; - params->dma_write_delay = dma_write_delay; - params->dma_write_factor = dma_write_factor; - params->dma_no_allocate = dma_no_allocate; + + params->rx_filter = rx_filter; + params->eaddr = hardware_address; + params->dedicated = dedicated; + return new Device(params); } diff --git a/dev/sinic.hh b/dev/sinic.hh index d190746a4..e01015061 100644 --- a/dev/sinic.hh +++ b/dev/sinic.hh @@ -48,8 +48,8 @@ class Base : public PciDev protected: bool rxEnable; bool txEnable; - Tick cycleTime; - inline Tick cycles(int numCycles) const { return numCycles * cycleTime; } + Tick clock; + inline Tick cycles(int numCycles) const { return numCycles * clock; } protected: Tick intrDelay; @@ -81,7 +81,7 @@ class Base : public PciDev public: struct Params : public PciDev::Params { - Tick cycle_time; + Tick clock; Tick intr_delay; }; @@ -115,19 +115,31 @@ class Device : public Base /** device register file */ struct { - uint32_t Config; - uint32_t RxMaxCopy; - uint32_t TxMaxCopy; - uint32_t RxThreshold; - uint32_t TxThreshold; - uint32_t IntrStatus; - uint32_t IntrMask; - uint64_t RxData; - uint64_t RxDone; - uint64_t TxData; - uint64_t TxDone; + uint32_t Config; // 0x00 + uint32_t Command; // 0x04 + uint32_t IntrStatus; // 0x08 + uint32_t IntrMask; // 0x0c + uint32_t RxMaxCopy; // 0x10 + uint32_t TxMaxCopy; // 0x14 + uint32_t RxMaxIntr; // 0x18 + uint32_t Reserved0; // 0x1c + uint32_t RxFifoSize; // 0x20 + uint32_t TxFifoSize; // 0x24 + uint32_t RxFifoMark; // 0x28 + uint32_t TxFifoMark; // 0x2c + uint64_t RxData; // 0x30 + uint64_t RxDone; // 0x38 + uint64_t RxWait; // 0x40 + uint64_t TxData; // 0x48 + uint64_t TxDone; // 0x50 + uint64_t TxWait; // 0x58 + uint64_t HwAddr; // 0x60 } regs; + uint8_t ®Data8(Addr daddr) { return *((uint8_t *)®s + daddr); } + uint32_t ®Data32(Addr daddr) { return *(uint32_t *)®Data8(daddr); } + uint64_t ®Data64(Addr daddr) { return *(uint64_t *)®Data8(daddr); } + private: Addr addr; static const Addr size = Regs::Size; @@ -135,6 +147,7 @@ class Device : public Base protected: RxState rxState; PacketFifo rxFifo; + bool rxEmpty; PacketPtr rxPacket; uint8_t *rxPacketBufPtr; int rxPktBytes; @@ -145,6 +158,7 @@ class Device : public Base TxState txState; PacketFifo txFifo; + bool txFull; PacketPtr txPacket; uint8_t *txPacketBufPtr; int txPktBytes; @@ -191,6 +205,7 @@ class Device : public Base * device configuration */ void changeConfig(uint32_t newconfig); + void command(uint32_t command); /** * device ethernet interface @@ -212,7 +227,7 @@ class Device : public Base void txDmaCopy(); void txDmaDone(); friend class EventWrapper<Device, &Device::txDmaDone>; - EventWrapper<Device, &Device::rxDmaDone> txDmaEvent; + EventWrapper<Device, &Device::txDmaDone> txDmaEvent; Tick dmaReadDelay; Tick dmaReadFactor; @@ -244,6 +259,8 @@ class Device : public Base * Memory Interface */ public: + void prepareRead(); + Fault iprRead(Addr daddr, uint64_t &result); virtual Fault read(MemReqPtr &req, uint8_t *data); virtual Fault write(MemReqPtr &req, const uint8_t *data); Tick cacheAccess(MemReqPtr &req); @@ -308,6 +325,7 @@ class Device : public Base Net::EthAddr eaddr; uint32_t rx_max_copy; uint32_t tx_max_copy; + uint32_t rx_max_intr; uint32_t rx_fifo_size; uint32_t tx_fifo_size; uint32_t rx_fifo_threshold; @@ -317,6 +335,7 @@ class Device : public Base Tick dma_write_delay; Tick dma_write_factor; bool dma_no_allocate; + bool dedicated; }; protected: diff --git a/dev/sinicreg.hh b/dev/sinicreg.hh index 78b175f71..12f545255 100644 --- a/dev/sinicreg.hh +++ b/dev/sinicreg.hh @@ -57,23 +57,28 @@ namespace Regs { // Registers __SINIC_REG32(Config, 0x00); // 32: configuration register -__SINIC_REG32(RxMaxCopy, 0x04); // 32: max rx copy -__SINIC_REG32(TxMaxCopy, 0x08); // 32: max tx copy -__SINIC_REG32(RxThreshold, 0x0c); // 32: receive fifo threshold -__SINIC_REG32(TxThreshold, 0x10); // 32: transmit fifo threshold -__SINIC_REG32(IntrStatus, 0x14); // 32: interrupt status -__SINIC_REG32(IntrMask, 0x18); // 32: interrupt mask -__SINIC_REG32(RxData, 0x20); // 64: receive data -__SINIC_REG32(RxDone, 0x28); // 64: receive done -__SINIC_REG32(RxWait, 0x30); // 64: receive done (busy wait) -__SINIC_REG32(TxData, 0x38); // 64: transmit data -__SINIC_REG32(TxDone, 0x40); // 64: transmit done -__SINIC_REG32(TxWait, 0x48); // 64: transmit done (busy wait) -__SINIC_REG32(HwAddr, 0x50); // 64: mac address -__SINIC_REG32(Size, 0x58); +__SINIC_REG32(Command, 0x04); // 32: command register +__SINIC_REG32(IntrStatus, 0x08); // 32: interrupt status +__SINIC_REG32(IntrMask, 0x0c); // 32: interrupt mask +__SINIC_REG32(RxMaxCopy, 0x10); // 32: max bytes per rx copy +__SINIC_REG32(TxMaxCopy, 0x14); // 32: max bytes per tx copy +__SINIC_REG32(RxMaxIntr, 0x18); // 32: max receives per interrupt +__SINIC_REG32(Reserved0, 0x1c); // 32: reserved +__SINIC_REG32(RxFifoSize, 0x20); // 32: rx fifo capacity in bytes +__SINIC_REG32(TxFifoSize, 0x24); // 32: tx fifo capacity in bytes +__SINIC_REG32(RxFifoMark, 0x28); // 32: rx fifo high watermark +__SINIC_REG32(TxFifoMark, 0x2c); // 32: tx fifo low watermark +__SINIC_REG32(RxData, 0x30); // 64: receive data +__SINIC_REG32(RxDone, 0x38); // 64: receive done +__SINIC_REG32(RxWait, 0x40); // 64: receive done (busy wait) +__SINIC_REG32(TxData, 0x48); // 64: transmit data +__SINIC_REG32(TxDone, 0x50); // 64: transmit done +__SINIC_REG32(TxWait, 0x58); // 64: transmit done (busy wait) +__SINIC_REG32(HwAddr, 0x60); // 64: mac address +__SINIC_REG32(Size, 0x68); // register addres space size // Config register bits -__SINIC_VAL32(Config_Reset, 31, 1); // reset chip +__SINIC_VAL32(Config_Thread, 8, 1); // enable receive filter __SINIC_VAL32(Config_Filter, 7, 1); // enable receive filter __SINIC_VAL32(Config_Vlan, 6, 1); // enable vlan tagging __SINIC_VAL32(Config_Virtual, 5, 1); // enable virtual addressing @@ -83,105 +88,103 @@ __SINIC_VAL32(Config_IntEn, 2, 1); // enable interrupts __SINIC_VAL32(Config_TxEn, 1, 1); // enable transmit __SINIC_VAL32(Config_RxEn, 0, 1); // enable receive +// Command register bits +__SINIC_VAL32(Command_Reset, 0, 1); // reset chip + // Interrupt register bits -__SINIC_VAL32(Intr_TxFifo, 5, 1); // Fifo oflow/uflow/threshold -__SINIC_VAL32(Intr_TxData, 4, 1); // DMA Completed w/ interrupt -__SINIC_VAL32(Intr_TxDone, 3, 1); // Packet transmitted -__SINIC_VAL32(Intr_RxFifo, 2, 1); // Fifo oflow/uflow/threshold -__SINIC_VAL32(Intr_RxData, 1, 1); // DMA Completed w/ interrupt -__SINIC_VAL32(Intr_RxDone, 0, 1); // Packet received -__SINIC_REG32(Intr_All, 0x3f); -__SINIC_REG32(Intr_NoDelay, 0x24); -__SINIC_REG32(Intr_Res, ~0x3f); +__SINIC_VAL32(Intr_TxLow, 7, 1); // tx fifo dropped below watermark +__SINIC_VAL32(Intr_TxFull, 6, 1); // tx fifo full +__SINIC_VAL32(Intr_TxDMA, 5, 1); // tx dma completed w/ interrupt +__SINIC_VAL32(Intr_TxPacket, 4, 1); // packet transmitted +__SINIC_VAL32(Intr_RxHigh, 3, 1); // rx fifo above high watermark +__SINIC_VAL32(Intr_RxEmpty, 2, 1); // rx fifo empty +__SINIC_VAL32(Intr_RxDMA, 1, 1); // rx dma completed w/ interrupt +__SINIC_VAL32(Intr_RxPacket, 0, 1); // packet received +__SINIC_REG32(Intr_All, 0xff); // all valid interrupts +__SINIC_REG32(Intr_NoDelay, 0xcc); // interrupts that shouldn't be coalesced +__SINIC_REG32(Intr_Res, ~0xff); // reserved interrupt bits // RX Data Description __SINIC_VAL64(RxData_Len, 40, 20); // 0 - 1M __SINIC_VAL64(RxData_Addr, 0, 40); // Address 1TB // TX Data Description -__SINIC_VAL64(TxData_More, 63, 1); -__SINIC_VAL64(TxData_Checksum, 62, 1); +__SINIC_VAL64(TxData_More, 63, 1); // Packet not complete (will dma more) +__SINIC_VAL64(TxData_Checksum, 62, 1); // do checksum __SINIC_VAL64(TxData_Len, 40, 20); // 0 - 1M __SINIC_VAL64(TxData_Addr, 0, 40); // Address 1TB // RX Done/Busy Information -__SINIC_VAL64(RxDone_Complete, 63, 1); -__SINIC_VAL64(RxDone_IpPacket, 45, 1); -__SINIC_VAL64(RxDone_TcpPacket, 44, 1); -__SINIC_VAL64(RxDone_UdpPacket, 43, 1); -__SINIC_VAL64(RxDone_IpError, 42, 1); -__SINIC_VAL64(RxDone_TcpError, 41, 1); -__SINIC_VAL64(RxDone_UdpError, 40, 1); -__SINIC_VAL64(RxDone_More, 32, 1); -__SINIC_VAL64(RxDone_FifoLen, 20, 8); // up to 255 packets +__SINIC_VAL64(RxDone_Packets, 32, 16); // number of packets in rx fifo +__SINIC_VAL64(RxDone_Busy, 31, 1); // receive dma busy copying +__SINIC_VAL64(RxDone_Complete, 30, 1); // valid data (packet complete) +__SINIC_VAL64(RxDone_More, 29, 1); // Packet has more data (dma again) +__SINIC_VAL64(RxDone_TcpError, 25, 1); // TCP packet error (bad checksum) +__SINIC_VAL64(RxDone_UdpError, 24, 1); // UDP packet error (bad checksum) +__SINIC_VAL64(RxDone_IpError, 23, 1); // IP packet error (bad checksum) +__SINIC_VAL64(RxDone_TcpPacket, 22, 1); // this is a TCP packet +__SINIC_VAL64(RxDone_UdpPacket, 21, 1); // this is a UDP packet +__SINIC_VAL64(RxDone_IpPacket, 20, 1); // this is an IP packet __SINIC_VAL64(RxDone_CopyLen, 0, 20); // up to 256k // TX Done/Busy Information -__SINIC_VAL64(TxDone_Complete, 63, 1); -__SINIC_VAL64(TxDone_FifoLen, 20, 8); // up to 255 packets -__SINIC_VAL64(TxDone_CopyLen, 0, 20); // up to 256k - -inline int -regSize(int offset) +__SINIC_VAL64(TxDone_Packets, 32, 16); // number of packets in tx fifo +__SINIC_VAL64(TxDone_Busy, 31, 1); // transmit dma busy copying +__SINIC_VAL64(TxDone_Complete, 30, 1); // valid data (packet complete) +__SINIC_VAL64(TxDone_Full, 29, 1); // tx fifo is full +__SINIC_VAL64(TxDone_Low, 28, 1); // tx fifo is below the watermark +__SINIC_VAL64(TxDone_CopyLen, 0, 20); // up to 256k + +struct Info { - static const char sizes[] = { - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 0, - 8, 0, - 8, 0, - 8, 0, - 8, 0, - 8, 0, - 8, 0, - 8, 0 - }; + uint8_t size; + bool read; + bool write; + const char *name; +}; - if (offset & 0x3) - return 0; +/* namespace Regs */ } - if (offset >= Size) - return 0; +inline const Regs::Info& +regInfo(Addr daddr) +{ + static Regs::Info info [] = { + { 4, true, true, "Config" }, + { 4, false, true, "Command" }, + { 4, true, true, "IntrStatus" }, + { 4, true, true, "IntrMask" }, + { 4, true, false, "RxMaxCopy" }, + { 4, true, false, "TxMaxCopy" }, + { 4, true, false, "RxMaxIntr" }, + { 0, false, false, "invalid" }, + { 4, true, false, "RxFifoSize" }, + { 4, true, false, "TxFifoSize" }, + { 4, true, false, "RxFifoMark" }, + { 4, true, false, "TxFifoMark" }, + { 8, true, true, "RxData" }, { 0, false, false, "invalid" }, + { 8, true, false, "RxDone" }, { 0, false, false, "invalid" }, + { 8, true, false, "RxWait" }, { 0, false, false, "invalid" }, + { 8, true, true, "TxData" }, { 0, false, false, "invalid" }, + { 8, true, false, "TxDone" }, { 0, false, false, "invalid" }, + { 8, true, false, "TxWait" }, { 0, false, false, "invalid" }, + { 8, true, false, "HwAddr" }, { 0, false, false, "invalid" } + }; - return sizes[offset / 4]; + return info[daddr / 4]; } -inline const char * -regName(int offset) +inline bool +regValid(Addr daddr) { - static const char *names[] = { - "Config", - "RxMaxCopy", - "TxMaxCopy", - "RxThreshold", - "TxThreshold", - "IntrStatus", - "IntrMask", - "invalid", - "RxData", "invalid", - "RxDone", "invalid", - "RxWait", "invalid", - "TxData", "invalid", - "TxDone", "invalid", - "TxWait", "invalid", - "HwAddr", "invalid" - }; + if (daddr > Regs::Size) + return false; - if (offset & 0x3) - return "invalid"; + if (regInfo(daddr).size == 0) + return false; - if (offset >= Size) - return "invalid"; - - return names[offset / 4]; + return true; } -/* namespace Regs */ } /* namespace Sinic */ } #endif // __DEV_SINICREG_HH__ diff --git a/kern/kernel_stats.hh b/kern/kernel_stats.hh index 7b931ef79..62dd84a28 100644 --- a/kern/kernel_stats.hh +++ b/kern/kernel_stats.hh @@ -34,11 +34,12 @@ #include <string> #include <vector> +#include "cpu/static_inst.hh" + class BaseCPU; class ExecContext; class FnEvent; // What does kernel stats expect is included? -class StaticInstBase; class System; enum Fault; @@ -105,7 +106,7 @@ class Binning cpu_mode themode; void palSwapContext(ExecContext *xc); - void execute(ExecContext *xc, const StaticInstBase *inst); + void execute(ExecContext *xc, StaticInstPtr<TheISA> inst); void call(ExecContext *xc, Stats::MainBin *myBin); void changeMode(cpu_mode mode); diff --git a/python/m5/objects/Ethernet.py b/python/m5/objects/Ethernet.py index d3e8c2811..a97e58bda 100644 --- a/python/m5/objects/Ethernet.py +++ b/python/m5/objects/Ethernet.py @@ -60,66 +60,51 @@ if build_env['ALPHA_TLASER']: type = 'EtherDevInt' device = Param.EtherDev("Ethernet device of this interface") -class NSGigE(PciDevice): - type = 'NSGigE' +class EtherDevBase(PciDevice): hardware_address = Param.EthernetAddr(NextEthernetAddr, "Ethernet Hardware Address") clock = Param.Clock('0ns', "State machine processor frequency") - dma_data_free = Param.Bool(False, "DMA of Data is free") - dma_desc_free = Param.Bool(False, "DMA of Descriptors is free") + physmem = Param.PhysicalMemory(Parent.any, "Physical Memory") + + hier = Param.HierParams(Parent.any, "Hierarchy global variables") + payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload") dma_read_delay = Param.Latency('0us', "fixed delay for dma reads") dma_read_factor = Param.Latency('0us', "multiplier for dma reads") dma_write_delay = Param.Latency('0us', "fixed delay for dma writes") dma_write_factor = Param.Latency('0us', "multiplier for dma writes") dma_no_allocate = Param.Bool(True, "Should we allocate cache on read") - - rx_filter = Param.Bool(True, "Enable Receive Filter") rx_delay = Param.Latency('1us', "Receive Delay") tx_delay = Param.Latency('1us', "Transmit Delay") + rx_fifo_size = Param.MemorySize('512kB', "max size of rx fifo") + tx_fifo_size = Param.MemorySize('512kB', "max size of tx fifo") - rx_fifo_size = Param.MemorySize('128kB', "max size in bytes of rxFifo") - tx_fifo_size = Param.MemorySize('128kB', "max size in bytes of txFifo") + rx_filter = Param.Bool(True, "Enable Receive Filter") + intr_delay = Param.Latency('10us', "Interrupt Propagation Delay") + dedicated = Param.Bool(False, "dedicate a kernel thread to the driver") - m5reg = Param.UInt32(0, "Register for m5 usage") +class NSGigE(EtherDevBase): + type = 'NSGigE' + + dma_data_free = Param.Bool(False, "DMA of Data is free") + dma_desc_free = Param.Bool(False, "DMA of Descriptors is free") - intr_delay = Param.Latency('0us', "Interrupt Delay in microseconds") - payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload") - physmem = Param.PhysicalMemory(Parent.any, "Physical Memory") class NSGigEInt(EtherInt): type = 'NSGigEInt' device = Param.NSGigE("Ethernet device of this interface") -class Sinic(PciDevice): +class Sinic(EtherDevBase): type = 'Sinic' - hardware_address = Param.EthernetAddr(NextEthernetAddr, - "Ethernet Hardware Address") - - clock = Param.Clock('100MHz', "State machine processor frequency") - - dma_read_delay = Param.Latency('0us', "fixed delay for dma reads") - dma_read_factor = Param.Latency('0us', "multiplier for dma reads") - dma_write_delay = Param.Latency('0us', "fixed delay for dma writes") - dma_write_factor = Param.Latency('0us', "multiplier for dma writes") - rx_filter = Param.Bool(True, "Enable Receive Filter") - rx_delay = Param.Latency('1us', "Receive Delay") - tx_delay = Param.Latency('1us', "Transmit Delay") - - rx_max_copy = Param.MemorySize('16kB', "rx max copy") + rx_max_copy = Param.MemorySize('1514B', "rx max copy") tx_max_copy = Param.MemorySize('16kB', "tx max copy") - rx_fifo_size = Param.MemorySize('64kB', "max size of rx fifo") - tx_fifo_size = Param.MemorySize('64kB', "max size of tx fifo") + rx_max_intr = Param.UInt32(10, "max rx packets per interrupt") rx_fifo_threshold = Param.MemorySize('48kB', "rx fifo high threshold") tx_fifo_threshold = Param.MemorySize('16kB', "tx fifo low threshold") - intr_delay = Param.Latency('0us', "Interrupt Delay in microseconds") - payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload") - physmem = Param.PhysicalMemory(Parent.any, "Physical Memory") - class SinicInt(EtherInt): type = 'SinicInt' device = Param.Sinic("Ethernet device of this interface") diff --git a/sim/system.cc b/sim/system.cc index e67cae333..f14a97603 100644 --- a/sim/system.cc +++ b/sim/system.cc @@ -54,6 +54,7 @@ System::System(Params *p) kernelSymtab = new SymbolTable; consoleSymtab = new SymbolTable; palSymtab = new SymbolTable; + allSymtab = new SymbolTable; debugSymbolTable = new SymbolTable; /** @@ -101,6 +102,21 @@ System::System(Params *p) if (!pal->loadLocalSymbols(palSymtab)) panic("could not load pal symbols\n"); + if (!kernel->loadGlobalSymbols(allSymtab)) + panic("could not load kernel symbols\n"); + + if (!kernel->loadLocalSymbols(allSymtab)) + panic("could not load kernel local symbols\n"); + + if (!console->loadGlobalSymbols(allSymtab)) + panic("could not load console symbols\n"); + + if (!pal->loadGlobalSymbols(allSymtab)) + panic("could not load pal symbols\n"); + + if (!pal->loadLocalSymbols(allSymtab)) + panic("could not load pal symbols\n"); + if (!kernel->loadGlobalSymbols(debugSymbolTable)) panic("could not load kernel symbols\n"); diff --git a/sim/system.hh b/sim/system.hh index 8cfe790de..ed78eb3d4 100644 --- a/sim/system.hh +++ b/sim/system.hh @@ -77,6 +77,9 @@ class System : public SimObject /** pal symbol table */ SymbolTable *palSymtab; + /** all symbols table */ + SymbolTable *allSymtab; + /** Object pointer for the kernel code */ ObjectFile *kernel; diff --git a/test/Makefile b/test/Makefile index 20abe8466..6fe0e5f48 100644 --- a/test/Makefile +++ b/test/Makefile @@ -33,8 +33,8 @@ initest: test/initest.cc base/str.cc base/inifile.cc base/cprintf.cc lrutest: test/lru_test.cc $(CXX) $(CCFLAGS) -o $@ $^ -nmtest: test/nmtest.cc base/object_file.cc base/symtab.cc base/misc.cc base/str.cc - $(CXX) $(CCFLAGS) -o $@ $^ +nmtest: test/nmtest.cc base/output.cc base/hostinfo.cc base/cprintf.cc base/misc.cc base/loader/object_file.cc base/loader/symtab.cc base/misc.cc base/str.cc base/loader/aout_object.cc base/loader/ecoff_object.cc base/loader/elf_object.cc + $(CXX) $(CCFLAGS) -I/n/ziff/z/binkertn/build/work/ALPHA_FS -lelf -o $@ $^ offtest: test/offtest.cc $(CXX) $(CCFLAGS) -o $@ $^ diff --git a/test/nmtest.cc b/test/nmtest.cc index 90166adf3..e9c20d19d 100644 --- a/test/nmtest.cc +++ b/test/nmtest.cc @@ -30,45 +30,53 @@ #include <string> #include <vector> -#include "ecoff.hh" #include "base/loader/object_file.hh" -#include "base/str.hh" #include "base/loader/symtab.hh" +#include "base/misc.hh" +#include "base/str.hh" +using namespace std; Tick curTick; +ostream *outputStream = &cout; + int main(int argc, char *argv[]) { - EcoffObject obj; - if (argc != 3) { - cout << "usage: " << argv[0] << " <filename> <symbol>\n"; - return 1; - } + if (argc != 2 && argc != 3) + panic("usage: %s <filename> <symbol>\n", argv[0]); - if (!obj.open(argv[1])) { - cout << "file not found\n"; - return 1; - } + ObjectFile *obj = createObjectFile(argv[1]); + if (!obj) + panic("file not found\n"); SymbolTable symtab; - obj.loadGlobals(&symtab); - - string symbol = argv[2]; - Addr address; + obj->loadGlobalSymbols(&symtab); + obj->loadLocalSymbols(&symtab); - if (symbol[0] == '0' && symbol[1] == 'x') { - if (to_number(symbol, address) && symtab.findSymbol(address, symbol)) - cout << "address = 0x" << hex << address - << ", symbol = " << symbol << "\n"; - else - cout << "address = 0x" << hex << address << " was not found\n"; + if (argc == 2) { + SymbolTable::ATable::const_iterator i = symtab.getAddrTable().begin(); + SymbolTable::ATable::const_iterator end = symtab.getAddrTable().end(); + while (i != end) { + cprintf("%#x %s\n", i->first, i->second); + ++i; + } } else { - if (symtab.findAddress(symbol, address)) - cout << "symbol = " << symbol << ", address = 0x" << hex - << address << "\n"; - else - cout << "symbol = " << symbol << " was not found\n"; + string symbol = argv[2]; + Addr address; + + if (symbol[0] == '0' && symbol[1] == 'x') { + if (to_number(symbol, address) && + symtab.findSymbol(address, symbol)) + cprintf("address = %#x, symbol = %s\n", address, symbol); + else + cprintf("address = %#x was not found\n", address); + } else { + if (symtab.findAddress(symbol, address)) + cprintf("symbol = %s address = %#x\n", symbol, address); + else + cprintf("symbol = %s was not found\n", symbol); + } } return 0; diff --git a/util/pbs/job.py b/util/pbs/job.py index fb375cf5d..0fd3b4f97 100755 --- a/util/pbs/job.py +++ b/util/pbs/job.py @@ -149,7 +149,7 @@ if __name__ == '__main__': pbs_jobname = env['PBS_JOBNAME'] basedir = joinpath(rootdir, 'Base') jobname = env.setdefault('JOBNAME', pbs_jobname) - jobfile = env.setdefault('JOBFILE', joinpath(basedir, 'test.py')) + jobfile = env.setdefault('JOBFILE', joinpath(rootdir, 'Test.py')) outdir = env.setdefault('OUTPUT_DIR', joinpath(rootdir, jobname)) env['POOLJOB'] = 'True' diff --git a/util/pbs/pbs.py b/util/pbs/pbs.py index ecacbeba2..70a0c6bed 100755 --- a/util/pbs/pbs.py +++ b/util/pbs/pbs.py @@ -91,19 +91,20 @@ class MyPOpen(object): class qsub: def __init__(self): + self.afterok = None self.hold = False self.join = False self.keep_stdout = False self.keep_stderr = False - self.node_type = '' + self.node_type = None self.mail_abort = False self.mail_begin = False self.mail_end = False - self.name = '' - self.stdout = '' - self.priority = 0 - self.queue = '' - self.pbshost = '' + self.name = None + self.stdout = None + self.priority = None + self.queue = None + self.pbshost = None self.qsub = 'qsub' self.env = {} @@ -118,7 +119,7 @@ class qsub: if self.hold: self.cmd.append('-h') - if len(self.stdout): + if self.stdout: self.cmd.append('-olocalhost:' + self.stdout) if self.keep_stdout and self.keep_stderr: @@ -133,7 +134,7 @@ class qsub: if self.join: self.cmd.append('-joe') - if len(self.node_type): + if self.node_type: self.cmd.append('-lnodes=' + self.node_type) if self.mail_abort or self.mail_begin or self.mail_end: @@ -147,15 +148,18 @@ class qsub: if len(flags): self.cmd.append('-m ' + flags) - if len(self.name): + if self.name: self.cmd.append("-N%s" % self.name) - if self.priority != 0: + if self.priority: self.cmd.append('-p' + self.priority) - if len(self.queue): + if self.queue: self.cmd.append('-q' + self.queue) + if self.afterok: + self.cmd.append('-Wdepend=afterok:%s' % self.afterok) + self.cmd.extend(args) self.script = script self.command = ' '.join(self.cmd + [ self.script ]) diff --git a/util/pbs/send.py b/util/pbs/send.py index 51eb8425e..d04f9066b 100755 --- a/util/pbs/send.py +++ b/util/pbs/send.py @@ -82,11 +82,11 @@ Usage: -e only echo pbs command info, don't actually send the job -f force the job to run regardless of state -q <queue> submit job to the named queue - -j <jobfile> specify the jobfile (default is <basedir>/test.py) + -j <jobfile> specify the jobfile (default is <rootdir>/Test.py) -v be verbose %(progname)s [-j <jobfile>] -l [-v] <regexp> - -j <jobfile> specify the jobfile (default is <basedir>/test.py) + -j <jobfile> specify the jobfile (default is <rootdir>/Test.py) -l list job names, don't submit -v be verbose (list job parameters) @@ -96,10 +96,11 @@ Usage: try: import getopt - opts, args = getopt.getopt(sys.argv[1:], '-CRcd:efhj:lq:v') + opts, args = getopt.getopt(sys.argv[1:], '-Ccdefhj:lq:Rt:v') except getopt.GetoptError: sys.exit(usage) +depend = False clean = False onlyecho = False exprs = [] @@ -107,18 +108,19 @@ force = False listonly = False queue = '' verbose = False -jfile = 'Base/test.py' +jfile = 'Test.py' docpts = False doruns = True runflag = False +node_type = 'FAST' for opt,arg in opts: if opt == '-C': docpts = True - if opt == '-R': - runflag = True if opt == '-c': clean = True + if opt == '-d': + depend = True if opt == '-e': onlyecho = True if opt == '-f': @@ -132,6 +134,10 @@ for opt,arg in opts: listonly = True if opt == '-q': queue = arg + if opt == '-R': + runflag = True + if opt == '-t': + node_type = arg if opt == '-v': verbose = True @@ -149,6 +155,8 @@ conf = jobfile.JobFile(jfile) if not listonly and not onlyecho and isdir(conf.linkdir): if verbose: print 'Checking for outdated files in Link directory' + if not isdir(conf.basedir): + os.mkdir(conf.basedir) syncdir(conf.linkdir, conf.basedir) jobnames = {} @@ -237,6 +245,9 @@ namehack = NameHack() for job in joblist: jobdir = JobDir(joinpath(conf.rootdir, job.name)) + if depend: + cptdir = JobDir(joinpath(conf.rootdir, job.checkpoint.name)) + cptjob = cptdir.readval('.pbs_jobid') if not onlyecho: jobdir.create() @@ -249,10 +260,12 @@ for job in joblist: qsub.stdout = jobdir.file('jobout') qsub.name = job.name[:15] qsub.join = True - qsub.node_type = 'FAST' + qsub.node_type = node_type qsub.env['ROOTDIR'] = conf.rootdir qsub.env['JOBNAME'] = job.name - if len(queue): + if depend: + qsub.afterok = cptjob + if queue: qsub.queue = queue qsub.build(joinpath(progpath, 'job.py')) @@ -45,7 +45,11 @@ optparser.add_option('-o', dest='stdout_file', help='command stdout output file') optparser.add_option('-l', dest='save_log', action='store_true', help='save qsub output log file') -optparser.add_option('-q', dest='qsub_timeout', type='int', +optparser.add_option('-N', dest='job_name', + help='qsub job name') +optparser.add_option('-q', dest='dest_queue', + help='qsub destination queue') +optparser.add_option('--qwait', dest='qsub_timeout', type='int', help='qsub queue wait timeout', default=30*60) optparser.add_option('-t', dest='cmd_timeout', type='int', help='command execution timeout', default=600*60) @@ -56,6 +60,12 @@ if cmd == []: print >>sys.stderr, "%s: missing command" % progname sys.exit(1) +# If we want to do this, need to add check here to make sure cmd[0] is +# a valid PBS job name, else qsub will die on us. +# +#if not options.job_name: +# options.job_name = cmd[0] + cwd = os.getcwd() # Deal with systems where /n is a symlink to /.automount @@ -137,6 +147,10 @@ if False and len(cmd) > 50: print "%s: running %s on poolfs" % (progname, cmd[0]) else: shell_cmd = 'qsub -I -S /bin/sh' + if options.job_name: + shell_cmd += ' -N "%s"' % options.job_name + if options.dest_queue: + shell_cmd += ' -q ' + options.dest_queue shell = Shell(shell_cmd) diff --git a/util/stats/categories.py b/util/stats/categories.py index 0c359b856..8d5d506a2 100644 --- a/util/stats/categories.py +++ b/util/stats/categories.py @@ -26,7 +26,95 @@ # # Authors: Nathan Binkert -categories = { +func_categories = { \ + # Buffer management functions + '__skb_linearize' : 'buffer', + 'skb_clone' : 'buffer', + 'skb_clone_fraglist' : 'buffer', + 'skb_seq_read' : 'buffer', + 'sock_alloc_send_skb' : 'buffer', + + # Copy functions + '__copy_user' : 'copy', + 'skb_copy_bits' : 'copy', + + # Driver functions + 'do_tx_done' : 'driver', + 'ns83820_get_drvinfo' : 'driver', + 'ns83820_get_stats' : 'driver', + 'ns83820_hard_start_xmit' : 'driver', + 'ns83820_open' : 'driver', + 'ns83820_rx_kick' : 'driver', + 'ns83820_update_stats' : 'driver', + 'ns83820_irq' : 'driver', + 'phy_intr' : 'driver', + 'rx_irq' : 'driver', + 'rx_action' : 'driver', + 'sinic_intr' : 'driver', + 'sinic_xmit' : 'driver', + 'sinic_rxskb_new' : 'driver', + + # Idle functions + 'cpu_idle' : 'idle', + + # Interrupt functions + 'do_entInt' : 'interrupt', + 'entInt' : 'interrupt', + 'handle_IRQ_event' : 'interrupt', + 'irq_exit' : 'interrupt', + + # Other functions + 'ret_from_sys_call' : 'other', + 'top' : 'other', + + # Stack functions + '__ip_conntrack_confirm' : 'stack', + '__ip_conntrack_find' : 'stack', + '__tcp_ack_snd_check' : 'stack', + '__tcp_checksum_complete_user' : 'stack', + 'dev_queue_xmit' : 'stack', + 'eth_header_cache' : 'stack', + 'ether_setup' : 'stack', + 'icmp_error' : 'stack', + 'ip_call_ra_chain' : 'stack', + 'ip_conntrack_alter_reply' : 'stack', + 'ip_conntrack_tcp_update' : 'stack', + 'ip_ct_find_helper' : 'stack', + 'ip_finish_output' : 'stack', + 'ip_finish_output2' : 'stack', + 'ip_local_deliver_finish' : 'stack', + 'ip_nat_setup_info' : 'stack', + 'ip_rcv' : 'stack', + 'ip_rcv_finish' : 'stack', + 'netif_receive_skb' : 'stack', + 'nf_log_packet' : 'stack', + 'nf_queue' : 'stack', + 'tcp_connect' : 'stack', + 'tcp_data_queue' : 'stack', + 'tcp_packet' : 'stack', + 'tcp_read_sock' : 'stack', + 'tcp_rcv_established' : 'stack', + 'tcp_recvmsg' : 'stack', + 'tcp_sendpage' : 'stack', + 'tcp_transmit_skb' : 'stack', + 'tcp_v4_do_rcv' : 'stack', + 'unregister_netdevice' : 'stack', + + # Syscall functions + 'entSys' : 'syscall', + + # User functions + 'user' : 'user', + } + +def func_categorize(symbol): + from categories import func_categories + if symbol in func_categories: + return func_categories[symbol] + return None + + +pc_categories = { 'CALL_PALrdunique_' : 'interrupt', # 'Call_Pal_Callsys' : 'interrupt', # 'Call_Pal_Rdps' : 'interrupt', # @@ -37,15 +125,15 @@ categories = { 'Call_Pal_Wrusp' : 'interrupt', # 'SHATransform': 'driver', # drivers/char/random.c, 'TRAP_INTERRUPT_10_' : 'interrupt', # - 'Trap_Dtbmiss_Single' : 'bufmgt', # - 'Trap_Dtbmiss_double' : 'bufmgt', # + 'Trap_Dtbmiss_Single' : 'buffer', # + 'Trap_Dtbmiss_double' : 'buffer', # 'Trap_Interrupt' : 'interrupt', # - 'Trap_Itbmiss' : 'bufmgt', # + 'Trap_Itbmiss' : 'buffer', # 'Trap_Unalign' : 'alignment', 'UNALIGN_NO_DISMISS' : 'alignment', 'UNALIGN_NO_DISMISS_10_' : 'alignment', - '__alloc_pages' : 'bufmgt', # mm/page_alloc.c, - '__anon_vma_link': 'bufmgt', # mm/rmap.c, include/linux/rmap.h, + '__alloc_pages' : 'buffer', # mm/page_alloc.c, + '__anon_vma_link': 'buffer', # mm/rmap.c, include/linux/rmap.h, '__bio_add_page' : 'other', # fs/bio.c, '__bitmap_weight' : 'other', # lib/bitmap.c, include/linux/bitmap.h, '__blk_put_request' : 'other', # drivers/block/ll_rw_blk.c, @@ -78,17 +166,17 @@ categories = { '__end_that_request_first' : 'other', # drivers/block/ll_rw_blk.c, '__exit_sighand': 'other', # kernel/signal.c, include/linux/sched.h, '__exit_signal': 'other', # kernel/signal.c, include/linux/sched.h, - '__filemap_copy_from_user_iovec' : 'bufmgt', # mm/filemap.c, - '__filemap_fdatawrite' : 'bufmgt', # mm/filemap.c, + '__filemap_copy_from_user_iovec' : 'buffer', # mm/filemap.c, + '__filemap_fdatawrite' : 'buffer', # mm/filemap.c, '__find_get_block' : 'other', # fs/buffer.c, include/linux/buffer_head.h, '__find_get_block_slow' : 'other', # fs/buffer.c, '__fput' : 'other', # fs/file_table.c, - '__free_pages' : 'bufmgt', # mm/page_alloc.c, - '__free_pages_ok': 'bufmgt', # mm/page_alloc.c, - '__generic_file_aio_read': 'bufmgt', # mm/filemap.c, include/linux/fs.h, + '__free_pages' : 'buffer', # mm/page_alloc.c, + '__free_pages_ok': 'buffer', # mm/page_alloc.c, + '__generic_file_aio_read': 'buffer', # mm/filemap.c, include/linux/fs.h, '__generic_unplug_device' : 'other', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, '__get_free_pages' : 'other', # mm/page_alloc.c, drivers/md/raid6.h, - '__get_page_state': 'bufmgt', # mm/page_alloc.c, + '__get_page_state': 'buffer', # mm/page_alloc.c, '__get_user_4': 'other', # include/asm-i386/uaccess.h, '__get_zone_counts': 'other', # '__getblk' : 'other', # fs/buffer.c, include/linux/buffer_head.h, @@ -97,17 +185,17 @@ categories = { '__group_send_sig_info' : 'user', # kernel/signal.c, is kinda syscall '__iget' : 'other', # fs/inode.c, include/linux/fs.h, '__insert_inode_hash': 'other', # fs/inode.c, include/linux/fs.h, - '__insert_vm_struct': 'bufmgt', # mm/mmap.c, + '__insert_vm_struct': 'buffer', # mm/mmap.c, '__ip_conntrack_confirm' : 'stack', # net/ipv4/netfilter/ip_conntrack_core.c, include/linux/netfilter_ipv4/ip_conntrack_core.h, '__ip_conntrack_find' : 'stack', # net/ipv4/netfilter/ip_conntrack_core.c, '__ip_ct_find_proto' : 'stack', # net/ipv4/netfilter/ip_conntrack_core.c, include/linux/netfilter_ipv4/ip_conntrack_core.h, '__ip_route_output_key' : 'stack', # net/ipv4/route.c, - '__kfree_skb' : 'bufmgt', # net/core/skbuff.c, include/linux/skbuff.h, - '__kmalloc' : 'bufmgt', # mm/slab.c, include/linux/slab.h, - '__load_new_mm_context': 'bufmgt', + '__kfree_skb' : 'buffer', # net/core/skbuff.c, include/linux/skbuff.h, + '__kmalloc' : 'buffer', # mm/slab.c, include/linux/slab.h, + '__load_new_mm_context': 'buffer', '__lookup': 'other', # lib/radix-tree.c, '__lookup_hash': 'other', # fs/namei.c, - '__lookup_tag' : 'bufmgt', # lib/radix-tree.c, + '__lookup_tag' : 'buffer', # lib/radix-tree.c, '__make_request' : 'driver', # drivers/block/ll_rw_blk.c, drivers/block/ll_rw_blk.c, '__mark_inode_dirty' : 'other', # fs/fs-writeback.c, include/linux/fs.h, '__memcpy_aligned_up' : 'copy', # arch/alpha/lib/memcpy.c, @@ -117,31 +205,31 @@ categories = { '__mod_timer' : 'other', # kernel/timer.c, include/linux/timer.h, '__modify_IO_APIC_irq': 'interrupt', # '__net_random': 'other', # - '__page_cache_release' : 'bufmgt', # mm/swap.c, - '__pagevec_free': 'bufmgt', # mm/page_alloc.c, include/linux/pagevec.h, - '__pagevec_lru_add' : 'bufmgt', # mm/swap.c, include/linux/pagevec.h, - '__pagevec_lru_add_active': 'bufmgt', # mm/swap.c, include/linux/pagevec.h, - '__pagevec_release' : 'bufmgt', # mm/swap.c, include/linux/pagevec.h, + '__page_cache_release' : 'buffer', # mm/swap.c, + '__pagevec_free': 'buffer', # mm/page_alloc.c, include/linux/pagevec.h, + '__pagevec_lru_add' : 'buffer', # mm/swap.c, include/linux/pagevec.h, + '__pagevec_lru_add_active': 'buffer', # mm/swap.c, include/linux/pagevec.h, + '__pagevec_release' : 'buffer', # mm/swap.c, include/linux/pagevec.h, '__pollwait' : 'other', # fs/select.c, fs/select.c, '__pskb_trim_head': 'stack', # net/ipv4/tcp_output.c, '__put_task_struct': 'other', # kernel/fork.c, include/linux/sched.h, '__queue_work': 'other', # kernel/workqueue.c, - '__rb_erase_color' : 'bufmgt', # lib/rbtree.c, - '__rb_rotate_left' : 'bufmgt', # lib/rbtree.c, - '__rb_rotate_right' : 'bufmgt', # lib/rbtree.c, + '__rb_erase_color' : 'buffer', # lib/rbtree.c, + '__rb_rotate_left' : 'buffer', # lib/rbtree.c, + '__rb_rotate_right' : 'buffer', # lib/rbtree.c, '__rcu_process_callbacks': 'other', # - '__read_page_state' : 'bufmgt', # mm/page_alloc.c, include/linux/page-flags.h, + '__read_page_state' : 'buffer', # mm/page_alloc.c, include/linux/page-flags.h, '__release_sock' : 'stack', # net/core/sock.c, '__remlu' : 'other', # arch/alpha/kernel/alpha_ksyms.c, - '__remove_from_page_cache': 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, - '__remove_shared_vm_struct': 'bufmgt', # mm/mmap.c, + '__remove_from_page_cache': 'buffer', # mm/filemap.c, include/linux/pagemap.h, + '__remove_shared_vm_struct': 'buffer', # mm/mmap.c, '__remqu' : 'other', # arch/alpha/kernel/alpha_ksyms.c, - '__rmqueue' : 'bufmgt', # mm/page_alloc.c, + '__rmqueue' : 'buffer', # mm/page_alloc.c, '__scsi_done' : 'other', # drivers/scsi/scsi.c, drivers/scsi/scsi_priv.h, '__scsi_get_command' : 'other', # drivers/scsi/scsi.c, '__set_page_buffers' : 'other', # fs/buffer.c, - '__set_page_dirty_nobuffers' : 'bufmgt', # mm/page-writeback.c, include/linux/mm.h, - '__sk_stream_mem_reclaim' : 'bufmgt', # net/core/stream.c, + '__set_page_dirty_nobuffers' : 'buffer', # mm/page-writeback.c, include/linux/mm.h, + '__sk_stream_mem_reclaim' : 'buffer', # net/core/stream.c, '__sock_create': 'stack', # net/socket.c, '__strncpy_from_user' : 'copy', # include/asm-alpha/uaccess.h, '__strnlen_user': 'user', @@ -160,8 +248,8 @@ categories = { '__up_wakeup' : 'interrupt', # arch/alpha/kernel/semaphore.c, include/asm-alpha/semaphore.h, '__user_walk' : 'other', # fs/namei.c, '__vm_stat_account': 'other', # - '__vma_link': 'bufmgt', # mm/mmap.c, - '__vma_link_rb': 'bufmgt', # mm/mmap.c, include/linux/mm.h, + '__vma_link': 'buffer', # mm/mmap.c, + '__vma_link_rb': 'buffer', # mm/mmap.c, include/linux/mm.h, '__wait_on_buffer' : 'other', # fs/buffer.c, include/linux/buffer_head.h, '__wake_up' : 'other', # kernel/sched.c, '__wake_up_common' : 'other', # kernel/sched.c, @@ -172,13 +260,13 @@ categories = { 'acct_process': 'other', # kernel/acct.c, include/linux/acct.h, include/linux/acct.h, 'ack_edge_ioapic_irq': 'interrupt', # 'ack_edge_ioapic_vector': 'interrupt', # - 'activate_page' : 'bufmgt', # mm/swap.c, + 'activate_page' : 'buffer', # mm/swap.c, 'activate_task' : 'other', # kernel/sched.c, 'add_disk_randomness' : 'other', # drivers/char/random.c, include/linux/genhd.h, 'add_interrupt_randomness': 'driver', # drivers/char/random.c, include/linux/random.h, 'add_timer_randomness' : 'driver', # drivers/char/random.c, - 'add_to_page_cache' : 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, - 'add_to_page_cache_lru' : 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, + 'add_to_page_cache' : 'buffer', # mm/filemap.c, include/linux/pagemap.h, + 'add_to_page_cache_lru' : 'buffer', # mm/filemap.c, include/linux/pagemap.h, 'add_wait_queue' : 'other', # kernel/fork.c, 'add_wait_queue_exclusive' : 'other', # kernel/fork.c, 'aligned' : 'other', # @@ -187,16 +275,16 @@ categories = { 'alloc_fd_array': 'other', # fs/file.c, include/linux/file.h, 'alloc_inode' : 'other', # fs/inode.c, 'alloc_pidmap': 'other', # kernel/pid.c, include/linux/pid.h, - 'alloc_skb' : 'bufmgt', # net/core/skbuff.c, include/linux/skbuff.h, - 'alloc_slabmgmt' : 'bufmgt', # mm/slab.c, + 'alloc_skb' : 'buffer', # net/core/skbuff.c, include/linux/skbuff.h, + 'alloc_slabmgmt' : 'buffer', # mm/slab.c, 'alpha_switch_to' : 'other', # include/asm-alpha/system.h, - 'anon_vma_link': 'bufmgt', # mm/rmap.c, include/linux/rmap.h, include/linux/rmap.h, - 'anon_vma_prepare': 'bufmgt', # mm/rmap.c, include/linux/rmap.h, include/linux/rmap.h, - 'anon_vma_unlink': 'bufmgt', # mm/rmap.c, include/linux/rmap.h, + 'anon_vma_link': 'buffer', # mm/rmap.c, include/linux/rmap.h, include/linux/rmap.h, + 'anon_vma_prepare': 'buffer', # mm/rmap.c, include/linux/rmap.h, include/linux/rmap.h, + 'anon_vma_unlink': 'buffer', # mm/rmap.c, include/linux/rmap.h, 'apache': 'other', # 'apic_timer_interrupt': 'interrupt', # include/asm-i386/hw_irq.h, - 'arch_get_unmapped_area': 'bufmgt', - 'arch_get_unmapped_area_1': 'bufmgt', + 'arch_get_unmapped_area': 'buffer', + 'arch_get_unmapped_area_1': 'buffer', 'arch_get_unmapped_area_topdown': 'other', # 'arch_pick_mmap_layout': 'other', # 'arch_unmap_area_topdown': 'other', # @@ -241,9 +329,9 @@ categories = { 'auth_domain_drop' : 'other', # net/sunrpc/svcauth.c, 'auth_domain_put' : 'other', # net/sunrpc/svcauth.c, include/linux/sunrpc/svcauth.h, 'autoremove_wake_function' : 'other', # kernel/fork.c, include/linux/wait.h, - 'bad_range' : 'bufmgt', # mm/page_alloc.c, - 'balance_dirty_pages' : 'bufmgt', # mm/page-writeback.c, - 'balance_dirty_pages_ratelimited' : 'bufmgt', # mm/page-writeback.c, include/linux/writeback.h, + 'bad_range' : 'buffer', # mm/page_alloc.c, + 'balance_dirty_pages' : 'buffer', # mm/page-writeback.c, + 'balance_dirty_pages_ratelimited' : 'buffer', # mm/page-writeback.c, include/linux/writeback.h, 'basename': 'other', # 'bash': 'other', # 'batch_entropy_store' : 'interrupt', # drivers/char/random.c, include/linux/random.h, @@ -264,7 +352,7 @@ categories = { 'blk_hw_contig_segment' : 'other', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, 'blk_phys_contig_segment' : 'other', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, 'blk_plug_device' : 'other', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, - 'blk_queue_bounce' : 'bufmgt', # mm/highmem.c, include/linux/blkdev.h, + 'blk_queue_bounce' : 'buffer', # mm/highmem.c, include/linux/blkdev.h, 'blk_recount_segments' : 'other', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, 'blk_remove_plug' : 'other', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, 'blk_rq_map_sg' : 'other', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, @@ -276,18 +364,18 @@ categories = { 'block_write_full_page': 'other', # fs/buffer.c, include/linux/buffer_head.h, 'bmap': 'other', # fs/jfs/jfs_dmap.h, fs/inode.c, include/linux/fs.h, 'buffer_insert_list' : 'other', # fs/buffer.c, include/linux/buffer_head.h, - 'buffered_rmqueue' : 'bufmgt', # mm/page_alloc.c, - 'cache_alloc_refill' : 'bufmgt', # mm/slab.c, + 'buffered_rmqueue' : 'buffer', # mm/page_alloc.c, + 'cache_alloc_refill' : 'buffer', # mm/slab.c, 'cache_check' : 'other', # net/sunrpc/cache.c, include/linux/sunrpc/cache.h, - 'cache_flusharray' : 'bufmgt', # mm/slab.c, - 'cache_grow' : 'bufmgt', # mm/slab.c, - 'cache_init_objs' : 'bufmgt', # mm/slab.c, - 'cache_reap': 'bufmgt', # mm/slab.c, + 'cache_flusharray' : 'buffer', # mm/slab.c, + 'cache_grow' : 'buffer', # mm/slab.c, + 'cache_init_objs' : 'buffer', # mm/slab.c, + 'cache_reap': 'buffer', # mm/slab.c, 'cached_lookup': 'other', # fs/namei.c, 'call_rcu' : 'other', # kernel/rcupdate.c, - 'can_share_swap_page': 'bufmgt', # mm/swapfile.c, include/linux/swap.h, include/linux/swap.h, - 'can_vma_merge_after': 'bufmgt', # mm/mmap.c, - 'can_vma_merge_before': 'bufmgt', # mm/mmap.c, + 'can_share_swap_page': 'buffer', # mm/swapfile.c, include/linux/swap.h, include/linux/swap.h, + 'can_vma_merge_after': 'buffer', # mm/mmap.c, + 'can_vma_merge_before': 'buffer', # mm/mmap.c, 'capable': 'other', 'cascade' : 'interrupt', # kernel/timer.c, 'cat': 'other', # @@ -297,9 +385,9 @@ categories = { 'chrdev_open': 'other', # fs/char_dev.c, include/linux/fs.h, 'cleanup_rbuf' : 'stack', # net/ipv4/tcp.c, 'clear_inode' : 'other', # fs/inode.c, include/linux/fs.h, - 'clear_page' : 'bufmgt', # include/asm-alpha/page.h, - 'clear_page_dirty_for_io' : 'bufmgt', # mm/page-writeback.c, include/linux/mm.h, - 'clear_page_tables': 'bufmgt', # mm/memory.c, include/linux/mm.h, + 'clear_page' : 'buffer', # include/asm-alpha/page.h, + 'clear_page_dirty_for_io' : 'buffer', # mm/page-writeback.c, include/linux/mm.h, + 'clear_page_tables': 'buffer', # mm/memory.c, include/linux/mm.h, 'clear_queue_congested' : 'other', # drivers/block/ll_rw_blk.c, 'clear_user': 'other', # include/asm-alpha/uaccess.h, include/asm-i386/uaccess.h, 'clock_panelapplet.so': 'other', # @@ -317,14 +405,14 @@ categories = { 'copy_mm': 'other', # kernel/fork.c, 'copy_namespace': 'other', # fs/namespace.c, include/linux/namespace.h, 'copy_page': 'copy', - 'copy_page_range': 'bufmgt', # mm/memory.c, include/linux/mm.h, + 'copy_page_range': 'buffer', # mm/memory.c, include/linux/mm.h, 'copy_process': 'other', # kernel/fork.c, include/linux/sched.h, 'copy_semundo': 'other', # ipc/sem.c, include/linux/sem.h, 'copy_strings': 'other', # fs/exec.c, include/linux/binfmts.h, 'copy_strings_kernel': 'other', # fs/exec.c, include/linux/binfmts.h, 'copy_thread': 'syscall', # arch/alpha/kernel/process.c, include/linux/sched.h, 'copy_to_user': 'copy', # include/asm-alpha/uaccess.h, include/asm-i386/uaccess.h, - 'copy_vma': 'bufmgt', # mm/mmap.c, include/linux/mm.h, + 'copy_vma': 'buffer', # mm/mmap.c, include/linux/mm.h, 'count': 'driver', # fs/exec.c, init/initramfs.c, drivers/char/serial_tx3912.c, drivers/char/rocket.c, drivers/isdn/hardware/eicon/diva_didd.c, drivers/isdn/hardware/eicon/divasmain.c, drivers/isdn/hardware/eicon/divasmain.c, drivers/isdn/hardware/eicon/capimain.c, drivers/isdn/hardware/eicon/divasi.c, drivers/isdn/hardware/eicon/divasi.c, drivers/isdn/hardware/eicon/divasi.c, drivers/isdn/hardware/eicon/divasi.c, drivers/isdn/hardware/eicon/divasi.c, drivers/isdn/hardware/eicon/divamnt.c, drivers/isdn/hardware/eicon/divamnt.c, drivers/isdn/hardware/eicon/divamnt.c, drivers/isdn/hardware/eicon/divamnt.c, drivers/isdn/hardware/eicon/divamnt.c, drivers/media/video/w9966.c, drivers/media/video/w9966.c, 'count_open_files': 'other', # kernel/fork.c, 'cp_new_stat' : 'other', # fs/stat.c, @@ -366,7 +454,7 @@ categories = { 'destroy_context': 'interrupt', # include/asm-alpha/mmu_context.h, include/asm-i386/mmu_context.h, 'destroy_inode' : 'other', # fs/inode.c, include/linux/fs.h, 'detach_pid': 'other', # kernel/pid.c, - 'detach_vmas_to_be_unmapped': 'bufmgt', # mm/mmap.c, + 'detach_vmas_to_be_unmapped': 'buffer', # mm/mmap.c, 'dev_queue_xmit' : 'stack', # net/core/dev.c, include/linux/netdevice.h, 'dev_shutdown' : 'stack', # net/sched/sch_generic.c, 'dev_watchdog': 'stack', # net/sched/sch_generic.c, @@ -376,9 +464,9 @@ categories = { 'dnotify_flush' : 'other', # fs/dnotify.c, include/linux/dnotify.h, 'dnotify_parent' : 'other', # fs/dnotify.c, include/linux/dnotify.h, 'do_IRQ': 'driver', # drivers/s390/cio/cio.c, - 'do_anonymous_page' : 'bufmgt', # mm/memory.c, + 'do_anonymous_page' : 'buffer', # mm/memory.c, 'do_bindings' : 'stack', # net/ipv4/netfilter/ip_nat_core.c, include/linux/netfilter_ipv4/ip_nat_core.h, - 'do_brk': 'bufmgt', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, + 'do_brk': 'buffer', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, 'do_csum_partial_copy_from_user' : 'copy', # arch/alpha/lib/csum_partial_copy.c, 'do_entInt' : 'interrupt', # arch/alpha/kernel/irq_alpha.c, 'do_entUna': 'alignment', @@ -387,21 +475,21 @@ categories = { 'do_fcntl' : 'user', # fs/fcntl.c, used to be syscall` 'do_fork': 'other', # kernel/fork.c, include/linux/sched.h, 'do_futex': 'other', # kernel/futex.c, include/linux/futex.h, - 'do_generic_mapping_read': 'bufmgt', # mm/filemap.c, include/linux/fs.h, + 'do_generic_mapping_read': 'buffer', # mm/filemap.c, include/linux/fs.h, 'do_gettimeofday' : 'user', # arch/alpha/kernel/time.c, include/linux/time.h, used to by syscall 'do_group_exit': 'other', # kernel/exit.c, include/linux/sched.h, - 'do_invalidatepage': 'bufmgt', # mm/truncate.c, + 'do_invalidatepage': 'buffer', # mm/truncate.c, 'do_lookup' : 'user', # fs/namei.c, used to by syscall - 'do_mmap_pgoff': 'bufmgt', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, + 'do_mmap_pgoff': 'buffer', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, 'do_mpage_readpage': 'other', # fs/mpage.c, - 'do_mremap': 'bufmgt', # mm/mremap.c, - 'do_munmap': 'bufmgt', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, + 'do_mremap': 'buffer', # mm/mremap.c, + 'do_munmap': 'buffer', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, 'do_no_page' : 'user', # mm/memory.c, used to by syscall 'do_nosym': 'other', # 'do_notify_parent': 'other', # kernel/signal.c, include/linux/sched.h, 'do_notify_resume': 'interrupt', # arch/alpha/kernel/signal.c, 'do_osf_sigprocmask' : 'user', # arch/alpha/kernel/signal.c, used to by syscall - 'do_page_cache_readahead': 'bufmgt', # mm/readahead.c, include/linux/mm.h, + 'do_page_cache_readahead': 'buffer', # mm/readahead.c, include/linux/mm.h, 'do_page_fault' : 'user', # arch/alpha/mm/fault.c, used to by syscall 'do_pipe': 'syscall', # fs/pipe.c, arch/alpha/kernel/osf_sys.c, include/linux/fs.h, 'do_poll' : 'user', # fs/select.c, drivers/macintosh/apm_emu.c, used to by syscall @@ -424,15 +512,15 @@ categories = { 'do_truncate': 'other', # fs/open.c, include/linux/fs.h, 'do_tx_done' : 'driver', # drivers/net/ns83820.c, 'do_wait': 'other', # - 'do_wp_page': 'bufmgt', # mm/memory.c, - 'do_writepages' : 'bufmgt', # mm/page-writeback.c, include/linux/writeback.h, + 'do_wp_page': 'buffer', # mm/memory.c, + 'do_writepages' : 'buffer', # mm/page-writeback.c, include/linux/writeback.h, 'done' : 'other', # drivers/usb/gadget/net2280.c, drivers/usb/gadget/goku_udc.c, drivers/usb/gadget/pxa2xx_udc.c, drivers/scsi/aha152x.c, drivers/scsi/aha152x.c, include/linux/wavefront.h, 'dp264_disable_irq' : 'interrupt', # arch/alpha/kernel/sys_dp264.c, 'dp264_enable_irq' : 'interrupt', # arch/alpha/kernel/sys_dp264.c, 'dp264_end_irq' : 'interrupt', # arch/alpha/kernel/sys_dp264.c, 'dp264_srm_device_interrupt' : 'interrupt', # arch/alpha/kernel/sys_dp264.c, 'dput' : 'other', # fs/dcache.c, include/linux/dcache.h, - 'drain_array_locked': 'bufmgt', # mm/slab.c, mm/slab.c, + 'drain_array_locked': 'buffer', # mm/slab.c, mm/slab.c, 'drive_stat_acct' : 'other', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, 'drop_buffers': 'other', # fs/buffer.c, 'drop_key_refs': 'other', # kernel/futex.c, @@ -493,7 +581,7 @@ categories = { 'end_edge_ioapic_vector': 'other', # include/asm-i386/io_apic.h, 'end_level_ioapic_irq': 'interrupt', # 'end_level_ioapic_vector': 'interrupt', # - 'end_page_writeback' : 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, + 'end_page_writeback' : 'buffer', # mm/filemap.c, include/linux/pagemap.h, 'end_that_request_chunk' : 'other', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, 'end_that_request_first': 'driver', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, 'end_that_request_last' : 'other', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, @@ -506,14 +594,14 @@ categories = { 'error_code': 'other', # 'eth_header' : 'stack', # net/ethernet/eth.c, include/linux/etherdevice.h, 'eth_type_trans' : 'stack', # net/ethernet/eth.c, include/linux/etherdevice.h, - 'ev5_flush_tlb_current_page': 'bufmgt', + 'ev5_flush_tlb_current_page': 'buffer', 'ev5_switch_mm' : 'other', # include/asm-alpha/mmu_context.h, 'eventpoll_init_file' : 'other', # fs/eventpoll.c, include/linux/eventpoll.h, 'exec_mmap': 'other', # fs/exec.c, 'exim4': 'other', # 'exit_aio': 'other', # fs/aio.c, 'exit_itimers': 'other', # kernel/posix-timers.c, include/linux/sched.h, - 'exit_mmap': 'bufmgt', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, + 'exit_mmap': 'buffer', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, 'exit_notify': 'other', # kernel/exit.c, 'exit_sem': 'other', # ipc/sem.c, include/linux/sem.h, include/linux/sem.h, 'exp_find_key' : 'other', # fs/nfsd/export.c, include/linux/nfsd/export.h, @@ -521,7 +609,7 @@ categories = { 'exp_readunlock' : 'other', # fs/nfsd/export.c, include/linux/nfsd/export.h, 'expand_fd_array': 'other', # fs/file.c, include/linux/file.h, 'expand_files': 'other', # fs/fcntl.c, - 'expand_stack': 'bufmgt', # mm/mmap.c, include/linux/mm.h, + 'expand_stack': 'buffer', # mm/mmap.c, include/linux/mm.h, 'expkey_put' : 'other', # fs/nfsd/export.c, include/linux/nfsd/export.h, 'export_decode_fh' : 'other', # fs/exportfs/expfs.c, 'export_iget' : 'other', # fs/exportfs/expfs.c, @@ -559,11 +647,11 @@ categories = { 'file_ioctl': 'other', # fs/ioctl.c, 'file_kill' : 'other', # fs/file_table.c, include/linux/fs.h, 'file_move': 'other', # fs/file_table.c, include/linux/fs.h, - 'file_ra_state_init': 'bufmgt', # mm/readahead.c, include/linux/fs.h, - 'file_read_actor': 'bufmgt', # mm/filemap.c, include/linux/fs.h, - 'filemap_fdatawait' : 'bufmgt', # mm/filemap.c, include/linux/fs.h, - 'filemap_fdatawrite' : 'bufmgt', # mm/filemap.c, include/linux/fs.h, - 'filemap_nopage': 'bufmgt', # mm/filemap.c, include/linux/mm.h, + 'file_ra_state_init': 'buffer', # mm/readahead.c, include/linux/fs.h, + 'file_read_actor': 'buffer', # mm/filemap.c, include/linux/fs.h, + 'filemap_fdatawait' : 'buffer', # mm/filemap.c, include/linux/fs.h, + 'filemap_fdatawrite' : 'buffer', # mm/filemap.c, include/linux/fs.h, + 'filemap_nopage': 'buffer', # mm/filemap.c, include/linux/mm.h, 'filesystems_read_proc': 'other', # fs/proc/proc_misc.c, 'filp_close' : 'other', # fs/open.c, include/linux/fs.h, 'filp_open' : 'other', # fs/open.c, include/linux/fs.h, @@ -571,24 +659,24 @@ categories = { 'find_busiest_group' : 'other', # kernel/sched.c, 'find_dcookie': 'other', # fs/dcookies.c, 'find_exported_dentry' : 'other', # fs/exportfs/expfs.c, fs/nfsd/export.c, - 'find_extend_vma': 'bufmgt', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, - 'find_get_page' : 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, - 'find_get_pages': 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, - 'find_get_pages_tag' : 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, + 'find_extend_vma': 'buffer', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, + 'find_get_page' : 'buffer', # mm/filemap.c, include/linux/pagemap.h, + 'find_get_pages': 'buffer', # mm/filemap.c, include/linux/pagemap.h, + 'find_get_pages_tag' : 'buffer', # mm/filemap.c, include/linux/pagemap.h, 'find_inode_fast' : 'other', # fs/inode.c, 'find_inode_number' : 'other', # fs/dcache.c, include/linux/fs.h, - 'find_lock_page' : 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, - 'find_mergeable_anon_vma': 'bufmgt', # mm/mmap.c, include/linux/mm.h, + 'find_lock_page' : 'buffer', # mm/filemap.c, include/linux/pagemap.h, + 'find_mergeable_anon_vma': 'buffer', # mm/mmap.c, include/linux/mm.h, 'find_nat_proto' : 'stack', # net/ipv4/netfilter/ip_nat_core.c, include/linux/netfilter_ipv4/ip_nat_protocol.h, 'find_next_zero_bit': 'other', # include/asm-alpha/bitops.h, include/asm-i386/bitops.h, - 'find_or_create_page' : 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, + 'find_or_create_page' : 'buffer', # mm/filemap.c, include/linux/pagemap.h, 'find_pid' : 'user', # kernel/pid.c, used to be syscall 'find_snap_client': 'stack', # net/802/psnap.c, 'find_task_by_pid' : 'user', # kernel/pid.c, include/linux/sched.h, used to be syscall 'find_task_by_pid_type': 'other', # - 'find_vma' : 'bufmgt', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, used to be syscall - 'find_vma_prepare': 'bufmgt', # mm/mmap.c, - 'find_vma_prev': 'bufmgt', # mm/mmap.c, include/linux/mm.h, + 'find_vma' : 'buffer', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, used to be syscall + 'find_vma_prepare': 'buffer', # mm/mmap.c, + 'find_vma_prev': 'buffer', # mm/mmap.c, include/linux/mm.h, 'finish_task_switch' : 'other', # kernel/sched.c, used to be syscall 'finish_wait' : 'other', # kernel/fork.c, used to be syscall 'flush_old_exec': 'other', # fs/exec.c, include/linux/binfmts.h, @@ -599,15 +687,15 @@ categories = { 'follow_mount' : 'user', # fs/namei.c, used to be syscall 'found' : 'other', # sound/oss/forte.c, scripts/kconfig/gconf.c, drivers/net/fec.c, drivers/scsi/ibmmca.c, drivers/scsi/fd_mcs.c, 'fput' : 'user', # fs/file_table.c, used to be syscall - 'free_block' : 'bufmgt', # mm/slab.c, drivers/char/drm/radeon_mem.c, mm/slab.c, + 'free_block' : 'buffer', # mm/slab.c, drivers/char/drm/radeon_mem.c, mm/slab.c, 'free_buffer_head': 'other', # fs/buffer.c, include/linux/buffer_head.h, 'free_fd_array': 'other', # fs/file.c, include/linux/file.h, - 'free_hot_cold_page' : 'bufmgt', # mm/page_alloc.c, - 'free_hot_page' : 'bufmgt', # mm/page_alloc.c, - 'free_page_and_swap_cache': 'bufmgt', # mm/swap_state.c, include/linux/swap.h, include/linux/swap.h, - 'free_pages' : 'bufmgt', # mm/page_alloc.c, drivers/char/drm/drm_memory_debug.h, drivers/md/raid6.h, drivers/char/drm/drmP.h, - 'free_pages_bulk': 'bufmgt', # mm/page_alloc.c, - 'free_pgtables': 'bufmgt', # mm/mmap.c, + 'free_hot_cold_page' : 'buffer', # mm/page_alloc.c, + 'free_hot_page' : 'buffer', # mm/page_alloc.c, + 'free_page_and_swap_cache': 'buffer', # mm/swap_state.c, include/linux/swap.h, include/linux/swap.h, + 'free_pages' : 'buffer', # mm/page_alloc.c, drivers/char/drm/drm_memory_debug.h, drivers/md/raid6.h, drivers/char/drm/drmP.h, + 'free_pages_bulk': 'buffer', # mm/page_alloc.c, + 'free_pgtables': 'buffer', # mm/mmap.c, 'free_pidmap': 'other', # kernel/pid.c, 'free_task': 'other', # kernel/fork.c, 'free_uid' : 'other', # kernel/user.c, include/linux/sched.h, @@ -620,12 +708,12 @@ categories = { 'generic_commit_write' : 'user', # fs/buffer.c, include/linux/buffer_head.h, used to be syscall 'generic_delete_inode': 'other', # fs/inode.c, include/linux/fs.h, 'generic_drop_inode' : 'user', # fs/inode.c, used to be syscall - 'generic_file_aio_read': 'bufmgt', # mm/filemap.c, include/linux/fs.h, - 'generic_file_aio_write': 'bufmgt', # mm/filemap.c, include/linux/fs.h, + 'generic_file_aio_read': 'buffer', # mm/filemap.c, include/linux/fs.h, + 'generic_file_aio_write': 'buffer', # mm/filemap.c, include/linux/fs.h, 'generic_file_aio_write_nolock' : 'user', # mm/filemap.c, include/linux/fs.h, used to be syscall 'generic_file_buffered_write': 'other', # 'generic_file_llseek': 'other', # fs/read_write.c, include/linux/fs.h, - 'generic_file_mmap': 'bufmgt', # mm/filemap.c, include/linux/fs.h, + 'generic_file_mmap': 'buffer', # mm/filemap.c, include/linux/fs.h, 'generic_file_open' : 'user', # fs/open.c, include/linux/fs.h, used to be syscall 'generic_file_write' : 'user', # mm/filemap.c, include/linux/fs.h, used to be syscall 'generic_file_write_nolock' : 'user', # mm/filemap.c, include/linux/fs.h, used to be syscall @@ -636,7 +724,7 @@ categories = { 'generic_unplug_device' : 'driver', # drivers/block/ll_rw_blk.c, include/linux/blkdev.h, 'get_conntrack_index' : 'stack', # net/ipv4/netfilter/ip_conntrack_proto_tcp.c, 'get_device' : 'driver', # drivers/base/core.c, include/linux/device.h, - 'get_dirty_limits' : 'bufmgt', # mm/page-writeback.c, + 'get_dirty_limits' : 'buffer', # mm/page-writeback.c, 'get_empty_filp' : 'other', # fs/file_table.c, include/linux/fs.h, 'get_free_idx': 'interrupt', # 'get_futex_key': 'other', # kernel/futex.c, @@ -645,8 +733,8 @@ categories = { 'get_new_inode_fast': 'other', # fs/inode.c, 'get_object' : 'other', # fs/exportfs/expfs.c, 'get_offset_pmtmr': 'interrupt', # - 'get_one_pte_map_nested': 'bufmgt', # mm/mremap.c, - 'get_page_state': 'bufmgt', # mm/page_alloc.c, include/linux/page-flags.h, + 'get_one_pte_map_nested': 'buffer', # mm/mremap.c, + 'get_page_state': 'buffer', # mm/page_alloc.c, include/linux/page-flags.h, 'get_pipe_inode': 'other', # fs/pipe.c, 'get_request' : 'other', # drivers/block/ll_rw_blk.c, 'get_sample_stats' : 'stack', # net/core/dev.c, @@ -654,12 +742,12 @@ categories = { 'get_task_mm': 'other', # include/linux/sched.h, 'get_tuple' : 'driver', # net/ipv4/netfilter/ip_conntrack_core.c, drivers/isdn/hisax/elsa_cs.c, drivers/isdn/hisax/teles_cs.c, drivers/isdn/hisax/avma1_cs.c, drivers/isdn/hardware/avm/avm_cs.c, drivers/bluetooth/bt3c_cs.c, drivers/bluetooth/btuart_cs.c, drivers/bluetooth/dtl1_cs.c, include/linux/netfilter_ipv4/ip_conntrack_core.h, 'get_unique_tuple' : 'stack', # net/ipv4/netfilter/ip_nat_core.c, - 'get_unmapped_area': 'bufmgt', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, + 'get_unmapped_area': 'buffer', # mm/mmap.c, mm/nommu.c, include/linux/mm.h, 'get_unused_fd' : 'other', # fs/open.c, include/linux/file.h, used to be syscall 'get_vmalloc_info': 'other', # fs/proc/proc_misc.c, 'get_write_access' : 'other', # fs/namei.c, include/linux/fs.h, used to be syscall 'get_writeback_state' : 'other', # mm/page-writeback.c, used to be syscall - 'get_zone_counts': 'bufmgt', # mm/page_alloc.c, include/linux/mmzone.h, + 'get_zone_counts': 'buffer', # mm/page_alloc.c, include/linux/mmzone.h, 'getname' : 'other', # fs/namei.c, include/linux/fs.h, used to be syscall 'getnstimeofday': 'other', # 'getrusage': 'other', # kernel/sys.c, kernel/exit.c, @@ -715,7 +803,7 @@ categories = { 'inode_sub_bytes' : 'other', # fs/stat.c, include/linux/fs.h, 'inode_times_differ' : 'other', # fs/inode.c, 'inode_update_time' : 'other', # fs/inode.c, include/linux/fs.h, - 'insert_vm_struct': 'bufmgt', # mm/mmap.c, include/linux/mm.h, + 'insert_vm_struct': 'buffer', # mm/mmap.c, include/linux/mm.h, 'install_arg_page': 'other', # fs/exec.c, include/linux/mm.h, 'internal_add_timer' : 'other', # kernel/timer.c, 'invalid_dpte_no_dismiss_10_' : 'interrupt', # @@ -795,19 +883,19 @@ categories = { 'kded_kmilod.so': 'other', # 'kdeinit': 'other', # 'kernel_read': 'other', # fs/exec.c, include/linux/fs.h, - 'kfree' : 'bufmgt', # mm/slab.c, include/linux/slab.h, - 'kfree_skbmem' : 'bufmgt', # net/core/skbuff.c, include/linux/skbuff.h, + 'kfree' : 'buffer', # mm/slab.c, include/linux/slab.h, + 'kfree_skbmem' : 'buffer', # net/core/skbuff.c, include/linux/skbuff.h, 'kill_fasync': 'other', # fs/fcntl.c, include/linux/fs.h, 'kill_proc_info' : 'other', # kernel/signal.c, include/linux/sched.h, 'kill_something_info' : 'other', # kernel/signal.c, - 'kmap': 'bufmgt', # include/asm-i386/highmem.h, - 'kmap_atomic': 'bufmgt', # include/linux/highmem.h, include/asm-i386/highmem.h, - 'kmap_high': 'bufmgt', # mm/highmem.c, - 'kmem_cache_alloc' : 'bufmgt', # mm/slab.c, include/linux/slab.h, - 'kmem_cache_free' : 'bufmgt', # mm/slab.c, include/linux/slab.h, - 'kmem_flagcheck' : 'bufmgt', # mm/slab.c, - 'kmem_freepages' : 'bufmgt', # mm/slab.c, - 'kmem_getpages' : 'bufmgt', # mm/slab.c, + 'kmap': 'buffer', # include/asm-i386/highmem.h, + 'kmap_atomic': 'buffer', # include/linux/highmem.h, include/asm-i386/highmem.h, + 'kmap_high': 'buffer', # mm/highmem.c, + 'kmem_cache_alloc' : 'buffer', # mm/slab.c, include/linux/slab.h, + 'kmem_cache_free' : 'buffer', # mm/slab.c, include/linux/slab.h, + 'kmem_flagcheck' : 'buffer', # mm/slab.c, + 'kmem_freepages' : 'buffer', # mm/slab.c, + 'kmem_getpages' : 'buffer', # mm/slab.c, 'kobject_get' : 'other', # lib/kobject.c, include/linux/kobject.h, 'kobject_put' : 'other', # lib/kobject.c, include/linux/kobject.h, 'kref_get': 'other', # lib/kref.c, include/linux/kref.h, @@ -815,9 +903,9 @@ categories = { 'ksoftirqd' : 'interrupt', # kernel/softirq.c, 'ksysguardd': 'other', # 'kthread_should_stop' : 'other', # kernel/kthread.c, include/linux/kthread.h, - 'kunmap': 'bufmgt', # include/linux/highmem.h, include/asm-i386/highmem.h, - 'kunmap_atomic': 'bufmgt', # include/linux/highmem.h, include/asm-i386/highmem.h, - 'kunmap_high': 'bufmgt', # mm/highmem.c, + 'kunmap': 'buffer', # include/linux/highmem.h, include/asm-i386/highmem.h, + 'kunmap_atomic': 'buffer', # include/linux/highmem.h, include/asm-i386/highmem.h, + 'kunmap_high': 'buffer', # mm/highmem.c, 'kwrapper': 'other', # 'ld-2.3.2.so': 'other', # 'lease_get_mtime' : 'other', # fs/locks.c, include/linux/fs.h, @@ -939,21 +1027,21 @@ categories = { 'lookup_mnt' : 'other', # fs/namespace.c, include/linux/dcache.h, 'loop' : 'interrupt', # 'loopback_xmit': 'driver', - 'lru_add_drain' : 'bufmgt', # mm/swap.c, include/linux/swap.h, - 'lru_cache_add' : 'bufmgt', # mm/swap.c, - 'lru_cache_add_active': 'bufmgt', # mm/swap.c, + 'lru_add_drain' : 'buffer', # mm/swap.c, include/linux/swap.h, + 'lru_cache_add' : 'buffer', # mm/swap.c, + 'lru_cache_add_active': 'buffer', # mm/swap.c, 'lru_put_front' : 'other', # fs/nfsd/nfscache.c, 'ls': 'driver', # drivers/fc4/fc.c, 'mail': 'other', # - 'mapping_tagged' : 'bufmgt', # mm/page-writeback.c, include/linux/fs.h, + 'mapping_tagged' : 'buffer', # mm/page-writeback.c, include/linux/fs.h, 'mark_buffer_dirty' : 'other', # fs/buffer.c, 'mark_buffer_dirty_inode' : 'other', # fs/buffer.c, include/linux/buffer_head.h, 'mark_offset_pmtmr': 'interrupt', # - 'mark_page_accessed' : 'bufmgt', # mm/swap.c, + 'mark_page_accessed' : 'buffer', # mm/swap.c, 'mask_and_ack_level_ioapic_vector': 'interrupt', # include/asm-i386/io_apic.h, 'math_state_restore': 'interrupt', # 'mawk': 'other', # - 'max_sane_readahead': 'bufmgt', # mm/readahead.c, include/linux/mm.h, + 'max_sane_readahead': 'buffer', # mm/readahead.c, include/linux/mm.h, 'max_select_fd': 'other', # fs/select.c, 'may_open': 'other', # fs/namei.c, include/linux/fs.h, 'memcmp' : 'copy', # lib/string.c, @@ -963,20 +1051,20 @@ categories = { 'memcpy_toiovec' : 'copy', # net/core/iovec.c, include/linux/socket.h, 'meminfo_read_proc': 'other', # fs/proc/proc_misc.c, 'memmove' : 'copy', # lib/string.c, include/asm-alpha/string.h, - 'mempool_alloc' : 'bufmgt', # mm/mempool.c, include/linux/mempool.h, - 'mempool_alloc_slab' : 'bufmgt', # mm/mempool.c, include/linux/mempool.h, - 'mempool_free' : 'bufmgt', # mm/mempool.c, include/linux/mempool.h, - 'mempool_free_slab' : 'bufmgt', # mm/mempool.c, include/linux/mempool.h, + 'mempool_alloc' : 'buffer', # mm/mempool.c, include/linux/mempool.h, + 'mempool_alloc_slab' : 'buffer', # mm/mempool.c, include/linux/mempool.h, + 'mempool_free' : 'buffer', # mm/mempool.c, include/linux/mempool.h, + 'mempool_free_slab' : 'buffer', # mm/mempool.c, include/linux/mempool.h, 'memscan' : 'copy', # lib/string.c, 'mkdir': 'other', # - 'mm_alloc': 'bufmgt', # kernel/fork.c, include/linux/sched.h, + 'mm_alloc': 'buffer', # kernel/fork.c, include/linux/sched.h, 'mm_init': 'driver', # drivers/block/umem.c, kernel/fork.c, 'mm_release': 'other', # kernel/fork.c, include/linux/sched.h, 'mmput': 'other', # kernel/fork.c, include/linux/sched.h, 'mod_timer' : 'other', # kernel/timer.c, include/linux/timer.h, 'move_addr_to_user' : 'copy', # net/socket.c, include/linux/socket.h, - 'move_one_page': 'bufmgt', # mm/mremap.c, - 'move_vma': 'bufmgt', # mm/mremap.c, + 'move_one_page': 'buffer', # mm/mremap.c, + 'move_vma': 'buffer', # mm/mremap.c, 'mpage_alloc' : 'other', # fs/mpage.c, 'mpage_bio_submit' : 'other', # fs/mpage.c, 'mpage_end_io_write' : 'other', # fs/mpage.c, @@ -1034,7 +1122,7 @@ categories = { 'notifier_call_chain': 'other', # kernel/sys.c, include/linux/notifier.h, 'notify_change': 'other', # fs/attr.c, include/linux/fs.h, 'nr_blockdev_pages': 'other', # fs/block_dev.c, include/linux/blkdev.h, - 'nr_free_pages': 'bufmgt', # mm/page_alloc.c, include/linux/swap.h, + 'nr_free_pages': 'buffer', # mm/page_alloc.c, include/linux/swap.h, 'nr_running': 'other', # kernel/sched.c, include/linux/sched.h, 'ns83820': 'driver', 'ns83820_do_isr' : 'driver', @@ -1059,17 +1147,17 @@ categories = { 'osf_sigprocmask' : 'other', # 'osync_buffers_list' : 'other', # fs/buffer.c, 'padzero': 'other', # fs/binfmt_elf.c, - 'page_add_anon_rmap' : 'bufmgt', # mm/rmap.c, include/linux/rmap.h, - 'page_add_file_rmap': 'bufmgt', # mm/rmap.c, include/linux/rmap.h, - 'page_address': 'bufmgt', # mm/highmem.c, include/linux/mm.h, include/linux/mm.h, include/linux/mm.h, - 'page_cache_readahead': 'bufmgt', # mm/readahead.c, include/linux/mm.h, + 'page_add_anon_rmap' : 'buffer', # mm/rmap.c, include/linux/rmap.h, + 'page_add_file_rmap': 'buffer', # mm/rmap.c, include/linux/rmap.h, + 'page_address': 'buffer', # mm/highmem.c, include/linux/mm.h, include/linux/mm.h, include/linux/mm.h, + 'page_cache_readahead': 'buffer', # mm/readahead.c, include/linux/mm.h, 'page_fault': 'interrupt', # - 'page_remove_rmap': 'bufmgt', # mm/rmap.c, include/linux/rmap.h, - 'page_slot': 'bufmgt', # mm/highmem.c, + 'page_remove_rmap': 'buffer', # mm/rmap.c, include/linux/rmap.h, + 'page_slot': 'buffer', # mm/highmem.c, 'page_symlink' : 'other', # fs/namei.c, include/linux/fs.h, - 'page_waitqueue' : 'bufmgt', # mm/filemap.c, - 'pagevec_lookup': 'bufmgt', # mm/swap.c, include/linux/pagevec.h, - 'pagevec_lookup_tag' : 'bufmgt', # mm/swap.c, include/linux/pagevec.h, + 'page_waitqueue' : 'buffer', # mm/filemap.c, + 'pagevec_lookup': 'buffer', # mm/swap.c, include/linux/pagevec.h, + 'pagevec_lookup_tag' : 'buffer', # mm/swap.c, include/linux/pagevec.h, 'pal_dtb_ldq' : 'interrupt', # 'pal_itb_ldq' : 'interrupt', # 'pal_post_interrupt' : 'interrupt', # @@ -1084,14 +1172,14 @@ categories = { 'pci_read': 'driver', # 'pci_unmap_page' : 'driver', # arch/alpha/kernel/pci_iommu.c, include/asm-generic/pci-dma-compat.h, include/asm-alpha/pci.h, 'pci_unmap_single' : 'driver', # arch/alpha/kernel/pci_iommu.c, arch/alpha/kernel/pci-noop.c, include/asm-generic/pci-dma-compat.h, drivers/scsi/aic7xxx/aic79xx_osm.h, drivers/scsi/aic7xxx/aic7xxx_osm.h, include/asm-alpha/pci.h, - 'percpu_counter_mod' : 'bufmgt', # mm/swap.c, include/linux/percpu_counter.h, + 'percpu_counter_mod' : 'buffer', # mm/swap.c, include/linux/percpu_counter.h, 'perl': 'other', # 'permission' : 'user', # fs/namei.c, include/linux/fs.h, used to be syscall 'pfifo_fast_dequeue' : 'stack', # net/sched/sch_generic.c, 'pfifo_fast_enqueue' : 'stack', # net/sched/sch_generic.c, - 'pgd_alloc': 'bufmgt', # arch/alpha/mm/init.c, include/asm-alpha/pgalloc.h, include/asm-i386/pgalloc.h, - 'pgd_ctor': 'bufmgt', # include/asm-i386/pgtable.h, - 'pgd_free': 'bufmgt', # include/asm-alpha/pgalloc.h, include/asm-i386/pgalloc.h, + 'pgd_alloc': 'buffer', # arch/alpha/mm/init.c, include/asm-alpha/pgalloc.h, include/asm-i386/pgalloc.h, + 'pgd_ctor': 'buffer', # include/asm-i386/pgtable.h, + 'pgd_free': 'buffer', # include/asm-alpha/pgalloc.h, include/asm-i386/pgalloc.h, 'pipe_ioctl': 'other', # fs/pipe.c, 'pipe_new': 'other', # fs/pipe.c, include/linux/pipe_fs_i.h, 'pipe_poll': 'other', # fs/pipe.c, @@ -1111,14 +1199,14 @@ categories = { 'poll_initwait' : 'other', # fs/select.c, include/linux/poll.h, 'portmap': 'other', # 'preempt_schedule': 'other', # kernel/sched.c, include/linux/preempt.h, - 'prep_new_page' : 'bufmgt', # mm/page_alloc.c, + 'prep_new_page' : 'buffer', # mm/page_alloc.c, 'prepare_binprm': 'other', # fs/exec.c, include/linux/binfmts.h, 'prepare_to_copy': 'interrupt', # include/asm-alpha/processor.h, include/asm-i386/processor.h, 'prepare_to_wait' : 'other', # kernel/fork.c, - 'prio_tree_expand': 'bufmgt', # mm/prio_tree.c, - 'prio_tree_insert': 'bufmgt', # mm/prio_tree.c, - 'prio_tree_remove': 'bufmgt', # mm/prio_tree.c, - 'prio_tree_replace': 'bufmgt', # mm/prio_tree.c, + 'prio_tree_expand': 'buffer', # mm/prio_tree.c, + 'prio_tree_insert': 'buffer', # mm/prio_tree.c, + 'prio_tree_remove': 'buffer', # mm/prio_tree.c, + 'prio_tree_replace': 'buffer', # mm/prio_tree.c, 'proc_alloc_inode': 'other', # fs/proc/inode.c, 'proc_calc_metrics': 'other', # fs/proc/proc_misc.c, 'proc_delete_inode': 'other', # fs/proc/inode.c, @@ -1137,8 +1225,8 @@ categories = { 'profile_task_exit': 'other', # 'profile_tick': 'other', # 'pskb_expand_head': 'stack', # net/core/skbuff.c, include/linux/skbuff.h, - 'pte_alloc_map': 'bufmgt', # mm/memory.c, - 'pte_alloc_one': 'bufmgt', # include/asm-alpha/pgalloc.h, include/asm-i386/pgalloc.h, + 'pte_alloc_map': 'buffer', # mm/memory.c, + 'pte_alloc_one': 'buffer', # include/asm-alpha/pgalloc.h, include/asm-i386/pgalloc.h, 'ptrace_cancel_bpt' : 'user', # arch/alpha/kernel/ptrace.c, arch/alpha/kernel/proto.h, used to be syscall 'pty_chars_in_buffer': 'driver', # drivers/char/pty.c, 'pty_open': 'driver', # drivers/char/pty.c, @@ -1165,10 +1253,10 @@ categories = { 'radix_tree_tagged' : 'other', # lib/radix-tree.c, include/linux/radix-tree.h, 'raise_softirq' : 'interrupt', # kernel/softirq.c, 'raise_softirq_irqoff' : 'interrupt', # kernel/softirq.c, - 'rb_erase' : 'bufmgt', # lib/rbtree.c, include/linux/rbtree.h, - 'rb_insert_color' : 'bufmgt', # lib/rbtree.c, include/linux/rbtree.h, - 'rb_next' : 'bufmgt', # lib/rbtree.c, fs/jffs2/nodelist.h, include/linux/rbtree.h, - 'rb_prev' : 'bufmgt', # lib/rbtree.c, fs/jffs2/nodelist.h, include/linux/rbtree.h, + 'rb_erase' : 'buffer', # lib/rbtree.c, include/linux/rbtree.h, + 'rb_insert_color' : 'buffer', # lib/rbtree.c, include/linux/rbtree.h, + 'rb_next' : 'buffer', # lib/rbtree.c, fs/jffs2/nodelist.h, include/linux/rbtree.h, + 'rb_prev' : 'buffer', # lib/rbtree.c, fs/jffs2/nodelist.h, include/linux/rbtree.h, 'rcu_check_callbacks' : 'other', # kernel/rcupdate.c, include/linux/rcupdate.h, 'rcu_check_quiescent_state' : 'other', # kernel/rcupdate.c, 'rcu_do_batch' : 'other', # kernel/rcupdate.c, @@ -1182,15 +1270,15 @@ categories = { 'recalc_sigpending_tsk' : 'interrupt', # kernel/signal.c, 'recalc_task_prio' : 'other', # kernel/sched.c, 'release_blocks' : 'other', # fs/ext2/balloc.c, - 'release_pages' : 'bufmgt', # mm/swap.c, include/linux/pagemap.h, + 'release_pages' : 'buffer', # mm/swap.c, include/linux/pagemap.h, 'release_sock' : 'stack', # net/core/sock.c, 'release_task': 'other', # kernel/exit.c, include/linux/sched.h, 'release_thread': 'interrupt', # arch/alpha/kernel/process.c, include/asm-um/processor-generic.h, include/asm-alpha/processor.h, include/asm-i386/processor.h, 'release_x86_irqs': 'interrupt', # include/asm-i386/irq.h, 'remove_arg_zero': 'other', # fs/exec.c, include/linux/binfmts.h, - 'remove_from_page_cache': 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, - 'remove_suid' : 'bufmgt', # mm/filemap.c, include/linux/fs.h, - 'remove_vm_struct': 'bufmgt', # mm/mmap.c, + 'remove_from_page_cache': 'buffer', # mm/filemap.c, include/linux/pagemap.h, + 'remove_suid' : 'buffer', # mm/filemap.c, include/linux/fs.h, + 'remove_vm_struct': 'buffer', # mm/mmap.c, 'remove_wait_queue' : 'other', # kernel/fork.c, 'resched_task' : 'other', # kernel/sched.c, 'reserve_blocks' : 'other', # fs/ext2/balloc.c, @@ -1207,7 +1295,7 @@ categories = { 'ret_from_sys_call' : 'user', # arch/alpha/kernel/signal.c, used to be syscall 'rm': 'other', # 'rm_from_queue': 'other', # kernel/signal.c, - 'rmqueue_bulk' : 'bufmgt', # mm/page_alloc.c, + 'rmqueue_bulk' : 'buffer', # mm/page_alloc.c, 'rt_check_expire': 'stack', # net/ipv4/route.c, 'rt_hash_code' : 'stack', # net/ipv4/route.c, 'rt_intern_hash': 'stack', # net/ipv4/route.c, net/ipv4/route.c, @@ -1268,48 +1356,48 @@ categories = { 'set_binfmt': 'other', # fs/exec.c, include/linux/binfmts.h, 'set_brk': 'user', # fs/binfmt_aout.c, fs/binfmt_elf.c, 'set_current_groups' : 'other', # kernel/sys.c, include/linux/sched.h, - 'set_page_address': 'bufmgt', # mm/highmem.c, include/linux/mm.h, include/linux/mm.h, include/linux/mm.h, - 'set_page_dirty': 'bufmgt', # mm/page-writeback.c, - 'set_slab_attr' : 'bufmgt', # mm/slab.c, + 'set_page_address': 'buffer', # mm/highmem.c, include/linux/mm.h, include/linux/mm.h, include/linux/mm.h, + 'set_page_dirty': 'buffer', # mm/page-writeback.c, + 'set_slab_attr' : 'buffer', # mm/slab.c, 'set_task_comm': 'other', # 'setfl' : 'user', # fs/fcntl.c, used to be syscall 'setup_arg_pages': 'other', # fs/exec.c, include/linux/binfmts.h, 'setup_frame' : 'interrupt', # arch/alpha/kernel/signal.c, 'setup_sigcontext' : 'interrupt', # arch/alpha/kernel/signal.c, 'show_stat': 'other', # fs/proc/proc_misc.c, - 'si_swapinfo': 'bufmgt', # mm/swapfile.c, include/linux/swap.h, include/linux/swap.h, + 'si_swapinfo': 'buffer', # mm/swapfile.c, include/linux/swap.h, include/linux/swap.h, 'sig_ignored' : 'other', # kernel/signal.c, 'signal_wake_up' : 'other', # kernel/signal.c, include/linux/sched.h, 'sigprocmask' : 'other', # kernel/signal.c, include/linux/signal.h, 'single_open': 'other', # fs/seq_file.c, include/linux/seq_file.h, - 'sk_alloc' : 'bufmgt', # net/core/sock.c, - 'sk_free' : 'bufmgt', # net/core/sock.c, - 'sk_reset_timer' : 'bufmgt', # net/core/sock.c, - 'sk_stop_timer' : 'bufmgt', # net/core/sock.c, - 'sk_stream_kill_queues' : 'bufmgt', # net/core/stream.c, - 'sk_stream_mem_schedule' : 'bufmgt', # net/core/stream.c, - 'sk_stream_rfree' : 'bufmgt', # net/core/stream.c, - 'sk_stream_wait_close' : 'bufmgt', # net/core/stream.c, - 'sk_stream_wait_memory' : 'bufmgt', # net/core/stream.c, - 'sk_stream_write_space' : 'bufmgt', # net/core/stream.c, - 'sk_wait_data' : 'bufmgt', # net/core/sock.c, + 'sk_alloc' : 'buffer', # net/core/sock.c, + 'sk_free' : 'buffer', # net/core/sock.c, + 'sk_reset_timer' : 'buffer', # net/core/sock.c, + 'sk_stop_timer' : 'buffer', # net/core/sock.c, + 'sk_stream_kill_queues' : 'buffer', # net/core/stream.c, + 'sk_stream_mem_schedule' : 'buffer', # net/core/stream.c, + 'sk_stream_rfree' : 'buffer', # net/core/stream.c, + 'sk_stream_wait_close' : 'buffer', # net/core/stream.c, + 'sk_stream_wait_memory' : 'buffer', # net/core/stream.c, + 'sk_stream_write_space' : 'buffer', # net/core/stream.c, + 'sk_wait_data' : 'buffer', # net/core/sock.c, 'skb_checksum': 'stack', # net/core/skbuff.c, include/linux/skbuff.h, 'skb_checksum_help': 'stack', # net/core/dev.c, include/linux/netdevice.h, - 'skb_clone' : 'bufmgt', # net/core/skbuff.c, include/linux/skbuff.h, + 'skb_clone' : 'buffer', # net/core/skbuff.c, include/linux/skbuff.h, 'skb_copy_and_csum_bits' : 'copy', # net/core/skbuff.c, include/linux/skbuff.h, 'skb_copy_and_csum_datagram':'copy', 'skb_copy_bits' : 'copy', # net/core/skbuff.c, include/linux/skbuff.h, 'skb_copy_datagram_iovec' : 'copy', # net/core/datagram.c, include/linux/skbuff.h, - 'skb_dequeue' : 'bufmgt', # net/core/skbuff.c, include/linux/skbuff.h, - 'skb_drop_fraglist' : 'bufmgt', # net/core/skbuff.c, - 'skb_free_datagram' : 'bufmgt', # net/core/datagram.c, include/linux/skbuff.h, + 'skb_dequeue' : 'buffer', # net/core/skbuff.c, include/linux/skbuff.h, + 'skb_drop_fraglist' : 'buffer', # net/core/skbuff.c, + 'skb_free_datagram' : 'buffer', # net/core/datagram.c, include/linux/skbuff.h, 'skb_queue_head': 'stack', # net/core/skbuff.c, include/linux/skbuff.h, - 'skb_queue_tail' : 'bufmgt', # net/core/skbuff.c, include/linux/skbuff.h, - 'skb_read_and_csum_bits' : 'bufmgt', # net/sunrpc/xprt.c, - 'skb_recv_datagram' : 'bufmgt', # net/core/datagram.c, include/linux/skbuff.h, - 'skb_release_data' : 'bufmgt', # net/core/skbuff.c, net/core/dev.c, + 'skb_queue_tail' : 'buffer', # net/core/skbuff.c, include/linux/skbuff.h, + 'skb_read_and_csum_bits' : 'buffer', # net/sunrpc/xprt.c, + 'skb_recv_datagram' : 'buffer', # net/core/datagram.c, include/linux/skbuff.h, + 'skb_release_data' : 'buffer', # net/core/skbuff.c, net/core/dev.c, 'skip_atoi': 'other', # lib/vsprintf.c, - 'slab_destroy' : 'bufmgt', # mm/slab.c, + 'slab_destroy' : 'buffer', # mm/slab.c, 'smp_apic_timer_interrupt': 'interrupt', # 'smp_percpu_timer_interrupt' : 'interrupt', # arch/alpha/kernel/smp.c, arch/alpha/kernel/proto.h, 'snap_rcv': 'stack', # net/802/psnap.c, @@ -1342,7 +1430,7 @@ categories = { 'sockfd_lookup' : 'user', # net/socket.c, net/sched/sch_atm.c, include/linux/net.h, used to be syscall 'sockfs_delete_dentry' : 'user', # net/socket.c, used to be syscall 'sort': 'driver', # drivers/scsi/eata.c, drivers/scsi/u14-34f.c, - 'split_vma': 'bufmgt', # mm/mmap.c, include/linux/mm.h, + 'split_vma': 'buffer', # mm/mmap.c, include/linux/mm.h, 'sprintf' : 'other', # lib/vsprintf.c, drivers/isdn/hardware/eicon/platform.h, 'sshd': 'other', # 'steal_locks': 'other', # fs/locks.c, include/linux/fs.h, @@ -1352,7 +1440,7 @@ categories = { 'strncpy' : 'copy', # lib/string.c, include/asm-alpha/string.h, 'strncpy_from_user': 'copy', # include/asm-alpha/uaccess.h, include/asm-i386/uaccess.h, 'strnlen_user': 'other', # include/asm-alpha/uaccess.h, include/asm-i386/uaccess.h, - 'submit_bh' : 'bufmgt', # fs/buffer.c, include/linux/buffer_head.h, + 'submit_bh' : 'buffer', # fs/buffer.c, include/linux/buffer_head.h, 'submit_bio' : 'other', # drivers/block/ll_rw_blk.c, include/linux/fs.h, 'sunrpc': 'other', # 'svc_authenticate' : 'other', # net/sunrpc/svcauth.c, include/linux/sunrpc/svcauth.h, @@ -1539,13 +1627,13 @@ categories = { 'tcp_v4_synq_add' : 'stack', # net/ipv4/tcp_ipv4.c, 'tcp_vegas_init' : 'stack', # net/ipv4/tcp_input.c, 'tcp_write_xmit' : 'stack', # net/ipv4/tcp_output.c, - 'test_clear_page_dirty': 'bufmgt', # mm/page-writeback.c, include/linux/page-flags.h, - 'test_clear_page_writeback' : 'bufmgt', # mm/page-writeback.c, include/linux/page-flags.h, - 'test_set_page_writeback' : 'bufmgt', # mm/page-writeback.c, include/linux/page-flags.h, + 'test_clear_page_dirty': 'buffer', # mm/page-writeback.c, include/linux/page-flags.h, + 'test_clear_page_writeback' : 'buffer', # mm/page-writeback.c, include/linux/page-flags.h, + 'test_set_page_writeback' : 'buffer', # mm/page-writeback.c, include/linux/page-flags.h, 'timer_interrupt' : 'interrupt', # arch/alpha/kernel/time.c, arch/alpha/kernel/proto.h, 'tr': 'other', # - 'truncate_complete_page': 'bufmgt', # mm/truncate.c, - 'truncate_inode_pages': 'bufmgt', # mm/truncate.c, include/linux/mm.h, + 'truncate_complete_page': 'buffer', # mm/truncate.c, + 'truncate_inode_pages': 'buffer', # mm/truncate.c, include/linux/mm.h, 'try_to_wake_up' : 'other', # kernel/sched.c, 'tsunami_readb': 'driver', 'tsunami_readl' : 'interrupt', # include/asm-alpha/core_tsunami.h, @@ -1577,14 +1665,14 @@ categories = { 'unix': 'other', # 'unlock_buffer' : 'other', # fs/buffer.c, 'unlock_new_inode': 'other', # fs/inode.c, include/linux/fs.h, - 'unlock_page' : 'bufmgt', # mm/filemap.c, - 'unmap_mapping_range': 'bufmgt', # mm/memory.c, include/linux/mm.h, - 'unmap_page_range': 'bufmgt', # mm/memory.c, - 'unmap_region': 'bufmgt', # mm/mmap.c, + 'unlock_page' : 'buffer', # mm/filemap.c, + 'unmap_mapping_range': 'buffer', # mm/memory.c, include/linux/mm.h, + 'unmap_page_range': 'buffer', # mm/memory.c, + 'unmap_region': 'buffer', # mm/mmap.c, 'unmap_underlying_metadata' : 'other', # fs/buffer.c, include/linux/buffer_head.h, - 'unmap_vma': 'bufmgt', # mm/mmap.c, - 'unmap_vma_list': 'bufmgt', # mm/mmap.c, - 'unmap_vmas': 'bufmgt', # mm/memory.c, include/linux/mm.h, + 'unmap_vma': 'buffer', # mm/mmap.c, + 'unmap_vma_list': 'buffer', # mm/mmap.c, + 'unmap_vmas': 'buffer', # mm/memory.c, include/linux/mm.h, 'unmask_IO_APIC_irq': 'interrupt', # 'unmask_IO_APIC_vector': 'interrupt', # 'unqueue_me': 'other', # kernel/futex.c, @@ -1610,28 +1698,28 @@ categories = { 'vfs_unlink': 'other', # fs/namei.c, include/linux/fs.h, 'vfs_write' : 'user', # fs/read_write.c, include/linux/fs.h, used to be syscall 'vfs_writev' : 'user', # fs/read_write.c, include/linux/fs.h, used to be syscall - 'vma_adjust': 'bufmgt', # mm/mmap.c, include/linux/mm.h, - 'vma_link': 'bufmgt', # mm/mmap.c, - 'vma_merge': 'bufmgt', # mm/mmap.c, include/linux/mm.h, - 'vma_prio_tree_add': 'bufmgt', # mm/prio_tree.c, include/linux/mm.h, - 'vma_prio_tree_insert': 'bufmgt', # mm/prio_tree.c, include/linux/mm.h, - 'vma_prio_tree_remove': 'bufmgt', # mm/prio_tree.c, include/linux/mm.h, + 'vma_adjust': 'buffer', # mm/mmap.c, include/linux/mm.h, + 'vma_link': 'buffer', # mm/mmap.c, + 'vma_merge': 'buffer', # mm/mmap.c, include/linux/mm.h, + 'vma_prio_tree_add': 'buffer', # mm/prio_tree.c, include/linux/mm.h, + 'vma_prio_tree_insert': 'buffer', # mm/prio_tree.c, include/linux/mm.h, + 'vma_prio_tree_remove': 'buffer', # mm/prio_tree.c, include/linux/mm.h, 'vmstat_open': 'other', # fs/proc/proc_misc.c, - 'vmstat_show': 'bufmgt', # mm/page_alloc.c, - 'vmtruncate': 'bufmgt', # mm/nommu.c, mm/memory.c, include/linux/mm.h, + 'vmstat_show': 'buffer', # mm/page_alloc.c, + 'vmtruncate': 'buffer', # mm/nommu.c, mm/memory.c, include/linux/mm.h, 'vsnprintf' : 'other', # lib/vsprintf.c, include/linux/kernel.h, 'vsprintf' : 'driver', # lib/vsprintf.c, arch/alpha/boot/main.c, drivers/scsi/aic7xxx_old/aic7xxx_proc.c, include/linux/kernel.h, 'wait_for_completion': 'driver', # drivers/acorn/block/mfmhd.c, kernel/sched.c, - 'wait_on_page_writeback_range' : 'bufmgt', # mm/filemap.c, + 'wait_on_page_writeback_range' : 'buffer', # mm/filemap.c, 'wait_task_zombie': 'other', # kernel/exit.c, 'wake_futex': 'other', # kernel/futex.c, 'wake_up_buffer' : 'other', # fs/buffer.c, include/linux/buffer_head.h, 'wake_up_inode' : 'other', # fs/inode.c, include/linux/writeback.h, 'wake_up_new_task': 'other', # - 'wake_up_page' : 'bufmgt', # mm/filemap.c, + 'wake_up_page' : 'buffer', # mm/filemap.c, 'wake_up_process' : 'other', # kernel/sched.c, 'wake_up_state' : 'other', # kernel/sched.c, - 'wb_timer_fn': 'bufmgt', # mm/page-writeback.c, mm/page-writeback.c, + 'wb_timer_fn': 'buffer', # mm/page-writeback.c, mm/page-writeback.c, 'wc': 'other', # 'work_notifysig': 'other', # 'work_pending' : 'other', # @@ -1647,9 +1735,9 @@ categories = { 'xdr_partial_copy_from_skb' : 'copy', # net/sunrpc/xdr.c, include/linux/sunrpc/xdr.h, 'xfrm_lookup' : 'stack', # net/xfrm/xfrm_policy.c, 'xmms': 'other', # - 'zap_pmd_range': 'bufmgt', # mm/memory.c, - 'zap_pte_range': 'bufmgt', # mm/memory.c, - 'zone_statistics' : 'bufmgt', # mm/page_alloc.c, + 'zap_pmd_range': 'buffer', # mm/memory.c, + 'zap_pte_range': 'buffer', # mm/memory.c, + 'zone_statistics' : 'buffer', # mm/page_alloc.c, 'libaprutil-0.so.0' : 'user', 'libapr-0.so.0' : 'user', 'httpd' : 'user', @@ -1660,7 +1748,7 @@ categories = { 'ip_route_output_slow': 'stack', 'tcp_sendpage': 'copy', 'file_send_actor': 'copy', - 'flush_tlb_page': 'bufmgt', + 'flush_tlb_page': 'buffer', 'sock_common_setsockopt': 'stack', 'sock_sendpage': 'copy', @@ -1668,7 +1756,7 @@ categories = { # New functions # - '__alloc_percpu': 'bufmgt', # mm/slab.c, include/linux/percpu.h, + '__alloc_percpu': 'buffer', # mm/slab.c, include/linux/percpu.h, '__pskb_pull_tail': 'stack', # net/core/skbuff.c, include/linux/skbuff.h, '__reml': 'other', # arch/alpha/kernel/alpha_ksyms.c, '__tasklet_hi_schedule': 'interrupt', # kernel/softirq.c, @@ -1681,13 +1769,13 @@ categories = { 'alcor_disable_irq': 'interrupt', # arch/alpha/kernel/sys_alcor.c, 'alpha_read_fp_reg': 'other', # arch/alpha/lib/fpreg.c, arch/alpha/kernel/proto.h, arch/alpha/math-emu/math.c, include/asm-alpha/fpu.h, 'atkbd_probe': 'other', # drivers/input/keyboard/atkbd.c, - 'background_writeout': 'bufmgt', # mm/page-writeback.c, mm/page-writeback.c, - 'bad_page': 'bufmgt', # mm/page_alloc.c, + 'background_writeout': 'buffer', # mm/page-writeback.c, mm/page-writeback.c, + 'bad_page': 'buffer', # mm/page_alloc.c, 'batch_entropy_process': 'other', # drivers/char/random.c, drivers/char/random.c, 'block_hotplug_filter': 'driver', # drivers/block/genhd.c, 'brioctl_set': 'stack', # net/socket.c, include/linux/if_bridge.h, 'cdev_put': 'fs', # fs/char_dev.c, include/linux/cdev.h, - 'change_protection': 'bufmgt', # mm/mprotect.c, + 'change_protection': 'buffer', # mm/mprotect.c, 'check_timer_failed': 'interrupt', # kernel/timer.c, 'clipper_disable_irq': 'interrupt', # arch/alpha/kernel/sys_dp264.c, 'clipper_enable_irq': 'interrupt', # arch/alpha/kernel/sys_dp264.c, @@ -1700,8 +1788,8 @@ categories = { 'do_entDbg': 'interrupt', # arch/alpha/kernel/traps.c, 'do_proc_dointvec_jiffies_conv': 'interrupt', # kernel/sysctl.c, 'down_interruptible': 'interrupt', # arch/alpha/kernel/semaphore.c, include/asm-alpha/semaphore.h, include/asm-i386/semaphore.h, include/asm-alpha/semaphore.h, net/ipv4/netfilter/ip_tables.c, net/ipv6/netfilter/ip6_tables.c, - 'drain_array': 'bufmgt', # - 'drain_cpu_caches': 'bufmgt', # mm/slab.c, + 'drain_array': 'buffer', # + 'drain_cpu_caches': 'buffer', # mm/slab.c, 'dummy_file_fcntl': 'other', # security/dummy.c, 'dummy_sem_semop': 'other', # security/dummy.c, 'emit_log_char': 'other', # kernel/printk.c, @@ -1711,19 +1799,19 @@ categories = { 'eth_header_parse': 'stack', # net/ethernet/eth.c, include/linux/etherdevice.h, 'ethtool_get_settings': 'stack', # net/core/ethtool.c, 'fifo_open': 'fs', # fs/fifo.c, - 'find_trylock_page': 'bufmgt', # mm/filemap.c, include/linux/pagemap.h, - 'find_undo': 'bufmgt', # ipc/sem.c, - 'find_user': 'bufmgt', # kernel/user.c, include/linux/sched.h, + 'find_trylock_page': 'buffer', # mm/filemap.c, include/linux/pagemap.h, + 'find_undo': 'buffer', # ipc/sem.c, + 'find_user': 'buffer', # kernel/user.c, include/linux/sched.h, 'flow_cache_cpu_prepare': 'stack', # net/core/flow.c, 'flow_cache_flush_per_cpu': 'stack', # net/core/flow.c, 'flow_cache_flush_tasklet': 'stack', # net/core/flow.c, 'flow_key_compare': 'stack', # net/core/flow.c, 'flush_icache_user_range': 'interrupt', # arch/alpha/kernel/smp.c, include/asm-alpha/cacheflush.h, include/asm-alpha/cacheflush.h, include/asm-i386/cacheflush.h, 'flush_tlb_mm': 'interrupt', # arch/alpha/kernel/smp.c, include/asm-alpha/tlbflush.h, include/asm-i386/tlbflush.h, include/asm-alpha/tlbflush.h, include/asm-i386/tlbflush.h, - 'force_page_cache_readahead': 'bufmgt', # mm/readahead.c, include/linux/mm.h, - 'free_percpu': 'bufmgt', # mm/slab.c, include/linux/percpu.h, include/linux/percpu.h, - 'generic_file_sendfile': 'bufmgt', # mm/filemap.c, include/linux/fs.h, - 'get_one_pte_map': 'bufmgt', # mm/mremap.c, + 'force_page_cache_readahead': 'buffer', # mm/readahead.c, include/linux/mm.h, + 'free_percpu': 'buffer', # mm/slab.c, include/linux/percpu.h, include/linux/percpu.h, + 'generic_file_sendfile': 'buffer', # mm/filemap.c, include/linux/fs.h, + 'get_one_pte_map': 'buffer', # mm/mremap.c, 'gunzip': 'other', # lib/inflate.c, 'handle_ipi': 'interrupt', # arch/alpha/kernel/smp.c, arch/alpha/kernel/proto.h, 'input_devices_read': 'driver', # drivers/input/input.c, @@ -1748,8 +1836,8 @@ categories = { 'isp1020_intr_handler': 'other', # drivers/scsi/qlogicisp.c, drivers/scsi/qlogicisp.c, 'isp1020_queuecommand': 'other', # drivers/scsi/qlogicisp.c, drivers/scsi/qlogicisp.h, 'kernel_thread': 'interrupt', # include/asm-um/processor-generic.h, include/asm-alpha/processor.h, include/asm-i386/processor.h, - 'kmem_find_general_cachep': 'bufmgt', # mm/slab.c, - 'kmem_ptr_validate': 'bufmgt', # mm/slab.c, + 'kmem_find_general_cachep': 'buffer', # mm/slab.c, + 'kmem_ptr_validate': 'buffer', # mm/slab.c, 'llc_mac_hdr_init': 'stack', # net/llc/llc_output.c, net/llc/llc_output.h, 'lock_rename': 'fs', # fs/namei.c, include/linux/namei.h, 'lookup_undo': 'stack', # ipc/sem.c, @@ -1759,7 +1847,7 @@ categories = { 'netlink_release': 'stack', # net/netlink/netlink_dev.c, net/netlink/af_netlink.c, 'nf_log_packet': 'stack', # net/core/netfilter.c, include/linux/netfilter_logging.h, include/linux/netfilter.h, 'nf_queue': 'stack', # net/core/netfilter.c, - 'nr_free_zone_pages': 'bufmgt', # mm/page_alloc.c, + 'nr_free_zone_pages': 'buffer', # mm/page_alloc.c, 'osf_writev': 'driver', # arch/alpha/kernel/osf_sys.c, 'pci_map_sg': 'driver', # arch/alpha/kernel/pci-noop.c, arch/alpha/kernel/pci_iommu.c, include/asm-generic/pci-dma-compat.h, include/asm-alpha/pci.h, 'pci_unmap_sg': 'driver', # arch/alpha/kernel/pci-noop.c, arch/alpha/kernel/pci_iommu.c, include/asm-generic/pci-dma-compat.h, include/asm-alpha/pci.h, @@ -1770,7 +1858,7 @@ categories = { 'prepare_timeout': 'interrupt', # ipc/mqueue.c, 'printk': 'other', # kernel/printk.c, drivers/md/raid6.h, 'process_mcheck_info': 'interrupt', # arch/alpha/kernel/irq_alpha.c, arch/alpha/kernel/proto.h, - 'read_cache_pages': 'bufmgt', # mm/readahead.c, include/linux/pagemap.h, + 'read_cache_pages': 'buffer', # mm/readahead.c, include/linux/pagemap.h, 'register_gifconf': 'stack', # net/core/dev.c, include/linux/netdevice.h, 'rwsem_down_read_failed': 'interrupt', # lib/rwsem.c, include/asm-alpha/rwsem.h, 'search_exception_tables': 'interrupt', # kernel/extable.c, include/linux/module.h, @@ -1790,10 +1878,10 @@ categories = { 'sock_wait_for_wmem': 'stack', # net/core/sock.c, 'srm_dispatch': 'other', # 'srm_fixup': 'other', # include/asm-alpha/console.h, - 'stxcpy_aligned': 'bufmgt', # + 'stxcpy_aligned': 'buffer', # 'sys_capset': 'other', # kernel/capability.c, include/linux/syscalls.h, - 'sys_fadvise64': 'bufmgt', # mm/fadvise.c, include/linux/syscalls.h, - 'sys_fadvise64_64': 'bufmgt', # mm/fadvise.c, include/linux/syscalls.h, + 'sys_fadvise64': 'buffer', # mm/fadvise.c, include/linux/syscalls.h, + 'sys_fadvise64_64': 'buffer', # mm/fadvise.c, include/linux/syscalls.h, 'sys_newfstat': 'fs', # fs/stat.c, include/linux/syscalls.h, 'sys_semop': 'stack', # ipc/sem.c, include/linux/syscalls.h, 'sys_semtimedop': 'stack', # ipc/sem.c, include/linux/syscalls.h, @@ -1825,15 +1913,24 @@ categories = { 'unregister_netdevice': 'stack', # net/core/dev.c, include/linux/netdevice.h, 'update_queue': 'stack', # ipc/sem.c, 'vegas_cong_avoid': 'stack', # net/ipv4/tcp_input.c, - 'vm_acct_memory': 'bufmgt', # mm/swap.c, include/linux/mman.h, + 'vm_acct_memory': 'buffer', # mm/swap.c, include/linux/mman.h, 'vsscanf': 'other', # lib/vsprintf.c, include/linux/kernel.h, 'wait_for_packet': 'stack', # net/core/datagram.c, 'westwood_update_window': 'stack', # net/ipv4/tcp_input.c, 'within_one_quad': 'other', # } -categories_re = [ +pc_categories_re = [ # ( re.compile('.*'), 'other' ) ] +def pc_categorize(symbol): + from categories import pc_categories, pc_categories_re + if symbol in pc_categories: + return pc_categories[symbol] + for regexp, category in pc_categories_re: + if regexp.match(symbol): + return category + + return None diff --git a/util/stats/db.py b/util/stats/db.py index ab005e67b..1ece6df88 100644 --- a/util/stats/db.py +++ b/util/stats/db.py @@ -103,6 +103,20 @@ class Node(object): def __str__(self): return self.name +class Result(object): + def __init__(self, x, y): + self.data = {} + self.x = x + self.y = y + + def __contains__(self, run): + return run in self.data + + def __getitem__(self, run): + if run not in self.data: + self.data[run] = [ [ 0.0 ] * self.y for i in xrange(self.x) ] + return self.data[run] + class Database(object): def __init__(self): self.host = 'zizzer.pool' @@ -135,7 +149,23 @@ class Database(object): self.runs = None self.bins = None self.ticks = None - self.__dict__['get'] = type(self).sum + self.method = 'sum' + self._method = type(self).sum + + def get(self, job, stat): + run = self.allRunNames.get(job.name, None) + if run is None: + print 'run "%s" not found' % job + return None + + from info import scalar, vector, value, values, total, len + stat.system = self[job.system] + if scalar(stat): + return value(stat, run.run) + if vector(stat): + return values(stat, run.run) + + return None def query(self, sql): self.cursor.execute(sql) @@ -203,7 +233,7 @@ class Database(object): self.query('select * from stats') import info for result in self.cursor.fetchall(): - stat = info.NewStat(StatData(result)) + stat = info.NewStat(self, StatData(result)) self.append(stat) self.allStats.append(stat) self.allStatIds[stat.stat] = stat @@ -421,30 +451,17 @@ class Database(object): def stdev(self, stat, bins, ticks): return self.outer('stddev', 'sum', stat, bins, ticks) - def __getattribute__(self, attr): - if attr != 'get': - return super(Database, self).__getattribute__(attr) - - if self.__dict__['get'] == type(self).sum: - return 'sum' - elif self.__dict__['get'] == type(self).avg: - return 'avg' - elif self.__dict__['get'] == type(self).stdev: - return 'stdev' - else: - return '' - def __setattr__(self, attr, value): - if attr != 'get': - super(Database, self).__setattr__(attr, value) + super(Database, self).__setattr__(attr, value) + if attr != 'method': return if value == 'sum': - self.__dict__['get'] = type(self).sum + self._method = self.sum elif value == 'avg': - self.__dict__['get'] = type(self).avg + self._method = self.avg elif value == 'stdev': - self.__dict__['get'] = type(self).stdev + self._method = self.stdev else: raise AttributeError, "can only set get to: sum | avg | stdev" @@ -453,10 +470,12 @@ class Database(object): bins = self.bins if ticks is None: ticks = self.ticks - sql = self.__dict__['get'](self, stat, bins, ticks) + sql = self._method(self, stat, bins, ticks) self.query(sql) runs = {} + xmax = 0 + ymax = 0 for x in self.cursor.fetchall(): data = Data(x) if not runs.has_key(data.run): @@ -464,8 +483,17 @@ class Database(object): if not runs[data.run].has_key(data.x): runs[data.run][data.x] = {} + xmax = max(xmax, data.x) + ymax = max(ymax, data.y) runs[data.run][data.x][data.y] = data.data - return runs + + results = Result(xmax + 1, ymax + 1) + for run,data in runs.iteritems(): + result = results[run] + for x,ydata in data.iteritems(): + for y,data in ydata.iteritems(): + result[x][y] = data + return results def __getitem__(self, key): return self.stattop[key] diff --git a/util/stats/display.py b/util/stats/display.py index 629684ca4..fbcff5c70 100644 --- a/util/stats/display.py +++ b/util/stats/display.py @@ -26,7 +26,7 @@ class Value: def __init__(self, value, precision, percent = False): - self.value = value + self.value = float(value) self.precision = precision self.percent = percent def __str__(self): @@ -90,61 +90,60 @@ class Print: class VectorDisplay: def display(self): + if not self.value: + return + p = Print() p.flags = self.flags p.precision = self.precision - if isinstance(self.value, (list, tuple)): - if not len(self.value): - return - - mytotal = reduce(lambda x,y: float(x) + float(y), self.value) - mycdf = 0.0 + if not isinstance(self.value, (list, tuple)): + p.name = self.name + p.desc = self.desc + p.value = self.value + p.display() + return - value = self.value + mytotal = reduce(lambda x,y: float(x) + float(y), self.value) + mycdf = 0.0 - if display_all: - subnames = [ '[%d]' % i for i in range(len(value)) ] - else: - subnames = [''] * len(value) - - if self.__dict__.has_key('subnames'): - for i,each in enumerate(self.subnames): - if len(each) > 0: - subnames[i] = '.%s' % each - - subdescs = [self.desc]*len(value) - if self.__dict__.has_key('subdescs'): - for i in xrange(min(len(value), len(self.subdescs))): - subdescs[i] = self.subdescs[i] - - for val,sname,sdesc in map(None, value, subnames, subdescs): - if mytotal > 0.0: - mypdf = float(val) / float(mytotal) - mycdf += mypdf - if (self.flags & flags_pdf): - p.pdf = mypdf - p.cdf = mycdf - - if len(sname) == 0: - continue - - p.name = self.name + sname - p.desc = sdesc - p.value = val - p.display() - - if (self.flags & flags_total): - if (p.__dict__.has_key('pdf')): del p.__dict__['pdf'] - if (p.__dict__.has_key('cdf')): del p.__dict__['cdf'] - p.name = self.name + '.total' - p.desc = self.desc - p.value = mytotal - p.display() + value = self.value + if display_all: + subnames = [ '[%d]' % i for i in range(len(value)) ] else: - p.name = self.name - p.desc = self.desc - p.value = self.value + subnames = [''] * len(value) + + if self.__dict__.has_key('subnames'): + for i,each in enumerate(self.subnames): + if len(each) > 0: + subnames[i] = '.%s' % each + + subdescs = [self.desc]*len(value) + if self.__dict__.has_key('subdescs'): + for i in xrange(min(len(value), len(self.subdescs))): + subdescs[i] = self.subdescs[i] + + for val,sname,sdesc in map(None, value, subnames, subdescs): + if mytotal > 0.0: + mypdf = float(val) / float(mytotal) + mycdf += mypdf + if (self.flags & flags_pdf): + p.pdf = mypdf + p.cdf = mycdf + + if len(sname) == 0: + continue + + p.name = self.name + sname + p.desc = sdesc + p.value = val p.display() + if (self.flags & flags_total): + if (p.__dict__.has_key('pdf')): del p.__dict__['pdf'] + if (p.__dict__.has_key('cdf')): del p.__dict__['cdf'] + p.name = self.name + '.total' + p.desc = self.desc + p.value = mytotal + p.display() diff --git a/util/stats/info.py b/util/stats/info.py index ae5d3211f..889af6d53 100644 --- a/util/stats/info.py +++ b/util/stats/info.py @@ -27,391 +27,347 @@ from __future__ import division import operator, re, types -source = None -display_run = 0 -global globalTicks -globalTicks = None - -def total(f): - if isinstance(f, FormulaStat): - v = f.value - else: - v = f - - f = FormulaStat() - if isinstance(v, (list, tuple)): - f.value = reduce(operator.add, v) - else: - f.value = v - - return f - -def unaryop(op, f): - if isinstance(f, FormulaStat): - v = f.value - else: - v = f - - if isinstance(v, (list, tuple)): - return map(op, v) - else: - return op(v) - -def zerodiv(lv, rv): - if rv == 0.0: - return 0.0 - else: - return operator.truediv(lv, rv) - -def wrapop(op, lv, rv): - if isinstance(lv, str): - return lv - - if isinstance(rv, str): - return rv - - return op(lv, rv) - -def same(lrun, rrun): - for lx,rx in zip(lrun.keys(),rrun.keys()): - if lx != rx: - print 'lx != rx' - print lx, rx - print lrun.keys() - print rrun.keys() - return False - for ly,ry in zip(lrun[lx].keys(),rrun[rx].keys()): - if ly != ry: - print 'ly != ry' - print ly, ry - print lrun[lx].keys() - print rrun[rx].keys() - return False - return True - - -def binaryop(op, lf, rf): - result = {} - - if isinstance(lf, FormulaStat) and isinstance(rf, FormulaStat): - lv = lf.value - rv = rf.value - - theruns = [] - for r in lv.keys(): - if rv.has_key(r): - if same(lv[r], rv[r]): - theruns.append(r) - else: - raise AttributeError - - for run in theruns: - result[run] = {} - for x in lv[run].keys(): - result[run][x] = {} - for y in lv[run][x].keys(): - result[run][x][y] = wrapop(op, lv[run][x][y], - rv[run][x][y]) - elif isinstance(lf, FormulaStat): - lv = lf.value - for run in lv.keys(): - result[run] = {} - for x in lv[run].keys(): - result[run][x] = {} - for y in lv[run][x].keys(): - result[run][x][y] = wrapop(op, lv[run][x][y], rf) - elif isinstance(rf, FormulaStat): - rv = rf.value - for run in rv.keys(): - result[run] = {} - for x in rv[run].keys(): - result[run][x] = {} - for y in rv[run][x].keys(): - result[run][x][y] = wrapop(op, lf, rv[run][x][y]) - +def unproxy(proxy): + if hasattr(proxy, '__unproxy__'): + return proxy.__unproxy__() + + return proxy + +def scalar(stat): + stat = unproxy(stat) + assert(stat.__scalar__() != stat.__vector__()) + return stat.__scalar__() + +def vector(stat): + stat = unproxy(stat) + assert(stat.__scalar__() != stat.__vector__()) + return stat.__vector__() + +def value(stat, *args): + stat = unproxy(stat) + return stat.__value__(*args) + +def values(stat, run): + stat = unproxy(stat) + result = [] + for i in xrange(len(stat)): + val = value(stat, run, i) + if val is None: + return None + result.append(val) return result -def sums(x, y): - if isinstance(x, (list, tuple)): - return map(lambda x, y: x + y, x, y) - else: - return x + y - -def alltrue(seq): - return reduce(lambda x, y: x and y, seq) - -def allfalse(seq): - return not reduce(lambda x, y: x or y, seq) - -def enumerate(seq): - return map(None, range(len(seq)), seq) - -def cmp(a, b): - if a < b: - return -1 - elif a == b: - return 0 - else: - return 1 - -class Statistic(object): - - def __init__(self, data): - self.__dict__.update(data.__dict__) - if not self.__dict__.has_key('value'): - self.__dict__['value'] = None - if not self.__dict__.has_key('bins'): - self.__dict__['bins'] = None - if not self.__dict__.has_key('ticks'): - self.__dict__['ticks'] = None - if 'vc' not in self.__dict__: - self.vc = {} - - def __getattribute__(self, attr): - if attr == 'ticks': - if self.__dict__['ticks'] != globalTicks: - self.__dict__['value'] = None - self.__dict__['ticks'] = globalTicks - return self.__dict__['ticks'] - if attr == 'value': - if self.__dict__['ticks'] != globalTicks: - if self.__dict__['ticks'] != None and \ - len(self.__dict__['ticks']) == 1: - self.vc[self.__dict__['ticks'][0]] = self.__dict__['value'] - self.__dict__['ticks'] = globalTicks - if len(globalTicks) == 1 and self.vc.has_key(globalTicks[0]): - self.__dict__['value'] = self.vc[globalTicks[0]] - else: - self.__dict__['value'] = None - if self.__dict__['value'] == None: - self.__dict__['value'] = self.getValue() - return self.__dict__['value'] - else: - return super(Statistic, self).__getattribute__(attr) - - def __setattr__(self, attr, value): - if attr == 'bins' or attr == 'ticks': - if attr == 'bins': - if value is not None: - value = source.getBin(value) - #elif attr == 'ticks' and type(value) is str: - # value = [ int(x) for x in value.split() ] - - self.__dict__[attr] = value - self.__dict__['value'] = None - self.vc = {} - else: - super(Statistic, self).__setattr__(attr, value) +def total(stat, run): + return sum(values(stat, run)) - def getValue(self): - raise AttributeError, 'getValue() must be defined' - - def zero(self): - return False +def len(stat): + stat = unproxy(stat) + return stat.__len__() - def __ne__(self, other): - return not (self == other) +class Value(object): + def __scalar__(self): + raise AttributeError, "must define __scalar__ for %s" % (type (self)) + def __vector__(self): + raise AttributeError, "must define __vector__ for %s" % (type (self)) - def __str__(self): - return '%f' % (float(self)) - -class FormulaStat(object): def __add__(self, other): - f = FormulaStat() - f.value = binaryop(operator.add, self, other) - return f + return BinaryProxy(operator.__add__, self, other) def __sub__(self, other): - f = FormulaStat() - f.value = binaryop(operator.sub, self, other) - return f + return BinaryProxy(operator.__sub__, self, other) def __mul__(self, other): - f = FormulaStat() - f.value = binaryop(operator.mul, self, other) - return f + return BinaryProxy(operator.__mul__, self, other) + def __div__(self, other): + return BinaryProxy(operator.__div__, self, other) def __truediv__(self, other): - f = FormulaStat() - f.value = binaryop(zerodiv, self, other) - return f - def __mod__(self, other): - f = FormulaStat() - f.value = binaryop(operator.mod, self, other) - return f + return BinaryProxy(operator.__truediv__, self, other) + def __floordiv__(self, other): + return BinaryProxy(operator.__floordiv__, self, other) + def __radd__(self, other): - f = FormulaStat() - f.value = binaryop(operator.add, other, self) - return f + return BinaryProxy(operator.__add__, other, self) def __rsub__(self, other): - f = FormulaStat() - f.value = binaryop(operator.sub, other, self) - return f + return BinaryProxy(operator.__sub__, other, self) def __rmul__(self, other): - f = FormulaStat() - f.value = binaryop(operator.mul, other, self) - return f + return BinaryProxy(operator.__mul__, other, self) + def __rdiv__(self, other): + return BinaryProxy(operator.__div__, other, self) def __rtruediv__(self, other): - f = FormulaStat() - f.value = binaryop(zerodiv, other, self) - return f - def __rmod__(self, other): - f = FormulaStat() - f.value = binaryop(operator.mod, other, self) - return f + return BinaryProxy(operator.__truediv__, other, self) + def __rfloordiv__(self, other): + return BinaryProxy(operator.__floordiv__, other, self) + def __neg__(self): - f = FormulaStat() - f.value = unaryop(operator.neg, self) - return f - def __getitem__(self, idx): - f = FormulaStat() - f.value = {} - for key in self.value.keys(): - f.value[key] = {} - f.value[key][0] = {} - f.value[key][0][0] = self.value[key][idx][0] - return f - - def __float__(self): - if isinstance(self.value, FormulaStat): - return float(self.value) - if not self.value.has_key(display_run): - return (1e300*1e300) - if len(self.value[display_run]) == 1: - return self.value[display_run][0][0] - else: - #print self.value[display_run] - return self.value[display_run][4][0] - #raise ValueError + return UnaryProxy(operator.__neg__, self) + def __pos__(self): + return UnaryProxy(operator.__pos__, self) + def __abs__(self): + return UnaryProxy(operator.__abs__, self) + +class Scalar(Value): + def __scalar__(self): + return True - def display(self): - import display - d = display.VectorDisplay() - d.flags = 0 - d.precision = 1 - d.name = 'formula' - d.desc = 'formula' - val = self.value[display_run] - d.value = [ val[x][0] for x in val.keys() ] - d.display() + def __vector__(self): + return False + def __value__(self, run): + raise AttributeError, '__value__ must be defined' -class Scalar(Statistic,FormulaStat): - def getValue(self): - return source.data(self, self.bins, self.ticks) +class VectorItemProxy(Value): + def __init__(self, proxy, index): + self.proxy = proxy + self.index = index - def display(self): - import display - p = display.Print() - p.name = self.name - p.desc = self.desc - p.value = float(self) - p.flags = self.flags - p.precision = self.precision - if display.all or (self.flags & flags.printable): - p.display() + def __scalar__(self): + return True - def comparable(self, other): - return self.name == other.name + def __vector__(self): + return False - def __eq__(self, other): - return self.value == other.value + def __value__(self, run): + return value(self.proxy, run, self.index) - def __isub__(self, other): - self.value -= other.value - return self +class Vector(Value): + def __scalar__(self): + return False - def __iadd__(self, other): - self.value += other.value - return self + def __vector__(self): + return True - def __itruediv__(self, other): - if not other: - return self - self.value /= other - return self + def __value__(self, run, index): + raise AttributeError, '__value__ must be defined' -class Vector(Statistic,FormulaStat): - def getValue(self): - return source.data(self, self.bins, self.ticks); + def __getitem__(self, index): + return VectorItemProxy(self, index) - def display(self): - import display - if not display.all and not (self.flags & flags.printable): - return +class ScalarConstant(Scalar): + def __init__(self, constant): + self.constant = constant + def __value__(self, run): + return self.constant - d = display.VectorDisplay() - d.__dict__.update(self.__dict__) - d.display() +class VectorConstant(Vector): + def __init__(self, constant): + self.constant = constant + def __value__(self, run, index): + return self.constant[index] + def __len__(self): + return len(self.constant) - def comparable(self, other): - return self.name == other.name and \ - len(self.value) == len(other.value) +def WrapValue(value): + if isinstance(value, (int, long, float)): + return ScalarConstant(value) + if isinstance(value, (list, tuple)): + return VectorConstant(value) + if isinstance(value, Value): + return value - def __eq__(self, other): - if isinstance(self.value, (list, tuple)) != \ - isinstance(other.value, (list, tuple)): - return False + raise AttributeError, 'Only values can be wrapped' - if isinstance(self.value, (list, tuple)): - if len(self.value) != len(other.value): - return False - else: - for v1,v2 in zip(self.value, other.value): - if v1 != v2: - return False - return True - else: - return self.value == other.value +class Statistic(object): + def __getattr__(self, attr): + if attr in ('data', 'x', 'y'): + result = self.source.data(self, self.bins, self.ticks) + self.data = result.data + self.x = result.x + self.y = result.y + return super(Statistic, self).__getattribute__(attr) - def __isub__(self, other): - self.value = binaryop(operator.sub, self.value, other.value) - return self + def __setattr__(self, attr, value): + if attr == 'stat': + raise AttributeError, '%s is read only' % stat + if attr in ('source', 'bins', 'ticks'): + if getattr(self, attr) != value: + if hasattr(self, 'data'): + delattr(self, 'data') + + super(Statistic, self).__setattr__(attr, value) + +class ValueProxy(Value): + def __getattr__(self, attr): + if attr == '__value__': + if scalar(self): + return self.__scalarvalue__ + if vector(self): + return self.__vectorvalue__ + if attr == '__len__': + if vector(self): + return self.__vectorlen__ + return super(ValueProxy, self).__getattribute__(attr) + +class UnaryProxy(ValueProxy): + def __init__(self, op, arg): + self.op = op + self.arg = WrapValue(arg) + + def __scalar__(self): + return scalar(self.arg) + + def __vector__(self): + return vector(self.arg) + + def __scalarvalue__(self, run): + val = value(self.arg, run) + if val is None: + return None + return self.op(val) + + def __vectorvalue__(self, run, index): + val = value(self.arg, run, index) + if val is None: + return None + return self.op(val) + + def __vectorlen__(self): + return len(unproxy(self.arg)) + +class BinaryProxy(ValueProxy): + def __init__(self, op, arg0, arg1): + super(BinaryProxy, self).__init__() + self.op = op + self.arg0 = WrapValue(arg0) + self.arg1 = WrapValue(arg1) + + def __scalar__(self): + return scalar(self.arg0) and scalar(self.arg1) + + def __vector__(self): + return vector(self.arg0) or vector(self.arg1) + + def __scalarvalue__(self, run): + val0 = value(self.arg0, run) + val1 = value(self.arg1, run) + if val0 is None or val1 is None: + return None + return self.op(val0, val1) + + def __vectorvalue__(self, run, index): + if scalar(self.arg0): + val0 = value(self.arg0, run) + if vector(self.arg0): + val0 = value(self.arg0, run, index) + if scalar(self.arg1): + val1 = value(self.arg1, run) + if vector(self.arg1): + val1 = value(self.arg1, run, index) + + if val0 is None or val1 is None: + return None + + return self.op(val0, val1) + + def __vectorlen__(self): + if vector(self.arg0) and scalar(self.arg1): + return len(self.arg0) + if scalar(self.arg0) and vector(self.arg1): + return len(self.arg1) + + len0 = len(self.arg0) + len1 = len(self.arg1) + + if len0 != len1: + raise AttributeError, \ + "vectors of different lengths %d != %d" % (len0, len1) + + return len0 + +class Proxy(Value): + def __init__(self, name, dict): + self.name = name + self.dict = dict + + def __unproxy__(self): + return unproxy(self.dict[self.name]) + + def __getitem__(self, index): + return ItemProxy(self, index) + + def __getattr__(self, attr): + return AttrProxy(self, attr) + +class ItemProxy(Proxy): + def __init__(self, proxy, index): + self.proxy = proxy + self.index = index + + def __unproxy__(self): + return unproxy(unproxy(self.proxy)[self.index]) - def __iadd__(self, other): - self.value = binaryop(operator.add, self.value, other.value) - return self +class AttrProxy(Proxy): + def __init__(self, proxy, attr): + self.proxy = proxy + self.attr = attr - def __itruediv__(self, other): - if not other: - return self - if isinstance(self.value, (list, tuple)): - for i in xrange(len(self.value)): - self.value[i] /= other - else: - self.value /= other - return self + def __unproxy__(self): + return unproxy(getattr(unproxy(self.proxy), self.attr)) -class Formula(Vector): - def getValue(self): - formula = re.sub(':', '__', self.formula) - x = eval(formula, source.stattop) - return x.value +class ProxyGroup(object): + def __init__(self, dict=None, **kwargs): + self.__dict__['dict'] = {} - def comparable(self, other): - return self.name == other.name and \ - compare(self.dist, other.dist) + if dict is not None: + self.dict.update(dict) - def __eq__(self, other): - return self.value == other.value + if kwargs: + self.dict.update(kwargs) - def __isub__(self, other): - return self + def __getattr__(self, name): + return Proxy(name, self.dict) - def __iadd__(self, other): - return self + def __setattr__(self, attr, value): + self.dict[attr] = value - def __itruediv__(self, other): - if not other: - return self - return self +class ScalarStat(Statistic,Scalar): + def __value__(self, run): + if run not in self.data: + return None + return self.data[run][0][0] + + def display(self, run=None): + import display + p = display.Print() + p.name = self.name + p.desc = self.desc + p.value = value(self, run) + p.flags = self.flags + p.precision = self.precision + if display.all or (self.flags & flags.printable): + p.display() + +class VectorStat(Statistic,Vector): + def __value__(self, run, item): + if run not in self.data: + return None + return self.data[run][item][0] + + def __len__(self): + return self.x -class SimpleDist(object): + def display(self, run=None): + import display + d = display.VectorDisplay() + d.name = self.name + d.desc = self.desc + d.value = [ value(self, run, i) for i in xrange(len(self)) ] + d.flags = self.flags + d.precision = self.precision + d.display() + +class Formula(Value): + def __getattribute__(self, attr): + if attr not in ( '__scalar__', '__vector__', '__value__', '__len__' ): + return super(Formula, self).__getattribute__(attr) + + formula = re.sub(':', '__', self.formula) + value = eval(formula, self.source.stattop) + return getattr(value, attr) + +class SimpleDist(Statistic): def __init__(self, sums, squares, samples): self.sums = sums self.squares = squares self.samples = samples - def getValue(self): - return 0.0 - def display(self, name, desc, flags, precision): import display p = display.Print() @@ -482,9 +438,6 @@ class FullDist(SimpleDist): self.bsize = bsize self.size = size - def getValue(self): - return 0.0 - def display(self, name, desc, flags, precision): import display p = display.Print() @@ -574,9 +527,6 @@ class FullDist(SimpleDist): return self class Dist(Statistic): - def getValue(self): - return 0.0 - def display(self): import display if not display.all and not (self.flags & flags.printable): @@ -606,9 +556,6 @@ class Dist(Statistic): return self class VectorDist(Statistic): - def getValue(self): - return 0.0 - def display(self): import display if not display.all and not (self.flags & flags.printable): @@ -694,9 +641,6 @@ class VectorDist(Statistic): return self class Vector2d(Statistic): - def getValue(self): - return 0.0 - def display(self): import display if not display.all and not (self.flags & flags.printable): @@ -748,20 +692,25 @@ class Vector2d(Statistic): return self return self -def NewStat(data): +def NewStat(source, data): stat = None if data.type == 'SCALAR': - stat = Scalar(data) + stat = ScalarStat() elif data.type == 'VECTOR': - stat = Vector(data) + stat = VectorStat() elif data.type == 'DIST': - stat = Dist(data) + stat = Dist() elif data.type == 'VECTORDIST': - stat = VectorDist(data) + stat = VectorDist() elif data.type == 'VECTOR2D': - stat = Vector2d(data) + stat = Vector2d() elif data.type == 'FORMULA': - stat = Formula(data) + stat = Formula() + + stat.__dict__['source'] = source + stat.__dict__['bins'] = None + stat.__dict__['ticks'] = None + stat.__dict__.update(data.__dict__) return stat diff --git a/util/stats/output.py b/util/stats/output.py index 44dba5d15..cf76f291e 100644 --- a/util/stats/output.py +++ b/util/stats/output.py @@ -26,24 +26,8 @@ # # Authors: Nathan Binkert -class dbinfo(object): - def get(self, job, stat): - import info - - run = info.source.allRunNames.get(job.name, None) - if run is None: - print 'run "%s" not found' % job - return None - - stat.system = info.source[job.system] - info.display_run = run.run; - val = float(stat) - if val == 1e300*1e300: - return None - return val - class StatOutput(object): - def __init__(self, name, jobfile, stat=None, info=dbinfo(), binstats=None): + def __init__(self, name, jobfile, info, stat=None, binstats=None): self.name = name self.jobfile = jobfile self.stat = stat @@ -96,10 +80,10 @@ class StatOutput(object): self.printdata(printmode=printmode) def graph(self, graphdir): - from os.path import expanduser, join as joinpath + from os.path import expanduser, isdir, join as joinpath from barchart import BarChart - from matplotlib.numerix import Float, zeros - import re + from matplotlib.numerix import Float, array, zeros + import os, re confgroups = self.jobfile.groups() ngroups = len(confgroups) @@ -130,6 +114,8 @@ class StatOutput(object): raise AttributeError, 'No group selected for graph bars' directory = expanduser(graphdir) + if not isdir(directory): + os.mkdir(directory) html = file(joinpath(directory, '%s.html' % self.name), 'w') print >>html, '<html>' print >>html, '<title>Graphs for %s</title>' % self.name @@ -139,27 +125,47 @@ class StatOutput(object): data = zeros((len(groupopts), len(baropts)), Float) data = [ [ None ] * len(baropts) for i in xrange(len(groupopts)) ] enabled = False - stacked = None + stacked = 0 for g,gopt in enumerate(groupopts): for b,bopt in enumerate(baropts): job = self.jobfile.job(options + [ gopt, bopt ]) + if not job: + continue val = self.info.get(job, self.stat) - if val is None: - val = 0.0 - curstacked = isinstance(val, (list, tuple)) - if stacked is None: - stacked = curstacked - else: - if stacked != curstacked: - raise ValueError, "some stats stacked, some not" + if isinstance(val, (list, tuple)): + if len(val) == 1: + val = val[0] + else: + stacked = len(val) data[g][b] = val + if stacked == 0: + for i in xrange(len(groupopts)): + for j in xrange(len(baropts)): + if data[i][j] is None: + data[i][j] = 0.0 + else: + for i in xrange(len(groupopts)): + for j in xrange(len(baropts)): + val = data[i][j] + if val is None: + data[i][j] = [] * stacked + elif len(val) != stacked: + raise ValueError, "some stats stacked, some not" + + data = array(data) + if data.sum() == 0: + continue + bar_descs = [ opt.desc for opt in baropts ] group_descs = [ opt.desc for opt in groupopts ] if stacked: - legend = self.info.rcategories + try: + legend = self.info.rcategories + except: + legend = [ str(i) for i in xrange(stacked) ] else: legend = bar_descs diff --git a/util/stats/profile.py b/util/stats/profile.py index 65a03e9aa..57b854a30 100644 --- a/util/stats/profile.py +++ b/util/stats/profile.py @@ -27,103 +27,227 @@ from orderdict import orderdict import output -class ProfileData(object): - def __init__(self): - self.data = {} - self.total = {} - self.runs = orderdict() - self.runlist = [] +class RunData(dict): + def __init__(self, filename=None): + self.filename = filename - def addvalue(self, run, cpu, symbol, value): - value = float(value) - self.data[run, cpu, symbol] = self.getvalue(run, cpu, symbol) + value - self.total[run, cpu] = self.gettotal(run, cpu) + value - if run not in self.runs: - self.runs[run] = orderdict() + def __getattr__(self, attr): + if attr == 'total': + total = 0.0 + for value in self.itervalues(): + total += value + return total + if attr == 'maxsymlen': + return max([ len(sym) for sym in self.iterkeys() ]) - if cpu not in self.runs[run]: - self.runs[run][cpu] = {} + def display(self, output=None, limit=None, maxsymlen=None): + if not output: + import sys + output = sys.stdout + elif isinstance(output, str): + output = file(output, 'w') - if symbol not in self.runs[run][cpu]: - self.runs[run][cpu][symbol] = 0 + total = float(self.total) - self.runs[run][cpu][symbol] += value + # swap (string,count) order so we can sort on count + symbols = [ (count,name) for name,count in self.iteritems() ] + symbols.sort(reverse=True) + if limit is not None: + symbols = symbols[:limit] - def getvalue(self, run, cpu, symbol): - return self.data.get((run, cpu, symbol), 0) + if not maxsymlen: + maxsymlen = self.maxsymlen - def gettotal(self, run, cpu): - return self.total.get((run, cpu), 0) + symbolf = "%-" + str(maxsymlen + 1) + "s %.2f%%" + for number,name in symbols: + print >>output, symbolf % (name, 100.0 * (float(number) / total)) -class Profile(object): - default_order = ['ste', 'hte', 'htd', 'ocm', 'occ', 'ocp'] - # This list controls the order of values in stacked bar data output - default_categories = [ 'interrupt', - 'driver', - 'stack', - 'bufmgt', - 'copy', - 'user', - 'other', - 'idle'] - def __init__(self, run_order=[], categories=[], stacknames=[]): - if not run_order: - run_order = Profile.default_order - if not categories: - categories = Profile.default_categories +class PCData(RunData): + def __init__(self, filename=None, categorize=None, showidle=True): + super(PCData, self).__init__(self, filename) + if filename is None: + return - self.run_order = run_order - self.categories = categories - self.rcategories = [] - self.rcategories.extend(categories) - self.rcategories.reverse() - self.stacknames = stacknames - self.prof = ProfileData() - self.categorize = True - self.showidle = True - self.maxsymlen = 0 - - def category(self, symbol): - from categories import categories, categories_re - if categories.has_key(symbol): - return categories[symbol] - for regexp, cat in categories_re: - if regexp.match(symbol): - return cat - return 'other' - - # Parse input file and put the results in the given run and cpu - def parsefile(self, run, cpu, filename): fd = file(filename) for line in fd: + if line.strip() == '>>>PC data': + break + + for line in fd: + if line.startswith('>>>'): + break + (symbol, count) = line.split() if symbol == "0x0": continue count = int(count) - if self.categorize: - symbol = self.category(symbol) - if symbol == 'idle' and not self.showidle: + if categorize is not None: + category = categorize(symbol) + if category is None: + category = 'other' + elif category == 'idle' and not showidle: continue - if symbol not in self.categories: - symbol = 'other' - - self.maxsymlen = max(self.maxsymlen, len(symbol)) - self.prof.addvalue(run, cpu, symbol, count) + self[category] = count fd.close() +class FuncNode(object): + def __new__(cls, filename = None): + if filename is None: + return super(FuncNode, cls).__new__(cls) + + fd = file(filename, 'r') + fditer = iter(fd) + nodes = {} + for line in fditer: + if line.strip() == '>>>function data': + break + + for line in fditer: + if line.startswith('>>>'): + break + + data = line.split() + node_id = int(data[0], 16) + node = FuncNode() + node.symbol = data[1] + node.count = int(data[2]) + node.children = [ int(child, 16) for child in data[3:] ] + nodes[node_id] = node + + for node in nodes.itervalues(): + children = [] + for cid in node.children: + child = nodes[cid] + children.append(child) + child.parent = node + node.children = tuple(children) + if not nodes: + print filename + print nodes + return nodes[0] + + def __init__(self, filename=None): + pass + + def total(self): + total = self.count + for child in self.children: + total += child.total() + + return total + + def aggregate(self, dict, categorize, incategory): + category = None + if categorize: + category = categorize(self.symbol) + + total = self.count + for child in self.children: + total += child.aggregate(dict, categorize, category or incategory) + + if category: + dict[category] = dict.get(category, 0) + total + return 0 + elif not incategory: + dict[self.symbol] = dict.get(self.symbol, 0) + total + + return total + + def dump(self): + kids = [ child.symbol for child in self.children] + print '%s %d <%s>' % (self.symbol, self.count, ', '.join(kids)) + for child in self.children: + child.dump() + + def _dot(self, dot, threshold, categorize, total): + from pydot import Dot, Edge, Node + self.dot_node = None + + value = self.total() * 100.0 / total + if value < threshold: + return + if categorize: + category = categorize(self.symbol) + if category and category != 'other': + return + label = '%s %.2f%%' % (self.symbol, value) + self.dot_node = Node(self, label=label) + dot.add_node(self.dot_node) + + for child in self.children: + child._dot(dot, threshold, categorize, total) + if child.dot_node is not None: + dot.add_edge(Edge(self, child)) + + def _cleandot(self): + for child in self.children: + child._cleandot() + self.dot_node = None + del self.__dict__['dot_node'] + + def dot(self, dot, threshold=0.1, categorize=None): + self._dot(dot, threshold, categorize, self.total()) + self._cleandot() + +class FuncData(RunData): + def __init__(self, filename, categorize=None): + super(FuncData, self).__init__(filename) + self.tree = FuncNode(filename) + self.tree.aggregate(self, categorize, incategory=False) + self.total = self.tree.total() + + def displayx(self, output=None, maxcount=None): + if output is None: + import sys + output = sys.stdout + + items = [ (val,key) for key,val in self.iteritems() ] + items.sort(reverse=True) + for val,key in items: + if maxcount is not None: + if maxcount == 0: + return + maxcount -= 1 + + percent = val * 100.0 / self.total + print >>output, '%-30s %8s' % (key, '%3.2f%%' % percent) + +class Profile(object): + # This list controls the order of values in stacked bar data output + default_categories = [ 'interrupt', + 'driver', + 'stack', + 'buffer', + 'copy', + 'syscall', + 'user', + 'other', + 'idle'] + + def __init__(self, datatype, categorize=None): + categories = Profile.default_categories + + self.datatype = datatype + self.categorize = categorize + self.data = {} + self.categories = categories[:] + self.rcategories = categories[:] + self.rcategories.reverse() + self.cpu = 0 + # Read in files def inputdir(self, directory): import os, os.path, re from os.path import expanduser, join as joinpath directory = expanduser(directory) - label_ex = re.compile(r'm5prof\.(.*)') + label_ex = re.compile(r'profile\.(.*).dat') for root,dirs,files in os.walk(directory): for name in files: match = label_ex.match(name) @@ -133,14 +257,229 @@ class Profile(object): filename = joinpath(root, name) prefix = os.path.commonprefix([root, directory]) dirname = root[len(prefix)+1:] - self.parsefile(dirname, match.group(1), filename) + data = self.datatype(filename, self.categorize) + self.setdata(dirname, match.group(1), data) + + def setdata(self, run, cpu, data): + if run not in self.data: + self.data[run] = {} + + if cpu in self.data[run]: + raise AttributeError, \ + 'data already stored for run %s and cpu %s' % (run, cpu) + + self.data[run][cpu] = data + + def getdata(self, run, cpu): + try: + return self.data[run][cpu] + except KeyError: + return None + + def alldata(self): + for run,cpus in self.data.iteritems(): + for cpu,data in cpus.iteritems(): + yield run,cpu,data def get(self, job, stat): if job.system is None: raise AttributeError, 'The job must have a system set' - cpu = '%s.full0' % job.system + data = self.getdata(job.name, '%s.full%d' % (job.system, self.cpu)) + if not data: + return [ 0.0 for c in self.categories ] + values = [] - for cat in self.categories: - values.append(self.prof.getvalue(job.name, cpu, cat)) + for category in self.categories: + values.append(data.get(category, 0.0)) return values + + def dump(self): + for run,cpu,data in self.alldata(): + print 'run %s, cpu %s' % (run, cpu) + data.dump() + print + + def write_dot(self, threshold, jobfile=None, jobs=None): + import pydot + + if jobs is None: + jobs = [ job for job in jobfile.jobs() ] + + for job in jobs: + cpu = '%s.full%d' % (job.system, self.cpu) + symbols = self.getdata(job.name, cpu) + if not symbols: + continue + + dot = pydot.Dot() + symbols.tree.dot(dot, threshold=threshold) + dot.write(symbols.filename[:-3] + 'dot') + + def write_txt(self, jobfile=None, jobs=None, limit=None): + if jobs is None: + jobs = [ job for job in jobfile.jobs() ] + + for job in jobs: + cpu = '%s.full%d' % (job.system, self.cpu) + symbols = self.getdata(job.name, cpu) + if not symbols: + continue + + output = file(symbols.filename[:-3] + 'txt', 'w') + symbols.display(output, limit) + + def display(self, jobfile=None, jobs=None, limit=None): + if jobs is None: + jobs = [ job for job in jobfile.jobs() ] + + maxsymlen = 0 + + thejobs = [] + for job in jobs: + cpu = '%s.full%d' % (job.system, self.cpu) + symbols = self.getdata(job.name, cpu) + if symbols: + thejobs.append(job) + maxsymlen = max(maxsymlen, symbols.maxsymlen) + + for job in thejobs: + cpu = '%s.full%d' % (job.system, self.cpu) + symbols = self.getdata(job.name, cpu) + print job.name + symbols.display(limit=limit, maxsymlen=maxsymlen) + print + + +from categories import func_categorize, pc_categorize +class PCProfile(Profile): + def __init__(self, categorize=pc_categorize): + super(PCProfile, self).__init__(PCData, categorize) + + +class FuncProfile(Profile): + def __init__(self, categorize=func_categorize): + super(FuncProfile, self).__init__(FuncData, categorize) + +def usage(exitcode = None): + print '''\ +Usage: %s [-bc] [-g <dir>] [-j <jobfile>] [-n <num>] + + -c groups symbols into categories + -b dumps data for bar charts + -d generate dot output + -g <d> draw graphs and send output to <d> + -j <jobfile> specify a different jobfile (default is Test.py) + -n <n> selects number of top symbols to print (default 5) +''' % sys.argv[0] + + if exitcode is not None: + sys.exit(exitcode) + +if __name__ == '__main__': + import getopt, re, sys + from os.path import expanduser + from output import StatOutput + from jobfile import JobFile + + # default option values + numsyms = 10 + graph = None + cpus = [ 0 ] + categorize = False + showidle = True + funcdata = True + jobfilename = 'Test.py' + dodot = False + dotformat = 'raw' + textout = False + threshold = 0.01 + inputfile = None + + try: + opts, args = getopt.getopt(sys.argv[1:], 'C:cdD:f:g:ij:n:pT:t') + except getopt.GetoptError: + usage(2) + + for o,a in opts: + if o == '-C': + cpus = [ int(x) for x in a.split(',') ] + elif o == '-c': + categorize = True + elif o == '-D': + dotformat = a + elif o == '-d': + dodot = True + elif o == '-f': + inputfile = expanduser(a) + elif o == '-g': + graph = a + elif o == '-i': + showidle = False + elif o == '-j': + jobfilename = a + elif o == '-n': + numsyms = int(a) + elif o == '-p': + funcdata = False + elif o == '-T': + threshold = float(a) + elif o == '-t': + textout = True + + if args: + print "'%s'" % args, len(args) + usage(1) + + if inputfile: + data = FuncData(inputfile) + + if dodot: + import pydot + dot = pydot.Dot() + data.dot(dot, threshold=threshold) + #dot.orientation = 'landscape' + #dot.ranksep='equally' + #dot.rank='samerank' + dot.write(dotfile, format=dotformat) + else: + data.display(limit=numsyms) + + else: + jobfile = JobFile(jobfilename) + + if funcdata: + profile = FuncProfile() + else: + profile = PCProfile() + + if not categorize: + profile.categorize = None + profile.inputdir(jobfile.rootdir) + + if graph: + for cpu in cpus: + profile.cpu = cpu + if funcdata: + name = 'funcstacks%d' % cpu + else: + name = 'stacks%d' % cpu + output = StatOutput(name, jobfile, info=profile) + output.graph(graph) + + if dodot: + for cpu in cpus: + profile.cpu = cpu + profile.write_dot(jobfile=jobfile, threshold=threshold) + + if textout: + for cpu in cpus: + profile.cpu = cpu + profile.write_txt(jobfile=jobfile) + + if not graph and not textout and not dodot: + for cpu in cpus: + if not categorize: + profile.categorize = None + profile.cpu = cpu + profile.display(jobfile=jobfile, limit=numsyms) diff --git a/util/stats/stats.py b/util/stats/stats.py index c53d77d54..e481a794c 100755 --- a/util/stats/stats.py +++ b/util/stats/stats.py @@ -98,29 +98,27 @@ def commands(options, command, args): raise CommandException - import db, info - info.source = db.Database() - info.source.host = options.host - info.source.db = options.db - info.source.passwd = options.passwd - info.source.user = options.user - info.source.connect() - #info.source.update_dict(globals()) - - if type(options.get) is str: - info.source.get = options.get + import db + source = db.Database() + source.host = options.host + source.db = options.db + source.passwd = options.passwd + source.user = options.user + source.connect() + #source.update_dict(globals()) + + if type(options.method) is str: + source.method = options.method if options.runs is None: - runs = info.source.allRuns + runs = source.allRuns else: rx = re.compile(options.runs) runs = [] - for run in info.source.allRuns: + for run in source.allRuns: if rx.match(run.name): runs.append(run) - info.display_run = runs[0].run - if command == 'runs': user = None opts, args = getopts(args, '-u') @@ -129,14 +127,14 @@ def commands(options, command, args): for o,a in opts: if o == '-u': user = a - info.source.listRuns(user) + source.listRuns(user) return if command == 'stats': if len(args) == 0: - info.source.listStats() + source.listStats() elif len(args) == 1: - info.source.listStats(args[0]) + source.listStats(args[0]) else: raise CommandException @@ -144,9 +142,9 @@ def commands(options, command, args): if command == 'bins': if len(args) == 0: - info.source.listBins() + source.listBins() elif len(args) == 1: - info.source.listBins(args[0]) + source.listBins(args[0]) else: raise CommandException @@ -154,9 +152,9 @@ def commands(options, command, args): if command == 'formulas': if len(args) == 0: - info.source.listFormulas() + source.listFormulas() elif len(args) == 1: - info.source.listFormulas(args[0]) + source.listFormulas(args[0]) else: raise CommandException @@ -166,7 +164,7 @@ def commands(options, command, args): if len(args): raise CommandException - info.source.listTicks(runs) + source.listTicks(runs) return if command == 'stability': @@ -177,8 +175,8 @@ def commands(options, command, args): merge = int(args[0]) except ValueError: usage() - stats = info.source.getStat(args[1]) - info.source.get = "sum" + stats = source.getStat(args[1]) + source.method = 'sum' def disp(*args): print "%-20s %12s %12s %4s %5s %5s %5s %10s" % args @@ -195,18 +193,17 @@ def commands(options, command, args): #loop through all the selected runs for run in runs: - info.display_run = run.run; - runTicks = info.source.retTicks([ run ]) + runTicks = source.retTicks([ run ]) #throw away the first one, it's 0 runTicks.pop(0) - info.globalTicks = runTicks + source.ticks = runTicks avg = 0 stdev = 0 numoutsideavg = 0 numoutside1std = 0 numoutside2std = 0 pairRunTicks = [] - if float(stat) == 1e300*1e300: + if value(stat, run.run) == 1e300*1e300: continue for t in range(0, len(runTicks)-(merge-1), merge): tempPair = [] @@ -215,17 +212,17 @@ def commands(options, command, args): pairRunTicks.append(tempPair) #loop through all the various ticks for each run for tick in pairRunTicks: - info.globalTicks = tick - avg += float(stat) + source.ticks = tick + avg += value(stat, run.run) avg /= len(pairRunTicks) for tick in pairRunTicks: - info.globalTicks = tick - val = float(stat) + source.ticks = tick + val = value(stat, run.run) stdev += pow((val-avg),2) stdev = math.sqrt(stdev / len(pairRunTicks)) for tick in pairRunTicks: - info.globalTicks = tick - val = float(stat) + source.ticks = tick + val = value(stat, run.run) if (val < (avg * .9)) or (val > (avg * 1.1)): numoutsideavg += 1 if (val < (avg - stdev)) or (val > (avg + stdev)): @@ -264,9 +261,9 @@ def commands(options, command, args): if options.ticks: if not options.graph: print 'only displaying sample %s' % options.ticks - info.globalTicks = [ int(x) for x in options.ticks.split() ] + source.ticks = [ int(x) for x in options.ticks.split() ] - from output import StatOutput + import output def display(): if options.graph: @@ -280,12 +277,12 @@ def commands(options, command, args): raise CommandException if command == 'stat': - stats = info.source.getStat(args[0]) + stats = source.getStat(args[0]) if command == 'formula': stats = eval(args[0]) for stat in stats: - output = StatOutput(stat.name, options.jobfile) + output = output.StatOutput(stat.name, options.jobfile, source) output.stat = stat output.label = stat.name display() @@ -295,12 +292,11 @@ def commands(options, command, args): if len(args): raise CommandException - system = info.source.__dict__[options.system] - - from proxy import ProxyGroup - sim_ticks = info.source['sim_ticks'] - sim_seconds = info.source['sim_seconds'] - proxy = ProxyGroup(system = info.source[options.system]) + system = source.__dict__[options.system] + from info import ProxyGroup + sim_ticks = source['sim_ticks'] + sim_seconds = source['sim_seconds'] + proxy = ProxyGroup(system = source[options.system]) system = proxy.system etherdev = system.tsunami.etherdev0 @@ -309,7 +305,7 @@ def commands(options, command, args): packets = etherdev.rxPackets + etherdev.txPackets bps = etherdev.rxBandwidth + etherdev.txBandwidth - output = StatOutput(command, options.jobfile) + output = output.StatOutput(command, options.jobfile, source) if command == 'usertime': import copy @@ -460,15 +456,16 @@ if __name__ == '__main__': options.user = getpass.getuser() options.runs = None options.system = 'client' - options.get = None + options.method = None options.binned = False options.graph = False options.ticks = False options.printmode = 'G' + jobfilename = 'Test.py' options.jobfile = None options.all = False - opts, args = getopts(sys.argv[1:], '-BEFG:ad:g:h:j:pr:s:u:T:') + opts, args = getopts(sys.argv[1:], '-BEFJad:g:h:j:m:pr:s:u:T:') for o,a in opts: if o == '-B': options.binned = True @@ -476,8 +473,6 @@ if __name__ == '__main__': options.printmode = 'E' if o == '-F': options.printmode = 'F' - if o == '-G': - options.get = a if o == '-a': options.all = True if o == '-d': @@ -487,8 +482,12 @@ if __name__ == '__main__': options.graphdir = a if o == '-h': options.host = a + if o == '-J': + jobfilename = None if o == '-j': - options.jobfile = JobFile(a) + jobfilename = a + if o == '-m': + options.method = a if o == '-p': options.passwd = getpass.getpass() if o == '-r': @@ -500,7 +499,8 @@ if __name__ == '__main__': if o == '-T': options.ticks = a - if options.jobfile: + if jobfilename: + options.jobfile = JobFile(jobfilename) if not options.host: options.host = options.jobfile.dbhost if not options.db: |