diff options
Diffstat (limited to 'src')
37 files changed, 1567 insertions, 1132 deletions
diff --git a/src/SConscript b/src/SConscript index 74bed9a7e..d6b4c6c8d 100644 --- a/src/SConscript +++ b/src/SConscript @@ -133,6 +133,8 @@ base_sources = Split(''' python/swig/debug_wrap.cc python/swig/main_wrap.cc python/swig/event_wrap.cc + python/swig/random_wrap.cc + python/swig/trace_wrap.cc python/swig/pyevent.cc sim/builder.cc @@ -149,7 +151,6 @@ base_sources = Split(''' sim/stat_context.cc sim/stat_control.cc sim/system.cc - sim/trace_context.cc ''') trace_reader_sources = Split(''' diff --git a/src/arch/sparc/floatregfile.cc b/src/arch/sparc/floatregfile.cc index 585782ddb..e1b5ea7c8 100644 --- a/src/arch/sparc/floatregfile.cc +++ b/src/arch/sparc/floatregfile.cc @@ -69,22 +69,25 @@ FloatReg FloatRegFile::readReg(int floatReg, int width) switch(width) { case SingleWidth: - float32_t result32; + uint32_t result32; + float32_t fresult32; memcpy(&result32, regSpace + 4 * floatReg, sizeof(result32)); - result = htog(result32); - DPRINTF(Sparc, "Read FP32 register %d = 0x%x\n", floatReg, result); + result32 = htog(result32); + memcpy(&fresult32, &result32, sizeof(result32)); + result = fresult32; + DPRINTF(Sparc, "Read FP32 register %d = [%f]0x%x\n", floatReg, result, result32); break; case DoubleWidth: - float64_t result64; + uint64_t result64; + float64_t fresult64; memcpy(&result64, regSpace + 4 * floatReg, sizeof(result64)); - result = htog(result64); - DPRINTF(Sparc, "Read FP64 register %d = 0x%x\n", floatReg, result); + result64 = htog(result64); + memcpy(&fresult64, &result64, sizeof(result64)); + result = fresult64; + DPRINTF(Sparc, "Read FP64 register %d = [%f]0x%x\n", floatReg, result, result64); break; case QuadWidth: - float128_t result128; - memcpy(&result128, regSpace + 4 * floatReg, sizeof(result128)); - result = htog(result128); - DPRINTF(Sparc, "Read FP128 register %d = 0x%x\n", floatReg, result); + panic("Quad width FP not implemented."); break; default: panic("Attempted to read a %d bit floating point register!", width); @@ -113,10 +116,7 @@ FloatRegBits FloatRegFile::readRegBits(int floatReg, int width) DPRINTF(Sparc, "Read FP64 bits register %d = 0x%x\n", floatReg, result); break; case QuadWidth: - uint64_t result128; - memcpy(&result128, regSpace + 4 * floatReg, sizeof(result128)); - result = htog(result128); - DPRINTF(Sparc, "Read FP128 bits register %d = 0x%x\n", floatReg, result); + panic("Quad width FP not implemented."); break; default: panic("Attempted to read a %d bit floating point register!", width); @@ -132,15 +132,21 @@ Fault FloatRegFile::setReg(int floatReg, const FloatReg &val, int width) uint32_t result32; uint64_t result64; + float32_t fresult32; + float64_t fresult64; switch(width) { case SingleWidth: - result32 = gtoh((uint32_t)val); + fresult32 = val; + memcpy(&result32, &fresult32, sizeof(result32)); + result32 = gtoh(result32); memcpy(regSpace + 4 * floatReg, &result32, sizeof(result32)); DPRINTF(Sparc, "Write FP64 register %d = 0x%x\n", floatReg, result32); break; case DoubleWidth: - result64 = gtoh((uint64_t)val); + fresult64 = val; + memcpy(&result64, &fresult64, sizeof(result64)); + result64 = gtoh(result64); memcpy(regSpace + 4 * floatReg, &result64, sizeof(result64)); DPRINTF(Sparc, "Write FP64 register %d = 0x%x\n", floatReg, result64); break; diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh index 3af4f6342..dc3b235fe 100644 --- a/src/arch/sparc/interrupts.hh +++ b/src/arch/sparc/interrupts.hh @@ -46,164 +46,167 @@ enum interrupts_t { num_interrupt_types }; - class Interrupts - { +class Interrupts +{ - private: + private: - bool interrupts[num_interrupt_types]; - int numPosted; + bool interrupts[num_interrupt_types]; + int numPosted; - public: - Interrupts() - { - for (int i = 0; i < num_interrupt_types; ++i) { - interrupts[i] = false; - } - numPosted = 0; + public: + Interrupts() + { + for (int i = 0; i < num_interrupt_types; ++i) { + interrupts[i] = false; } + numPosted = 0; + } - void post(int int_type) - { - if (int_type < 0 || int_type >= num_interrupt_types) - panic("posting unknown interrupt!\n"); - - if (interrupts[int_type] == false) { - interrupts[int_type] = true; - ++numPosted; - } + void post(int int_type) + { + if (int_type < 0 || int_type >= num_interrupt_types) + panic("posting unknown interrupt!\n"); + if (interrupts[int_type] == false) { + interrupts[int_type] = true; + ++numPosted; } + } - void post(int int_num, int index) - { - - } + void post(int int_num, int index) + { - void clear(int int_num, int index) - { + } - } + void clear(int int_num, int index) + { - void clear_all() - { + } - } + void clear_all() + { - bool check_interrupts(ThreadContext * tc) const - { - if (numPosted) - return true; - else - return false; - } + } - Fault getInterrupt(ThreadContext * tc) - { - int hpstate = tc->readMiscReg(MISCREG_HPSTATE); - int pstate = tc->readMiscReg(MISCREG_PSTATE); - bool ie = pstate & PSTATE::ie; - - // THESE ARE IN ORDER OF PRIORITY - // since there are early returns, and the highest - // priority interrupts should get serviced, - // it is v. important that new interrupts are inserted - // in the right order of processing - if (hpstate & HPSTATE::hpriv) { - if (ie) { - if (interrupts[hstick_match]) { - if (tc->readMiscReg(MISCREG_HINTP) & 1) { - interrupts[hstick_match] = false; - --numPosted; - return new HstickMatch; - } - } - if (interrupts[interrupt_vector]) { - interrupts[interrupt_vector] = false; - --numPosted; - //HAVEN'T IMPLed THIS YET - return NoFault; - } - } else { - if (interrupts[hstick_match]) { - return NoFault; - } + bool check_interrupts(ThreadContext * tc) const + { + if (numPosted) + return true; + else + return false; + } - } - } else { - if (interrupts[trap_level_zero]) { - if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) { - interrupts[trap_level_zero] = false; - --numPosted; - return new TrapLevelZero; - } - } + Fault getInterrupt(ThreadContext * tc) + { + int hpstate = tc->readMiscReg(MISCREG_HPSTATE); + int pstate = tc->readMiscReg(MISCREG_PSTATE); + bool ie = pstate & PSTATE::ie; + + // THESE ARE IN ORDER OF PRIORITY + // since there are early returns, and the highest + // priority interrupts should get serviced, + // it is v. important that new interrupts are inserted + // in the right order of processing + if (hpstate & HPSTATE::hpriv) { + if (ie) { if (interrupts[hstick_match]) { if (tc->readMiscReg(MISCREG_HINTP) & 1) { interrupts[hstick_match] = false; --numPosted; return new HstickMatch; - } - } - if (ie) { - if (interrupts[cpu_mondo]) { - interrupts[cpu_mondo] = false; - --numPosted; - return new CpuMondo; } - if (interrupts[dev_mondo]) { - interrupts[dev_mondo] = false; - --numPosted; - return new DevMondo; + } + if (interrupts[interrupt_vector]) { + interrupts[interrupt_vector] = false; + --numPosted; + //HAVEN'T IMPLed THIS YET + return NoFault; + } + } else { + if (interrupts[hstick_match]) { + return NoFault; + } + + } + } else { + if (interrupts[trap_level_zero]) { + if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) { + interrupts[trap_level_zero] = false; + --numPosted; + return new TrapLevelZero; + } + } + if (interrupts[hstick_match]) { + if (tc->readMiscReg(MISCREG_HINTP) & 1) { + interrupts[hstick_match] = false; + --numPosted; + return new HstickMatch; } - if (interrupts[soft_interrupt]) { - int il = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT)); - // it seems that interrupt vectors are right in - // the middle of interrupt levels with regard to - // priority, so have to check - if ((il < 6) && - interrupts[interrupt_vector]) { - // may require more details here since there - // may be lots of interrupts embedded in an - // platform interrupt vector - interrupts[interrupt_vector] = false; + } + if (ie) { + if (interrupts[cpu_mondo]) { + interrupts[cpu_mondo] = false; + --numPosted; + return new CpuMondo; + } + if (interrupts[dev_mondo]) { + interrupts[dev_mondo] = false; + --numPosted; + return new DevMondo; + } + if (interrupts[soft_interrupt]) { + int il = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT)); + // it seems that interrupt vectors are right in + // the middle of interrupt levels with regard to + // priority, so have to check + if ((il < 6) && + interrupts[interrupt_vector]) { + // may require more details here since there + // may be lots of interrupts embedded in an + // platform interrupt vector + interrupts[interrupt_vector] = false; + --numPosted; + //HAVEN'T IMPLed YET + return NoFault; + } else { + if (il > tc->readMiscReg(MISCREG_PIL)) { + uint64_t si = tc->readMiscReg(MISCREG_SOFTINT); + uint64_t more = si & ~(1 << (il + 1)); + if (!InterruptLevel(more)) { + interrupts[soft_interrupt] = false; --numPosted; - //HAVEN'T IMPLed YET - return NoFault; - } else { - if (il > tc->readMiscReg(MISCREG_PIL)) { - uint64_t si = tc->readMiscReg(MISCREG_SOFTINT); - uint64_t more = si & ~(1 << (il + 1)); - if (!InterruptLevel(more)) { - interrupts[soft_interrupt] = false; - --numPosted; - } - return new InterruptLevelN(il); } + return new InterruptLevelN(il); } } - if (interrupts[resumable_error]) { - interrupts[resumable_error] = false; - --numPosted; - return new ResumableError; - } + } + if (interrupts[resumable_error]) { + interrupts[resumable_error] = false; + --numPosted; + return new ResumableError; } } - return NoFault; } + return NoFault; + } - void updateIntrInfo(ThreadContext * tc) - { + void updateIntrInfo(ThreadContext * tc) + { - } + } - void serialize(std::ostream &os) - { - } + void serialize(std::ostream &os) + { + SERIALIZE_ARRAY(interrupts,num_interrupt_types); + SERIALIZE_SCALAR(numPosted); + } - void unserialize(Checkpoint *cp, const std::string §ion) - { - } - }; -} + void unserialize(Checkpoint *cp, const std::string §ion) + { + UNSERIALIZE_ARRAY(interrupts,num_interrupt_types); + UNSERIALIZE_SCALAR(numPosted); + } +}; +} // namespace SPARC_ISA #endif // __ARCH_SPARC_INTERRUPT_HH__ diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 81443fecb..fb606c7cc 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -479,10 +479,10 @@ decode OP default Unknown::unknown() 0x11: PrivCheck::rdpic({{Rd = Pic;}}, {{Pcr<0:>}}); //0x12 should cause an illegal instruction exception 0x13: NoPriv::rdgsr({{ - if(Fprs<2:> == 0 || Pstate<4:> == 0) - Rd = Gsr; - else - fault = new FpDisabled; + fault = checkFpEnableFault(xc); + if (fault) + return fault; + Rd = Gsr; }}); //0x14-0x15 should cause an illegal instruction exception 0x16: Priv::rdsoftint({{Rd = Softint;}}); @@ -718,7 +718,7 @@ decode OP default Unknown::unknown() 0x1F: HPriv::wrhprhstick_cmpr({{HstickCmpr = Rs1 ^ Rs2_or_imm13;}}); } 0x34: decode OPF{ - format BasicOperate{ + format FpBasic{ 0x01: fmovs({{ Frds.uw = Frs2s.uw; //fsr.ftt = fsr.cexc = 0 @@ -765,7 +765,7 @@ decode OP default Unknown::unknown() 0x42: faddd({{Frd.df = Frs1.df + Frs2.df;}}); 0x43: FpUnimpl::faddq(); 0x45: fsubs({{Frds.sf = Frs1s.sf - Frs2s.sf;}}); - 0x46: fsubd({{Frd.df = Frs1.df - Frs2.df;}}); + 0x46: fsubd({{Frd.df = Frs1.df - Frs2.df; }}); 0x47: FpUnimpl::fsubq(); 0x49: fmuls({{Frds.sf = Frs1s.sf * Frs2s.sf;}}); 0x4A: fmuld({{Frd.df = Frs1.df * Frs2.df;}}); @@ -776,26 +776,26 @@ decode OP default Unknown::unknown() 0x69: fsmuld({{Frd.df = Frs1s.sf * Frs2s.sf;}}); 0x6E: FpUnimpl::fdmulq(); 0x81: fstox({{ - Frd.df = (double)static_cast<int64_t>(Frs2s.sf); + Frd.sdw = static_cast<int64_t>(Frs2s.sf); }}); 0x82: fdtox({{ - Frd.df = (double)static_cast<int64_t>(Frs2.df); + Frd.sdw = static_cast<int64_t>(Frs2.df); }}); 0x83: FpUnimpl::fqtox(); 0x84: fxtos({{ - Frds.sf = static_cast<float>((int64_t)Frs2.df); + Frds.sf = static_cast<float>(Frs2.sdw); }}); 0x88: fxtod({{ - Frd.df = static_cast<double>((int64_t)Frs2.df); + Frd.df = static_cast<double>(Frs2.sdw); }}); 0x8C: FpUnimpl::fxtoq(); 0xC4: fitos({{ - Frds.sf = static_cast<float>((int32_t)Frs2s.sf); + Frds.sf = static_cast<float>(Frs2s.sw); }}); 0xC6: fdtos({{Frds.sf = Frs2.df;}}); 0xC7: FpUnimpl::fqtos(); 0xC8: fitod({{ - Frd.df = static_cast<double>((int32_t)Frs2s.sf); + Frd.df = static_cast<double>(Frs2s.sw); }}); 0xC9: fstod({{Frd.df = Frs2s.sf;}}); 0xCB: FpUnimpl::fqtod(); @@ -803,17 +803,23 @@ decode OP default Unknown::unknown() 0xCD: FpUnimpl::fstoq(); 0xCE: FpUnimpl::fdtoq(); 0xD1: fstoi({{ - Frds.sf = (float)static_cast<int32_t>(Frs2s.sf); + Frds.sw = static_cast<int32_t>(Frs2s.sf); + float t = Frds.sw; + if (t != Frs2s.sf) + Fsr = insertBits(Fsr, 4,0, 0x01); }}); 0xD2: fdtoi({{ - Frds.sf = (float)static_cast<int32_t>(Frs2.df); + Frds.sw = static_cast<int32_t>(Frs2.df); + double t = Frds.sw; + if (t != Frs2.df) + Fsr = insertBits(Fsr, 4,0, 0x01); }}); 0xD3: FpUnimpl::fqtoi(); default: FailUnimpl::fpop1(); } } 0x35: decode OPF{ - format BasicOperate{ + format FpBasic{ 0x51: fcmps({{ uint8_t fcc; if(isnan(Frs1s) || isnan(Frs2s)) @@ -831,11 +837,11 @@ decode OP default Unknown::unknown() }}); 0x52: fcmpd({{ uint8_t fcc; - if(isnan(Frs1s) || isnan(Frs2s)) + if(isnan(Frs1) || isnan(Frs2)) fcc = 3; - else if(Frs1s < Frs2s) + else if(Frs1 < Frs2) fcc = 1; - else if(Frs1s > Frs2s) + else if(Frs1 > Frs2) fcc = 2; else fcc = 0; @@ -860,11 +866,11 @@ decode OP default Unknown::unknown() }}); 0x56: fcmped({{ uint8_t fcc = 0; - if(isnan(Frs1s) || isnan(Frs2s)) + if(isnan(Frs1) || isnan(Frs2)) fault = new FpExceptionIEEE754; - if(Frs1s < Frs2s) + if(Frs1 < Frs2) fcc = 1; - else if(Frs1s > Frs2s) + else if(Frs1 > Frs2) fcc = 2; uint8_t firstbit = 10; if(FCMPCC) @@ -960,24 +966,24 @@ decode OP default Unknown::unknown() 0x55: FailUnimpl::fpsub16s(); 0x56: FailUnimpl::fpsub32(); 0x57: FailUnimpl::fpsub32s(); - 0x60: BasicOperate::fzero({{Frd.df = 0;}}); - 0x61: BasicOperate::fzeros({{Frds.sf = 0;}}); + 0x60: FpBasic::fzero({{Frd.df = 0;}}); + 0x61: FpBasic::fzeros({{Frds.sf = 0;}}); 0x62: FailUnimpl::fnor(); 0x63: FailUnimpl::fnors(); 0x64: FailUnimpl::fandnot2(); 0x65: FailUnimpl::fandnot2s(); - 0x66: BasicOperate::fnot2({{ + 0x66: FpBasic::fnot2({{ Frd.df = (double)(~((uint64_t)Frs2.df)); }}); - 0x67: BasicOperate::fnot2s({{ + 0x67: FpBasic::fnot2s({{ Frds.sf = (float)(~((uint32_t)Frs2s.sf)); }}); 0x68: FailUnimpl::fandnot1(); 0x69: FailUnimpl::fandnot1s(); - 0x6A: BasicOperate::fnot1({{ + 0x6A: FpBasic::fnot1({{ Frd.df = (double)(~((uint64_t)Frs1.df)); }}); - 0x6B: BasicOperate::fnot1s({{ + 0x6B: FpBasic::fnot1s({{ Frds.sf = (float)(~((uint32_t)Frs1s.sf)); }}); 0x6C: FailUnimpl::fxor(); @@ -988,18 +994,18 @@ decode OP default Unknown::unknown() 0x71: FailUnimpl::fands(); 0x72: FailUnimpl::fxnor(); 0x73: FailUnimpl::fxnors(); - 0x74: BasicOperate::fsrc1({{Frd.udw = Frs1.udw;}}); - 0x75: BasicOperate::fsrc1s({{Frds.uw = Frs1s.uw;}}); + 0x74: FpBasic::fsrc1({{Frd.udw = Frs1.udw;}}); + 0x75: FpBasic::fsrc1s({{Frds.uw = Frs1s.uw;}}); 0x76: FailUnimpl::fornot2(); 0x77: FailUnimpl::fornot2s(); - 0x78: BasicOperate::fsrc2({{Frd.udw = Frs2.udw;}}); - 0x79: BasicOperate::fsrc2s({{Frds.uw = Frs2s.uw;}}); + 0x78: FpBasic::fsrc2({{Frd.udw = Frs2.udw;}}); + 0x79: FpBasic::fsrc2s({{Frds.uw = Frs2s.uw;}}); 0x7A: FailUnimpl::fornot1(); 0x7B: FailUnimpl::fornot1s(); 0x7C: FailUnimpl::for(); 0x7D: FailUnimpl::fors(); - 0x7E: BasicOperate::fone({{Frd.udw = std::numeric_limits<uint64_t>::max();}}); - 0x7F: BasicOperate::fones({{Frds.uw = std::numeric_limits<uint32_t>::max();}}); + 0x7E: FpBasic::fone({{Frd.udw = std::numeric_limits<uint64_t>::max();}}); + 0x7F: FpBasic::fones({{Frds.uw = std::numeric_limits<uint32_t>::max();}}); 0x80: Trap::shutdown({{fault = new IllegalInstruction;}}); 0x81: FailUnimpl::siam(); } @@ -1236,16 +1242,32 @@ decode OP default Unknown::unknown() Rd.uw = uReg0;}}, {{EXT_ASI}}); format Trap { 0x20: Load::ldf({{Frds.uw = Mem.uw;}}); - 0x21: decode X { - 0x0: Load::ldfsr({{Fsr = Mem.uw | Fsr<63:32>;}}); - 0x1: Load::ldxfsr({{Fsr = Mem.udw;}}); + 0x21: decode RD { + 0x0: Load::ldfsr({{fault = checkFpEnableFault(xc); + if (fault) + return fault; + Fsr = Mem.uw | Fsr<63:32>;}}); + 0x1: Load::ldxfsr({{fault = checkFpEnableFault(xc); + if (fault) + return fault; + Fsr = Mem.udw;}}); + default: FailUnimpl::ldfsrOther(); } 0x22: ldqf({{fault = new FpDisabled;}}); 0x23: Load::lddf({{Frd.udw = Mem.udw;}}); 0x24: Store::stf({{Mem.uw = Frds.uw;}}); - 0x25: decode X { - 0x0: Store::stfsr({{Mem.uw = Fsr<31:0>;}}); - 0x1: Store::stxfsr({{Mem.udw = Fsr;}}); + 0x25: decode RD { + 0x0: Store::stfsr({{fault = checkFpEnableFault(xc); + if (fault) + return fault; + Mem.uw = Fsr<31:0>; + Fsr = insertBits(Fsr,16,14,0);}}); + 0x1: Store::stxfsr({{fault = checkFpEnableFault(xc); + if (fault) + return fault; + Mem.udw = Fsr; + Fsr = insertBits(Fsr,16,14,0);}}); + default: FailUnimpl::stfsrOther(); } 0x26: stqf({{fault = new FpDisabled;}}); 0x27: Store::stdf({{Mem.udw = Frd.udw;}}); diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa index e8762a205..017f43780 100644 --- a/src/arch/sparc/isa/formats/basic.isa +++ b/src/arch/sparc/isa/formats/basic.isa @@ -103,3 +103,46 @@ def format BasicOperate(code, *flags) {{ decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; + +def format FpBasic(code, *flags) {{ + fp_code = """ + Fsr |= bits(Fsr,4,0) << 5; + Fsr = insertBits(Fsr,4,0,0); +#if defined(__sun) || defined (__OpenBSD__) + fp_rnd newrnd = FP_RN; + switch (Fsr<31:30>) { + case 0: newrnd = FP_RN; break; + case 1: newrnd = FP_RZ; break; + case 2: newrnd = FP_RP; break; + case 3: newrnd = FP_RM; break; + } + fp_rnd oldrnd = fpsetround(newrnd); +#else + int newrnd = FE_TONEAREST; + switch (Fsr<31:30>) { + case 0: newrnd = FE_TONEAREST; break; + case 1: newrnd = FE_TOWARDZERO; break; + case 2: newrnd = FE_UPWARD; break; + case 3: newrnd = FE_DOWNWARD; break; + } + int oldrnd = fegetround(); + fesetround(newrnd); +#endif +""" + + fp_code += code + + + fp_code += """ +#if defined(__sun) || defined (__OpenBSD__) + fpsetround(oldrnd); +#else + fesetround(oldrnd); +#endif +""" + iop = InstObjParams(name, Name, 'SparcStaticInst', fp_code, flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa index a6dca9bf1..d2ef67154 100644 --- a/src/arch/sparc/isa/includes.isa +++ b/src/arch/sparc/isa/includes.isa @@ -53,7 +53,7 @@ output decoder {{ #include "cpu/thread_context.hh" // for Jump::branchTarget() #include "mem/packet.hh" -#if defined(linux) +#if defined(linux) || defined(__APPLE__) #include <fenv.h> #endif #include <algorithm> @@ -62,9 +62,14 @@ using namespace SparcISA; }}; output exec {{ -#if defined(linux) +#if defined(linux) || defined(__APPLE__) #include <fenv.h> #endif + +#if defined(__sun) || defined (__OpenBSD__) +#include <ieeefp.h> +#endif + #include <limits> #include <cmath> diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 0fe3e96b2..8b612e8b4 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -232,6 +232,7 @@ MiscReg MiscRegFile::readReg(int miscReg) /** Floating Point Status Register */ case MISCREG_FSR: + DPRINTF(Sparc, "FSR read as: %#x\n", fsr); return fsr; case MISCREG_MMU_P_CONTEXT: @@ -337,10 +338,6 @@ MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) case MISCREG_PCR: case MISCREG_PIC: panic("Performance Instrumentation not impl\n"); - /** Floating Point Status Register */ - case MISCREG_FSR: - warn("Reading FSR Floating Point not implemented\n"); - break; case MISCREG_SOFTINT_CLR: case MISCREG_SOFTINT_SET: panic("Can read from softint clr/set\n"); @@ -488,6 +485,7 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val) /** Floating Point Status Register */ case MISCREG_FSR: fsr = val; + DPRINTF(Sparc, "FSR written with: %#x\n", fsr); break; case MISCREG_MMU_P_CONTEXT: diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index ebc8c0e7a..293f667d6 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -668,8 +668,6 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) if (!implicit && asi != ASI_P && asi != ASI_S) { if (AsiIsLittle(asi)) panic("Little Endian ASIs not supported\n"); - if (AsiIsBlock(asi)) - panic("Block ASIs not supported\n"); if (AsiIsNoFault(asi)) panic("No Fault ASIs not supported\n"); @@ -688,7 +686,7 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) goto handleSparcErrorRegAccess; if (!AsiIsReal(asi) && !AsiIsNucleus(asi) && !AsiIsAsIfUser(asi) && - !AsiIsTwin(asi)) + !AsiIsTwin(asi) && !AsiIsBlock(asi)) panic("Accessing ASI %#X. Should we?\n", asi); } diff --git a/src/base/cprintf.cc b/src/base/cprintf.cc index dd8ce858b..d4ba9ca21 100644 --- a/src/base/cprintf.cc +++ b/src/base/cprintf.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2002-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,232 +39,247 @@ using namespace std; namespace cp { -ArgList::~ArgList() +Print::Print(std::ostream &stream, const std::string &format) + : stream(stream), format(format.c_str()), ptr(format.c_str()) +{ + saved_flags = stream.flags(); + saved_fill = stream.fill(); + saved_precision = stream.precision(); +} + +Print::Print(std::ostream &stream, const char *format) + : stream(stream), format(format), ptr(format) +{ + saved_flags = stream.flags(); + saved_fill = stream.fill(); + saved_precision = stream.precision(); +} + +Print::~Print() { - while (!objects.empty()) { - delete objects.front(); - objects.pop_front(); - } } void -ArgList::dump(const string &format) +Print::process(Format &fmt) { - list_t::iterator iter = objects.begin(); - list_t::iterator end = objects.end(); - - const char *p = format.c_str(); - - stream->fill(' '); - stream->flags((ios::fmtflags)0); - - while (*p) { - switch (*p) { - case '%': { - if (p[1] == '%') { - *stream << '%'; - p += 2; - continue; - } - - Format fmt; - bool done = false; - bool end_number = false; - bool have_precision = false; - int number = 0; - - while (!done) { - ++p; - if (*p >= '0' && *p <= '9') { - if (end_number) - continue; - } else if (number > 0) - end_number = true; - - switch (*p) { - case 's': - fmt.format = Format::string; - done = true; - break; - - case 'c': - fmt.format = Format::character; - done = true; - break; - - case 'l': - continue; - - case 'p': - fmt.format = Format::integer; - fmt.base = Format::hex; - fmt.alternate_form = true; - done = true; - break; - - case 'X': - fmt.uppercase = true; - case 'x': - fmt.base = Format::hex; - fmt.format = Format::integer; - done = true; - break; - - case 'o': - fmt.base = Format::oct; - fmt.format = Format::integer; - done = true; - break; - - case 'd': - case 'i': - case 'u': - fmt.format = Format::integer; - done = true; - break; - - case 'G': - fmt.uppercase = true; - case 'g': - fmt.format = Format::floating; - fmt.float_format = Format::best; - done = true; - break; - - case 'E': - fmt.uppercase = true; - case 'e': - fmt.format = Format::floating; - fmt.float_format = Format::scientific; - done = true; - break; - - case 'f': - fmt.format = Format::floating; - fmt.float_format = Format::fixed; - done = true; - break; - - case 'n': - *stream << "we don't do %n!!!\n"; - done = true; - break; - - case '#': - fmt.alternate_form = true; - break; - - case '-': - fmt.flush_left = true; - break; - - case '+': - fmt.print_sign = true; - break; - - case ' ': - fmt.blank_space = true; - break; - - case '.': - fmt.width = number; - fmt.precision = 0; - have_precision = true; - number = 0; - end_number = false; - break; - - case '0': - if (number == 0) { - fmt.fill_zero = true; - break; - } - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - number = number * 10 + (*p - '0'); - break; - - case '%': - assert("we shouldn't get here"); - break; - - default: - done = true; - break; - } - - if (end_number) { - if (have_precision) - fmt.precision = number; - else - fmt.width = number; - - end_number = false; - number = 0; - } - } - - if (iter != end) - { - ios::fmtflags saved_flags = stream->flags(); - char old_fill = stream->fill(); - int old_precision = stream->precision(); - - (*iter)->process(*stream, fmt); - - stream->flags(saved_flags); - stream->fill(old_fill); - stream->precision(old_precision); - - ++iter; - } else { - *stream << "<missing arg for format>"; - } - - ++p; - } + size_t len; + + while (*ptr) { + switch (*ptr) { + case '%': + if (ptr[1] != '%') + goto processing; + + stream.put('%'); + ptr += 2; break; case '\n': - *stream << endl; - ++p; + stream << endl; + ++ptr; break; case '\r': - ++p; - if (*p != '\n') - *stream << endl; + ++ptr; + if (*ptr != '\n') + stream << endl; break; - default: { - size_t len = strcspn(p, "%\n\r\0"); - stream->write(p, len); - p += len; - } + default: + len = strcspn(ptr, "%\n\r\0"); + stream.write(ptr, len); + ptr += len; break; } } - while (iter != end) { - *stream << "<extra arg>"; - ++iter; + return; + + processing: + bool done = false; + bool end_number = false; + bool have_precision = false; + int number = 0; + + stream.fill(' '); + stream.flags((ios::fmtflags)0); + + while (!done) { + ++ptr; + if (*ptr >= '0' && *ptr <= '9') { + if (end_number) + continue; + } else if (number > 0) + end_number = true; + + switch (*ptr) { + case 's': + fmt.format = Format::string; + done = true; + break; + + case 'c': + fmt.format = Format::character; + done = true; + break; + + case 'l': + continue; + + case 'p': + fmt.format = Format::integer; + fmt.base = Format::hex; + fmt.alternate_form = true; + done = true; + break; + + case 'X': + fmt.uppercase = true; + case 'x': + fmt.base = Format::hex; + fmt.format = Format::integer; + done = true; + break; + + case 'o': + fmt.base = Format::oct; + fmt.format = Format::integer; + done = true; + break; + + case 'd': + case 'i': + case 'u': + fmt.format = Format::integer; + done = true; + break; + + case 'G': + fmt.uppercase = true; + case 'g': + fmt.format = Format::floating; + fmt.float_format = Format::best; + done = true; + break; + + case 'E': + fmt.uppercase = true; + case 'e': + fmt.format = Format::floating; + fmt.float_format = Format::scientific; + done = true; + break; + + case 'f': + fmt.format = Format::floating; + fmt.float_format = Format::fixed; + done = true; + break; + + case 'n': + stream << "we don't do %n!!!\n"; + done = true; + break; + + case '#': + fmt.alternate_form = true; + break; + + case '-': + fmt.flush_left = true; + break; + + case '+': + fmt.print_sign = true; + break; + + case ' ': + fmt.blank_space = true; + break; + + case '.': + fmt.width = number; + fmt.precision = 0; + have_precision = true; + number = 0; + end_number = false; + break; + + case '0': + if (number == 0) { + fmt.fill_zero = true; + break; + } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + number = number * 10 + (*ptr - '0'); + break; + + case '%': + assert("we shouldn't get here"); + break; + + default: + done = true; + break; + } + + if (end_number) { + if (have_precision) + fmt.precision = number; + else + fmt.width = number; + + end_number = false; + number = 0; + } } + + ++ptr; } -string -ArgList::dumpToString(const string &format) +void +Print::end_args() { - stringstream ss; + size_t len; - dump(ss, format); + while (*ptr) { + switch (*ptr) { + case '%': + if (ptr[1] != '%') + stream << "<extra arg>"; - return ss.str(); -} + stream.put('%'); + ptr += 2; + break; + case '\n': + stream << endl; + ++ptr; + break; + case '\r': + ++ptr; + if (*ptr != '\n') + stream << endl; + break; + + default: + len = strcspn(ptr, "%\n\r\0"); + stream.write(ptr, len); + ptr += len; + break; + } + } + + stream.flags(saved_flags); + stream.fill(saved_fill); + stream.precision(saved_precision); } + +/* end namespace cp */ } diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh index dd2256e69..7f8e33367 100644 --- a/src/base/cprintf.hh +++ b/src/base/cprintf.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2005 The Regents of The University of Michigan + * Copyright (c) 2002-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,142 +29,135 @@ * Steve Reinhardt */ -#ifndef __CPRINTF_HH__ -#define __CPRINTF_HH__ +#ifndef __BASE_CPRINTF_HH__ +#define __BASE_CPRINTF_HH__ +#include <ios> #include <iostream> #include <list> #include <string> +#include "base/varargs.hh" #include "base/cprintf_formats.hh" namespace cp { -class ArgList +#define CPRINTF_DECLARATION VARARGS_DECLARATION(cp::Print) +#define CPRINTF_DEFINITION VARARGS_DEFINITION(cp::Print) + +struct Print { - private: - class Base - { - public: - virtual ~Base() {} - virtual void process(std::ostream &out, Format &fmt) = 0; - }; + protected: + std::ostream &stream; + const char *format; + const char *ptr; + + std::ios::fmtflags saved_flags; + char saved_fill; + int saved_precision; + + void process(Format &fmt); + + public: + Print(std::ostream &stream, const std::string &format); + Print(std::ostream &stream, const char *format); + ~Print(); template <typename T> - class Node : public Base + void + add_arg(const T &data) { - public: - const T &data; - - public: - Node(const T &d) : data(d) {} - virtual void process(std::ostream &out, Format &fmt) { - switch (fmt.format) { - case Format::character: - format_char(out, data, fmt); - break; - - case Format::integer: - format_integer(out, data, fmt); - break; - - case Format::floating: - format_float(out, data, fmt); - break; - - case Format::string: - format_string(out, data, fmt); - break; - - default: - out << "<bad format>"; - break; - } - } - }; + Format fmt; + process(fmt); - typedef std::list<Base *> list_t; + switch (fmt.format) { + case Format::character: + format_char(stream, data, fmt); + break; - protected: - list_t objects; - std::ostream *stream; + case Format::integer: + format_integer(stream, data, fmt); + break; - public: - ArgList() : stream(&std::cout) {} - ~ArgList(); + case Format::floating: + format_float(stream, data, fmt); + break; - template<class T> - void append(const T &data) { - Base *obj = new ArgList::Node<T>(data); - objects.push_back(obj); - } + case Format::string: + format_string(stream, data, fmt); + break; - template<class T> - void prepend(const T &data) { - Base *obj = new ArgList::Node<T>(data); - objects.push_front(obj); + default: + stream << "<bad format>"; + break; + } } - void dump(const std::string &format); - void dump(std::ostream &strm, const std::string &fmt) - { stream = &strm; dump(fmt); } + void end_args(); +}; - std::string dumpToString(const std::string &format); +/* end namespace cp */ } - friend ArgList &operator<<(std::ostream &str, ArgList &list); -}; +typedef VarArgs::List<cp::Print> CPrintfArgsList; + +inline void +ccprintf(std::ostream &stream, const char *format, const CPrintfArgsList &args) +{ + cp::Print print(stream, format); + args.add_args(print); +} -template<class T> -inline ArgList & -operator,(ArgList &alist, const T &data) +inline void +ccprintf(std::ostream &stream, const char *format, CPRINTF_DECLARATION) { - alist.append(data); - return alist; + cp::Print print(stream, format); + VARARGS_ADDARGS(print); } -class ArgListNull { -}; +inline void +cprintf(const char *format, CPRINTF_DECLARATION) +{ + ccprintf(std::cout, format, VARARGS_ALLARGS); +} + +inline std::string +csprintf(const char *format, CPRINTF_DECLARATION) +{ + std::stringstream stream; + ccprintf(stream, format, VARARGS_ALLARGS); + return stream.str(); +} -inline ArgList & -operator,(ArgList &alist, ArgListNull) -{ return alist; } +/* + * functions again with std::string. We have both so we don't waste + * time converting const char * to std::string since we don't take + * advantage of it. + */ +inline void +ccprintf(std::ostream &stream, const std::string &format, + const CPrintfArgsList &args) +{ + ccprintf(stream, format.c_str(), args); +} -// -// cprintf(format, args, ...) prints to cout -// (analogous to printf()) -// inline void -__cprintf(const std::string &format, ArgList &args) -{ args.dump(format); delete &args; } -#define __cprintf__(format, ...) \ - cp::__cprintf(format, (*(new cp::ArgList), __VA_ARGS__)) -#define cprintf(...) \ - __cprintf__(__VA_ARGS__, cp::ArgListNull()) - -// -// ccprintf(stream, format, args, ...) prints to the specified stream -// (analogous to fprintf()) -// +ccprintf(std::ostream &stream, const std::string &format, CPRINTF_DECLARATION) +{ + ccprintf(stream, format, VARARGS_ALLARGS); +} + inline void -__ccprintf(std::ostream &stream, const std::string &format, ArgList &args) -{ args.dump(stream, format); delete &args; } -#define __ccprintf__(stream, format, ...) \ - cp::__ccprintf(stream, format, (*(new cp::ArgList), __VA_ARGS__)) -#define ccprintf(stream, ...) \ - __ccprintf__(stream, __VA_ARGS__, cp::ArgListNull()) - -// -// csprintf(format, args, ...) returns a string -// (roughly analogous to sprintf()) -// -inline std::string -__csprintf(const std::string &format, ArgList &args) -{ std::string s = args.dumpToString(format); delete &args; return s; } -#define __csprintf__(format, ...) \ - cp::__csprintf(format, (*(new cp::ArgList), __VA_ARGS__)) -#define csprintf(...) \ - __csprintf__(__VA_ARGS__, cp::ArgListNull()) +cprintf(const std::string &format, CPRINTF_DECLARATION) +{ + ccprintf(std::cout, format, VARARGS_ALLARGS); +} +inline std::string +csprintf(const std::string &format, CPRINTF_DECLARATION) +{ + std::stringstream stream; + ccprintf(stream, format, VARARGS_ALLARGS); + return stream.str(); } #endif // __CPRINTF_HH__ diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh index 0af493217..4e8b2b09e 100644 --- a/src/base/cprintf_formats.hh +++ b/src/base/cprintf_formats.hh @@ -28,8 +28,8 @@ * Authors: Nathan Binkert */ -#ifndef __CPRINTF_FORMATS_HH__ -#define __CPRINTF_FORMATS_HH__ +#ifndef __BASE_CPRINTF_FORMATS_HH__ +#define __BASE_CPRINTF_FORMATS_HH__ #include <sstream> #include <ostream> diff --git a/src/base/misc.cc b/src/base/misc.cc index 991a33736..29b6d2d88 100644 --- a/src/base/misc.cc +++ b/src/base/misc.cc @@ -36,91 +36,99 @@ #include "base/misc.hh" #include "base/output.hh" #include "base/trace.hh" +#include "base/varargs.hh" #include "sim/host.hh" #include "sim/root.hh" using namespace std; void -__panic(const string &format, cp::ArgList &args, const char *func, - const char *file, int line) +__panic(const char *func, const char *file, int line, const char *fmt, + CPRINTF_DEFINITION) { - string fmt = "panic: " + format; - switch (fmt[fmt.size() - 1]) { + string format = "panic: "; + format += fmt; + switch (format[format.size() - 1]) { case '\n': case '\r': break; default: - fmt += "\n"; + format += "\n"; } - fmt += " @ cycle %d\n[%s:%s, line %d]\n"; + format += " @ cycle %d\n[%s:%s, line %d]\n"; - args.append(curTick); - args.append(func); - args.append(file); - args.append(line); - args.dump(cerr, fmt); + CPrintfArgsList args(VARARGS_ALLARGS); - delete &args; + args.push_back(curTick); + args.push_back(func); + args.push_back(file); + args.push_back(line); + + ccprintf(cerr, format.c_str(), args); abort(); } void -__fatal(const string &format, cp::ArgList &args, const char *func, - const char *file, int line) +__fatal(const char *func, const char *file, int line, const char *fmt, + CPRINTF_DEFINITION) { - string fmt = "fatal: " + format; + CPrintfArgsList args(VARARGS_ALLARGS); + string format = "fatal: "; + format += fmt; - switch (fmt[fmt.size() - 1]) { + switch (format[format.size() - 1]) { case '\n': case '\r': break; default: - fmt += "\n"; + format += "\n"; } - fmt += " @ cycle %d\n[%s:%s, line %d]\n"; - fmt += "Memory Usage: %ld KBytes\n"; + format += " @ cycle %d\n[%s:%s, line %d]\n"; + format += "Memory Usage: %ld KBytes\n"; - args.append(curTick); - args.append(func); - args.append(file); - args.append(line); - args.append(memUsage()); - args.dump(cerr, fmt); + args.push_back(curTick); + args.push_back(func); + args.push_back(file); + args.push_back(line); + args.push_back(memUsage()); - delete &args; + ccprintf(cerr, format.c_str(), args); exit(1); } void -__warn(const string &format, cp::ArgList &args, const char *func, - const char *file, int line) +__warn(const char *func, const char *file, int line, const char *fmt, + CPRINTF_DEFINITION) { - string fmt = "warn: " + format; + string format = "warn: "; + format += fmt; - switch (fmt[fmt.size() - 1]) { + switch (format[format.size() - 1]) { case '\n': case '\r': break; default: - fmt += "\n"; + format += "\n"; } #ifdef VERBOSE_WARN - fmt += " @ cycle %d\n[%s:%s, line %d]\n"; - args.append(curTick); - args.append(func); - args.append(file); - args.append(line); + format += " @ cycle %d\n[%s:%s, line %d]\n"; #endif - args.dump(cerr, fmt); - if (simout.isFile(*outputStream)) - args.dump(*outputStream, fmt); + CPrintfArgsList args(VARARGS_ALLARGS); + +#ifdef VERBOSE_WARN + args.push_back(curTick); + args.push_back(func); + args.push_back(file); + args.push_back(line); +#endif - delete &args; + ccprintf(cerr, format.c_str(), args); + if (simout.isFile(*outputStream)) + ccprintf(*outputStream, format.c_str(), args); } diff --git a/src/base/misc.hh b/src/base/misc.hh index c12c2fe20..1509ea2d2 100644 --- a/src/base/misc.hh +++ b/src/base/misc.hh @@ -32,9 +32,11 @@ #ifndef __MISC_HH__ #define __MISC_HH__ -#include <assert.h> +#include <cassert> + #include "base/compiler.hh" #include "base/cprintf.hh" +#include "base/varargs.hh" #if defined(__SUNPRO_CC) #define __FUNCTION__ "how to fix me?" @@ -47,14 +49,20 @@ // calls abort which can dump core or enter the debugger. // // -void __panic(const std::string&, cp::ArgList &, const char*, const char*, int) - M5_ATTR_NORETURN; -#define __panic__(format, ...) \ - __panic(format, (*(new cp::ArgList), __VA_ARGS__), \ - __FUNCTION__ , __FILE__, __LINE__) -#define panic(...) \ - __panic__(__VA_ARGS__, cp::ArgListNull()) +void __panic(const char *func, const char *file, int line, const char *format, + CPRINTF_DECLARATION) M5_ATTR_NORETURN; +void __panic(const char *func, const char *file, int line, + const std::string &format, CPRINTF_DECLARATION) +M5_ATTR_NORETURN; + +inline void +__panic(const char *func, const char *file, int line, + const std::string &format, CPRINTF_DEFINITION) +{ + __panic(func, file, line, format.c_str(), VARARGS_ALLARGS); +} M5_PRAGMA_NORETURN(__panic) +#define panic(...) __panic(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) // // This implements a cprintf based fatal() function. fatal() should @@ -64,34 +72,43 @@ M5_PRAGMA_NORETURN(__panic) // "normal" exit with an error code, as opposed to abort() like // panic() does. // -void __fatal(const std::string&, cp::ArgList &, const char*, const char*, int) +void __fatal(const char *func, const char *file, int line, const char *format, + CPRINTF_DECLARATION) M5_ATTR_NORETURN; +void __fatal(const char *func, const char *file, int line, + const std::string &format, CPRINTF_DECLARATION) M5_ATTR_NORETURN; -#define __fatal__(format, ...) \ - __fatal(format, (*(new cp::ArgList), __VA_ARGS__), \ - __FUNCTION__ , __FILE__, __LINE__) -#define fatal(...) \ - __fatal__(__VA_ARGS__, cp::ArgListNull()) + +inline void +__fatal(const char *func, const char *file, int line, + const std::string &format, CPRINTF_DEFINITION) +{ + __fatal(func, file, line, format.c_str(), VARARGS_ALLARGS); +} M5_PRAGMA_NORETURN(__fatal) +#define fatal(...) __fatal(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) // // This implements a cprintf based warn // -void __warn(const std::string&, cp::ArgList &, const char*, const char*, int); -#define __warn__(format, ...) \ - __warn(format, (*(new cp::ArgList), __VA_ARGS__), \ - __FUNCTION__ , __FILE__, __LINE__) -#define warn(...) \ - __warn__(__VA_ARGS__, cp::ArgListNull()) +void __warn(const char *func, const char *file, int line, const char *format, + CPRINTF_DECLARATION); +inline void +__warn(const char *func, const char *file, int line, const std::string &format, + CPRINTF_DECLARATION) +{ + __warn(func, file, line, format, VARARGS_ALLARGS); +} +#define warn(...) __warn(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) // Only print the warning message the first time it is seen. This // doesn't check the warning string itself, it just only lets one // warning come from the statement. So, even if the arguments change // and that would have resulted in a different warning message, // subsequent messages would still be supressed. -#define warn_once(...) do { \ +#define warn_once(...) do { \ static bool once = false; \ if (!once) { \ - __warn__(__VA_ARGS__, cp::ArgListNull()); \ + warn(__VA_ARGS__); \ once = true; \ } \ } while (0) @@ -99,10 +116,10 @@ void __warn(const std::string&, cp::ArgList &, const char*, const char*, int); // // assert() that prints out the current cycle // -#define m5_assert(TEST) \ - if (!(TEST)) { \ - std::cerr << "Assertion failure, curTick = " << curTick << std::endl; \ - } \ - assert(TEST); +#define m5_assert(TEST) do { \ + if (!(TEST)) \ + ccprintf(std::cerr, "Assertion failure, curTick = %d\n", curTick); \ + assert(TEST); \ +} while (0) #endif // __MISC_HH__ diff --git a/src/base/random.cc b/src/base/random.cc index 0ccedcb00..ceab337d9 100644 --- a/src/base/random.cc +++ b/src/base/random.cc @@ -40,38 +40,20 @@ #include <cstdlib> #include <cmath> - -#include "sim/param.hh" #include "base/random.hh" -#include "base/trace.hh" using namespace std; -class RandomContext : public ParamContext -{ - public: - RandomContext(const string &_iniSection) - : ::ParamContext(_iniSection) {} - ~RandomContext() {} - - void checkParams(); -}; - -RandomContext paramContext("random"); - -Param<unsigned> -seed(¶mContext, "seed", "seed to random number generator", 1); - -void -RandomContext::checkParams() +uint32_t +getInt32() { - ::srand48(seed); + return mrand48() & 0xffffffff; } -long -getLong() +double +getDouble() { - return mrand48(); + return drand48(); } double @@ -105,21 +87,3 @@ getUniformPos(uint64_t min, uint64_t max) return (uint64_t)m5round(r); } - - -// idea for generating a double from erand48 -double -getDouble() -{ - union { - uint32_t _long[2]; - uint16_t _short[4]; - }; - - _long[0] = mrand48(); - _long[1] = mrand48(); - - return ldexp((double) _short[0], -48) + - ldexp((double) _short[1], -32) + - ldexp((double) _short[2], -16); -} diff --git a/src/base/random.hh b/src/base/random.hh index 40d62da7f..0cd88728d 100644 --- a/src/base/random.hh +++ b/src/base/random.hh @@ -34,7 +34,7 @@ #include "sim/host.hh" -long getLong(); +uint32_t getUInt32(); double getDouble(); double m5random(double r); uint64_t getUniformPos(uint64_t min, uint64_t max); @@ -46,7 +46,7 @@ struct Random; template<> struct Random<int8_t> { static int8_t get() - { return getLong() & (int8_t)-1; } + { return getUInt32() & (int8_t)-1; } static int8_t uniform(int8_t min, int8_t max) { return getUniform(min, max); } @@ -55,7 +55,7 @@ template<> struct Random<int8_t> template<> struct Random<uint8_t> { static uint8_t get() - { return getLong() & (uint8_t)-1; } + { return getUInt32() & (uint8_t)-1; } static uint8_t uniform(uint8_t min, uint8_t max) { return getUniformPos(min, max); } @@ -64,7 +64,7 @@ template<> struct Random<uint8_t> template<> struct Random<int16_t> { static int16_t get() - { return getLong() & (int16_t)-1; } + { return getUInt32() & (int16_t)-1; } static int16_t uniform(int16_t min, int16_t max) { return getUniform(min, max); } @@ -73,7 +73,7 @@ template<> struct Random<int16_t> template<> struct Random<uint16_t> { static uint16_t get() - { return getLong() & (uint16_t)-1; } + { return getUInt32() & (uint16_t)-1; } static uint16_t uniform(uint16_t min, uint16_t max) { return getUniformPos(min, max); } @@ -82,7 +82,7 @@ template<> struct Random<uint16_t> template<> struct Random<int32_t> { static int32_t get() - { return (int32_t)getLong(); } + { return (int32_t)getUInt32(); } static int32_t uniform(int32_t min, int32_t max) { return getUniform(min, max); } @@ -91,7 +91,7 @@ template<> struct Random<int32_t> template<> struct Random<uint32_t> { static uint32_t get() - { return (uint32_t)getLong(); } + { return (uint32_t)getUInt32(); } static uint32_t uniform(uint32_t min, uint32_t max) { return getUniformPos(min, max); } @@ -100,7 +100,7 @@ template<> struct Random<uint32_t> template<> struct Random<int64_t> { static int64_t get() - { return (int64_t)getLong() << 32 || (uint64_t)getLong(); } + { return (int64_t)getUInt32() << 32 || (uint64_t)getUInt32(); } static int64_t uniform(int64_t min, int64_t max) { return getUniform(min, max); } @@ -109,7 +109,7 @@ template<> struct Random<int64_t> template<> struct Random<uint64_t> { static uint64_t get() - { return (uint64_t)getLong() << 32 || (uint64_t)getLong(); } + { return (uint64_t)getUInt32() << 32 || (uint64_t)getUInt32(); } static uint64_t uniform(uint64_t min, uint64_t max) { return getUniformPos(min, max); } diff --git a/src/base/trace.cc b/src/base/trace.cc index 9fa615f4d..7afb038be 100644 --- a/src/base/trace.cc +++ b/src/base/trace.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2001-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,14 +37,17 @@ #include <vector> #include "base/misc.hh" -#include "base/trace.hh" +#include "base/output.hh" #include "base/str.hh" +#include "base/trace.hh" +#include "base/varargs.hh" using namespace std; namespace Trace { const string DefaultName("global"); FlagVec flags(NumFlags, false); +bool enabled = true; // // This variable holds the output stream for debug information. Other @@ -53,151 +56,74 @@ FlagVec flags(NumFlags, false); // output. // ostream *dprintf_stream = &cerr; - -ObjectMatch ignore; - -Log theLog; - -Log::Log() +ostream & +output() { - size = 0; - buffer = NULL; + return *dprintf_stream; } - void -Log::init(int _size) +setOutput(const string &filename) { - if (buffer != NULL) { - fatal("Trace::Log::init called twice!"); - } - - size = _size; - - buffer = new Record *[size]; - - for (int i = 0; i < size; ++i) { - buffer[i] = NULL; - } - - nextRecPtr = &buffer[0]; - wrapRecPtr = &buffer[size]; + dprintf_stream = simout.find(filename); } +ObjectMatch ignore; -Log::~Log() +void +dprintf(Tick when, const std::string &name, const char *format, + CPRINTF_DEFINITION) { - for (int i = 0; i < size; ++i) { - delete buffer[i]; - } - - delete [] buffer; -} + if (!name.empty() && ignore.match(name)) + return; + std::ostream &os = *dprintf_stream; -void -Log::append(Record *rec) -{ - // dump record to output stream if there's one open - if (dprintf_stream != NULL) { - rec->dump(*dprintf_stream); - } else { - rec->dump(cout); - } + string fmt = ""; + CPrintfArgsList args(VARARGS_ALLARGS); - // no buffering: justget rid of it now - if (buffer == NULL) { - delete rec; - return; + if (!name.empty()) { + fmt = "%s: " + fmt; + args.push_front(name); } - Record *oldRec = *nextRecPtr; - - if (oldRec != NULL) { - // log has wrapped: overwrite - delete oldRec; + if (when != (Tick)-1) { + fmt = "%7d: " + fmt; + args.push_front(when); } - *nextRecPtr = rec; + fmt += format; - if (++nextRecPtr == wrapRecPtr) { - nextRecPtr = &buffer[0]; - } + ccprintf(os, fmt.c_str(), args); + os.flush(); } - void -Log::dump(ostream &os) +dump(Tick when, const std::string &name, const void *d, int len) { - if (buffer == NULL) { + if (!name.empty() && ignore.match(name)) return; - } - - Record **bufPtr = nextRecPtr; - - if (*bufPtr == NULL) { - // next record slot is empty: log must not be full yet. - // start dumping from beginning of buffer - bufPtr = buffer; - } - do { - Record *rec = *bufPtr; - - rec->dump(os); - - if (++bufPtr == wrapRecPtr) { - bufPtr = &buffer[0]; - } - } while (bufPtr != nextRecPtr); -} - -PrintfRecord::~PrintfRecord() -{ - delete &args; -} + std::ostream &os = *dprintf_stream; -void -PrintfRecord::dump(ostream &os) -{ string fmt = ""; + CPrintfArgsList args; if (!name.empty()) { fmt = "%s: " + fmt; - args.prepend(name); + args.push_front(name); } - if (cycle != (Tick)-1) { + if (when != (Tick)-1) { fmt = "%7d: " + fmt; - args.prepend(cycle); + args.push_front(when); } - fmt += format; - - args.dump(os, fmt); - os.flush(); -} - -DataRecord::DataRecord(Tick _cycle, const string &_name, - const void *_data, int _len) - : Record(_cycle), name(_name), len(_len) -{ - data = new uint8_t[len]; - memcpy(data, _data, len); -} - -DataRecord::~DataRecord() -{ - delete [] data; -} - -void -DataRecord::dump(ostream &os) -{ + const char *data = static_cast<const char *>(d); int c, i, j; - for (i = 0; i < len; i += 16) { - ccprintf(os, "%d: %s: %08x ", cycle, name, i); + ccprintf(os, fmt, args); + ccprintf(os, "%08x ", i); c = len - i; if (c > 16) c = 16; @@ -213,8 +139,7 @@ DataRecord::dump(ostream &os) for (j = 0; j < c; j++) { int ch = data[i + j] & 0x7f; - ccprintf(os, - "%c", (char)(isprint(ch) ? ch : ' ')); + ccprintf(os, "%c", (char)(isprint(ch) ? ch : ' ')); } ccprintf(os, "\n"); @@ -223,126 +148,66 @@ DataRecord::dump(ostream &os) break; } } -} // namespace Trace -// -// Returns the current output stream for debug information. As a -// wrapper around Trace::dprintf_stream, this handles cases where debug -// information is generated in the process of parsing .ini options, -// before we process the option that sets up the debug output stream -// itself. -// -std::ostream & -DebugOut() -{ - return *Trace::dprintf_stream; -} - -///////////////////////////////////////////// -// -// C-linkage functions for invoking from gdb -// -///////////////////////////////////////////// - -// -// Dump trace buffer to specified file (cout if NULL) -// -void -dumpTrace(const char *filename) -{ - if (filename != NULL) { - ofstream out(filename); - Trace::theLog.dump(out); - out.close(); - } - else { - Trace::theLog.dump(cout); - } -} - - -// -// Turn on/off trace output to cerr. Typically used when trace output -// is only going to circular buffer, but you want to see what's being -// sent there as you step through some code in gdb. This uses the -// same facility as the "trace to file" feature, and will print error -// messages rather than clobbering an existing ostream pointer. -// -void -echoTrace(bool on) -{ - if (on) { - if (Trace::dprintf_stream != NULL) { - cerr << "Already echoing trace to a file... go do a 'tail -f'" - << " on that file instead." << endl; - } else { - Trace::dprintf_stream = &cerr; - } - } else { - if (Trace::dprintf_stream != &cerr) { - cerr << "Not echoing trace to cerr." << endl; - } else { - Trace::dprintf_stream = NULL; - } - } -} - -void -printTraceFlags() -{ - using namespace Trace; - for (int i = 0; i < numFlagStrings; ++i) - if (flags[i]) - cprintf("%s\n", flagStrings[i]); -} - -void -tweakTraceFlag(const char *string, bool value) +bool +changeFlag(const char *s, bool value) { using namespace Trace; - std::string str(string); + std::string str(s); for (int i = 0; i < numFlagStrings; ++i) { if (str != flagStrings[i]) continue; - int idx = i; - - if (idx < NumFlags) { - flags[idx] = value; + if (i < NumFlags) { + flags[i] = value; } else { - idx -= NumFlags; - if (idx >= NumCompoundFlags) { - ccprintf(cerr, "Invalid compound flag"); - return; - } - - const Flags *flagVec = compoundFlags[idx]; + i -= NumFlags; + const Flags *flagVec = compoundFlags[i]; for (int j = 0; flagVec[j] != -1; ++j) { - if (flagVec[j] >= NumFlags) { - ccprintf(cerr, "Invalid compound flag"); - return; - } - flags[flagVec[j]] = value; + if (flagVec[j] < NumFlags) + flags[flagVec[j]] = value; } } - cprintf("flag %s was %s\n", string, value ? "set" : "cleared"); - return; + return true; } - cprintf("could not find flag %s\n", string); + // the flag was not found. + return false; } void -setTraceFlag(const char *string) +dumpStatus() { - tweakTraceFlag(string, true); + using namespace Trace; + for (int i = 0; i < numFlagStrings; ++i) { + if (flags[i]) + cprintf("%s\n", flagStrings[i]); + } } -void -clearTraceFlag(const char *string) -{ - tweakTraceFlag(string, false); -} +/* namespace Trace */ } + + +// add a set of functions that can easily be invoked from gdb +extern "C" { + void + setTraceFlag(const char *string) + { + Trace::changeFlag(string, true); + } + + void + clearTraceFlag(const char *string) + { + Trace::changeFlag(string, false); + } + + void + dumpTraceStatus() + { + Trace::dumpStatus(); + } +/* extern "C" */ } diff --git a/src/base/trace.hh b/src/base/trace.hh index a46643159..8e380d8e1 100644 --- a/src/base/trace.hh +++ b/src/base/trace.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2005 The Regents of The University of Michigan + * Copyright (c) 2001-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,125 +32,35 @@ #ifndef __BASE_TRACE_HH__ #define __BASE_TRACE_HH__ +#include <string> #include <vector> #include "base/cprintf.hh" #include "base/match.hh" +#include "base/traceflags.hh" #include "sim/host.hh" #include "sim/root.hh" -#include "base/traceflags.hh" - namespace Trace { - typedef std::vector<bool> FlagVec; +std::ostream &output(); +void setOutput(const std::string &filename); - extern FlagVec flags; +extern bool enabled; +typedef std::vector<bool> FlagVec; +extern FlagVec flags; +inline bool IsOn(int t) { return flags[t]; } +bool changeFlag(const char *str, bool value); +void dumpStatus(); -#if TRACING_ON - const bool On = true; -#else - const bool On = false; -#endif - - inline bool - IsOn(int t) - { - return flags[t]; - - } - - void dump(const uint8_t *data, int count); - - class Record - { - protected: - Tick cycle; - - Record(Tick _cycle) - : cycle(_cycle) - { - } - - public: - virtual ~Record() {} - - virtual void dump(std::ostream &) = 0; - }; - - class PrintfRecord : public Record - { - private: - const char *format; - const std::string &name; - cp::ArgList &args; - - public: - PrintfRecord(const char *_format, cp::ArgList &_args, - Tick cycle, const std::string &_name) - : Record(cycle), format(_format), name(_name), args(_args) - { - } - - virtual ~PrintfRecord(); - - virtual void dump(std::ostream &); - }; - - class DataRecord : public Record - { - private: - const std::string &name; - uint8_t *data; - int len; - - public: - DataRecord(Tick cycle, const std::string &name, - const void *_data, int _len); - virtual ~DataRecord(); - - virtual void dump(std::ostream &); - }; - - class Log - { - private: - int size; // number of records in log - Record **buffer; // array of 'size' Record ptrs (circular buf) - Record **nextRecPtr; // next slot to use in buffer - Record **wrapRecPtr; // &buffer[size], for quick wrap check - - public: - - Log(); - ~Log(); - - void init(int _size); - - void append(Record *); // append trace record to log - void dump(std::ostream &); // dump contents to stream - }; - - extern Log theLog; - - extern ObjectMatch ignore; - - inline void - dprintf(const char *format, cp::ArgList &args, Tick cycle, - const std::string &name) - { - if (name.empty() || !ignore.match(name)) - theLog.append(new Trace::PrintfRecord(format, args, cycle, name)); - } - - inline void - dataDump(Tick cycle, const std::string &name, const void *data, int len) - { - theLog.append(new Trace::DataRecord(cycle, name, data, len)); - } - - extern const std::string DefaultName; -}; +extern ObjectMatch ignore; +extern const std::string DefaultName; + +void dprintf(Tick when, const std::string &name, const char *format, + CPRINTF_DECLARATION); +void dump(Tick when, const std::string &name, const void *data, int len); + +/* namespace Trace */ } // This silly little class allows us to wrap a string in a functor // object so that we can give a name() that DPRINTF will like @@ -162,7 +72,6 @@ struct StringWrap }; inline const std::string &name() { return Trace::DefaultName; } -std::ostream &DebugOut(); // // DPRINTF is a debugging trace facility that allows one to @@ -176,50 +85,44 @@ std::ostream &DebugOut(); #if TRACING_ON -#define DTRACE(x) (Trace::IsOn(Trace::x)) - -#define DCOUT(x) if (Trace::IsOn(Trace::x)) DebugOut() +#define DTRACE(x) (Trace::IsOn(Trace::x) && Trace::enabled) -#define DDUMP(x, data, count) \ -do { \ - if (Trace::IsOn(Trace::x)) \ - Trace::dataDump(curTick, name(), data, count); \ +#define DDUMP(x, data, count) do { \ + if (DTRACE(x)) \ + Trace::dump(curTick, name(), data, count); \ } while (0) -#define __dprintf(cycle, name, format, ...) \ - Trace::dprintf(format, (*(new cp::ArgList), __VA_ARGS__), cycle, name) +#define DPRINTF(x, ...) do { \ + if (DTRACE(x)) \ + Trace::dprintf(curTick, name(), __VA_ARGS__); \ +} while (0) -#define DPRINTF(x, ...) \ -do { \ - if (Trace::IsOn(Trace::x)) \ - __dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \ +#define DPRINTFR(x, ...) do { \ + if (DTRACE(x)) \ + Trace::dprintf((Tick)-1, std::string(), __VA_ARGS__); \ } while (0) -#define DPRINTFR(x, ...) \ -do { \ - if (Trace::IsOn(Trace::x)) \ - __dprintf((Tick)-1, std::string(), __VA_ARGS__, cp::ArgListNull()); \ +#define DDUMPN(data, count) do { \ + Trace::dump(curTick, name(), data, count); \ } while (0) -#define DPRINTFN(...) \ -do { \ - __dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \ +#define DPRINTFN(...) do { \ + Trace::dprintf(curTick, name(), __VA_ARGS__); \ } while (0) -#define DPRINTFNR(...) \ -do { \ - __dprintf((Tick)-1, string(), __VA_ARGS__, cp::ArgListNull()); \ +#define DPRINTFNR(...) do { \ + Trace::dprintf((Tick)-1, string(), __VA_ARGS__); \ } while (0) #else // !TRACING_ON #define DTRACE(x) (false) -#define DCOUT(x) if (0) DebugOut() +#define DDUMP(x, data, count) do {} while (0) #define DPRINTF(x, ...) do {} while (0) #define DPRINTFR(...) do {} while (0) +#define DDUMPN(data, count) do {} while (0) #define DPRINTFN(...) do {} while (0) #define DPRINTFNR(...) do {} while (0) -#define DDUMP(x, data, count) do {} while (0) #endif // TRACING_ON diff --git a/src/base/traceflags.py b/src/base/traceflags.py index c06399f81..800c24dee 100644 --- a/src/base/traceflags.py +++ b/src/base/traceflags.py @@ -178,15 +178,22 @@ baseFlags = [ # following the existing examples. # compoundFlagMap = { - 'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv', 'GDBExtra' ], - 'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ], - 'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ], - 'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ], - 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ], - 'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ], - 'O3CPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', 'O3CPU', 'Activity','Scoreboard','Writeback'], - 'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU'], - 'All' : baseFlags + 'All' : baseFlags, + 'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ], + 'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', + 'EthernetData' , 'EthernetDesc', 'EthernetIntr', + 'EthernetSM', 'EthernetCksum' ], + 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', + 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ], + 'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', + 'GDBRecv', 'GDBExtra' ], + 'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ], + 'O3CPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', + 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', + 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', + 'O3CPU', 'Activity','Scoreboard','Writeback' ], + 'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU' ], + 'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ] } ############################################################# diff --git a/src/base/varargs.hh b/src/base/varargs.hh new file mode 100644 index 000000000..2ba8c240a --- /dev/null +++ b/src/base/varargs.hh @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#ifndef __BASE_VARARGS_HH__ +#define __BASE_VARARGS_HH__ + +#include "base/refcnt.hh" + +#define VARARGS_DECLARATION(receiver) \ + VarArgs::Argument<receiver> a01 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a02 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a03 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a04 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a05 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a06 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a07 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a08 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a09 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a10 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a11 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a12 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a13 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a14 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a15 = VarArgs::Null(), \ + VarArgs::Argument<receiver> a16 = VarArgs::Null() + +#define VARARGS_DEFINITION(receiver) \ + VarArgs::Argument<receiver> a01, \ + VarArgs::Argument<receiver> a02, \ + VarArgs::Argument<receiver> a03, \ + VarArgs::Argument<receiver> a04, \ + VarArgs::Argument<receiver> a05, \ + VarArgs::Argument<receiver> a06, \ + VarArgs::Argument<receiver> a07, \ + VarArgs::Argument<receiver> a08, \ + VarArgs::Argument<receiver> a09, \ + VarArgs::Argument<receiver> a10, \ + VarArgs::Argument<receiver> a11, \ + VarArgs::Argument<receiver> a12, \ + VarArgs::Argument<receiver> a13, \ + VarArgs::Argument<receiver> a14, \ + VarArgs::Argument<receiver> a15, \ + VarArgs::Argument<receiver> a16 + +#define VARARGS_ALLARGS \ + a01, a02, a03, a04, a05, a06, a07, a08, \ + a09, a10, a11, a12, a13, a14, a15, a16 + +#define VARARGS_ADDARGS(receiver) do { \ + do { \ + if (!a01) break; \ + a01.add_arg(receiver); \ + if (!a02) break; \ + a02.add_arg(receiver); \ + if (!a03) break; \ + a03.add_arg(receiver); \ + if (!a04) break; \ + a04.add_arg(receiver); \ + if (!a05) break; \ + a05.add_arg(receiver); \ + if (!a06) break; \ + a06.add_arg(receiver); \ + if (!a07) break; \ + a07.add_arg(receiver); \ + if (!a08) break; \ + a08.add_arg(receiver); \ + if (!a09) break; \ + a09.add_arg(receiver); \ + if (!a10) break; \ + a10.add_arg(receiver); \ + if (!a11) break; \ + a11.add_arg(receiver); \ + if (!a12) break; \ + a12.add_arg(receiver); \ + if (!a13) break; \ + a13.add_arg(receiver); \ + if (!a14) break; \ + a14.add_arg(receiver); \ + if (!a15) break; \ + a15.add_arg(receiver); \ + if (!a16) break; \ + a16.add_arg(receiver); \ + } while (0); \ + receiver.end_args(); \ +} while (0) + +namespace VarArgs { + +struct Null {}; + +template <typename T> +struct Traits +{ + enum { enabled = true }; +}; + +template <> +struct Traits<Null> +{ + enum { enabled = false }; +}; + +template <class RECV> +struct Base : public RefCounted +{ + virtual void add_arg(RECV &receiver) const = 0; +}; + +template <typename T, class RECV> +struct Any : public Base<RECV> +{ + const T &argument; + + Any(const T &arg) : argument(arg) {} + + virtual void + add_arg(RECV &receiver) const + { + receiver.add_arg(argument); + } +}; + +template <class RECV> +struct Argument : public RefCountingPtr<Base<RECV> > +{ + typedef RefCountingPtr<Base<RECV> > Base; + + Argument() { } + Argument(const Null &null) { } + template <typename T> + Argument(const T& arg) : Base(new Any<T, RECV>(arg)) { } + + void + add_arg(RECV &receiver) const + { + if (this->data) + this->data->add_arg(receiver); + } +}; + +template<class RECV> +class List +{ + public: + typedef Argument<RECV> Argument; + typedef std::list<Argument> list; + typedef typename list::iterator iterator; + typedef typename list::const_iterator const_iterator; + typedef typename list::size_type size_type; + + protected: + list l; + + public: + List() {} + List(Argument a01, Argument a02, Argument a03, Argument a04, + Argument a05, Argument a06, Argument a07, Argument a08, + Argument a09, Argument a10, Argument a11, Argument a12, + Argument a13, Argument a14, Argument a15, Argument a16) + { + if (!a01) return; + l.push_back(a01); + if (!a02) return; + l.push_back(a02); + if (!a03) return; + l.push_back(a03); + if (!a04) return; + l.push_back(a04); + if (!a05) return; + l.push_back(a05); + if (!a06) return; + l.push_back(a06); + if (!a07) return; + l.push_back(a07); + if (!a08) return; + l.push_back(a08); + if (!a09) return; + l.push_back(a09); + if (!a10) return; + l.push_back(a10); + if (!a11) return; + l.push_back(a11); + if (!a12) return; + l.push_back(a12); + if (!a13) return; + l.push_back(a13); + if (!a14) return; + l.push_back(a14); + if (!a15) return; + l.push_back(a15); + if (!a16) return; + l.push_back(a16); + } + + size_type size() const { return l.size(); } + bool empty() const { return l.empty(); } + + iterator begin() { return l.begin(); } + const_iterator begin() const { return l.begin(); } + + iterator end() { return l.end(); } + const_iterator end() const { return l.end(); } + + void + push_back(const Argument &arg) + { + if (arg) + l.push_back(arg); + } + + void + push_front(const Argument &arg) + { + if (arg) + l.push_front(arg); + } + + template <typename T> + void + push_back(const T &arg) + { + if (Traits<T>::enabled) + l.push_back(arg); + } + + template <typename T> + void + push_front(const T &arg) + { + if (Traits<T>::enabled) + l.push_front(arg); + } + + Argument& front() { return l.front(); } + const Argument& front() const { return l.front(); } + Argument& back() { return l.back(); } + const Argument& back() const { return l.back(); } + + void erase(iterator position) { return l.erase(position); } + void erase(iterator first, iterator last) { return l.erase(first, last); } + void clear() { return l.clear(); } + void pop_front() { return l.pop_front(); } + void pop_back() { return l.pop_back(); } + void reverse() { l.reverse(); } + + /* + * Functions specific to variable arguments + */ + void + add_args(RECV &recv) const + { + const_iterator i = l.begin(); + const_iterator end = l.end(); + while (i != end) { + i->add_arg(recv); + ++i; + } + + recv.end_args(); + } +}; + +/* end namespace VarArgs */ } + +#endif /* __BASE_VARARGS_HH__ */ diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index e34ae3731..683cb138e 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -123,8 +123,10 @@ inline void printLevelHeader(ostream & os, int level) #endif void -Trace::InstRecord::dump(ostream &outs) +Trace::InstRecord::dump() { + ostream &outs = Trace::output(); + DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst); if (flags[PRINT_REG_DELTA]) { @@ -194,7 +196,7 @@ Trace::InstRecord::dump(ostream &outs) bool is_trace_system = true; #endif if (is_trace_system) { - ccprintf(outs, "%7d ) ", cycle); + ccprintf(outs, "%7d ) ", when); outs << "0x" << hex << PC << ":\t"; if (staticInst->isLoad()) { outs << "<RD 0x" << hex << addr; @@ -206,8 +208,8 @@ Trace::InstRecord::dump(ostream &outs) outs << endl; } } else { - if (flags[PRINT_CYCLE]) - ccprintf(outs, "%7d: ", cycle); + if (flags[PRINT_TICKS]) + ccprintf(outs, "%7d: ", when); outs << thread->getCpuPtr()->name() << " "; @@ -324,7 +326,7 @@ Trace::InstRecord::dump(ostream &outs) // We took a trap on a micro-op... if (wasMicro && !staticInst->isMicroOp()) { - // let's skip comparing this cycle + // let's skip comparing this tick while (!compared) if (shared_data->flags == OWN_M5) { shared_data->flags = OWN_LEGION; @@ -411,8 +413,14 @@ Trace::InstRecord::dump(ostream &outs) if(shared_data->y != thread->readIntReg(NumIntArchRegs + 1)) diffY = true; - if(shared_data->fsr != thread->readMiscReg(MISCREG_FSR)) + if(shared_data->fsr != thread->readMiscReg(MISCREG_FSR)) { diffFsr = true; + if (mbits(shared_data->fsr, 63,10) == + mbits(thread->readMiscReg(MISCREG_FSR), 63,10)) { + thread->setMiscReg(MISCREG_FSR, shared_data->fsr); + diffFsr = false; + } + } //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR)) if(shared_data->ccr != thread->readIntReg(NumIntArchRegs + 2)) @@ -450,16 +458,13 @@ Trace::InstRecord::dump(ostream &outs) diffTlb = true; } - if ((diffPC || diffCC || diffInst || diffIntRegs || + if (diffPC || diffCC || diffInst || diffIntRegs || diffFpRegs || diffTpc || diffTnpc || diffTstate || diffTt || diffHpstate || diffHtstate || diffHtba || diffPstate || diffY || diffCcr || diffTl || diffFsr || diffGl || diffAsi || diffPil || diffCwp || diffCansave || diffCanrestore || diffOtherwin || diffCleanwin || diffTlb) - && !((staticInst->machInst & 0xC1F80000) == 0x81D00000) - && !(((staticInst->machInst & 0xC0000000) == 0xC0000000) - && shared_data->tl == thread->readMiscReg(MISCREG_TL) + 1) - ) { + { outs << "Differences found between M5 and Legion:"; if (diffPC) @@ -639,7 +644,7 @@ Trace::InstRecord::dump(ostream &outs) char label[8]; sprintf(label, "%%f%d", x); printRegPair(outs, label, - thread->readFloatRegBits(x,FloatRegFile::DoubleWidth), + thread->readFloatRegBits(x*2,FloatRegFile::DoubleWidth), shared_data->fpregs[x]); } } @@ -667,7 +672,7 @@ Trace::InstRecord::dump(ostream &outs) } diffcount++; - if (diffcount > 2) + if (diffcount > 3) fatal("Differences found between Legion and M5\n"); } else diffcount = 0; @@ -745,7 +750,7 @@ Trace::InstRecord::setParams() { flags[TRACE_MISSPEC] = exe_trace_spec; - flags[PRINT_CYCLE] = exe_trace_print_cycle; + flags[PRINT_TICKS] = exe_trace_print_cycle; flags[PRINT_OP_CLASS] = exe_trace_print_opclass; flags[PRINT_THREAD_NUM] = exe_trace_print_thread; flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr; diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index a825f6a82..95a142f3c 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -36,22 +36,24 @@ #include <fstream> #include <vector> -#include "sim/host.hh" -#include "cpu/inst_seq.hh" // for InstSeqNum #include "base/trace.hh" -#include "cpu/thread_context.hh" +#include "cpu/inst_seq.hh" // for InstSeqNum #include "cpu/static_inst.hh" +#include "cpu/thread_context.hh" +#include "sim/host.hh" class ThreadContext; namespace Trace { -class InstRecord : public Record +class InstRecord { protected: typedef TheISA::IntRegFile IntRegFile; + Tick when; + // The following fields are initialized by the constructor and // thus guaranteed to be valid. ThreadContext *thread; @@ -95,10 +97,10 @@ class InstRecord : public Record bool regs_valid; public: - InstRecord(Tick _cycle, ThreadContext *_thread, + InstRecord(Tick _when, ThreadContext *_thread, const StaticInstPtr &_staticInst, Addr _pc, bool spec) - : Record(_cycle), thread(_thread), + : when(_when), thread(_thread), staticInst(_staticInst), PC(_pc), misspeculating(spec) { @@ -110,9 +112,7 @@ class InstRecord : public Record cp_seq_valid = false; } - virtual ~InstRecord() { } - - virtual void dump(std::ostream &outs); + ~InstRecord() { } void setAddr(Addr a) { addr = a; addr_valid = true; } @@ -136,11 +136,11 @@ class InstRecord : public Record void setRegs(const IntRegFile ®s); - void finalize() { theLog.append(this); } + void dump(); enum InstExecFlagBits { TRACE_MISSPEC = 0, - PRINT_CYCLE, + PRINT_TICKS, PRINT_OP_CLASS, PRINT_THREAD_NUM, PRINT_RESULT_DATA, @@ -176,13 +176,13 @@ InstRecord::setRegs(const IntRegFile ®s) inline InstRecord * -getInstRecord(Tick cycle, ThreadContext *tc, +getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst, Addr pc) { if (DTRACE(InstExec) && (InstRecord::traceMisspec() || !tc->misspeculating())) { - return new InstRecord(cycle, tc, staticInst, pc, + return new InstRecord(when, tc, staticInst, pc, tc->misspeculating()); } diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index f1457922c..18fb2aaa3 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -1106,7 +1106,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) if (head_inst->traceData) { head_inst->traceData->setFetchSeq(head_inst->seqNum); head_inst->traceData->setCPSeq(thread[tid]->numInst); - head_inst->traceData->finalize(); + head_inst->traceData->dump(); + delete head_inst->traceData; head_inst->traceData = NULL; } diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index b8d1f3bed..80b137909 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -427,7 +427,9 @@ BaseSimpleCPU::postExecute() traceFunctions(thread->readPC()); if (traceData) { - traceData->finalize(); + traceData->dump(); + delete traceData; + traceData = NULL; } } diff --git a/src/dev/sparc/mm_disk.cc b/src/dev/sparc/mm_disk.cc index 018415f6c..b8cabd0cf 100644 --- a/src/dev/sparc/mm_disk.cc +++ b/src/dev/sparc/mm_disk.cc @@ -47,7 +47,7 @@ MmDisk::MmDisk(Params *p) : BasicPioDevice(p), image(p->image), curSector((uint64_t)-1), dirty(false) { - std::memset(&bytes, 0, SectorSize); + std::memset(&diskData, 0, SectorSize); pioSize = image->size() * SectorSize; } @@ -57,9 +57,9 @@ MmDisk::read(PacketPtr pkt) Addr accessAddr; off_t sector; off_t bytes_read; - uint16_t *d16; - uint32_t *d32; - uint64_t *d64; + uint16_t d16; + uint32_t d32; + uint64_t d64; assert(pkt->result == Packet::Unknown); assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); @@ -68,26 +68,34 @@ MmDisk::read(PacketPtr pkt) sector = accessAddr / SectorSize; if (sector != curSector) { - if (dirty) - bytes_read = image->write(bytes, curSector); - bytes_read = image->read(bytes, sector); + if (dirty) { + bytes_read = image->write(diskData, curSector); + assert(bytes_read == SectorSize); + } + bytes_read = image->read(diskData, sector); + assert(bytes_read == SectorSize); curSector = sector; } switch (pkt->getSize()) { case sizeof(uint8_t): - pkt->set(bytes[accessAddr % SectorSize]); + pkt->set(diskData[accessAddr % SectorSize]); + DPRINTF(IdeDisk, "reading byte %#x value= %#x\n", accessAddr, diskData[accessAddr % + SectorSize]); break; case sizeof(uint16_t): - d16 = (uint16_t*)bytes + (accessAddr % SectorSize)/2; - pkt->set(htobe(*d16)); + memcpy(&d16, diskData + (accessAddr % SectorSize), 2); + pkt->set(htobe(d32)); + DPRINTF(IdeDisk, "reading word %#x value= %#x\n", accessAddr, d16); break; case sizeof(uint32_t): - d32 = (uint32_t*)bytes + (accessAddr % SectorSize)/4; - pkt->set(htobe(*d32)); + memcpy(&d32, diskData + (accessAddr % SectorSize), 4); + pkt->set(htobe(d32)); + DPRINTF(IdeDisk, "reading dword %#x value= %#x\n", accessAddr, d32); break; case sizeof(uint64_t): - d64 = (uint64_t*)bytes + (accessAddr % SectorSize)/8; - pkt->set(htobe(*d64)); + memcpy(&d64, diskData + (accessAddr % SectorSize), 8); + pkt->set(htobe(d64)); + DPRINTF(IdeDisk, "reading qword %#x value= %#x\n", accessAddr, d64); break; default: panic("Invalid access size\n"); @@ -100,11 +108,74 @@ MmDisk::read(PacketPtr pkt) Tick MmDisk::write(PacketPtr pkt) { - panic("need to implement\n"); - M5_DUMMY_RETURN + Addr accessAddr; + off_t sector; + off_t bytes_read; + uint16_t d16; + uint32_t d32; + uint64_t d64; + + assert(pkt->result == Packet::Unknown); + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + accessAddr = pkt->getAddr() - pioAddr; + + sector = accessAddr / SectorSize; + + if (sector != curSector) { + if (dirty) { + bytes_read = image->write(diskData, curSector); + assert(bytes_read == SectorSize); + } + bytes_read = image->read(diskData, sector); + assert(bytes_read == SectorSize); + curSector = sector; + } + dirty = true; + + switch (pkt->getSize()) { + case sizeof(uint8_t): + diskData[accessAddr % SectorSize] = htobe(pkt->get<uint8_t>()); + DPRINTF(IdeDisk, "writing byte %#x value= %#x\n", accessAddr, diskData[accessAddr % + SectorSize]); + break; + case sizeof(uint16_t): + d16 = htobe(pkt->get<uint16_t>()); + memcpy(diskData + (accessAddr % SectorSize), &d16, 2); + DPRINTF(IdeDisk, "writing word %#x value= %#x\n", accessAddr, d16); + break; + case sizeof(uint32_t): + d32 = htobe(pkt->get<uint32_t>()); + memcpy(diskData + (accessAddr % SectorSize), &d32, 4); + DPRINTF(IdeDisk, "writing dword %#x value= %#x\n", accessAddr, d32); + break; + case sizeof(uint64_t): + d64 = htobe(pkt->get<uint64_t>()); + memcpy(diskData + (accessAddr % SectorSize), &d64, 8); + DPRINTF(IdeDisk, "writing qword %#x value= %#x\n", accessAddr, d64); + break; + default: + panic("Invalid access size\n"); + } + + pkt->result = Packet::Success; + return pioDelay; +} + +void +MmDisk::serialize(std::ostream &os) +{ + // just write any dirty changes to the cow layer it will take care of + // serialization + int bytes_read; + if (dirty) { + bytes_read = image->write(diskData, curSector); + assert(bytes_read == SectorSize); + } } + + BEGIN_DECLARE_SIM_OBJECT_PARAMS(MmDisk) Param<Addr> pio_addr; Param<Tick> pio_latency; diff --git a/src/dev/sparc/mm_disk.hh b/src/dev/sparc/mm_disk.hh index 0a4626067..30028d2b6 100644 --- a/src/dev/sparc/mm_disk.hh +++ b/src/dev/sparc/mm_disk.hh @@ -46,10 +46,7 @@ class MmDisk : public BasicPioDevice DiskImage *image; off_t curSector; bool dirty; - union { - uint8_t bytes[SectorSize]; - uint32_t words[SectorSize/4]; - }; + uint8_t diskData[SectorSize]; public: struct Params : public BasicPioDevice::Params @@ -64,6 +61,8 @@ class MmDisk : public BasicPioDevice virtual Tick read(PacketPtr pkt); virtual Tick write(PacketPtr pkt); + + virtual void serialize(std::ostream &os); }; #endif //__DEV_SPARC_MM_DISK_HH__ diff --git a/src/kern/linux/printk.cc b/src/kern/linux/printk.cc index ea3d59f19..0e9fd6620 100644 --- a/src/kern/linux/printk.cc +++ b/src/kern/linux/printk.cc @@ -41,11 +41,12 @@ using namespace std; void Printk(TheISA::Arguments args) { + std::ostream &out = Trace::output(); char *p = (char *)args++; - ios::fmtflags saved_flags = DebugOut().flags(); - char old_fill = DebugOut().fill(); - int old_precision = DebugOut().precision(); + ios::fmtflags saved_flags = out.flags(); + char old_fill = out.fill(); + int old_precision = out.precision(); while (*p) { switch (*p) { @@ -118,53 +119,53 @@ Printk(TheISA::Arguments args) case 'P': case 'p': { if (hexnum) - DebugOut() << hex; + out << hex; if (octal) - DebugOut() << oct; + out << oct; if (format) { if (!zero) - DebugOut().setf(ios::showbase); + out.setf(ios::showbase); else { if (hexnum) { - DebugOut() << "0x"; + out << "0x"; width -= 2; } else if (octal) { - DebugOut() << "0"; + out << "0"; width -= 1; } } } if (zero) - DebugOut().fill('0'); + out.fill('0'); if (width > 0) - DebugOut().width(width); + out.width(width); if (leftjustify && !zero) - DebugOut().setf(ios::left); + out.setf(ios::left); if (sign) { if (islong) - DebugOut() << (int64_t)args; + out << (int64_t)args; else - DebugOut() << (int32_t)args; + out << (int32_t)args; } else { if (islong) - DebugOut() << (uint64_t)args; + out << (uint64_t)args; else - DebugOut() << (uint32_t)args; + out << (uint32_t)args; } if (zero) - DebugOut().fill(' '); + out.fill(' '); if (width > 0) - DebugOut().width(0); + out.width(0); - DebugOut() << dec; + out << dec; ++args; } @@ -176,11 +177,11 @@ Printk(TheISA::Arguments args) s = "<NULL>"; if (width > 0) - DebugOut().width(width); + out.width(width); if (leftjustify) - DebugOut().setf(ios::left); + out.setf(ios::left); - DebugOut() << s; + out << s; ++args; } break; @@ -201,7 +202,7 @@ Printk(TheISA::Arguments args) while (width-- > 0) { char c = (char)(num & mask); if (c) - DebugOut() << c; + out << c; num >>= 8; } @@ -211,7 +212,7 @@ Printk(TheISA::Arguments args) case 'b': { uint64_t n = (uint64_t)args++; char *s = (char *)args++; - DebugOut() << s << ": " << n; + out << s << ": " << n; } break; case 'n': @@ -233,32 +234,32 @@ Printk(TheISA::Arguments args) } break; case '%': - DebugOut() << '%'; + out << '%'; break; } ++p; } break; case '\n': - DebugOut() << endl; + out << endl; ++p; break; case '\r': ++p; if (*p != '\n') - DebugOut() << endl; + out << endl; break; default: { size_t len = strcspn(p, "%\n\r\0"); - DebugOut().write(p, len); + out.write(p, len); p += len; } } } - DebugOut().flags(saved_flags); - DebugOut().fill(old_fill); - DebugOut().precision(old_precision); + out.flags(saved_flags); + out.fill(old_fill); + out.precision(old_precision); } diff --git a/src/kern/tru64/dump_mbuf.cc b/src/kern/tru64/dump_mbuf.cc index 22d2228f0..5ccfbca5d 100644 --- a/src/kern/tru64/dump_mbuf.cc +++ b/src/kern/tru64/dump_mbuf.cc @@ -50,6 +50,7 @@ void DumpMbuf(Arguments args) { ThreadContext *tc = args.getThreadContext(); + StringWrap name(tc->getSystemPtr()->name()); Addr addr = (Addr)args; struct mbuf m; @@ -57,16 +58,14 @@ DumpMbuf(Arguments args) int count = m.m_pkthdr.len; - ccprintf(DebugOut(), "m=%#lx, m->m_pkthdr.len=%#d\n", addr, - m.m_pkthdr.len); + DPRINTFN("m=%#lx, m->m_pkthdr.len=%#d\n", addr, m.m_pkthdr.len); while (count > 0) { - ccprintf(DebugOut(), "m=%#lx, m->m_data=%#lx, m->m_len=%d\n", + DPRINTFN("m=%#lx, m->m_data=%#lx, m->m_len=%d\n", addr, m.m_data, m.m_len); char *buffer = new char[m.m_len]; CopyOut(tc, buffer, m.m_data, m.m_len); - Trace::dataDump(curTick, tc->getSystemPtr()->name(), (uint8_t *)buffer, - m.m_len); + DDUMPN((uint8_t *)buffer, m.m_len); delete [] buffer; count -= m.m_len; diff --git a/src/kern/tru64/printf.cc b/src/kern/tru64/printf.cc index 2c767c4d2..4245ac6d0 100644 --- a/src/kern/tru64/printf.cc +++ b/src/kern/tru64/printf.cc @@ -44,11 +44,13 @@ namespace tru64 { void Printf(TheISA::Arguments args) { + std::ostream &out = Trace::output(); + char *p = (char *)args++; - ios::fmtflags saved_flags = DebugOut().flags(); - char old_fill = DebugOut().fill(); - int old_precision = DebugOut().precision(); + ios::fmtflags saved_flags = out.flags(); + char old_fill = out.fill(); + int old_precision = out.precision(); while (*p) { switch (*p) { @@ -121,53 +123,53 @@ Printf(TheISA::Arguments args) case 'P': case 'p': { if (hexnum) - DebugOut() << hex; + out << hex; if (octal) - DebugOut() << oct; + out << oct; if (format) { if (!zero) - DebugOut().setf(ios::showbase); + out.setf(ios::showbase); else { if (hexnum) { - DebugOut() << "0x"; + out << "0x"; width -= 2; } else if (octal) { - DebugOut() << "0"; + out << "0"; width -= 1; } } } if (zero) - DebugOut().fill('0'); + out.fill('0'); if (width > 0) - DebugOut().width(width); + out.width(width); if (leftjustify && !zero) - DebugOut().setf(ios::left); + out.setf(ios::left); if (sign) { if (islong) - DebugOut() << (int64_t)args; + out << (int64_t)args; else - DebugOut() << (int32_t)args; + out << (int32_t)args; } else { if (islong) - DebugOut() << (uint64_t)args; + out << (uint64_t)args; else - DebugOut() << (uint32_t)args; + out << (uint32_t)args; } if (zero) - DebugOut().fill(' '); + out.fill(' '); if (width > 0) - DebugOut().width(0); + out.width(0); - DebugOut() << dec; + out << dec; ++args; } @@ -179,11 +181,11 @@ Printf(TheISA::Arguments args) s = "<NULL>"; if (width > 0) - DebugOut().width(width); + out.width(width); if (leftjustify) - DebugOut().setf(ios::left); + out.setf(ios::left); - DebugOut() << s; + out << s; ++args; } break; @@ -204,7 +206,7 @@ Printf(TheISA::Arguments args) while (width-- > 0) { char c = (char)(num & mask); if (c) - DebugOut() << c; + out << c; num >>= 8; } @@ -214,7 +216,7 @@ Printf(TheISA::Arguments args) case 'b': { uint64_t n = (uint64_t)args++; char *s = (char *)args++; - DebugOut() << s << ": " << n; + out << s << ": " << n; } break; case 'n': @@ -236,33 +238,33 @@ Printf(TheISA::Arguments args) } break; case '%': - DebugOut() << '%'; + out << '%'; break; } ++p; } break; case '\n': - DebugOut() << endl; + out << endl; ++p; break; case '\r': ++p; if (*p != '\n') - DebugOut() << endl; + out << endl; break; default: { size_t len = strcspn(p, "%\n\r\0"); - DebugOut().write(p, len); + out.write(p, len); p += len; } } } - DebugOut().flags(saved_flags); - DebugOut().fill(old_fill); - DebugOut().precision(old_precision); + out.flags(saved_flags); + out.fill(old_fill); + out.precision(old_precision); } } // namespace Tru64 diff --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc index 851b3a526..0ad89f8bd 100644 --- a/src/kern/tru64/tru64_events.cc +++ b/src/kern/tru64/tru64_events.cc @@ -79,7 +79,8 @@ void PrintfEvent::process(ThreadContext *tc) { if (DTRACE(Printf)) { - DebugOut() << curTick << ": " << tc->getCpuPtr()->name() << ": "; + StringWrap name(tc->getSystemPtr()->name()); + DPRINTFN(""); Arguments args(tc); tru64::Printf(args); @@ -90,8 +91,10 @@ void DebugPrintfEvent::process(ThreadContext *tc) { if (DTRACE(DebugPrintf)) { - if (!raw) - DebugOut() << curTick << ": " << tc->getCpuPtr()->name() << ": "; + if (!raw) { + StringWrap name(tc->getSystemPtr()->name()); + DPRINTFN(""); + } Arguments args(tc); tru64::Printf(args); diff --git a/src/python/SConscript b/src/python/SConscript index df1464809..61cab45f3 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -108,6 +108,8 @@ def swig_it(basename): swig_it('main') swig_it('debug') swig_it('event') +swig_it('random') +swig_it('trace') # Action function to build the zip archive. Uses the PyZipFile module # included in the standard Python library. diff --git a/src/python/m5/main.py b/src/python/m5/main.py index 5df6d03cf..d02bc466b 100644 --- a/src/python/m5/main.py +++ b/src/python/m5/main.py @@ -30,11 +30,6 @@ import code, optparse, os, socket, sys from datetime import datetime from attrdict import attrdict -try: - import info -except ImportError: - info = None - __all__ = [ 'options', 'arguments', 'main' ] usage="%prog [m5 options] script.py [script options]" @@ -142,18 +137,10 @@ add_option("--debug-break", metavar="TIME[,TIME]", action='append', split=',', set_group("Trace Options") add_option("--trace-flags", metavar="FLAG[,FLAG]", action='append', split=',', help="Sets the flags for tracing") -add_option("--trace-start", metavar="TIME", default='0s', - help="Start tracing at TIME (must have units)") -add_option("--trace-cycle", metavar="CYCLE", default='0', - help="Start tracing at CYCLE") +add_option("--trace-start", metavar="TIME", type='int', + help="Start tracing at TIME (must be in ticks)") add_option("--trace-file", metavar="FILE", default="cout", help="Sets the output file for tracing [Default: %default]") -add_option("--trace-circlebuf", metavar="SIZE", type="int", default=0, - help="If SIZE is non-zero, turn on the circular buffer with SIZE lines") -add_option("--no-trace-circlebuf", action="store_const", const=0, - dest='trace_circlebuf', help=optparse.SUPPRESS_HELP) -bool_option("trace-dumponexit", default=False, - help="Dump trace buffer on exit") add_option("--trace-ignore", metavar="EXPR", action='append', split=':', help="Ignore EXPR sim objects") @@ -211,6 +198,8 @@ def parse_args(): return opts,args def main(): + import defines + import info import internal parse_args() @@ -278,14 +267,19 @@ def main(): for when in options.debug_break: internal.debug.schedBreakCycle(int(when)) - # set tracing options - objects.Trace.flags = options.trace_flags - objects.Trace.start = options.trace_start - objects.Trace.cycle = options.trace_cycle - objects.Trace.file = options.trace_file - objects.Trace.bufsize = options.trace_circlebuf - objects.Trace.dump_on_exit = options.trace_dumponexit - objects.Trace.ignore = options.trace_ignore + for flag in options.trace_flags: + internal.trace.set(flag) + + if options.trace_start is not None: + internal.trace.enabled = False + def enable_trace(): + internal.event.enabled = True + internal.event.create(enable_trace, options.trace_start) + + internal.trace.output(options.trace_file) + + for ignore in options.trace_ignore: + internal.trace.ignore(ignore) # set execution trace options objects.ExecutionTrace.speculative = options.speculative @@ -309,7 +303,7 @@ def main(): # we want readline if we're doing anything interactive if options.interactive or options.pdb: - exec("import readline", scope) + exec "import readline" in scope # if pdb was requested, execfile the thing under pdb, otherwise, # just do the execfile normally diff --git a/src/python/m5/objects/Root.py b/src/python/m5/objects/Root.py index b6123f192..81482c1de 100644 --- a/src/python/m5/objects/Root.py +++ b/src/python/m5/objects/Root.py @@ -3,7 +3,6 @@ from m5.params import * from Serialize import Serialize from Serialize import Statreset from Statistics import Statistics -from Trace import Trace from ExeTrace import ExecutionTrace class Root(SimObject): @@ -15,9 +14,7 @@ class Root(SimObject): output_file = Param.String('cout', "file to dump simulator output to") checkpoint = Param.String('', "checkpoint file to load") # stats = Param.Statistics(Statistics(), "statistics object") -# trace = Param.Trace(Trace(), "trace object") # serialize = Param.Serialize(Serialize(), "checkpoint generation options") stats = Statistics() - trace = Trace() exetrace = ExecutionTrace() serialize = Serialize() diff --git a/src/python/swig/random.i b/src/python/swig/random.i new file mode 100644 index 000000000..657a59780 --- /dev/null +++ b/src/python/swig/random.i @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +%module random + +%include "stdint.i" + +%{ +#include <cstdlib> + +#include "sim/host.hh" + +inline void +seed(uint64_t seed) +{ + ::srand48(seed & ULL(0xffffffffffff)); +} +%} + +%inline %{ +extern void seed(uint64_t seed); +%} + +%wrapper %{ +// fix up module name to reflect the fact that it's inside the m5 package +#undef SWIG_name +#define SWIG_name "m5.internal._random" +%} diff --git a/src/python/swig/trace.i b/src/python/swig/trace.i new file mode 100644 index 000000000..69b44c025 --- /dev/null +++ b/src/python/swig/trace.i @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +%module trace + +%{ +#include "base/trace.hh" +#include "sim/host.hh" + +inline void +output(const char *filename) +{ + Trace::setOutput(filename); +} + +inline void +set(const char *flag) +{ + Trace::changeFlag(flag, true); +} + +inline void +clear(const char *flag) +{ + Trace::changeFlag(flag, false); +} + +inline void +ignore(const char *expr) +{ + Trace::ignore.setExpression(expr); +} + +using Trace::enabled; +%} + +%inline %{ +extern void output(const char *string); +extern void set(const char *string); +extern void clear(const char *string); +extern void ignore(const char *expr); +extern bool enabled; +%} + +%wrapper %{ +// fix up module name to reflect the fact that it's inside the m5 package +#undef SWIG_name +#define SWIG_name "m5.internal._trace" +%} diff --git a/src/sim/main.cc b/src/sim/main.cc index 04dbe1ef4..9f9a56450 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -111,11 +111,6 @@ void abortHandler(int sigtype) { cerr << "Program aborted at cycle " << curTick << endl; - -#if TRACING_ON - // dump trace buffer, if there is one - Trace::theLog.dump(cerr); -#endif } int diff --git a/src/unittest/Makefile b/src/unittest/Makefile index e22b80b48..e6a621a9e 100644 --- a/src/unittest/Makefile +++ b/src/unittest/Makefile @@ -56,6 +56,9 @@ circletest: unittest/circletest.cc base/circlebuf.cc cprintftest: unittest/cprintftest.cc base/cprintf.cc $(CXX) $(CCFLAGS) -o $@ $^ +cprintftime: unittest/cprintftime.cc base/cprintf.cc + $(CXX) $(CCFLAGS) -o $@ $^ + initest: unittest/initest.cc base/str.cc base/inifile.cc base/cprintf.cc $(CXX) $(CCFLAGS) -o $@ $^ diff --git a/src/unittest/cprintftime.cc b/src/unittest/cprintftime.cc new file mode 100644 index 000000000..f35e0aa25 --- /dev/null +++ b/src/unittest/cprintftime.cc @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2002-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Nathan Binkert + */ + +#include <iostream> +#include <list> +#include <string> +#include <sstream> + +#include "base/cprintf.hh" + +using namespace std; + +volatile int stop = false; + +void +handle_alarm(int signal) +{ + stop = true; +} + +void +do_test(int seconds) +{ + stop = false; + alarm(seconds); +} + +int +main() +{ + stringstream result; + int iterations = 0; + + signal(SIGALRM, handle_alarm); + + do_test(10); + while (!stop) { + stringstream result; + ccprintf(result, + "this is a %s of %d iterations %3.2f %#x\n", + "test", iterations, 51.934, &result); + + iterations += 1; + } + + cprintf("completed %d iterations of ccprintf in 10s, %f iterations/s\n", + iterations, iterations / 10.0); + + do_test(10); + while (!stop) { + char result[1024]; + sprintf(result, + "this is a %s of %d iterations %3.2f %#x\n", + "test", iterations, 51.934, &result); + + iterations += 1; + } + + cprintf("completed %d iterations of sprintf in 10s, %f iterations/s\n", + iterations, iterations / 10.0); + + return 0; +} |