diff options
Diffstat (limited to 'src/cpu/simple')
-rw-r--r-- | src/cpu/simple/SConscript | 43 | ||||
-rw-r--r-- | src/cpu/simple/SConsopts | 34 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 105 | ||||
-rw-r--r-- | src/cpu/simple/atomic.hh | 18 | ||||
-rw-r--r-- | src/cpu/simple/base.cc | 62 | ||||
-rw-r--r-- | src/cpu/simple/base.hh | 47 | ||||
-rw-r--r-- | src/cpu/simple/timing.cc | 87 | ||||
-rw-r--r-- | src/cpu/simple/timing.hh | 2 |
8 files changed, 287 insertions, 111 deletions
diff --git a/src/cpu/simple/SConscript b/src/cpu/simple/SConscript new file mode 100644 index 000000000..9a6a80473 --- /dev/null +++ b/src/cpu/simple/SConscript @@ -0,0 +1,43 @@ +# -*- mode:python -*- + +# 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: Nathan Binkert + +Import('*') + +need_simple_base = False +if 'AtomicSimpleCPU' in env['CPU_MODELS']: + need_simple_base = True + Source('atomic.cc') + +if 'TimingSimpleCPU' in env['CPU_MODELS']: + need_simple_base = True + Source('timing.cc') + +if need_simple_base: + Source('base.cc') diff --git a/src/cpu/simple/SConsopts b/src/cpu/simple/SConsopts new file mode 100644 index 000000000..32dbda1a5 --- /dev/null +++ b/src/cpu/simple/SConsopts @@ -0,0 +1,34 @@ +# -*- mode:python -*- + +# 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: Nathan Binkert + +Import('*') + +all_cpu_list.extend(('AtomicSimpleCPU', 'TimingSimpleCPU')) +default_cpus.extend(('AtomicSimpleCPU', 'TimingSimpleCPU')) diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 3b3536e44..6f69b5ac4 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -31,6 +31,7 @@ #include "arch/locked_mem.hh" #include "arch/mmaped_ipr.hh" #include "arch/utility.hh" +#include "base/bigint.hh" #include "cpu/exetrace.hh" #include "cpu/simple/atomic.hh" #include "mem/packet.hh" @@ -125,6 +126,17 @@ AtomicSimpleCPU::CpuPort::recvRetry() panic("AtomicSimpleCPU doesn't expect recvRetry callback!"); } +void +AtomicSimpleCPU::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + cpu->tcBase()->connectMemPorts(); +#endif +} AtomicSimpleCPU::AtomicSimpleCPU(Params *p) : BaseSimpleCPU(p), tickEvent(this), @@ -138,18 +150,20 @@ AtomicSimpleCPU::AtomicSimpleCPU(Params *p) ifetch_req = new Request(); ifetch_req->setThreadContext(p->cpu_id, 0); // Add thread ID if we add MT - ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); + ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); ifetch_pkt->dataStatic(&inst); data_read_req = new Request(); data_read_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too - data_read_pkt = new Packet(data_read_req, Packet::ReadReq, + data_read_pkt = new Packet(data_read_req, MemCmd::ReadReq, Packet::Broadcast); data_read_pkt->dataStatic(&dataReg); data_write_req = new Request(); data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too - data_write_pkt = new Packet(data_write_req, Packet::WriteReq, + data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq, + Packet::Broadcast); + data_swap_pkt = new Packet(data_write_req, MemCmd::SwapReq, Packet::Broadcast); } @@ -208,7 +222,7 @@ AtomicSimpleCPU::switchOut() void AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) { - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); assert(!tickEvent.scheduled()); @@ -239,12 +253,6 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay) notIdleFraction++; -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - tc->connectMemPorts(); -#endif - //Make sure ticks are still on multiples of cycles tickEvent.schedule(nextCycle(curTick + cycles(delay))); _status = Running; @@ -318,6 +326,14 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) template Fault +AtomicSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); + +template +Fault +AtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); + +template +Fault AtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); template @@ -363,10 +379,15 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { // use the CPU's statically allocated write request and packet objects Request *req = data_write_req; - PacketPtr pkt = data_write_pkt; + PacketPtr pkt; req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); + if (req->isSwap()) + pkt = data_swap_pkt; + else + pkt = data_write_pkt; + if (traceData) { traceData->setAddr(addr); } @@ -381,6 +402,11 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) if (req->isLocked()) { do_access = TheISA::handleLockedWrite(thread, req); } + if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); + } + if (do_access) { pkt->reinitFromRequest(); @@ -401,15 +427,11 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) #endif } - if (req->isLocked()) { - uint64_t scResult = req->getScResult(); - if (scResult != 0) { - // clear failure counter - thread->setStCondFailures(0); - } - if (res) { - *res = req->getScResult(); - } + if (req->isSwap()) { + assert(res); + *res = pkt->get<T>(); + } else if (res) { + *res = req->getExtraData(); } } @@ -424,6 +446,17 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) #ifndef DOXYGEN_SHOULD_SKIP_THIS + +template +Fault +AtomicSimpleCPU::write(Twin32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +AtomicSimpleCPU::write(Twin64_t data, Addr addr, + unsigned flags, uint64_t *res); + template Fault AtomicSimpleCPU::write(uint64_t data, Addr addr, @@ -483,17 +516,28 @@ AtomicSimpleCPU::tick() Fault fault = setupFetchRequest(ifetch_req); if (fault == NoFault) { - ifetch_pkt->reinitFromRequest(); + Tick icache_latency = 0; + bool icache_access = false; + dcache_access = false; // assume no dcache access - Tick icache_latency = icachePort.sendAtomic(ifetch_pkt); - // ifetch_req is initialized to read the instruction directly - // into the CPU object's inst field. + //Fetch more instruction memory if necessary + if(predecoder.needMoreBytes()) + { + icache_access = true; + ifetch_pkt->reinitFromRequest(); + + icache_latency = icachePort.sendAtomic(ifetch_pkt); + // ifetch_req is initialized to read the instruction directly + // into the CPU object's inst field. + } - dcache_access = false; // assume no dcache access preExecute(); - fault = curStaticInst->execute(this, traceData); - postExecute(); + if(curStaticInst) + { + fault = curStaticInst->execute(this, traceData); + postExecute(); + } // @todo remove me after debugging with legion done if (curStaticInst && (!curStaticInst->isMicroOp() || @@ -501,7 +545,8 @@ AtomicSimpleCPU::tick() instCnt++; if (simulate_stalls) { - Tick icache_stall = icache_latency - cycles(1); + Tick icache_stall = + icache_access ? icache_latency - cycles(1) : 0; Tick dcache_stall = dcache_access ? dcache_latency - cycles(1) : 0; Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1); @@ -512,8 +557,8 @@ AtomicSimpleCPU::tick() } } - - advancePC(fault); + if(predecoder.needMoreBytes()) + advancePC(fault); } if (_status != Idle) diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 42c7bf23a..ad4aa4708 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -81,9 +81,6 @@ class AtomicSimpleCPU : public BaseSimpleCPU class CpuPort : public Port { - - AtomicSimpleCPU *cpu; - public: CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu) @@ -94,6 +91,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU protected: + AtomicSimpleCPU *cpu; + virtual bool recvTiming(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt); @@ -110,7 +109,17 @@ class AtomicSimpleCPU : public BaseSimpleCPU }; CpuPort icachePort; - CpuPort dcachePort; + + class DcachePort : public CpuPort + { + public: + DcachePort(const std::string &_name, AtomicSimpleCPU *_cpu) + : CpuPort(_name, _cpu) + { } + + virtual void setPeer(Port *port); + }; + DcachePort dcachePort; Request *ifetch_req; PacketPtr ifetch_pkt; @@ -118,6 +127,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU PacketPtr data_read_pkt; Request *data_write_req; PacketPtr data_write_pkt; + PacketPtr data_swap_pkt; bool dcache_access; Tick dcache_latency; diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index b8d1f3bed..877dc5bd4 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -70,7 +70,7 @@ using namespace std; using namespace TheISA; BaseSimpleCPU::BaseSimpleCPU(Params *p) - : BaseCPU(p), thread(NULL) + : BaseCPU(p), thread(NULL), predecoder(NULL) { #if FULL_SYSTEM thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); @@ -301,7 +301,7 @@ BaseSimpleCPU::post_interrupt(int int_num, int index) BaseCPU::post_interrupt(int_num, index); if (thread->status() == ThreadContext::Suspended) { - DPRINTF(IPI,"Suspended Processor awoke\n"); + DPRINTF(Quiesce,"Suspended Processor awoke\n"); thread->activate(); } } @@ -367,16 +367,23 @@ BaseSimpleCPU::preExecute() inst = gtoh(inst); //If we're not in the middle of a macro instruction if (!curMacroStaticInst) { -#if THE_ISA == ALPHA_ISA - StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->readPC())); -#elif THE_ISA == SPARC_ISA - StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC())); -#elif THE_ISA == MIPS_ISA - //Mips doesn't do anything in it's MakeExtMI function right now, - //so it won't be called. - StaticInstPtr instPtr = StaticInst::decode(inst); -#endif - if (instPtr->isMacroOp()) { + StaticInstPtr instPtr = NULL; + + //Predecode, ie bundle up an ExtMachInst + //This should go away once the constructor can be set up properly + predecoder.setTC(thread->getTC()); + //If more fetch data is needed, pass it in. + if(predecoder.needMoreBytes()) + predecoder.moreBytes(thread->readPC(), 0, inst); + else + predecoder.process(); + //If an instruction is ready, decode it + if (predecoder.extMachInstReady()) + instPtr = StaticInst::decode(predecoder.getExtMachInst()); + + //If we decoded an instruction and it's microcoded, start pulling + //out micro ops + if (instPtr && instPtr->isMacroOp()) { curMacroStaticInst = instPtr; curStaticInst = curMacroStaticInst-> fetchMicroOp(thread->readMicroPC()); @@ -389,17 +396,19 @@ BaseSimpleCPU::preExecute() fetchMicroOp(thread->readMicroPC()); } + //If we decoded an instruction this "tick", record information about it. + if(curStaticInst) + { + traceData = Trace::getInstRecord(curTick, tc, curStaticInst, + thread->readPC()); - traceData = Trace::getInstRecord(curTick, tc, curStaticInst, - thread->readPC()); - - DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n", - curStaticInst->getName(), curStaticInst->getOpcode(), - curStaticInst->machInst); + DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", + curStaticInst->getName(), curStaticInst->machInst); #if FULL_SYSTEM - thread->setInst(inst); + thread->setInst(inst); #endif // FULL_SYSTEM + } } void @@ -409,7 +418,8 @@ BaseSimpleCPU::postExecute() if (thread->profile) { bool usermode = TheISA::inUserMode(tc); thread->profilePC = usermode ? 1 : thread->readPC(); - ProfileNode *node = thread->profile->consume(tc, inst); + StaticInstPtr si(inst); + ProfileNode *node = thread->profile->consume(tc, si); if (node) thread->profileNode = node; } @@ -427,7 +437,9 @@ BaseSimpleCPU::postExecute() traceFunctions(thread->readPC()); if (traceData) { - traceData->finalize(); + traceData->dump(); + delete traceData; + traceData = NULL; } } @@ -440,9 +452,9 @@ BaseSimpleCPU::advancePC(Fault fault) fault->invoke(tc); thread->setMicroPC(0); thread->setNextMicroPC(1); - } else { + } else if (predecoder.needMoreBytes()) { //If we're at the last micro op for this instruction - if (curStaticInst->isLastMicroOp()) { + if (curStaticInst && curStaticInst->isLastMicroOp()) { //We should be working with a macro op assert(curMacroStaticInst); //Close out this macro op, and clean up the @@ -461,13 +473,9 @@ BaseSimpleCPU::advancePC(Fault fault) } else { // go to the next instruction thread->setPC(thread->readNextPC()); -#if ISA_HAS_DELAY_SLOT thread->setNextPC(thread->readNextNPC()); thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); assert(thread->readNextPC() != thread->readNextNPC()); -#else - thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); -#endif } } diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index c4853b916..787259c96 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -33,6 +33,7 @@ #ifndef __CPU_SIMPLE_BASE_HH__ #define __CPU_SIMPLE_BASE_HH__ +#include "arch/predecoder.hh" #include "base/statistics.hh" #include "config/full_system.hh" #include "cpu/base.hh" @@ -63,6 +64,10 @@ class Process; class RemoteGDB; class GDBListener; +namespace TheISA +{ + class Predecoder; +} class ThreadContext; class Checkpoint; @@ -74,7 +79,6 @@ namespace Trace { class BaseSimpleCPU : public BaseCPU { protected: - typedef TheISA::MachInst MachInst; typedef TheISA::MiscReg MiscReg; typedef TheISA::FloatReg FloatReg; typedef TheISA::FloatRegBits FloatRegBits; @@ -122,10 +126,13 @@ class BaseSimpleCPU : public BaseCPU #endif // current instruction - MachInst inst; + TheISA::MachInst inst; + + // The predecoder + TheISA::Predecoder predecoder; // Static data storage - TheISA::IntReg dataReg; + TheISA::LargestRead dataReg; StaticInstPtr curStaticInst; StaticInstPtr curMacroStaticInst; @@ -284,14 +291,19 @@ class BaseSimpleCPU : public BaseCPU void setNextPC(uint64_t val) { thread->setNextPC(val); } void setNextNPC(uint64_t val) { thread->setNextNPC(val); } + MiscReg readMiscRegNoEffect(int misc_reg) + { + return thread->readMiscRegNoEffect(misc_reg); + } + MiscReg readMiscReg(int misc_reg) { return thread->readMiscReg(misc_reg); } - MiscReg readMiscRegWithEffect(int misc_reg) + void setMiscRegNoEffect(int misc_reg, const MiscReg &val) { - return thread->readMiscRegWithEffect(misc_reg); + return thread->setMiscRegNoEffect(misc_reg, val); } void setMiscReg(int misc_reg, const MiscReg &val) @@ -299,9 +311,10 @@ class BaseSimpleCPU : public BaseCPU return thread->setMiscReg(misc_reg, val); } - void setMiscRegWithEffect(int misc_reg, const MiscReg &val) + MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) { - return thread->setMiscRegWithEffect(misc_reg, val); + int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->readMiscRegNoEffect(reg_idx); } MiscReg readMiscRegOperand(const StaticInst *si, int idx) @@ -310,23 +323,25 @@ class BaseSimpleCPU : public BaseCPU return thread->readMiscReg(reg_idx); } - MiscReg readMiscRegOperandWithEffect(const StaticInst *si, int idx) + void setMiscRegOperandNoEffect(const StaticInst *si, int idx, const MiscReg &val) { - int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; - return thread->readMiscRegWithEffect(reg_idx); + int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; + return thread->setMiscRegNoEffect(reg_idx, val); } - void setMiscRegOperand(const StaticInst *si, int idx, const MiscReg &val) + void setMiscRegOperand( + const StaticInst *si, int idx, const MiscReg &val) { int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; return thread->setMiscReg(reg_idx, val); } - void setMiscRegOperandWithEffect( - const StaticInst *si, int idx, const MiscReg &val) - { - int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; - return thread->setMiscRegWithEffect(reg_idx, val); + unsigned readStCondFailures() { + return thread->readStCondFailures(); + } + + void setStCondFailures(unsigned sc_failures) { + thread->setStCondFailures(sc_failures); } #if FULL_SYSTEM diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index dfffb0b1f..45da7c3eb 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -30,6 +30,7 @@ #include "arch/locked_mem.hh" #include "arch/utility.hh" +#include "base/bigint.hh" #include "cpu/exetrace.hh" #include "cpu/simple/timing.hh" #include "mem/packet.hh" @@ -193,7 +194,7 @@ TimingSimpleCPU::switchOut() void TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) { - BaseCPU::takeOverFrom(oldCPU); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); // if any of this CPU's ThreadContexts are active, mark the CPU as // running and schedule its tick event. @@ -208,23 +209,6 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) if (_status != Running) { _status = Idle; } - - Port *peer; - if (icachePort.getPeer() == NULL) { - peer = oldCPU->getPort("icache_port")->getPeer(); - icachePort.setPeer(peer); - } else { - peer = icachePort.getPeer(); - } - peer->setPeer(&icachePort); - - if (dcachePort.getPeer() == NULL) { - peer = oldCPU->getPort("dcache_port")->getPeer(); - dcachePort.setPeer(peer); - } else { - peer = dcachePort.getPeer(); - } - peer->setPeer(&dcachePort); } @@ -239,12 +223,6 @@ TimingSimpleCPU::activateContext(int thread_num, int delay) notIdleFraction++; _status = Running; -#if FULL_SYSTEM - // Connect the ThreadContext's memory ports (Functional/Virtual - // Ports) - tc->connectMemPorts(); -#endif - // kick things off by initiating the fetch of the next instruction fetchEvent = new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false); @@ -286,7 +264,7 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // Now do the access. if (fault == NoFault) { PacketPtr pkt = - new Packet(req, Packet::ReadReq, Packet::Broadcast); + new Packet(req, MemCmd::ReadReq, Packet::Broadcast); pkt->dataDynamic<T>(new T); if (!dcachePort.sendTiming(pkt)) { @@ -297,14 +275,14 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // memory system takes ownership of packet dcache_pkt = NULL; } + + // This will need a new way to tell if it has a dcache attached. + if (req->isUncacheable()) + recordEvent("Uncached Read"); } else { delete req; } - // This will need a new way to tell if it has a dcache attached. - if (req->isUncacheable()) - recordEvent("Uncached Read"); - return fault; } @@ -312,6 +290,14 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) template Fault +TimingSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags); + +template +Fault +TimingSimpleCPU::read(Addr addr, Twin32_t &data, unsigned flags); + +template +Fault TimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags); template @@ -359,13 +345,20 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(), cpu_id, /* thread ID */ 0); + if (traceData) { + traceData->setAddr(req->getVaddr()); + } + // translate to physical address Fault fault = thread->translateDataWriteReq(req); // Now do the access. if (fault == NoFault) { assert(dcache_pkt == NULL); - dcache_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); + if (req->isSwap()) + dcache_pkt = new Packet(req, MemCmd::SwapReq, Packet::Broadcast); + else + dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast); dcache_pkt->allocate(); dcache_pkt->set(data); @@ -374,6 +367,10 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) if (req->isLocked()) { do_access = TheISA::handleLockedWrite(thread, req); } + if (req->isCondSwap()) { + assert(res); + req->setExtraData(*res); + } if (do_access) { if (!dcachePort.sendTiming(dcache_pkt)) { @@ -384,13 +381,13 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) dcache_pkt = NULL; } } + // This will need a new way to tell if it's hooked up to a cache or not. + if (req->isUncacheable()) + recordEvent("Uncached Write"); } else { delete req; } - // This will need a new way to tell if it's hooked up to a cache or not. - if (req->isUncacheable()) - 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. @@ -401,6 +398,16 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) #ifndef DOXYGEN_SHOULD_SKIP_THIS template Fault +TimingSimpleCPU::write(Twin32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +TimingSimpleCPU::write(Twin64_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault TimingSimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); @@ -454,7 +461,7 @@ TimingSimpleCPU::fetch() ifetch_req->setThreadContext(cpu_id, /* thread ID */ 0); Fault fault = setupFetchRequest(ifetch_req); - ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast); + ifetch_pkt = new Packet(ifetch_req, MemCmd::ReadReq, Packet::Broadcast); ifetch_pkt->dataStatic(&inst); if (fault == NoFault) { @@ -629,6 +636,18 @@ TimingSimpleCPU::completeDrain() drainEvent->process(); } +void +TimingSimpleCPU::DcachePort::setPeer(Port *port) +{ + Port::setPeer(port); + +#if FULL_SYSTEM + // Update the ThreadContext's memory ports (Functional/Virtual + // Ports) + cpu->tcBase()->connectMemPorts(); +#endif +} + bool TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) { diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index abcb224bf..ef062d24a 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -144,6 +144,8 @@ class TimingSimpleCPU : public BaseSimpleCPU : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu) { } + virtual void setPeer(Port *port); + protected: virtual bool recvTiming(PacketPtr pkt); |