diff --git a/SConstruct b/SConstruct index 0cf15b1f9..c9ba13679 100644 --- a/SConstruct +++ b/SConstruct @@ -260,8 +260,8 @@ env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips'] # Define the universe of supported CPU models env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU', - 'FullCPU', 'AlphaFullCPU', - 'OzoneSimpleCPU', 'OzoneCPU', 'CheckerCPU'] + 'FullCPU', 'AlphaO3CPU', + 'OzoneSimpleCPU', 'OzoneCPU'] # Sticky options get saved in the options file so they persist from # one invocation to the next (unless overridden, in which case the new @@ -289,6 +289,7 @@ sticky_opts.AddOptions( False), BoolOption('USE_MYSQL', 'Use MySQL for stats output', have_mysql), BoolOption('USE_FENV', 'Use IEEE mode control', have_fenv), + BoolOption('USE_CHECKER', 'Use checker for detailed CPU models', False), ('CC', 'C compiler', os.environ.get('CC', env['CC'])), ('CXX', 'C++ compiler', os.environ.get('CXX', env['CXX'])), BoolOption('BATCH', 'Use batch pool for build and tests', False), @@ -303,7 +304,8 @@ nonsticky_opts.AddOptions( # These options get exported to #defines in config/*.hh (see m5/SConscript). env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \ - 'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP'] + 'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \ + 'USE_CHECKER'] # Define a handy 'no-op' action def no_action(target, source, env): @@ -470,6 +472,10 @@ for build_path in build_paths: env.ParseConfig(mysql_config_libs) env.ParseConfig(mysql_config_include) + # Check if the Checker is being used. If so append it to env['CPU_MODELS'] + if env['USE_CHECKER']: + env['CPU_MODELS'].append('CheckerCPU') + # Save sticky option settings back to current options file sticky_opts.Save(current_opts_file, env) diff --git a/configs/test/test.py b/configs/test/test.py index 251755e71..76791d9d7 100644 --- a/configs/test/test.py +++ b/configs/test/test.py @@ -14,6 +14,7 @@ parser = optparse.OptionParser(option_list=m5.standardOptions) parser.add_option("-c", "--cmd", default="hello") parser.add_option("-t", "--timing", action="store_true") parser.add_option("-f", "--full", action="store_true") +parser.add_option("-m", "--maxtick", type="int") (options, args) = parser.parse_args() @@ -34,7 +35,7 @@ mem = PhysicalMemory() if options.timing: cpu = TimingSimpleCPU() elif options.full: - cpu = DetailedCPU() + cpu = DetailedO3CPU() else: cpu = AtomicSimpleCPU() cpu.workload = process @@ -48,7 +49,10 @@ root = Root(system = system) m5.instantiate(root) # simulate until program terminates -exit_event = m5.simulate() +if options.maxtick: + exit_event = m5.simulate(options.maxtick) +else: + exit_event = m5.simulate() print 'Exiting @ cycle', m5.curTick(), 'because', exit_event.getCause() diff --git a/src/SConscript b/src/SConscript index e6ed43804..933158f5f 100644 --- a/src/SConscript +++ b/src/SConscript @@ -85,6 +85,7 @@ base_sources = Split(''' cpu/base.cc cpu/cpuevent.cc cpu/exetrace.cc + cpu/func_unit.cc cpu/op_class.cc cpu/pc_event.cc cpu/quiesce_event.cc @@ -93,8 +94,6 @@ base_sources = Split(''' cpu/simple_thread.cc cpu/thread_state.cc - encumbered/cpu/full/fu_pool.cc - mem/bridge.cc mem/bus.cc mem/mem_object.cc diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index d2908b27a..f449d2d69 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -47,9 +47,11 @@ decode OPCODE default Unknown::unknown() { 0x23: ldt({{ Fa = Mem.df; }}); 0x2a: ldl_l({{ Ra.sl = Mem.sl; }}, mem_flags = LOCKED); 0x2b: ldq_l({{ Ra.uq = Mem.uq; }}, mem_flags = LOCKED); +#ifdef USE_COPY 0x20: MiscPrefetch::copy_load({{ EA = Ra; }}, {{ fault = xc->copySrcTranslate(EA); }}, inst_flags = [IsMemRef, IsLoad, IsCopy]); +#endif } format LoadOrPrefetch { @@ -69,9 +71,11 @@ decode OPCODE default Unknown::unknown() { 0x0f: stq_u({{ Mem.uq = Ra.uq; }}, {{ EA = (Rb + disp) & ~7; }}); 0x26: sts({{ Mem.ul = t_to_s(Fa.uq); }}); 0x27: stt({{ Mem.df = Fa; }}); +#ifdef USE_COPY 0x24: MiscPrefetch::copy_store({{ EA = Rb; }}, {{ fault = xc->copy(EA); }}, inst_flags = [IsMemRef, IsStore, IsCopy]); +#endif } format StoreCond { diff --git a/src/base/traceflags.py b/src/base/traceflags.py index 7ff68bcaf..c4dcb695b 100644 --- a/src/base/traceflags.py +++ b/src/base/traceflags.py @@ -115,6 +115,7 @@ baseFlags = [ 'MSHR', 'Mbox', 'MemDepUnit', + 'O3CPU', 'OzoneCPU', 'FE', 'IBE', diff --git a/src/cpu/SConscript b/src/cpu/SConscript index 34bad132c..608625ed4 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -92,6 +92,10 @@ env.Command('static_inst_exec_sigs.hh', models_db, Action(gen_cpu_exec_signatures, gen_sigs_string, varlist = ['CPU_MODELS'])) +# List of suppported CPUs by the Checker. Errors out if USE_CHECKER=True +# and one of these are not being used. +CheckerSupportedCPUList = ['AlphaO3CPU', 'OzoneCPU'] + ################################################################# # # Include CPU-model-specific files based on set of models @@ -116,7 +120,7 @@ if need_simple_base: if 'FastCPU' in env['CPU_MODELS']: sources += Split('fast/cpu.cc') -if 'AlphaFullCPU' in env['CPU_MODELS']: +if 'AlphaO3CPU' in env['CPU_MODELS']: sources += Split(''' base_dyn_inst.cc o3/2bit_local_pred.cc @@ -144,6 +148,8 @@ if 'AlphaFullCPU' in env['CPU_MODELS']: o3/store_set.cc o3/tournament_pred.cc ''') + if 'CheckerCPU' in env['CPU_MODELS']: + sources += Split('checker/o3_builder.cc') if 'OzoneSimpleCPU' in env['CPU_MODELS']: sources += Split(''' @@ -155,6 +161,8 @@ if 'OzoneSimpleCPU' in env['CPU_MODELS']: ozone/inst_queue.cc ozone/rename_table.cc ''') + if 'CheckerCPU' in env['CPU_MODELS']: + sources += Split('checker/ozone_builder.cc') if 'OzoneCPU' in env['CPU_MODELS']: sources += Split(''' @@ -164,10 +172,17 @@ if 'OzoneCPU' in env['CPU_MODELS']: ''') if 'CheckerCPU' in env['CPU_MODELS']: - sources += Split(''' - checker/cpu.cc - checker/o3_cpu_builder.cc - ''') + sources += Split('checker/cpu.cc') + checker_supports = False + for i in CheckerSupportedCPUList: + if i in env['CPU_MODELS']: + checker_supports = True + if not checker_supports: + print "Checker only supports CPU models %s, please " \ + "set USE_CHECKER=False or use one of those CPU models" \ + % CheckerSupportedCPUList + Exit(1) + # FullCPU sources are included from m5/SConscript since they're not # below this point in the file hierarchy. diff --git a/src/cpu/base_dyn_inst.cc b/src/cpu/base_dyn_inst.cc index e3829297d..5e2a6392a 100644 --- a/src/cpu/base_dyn_inst.cc +++ b/src/cpu/base_dyn_inst.cc @@ -71,8 +71,8 @@ my_hash_t thishash; template BaseDynInst::BaseDynInst(ExtMachInst machInst, Addr inst_PC, Addr pred_PC, InstSeqNum seq_num, - FullCPU *cpu) - : staticInst(machInst), traceData(NULL), cpu(cpu)/*, xc(cpu->xcBase())*/ + ImplCPU *cpu) + : staticInst(machInst), traceData(NULL), cpu(cpu) { seqNum = seq_num; @@ -99,39 +99,18 @@ BaseDynInst::initVars() memData = NULL; effAddr = 0; physEffAddr = 0; - storeSize = 0; readyRegs = 0; instResult.integer = 0; - // May want to turn this into a bit vector or something. - completed = false; - resultReady = false; - canIssue = false; - issued = false; - executed = false; - canCommit = false; - committed = false; - squashed = false; - squashedInIQ = false; - squashedInLSQ = false; - squashedInROB = false; + status.reset(); + eaCalcDone = false; memOpDone = false; + lqIdx = -1; sqIdx = -1; - reachedCommit = false; - - blockingInst = false; - recoverInst = false; - - iqEntry = false; - robEntry = false; - - serializeBefore = false; - serializeAfter = false; - serializeHandled = false; // Eventually make this a parameter. threadNumber = 0; @@ -294,7 +273,7 @@ void BaseDynInst::markSrcRegReady() { if (++readyRegs == numSrcRegs()) { - canIssue = true; + status.set(CanIssue); } } @@ -302,13 +281,9 @@ template void BaseDynInst::markSrcRegReady(RegIndex src_idx) { - ++readyRegs; - _readySrcRegIdx[src_idx] = true; - if (readyRegs == numSrcRegs()) { - canIssue = true; - } + markSrcRegReady(); } template diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index fc9bf8b94..9cc61f74c 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -31,6 +31,7 @@ #ifndef __CPU_BASE_DYN_INST_HH__ #define __CPU_BASE_DYN_INST_HH__ +#include #include #include @@ -58,8 +59,8 @@ class BaseDynInst : public FastAlloc, public RefCounted { public: // Typedef for the CPU. - typedef typename Impl::FullCPU FullCPU; - typedef typename FullCPU::ImplState ImplState; + typedef typename Impl::CPUType ImplCPU; + typedef typename ImplCPU::ImplState ImplState; // Binary machine instruction type. typedef TheISA::MachInst MachInst; @@ -126,56 +127,34 @@ class BaseDynInst : public FastAlloc, public RefCounted /** The sequence number of the instruction. */ InstSeqNum seqNum; - /** Is the instruction in the IQ */ - bool iqEntry; + enum Status { + IqEntry, /// Instruction is in the IQ + RobEntry, /// Instruction is in the ROB + LsqEntry, /// Instruction is in the LSQ + Completed, /// Instruction has completed + ResultReady, /// Instruction has its result + CanIssue, /// Instruction can issue and execute + Issued, /// Instruction has issued + Executed, /// Instruction has executed + CanCommit, /// Instruction can commit + AtCommit, /// Instruction has reached commit + Committed, /// Instruction has committed + Squashed, /// Instruction is squashed + SquashedInIQ, /// Instruction is squashed in the IQ + SquashedInLSQ, /// Instruction is squashed in the LSQ + SquashedInROB, /// Instruction is squashed in the ROB + RecoverInst, /// Is a recover instruction + BlockingInst, /// Is a blocking instruction + ThreadsyncWait, /// Is a thread synchronization instruction + SerializeBefore, /// Needs to serialize on + /// instructions ahead of it + SerializeAfter, /// Needs to serialize instructions behind it + SerializeHandled, /// Serialization has been handled + NumStatus + }; - /** Is the instruction in the ROB */ - bool robEntry; - - /** Is the instruction in the LSQ */ - bool lsqEntry; - - /** Is the instruction completed. */ - bool completed; - - /** Is the instruction's result ready. */ - bool resultReady; - - /** Can this instruction issue. */ - bool canIssue; - - /** Has this instruction issued. */ - bool issued; - - /** Has this instruction executed (or made it through execute) yet. */ - bool executed; - - /** Can this instruction commit. */ - bool canCommit; - - /** Is this instruction committed. */ - bool committed; - - /** Is this instruction squashed. */ - bool squashed; - - /** Is this instruction squashed in the instruction queue. */ - bool squashedInIQ; - - /** Is this instruction squashed in the instruction queue. */ - bool squashedInLSQ; - - /** Is this instruction squashed in the instruction queue. */ - bool squashedInROB; - - /** Is this a recover instruction. */ - bool recoverInst; - - /** Is this a thread blocking instruction. */ - bool blockingInst; /* this inst has called thread_block() */ - - /** Is this a thread syncrhonization instruction. */ - bool threadsyncWait; + /** The status of this BaseDynInst. Several bits can be set. */ + std::bitset status; /** The thread this instruction is from. */ short threadNumber; @@ -186,8 +165,8 @@ class BaseDynInst : public FastAlloc, public RefCounted /** How many source registers are ready. */ unsigned readyRegs; - /** Pointer to the FullCPU object. */ - FullCPU *cpu; + /** Pointer to the Impl's CPU object. */ + ImplCPU *cpu; /** Pointer to the thread state. */ ImplState *thread; @@ -216,12 +195,6 @@ class BaseDynInst : public FastAlloc, public RefCounted /** The memory request flags (from translation). */ unsigned memReqFlags; - /** The size of the data to be stored. */ - int storeSize; - - /** The data to be stored. */ - IntReg storeData; - union Result { uint64_t integer; float fp; @@ -266,7 +239,7 @@ class BaseDynInst : public FastAlloc, public RefCounted * @param cpu Pointer to the instruction's CPU. */ BaseDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num, - FullCPU *cpu); + ImplCPU *cpu); /** BaseDynInst constructor given a StaticInst pointer. * @param _staticInst The StaticInst for this BaseDynInst. @@ -338,9 +311,9 @@ class BaseDynInst : public FastAlloc, public RefCounted bool isThreadSync() const { return staticInst->isThreadSync(); } bool isSerializing() const { return staticInst->isSerializing(); } bool isSerializeBefore() const - { return staticInst->isSerializeBefore() || serializeBefore; } + { return staticInst->isSerializeBefore() || status[SerializeBefore]; } bool isSerializeAfter() const - { return staticInst->isSerializeAfter() || serializeAfter; } + { return staticInst->isSerializeAfter() || status[SerializeAfter]; } bool isMemBarrier() const { return staticInst->isMemBarrier(); } bool isWriteBarrier() const { return staticInst->isWriteBarrier(); } bool isNonSpeculative() const { return staticInst->isNonSpeculative(); } @@ -349,41 +322,32 @@ class BaseDynInst : public FastAlloc, public RefCounted bool isUnverifiable() const { return staticInst->isUnverifiable(); } /** Temporarily sets this instruction as a serialize before instruction. */ - void setSerializeBefore() { serializeBefore = true; } + void setSerializeBefore() { status.set(SerializeBefore); } /** Clears the serializeBefore part of this instruction. */ - void clearSerializeBefore() { serializeBefore = false; } + void clearSerializeBefore() { status.reset(SerializeBefore); } /** Checks if this serializeBefore is only temporarily set. */ - bool isTempSerializeBefore() { return serializeBefore; } - - /** Tracks if instruction has been externally set as serializeBefore. */ - bool serializeBefore; + bool isTempSerializeBefore() { return status[SerializeBefore]; } /** Temporarily sets this instruction as a serialize after instruction. */ - void setSerializeAfter() { serializeAfter = true; } + void setSerializeAfter() { status.set(SerializeAfter); } /** Clears the serializeAfter part of this instruction.*/ - void clearSerializeAfter() { serializeAfter = false; } + void clearSerializeAfter() { status.reset(SerializeAfter); } /** Checks if this serializeAfter is only temporarily set. */ - bool isTempSerializeAfter() { return serializeAfter; } + bool isTempSerializeAfter() { return status[SerializeAfter]; } - /** Tracks if instruction has been externally set as serializeAfter. */ - bool serializeAfter; + /** Sets the serialization part of this instruction as handled. */ + void setSerializeHandled() { status.set(SerializeHandled); } /** Checks if the serialization part of this instruction has been * handled. This does not apply to the temporary serializing * state; it only applies to this instruction's own permanent * serializing state. */ - bool isSerializeHandled() { return serializeHandled; } - - /** Sets the serialization part of this instruction as handled. */ - void setSerializeHandled() { serializeHandled = true; } - - /** Whether or not the serialization of this instruction has been handled. */ - bool serializeHandled; + bool isSerializeHandled() { return status[SerializeHandled]; } /** Returns the opclass of this instruction. */ OpClass opClass() const { return staticInst->opClass(); } @@ -465,106 +429,112 @@ class BaseDynInst : public FastAlloc, public RefCounted } /** Sets this instruction as completed. */ - void setCompleted() { completed = true; } + void setCompleted() { status.set(Completed); } /** Returns whether or not this instruction is completed. */ - bool isCompleted() const { return completed; } + bool isCompleted() const { return status[Completed]; } - void setResultReady() { resultReady = true; } + /** Marks the result as ready. */ + void setResultReady() { status.set(ResultReady); } - bool isResultReady() const { return resultReady; } + /** Returns whether or not the result is ready. */ + bool isResultReady() const { return status[ResultReady]; } /** Sets this instruction as ready to issue. */ - void setCanIssue() { canIssue = true; } + void setCanIssue() { status.set(CanIssue); } /** Returns whether or not this instruction is ready to issue. */ - bool readyToIssue() const { return canIssue; } + bool readyToIssue() const { return status[CanIssue]; } /** Sets this instruction as issued from the IQ. */ - void setIssued() { issued = true; } + void setIssued() { status.set(Issued); } /** Returns whether or not this instruction has issued. */ - bool isIssued() const { return issued; } + bool isIssued() const { return status[Issued]; } /** Sets this instruction as executed. */ - void setExecuted() { executed = true; } + void setExecuted() { status.set(Executed); } /** Returns whether or not this instruction has executed. */ - bool isExecuted() const { return executed; } + bool isExecuted() const { return status[Executed]; } /** Sets this instruction as ready to commit. */ - void setCanCommit() { canCommit = true; } + void setCanCommit() { status.set(CanCommit); } /** Clears this instruction as being ready to commit. */ - void clearCanCommit() { canCommit = false; } + void clearCanCommit() { status.reset(CanCommit); } /** Returns whether or not this instruction is ready to commit. */ - bool readyToCommit() const { return canCommit; } + bool readyToCommit() const { return status[CanCommit]; } + + void setAtCommit() { status.set(AtCommit); } + + bool isAtCommit() { return status[AtCommit]; } /** Sets this instruction as committed. */ - void setCommitted() { committed = true; } + void setCommitted() { status.set(Committed); } /** Returns whether or not this instruction is committed. */ - bool isCommitted() const { return committed; } + bool isCommitted() const { return status[Committed]; } /** Sets this instruction as squashed. */ - void setSquashed() { squashed = true; } + void setSquashed() { status.set(Squashed); } /** Returns whether or not this instruction is squashed. */ - bool isSquashed() const { return squashed; } + bool isSquashed() const { return status[Squashed]; } //Instruction Queue Entry //----------------------- /** Sets this instruction as a entry the IQ. */ - void setInIQ() { iqEntry = true; } + void setInIQ() { status.set(IqEntry); } /** Sets this instruction as a entry the IQ. */ - void removeInIQ() { iqEntry = false; } - - /** Sets this instruction as squashed in the IQ. */ - void setSquashedInIQ() { squashedInIQ = true; squashed = true;} - - /** Returns whether or not this instruction is squashed in the IQ. */ - bool isSquashedInIQ() const { return squashedInIQ; } + void clearInIQ() { status.reset(IqEntry); } /** Returns whether or not this instruction has issued. */ - bool isInIQ() const { return iqEntry; } + bool isInIQ() const { return status[IqEntry]; } + + /** Sets this instruction as squashed in the IQ. */ + void setSquashedInIQ() { status.set(SquashedInIQ); status.set(Squashed);} + + /** Returns whether or not this instruction is squashed in the IQ. */ + bool isSquashedInIQ() const { return status[SquashedInIQ]; } //Load / Store Queue Functions //----------------------- /** Sets this instruction as a entry the LSQ. */ - void setInLSQ() { lsqEntry = true; } + void setInLSQ() { status.set(LsqEntry); } /** Sets this instruction as a entry the LSQ. */ - void removeInLSQ() { lsqEntry = false; } - - /** Sets this instruction as squashed in the LSQ. */ - void setSquashedInLSQ() { squashedInLSQ = true;} - - /** Returns whether or not this instruction is squashed in the LSQ. */ - bool isSquashedInLSQ() const { return squashedInLSQ; } + void removeInLSQ() { status.reset(LsqEntry); } /** Returns whether or not this instruction is in the LSQ. */ - bool isInLSQ() const { return lsqEntry; } + bool isInLSQ() const { return status[LsqEntry]; } + + /** Sets this instruction as squashed in the LSQ. */ + void setSquashedInLSQ() { status.set(SquashedInLSQ);} + + /** Returns whether or not this instruction is squashed in the LSQ. */ + bool isSquashedInLSQ() const { return status[SquashedInLSQ]; } //Reorder Buffer Functions //----------------------- /** Sets this instruction as a entry the ROB. */ - void setInROB() { robEntry = true; } + void setInROB() { status.set(RobEntry); } /** Sets this instruction as a entry the ROB. */ - void removeInROB() { robEntry = false; } - - /** Sets this instruction as squashed in the ROB. */ - void setSquashedInROB() { squashedInROB = true; } - - /** Returns whether or not this instruction is squashed in the ROB. */ - bool isSquashedInROB() const { return squashedInROB; } + void clearInROB() { status.reset(RobEntry); } /** Returns whether or not this instruction is in the ROB. */ - bool isInROB() const { return robEntry; } + bool isInROB() const { return status[RobEntry]; } + + /** Sets this instruction as squashed in the ROB. */ + void setSquashedInROB() { status.set(SquashedInROB); } + + /** Returns whether or not this instruction is squashed in the ROB. */ + bool isSquashedInROB() const { return status[SquashedInROB]; } /** Read the PC of this instruction. */ const Addr readPC() const { return PC; } @@ -581,10 +551,10 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Sets the thread id. */ void setTid(unsigned tid) { threadNumber = tid; } + /** Sets the pointer to the thread state. */ void setThreadState(ImplState *state) { thread = state; } - /** Returns the thread context. - */ + /** Returns the thread context. */ ThreadContext *tcBase() { return thread->getTC(); } private: @@ -621,8 +591,6 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Store queue index. */ int16_t sqIdx; - bool reachedCommit; - /** Iterator pointing to this BaseDynInst in the list of all insts. */ ListIt instListIt; diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index 6971ab37f..45c57d276 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -78,6 +78,7 @@ CheckerCPU::CheckerCPU(Params *p) changedPC = willChangePC = changedNextPC = false; exitOnError = p->exitOnError; + warnOnlyOnLoadError = p->warnOnlyOnLoadError; #if FULL_SYSTEM itb = p->itb; dtb = p->dtb; @@ -409,9 +410,17 @@ CheckerCPU::checkFlags(Request *req) } } +void +CheckerCPU::dumpAndExit() +{ + warn("%lli: Checker PC:%#x, next PC:%#x", + curTick, thread->readPC(), thread->readNextPC()); + panic("Checker found an error!"); +} + template void -Checker::tick(DynInstPtr &completed_inst) +Checker::verify(DynInstPtr &completed_inst) { DynInstPtr inst; @@ -485,7 +494,7 @@ Checker::tick(DynInstPtr &completed_inst) warn("%lli: Changed PC does not match expected PC, " "changed: %#x, expected: %#x", curTick, thread->readPC(), newPC); - handleError(); + CheckerCPU::handleError(); } willChangePC = false; } @@ -524,7 +533,7 @@ Checker::tick(DynInstPtr &completed_inst) // possible that its ITB entry was kicked out. warn("%lli: Instruction PC %#x was not found in the ITB!", curTick, thread->readPC()); - handleError(); + handleError(inst); // go to the next instruction thread->setPC(thread->readNextPC()); @@ -676,7 +685,7 @@ Checker::validateInst(DynInstPtr &inst) warn("%lli: Changed PCs recently, may not be an error", curTick); } else { - handleError(); + handleError(inst); } } @@ -686,7 +695,7 @@ Checker::validateInst(DynInstPtr &inst) warn("%lli: Binary instructions do not match! Inst: %#x, " "checker: %#x", curTick, mi, machInst); - handleError(); + handleError(inst); } } @@ -694,25 +703,33 @@ template void Checker::validateExecution(DynInstPtr &inst) { + bool result_mismatch = false; if (inst->numDestRegs()) { // @todo: Support more destination registers. if (inst->isUnverifiable()) { // Unverifiable instructions assume they were executed // properly by the CPU. Grab the result from the // instruction and write it to the register. - RegIndex idx = inst->destRegIdx(0); - if (idx < TheISA::FP_Base_DepTag) { - thread->setIntReg(idx, inst->readIntResult()); - } else if (idx < TheISA::Fpcr_DepTag) { - thread->setFloatRegBits(idx, inst->readIntResult()); - } else { - thread->setMiscReg(idx, inst->readIntResult()); - } + copyResult(inst); } else if (result.integer != inst->readIntResult()) { - warn("%lli: Instruction results do not match! (Values may not " - "actually be integers) Inst: %#x, checker: %#x", - curTick, inst->readIntResult(), result.integer); - handleError(); + result_mismatch = true; + } + } + + if (result_mismatch) { + warn("%lli: Instruction results do not match! (Values may not " + "actually be integers) Inst: %#x, checker: %#x", + curTick, inst->readIntResult(), result.integer); + + // It's useful to verify load values from memory, but in MP + // systems the value obtained at execute may be different than + // the value obtained at completion. Similarly DMA can + // present the same problem on even UP systems. Thus there is + // the option to only warn on loads having a result error. + if (inst->isLoad() && warnOnlyOnLoadError) { + copyResult(inst); + } else { + handleError(inst); } } @@ -720,7 +737,7 @@ Checker::validateExecution(DynInstPtr &inst) warn("%lli: Instruction next PCs do not match! Inst: %#x, " "checker: %#x", curTick, inst->readNextPC(), thread->readNextPC()); - handleError(); + handleError(inst); } // Checking side effect registers can be difficult if they are not @@ -739,7 +756,7 @@ Checker::validateExecution(DynInstPtr &inst) curTick, misc_reg_idx, inst->tcBase()->readMiscReg(misc_reg_idx), thread->readMiscReg(misc_reg_idx)); - handleError(); + handleError(inst); } } } @@ -750,6 +767,36 @@ Checker::validateState() { } +template +void +Checker::copyResult(DynInstPtr &inst) +{ + RegIndex idx = inst->destRegIdx(0); + if (idx < TheISA::FP_Base_DepTag) { + thread->setIntReg(idx, inst->readIntResult()); + } else if (idx < TheISA::Fpcr_DepTag) { + thread->setFloatRegBits(idx, inst->readIntResult()); + } else { + thread->setMiscReg(idx, inst->readIntResult()); + } +} + +template +void +Checker::dumpAndExit(DynInstPtr &inst) +{ + cprintf("Error detected, instruction information:\n"); + cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n" + "Completed:%i\n", + inst->readPC(), + inst->readNextPC(), + inst->seqNum, + inst->threadNumber, + inst->isCompleted()); + inst->dump(); + CheckerCPU::dumpAndExit(); +} + template void Checker::dumpInsts() @@ -782,6 +829,6 @@ Checker::dumpInsts() //template //class Checker > >; - +// Manually instantiate checker template class Checker > >; diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index c9986d228..785387e60 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -103,6 +103,7 @@ class CheckerCPU : public BaseCPU Process *process; #endif bool exitOnError; + bool warnOnlyOnLoadError; }; public: @@ -335,10 +336,13 @@ class CheckerCPU : public BaseCPU void handleError() { if (exitOnError) - panic("Checker found error!"); + dumpAndExit(); } + bool checkFlags(Request *req); + void dumpAndExit(); + ThreadContext *tcBase() { return tc; } SimpleThread *threadBase() { return thread; } @@ -351,6 +355,7 @@ class CheckerCPU : public BaseCPU uint64_t newPC; bool changedNextPC; bool exitOnError; + bool warnOnlyOnLoadError; InstSeqNum youngestSN; }; @@ -372,12 +377,23 @@ class Checker : public CheckerCPU void switchOut(Sampler *s); void takeOverFrom(BaseCPU *oldCPU); - void tick(DynInstPtr &inst); + void verify(DynInstPtr &inst); void validateInst(DynInstPtr &inst); void validateExecution(DynInstPtr &inst); void validateState(); + void copyResult(DynInstPtr &inst); + + private: + void handleError(DynInstPtr &inst) + { + if (exitOnError) + dumpAndExit(inst); + } + + void dumpAndExit(DynInstPtr &inst); + std::list instList; typedef typename std::list::iterator InstListIt; void dumpInsts(); diff --git a/src/cpu/checker/o3_cpu_builder.cc b/src/cpu/checker/o3_builder.cc similarity index 95% rename from src/cpu/checker/o3_cpu_builder.cc rename to src/cpu/checker/o3_builder.cc index 59a6c7158..534a5e28c 100644 --- a/src/cpu/checker/o3_cpu_builder.cc +++ b/src/cpu/checker/o3_builder.cc @@ -75,6 +75,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(O3Checker) Param defer_registration; Param exitOnError; + Param warnOnlyOnLoadError; Param function_trace; Param function_trace_start; @@ -105,6 +106,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(O3Checker) INIT_PARAM(defer_registration, "defer system registration (for sampling)"), INIT_PARAM(exitOnError, "exit on error"), + INIT_PARAM_DFLT(warnOnlyOnLoadError, "warn, but don't exit, if a load " + "result errors", false), INIT_PARAM(function_trace, "Enable function trace"), INIT_PARAM(function_trace_start, "Cycle to start function trace") @@ -121,6 +124,7 @@ CREATE_SIM_OBJECT(O3Checker) params->max_loads_any_thread = 0; params->max_loads_all_threads = 0; params->exitOnError = exitOnError; + params->warnOnlyOnLoadError = warnOnlyOnLoadError; params->deferRegistration = defer_registration; params->functionTrace = function_trace; params->functionTraceStart = function_trace_start; diff --git a/src/cpu/checker/cpu_builder.cc b/src/cpu/checker/ozone_builder.cc similarity index 96% rename from src/cpu/checker/cpu_builder.cc rename to src/cpu/checker/ozone_builder.cc index 3b7583294..3c43ab503 100644 --- a/src/cpu/checker/cpu_builder.cc +++ b/src/cpu/checker/ozone_builder.cc @@ -77,6 +77,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(OzoneChecker) Param defer_registration; Param exitOnError; + Param warnOnlyOnLoadError; Param function_trace; Param function_trace_start; @@ -110,6 +111,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(OzoneChecker) INIT_PARAM(defer_registration, "defer system registration (for sampling)"), INIT_PARAM(exitOnError, "exit on error"), + INIT_PARAM_DFLT(warnOnlyOnLoadError, "warn, but don't exit, if a load " + "result errors", false), INIT_PARAM(function_trace, "Enable function trace"), INIT_PARAM(function_trace_start, "Cycle to start function trace") @@ -126,6 +129,7 @@ CREATE_SIM_OBJECT(OzoneChecker) params->max_loads_any_thread = 0; params->max_loads_all_threads = 0; params->exitOnError = exitOnError; + params->warnOnlyOnLoadError = warnOnlyOnLoadError; params->deferRegistration = defer_registration; params->functionTrace = function_trace; params->functionTraceStart = function_trace_start; diff --git a/src/cpu/cpu_models.py b/src/cpu/cpu_models.py index 1a9724ca6..e7ef9ab42 100644 --- a/src/cpu/cpu_models.py +++ b/src/cpu/cpu_models.py @@ -67,7 +67,7 @@ CpuModel('TimingSimpleCPU', 'timing_simple_cpu_exec.cc', CpuModel('FullCPU', 'full_cpu_exec.cc', '#include "encumbered/cpu/full/dyn_inst.hh"', { 'CPU_exec_context': 'DynInst' }) -CpuModel('AlphaFullCPU', 'alpha_o3_exec.cc', +CpuModel('AlphaO3CPU', 'alpha_o3_exec.cc', '#include "cpu/o3/alpha_dyn_inst.hh"', { 'CPU_exec_context': 'AlphaDynInst' }) CpuModel('OzoneSimpleCPU', 'ozone_simple_exec.cc', diff --git a/src/cpu/cpuevent.hh b/src/cpu/cpuevent.hh index 11ac7aafb..9dfae27cf 100644 --- a/src/cpu/cpuevent.hh +++ b/src/cpu/cpuevent.hh @@ -36,7 +36,7 @@ class ThreadContext; -/** This class creates a global list of events than need a pointer to an +/** This class creates a global list of events that need a pointer to a * thread context. When a switchover takes place the events can be migrated * to the new thread context, otherwise you could have a wake timer interrupt * go off on a switched out cpu or other unfortunate events. This object MUST be diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh new file mode 100644 index 000000000..f6e8d7c25 --- /dev/null +++ b/src/cpu/exec_context.hh @@ -0,0 +1,161 @@ +/* + * 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: Kevin Lim + */ + +#error "Cannot include this file" + +/** + * The ExecContext is not a usable class. It is simply here for + * documentation purposes. It shows the interface that is used by the + * ISA to access and change CPU state. + */ +class ExecContext { + // 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 reduce 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). + + /** Reads an integer register. */ + uint64_t readIntReg(const StaticInst *si, int idx); + + /** Reads a floating point register of a specific width. */ + FloatReg readFloatReg(const StaticInst *si, int idx, int width); + + /** Reads a floating point register of single register width. */ + FloatReg readFloatReg(const StaticInst *si, int idx); + + /** Reads a floating point register of a specific width in its + * binary format, instead of by value. */ + FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width); + + /** Reads a floating point register in its binary format, instead + * of by value. */ + FloatRegBits readFloatRegBits(const StaticInst *si, int idx); + + /** Sets an integer register to a value. */ + void setIntReg(const StaticInst *si, int idx, uint64_t val); + + /** Sets a floating point register of a specific width to a value. */ + void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width); + + /** Sets a floating point register of single width to a value. */ + void setFloatReg(const StaticInst *si, int idx, FloatReg val); + + /** Sets the bits of a floating point register of a specific width + * to a binary value. */ + void setFloatRegBits(const StaticInst *si, int idx, + FloatRegBits val, int width); + + /** Sets the bits of a floating point register of single width + * to a binary value. */ + void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val); + + /** Reads the PC. */ + uint64_t readPC(); + /** Reads the NextPC. */ + uint64_t readNextPC(); + /** Reads the Next-NextPC. Only for architectures like SPARC or MIPS. */ + uint64_t readNextNPC(); + + /** Sets the PC. */ + void setPC(uint64_t val); + /** Sets the NextPC. */ + void setNextPC(uint64_t val); + /** Sets the Next-NextPC. Only for architectures like SPARC or MIPS. */ + void setNextNPC(uint64_t val); + + /** Reads a miscellaneous register. */ + MiscReg readMiscReg(int misc_reg); + + /** Reads a miscellaneous register, handling any architectural + * side effects due to reading that register. */ + MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault); + + /** Sets a miscellaneous register. */ + Fault setMiscReg(int misc_reg, const MiscReg &val); + + /** Sets a miscellaneous register, handling any architectural + * side effects due to writing that register. */ + Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val); + + /** Records the effective address of the instruction. Only valid + * for memory ops. */ + void setEA(Addr EA); + /** Returns the effective address of the instruction. Only valid + * for memory ops. */ + Addr getEA(); + + /** Returns a pointer to the ThreadContext. */ + ThreadContext *tcBase(); + + /** Reads an address, creating a memory request with the given + * flags. Stores result of read in data. */ + template + Fault read(Addr addr, T &data, unsigned flags); + + /** Writes to an address, creating a memory request with the given + * flags. Writes data to memory. For store conditionals, returns + * the result of the store in res. */ + template + Fault write(T data, Addr addr, unsigned flags, uint64_t *res); + + /** Prefetches an address, creating a memory request with the + * given flags. */ + void prefetch(Addr addr, unsigned flags); + + /** Hints to the memory system that an address will be written to + * soon, with the given size. Creates a memory request with the + * given flags. */ + void writeHint(Addr addr, int size, unsigned flags); + +#if FULL_SYSTEM + /** Somewhat Alpha-specific function that handles returning from + * an error or interrupt. */ + Fault hwrei(); + /** Reads the interrupt flags. */ + int readIntrFlag(); + /** Sets the interrupt flags to a value. */ + void setIntrFlag(int val); + + /** + * Check for special simulator handling of specific PAL calls. If + * return value is false, actual PAL call will be suppressed. + */ + bool simPalCheck(int palFunc); +#else + /** Executes a syscall specified by the callnum. */ + void syscall(int64_t callnum); +#endif +}; diff --git a/src/cpu/func_unit.cc b/src/cpu/func_unit.cc new file mode 100644 index 000000000..c20578a43 --- /dev/null +++ b/src/cpu/func_unit.cc @@ -0,0 +1,171 @@ +/* + * 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 + * 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: Steve Raasch + */ + +#include + +#include "base/misc.hh" +#include "cpu/func_unit.hh" +#include "sim/builder.hh" + +using namespace std; + + +//////////////////////////////////////////////////////////////////////////// +// +// The funciton unit +// +FuncUnit::FuncUnit() +{ + capabilityList.reset(); +} + + +// Copy constructor +FuncUnit::FuncUnit(const FuncUnit &fu) +{ + + for (int i = 0; i < Num_OpClasses; ++i) { + opLatencies[i] = fu.opLatencies[i]; + issueLatencies[i] = fu.issueLatencies[i]; + } + + capabilityList = fu.capabilityList; +} + + +void +FuncUnit::addCapability(OpClass cap, unsigned oplat, unsigned issuelat) +{ + if (issuelat == 0 || oplat == 0) + panic("FuncUnit: you don't really want a zero-cycle latency do you?"); + + capabilityList.set(cap); + + opLatencies[cap] = oplat; + issueLatencies[cap] = issuelat; +} + +bool +FuncUnit::provides(OpClass capability) +{ + return capabilityList[capability]; +} + +bitset +FuncUnit::capabilities() +{ + return capabilityList; +} + +unsigned & +FuncUnit::opLatency(OpClass cap) +{ + return opLatencies[cap]; +} + +unsigned +FuncUnit::issueLatency(OpClass capability) +{ + return issueLatencies[capability]; +} + +//////////////////////////////////////////////////////////////////////////// +// +// The SimObjects we use to get the FU information into the simulator +// +//////////////////////////////////////////////////////////////////////////// + +// +// We use 2 objects to specify this data in the INI file: +// (1) OpDesc - Describes the operation class & latencies +// (multiple OpDesc objects can refer to the same +// operation classes) +// (2) FUDesc - Describes the operations available in the unit & +// the number of these units +// +// + + +// +// The operation-class description object +// + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(OpDesc) + + SimpleEnumParam opClass; + Param opLat; + Param issueLat; + +END_DECLARE_SIM_OBJECT_PARAMS(OpDesc) + +BEGIN_INIT_SIM_OBJECT_PARAMS(OpDesc) + + INIT_ENUM_PARAM(opClass, "type of operation", opClassStrings), + INIT_PARAM(opLat, "cycles until result is available"), + INIT_PARAM(issueLat, "cycles until another can be issued") + +END_INIT_SIM_OBJECT_PARAMS(OpDesc) + + +CREATE_SIM_OBJECT(OpDesc) +{ + return new OpDesc(getInstanceName(), opClass, opLat, issueLat); +} + +REGISTER_SIM_OBJECT("OpDesc", OpDesc) + + +// +// The FuDesc object +// + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(FUDesc) + + SimObjectVectorParam opList; + Param count; + +END_DECLARE_SIM_OBJECT_PARAMS(FUDesc) + + +BEGIN_INIT_SIM_OBJECT_PARAMS(FUDesc) + + INIT_PARAM(opList, "list of operation classes for this FU type"), + INIT_PARAM(count, "number of these FU's available") + +END_INIT_SIM_OBJECT_PARAMS(FUDesc) + + +CREATE_SIM_OBJECT(FUDesc) +{ + return new FUDesc(getInstanceName(), opList, count); +} + +REGISTER_SIM_OBJECT("FUDesc", FUDesc) + diff --git a/src/cpu/func_unit.hh b/src/cpu/func_unit.hh new file mode 100644 index 000000000..780143096 --- /dev/null +++ b/src/cpu/func_unit.hh @@ -0,0 +1,101 @@ +/* + * 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 + * 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: Steve Raasch + */ + +#ifndef __CPU_FUNC_UNIT_HH__ +#define __CPU_FUNC_UNIT_HH__ + +#include +#include +#include + +#include "cpu/op_class.hh" +#include "sim/sim_object.hh" + +//////////////////////////////////////////////////////////////////////////// +// +// Structures used ONLY during the initialization phase... +// +// +// + +struct OpDesc : public SimObject +{ + OpClass opClass; + unsigned opLat; + unsigned issueLat; + + OpDesc(std::string name, OpClass c, unsigned o, unsigned i) + : SimObject(name), opClass(c), opLat(o), issueLat(i) {}; +}; + +struct FUDesc : public SimObject +{ + std::vector opDescList; + unsigned number; + + FUDesc(std::string name, std::vector l, unsigned n) + : SimObject(name), opDescList(l), number(n) {}; +}; + +typedef std::vector::iterator OPDDiterator; +typedef std::vector::iterator FUDDiterator; + + + + +//////////////////////////////////////////////////////////////////////////// +// +// The actual FU object +// +// +// +class FuncUnit +{ + private: + unsigned opLatencies[Num_OpClasses]; + unsigned issueLatencies[Num_OpClasses]; + std::bitset capabilityList; + + public: + FuncUnit(); + FuncUnit(const FuncUnit &fu); + + std::string name; + + void addCapability(OpClass cap, unsigned oplat, unsigned issuelat); + + bool provides(OpClass capability); + std::bitset capabilities(); + + unsigned &opLatency(OpClass capability); + unsigned issueLatency(OpClass capability); +}; + +#endif // __FU_POOL_HH__ diff --git a/src/cpu/o3/alpha_cpu.cc b/src/cpu/o3/alpha_cpu.cc index 39cae696b..e44ed0031 100644 --- a/src/cpu/o3/alpha_cpu.cc +++ b/src/cpu/o3/alpha_cpu.cc @@ -32,7 +32,7 @@ #include "cpu/o3/alpha_cpu_impl.hh" #include "cpu/o3/alpha_dyn_inst.hh" -// Force instantiation of AlphaFullCPU for all the implemntations that are +// Force instantiation of AlphaO3CPU for all the implemntations that are // needed. Consider merging this and alpha_dyn_inst.cc, and maybe all // classes that depend on a certain impl, into one file (alpha_impl.cc?). -template class AlphaFullCPU; +template class AlphaO3CPU; diff --git a/src/cpu/o3/alpha_cpu.hh b/src/cpu/o3/alpha_cpu.hh index f81837f3c..4daa8b3ba 100644 --- a/src/cpu/o3/alpha_cpu.hh +++ b/src/cpu/o3/alpha_cpu.hh @@ -44,7 +44,7 @@ namespace Kernel { class TranslatingPort; /** - * AlphaFullCPU class. Derives from the FullO3CPU class, and + * AlphaO3CPU class. Derives from the FullO3CPU class, and * implements all ISA and implementation specific functions of the * CPU. This is the CPU class that is used for the SimObjects, and is * what is given to the DynInsts. Most of its state exists in the @@ -52,7 +52,7 @@ class TranslatingPort; * functionality. */ template -class AlphaFullCPU : public FullO3CPU +class AlphaO3CPU : public FullO3CPU { protected: typedef TheISA::IntReg IntReg; @@ -67,17 +67,17 @@ class AlphaFullCPU : public FullO3CPU typedef O3ThreadState Thread; typedef typename Impl::Params Params; - /** Constructs an AlphaFullCPU with the given parameters. */ - AlphaFullCPU(Params *params); + /** Constructs an AlphaO3CPU with the given parameters. */ + AlphaO3CPU(Params *params); /** - * Derived ThreadContext class for use with the AlphaFullCPU. It + * Derived ThreadContext class for use with the AlphaO3CPU. It * provides the interface for any external objects to access a * single thread's state and some general CPU state. Any time * external objects try to update state through this interface, * the CPU will create an event to squash all in-flight * instructions in order to ensure state is maintained correctly. - * It must be defined specifically for the AlphaFullCPU because + * It must be defined specifically for the AlphaO3CPU because * not all architectural state is located within the O3ThreadState * (such as the commit PC, and registers), and specific actions * must be taken when using this interface (such as squashing all @@ -87,7 +87,7 @@ class AlphaFullCPU : public FullO3CPU { public: /** Pointer to the CPU. */ - AlphaFullCPU *cpu; + AlphaO3CPU *cpu; /** Pointer to the thread state that this TC corrseponds to. */ O3ThreadState *thread; diff --git a/src/cpu/o3/alpha_cpu_builder.cc b/src/cpu/o3/alpha_cpu_builder.cc index a6fbe34d7..b1e141ff4 100644 --- a/src/cpu/o3/alpha_cpu_builder.cc +++ b/src/cpu/o3/alpha_cpu_builder.cc @@ -37,15 +37,15 @@ #include "cpu/o3/fu_pool.hh" #include "sim/builder.hh" -class DerivAlphaFullCPU : public AlphaFullCPU +class DerivAlphaO3CPU : public AlphaO3CPU { public: - DerivAlphaFullCPU(AlphaSimpleParams *p) - : AlphaFullCPU(p) + DerivAlphaO3CPU(AlphaSimpleParams *p) + : AlphaO3CPU(p) { } }; -BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU) +BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaO3CPU) Param clock; Param numThreads; @@ -144,9 +144,9 @@ Param defer_registration; Param function_trace; Param function_trace_start; -END_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU) +END_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaO3CPU) -BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU) +BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaO3CPU) INIT_PARAM(clock, "clock speed"), INIT_PARAM(numThreads, "number of HW thread contexts"), @@ -261,11 +261,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU) INIT_PARAM(function_trace, "Enable function trace"), INIT_PARAM(function_trace_start, "Cycle to start function trace") -END_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU) +END_INIT_SIM_OBJECT_PARAMS(DerivAlphaO3CPU) -CREATE_SIM_OBJECT(DerivAlphaFullCPU) +CREATE_SIM_OBJECT(DerivAlphaO3CPU) { - DerivAlphaFullCPU *cpu; + DerivAlphaO3CPU *cpu; #if FULL_SYSTEM // Full-system only supports a single thread for the moment. @@ -386,10 +386,10 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU) params->functionTrace = function_trace; params->functionTraceStart = function_trace_start; - cpu = new DerivAlphaFullCPU(params); + cpu = new DerivAlphaO3CPU(params); return cpu; } -REGISTER_SIM_OBJECT("DerivAlphaFullCPU", DerivAlphaFullCPU) +REGISTER_SIM_OBJECT("DerivAlphaO3CPU", DerivAlphaO3CPU) diff --git a/src/cpu/o3/alpha_cpu_impl.hh b/src/cpu/o3/alpha_cpu_impl.hh index bfd05d260..532611fb6 100644 --- a/src/cpu/o3/alpha_cpu_impl.hh +++ b/src/cpu/o3/alpha_cpu_impl.hh @@ -28,6 +28,8 @@ * Authors: Kevin Lim */ +#include "config/use_checker.hh" + #include "arch/alpha/faults.hh" #include "base/cprintf.hh" #include "base/statistics.hh" @@ -53,14 +55,14 @@ using namespace TheISA; template -AlphaFullCPU::AlphaFullCPU(Params *params) +AlphaO3CPU::AlphaO3CPU(Params *params) #if FULL_SYSTEM : FullO3CPU(params), itb(params->itb), dtb(params->dtb) #else : FullO3CPU(params) #endif { - DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n"); + DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n"); // Setup any thread state. this->thread.resize(this->numThreads); @@ -73,7 +75,7 @@ AlphaFullCPU::AlphaFullCPU(Params *params) this->thread[i]->setStatus(ThreadContext::Suspended); #else if (i < params->workload.size()) { - DPRINTF(FullCPU, "FullCPU: Workload[%i] process is %#x", + DPRINTF(O3CPU, "Workload[%i] process is %#x", i, this->thread[i]); this->thread[i] = new Thread(this, i, params->workload[i], i, params->mem); @@ -110,14 +112,16 @@ AlphaFullCPU::AlphaFullCPU(Params *params) // Setup the TC that will serve as the interface to the threads/CPU. AlphaTC *alpha_tc = new AlphaTC; + tc = alpha_tc; + // If we're using a checker, then the TC should be the // CheckerThreadContext. +#if USE_CHECKER if (params->checker) { tc = new CheckerThreadContext( alpha_tc, this->checker); - } else { - tc = alpha_tc; } +#endif alpha_tc->cpu = this; alpha_tc->thread = this->thread[i]; @@ -172,7 +176,7 @@ AlphaFullCPU::AlphaFullCPU(Params *params) template void -AlphaFullCPU::regStats() +AlphaO3CPU::regStats() { // Register stats for everything that has stats. this->fullCPURegStats(); @@ -186,7 +190,7 @@ AlphaFullCPU::regStats() #if FULL_SYSTEM template VirtualPort * -AlphaFullCPU::AlphaTC::getVirtPort(ThreadContext *src_tc) +AlphaO3CPU::AlphaTC::getVirtPort(ThreadContext *src_tc) { if (!src_tc) return thread->getVirtPort(); @@ -203,7 +207,7 @@ AlphaFullCPU::AlphaTC::getVirtPort(ThreadContext *src_tc) template void -AlphaFullCPU::AlphaTC::dumpFuncProfile() +AlphaO3CPU::AlphaTC::dumpFuncProfile() { // Currently not supported } @@ -211,7 +215,7 @@ AlphaFullCPU::AlphaTC::dumpFuncProfile() template void -AlphaFullCPU::AlphaTC::takeOverFrom(ThreadContext *old_context) +AlphaO3CPU::AlphaTC::takeOverFrom(ThreadContext *old_context) { // some things should already be set up #if FULL_SYSTEM @@ -253,7 +257,7 @@ AlphaFullCPU::AlphaTC::takeOverFrom(ThreadContext *old_context) #if FULL_SYSTEM template void -AlphaFullCPU::AlphaTC::delVirtPort(VirtualPort *vp) +AlphaO3CPU::AlphaTC::delVirtPort(VirtualPort *vp) { delete vp->getPeer(); delete vp; @@ -262,9 +266,9 @@ AlphaFullCPU::AlphaTC::delVirtPort(VirtualPort *vp) template void -AlphaFullCPU::AlphaTC::activate(int delay) +AlphaO3CPU::AlphaTC::activate(int delay) { - DPRINTF(FullCPU, "Calling activate on AlphaTC\n"); + DPRINTF(O3CPU, "Calling activate on AlphaTC\n"); if (thread->status() == ThreadContext::Active) return; @@ -286,9 +290,9 @@ AlphaFullCPU::AlphaTC::activate(int delay) template void -AlphaFullCPU::AlphaTC::suspend() +AlphaO3CPU::AlphaTC::suspend() { - DPRINTF(FullCPU, "Calling suspend on AlphaTC\n"); + DPRINTF(O3CPU, "Calling suspend on AlphaTC\n"); if (thread->status() == ThreadContext::Suspended) return; @@ -312,9 +316,9 @@ AlphaFullCPU::AlphaTC::suspend() template void -AlphaFullCPU::AlphaTC::deallocate() +AlphaO3CPU::AlphaTC::deallocate() { - DPRINTF(FullCPU, "Calling deallocate on AlphaTC\n"); + DPRINTF(O3CPU, "Calling deallocate on AlphaTC\n"); if (thread->status() == ThreadContext::Unallocated) return; @@ -325,9 +329,9 @@ AlphaFullCPU::AlphaTC::deallocate() template void -AlphaFullCPU::AlphaTC::halt() +AlphaO3CPU::AlphaTC::halt() { - DPRINTF(FullCPU, "Calling halt on AlphaTC\n"); + DPRINTF(O3CPU, "Calling halt on AlphaTC\n"); if (thread->status() == ThreadContext::Halted) return; @@ -338,7 +342,7 @@ AlphaFullCPU::AlphaTC::halt() template void -AlphaFullCPU::AlphaTC::regStats(const std::string &name) +AlphaO3CPU::AlphaTC::regStats(const std::string &name) { #if FULL_SYSTEM thread->kernelStats = new Kernel::Statistics(cpu->system); @@ -348,7 +352,7 @@ AlphaFullCPU::AlphaTC::regStats(const std::string &name) template void -AlphaFullCPU::AlphaTC::serialize(std::ostream &os) +AlphaO3CPU::AlphaTC::serialize(std::ostream &os) { #if FULL_SYSTEM if (thread->kernelStats) @@ -359,7 +363,7 @@ AlphaFullCPU::AlphaTC::serialize(std::ostream &os) template void -AlphaFullCPU::AlphaTC::unserialize(Checkpoint *cp, const std::string §ion) +AlphaO3CPU::AlphaTC::unserialize(Checkpoint *cp, const std::string §ion) { #if FULL_SYSTEM if (thread->kernelStats) @@ -371,46 +375,46 @@ AlphaFullCPU::AlphaTC::unserialize(Checkpoint *cp, const std::string § #if FULL_SYSTEM template EndQuiesceEvent * -AlphaFullCPU::AlphaTC::getQuiesceEvent() +AlphaO3CPU::AlphaTC::getQuiesceEvent() { return thread->quiesceEvent; } template Tick -AlphaFullCPU::AlphaTC::readLastActivate() +AlphaO3CPU::AlphaTC::readLastActivate() { return thread->lastActivate; } template Tick -AlphaFullCPU::AlphaTC::readLastSuspend() +AlphaO3CPU::AlphaTC::readLastSuspend() { return thread->lastSuspend; } template void -AlphaFullCPU::AlphaTC::profileClear() +AlphaO3CPU::AlphaTC::profileClear() {} template void -AlphaFullCPU::AlphaTC::profileSample() +AlphaO3CPU::AlphaTC::profileSample() {} #endif template TheISA::MachInst -AlphaFullCPU::AlphaTC:: getInst() +AlphaO3CPU::AlphaTC:: getInst() { return thread->getInst(); } template void -AlphaFullCPU::AlphaTC::copyArchRegs(ThreadContext *tc) +AlphaO3CPU::AlphaTC::copyArchRegs(ThreadContext *tc) { // This function will mess things up unless the ROB is empty and // there are no instructions in the pipeline. @@ -421,7 +425,7 @@ AlphaFullCPU::AlphaTC::copyArchRegs(ThreadContext *tc) for (int i = 0; i < AlphaISA::NumIntRegs; ++i) { renamed_reg = cpu->renameMap[tid].lookup(i); - DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, " + DPRINTF(O3CPU, "Copying over register %i, had data %lli, " "now has data %lli.\n", renamed_reg, cpu->readIntReg(renamed_reg), tc->readIntReg(i)); @@ -449,19 +453,19 @@ AlphaFullCPU::AlphaTC::copyArchRegs(ThreadContext *tc) template void -AlphaFullCPU::AlphaTC::clearArchRegs() +AlphaO3CPU::AlphaTC::clearArchRegs() {} template uint64_t -AlphaFullCPU::AlphaTC::readIntReg(int reg_idx) +AlphaO3CPU::AlphaTC::readIntReg(int reg_idx) { return cpu->readArchIntReg(reg_idx, thread->readTid()); } template FloatReg -AlphaFullCPU::AlphaTC::readFloatReg(int reg_idx, int width) +AlphaO3CPU::AlphaTC::readFloatReg(int reg_idx, int width) { switch(width) { case 32: @@ -476,14 +480,14 @@ AlphaFullCPU::AlphaTC::readFloatReg(int reg_idx, int width) template FloatReg -AlphaFullCPU::AlphaTC::readFloatReg(int reg_idx) +AlphaO3CPU::AlphaTC::readFloatReg(int reg_idx) { return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); } template FloatRegBits -AlphaFullCPU::AlphaTC::readFloatRegBits(int reg_idx, int width) +AlphaO3CPU::AlphaTC::readFloatRegBits(int reg_idx, int width) { DPRINTF(Fault, "Reading floatint register through the TC!\n"); return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); @@ -491,14 +495,14 @@ AlphaFullCPU::AlphaTC::readFloatRegBits(int reg_idx, int width) template FloatRegBits -AlphaFullCPU::AlphaTC::readFloatRegBits(int reg_idx) +AlphaO3CPU::AlphaTC::readFloatRegBits(int reg_idx) { return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); } template void -AlphaFullCPU::AlphaTC::setIntReg(int reg_idx, uint64_t val) +AlphaO3CPU::AlphaTC::setIntReg(int reg_idx, uint64_t val) { cpu->setArchIntReg(reg_idx, val, thread->readTid()); @@ -510,7 +514,7 @@ AlphaFullCPU::AlphaTC::setIntReg(int reg_idx, uint64_t val) template void -AlphaFullCPU::AlphaTC::setFloatReg(int reg_idx, FloatReg val, int width) +AlphaO3CPU::AlphaTC::setFloatReg(int reg_idx, FloatReg val, int width) { switch(width) { case 32: @@ -529,7 +533,7 @@ AlphaFullCPU::AlphaTC::setFloatReg(int reg_idx, FloatReg val, int width) template void -AlphaFullCPU::AlphaTC::setFloatReg(int reg_idx, FloatReg val) +AlphaO3CPU::AlphaTC::setFloatReg(int reg_idx, FloatReg val) { cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); @@ -540,7 +544,7 @@ AlphaFullCPU::AlphaTC::setFloatReg(int reg_idx, FloatReg val) template void -AlphaFullCPU::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val, +AlphaO3CPU::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val, int width) { DPRINTF(Fault, "Setting floatint register through the TC!\n"); @@ -554,7 +558,7 @@ AlphaFullCPU::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val, template void -AlphaFullCPU::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val) +AlphaO3CPU::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val) { cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); @@ -566,7 +570,7 @@ AlphaFullCPU::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val) template void -AlphaFullCPU::AlphaTC::setPC(uint64_t val) +AlphaO3CPU::AlphaTC::setPC(uint64_t val) { cpu->setPC(val, thread->readTid()); @@ -578,7 +582,7 @@ AlphaFullCPU::AlphaTC::setPC(uint64_t val) template void -AlphaFullCPU::AlphaTC::setNextPC(uint64_t val) +AlphaO3CPU::AlphaTC::setNextPC(uint64_t val) { cpu->setNextPC(val, thread->readTid()); @@ -590,7 +594,7 @@ AlphaFullCPU::AlphaTC::setNextPC(uint64_t val) template Fault -AlphaFullCPU::AlphaTC::setMiscReg(int misc_reg, const MiscReg &val) +AlphaO3CPU::AlphaTC::setMiscReg(int misc_reg, const MiscReg &val) { Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->readTid()); @@ -604,8 +608,8 @@ AlphaFullCPU::AlphaTC::setMiscReg(int misc_reg, const MiscReg &val) template Fault -AlphaFullCPU::AlphaTC::setMiscRegWithEffect(int misc_reg, - const MiscReg &val) +AlphaO3CPU::AlphaTC::setMiscRegWithEffect(int misc_reg, + const MiscReg &val) { Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, thread->readTid()); @@ -622,21 +626,21 @@ AlphaFullCPU::AlphaTC::setMiscRegWithEffect(int misc_reg, template TheISA::IntReg -AlphaFullCPU::AlphaTC::getSyscallArg(int i) +AlphaO3CPU::AlphaTC::getSyscallArg(int i) { return cpu->getSyscallArg(i, thread->readTid()); } template void -AlphaFullCPU::AlphaTC::setSyscallArg(int i, IntReg val) +AlphaO3CPU::AlphaTC::setSyscallArg(int i, IntReg val) { cpu->setSyscallArg(i, val, thread->readTid()); } template void -AlphaFullCPU::AlphaTC::setSyscallReturn(SyscallReturn return_value) +AlphaO3CPU::AlphaTC::setSyscallReturn(SyscallReturn return_value) { cpu->setSyscallReturn(return_value, thread->readTid()); } @@ -645,37 +649,37 @@ AlphaFullCPU::AlphaTC::setSyscallReturn(SyscallReturn return_value) template MiscReg -AlphaFullCPU::readMiscReg(int misc_reg, unsigned tid) +AlphaO3CPU::readMiscReg(int misc_reg, unsigned tid) { return this->regFile.readMiscReg(misc_reg, tid); } template MiscReg -AlphaFullCPU::readMiscRegWithEffect(int misc_reg, Fault &fault, - unsigned tid) +AlphaO3CPU::readMiscRegWithEffect(int misc_reg, Fault &fault, + unsigned tid) { return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid); } template Fault -AlphaFullCPU::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +AlphaO3CPU::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) { return this->regFile.setMiscReg(misc_reg, val, tid); } template Fault -AlphaFullCPU::setMiscRegWithEffect(int misc_reg, const MiscReg &val, - unsigned tid) +AlphaO3CPU::setMiscRegWithEffect(int misc_reg, const MiscReg &val, + unsigned tid) { return this->regFile.setMiscRegWithEffect(misc_reg, val, tid); } template void -AlphaFullCPU::squashFromTC(unsigned tid) +AlphaO3CPU::squashFromTC(unsigned tid) { this->thread[tid]->inSyscall = true; this->commit.generateTCEvent(tid); @@ -685,7 +689,7 @@ AlphaFullCPU::squashFromTC(unsigned tid) template void -AlphaFullCPU::post_interrupt(int int_num, int index) +AlphaO3CPU::post_interrupt(int int_num, int index) { BaseCPU::post_interrupt(int_num, index); @@ -697,21 +701,21 @@ AlphaFullCPU::post_interrupt(int int_num, int index) template int -AlphaFullCPU::readIntrFlag() +AlphaO3CPU::readIntrFlag() { return this->regFile.readIntrFlag(); } template void -AlphaFullCPU::setIntrFlag(int val) +AlphaO3CPU::setIntrFlag(int val) { this->regFile.setIntrFlag(val); } template Fault -AlphaFullCPU::hwrei(unsigned tid) +AlphaO3CPU::hwrei(unsigned tid) { // Need to clear the lock flag upon returning from an interrupt. this->lockFlag = false; @@ -726,7 +730,7 @@ AlphaFullCPU::hwrei(unsigned tid) template bool -AlphaFullCPU::simPalCheck(int palFunc, unsigned tid) +AlphaO3CPU::simPalCheck(int palFunc, unsigned tid) { if (this->thread[tid]->kernelStats) this->thread[tid]->kernelStats->callpal(palFunc, @@ -751,7 +755,7 @@ AlphaFullCPU::simPalCheck(int palFunc, unsigned tid) template void -AlphaFullCPU::trap(Fault fault, unsigned tid) +AlphaO3CPU::trap(Fault fault, unsigned tid) { // Pass the thread's TC into the invoke method. fault->invoke(this->threadContexts[tid]); @@ -759,7 +763,7 @@ AlphaFullCPU::trap(Fault fault, unsigned tid) template void -AlphaFullCPU::processInterrupts() +AlphaO3CPU::processInterrupts() { // Check for interrupts here. For now can copy the code that // exists within isa_fullsys_traits.hh. Also assume that thread 0 @@ -805,10 +809,12 @@ AlphaFullCPU::processInterrupts() this->setMiscReg(IPR_ISR, summary, 0); this->setMiscReg(IPR_INTID, ipl, 0); // Checker needs to know these two registers were updated. +#if USE_CHECKER if (this->checker) { this->checker->threadBase()->setMiscReg(IPR_ISR, summary); this->checker->threadBase()->setMiscReg(IPR_INTID, ipl); } +#endif this->trap(Fault(new InterruptFault), 0); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", this->readMiscReg(IPR_IPLR, 0), ipl, summary); @@ -821,9 +827,9 @@ AlphaFullCPU::processInterrupts() template void -AlphaFullCPU::syscall(int64_t callnum, int tid) +AlphaO3CPU::syscall(int64_t callnum, int tid) { - DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid); + DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid); DPRINTF(Activity,"Activity: syscall() called.\n"); @@ -841,21 +847,21 @@ AlphaFullCPU::syscall(int64_t callnum, int tid) template TheISA::IntReg -AlphaFullCPU::getSyscallArg(int i, int tid) +AlphaO3CPU::getSyscallArg(int i, int tid) { return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid); } template void -AlphaFullCPU::setSyscallArg(int i, IntReg val, int tid) +AlphaO3CPU::setSyscallArg(int i, IntReg val, int tid) { this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid); } template void -AlphaFullCPU::setSyscallReturn(SyscallReturn return_value, int tid) +AlphaO3CPU::setSyscallReturn(SyscallReturn return_value, int tid) { // check for error condition. Alpha syscall convention is to // indicate success/failure in reg a3 (r19) and put the diff --git a/src/cpu/o3/alpha_dyn_inst.hh b/src/cpu/o3/alpha_dyn_inst.hh index 36a08c4a7..464e53e9d 100644 --- a/src/cpu/o3/alpha_dyn_inst.hh +++ b/src/cpu/o3/alpha_dyn_inst.hh @@ -51,7 +51,7 @@ class AlphaDynInst : public BaseDynInst { public: /** Typedef for the CPU. */ - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; /** Binary machine instruction type. */ typedef TheISA::MachInst MachInst; @@ -74,7 +74,7 @@ class AlphaDynInst : public BaseDynInst public: /** BaseDynInst constructor given a binary instruction. */ AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num, - FullCPU *cpu); + O3CPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ AlphaDynInst(StaticInstPtr &_staticInst); diff --git a/src/cpu/o3/alpha_dyn_inst_impl.hh b/src/cpu/o3/alpha_dyn_inst_impl.hh index a73cf4a7d..6183a755e 100644 --- a/src/cpu/o3/alpha_dyn_inst_impl.hh +++ b/src/cpu/o3/alpha_dyn_inst_impl.hh @@ -32,7 +32,7 @@ template AlphaDynInst::AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, - InstSeqNum seq_num, FullCPU *cpu) + InstSeqNum seq_num, O3CPU *cpu) : BaseDynInst(inst, PC, Pred_PC, seq_num, cpu) { initVars(); diff --git a/src/cpu/o3/alpha_impl.hh b/src/cpu/o3/alpha_impl.hh index 52f7c2394..84c9e1c00 100644 --- a/src/cpu/o3/alpha_impl.hh +++ b/src/cpu/o3/alpha_impl.hh @@ -41,12 +41,12 @@ template class AlphaDynInst; template -class AlphaFullCPU; +class AlphaO3CPU; /** Implementation specific struct that defines several key types to the * CPU, the stages within the CPU, the time buffers, and the DynInst. * The struct defines the ISA, the CPU policy, the specific DynInst, the - * specific FullCPU, and all of the structs from the time buffers to do + * specific O3CPU, and all of the structs from the time buffers to do * communication. * This is one of the key things that must be defined for each hardware * specific CPU implementation. @@ -67,8 +67,14 @@ struct AlphaSimpleImpl */ typedef RefCountingPtr DynInstPtr; - /** The FullCPU type to be used. */ - typedef AlphaFullCPU FullCPU; + /** The O3CPU type to be used. */ + typedef AlphaO3CPU O3CPU; + + /** Same typedef, but for CPUType. BaseDynInst may not always use + * an O3 CPU, so it's clearer to call it CPUType instead in that + * case. + */ + typedef O3CPU CPUType; /** The Params to be passed to each stage. */ typedef AlphaSimpleParams Params; diff --git a/src/cpu/o3/alpha_params.hh b/src/cpu/o3/alpha_params.hh index 2ece7fb7f..f0732733e 100644 --- a/src/cpu/o3/alpha_params.hh +++ b/src/cpu/o3/alpha_params.hh @@ -42,12 +42,12 @@ class Process; class System; /** - * This file defines the parameters that will be used for the AlphaFullCPU. + * This file defines the parameters that will be used for the AlphaO3CPU. * This must be defined externally so that the Impl can have a params class * defined that it can pass to all of the individual stages. */ -class AlphaSimpleParams : public BaseFullCPU::Params +class AlphaSimpleParams : public BaseO3CPU::Params { public: diff --git a/src/cpu/o3/bpred_unit.cc b/src/cpu/o3/bpred_unit.cc index b33543bdc..294438704 100644 --- a/src/cpu/o3/bpred_unit.cc +++ b/src/cpu/o3/bpred_unit.cc @@ -31,9 +31,9 @@ #include "cpu/o3/bpred_unit_impl.hh" #include "cpu/o3/alpha_impl.hh" #include "cpu/o3/alpha_dyn_inst.hh" -#include "cpu/ozone/ozone_impl.hh" +//#include "cpu/ozone/ozone_impl.hh" //#include "cpu/ozone/simple_impl.hh" template class BPredUnit; -template class BPredUnit; +//template class BPredUnit; //template class BPredUnit; diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index c73b39ec6..860326283 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -68,7 +68,7 @@ class DefaultCommit { public: // Typedefs from the Impl. - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::Params Params; typedef typename Impl::CPUPol CPUPol; @@ -146,7 +146,7 @@ class DefaultCommit void regStats(); /** Sets the CPU pointer. */ - void setCPU(FullCPU *cpu_ptr); + void setCPU(O3CPU *cpu_ptr); /** Sets the list of threads. */ void setThreads(std::vector &threads); @@ -326,8 +326,8 @@ class DefaultCommit ROB *rob; private: - /** Pointer to FullCPU. */ - FullCPU *cpu; + /** Pointer to O3CPU. */ + O3CPU *cpu; /** Vector of all of the threads. */ std::vector thread; diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 021d3ef90..566324b69 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -28,6 +28,9 @@ * Authors: Kevin Lim */ +#include "config/full_system.hh" +#include "config/use_checker.hh" + #include #include @@ -219,14 +222,14 @@ DefaultCommit::regStats() template void -DefaultCommit::setCPU(FullCPU *cpu_ptr) +DefaultCommit::setCPU(O3CPU *cpu_ptr) { DPRINTF(Commit, "Commit: Setting CPU pointer.\n"); cpu = cpu_ptr; // Commit must broadcast the number of free entries it has at the start of // the simulation, so it starts as active. - cpu->activateStage(FullCPU::CommitIdx); + cpu->activateStage(O3CPU::CommitIdx); trapLatency = cpu->cycles(trapLatency); fetchTrapLatency = cpu->cycles(fetchTrapLatency); @@ -395,10 +398,10 @@ DefaultCommit::updateStatus() if (_nextStatus == Inactive && _status == Active) { DPRINTF(Activity, "Deactivating stage.\n"); - cpu->deactivateStage(FullCPU::CommitIdx); + cpu->deactivateStage(O3CPU::CommitIdx); } else if (_nextStatus == Active && _status == Inactive) { DPRINTF(Activity, "Activating stage.\n"); - cpu->activateStage(FullCPU::CommitIdx); + cpu->activateStage(O3CPU::CommitIdx); } _status = _nextStatus; @@ -907,7 +910,7 @@ DefaultCommit::commitHead(DynInstPtr &head_inst, unsigned inst_num) // and committed this instruction. thread[tid]->funcExeInst--; - head_inst->reachedCommit = true; + head_inst->setAtCommit(); if (head_inst->isNonSpeculative() || head_inst->isStoreConditional() || @@ -972,11 +975,13 @@ DefaultCommit::commitHead(DynInstPtr &head_inst, unsigned inst_num) head_inst->setCompleted(); } +#if USE_CHECKER // Use checker prior to updating anything due to traps or PC // based events. if (cpu->checker) { - cpu->checker->tick(head_inst); + cpu->checker->verify(head_inst); } +#endif // Check if the instruction caused a fault. If so, trap. Fault inst_fault = head_inst->getFault(); @@ -992,9 +997,11 @@ DefaultCommit::commitHead(DynInstPtr &head_inst, unsigned inst_num) return false; } +#if USE_CHECKER if (cpu->checker && head_inst->isStore()) { - cpu->checker->tick(head_inst); + cpu->checker->verify(head_inst); } +#endif assert(!thread[tid]->inSyscall); diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index d5538cdf0..a411fe42e 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -30,6 +30,7 @@ */ #include "config/full_system.hh" +#include "config/use_checker.hh" #if FULL_SYSTEM #include "sim/system.hh" @@ -51,13 +52,13 @@ using namespace std; using namespace TheISA; -BaseFullCPU::BaseFullCPU(Params *params) +BaseO3CPU::BaseO3CPU(Params *params) : BaseCPU(params), cpu_id(0) { } void -BaseFullCPU::regStats() +BaseO3CPU::regStats() { BaseCPU::regStats(); } @@ -84,7 +85,7 @@ FullO3CPU::TickEvent::description() template FullO3CPU::FullO3CPU(Params *params) - : BaseFullCPU(params), + : BaseO3CPU(params), tickEvent(this), removeInstsThisCycle(false), fetch(params), @@ -132,6 +133,9 @@ FullO3CPU::FullO3CPU(Params *params) { _status = Idle; + checker = NULL; + +#if USE_CHECKER if (params->checker) { BaseCPU *temp_checker = params->checker; checker = dynamic_cast *>(temp_checker); @@ -139,9 +143,8 @@ FullO3CPU::FullO3CPU(Params *params) #if FULL_SYSTEM checker->setSystem(params->system); #endif - } else { - checker = NULL; } +#endif #if !FULL_SYSTEM thread.resize(number_of_threads); @@ -262,9 +265,9 @@ template void FullO3CPU::fullCPURegStats() { - BaseFullCPU::regStats(); + BaseO3CPU::regStats(); - // Register any of the FullCPU's stats here. + // Register any of the O3CPU's stats here. timesIdled .name(name() + ".timesIdled") .desc("Number of times that the entire CPU went into an idle state and" @@ -320,7 +323,7 @@ template void FullO3CPU::tick() { - DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n"); + DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); ++numCycles; @@ -419,7 +422,7 @@ template void FullO3CPU::insertThread(unsigned tid) { - DPRINTF(FullCPU,"[tid:%i] Initializing thread data"); + DPRINTF(O3CPU,"[tid:%i] Initializing thread data"); // Will change now that the PC and thread state is internal to the CPU // and not in the ThreadContext. #if 0 @@ -466,7 +469,7 @@ template void FullO3CPU::removeThread(unsigned tid) { - DPRINTF(FullCPU,"[tid:%i] Removing thread data"); + DPRINTF(O3CPU,"[tid:%i] Removing thread data"); #if 0 //Unbind Int Regs from Rename Map for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) { @@ -512,37 +515,37 @@ template void FullO3CPU::activateWhenReady(int tid) { - DPRINTF(FullCPU,"[tid:%i]: Checking if resources are available for incoming" + DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming" "(e.g. PhysRegs/ROB/IQ/LSQ) \n", tid); bool ready = true; if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) { - DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough " + DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " "Phys. Int. Regs.\n", tid); ready = false; } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) { - DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough " + DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " "Phys. Float. Regs.\n", tid); ready = false; } else if (commit.rob->numFreeEntries() >= commit.rob->entryAmount(activeThreads.size() + 1)) { - DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough " + DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " "ROB entries.\n", tid); ready = false; } else if (iew.instQueue.numFreeEntries() >= iew.instQueue.entryAmount(activeThreads.size() + 1)) { - DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough " + DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " "IQ entries.\n", tid); ready = false; } else if (iew.ldstQueue.numFreeEntries() >= iew.ldstQueue.entryAmount(activeThreads.size() + 1)) { - DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough " + DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough " "LSQ entries.\n", tid); ready = false; @@ -576,7 +579,7 @@ FullO3CPU::activateContext(int tid, int delay) if (isActive == activeThreads.end()) { //May Need to Re-code this if the delay variable is the //delay needed for thread to activate - DPRINTF(FullCPU, "Adding Thread %i to active threads list\n", + DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", tid); activeThreads.push_back(tid); @@ -598,7 +601,7 @@ template void FullO3CPU::suspendContext(int tid) { - DPRINTF(FullCPU,"[tid: %i]: Suspended ...\n", tid); + DPRINTF(O3CPU,"[tid: %i]: Suspended ...\n", tid); unscheduleTickEvent(); _status = Idle; /* @@ -607,7 +610,7 @@ FullO3CPU::suspendContext(int tid) activeThreads.begin(), activeThreads.end(), tid); if (isActive != activeThreads.end()) { - DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n", + DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", tid); activeThreads.erase(isActive); } @@ -618,14 +621,14 @@ template void FullO3CPU::deallocateContext(int tid) { - DPRINTF(FullCPU,"[tid:%i]: Deallocating ...", tid); + DPRINTF(O3CPU,"[tid:%i]: Deallocating ...", tid); /* //Remove From Active List, if Active list::iterator isActive = find( activeThreads.begin(), activeThreads.end(), tid); if (isActive != activeThreads.end()) { - DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n", + DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", tid); activeThreads.erase(isActive); @@ -638,14 +641,14 @@ template void FullO3CPU::haltContext(int tid) { - DPRINTF(FullCPU,"[tid:%i]: Halted ...", tid); + DPRINTF(O3CPU,"[tid:%i]: Halted ...", tid); /* //Remove From Active List, if Active list::iterator isActive = find( activeThreads.begin(), activeThreads.end(), tid); if (isActive != activeThreads.end()) { - DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n", + DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n", tid); activeThreads.erase(isActive); @@ -731,7 +734,7 @@ FullO3CPU::takeOverFrom(BaseCPU *oldCPU) if (isActive == activeThreads.end()) { //May Need to Re-code this if the delay variable is the delay //needed for thread to activate - DPRINTF(FullCPU, "Adding Thread %i to active threads list\n", + DPRINTF(O3CPU, "Adding Thread %i to active threads list\n", tid); activeThreads.push_back(tid); @@ -975,7 +978,7 @@ template void FullO3CPU::removeFrontInst(DynInstPtr &inst) { - DPRINTF(FullCPU, "FullCPU: Removing committed instruction [tid:%i] PC %#x " + DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " "[sn:%lli]\n", inst->threadNumber, inst->readPC(), inst->seqNum); @@ -989,7 +992,7 @@ template void FullO3CPU::removeInstsNotInROB(unsigned tid) { - DPRINTF(FullCPU, "FullCPU: Thread %i: Deleting instructions from instruction" + DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction" " list.\n", tid); ListIt end_it; @@ -999,12 +1002,12 @@ FullO3CPU::removeInstsNotInROB(unsigned tid) if (instList.empty()) { return; } else if (rob.isEmpty(/*tid*/)) { - DPRINTF(FullCPU, "FullCPU: ROB is empty, squashing all insts.\n"); + DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n"); end_it = instList.begin(); rob_empty = true; } else { end_it = (rob.readTailInst(tid))->getInstListIt(); - DPRINTF(FullCPU, "FullCPU: ROB is not empty, squashing insts not in ROB.\n"); + DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n"); } removeInstsThisCycle = true; @@ -1043,7 +1046,7 @@ FullO3CPU::removeInstsUntil(const InstSeqNum &seq_num, inst_iter--; - DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction " + DPRINTF(O3CPU, "Deleting instructions from instruction " "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", tid, seq_num, (*inst_iter)->seqNum); @@ -1065,7 +1068,7 @@ inline void FullO3CPU::squashInstIt(const ListIt &instIt, const unsigned &tid) { if ((*instIt)->threadNumber == tid) { - DPRINTF(FullCPU, "FullCPU: Squashing instruction, " + DPRINTF(O3CPU, "Squashing instruction, " "[tid:%i] [sn:%lli] PC %#x\n", (*instIt)->threadNumber, (*instIt)->seqNum, @@ -1086,7 +1089,7 @@ void FullO3CPU::cleanUpRemovedInsts() { while (!removeList.empty()) { - DPRINTF(FullCPU, "FullCPU: Removing instruction, " + DPRINTF(O3CPU, "Removing instruction, " "[tid:%i] [sn:%lli] PC %#x\n", (*removeList.front())->threadNumber, (*removeList.front())->seqNum, diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 8f4175c70..b1ebcce9d 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -57,13 +57,13 @@ class ThreadContext; class MemObject; class Process; -class BaseFullCPU : public BaseCPU +class BaseO3CPU : public BaseCPU { //Stuff that's pretty ISA independent will go here. public: typedef BaseCPU::Params Params; - BaseFullCPU(Params *params); + BaseO3CPU(Params *params); void regStats(); @@ -79,7 +79,7 @@ class BaseFullCPU : public BaseCPU * tick() function for the CPU is defined here. */ template -class FullO3CPU : public BaseFullCPU +class FullO3CPU : public BaseO3CPU { public: typedef TheISA::FloatReg FloatReg; diff --git a/src/cpu/o3/decode.hh b/src/cpu/o3/decode.hh index ff88358d6..1edf3335d 100644 --- a/src/cpu/o3/decode.hh +++ b/src/cpu/o3/decode.hh @@ -48,7 +48,7 @@ class DefaultDecode { private: // Typedefs from the Impl. - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::Params Params; typedef typename Impl::CPUPol CPUPol; @@ -95,7 +95,7 @@ class DefaultDecode void regStats(); /** Sets CPU pointer. */ - void setCPU(FullCPU *cpu_ptr); + void setCPU(O3CPU *cpu_ptr); /** Sets the main backwards communication time buffer pointer. */ void setTimeBuffer(TimeBuffer *tb_ptr); @@ -189,7 +189,7 @@ class DefaultDecode private: // Interfaces to objects outside of decode. /** CPU interface. */ - FullCPU *cpu; + O3CPU *cpu; /** Time buffer interface. */ TimeBuffer *timeBuffer; diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index 0748ddb3b..16be01784 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -112,7 +112,7 @@ DefaultDecode::regStats() template void -DefaultDecode::setCPU(FullCPU *cpu_ptr) +DefaultDecode::setCPU(O3CPU *cpu_ptr) { DPRINTF(Decode, "Setting CPU pointer.\n"); cpu = cpu_ptr; @@ -296,7 +296,7 @@ DefaultDecode::squash(DynInstPtr &inst, unsigned tid) for (int i=0; isize; i++) { if (fromFetch->insts[i]->threadNumber == tid && fromFetch->insts[i]->seqNum > inst->seqNum) { - fromFetch->insts[i]->squashed = true; + fromFetch->insts[i]->setSquashed(); } } @@ -345,7 +345,7 @@ DefaultDecode::squash(unsigned tid) for (int i=0; isize; i++) { if (fromFetch->insts[i]->threadNumber == tid) { - fromFetch->insts[i]->squashed = true; + fromFetch->insts[i]->setSquashed(); squash_count++; } } @@ -427,7 +427,7 @@ DefaultDecode::updateStatus() DPRINTF(Activity, "Activating stage.\n"); - cpu->activateStage(FullCPU::DecodeIdx); + cpu->activateStage(O3CPU::DecodeIdx); } } else { // If it's not unblocking, then decode will not have any internal @@ -436,7 +436,7 @@ DefaultDecode::updateStatus() _status = Inactive; DPRINTF(Activity, "Deactivating stage.\n"); - cpu->deactivateStage(FullCPU::DecodeIdx); + cpu->deactivateStage(O3CPU::DecodeIdx); } } } diff --git a/src/cpu/o3/dep_graph.hh b/src/cpu/o3/dep_graph.hh index 3659b1a37..c19fd0abf 100644 --- a/src/cpu/o3/dep_graph.hh +++ b/src/cpu/o3/dep_graph.hh @@ -68,6 +68,8 @@ class DependencyGraph : numEntries(0), memAllocCounter(0), nodesTraversed(0), nodesRemoved(0) { } + ~DependencyGraph(); + /** Resize the dependency graph to have num_entries registers. */ void resize(int num_entries); @@ -120,6 +122,12 @@ class DependencyGraph uint64_t nodesRemoved; }; +template +DependencyGraph::~DependencyGraph() +{ + delete [] dependGraph; +} + template void DependencyGraph::resize(int num_entries) diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index c2d91a379..790c28f09 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -58,7 +58,7 @@ class DefaultFetch typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInst DynInst; typedef typename Impl::DynInstPtr DynInstPtr; - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; typedef typename Impl::Params Params; /** Typedefs from the CPU policy. */ @@ -165,7 +165,7 @@ class DefaultFetch void regStats(); /** Sets CPU pointer. */ - void setCPU(FullCPU *cpu_ptr); + void setCPU(O3CPU *cpu_ptr); /** Sets the main backwards communication time buffer pointer. */ void setTimeBuffer(TimeBuffer *time_buffer); @@ -297,8 +297,8 @@ class DefaultFetch int branchCount(); private: - /** Pointer to the FullCPU. */ - FullCPU *cpu; + /** Pointer to the O3CPU. */ + O3CPU *cpu; /** Time buffer interface. */ TimeBuffer *timeBuffer; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 4993819be..7cbf0ab02 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -29,6 +29,8 @@ * Korey Sewell */ +#include "config/use_checker.hh" + #include "arch/isa_traits.hh" #include "arch/utility.hh" #include "cpu/checker/cpu.hh" @@ -269,7 +271,7 @@ DefaultFetch::regStats() template void -DefaultFetch::setCPU(FullCPU *cpu_ptr) +DefaultFetch::setCPU(O3CPU *cpu_ptr) { DPRINTF(Fetch, "Setting the CPU pointer.\n"); cpu = cpu_ptr; @@ -281,9 +283,11 @@ DefaultFetch::setCPU(FullCPU *cpu_ptr) icachePort->setPeer(mem_dport); mem_dport->setPeer(icachePort); +#if USE_CHECKER if (cpu->checker) { cpu->checker->setIcachePort(icachePort); } +#endif // Fetch needs to start fetching instructions at the very beginning, // so it must start up in active state. @@ -437,7 +441,7 @@ DefaultFetch::switchToActive() if (_status == Inactive) { DPRINTF(Activity, "Activating stage.\n"); - cpu->activateStage(FullCPU::FetchIdx); + cpu->activateStage(O3CPU::FetchIdx); _status = Active; } @@ -450,7 +454,7 @@ DefaultFetch::switchToInactive() if (_status == Active) { DPRINTF(Activity, "Deactivating stage.\n"); - cpu->deactivateStage(FullCPU::FetchIdx); + cpu->deactivateStage(O3CPU::FetchIdx); _status = Inactive; } @@ -669,7 +673,7 @@ DefaultFetch::updateFetchStatus() "completion\n",tid); } - cpu->activateStage(FullCPU::FetchIdx); + cpu->activateStage(O3CPU::FetchIdx); } return Active; @@ -680,7 +684,7 @@ DefaultFetch::updateFetchStatus() if (_status == Active) { DPRINTF(Activity, "Deactivating stage.\n"); - cpu->deactivateStage(FullCPU::FetchIdx); + cpu->deactivateStage(O3CPU::FetchIdx); } return Inactive; diff --git a/src/cpu/o3/fu_pool.cc b/src/cpu/o3/fu_pool.cc index 545deea9b..42e329aca 100644 --- a/src/cpu/o3/fu_pool.cc +++ b/src/cpu/o3/fu_pool.cc @@ -31,7 +31,7 @@ #include #include "cpu/o3/fu_pool.hh" -#include "encumbered/cpu/full/fu_pool.hh" +#include "cpu/func_unit.hh" #include "sim/builder.hh" using namespace std; diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh index 615022dc9..2af68d8fc 100644 --- a/src/cpu/o3/iew.hh +++ b/src/cpu/o3/iew.hh @@ -68,7 +68,7 @@ class DefaultIEW //Typedefs from Impl typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInstPtr DynInstPtr; - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; typedef typename Impl::Params Params; typedef typename CPUPol::IQ IQ; @@ -80,7 +80,7 @@ class DefaultIEW typedef typename CPUPol::RenameStruct RenameStruct; typedef typename CPUPol::IssueStruct IssueStruct; - friend class Impl::FullCPU; + friend class Impl::O3CPU; friend class CPUPol::IQ; public: @@ -126,7 +126,7 @@ class DefaultIEW void initStage(); /** Sets CPU pointer for IEW, IQ, and LSQ. */ - void setCPU(FullCPU *cpu_ptr); + void setCPU(O3CPU *cpu_ptr); /** Sets main time buffer used for backwards communication. */ void setTimeBuffer(TimeBuffer *tb_ptr); @@ -331,7 +331,7 @@ class DefaultIEW private: /** CPU pointer. */ - FullCPU *cpu; + O3CPU *cpu; /** Records if IEW has written to the time buffer this cycle, so that the * CPU can deschedule itself if there is no activity. diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index b02ee8555..8e6fd46a1 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -276,7 +276,7 @@ DefaultIEW::initStage() template void -DefaultIEW::setCPU(FullCPU *cpu_ptr) +DefaultIEW::setCPU(O3CPU *cpu_ptr) { DPRINTF(IEW, "Setting CPU pointer.\n"); cpu = cpu_ptr; @@ -284,7 +284,7 @@ DefaultIEW::setCPU(FullCPU *cpu_ptr) instQueue.setCPU(cpu_ptr); ldstQueue.setCPU(cpu_ptr); - cpu->activateStage(FullCPU::IEWIdx); + cpu->activateStage(O3CPU::IEWIdx); } template @@ -579,7 +579,7 @@ DefaultIEW::validInstsFromRename() unsigned inst_count = 0; for (int i=0; isize; i++) { - if (!fromRename->insts[i]->squashed) + if (!fromRename->insts[i]->isSquashed()) inst_count++; } @@ -857,7 +857,7 @@ inline void DefaultIEW::activateStage() { DPRINTF(Activity, "Activating stage.\n"); - cpu->activateStage(FullCPU::IEWIdx); + cpu->activateStage(O3CPU::IEWIdx); } template @@ -865,7 +865,7 @@ inline void DefaultIEW::deactivateStage() { DPRINTF(Activity, "Deactivating stage.\n"); - cpu->deactivateStage(FullCPU::IEWIdx); + cpu->deactivateStage(O3CPU::IEWIdx); } template diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh index 6fd3c6d0b..d745faf7b 100644 --- a/src/cpu/o3/inst_queue.hh +++ b/src/cpu/o3/inst_queue.hh @@ -68,7 +68,7 @@ class InstructionQueue { public: //Typedefs from the Impl. - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::Params Params; @@ -80,7 +80,7 @@ class InstructionQueue // Typedef of iterator through the list of instructions. typedef typename std::list::iterator ListIt; - friend class Impl::FullCPU; + friend class Impl::O3CPU; /** FU completion event class. */ class FUCompletion : public Event { @@ -125,7 +125,7 @@ class InstructionQueue void resetState(); /** Sets CPU pointer. */ - void setCPU(FullCPU *_cpu) { cpu = _cpu; } + void setCPU(O3CPU *_cpu) { cpu = _cpu; } /** Sets active threads list. */ void setActiveThreads(std::list *at_ptr); @@ -252,7 +252,7 @@ class InstructionQueue ///////////////////////// /** Pointer to the CPU. */ - FullCPU *cpu; + O3CPU *cpu; /** Cache interface. */ MemInterface *dcacheInterface; diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 66d4a54c6..1ef1b2cff 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -776,7 +776,7 @@ InstructionQueue::scheduleReadyInsts() // complete. ++freeEntries; count[tid]--; - issuing_inst->removeInIQ(); + issuing_inst->clearInIQ(); } else { memDepUnit[tid].issue(issuing_inst); } @@ -1082,7 +1082,7 @@ InstructionQueue::doSquash(unsigned tid) // inst will flow through the rest of the pipeline. squashed_inst->setIssued(); squashed_inst->setCanCommit(); - squashed_inst->removeInIQ(); + squashed_inst->clearInIQ(); //Update Thread IQ Count count[squashed_inst->threadNumber]--; diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 1dbd46b8e..89791fec9 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -44,7 +44,7 @@ template class LSQ { public: typedef typename Impl::Params Params; - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::CPUPol::IEW IEW; typedef typename Impl::CPUPol::LSQUnit LSQUnit; @@ -68,7 +68,7 @@ class LSQ { /** Sets the pointer to the list of active threads. */ void setActiveThreads(std::list *at_ptr); /** Sets the CPU pointer. */ - void setCPU(FullCPU *cpu_ptr); + void setCPU(O3CPU *cpu_ptr); /** Sets the IEW stage pointer. */ void setIEW(IEW *iew_ptr); /** Switches out the LSQ. */ @@ -275,7 +275,7 @@ class LSQ { LSQUnit thread[Impl::MaxThreads]; /** The CPU pointer. */ - FullCPU *cpu; + O3CPU *cpu; /** The IEW stage pointer. */ IEW *iewStage; diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 0b6c6f542..5173f8be1 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -126,7 +126,7 @@ LSQ::setActiveThreads(list *at_ptr) template void -LSQ::setCPU(FullCPU *cpu_ptr) +LSQ::setCPU(O3CPU *cpu_ptr) { cpu = cpu_ptr; diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 3de581519..cef6e0a2e 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -61,7 +61,7 @@ class LSQUnit { typedef TheISA::IntReg IntReg; public: typedef typename Impl::Params Params; - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef typename Impl::CPUPol::IEW IEW; typedef typename Impl::CPUPol::IssueStruct IssueStruct; @@ -81,7 +81,7 @@ class LSQUnit { void regStats(); /** Sets the CPU pointer. */ - void setCPU(FullCPU *cpu_ptr); + void setCPU(O3CPU *cpu_ptr); /** Sets the IEW stage pointer. */ void setIEW(IEW *iew_ptr) @@ -232,7 +232,7 @@ class LSQUnit { private: /** Pointer to the CPU. */ - FullCPU *cpu; + O3CPU *cpu; /** Pointer to the IEW stage. */ IEW *iewStage; @@ -249,13 +249,13 @@ class LSQUnit { { protected: /** Pointer to CPU. */ - FullCPU *cpu; + O3CPU *cpu; /** Pointer to LSQ. */ LSQUnit *lsq; public: /** Default constructor. */ - DcachePort(FullCPU *_cpu, LSQUnit *_lsq) + DcachePort(O3CPU *_cpu, LSQUnit *_lsq) : Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq) { } @@ -527,7 +527,7 @@ LSQUnit::read(Request *req, T &data, int load_idx) // at the head of the LSQ and are ready to commit (at the head of the ROB // too). if (req->getFlags() & UNCACHEABLE && - (load_idx != loadHead || !load_inst->reachedCommit)) { + (load_idx != loadHead || !load_inst->isAtCommit())) { iewStage->rescheduleMemInst(load_inst); ++lsqRescheduledLoads; return TheISA::genMachineCheckFault(); diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index a5c1eb12a..f4a656aa1 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -29,6 +29,8 @@ * Korey Sewell */ +#include "config/use_checker.hh" + #include "cpu/checker/cpu.hh" #include "cpu/o3/lsq_unit.hh" #include "base/str.hh" @@ -171,7 +173,7 @@ LSQUnit::init(Params *params, unsigned maxLQEntries, template void -LSQUnit::setCPU(FullCPU *cpu_ptr) +LSQUnit::setCPU(O3CPU *cpu_ptr) { cpu = cpu_ptr; dcachePort = new DcachePort(cpu, this); @@ -180,9 +182,11 @@ LSQUnit::setCPU(FullCPU *cpu_ptr) dcachePort->setPeer(mem_dport); mem_dport->setPeer(dcachePort); +#if USE_CHECKER if (cpu->checker) { cpu->checker->setDcachePort(dcachePort); } +#endif } template @@ -710,7 +714,7 @@ LSQUnit::squash(const InstSeqNum &squashed_num) } // Clear the smart pointer to make sure it is decremented. - loadQueue[load_idx]->squashed = true; + loadQueue[load_idx]->setSquashed(); loadQueue[load_idx] = NULL; --loads; @@ -754,7 +758,7 @@ LSQUnit::squash(const InstSeqNum &squashed_num) } // Clear the smart pointer to make sure it is decremented. - storeQueue[store_idx].inst->squashed = true; + storeQueue[store_idx].inst->setSquashed(); storeQueue[store_idx].inst = NULL; storeQueue[store_idx].canWB = 0; @@ -788,9 +792,11 @@ LSQUnit::storePostSend(Packet *pkt) // only works so long as the checker doesn't try to // verify the value in memory for stores. storeQueue[storeWBIdx].inst->setCompleted(); +#if USE_CHECKER if (cpu->checker) { - cpu->checker->tick(storeQueue[storeWBIdx].inst); + cpu->checker->verify(storeQueue[storeWBIdx].inst); } +#endif } if (pkt->result != Packet::Success) { @@ -884,9 +890,11 @@ LSQUnit::completeStore(int store_idx) // Tell the checker we've completed this instruction. Some stores // may get reported twice to the checker, but the checker can // handle that case. +#if USE_CHECKER if (cpu->checker) { - cpu->checker->tick(storeQueue[store_idx].inst); + cpu->checker->verify(storeQueue[store_idx].inst); } +#endif } template diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index ade5e4e56..6972f055f 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -72,7 +72,7 @@ class PhysRegFile // Will make these registers public for now, but they probably should // be private eventually with some accessor functions. public: - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; /** * Constructs a physical register file with the specified amount of @@ -278,11 +278,11 @@ class PhysRegFile private: /** CPU pointer. */ - FullCPU *cpu; + O3CPU *cpu; public: /** Sets the CPU pointer. */ - void setCPU(FullCPU *cpu_ptr) { cpu = cpu_ptr; } + void setCPU(O3CPU *cpu_ptr) { cpu = cpu_ptr; } /** Number of physical integer registers. */ unsigned numPhysicalIntRegs; diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index 42fdf6bf5..581fc8f81 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -55,7 +55,7 @@ class DefaultRename // Typedefs from the Impl. typedef typename Impl::CPUPol CPUPol; typedef typename Impl::DynInstPtr DynInstPtr; - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; typedef typename Impl::Params Params; // Typedefs from the CPUPol @@ -115,7 +115,7 @@ class DefaultRename void regStats(); /** Sets CPU pointer. */ - void setCPU(FullCPU *cpu_ptr); + void setCPU(O3CPU *cpu_ptr); /** Sets the main backwards communication time buffer pointer. */ void setTimeBuffer(TimeBuffer *tb_ptr); @@ -291,7 +291,7 @@ class DefaultRename std::list historyBuffer[Impl::MaxThreads]; /** Pointer to CPU. */ - FullCPU *cpu; + O3CPU *cpu; /** Pointer to main time buffer used for backwards communication. */ TimeBuffer *timeBuffer; diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index f9e2a03ee..df8b7f9da 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -162,7 +162,7 @@ DefaultRename::regStats() template void -DefaultRename::setCPU(FullCPU *cpu_ptr) +DefaultRename::setCPU(O3CPU *cpu_ptr) { DPRINTF(Rename, "Setting CPU pointer.\n"); cpu = cpu_ptr; @@ -341,7 +341,7 @@ DefaultRename::squash(unsigned tid) for (int i=0; isize; i++) { if (fromDecode->insts[i]->threadNumber == tid) { - fromDecode->insts[i]->squashed = true; + fromDecode->insts[i]->setSquashed(); wroteToTimeBuffer = true; squashCount++; } @@ -755,7 +755,7 @@ DefaultRename::updateStatus() DPRINTF(Activity, "Activating stage.\n"); - cpu->activateStage(FullCPU::RenameIdx); + cpu->activateStage(O3CPU::RenameIdx); } } else { // If it's not unblocking, then rename will not have any internal @@ -764,7 +764,7 @@ DefaultRename::updateStatus() _status = Inactive; DPRINTF(Activity, "Deactivating stage.\n"); - cpu->deactivateStage(FullCPU::RenameIdx); + cpu->deactivateStage(O3CPU::RenameIdx); } } } @@ -1022,7 +1022,7 @@ DefaultRename::validInsts() unsigned inst_count = 0; for (int i=0; isize; i++) { - if (!fromDecode->insts[i]->squashed) + if (!fromDecode->insts[i]->isSquashed()) inst_count++; } diff --git a/src/cpu/o3/rob.hh b/src/cpu/o3/rob.hh index 6d1402531..b98d7c4c2 100644 --- a/src/cpu/o3/rob.hh +++ b/src/cpu/o3/rob.hh @@ -45,7 +45,7 @@ class ROB typedef TheISA::RegIndex RegIndex; public: //Typedefs from the Impl. - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; typedef typename Impl::DynInstPtr DynInstPtr; typedef std::pair UnmapInfo; @@ -90,7 +90,7 @@ class ROB * is created within. * @param cpu_ptr Pointer to the implementation specific full CPU object. */ - void setCPU(FullCPU *cpu_ptr); + void setCPU(O3CPU *cpu_ptr); /** Sets pointer to the list of active threads. * @param at_ptr Pointer to the list of active threads. @@ -257,7 +257,7 @@ class ROB private: /** Pointer to the CPU. */ - FullCPU *cpu; + O3CPU *cpu; /** Active Threads in CPU */ std::list* activeThreads; diff --git a/src/cpu/o3/rob_impl.hh b/src/cpu/o3/rob_impl.hh index 97694e371..6277dd68b 100644 --- a/src/cpu/o3/rob_impl.hh +++ b/src/cpu/o3/rob_impl.hh @@ -100,7 +100,7 @@ ROB::name() const template void -ROB::setCPU(FullCPU *cpu_ptr) +ROB::setCPU(O3CPU *cpu_ptr) { cpu = cpu_ptr; @@ -276,7 +276,7 @@ ROB::retireHead(unsigned tid) --numInstsInROB; --threadEntries[tid]; - head_inst->removeInROB(); + head_inst->clearInROB(); head_inst->setCommitted(); instList[tid].erase(head_it); diff --git a/src/cpu/o3/thread_state.hh b/src/cpu/o3/thread_state.hh index b6535baa1..19cbffb44 100644 --- a/src/cpu/o3/thread_state.hh +++ b/src/cpu/o3/thread_state.hh @@ -58,11 +58,11 @@ class Process; template struct O3ThreadState : public ThreadState { typedef ThreadContext::Status Status; - typedef typename Impl::FullCPU FullCPU; + typedef typename Impl::O3CPU O3CPU; private: /** Pointer to the CPU. */ - FullCPU *cpu; + O3CPU *cpu; public: /** Whether or not the thread is currently in syscall mode, and * thus able to be externally updated without squashing. @@ -75,12 +75,12 @@ struct O3ThreadState : public ThreadState { bool trapPending; #if FULL_SYSTEM - O3ThreadState(FullCPU *_cpu, int _thread_num) + O3ThreadState(O3CPU *_cpu, int _thread_num) : ThreadState(-1, _thread_num), inSyscall(0), trapPending(0) { } #else - O3ThreadState(FullCPU *_cpu, int _thread_num, Process *_process, int _asid, + O3ThreadState(O3CPU *_cpu, int _thread_num, Process *_process, int _asid, MemObject *mem) : ThreadState(-1, _thread_num, mem, _process, _asid), cpu(_cpu), inSyscall(0), trapPending(0) diff --git a/src/python/m5/objects/AlphaFullCPU.py b/src/python/m5/objects/AlphaO3CPU.py similarity index 98% rename from src/python/m5/objects/AlphaFullCPU.py rename to src/python/m5/objects/AlphaO3CPU.py index 2988305d3..f14f8c88e 100644 --- a/src/python/m5/objects/AlphaFullCPU.py +++ b/src/python/m5/objects/AlphaO3CPU.py @@ -2,8 +2,8 @@ from m5 import build_env from m5.config import * from BaseCPU import BaseCPU -class DerivAlphaFullCPU(BaseCPU): - type = 'DerivAlphaFullCPU' +class DerivAlphaO3CPU(BaseCPU): + type = 'DerivAlphaO3CPU' activity = Param.Unsigned("Initial count") numThreads = Param.Unsigned("number of HW thread contexts") diff --git a/src/python/m5/objects/FuncUnit.py b/src/python/m5/objects/FuncUnit.py new file mode 100644 index 000000000..f61590ae9 --- /dev/null +++ b/src/python/m5/objects/FuncUnit.py @@ -0,0 +1,17 @@ +from m5.config import * + +class OpType(Enum): + vals = ['(null)', 'IntAlu', 'IntMult', 'IntDiv', 'FloatAdd', + 'FloatCmp', 'FloatCvt', 'FloatMult', 'FloatDiv', 'FloatSqrt', + 'MemRead', 'MemWrite', 'IprAccess', 'InstPrefetch'] + +class OpDesc(SimObject): + type = 'OpDesc' + issueLat = Param.Int(1, "cycles until another can be issued") + opClass = Param.OpType("type of operation") + opLat = Param.Int(1, "cycles until result is available") + +class FUDesc(SimObject): + type = 'FUDesc' + count = Param.Int("number of these FU's available") + opList = VectorParam.OpDesc("operation classes for this FU type")