base.cc revision 146
15326Sgblack@eecs.umich.edu/*
25326Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan
35326Sgblack@eecs.umich.edu * All rights reserved.
45326Sgblack@eecs.umich.edu *
55326Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
65326Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
75326Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
85326Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
95326Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
105326Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
115326Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
125326Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
135326Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
145326Sgblack@eecs.umich.edu * this software without specific prior written permission.
155326Sgblack@eecs.umich.edu *
165326Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175326Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185326Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195326Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205326Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215326Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225326Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235326Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245326Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255326Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265326Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275326Sgblack@eecs.umich.edu */
285326Sgblack@eecs.umich.edu
295326Sgblack@eecs.umich.edu#include <cmath>
305081Sgblack@eecs.umich.edu#include <cstdio>
315081Sgblack@eecs.umich.edu#include <cstdlib>
325081Sgblack@eecs.umich.edu#include <iostream>
335081Sgblack@eecs.umich.edu#include <iomanip>
345081Sgblack@eecs.umich.edu#include <list>
355081Sgblack@eecs.umich.edu#include <sstream>
365081Sgblack@eecs.umich.edu#include <string>
375081Sgblack@eecs.umich.edu
385081Sgblack@eecs.umich.edu#include "base/cprintf.hh"
395081Sgblack@eecs.umich.edu#include "base/inifile.hh"
405081Sgblack@eecs.umich.edu#include "base/loader/symtab.hh"
415081Sgblack@eecs.umich.edu#include "base/misc.hh"
425081Sgblack@eecs.umich.edu#include "base/pollevent.hh"
435081Sgblack@eecs.umich.edu#include "base/range.hh"
445081Sgblack@eecs.umich.edu#include "base/trace.hh"
455081Sgblack@eecs.umich.edu#include "cpu/base_cpu.hh"
465081Sgblack@eecs.umich.edu#include "cpu/exec_context.hh"
475081Sgblack@eecs.umich.edu#include "cpu/exetrace.hh"
485081Sgblack@eecs.umich.edu#include "cpu/full_cpu/smt.hh"
495081Sgblack@eecs.umich.edu#include "cpu/simple_cpu/simple_cpu.hh"
505081Sgblack@eecs.umich.edu#include "cpu/static_inst.hh"
515081Sgblack@eecs.umich.edu#include "mem/base_mem.hh"
525081Sgblack@eecs.umich.edu#include "mem/mem_interface.hh"
535081Sgblack@eecs.umich.edu#include "sim/annotation.hh"
545081Sgblack@eecs.umich.edu#include "sim/builder.hh"
555081Sgblack@eecs.umich.edu#include "sim/debug.hh"
565081Sgblack@eecs.umich.edu#include "sim/host.hh"
575081Sgblack@eecs.umich.edu#include "sim/sim_events.hh"
585081Sgblack@eecs.umich.edu#include "sim/sim_object.hh"
595081Sgblack@eecs.umich.edu#include "sim/sim_stats.hh"
605081Sgblack@eecs.umich.edu
615081Sgblack@eecs.umich.edu#ifdef FULL_SYSTEM
625081Sgblack@eecs.umich.edu#include "base/remote_gdb.hh"
635081Sgblack@eecs.umich.edu#include "dev/alpha_access.h"
645081Sgblack@eecs.umich.edu#include "dev/pciareg.h"
655081Sgblack@eecs.umich.edu#include "mem/functional_mem/memory_control.hh"
665081Sgblack@eecs.umich.edu#include "mem/functional_mem/physical_memory.hh"
675081Sgblack@eecs.umich.edu#include "sim/system.hh"
685081Sgblack@eecs.umich.edu#include "targetarch/alpha_memory.hh"
695081Sgblack@eecs.umich.edu#include "targetarch/vtophys.hh"
705081Sgblack@eecs.umich.edu#else // !FULL_SYSTEM
715081Sgblack@eecs.umich.edu#include "eio/eio.hh"
725081Sgblack@eecs.umich.edu#include "mem/functional_mem/functional_memory.hh"
735081Sgblack@eecs.umich.edu#include "sim/prog.hh"
745081Sgblack@eecs.umich.edu#endif // FULL_SYSTEM
755081Sgblack@eecs.umich.edu
765081Sgblack@eecs.umich.eduusing namespace std;
775081Sgblack@eecs.umich.edu
785081Sgblack@eecs.umich.eduSimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu)
795081Sgblack@eecs.umich.edu    : Event(&mainEventQueue),
805081Sgblack@eecs.umich.edu      cpu(_cpu)
815081Sgblack@eecs.umich.edu{
825081Sgblack@eecs.umich.edu}
835081Sgblack@eecs.umich.edu
845240Sgblack@eecs.umich.eduvoid SimpleCPU::CacheCompletionEvent::process()
855240Sgblack@eecs.umich.edu{
865240Sgblack@eecs.umich.edu    cpu->processCacheCompletion();
875240Sgblack@eecs.umich.edu}
885240Sgblack@eecs.umich.edu
895240Sgblack@eecs.umich.educonst char *
905306Sgblack@eecs.umich.eduSimpleCPU::CacheCompletionEvent::description()
915240Sgblack@eecs.umich.edu{
925240Sgblack@eecs.umich.edu    return "cache completion event";
935240Sgblack@eecs.umich.edu}
945326Sgblack@eecs.umich.edu
955240Sgblack@eecs.umich.edu#ifdef FULL_SYSTEM
965240Sgblack@eecs.umich.eduSimpleCPU::SimpleCPU(const string &_name,
975240Sgblack@eecs.umich.edu                     System *_system,
985240Sgblack@eecs.umich.edu                     Counter max_insts_any_thread,
995240Sgblack@eecs.umich.edu                     Counter max_insts_all_threads,
1005306Sgblack@eecs.umich.edu                     Counter max_loads_any_thread,
1015326Sgblack@eecs.umich.edu                     Counter max_loads_all_threads,
1025240Sgblack@eecs.umich.edu                     AlphaItb *itb, AlphaDtb *dtb,
1035240Sgblack@eecs.umich.edu                     FunctionalMemory *mem,
1045240Sgblack@eecs.umich.edu                     MemInterface *icache_interface,
1055240Sgblack@eecs.umich.edu                     MemInterface *dcache_interface,
1065240Sgblack@eecs.umich.edu                     int cpu_id, Tick freq)
1075240Sgblack@eecs.umich.edu    : BaseCPU(_name, /* number_of_threads */ 1,
1085240Sgblack@eecs.umich.edu              max_insts_any_thread, max_insts_all_threads,
1095240Sgblack@eecs.umich.edu              max_loads_any_thread, max_loads_all_threads,
1105326Sgblack@eecs.umich.edu              _system, cpu_id, freq),
1115326Sgblack@eecs.umich.edu#else
1125326Sgblack@eecs.umich.eduSimpleCPU::SimpleCPU(const string &_name, Process *_process,
1135326Sgblack@eecs.umich.edu                     Counter max_insts_any_thread,
1145240Sgblack@eecs.umich.edu                     Counter max_insts_all_threads,
1155240Sgblack@eecs.umich.edu                     Counter max_loads_any_thread,
1165240Sgblack@eecs.umich.edu                     Counter max_loads_all_threads,
1175240Sgblack@eecs.umich.edu                     MemInterface *icache_interface,
1185240Sgblack@eecs.umich.edu                     MemInterface *dcache_interface)
1195326Sgblack@eecs.umich.edu    : BaseCPU(_name, /* number_of_threads */ 1,
1205326Sgblack@eecs.umich.edu              max_insts_any_thread, max_insts_all_threads,
1215326Sgblack@eecs.umich.edu              max_loads_any_thread, max_loads_all_threads),
1225326Sgblack@eecs.umich.edu#endif
1235240Sgblack@eecs.umich.edu      tickEvent(this), xc(NULL), cacheCompletionEvent(this)
1245240Sgblack@eecs.umich.edu{
1255240Sgblack@eecs.umich.edu#ifdef FULL_SYSTEM
1265240Sgblack@eecs.umich.edu    xc = new ExecContext(this, 0, system, itb, dtb, mem, cpu_id);
1275240Sgblack@eecs.umich.edu
1285240Sgblack@eecs.umich.edu    _status = Running;
1295240Sgblack@eecs.umich.edu    if (cpu_id != 0) {
1305240Sgblack@eecs.umich.edu
1315240Sgblack@eecs.umich.edu       xc->setStatus(ExecContext::Unallocated);
1325240Sgblack@eecs.umich.edu
1335240Sgblack@eecs.umich.edu       //Open a GDB debug session on port (7000 + the cpu_id)
1345306Sgblack@eecs.umich.edu       (new GDBListener(new RemoteGDB(system, xc), 7000 + cpu_id))->listen();
1355240Sgblack@eecs.umich.edu
1365240Sgblack@eecs.umich.edu       AlphaISA::init(system->physmem, &xc->regs);
1375240Sgblack@eecs.umich.edu
1385326Sgblack@eecs.umich.edu       fault = Reset_Fault;
1395326Sgblack@eecs.umich.edu
1405326Sgblack@eecs.umich.edu       IntReg *ipr = xc->regs.ipr;
1415240Sgblack@eecs.umich.edu       ipr[TheISA::IPR_MCSR] = 0x6;
1425326Sgblack@eecs.umich.edu
1435326Sgblack@eecs.umich.edu       AlphaISA::swap_palshadow(&xc->regs, true);
1445240Sgblack@eecs.umich.edu
1455240Sgblack@eecs.umich.edu       xc->regs.pc =
1465240Sgblack@eecs.umich.edu           ipr[TheISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
1475306Sgblack@eecs.umich.edu       xc->regs.npc = xc->regs.pc + sizeof(MachInst);
1485306Sgblack@eecs.umich.edu
1495326Sgblack@eecs.umich.edu       _status = Idle;
1505326Sgblack@eecs.umich.edu    }
1515326Sgblack@eecs.umich.edu    else {
1525240Sgblack@eecs.umich.edu      system->init(xc);
1535326Sgblack@eecs.umich.edu
1545326Sgblack@eecs.umich.edu      // Reset the system
1555240Sgblack@eecs.umich.edu      //
1565240Sgblack@eecs.umich.edu      AlphaISA::init(system->physmem, &xc->regs);
1576096Sgblack@eecs.umich.edu
1586096Sgblack@eecs.umich.edu      fault = Reset_Fault;
1596096Sgblack@eecs.umich.edu
1606096Sgblack@eecs.umich.edu      IntReg *ipr = xc->regs.ipr;
1616096Sgblack@eecs.umich.edu      ipr[TheISA::IPR_MCSR] = 0x6;
1626096Sgblack@eecs.umich.edu
1636096Sgblack@eecs.umich.edu      AlphaISA::swap_palshadow(&xc->regs, true);
1646096Sgblack@eecs.umich.edu
1656096Sgblack@eecs.umich.edu      xc->regs.pc = ipr[TheISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
1666096Sgblack@eecs.umich.edu      xc->regs.npc = xc->regs.pc + sizeof(MachInst);
1676096Sgblack@eecs.umich.edu
1686096Sgblack@eecs.umich.edu       _status = Running;
1696096Sgblack@eecs.umich.edu       tickEvent.schedule(0);
1706096Sgblack@eecs.umich.edu    }
1716096Sgblack@eecs.umich.edu
1726096Sgblack@eecs.umich.edu#else
1736096Sgblack@eecs.umich.edu    xc = new ExecContext(this, /* thread_num */ 0, _process, /* asid */ 0);
1746096Sgblack@eecs.umich.edu    fault = No_Fault;
1756096Sgblack@eecs.umich.edu    if (xc->status() == ExecContext::Active) {
1766096Sgblack@eecs.umich.edu        _status = Running;
1776096Sgblack@eecs.umich.edu       tickEvent.schedule(0);
1785240Sgblack@eecs.umich.edu    } else
1795240Sgblack@eecs.umich.edu        _status = Idle;
1805240Sgblack@eecs.umich.edu#endif // !FULL_SYSTEM
1815240Sgblack@eecs.umich.edu
1825240Sgblack@eecs.umich.edu    icacheInterface = icache_interface;
1835240Sgblack@eecs.umich.edu    dcacheInterface = dcache_interface;
1845240Sgblack@eecs.umich.edu
1855240Sgblack@eecs.umich.edu    memReq = new MemReq();
1865326Sgblack@eecs.umich.edu    memReq->xc = xc;
1875326Sgblack@eecs.umich.edu    memReq->asid = 0;
1885326Sgblack@eecs.umich.edu    memReq->data = new uint8_t[64];
1895326Sgblack@eecs.umich.edu
1905326Sgblack@eecs.umich.edu    numInst = 0;
1915326Sgblack@eecs.umich.edu    numLoad = 0;
1925240Sgblack@eecs.umich.edu    last_idle = 0;
1935326Sgblack@eecs.umich.edu    lastIcacheStall = 0;
1945326Sgblack@eecs.umich.edu    lastDcacheStall = 0;
1955240Sgblack@eecs.umich.edu
1965240Sgblack@eecs.umich.edu    contexts.push_back(xc);
1975240Sgblack@eecs.umich.edu}
1985306Sgblack@eecs.umich.edu
1995326Sgblack@eecs.umich.eduSimpleCPU::~SimpleCPU()
2005326Sgblack@eecs.umich.edu{
2015326Sgblack@eecs.umich.edu}
2025326Sgblack@eecs.umich.edu
2035326Sgblack@eecs.umich.eduvoid
2045326Sgblack@eecs.umich.eduSimpleCPU::regStats()
2055240Sgblack@eecs.umich.edu{
2065326Sgblack@eecs.umich.edu    BaseCPU::regStats();
2075297Sgblack@eecs.umich.edu
2085240Sgblack@eecs.umich.edu    numInsts
2095240Sgblack@eecs.umich.edu        .name(name() + ".num_insts")
2106096Sgblack@eecs.umich.edu        .desc("Number of instructions executed")
2116096Sgblack@eecs.umich.edu        ;
2126096Sgblack@eecs.umich.edu
2136096Sgblack@eecs.umich.edu    numMemRefs
2146096Sgblack@eecs.umich.edu        .name(name() + ".num_refs")
2156096Sgblack@eecs.umich.edu        .desc("Number of memory references")
2166096Sgblack@eecs.umich.edu        ;
2176096Sgblack@eecs.umich.edu
2186096Sgblack@eecs.umich.edu    idleCycles
2196096Sgblack@eecs.umich.edu        .name(name() + ".idle_cycles")
2206096Sgblack@eecs.umich.edu        .desc("Number of idle cycles")
2216096Sgblack@eecs.umich.edu        ;
2226096Sgblack@eecs.umich.edu
2236096Sgblack@eecs.umich.edu    idleFraction
2246096Sgblack@eecs.umich.edu        .name(name() + ".idle_fraction")
2256096Sgblack@eecs.umich.edu        .desc("Percentage of idle cycles")
2266096Sgblack@eecs.umich.edu        ;
2276096Sgblack@eecs.umich.edu
2286096Sgblack@eecs.umich.edu    icacheStallCycles
2296096Sgblack@eecs.umich.edu        .name(name() + ".icache_stall_cycles")
2306096Sgblack@eecs.umich.edu        .desc("ICache total stall cycles")
2316096Sgblack@eecs.umich.edu        .prereq(icacheStallCycles)
2326096Sgblack@eecs.umich.edu        ;
2336096Sgblack@eecs.umich.edu
2346096Sgblack@eecs.umich.edu    dcacheStallCycles
2355240Sgblack@eecs.umich.edu        .name(name() + ".dcache_stall_cycles")
2365240Sgblack@eecs.umich.edu        .desc("DCache total stall cycles")
2375240Sgblack@eecs.umich.edu        .prereq(dcacheStallCycles)
2385240Sgblack@eecs.umich.edu        ;
2395240Sgblack@eecs.umich.edu
2405240Sgblack@eecs.umich.edu    idleFraction = idleCycles / simTicks;
2415240Sgblack@eecs.umich.edu
2425240Sgblack@eecs.umich.edu    numInsts = Statistics::scalar(numInst);
2435306Sgblack@eecs.umich.edu    simInsts += numInsts;
2445326Sgblack@eecs.umich.edu}
2455326Sgblack@eecs.umich.edu
2465326Sgblack@eecs.umich.eduvoid
2475240Sgblack@eecs.umich.eduSimpleCPU::serialize()
2485326Sgblack@eecs.umich.edu{
2495326Sgblack@eecs.umich.edu    nameOut();
2505240Sgblack@eecs.umich.edu
2515240Sgblack@eecs.umich.edu#ifdef FULL_SYSTEM
2525240Sgblack@eecs.umich.edu#if 0
2535306Sgblack@eecs.umich.edu    // do we need this anymore?? egh
2545306Sgblack@eecs.umich.edu    childOut("itb", xc->itb);
2555326Sgblack@eecs.umich.edu    childOut("dtb", xc->dtb);
2565326Sgblack@eecs.umich.edu    childOut("physmem", physmem);
2575326Sgblack@eecs.umich.edu#endif
2585240Sgblack@eecs.umich.edu#endif
2595326Sgblack@eecs.umich.edu
2605326Sgblack@eecs.umich.edu    for (int i = 0; i < NumIntRegs; i++) {
2615240Sgblack@eecs.umich.edu        stringstream buf;
2625240Sgblack@eecs.umich.edu        ccprintf(buf, "R%02d", i);
2636095Sgblack@eecs.umich.edu        paramOut(buf.str(), xc->regs.intRegFile[i]);
2646095Sgblack@eecs.umich.edu    }
2656095Sgblack@eecs.umich.edu    for (int i = 0; i < NumFloatRegs; i++) {
2666095Sgblack@eecs.umich.edu        stringstream buf;
2676095Sgblack@eecs.umich.edu        ccprintf(buf, "F%02d", i);
2686095Sgblack@eecs.umich.edu        paramOut(buf.str(), xc->regs.floatRegFile.d[i]);
2696095Sgblack@eecs.umich.edu    }
2706095Sgblack@eecs.umich.edu    // CPUTraitsType::serializeSpecialRegs(getProxy(), xc->regs);
2716095Sgblack@eecs.umich.edu}
2726095Sgblack@eecs.umich.edu
2736095Sgblack@eecs.umich.eduvoid
2746095Sgblack@eecs.umich.eduSimpleCPU::unserialize(IniFile &db, const string &category, ConfigNode *node)
2756095Sgblack@eecs.umich.edu{
2766095Sgblack@eecs.umich.edu    string data;
2776095Sgblack@eecs.umich.edu
2786095Sgblack@eecs.umich.edu    for (int i = 0; i < NumIntRegs; i++) {
2796095Sgblack@eecs.umich.edu        stringstream buf;
2806095Sgblack@eecs.umich.edu        ccprintf(buf, "R%02d", i);
2816095Sgblack@eecs.umich.edu        db.findDefault(category, buf.str(), data);
2826095Sgblack@eecs.umich.edu        to_number(data,xc->regs.intRegFile[i]);
2836095Sgblack@eecs.umich.edu    }
2845240Sgblack@eecs.umich.edu    for (int i = 0; i < NumFloatRegs; i++) {
2855240Sgblack@eecs.umich.edu        stringstream buf;
2865240Sgblack@eecs.umich.edu        ccprintf(buf, "F%02d", i);
2875240Sgblack@eecs.umich.edu        db.findDefault(category, buf.str(), data);
2885240Sgblack@eecs.umich.edu        xc->regs.floatRegFile.d[i] = strtod(data.c_str(),NULL);
2895240Sgblack@eecs.umich.edu    }
2905240Sgblack@eecs.umich.edu
2915240Sgblack@eecs.umich.edu    // Read in Special registers
2925326Sgblack@eecs.umich.edu
2935326Sgblack@eecs.umich.edu    // CPUTraitsType::unserializeSpecialRegs(db,category,node,xc->regs);
2945326Sgblack@eecs.umich.edu}
2955326Sgblack@eecs.umich.edu
2965326Sgblack@eecs.umich.eduvoid
2975326Sgblack@eecs.umich.educhange_thread_state(int thread_number, int activate, int priority)
2985240Sgblack@eecs.umich.edu{
2995326Sgblack@eecs.umich.edu}
3005326Sgblack@eecs.umich.edu
3015240Sgblack@eecs.umich.edu// precise architected memory state accessor macros
3025240Sgblack@eecs.umich.edutemplate <class T>
3035240Sgblack@eecs.umich.eduFault
3045306Sgblack@eecs.umich.eduSimpleCPU::read(Addr addr, T& data, unsigned flags)
3055326Sgblack@eecs.umich.edu{
3065326Sgblack@eecs.umich.edu    memReq->reset(addr, sizeof(T), flags);
3075326Sgblack@eecs.umich.edu
3085326Sgblack@eecs.umich.edu    // translate to physical address
3095326Sgblack@eecs.umich.edu    Fault fault = xc->translateDataReadReq(memReq);
3105326Sgblack@eecs.umich.edu
3115240Sgblack@eecs.umich.edu    // do functional access
3125326Sgblack@eecs.umich.edu    if (fault == No_Fault)
3135326Sgblack@eecs.umich.edu        fault = xc->read(memReq, data);
3145240Sgblack@eecs.umich.edu
3155240Sgblack@eecs.umich.edu    if (traceData) {
3166095Sgblack@eecs.umich.edu        traceData->setAddr(addr);
3176095Sgblack@eecs.umich.edu        if (fault == No_Fault)
3186095Sgblack@eecs.umich.edu            traceData->setData(data);
3196095Sgblack@eecs.umich.edu    }
3206095Sgblack@eecs.umich.edu
3216095Sgblack@eecs.umich.edu    // if we have a cache, do cache access too
3226095Sgblack@eecs.umich.edu    if (fault == No_Fault && dcacheInterface) {
3236095Sgblack@eecs.umich.edu        memReq->cmd = Read;
3246095Sgblack@eecs.umich.edu        memReq->completionEvent = NULL;
3256095Sgblack@eecs.umich.edu        memReq->time = curTick;
3266095Sgblack@eecs.umich.edu        memReq->flags &= ~UNCACHEABLE;
3276095Sgblack@eecs.umich.edu        MemAccessResult result = dcacheInterface->access(memReq);
3286095Sgblack@eecs.umich.edu
3296095Sgblack@eecs.umich.edu        // Ugly hack to get an event scheduled *only* if the access is
3306095Sgblack@eecs.umich.edu        // a miss.  We really should add first-class support for this
3316095Sgblack@eecs.umich.edu        // at some point.
3326095Sgblack@eecs.umich.edu        if (result != MA_HIT && dcacheInterface->doEvents) {
3336095Sgblack@eecs.umich.edu            memReq->completionEvent = &cacheCompletionEvent;
3346095Sgblack@eecs.umich.edu            setStatus(DcacheMissStall);
3356095Sgblack@eecs.umich.edu        }
3366095Sgblack@eecs.umich.edu    }
3376095Sgblack@eecs.umich.edu
3386095Sgblack@eecs.umich.edu    return fault;
3396095Sgblack@eecs.umich.edu}
3406095Sgblack@eecs.umich.edu
3415240Sgblack@eecs.umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
3425240Sgblack@eecs.umich.edu
3435240Sgblack@eecs.umich.edutemplate
3445240Sgblack@eecs.umich.eduFault
3455240Sgblack@eecs.umich.eduSimpleCPU::read(Addr addr, uint64_t& data, unsigned flags);
3465240Sgblack@eecs.umich.edu
3475240Sgblack@eecs.umich.edutemplate
3485240Sgblack@eecs.umich.eduFault
3495306Sgblack@eecs.umich.eduSimpleCPU::read(Addr addr, uint32_t& data, unsigned flags);
3505326Sgblack@eecs.umich.edu
3515326Sgblack@eecs.umich.edutemplate
3525326Sgblack@eecs.umich.eduFault
3535240Sgblack@eecs.umich.eduSimpleCPU::read(Addr addr, uint16_t& data, unsigned flags);
3545326Sgblack@eecs.umich.edu
3555326Sgblack@eecs.umich.edutemplate
3565240Sgblack@eecs.umich.eduFault
3575240Sgblack@eecs.umich.eduSimpleCPU::read(Addr addr, uint8_t& data, unsigned flags);
3585240Sgblack@eecs.umich.edu
3595306Sgblack@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
3605306Sgblack@eecs.umich.edu
3615326Sgblack@eecs.umich.edutemplate<>
3625326Sgblack@eecs.umich.eduFault
3635326Sgblack@eecs.umich.eduSimpleCPU::read(Addr addr, double& data, unsigned flags)
3645240Sgblack@eecs.umich.edu{
3655326Sgblack@eecs.umich.edu    return read(addr, *(uint64_t*)&data, flags);
3665326Sgblack@eecs.umich.edu}
3675240Sgblack@eecs.umich.edu
3685240Sgblack@eecs.umich.edutemplate<>
3696093Sgblack@eecs.umich.eduFault
3706093Sgblack@eecs.umich.eduSimpleCPU::read(Addr addr, float& data, unsigned flags)
3716093Sgblack@eecs.umich.edu{
3726093Sgblack@eecs.umich.edu    return read(addr, *(uint32_t*)&data, flags);
3736093Sgblack@eecs.umich.edu}
3746093Sgblack@eecs.umich.edu
3756093Sgblack@eecs.umich.edu
3766093Sgblack@eecs.umich.edutemplate<>
3776093Sgblack@eecs.umich.eduFault
3786093Sgblack@eecs.umich.eduSimpleCPU::read(Addr addr, int32_t& data, unsigned flags)
3796093Sgblack@eecs.umich.edu{
3806093Sgblack@eecs.umich.edu    return read(addr, (uint32_t&)data, flags);
3816093Sgblack@eecs.umich.edu}
3826093Sgblack@eecs.umich.edu
3836093Sgblack@eecs.umich.edu
3846093Sgblack@eecs.umich.edutemplate <class T>
3856093Sgblack@eecs.umich.eduFault
3866093Sgblack@eecs.umich.eduSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
3876093Sgblack@eecs.umich.edu{
3886093Sgblack@eecs.umich.edu    if (traceData) {
3896093Sgblack@eecs.umich.edu        traceData->setAddr(addr);
3905240Sgblack@eecs.umich.edu        traceData->setData(data);
3915240Sgblack@eecs.umich.edu    }
3925240Sgblack@eecs.umich.edu
3935240Sgblack@eecs.umich.edu    memReq->reset(addr, sizeof(T), flags);
3945240Sgblack@eecs.umich.edu
3955240Sgblack@eecs.umich.edu    // translate to physical address
3965240Sgblack@eecs.umich.edu    Fault fault = xc->translateDataWriteReq(memReq);
3975240Sgblack@eecs.umich.edu
3985326Sgblack@eecs.umich.edu    // do functional access
3995326Sgblack@eecs.umich.edu    if (fault == No_Fault)
4005326Sgblack@eecs.umich.edu        fault = xc->write(memReq, data);
4015326Sgblack@eecs.umich.edu
4025326Sgblack@eecs.umich.edu    if (fault == No_Fault && dcacheInterface) {
4035326Sgblack@eecs.umich.edu        memReq->cmd = Write;
4045240Sgblack@eecs.umich.edu        memcpy(memReq->data,(uint8_t *)&data,memReq->size);
4055326Sgblack@eecs.umich.edu        memReq->completionEvent = NULL;
4065326Sgblack@eecs.umich.edu        memReq->time = curTick;
4075240Sgblack@eecs.umich.edu        memReq->flags &= ~UNCACHEABLE;
4085240Sgblack@eecs.umich.edu        MemAccessResult result = dcacheInterface->access(memReq);
4095240Sgblack@eecs.umich.edu
4105306Sgblack@eecs.umich.edu        // Ugly hack to get an event scheduled *only* if the access is
4115326Sgblack@eecs.umich.edu        // a miss.  We really should add first-class support for this
4125326Sgblack@eecs.umich.edu        // at some point.
4135326Sgblack@eecs.umich.edu        if (result != MA_HIT && dcacheInterface->doEvents) {
4145326Sgblack@eecs.umich.edu            memReq->completionEvent = &cacheCompletionEvent;
4155326Sgblack@eecs.umich.edu            setStatus(DcacheMissStall);
4165326Sgblack@eecs.umich.edu        }
4175240Sgblack@eecs.umich.edu    }
4185326Sgblack@eecs.umich.edu
4195326Sgblack@eecs.umich.edu    if (res && (fault == No_Fault))
4205240Sgblack@eecs.umich.edu        *res = memReq->result;
4216093Sgblack@eecs.umich.edu
4226093Sgblack@eecs.umich.edu    return fault;
4236093Sgblack@eecs.umich.edu}
4246093Sgblack@eecs.umich.edu
4256093Sgblack@eecs.umich.edu
4266093Sgblack@eecs.umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS
4276093Sgblack@eecs.umich.edutemplate
4286093Sgblack@eecs.umich.eduFault
4296093Sgblack@eecs.umich.eduSimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
4306093Sgblack@eecs.umich.edu
4316093Sgblack@eecs.umich.edutemplate
4326093Sgblack@eecs.umich.eduFault
4336093Sgblack@eecs.umich.eduSimpleCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
4346093Sgblack@eecs.umich.edu
4356093Sgblack@eecs.umich.edutemplate
4366093Sgblack@eecs.umich.eduFault
4376093Sgblack@eecs.umich.eduSimpleCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
4386093Sgblack@eecs.umich.edu
4396093Sgblack@eecs.umich.edutemplate
4406093Sgblack@eecs.umich.eduFault
4416093Sgblack@eecs.umich.eduSimpleCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
4426093Sgblack@eecs.umich.edu
4436093Sgblack@eecs.umich.edu#endif //DOXYGEN_SHOULD_SKIP_THIS
4446093Sgblack@eecs.umich.edu
4456093Sgblack@eecs.umich.edutemplate<>
4465240Sgblack@eecs.umich.eduFault
447SimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
448{
449    return write(*(uint64_t*)&data, addr, flags, res);
450}
451
452template<>
453Fault
454SimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
455{
456    return write(*(uint32_t*)&data, addr, flags, res);
457}
458
459
460template<>
461Fault
462SimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
463{
464    return write((uint32_t)data, addr, flags, res);
465}
466
467
468#ifdef FULL_SYSTEM
469Addr
470SimpleCPU::dbg_vtophys(Addr addr)
471{
472    return vtophys(xc, addr);
473}
474#endif // FULL_SYSTEM
475
476Tick save_cycle = 0;
477
478
479void
480SimpleCPU::processCacheCompletion()
481{
482    switch (status()) {
483      case IcacheMissStall:
484        icacheStallCycles += curTick - lastIcacheStall;
485        setStatus(IcacheMissComplete);
486        break;
487      case DcacheMissStall:
488        dcacheStallCycles += curTick - lastDcacheStall;
489        setStatus(Running);
490        break;
491      default:
492        panic("SimpleCPU::processCacheCompletion: bad state");
493        break;
494    }
495}
496
497#ifdef FULL_SYSTEM
498void
499SimpleCPU::post_interrupt(int int_num, int index)
500{
501    BaseCPU::post_interrupt(int_num, index);
502
503    if (xc->status() == ExecContext::Suspended) {
504                DPRINTF(IPI,"Suspended Processor awoke\n");
505        xc->setStatus(ExecContext::Active);
506        Annotate::Resume(xc);
507    }
508}
509#endif // FULL_SYSTEM
510
511/* start simulation, program loaded, processor precise state initialized */
512void
513SimpleCPU::tick()
514{
515    traceData = NULL;
516
517#ifdef FULL_SYSTEM
518    if (fault == No_Fault && AlphaISA::check_interrupts &&
519        xc->cpu->check_interrupts() &&
520        !PC_PAL(xc->regs.pc) &&
521        status() != IcacheMissComplete) {
522        int ipl = 0;
523        int summary = 0;
524        AlphaISA::check_interrupts = 0;
525        IntReg *ipr = xc->regs.ipr;
526
527        if (xc->regs.ipr[TheISA::IPR_SIRR]) {
528            for (int i = TheISA::INTLEVEL_SOFTWARE_MIN;
529                 i < TheISA::INTLEVEL_SOFTWARE_MAX; i++) {
530                if (ipr[TheISA::IPR_SIRR] & (ULL(1) << i)) {
531                    // See table 4-19 of 21164 hardware reference
532                    ipl = (i - TheISA::INTLEVEL_SOFTWARE_MIN) + 1;
533                    summary |= (ULL(1) << i);
534                }
535            }
536        }
537
538        uint64_t interrupts = xc->cpu->intr_status();
539        for (int i = TheISA::INTLEVEL_EXTERNAL_MIN;
540            i < TheISA::INTLEVEL_EXTERNAL_MAX; i++) {
541            if (interrupts & (ULL(1) << i)) {
542                // See table 4-19 of 21164 hardware reference
543                ipl = i;
544                summary |= (ULL(1) << i);
545            }
546        }
547
548        if (ipr[TheISA::IPR_ASTRR])
549            panic("asynchronous traps not implemented\n");
550
551        if (ipl && ipl > xc->regs.ipr[TheISA::IPR_IPLR]) {
552            ipr[TheISA::IPR_ISR] = summary;
553            ipr[TheISA::IPR_INTID] = ipl;
554            xc->ev5_trap(Interrupt_Fault);
555
556            DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
557                    ipr[TheISA::IPR_IPLR], ipl, summary);
558        }
559    }
560#endif
561
562    // maintain $r0 semantics
563    xc->regs.intRegFile[ZeroReg] = 0;
564#ifdef TARGET_ALPHA
565    xc->regs.floatRegFile.d[ZeroReg] = 0.0;
566#endif // TARGET_ALPHA
567
568    if (status() == IcacheMissComplete) {
569        // We've already fetched an instruction and were stalled on an
570        // I-cache miss.  No need to fetch it again.
571
572        setStatus(Running);
573    }
574    else {
575        // Try to fetch an instruction
576
577        // set up memory request for instruction fetch
578#ifdef FULL_SYSTEM
579#define IFETCH_FLAGS(pc)	((pc) & 1) ? PHYSICAL : 0
580#else
581#define IFETCH_FLAGS(pc)	0
582#endif
583
584        memReq->cmd = Read;
585        memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t),
586                     IFETCH_FLAGS(xc->regs.pc));
587
588        fault = xc->translateInstReq(memReq);
589
590        if (fault == No_Fault)
591            fault = xc->mem->read(memReq, inst);
592
593        if (icacheInterface && fault == No_Fault) {
594            memReq->completionEvent = NULL;
595
596            memReq->time = curTick;
597            memReq->flags &= ~UNCACHEABLE;
598            MemAccessResult result = icacheInterface->access(memReq);
599
600            // Ugly hack to get an event scheduled *only* if the access is
601            // a miss.  We really should add first-class support for this
602            // at some point.
603            if (result != MA_HIT && icacheInterface->doEvents) {
604                memReq->completionEvent = &cacheCompletionEvent;
605                setStatus(IcacheMissStall);
606                return;
607            }
608        }
609    }
610
611    // If we've got a valid instruction (i.e., no fault on instruction
612    // fetch), then execute it.
613    if (fault == No_Fault) {
614
615        // keep an instruction count
616        numInst++;
617
618        // check for instruction-count-based events
619        comInsnEventQueue[0]->serviceEvents(numInst);
620
621        // decode the instruction
622        StaticInstPtr<TheISA> si(inst);
623
624        traceData = Trace::getInstRecord(curTick, xc, this, si,
625                                         xc->regs.pc);
626
627#ifdef FULL_SYSTEM
628        xc->regs.opcode = (inst >> 26) & 0x3f;
629        xc->regs.ra = (inst >> 21) & 0x1f;
630#endif // FULL_SYSTEM
631
632        xc->func_exe_insn++;
633
634        fault = si->execute(this, xc, traceData);
635
636        if (si->isMemRef()) {
637            numMemRefs++;
638        }
639
640        if (si->isLoad()) {
641            ++numLoad;
642            comLoadEventQueue[0]->serviceEvents(numLoad);
643        }
644
645        if (traceData)
646            traceData->finalize();
647
648    }	// if (fault == No_Fault)
649
650    if (fault != No_Fault) {
651#ifdef FULL_SYSTEM
652        xc->ev5_trap(fault);
653#else // !FULL_SYSTEM
654        fatal("fault (%d) detected @ PC 0x%08p", fault, xc->regs.pc);
655#endif // FULL_SYSTEM
656    }
657    else {
658        // go to the next instruction
659        xc->regs.pc = xc->regs.npc;
660        xc->regs.npc += sizeof(MachInst);
661    }
662
663#ifdef FULL_SYSTEM
664    Addr oldpc;
665    do {
666        oldpc = xc->regs.pc;
667        system->pcEventQueue.service(xc);
668    } while (oldpc != xc->regs.pc);
669#endif
670
671    assert(status() == Running ||
672           status() == Idle ||
673           status() == DcacheMissStall);
674
675    if (status() == Running && !tickEvent.scheduled())
676        tickEvent.schedule(curTick + 1);
677}
678
679
680////////////////////////////////////////////////////////////////////////
681//
682//  SimpleCPU Simulation Object
683//
684BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
685
686    Param<Counter> max_insts_any_thread;
687    Param<Counter> max_insts_all_threads;
688    Param<Counter> max_loads_any_thread;
689    Param<Counter> max_loads_all_threads;
690
691#ifdef FULL_SYSTEM
692    SimObjectParam<AlphaItb *> itb;
693    SimObjectParam<AlphaDtb *> dtb;
694    SimObjectParam<FunctionalMemory *> mem;
695    SimObjectParam<System *> system;
696    Param<int> cpu_id;
697    Param<int> mult;
698#else
699    SimObjectParam<Process *> workload;
700#endif // FULL_SYSTEM
701
702    SimObjectParam<BaseMem *> icache;
703    SimObjectParam<BaseMem *> dcache;
704
705END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
706
707BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
708
709    INIT_PARAM_DFLT(max_insts_any_thread,
710                    "terminate when any thread reaches this insn count",
711                    0),
712    INIT_PARAM_DFLT(max_insts_all_threads,
713                    "terminate when all threads have reached this insn count",
714                    0),
715    INIT_PARAM_DFLT(max_loads_any_thread,
716                    "terminate when any thread reaches this load count",
717                    0),
718    INIT_PARAM_DFLT(max_loads_all_threads,
719                    "terminate when all threads have reached this load count",
720                    0),
721
722#ifdef FULL_SYSTEM
723    INIT_PARAM(itb, "Instruction TLB"),
724    INIT_PARAM(dtb, "Data TLB"),
725    INIT_PARAM(mem, "memory"),
726    INIT_PARAM(system, "system object"),
727    INIT_PARAM_DFLT(cpu_id, "CPU identification number", 0),
728    INIT_PARAM_DFLT(mult, "system clock multiplier", 1),
729#else
730    INIT_PARAM(workload, "processes to run"),
731#endif // FULL_SYSTEM
732
733    INIT_PARAM_DFLT(icache, "L1 instruction cache object", NULL),
734    INIT_PARAM_DFLT(dcache, "L1 data cache object", NULL)
735
736END_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
737
738
739CREATE_SIM_OBJECT(SimpleCPU)
740{
741#ifdef FULL_SYSTEM
742    if (mult != 1)
743        panic("processor clock multiplier must be 1\n");
744
745    return new SimpleCPU(getInstanceName(), system,
746                         max_insts_any_thread, max_insts_all_threads,
747                         max_loads_any_thread, max_loads_all_threads,
748                         itb, dtb, mem,
749                         (icache) ? icache->getInterface() : NULL,
750                         (dcache) ? dcache->getInterface() : NULL,
751                         cpu_id, ticksPerSecond * mult);
752#else
753
754    return new SimpleCPU(getInstanceName(), workload,
755                         max_insts_any_thread, max_insts_all_threads,
756                         max_loads_any_thread, max_loads_all_threads,
757                         icache->getInterface(), dcache->getInterface());
758
759#endif // FULL_SYSTEM
760}
761
762REGISTER_SIM_OBJECT("SimpleCPU", SimpleCPU)
763