#include "arch/mmaped_ipr.hh"
#include "arch/utility.hh"
#include "base/bigint.hh"
+#include "config/the_isa.hh"
#include "cpu/exetrace.hh"
#include "cpu/simple/atomic.hh"
#include "mem/packet.hh"
}
Port *
-AtomicSimpleCPU::getPort(const std::string &if_name, int idx)
+AtomicSimpleCPU::getPort(const string &if_name, int idx)
{
if (if_name == "dcache_port")
return &dcachePort;
{
BaseCPU::init();
#if FULL_SYSTEM
- for (int i = 0; i < threadContexts.size(); ++i) {
+ ThreadID size = threadContexts.size();
+ for (ThreadID i = 0; i < size; ++i) {
ThreadContext *tc = threadContexts[i];
// initialize CPU, including PC
}
AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p)
- : BaseSimpleCPU(p), tickEvent(this), width(p->width),
+ : BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false),
simulate_data_stalls(p->simulate_data_stalls),
simulate_inst_stalls(p->simulate_inst_stalls),
icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this),
AtomicSimpleCPU::~AtomicSimpleCPU()
{
+ if (tickEvent.scheduled()) {
+ deschedule(tickEvent);
+ }
}
void
{
SimObject::State so_state = SimObject::getState();
SERIALIZE_ENUM(so_state);
+ SERIALIZE_SCALAR(locked);
BaseSimpleCPU::serialize(os);
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
{
SimObject::State so_state;
UNSERIALIZE_ENUM(so_state);
+ UNSERIALIZE_SCALAR(locked);
BaseSimpleCPU::unserialize(cp, section);
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
}
// if any of this CPU's ThreadContexts are active, mark the CPU as
// running and schedule its tick event.
- for (int i = 0; i < threadContexts.size(); ++i) {
+ ThreadID size = threadContexts.size();
+ for (ThreadID i = 0; i < size; ++i) {
ThreadContext *tc = threadContexts[i];
if (tc->status() == ThreadContext::Active && _status != Running) {
_status = Running;
assert(thread_num == 0);
assert(thread);
+ if (_status == Idle)
+ return;
+
assert(_status == Running);
// tick event may not be scheduled if this gets called from inside
}
//The block size of our peer.
- int blockSize = dcachePort.peerBlockSize();
+ unsigned blockSize = dcachePort.peerBlockSize();
//The size of the data we're trying to read.
int dataSize = sizeof(T);
req->setVirt(0, addr, dataSize, flags, thread->readPC());
// translate to physical address
- Fault fault = thread->dtb->translateAtomic(req, tc, false);
+ Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read);
// Now do the access.
- if (fault == NoFault) {
+ if (fault == NoFault && !req->getFlags().isSet(Request::NO_ACCESS)) {
Packet pkt = Packet(req,
- req->isLocked() ? MemCmd::LoadLockedReq : MemCmd::ReadReq,
+ req->isLLSC() ? MemCmd::LoadLockedReq : MemCmd::ReadReq,
Packet::Broadcast);
pkt.dataStatic(dataPtr);
assert(!pkt.isError());
- if (req->isLocked()) {
+ if (req->isLLSC()) {
TheISA::handleLockedRead(thread, req);
}
}
recordEvent("Uncached Read");
//If there's a fault, return it
- if (fault != NoFault)
- return fault;
+ if (fault != NoFault) {
+ if (req->isPrefetch()) {
+ return NoFault;
+ } else {
+ return fault;
+ }
+ }
+
//If we don't need to access a second cache line, stop now.
if (secondAddr <= addr)
{
if (traceData) {
traceData->setData(data);
}
+ if (req->isLocked() && fault == NoFault) {
+ assert(!locked);
+ locked = true;
+ }
return fault;
}
}
//The block size of our peer.
- int blockSize = dcachePort.peerBlockSize();
+ unsigned blockSize = dcachePort.peerBlockSize();
//The size of the data we're trying to read.
int dataSize = sizeof(T);
req->setVirt(0, addr, dataSize, flags, thread->readPC());
// translate to physical address
- Fault fault = thread->dtb->translateAtomic(req, tc, true);
+ Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write);
// Now do the access.
if (fault == NoFault) {
MemCmd cmd = MemCmd::WriteReq; // default
bool do_access = true; // flag to suppress cache access
- if (req->isLocked()) {
+ if (req->isLLSC()) {
cmd = MemCmd::StoreCondReq;
do_access = TheISA::handleLockedWrite(thread, req);
} else if (req->isSwap()) {
}
}
- if (do_access) {
+ if (do_access && !req->getFlags().isSet(Request::NO_ACCESS)) {
Packet pkt = Packet(req, cmd, Packet::Broadcast);
pkt.dataStatic(dataPtr);
// calling changeStatus() and changing it to "bad addr write"
// or something.
if (traceData) {
- traceData->setData(data);
+ traceData->setData(gtoh(data));
+ }
+ if (req->isLocked() && fault == NoFault) {
+ assert(locked);
+ locked = false;
+ }
+ if (fault != NoFault && req->isPrefetch()) {
+ return NoFault;
+ } else {
+ return fault;
}
- return fault;
}
/*
Tick latency = 0;
- for (int i = 0; i < width; ++i) {
+ for (int i = 0; i < width || locked; ++i) {
numCycles++;
if (!curStaticInst || !curStaticInst->isDelayedCommit())
bool fromRom = isRomMicroPC(thread->readMicroPC());
if (!fromRom && !curMacroStaticInst) {
setupFetchRequest(&ifetch_req);
- fault = thread->itb->translateAtomic(&ifetch_req, tc);
+ fault = thread->itb->translateAtomic(&ifetch_req, tc,
+ BaseTLB::Execute);
}
if (fault == NoFault) {