diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/base.cc | 3 | ||||
-rw-r--r-- | cpu/base.hh | 8 | ||||
-rw-r--r-- | cpu/cpu_exec_context.cc | 20 | ||||
-rw-r--r-- | cpu/cpu_exec_context.hh | 80 | ||||
-rw-r--r-- | cpu/exec_context.hh | 24 | ||||
-rw-r--r-- | cpu/exetrace.cc | 3 | ||||
-rw-r--r-- | cpu/o3/alpha_cpu.hh | 4 | ||||
-rw-r--r-- | cpu/op_class.cc | 50 | ||||
-rw-r--r-- | cpu/op_class.hh | 64 | ||||
-rw-r--r-- | cpu/pc_event.hh | 5 | ||||
-rw-r--r-- | cpu/simple/cpu.cc | 406 | ||||
-rw-r--r-- | cpu/simple/cpu.hh | 107 | ||||
-rw-r--r-- | cpu/static_inst.hh | 3 |
13 files changed, 582 insertions, 195 deletions
diff --git a/cpu/base.cc b/cpu/base.cc index 2eb5f7fd3..9ce458c64 100644 --- a/cpu/base.cc +++ b/cpu/base.cc @@ -65,7 +65,7 @@ BaseCPU::BaseCPU(Params *p) #else BaseCPU::BaseCPU(Params *p) : SimObject(p->name), clock(p->clock), params(p), - number_of_threads(p->numberOfThreads) + number_of_threads(p->numberOfThreads), system(p->system) #endif { DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this); @@ -229,6 +229,7 @@ BaseCPU::registerExecContexts() { for (int i = 0; i < execContexts.size(); ++i) { ExecContext *xc = execContexts[i]; + #if FULL_SYSTEM int id = params->cpu_id; if (id != -1) diff --git a/cpu/base.hh b/cpu/base.hh index d9d5d2b88..0866b49a7 100644 --- a/cpu/base.hh +++ b/cpu/base.hh @@ -38,13 +38,11 @@ #include "sim/sim_object.hh" #include "arch/isa_traits.hh" -#if FULL_SYSTEM class System; namespace Kernel { class Statistics; } -#endif - class BranchPred; class ExecContext; +class Port; class BaseCPU : public SimObject { @@ -123,8 +121,8 @@ class BaseCPU : public SimObject Tick clock; bool functionTrace; Tick functionTraceStart; -#if FULL_SYSTEM System *system; +#if FULL_SYSTEM int cpu_id; Tick profile; #endif @@ -173,9 +171,9 @@ class BaseCPU : public SimObject */ EventQueue **comLoadEventQueue; -#if FULL_SYSTEM System *system; +#if FULL_SYSTEM /** * Serialize this object to the given output stream. * @param os The stream to serialize to. diff --git a/cpu/cpu_exec_context.cc b/cpu/cpu_exec_context.cc index b7238e73a..f840c38dc 100644 --- a/cpu/cpu_exec_context.cc +++ b/cpu/cpu_exec_context.cc @@ -45,6 +45,7 @@ #include "arch/stacktrace.hh" #else #include "sim/process.hh" +#include "mem/translating_port.hh" #endif using namespace std; @@ -53,7 +54,7 @@ using namespace std; #if FULL_SYSTEM CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, AlphaITB *_itb, AlphaDTB *_dtb, - FunctionalMemory *_mem) + Memory *_mem) : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb), dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem), @@ -79,27 +80,19 @@ CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, } #else CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, - Process *_process, int _asid) + Process *_process, int _asid, Port *mem_port) : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), - lastSuspend(0), process(_process), mem(process->getMemory()), asid(_asid), - func_exe_inst(0), storeCondFailures(0) -{ - memset(®s, 0, sizeof(RegFile)); - proxy = new ProxyExecContext<CPUExecContext>(this); -} - -CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, - FunctionalMemory *_mem, int _asid) - : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid), + lastSuspend(0), process(_process), asid(_asid), func_exe_inst(0), storeCondFailures(0) { + port = new TranslatingPort(mem_port, process->pTable); memset(®s, 0, sizeof(RegFile)); proxy = new ProxyExecContext<CPUExecContext>(this); } CPUExecContext::CPUExecContext(RegFile *regFile) - : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1), + : cpu(NULL), thread_num(-1), process(NULL), asid(-1), func_exe_inst(0), storeCondFailures(0) { regs = *regFile; @@ -158,7 +151,6 @@ void CPUExecContext::takeOverFrom(ExecContext *oldContext) { // some things should already be set up - assert(mem == oldContext->getMemPtr()); #if FULL_SYSTEM assert(system == oldContext->getSystemPtr()); #else diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh index beaf67352..764c8fab3 100644 --- a/cpu/cpu_exec_context.hh +++ b/cpu/cpu_exec_context.hh @@ -32,16 +32,13 @@ #include "arch/isa_traits.hh" #include "config/full_system.hh" #include "cpu/exec_context.hh" -#include "mem/functional/functional.hh" -#include "mem/mem_req.hh" +#include "mem/physical.hh" +#include "mem/request.hh" #include "sim/byteswap.hh" #include "sim/eventq.hh" #include "sim/host.hh" #include "sim/serialize.hh" -// forward declaration: see functional_memory.hh -class FunctionalMemory; -class PhysicalMemory; class BaseCPU; #if FULL_SYSTEM @@ -56,6 +53,7 @@ class MemoryController; #else // !FULL_SYSTEM #include "sim/process.hh" +class TranslatingPort; #endif // FULL_SYSTEM @@ -118,17 +116,21 @@ class CPUExecContext Tick lastActivate; Tick lastSuspend; + System *system; + + /// Port that syscalls can use to access memory (provides translation step). + TranslatingPort *port; +// Memory *mem; + #if FULL_SYSTEM - FunctionalMemory *mem; AlphaITB *itb; AlphaDTB *dtb; - System *system; // the following two fields are redundant, since we can always // look them up through the system pointer, but we'll leave them // here for now for convenience MemoryController *memctrl; - PhysicalMemory *physmem; +// PhysicalMemory *physmem; FunctionProfile *profile; ProfileNode *profileNode; @@ -164,8 +166,6 @@ class CPUExecContext #else Process *process; - FunctionalMemory *mem; // functional storage for process address space - // Address space ID. Note that this is used for TIMING cache // simulation only; all functional memory accesses should use // one of the FunctionalMemory pointers above. @@ -202,9 +202,7 @@ class CPUExecContext CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system, AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem); #else - CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid); - CPUExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem, - int _asid); + CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, Port *mem_port); // Constructor to use XC to pass reg file around. Not used for anything // else. CPUExecContext(RegFile *regFile); @@ -218,6 +216,8 @@ class CPUExecContext void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); + TranslatingPort *getMemPort() { return port; } + BaseCPU *getCpuPtr() { return cpu; } ExecContext *getProxy() { return proxy; } @@ -238,17 +238,17 @@ class CPUExecContext int getInstAsid() { return regs.instAsid(); } int getDataAsid() { return regs.dataAsid(); } - Fault translateInstReq(MemReqPtr &req) + Fault translateInstReq(CpuRequestPtr &req) { return itb->translate(req); } - Fault translateDataReadReq(MemReqPtr &req) + Fault translateDataReadReq(CpuRequestPtr &req) { return dtb->translate(req, false); } - Fault translateDataWriteReq(MemReqPtr &req) + Fault translateDataWriteReq(CpuRequestPtr &req) { return dtb->translate(req, true); } @@ -265,36 +265,28 @@ class CPUExecContext int getInstAsid() { return asid; } int getDataAsid() { return asid; } - Fault dummyTranslation(MemReqPtr &req) + Fault translateInstReq(CpuRequestPtr &req) { -#if 0 - assert((req->vaddr >> 48 & 0xffff) == 0); -#endif - - // put the asid in the upper 16 bits of the paddr - req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); - req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; - return NoFault; + return process->pTable->translate(req); } - Fault translateInstReq(MemReqPtr &req) - { - return dummyTranslation(req); - } - Fault translateDataReadReq(MemReqPtr &req) + + Fault translateDataReadReq(CpuRequestPtr &req) { - return dummyTranslation(req); + return process->pTable->translate(req); } - Fault translateDataWriteReq(MemReqPtr &req) + + Fault translateDataWriteReq(CpuRequestPtr &req) { - return dummyTranslation(req); + return process->pTable->translate(req); } #endif +/* template <class T> - Fault read(MemReqPtr &req, T &data) + Fault read(CpuRequestPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA if (req->flags & LOCKED) { req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr); req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true); @@ -302,15 +294,15 @@ class CPUExecContext #endif Fault error; - error = mem->read(req, data); + error = mem->prot_read(req->paddr, data, req->size); data = LittleEndianGuest::gtoh(data); return error; } template <class T> - Fault write(MemReqPtr &req, T &data) + Fault write(CpuRequestPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA ExecContext *xc; // If this is a store conditional, act appropriately @@ -356,9 +348,9 @@ class CPUExecContext } #endif - return mem->write(req, (T)LittleEndianGuest::htog(data)); + return mem->prot_write(req->paddr, (T)htog(data), req->size); } - +*/ virtual bool misspeculating(); @@ -369,17 +361,17 @@ class CPUExecContext inst = new_inst; } - Fault instRead(MemReqPtr &req) + Fault instRead(CpuRequestPtr &req) { - return mem->read(req, inst); + panic("instRead not implemented"); + // return funcPhysMem->read(req, inst); + return NoFault; } void setCpuId(int id) { cpu_id = id; } int readCpuId() { return cpu_id; } - FunctionalMemory *getMemPtr() { return mem; } - void copyArchRegs(ExecContext *xc); // diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index 2b6c41bd7..225f19b87 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -30,7 +30,7 @@ #define __CPU_EXEC_CONTEXT_HH__ #include "config/full_system.hh" -#include "mem/mem_req.hh" +#include "mem/request.hh" #include "sim/faults.hh" #include "sim/host.hh" #include "sim/serialize.hh" @@ -43,8 +43,8 @@ class AlphaDTB; class AlphaITB; class BaseCPU; class Event; -class FunctionalMemory; class PhysicalMemory; +class TranslatingPort; class Process; class System; @@ -81,14 +81,14 @@ class ExecContext virtual ~ExecContext() { }; + virtual TranslatingPort *getMemPort() = 0; + virtual BaseCPU *getCpuPtr() = 0; virtual void setCpuId(int id) = 0; virtual int readCpuId() = 0; - virtual FunctionalMemory *getMemPtr() = 0; - #if FULL_SYSTEM virtual System *getSystemPtr() = 0; @@ -148,11 +148,11 @@ class ExecContext virtual int getInstAsid() = 0; virtual int getDataAsid() = 0; - virtual Fault translateInstReq(MemReqPtr &req) = 0; + virtual Fault translateInstReq(CpuRequestPtr &req) = 0; - virtual Fault translateDataReadReq(MemReqPtr &req) = 0; + virtual Fault translateDataReadReq(CpuRequestPtr &req) = 0; - virtual Fault translateDataWriteReq(MemReqPtr &req) = 0; + virtual Fault translateDataWriteReq(CpuRequestPtr &req) = 0; // Also somewhat obnoxious. Really only used for the TLB fault. // However, may be quite useful in SPARC. @@ -243,14 +243,14 @@ class ProxyExecContext : public ExecContext public: + TranslatingPort *getMemPort() { return actualXC->getMemPort(); } + BaseCPU *getCpuPtr() { return actualXC->getCpuPtr(); } void setCpuId(int id) { actualXC->setCpuId(id); } int readCpuId() { return actualXC->readCpuId(); } - FunctionalMemory *getMemPtr() { return actualXC->getMemPtr(); } - #if FULL_SYSTEM System *getSystemPtr() { return actualXC->getSystemPtr(); } @@ -310,13 +310,13 @@ class ProxyExecContext : public ExecContext int getInstAsid() { return actualXC->getInstAsid(); } int getDataAsid() { return actualXC->getDataAsid(); } - Fault translateInstReq(MemReqPtr &req) + Fault translateInstReq(CpuRequestPtr &req) { return actualXC->translateInstReq(req); } - Fault translateDataReadReq(MemReqPtr &req) + Fault translateDataReadReq(CpuRequestPtr &req) { return actualXC->translateDataReadReq(req); } - Fault translateDataWriteReq(MemReqPtr &req) + Fault translateDataWriteReq(CpuRequestPtr &req) { return actualXC->translateDataWriteReq(req); } // @todo: Do I need this? diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc index 84b5eacf7..ebb719b2c 100644 --- a/cpu/exetrace.cc +++ b/cpu/exetrace.cc @@ -30,9 +30,6 @@ #include <iomanip> #include "sim/param.hh" -#include "encumbered/cpu/full/dyn_inst.hh" -#include "encumbered/cpu/full/spec_state.hh" -#include "encumbered/cpu/full/issue.hh" #include "cpu/exetrace.hh" #include "base/loader/symtab.hh" #include "cpu/base.hh" diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh index 0352e9972..8e1e0f42a 100644 --- a/cpu/o3/alpha_cpu.hh +++ b/cpu/o3/alpha_cpu.hh @@ -208,7 +208,7 @@ class AlphaFullCPU : public FullO3CPU<Impl> template <class T> Fault read(MemReqPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA if (req->flags & LOCKED) { req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr); req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true); @@ -230,7 +230,7 @@ class AlphaFullCPU : public FullO3CPU<Impl> template <class T> Fault write(MemReqPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA ExecContext *xc; // If this is a store conditional, act appropriately diff --git a/cpu/op_class.cc b/cpu/op_class.cc new file mode 100644 index 000000000..00136ded5 --- /dev/null +++ b/cpu/op_class.cc @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003-2005 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. + */ + +#include "cpu/op_class.hh" + +/** OpClass enum -> description string */ +const char * +opClassStrings[Num_OpClasses] = +{ + "(null)", + "IntAlu", + "IntMult", + "IntDiv", + "FloatAdd", + "FloatCmp", + "FloatCvt", + "FloatMult", + "FloatDiv", + "FloatSqrt", + "MemRead", + "MemWrite", + "IprAccess", + "InstPrefetch" +}; + diff --git a/cpu/op_class.hh b/cpu/op_class.hh new file mode 100644 index 000000000..cdb40a0fb --- /dev/null +++ b/cpu/op_class.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003-2005 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 __CPU__OP_CLASS_HH__ +#define __CPU__OP_CLASS_HH__ + +/** + * @file + * Definition of operation classes. + */ + +/** + * Instruction operation classes. These classes are used for + * assigning instructions to functional units. + */ +enum OpClass { + No_OpClass = 0, ///< Instruction does not use a functional unit + IntAluOp, ///< Integer ALU operaton (add/sub/logical) + IntMultOp, ///< Integer multiply + IntDivOp, ///< Integer divide + FloatAddOp, ///< Floating point add/subtract + FloatCmpOp, ///< Floating point comparison + FloatCvtOp, ///< Floating point<->integer conversion + FloatMultOp, ///< Floating point multiply + FloatDivOp, ///< Floating point divide + FloatSqrtOp, ///< Floating point square root + MemReadOp, ///< Memory read port + MemWriteOp, ///< Memory write port + IprAccessOp, ///< Internal Processor Register read/write port + InstPrefetchOp, ///< Instruction prefetch port (on I-cache) + Num_OpClasses ///< Total number of operation classes +}; + +/** + * Array mapping OpClass enum values to strings. Defined in op_class.cc. + */ +extern const char *opClassStrings[]; + +#endif // __CPU__OP_CLASS_HH__ diff --git a/cpu/pc_event.hh b/cpu/pc_event.hh index 7fa3902cc..32b7f3ef5 100644 --- a/cpu/pc_event.hh +++ b/cpu/pc_event.hh @@ -31,7 +31,7 @@ #include <vector> -#include "mem/mem_req.hh" +#include "base/misc.hh" class ExecContext; class PCEventQueue; @@ -39,9 +39,6 @@ class PCEventQueue; class PCEvent { protected: - static const Addr badpc = MemReq::inval_addr; - - protected: std::string description; PCEventQueue *queue; Addr evpc; diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc index 8db72b77e..b5ba6ecc9 100644 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@ -35,6 +35,7 @@ #include <sstream> #include <string> +#include "arch/utility.hh" #include "base/cprintf.hh" #include "base/inifile.hh" #include "base/loader/symtab.hh" @@ -53,8 +54,6 @@ #include "cpu/smt.hh" #include "cpu/static_inst.hh" #include "kern/kernel_stats.hh" -#include "mem/base_mem.hh" -#include "mem/mem_interface.hh" #include "sim/byteswap.hh" #include "sim/builder.hh" #include "sim/debug.hh" @@ -72,7 +71,7 @@ #include "arch/stacktrace.hh" #include "arch/vtophys.hh" #else // !FULL_SYSTEM -#include "mem/functional/functional.hh" +#include "mem/memory.hh" #endif // FULL_SYSTEM using namespace std; @@ -116,43 +115,85 @@ SimpleCPU::TickEvent::description() } -SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu) - : Event(&mainEventQueue), cpu(_cpu) +bool +SimpleCPU::CpuPort::recvTiming(Packet &pkt) { + cpu->processResponse(pkt); + return true; } -void SimpleCPU::CacheCompletionEvent::process() +Tick +SimpleCPU::CpuPort::recvAtomic(Packet &pkt) { - cpu->processCacheCompletion(); + panic("CPU doesn't expect callback!"); + return curTick; } -const char * -SimpleCPU::CacheCompletionEvent::description() +void +SimpleCPU::CpuPort::recvFunctional(Packet &pkt) +{ + panic("CPU doesn't expect callback!"); +} + +void +SimpleCPU::CpuPort::recvStatusChange(Status status) +{ + cpu->recvStatusChange(status); +} + +Packet * +SimpleCPU::CpuPort::recvRetry() { - return "SimpleCPU cache completion event"; + return cpu->processRetry(); } SimpleCPU::SimpleCPU(Params *p) - : BaseCPU(p), tickEvent(this, p->width), cpuXC(NULL), - cacheCompletionEvent(this) + : BaseCPU(p), icachePort(this), + dcachePort(this), tickEvent(this, p->width), cpuXC(NULL) { _status = Idle; + + //Create Memory Ports (conect them up) + p->mem->addPort("DCACHE"); + dcachePort.setPeer(p->mem->getPort("DCACHE")); + (p->mem->getPort("DCACHE"))->setPeer(&dcachePort); + + p->mem->addPort("ICACHE"); + icachePort.setPeer(p->mem->getPort("ICACHE")); + (p->mem->getPort("ICACHE"))->setPeer(&icachePort); + #if FULL_SYSTEM cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem); - #else - cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, - /* asid */ 0); + cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0, + &dcachePort); #endif // !FULL_SYSTEM - xcProxy = cpuXC->getProxy(); - icacheInterface = p->icache_interface; - dcacheInterface = p->dcache_interface; + xcProxy = cpuXC->getProxy(); - memReq = new MemReq(); - memReq->xc = xcProxy; - memReq->asid = 0; - memReq->data = new uint8_t[64]; +#if SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE + ifetch_req = new CpuRequest; + ifetch_req->asid = 0; + ifetch_req->size = sizeof(MachInst); + ifetch_pkt = new Packet; + ifetch_pkt->cmd = Read; + ifetch_pkt->data = (uint8_t *)&inst; + ifetch_pkt->req = ifetch_req; + ifetch_pkt->size = sizeof(MachInst); + + data_read_req = new CpuRequest; + data_read_req->asid = 0; + data_read_pkt = new Packet; + data_read_pkt->cmd = Read; + data_read_pkt->data = new uint8_t[8]; + data_read_pkt->req = data_read_req; + + data_write_req = new CpuRequest; + data_write_req->asid = 0; + data_write_pkt = new Packet; + data_write_pkt->cmd = Write; + data_write_pkt->req = data_write_req; +#endif numInst = 0; startNumInst = 0; @@ -172,9 +213,9 @@ void SimpleCPU::switchOut(Sampler *s) { sampler = s; - if (status() == DcacheMissStall) { + if (status() == DcacheWaitResponse) { DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n"); - _status = DcacheMissSwitch; + _status = DcacheWaitSwitch; } else { _status = SwitchedOut; @@ -287,6 +328,18 @@ SimpleCPU::regStats() .prereq(dcacheStallCycles) ; + icacheRetryCycles + .name(name() + ".icache_retry_cycles") + .desc("ICache total retry cycles") + .prereq(icacheRetryCycles) + ; + + dcacheRetryCycles + .name(name() + ".dcache_retry_cycles") + .desc("DCache total retry cycles") + .prereq(dcacheRetryCycles) + ; + idleFraction = constant(1.0) - notIdleFraction; } @@ -308,7 +361,6 @@ SimpleCPU::serialize(ostream &os) nameOut(os, csprintf("%s.tickEvent", name())); tickEvent.serialize(os); nameOut(os, csprintf("%s.cacheCompletionEvent", name())); - cacheCompletionEvent.serialize(os); } void @@ -319,8 +371,6 @@ SimpleCPU::unserialize(Checkpoint *cp, const string §ion) UNSERIALIZE_SCALAR(inst); cpuXC->unserialize(cp, csprintf("%s.xc", section)); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); - cacheCompletionEvent - .unserialize(cp, csprintf("%s.cacheCompletionEvent", section)); } void @@ -331,6 +381,7 @@ change_thread_state(int thread_number, int activate, int priority) Fault SimpleCPU::copySrcTranslate(Addr src) { +#if 0 static bool no_warn = true; int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; // Only support block sizes of 64 atm. @@ -347,8 +398,7 @@ SimpleCPU::copySrcTranslate(Addr src) memReq->reset(src & ~(blk_size - 1), blk_size); - // translate to physical address - Fault fault = cpuXC->translateDataReadReq(memReq); + // translate to physical address Fault fault = cpuXC->translateDataReadReq(req); if (fault == NoFault) { cpuXC->copySrcAddr = src; @@ -360,11 +410,15 @@ SimpleCPU::copySrcTranslate(Addr src) cpuXC->copySrcPhysAddr = 0; } return fault; +#else + return NoFault; +#endif } Fault SimpleCPU::copy(Addr dest) { +#if 0 static bool no_warn = true; int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; // Only support block sizes of 64 atm. @@ -383,7 +437,7 @@ SimpleCPU::copy(Addr dest) memReq->reset(dest & ~(blk_size -1), blk_size); // translate to physical address - Fault fault = cpuXC->translateDataWriteReq(memReq); + Fault fault = cpuXC->translateDataWriteReq(req); if (fault == NoFault) { Addr dest_addr = memReq->paddr + offset; @@ -407,6 +461,10 @@ SimpleCPU::copy(Addr dest) assert(!fault->isAlignmentFault()); return fault; +#else + panic("copy not implemented"); + return NoFault; +#endif } // precise architected memory state accessor macros @@ -414,22 +472,64 @@ template <class T> Fault SimpleCPU::read(Addr addr, T &data, unsigned flags) { - if (status() == DcacheMissStall || status() == DcacheMissSwitch) { - Fault fault = cpuXC->read(memReq,data); + if (status() == DcacheWaitResponse || status() == DcacheWaitSwitch) { +// Fault fault = xc->read(memReq,data); + // Not sure what to check for no fault... + if (data_read_pkt->result == Success) { + memcpy(&data, data_read_pkt->data, sizeof(T)); + } if (traceData) { traceData->setAddr(addr); } - return fault; + + // @todo: Figure out a way to create a Fault from the packet result. + return NoFault; } - memReq->reset(addr, sizeof(T), flags); +// memReq->reset(addr, sizeof(T), flags); + +#if SIMPLE_CPU_MEM_TIMING + CpuRequest *data_read_req = new CpuRequest; +#endif + + data_read_req->vaddr = addr; + data_read_req->size = sizeof(T); + data_read_req->flags = flags; + data_read_req->time = curTick; // translate to physical address - Fault fault = cpuXC->translateDataReadReq(memReq); + Fault fault = cpuXC->translateDataReadReq(data_read_req); - // if we have a cache, do cache access too - if (fault == NoFault && dcacheInterface) { + // Now do the access. + if (fault == NoFault) { +#if SIMPLE_CPU_MEM_TIMING + data_read_pkt = new Packet; + data_read_pkt->cmd = Read; + data_read_pkt->req = data_read_req; + data_read_pkt->data = new uint8_t[8]; +#endif + data_read_pkt->addr = data_read_req->paddr; + data_read_pkt->size = sizeof(T); + + sendDcacheRequest(data_read_pkt); + +#if SIMPLE_CPU_MEM_IMMEDIATE + // Need to find a way to not duplicate code above. + + if (data_read_pkt->result == Success) { + memcpy(&data, data_read_pkt->data, sizeof(T)); + } + + if (traceData) { + traceData->setAddr(addr); + } + + // @todo: Figure out a way to create a Fault from the packet result. + return NoFault; +#endif + } +/* memReq->cmd = Read; memReq->completionEvent = NULL; memReq->time = curTick; @@ -454,8 +554,9 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) fault = cpuXC->read(memReq, data); } - - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) +*/ + // This will need a new way to tell if it has a dcache attached. + if (data_read_req->flags & UNCACHEABLE) recordEvent("Uncached Read"); return fault; @@ -508,11 +609,31 @@ template <class T> Fault SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { - memReq->reset(addr, sizeof(T), flags); + data_write_req->vaddr = addr; + data_write_req->time = curTick; + data_write_req->size = sizeof(T); + data_write_req->flags = flags; // translate to physical address - Fault fault = cpuXC->translateDataWriteReq(memReq); + Fault fault = cpuXC->translateDataWriteReq(data_write_req); + // Now do the access. + if (fault == NoFault) { +#if SIMPLE_CPU_MEM_TIMING + data_write_pkt = new Packet; + data_write_pkt->cmd = Write; + data_write_pkt->req = data_write_req; + data_write_pkt->data = new uint8_t[64]; + memcpy(data_write_pkt->data, &data, sizeof(T)); +#else + data_write_pkt->data = (uint8_t *)&data; +#endif + data_write_pkt->addr = data_write_req->paddr; + data_write_pkt->size = sizeof(T); + + sendDcacheRequest(data_write_pkt); + } +/* // do functional access if (fault == NoFault) fault = cpuXC->write(memReq, data); @@ -535,13 +656,16 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) _status = DcacheMissStall; } } - +*/ if (res && (fault == NoFault)) - *res = memReq->result; + *res = data_write_pkt->result; - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) + // This will need a new way to tell if it's hooked up to a cache or not. + if (data_write_req->flags & UNCACHEABLE) recordEvent("Uncached Write"); + // If the write needs to have a fault on the access, consider calling + // changeStatus() and changing it to "bad addr write" or something. return fault; } @@ -597,36 +721,130 @@ SimpleCPU::dbg_vtophys(Addr addr) #endif // FULL_SYSTEM void -SimpleCPU::processCacheCompletion() +SimpleCPU::sendIcacheRequest(Packet *pkt) +{ + assert(!tickEvent.scheduled()); +#if SIMPLE_CPU_MEM_TIMING + retry_pkt = pkt; + bool success = icachePort.sendTiming(*pkt); + + unscheduleTickEvent(); + + lastIcacheStall = curTick; + + if (!success) { + // Need to wait for retry + _status = IcacheRetry; + } else { + // Need to wait for cache to respond + _status = IcacheWaitResponse; + } +#elif SIMPLE_CPU_MEM_ATOMIC + Tick latency = icachePort.sendAtomic(*pkt); + + unscheduleTickEvent(); + scheduleTickEvent(latency); + + // Note that Icache miss cycles will be incorrect. Unless + // we check the status of the packet sent (is this valid?), + // we won't know if the latency is a hit or a miss. + icacheStallCycles += latency; + + _status = IcacheAccessComplete; +#elif SIMPLE_CPU_MEM_IMMEDIATE + icachePort.sendAtomic(*pkt); +#else +#error "SimpleCPU has no mem model set" +#endif +} + +void +SimpleCPU::sendDcacheRequest(Packet *pkt) { + assert(!tickEvent.scheduled()); +#if SIMPLE_CPU_MEM_TIMING + unscheduleTickEvent(); + + retry_pkt = pkt; + bool success = dcachePort.sendTiming(*pkt); + + lastDcacheStall = curTick; + + if (!success) { + _status = DcacheRetry; + } else { + _status = DcacheWaitResponse; + } +#elif SIMPLE_CPU_MEM_ATOMIC + unscheduleTickEvent(); + + Tick latency = dcachePort.sendAtomic(*pkt); + + scheduleTickEvent(latency); + + // Note that Dcache miss cycles will be incorrect. Unless + // we check the status of the packet sent (is this valid?), + // we won't know if the latency is a hit or a miss. + dcacheStallCycles += latency; +#elif SIMPLE_CPU_MEM_IMMEDIATE + dcachePort.sendAtomic(*pkt); +#else +#error "SimpleCPU has no mem model set" +#endif +} + +void +SimpleCPU::processResponse(Packet &response) +{ + assert(SIMPLE_CPU_MEM_TIMING); + + // For what things is the CPU the consumer of the packet it sent + // out? This may create a memory leak if that's the case and it's + // expected of the SimpleCPU to delete its own packet. + Packet *pkt = &response; + switch (status()) { - case IcacheMissStall: + case IcacheWaitResponse: icacheStallCycles += curTick - lastIcacheStall; - _status = IcacheMissComplete; + + _status = IcacheAccessComplete; scheduleTickEvent(1); + + // Copy the icache data into the instruction itself. + memcpy(&inst, pkt->data, sizeof(inst)); + + delete pkt; break; - case DcacheMissStall: - if (memReq->cmd.isRead()) { + case DcacheWaitResponse: + if (pkt->cmd == Read) { curStaticInst->execute(this,traceData); if (traceData) traceData->finalize(); } + + delete pkt; + dcacheStallCycles += curTick - lastDcacheStall; _status = Running; scheduleTickEvent(1); break; - case DcacheMissSwitch: - if (memReq->cmd.isRead()) { + case DcacheWaitSwitch: + if (pkt->cmd == Read) { curStaticInst->execute(this,traceData); if (traceData) traceData->finalize(); } + + delete pkt; + _status = SwitchedOut; sampler->signalSwitched(); case SwitchedOut: // If this CPU has been switched out due to sampling/warm-up, // ignore any further status changes (e.g., due to cache // misses outstanding at the time of the switch). + delete pkt; + return; default: panic("SimpleCPU::processCacheCompletion: bad state"); @@ -634,6 +852,28 @@ SimpleCPU::processCacheCompletion() } } +Packet * +SimpleCPU::processRetry() +{ +#if SIMPLE_CPU_MEM_TIMING + switch(status()) { + case IcacheRetry: + icacheRetryCycles += curTick - lastIcacheStall; + return retry_pkt; + break; + case DcacheRetry: + dcacheRetryCycles += curTick - lastDcacheStall; + return retry_pkt; + break; + default: + panic("SimpleCPU::processRetry: bad state"); + break; + } +#else + panic("shouldn't be here"); +#endif +} + #if FULL_SYSTEM void SimpleCPU::post_interrupt(int int_num, int index) @@ -702,19 +942,18 @@ SimpleCPU::tick() // maintain $r0 semantics cpuXC->setIntReg(ZeroReg, 0); -#ifdef TARGET_ALPHA +#if THE_ISA == ALPHA_ISA cpuXC->setFloatRegDouble(ZeroReg, 0.0); -#endif // TARGET_ALPHA +#endif // ALPHA_ISA - if (status() == IcacheMissComplete) { + if (status() == IcacheAccessComplete) { // We've already fetched an instruction and were stalled on an // I-cache miss. No need to fetch it again. // Set status to running; tick event will get rescheduled if // necessary at end of tick() function. _status = Running; - } - else { + } else { // Try to fetch an instruction // set up memory request for instruction fetch @@ -724,15 +963,35 @@ SimpleCPU::tick() #define IFETCH_FLAGS(pc) 0 #endif - memReq->cmd = Read; - memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t), - IFETCH_FLAGS(cpuXC->readPC())); +#if SIMPLE_CPU_MEM_TIMING + CpuRequest *ifetch_req = new CpuRequest(); + ifetch_req->size = sizeof(MachInst); +#endif + + ifetch_req->vaddr = cpuXC->readPC() & ~3; + ifetch_req->time = curTick; - fault = cpuXC->translateInstReq(memReq); +/* memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t), + IFETCH_FLAGS(xc->regs.pc)); +*/ - if (fault == NoFault) - fault = cpuXC->mem->read(memReq, inst); + fault = cpuXC->translateInstReq(ifetch_req); + + if (fault == NoFault) { +#if SIMPLE_CPU_MEM_TIMING + Packet *ifetch_pkt = new Packet; + ifetch_pkt->cmd = Read; + ifetch_pkt->data = (uint8_t *)&inst; + ifetch_pkt->req = ifetch_req; + ifetch_pkt->size = sizeof(MachInst); +#endif + ifetch_pkt->addr = ifetch_req->paddr; + sendIcacheRequest(ifetch_pkt); +#if SIMPLE_CPU_MEM_TIMING || SIMPLE_CPU_MEM_ATOMIC + return; +#endif +/* if (icacheInterface && fault == NoFault) { memReq->completionEvent = NULL; @@ -743,7 +1002,7 @@ SimpleCPU::tick() // Ugly hack to get an event scheduled *only* if the access is // a miss. We really should add first-class support for this // at some point. - if (result != MA_HIT && icacheInterface->doEvents()) { + if (result != MA_HIT && icacheInterface->doEvents()) { memReq->completionEvent = &cacheCompletionEvent; lastIcacheStall = curTick; unscheduleTickEvent(); @@ -751,6 +1010,8 @@ SimpleCPU::tick() return; } } +*/ + } } // If we've got a valid instruction (i.e., no fault on instruction @@ -806,8 +1067,7 @@ SimpleCPU::tick() // If we have a dcache miss, then we can't finialize the instruction // trace yet because we want to populate it with the data later - if (traceData && - !(status() == DcacheMissStall && memReq->cmd.isRead())) { + if (traceData && (status() != DcacheWaitResponse)) { traceData->finalize(); } @@ -819,7 +1079,7 @@ SimpleCPU::tick() #if FULL_SYSTEM fault->invoke(xcProxy); #else // !FULL_SYSTEM - fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC()); + fatal("fault (%d) detected @ PC %08p", fault, cpuXC->readPC()); #endif // FULL_SYSTEM } else { @@ -846,7 +1106,7 @@ SimpleCPU::tick() assert(status() == Running || status() == Idle || - status() == DcacheMissStall); + status() == DcacheWaitResponse); if (status() == Running && !tickEvent.scheduled()) tickEvent.schedule(curTick + cycles(1)); @@ -866,17 +1126,15 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) #if FULL_SYSTEM SimObjectParam<AlphaITB *> itb; SimObjectParam<AlphaDTB *> dtb; - SimObjectParam<FunctionalMemory *> mem; SimObjectParam<System *> system; Param<int> cpu_id; Param<Tick> profile; #else + SimObjectParam<Memory *> mem; SimObjectParam<Process *> workload; #endif // FULL_SYSTEM Param<int> clock; - SimObjectParam<BaseMem *> icache; - SimObjectParam<BaseMem *> dcache; Param<bool> defer_registration; Param<int> width; @@ -899,17 +1157,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) #if FULL_SYSTEM INIT_PARAM(itb, "Instruction TLB"), INIT_PARAM(dtb, "Data TLB"), - INIT_PARAM(mem, "memory"), INIT_PARAM(system, "system object"), INIT_PARAM(cpu_id, "processor ID"), INIT_PARAM(profile, ""), #else + INIT_PARAM(mem, "memory"), INIT_PARAM(workload, "processes to run"), #endif // FULL_SYSTEM INIT_PARAM(clock, "clock speed"), - INIT_PARAM(icache, "L1 instruction cache object"), - INIT_PARAM(dcache, "L1 data cache object"), INIT_PARAM(defer_registration, "defer system registration (for sampling)"), INIT_PARAM(width, "cpu width"), INIT_PARAM(function_trace, "Enable function trace"), @@ -931,18 +1187,16 @@ CREATE_SIM_OBJECT(SimpleCPU) params->clock = clock; params->functionTrace = function_trace; params->functionTraceStart = function_trace_start; - params->icache_interface = (icache) ? icache->getInterface() : NULL; - params->dcache_interface = (dcache) ? dcache->getInterface() : NULL; params->width = width; #if FULL_SYSTEM params->itb = itb; params->dtb = dtb; - params->mem = mem; params->system = system; params->cpu_id = cpu_id; params->profile = profile; #else + params->mem = mem; params->process = workload; #endif diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh index 4ab9a1c3e..fbfae950f 100644 --- a/cpu/simple/cpu.hh +++ b/cpu/simple/cpu.hh @@ -36,6 +36,9 @@ #include "cpu/pc_event.hh" #include "cpu/sampler/sampler.hh" #include "cpu/static_inst.hh" +#include "mem/packet.hh" +#include "mem/port.hh" +#include "mem/request.hh" #include "sim/eventq.hh" // forward declarations @@ -43,7 +46,7 @@ class Processor; class AlphaITB; class AlphaDTB; -class PhysicalMemory; +class Memory; class RemoteGDB; class GDBListener; @@ -62,11 +65,48 @@ namespace Trace { class InstRecord; } + +// Set exactly one of these symbols to 1 to set the memory access +// model. Probably should make these template parameters, or even +// just fork the CPU models. +// +#define SIMPLE_CPU_MEM_TIMING 0 +#define SIMPLE_CPU_MEM_ATOMIC 0 +#define SIMPLE_CPU_MEM_IMMEDIATE 1 + + class SimpleCPU : public BaseCPU { protected: typedef TheISA::MachInst MachInst; typedef TheISA::MiscReg MiscReg; + class CpuPort : public Port + { + + SimpleCPU *cpu; + + public: + + CpuPort(SimpleCPU *_cpu) + : cpu(_cpu) + { } + + protected: + + virtual bool recvTiming(Packet &pkt); + + virtual Tick recvAtomic(Packet &pkt); + + virtual void recvFunctional(Packet &pkt); + + virtual void recvStatusChange(Status status); + + virtual Packet *recvRetry(); + }; + + CpuPort icachePort; + CpuPort dcachePort; + public: // main simulation loop (one cycle) void tick(); @@ -109,10 +149,12 @@ class SimpleCPU : public BaseCPU enum Status { Running, Idle, - IcacheMissStall, - IcacheMissComplete, - DcacheMissStall, - DcacheMissSwitch, + IcacheRetry, + IcacheWaitResponse, + IcacheAccessComplete, + DcacheRetry, + DcacheWaitResponse, + DcacheWaitSwitch, SwitchedOut }; @@ -133,14 +175,12 @@ class SimpleCPU : public BaseCPU public: struct Params : public BaseCPU::Params { - MemInterface *icache_interface; - MemInterface *dcache_interface; int width; #if FULL_SYSTEM AlphaITB *itb; AlphaDTB *dtb; - FunctionalMemory *mem; #else + Memory *mem; Process *process; #endif }; @@ -162,17 +202,19 @@ class SimpleCPU : public BaseCPU bool interval_stats; #endif - // L1 instruction cache - MemInterface *icacheInterface; - - // L1 data cache - MemInterface *dcacheInterface; - // current instruction MachInst inst; - // Refcounted pointer to the one memory request. - MemReqPtr memReq; +#if SIMPLE_CPU_MEM_TIMING + Packet *retry_pkt; +#elif SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE + CpuRequest *ifetch_req; + Packet *ifetch_pkt; + CpuRequest *data_read_req; + Packet *data_read_pkt; + CpuRequest *data_write_req; + Packet *data_write_pkt; +#endif // Pointer to the sampler that is telling us to switchover. // Used to signal the completion of the pipe drain and schedule @@ -181,20 +223,6 @@ class SimpleCPU : public BaseCPU StaticInstPtr curStaticInst; - 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 activateContext(int thread_num, int delay); @@ -227,15 +255,28 @@ class SimpleCPU : public BaseCPU Stats::Average<> notIdleFraction; Stats::Formula idleFraction; - // number of cycles stalled for I-cache misses + // number of cycles stalled for I-cache responses Stats::Scalar<> icacheStallCycles; Counter lastIcacheStall; - // number of cycles stalled for D-cache misses + // number of cycles stalled for I-cache retries + Stats::Scalar<> icacheRetryCycles; + Counter lastIcacheRetry; + + // number of cycles stalled for D-cache responses Stats::Scalar<> dcacheStallCycles; Counter lastDcacheStall; - void processCacheCompletion(); + // number of cycles stalled for D-cache retries + Stats::Scalar<> dcacheRetryCycles; + Counter lastDcacheRetry; + + void sendIcacheRequest(Packet *pkt); + void sendDcacheRequest(Packet *pkt); + void processResponse(Packet &response); + + Packet * processRetry(); + void recvStatusChange(Port::Status status) {} virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh index 20116554e..764020577 100644 --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@ -33,8 +33,9 @@ #include <string> #include "base/hashmap.hh" +#include "base/misc.hh" #include "base/refcnt.hh" -#include "encumbered/cpu/full/op_class.hh" +#include "cpu/op_class.hh" #include "sim/host.hh" #include "arch/isa_traits.hh" |