base.cc revision 1388
12929Sktlim@umich.edu/* 22929Sktlim@umich.edu * Copyright (c) 2002-2004 The Regents of The University of Michigan 32929Sktlim@umich.edu * All rights reserved. 42929Sktlim@umich.edu * 52929Sktlim@umich.edu * Redistribution and use in source and binary forms, with or without 62929Sktlim@umich.edu * modification, are permitted provided that the following conditions are 72929Sktlim@umich.edu * met: redistributions of source code must retain the above copyright 82929Sktlim@umich.edu * notice, this list of conditions and the following disclaimer; 92929Sktlim@umich.edu * redistributions in binary form must reproduce the above copyright 102929Sktlim@umich.edu * notice, this list of conditions and the following disclaimer in the 112929Sktlim@umich.edu * documentation and/or other materials provided with the distribution; 122929Sktlim@umich.edu * neither the name of the copyright holders nor the names of its 132929Sktlim@umich.edu * contributors may be used to endorse or promote products derived from 142929Sktlim@umich.edu * this software without specific prior written permission. 152929Sktlim@umich.edu * 162929Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172929Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182929Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192929Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202929Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212929Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222929Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232929Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242929Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252929Sktlim@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262929Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272929Sktlim@umich.edu */ 282929Sktlim@umich.edu 292929Sktlim@umich.edu#include <iostream> 302929Sktlim@umich.edu#include <string> 312929Sktlim@umich.edu#include <sstream> 322929Sktlim@umich.edu 332929Sktlim@umich.edu#include "base/cprintf.hh" 342929Sktlim@umich.edu#include "base/loader/symtab.hh" 352929Sktlim@umich.edu#include "base/misc.hh" 367686Ssteve.reinhardt@amd.com#include "base/output.hh" 372929Sktlim@umich.edu#include "cpu/base_cpu.hh" 382929Sktlim@umich.edu#include "cpu/exec_context.hh" 392929Sktlim@umich.edu#include "sim/param.hh" 402929Sktlim@umich.edu#include "sim/sim_events.hh" 417686Ssteve.reinhardt@amd.com 427686Ssteve.reinhardt@amd.comusing namespace std; 437686Ssteve.reinhardt@amd.com 447686Ssteve.reinhardt@amd.comvector<BaseCPU *> BaseCPU::cpuList; 457686Ssteve.reinhardt@amd.com 467686Ssteve.reinhardt@amd.com// This variable reflects the max number of threads in any CPU. Be 472929Sktlim@umich.edu// careful to only use it once all the CPUs that you care about have 482929Sktlim@umich.edu// been initialized 492929Sktlim@umich.eduint maxThreadsPerCPU = 1; 502929Sktlim@umich.edu 512929Sktlim@umich.edu#ifdef FULL_SYSTEM 522929Sktlim@umich.eduBaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg, 532929Sktlim@umich.edu Counter max_insts_any_thread, 542929Sktlim@umich.edu Counter max_insts_all_threads, 552929Sktlim@umich.edu Counter max_loads_any_thread, 562929Sktlim@umich.edu Counter max_loads_all_threads, 572929Sktlim@umich.edu System *_system, Tick freq, 587686Ssteve.reinhardt@amd.com bool _function_trace, Tick _function_trace_start) 592929Sktlim@umich.edu : SimObject(_name), frequency(freq), checkInterrupts(true), 602929Sktlim@umich.edu deferRegistration(_def_reg), number_of_threads(_number_of_threads), 617686Ssteve.reinhardt@amd.com system(_system) 622929Sktlim@umich.edu#else 632929Sktlim@umich.eduBaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg, 642929Sktlim@umich.edu Counter max_insts_any_thread, 652929Sktlim@umich.edu Counter max_insts_all_threads, 662929Sktlim@umich.edu Counter max_loads_any_thread, 672929Sktlim@umich.edu Counter max_loads_all_threads, 682929Sktlim@umich.edu bool _function_trace, Tick _function_trace_start) 692929Sktlim@umich.edu : SimObject(_name), deferRegistration(_def_reg), 702929Sktlim@umich.edu number_of_threads(_number_of_threads) 712929Sktlim@umich.edu#endif 722929Sktlim@umich.edu{ 732929Sktlim@umich.edu // add self to global list of CPUs 742929Sktlim@umich.edu cpuList.push_back(this); 752929Sktlim@umich.edu 762929Sktlim@umich.edu if (number_of_threads > maxThreadsPerCPU) 772929Sktlim@umich.edu maxThreadsPerCPU = number_of_threads; 782929Sktlim@umich.edu 792929Sktlim@umich.edu // allocate per-thread instruction-based event queues 802929Sktlim@umich.edu comInstEventQueue = new EventQueue *[number_of_threads]; 812929Sktlim@umich.edu for (int i = 0; i < number_of_threads; ++i) 822929Sktlim@umich.edu comInstEventQueue[i] = new EventQueue("instruction-based event queue"); 832929Sktlim@umich.edu 842929Sktlim@umich.edu // 852929Sktlim@umich.edu // set up instruction-count-based termination events, if any 862929Sktlim@umich.edu // 872929Sktlim@umich.edu if (max_insts_any_thread != 0) 882929Sktlim@umich.edu for (int i = 0; i < number_of_threads; ++i) 892929Sktlim@umich.edu new SimExitEvent(comInstEventQueue[i], max_insts_any_thread, 902929Sktlim@umich.edu "a thread reached the max instruction count"); 912929Sktlim@umich.edu 922929Sktlim@umich.edu if (max_insts_all_threads != 0) { 932929Sktlim@umich.edu // allocate & initialize shared downcounter: each event will 942929Sktlim@umich.edu // decrement this when triggered; simulation will terminate 952929Sktlim@umich.edu // when counter reaches 0 962929Sktlim@umich.edu int *counter = new int; 972929Sktlim@umich.edu *counter = number_of_threads; 982929Sktlim@umich.edu for (int i = 0; i < number_of_threads; ++i) 992929Sktlim@umich.edu new CountedExitEvent(comInstEventQueue[i], 1002929Sktlim@umich.edu "all threads reached the max instruction count", 1012929Sktlim@umich.edu max_insts_all_threads, *counter); 1022929Sktlim@umich.edu } 1032929Sktlim@umich.edu 1042929Sktlim@umich.edu // allocate per-thread load-based event queues 1052929Sktlim@umich.edu comLoadEventQueue = new EventQueue *[number_of_threads]; 1062929Sktlim@umich.edu for (int i = 0; i < number_of_threads; ++i) 1072929Sktlim@umich.edu comLoadEventQueue[i] = new EventQueue("load-based event queue"); 1082929Sktlim@umich.edu 1092929Sktlim@umich.edu // 1102929Sktlim@umich.edu // set up instruction-count-based termination events, if any 1112929Sktlim@umich.edu // 1122929Sktlim@umich.edu if (max_loads_any_thread != 0) 1132929Sktlim@umich.edu for (int i = 0; i < number_of_threads; ++i) 1142929Sktlim@umich.edu new SimExitEvent(comLoadEventQueue[i], max_loads_any_thread, 1152929Sktlim@umich.edu "a thread reached the max load count"); 1162929Sktlim@umich.edu 1172929Sktlim@umich.edu if (max_loads_all_threads != 0) { 1182929Sktlim@umich.edu // allocate & initialize shared downcounter: each event will 1192929Sktlim@umich.edu // decrement this when triggered; simulation will terminate 1202929Sktlim@umich.edu // when counter reaches 0 1212929Sktlim@umich.edu int *counter = new int; 1222929Sktlim@umich.edu *counter = number_of_threads; 1232929Sktlim@umich.edu for (int i = 0; i < number_of_threads; ++i) 1242929Sktlim@umich.edu new CountedExitEvent(comLoadEventQueue[i], 1252929Sktlim@umich.edu "all threads reached the max load count", 1262929Sktlim@umich.edu max_loads_all_threads, *counter); 1272929Sktlim@umich.edu } 1282929Sktlim@umich.edu 1292929Sktlim@umich.edu#ifdef FULL_SYSTEM 1302929Sktlim@umich.edu memset(interrupts, 0, sizeof(interrupts)); 1312929Sktlim@umich.edu intstatus = 0; 1322929Sktlim@umich.edu#endif 1332929Sktlim@umich.edu 1347448Sstever@gmail.com functionTracingEnabled = false; 1357448Sstever@gmail.com if (_function_trace) { 1367448Sstever@gmail.com functionTraceStream = simout.find(csprintf("ftrace.%s", name())); 1377448Sstever@gmail.com currentFunctionStart = currentFunctionEnd = 0; 1382929Sktlim@umich.edu functionEntryTick = _function_trace_start; 1397448Sstever@gmail.com 1407448Sstever@gmail.com if (_function_trace_start == 0) { 1417448Sstever@gmail.com functionTracingEnabled = true; 1427448Sstever@gmail.com } else { 1437448Sstever@gmail.com Event *e = 1447448Sstever@gmail.com new EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace>(this, 1457448Sstever@gmail.com true); 1467448Sstever@gmail.com e->schedule(_function_trace_start); 1477448Sstever@gmail.com } 1482929Sktlim@umich.edu } 1492929Sktlim@umich.edu} 1502929Sktlim@umich.edu 1512929Sktlim@umich.edu 1522929Sktlim@umich.eduvoid 1532929Sktlim@umich.eduBaseCPU::enableFunctionTrace() 1542929Sktlim@umich.edu{ 1552929Sktlim@umich.edu functionTracingEnabled = true; 1562929Sktlim@umich.edu} 1572929Sktlim@umich.edu 1582929Sktlim@umich.eduBaseCPU::~BaseCPU() 1592929Sktlim@umich.edu{ 1602929Sktlim@umich.edu} 1612929Sktlim@umich.edu 1622929Sktlim@umich.eduvoid 1632929Sktlim@umich.eduBaseCPU::init() 1642929Sktlim@umich.edu{ 1652929Sktlim@umich.edu if (!deferRegistration) 1662929Sktlim@umich.edu registerExecContexts(); 1672929Sktlim@umich.edu} 1682929Sktlim@umich.edu 1692929Sktlim@umich.eduvoid 1702929Sktlim@umich.eduBaseCPU::regStats() 1712929Sktlim@umich.edu{ 1722929Sktlim@umich.edu using namespace Stats; 1732929Sktlim@umich.edu 1742929Sktlim@umich.edu numCycles 1752929Sktlim@umich.edu .name(name() + ".numCycles") 1762929Sktlim@umich.edu .desc("number of cpu cycles simulated") 1772929Sktlim@umich.edu ; 1782929Sktlim@umich.edu 1792929Sktlim@umich.edu int size = execContexts.size(); 1802929Sktlim@umich.edu if (size > 1) { 1812929Sktlim@umich.edu for (int i = 0; i < size; ++i) { 1822929Sktlim@umich.edu stringstream namestr; 1832929Sktlim@umich.edu ccprintf(namestr, "%s.ctx%d", name(), i); 1842929Sktlim@umich.edu execContexts[i]->regStats(namestr.str()); 1852929Sktlim@umich.edu } 1862929Sktlim@umich.edu } else if (size == 1) 1872929Sktlim@umich.edu execContexts[0]->regStats(name()); 1882929Sktlim@umich.edu} 1892929Sktlim@umich.edu 1902929Sktlim@umich.edu 1912929Sktlim@umich.eduvoid 1922929Sktlim@umich.eduBaseCPU::registerExecContexts() 1932929Sktlim@umich.edu{ 1942929Sktlim@umich.edu for (int i = 0; i < execContexts.size(); ++i) { 1952929Sktlim@umich.edu ExecContext *xc = execContexts[i]; 1962929Sktlim@umich.edu int cpu_id; 1972929Sktlim@umich.edu 1982929Sktlim@umich.edu#ifdef FULL_SYSTEM 1992929Sktlim@umich.edu cpu_id = system->registerExecContext(xc); 2002929Sktlim@umich.edu#else 2012929Sktlim@umich.edu cpu_id = xc->process->registerExecContext(xc); 2022929Sktlim@umich.edu#endif 2032929Sktlim@umich.edu 2042929Sktlim@umich.edu xc->cpu_id = cpu_id; 2052929Sktlim@umich.edu } 2062929Sktlim@umich.edu} 2072929Sktlim@umich.edu 2082929Sktlim@umich.edu 2092929Sktlim@umich.eduvoid 2102929Sktlim@umich.eduBaseCPU::switchOut() 2112929Sktlim@umich.edu{ 2122929Sktlim@umich.edu // default: do nothing 2132929Sktlim@umich.edu} 2142929Sktlim@umich.edu 2152929Sktlim@umich.eduvoid 2162929Sktlim@umich.eduBaseCPU::takeOverFrom(BaseCPU *oldCPU) 2172929Sktlim@umich.edu{ 2182929Sktlim@umich.edu assert(execContexts.size() == oldCPU->execContexts.size()); 2192929Sktlim@umich.edu 2202929Sktlim@umich.edu for (int i = 0; i < execContexts.size(); ++i) { 2212929Sktlim@umich.edu ExecContext *newXC = execContexts[i]; 2222929Sktlim@umich.edu ExecContext *oldXC = oldCPU->execContexts[i]; 2232929Sktlim@umich.edu 2242929Sktlim@umich.edu newXC->takeOverFrom(oldXC); 2252929Sktlim@umich.edu assert(newXC->cpu_id == oldXC->cpu_id); 2262929Sktlim@umich.edu#ifdef FULL_SYSTEM 2272929Sktlim@umich.edu system->replaceExecContext(newXC, newXC->cpu_id); 2282929Sktlim@umich.edu#else 2292929Sktlim@umich.edu assert(newXC->process == oldXC->process); 2302929Sktlim@umich.edu newXC->process->replaceExecContext(newXC, newXC->cpu_id); 2312929Sktlim@umich.edu#endif 2322929Sktlim@umich.edu } 2332929Sktlim@umich.edu 2342929Sktlim@umich.edu#ifdef FULL_SYSTEM 2352929Sktlim@umich.edu for (int i = 0; i < NumInterruptLevels; ++i) 2362929Sktlim@umich.edu interrupts[i] = oldCPU->interrupts[i]; 2372929Sktlim@umich.edu intstatus = oldCPU->intstatus; 2382929Sktlim@umich.edu#endif 2392929Sktlim@umich.edu} 2402929Sktlim@umich.edu 2412929Sktlim@umich.edu 2422929Sktlim@umich.edu#ifdef FULL_SYSTEM 2432929Sktlim@umich.eduvoid 2442929Sktlim@umich.eduBaseCPU::post_interrupt(int int_num, int index) 2452929Sktlim@umich.edu{ 2462929Sktlim@umich.edu DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); 2472929Sktlim@umich.edu 2482929Sktlim@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 2492929Sktlim@umich.edu panic("int_num out of bounds\n"); 2502929Sktlim@umich.edu 2512929Sktlim@umich.edu if (index < 0 || index >= sizeof(uint64_t) * 8) 2522929Sktlim@umich.edu panic("int_num out of bounds\n"); 2532929Sktlim@umich.edu 2542929Sktlim@umich.edu checkInterrupts = true; 2552929Sktlim@umich.edu interrupts[int_num] |= 1 << index; 2562929Sktlim@umich.edu intstatus |= (ULL(1) << int_num); 2572929Sktlim@umich.edu} 2582929Sktlim@umich.edu 2592929Sktlim@umich.eduvoid 2602929Sktlim@umich.eduBaseCPU::clear_interrupt(int int_num, int index) 2612929Sktlim@umich.edu{ 2622929Sktlim@umich.edu DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); 2632929Sktlim@umich.edu 2642929Sktlim@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 2652929Sktlim@umich.edu panic("int_num out of bounds\n"); 2662929Sktlim@umich.edu 2672929Sktlim@umich.edu if (index < 0 || index >= sizeof(uint64_t) * 8) 2682929Sktlim@umich.edu panic("int_num out of bounds\n"); 2692929Sktlim@umich.edu 2702929Sktlim@umich.edu interrupts[int_num] &= ~(1 << index); 2712929Sktlim@umich.edu if (interrupts[int_num] == 0) 2722929Sktlim@umich.edu intstatus &= ~(ULL(1) << int_num); 2732929Sktlim@umich.edu} 2742929Sktlim@umich.edu 2752929Sktlim@umich.eduvoid 2762929Sktlim@umich.eduBaseCPU::clear_interrupts() 2772929Sktlim@umich.edu{ 2782929Sktlim@umich.edu DPRINTF(Interrupt, "Interrupts all cleared\n"); 2792929Sktlim@umich.edu 2802929Sktlim@umich.edu memset(interrupts, 0, sizeof(interrupts)); 2812929Sktlim@umich.edu intstatus = 0; 2822929Sktlim@umich.edu} 2832929Sktlim@umich.edu 2842929Sktlim@umich.edu 2852929Sktlim@umich.eduvoid 2862929Sktlim@umich.eduBaseCPU::serialize(std::ostream &os) 2872929Sktlim@umich.edu{ 2887686Ssteve.reinhardt@amd.com SERIALIZE_ARRAY(interrupts, NumInterruptLevels); 2892929Sktlim@umich.edu SERIALIZE_SCALAR(intstatus); 2907686Ssteve.reinhardt@amd.com} 2917686Ssteve.reinhardt@amd.com 2927686Ssteve.reinhardt@amd.comvoid 2937686Ssteve.reinhardt@amd.comBaseCPU::unserialize(Checkpoint *cp, const std::string §ion) 2942929Sktlim@umich.edu{ 2952929Sktlim@umich.edu UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); 2962929Sktlim@umich.edu UNSERIALIZE_SCALAR(intstatus); 2972929Sktlim@umich.edu} 2987686Ssteve.reinhardt@amd.com 2997686Ssteve.reinhardt@amd.com#endif // FULL_SYSTEM 3002929Sktlim@umich.edu 3012929Sktlim@umich.eduvoid 3022929Sktlim@umich.eduBaseCPU::traceFunctionsInternal(Addr pc) 3032929Sktlim@umich.edu{ 3042929Sktlim@umich.edu if (!debugSymbolTable) 3052929Sktlim@umich.edu return; 3062929Sktlim@umich.edu 3072929Sktlim@umich.edu // if pc enters different function, print new function symbol and 3082929Sktlim@umich.edu // update saved range. Otherwise do nothing. 3092929Sktlim@umich.edu if (pc < currentFunctionStart || pc >= currentFunctionEnd) { 3102929Sktlim@umich.edu string sym_str; 3112929Sktlim@umich.edu bool found = debugSymbolTable->findNearestSymbol(pc, sym_str, 3122929Sktlim@umich.edu currentFunctionStart, 3132929Sktlim@umich.edu currentFunctionEnd); 3142929Sktlim@umich.edu 3152929Sktlim@umich.edu if (!found) { 3162929Sktlim@umich.edu // no symbol found: use addr as label 3177686Ssteve.reinhardt@amd.com sym_str = csprintf("0x%x", pc); 3182929Sktlim@umich.edu currentFunctionStart = pc; 3197686Ssteve.reinhardt@amd.com currentFunctionEnd = pc + 1; 3202929Sktlim@umich.edu } 3212929Sktlim@umich.edu 3222929Sktlim@umich.edu ccprintf(*functionTraceStream, " (%d)\n%d: %s", 3232929Sktlim@umich.edu curTick - functionEntryTick, curTick, sym_str); 3242929Sktlim@umich.edu functionEntryTick = curTick; 3257448Sstever@gmail.com } 3267448Sstever@gmail.com} 3272929Sktlim@umich.edu 3282929Sktlim@umich.edu 3292929Sktlim@umich.eduDEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU) 3302929Sktlim@umich.edu