/* * Copyright (c) 2006 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. * * Authors: Kevin Lim */ #ifndef __CPU_OZONE_CPU_HH__ #define __CPU_OZONE_CPU_HH__ #include #include "arch/alpha/tlb.hh" #include "base/statistics.hh" #include "config/the_isa.hh" #include "cpu/ozone/rename_table.hh" #include "cpu/ozone/thread_state.hh" #include "cpu/base.hh" #include "cpu/inst_seq.hh" #include "cpu/pc_event.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" #include "cpu/timebuf.hh" #include "mem/page_table.hh" #include "sim/eventq.hh" // forward declarations namespace TheISA { namespace Kernel { class Statistics; }; class TLB; }; class Checkpoint; class EndQuiesceEvent; class MemoryController; class MemObject; class PhysicalMemory; class Process; class Request; namespace Trace { class InstRecord; } template class Checker; /** * Light weight out of order CPU model that approximates an out of * order CPU. It is separated into a front end and a back end, with * the template parameter Impl describing the classes used for each. * The goal is to be able to specify through the Impl the class to use * for the front end and back end, with different classes used to * model different levels of detail. */ template class OzoneCPU : public BaseCPU { private: typedef typename Impl::FrontEnd FrontEnd; typedef typename Impl::BackEnd BackEnd; typedef typename Impl::DynInst DynInst; typedef typename Impl::DynInstPtr DynInstPtr; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; typedef TheISA::MiscReg MiscReg; public: class OzoneTC : public ThreadContext { public: OzoneCPU *cpu; OzoneThreadState *thread; BaseCPU *getCpuPtr(); TheISA::TLB *getITBPtr() { return cpu->itb; } TheISA::TLB * getDTBPtr() { return cpu->dtb; } System *getSystemPtr() { return cpu->system; } PhysicalMemory *getPhysMemPtr() { return cpu->physmem; } TheISA::Kernel::Statistics *getKernelStats() { return thread->getKernelStats(); } Process *getProcessPtr() { return thread->getProcessPtr(); } TranslatingPort *getMemPort() { return thread->getMemPort(); } VirtualPort *getVirtPort() { return thread->getVirtPort(); } FunctionalPort *getPhysPort() { return thread->getPhysPort(); } Status status() const { return thread->status(); } void setStatus(Status new_status); /// Set the status to Active. Optional delay indicates number of /// cycles to wait before beginning execution. void activate(int delay = 1); /// Set the status to Suspended. void suspend(); /// Set the status to Halted. void halt(); void dumpFuncProfile(); void takeOverFrom(ThreadContext *old_context); void regStats(const std::string &name); void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); EndQuiesceEvent *getQuiesceEvent(); Tick readLastActivate(); Tick readLastSuspend(); void profileClear(); void profileSample(); int threadId(); void copyArchRegs(ThreadContext *tc); void clearArchRegs(); uint64_t readIntReg(int reg_idx); FloatReg readFloatReg(int reg_idx); FloatRegBits readFloatRegBits(int reg_idx); void setIntReg(int reg_idx, uint64_t val); void setFloatReg(int reg_idx, FloatReg val); void setFloatRegBits(int reg_idx, FloatRegBits val); uint64_t readPC() { return thread->PC; } void setPC(Addr val); uint64_t readNextPC() { return thread->nextPC; } void setNextPC(Addr val); uint64_t readNextNPC() { #if ISA_HAS_DELAY_SLOT panic("Ozone needs to support nextNPC"); #else return thread->nextPC + sizeof(TheISA::MachInst); #endif } void setNextNPC(uint64_t val) { #if ISA_HAS_DELAY_SLOT panic("Ozone needs to support nextNPC"); #endif } public: // ISA stuff: MiscReg readMiscRegNoEffect(int misc_reg); MiscReg readMiscReg(int misc_reg); void setMiscRegNoEffect(int misc_reg, const MiscReg &val); void setMiscReg(int misc_reg, const MiscReg &val); unsigned readStCondFailures() { return thread->storeCondFailures; } void setStCondFailures(unsigned sc_failures) { thread->storeCondFailures = sc_failures; } bool misspeculating() { return false; } Counter readFuncExeInst() { return thread->funcExeInst; } void setFuncExeInst(Counter new_val) { thread->funcExeInst = new_val; } }; // Ozone specific thread context OzoneTC ozoneTC; // Thread context to be used ThreadContext *tc; // Checker thread context; will wrap the OzoneTC if a checker is // being used. ThreadContext *checkerTC; typedef OzoneThreadState ImplState; private: // Committed thread state for the OzoneCPU. OzoneThreadState thread; public: // main simulation loop (one cycle) void tick(); #ifndef NDEBUG /** Count of total number of dynamic instructions in flight. */ int instcount; #endif std::set snList; std::set lockAddrList; private: struct TickEvent : public Event { OzoneCPU *cpu; int width; TickEvent(OzoneCPU *c, int w); void process(); const char *description() const; }; TickEvent tickEvent; /// Schedule tick event, regardless of its current state. void scheduleTickEvent(int delay) { if (tickEvent.squashed()) tickEvent.reschedule(curTick() + ticks(delay)); else if (!tickEvent.scheduled()) tickEvent.schedule(curTick() + ticks(delay)); } /// Unschedule tick event, regardless of its current state. void unscheduleTickEvent() { if (tickEvent.scheduled()) tickEvent.squash(); } public: enum Status { Running, Idle, SwitchedOut }; Status _status; public: void wakeup(); void zero_fill_64(Addr addr) { static int warned = 0; if (!warned) { warn ("WH64 is not implemented"); warned = 1; } }; typedef typename Impl::Params Params; OzoneCPU(Params *params); virtual ~OzoneCPU(); void init(); public: BaseCPU *getCpuPtr() { return this; } void switchOut(); void signalSwitched(); void takeOverFrom(BaseCPU *oldCPU); int switchCount; Addr dbg_vtophys(Addr addr); bool interval_stats; TheISA::TLB *itb; TheISA::TLB *dtb; System *system; PhysicalMemory *physmem; virtual Port *getPort(const std::string &name, int idx); FrontEnd *frontEnd; BackEnd *backEnd; private: Status status() const { return _status; } void setStatus(Status new_status) { _status = new_status; } virtual void activateContext(int thread_num, int delay); virtual void suspendContext(int thread_num); virtual void deallocateContext(int thread_num, int delay); virtual void haltContext(int thread_num); // statistics virtual void regStats(); virtual void resetStats(); // number of simulated instructions public: Counter numInst; Counter startNumInst; virtual Counter totalInstructions() const { return numInst - startNumInst; } private: // number of simulated loads Counter numLoad; Counter startNumLoad; // number of idle cycles Stats::Average notIdleFraction; Stats::Formula idleFraction; public: virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); void demapPage(Addr vaddr, uint64_t asn) { cpu->itb->demap(vaddr, asn); cpu->dtb->demap(vaddr, asn); } void demapInstPage(Addr vaddr, uint64_t asn) { cpu->itb->demap(vaddr, asn); } void demapDataPage(Addr vaddr, uint64_t asn) { cpu->dtb->demap(vaddr, asn); } /** CPU read function, forwards read to LSQ. */ template Fault read(Request *req, T &data, int load_idx) { return backEnd->read(req, data, load_idx); } /** CPU write function, forwards write to LSQ. */ template Fault write(Request *req, T &data, int store_idx) { return backEnd->write(req, data, store_idx); } public: void squashFromTC(); void dumpInsts() { frontEnd->dumpInsts(); } Fault hwrei(); bool simPalCheck(int palFunc); void processInterrupts(); void syscall(uint64_t &callnum); ThreadContext *tcBase() { return tc; } struct CommStruct { InstSeqNum doneSeqNum; InstSeqNum nonSpecSeqNum; bool uncached; unsigned lqIdx; bool stall; }; InstSeqNum globalSeqNum; TimeBuffer comm; bool decoupledFrontEnd; bool lockFlag; Stats::Scalar quiesceCycles; Checker *checker; }; #endif // __CPU_OZONE_CPU_HH__