base.cc revision 695
12SN/A/* 21762SN/A * Copyright (c) 2003 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "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. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292665Ssaidi@eecs.umich.edu#include <string> 302SN/A#include <sstream> 312SN/A#include <iostream> 321388SN/A 332SN/A#include "cpu/base_cpu.hh" 342SN/A#include "base/cprintf.hh" 352SN/A#include "cpu/exec_context.hh" 361191SN/A#include "base/misc.hh" 371191SN/A#include "sim/param.hh" 381191SN/A#include "sim/sim_events.hh" 391388SN/A 401717SN/Ausing namespace std; 412651Ssaidi@eecs.umich.edu 422680Sktlim@umich.eduvector<BaseCPU *> BaseCPU::cpuList; 431977SN/A 443144Shsul@eecs.umich.edu// This variable reflects the max number of threads in any CPU. Be 45161SN/A// careful to only use it once all the CPUs that you care about have 462190SN/A// been initialized 4756SN/Aint maxThreadsPerCPU = 1; 482190SN/A 492SN/A#ifdef FULL_SYSTEM 501062SN/ABaseCPU::BaseCPU(const string &_name, int _number_of_threads, 511062SN/A Counter max_insts_any_thread, 522359SN/A Counter max_insts_all_threads, 532359SN/A Counter max_loads_any_thread, 542359SN/A Counter max_loads_all_threads, 552SN/A System *_system, Tick freq) 562SN/A : SimObject(_name), frequency(freq), 572SN/A number_of_threads(_number_of_threads), system(_system) 582SN/A#else 592SN/ABaseCPU::BaseCPU(const string &_name, int _number_of_threads, 602SN/A Counter max_insts_any_thread, 612SN/A Counter max_insts_all_threads, 622SN/A Counter max_loads_any_thread, 632SN/A Counter max_loads_all_threads) 643126Sktlim@umich.edu : SimObject(_name), number_of_threads(_number_of_threads) 653126Sktlim@umich.edu#endif 664075Sbinkertn@umich.edu{ 673126Sktlim@umich.edu // add self to global list of CPUs 683126Sktlim@umich.edu cpuList.push_back(this); 693126Sktlim@umich.edu 703126Sktlim@umich.edu if (number_of_threads > maxThreadsPerCPU) 713126Sktlim@umich.edu maxThreadsPerCPU = number_of_threads; 723126Sktlim@umich.edu 732356SN/A // allocate per-thread instruction-based event queues 742356SN/A comInstEventQueue = new (EventQueue *)[number_of_threads]; 752356SN/A for (int i = 0; i < number_of_threads; ++i) 762367SN/A comInstEventQueue[i] = new EventQueue("instruction-based event queue"); 772356SN/A 782356SN/A // 792367SN/A // set up instruction-count-based termination events, if any 802356SN/A // 812356SN/A if (max_insts_any_thread != 0) 822356SN/A for (int i = 0; i < number_of_threads; ++i) 832367SN/A new SimExitEvent(comInstEventQueue[i], max_insts_any_thread, 842367SN/A "a thread reached the max instruction count"); 852367SN/A 862367SN/A if (max_insts_all_threads != 0) { 872356SN/A // allocate & initialize shared downcounter: each event will 882356SN/A // decrement this when triggered; simulation will terminate 892356SN/A // when counter reaches 0 902356SN/A int *counter = new int; 912356SN/A *counter = number_of_threads; 922356SN/A for (int i = 0; i < number_of_threads; ++i) 932356SN/A new CountedExitEvent(comInstEventQueue[i], 942356SN/A "all threads reached the max instruction count", 952356SN/A max_insts_all_threads, *counter); 962356SN/A } 971858SN/A 981400SN/A // allocate per-thread load-based event queues 993923Shsul@eecs.umich.edu comLoadEventQueue = new (EventQueue *)[number_of_threads]; 1003661Srdreslin@umich.edu for (int i = 0; i < number_of_threads; ++i) 1013661Srdreslin@umich.edu comLoadEventQueue[i] = new EventQueue("load-based event queue"); 1022SN/A 1031400SN/A // 1042856Srdreslin@umich.edu // set up instruction-count-based termination events, if any 1053661Srdreslin@umich.edu // 1063661Srdreslin@umich.edu if (max_loads_any_thread != 0) 1072SN/A for (int i = 0; i < number_of_threads; ++i) 1082SN/A new SimExitEvent(comLoadEventQueue[i], max_loads_any_thread, 1092359SN/A "a thread reached the max load count"); 1102831Sksewell@umich.edu 1111062SN/A if (max_loads_all_threads != 0) { 1122SN/A // allocate & initialize shared downcounter: each event will 1132SN/A // decrement this when triggered; simulation will terminate 1142SN/A // when counter reaches 0 1152831Sksewell@umich.edu int *counter = new int; 1161062SN/A *counter = number_of_threads; 1171062SN/A for (int i = 0; i < number_of_threads; ++i) 1182SN/A new CountedExitEvent(comLoadEventQueue[i], 1192SN/A "all threads reached the max load count", 1202SN/A max_loads_all_threads, *counter); 1212SN/A } 1221354SN/A 1232SN/A#ifdef FULL_SYSTEM 124503SN/A memset(interrupts, 0, sizeof(interrupts)); 1252SN/A intstatus = 0; 1262SN/A#endif 1272SN/A} 1282SN/A 1291400SN/A 1302SN/Avoid 1313144Shsul@eecs.umich.eduBaseCPU::regStats() 1323144Shsul@eecs.umich.edu{ 1333144Shsul@eecs.umich.edu int size = execContexts.size(); 1342SN/A if (size > 1) { 1351400SN/A for (int i = 0; i < size; ++i) { 1362SN/A stringstream namestr; 1372SN/A ccprintf(namestr, "%s.ctx%d", name(), i); 1382SN/A execContexts[i]->regStats(namestr.str()); 1392SN/A } 1402SN/A } else if (size == 1) 1412SN/A execContexts[0]->regStats(name()); 142503SN/A} 1432SN/A 1441400SN/A 1452SN/Avoid 1462SN/ABaseCPU::registerExecContexts() 147124SN/A{ 1481354SN/A for (int i = 0; i < execContexts.size(); ++i) { 149124SN/A ExecContext *xc = execContexts[i]; 150124SN/A int cpu_id; 151124SN/A 152124SN/A#ifdef FULL_SYSTEM 153124SN/A cpu_id = system->registerExecContext(xc); 154124SN/A#else 1551400SN/A cpu_id = xc->process->registerExecContext(xc); 156124SN/A#endif 1573144Shsul@eecs.umich.edu 1583144Shsul@eecs.umich.edu xc->cpu_id = cpu_id; 1593144Shsul@eecs.umich.edu } 160124SN/A} 1611400SN/A 162124SN/A 163124SN/Avoid 164124SN/ABaseCPU::switchOut() 165124SN/A{ 166124SN/A // default: do nothing 167124SN/A} 168124SN/A 169124SN/Avoid 1701400SN/ABaseCPU::takeOverFrom(BaseCPU *oldCPU) 171124SN/A{ 172124SN/A assert(execContexts.size() == oldCPU->execContexts.size()); 1731191SN/A 1741400SN/A for (int i = 0; i < execContexts.size(); ++i) { 1751388SN/A ExecContext *newXC = execContexts[i]; 1761191SN/A ExecContext *oldXC = oldCPU->execContexts[i]; 1771400SN/A 1781191SN/A newXC->takeOverFrom(oldXC); 1791400SN/A assert(newXC->cpu_id == oldXC->cpu_id); 1801191SN/A#ifdef FULL_SYSTEM 1811191SN/A system->replaceExecContext(newXC->cpu_id, newXC); 1824471Sstever@eecs.umich.edu#else 1834471Sstever@eecs.umich.edu assert(newXC->process == oldXC->process); 1844471Sstever@eecs.umich.edu newXC->process->replaceExecContext(newXC->cpu_id, newXC); 1851191SN/A#endif 1861191SN/A } 1871917SN/A 1881917SN/A#ifdef FULL_SYSTEM 1891917SN/A for (int i = 0; i < NumInterruptLevels; ++i) 1901917SN/A interrupts[i] = oldCPU->interrupts[i]; 1911917SN/A intstatus = oldCPU->intstatus; 1922SN/A#endif 1932SN/A} 1941917SN/A 1951917SN/A 1961917SN/A#ifdef FULL_SYSTEM 1971917SN/Avoid 1981917SN/ABaseCPU::post_interrupt(int int_num, int index) 1992315SN/A{ 2001917SN/A DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); 2011191SN/A 2021191SN/A if (int_num < 0 || int_num >= NumInterruptLevels) 2031191SN/A panic("int_num out of bounds\n"); 2041191SN/A 2051191SN/A if (index < 0 || index >= sizeof(uint8_t) * 8) 2061191SN/A panic("int_num out of bounds\n"); 2071191SN/A 2081191SN/A AlphaISA::check_interrupts = 1; 2091191SN/A interrupts[int_num] |= 1 << index; 2101191SN/A intstatus |= (ULL(1) << int_num); 2111191SN/A} 2121129SN/A 2131129SN/Avoid 2141129SN/ABaseCPU::clear_interrupt(int int_num, int index) 2151400SN/A{ 2162680Sktlim@umich.edu DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); 2171129SN/A 218180SN/A if (int_num < 0 || int_num >= NumInterruptLevels) 2192SN/A panic("int_num out of bounds\n"); 2201917SN/A 2211917SN/A if (index < 0 || index >= sizeof(uint8_t) * 8) 2221917SN/A panic("int_num out of bounds\n"); 2231917SN/A 2241917SN/A interrupts[int_num] &= ~(1 << index); 2251917SN/A if (interrupts[int_num] == 0) 2262356SN/A intstatus &= ~(ULL(1) << int_num); 2272356SN/A} 2284031Sktlim@umich.edu 2294031Sktlim@umich.eduvoid 2302356SN/ABaseCPU::clear_interrupts() 2312356SN/A{ 2321917SN/A DPRINTF(Interrupt, "Interrupts all cleared\n"); 2331917SN/A 2341917SN/A memset(interrupts, 0, sizeof(interrupts)); 2351917SN/A intstatus = 0; 2362SN/A} 2372SN/A 238729SN/A#endif // FULL_SYSTEM 239707SN/A 240707SN/ADEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU) 241707SN/A