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