base.cc revision 1762
12SN/A/* 212276Sanouk.vanlaer@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 38707Sandreas.hansson@arm.com * All rights reserved. 48707Sandreas.hansson@arm.com * 58707Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68707Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78707Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98707Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118707Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128707Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138707Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 141762SN/A * this software without specific prior written permission. 157897Shestness@cs.utexas.edu * 169983Sstever@gmail.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179983Sstever@gmail.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A */ 282SN/A 292SN/A#include <iostream> 302SN/A#include <string> 312SN/A#include <sstream> 322SN/A 332SN/A#include "base/cprintf.hh" 342SN/A#include "base/loader/symtab.hh" 352SN/A#include "base/misc.hh" 362SN/A#include "base/output.hh" 372SN/A#include "cpu/base.hh" 382SN/A#include "cpu/exec_context.hh" 392SN/A#include "cpu/sampler/sampler.hh" 402SN/A#include "sim/param.hh" 412SN/A#include "sim/sim_events.hh" 422665Ssaidi@eecs.umich.edu 432665Ssaidi@eecs.umich.edu#include "base/trace.hh" 442665Ssaidi@eecs.umich.edu 457897Shestness@cs.utexas.eduusing namespace std; 462SN/A 472SN/Avector<BaseCPU *> BaseCPU::cpuList; 4811793Sbrandon.potter@amd.com 4911793Sbrandon.potter@amd.com// This variable reflects the max number of threads in any CPU. Be 501388SN/A// careful to only use it once all the CPUs that you care about have 518229Snate@binkert.org// been initialized 522SN/Aint maxThreadsPerCPU = 1; 532SN/A 5412406Sgabeblack@google.com#ifdef FULL_SYSTEM 5511793Sbrandon.potter@amd.comBaseCPU::BaseCPU(Params *p) 568229Snate@binkert.org : SimObject(p->name), clock(p->clock), checkInterrupts(true), 5712334Sgabeblack@google.com params(p), number_of_threads(p->numberOfThreads), system(p->system) 581388SN/A#else 595529Snate@binkert.orgBaseCPU::BaseCPU(Params *p) 6010529Smorr@cs.wisc.edu : SimObject(p->name), clock(p->clock), params(p), 612651Ssaidi@eecs.umich.edu number_of_threads(p->numberOfThreads) 628229Snate@binkert.org#endif 632680Sktlim@umich.edu{ 6410529Smorr@cs.wisc.edu DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this); 658232Snate@binkert.org 6610529Smorr@cs.wisc.edu // add self to global list of CPUs 675529Snate@binkert.org cpuList.push_back(this); 6811526Sdavid.guillen@arm.com 698779Sgblack@eecs.umich.edu DPRINTF(FullCPU, "BaseCPU: CPU added to cpuList, mem address %#x.\n", 702190SN/A this); 7156SN/A 728229Snate@binkert.org if (number_of_threads > maxThreadsPerCPU) 732190SN/A maxThreadsPerCPU = number_of_threads; 742SN/A 752359SN/A // allocate per-thread instruction-based event queues 762359SN/A comInstEventQueue = new EventQueue *[number_of_threads]; 772359SN/A for (int i = 0; i < number_of_threads; ++i) 782SN/A comInstEventQueue[i] = new EventQueue("instruction-based event queue"); 792SN/A 802SN/A // 812SN/A // set up instruction-count-based termination events, if any 822SN/A // 832SN/A if (p->max_insts_any_thread != 0) 842SN/A for (int i = 0; i < number_of_threads; ++i) 852SN/A new SimExitEvent(comInstEventQueue[i], p->max_insts_any_thread, 862SN/A "a thread reached the max instruction count"); 875606Snate@binkert.org 886144Sksewell@umich.edu if (p->max_insts_all_threads != 0) { 896144Sksewell@umich.edu // allocate & initialize shared downcounter: each event will 903126Sktlim@umich.edu // decrement this when triggered; simulation will terminate 916144Sksewell@umich.edu // when counter reaches 0 927823Ssteve.reinhardt@amd.com int *counter = new int; 933126Sktlim@umich.edu *counter = number_of_threads; 943126Sktlim@umich.edu for (int i = 0; i < number_of_threads; ++i) 952356SN/A new CountedExitEvent(comInstEventQueue[i], 962356SN/A "all threads reached the max instruction count", 972356SN/A p->max_insts_all_threads, *counter); 988834Satgutier@umich.edu } 9910786Smalek.musleh@gmail.com 10010786Smalek.musleh@gmail.com // allocate per-thread load-based event queues 10110786Smalek.musleh@gmail.com comLoadEventQueue = new EventQueue *[number_of_threads]; 10210786Smalek.musleh@gmail.com for (int i = 0; i < number_of_threads; ++i) 10311321Ssteve.reinhardt@amd.com comLoadEventQueue[i] = new EventQueue("load-based event queue"); 10410786Smalek.musleh@gmail.com 10510786Smalek.musleh@gmail.com // 10610786Smalek.musleh@gmail.com // set up instruction-count-based termination events, if any 1072356SN/A // 1089179Sandreas.hansson@arm.com if (p->max_loads_any_thread != 0) 1092367SN/A for (int i = 0; i < number_of_threads; ++i) 1106144Sksewell@umich.edu new SimExitEvent(comLoadEventQueue[i], p->max_loads_any_thread, 1116144Sksewell@umich.edu "a thread reached the max load count"); 1126144Sksewell@umich.edu 1132356SN/A if (p->max_loads_all_threads != 0) { 1142367SN/A // allocate & initialize shared downcounter: each event will 1156144Sksewell@umich.edu // decrement this when triggered; simulation will terminate 1167823Ssteve.reinhardt@amd.com // when counter reaches 0 1176144Sksewell@umich.edu int *counter = new int; 1182367SN/A *counter = number_of_threads; 1192356SN/A for (int i = 0; i < number_of_threads; ++i) 1202356SN/A new CountedExitEvent(comLoadEventQueue[i], 1212356SN/A "all threads reached the max load count", 1222356SN/A p->max_loads_all_threads, *counter); 1235336Shines@cs.fsu.edu } 1242356SN/A 1254873Sstever@eecs.umich.edu#ifdef FULL_SYSTEM 1262356SN/A memset(interrupts, 0, sizeof(interrupts)); 1272356SN/A intstatus = 0; 1288876Sandreas.hansson@arm.com#endif 12913892Sgabeblack@google.com 13012680Sgiacomo.travaglini@arm.com functionTracingEnabled = false; 13112680Sgiacomo.travaglini@arm.com if (p->functionTrace) { 13211050Sandreas.hansson@arm.com functionTraceStream = simout.find(csprintf("ftrace.%s", name())); 1339814Sandreas.hansson@arm.com currentFunctionStart = currentFunctionEnd = 0; 1349220Shestness@cs.wisc.edu functionEntryTick = p->functionTraceStart; 13510529Smorr@cs.wisc.edu 13612284Sjose.marinho@arm.com if (p->functionTraceStart == 0) { 13710537Sandreas.hansson@arm.com functionTracingEnabled = true; 13810537Sandreas.hansson@arm.com } else { 13911877Sbrandon.potter@amd.com Event *e = 14012276Sanouk.vanlaer@arm.com new EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace>(this, 14112276Sanouk.vanlaer@arm.com true); 14212277Sjose.marinho@arm.com e->schedule(p->functionTraceStart); 14312276Sanouk.vanlaer@arm.com } 1442SN/A } 1455712Shsul@eecs.umich.edu} 1465712Shsul@eecs.umich.edu 1475712Shsul@eecs.umich.edu 1485712Shsul@eecs.umich.eduvoid 1495712Shsul@eecs.umich.eduBaseCPU::enableFunctionTrace() 1502SN/A{ 1512SN/A functionTracingEnabled = true; 1522SN/A} 15310190Sakash.bagdia@arm.com 15410190Sakash.bagdia@arm.comBaseCPU::~BaseCPU() 1555712Shsul@eecs.umich.edu{ 1566221Snate@binkert.org} 1576221Snate@binkert.org 1582SN/Avoid 1592SN/ABaseCPU::init() 1606221Snate@binkert.org{ 1616221Snate@binkert.org if (!params->deferRegistration) 1626221Snate@binkert.org registerExecContexts(); 1636221Snate@binkert.org} 1642SN/A 1652SN/Avoid 1662SN/ABaseCPU::regStats() 1672SN/A{ 1685606Snate@binkert.org using namespace Stats; 1695606Snate@binkert.org 1709749Sandreas@sandberg.pp.se numCycles 1719749Sandreas@sandberg.pp.se .name(name() + ".numCycles") 1725606Snate@binkert.org .desc("number of cpu cycles simulated") 1732SN/A ; 1749647Sdam.sunwoo@arm.com 1759647Sdam.sunwoo@arm.com int size = execContexts.size(); 1769647Sdam.sunwoo@arm.com if (size > 1) { 1779647Sdam.sunwoo@arm.com for (int i = 0; i < size; ++i) { 1789647Sdam.sunwoo@arm.com stringstream namestr; 1799647Sdam.sunwoo@arm.com ccprintf(namestr, "%s.ctx%d", name(), i); 1809749Sandreas@sandberg.pp.se execContexts[i]->regStats(namestr.str()); 1819749Sandreas@sandberg.pp.se } 1829647Sdam.sunwoo@arm.com } else if (size == 1) 1839647Sdam.sunwoo@arm.com execContexts[0]->regStats(name()); 1841400SN/A} 1855606Snate@binkert.org 1865606Snate@binkert.org 1872SN/Avoid 1882SN/ABaseCPU::registerExecContexts() 1892SN/A{ 1902SN/A for (int i = 0; i < execContexts.size(); ++i) { 1916221Snate@binkert.org ExecContext *xc = execContexts[i]; 1926221Snate@binkert.org int cpu_id; 1935606Snate@binkert.org 1946670Shsul@eecs.umich.edu#ifdef FULL_SYSTEM 1955606Snate@binkert.org cpu_id = system->registerExecContext(xc); 1962SN/A#else 1972SN/A cpu_id = xc->process->registerExecContext(xc); 198124SN/A#endif 1996221Snate@binkert.org 2006221Snate@binkert.org xc->cpu_id = cpu_id; 2016221Snate@binkert.org } 202124SN/A} 203124SN/A 204124SN/A 205124SN/Avoid 2065606Snate@binkert.orgBaseCPU::switchOut(Sampler *sampler) 2075606Snate@binkert.org{ 2089749Sandreas@sandberg.pp.se panic("This CPU doesn't support sampling!"); 2099749Sandreas@sandberg.pp.se} 2105606Snate@binkert.org 211124SN/Avoid 2121400SN/ABaseCPU::takeOverFrom(BaseCPU *oldCPU) 2135606Snate@binkert.org{ 214124SN/A assert(execContexts.size() == oldCPU->execContexts.size()); 215124SN/A 216124SN/A for (int i = 0; i < execContexts.size(); ++i) { 217124SN/A ExecContext *newXC = execContexts[i]; 2186221Snate@binkert.org ExecContext *oldXC = oldCPU->execContexts[i]; 2196221Snate@binkert.org 2205606Snate@binkert.org newXC->takeOverFrom(oldXC); 2216221Snate@binkert.org assert(newXC->cpu_id == oldXC->cpu_id); 2225606Snate@binkert.org#ifdef FULL_SYSTEM 223124SN/A system->replaceExecContext(newXC, newXC->cpu_id); 224124SN/A#else 2251191SN/A assert(newXC->process == oldXC->process); 2265529Snate@binkert.org newXC->process->replaceExecContext(newXC, newXC->cpu_id); 2278634Schris.emmons@arm.com#endif 22811359Sandreas@sandberg.pp.se } 2298634Schris.emmons@arm.com 2301191SN/A#ifdef FULL_SYSTEM 2315529Snate@binkert.org for (int i = 0; i < NumInterruptLevels; ++i) 2321191SN/A interrupts[i] = oldCPU->interrupts[i]; 2335529Snate@binkert.org intstatus = oldCPU->intstatus; 2341191SN/A#endif 2351191SN/A} 23612085Sspwilson2@wisc.edu 23712085Sspwilson2@wisc.edu 2385606Snate@binkert.org#ifdef FULL_SYSTEM 2391191SN/Avoid 2401191SN/ABaseCPU::post_interrupt(int int_num, int index) 2418876Sandreas.hansson@arm.com{ 2428876Sandreas.hansson@arm.com DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); 2438876Sandreas.hansson@arm.com 2449433SAndreas.Sandberg@ARM.com if (int_num < 0 || int_num >= NumInterruptLevels) 24511221Sandreas.sandberg@arm.com panic("int_num out of bounds\n"); 24611221Sandreas.sandberg@arm.com 24711221Sandreas.sandberg@arm.com if (index < 0 || index >= sizeof(uint64_t) * 8) 24811221Sandreas.sandberg@arm.com panic("int_num out of bounds\n"); 24911221Sandreas.sandberg@arm.com 25011221Sandreas.sandberg@arm.com checkInterrupts = true; 2518876Sandreas.hansson@arm.com interrupts[int_num] |= 1 << index; 2525810Sgblack@eecs.umich.edu intstatus |= (ULL(1) << int_num); 2538779Sgblack@eecs.umich.edu} 2548779Sgblack@eecs.umich.edu 25512127Sspwilson2@wisc.eduvoid 25612127Sspwilson2@wisc.eduBaseCPU::clear_interrupt(int int_num, int index) 25712127Sspwilson2@wisc.edu{ 2588779Sgblack@eecs.umich.edu DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); 2595529Snate@binkert.org 2609384SAndreas.Sandberg@arm.com if (int_num < 0 || int_num >= NumInterruptLevels) 2619384SAndreas.Sandberg@arm.com panic("int_num out of bounds\n"); 2629384SAndreas.Sandberg@arm.com 2639384SAndreas.Sandberg@arm.com if (index < 0 || index >= sizeof(uint64_t) * 8) 2649384SAndreas.Sandberg@arm.com panic("int_num out of bounds\n"); 2651917SN/A 2661191SN/A interrupts[int_num] &= ~(1 << index); 2671191SN/A if (interrupts[int_num] == 0) 2681191SN/A intstatus &= ~(ULL(1) << int_num); 2691191SN/A} 2701191SN/A 2711191SN/Avoid 2721191SN/ABaseCPU::clear_interrupts() 2731191SN/A{ 2741191SN/A DPRINTF(Interrupt, "Interrupts all cleared\n"); 2759086Sandreas.hansson@arm.com 2769086Sandreas.hansson@arm.com memset(interrupts, 0, sizeof(interrupts)); 2779086Sandreas.hansson@arm.com intstatus = 0; 2781191SN/A} 2791191SN/A 2801129SN/A 28111148Smitch.hayenga@arm.comvoid 28210529Smorr@cs.wisc.eduBaseCPU::serialize(std::ostream &os) 28311148Smitch.hayenga@arm.com{ 28411148Smitch.hayenga@arm.com SERIALIZE_ARRAY(interrupts, NumInterruptLevels); 28511148Smitch.hayenga@arm.com SERIALIZE_SCALAR(intstatus); 28611148Smitch.hayenga@arm.com} 28711148Smitch.hayenga@arm.com 28811148Smitch.hayenga@arm.comvoid 28911148Smitch.hayenga@arm.comBaseCPU::unserialize(Checkpoint *cp, const std::string §ion) 29010529Smorr@cs.wisc.edu{ 29110529Smorr@cs.wisc.edu UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); 29210529Smorr@cs.wisc.edu UNSERIALIZE_SCALAR(intstatus); 29311148Smitch.hayenga@arm.com} 29410529Smorr@cs.wisc.edu 29511148Smitch.hayenga@arm.com#endif // FULL_SYSTEM 29611148Smitch.hayenga@arm.com 29711148Smitch.hayenga@arm.comvoid 29811325Ssteve.reinhardt@amd.comBaseCPU::traceFunctionsInternal(Addr pc) 29910529Smorr@cs.wisc.edu{ 30010529Smorr@cs.wisc.edu if (!debugSymbolTable) 30110529Smorr@cs.wisc.edu return; 30210529Smorr@cs.wisc.edu 30311148Smitch.hayenga@arm.com // if pc enters different function, print new function symbol and 30411148Smitch.hayenga@arm.com // update saved range. Otherwise do nothing. 30510529Smorr@cs.wisc.edu if (pc < currentFunctionStart || pc >= currentFunctionEnd) { 30611148Smitch.hayenga@arm.com string sym_str; 30711148Smitch.hayenga@arm.com bool found = debugSymbolTable->findNearestSymbol(pc, sym_str, 30810529Smorr@cs.wisc.edu currentFunctionStart, 30910529Smorr@cs.wisc.edu currentFunctionEnd); 31011148Smitch.hayenga@arm.com 31110529Smorr@cs.wisc.edu if (!found) { 31210529Smorr@cs.wisc.edu // no symbol found: use addr as label 31310529Smorr@cs.wisc.edu sym_str = csprintf("0x%x", pc); 31410529Smorr@cs.wisc.edu currentFunctionStart = pc; 31510529Smorr@cs.wisc.edu currentFunctionEnd = pc + 1; 31612406Sgabeblack@google.com } 31710529Smorr@cs.wisc.edu 31811148Smitch.hayenga@arm.com ccprintf(*functionTraceStream, " (%d)\n%d: %s", 31911148Smitch.hayenga@arm.com curTick - functionEntryTick, curTick, sym_str); 32011148Smitch.hayenga@arm.com functionEntryTick = curTick; 32112784Sgiacomo.travaglini@arm.com } 32212784Sgiacomo.travaglini@arm.com} 32311148Smitch.hayenga@arm.com 32410529Smorr@cs.wisc.edu 32510529Smorr@cs.wisc.eduDEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU) 32610529Smorr@cs.wisc.edu