base.cc revision 2
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
292SN/A#include <string>
302SN/A#include <sstream>
312439SN/A#include <iostream>
322984Sgblack@eecs.umich.edu
33146SN/A#include "base_cpu.hh"
34146SN/A#include "cprintf.hh"
35146SN/A#include "stats.hh"
36146SN/A#include "exec_context.hh"
37146SN/A#include "misc.hh"
38146SN/A#include "sim_events.hh"
391717SN/A
40146SN/Ausing namespace std;
411717SN/A
42146SN/Avector<BaseCPU *> BaseCPU::cpuList;
431977SN/A
442623SN/A// This variable reflects the max number of threads in any CPU.  Be
452683Sktlim@umich.edu// careful to only use it once all the CPUs that you care about have
461717SN/A// been initialized
47146SN/Aint maxThreadsPerCPU = 1;
482683Sktlim@umich.edu
493348Sbinkertn@umich.edu#ifdef FULL_SYSTEM
502683Sktlim@umich.eduBaseCPU::BaseCPU(const string &_name, int _number_of_threads,
512036SN/A                 Counter max_insts_any_thread,
52146SN/A                 Counter max_insts_all_threads,
5356SN/A                 System *_system, int num, Tick freq)
5456SN/A    : SimObject(_name), number(num), frequency(freq),
5556SN/A      number_of_threads(_number_of_threads), system(_system)
56695SN/A#else
572901Ssaidi@eecs.umich.eduBaseCPU::BaseCPU(const string &_name, int _number_of_threads,
582SN/A                 Counter max_insts_any_thread,
591858SN/A                 Counter max_insts_all_threads)
603565Sgblack@eecs.umich.edu    : SimObject(_name), number_of_threads(_number_of_threads)
613565Sgblack@eecs.umich.edu#endif
622171SN/A{
632170SN/A    // add self to global list of CPUs
643562Sgblack@eecs.umich.edu    cpuList.push_back(this);
65146SN/A
662462SN/A    if (number_of_threads > maxThreadsPerCPU)
67146SN/A        maxThreadsPerCPU = number_of_threads;
682SN/A
692SN/A    // allocate per-thread instruction-based event queues
702449SN/A    comInsnEventQueue = new (EventQueue *)[number_of_threads];
711355SN/A    for (int i = 0; i < number_of_threads; ++i)
722623SN/A        comInsnEventQueue[i] = new EventQueue("instruction-based event queue");
733402Sktlim@umich.edu
74224SN/A    //
751858SN/A    // set up instruction-count-based termination events, if any
762683Sktlim@umich.edu    //
772420SN/A    if (max_insts_any_thread != 0)
782683Sktlim@umich.edu        for (int i = 0; i < number_of_threads; ++i)
793402Sktlim@umich.edu            new SimExitEvent(comInsnEventQueue[i], max_insts_any_thread,
802420SN/A                "a thread reached the max instruction count");
812SN/A
822683Sktlim@umich.edu    if (max_insts_all_threads != 0) {
832672Sktlim@umich.edu        // allocate & initialize shared downcounter: each event will
842683Sktlim@umich.edu        // decrement this when triggered; simulation will terminate
852SN/A        // when counter reaches 0
862SN/A        int *counter = new int;
87334SN/A        *counter = number_of_threads;
88140SN/A        for (int i = 0; i < number_of_threads; ++i)
89334SN/A            new CountedExitEvent(comInsnEventQueue[i],
902SN/A                "all threads reached the max instruction count",
912SN/A                max_insts_all_threads, *counter);
922SN/A    }
932680Sktlim@umich.edu
942SN/A#ifdef FULL_SYSTEM
952SN/A    memset(interrupts, 0, sizeof(interrupts));
962623SN/A    intstatus = 0;
972SN/A#endif
982SN/A}
992SN/A
100180SN/Avoid
1012623SN/ABaseCPU::regStats()
102393SN/A{
103393SN/A    int size = contexts.size();
104393SN/A    if (size > 1) {
105393SN/A        for (int i = 0; i < size; ++i) {
106384SN/A            stringstream namestr;
107384SN/A            ccprintf(namestr, "%s.ctx%d", name(), i);
108393SN/A            contexts[i]->regStats(namestr.str());
1092623SN/A        }
110393SN/A    } else if (size == 1)
111393SN/A        contexts[0]->regStats(name());
112393SN/A}
113393SN/A
114384SN/A#ifdef FULL_SYSTEM
115189SN/Avoid
116189SN/ABaseCPU::post_interrupt(int int_num, int index)
1172623SN/A{
1182SN/A    DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
119729SN/A
120334SN/A    if (int_num < 0 || int_num >= NumInterruptLevels)
1212SN/A        panic("int_num out of bounds\n");
1222SN/A
1232SN/A    if (index < 0 || index >= sizeof(uint8_t) * 8)
1242SN/A        panic("int_num out of bounds\n");
1252SN/A
1262SN/A    AlphaISA::check_interrupts = 1;
1272SN/A    interrupts[int_num] |= 1 << index;
1282SN/A    intstatus |= (ULL(1) << int_num);
1292SN/A}
1302SN/A
1312SN/Avoid
1322SN/ABaseCPU::clear_interrupt(int int_num, int index)
1331001SN/A{
1341001SN/A    DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
1351001SN/A
1361001SN/A    if (int_num < 0 || int_num >= NumInterruptLevels)
1371001SN/A        panic("int_num out of bounds\n");
1382SN/A
1392SN/A    if (index < 0 || index >= sizeof(uint8_t) * 8)
1402SN/A        panic("int_num out of bounds\n");
1412SN/A
1422SN/A    interrupts[int_num] &= ~(1 << index);
1432SN/A    if (interrupts[int_num] == 0)
1442SN/A        intstatus &= ~(ULL(1) << int_num);
1452SN/A}
1462SN/A
1472SN/Avoid
1482SN/ABaseCPU::clear_interrupts()
1492SN/A{
1502SN/A    DPRINTF(Interrupt, "Interrupts all cleared\n");
1512SN/A
1522SN/A    memset(interrupts, 0, sizeof(interrupts));
1532SN/A    intstatus = 0;
1542SN/A}
1552390SN/A
1562390SN/A#endif // FULL_SYSTEM
1572390SN/A
1582390SN/ADEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU)
1592390SN/A