summaryrefslogtreecommitdiff
path: root/src/cpu/simple
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/simple')
-rw-r--r--src/cpu/simple/SConscript43
-rw-r--r--src/cpu/simple/SConsopts34
-rw-r--r--src/cpu/simple/atomic.cc105
-rw-r--r--src/cpu/simple/atomic.hh18
-rw-r--r--src/cpu/simple/base.cc62
-rw-r--r--src/cpu/simple/base.hh47
-rw-r--r--src/cpu/simple/timing.cc87
-rw-r--r--src/cpu/simple/timing.hh2
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);