base.cc revision 180
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" 373565Sgblack@eecs.umich.edu#include "sim/param.hh" 385529Snate@binkert.org#include "sim/sim_events.hh" 398777Sgblack@eecs.umich.edu 401917SN/Ausing namespace std; 411070SN/A 421917SN/Avector<BaseCPU *> BaseCPU::cpuList; 432188SN/A 448777Sgblack@eecs.umich.edu// This variable reflects the max number of threads in any CPU. Be 458777Sgblack@eecs.umich.edu// careful to only use it once all the CPUs that you care about have 461917SN/A// been initialized 472290SN/Aint maxThreadsPerCPU = 1; 488777Sgblack@eecs.umich.edu 498777Sgblack@eecs.umich.edu#ifdef FULL_SYSTEM 508706Sandreas.hansson@arm.comBaseCPU::BaseCPU(const string &_name, int _number_of_threads, 518799Sgblack@eecs.umich.edu Counter max_insts_any_thread, 528809Sgblack@eecs.umich.edu Counter max_insts_all_threads, 538793Sgblack@eecs.umich.edu Counter max_loads_any_thread, 548777Sgblack@eecs.umich.edu Counter max_loads_all_threads, 551070SN/A System *_system, Tick freq) 561917SN/A : SimObject(_name), frequency(freq), 572519SN/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, 628820Sgblack@eecs.umich.edu Counter max_loads_any_thread, 638820Sgblack@eecs.umich.edu Counter max_loads_all_threads) 649384SAndreas.Sandberg@arm.com : SimObject(_name), number_of_threads(_number_of_threads) 659384SAndreas.Sandberg@arm.com#endif 669384SAndreas.Sandberg@arm.com{ 678766Sgblack@eecs.umich.edu // add self to global list of CPUs 688766Sgblack@eecs.umich.edu cpuList.push_back(this); 698766Sgblack@eecs.umich.edu 708766Sgblack@eecs.umich.edu if (number_of_threads > maxThreadsPerCPU) 719377Sgblack@eecs.umich.edu maxThreadsPerCPU = number_of_threads; 722683Sktlim@umich.edu 736022Sgblack@eecs.umich.edu // allocate per-thread instruction-based event queues 749384SAndreas.Sandberg@arm.com comInsnEventQueue = new (EventQueue *)[number_of_threads]; 759384SAndreas.Sandberg@arm.com for (int i = 0; i < number_of_threads; ++i) 769384SAndreas.Sandberg@arm.com comInsnEventQueue[i] = new EventQueue("instruction-based event queue"); 772SN/A 782683Sktlim@umich.edu // 792190SN/A // set up instruction-count-based termination events, if any 802680SN/A // 812290SN/A if (max_insts_any_thread != 0) 826316Sgblack@eecs.umich.edu for (int i = 0; i < number_of_threads; ++i) 831917SN/A new SimExitEvent(comInsnEventQueue[i], max_insts_any_thread, 848735Sandreas.hanson@arm.com "a thread reached the max instruction count"); 851982SN/A 861917SN/A if (max_insts_all_threads != 0) { 872683Sktlim@umich.edu // allocate & initialize shared downcounter: each event will 882683Sktlim@umich.edu // decrement this when triggered; simulation will terminate 891917SN/A // when counter reaches 0 901917SN/A int *counter = new int; 911917SN/A *counter = number_of_threads; 921917SN/A for (int i = 0; i < number_of_threads; ++i) 931917SN/A new CountedExitEvent(comInsnEventQueue[i], 941917SN/A "all threads reached the max instruction count", 951917SN/A max_insts_all_threads, *counter); 961917SN/A } 972521SN/A 985482Snate@binkert.org // allocate per-thread load-based event queues 993548Sgblack@eecs.umich.edu comLoadEventQueue = new (EventQueue *)[number_of_threads]; 1002SN/A for (int i = 0; i < number_of_threads; ++i) 1012862Sktlim@umich.edu comLoadEventQueue[i] = new EventQueue("load-based event queue"); 1022864Sktlim@umich.edu 1039384SAndreas.Sandberg@arm.com // 1042190SN/A // set up instruction-count-based termination events, if any 1052683Sktlim@umich.edu // 1062190SN/A if (max_loads_any_thread != 0) 1072190SN/A for (int i = 0; i < number_of_threads; ++i) 1082683Sktlim@umich.edu new SimExitEvent(comLoadEventQueue[i], max_loads_any_thread, 1091070SN/A "a thread reached the max load count"); 1102680SN/A 1111070SN/A if (max_loads_all_threads != 0) { 1121070SN/A // allocate & initialize shared downcounter: each event will 1131917SN/A // decrement this when triggered; simulation will terminate 1142683Sktlim@umich.edu // when counter reaches 0 115180SN/A int *counter = new int; 116180SN/A *counter = number_of_threads; 1178793Sgblack@eecs.umich.edu for (int i = 0; i < number_of_threads; ++i) 1188793Sgblack@eecs.umich.edu new CountedExitEvent(comLoadEventQueue[i], 1192235SN/A "all threads reached the max load count", 120180SN/A max_loads_all_threads, *counter); 1212862Sktlim@umich.edu } 1228793Sgblack@eecs.umich.edu 1238793Sgblack@eecs.umich.edu#ifdef FULL_SYSTEM 1248793Sgblack@eecs.umich.edu memset(interrupts, 0, sizeof(interrupts)); 1258793Sgblack@eecs.umich.edu intstatus = 0; 1268793Sgblack@eecs.umich.edu#endif 1278793Sgblack@eecs.umich.edu} 1288793Sgblack@eecs.umich.edu 1298793Sgblack@eecs.umich.edu 1308793Sgblack@eecs.umich.eduvoid 1318793Sgblack@eecs.umich.eduBaseCPU::regStats() 1328793Sgblack@eecs.umich.edu{ 1338793Sgblack@eecs.umich.edu int size = execContexts.size(); 1348793Sgblack@eecs.umich.edu if (size > 1) { 1358793Sgblack@eecs.umich.edu for (int i = 0; i < size; ++i) { 1368793Sgblack@eecs.umich.edu stringstream namestr; 1372313SN/A ccprintf(namestr, "%s.ctx%d", name(), i); 138180SN/A execContexts[i]->regStats(namestr.str()); 139180SN/A } 140180SN/A } else if (size == 1) 1416029Ssteve.reinhardt@amd.com execContexts[0]->regStats(name()); 142180SN/A} 143180SN/A 1442SN/A 1452864Sktlim@umich.eduvoid 1462864Sktlim@umich.eduBaseCPU::registerExecContexts() 1472864Sktlim@umich.edu{ 1482864Sktlim@umich.edu for (int i = 0; i < execContexts.size(); ++i) { 1498793Sgblack@eecs.umich.edu ExecContext *xc = execContexts[i]; 1508793Sgblack@eecs.umich.edu int cpu_id; 1518793Sgblack@eecs.umich.edu 1528793Sgblack@eecs.umich.edu#ifdef FULL_SYSTEM 1538793Sgblack@eecs.umich.edu cpu_id = system->registerExecContext(xc); 1548793Sgblack@eecs.umich.edu#else 1558793Sgblack@eecs.umich.edu cpu_id = xc->process->registerExecContext(xc); 1568793Sgblack@eecs.umich.edu#endif 1578793Sgblack@eecs.umich.edu 1582864Sktlim@umich.edu xc->cpu_id = cpu_id; 1592864Sktlim@umich.edu } 1602864Sktlim@umich.edu} 1612864Sktlim@umich.edu 1622862Sktlim@umich.edu 1632862Sktlim@umich.eduvoid 1642862Sktlim@umich.eduBaseCPU::switchOut() 1652862Sktlim@umich.edu{ 1662862Sktlim@umich.edu // default: do nothing 1678793Sgblack@eecs.umich.edu} 1688793Sgblack@eecs.umich.edu 1695714Shsul@eecs.umich.eduvoid 1705715Shsul@eecs.umich.eduBaseCPU::takeOverFrom(BaseCPU *oldCPU) 1715714Shsul@eecs.umich.edu{ 1722862Sktlim@umich.edu assert(execContexts.size() == oldCPU->execContexts.size()); 1732862Sktlim@umich.edu 1742862Sktlim@umich.edu for (int i = 0; i < execContexts.size(); ++i) { 1752683Sktlim@umich.edu ExecContext *newXC = execContexts[i]; 176217SN/A ExecContext *oldXC = oldCPU->execContexts[i]; 1772862Sktlim@umich.edu 1786315Sgblack@eecs.umich.edu newXC->takeOverFrom(oldXC); 1796316Sgblack@eecs.umich.edu assert(newXC->cpu_id == oldXC->cpu_id); 1807720Sgblack@eecs.umich.edu#ifdef FULL_SYSTEM 181223SN/A system->replaceExecContext(newXC->cpu_id, newXC); 1826677SBrad.Beckmann@amd.com#else 1836677SBrad.Beckmann@amd.com assert(newXC->process == oldXC->process); 1846677SBrad.Beckmann@amd.com newXC->process->replaceExecContext(newXC->cpu_id, newXC); 1856677SBrad.Beckmann@amd.com#endif 1869384SAndreas.Sandberg@arm.com } 187217SN/A} 188217SN/A 189217SN/A 190217SN/A#ifdef FULL_SYSTEM 1912683Sktlim@umich.eduvoid 192217SN/ABaseCPU::post_interrupt(int int_num, int index) 1932862Sktlim@umich.edu{ 1946315Sgblack@eecs.umich.edu DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); 1956316Sgblack@eecs.umich.edu 1967720Sgblack@eecs.umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 197223SN/A panic("int_num out of bounds\n"); 1986677SBrad.Beckmann@amd.com 1996677SBrad.Beckmann@amd.com if (index < 0 || index >= sizeof(uint8_t) * 8) 2006677SBrad.Beckmann@amd.com panic("int_num out of bounds\n"); 2016677SBrad.Beckmann@amd.com 2029384SAndreas.Sandberg@arm.com AlphaISA::check_interrupts = 1; 203217SN/A interrupts[int_num] |= 1 << index; 204217SN/A intstatus |= (ULL(1) << int_num); 2052683Sktlim@umich.edu} 2062683Sktlim@umich.edu 2072683Sktlim@umich.eduvoid 2088735Sandreas.hanson@arm.comBaseCPU::clear_interrupt(int int_num, int index) 2098735Sandreas.hanson@arm.com{ 2102683Sktlim@umich.edu DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); 2112683Sktlim@umich.edu 212217SN/A if (int_num < 0 || int_num >= NumInterruptLevels) 213217SN/A panic("int_num out of bounds\n"); 2149180Sandreas.hansson@arm.com 2152SN/A if (index < 0 || index >= sizeof(uint8_t) * 8) 2162680SN/A panic("int_num out of bounds\n"); 2172SN/A 2182SN/A interrupts[int_num] &= ~(1 << index); 2197823Ssteve.reinhardt@amd.com if (interrupts[int_num] == 0) 2202188SN/A intstatus &= ~(ULL(1) << int_num); 2214400Srdreslin@umich.edu} 2225715Shsul@eecs.umich.edu 2235543Ssaidi@eecs.umich.eduvoid 2244400Srdreslin@umich.eduBaseCPU::clear_interrupts() 2252290SN/A{ 2262680SN/A DPRINTF(Interrupt, "Interrupts all cleared\n"); 2272290SN/A 2282290SN/A memset(interrupts, 0, sizeof(interrupts)); 2298735Sandreas.hanson@arm.com intstatus = 0; 230393SN/A} 231393SN/A 232393SN/A#endif // FULL_SYSTEM 2332683Sktlim@umich.edu 234393SN/A// 2352680SN/A// This declaration is not needed now that SamplingCPU provides a 236393SN/A// BaseCPUBuilder object. 237393SN/A// 2387823Ssteve.reinhardt@amd.com#if 0 2397823Ssteve.reinhardt@amd.comDEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU) 2402680SN/A#endif 2418735Sandreas.hanson@arm.com