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