diff options
Diffstat (limited to 'cpu/simple_cpu/simple_cpu.hh')
-rw-r--r-- | cpu/simple_cpu/simple_cpu.hh | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh new file mode 100644 index 000000000..c5671eb6f --- /dev/null +++ b/cpu/simple_cpu/simple_cpu.hh @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SIMPLE_CPU_HH__ +#define __SIMPLE_CPU_HH__ + +#include "base_cpu.hh" +#include "eventq.hh" +#include "symtab.hh" +#include "pc_event.hh" +#include "statistics.hh" + + +// forward declarations +#ifdef FULL_SYSTEM +class Processor; +class Kernel; +class AlphaItb; +class AlphaDtb; +class PhysicalMemory; + +class RemoteGDB; +class GDBListener; +#endif // FULL_SYSTEM + +class MemInterface; +class IniFile; + +namespace Trace { + class InstRecord; +} + +class SimpleCPU : public BaseCPU +{ + public: + // main simulation loop (one cycle) + void tick(); + + private: + class TickEvent : public Event + { + private: + SimpleCPU *cpu; + + public: + TickEvent(SimpleCPU *c) + : Event(&mainEventQueue, 100), cpu(c) { } + void process() { cpu->tick(); } + virtual const char *description() { return "tick event"; } + }; + + TickEvent tickEvent; + + private: + Trace::InstRecord *traceData; + template<typename T> + void trace_data(T data) { + if (traceData) { + traceData->setData(data); + } + }; + + public: + // + enum Status { + Running, + Idle, + IcacheMissStall, + IcacheMissComplete, + DcacheMissStall + }; + + private: + Status _status; + + public: + void post_interrupt(int int_num, int index); + + void zero_fill_64(Addr addr) { + static int warned = 0; + if (!warned) { + warn ("WH64 is not implemented"); + warned = 1; + } + }; + +#ifdef FULL_SYSTEM + + SimpleCPU(const std::string &_name, + System *_system, + Counter max_insts_any_thread, Counter max_insts_all_threads, + AlphaItb *itb, AlphaDtb *dtb, FunctionalMemory *mem, + MemInterface *icache_interface, MemInterface *dcache_interface, + int cpu_id, Tick freq); + +#else + + SimpleCPU(const std::string &_name, Process *_process, + Counter max_insts_any_thread, + Counter max_insts_all_threads, + MemInterface *icache_interface, MemInterface *dcache_interface); + +#endif + + virtual ~SimpleCPU(); + + // execution context + ExecContext *xc; + +#ifdef FULL_SYSTEM + Addr dbg_vtophys(Addr addr); + + bool interval_stats; +#endif + + // L1 instruction cache + MemInterface *icacheInterface; + + // L1 data cache + MemInterface *dcacheInterface; + + // current instruction + MachInst inst; + + // current fault status + Fault fault; + + // Refcounted pointer to the one memory request. + MemReqPtr memReq; + + class CacheCompletionEvent : public Event + { + private: + SimpleCPU *cpu; + + public: + CacheCompletionEvent(SimpleCPU *_cpu); + + virtual void process(); + virtual const char *description(); + }; + + CacheCompletionEvent cacheCompletionEvent; + + Status status() const { return _status; } + virtual void execCtxStatusChg() { + if (xc) { + if (xc->status() == ExecContext::Active) + setStatus(Running); + else + setStatus(Idle); + } + } + + void setStatus(Status new_status) { + Status old_status = status(); + _status = new_status; + + switch (status()) { + case IcacheMissStall: + assert(old_status == Running); + lastIcacheStall = curTick; + if (tickEvent.scheduled()) + tickEvent.squash(); + break; + + case IcacheMissComplete: + assert(old_status == IcacheMissStall); + if (tickEvent.squashed()) + tickEvent.reschedule(curTick + 1); + else if (!tickEvent.scheduled()) + tickEvent.schedule(curTick + 1); + break; + + case DcacheMissStall: + assert(old_status == Running); + lastDcacheStall = curTick; + if (tickEvent.scheduled()) + tickEvent.squash(); + break; + + case Idle: + assert(old_status == Running); + last_idle = curTick; + if (tickEvent.scheduled()) + tickEvent.squash(); + break; + + case Running: + assert(old_status == Idle || + old_status == DcacheMissStall || + old_status == IcacheMissComplete); + if (old_status == Idle) + idleCycles += curTick - last_idle; + + if (tickEvent.squashed()) + tickEvent.reschedule(curTick + 1); + else if (!tickEvent.scheduled()) + tickEvent.schedule(curTick + 1); + break; + + default: + panic("can't get here"); + } + } + + // statistics + void regStats(); + + // number of simulated instructions + Counter numInst; + Statistics::Formula numInsts; + + // number of simulated memory references + Statistics::Scalar<> numMemRefs; + + // number of idle cycles + Statistics::Scalar<> idleCycles; + Statistics::Formula idleFraction; + Counter last_idle; + + // number of cycles stalled for I-cache misses + Statistics::Scalar<> icacheStallCycles; + Counter lastIcacheStall; + + // number of cycles stalled for D-cache misses + Statistics::Scalar<> dcacheStallCycles; + Counter lastDcacheStall; + + void processCacheCompletion(); + + virtual void serialize(); + virtual void unserialize(IniFile &db, const std::string &category, + ConfigNode *node); + + template <class T> + Fault read(Addr addr, T& data, unsigned flags); + + template <class T> + Fault write(T data, Addr addr, unsigned flags, + uint64_t *res); + + Fault prefetch(Addr addr, unsigned flags) + { + // need to do this... + return No_Fault; + } + + void writeHint(Addr addr, int size) + { + // need to do this... + } +}; + +#endif // __SIMPLE_CPU_HH__ |