base.cc revision 1129
110259SAndrew.Bardsley@arm.com/* 210259SAndrew.Bardsley@arm.com * Copyright (c) 2002-2004 The Regents of The University of Michigan 310259SAndrew.Bardsley@arm.com * All rights reserved. 410259SAndrew.Bardsley@arm.com * 510259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without 610259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are 710259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright 810259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer; 910259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright 1010259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the 1110259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution; 1210259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its 1310259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from 1410259SAndrew.Bardsley@arm.com * this software without specific prior written permission. 1510259SAndrew.Bardsley@arm.com * 1610259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710259SAndrew.Bardsley@arm.com */ 2810259SAndrew.Bardsley@arm.com 2910259SAndrew.Bardsley@arm.com#include <string> 3010259SAndrew.Bardsley@arm.com#include <sstream> 3110259SAndrew.Bardsley@arm.com#include <iostream> 3210259SAndrew.Bardsley@arm.com 3310259SAndrew.Bardsley@arm.com#include "cpu/base_cpu.hh" 3410259SAndrew.Bardsley@arm.com#include "base/cprintf.hh" 3510259SAndrew.Bardsley@arm.com#include "cpu/exec_context.hh" 3610259SAndrew.Bardsley@arm.com#include "base/misc.hh" 3710259SAndrew.Bardsley@arm.com#include "sim/param.hh" 3810259SAndrew.Bardsley@arm.com#include "sim/sim_events.hh" 3910259SAndrew.Bardsley@arm.com 4010259SAndrew.Bardsley@arm.comusing namespace std; 4110259SAndrew.Bardsley@arm.com 4210259SAndrew.Bardsley@arm.comvector<BaseCPU *> BaseCPU::cpuList; 4312563Sgabeblack@google.com 4412563Sgabeblack@google.com// This variable reflects the max number of threads in any CPU. Be 4510259SAndrew.Bardsley@arm.com// careful to only use it once all the CPUs that you care about have 4610259SAndrew.Bardsley@arm.com// been initialized 4710259SAndrew.Bardsley@arm.comint maxThreadsPerCPU = 1; 4810259SAndrew.Bardsley@arm.com 4910259SAndrew.Bardsley@arm.com#ifdef FULL_SYSTEM 5010259SAndrew.Bardsley@arm.comBaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg, 5110785Sgope@wisc.edu Counter max_insts_any_thread, 5210259SAndrew.Bardsley@arm.com Counter max_insts_all_threads, 5310259SAndrew.Bardsley@arm.com Counter max_loads_any_thread, 5410259SAndrew.Bardsley@arm.com Counter max_loads_all_threads, 5510259SAndrew.Bardsley@arm.com System *_system, Tick freq) 5610259SAndrew.Bardsley@arm.com : SimObject(_name), frequency(freq), deferRegistration(_def_reg), 5710259SAndrew.Bardsley@arm.com number_of_threads(_number_of_threads), system(_system) 5810259SAndrew.Bardsley@arm.com#else 5910259SAndrew.Bardsley@arm.comBaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg, 6010259SAndrew.Bardsley@arm.com Counter max_insts_any_thread, 6110259SAndrew.Bardsley@arm.com Counter max_insts_all_threads, 6210259SAndrew.Bardsley@arm.com Counter max_loads_any_thread, 6310259SAndrew.Bardsley@arm.com Counter max_loads_all_threads) 6410259SAndrew.Bardsley@arm.com : SimObject(_name), deferRegistration(_def_reg), 6510259SAndrew.Bardsley@arm.com number_of_threads(_number_of_threads) 6610259SAndrew.Bardsley@arm.com#endif 6710259SAndrew.Bardsley@arm.com{ 6810259SAndrew.Bardsley@arm.com // add self to global list of CPUs 6910259SAndrew.Bardsley@arm.com cpuList.push_back(this); 7010259SAndrew.Bardsley@arm.com 7110259SAndrew.Bardsley@arm.com if (number_of_threads > maxThreadsPerCPU) 7210259SAndrew.Bardsley@arm.com maxThreadsPerCPU = number_of_threads; 7310259SAndrew.Bardsley@arm.com 7410259SAndrew.Bardsley@arm.com // allocate per-thread instruction-based event queues 7510259SAndrew.Bardsley@arm.com comInstEventQueue = new (EventQueue *)[number_of_threads]; 7610259SAndrew.Bardsley@arm.com for (int i = 0; i < number_of_threads; ++i) 7710259SAndrew.Bardsley@arm.com comInstEventQueue[i] = new EventQueue("instruction-based event queue"); 7810259SAndrew.Bardsley@arm.com 7910259SAndrew.Bardsley@arm.com // 8010259SAndrew.Bardsley@arm.com // set up instruction-count-based termination events, if any 8110259SAndrew.Bardsley@arm.com // 8210259SAndrew.Bardsley@arm.com if (max_insts_any_thread != 0) 8310259SAndrew.Bardsley@arm.com for (int i = 0; i < number_of_threads; ++i) 8410259SAndrew.Bardsley@arm.com new SimExitEvent(comInstEventQueue[i], max_insts_any_thread, 8510259SAndrew.Bardsley@arm.com "a thread reached the max instruction count"); 8610259SAndrew.Bardsley@arm.com 8710259SAndrew.Bardsley@arm.com if (max_insts_all_threads != 0) { 8810259SAndrew.Bardsley@arm.com // allocate & initialize shared downcounter: each event will 8910259SAndrew.Bardsley@arm.com // decrement this when triggered; simulation will terminate 9010259SAndrew.Bardsley@arm.com // when counter reaches 0 9110259SAndrew.Bardsley@arm.com int *counter = new int; 9210259SAndrew.Bardsley@arm.com *counter = number_of_threads; 9310259SAndrew.Bardsley@arm.com for (int i = 0; i < number_of_threads; ++i) 9410259SAndrew.Bardsley@arm.com new CountedExitEvent(comInstEventQueue[i], 9510259SAndrew.Bardsley@arm.com "all threads reached the max instruction count", 9610259SAndrew.Bardsley@arm.com max_insts_all_threads, *counter); 9710259SAndrew.Bardsley@arm.com } 9810259SAndrew.Bardsley@arm.com 9910259SAndrew.Bardsley@arm.com // allocate per-thread load-based event queues 10010259SAndrew.Bardsley@arm.com comLoadEventQueue = new (EventQueue *)[number_of_threads]; 10110259SAndrew.Bardsley@arm.com for (int i = 0; i < number_of_threads; ++i) 10210259SAndrew.Bardsley@arm.com comLoadEventQueue[i] = new EventQueue("load-based event queue"); 10310259SAndrew.Bardsley@arm.com 10410259SAndrew.Bardsley@arm.com // 10510259SAndrew.Bardsley@arm.com // set up instruction-count-based termination events, if any 10610259SAndrew.Bardsley@arm.com // 10710259SAndrew.Bardsley@arm.com if (max_loads_any_thread != 0) 10810259SAndrew.Bardsley@arm.com for (int i = 0; i < number_of_threads; ++i) 10910259SAndrew.Bardsley@arm.com new SimExitEvent(comLoadEventQueue[i], max_loads_any_thread, 11010259SAndrew.Bardsley@arm.com "a thread reached the max load count"); 11110259SAndrew.Bardsley@arm.com 11210259SAndrew.Bardsley@arm.com if (max_loads_all_threads != 0) { 11310259SAndrew.Bardsley@arm.com // allocate & initialize shared downcounter: each event will 11410259SAndrew.Bardsley@arm.com // decrement this when triggered; simulation will terminate 11510259SAndrew.Bardsley@arm.com // when counter reaches 0 11610259SAndrew.Bardsley@arm.com int *counter = new int; 11710259SAndrew.Bardsley@arm.com *counter = number_of_threads; 11810259SAndrew.Bardsley@arm.com for (int i = 0; i < number_of_threads; ++i) 11910259SAndrew.Bardsley@arm.com new CountedExitEvent(comLoadEventQueue[i], 12010259SAndrew.Bardsley@arm.com "all threads reached the max load count", 12110259SAndrew.Bardsley@arm.com max_loads_all_threads, *counter); 12210259SAndrew.Bardsley@arm.com } 12310259SAndrew.Bardsley@arm.com 12410259SAndrew.Bardsley@arm.com#ifdef FULL_SYSTEM 12510259SAndrew.Bardsley@arm.com memset(interrupts, 0, sizeof(interrupts)); 12610259SAndrew.Bardsley@arm.com intstatus = 0; 12710259SAndrew.Bardsley@arm.com#endif 12810259SAndrew.Bardsley@arm.com} 12910259SAndrew.Bardsley@arm.com 13010259SAndrew.Bardsley@arm.comvoid 13110259SAndrew.Bardsley@arm.comBaseCPU::init() 13210259SAndrew.Bardsley@arm.com{ 13310259SAndrew.Bardsley@arm.com if (!deferRegistration) 13410259SAndrew.Bardsley@arm.com registerExecContexts(); 13510259SAndrew.Bardsley@arm.com} 13610259SAndrew.Bardsley@arm.com 13710259SAndrew.Bardsley@arm.comvoid 13810259SAndrew.Bardsley@arm.comBaseCPU::regStats() 13910259SAndrew.Bardsley@arm.com{ 14010259SAndrew.Bardsley@arm.com using namespace Stats; 14110259SAndrew.Bardsley@arm.com 14210259SAndrew.Bardsley@arm.com numCycles 14310259SAndrew.Bardsley@arm.com .name(name() + ".numCycles") 14410259SAndrew.Bardsley@arm.com .desc("number of cpu cycles simulated") 14510259SAndrew.Bardsley@arm.com ; 14610259SAndrew.Bardsley@arm.com 14711683Sfernando.endo2@gmail.com int size = execContexts.size(); 14811683Sfernando.endo2@gmail.com if (size > 1) { 14910259SAndrew.Bardsley@arm.com for (int i = 0; i < size; ++i) { 15010259SAndrew.Bardsley@arm.com stringstream namestr; 15110259SAndrew.Bardsley@arm.com ccprintf(namestr, "%s.ctx%d", name(), i); 15210259SAndrew.Bardsley@arm.com execContexts[i]->regStats(namestr.str()); 15310259SAndrew.Bardsley@arm.com } 15410259SAndrew.Bardsley@arm.com } else if (size == 1) 15510259SAndrew.Bardsley@arm.com execContexts[0]->regStats(name()); 15610259SAndrew.Bardsley@arm.com} 15710259SAndrew.Bardsley@arm.com 15810259SAndrew.Bardsley@arm.com 15911683Sfernando.endo2@gmail.comvoid 16011683Sfernando.endo2@gmail.comBaseCPU::registerExecContexts() 16110259SAndrew.Bardsley@arm.com{ 16210259SAndrew.Bardsley@arm.com for (int i = 0; i < execContexts.size(); ++i) { 16310259SAndrew.Bardsley@arm.com ExecContext *xc = execContexts[i]; 16410259SAndrew.Bardsley@arm.com int cpu_id; 16510259SAndrew.Bardsley@arm.com 16610259SAndrew.Bardsley@arm.com#ifdef FULL_SYSTEM 16710259SAndrew.Bardsley@arm.com cpu_id = system->registerExecContext(xc); 16810259SAndrew.Bardsley@arm.com#else 16910259SAndrew.Bardsley@arm.com cpu_id = xc->process->registerExecContext(xc); 17010259SAndrew.Bardsley@arm.com#endif 17110259SAndrew.Bardsley@arm.com 17210259SAndrew.Bardsley@arm.com xc->cpu_id = cpu_id; 17310259SAndrew.Bardsley@arm.com } 17410259SAndrew.Bardsley@arm.com} 17511567Smitch.hayenga@arm.com 17611567Smitch.hayenga@arm.com 17710259SAndrew.Bardsley@arm.comvoid 17810259SAndrew.Bardsley@arm.comBaseCPU::switchOut() 17910259SAndrew.Bardsley@arm.com{ 18010259SAndrew.Bardsley@arm.com // default: do nothing 18110259SAndrew.Bardsley@arm.com} 18210259SAndrew.Bardsley@arm.com 18310259SAndrew.Bardsley@arm.comvoid 18410259SAndrew.Bardsley@arm.comBaseCPU::takeOverFrom(BaseCPU *oldCPU) 18510259SAndrew.Bardsley@arm.com{ 18610259SAndrew.Bardsley@arm.com assert(execContexts.size() == oldCPU->execContexts.size()); 18710259SAndrew.Bardsley@arm.com 18810259SAndrew.Bardsley@arm.com for (int i = 0; i < execContexts.size(); ++i) { 18910259SAndrew.Bardsley@arm.com ExecContext *newXC = execContexts[i]; 19010259SAndrew.Bardsley@arm.com ExecContext *oldXC = oldCPU->execContexts[i]; 19110259SAndrew.Bardsley@arm.com 19210259SAndrew.Bardsley@arm.com newXC->takeOverFrom(oldXC); 19311567Smitch.hayenga@arm.com assert(newXC->cpu_id == oldXC->cpu_id); 19411567Smitch.hayenga@arm.com#ifdef FULL_SYSTEM 19510259SAndrew.Bardsley@arm.com system->replaceExecContext(newXC, newXC->cpu_id); 19610259SAndrew.Bardsley@arm.com#else 19710259SAndrew.Bardsley@arm.com assert(newXC->process == oldXC->process); 19810259SAndrew.Bardsley@arm.com newXC->process->replaceExecContext(newXC, newXC->cpu_id); 19910259SAndrew.Bardsley@arm.com#endif 20010259SAndrew.Bardsley@arm.com } 20110259SAndrew.Bardsley@arm.com 20210259SAndrew.Bardsley@arm.com#ifdef FULL_SYSTEM 20310259SAndrew.Bardsley@arm.com for (int i = 0; i < NumInterruptLevels; ++i) 20410259SAndrew.Bardsley@arm.com interrupts[i] = oldCPU->interrupts[i]; 20510259SAndrew.Bardsley@arm.com intstatus = oldCPU->intstatus; 20610259SAndrew.Bardsley@arm.com#endif 20710259SAndrew.Bardsley@arm.com} 20810259SAndrew.Bardsley@arm.com 20910259SAndrew.Bardsley@arm.com 21010259SAndrew.Bardsley@arm.com#ifdef FULL_SYSTEM 21110259SAndrew.Bardsley@arm.comvoid 21210259SAndrew.Bardsley@arm.comBaseCPU::post_interrupt(int int_num, int index) 21310259SAndrew.Bardsley@arm.com{ 21410259SAndrew.Bardsley@arm.com DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); 21510259SAndrew.Bardsley@arm.com 21610259SAndrew.Bardsley@arm.com if (int_num < 0 || int_num >= NumInterruptLevels) 21710259SAndrew.Bardsley@arm.com panic("int_num out of bounds\n"); 21810259SAndrew.Bardsley@arm.com 21910259SAndrew.Bardsley@arm.com if (index < 0 || index >= sizeof(uint64_t) * 8) 22010259SAndrew.Bardsley@arm.com panic("int_num out of bounds\n"); 22110259SAndrew.Bardsley@arm.com 22210259SAndrew.Bardsley@arm.com AlphaISA::check_interrupts = 1; 22310259SAndrew.Bardsley@arm.com interrupts[int_num] |= 1 << index; 22410259SAndrew.Bardsley@arm.com intstatus |= (ULL(1) << int_num); 22510259SAndrew.Bardsley@arm.com} 22610259SAndrew.Bardsley@arm.com 22710259SAndrew.Bardsley@arm.comvoid 22810259SAndrew.Bardsley@arm.comBaseCPU::clear_interrupt(int int_num, int index) 22910259SAndrew.Bardsley@arm.com{ 23010259SAndrew.Bardsley@arm.com DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); 23110259SAndrew.Bardsley@arm.com 23210259SAndrew.Bardsley@arm.com if (int_num < 0 || int_num >= NumInterruptLevels) 23310259SAndrew.Bardsley@arm.com panic("int_num out of bounds\n"); 23410259SAndrew.Bardsley@arm.com 23510259SAndrew.Bardsley@arm.com if (index < 0 || index >= sizeof(uint64_t) * 8) 23610259SAndrew.Bardsley@arm.com panic("int_num out of bounds\n"); 23710259SAndrew.Bardsley@arm.com 23810259SAndrew.Bardsley@arm.com interrupts[int_num] &= ~(1 << index); 23910259SAndrew.Bardsley@arm.com if (interrupts[int_num] == 0) 24010259SAndrew.Bardsley@arm.com intstatus &= ~(ULL(1) << int_num); 24110259SAndrew.Bardsley@arm.com} 24210259SAndrew.Bardsley@arm.com 24310259SAndrew.Bardsley@arm.comvoid 24410259SAndrew.Bardsley@arm.comBaseCPU::clear_interrupts() 24510259SAndrew.Bardsley@arm.com{ 24610259SAndrew.Bardsley@arm.com DPRINTF(Interrupt, "Interrupts all cleared\n"); 24710259SAndrew.Bardsley@arm.com 24810259SAndrew.Bardsley@arm.com memset(interrupts, 0, sizeof(interrupts)); 24910259SAndrew.Bardsley@arm.com intstatus = 0; 25010259SAndrew.Bardsley@arm.com} 25110259SAndrew.Bardsley@arm.com 25210259SAndrew.Bardsley@arm.com 25310259SAndrew.Bardsley@arm.comvoid 25410259SAndrew.Bardsley@arm.comBaseCPU::serialize(std::ostream &os) 25510259SAndrew.Bardsley@arm.com{ 25610259SAndrew.Bardsley@arm.com SERIALIZE_ARRAY(interrupts, NumInterruptLevels); 25710259SAndrew.Bardsley@arm.com SERIALIZE_SCALAR(intstatus); 25810259SAndrew.Bardsley@arm.com} 25910259SAndrew.Bardsley@arm.com 26010259SAndrew.Bardsley@arm.comvoid 26110259SAndrew.Bardsley@arm.comBaseCPU::unserialize(Checkpoint *cp, const std::string §ion) 26210259SAndrew.Bardsley@arm.com{ 26310259SAndrew.Bardsley@arm.com UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels); 26410259SAndrew.Bardsley@arm.com UNSERIALIZE_SCALAR(intstatus); 26510259SAndrew.Bardsley@arm.com} 26610259SAndrew.Bardsley@arm.com 26710259SAndrew.Bardsley@arm.com#endif // FULL_SYSTEM 26810259SAndrew.Bardsley@arm.com 26910259SAndrew.Bardsley@arm.comDEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU) 27010259SAndrew.Bardsley@arm.com