base.cc revision 707
12SN/A/* 22188SN/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. 272665SN/A */ 282665SN/A 292665SN/A#include <string> 302665SN/A#include <sstream> 312665SN/A#include <iostream> 322SN/A 332SN/A#include "cpu/base_cpu.hh" 342SN/A#include "base/cprintf.hh" 352SN/A#include "cpu/exec_context.hh" 362465SN/A#include "base/misc.hh" 371717SN/A#include "sim/param.hh" 382683Sktlim@umich.edu#include "sim/sim_events.hh" 392680SN/A 402SN/Ausing namespace std; 411858SN/A 423565Sgblack@eecs.umich.eduvector<BaseCPU *> BaseCPU::cpuList; 431917SN/A 441070SN/A// This variable reflects the max number of threads in any CPU. Be 451917SN/A// careful to only use it once all the CPUs that you care about have 462188SN/A// been initialized 471917SN/Aint maxThreadsPerCPU = 1; 482290SN/A 491070SN/A#ifdef FULL_SYSTEM 501917SN/ABaseCPU::BaseCPU(const string &_name, int _number_of_threads, 512170SN/A Counter max_insts_any_thread, 522SN/A Counter max_insts_all_threads, 53360SN/A Counter max_loads_any_thread, 542519SN/A Counter max_loads_all_threads, 552420SN/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, 611858SN/A Counter max_insts_all_threads, 622683Sktlim@umich.edu Counter max_loads_any_thread, 633453Sgblack@eecs.umich.edu Counter max_loads_all_threads) 642683Sktlim@umich.edu : SimObject(_name), number_of_threads(_number_of_threads) 653402Sktlim@umich.edu#endif 662683Sktlim@umich.edu{ 672521SN/A // add self to global list of CPUs 682SN/A cpuList.push_back(this); 692683Sktlim@umich.edu 702190SN/A if (number_of_threads > maxThreadsPerCPU) 712680SN/A maxThreadsPerCPU = number_of_threads; 722290SN/A 732526SN/A // allocate per-thread instruction-based event queues 741917SN/A comInstEventQueue = new (EventQueue *)[number_of_threads]; 751917SN/A for (int i = 0; i < number_of_threads; ++i) 761982SN/A comInstEventQueue[i] = new EventQueue("instruction-based event queue"); 771917SN/A 782683Sktlim@umich.edu // 792683Sktlim@umich.edu // set up instruction-count-based termination events, if any 801917SN/A // 811917SN/A if (max_insts_any_thread != 0) 821917SN/A for (int i = 0; i < number_of_threads; ++i) 831917SN/A new SimExitEvent(comInstEventQueue[i], max_insts_any_thread, 841917SN/A "a thread reached the max instruction count"); 851917SN/A 861917SN/A if (max_insts_all_threads != 0) { 871917SN/A // allocate & initialize shared downcounter: each event will 882521SN/A // decrement this when triggered; simulation will terminate 895482Snate@binkert.org // when counter reaches 0 903548Sgblack@eecs.umich.edu int *counter = new int; 912SN/A *counter = number_of_threads; 922SN/A for (int i = 0; i < number_of_threads; ++i) 934997Sgblack@eecs.umich.edu new CountedExitEvent(comInstEventQueue[i], 944997Sgblack@eecs.umich.edu "all threads reached the max instruction count", 953402Sktlim@umich.edu max_insts_all_threads, *counter); 964997Sgblack@eecs.umich.edu } 972SN/A 982526SN/A // allocate per-thread load-based event queues 992683Sktlim@umich.edu comLoadEventQueue = new (EventQueue *)[number_of_threads]; 1002SN/A for (int i = 0; i < number_of_threads; ++i) 1012190SN/A comLoadEventQueue[i] = new EventQueue("load-based event queue"); 1022862Sktlim@umich.edu 1032862Sktlim@umich.edu // 1042864Sktlim@umich.edu // set up instruction-count-based termination events, if any 1052862Sktlim@umich.edu // 1063402Sktlim@umich.edu if (max_loads_any_thread != 0) 1072862Sktlim@umich.edu for (int i = 0; i < number_of_threads; ++i) 1083402Sktlim@umich.edu new SimExitEvent(comLoadEventQueue[i], max_loads_any_thread, 1092862Sktlim@umich.edu "a thread reached the max load count"); 1102190SN/A 1112683Sktlim@umich.edu if (max_loads_all_threads != 0) { 1122862Sktlim@umich.edu // allocate & initialize shared downcounter: each event will 1132190SN/A // decrement this when triggered; simulation will terminate 1142190SN/A // when counter reaches 0 1152683Sktlim@umich.edu int *counter = new int; 1161070SN/A *counter = number_of_threads; 1173486Sktlim@umich.edu for (int i = 0; i < number_of_threads; ++i) 1183486Sktlim@umich.edu new CountedExitEvent(comLoadEventQueue[i], 1193486Sktlim@umich.edu "all threads reached the max load count", 1203486Sktlim@umich.edu max_loads_all_threads, *counter); 1212680SN/A } 1221070SN/A 1231070SN/A#ifdef FULL_SYSTEM 1241917SN/A memset(interrupts, 0, sizeof(interrupts)); 1252683Sktlim@umich.edu intstatus = 0; 126180SN/A#endif 127180SN/A} 1281858SN/A 1292235SN/A 130180SN/Avoid 1312235SN/ABaseCPU::regStats() 132180SN/A{ 133180SN/A using namespace Statistics; 1342862Sktlim@umich.edu 1352862Sktlim@umich.edu numCycles 1362313SN/A .name(name() + ".numCycles") 1372313SN/A .desc("number of cpu cycles simulated") 1382680SN/A ; 1392313SN/A 1402680SN/A int size = execContexts.size(); 1412313SN/A if (size > 1) { 1422313SN/A for (int i = 0; i < size; ++i) { 1432680SN/A stringstream namestr; 1442313SN/A ccprintf(namestr, "%s.ctx%d", name(), i); 1452361SN/A execContexts[i]->regStats(namestr.str()); 1463548Sgblack@eecs.umich.edu } 1472361SN/A } else if (size == 1) 1482361SN/A execContexts[0]->regStats(name()); 1492361SN/A} 1502235SN/A 151180SN/A 152180SN/Avoid 153180SN/ABaseCPU::registerExecContexts() 1542680SN/A{ 155180SN/A for (int i = 0; i < execContexts.size(); ++i) { 156180SN/A ExecContext *xc = execContexts[i]; 1572SN/A int cpu_id; 1582864Sktlim@umich.edu 1592864Sktlim@umich.edu#ifdef FULL_SYSTEM 1602864Sktlim@umich.edu cpu_id = system->registerExecContext(xc); 1612864Sktlim@umich.edu#else 1622864Sktlim@umich.edu cpu_id = xc->process->registerExecContext(xc); 1632864Sktlim@umich.edu#endif 1642864Sktlim@umich.edu 1652864Sktlim@umich.edu xc->cpu_id = cpu_id; 1662864Sktlim@umich.edu } 1673548Sgblack@eecs.umich.edu} 1682864Sktlim@umich.edu 1692864Sktlim@umich.edu 1702864Sktlim@umich.eduvoid 1712864Sktlim@umich.eduBaseCPU::switchOut() 1722864Sktlim@umich.edu{ 1732864Sktlim@umich.edu // default: do nothing 1742864Sktlim@umich.edu} 1752862Sktlim@umich.edu 1762862Sktlim@umich.eduvoid 1772862Sktlim@umich.eduBaseCPU::takeOverFrom(BaseCPU *oldCPU) 1782862Sktlim@umich.edu{ 1792862Sktlim@umich.edu assert(execContexts.size() == oldCPU->execContexts.size()); 1802862Sktlim@umich.edu 1812862Sktlim@umich.edu for (int i = 0; i < execContexts.size(); ++i) { 1822862Sktlim@umich.edu ExecContext *newXC = execContexts[i]; 1832862Sktlim@umich.edu ExecContext *oldXC = oldCPU->execContexts[i]; 1842915Sktlim@umich.edu 1852862Sktlim@umich.edu newXC->takeOverFrom(oldXC); 1862862Sktlim@umich.edu assert(newXC->cpu_id == oldXC->cpu_id); 1872862Sktlim@umich.edu#ifdef FULL_SYSTEM 1882683Sktlim@umich.edu system->replaceExecContext(newXC->cpu_id, newXC); 189217SN/A#else 1902862Sktlim@umich.edu assert(newXC->process == oldXC->process); 191223SN/A newXC->process->replaceExecContext(newXC->cpu_id, newXC); 192223SN/A#endif 193217SN/A } 194217SN/A 195217SN/A#ifdef FULL_SYSTEM 196217SN/A for (int i = 0; i < NumInterruptLevels; ++i) 1972683Sktlim@umich.edu interrupts[i] = oldCPU->interrupts[i]; 198217SN/A intstatus = oldCPU->intstatus; 1992862Sktlim@umich.edu#endif 200237SN/A} 201223SN/A 202217SN/A 203217SN/A#ifdef FULL_SYSTEM 2042683Sktlim@umich.eduvoid 2052683Sktlim@umich.eduBaseCPU::post_interrupt(int int_num, int index) 2062683Sktlim@umich.edu{ 2072683Sktlim@umich.edu DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); 2082683Sktlim@umich.edu 2092683Sktlim@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 2102683Sktlim@umich.edu panic("int_num out of bounds\n"); 2112683Sktlim@umich.edu 212217SN/A if (index < 0 || index >= sizeof(uint8_t) * 8) 213217SN/A panic("int_num out of bounds\n"); 2142683Sktlim@umich.edu 2152SN/A AlphaISA::check_interrupts = 1; 2162680SN/A interrupts[int_num] |= 1 << index; 2172SN/A intstatus |= (ULL(1) << int_num); 2182SN/A} 2192188SN/A 2202188SN/Avoid 2214400Srdreslin@umich.eduBaseCPU::clear_interrupt(int int_num, int index) 2224400Srdreslin@umich.edu{ 2234400Srdreslin@umich.edu DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); 2244400Srdreslin@umich.edu 2252290SN/A if (int_num < 0 || int_num >= NumInterruptLevels) 2262680SN/A panic("int_num out of bounds\n"); 2272290SN/A 2282290SN/A if (index < 0 || index >= sizeof(uint8_t) * 8) 2292683Sktlim@umich.edu panic("int_num out of bounds\n"); 230393SN/A 231393SN/A interrupts[int_num] &= ~(1 << index); 232393SN/A if (interrupts[int_num] == 0) 2332683Sktlim@umich.edu intstatus &= ~(ULL(1) << int_num); 234393SN/A} 2352680SN/A 236393SN/Avoid 237393SN/ABaseCPU::clear_interrupts() 2382188SN/A{ 2392188SN/A DPRINTF(Interrupt, "Interrupts all cleared\n"); 2402188SN/A 2411858SN/A memset(interrupts, 0, sizeof(interrupts)); 2422SN/A intstatus = 0; 243393SN/A} 2442680SN/A 2452SN/A#endif // FULL_SYSTEM 2462SN/A 2472SN/ADEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU) 2482188SN/A