diff options
Diffstat (limited to 'src/cpu')
67 files changed, 1073 insertions, 753 deletions
diff --git a/src/cpu/SConscript b/src/cpu/SConscript index 4d4b7574c..1c2278f6f 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -28,11 +28,7 @@ # # Authors: Steve Reinhardt -import os -import os.path - -# Import build environment variable from SConstruct. -Import('env') +Import('*') ################################################################# # @@ -107,89 +103,24 @@ env.Depends('static_inst_exec_sigs.hh', Value(env['CPU_MODELS'])) # and one of these are not being used. CheckerSupportedCPUList = ['O3CPU', 'OzoneCPU'] -################################################################# -# -# Include CPU-model-specific files based on set of models -# specified in CPU_MODELS build option. -# -################################################################# - -# Keep a list of CPU models that support SMT -env['SMT_CPU_MODELS'] = [] - -sources = [] - -need_simple_base = False -if 'AtomicSimpleCPU' in env['CPU_MODELS']: - need_simple_base = True - sources += Split('simple/atomic.cc') - -if 'TimingSimpleCPU' in env['CPU_MODELS']: - need_simple_base = True - sources += Split('simple/timing.cc') - -if need_simple_base: - sources += Split('simple/base.cc') - -if 'FastCPU' in env['CPU_MODELS']: - sources += Split('fast/cpu.cc') - -need_bp_unit = False -if 'O3CPU' in env['CPU_MODELS']: - need_bp_unit = True - sources += SConscript('o3/SConscript', exports = 'env') - sources += Split(''' - o3/base_dyn_inst.cc - o3/bpred_unit.cc - o3/commit.cc - o3/decode.cc - o3/fetch.cc - o3/free_list.cc - o3/fu_pool.cc - o3/cpu.cc - o3/iew.cc - o3/inst_queue.cc - o3/lsq_unit.cc - o3/lsq.cc - o3/mem_dep_unit.cc - o3/rename.cc - o3/rename_map.cc - o3/rob.cc - o3/scoreboard.cc - o3/store_set.cc - ''') - sources += Split('memtest/memtest.cc') - if env['USE_CHECKER']: - sources += Split('o3/checker_builder.cc') - else: - env['SMT_CPU_MODELS'].append('O3CPU') # Checker doesn't support SMT right now - -if 'OzoneCPU' in env['CPU_MODELS']: - need_bp_unit = True - sources += Split(''' - ozone/base_dyn_inst.cc - ozone/bpred_unit.cc - ozone/cpu.cc - ozone/cpu_builder.cc - ozone/dyn_inst.cc - ozone/front_end.cc - ozone/lw_back_end.cc - ozone/lw_lsq.cc - ozone/rename_table.cc - ''') - if env['USE_CHECKER']: - sources += Split('ozone/checker_builder.cc') - -if need_bp_unit: - sources += Split(''' - o3/2bit_local_pred.cc - o3/btb.cc - o3/ras.cc - o3/tournament_pred.cc - ''') +Source('activity.cc') +Source('base.cc') +Source('cpuevent.cc') +Source('exetrace.cc') +Source('func_unit.cc') +Source('op_class.cc') +Source('pc_event.cc') +Source('quiesce_event.cc') +Source('static_inst.cc') +Source('simple_thread.cc') +Source('thread_state.cc') + +if env['FULL_SYSTEM']: + Source('intr_control.cc') + Source('profile.cc') if env['USE_CHECKER']: - sources += Split('checker/cpu.cc') + Source('checker/cpu.cc') checker_supports = False for i in CheckerSupportedCPUList: if i in env['CPU_MODELS']: @@ -198,16 +129,5 @@ if env['USE_CHECKER']: print "Checker only supports CPU models", for i in CheckerSupportedCPUList: print i, - print ", please set USE_CHECKER=False or use one of those CPU models" + print ", please set USE_CHECKER=False or use one of those CPU models" Exit(1) - - -# FullCPU sources are included from src/SConscript since they're not -# below this point in the file hierarchy. - -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] - -Return('sources') - diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 03110630c..4dccee0d3 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -63,7 +63,7 @@ int maxThreadsPerCPU = 1; CPUProgressEvent::CPUProgressEvent(EventQueue *q, Tick ival, BaseCPU *_cpu) - : Event(q, Event::Stat_Event_Pri), interval(ival), + : Event(q, Event::Progress_Event_Pri), interval(ival), lastNumInst(0), cpu(_cpu) { if (interval) @@ -320,7 +320,7 @@ BaseCPU::switchOut() } void -BaseCPU::takeOverFrom(BaseCPU *oldCPU) +BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) { assert(threadContexts.size() == oldCPU->threadContexts.size()); @@ -353,6 +353,26 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) // if (profileEvent) // profileEvent->schedule(curTick); #endif + + // Connect new CPU to old CPU's memory only if new CPU isn't + // connected to anything. Also connect old CPU's memory to new + // CPU. + Port *peer; + if (ic->getPeer() == NULL) { + peer = oldCPU->getPort("icache_port")->getPeer(); + ic->setPeer(peer); + } else { + peer = ic->getPeer(); + } + peer->setPeer(ic); + + if (dc->getPeer() == NULL) { + peer = oldCPU->getPort("dcache_port")->getPeer(); + dc->setPeer(peer); + } else { + peer = dc->getPeer(); + } + peer->setPeer(dc); } @@ -373,12 +393,6 @@ BaseCPU::ProfileEvent::process() } void -BaseCPU::post_interrupt(int int_type) -{ - interrupts.post(int_type); -} - -void BaseCPU::post_interrupt(int int_num, int index) { interrupts.post(int_num, index); @@ -396,6 +410,11 @@ BaseCPU::clear_interrupts() interrupts.clear_all(); } +uint64_t +BaseCPU::get_interrupts(int int_num) +{ + return interrupts.get_vec(int_num); +} void BaseCPU::serialize(std::ostream &os) diff --git a/src/cpu/base.hh b/src/cpu/base.hh index a1265b748..4d8300186 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -34,11 +34,11 @@ #include <vector> +#include "arch/isa_traits.hh" #include "base/statistics.hh" #include "config/full_system.hh" #include "sim/eventq.hh" #include "mem/mem_object.hh" -#include "arch/isa_traits.hh" #if FULL_SYSTEM #include "arch/interrupts.hh" @@ -50,6 +50,11 @@ class ThreadContext; class System; class Port; +namespace TheISA +{ + class Predecoder; +} + class CPUProgressEvent : public Event { protected: @@ -102,10 +107,10 @@ class BaseCPU : public MemObject TheISA::Interrupts interrupts; public: - virtual void post_interrupt(int int_type); virtual void post_interrupt(int int_num, int index); virtual void clear_interrupt(int int_num, int index); virtual void clear_interrupts(); + virtual uint64_t get_interrupts(int int_num); bool check_interrupts(ThreadContext * tc) const { return interrupts.check_interrupts(tc); } @@ -125,6 +130,7 @@ class BaseCPU : public MemObject protected: std::vector<ThreadContext *> threadContexts; + std::vector<TheISA::Predecoder *> predecoders; public: @@ -196,7 +202,7 @@ class BaseCPU : public MemObject /// Take over execution from the given CPU. Used for warm-up and /// sampling. - virtual void takeOverFrom(BaseCPU *); + virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc); /** * Number of threads we're actually simulating (<= SMT_MAX_THREADS). diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index d6cd9409b..a6af98d66 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -244,7 +244,7 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) !(unverifiedReq->isUncacheable()) && (!(unverifiedReq->isLocked()) || ((unverifiedReq->isLocked()) && - unverifiedReq->getScResult() == 1))) { + unverifiedReq->getExtraData() == 1))) { T inst_data; /* // This code would work if the LSQ allowed for snooping. @@ -269,7 +269,7 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) // doesn't check if the SC should succeed or fail, it just checks the // value. if (res && unverifiedReq->scResultValid()) - *res = unverifiedReq->getScResult(); + *res = unverifiedReq->getExtraData(); return NoFault; } diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 3e08193ee..7b3628986 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -298,27 +298,27 @@ class CheckerCPU : public BaseCPU thread->setNextPC(val); } - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg) { - return thread->readMiscReg(misc_reg); + return thread->readMiscRegNoEffect(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) + MiscReg readMiscReg(int misc_reg) { - return thread->readMiscRegWithEffect(misc_reg); + return thread->readMiscReg(misc_reg); } - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { result.integer = val; miscRegIdxs.push(misc_reg); - return thread->setMiscReg(misc_reg, val); + return thread->setMiscRegNoEffect(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val) { miscRegIdxs.push(misc_reg); - return thread->setMiscRegWithEffect(misc_reg, val); + return thread->setMiscReg(misc_reg, val); } void recordPCChange(uint64_t val) { changedPC = true; newPC = val; } diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh index 56e13dd1e..f3f8a0bb3 100644 --- a/src/cpu/checker/cpu_impl.hh +++ b/src/cpu/checker/cpu_impl.hh @@ -386,13 +386,13 @@ Checker<DynInstPtr>::validateExecution(DynInstPtr &inst) int misc_reg_idx = miscRegIdxs.front(); miscRegIdxs.pop(); - if (inst->tcBase()->readMiscReg(misc_reg_idx) != - thread->readMiscReg(misc_reg_idx)) { + if (inst->tcBase()->readMiscRegNoEffect(misc_reg_idx) != + thread->readMiscRegNoEffect(misc_reg_idx)) { warn("%lli: Misc reg idx %i (side effect) does not match! " "Inst: %#x, checker: %#x", curTick, misc_reg_idx, - inst->tcBase()->readMiscReg(misc_reg_idx), - thread->readMiscReg(misc_reg_idx)); + inst->tcBase()->readMiscRegNoEffect(misc_reg_idx), + thread->readMiscRegNoEffect(misc_reg_idx)); handleError(inst); } } @@ -432,7 +432,7 @@ Checker<DynInstPtr>::copyResult(DynInstPtr &inst) } else if (idx < TheISA::Fpcr_DepTag) { thread->setFloatRegBits(idx, inst->readIntResult()); } else { - thread->setMiscReg(idx, inst->readIntResult()); + thread->setMiscRegNoEffect(idx, inst->readIntResult()); } } diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index cf36d8392..3b4d21e13 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -248,11 +248,17 @@ class CheckerThreadContext : public ThreadContext checkerCPU->recordNextPCChange(val); } + MiscReg readMiscRegNoEffect(int misc_reg) + { return actualTC->readMiscRegNoEffect(misc_reg); } + MiscReg readMiscReg(int misc_reg) { return actualTC->readMiscReg(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) - { return actualTC->readMiscRegWithEffect(misc_reg); } + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) + { + checkerTC->setMiscRegNoEffect(misc_reg, val); + actualTC->setMiscRegNoEffect(misc_reg, val); + } void setMiscReg(int misc_reg, const MiscReg &val) { @@ -260,12 +266,6 @@ class CheckerThreadContext : public ThreadContext actualTC->setMiscReg(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) - { - checkerTC->setMiscRegWithEffect(misc_reg, val); - actualTC->setMiscRegWithEffect(misc_reg, val); - } - unsigned readStCondFailures() { return actualTC->readStCondFailures(); } diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh index edccd747f..2b9fe4bcf 100644 --- a/src/cpu/exec_context.hh +++ b/src/cpu/exec_context.hh @@ -100,18 +100,18 @@ class ExecContext { void setNextNPC(uint64_t val); /** Reads a miscellaneous register. */ - MiscReg readMiscReg(int misc_reg); + MiscReg readMiscRegNoEffect(int misc_reg); /** Reads a miscellaneous register, handling any architectural * side effects due to reading that register. */ - MiscReg readMiscRegWithEffect(int misc_reg); + MiscReg readMiscReg(int misc_reg); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const MiscReg &val); + void setMiscRegNoEffect(int misc_reg, const MiscReg &val); /** Sets a miscellaneous register, handling any architectural * side effects due to writing that register. */ - void setMiscRegWithEffect(int misc_reg, const MiscReg &val); + void setMiscReg(int misc_reg, const MiscReg &val); /** Records the effective address of the instruction. Only valid * for memory ops. */ diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 5108d7338..c568b1439 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -31,14 +31,17 @@ * Steve Raasch */ +#include <errno.h> #include <fstream> #include <iomanip> #include <sys/ipc.h> #include <sys/shm.h> +#include "arch/predecoder.hh" #include "arch/regfile.hh" #include "arch/utility.hh" #include "base/loader/symtab.hh" +#include "base/socket.hh" #include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" @@ -64,6 +67,28 @@ static bool wasMicro = false; namespace Trace { SharedData *shared_data = NULL; +ListenSocket *cosim_listener = NULL; + +void +setupSharedData() +{ + int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777); + if (shmfd < 0) + fatal("Couldn't get shared memory fd. Is Legion running?"); + + shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND); + if (shared_data == (SharedData*)-1) + fatal("Couldn't allocate shared memory"); + + if (shared_data->flags != OWN_M5) + fatal("Shared memory has invalid owner"); + + if (shared_data->version != VERSION) + fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION, + shared_data->version); + + // step legion forward one cycle so we can get register values + shared_data->flags = OWN_LEGION; } //////////////////////////////////////////////////////////////////////// @@ -123,12 +148,101 @@ inline void printLevelHeader(ostream & os, int level) #endif void -Trace::InstRecord::dump(ostream &outs) +Trace::InstRecord::dump() { + ostream &outs = Trace::output(); + DPRINTF(Sparc, "Instruction: %#X\n", staticInst->machInst); - if (flags[PRINT_REG_DELTA]) + bool diff = true; + if (IsOn(ExecRegDelta)) { + diff = false; +#ifndef NDEBUG #if THE_ISA == SPARC_ISA + static int fd = 0; + //Don't print what happens for each micro-op, just print out + //once at the last op, and for regular instructions. + if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) + { + if(!cosim_listener) + { + int port = 8000; + cosim_listener = new ListenSocket(); + while(!cosim_listener->listen(port, true)) + { + DPRINTF(GDBMisc, "Can't bind port %d\n", port); + port++; + } + ccprintf(cerr, "Listening for cosimulator on port %d\n", port); + fd = cosim_listener->accept(); + } + char prefix[] = "goli"; + for(int p = 0; p < 4; p++) + { + for(int i = 0; i < 8; i++) + { + uint64_t regVal; + int res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + uint64_t realRegVal = thread->readIntReg(p * 8 + i); + if((regVal & 0xffffffffULL) != (realRegVal & 0xffffffffULL)) + { + DPRINTF(ExecRegDelta, "Register %s%d should be %#x but is %#x.\n", prefix[p], i, regVal, realRegVal); + diff = true; + } + //ccprintf(outs, "%s%d m5 = %#x statetrace = %#x\n", prefix[p], i, realRegVal, regVal); + } + } + /*for(int f = 0; f <= 62; f+=2) + { + uint64_t regVal; + int res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + uint64_t realRegVal = thread->readFloatRegBits(f, 64); + if(regVal != realRegVal) + { + DPRINTF(ExecRegDelta, "Register f%d should be %#x but is %#x.\n", f, regVal, realRegVal); + } + }*/ + uint64_t regVal; + int res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + uint64_t realRegVal = thread->readNextPC(); + if(regVal != realRegVal) + { + DPRINTF(ExecRegDelta, "Register pc should be %#x but is %#x.\n", regVal, realRegVal); + diff = true; + } + res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + realRegVal = thread->readNextNPC(); + if(regVal != realRegVal) + { + DPRINTF(ExecRegDelta, "Register npc should be %#x but is %#x.\n", regVal, realRegVal); + diff = true; + } + res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + realRegVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2); + if((regVal & 0xF) != (realRegVal & 0xF)) + { + DPRINTF(ExecRegDelta, "Register ccr should be %#x but is %#x.\n", regVal, realRegVal); + diff = true; + } + } +#endif +#endif +#if 0 //THE_ISA == SPARC_ISA //Don't print what happens for each micro-op, just print out //once at the last op, and for regular instructions. if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) @@ -148,14 +262,14 @@ Trace::InstRecord::dump(ostream &outs) outs << "PC = " << thread->readNextPC(); outs << " NPC = " << thread->readNextNPC(); newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2); - //newVal = thread->readMiscReg(SparcISA::MISCREG_CCR); + //newVal = thread->readMiscRegNoEffect(SparcISA::MISCREG_CCR); if(newVal != ccr) { outs << " CCR = " << newVal; ccr = newVal; } newVal = thread->readIntReg(SparcISA::NumIntArchRegs + 1); - //newVal = thread->readMiscReg(SparcISA::MISCREG_Y); + //newVal = thread->readMiscRegNoEffect(SparcISA::MISCREG_Y); if(newVal != y) { outs << " Y = " << newVal; @@ -187,34 +301,26 @@ Trace::InstRecord::dump(ostream &outs) } #endif } - else if (flags[INTEL_FORMAT]) { -#if FULL_SYSTEM - bool is_trace_system = (thread->getCpuPtr()->system->name() == trace_system); -#else - bool is_trace_system = true; -#endif - if (is_trace_system) { - ccprintf(outs, "%7d ) ", cycle); - outs << "0x" << hex << PC << ":\t"; - if (staticInst->isLoad()) { - outs << "<RD 0x" << hex << addr; - outs << ">"; - } else if (staticInst->isStore()) { - outs << "<WR 0x" << hex << addr; - outs << ">"; - } - outs << endl; + if(!diff) { + } else if (IsOn(ExecIntel)) { + ccprintf(outs, "%7d ) ", when); + outs << "0x" << hex << PC << ":\t"; + if (staticInst->isLoad()) { + ccprintf(outs, "<RD %#x>", addr); + } else if (staticInst->isStore()) { + ccprintf(outs, "<WR %#x>", addr); } + outs << endl; } else { - if (flags[PRINT_CYCLE]) - ccprintf(outs, "%7d: ", cycle); + if (IsOn(ExecTicks)) + ccprintf(outs, "%7d: ", when); outs << thread->getCpuPtr()->name() << " "; - if (flags[TRACE_MISSPEC]) + if (IsOn(ExecSpeculative)) outs << (misspeculating ? "-" : "+") << " "; - if (flags[PRINT_THREAD_NUM]) + if (IsOn(ExecThread)) outs << "T" << thread->getThreadNum() << " : "; @@ -222,7 +328,7 @@ Trace::InstRecord::dump(ostream &outs) Addr sym_addr; if (debugSymbolTable && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr) - && flags[PC_SYMBOL]) { + && IsOn(ExecSymbol)) { if (PC != sym_addr) sym_str += csprintf("+%d", PC - sym_addr); outs << "@" << sym_str << " : "; @@ -248,11 +354,11 @@ Trace::InstRecord::dump(ostream &outs) outs << " : "; - if (flags[PRINT_OP_CLASS]) { + if (IsOn(ExecOpClass)) { outs << opClassStrings[staticInst->opClass()] << " : "; } - if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) { + if (IsOn(ExecResult) && data_status != DataInvalid) { outs << " D="; #if 0 if (data_status == DataDouble) @@ -264,10 +370,10 @@ Trace::InstRecord::dump(ostream &outs) #endif } - if (flags[PRINT_EFF_ADDR] && addr_valid) + if (IsOn(ExecEffAddr) && addr_valid) outs << " A=0x" << hex << addr; - if (flags[PRINT_INT_REGS] && regs_valid) { + if (IsOn(ExecIntRegs) && regs_valid) { for (int i = 0; i < TheISA::NumIntRegs;) for (int j = i + 1; i <= j; i++) ccprintf(outs, "r%02d = %#018x%s", i, @@ -276,10 +382,10 @@ Trace::InstRecord::dump(ostream &outs) outs << "\n"; } - if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid) + if (IsOn(ExecFetchSeq) && fetch_seq_valid) outs << " FetchSeq=" << dec << fetch_seq; - if (flags[PRINT_CP_SEQ] && cp_seq_valid) + if (IsOn(ExecCPSeq) && cp_seq_valid) outs << " CPSeq=" << dec << cp_seq; // @@ -288,8 +394,9 @@ Trace::InstRecord::dump(ostream &outs) outs << endl; } #if THE_ISA == SPARC_ISA && FULL_SYSTEM + static TheISA::Predecoder predecoder(NULL); // Compare - if (flags[LEGION_LOCKSTEP]) + if (IsOn(ExecLegion)) { bool compared = false; bool diffPC = false; @@ -321,10 +428,13 @@ Trace::InstRecord::dump(ostream &outs) bool diffTlb = false; Addr m5Pc, lgnPc; + if (!shared_data) + setupSharedData(); + // We took a trap on a micro-op... if (wasMicro && !staticInst->isMicroOp()) { - // let's skip comparing this cycle + // let's skip comparing this tick while (!compared) if (shared_data->flags == OWN_M5) { shared_data->flags = OWN_LEGION; @@ -370,30 +480,30 @@ Trace::InstRecord::dump(ostream &outs) diffFpRegs = true; } } - uint64_t oldTl = thread->readMiscReg(MISCREG_TL); + uint64_t oldTl = thread->readMiscRegNoEffect(MISCREG_TL); if (oldTl != shared_data->tl) diffTl = true; for (int i = 1; i <= MaxTL; i++) { - thread->setMiscReg(MISCREG_TL, i); - if (thread->readMiscReg(MISCREG_TPC) != + thread->setMiscRegNoEffect(MISCREG_TL, i); + if (thread->readMiscRegNoEffect(MISCREG_TPC) != shared_data->tpc[i-1]) diffTpc = true; - if (thread->readMiscReg(MISCREG_TNPC) != + if (thread->readMiscRegNoEffect(MISCREG_TNPC) != shared_data->tnpc[i-1]) diffTnpc = true; - if (thread->readMiscReg(MISCREG_TSTATE) != + if (thread->readMiscRegNoEffect(MISCREG_TSTATE) != shared_data->tstate[i-1]) diffTstate = true; - if (thread->readMiscReg(MISCREG_TT) != + if (thread->readMiscRegNoEffect(MISCREG_TT) != shared_data->tt[i-1]) diffTt = true; - if (thread->readMiscReg(MISCREG_HTSTATE) != + if (thread->readMiscRegNoEffect(MISCREG_HTSTATE) != shared_data->htstate[i-1]) diffHtstate = true; } - thread->setMiscReg(MISCREG_TL, oldTl); + thread->setMiscRegNoEffect(MISCREG_TL, oldTl); - if(shared_data->tba != thread->readMiscReg(MISCREG_TBA)) + if(shared_data->tba != thread->readMiscRegNoEffect(MISCREG_TBA)) diffTba = true; //When the hpstate register is read by an instruction, //legion has bit 11 set. When it's in storage, it doesn't. @@ -401,50 +511,50 @@ Trace::InstRecord::dump(ostream &outs) //of the registers like that, the bit is always set to 1 and //we just don't compare it. It's not supposed to matter //anyway. - if((shared_data->hpstate | (1 << 11)) != thread->readMiscReg(MISCREG_HPSTATE)) + if((shared_data->hpstate | (1 << 11)) != thread->readMiscRegNoEffect(MISCREG_HPSTATE)) diffHpstate = true; - if(shared_data->htba != thread->readMiscReg(MISCREG_HTBA)) + if(shared_data->htba != thread->readMiscRegNoEffect(MISCREG_HTBA)) diffHtba = true; - if(shared_data->pstate != thread->readMiscReg(MISCREG_PSTATE)) + if(shared_data->pstate != thread->readMiscRegNoEffect(MISCREG_PSTATE)) diffPstate = true; - //if(shared_data->y != thread->readMiscReg(MISCREG_Y)) + //if(shared_data->y != thread->readMiscRegNoEffect(MISCREG_Y)) if(shared_data->y != thread->readIntReg(NumIntArchRegs + 1)) diffY = true; - if(shared_data->fsr != thread->readMiscReg(MISCREG_FSR)) { + if(shared_data->fsr != thread->readMiscRegNoEffect(MISCREG_FSR)) { diffFsr = true; if (mbits(shared_data->fsr, 63,10) == - mbits(thread->readMiscReg(MISCREG_FSR), 63,10)) { - thread->setMiscReg(MISCREG_FSR, shared_data->fsr); + mbits(thread->readMiscRegNoEffect(MISCREG_FSR), 63,10)) { + thread->setMiscRegNoEffect(MISCREG_FSR, shared_data->fsr); diffFsr = false; } } - //if(shared_data->ccr != thread->readMiscReg(MISCREG_CCR)) + //if(shared_data->ccr != thread->readMiscRegNoEffect(MISCREG_CCR)) if(shared_data->ccr != thread->readIntReg(NumIntArchRegs + 2)) diffCcr = true; - if(shared_data->gl != thread->readMiscReg(MISCREG_GL)) + if(shared_data->gl != thread->readMiscRegNoEffect(MISCREG_GL)) diffGl = true; - if(shared_data->asi != thread->readMiscReg(MISCREG_ASI)) + if(shared_data->asi != thread->readMiscRegNoEffect(MISCREG_ASI)) diffAsi = true; - if(shared_data->pil != thread->readMiscReg(MISCREG_PIL)) + if(shared_data->pil != thread->readMiscRegNoEffect(MISCREG_PIL)) diffPil = true; - if(shared_data->cwp != thread->readMiscReg(MISCREG_CWP)) + if(shared_data->cwp != thread->readMiscRegNoEffect(MISCREG_CWP)) diffCwp = true; - //if(shared_data->cansave != thread->readMiscReg(MISCREG_CANSAVE)) + //if(shared_data->cansave != thread->readMiscRegNoEffect(MISCREG_CANSAVE)) if(shared_data->cansave != thread->readIntReg(NumIntArchRegs + 3)) diffCansave = true; //if(shared_data->canrestore != - // thread->readMiscReg(MISCREG_CANRESTORE)) + // thread->readMiscRegNoEffect(MISCREG_CANRESTORE)) if(shared_data->canrestore != thread->readIntReg(NumIntArchRegs + 4)) diffCanrestore = true; - //if(shared_data->otherwin != thread->readMiscReg(MISCREG_OTHERWIN)) + //if(shared_data->otherwin != thread->readMiscRegNoEffect(MISCREG_OTHERWIN)) if(shared_data->otherwin != thread->readIntReg(NumIntArchRegs + 6)) diffOtherwin = true; - //if(shared_data->cleanwin != thread->readMiscReg(MISCREG_CLEANWIN)) + //if(shared_data->cleanwin != thread->readMiscRegNoEffect(MISCREG_CLEANWIN)) if(shared_data->cleanwin != thread->readIntReg(NumIntArchRegs + 5)) diffCleanwin = true; @@ -539,9 +649,13 @@ Trace::InstRecord::dump(ostream &outs) << staticInst->disassemble(m5Pc, debugSymbolTable) << endl; + predecoder.setTC(thread); + predecoder.moreBytes(m5Pc, 0, shared_data->instruction); + + assert(predecoder.extMachInstRead()); + StaticInstPtr legionInst = - StaticInst::decode(makeExtMI(shared_data->instruction, - thread)); + StaticInst::decode(predecoder.getExtMachInst()); outs << setfill(' ') << setw(15) << " Legion Inst: " << "0x" << setw(8) << setfill('0') << hex @@ -552,78 +666,78 @@ Trace::InstRecord::dump(ostream &outs) printSectionHeader(outs, "General State"); printColumnLabels(outs); printRegPair(outs, "HPstate", - thread->readMiscReg(MISCREG_HPSTATE), + thread->readMiscRegNoEffect(MISCREG_HPSTATE), shared_data->hpstate | (1 << 11)); printRegPair(outs, "Htba", - thread->readMiscReg(MISCREG_HTBA), + thread->readMiscRegNoEffect(MISCREG_HTBA), shared_data->htba); printRegPair(outs, "Pstate", - thread->readMiscReg(MISCREG_PSTATE), + thread->readMiscRegNoEffect(MISCREG_PSTATE), shared_data->pstate); printRegPair(outs, "Y", - //thread->readMiscReg(MISCREG_Y), + //thread->readMiscRegNoEffect(MISCREG_Y), thread->readIntReg(NumIntArchRegs + 1), shared_data->y); printRegPair(outs, "FSR", - thread->readMiscReg(MISCREG_FSR), + thread->readMiscRegNoEffect(MISCREG_FSR), shared_data->fsr); printRegPair(outs, "Ccr", - //thread->readMiscReg(MISCREG_CCR), + //thread->readMiscRegNoEffect(MISCREG_CCR), thread->readIntReg(NumIntArchRegs + 2), shared_data->ccr); printRegPair(outs, "Tl", - thread->readMiscReg(MISCREG_TL), + thread->readMiscRegNoEffect(MISCREG_TL), shared_data->tl); printRegPair(outs, "Gl", - thread->readMiscReg(MISCREG_GL), + thread->readMiscRegNoEffect(MISCREG_GL), shared_data->gl); printRegPair(outs, "Asi", - thread->readMiscReg(MISCREG_ASI), + thread->readMiscRegNoEffect(MISCREG_ASI), shared_data->asi); printRegPair(outs, "Pil", - thread->readMiscReg(MISCREG_PIL), + thread->readMiscRegNoEffect(MISCREG_PIL), shared_data->pil); printRegPair(outs, "Cwp", - thread->readMiscReg(MISCREG_CWP), + thread->readMiscRegNoEffect(MISCREG_CWP), shared_data->cwp); printRegPair(outs, "Cansave", - //thread->readMiscReg(MISCREG_CANSAVE), + //thread->readMiscRegNoEffect(MISCREG_CANSAVE), thread->readIntReg(NumIntArchRegs + 3), shared_data->cansave); printRegPair(outs, "Canrestore", - //thread->readMiscReg(MISCREG_CANRESTORE), + //thread->readMiscRegNoEffect(MISCREG_CANRESTORE), thread->readIntReg(NumIntArchRegs + 4), shared_data->canrestore); printRegPair(outs, "Otherwin", - //thread->readMiscReg(MISCREG_OTHERWIN), + //thread->readMiscRegNoEffect(MISCREG_OTHERWIN), thread->readIntReg(NumIntArchRegs + 6), shared_data->otherwin); printRegPair(outs, "Cleanwin", - //thread->readMiscReg(MISCREG_CLEANWIN), + //thread->readMiscRegNoEffect(MISCREG_CLEANWIN), thread->readIntReg(NumIntArchRegs + 5), shared_data->cleanwin); outs << endl; for (int i = 1; i <= MaxTL; i++) { printLevelHeader(outs, i); printColumnLabels(outs); - thread->setMiscReg(MISCREG_TL, i); + thread->setMiscRegNoEffect(MISCREG_TL, i); printRegPair(outs, "Tpc", - thread->readMiscReg(MISCREG_TPC), + thread->readMiscRegNoEffect(MISCREG_TPC), shared_data->tpc[i-1]); printRegPair(outs, "Tnpc", - thread->readMiscReg(MISCREG_TNPC), + thread->readMiscRegNoEffect(MISCREG_TNPC), shared_data->tnpc[i-1]); printRegPair(outs, "Tstate", - thread->readMiscReg(MISCREG_TSTATE), + thread->readMiscRegNoEffect(MISCREG_TSTATE), shared_data->tstate[i-1]); printRegPair(outs, "Tt", - thread->readMiscReg(MISCREG_TT), + thread->readMiscRegNoEffect(MISCREG_TT), shared_data->tt[i-1]); printRegPair(outs, "Htstate", - thread->readMiscReg(MISCREG_HTSTATE), + thread->readMiscRegNoEffect(MISCREG_HTSTATE), shared_data->htstate[i-1]); } - thread->setMiscReg(MISCREG_TL, oldTl); + thread->setMiscRegNoEffect(MISCREG_TL, oldTl); outs << endl; printSectionHeader(outs, "General Purpose Registers"); @@ -684,110 +798,4 @@ Trace::InstRecord::dump(ostream &outs) #endif } - -vector<bool> Trace::InstRecord::flags(NUM_BITS); -string Trace::InstRecord::trace_system; - -//////////////////////////////////////////////////////////////////////// -// -// Parameter space for per-cycle execution address tracing options. -// Derive from ParamContext so we can override checkParams() function. -// -class ExecutionTraceParamContext : public ParamContext -{ - public: - ExecutionTraceParamContext(const string &_iniSection) - : ParamContext(_iniSection) - { - } - - void checkParams(); // defined at bottom of file -}; - -ExecutionTraceParamContext exeTraceParams("exetrace"); - -Param<bool> exe_trace_spec(&exeTraceParams, "speculative", - "capture speculative instructions", true); - -Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle", - "print cycle number", true); -Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass", - "print op class", true); -Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread", - "print thread number", true); -Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr", - "print effective address", true); -Param<bool> exe_trace_print_data(&exeTraceParams, "print_data", - "print result data", true); -Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs", - "print all integer regs", false); -Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq", - "print fetch sequence number", false); -Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq", - "print correct-path sequence number", false); -Param<bool> exe_trace_print_reg_delta(&exeTraceParams, "print_reg_delta", - "print which registers changed to what", false); -Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol", - "Use symbols for the PC if available", true); -Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format", - "print trace in intel compatible format", false); -Param<bool> exe_trace_legion_lockstep(&exeTraceParams, "legion_lockstep", - "Compare sim state to legion state every cycle", - false); -Param<string> exe_trace_system(&exeTraceParams, "trace_system", - "print trace of which system (client or server)", - "client"); - - -// -// Helper function for ExecutionTraceParamContext::checkParams() just -// to get us into the InstRecord namespace -// -void -Trace::InstRecord::setParams() -{ - flags[TRACE_MISSPEC] = exe_trace_spec; - - flags[PRINT_CYCLE] = exe_trace_print_cycle; - flags[PRINT_OP_CLASS] = exe_trace_print_opclass; - flags[PRINT_THREAD_NUM] = exe_trace_print_thread; - flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr; - flags[PRINT_EFF_ADDR] = exe_trace_print_data; - flags[PRINT_INT_REGS] = exe_trace_print_iregs; - flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq; - flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq; - flags[PRINT_REG_DELTA] = exe_trace_print_reg_delta; - flags[PC_SYMBOL] = exe_trace_pc_symbol; - flags[INTEL_FORMAT] = exe_trace_intel_format; - flags[LEGION_LOCKSTEP] = exe_trace_legion_lockstep; - trace_system = exe_trace_system; - - // If were going to be in lockstep with Legion - // Setup shared memory, and get otherwise ready - if (flags[LEGION_LOCKSTEP]) { - int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777); - if (shmfd < 0) - fatal("Couldn't get shared memory fd. Is Legion running?"); - - shared_data = (SharedData*)shmat(shmfd, NULL, SHM_RND); - if (shared_data == (SharedData*)-1) - fatal("Couldn't allocate shared memory"); - - if (shared_data->flags != OWN_M5) - fatal("Shared memory has invalid owner"); - - if (shared_data->version != VERSION) - fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION, - shared_data->version); - - // step legion forward one cycle so we can get register values - shared_data->flags = OWN_LEGION; - } -} - -void -ExecutionTraceParamContext::checkParams() -{ - Trace::InstRecord::setParams(); -} - +/* namespace Trace */ } diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index a825f6a82..8c0fa22cb 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -36,22 +36,24 @@ #include <fstream> #include <vector> -#include "sim/host.hh" -#include "cpu/inst_seq.hh" // for InstSeqNum #include "base/trace.hh" -#include "cpu/thread_context.hh" +#include "cpu/inst_seq.hh" // for InstSeqNum #include "cpu/static_inst.hh" +#include "cpu/thread_context.hh" +#include "sim/host.hh" class ThreadContext; namespace Trace { -class InstRecord : public Record +class InstRecord { protected: typedef TheISA::IntRegFile IntRegFile; + Tick when; + // The following fields are initialized by the constructor and // thus guaranteed to be valid. ThreadContext *thread; @@ -95,10 +97,10 @@ class InstRecord : public Record bool regs_valid; public: - InstRecord(Tick _cycle, ThreadContext *_thread, + InstRecord(Tick _when, ThreadContext *_thread, const StaticInstPtr &_staticInst, Addr _pc, bool spec) - : Record(_cycle), thread(_thread), + : when(_when), thread(_thread), staticInst(_staticInst), PC(_pc), misspeculating(spec) { @@ -110,12 +112,12 @@ class InstRecord : public Record cp_seq_valid = false; } - virtual ~InstRecord() { } - - virtual void dump(std::ostream &outs); + ~InstRecord() { } void setAddr(Addr a) { addr = a; addr_valid = true; } + void setData(Twin64_t d) { data.as_int = d.a; data_status = DataInt64; } + void setData(Twin32_t d) { data.as_int = d.a; data_status = DataInt32; } void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; } void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; } void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; } @@ -136,31 +138,7 @@ class InstRecord : public Record void setRegs(const IntRegFile ®s); - void finalize() { theLog.append(this); } - - enum InstExecFlagBits { - TRACE_MISSPEC = 0, - PRINT_CYCLE, - PRINT_OP_CLASS, - PRINT_THREAD_NUM, - PRINT_RESULT_DATA, - PRINT_EFF_ADDR, - PRINT_INT_REGS, - PRINT_FETCH_SEQ, - PRINT_CP_SEQ, - PRINT_REG_DELTA, - PC_SYMBOL, - INTEL_FORMAT, - LEGION_LOCKSTEP, - NUM_BITS - }; - - static std::vector<bool> flags; - static std::string trace_system; - - static void setParams(); - - static bool traceMisspec() { return flags[TRACE_MISSPEC]; } + void dump(); }; @@ -174,22 +152,22 @@ InstRecord::setRegs(const IntRegFile ®s) regs_valid = true; } -inline -InstRecord * -getInstRecord(Tick cycle, ThreadContext *tc, - const StaticInstPtr staticInst, +inline InstRecord * +getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst, Addr pc) { - if (DTRACE(InstExec) && - (InstRecord::traceMisspec() || !tc->misspeculating())) { - return new InstRecord(cycle, tc, staticInst, pc, - tc->misspeculating()); - } + if (!IsOn(ExecEnable)) + return NULL; - return NULL; -} + if (!Trace::enabled) + return NULL; + if (!IsOn(ExecSpeculative) && tc->misspeculating()) + return NULL; + return new InstRecord(when, tc, staticInst, pc, tc->misspeculating()); } +/* namespace Trace */ } + #endif // __EXETRACE_HH__ diff --git a/src/cpu/intr_control.cc b/src/cpu/intr_control.cc index 4cbc86891..be0f6599b 100644 --- a/src/cpu/intr_control.cc +++ b/src/cpu/intr_control.cc @@ -40,18 +40,14 @@ using namespace std; -IntrControl::IntrControl(const string &name, BaseCPU *c) - : SimObject(name), cpu(c) +IntrControl::IntrControl(const string &name, System *s) + : SimObject(name), sys(s) {} -/* @todo - *Fix the cpu sim object parameter to be a system pointer - *instead, to avoid some extra dereferencing - */ void IntrControl::post(int int_num, int index) { - std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts; + std::vector<ThreadContext *> &tcvec = sys->threadContexts; BaseCPU *temp = tcvec[0]->getCpuPtr(); temp->post_interrupt(int_num, index); } @@ -59,7 +55,7 @@ IntrControl::post(int int_num, int index) void IntrControl::post(int cpu_id, int int_num, int index) { - std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts; + std::vector<ThreadContext *> &tcvec = sys->threadContexts; BaseCPU *temp = tcvec[cpu_id]->getCpuPtr(); temp->post_interrupt(int_num, index); } @@ -67,7 +63,7 @@ IntrControl::post(int cpu_id, int int_num, int index) void IntrControl::clear(int int_num, int index) { - std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts; + std::vector<ThreadContext *> &tcvec = sys->threadContexts; BaseCPU *temp = tcvec[0]->getCpuPtr(); temp->clear_interrupt(int_num, index); } @@ -75,26 +71,26 @@ IntrControl::clear(int int_num, int index) void IntrControl::clear(int cpu_id, int int_num, int index) { - std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts; + std::vector<ThreadContext *> &tcvec = sys->threadContexts; BaseCPU *temp = tcvec[cpu_id]->getCpuPtr(); temp->clear_interrupt(int_num, index); } BEGIN_DECLARE_SIM_OBJECT_PARAMS(IntrControl) - SimObjectParam<BaseCPU *> cpu; + SimObjectParam<System *> sys; END_DECLARE_SIM_OBJECT_PARAMS(IntrControl) BEGIN_INIT_SIM_OBJECT_PARAMS(IntrControl) - INIT_PARAM(cpu, "the cpu") + INIT_PARAM(sys, "the system we are part of") END_INIT_SIM_OBJECT_PARAMS(IntrControl) CREATE_SIM_OBJECT(IntrControl) { - return new IntrControl(getInstanceName(), cpu); + return new IntrControl(getInstanceName(), sys); } REGISTER_SIM_OBJECT("IntrControl", IntrControl) diff --git a/src/cpu/intr_control.hh b/src/cpu/intr_control.hh index 2e3f9e038..c6f75abf0 100644 --- a/src/cpu/intr_control.hh +++ b/src/cpu/intr_control.hh @@ -42,8 +42,8 @@ class IntrControl : public SimObject { public: - BaseCPU *cpu; - IntrControl(const std::string &name, BaseCPU *c); + System *sys; + IntrControl(const std::string &name, System *s); void clear(int int_num, int index = 0); void post(int int_num, int index = 0); diff --git a/src/cpu/memtest/SConscript b/src/cpu/memtest/SConscript new file mode 100644 index 000000000..7b4d6d2c5 --- /dev/null +++ b/src/cpu/memtest/SConscript @@ -0,0 +1,34 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +if 'O3CPU' in env['CPU_MODELS']: + Source('memtest.cc') diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc index 180f41541..607cf1066 100644 --- a/src/cpu/memtest/memtest.cc +++ b/src/cpu/memtest/memtest.cc @@ -226,8 +226,8 @@ MemTest::completeRequest(PacketPtr pkt) assert(removeAddr != outstandingAddrs.end()); outstandingAddrs.erase(removeAddr); - switch (pkt->cmd) { - case Packet::ReadResp: + switch (pkt->cmd.toInt()) { + case MemCmd::ReadResp: if (memcmp(pkt_data, data, pkt->getSize()) != 0) { cerr << name() << ": on read of 0x" << hex << req->getPaddr() @@ -254,7 +254,7 @@ MemTest::completeRequest(PacketPtr pkt) exitSimLoop("Maximum number of loads reached!"); break; - case Packet::WriteResp: + case MemCmd::WriteResp: numWritesStat++; break; /* @@ -369,7 +369,7 @@ MemTest::tick() //This means we assume CPU does write forwarding to reads that alias something //in the cpu store buffer. if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) { - delete result; + delete [] result; delete req; return; } @@ -389,7 +389,7 @@ MemTest::tick() << dec << curTick << endl; } - PacketPtr pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); + PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast); pkt->dataDynamicArray(new uint8_t[req->getSize()]); MemTestSenderState *state = new MemTestSenderState(result); pkt->senderState = state; @@ -429,7 +429,7 @@ MemTest::tick() << dec << curTick << endl; } */ - PacketPtr pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); + PacketPtr pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast); uint8_t *pkt_data = new uint8_t[req->getSize()]; pkt->dataDynamicArray(pkt_data); memcpy(pkt_data, &data, req->getSize()); diff --git a/src/cpu/o3/SConscript b/src/cpu/o3/SConscript index afbd4c533..bb1dfb613 100755 --- a/src/cpu/o3/SConscript +++ b/src/cpu/o3/SConscript @@ -26,52 +26,56 @@ # (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: Korey Sewell +# Authors: Nathan Binkert -import os -import os.path import sys -# Import build environment variable from SConstruct. -Import('env') +Import('*') +if 'O3CPU' in env['CPU_MODELS']: + Source('base_dyn_inst.cc') + Source('bpred_unit.cc') + Source('commit.cc') + Source('cpu.cc') + Source('decode.cc') + Source('fetch.cc') + Source('free_list.cc') + Source('fu_pool.cc') + Source('iew.cc') + Source('inst_queue.cc') + Source('lsq.cc') + Source('lsq_unit.cc') + Source('mem_dep_unit.cc') + Source('rename.cc') + Source('rename_map.cc') + Source('rob.cc') + Source('scoreboard.cc') + Source('store_set.cc') -################################################################# -# -# Include ISA-specific files for the O3 CPU-model -# -################################################################# - -sources = [] - -if env['TARGET_ISA'] == 'alpha': - sources += Split(''' - alpha/dyn_inst.cc - alpha/cpu.cc - alpha/thread_context.cc - alpha/cpu_builder.cc - ''') -elif env['TARGET_ISA'] == 'mips': - sources += Split(''' - mips/dyn_inst.cc - mips/cpu.cc - mips/thread_context.cc - mips/cpu_builder.cc - ''') -elif env['TARGET_ISA'] == 'sparc': - sources += Split(''' - sparc/dyn_inst.cc - sparc/cpu.cc - sparc/thread_context.cc - sparc/cpu_builder.cc - ''') -else: - sys.exit('O3 CPU does not support the \'%s\' ISA' % env['TARGET_ISA']) - + if env['TARGET_ISA'] == 'alpha': + Source('alpha/cpu.cc') + Source('alpha/cpu_builder.cc') + Source('alpha/dyn_inst.cc') + Source('alpha/thread_context.cc') + elif env['TARGET_ISA'] == 'mips': + Source('mips/cpu.cc') + Source('mips/cpu_builder.cc') + Source('mips/dyn_inst.cc') + Source('mips/thread_context.cc') + elif env['TARGET_ISA'] == 'sparc': + Source('sparc/cpu.cc') + Source('sparc/cpu_builder.cc') + Source('sparc/dyn_inst.cc') + Source('sparc/thread_context.cc') + else: + sys.exit('O3 CPU does not support the \'%s\' ISA' % env['TARGET_ISA']) -# Convert file names to SCons File objects. This takes care of the -# path relative to the top of the directory tree. -sources = [File(s) for s in sources] + if env['USE_CHECKER']: + Source('checker_builder.cc') -Return('sources') +if 'O3CPU' in env['CPU_MODELS'] or 'OzoneCPU' in env['CPU_MODELS']: + Source('2bit_local_pred.cc') + Source('btb.cc') + Source('ras.cc') + Source('tournament_pred.cc') diff --git a/src/cpu/o3/SConsopts b/src/cpu/o3/SConsopts new file mode 100644 index 000000000..040352e6a --- /dev/null +++ b/src/cpu/o3/SConsopts @@ -0,0 +1,34 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +all_cpu_list.append('O3CPU') +default_cpus.append('O3CPU') diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh index 4a2086296..676893098 100644 --- a/src/cpu/o3/alpha/cpu.hh +++ b/src/cpu/o3/alpha/cpu.hh @@ -106,21 +106,21 @@ class AlphaO3CPU : public FullO3CPU<Impl> #endif /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); /** Reads a misc. register, including any side effects the read * might have as defined by the architecture. */ - TheISA::MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val, + void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid); /** Sets a misc. register, including any side effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val, + void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); /** Initiates a squash of all in-flight instructions for a given diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh index 7799d8f05..304ee6c38 100644 --- a/src/cpu/o3/alpha/cpu_impl.hh +++ b/src/cpu/o3/alpha/cpu_impl.hh @@ -155,32 +155,32 @@ AlphaO3CPU<Impl>::regStats() template <class Impl> TheISA::MiscReg -AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) +AlphaO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid) { - return this->regFile.readMiscReg(misc_reg, tid); + return this->regFile.readMiscRegNoEffect(misc_reg, tid); } template <class Impl> TheISA::MiscReg -AlphaO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid) +AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) { - return this->regFile.readMiscRegWithEffect(misc_reg, tid); + return this->regFile.readMiscReg(misc_reg, tid); } template <class Impl> void -AlphaO3CPU<Impl>::setMiscReg(int misc_reg, const TheISA::MiscReg &val, +AlphaO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid) { - this->regFile.setMiscReg(misc_reg, val, tid); + this->regFile.setMiscRegNoEffect(misc_reg, val, tid); } template <class Impl> void -AlphaO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, +AlphaO3CPU<Impl>::setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid) { - this->regFile.setMiscRegWithEffect(misc_reg, val, tid); + this->regFile.setMiscReg(misc_reg, val, tid); } template <class Impl> @@ -210,7 +210,7 @@ Fault AlphaO3CPU<Impl>::hwrei(unsigned tid) { // Need to clear the lock flag upon returning from an interrupt. - this->setMiscReg(AlphaISA::MISCREG_LOCKFLAG, false, tid); + this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); this->thread[tid]->kernelStats->hwrei(); diff --git a/src/cpu/o3/alpha/dyn_inst.hh b/src/cpu/o3/alpha/dyn_inst.hh index 603a1b52d..20759d849 100644 --- a/src/cpu/o3/alpha/dyn_inst.hh +++ b/src/cpu/o3/alpha/dyn_inst.hh @@ -95,39 +95,39 @@ class AlphaDynInst : public BaseDynInst<Impl> public: /** Reads a miscellaneous register. */ - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg) { - return this->cpu->readMiscReg(misc_reg, this->threadNumber); + return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber); } /** Reads a misc. register, including any side-effects the read * might have as defined by the architecture. */ - MiscReg readMiscRegWithEffect(int misc_reg) + MiscReg readMiscReg(int misc_reg) { - return this->cpu->readMiscRegWithEffect(misc_reg, this->threadNumber); + return this->cpu->readMiscReg(misc_reg, this->threadNumber); } /** Sets a misc. register. */ - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { this->instResult.integer = val; - return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); + return this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber); } /** Sets a misc. register, including any side-effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val) { - return this->cpu->setMiscRegWithEffect(misc_reg, val, + return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); } /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) + TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) { - return this->cpu->readMiscReg( + return this->cpu->readMiscRegNoEffect( si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, this->threadNumber); } @@ -135,18 +135,18 @@ class AlphaDynInst : public BaseDynInst<Impl> /** Reads a misc. register, including any side-effects the read * might have as defined by the architecture. */ - TheISA::MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) { - return this->cpu->readMiscRegWithEffect( + return this->cpu->readMiscReg( si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, this->threadNumber); } /** Sets a misc. register. */ - void setMiscRegOperand(const StaticInst * si, int idx, const MiscReg &val) + void setMiscRegOperandNoEffect(const StaticInst * si, int idx, const MiscReg &val) { this->instResult.integer = val; - return this->cpu->setMiscReg( + return this->cpu->setMiscRegNoEffect( si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, val, this->threadNumber); } @@ -154,10 +154,10 @@ class AlphaDynInst : public BaseDynInst<Impl> /** Sets a misc. register, including any side-effects the write * might have as defined by the architecture. */ - void setMiscRegOperandWithEffect(const StaticInst *si, int idx, + void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val) { - return this->cpu->setMiscRegWithEffect( + return this->cpu->setMiscReg( si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, val, this->threadNumber); } diff --git a/src/cpu/o3/alpha/dyn_inst_impl.hh b/src/cpu/o3/alpha/dyn_inst_impl.hh index 50cdec408..fdce1ade5 100644 --- a/src/cpu/o3/alpha/dyn_inst_impl.hh +++ b/src/cpu/o3/alpha/dyn_inst_impl.hh @@ -118,7 +118,7 @@ AlphaDynInst<Impl>::hwrei() return new AlphaISA::UnimplementedOpcodeFault; // Set the next PC based on the value of the EXC_ADDR IPR. - this->setNextPC(this->cpu->readMiscReg(AlphaISA::IPR_EXC_ADDR, + this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, this->threadNumber)); // Tell CPU to clear any state it needs to if a hwrei is taken. diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index b42a6f523..c17c8836d 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -1148,7 +1148,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) if (head_inst->traceData) { head_inst->traceData->setFetchSeq(head_inst->seqNum); head_inst->traceData->setCPSeq(thread[tid]->numInst); - head_inst->traceData->finalize(); + head_inst->traceData->dump(); + delete head_inst->traceData; head_inst->traceData = NULL; } diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index f9e094d75..354e3c490 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -45,7 +45,7 @@ #include "cpu/o3/isa_specific.hh" #include "cpu/o3/cpu.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/stat_control.hh" #if USE_CHECKER @@ -557,12 +557,6 @@ template <class Impl> void FullO3CPU<Impl>::activateContext(int tid, int delay) { -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - threadContexts[tid]->connectMemPorts(); -#endif - // Needs to set each stage to running as well. if (delay){ DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate " @@ -781,6 +775,18 @@ FullO3CPU<Impl>::activateWhenReady(int tid) } } +#if FULL_SYSTEM +template <class Impl> +void +FullO3CPU<Impl>::updateMemPorts() +{ + // Update all ThreadContext's memory ports (Functional/Virtual + // Ports) + for (int i = 0; i < thread.size(); ++i) + thread[i]->connectMemPorts(); +} +#endif + template <class Impl> void FullO3CPU<Impl>::serialize(std::ostream &os) @@ -941,7 +947,7 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) activityRec.reset(); - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort()); fetch.takeOverFrom(); decode.takeOverFrom(); @@ -978,25 +984,6 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) } if (!tickEvent.scheduled()) tickEvent.schedule(nextCycle()); - - Port *peer; - Port *icachePort = fetch.getIcachePort(); - if (icachePort->getPeer() == NULL) { - peer = oldCPU->getPort("icache_port")->getPeer(); - icachePort->setPeer(peer); - } else { - peer = icachePort->getPeer(); - } - peer->setPeer(icachePort); - - Port *dcachePort = iew.getDcachePort(); - if (dcachePort->getPeer() == NULL) { - peer = oldCPU->getPort("dcache_port")->getPeer(); - dcachePort->setPeer(peer); - } else { - peer = dcachePort->getPeer(); - } - peer->setPeer(dcachePort); } template <class Impl> diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index b47c2a494..0ab20ba2a 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -361,6 +361,10 @@ class FullO3CPU : public BaseO3CPU { return globalSeqNum++; } #if FULL_SYSTEM + /** Update the Virt and Phys ports of all ThreadContexts to + * reflect change in memory connections. */ + void updateMemPorts(); + /** Check if this address is a valid instruction address. */ bool validInstAddr(Addr addr) { return true; } diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 279513493..c37f8007e 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -45,6 +45,10 @@ template <class Impl> class SparcDynInst; struct SparcSimpleImpl; typedef SparcDynInst<SparcSimpleImpl> O3DynInst; +#elif THE_ISA == X86_ISA + template <class Impl> class X86DynInst; + struct X86SimpleImpl; + typedef X86DynInst<X86SimpleImpl> O3DynInst; #else #error "O3DynInst not defined for this ISA" #endif diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 8347ed775..da7ce00f5 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -33,6 +33,7 @@ #define __CPU_O3_FETCH_HH__ #include "arch/utility.hh" +#include "arch/predecoder.hh" #include "base/statistics.hh" #include "base/timebuf.hh" #include "cpu/pc_event.hh" @@ -338,6 +339,9 @@ class DefaultFetch /** BPredUnit. */ BPredUnit branchPred; + /** Predecoder. */ + TheISA::Predecoder predecoder; + /** Per-thread fetch PC. */ Addr PC[Impl::MaxThreads]; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index a8727a425..663cd3142 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -40,7 +40,7 @@ #include "mem/request.hh" #include "sim/byteswap.hh" #include "sim/host.hh" -#include "sim/root.hh" +#include "sim/core.hh" #if FULL_SYSTEM #include "arch/tlb.hh" @@ -103,6 +103,7 @@ DefaultFetch<Impl>::IcachePort::recvRetry() template<class Impl> DefaultFetch<Impl>::DefaultFetch(Params *params) : branchPred(params), + predecoder(NULL), decodeToFetchDelay(params->decodeToFetchDelay), renameToFetchDelay(params->renameToFetchDelay), iewToFetchDelay(params->iewToFetchDelay), @@ -602,7 +603,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid // Build packet here. PacketPtr data_pkt = new Packet(mem_req, - Packet::ReadReq, Packet::Broadcast); + MemCmd::ReadReq, Packet::Broadcast); data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]); cacheDataPC[tid] = block_PC; @@ -1119,13 +1120,10 @@ DefaultFetch<Impl>::fetch(bool &status_change) inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *> (&cacheData[tid][offset])); -#if THE_ISA == ALPHA_ISA - ext_inst = TheISA::makeExtMI(inst, fetch_PC); -#elif THE_ISA == SPARC_ISA - ext_inst = TheISA::makeExtMI(inst, cpu->thread[tid]->getTC()); -#elif THE_ISA == MIPS_ISA - ext_inst = TheISA::makeExtMI(inst, cpu->thread[tid]->getTC()); -#endif + predecoder.setTC(cpu->thread[tid]->getTC()); + predecoder.moreBytes(fetch_PC, 0, inst); + + ext_inst = predecoder.getExtMachInst(); // Create a new DynInst from the instruction fetched. DynInstPtr instruction = new DynInst(ext_inst, diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 87bf60dfa..79e03d4bf 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -32,7 +32,7 @@ #include <limits> #include <vector> -#include "sim/root.hh" +#include "sim/core.hh" #include "cpu/o3/fu_pool.hh" #include "cpu/o3/inst_queue.hh" diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index e68085cfd..80f53a726 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -300,6 +300,8 @@ class LSQ { bool snoopRangeSent; + virtual void setPeer(Port *port); + protected: /** Atomic version of receive. Panics. */ virtual Tick recvAtomic(PacketPtr pkt); @@ -327,6 +329,11 @@ class LSQ { /** D-cache port. */ DcachePort dcachePort; +#if FULL_SYSTEM + /** Tell the CPU to update the Phys and Virt ports. */ + void updateMemPorts() { cpu->updateMemPorts(); } +#endif + protected: /** The LSQ policy for SMT mode. */ LSQPolicy lsqPolicy; diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index fb738f7c9..d4994fcb7 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -34,6 +34,19 @@ #include "cpu/o3/lsq.hh" +template<class Impl> +void +LSQ<Impl>::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + lsq->updateMemPorts(); +#endif +} + template <class Impl> Tick LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index 704d2183d..1b10843f5 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -583,7 +583,8 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx) "addr %#x, data %#x\n", store_idx, req->getVaddr(), data); - PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); + PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq, + Packet::Broadcast); data_pkt->dataStatic(load_inst->memData); WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this); @@ -653,7 +654,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx) // if we the cache is not blocked, do cache access if (!lsq->cacheBlocked()) { PacketPtr data_pkt = - new Packet(req, Packet::ReadReq, Packet::Broadcast); + new Packet(req, MemCmd::ReadReq, Packet::Broadcast); data_pkt->dataStatic(load_inst->memData); LSQSenderState *state = new LSQSenderState; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index ed331386b..e70c960b3 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -656,7 +656,8 @@ LSQUnit<Impl>::writebackStores() (sizeof(TheISA::IntReg) - req->getSize()) : 0), req->getSize()); - PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); + PacketPtr data_pkt = new Packet(req, MemCmd::WriteReq, + Packet::Broadcast); data_pkt->dataStatic(inst->memData); LSQSenderState *state = new LSQSenderState; diff --git a/src/cpu/o3/mips/cpu.hh b/src/cpu/o3/mips/cpu.hh index 7e6268cdf..0361c1814 100755 --- a/src/cpu/o3/mips/cpu.hh +++ b/src/cpu/o3/mips/cpu.hh @@ -87,20 +87,20 @@ class MipsO3CPU : public FullO3CPU<Impl> } /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); /** Reads a misc. register, including any side effects the read * might have as defined by the architecture. */ - TheISA::MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); + void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid); /** Sets a misc. register, including any side effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, + void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); /** Initiates a squash of all in-flight instructions for a given diff --git a/src/cpu/o3/mips/cpu_impl.hh b/src/cpu/o3/mips/cpu_impl.hh index e7dbd3aba..317fd748e 100644 --- a/src/cpu/o3/mips/cpu_impl.hh +++ b/src/cpu/o3/mips/cpu_impl.hh @@ -135,31 +135,31 @@ MipsO3CPU<Impl>::regStats() template <class Impl> MiscReg -MipsO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) +MipsO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid) { - return this->regFile.readMiscReg(misc_reg, tid); + return this->regFile.readMiscRegNoEffect(misc_reg, tid); } template <class Impl> MiscReg -MipsO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid) +MipsO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) { - return this->regFile.readMiscRegWithEffect(misc_reg, tid); + return this->regFile.readMiscReg(misc_reg, tid); } template <class Impl> void -MipsO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +MipsO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid) { - this->regFile.setMiscReg(misc_reg, val, tid); + this->regFile.setMiscRegNoEffect(misc_reg, val, tid); } template <class Impl> void -MipsO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val, +MipsO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) { - this->regFile.setMiscRegWithEffect(misc_reg, val, tid); + this->regFile.setMiscReg(misc_reg, val, tid); } template <class Impl> diff --git a/src/cpu/o3/mips/dyn_inst.hh b/src/cpu/o3/mips/dyn_inst.hh index f53530908..366b4bb23 100755 --- a/src/cpu/o3/mips/dyn_inst.hh +++ b/src/cpu/o3/mips/dyn_inst.hh @@ -93,32 +93,32 @@ class MipsDynInst : public BaseDynInst<Impl> public: /** Reads a miscellaneous register. */ - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg) { - return this->cpu->readMiscReg(misc_reg, this->threadNumber); + return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber); } /** Reads a misc. register, including any side-effects the read * might have as defined by the architecture. */ - MiscReg readMiscRegWithEffect(int misc_reg) + MiscReg readMiscReg(int misc_reg) { - return this->cpu->readMiscRegWithEffect(misc_reg, this->threadNumber); + return this->cpu->readMiscReg(misc_reg, this->threadNumber); } /** Sets a misc. register. */ - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { this->instResult.integer = val; - this->cpu->setMiscReg(misc_reg, val, this->threadNumber); + this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber); } /** Sets a misc. register, including any side-effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val) { - return this->cpu->setMiscRegWithEffect(misc_reg, val, + return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); } diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index 598af123e..c4f8f3a9f 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -225,26 +225,26 @@ class PhysRegFile floatRegFile[reg_idx].q = val; } - MiscReg readMiscReg(int misc_reg, unsigned thread_id) + MiscReg readMiscRegNoEffect(int misc_reg, unsigned thread_id) { - return miscRegs[thread_id].readReg(misc_reg); + return miscRegs[thread_id].readRegNoEffect(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg, unsigned thread_id) + MiscReg readMiscReg(int misc_reg, unsigned thread_id) { - return miscRegs[thread_id].readRegWithEffect(misc_reg, + return miscRegs[thread_id].readReg(misc_reg, cpu->tcBase(thread_id)); } - void setMiscReg(int misc_reg, const MiscReg &val, unsigned thread_id) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned thread_id) { - miscRegs[thread_id].setReg(misc_reg, val); + miscRegs[thread_id].setRegNoEffect(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val, + void setMiscReg(int misc_reg, const MiscReg &val, unsigned thread_id) { - miscRegs[thread_id].setRegWithEffect(misc_reg, val, + miscRegs[thread_id].setReg(misc_reg, val, cpu->tcBase(thread_id)); } diff --git a/src/cpu/o3/sparc/cpu.hh b/src/cpu/o3/sparc/cpu.hh index 08ebd2710..7b932e429 100644 --- a/src/cpu/o3/sparc/cpu.hh +++ b/src/cpu/o3/sparc/cpu.hh @@ -106,20 +106,20 @@ class SparcO3CPU : public FullO3CPU<Impl> #endif /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid); /** Reads a misc. register, including any side effects the read * might have as defined by the architecture. */ - TheISA::MiscReg readMiscRegWithEffect(int misc_reg, unsigned tid); + TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid); /** Sets a miscellaneous register. */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); + void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid); /** Sets a misc. register, including any side effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val, + void setMiscReg(int misc_reg, const TheISA::MiscReg &val, unsigned tid); /** Initiates a squash of all in-flight instructions for a given diff --git a/src/cpu/o3/sparc/cpu_impl.hh b/src/cpu/o3/sparc/cpu_impl.hh index c039a8fec..a425a8a56 100644 --- a/src/cpu/o3/sparc/cpu_impl.hh +++ b/src/cpu/o3/sparc/cpu_impl.hh @@ -153,32 +153,32 @@ SparcO3CPU<Impl>::regStats() template <class Impl> TheISA::MiscReg -SparcO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) +SparcO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid) { - return this->regFile.readMiscReg(misc_reg, tid); + return this->regFile.readMiscRegNoEffect(misc_reg, tid); } template <class Impl> TheISA::MiscReg -SparcO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid) +SparcO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid) { - return this->regFile.readMiscRegWithEffect(misc_reg, tid); + return this->regFile.readMiscReg(misc_reg, tid); } template <class Impl> void -SparcO3CPU<Impl>::setMiscReg(int misc_reg, +SparcO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, const SparcISA::MiscReg &val, unsigned tid) { - this->regFile.setMiscReg(misc_reg, val, tid); + this->regFile.setMiscRegNoEffect(misc_reg, val, tid); } template <class Impl> void -SparcO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, +SparcO3CPU<Impl>::setMiscReg(int misc_reg, const SparcISA::MiscReg &val, unsigned tid) { - this->regFile.setMiscRegWithEffect(misc_reg, val, tid); + this->regFile.setMiscReg(misc_reg, val, tid); } template <class Impl> diff --git a/src/cpu/o3/sparc/dyn_inst.hh b/src/cpu/o3/sparc/dyn_inst.hh index 4314488b5..72242b161 100644 --- a/src/cpu/o3/sparc/dyn_inst.hh +++ b/src/cpu/o3/sparc/dyn_inst.hh @@ -77,39 +77,39 @@ class SparcDynInst : public BaseDynInst<Impl> public: /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscReg(int misc_reg) + TheISA::MiscReg readMiscRegNoEffect(int misc_reg) { - return this->cpu->readMiscReg(misc_reg, this->threadNumber); + return this->cpu->readMiscRegNoEffect(misc_reg, this->threadNumber); } /** Reads a misc. register, including any side-effects the read * might have as defined by the architecture. */ - TheISA::MiscReg readMiscRegWithEffect(int misc_reg) + TheISA::MiscReg readMiscReg(int misc_reg) { - return this->cpu->readMiscRegWithEffect(misc_reg, this->threadNumber); + return this->cpu->readMiscReg(misc_reg, this->threadNumber); } /** Sets a misc. register. */ - void setMiscReg(int misc_reg, const TheISA::MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val) { this->instResult.integer = val; - return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); + return this->cpu->setMiscRegNoEffect(misc_reg, val, this->threadNumber); } /** Sets a misc. register, including any side-effects the write * might have as defined by the architecture. */ - void setMiscRegWithEffect(int misc_reg, const TheISA::MiscReg &val) + void setMiscReg(int misc_reg, const TheISA::MiscReg &val) { - return this->cpu->setMiscRegWithEffect(misc_reg, val, + return this->cpu->setMiscReg(misc_reg, val, this->threadNumber); } /** Reads a miscellaneous register. */ - TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) + TheISA::MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) { - return this->cpu->readMiscReg( + return this->cpu->readMiscRegNoEffect( si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, this->threadNumber); } @@ -117,19 +117,19 @@ class SparcDynInst : public BaseDynInst<Impl> /** Reads a misc. register, including any side-effects the read * might have as defined by the architecture. */ - TheISA::MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + TheISA::MiscReg readMiscRegOperand(const StaticInst *si, int idx) { - return this->cpu->readMiscRegWithEffect( + return this->cpu->readMiscReg( si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag, this->threadNumber); } /** Sets a misc. register. */ - void setMiscRegOperand(const StaticInst * si, + void setMiscRegOperandNoEffect(const StaticInst * si, int idx, const TheISA::MiscReg &val) { this->instResult.integer = val; - return this->cpu->setMiscReg( + return this->cpu->setMiscRegNoEffect( si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, val, this->threadNumber); } @@ -137,10 +137,10 @@ class SparcDynInst : public BaseDynInst<Impl> /** Sets a misc. register, including any side-effects the write * might have as defined by the architecture. */ - void setMiscRegOperandWithEffect( + void setMiscRegOperand( const StaticInst *si, int idx, const TheISA::MiscReg &val) { - return this->cpu->setMiscRegWithEffect( + return this->cpu->setMiscReg( si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag, val, this->threadNumber); } diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 4987d6eb4..93638673b 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -206,20 +206,20 @@ class O3ThreadContext : public ThreadContext virtual void setNextPC(uint64_t val); /** Reads a miscellaneous register. */ - virtual MiscReg readMiscReg(int misc_reg) - { return cpu->readMiscReg(misc_reg, thread->readTid()); } + virtual MiscReg readMiscRegNoEffect(int misc_reg) + { return cpu->readMiscRegNoEffect(misc_reg, thread->readTid()); } /** Reads a misc. register, including any side-effects the * read might have as defined by the architecture. */ - virtual MiscReg readMiscRegWithEffect(int misc_reg) - { return cpu->readMiscRegWithEffect(misc_reg, thread->readTid()); } + virtual MiscReg readMiscReg(int misc_reg) + { return cpu->readMiscReg(misc_reg, thread->readTid()); } /** Sets a misc. register. */ - virtual void setMiscReg(int misc_reg, const MiscReg &val); + virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val); /** Sets a misc. register, including any side-effects the * write might have as defined by the architecture. */ - virtual void setMiscRegWithEffect(int misc_reg, const MiscReg &val); + virtual void setMiscReg(int misc_reg, const MiscReg &val); /** Returns the number of consecutive store conditional failures. */ // @todo: Figure out where these store cond failures should go. diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index af98fa1f5..a145e046e 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -103,7 +103,7 @@ void O3ThreadContext<Impl>::delVirtPort(VirtualPort *vp) { if (vp != thread->getVirtPort()) { - delete vp->getPeer(); + vp->removeConn(); delete vp; } } @@ -442,9 +442,9 @@ O3ThreadContext<Impl>::setNextPC(uint64_t val) template <class Impl> void -O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) +O3ThreadContext<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { - cpu->setMiscReg(misc_reg, val, thread->readTid()); + cpu->setMiscRegNoEffect(misc_reg, val, thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { @@ -454,10 +454,10 @@ O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) template <class Impl> void -O3ThreadContext<Impl>::setMiscRegWithEffect(int misc_reg, +O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) { - cpu->setMiscRegWithEffect(misc_reg, val, thread->readTid()); + cpu->setMiscReg(misc_reg, val, thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { diff --git a/src/cpu/ozone/SConscript b/src/cpu/ozone/SConscript new file mode 100644 index 000000000..4a040684a --- /dev/null +++ b/src/cpu/ozone/SConscript @@ -0,0 +1,45 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +if 'OzoneCPU' in env['CPU_MODELS']: + need_bp_unit = True + Source('base_dyn_inst.cc') + Source('bpred_unit.cc') + Source('cpu.cc') + Source('cpu_builder.cc') + Source('dyn_inst.cc') + Source('front_end.cc') + Source('lw_back_end.cc') + Source('lw_lsq.cc') + Source('rename_table.cc') + if env['USE_CHECKER']: + Source('checker_builder.cc') diff --git a/src/cpu/ozone/SConsopts b/src/cpu/ozone/SConsopts new file mode 100644 index 000000000..341644dcd --- /dev/null +++ b/src/cpu/ozone/SConsopts @@ -0,0 +1,33 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +all_cpu_list.append('OzoneCPU') diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index baea7a546..2432df55e 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -235,14 +235,14 @@ class OzoneCPU : public BaseCPU public: // ISA stuff: + MiscReg readMiscRegNoEffect(int misc_reg); + MiscReg readMiscReg(int misc_reg); - MiscReg readMiscRegWithEffect(int misc_reg); + void setMiscRegNoEffect(int misc_reg, const MiscReg &val); void setMiscReg(int misc_reg, const MiscReg &val); - void setMiscRegWithEffect(int misc_reg, const MiscReg &val); - unsigned readStCondFailures() { return thread->storeCondFailures; } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index a854de8de..d78162243 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -748,7 +748,7 @@ template <class Impl> void OzoneCPU<Impl>::OzoneTC::delVirtPort(VirtualPort *vp) { - delete vp->getPeer(); + vp->removeConn(); delete vp; } #endif @@ -1089,24 +1089,24 @@ OzoneCPU<Impl>::OzoneTC::setNextPC(Addr val) template <class Impl> TheISA::MiscReg -OzoneCPU<Impl>::OzoneTC::readMiscReg(int misc_reg) +OzoneCPU<Impl>::OzoneTC::readMiscRegNoEffect(int misc_reg) { - return thread->miscRegFile.readReg(misc_reg); + return thread->miscRegFile.readRegNoEffect(misc_reg); } template <class Impl> TheISA::MiscReg -OzoneCPU<Impl>::OzoneTC::readMiscRegWithEffect(int misc_reg) +OzoneCPU<Impl>::OzoneTC::readMiscReg(int misc_reg) { - return thread->miscRegFile.readRegWithEffect(misc_reg, this); + return thread->miscRegFile.readReg(misc_reg, this); } template <class Impl> void -OzoneCPU<Impl>::OzoneTC::setMiscReg(int misc_reg, const MiscReg &val) +OzoneCPU<Impl>::OzoneTC::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { // Needs to setup a squash event unless we're in syscall mode - thread->miscRegFile.setReg(misc_reg, val); + thread->miscRegFile.setRegNoEffect(misc_reg, val); if (!thread->inSyscall) { cpu->squashFromTC(); @@ -1115,10 +1115,10 @@ OzoneCPU<Impl>::OzoneTC::setMiscReg(int misc_reg, const MiscReg &val) template <class Impl> void -OzoneCPU<Impl>::OzoneTC::setMiscRegWithEffect(int misc_reg, const MiscReg &val) +OzoneCPU<Impl>::OzoneTC::setMiscReg(int misc_reg, const MiscReg &val) { // Needs to setup a squash event unless we're in syscall mode - thread->miscRegFile.setRegWithEffect(misc_reg, val, this); + thread->miscRegFile.setReg(misc_reg, val, this); if (!thread->inSyscall) { cpu->squashFromTC(); diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh index 88f96b14b..e138cbe13 100644 --- a/src/cpu/ozone/dyn_inst.hh +++ b/src/cpu/ozone/dyn_inst.hh @@ -231,14 +231,14 @@ class OzoneDynInst : public BaseDynInst<Impl> public: // ISA stuff + MiscReg readMiscRegNoEffect(int misc_reg); + MiscReg readMiscReg(int misc_reg); - MiscReg readMiscRegWithEffect(int misc_reg); + void setMiscRegNoEffect(int misc_reg, const MiscReg &val); void setMiscReg(int misc_reg, const MiscReg &val); - void setMiscRegWithEffect(int misc_reg, const MiscReg &val); - #if FULL_SYSTEM Fault hwrei(); void trap(Fault fault); diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index 05a66d77a..8519917f5 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -219,31 +219,31 @@ OzoneDynInst<Impl>::clearMemDependents() template <class Impl> TheISA::MiscReg -OzoneDynInst<Impl>::readMiscReg(int misc_reg) +OzoneDynInst<Impl>::readMiscRegNoEffect(int misc_reg) { - return this->thread->readMiscReg(misc_reg); + return this->thread->readMiscRegNoEffect(misc_reg); } template <class Impl> TheISA::MiscReg -OzoneDynInst<Impl>::readMiscRegWithEffect(int misc_reg) +OzoneDynInst<Impl>::readMiscReg(int misc_reg) { - return this->thread->readMiscRegWithEffect(misc_reg); + return this->thread->readMiscReg(misc_reg); } template <class Impl> void -OzoneDynInst<Impl>::setMiscReg(int misc_reg, const MiscReg &val) +OzoneDynInst<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { this->setIntResult(val); - this->thread->setMiscReg(misc_reg, val); + this->thread->setMiscRegNoEffect(misc_reg, val); } template <class Impl> void -OzoneDynInst<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val) +OzoneDynInst<Impl>::setMiscReg(int misc_reg, const MiscReg &val) { - this->thread->setMiscRegWithEffect(misc_reg, val); + this->thread->setMiscReg(misc_reg, val); } #if FULL_SYSTEM @@ -255,7 +255,7 @@ OzoneDynInst<Impl>::hwrei() if (!(this->readPC() & 0x3)) return new AlphaISA::UnimplementedOpcodeFault; - this->setNextPC(this->thread->readMiscReg(AlphaISA::IPR_EXC_ADDR)); + this->setNextPC(this->thread->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR)); this->cpu->hwrei(); diff --git a/src/cpu/ozone/inorder_back_end_impl.hh b/src/cpu/ozone/inorder_back_end_impl.hh index 84f935a72..8d7ebb60e 100644 --- a/src/cpu/ozone/inorder_back_end_impl.hh +++ b/src/cpu/ozone/inorder_back_end_impl.hh @@ -89,13 +89,13 @@ InorderBackEnd<Impl>::checkInterrupts() int summary = 0; - if (thread->readMiscReg(IPR_ASTRR)) + if (thread->readMiscRegNoEffect(IPR_ASTRR)) panic("asynchronous traps not implemented\n"); - if (thread->readMiscReg(IPR_SIRR)) { + if (thread->readMiscRegNoEffect(IPR_SIRR)) { for (int i = INTLEVEL_SOFTWARE_MIN; i < INTLEVEL_SOFTWARE_MAX; i++) { - if (thread->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { + if (thread->readMiscRegNoEffect(IPR_SIRR) & (ULL(1) << i)) { // See table 4-19 of the 21164 hardware reference ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; summary |= (ULL(1) << i); @@ -116,14 +116,14 @@ InorderBackEnd<Impl>::checkInterrupts() } } - if (ipl && ipl > thread->readMiscReg(IPR_IPLR)) { + if (ipl && ipl > thread->readMiscRegNoEffect(IPR_IPLR)) { thread->inSyscall = true; - thread->setMiscReg(IPR_ISR, summary); - thread->setMiscReg(IPR_INTID, ipl); + thread->setMiscRegNoEffect(IPR_ISR, summary); + thread->setMiscRegNoEffect(IPR_INTID, ipl); Fault(new InterruptFault)->invoke(xc); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - thread->readMiscReg(IPR_IPLR), ipl, summary); + thread->readMiscRegNoEffect(IPR_IPLR), ipl, summary); // May need to go 1 inst prior squashPending = true; diff --git a/src/cpu/ozone/inst_queue_impl.hh b/src/cpu/ozone/inst_queue_impl.hh index 84f2b2a19..ea9d03c0d 100644 --- a/src/cpu/ozone/inst_queue_impl.hh +++ b/src/cpu/ozone/inst_queue_impl.hh @@ -38,7 +38,7 @@ #include <vector> -#include "sim/root.hh" +#include "sim/core.hh" #include "cpu/ozone/inst_queue.hh" #if 0 diff --git a/src/cpu/ozone/lw_back_end_impl.hh b/src/cpu/ozone/lw_back_end_impl.hh index a181c93f4..c0a9cad24 100644 --- a/src/cpu/ozone/lw_back_end_impl.hh +++ b/src/cpu/ozone/lw_back_end_impl.hh @@ -1193,7 +1193,7 @@ LWBackEnd<Impl>::commitInst(int inst_num) #if FULL_SYSTEM if (thread->profile) { // bool usermode = -// (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; +// (xc->readMiscRegNoEffect(AlphaISA::IPR_DTB_CM) & 0x18) != 0; // thread->profilePC = usermode ? 1 : inst->readPC(); thread->profilePC = inst->readPC(); ProfileNode *node = thread->profile->consume(thread->getTC(), diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index ee1968626..f26b06453 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -605,12 +605,12 @@ OzoneLWLSQ<Impl>::writebackStores() // @todo: Remove this SC hack once the memory system handles it. if (req->isLocked()) { if (req->isUncacheable()) { - req->setScResult(2); + req->setExtraData(2); } else { if (cpu->lockFlag) { - req->setScResult(1); + req->setExtraData(1); } else { - req->setScResult(0); + req->setExtraData(0); // Hack: Instantly complete this store. completeDataAccess(data_pkt); --sq_it; diff --git a/src/cpu/ozone/thread_state.hh b/src/cpu/ozone/thread_state.hh index a71795851..53776e7d9 100644 --- a/src/cpu/ozone/thread_state.hh +++ b/src/cpu/ozone/thread_state.hh @@ -115,24 +115,24 @@ struct OzoneThreadState : public ThreadState { ThreadContext *getTC() { return tc; } - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg) { - return miscRegFile.readReg(misc_reg); + return miscRegFile.readRegNoEffect(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) + MiscReg readMiscReg(int misc_reg) { - return miscRegFile.readRegWithEffect(misc_reg, tc); + return miscRegFile.readReg(misc_reg, tc); } - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { - miscRegFile.setReg(misc_reg, val); + miscRegFile.setRegNoEffect(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val) { - miscRegFile.setRegWithEffect(misc_reg, val, tc); + miscRegFile.setReg(misc_reg, val, tc); } uint64_t readPC() diff --git a/src/cpu/pc_event.cc b/src/cpu/pc_event.cc index fca357fe3..438218df2 100644 --- a/src/cpu/pc_event.cc +++ b/src/cpu/pc_event.cc @@ -40,7 +40,7 @@ #include "cpu/thread_context.hh" #include "cpu/pc_event.hh" #include "sim/debug.hh" -#include "sim/root.hh" +#include "sim/core.hh" #include "sim/system.hh" using namespace std; @@ -138,14 +138,12 @@ BreakPCEvent::process(ThreadContext *tc) } #if FULL_SYSTEM -extern "C" void sched_break_pc_sys(System *sys, Addr addr) { new BreakPCEvent(&sys->pcEventQueue, "debug break", addr, true); } -extern "C" void sched_break_pc(Addr addr) { diff --git a/src/cpu/simple/SConscript b/src/cpu/simple/SConscript new file mode 100644 index 000000000..9a6a80473 --- /dev/null +++ b/src/cpu/simple/SConscript @@ -0,0 +1,43 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +need_simple_base = False +if 'AtomicSimpleCPU' in env['CPU_MODELS']: + need_simple_base = True + Source('atomic.cc') + +if 'TimingSimpleCPU' in env['CPU_MODELS']: + need_simple_base = True + Source('timing.cc') + +if need_simple_base: + Source('base.cc') diff --git a/src/cpu/simple/SConsopts b/src/cpu/simple/SConsopts new file mode 100644 index 000000000..32dbda1a5 --- /dev/null +++ b/src/cpu/simple/SConsopts @@ -0,0 +1,34 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +all_cpu_list.extend(('AtomicSimpleCPU', 'TimingSimpleCPU')) +default_cpus.extend(('AtomicSimpleCPU', 'TimingSimpleCPU')) diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 3b3536e44..6f69b5ac4 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -31,6 +31,7 @@ #include "arch/locked_mem.hh" #include "arch/mmaped_ipr.hh" #include "arch/utility.hh" +#include "base/bigint.hh" #include "cpu/exetrace.hh" #include "cpu/simple/atomic.hh" #include "mem/packet.hh" @@ -125,6 +126,17 @@ AtomicSimpleCPU::CpuPort::recvRetry() panic("AtomicSimpleCPU doesn't expect recvRetry callback!"); } +void +AtomicSimpleCPU::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + cpu->tcBase()->connectMemPorts(); +#endif +} AtomicSimpleCPU::AtomicSimpleCPU(Params *p) : BaseSimpleCPU(p), tickEvent(this), @@ -138,18 +150,20 @@ AtomicSimpleCPU::AtomicSimpleCPU(Params *p) ifetch_req = new Request(); ifetch_req->setThreadContext(p->cpu_id, 0); // Add thread ID if we add MT - ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); + ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); ifetch_pkt->dataStatic(&inst); data_read_req = new Request(); data_read_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too - data_read_pkt = new Packet(data_read_req, Packet::ReadReq, + data_read_pkt = new Packet(data_read_req, MemCmd::ReadReq, Packet::Broadcast); data_read_pkt->dataStatic(&dataReg); data_write_req = new Request(); data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too - data_write_pkt = new Packet(data_write_req, Packet::WriteReq, + data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq, + Packet::Broadcast); + data_swap_pkt = new Packet(data_write_req, MemCmd::SwapReq, Packet::Broadcast); } @@ -208,7 +222,7 @@ AtomicSimpleCPU::switchOut() void AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) { - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); assert(!tickEvent.scheduled()); @@ -239,12 +253,6 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay) notIdleFraction++; -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - tc->connectMemPorts(); -#endif - //Make sure ticks are still on multiples of cycles tickEvent.schedule(nextCycle(curTick + cycles(delay))); _status = Running; @@ -318,6 +326,14 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) template Fault +AtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); + +template +Fault +AtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); + +template +Fault AtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); template @@ -363,10 +379,15 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { // use the CPU's statically allocated write request and packet objects Request *req = data_write_req; - PacketPtr pkt = data_write_pkt; + PacketPtr pkt; req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); + if (req->isSwap()) + pkt = data_swap_pkt; + else + pkt = data_write_pkt; + if (traceData) { traceData->setAddr(addr); } @@ -381,6 +402,11 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) if (req->isLocked()) { do_access = TheISA::handleLockedWrite(thread, req); } + if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); + } + if (do_access) { pkt->reinitFromRequest(); @@ -401,15 +427,11 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) #endif } - if (req->isLocked()) { - uint64_t scResult = req->getScResult(); - if (scResult != 0) { - // clear failure counter - thread->setStCondFailures(0); - } - if (res) { - *res = req->getScResult(); - } + if (req->isSwap()) { + assert(res); + *res = pkt->get<T>(); + } else if (res) { + *res = req->getExtraData(); } } @@ -424,6 +446,17 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) #ifndef DOXYGEN_SHOULD_SKIP_THIS + +template +Fault +AtomicSimpleCPU::write(Twin32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +AtomicSimpleCPU::write(Twin64_t data, Addr addr, + unsigned flags, uint64_t *res); + template Fault AtomicSimpleCPU::write(uint64_t data, Addr addr, @@ -483,17 +516,28 @@ AtomicSimpleCPU::tick() Fault fault = setupFetchRequest(ifetch_req); if (fault == NoFault) { - ifetch_pkt->reinitFromRequest(); + Tick icache_latency = 0; + bool icache_access = false; + dcache_access = false; // assume no dcache access - Tick icache_latency = icachePort.sendAtomic(ifetch_pkt); - // ifetch_req is initialized to read the instruction directly - // into the CPU object's inst field. + //Fetch more instruction memory if necessary + if(predecoder.needMoreBytes()) + { + icache_access = true; + ifetch_pkt->reinitFromRequest(); + + icache_latency = icachePort.sendAtomic(ifetch_pkt); + // ifetch_req is initialized to read the instruction directly + // into the CPU object's inst field. + } - dcache_access = false; // assume no dcache access preExecute(); - fault = curStaticInst->execute(this, traceData); - postExecute(); + if(curStaticInst) + { + fault = curStaticInst->execute(this, traceData); + postExecute(); + } // @todo remove me after debugging with legion done if (curStaticInst && (!curStaticInst->isMicroOp() || @@ -501,7 +545,8 @@ AtomicSimpleCPU::tick() instCnt++; if (simulate_stalls) { - Tick icache_stall = icache_latency - cycles(1); + Tick icache_stall = + icache_access ? icache_latency - cycles(1) : 0; Tick dcache_stall = dcache_access ? dcache_latency - cycles(1) : 0; Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1); @@ -512,8 +557,8 @@ AtomicSimpleCPU::tick() } } - - advancePC(fault); + if(predecoder.needMoreBytes()) + advancePC(fault); } if (_status != Idle) diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 42c7bf23a..ad4aa4708 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -81,9 +81,6 @@ class AtomicSimpleCPU : public BaseSimpleCPU class CpuPort : public Port { - - AtomicSimpleCPU *cpu; - public: CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu) @@ -94,6 +91,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU protected: + AtomicSimpleCPU *cpu; + virtual bool recvTiming(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt); @@ -110,7 +109,17 @@ class AtomicSimpleCPU : public BaseSimpleCPU }; CpuPort icachePort; - CpuPort dcachePort; + + class DcachePort : public CpuPort + { + public: + DcachePort(const std::string &_name, AtomicSimpleCPU *_cpu) + : CpuPort(_name, _cpu) + { } + + virtual void setPeer(Port *port); + }; + DcachePort dcachePort; Request *ifetch_req; PacketPtr ifetch_pkt; @@ -118,6 +127,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU PacketPtr data_read_pkt; Request *data_write_req; PacketPtr data_write_pkt; + PacketPtr data_swap_pkt; bool dcache_access; Tick dcache_latency; diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index b8d1f3bed..877dc5bd4 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -70,7 +70,7 @@ using namespace std; using namespace TheISA; BaseSimpleCPU::BaseSimpleCPU(Params *p) - : BaseCPU(p), thread(NULL) + : BaseCPU(p), thread(NULL), predecoder(NULL) { #if FULL_SYSTEM thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); @@ -301,7 +301,7 @@ BaseSimpleCPU::post_interrupt(int int_num, int index) BaseCPU::post_interrupt(int_num, index); if (thread->status() == ThreadContext::Suspended) { - DPRINTF(IPI,"Suspended Processor awoke\n"); + DPRINTF(Quiesce,"Suspended Processor awoke\n"); thread->activate(); } } @@ -367,16 +367,23 @@ BaseSimpleCPU::preExecute() inst = gtoh(inst); //If we're not in the middle of a macro instruction if (!curMacroStaticInst) { -#if THE_ISA == ALPHA_ISA - StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->readPC())); -#elif THE_ISA == SPARC_ISA - StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC())); -#elif THE_ISA == MIPS_ISA - //Mips doesn't do anything in it's MakeExtMI function right now, - //so it won't be called. - StaticInstPtr instPtr = StaticInst::decode(inst); -#endif - if (instPtr->isMacroOp()) { + StaticInstPtr instPtr = NULL; + + //Predecode, ie bundle up an ExtMachInst + //This should go away once the constructor can be set up properly + predecoder.setTC(thread->getTC()); + //If more fetch data is needed, pass it in. + if(predecoder.needMoreBytes()) + predecoder.moreBytes(thread->readPC(), 0, inst); + else + predecoder.process(); + //If an instruction is ready, decode it + if (predecoder.extMachInstReady()) + instPtr = StaticInst::decode(predecoder.getExtMachInst()); + + //If we decoded an instruction and it's microcoded, start pulling + //out micro ops + if (instPtr && instPtr->isMacroOp()) { curMacroStaticInst = instPtr; curStaticInst = curMacroStaticInst-> fetchMicroOp(thread->readMicroPC()); @@ -389,17 +396,19 @@ BaseSimpleCPU::preExecute() fetchMicroOp(thread->readMicroPC()); } + //If we decoded an instruction this "tick", record information about it. + if(curStaticInst) + { + traceData = Trace::getInstRecord(curTick, tc, curStaticInst, + thread->readPC()); - traceData = Trace::getInstRecord(curTick, tc, curStaticInst, - thread->readPC()); - - DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n", - curStaticInst->getName(), curStaticInst->getOpcode(), - curStaticInst->machInst); + DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", + curStaticInst->getName(), curStaticInst->machInst); #if FULL_SYSTEM - thread->setInst(inst); + thread->setInst(inst); #endif // FULL_SYSTEM + } } void @@ -409,7 +418,8 @@ BaseSimpleCPU::postExecute() if (thread->profile) { bool usermode = TheISA::inUserMode(tc); thread->profilePC = usermode ? 1 : thread->readPC(); - ProfileNode *node = thread->profile->consume(tc, inst); + StaticInstPtr si(inst); + ProfileNode *node = thread->profile->consume(tc, si); if (node) thread->profileNode = node; } @@ -427,7 +437,9 @@ BaseSimpleCPU::postExecute() traceFunctions(thread->readPC()); if (traceData) { - traceData->finalize(); + traceData->dump(); + delete traceData; + traceData = NULL; } } @@ -440,9 +452,9 @@ BaseSimpleCPU::advancePC(Fault fault) fault->invoke(tc); thread->setMicroPC(0); thread->setNextMicroPC(1); - } else { + } else if (predecoder.needMoreBytes()) { //If we're at the last micro op for this instruction - if (curStaticInst->isLastMicroOp()) { + if (curStaticInst && curStaticInst->isLastMicroOp()) { //We should be working with a macro op assert(curMacroStaticInst); //Close out this macro op, and clean up the @@ -461,13 +473,9 @@ BaseSimpleCPU::advancePC(Fault fault) } else { // go to the next instruction thread->setPC(thread->readNextPC()); -#if ISA_HAS_DELAY_SLOT thread->setNextPC(thread->readNextNPC()); thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); assert(thread->readNextPC() != thread->readNextNPC()); -#else - thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); -#endif } } diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index c4853b916..787259c96 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -33,6 +33,7 @@ #ifndef __CPU_SIMPLE_BASE_HH__ #define __CPU_SIMPLE_BASE_HH__ +#include "arch/predecoder.hh" #include "base/statistics.hh" #include "config/full_system.hh" #include "cpu/base.hh" @@ -63,6 +64,10 @@ class Process; class RemoteGDB; class GDBListener; +namespace TheISA +{ + class Predecoder; +} class ThreadContext; class Checkpoint; @@ -74,7 +79,6 @@ namespace Trace { class BaseSimpleCPU : public BaseCPU { protected: - typedef TheISA::MachInst MachInst; typedef TheISA::MiscReg MiscReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; @@ -122,10 +126,13 @@ class BaseSimpleCPU : public BaseCPU #endif // current instruction - MachInst inst; + TheISA::MachInst inst; + + // The predecoder + TheISA::Predecoder predecoder; // Static data storage - TheISA::IntReg dataReg; + TheISA::LargestRead dataReg; StaticInstPtr curStaticInst; StaticInstPtr curMacroStaticInst; @@ -284,14 +291,19 @@ class BaseSimpleCPU : public BaseCPU void setNextPC(uint64_t val) { thread->setNextPC(val); } void setNextNPC(uint64_t val) { thread->setNextNPC(val); } + MiscReg readMiscRegNoEffect(int misc_reg) + { + return thread->readMiscRegNoEffect(misc_reg); + } + MiscReg readMiscReg(int misc_reg) { return thread->readMiscReg(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { - return thread->readMiscRegWithEffect(misc_reg); + return thread->setMiscRegNoEffect(misc_reg, val); } void setMiscReg(int misc_reg, const MiscReg &val) @@ -299,9 +311,10 @@ class BaseSimpleCPU : public BaseCPU return thread->setMiscReg(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) { - return thread->setMiscRegWithEffect(misc_reg, val); + int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->readMiscRegNoEffect(reg_idx); } MiscReg readMiscRegOperand(const StaticInst *si, int idx) @@ -310,23 +323,25 @@ class BaseSimpleCPU : public BaseCPU return thread->readMiscReg(reg_idx); } - MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + void setMiscRegOperandNoEffect(const StaticInst *si, int idx, const MiscReg &val) { - int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; - return thread->readMiscRegWithEffect(reg_idx); + int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->setMiscRegNoEffect(reg_idx, val); } - void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val) + void setMiscRegOperand( + const StaticInst *si, int idx, const MiscReg &val) { int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; return thread->setMiscReg(reg_idx, val); } - void setMiscRegOperandWithEffect( - const StaticInst *si, int idx, const MiscReg &val) - { - int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; - return thread->setMiscRegWithEffect(reg_idx, val); + unsigned readStCondFailures() { + return thread->readStCondFailures(); + } + + void setStCondFailures(unsigned sc_failures) { + thread->setStCondFailures(sc_failures); } #if FULL_SYSTEM diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index dfffb0b1f..45da7c3eb 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -30,6 +30,7 @@ #include "arch/locked_mem.hh" #include "arch/utility.hh" +#include "base/bigint.hh" #include "cpu/exetrace.hh" #include "cpu/simple/timing.hh" #include "mem/packet.hh" @@ -193,7 +194,7 @@ TimingSimpleCPU::switchOut() void TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) { - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); // if any of this CPU's ThreadContexts are active, mark the CPU as // running and schedule its tick event. @@ -208,23 +209,6 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) if (_status != Running) { _status = Idle; } - - Port *peer; - if (icachePort.getPeer() == NULL) { - peer = oldCPU->getPort("icache_port")->getPeer(); - icachePort.setPeer(peer); - } else { - peer = icachePort.getPeer(); - } - peer->setPeer(&icachePort); - - if (dcachePort.getPeer() == NULL) { - peer = oldCPU->getPort("dcache_port")->getPeer(); - dcachePort.setPeer(peer); - } else { - peer = dcachePort.getPeer(); - } - peer->setPeer(&dcachePort); } @@ -239,12 +223,6 @@ TimingSimpleCPU::activateContext(int thread_num, int delay) notIdleFraction++; _status = Running; -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - tc->connectMemPorts(); -#endif - // kick things off by initiating the fetch of the next instruction fetchEvent = new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false); @@ -286,7 +264,7 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // Now do the access. if (fault == NoFault) { PacketPtr pkt = - new Packet(req, Packet::ReadReq, Packet::Broadcast); + new Packet(req, MemCmd::ReadReq, Packet::Broadcast); pkt->dataDynamic<T>(new T); if (!dcachePort.sendTiming(pkt)) { @@ -297,14 +275,14 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // memory system takes ownership of packet dcache_pkt = NULL; } + + // This will need a new way to tell if it has a dcache attached. + if (req->isUncacheable()) + recordEvent("Uncached Read"); } else { delete req; } - // This will need a new way to tell if it has a dcache attached. - if (req->isUncacheable()) - recordEvent("Uncached Read"); - return fault; } @@ -312,6 +290,14 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) template Fault +TimingSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); + +template +Fault +TimingSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); + +template +Fault TimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); template @@ -359,13 +345,20 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), cpu_id, /* thread ID */ 0); + if (traceData) { + traceData->setAddr(req->getVaddr()); + } + // translate to physical address Fault fault = thread->translateDataWriteReq(req); // Now do the access. if (fault == NoFault) { assert(dcache_pkt == NULL); - dcache_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); + if (req->isSwap()) + dcache_pkt = new Packet(req, MemCmd::SwapReq, Packet::Broadcast); + else + dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast); dcache_pkt->allocate(); dcache_pkt->set(data); @@ -374,6 +367,10 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) if (req->isLocked()) { do_access = TheISA::handleLockedWrite(thread, req); } + if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); + } if (do_access) { if (!dcachePort.sendTiming(dcache_pkt)) { @@ -384,13 +381,13 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) dcache_pkt = NULL; } } + // This will need a new way to tell if it's hooked up to a cache or not. + if (req->isUncacheable()) + recordEvent("Uncached Write"); } else { delete req; } - // This will need a new way to tell if it's hooked up to a cache or not. - if (req->isUncacheable()) - recordEvent("Uncached Write"); // If the write needs to have a fault on the access, consider calling // changeStatus() and changing it to "bad addr write" or something. @@ -401,6 +398,16 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) #ifndef DOXYGEN_SHOULD_SKIP_THIS template Fault +TimingSimpleCPU::write(Twin32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +TimingSimpleCPU::write(Twin64_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault TimingSimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); @@ -454,7 +461,7 @@ TimingSimpleCPU::fetch() ifetch_req->setThreadContext(cpu_id, /* thread ID */ 0); Fault fault = setupFetchRequest(ifetch_req); - ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); + ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); ifetch_pkt->dataStatic(&inst); if (fault == NoFault) { @@ -629,6 +636,18 @@ TimingSimpleCPU::completeDrain() drainEvent->process(); } +void +TimingSimpleCPU::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + cpu->tcBase()->connectMemPorts(); +#endif +} + bool TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) { diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index abcb224bf..ef062d24a 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -144,6 +144,8 @@ class TimingSimpleCPU : public BaseSimpleCPU : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu) { } + virtual void setPeer(Port *port); + protected: virtual bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 13d0e2e29..39f31782b 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -305,7 +305,7 @@ void SimpleThread::delVirtPort(VirtualPort *vp) { if (vp != virtPort) { - delete vp->getPeer(); + vp->removeConn(); delete vp; } } diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index f2f79c070..824914ad0 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -350,24 +350,24 @@ class SimpleThread : public ThreadState regs.setNextNPC(val); } - MiscReg readMiscReg(int misc_reg) + MiscReg readMiscRegNoEffect(int misc_reg) { - return regs.readMiscReg(misc_reg); + return regs.readMiscRegNoEffect(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) + MiscReg readMiscReg(int misc_reg) { - return regs.readMiscRegWithEffect(misc_reg, tc); + return regs.readMiscReg(misc_reg, tc); } - void setMiscReg(int misc_reg, const MiscReg &val) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { - return regs.setMiscReg(misc_reg, val); + return regs.setMiscRegNoEffect(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + void setMiscReg(int misc_reg, const MiscReg &val) { - return regs.setMiscRegWithEffect(misc_reg, val, tc); + return regs.setMiscReg(misc_reg, val, tc); } unsigned readStCondFailures() { return storeCondFailures; } diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc index cb4a7cdf7..64fcc0580 100644 --- a/src/cpu/static_inst.cc +++ b/src/cpu/static_inst.cc @@ -31,7 +31,7 @@ #include <iostream> #include "cpu/static_inst.hh" -#include "sim/root.hh" +#include "sim/core.hh" StaticInstPtr StaticInst::nullStaticInstPtr; diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 416c8ab56..a58ac85d6 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -35,6 +35,7 @@ #include <string> #include "arch/isa_traits.hh" +#include "arch/utility.hh" #include "sim/faults.hh" #include "base/bitfield.hh" #include "base/hashmap.hh" @@ -439,9 +440,6 @@ class StaticInst : public StaticInstBase //This is defined as inline below. static StaticInstPtr decode(ExtMachInst mach_inst); - /// Return opcode of machine instruction - uint32_t getOpcode() { return bits(machInst, 31, 26);} - /// Return name of machine instruction std::string getName() { return mnemonic; } }; @@ -474,7 +472,7 @@ class StaticInstPtr : public RefCountingPtr<StaticInst> /// Construct directly from machine instruction. /// Calls StaticInst::decode(). - StaticInstPtr(TheISA::ExtMachInst mach_inst) + explicit StaticInstPtr(TheISA::ExtMachInst mach_inst) : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst)) { } diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 16e491fd3..05c409c95 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -226,14 +226,14 @@ class ThreadContext virtual void setNextNPC(uint64_t val) = 0; + virtual MiscReg readMiscRegNoEffect(int misc_reg) = 0; + virtual MiscReg readMiscReg(int misc_reg) = 0; - virtual MiscReg readMiscRegWithEffect(int misc_reg) = 0; + virtual void setMiscRegNoEffect(int misc_reg, const MiscReg &val) = 0; virtual void setMiscReg(int misc_reg, const MiscReg &val) = 0; - virtual void setMiscRegWithEffect(int misc_reg, const MiscReg &val) = 0; - // Also not necessarily the best location for these two. Hopefully will go // away once we decide upon where st cond failures goes. virtual unsigned readStCondFailures() = 0; @@ -254,6 +254,8 @@ class ThreadContext // Same with st cond failures. virtual Counter readFuncExeInst() = 0; + virtual void syscall(int64_t callnum) = 0; + // This function exits the thread context in the CPU and returns // 1 if the CPU has no more active threads (meaning it's OK to exit); // Used in syscall-emulation mode when a thread calls the exit syscall. @@ -410,18 +412,18 @@ class ProxyThreadContext : public ThreadContext void setNextNPC(uint64_t val) { actualTC->setNextNPC(val); } + MiscReg readMiscRegNoEffect(int misc_reg) + { return actualTC->readMiscRegNoEffect(misc_reg); } + MiscReg readMiscReg(int misc_reg) { return actualTC->readMiscReg(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) - { return actualTC->readMiscRegWithEffect(misc_reg); } + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) + { return actualTC->setMiscRegNoEffect(misc_reg, val); } void setMiscReg(int misc_reg, const MiscReg &val) { return actualTC->setMiscReg(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) - { return actualTC->setMiscRegWithEffect(misc_reg, val); } - unsigned readStCondFailures() { return actualTC->readStCondFailures(); } @@ -441,6 +443,9 @@ class ProxyThreadContext : public ThreadContext void setSyscallReturn(SyscallReturn return_value) { actualTC->setSyscallReturn(return_value); } + void syscall(int64_t callnum) + { actualTC->syscall(callnum); } + Counter readFuncExeInst() { return actualTC->readFuncExeInst(); } #endif diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index 93dd1e2eb..4b65ca4b8 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -125,7 +125,10 @@ ThreadState::connectPhysPort() // @todo: For now this disregards any older port that may have // already existed. Fix this memory leak once the bus port IDs // for functional ports is resolved. - physPort = new FunctionalPort(csprintf("%s-%d-funcport", + if (physPort) + physPort->removeConn(); + else + physPort = new FunctionalPort(csprintf("%s-%d-funcport", baseCpu->name(), tid)); connectToMemFunc(physPort); } @@ -136,7 +139,10 @@ ThreadState::connectVirtPort() // @todo: For now this disregards any older port that may have // already existed. Fix this memory leak once the bus port IDs // for functional ports is resolved. - virtPort = new VirtualPort(csprintf("%s-%d-vport", + if (virtPort) + virtPort->removeConn(); + else + virtPort = new VirtualPort(csprintf("%s-%d-vport", baseCpu->name(), tid)); connectToMemFunc(virtPort); } diff --git a/src/cpu/trace/SConscript b/src/cpu/trace/SConscript new file mode 100644 index 000000000..f166b2f23 --- /dev/null +++ b/src/cpu/trace/SConscript @@ -0,0 +1,40 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 The Regents of The University of Michigan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert + +Import('*') + +if False: + Source('opt_cpu.cc') + Source('trace_cpu.cc') + + Source('reader/mem_trace_reader.cc') + Source('reader/ibm_reader.cc') + Source('reader/itx_reader.cc') + Source('reader/m5_reader.cc') |