From 4c55d26e664f870d56889097939569c4b07c6de2 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 18 May 2004 16:09:02 -0700 Subject: Replace explicit xc->misspeculating() tests in execute() methods with an IsNonSpeculative flag. No effect on results of non-full-system or SimpleCPU. Very small impact on full-system FullCPU runs since old wrong-path call_pal insts used to change the PC, where now they're treated as no-ops. arch/alpha/isa_desc: Get rid of xc->misspeculating() checks, use IsNonSpeculative flag instead. cpu/static_inst.hh: Add IsNonSpeculative flag and isNonSpeculative() method to test it. --HG-- extra : convert_revision : 7ec536bfc28b905c429c09eb920ed73ef2beeeba --- cpu/static_inst.hh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'cpu') diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh index 1065fa3d4..088fdbdb7 100644 --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@ -106,11 +106,13 @@ class StaticInstBase : public RefCounted IsThreadSync, ///< Thread synchronization operation. - IsSerializing, ///< Serializes pipeline: won't until all + IsSerializing, ///< Serializes pipeline: won't execute until all /// older instructions have committed. IsMemBarrier, ///< Is a memory barrier IsWriteBarrier, ///< Is a write barrier + IsNonSpeculative, ///< Should not be executed speculatively + NumFlags }; @@ -192,6 +194,7 @@ class StaticInstBase : public RefCounted bool isSerializing() const { return flags[IsSerializing]; } bool isMemBarrier() const { return flags[IsMemBarrier]; } bool isWriteBarrier() const { return flags[IsWriteBarrier]; } + bool isNonSpeculative() const { return flags[IsNonSpeculative]; } //@} /// Operation class. Used to select appropriate function unit in issue. -- cgit v1.2.3 From 27a6e8258dabef233bc1681649b871bf150878ed Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 18 May 2004 22:09:13 -0700 Subject: Add a level of indirection to the register accessors used in instruction execute methods. Register i now means the instruction's i'th src (or dest) operand, not architectural register i. Current models that use the architectural reg index can look that up easily in the instruction object. Future models that do register renaming should find this much simpler to deal with. arch/isa_parser.py: Generate register accessors with an extra level of indirection. cpu/simple_cpu/simple_cpu.hh: Modify register accessors to use an extra level of indirection. --HG-- extra : convert_revision : f4c7d6bfa92fb2ea6251f31ee368809c3643f08f --- cpu/simple_cpu/simple_cpu.hh | 73 ++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 19 deletions(-) (limited to 'cpu') diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index a04dcd057..0c7204fcd 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -35,6 +35,7 @@ #include "cpu/pc_event.hh" #include "base/statistics.hh" #include "cpu/exec_context.hh" +#include "cpu/static_inst.hh" // forward declarations #ifdef FULL_SYSTEM @@ -261,37 +262,71 @@ class SimpleCPU : public BaseCPU Fault copy(Addr dest); - uint64_t readIntReg(int reg_idx) { return xc->readIntReg(reg_idx); } + // The register accessor methods provide the index of the + // instruction's operand (e.g., 0 or 1), not the architectural + // register index, to simplify the implementation of register + // renaming. We find the architectural register index by indexing + // into the instruction's own operand index table. Note that a + // raw pointer to the StaticInst is provided instead of a + // ref-counted StaticInstPtr to redice overhead. This is fine as + // long as these methods don't copy the pointer into any long-term + // storage (which is pretty hard to imagine they would have reason + // to do). + + uint64_t readIntReg(StaticInst *si, int idx) + { + return xc->readIntReg(si->srcRegIdx(idx)); + } - float readFloatRegSingle(int reg_idx) - { return xc->readFloatRegSingle(reg_idx); } + float readFloatRegSingle(StaticInst *si, int idx) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; + return xc->readFloatRegSingle(reg_idx); + } - double readFloatRegDouble(int reg_idx) - { return xc->readFloatRegDouble(reg_idx); } + double readFloatRegDouble(StaticInst *si, int idx) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; + return xc->readFloatRegDouble(reg_idx); + } - uint64_t readFloatRegInt(int reg_idx) - { return xc->readFloatRegInt(reg_idx); } + uint64_t readFloatRegInt(StaticInst *si, int idx) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; + return xc->readFloatRegInt(reg_idx); + } - void setIntReg(int reg_idx, uint64_t val) - { return xc->setIntReg(reg_idx, val); } + void setIntReg(StaticInst *si, int idx, uint64_t val) + { + xc->setIntReg(si->destRegIdx(idx), val); + } - void setFloatRegSingle(int reg_idx, float val) - { return xc->setFloatRegSingle(reg_idx, val); } + void setFloatRegSingle(StaticInst *si, int idx, float val) + { + int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; + xc->setFloatRegSingle(reg_idx, val); + } - void setFloatRegDouble(int reg_idx, double val) - { return xc->setFloatRegDouble(reg_idx, val); } + void setFloatRegDouble(StaticInst *si, int idx, double val) + { + int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; + xc->setFloatRegDouble(reg_idx, val); + } - void setFloatRegInt(int reg_idx, uint64_t val) - { return xc->setFloatRegInt(reg_idx, val); } + void setFloatRegInt(StaticInst *si, int idx, uint64_t val) + { + int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; + xc->setFloatRegInt(reg_idx, val); + } uint64_t readPC() { return xc->readPC(); } - void setNextPC(uint64_t val) { return xc->setNextPC(val); } + void setNextPC(uint64_t val) { xc->setNextPC(val); } uint64_t readUniq() { return xc->readUniq(); } - void setUniq(uint64_t val) { return xc->setUniq(val); } + void setUniq(uint64_t val) { xc->setUniq(val); } uint64_t readFpcr() { return xc->readFpcr(); } - void setFpcr(uint64_t val) { return xc->setFpcr(val); } + void setFpcr(uint64_t val) { xc->setFpcr(val); } #ifdef FULL_SYSTEM uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); } @@ -300,7 +335,7 @@ class SimpleCPU : public BaseCPU int readIntrFlag() { return xc->readIntrFlag(); } void setIntrFlag(int val) { xc->setIntrFlag(val); } bool inPalMode() { return xc->inPalMode(); } - void ev5_trap(Fault fault) { return xc->ev5_trap(fault); } + void ev5_trap(Fault fault) { xc->ev5_trap(fault); } bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); } #else void syscall() { xc->syscall(); } -- cgit v1.2.3 From b4405682d9f0d7bd01ff461a7e457f8dbbfff1a0 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 21 May 2004 13:03:17 -0400 Subject: Change the namespace Statistics to Stats --HG-- extra : convert_revision : 3084b292bbe2e8a392af8e99a31763ca0b0a9467 --- cpu/base_cpu.cc | 2 +- cpu/base_cpu.hh | 2 +- cpu/exec_context.cc | 2 +- cpu/memtest/memtest.cc | 2 +- cpu/memtest/memtest.hh | 6 +++--- cpu/simple_cpu/simple_cpu.cc | 2 +- cpu/simple_cpu/simple_cpu.hh | 12 ++++++------ 7 files changed, 14 insertions(+), 14 deletions(-) (limited to 'cpu') diff --git a/cpu/base_cpu.cc b/cpu/base_cpu.cc index 624023f0a..702a9afe8 100644 --- a/cpu/base_cpu.cc +++ b/cpu/base_cpu.cc @@ -130,7 +130,7 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads, void BaseCPU::regStats() { - using namespace Statistics; + using namespace Stats; numCycles .name(name() + ".numCycles") diff --git a/cpu/base_cpu.hh b/cpu/base_cpu.hh index c4826cf15..9c4026784 100644 --- a/cpu/base_cpu.hh +++ b/cpu/base_cpu.hh @@ -167,7 +167,7 @@ class BaseCPU : public SimObject public: // Number of CPU cycles simulated - Statistics::Scalar<> numCycles; + Stats::Scalar<> numCycles; }; #endif // __BASE_CPU_HH__ diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc index a89cf4bb5..7f7719bf0 100644 --- a/cpu/exec_context.cc +++ b/cpu/exec_context.cc @@ -128,7 +128,7 @@ ExecContext::serialize(ostream &os) SERIALIZE_SCALAR(ctx); } if (system->bin) { - Statistics::MainBin *cur = Statistics::MainBin::curBin(); + Stats::MainBin *cur = Stats::MainBin::curBin(); string bin_name = cur->name(); SERIALIZE_SCALAR(bin_name); } diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc index 5d608976d..1d745724f 100644 --- a/cpu/memtest/memtest.cc +++ b/cpu/memtest/memtest.cc @@ -186,7 +186,7 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data) void MemTest::regStats() { - using namespace Statistics; + using namespace Stats; numReadsStat diff --git a/cpu/memtest/memtest.hh b/cpu/memtest/memtest.hh index f2409d54c..4bde5c066 100644 --- a/cpu/memtest/memtest.hh +++ b/cpu/memtest/memtest.hh @@ -111,9 +111,9 @@ class MemTest : public BaseCPU Tick noResponseCycles; uint64_t numReads; - Statistics::Scalar<> numReadsStat; - Statistics::Scalar<> numWritesStat; - Statistics::Scalar<> numCopiesStat; + Stats::Scalar<> numReadsStat; + Stats::Scalar<> numWritesStat; + Stats::Scalar<> numCopiesStat; // called by MemCompleteEvent::process() void completeRequest(MemReqPtr &req, uint8_t *data); diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 617c91e68..765507345 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -254,7 +254,7 @@ SimpleCPU::haltContext(int thread_num) void SimpleCPU::regStats() { - using namespace Statistics; + using namespace Stats; BaseCPU::regStats(); diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index 0c7204fcd..1c6b18d03 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -210,7 +210,7 @@ class SimpleCPU : public BaseCPU // number of simulated instructions Counter numInst; Counter startNumInst; - Statistics::Scalar<> numInsts; + Stats::Scalar<> numInsts; virtual Counter totalInstructions() const { @@ -218,22 +218,22 @@ class SimpleCPU : public BaseCPU } // number of simulated memory references - Statistics::Scalar<> numMemRefs; + Stats::Scalar<> numMemRefs; // number of simulated loads Counter numLoad; Counter startNumLoad; // number of idle cycles - Statistics::Average<> notIdleFraction; - Statistics::Formula idleFraction; + Stats::Average<> notIdleFraction; + Stats::Formula idleFraction; // number of cycles stalled for I-cache misses - Statistics::Scalar<> icacheStallCycles; + Stats::Scalar<> icacheStallCycles; Counter lastIcacheStall; // number of cycles stalled for D-cache misses - Statistics::Scalar<> dcacheStallCycles; + Stats::Scalar<> dcacheStallCycles; Counter lastDcacheStall; void processCacheCompletion(); -- cgit v1.2.3 From f622d74f81f6d0c451bc8437d19a38057bc0d164 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Fri, 21 May 2004 13:58:39 -0400 Subject: add a few statistics events arch/alpha/ev5.cc: Add an event for faults cpu/simple_cpu/simple_cpu.cc: add events for uncached reads/writes --HG-- extra : convert_revision : 747bdf12761e2de6ebbf54fecc9e0b71915b3a02 --- cpu/simple_cpu/simple_cpu.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'cpu') diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 765507345..1ade235ed 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -42,6 +42,7 @@ #include "base/pollevent.hh" #include "base/range.hh" #include "base/trace.hh" +#include "base/stats/events.hh" #include "cpu/base_cpu.hh" #include "cpu/exec_context.hh" #include "cpu/exetrace.hh" @@ -402,6 +403,9 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) } } + if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) + Stats::recordEvent("Uncached Read"); + return fault; } @@ -487,6 +491,9 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) if (res && (fault == No_Fault)) *res = memReq->result; + if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) + Stats::recordEvent("Uncached Write"); + return fault; } -- cgit v1.2.3 From a896960cbfce76a0e0c8cfb5cbdfc805ce72577b Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Thu, 27 May 2004 17:46:16 -0400 Subject: FastCPU model added. It's very similar to the SimpleCPU, just without a lot of the stats tracking. Also various changes to make the CPU model less ISA dependent, which includes moving the code that checks for interrupts up to the ISA level, moving code that zeroes the zero registers up to the ISA level, and removing opcode and ra from the regfile. arch/alpha/alpha_memory.cc: The regfile has been changed so it no longer has the opcode and ra. Instead the xc holds the actual instruction, and from there the opcode and ra can be obtained with OPCODE() and RA(). arch/alpha/ev5.cc: Moved code that once existed within simpleCPU to ev5, and templatized it. This way the CPU models can call processInterrupts and the ISA specific interrupt handling is left to the ISA's code. Also moved ISA specific zero registers from simpleCPU to here. arch/alpha/ev5.hh: Added macros for obtaining the opcode and ra from the instruction itself, as there is no longer opcode or ra in the regfile. arch/alpha/isa_desc: Added in declarations for the FastCPU model. arch/alpha/isa_traits.hh: Removed opcode and ra from the regfile. The xc now holds the actual instruction, and the opcode and ra can be obtained through it. Also added the declaration for the templated zeroRegisters() function, which will set the zero registers to 0. arch/isa_parser.py: Added in FastCPUExecContext so it will generate code for the FastCPU model as well. cpu/exec_context.cc: Added in a more generic trap function so "ev5_trap" doesn't need to be called. It currently still calls the old method, with plans for making this ISA dependent in the future. cpu/exec_context.hh: Exec context now has the instruction within it. Also added methods for exec context to read an instruction from memory, return the current instruction, and set the instruction if needed. Also has declaration for more generic trap() function. cpu/simple_cpu/simple_cpu.cc: Removed references to opcode and ra, and instead sets the xc's instruction with the fetched instruction. cpu/static_inst.hh: Added declaration for execute() using FastCPUExecContext. --HG-- extra : convert_revision : 0441ea3700ac50b733e485395d4dd4ac83666f92 --- cpu/exec_context.cc | 15 +++++++++++++++ cpu/exec_context.hh | 24 ++++++++++++++++++++++++ cpu/simple_cpu/simple_cpu.cc | 3 +-- cpu/static_inst.hh | 8 ++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) (limited to 'cpu') diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc index a89cf4bb5..832a621f8 100644 --- a/cpu/exec_context.cc +++ b/cpu/exec_context.cc @@ -106,6 +106,7 @@ ExecContext::serialize(ostream &os) regs.serialize(os); // thread_num and cpu_id are deterministic from the config SERIALIZE_SCALAR(func_exe_inst); + SERIALIZE_SCALAR(inst); #ifdef FULL_SYSTEM bool ctx = false; @@ -143,6 +144,7 @@ ExecContext::unserialize(Checkpoint *cp, const std::string §ion) regs.unserialize(cp, section); // thread_num and cpu_id are deterministic from the config UNSERIALIZE_SCALAR(func_exe_inst); + UNSERIALIZE_SCALAR(inst); #ifdef FULL_SYSTEM bool ctx; @@ -233,3 +235,16 @@ ExecContext::regStats(const string &name) kernelStats.regStats(name + ".kern"); #endif } + +void +ExecContext::trap(Fault fault) +{ + //TheISA::trap(fault); //One possible way to do it... + + /** @todo: Going to hack it for now. Do a true fixup later. */ +#ifdef FULL_SYSTEM + ev5_trap(fault); +#else + fatal("fault (%d) detected @ PC 0x%08p", fault, readPC()); +#endif +} diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index 7be83539a..a62225f1b 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -31,6 +31,7 @@ #include "sim/host.hh" #include "mem/mem_req.hh" +#include "mem/functional_mem/functional_memory.hh" #include "sim/serialize.hh" // forward declaration: see functional_memory.hh @@ -114,6 +115,9 @@ class ExecContext // pointer to CPU associated with this context BaseCPU *cpu; + // Current instruction + MachInst inst; + // Index of hardware thread context on the CPU that this represents. int thread_num; @@ -311,6 +315,18 @@ class ExecContext virtual bool misspeculating(); + MachInst getInst() { return inst; } + + void setInst(MachInst new_inst) + { + inst = new_inst; + } + + Fault instRead(MemReqPtr &req) + { + return mem->read(req, inst); + } + // // New accessors for new decoder. // @@ -395,6 +411,14 @@ class ExecContext bool simPalCheck(int palFunc); #endif + /** Meant to be more generic trap function to be + * called when an instruction faults. + * @param fault The fault generated by executing the instruction. + * @todo How to do this properly so it's dependent upon ISA only? + */ + + void trap(Fault fault); + #ifndef FULL_SYSTEM IntReg getSyscallArg(int i) { diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 065140883..05b88b04b 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -708,8 +708,7 @@ SimpleCPU::tick() xc->regs.pc); #ifdef FULL_SYSTEM - xc->regs.opcode = (inst >> 26) & 0x3f; - xc->regs.ra = (inst >> 21) & 0x1f; + xc->setInst(inst); #endif // FULL_SYSTEM xc->func_exe_inst++; diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh index 57208f8e6..131c5f756 100644 --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@ -43,6 +43,8 @@ class ExecContext; class DynInst; typedef DynInst FullCPUExecContext; +class FastCPU; +typedef FastCPU FastCPUExecContext; class SimpleCPU; typedef SimpleCPU SimpleCPUExecContext; class SymbolTable; @@ -310,6 +312,12 @@ class StaticInst : public StaticInstBase virtual Fault execute(SimpleCPUExecContext *xc, Trace::InstRecord *traceData) = 0; + /** + * Execute this instruction under FastCPU model. + */ + virtual Fault execute(FastCPUExecContext *xc, + Trace::InstRecord *traceData) = 0; + /** * Execute this instruction under detailed FullCPU model. */ -- cgit v1.2.3