X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcpu%2Fbase.cc;h=16760613598830557ead10db0f22ae6078f17ff7;hb=909380f3ee576f915f52c6245c59d41050a46f49;hp=ee409048b961d3c93bf095b0fc31077392fdfa49;hpb=08474ccf68e14f59b4517c6024a9bc6ecbd4a1d5;p=gem5.git diff --git a/src/cpu/base.cc b/src/cpu/base.cc index ee409048b..167606135 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -37,17 +37,17 @@ #include "base/loader/symtab.hh" #include "base/misc.hh" #include "base/output.hh" +#include "base/trace.hh" #include "cpu/base.hh" #include "cpu/cpuevent.hh" #include "cpu/thread_context.hh" #include "cpu/profile.hh" +#include "params/BaseCPU.hh" #include "sim/sim_exit.hh" #include "sim/process.hh" #include "sim/sim_events.hh" #include "sim/system.hh" -#include "base/trace.hh" - // Hack #include "sim/stat_control.hh" @@ -60,13 +60,12 @@ vector BaseCPU::cpuList; // been initialized int maxThreadsPerCPU = 1; -CPUProgressEvent::CPUProgressEvent(EventQueue *q, Tick ival, - BaseCPU *_cpu) - : Event(q, Event::Progress_Event_Pri), interval(ival), - lastNumInst(0), cpu(_cpu) +CPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival) + : Event(Event::Progress_Event_Pri), interval(ival), lastNumInst(0), + cpu(_cpu) { if (interval) - schedule(curTick + interval); + cpu->schedule(this, curTick + interval); } void @@ -74,7 +73,7 @@ CPUProgressEvent::process() { Counter temp = cpu->totalInstructions(); #ifndef NDEBUG - double ipc = double(temp - lastNumInst) / (interval / cpu->cycles(1)); + double ipc = double(temp - lastNumInst) / (interval / cpu->ticks(1)); DPRINTFN("%s progress event, instructions committed: %lli, IPC: %0.8d\n", cpu->name(), temp - lastNumInst, ipc); @@ -84,32 +83,40 @@ CPUProgressEvent::process() curTick, cpu->name(), temp - lastNumInst); #endif lastNumInst = temp; - schedule(curTick + interval); + cpu->schedule(this, curTick + interval); } const char * -CPUProgressEvent::description() +CPUProgressEvent::description() const { return "CPU Progress"; } #if FULL_SYSTEM BaseCPU::BaseCPU(Params *p) - : MemObject(p->name), clock(p->clock), instCnt(0), - params(p), number_of_threads(p->numberOfThreads), system(p->system), + : MemObject(p), clock(p->clock), instCnt(0), _cpuId(p->cpu_id), + interrupts(p->interrupts), + number_of_threads(p->numThreads), system(p->system), phase(p->phase) #else BaseCPU::BaseCPU(Params *p) - : MemObject(p->name), clock(p->clock), params(p), - number_of_threads(p->numberOfThreads), system(p->system), + : MemObject(p), clock(p->clock), _cpuId(p->cpu_id), + number_of_threads(p->numThreads), system(p->system), phase(p->phase) #endif { // currentTick = curTick; + // if Python did not provide a valid ID, do it here + if (_cpuId == -1 ) { + _cpuId = cpuList.size(); + } + // add self to global list of CPUs cpuList.push_back(this); + DPRINTF(SyscallVerbose, "Constructing CPU with id %d\n", _cpuId); + if (number_of_threads > maxThreadsPerCPU) maxThreadsPerCPU = number_of_threads; @@ -121,22 +128,26 @@ BaseCPU::BaseCPU(Params *p) // // set up instruction-count-based termination events, if any // - if (p->max_insts_any_thread != 0) - for (int i = 0; i < number_of_threads; ++i) - schedExitSimLoop("a thread reached the max instruction count", - p->max_insts_any_thread, 0, - comInstEventQueue[i]); + if (p->max_insts_any_thread != 0) { + const char *cause = "a thread reached the max instruction count"; + for (int i = 0; i < number_of_threads; ++i) { + Event *event = new SimLoopExitEvent(cause, 0); + comInstEventQueue[i]->schedule(event, p->max_insts_any_thread); + } + } if (p->max_insts_all_threads != 0) { + const char *cause = "all threads reached the max instruction count"; + // allocate & initialize shared downcounter: each event will // decrement this when triggered; simulation will terminate // when counter reaches 0 int *counter = new int; *counter = number_of_threads; - for (int i = 0; i < number_of_threads; ++i) - new CountedExitEvent(comInstEventQueue[i], - "all threads reached the max instruction count", - p->max_insts_all_threads, *counter); + for (int i = 0; i < number_of_threads; ++i) { + Event *event = new CountedExitEvent(cause, *counter); + comInstEventQueue[i]->schedule(event, p->max_insts_any_thread); + } } // allocate per-thread load-based event queues @@ -147,53 +158,47 @@ BaseCPU::BaseCPU(Params *p) // // set up instruction-count-based termination events, if any // - if (p->max_loads_any_thread != 0) - for (int i = 0; i < number_of_threads; ++i) - schedExitSimLoop("a thread reached the max load count", - p->max_loads_any_thread, 0, - comLoadEventQueue[i]); + if (p->max_loads_any_thread != 0) { + const char *cause = "a thread reached the max load count"; + for (int i = 0; i < number_of_threads; ++i) { + Event *event = new SimLoopExitEvent(cause, 0); + comLoadEventQueue[i]->schedule(event, p->max_loads_any_thread); + } + } if (p->max_loads_all_threads != 0) { + const char *cause = "all threads reached the max load count"; // allocate & initialize shared downcounter: each event will // decrement this when triggered; simulation will terminate // when counter reaches 0 int *counter = new int; *counter = number_of_threads; - for (int i = 0; i < number_of_threads; ++i) - new CountedExitEvent(comLoadEventQueue[i], - "all threads reached the max load count", - p->max_loads_all_threads, *counter); + for (int i = 0; i < number_of_threads; ++i) { + Event *event = new CountedExitEvent(cause, *counter); + comLoadEventQueue[i]->schedule(event, p->max_loads_all_threads); + } } functionTracingEnabled = false; - if (p->functionTrace) { + if (p->function_trace) { functionTraceStream = simout.find(csprintf("ftrace.%s", name())); currentFunctionStart = currentFunctionEnd = 0; - functionEntryTick = p->functionTraceStart; + functionEntryTick = p->function_trace_start; - if (p->functionTraceStart == 0) { + if (p->function_trace_start == 0) { functionTracingEnabled = true; } else { - new EventWrapper(this, - p->functionTraceStart, - true); + typedef EventWrapper wrap; + Event *event = new wrap(this, true); + schedule(event, p->function_trace_start); } } #if FULL_SYSTEM profileEvent = NULL; - if (params->profile) - profileEvent = new ProfileEvent(this, params->profile); -#endif - tracer = params->tracer; -} - -BaseCPU::Params::Params() -{ -#if FULL_SYSTEM - profile = false; + if (params()->profile) + profileEvent = new ProfileEvent(this, params()->profile); #endif - checker = NULL; - tracer = NULL; + tracer = params()->tracer; } void @@ -209,7 +214,7 @@ BaseCPU::~BaseCPU() void BaseCPU::init() { - if (!params->deferRegistration) + if (!params()->defer_registration) registerThreadContexts(); } @@ -217,14 +222,14 @@ void BaseCPU::startup() { #if FULL_SYSTEM - if (!params->deferRegistration && profileEvent) - profileEvent->schedule(curTick); + if (!params()->defer_registration && profileEvent) + schedule(profileEvent, curTick); #endif - if (params->progress_interval) { - new CPUProgressEvent(&mainEventQueue, - cycles(params->progress_interval), - this); + if (params()->progress_interval) { + Tick num_ticks = ticks(params()->progress_interval); + Event *event = new CPUProgressEvent(this, num_ticks); + schedule(event, curTick + num_ticks); } } @@ -280,14 +285,19 @@ BaseCPU::registerThreadContexts() for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *tc = threadContexts[i]; -#if FULL_SYSTEM - int id = params->cpu_id; - if (id != -1) - id += i; - - tc->setCpuId(system->registerThreadContext(tc, id)); -#else - tc->setCpuId(tc->getProcessPtr()->registerThreadContext(tc)); + /** This is so that contextId and cpuId match where there is a + * 1cpu:1context relationship. Otherwise, the order of registration + * could affect the assignment and cpu 1 could have context id 3, for + * example. We may even want to do something like this for SMT so that + * cpu 0 has the lowest thread contexts and cpu N has the highest, but + * I'll just do this for now + */ + if (number_of_threads == 1) + tc->setContextId(system->registerThreadContext(tc, _cpuId)); + else + tc->setContextId(system->registerThreadContext(tc)); +#if !FULL_SYSTEM + tc->getProcessPtr()->assignThreadContext(tc->contextId()); #endif } } @@ -309,7 +319,7 @@ BaseCPU::switchOut() // panic("This CPU doesn't support sampling!"); #if FULL_SYSTEM if (profileEvent && profileEvent->scheduled()) - profileEvent->deschedule(); + deschedule(profileEvent); #endif } @@ -318,6 +328,8 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) { assert(threadContexts.size() == oldCPU->threadContexts.size()); + _cpuId = oldCPU->cpuId(); + for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *newTC = threadContexts[i]; ThreadContext *oldTC = oldCPU->threadContexts[i]; @@ -326,15 +338,12 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) CpuEvent::replaceThreadContext(oldTC, newTC); - assert(newTC->readCpuId() == oldTC->readCpuId()); -#if FULL_SYSTEM - system->replaceThreadContext(newTC, newTC->readCpuId()); -#else - assert(newTC->getProcessPtr() == oldTC->getProcessPtr()); - newTC->getProcessPtr()->replaceThreadContext(newTC, newTC->readCpuId()); -#endif + assert(newTC->contextId() == oldTC->contextId()); + assert(newTC->threadId() == oldTC->threadId()); + system->replaceThreadContext(newTC, newTC->contextId()); -// TheISA::compareXCs(oldXC, newXC); + if (DTRACE(Context)) + ThreadContext::compare(oldTC, newTC); } #if FULL_SYSTEM @@ -343,36 +352,30 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc) for (int i = 0; i < threadContexts.size(); ++i) threadContexts[i]->profileClear(); - // The Sampler must take care of this! -// if (profileEvent) -// profileEvent->schedule(curTick); + if (profileEvent) + schedule(profileEvent, 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(); + if (!ic->isConnected()) { + Port *peer = oldCPU->getPort("icache_port")->getPeer(); ic->setPeer(peer); - } else { - peer = ic->getPeer(); + peer->setPeer(ic); } - peer->setPeer(ic); - if (dc->getPeer() == NULL) { - peer = oldCPU->getPort("dcache_port")->getPeer(); + if (!dc->isConnected()) { + Port *peer = oldCPU->getPort("dcache_port")->getPeer(); dc->setPeer(peer); - } else { - peer = dc->getPeer(); + peer->setPeer(dc); } - peer->setPeer(dc); } #if FULL_SYSTEM -BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, int _interval) - : Event(&mainEventQueue), cpu(_cpu), interval(_interval) +BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, Tick _interval) + : cpu(_cpu), interval(_interval) { } void @@ -383,45 +386,39 @@ BaseCPU::ProfileEvent::process() tc->profileSample(); } - schedule(curTick + interval); + cpu->schedule(this, curTick + interval); } void -BaseCPU::post_interrupt(int int_num, int index) +BaseCPU::postInterrupt(int int_num, int index) { - interrupts.post(int_num, index); + interrupts->post(int_num, index); } void -BaseCPU::clear_interrupt(int int_num, int index) +BaseCPU::clearInterrupt(int int_num, int index) { - interrupts.clear(int_num, index); + interrupts->clear(int_num, index); } void -BaseCPU::clear_interrupts() -{ - interrupts.clear_all(); -} - -uint64_t -BaseCPU::get_interrupts(int int_num) +BaseCPU::clearInterrupts() { - return interrupts.get_vec(int_num); + interrupts->clearAll(); } void BaseCPU::serialize(std::ostream &os) { SERIALIZE_SCALAR(instCnt); - interrupts.serialize(os); + interrupts->serialize(os); } void BaseCPU::unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_SCALAR(instCnt); - interrupts.unserialize(cp, section); + interrupts->unserialize(cp, section); } #endif // FULL_SYSTEM