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