Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/o3-merge/newmem
src/cpu/memtest/memtest.cc:
src/cpu/memtest/memtest.hh:
src/cpu/simple/timing.hh:
tests/configs/o3-timing-mp.py:
Hand merge.
--HG--
extra : convert_revision : a58cc439eb5e8f900d175ed8b5a85b6c8723e558
This commit is contained in:
@@ -158,6 +158,7 @@ if 'O3CPU' in env['CPU_MODELS']:
|
||||
o3/scoreboard.cc
|
||||
o3/store_set.cc
|
||||
''')
|
||||
sources += Split('memtest/memtest.cc')
|
||||
if env['USE_CHECKER']:
|
||||
sources += Split('o3/checker_builder.cc')
|
||||
else:
|
||||
|
||||
@@ -140,8 +140,8 @@ class BaseCPU : public MemObject
|
||||
bool functionTrace;
|
||||
Tick functionTraceStart;
|
||||
System *system;
|
||||
#if FULL_SYSTEM
|
||||
int cpu_id;
|
||||
#if FULL_SYSTEM
|
||||
Tick profile;
|
||||
#endif
|
||||
Tick progress_interval;
|
||||
|
||||
@@ -193,7 +193,7 @@ BaseDynInst<Impl>::prefetch(Addr addr, unsigned flags)
|
||||
// note this is a local, not BaseDynInst::fault
|
||||
Fault trans_fault = cpu->translateDataReadReq(req);
|
||||
|
||||
if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) {
|
||||
if (trans_fault == NoFault && !(req->isUncacheable())) {
|
||||
// It's a valid address to cacheable space. Record key MemReq
|
||||
// parameters so we can generate another one just like it for
|
||||
// the timing access without calling translate() again (which
|
||||
|
||||
@@ -175,7 +175,7 @@ CheckerCPU::read(Addr addr, T &data, unsigned flags)
|
||||
|
||||
pkt->dataStatic(&data);
|
||||
|
||||
if (!(memReq->getFlags() & UNCACHEABLE)) {
|
||||
if (!(memReq->isUncacheable())) {
|
||||
// Access memory to see if we have the same data
|
||||
dcachePort->sendFunctional(pkt);
|
||||
} else {
|
||||
@@ -251,9 +251,9 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||
// This is because the LSQ would have to be snooped in the CPU to
|
||||
// verify this data.
|
||||
if (unverifiedReq &&
|
||||
!(unverifiedReq->getFlags() & UNCACHEABLE) &&
|
||||
(!(unverifiedReq->getFlags() & LOCKED) ||
|
||||
((unverifiedReq->getFlags() & LOCKED) &&
|
||||
!(unverifiedReq->isUncacheable()) &&
|
||||
(!(unverifiedReq->isLocked()) ||
|
||||
((unverifiedReq->isLocked()) &&
|
||||
unverifiedReq->getScResult() == 1))) {
|
||||
T inst_data;
|
||||
/*
|
||||
|
||||
@@ -38,16 +38,19 @@
|
||||
|
||||
#include "base/misc.hh"
|
||||
#include "base/statistics.hh"
|
||||
#include "cpu/simple_thread.hh"
|
||||
//#include "cpu/simple_thread.hh"
|
||||
#include "cpu/memtest/memtest.hh"
|
||||
//#include "mem/cache/base_cache.hh"
|
||||
#include "mem/physical.hh"
|
||||
//#include "mem/physical.hh"
|
||||
#include "sim/builder.hh"
|
||||
#include "sim/sim_events.hh"
|
||||
#include "sim/stats.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/request.hh"
|
||||
#include "mem/port.hh"
|
||||
#include "mem/mem_object.hh"
|
||||
|
||||
using namespace std;
|
||||
using namespace TheISA;
|
||||
|
||||
int TESTER_ALLOCATOR=0;
|
||||
|
||||
@@ -68,7 +71,8 @@ MemTest::CpuPort::recvAtomic(Packet *pkt)
|
||||
void
|
||||
MemTest::CpuPort::recvFunctional(Packet *pkt)
|
||||
{
|
||||
memtest->completeRequest(pkt);
|
||||
//Do nothing if we see one come through
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -86,11 +90,10 @@ MemTest::CpuPort::recvRetry()
|
||||
memtest->doRetry();
|
||||
}
|
||||
|
||||
|
||||
MemTest::MemTest(const string &name,
|
||||
// MemInterface *_cache_interface,
|
||||
PhysicalMemory *main_mem,
|
||||
PhysicalMemory *check_mem,
|
||||
// PhysicalMemory *main_mem,
|
||||
// PhysicalMemory *check_mem,
|
||||
unsigned _memorySize,
|
||||
unsigned _percentReads,
|
||||
// unsigned _percentCopies,
|
||||
@@ -102,10 +105,11 @@ MemTest::MemTest(const string &name,
|
||||
Counter _max_loads)
|
||||
: MemObject(name),
|
||||
tickEvent(this),
|
||||
cachePort("dcache", this),
|
||||
cachePort("test", this),
|
||||
funcPort("functional", this),
|
||||
retryPkt(NULL),
|
||||
mainMem(main_mem),
|
||||
checkMem(check_mem),
|
||||
// mainMem(main_mem),
|
||||
// checkMem(check_mem),
|
||||
size(_memorySize),
|
||||
percentReads(_percentReads),
|
||||
// percentCopies(_percentCopies),
|
||||
@@ -119,7 +123,7 @@ MemTest::MemTest(const string &name,
|
||||
vector<string> cmd;
|
||||
cmd.push_back("/bin/ls");
|
||||
vector<string> null_vec;
|
||||
thread = new SimpleThread(NULL, 0, NULL, 0, mainMem);
|
||||
// thread = new SimpleThread(NULL, 0, NULL, 0, mainMem);
|
||||
curTick = 0;
|
||||
|
||||
// Needs to be masked off once we know the block size.
|
||||
@@ -134,16 +138,18 @@ MemTest::MemTest(const string &name,
|
||||
tickEvent.schedule(0);
|
||||
|
||||
id = TESTER_ALLOCATOR++;
|
||||
if (TESTER_ALLOCATOR > 8)
|
||||
panic("False sharing memtester only allows up to 8 testers");
|
||||
|
||||
accessRetry = false;
|
||||
}
|
||||
|
||||
Port *
|
||||
MemTest::getPort(const std::string &if_name, int idx)
|
||||
{
|
||||
// ***** NOTE TO RON: I'm not sure what it should do if these get ports
|
||||
// are called on it.
|
||||
if (if_name == "dcache_port")
|
||||
return &cachePort;
|
||||
else if (if_name == "icache_port")
|
||||
if (if_name == "functional")
|
||||
return &funcPort;
|
||||
else if (if_name == "test")
|
||||
return &cachePort;
|
||||
else
|
||||
panic("No Such Port\n");
|
||||
@@ -157,29 +163,14 @@ MemTest::init()
|
||||
blockAddrMask = blockSize - 1;
|
||||
traceBlockAddr = blockAddr(traceBlockAddr);
|
||||
|
||||
//setup data storage with interesting values
|
||||
uint8_t *data1 = new uint8_t[size];
|
||||
uint8_t *data2 = new uint8_t[size];
|
||||
uint8_t *data3 = new uint8_t[size];
|
||||
memset(data1, 1, size);
|
||||
memset(data2, 2, size);
|
||||
memset(data3, 3, size);
|
||||
|
||||
// set up intial memory contents here
|
||||
// ***** NOTE FOR RON: I'm not sure how to setup initial memory
|
||||
// contents. - Kevin
|
||||
/*
|
||||
mainMem->prot_write(baseAddr1, data1, size);
|
||||
checkMem->prot_write(baseAddr1, data1, size);
|
||||
mainMem->prot_write(baseAddr2, data2, size);
|
||||
checkMem->prot_write(baseAddr2, data2, size);
|
||||
mainMem->prot_write(uncacheAddr, data3, size);
|
||||
checkMem->prot_write(uncacheAddr, data3, size);
|
||||
*/
|
||||
|
||||
delete [] data1;
|
||||
delete [] data2;
|
||||
delete [] data3;
|
||||
cachePort.memsetBlob(baseAddr1, 1, size);
|
||||
funcPort.memsetBlob(baseAddr1, 1, size);
|
||||
cachePort.memsetBlob(baseAddr2, 2, size);
|
||||
funcPort.memsetBlob(baseAddr2, 2, size);
|
||||
cachePort.memsetBlob(uncacheAddr, 3, size);
|
||||
funcPort.memsetBlob(uncacheAddr, 3, size);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -209,7 +200,7 @@ MemTest::completeRequest(Packet *pkt)
|
||||
outstandingAddrs.erase(removeAddr);
|
||||
|
||||
switch (pkt->cmd) {
|
||||
case Packet::ReadReq:
|
||||
case Packet::ReadResp:
|
||||
|
||||
if (memcmp(pkt_data, data, pkt->getSize()) != 0) {
|
||||
cerr << name() << ": on read of 0x" << hex << req->getPaddr()
|
||||
@@ -236,7 +227,7 @@ MemTest::completeRequest(Packet *pkt)
|
||||
exitSimLoop("Maximum number of loads reached!");
|
||||
break;
|
||||
|
||||
case Packet::WriteReq:
|
||||
case Packet::WriteResp:
|
||||
numWritesStat++;
|
||||
break;
|
||||
/*
|
||||
@@ -319,20 +310,14 @@ MemTest::tick()
|
||||
|
||||
//If we aren't doing copies, use id as offset, and do a false sharing
|
||||
//mem tester
|
||||
// ***** NOTE FOR RON: We're not doing copies, but I'm not sure if this
|
||||
// code should be used.
|
||||
/*
|
||||
if (percentCopies == 0) {
|
||||
//We can eliminate the lower bits of the offset, and then use the id
|
||||
//to offset within the blks
|
||||
offset &= ~63; //Not the low order bits
|
||||
offset += id;
|
||||
access_size = 0;
|
||||
}
|
||||
*/
|
||||
//We can eliminate the lower bits of the offset, and then use the id
|
||||
//to offset within the blks
|
||||
offset &= ~63; //Not the low order bits
|
||||
offset += id;
|
||||
access_size = 0;
|
||||
|
||||
Request *req = new Request();
|
||||
uint32_t flags = req->getFlags();
|
||||
uint32_t flags = 0;
|
||||
Addr paddr;
|
||||
|
||||
if (cacheable < percentUncacheable) {
|
||||
@@ -341,11 +326,12 @@ MemTest::tick()
|
||||
} else {
|
||||
paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
|
||||
}
|
||||
// bool probe = (random() % 2 == 1) && !req->isUncacheable();
|
||||
//bool probe = (random() % 2 == 1) && !req->isUncacheable();
|
||||
bool probe = false;
|
||||
|
||||
paddr &= ~((1 << access_size) - 1);
|
||||
req->setPhys(paddr, 1 << access_size, flags);
|
||||
req->setThreadContext(id,0);
|
||||
|
||||
uint8_t *result = new uint8_t[8];
|
||||
|
||||
@@ -359,7 +345,8 @@ MemTest::tick()
|
||||
else outstandingAddrs.insert(paddr);
|
||||
|
||||
// ***** NOTE FOR RON: I'm not sure how to access checkMem. - Kevin
|
||||
// checkMem->access(Read, req->getPaddr(), result, req->size);
|
||||
funcPort.readBlob(req->getPaddr(), result, req->getSize());
|
||||
|
||||
if (blockAddr(paddr) == traceBlockAddr) {
|
||||
cerr << name()
|
||||
<< ": initiating read "
|
||||
@@ -377,10 +364,8 @@ MemTest::tick()
|
||||
pkt->senderState = state;
|
||||
|
||||
if (probe) {
|
||||
// ***** NOTE FOR RON: Send functional access? It used to
|
||||
// be a probeAndUpdate access. - Kevin
|
||||
cachePort.sendFunctional(pkt);
|
||||
// completeRequest(pkt, result);
|
||||
completeRequest(pkt);
|
||||
} else {
|
||||
// req->completionEvent = new MemCompleteEvent(req, result, this);
|
||||
if (!cachePort.sendTiming(pkt)) {
|
||||
@@ -397,8 +382,6 @@ MemTest::tick()
|
||||
if (outstandingAddrs.find(paddr) != outstandingAddrs.end()) return;
|
||||
else outstandingAddrs.insert(paddr);
|
||||
|
||||
// ***** NOTE FOR RON: Not sure how to access memory.
|
||||
// checkMem->access(Write, req->paddr, req->data, req->size);
|
||||
/*
|
||||
if (blockAddr(req->getPaddr()) == traceBlockAddr) {
|
||||
cerr << name() << ": initiating write "
|
||||
@@ -419,9 +402,9 @@ MemTest::tick()
|
||||
MemTestSenderState *state = new MemTestSenderState(result);
|
||||
pkt->senderState = state;
|
||||
|
||||
funcPort.writeBlob(req->getPaddr(), pkt_data, req->getSize());
|
||||
|
||||
if (probe) {
|
||||
// ***** NOTE FOR RON: Send functional access? It used to
|
||||
// be a probe access. - Kevin
|
||||
cachePort.sendFunctional(pkt);
|
||||
// completeRequest(req, NULL);
|
||||
} else {
|
||||
@@ -490,8 +473,8 @@ MemTest::doRetry()
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest)
|
||||
|
||||
// SimObjectParam<BaseCache *> cache;
|
||||
SimObjectParam<PhysicalMemory *> main_mem;
|
||||
SimObjectParam<PhysicalMemory *> check_mem;
|
||||
// SimObjectParam<PhysicalMemory *> main_mem;
|
||||
// SimObjectParam<PhysicalMemory *> check_mem;
|
||||
Param<unsigned> memory_size;
|
||||
Param<unsigned> percent_reads;
|
||||
// Param<unsigned> percent_copies;
|
||||
@@ -508,8 +491,8 @@ END_DECLARE_SIM_OBJECT_PARAMS(MemTest)
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest)
|
||||
|
||||
// INIT_PARAM(cache, "L1 cache"),
|
||||
INIT_PARAM(main_mem, "hierarchical memory"),
|
||||
INIT_PARAM(check_mem, "check memory"),
|
||||
// INIT_PARAM(main_mem, "hierarchical memory"),
|
||||
// INIT_PARAM(check_mem, "check memory"),
|
||||
INIT_PARAM(memory_size, "memory size"),
|
||||
INIT_PARAM(percent_reads, "target read percentage"),
|
||||
// INIT_PARAM(percent_copies, "target copy percentage"),
|
||||
@@ -527,8 +510,8 @@ END_INIT_SIM_OBJECT_PARAMS(MemTest)
|
||||
|
||||
CREATE_SIM_OBJECT(MemTest)
|
||||
{
|
||||
return new MemTest(getInstanceName(), /*cache->getInterface(),*/ main_mem,
|
||||
check_mem, memory_size, percent_reads, /*percent_copies,*/
|
||||
return new MemTest(getInstanceName(), /*cache->getInterface(),*/ /*main_mem,*/
|
||||
/*check_mem,*/ memory_size, percent_reads, /*percent_copies,*/
|
||||
percent_uncacheable, progress_interval,
|
||||
percent_source_unaligned, percent_dest_unaligned,
|
||||
trace_addr, max_loads);
|
||||
|
||||
@@ -41,17 +41,18 @@
|
||||
#include "sim/sim_exit.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/stats.hh"
|
||||
#include "mem/mem_object.hh"
|
||||
#include "mem/port.hh"
|
||||
|
||||
class PhysicalMemory;
|
||||
class ThreadContext;
|
||||
class Packet;
|
||||
class MemTest : public MemObject
|
||||
{
|
||||
public:
|
||||
|
||||
MemTest(const std::string &name,
|
||||
// MemInterface *_cache_interface,
|
||||
PhysicalMemory *main_mem,
|
||||
PhysicalMemory *check_mem,
|
||||
// PhysicalMemory *main_mem,
|
||||
// PhysicalMemory *check_mem,
|
||||
unsigned _memorySize,
|
||||
unsigned _percentReads,
|
||||
// unsigned _percentCopies,
|
||||
@@ -112,10 +113,11 @@ class MemTest : public MemObject
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
AddrRangeList &snoop)
|
||||
{ resp.clear(); snoop.clear(); }
|
||||
{ resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
|
||||
};
|
||||
|
||||
CpuPort cachePort;
|
||||
CpuPort funcPort;
|
||||
|
||||
class MemTestSenderState : public Packet::SenderState
|
||||
{
|
||||
@@ -132,9 +134,9 @@ class MemTest : public MemObject
|
||||
// Request *dataReq;
|
||||
Packet *retryPkt;
|
||||
// MemInterface *cacheInterface;
|
||||
PhysicalMemory *mainMem;
|
||||
PhysicalMemory *checkMem;
|
||||
SimpleThread *thread;
|
||||
// PhysicalMemory *mainMem;
|
||||
// PhysicalMemory *checkMem;
|
||||
// SimpleThread *thread;
|
||||
|
||||
bool accessRetry;
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ class DefaultFetch
|
||||
/** Returns the address ranges of this device. */
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
AddrRangeList &snoop)
|
||||
{ resp.clear(); snoop.clear(); }
|
||||
{ resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
|
||||
|
||||
/** Timing version of receive. Handles setting fetch to the
|
||||
* proper status to start fetching. */
|
||||
|
||||
@@ -63,7 +63,7 @@ template<class Impl>
|
||||
void
|
||||
DefaultFetch<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
panic("DefaultFetch doesn't expect recvFunctional callback!");
|
||||
warn("Default fetch doesn't update it's state from a functional call.");
|
||||
}
|
||||
|
||||
template<class Impl>
|
||||
@@ -599,7 +599,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
|
||||
if (fault == NoFault) {
|
||||
#if 0
|
||||
if (cpu->system->memctrl->badaddr(memReq[tid]->paddr) ||
|
||||
memReq[tid]->flags & UNCACHEABLE) {
|
||||
memReq[tid]->isUncacheable()) {
|
||||
DPRINTF(Fetch, "Fetch: Bad address %#x (hopefully on a "
|
||||
"misspeculating path)!",
|
||||
memReq[tid]->paddr);
|
||||
|
||||
@@ -311,7 +311,7 @@ class LSQ {
|
||||
/** Returns the address ranges of this device. */
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
AddrRangeList &snoop)
|
||||
{ resp.clear(); snoop.clear(); }
|
||||
{ resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
|
||||
|
||||
/** Timing version of receive. Handles writing back and
|
||||
* completing the load or store that has returned from
|
||||
|
||||
@@ -46,7 +46,7 @@ template <class Impl>
|
||||
void
|
||||
LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
panic("O3CPU doesn't expect recvFunctional callback!");
|
||||
warn("O3CPU doesn't update things on a recvFunctional.");
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
|
||||
@@ -492,7 +492,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||
// A bit of a hackish way to get uncached accesses to work only if they're
|
||||
// at the head of the LSQ and are ready to commit (at the head of the ROB
|
||||
// too).
|
||||
if (req->getFlags() & UNCACHEABLE &&
|
||||
if (req->isUncacheable() &&
|
||||
(load_idx != loadHead || !load_inst->isAtCommit())) {
|
||||
iewStage->rescheduleMemInst(load_inst);
|
||||
++lsqRescheduledLoads;
|
||||
@@ -509,7 +509,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||
load_idx, store_idx, storeHead, req->getPaddr());
|
||||
|
||||
#if FULL_SYSTEM
|
||||
if (req->getFlags() & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
cpu->lockAddr = req->getPaddr();
|
||||
cpu->lockFlag = true;
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
|
||||
// realizes there is activity.
|
||||
// Mark it as executed unless it is an uncached load that
|
||||
// needs to hit the head of commit.
|
||||
if (!(inst->req->getFlags() & UNCACHEABLE) || inst->isAtCommit()) {
|
||||
if (!(inst->req->isUncacheable()) || inst->isAtCommit()) {
|
||||
inst->setExecuted();
|
||||
}
|
||||
iewStage->instToCommit(inst);
|
||||
@@ -613,8 +613,8 @@ LSQUnit<Impl>::writebackStores()
|
||||
inst->seqNum);
|
||||
|
||||
// @todo: Remove this SC hack once the memory system handles it.
|
||||
if (req->getFlags() & LOCKED) {
|
||||
if (req->getFlags() & UNCACHEABLE) {
|
||||
if (req->isLocked()) {
|
||||
if (req->isUncacheable()) {
|
||||
req->setScResult(2);
|
||||
} else {
|
||||
if (cpu->lockFlag) {
|
||||
|
||||
@@ -493,7 +493,7 @@ BackEnd<Impl>::read(RequestPtr req, T &data, int load_idx)
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
|
||||
if (!dcacheInterface && (memReq->isUncacheable()))
|
||||
recordEvent("Uncached Read");
|
||||
*/
|
||||
return LSQ.read(req, data, load_idx);
|
||||
@@ -534,7 +534,7 @@ BackEnd<Impl>::write(RequestPtr req, T &data, int store_idx)
|
||||
*res = memReq->result;
|
||||
*/
|
||||
/*
|
||||
if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
|
||||
if (!dcacheInterface && (memReq->isUncacheable()))
|
||||
recordEvent("Uncached Write");
|
||||
*/
|
||||
return LSQ.write(req, data, store_idx);
|
||||
|
||||
@@ -1256,7 +1256,7 @@ BackEnd<Impl>::executeInsts()
|
||||
|
||||
// ++iewExecStoreInsts;
|
||||
|
||||
if (!(inst->req->flags & LOCKED)) {
|
||||
if (!(inst->req->isLocked())) {
|
||||
inst->setExecuted();
|
||||
|
||||
instToCommit(inst);
|
||||
|
||||
@@ -455,12 +455,12 @@ class OzoneCPU : public BaseCPU
|
||||
{
|
||||
#if 0
|
||||
#if FULL_SYSTEM && defined(TARGET_ALPHA)
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
|
||||
req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
|
||||
}
|
||||
#endif
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
lockAddrList.insert(req->paddr);
|
||||
lockFlag = true;
|
||||
}
|
||||
@@ -489,10 +489,10 @@ class OzoneCPU : public BaseCPU
|
||||
ExecContext *xc;
|
||||
|
||||
// If this is a store conditional, act appropriately
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
xc = req->xc;
|
||||
|
||||
if (req->flags & UNCACHEABLE) {
|
||||
if (req->isUncacheable()) {
|
||||
// Don't update result register (see stq_c in isa_desc)
|
||||
req->result = 2;
|
||||
xc->setStCondFailures(0);//Needed? [RGD]
|
||||
@@ -532,8 +532,8 @@ class OzoneCPU : public BaseCPU
|
||||
|
||||
#endif
|
||||
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->flags & UNCACHEABLE) {
|
||||
if (req->isLocked()) {
|
||||
if (req->isUncacheable()) {
|
||||
req->result = 2;
|
||||
} else {
|
||||
if (this->lockFlag) {
|
||||
|
||||
@@ -92,7 +92,7 @@ class FrontEnd
|
||||
/** Returns the address ranges of this device. */
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
AddrRangeList &snoop)
|
||||
{ resp.clear(); snoop.clear(); }
|
||||
{ resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
|
||||
|
||||
/** Timing version of receive. Handles setting fetch to the
|
||||
* proper status to start fetching. */
|
||||
|
||||
@@ -59,7 +59,7 @@ template<class Impl>
|
||||
void
|
||||
FrontEnd<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
panic("FrontEnd doesn't expect recvFunctional callback!");
|
||||
warn("FrontEnd doesn't update state from functional calls");
|
||||
}
|
||||
|
||||
template<class Impl>
|
||||
@@ -493,7 +493,7 @@ FrontEnd<Impl>::fetchCacheLine()
|
||||
if (fault == NoFault) {
|
||||
#if 0
|
||||
if (cpu->system->memctrl->badaddr(memReq->paddr) ||
|
||||
memReq->flags & UNCACHEABLE) {
|
||||
memReq->isUncacheable()) {
|
||||
DPRINTF(FE, "Fetch: Bad address %#x (hopefully on a "
|
||||
"misspeculating path!",
|
||||
memReq->paddr);
|
||||
|
||||
@@ -231,7 +231,7 @@ InorderBackEnd<Impl>::read(Addr addr, T &data, unsigned flags)
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
|
||||
if (!dcacheInterface && (memReq->isUncacheable()))
|
||||
recordEvent("Uncached Read");
|
||||
*/
|
||||
return fault;
|
||||
@@ -243,7 +243,7 @@ Fault
|
||||
InorderBackEnd<Impl>::read(MemReqPtr &req, T &data)
|
||||
{
|
||||
#if FULL_SYSTEM && defined(TARGET_ALPHA)
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
|
||||
req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
|
||||
}
|
||||
@@ -291,7 +291,7 @@ InorderBackEnd<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||
if (res && (fault == NoFault))
|
||||
*res = memReq->result;
|
||||
/*
|
||||
if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
|
||||
if (!dcacheInterface && (memReq->isUncacheable()))
|
||||
recordEvent("Uncached Write");
|
||||
*/
|
||||
return fault;
|
||||
@@ -306,10 +306,10 @@ InorderBackEnd<Impl>::write(MemReqPtr &req, T &data)
|
||||
ExecContext *xc;
|
||||
|
||||
// If this is a store conditional, act appropriately
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
xc = req->xc;
|
||||
|
||||
if (req->flags & UNCACHEABLE) {
|
||||
if (req->isUncacheable()) {
|
||||
// Don't update result register (see stq_c in isa_desc)
|
||||
req->result = 2;
|
||||
xc->setStCondFailures(0);//Needed? [RGD]
|
||||
@@ -391,7 +391,7 @@ InorderBackEnd<Impl>::read(MemReqPtr &req, T &data, int load_idx)
|
||||
}
|
||||
|
||||
/*
|
||||
if (!dcacheInterface && (req->flags & UNCACHEABLE))
|
||||
if (!dcacheInterface && (req->isUncacheable()))
|
||||
recordEvent("Uncached Read");
|
||||
*/
|
||||
return NoFault;
|
||||
@@ -455,8 +455,8 @@ InorderBackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx)
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->flags & UNCACHEABLE) {
|
||||
if (req->isLocked()) {
|
||||
if (req->isUncacheable()) {
|
||||
// Don't update result register (see stq_c in isa_desc)
|
||||
req->result = 2;
|
||||
} else {
|
||||
@@ -469,7 +469,7 @@ InorderBackEnd<Impl>::write(MemReqPtr &req, T &data, int store_idx)
|
||||
*res = req->result;
|
||||
*/
|
||||
/*
|
||||
if (!dcacheInterface && (req->flags & UNCACHEABLE))
|
||||
if (!dcacheInterface && (req->isUncacheable()))
|
||||
recordEvent("Uncached Write");
|
||||
*/
|
||||
return NoFault;
|
||||
|
||||
@@ -426,7 +426,7 @@ OzoneLSQ<Impl>::read(MemReqPtr &req, T &data, int load_idx)
|
||||
// at the head of the LSQ and are ready to commit (at the head of the ROB
|
||||
// too).
|
||||
// @todo: Fix uncached accesses.
|
||||
if (req->flags & UNCACHEABLE &&
|
||||
if (req->isUncacheable() &&
|
||||
(load_idx != loadHead || !loadQueue[load_idx]->readyToCommit())) {
|
||||
|
||||
return TheISA::genMachineCheckFault();
|
||||
|
||||
@@ -577,7 +577,7 @@ OzoneLSQ<Impl>::writebackStores()
|
||||
MemAccessResult result = dcacheInterface->access(req);
|
||||
|
||||
//@todo temp fix for LL/SC (works fine for 1 CPU)
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
req->result=1;
|
||||
panic("LL/SC! oh no no support!!!");
|
||||
}
|
||||
@@ -596,7 +596,7 @@ OzoneLSQ<Impl>::writebackStores()
|
||||
Event *wb = NULL;
|
||||
/*
|
||||
typename IEW::LdWritebackEvent *wb = NULL;
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
// Stx_C does not generate a system port transaction.
|
||||
req->result=0;
|
||||
wb = new typename IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst,
|
||||
@@ -630,7 +630,7 @@ OzoneLSQ<Impl>::writebackStores()
|
||||
// DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
|
||||
// storeQueue[storeWBIdx].inst->seqNum);
|
||||
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
// Stx_C does not generate a system port transaction.
|
||||
req->result=1;
|
||||
typename BackEnd::LdWritebackEvent *wb =
|
||||
|
||||
@@ -260,7 +260,7 @@ class OzoneLWLSQ {
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
AddrRangeList &snoop)
|
||||
{ resp.clear(); snoop.clear(); }
|
||||
{ resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1); }
|
||||
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
|
||||
@@ -507,7 +507,7 @@ OzoneLWLSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
|
||||
// at the head of the LSQ and are ready to commit (at the head of the ROB
|
||||
// too).
|
||||
// @todo: Fix uncached accesses.
|
||||
if (req->getFlags() & UNCACHEABLE &&
|
||||
if (req->isUncacheable() &&
|
||||
(inst != loadQueue.back() || !inst->isAtCommit())) {
|
||||
DPRINTF(OzoneLSQ, "[sn:%lli] Uncached load and not head of "
|
||||
"commit/LSQ!\n",
|
||||
@@ -659,7 +659,7 @@ OzoneLWLSQ<Impl>::read(RequestPtr req, T &data, int load_idx)
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
if (req->getFlags() & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
cpu->lockFlag = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ template <class Impl>
|
||||
void
|
||||
OzoneLWLSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
panic("O3CPU doesn't expect recvFunctional callback!");
|
||||
warn("O3CPU doesn't update things on a recvFunctional");
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
@@ -394,7 +394,7 @@ OzoneLWLSQ<Impl>::executeLoad(DynInstPtr &inst)
|
||||
// Actually probably want the oldest faulting load
|
||||
if (load_fault != NoFault) {
|
||||
DPRINTF(OzoneLSQ, "Load [sn:%lli] has a fault\n", inst->seqNum);
|
||||
if (!(inst->req->getFlags() & UNCACHEABLE && !inst->isAtCommit())) {
|
||||
if (!(inst->req->isUncacheable() && !inst->isAtCommit())) {
|
||||
inst->setExecuted();
|
||||
}
|
||||
// Maybe just set it as can commit here, although that might cause
|
||||
@@ -605,8 +605,8 @@ OzoneLWLSQ<Impl>::writebackStores()
|
||||
inst->seqNum);
|
||||
|
||||
// @todo: Remove this SC hack once the memory system handles it.
|
||||
if (req->getFlags() & LOCKED) {
|
||||
if (req->getFlags() & UNCACHEABLE) {
|
||||
if (req->isLocked()) {
|
||||
if (req->isUncacheable()) {
|
||||
req->setScResult(2);
|
||||
} else {
|
||||
if (cpu->lockFlag) {
|
||||
@@ -663,7 +663,7 @@ OzoneLWLSQ<Impl>::writebackStores()
|
||||
if (result != MA_HIT && dcacheInterface->doEvents()) {
|
||||
store_event->miss = true;
|
||||
typename BackEnd::LdWritebackEvent *wb = NULL;
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
wb = new typename BackEnd::LdWritebackEvent(inst,
|
||||
be);
|
||||
store_event->wbEvent = wb;
|
||||
@@ -690,7 +690,7 @@ OzoneLWLSQ<Impl>::writebackStores()
|
||||
// DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n",
|
||||
// inst->seqNum);
|
||||
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
// Stx_C does not generate a system port
|
||||
// transaction in the 21264, but that might be
|
||||
// hard to accomplish in this model.
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
* Authors: Steve Reinhardt
|
||||
*/
|
||||
|
||||
#include "arch/locked_mem.hh"
|
||||
#include "arch/utility.hh"
|
||||
#include "cpu/exetrace.hh"
|
||||
#include "cpu/simple/atomic.hh"
|
||||
@@ -93,7 +94,7 @@ AtomicSimpleCPU::init()
|
||||
bool
|
||||
AtomicSimpleCPU::CpuPort::recvTiming(Packet *pkt)
|
||||
{
|
||||
panic("AtomicSimpleCPU doesn't expect recvAtomic callback!");
|
||||
panic("AtomicSimpleCPU doesn't expect recvTiming callback!");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -107,7 +108,8 @@ AtomicSimpleCPU::CpuPort::recvAtomic(Packet *pkt)
|
||||
void
|
||||
AtomicSimpleCPU::CpuPort::recvFunctional(Packet *pkt)
|
||||
{
|
||||
panic("AtomicSimpleCPU doesn't expect recvFunctional callback!");
|
||||
//No internal storage to update, just return
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -133,20 +135,19 @@ AtomicSimpleCPU::AtomicSimpleCPU(Params *p)
|
||||
{
|
||||
_status = Idle;
|
||||
|
||||
// @todo fix me and get the real cpu id & thread number!!!
|
||||
ifetch_req = new Request();
|
||||
ifetch_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
|
||||
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->dataStatic(&inst);
|
||||
|
||||
data_read_req = new Request();
|
||||
data_read_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
|
||||
data_read_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
|
||||
data_read_pkt = new Packet(data_read_req, Packet::ReadReq,
|
||||
Packet::Broadcast);
|
||||
data_read_pkt->dataStatic(&dataReg);
|
||||
|
||||
data_write_req = new Request();
|
||||
data_write_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
|
||||
data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
|
||||
data_write_pkt = new Packet(data_write_req, Packet::WriteReq,
|
||||
Packet::Broadcast);
|
||||
}
|
||||
@@ -161,6 +162,8 @@ AtomicSimpleCPU::serialize(ostream &os)
|
||||
{
|
||||
SimObject::State so_state = SimObject::getState();
|
||||
SERIALIZE_ENUM(so_state);
|
||||
Status _status = status();
|
||||
SERIALIZE_ENUM(_status);
|
||||
BaseSimpleCPU::serialize(os);
|
||||
nameOut(os, csprintf("%s.tickEvent", name()));
|
||||
tickEvent.serialize(os);
|
||||
@@ -171,6 +174,7 @@ AtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion)
|
||||
{
|
||||
SimObject::State so_state;
|
||||
UNSERIALIZE_ENUM(so_state);
|
||||
UNSERIALIZE_ENUM(_status);
|
||||
BaseSimpleCPU::unserialize(cp, section);
|
||||
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
|
||||
}
|
||||
@@ -253,29 +257,36 @@ template <class T>
|
||||
Fault
|
||||
AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||
{
|
||||
data_read_req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
|
||||
// use the CPU's statically allocated read request and packet objects
|
||||
Request *req = data_read_req;
|
||||
Packet *pkt = data_read_pkt;
|
||||
|
||||
req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
|
||||
|
||||
if (traceData) {
|
||||
traceData->setAddr(addr);
|
||||
}
|
||||
|
||||
// translate to physical address
|
||||
Fault fault = thread->translateDataReadReq(data_read_req);
|
||||
Fault fault = thread->translateDataReadReq(req);
|
||||
|
||||
// Now do the access.
|
||||
if (fault == NoFault) {
|
||||
data_read_pkt->reinitFromRequest();
|
||||
pkt->reinitFromRequest();
|
||||
|
||||
dcache_latency = dcachePort.sendAtomic(data_read_pkt);
|
||||
dcache_latency = dcachePort.sendAtomic(pkt);
|
||||
dcache_access = true;
|
||||
|
||||
assert(data_read_pkt->result == Packet::Success);
|
||||
data = data_read_pkt->get<T>();
|
||||
assert(pkt->result == Packet::Success);
|
||||
data = pkt->get<T>();
|
||||
|
||||
if (req->isLocked()) {
|
||||
TheISA::handleLockedRead(thread, req);
|
||||
}
|
||||
}
|
||||
|
||||
// This will need a new way to tell if it has a dcache attached.
|
||||
if (data_read_req->getFlags() & UNCACHEABLE)
|
||||
if (req->isUncacheable())
|
||||
recordEvent("Uncached Read");
|
||||
|
||||
return fault;
|
||||
@@ -328,33 +339,52 @@ template <class T>
|
||||
Fault
|
||||
AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||
{
|
||||
data_write_req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
|
||||
// use the CPU's statically allocated write request and packet objects
|
||||
Request *req = data_write_req;
|
||||
Packet *pkt = data_write_pkt;
|
||||
|
||||
req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
|
||||
|
||||
if (traceData) {
|
||||
traceData->setAddr(addr);
|
||||
}
|
||||
|
||||
// translate to physical address
|
||||
Fault fault = thread->translateDataWriteReq(data_write_req);
|
||||
Fault fault = thread->translateDataWriteReq(req);
|
||||
|
||||
// Now do the access.
|
||||
if (fault == NoFault) {
|
||||
data = htog(data);
|
||||
data_write_pkt->reinitFromRequest();
|
||||
data_write_pkt->dataStatic(&data);
|
||||
bool do_access = true; // flag to suppress cache access
|
||||
|
||||
dcache_latency = dcachePort.sendAtomic(data_write_pkt);
|
||||
dcache_access = true;
|
||||
if (req->isLocked()) {
|
||||
do_access = TheISA::handleLockedWrite(thread, req);
|
||||
}
|
||||
|
||||
assert(data_write_pkt->result == Packet::Success);
|
||||
if (do_access) {
|
||||
data = htog(data);
|
||||
pkt->reinitFromRequest();
|
||||
pkt->dataStatic(&data);
|
||||
|
||||
if (res && data_write_req->getFlags() & LOCKED) {
|
||||
*res = data_write_req->getScResult();
|
||||
dcache_latency = dcachePort.sendAtomic(pkt);
|
||||
dcache_access = true;
|
||||
|
||||
assert(pkt->result == Packet::Success);
|
||||
}
|
||||
|
||||
if (req->isLocked()) {
|
||||
uint64_t scResult = req->getScResult();
|
||||
if (scResult != 0) {
|
||||
// clear failure counter
|
||||
thread->setStCondFailures(0);
|
||||
}
|
||||
if (res) {
|
||||
*res = req->getScResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This will need a new way to tell if it's hooked up to a cache or not.
|
||||
if (data_write_req->getFlags() & UNCACHEABLE)
|
||||
if (req->isUncacheable())
|
||||
recordEvent("Uncached Write");
|
||||
|
||||
// If the write needs to have a fault on the access, consider calling
|
||||
@@ -467,11 +497,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
|
||||
Param<Tick> progress_interval;
|
||||
SimObjectParam<MemObject *> mem;
|
||||
SimObjectParam<System *> system;
|
||||
Param<int> cpu_id;
|
||||
|
||||
#if FULL_SYSTEM
|
||||
SimObjectParam<AlphaITB *> itb;
|
||||
SimObjectParam<AlphaDTB *> dtb;
|
||||
Param<int> cpu_id;
|
||||
Param<Tick> profile;
|
||||
#else
|
||||
SimObjectParam<Process *> workload;
|
||||
@@ -500,11 +530,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
|
||||
INIT_PARAM(progress_interval, "Progress interval"),
|
||||
INIT_PARAM(mem, "memory"),
|
||||
INIT_PARAM(system, "system object"),
|
||||
INIT_PARAM(cpu_id, "processor ID"),
|
||||
|
||||
#if FULL_SYSTEM
|
||||
INIT_PARAM(itb, "Instruction TLB"),
|
||||
INIT_PARAM(dtb, "Data TLB"),
|
||||
INIT_PARAM(cpu_id, "processor ID"),
|
||||
INIT_PARAM(profile, ""),
|
||||
#else
|
||||
INIT_PARAM(workload, "processes to run"),
|
||||
@@ -538,11 +568,11 @@ CREATE_SIM_OBJECT(AtomicSimpleCPU)
|
||||
params->simulate_stalls = simulate_stalls;
|
||||
params->mem = mem;
|
||||
params->system = system;
|
||||
params->cpu_id = cpu_id;
|
||||
|
||||
#if FULL_SYSTEM
|
||||
params->itb = itb;
|
||||
params->dtb = dtb;
|
||||
params->cpu_id = cpu_id;
|
||||
params->profile = profile;
|
||||
#else
|
||||
params->process = workload;
|
||||
|
||||
@@ -104,9 +104,9 @@ class AtomicSimpleCPU : public BaseSimpleCPU
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
AddrRangeList &snoop)
|
||||
{ resp.clear(); snoop.clear(); }
|
||||
};
|
||||
{ resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
|
||||
|
||||
};
|
||||
CpuPort icachePort;
|
||||
CpuPort dcachePort;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
* Authors: Steve Reinhardt
|
||||
*/
|
||||
|
||||
#include "arch/locked_mem.hh"
|
||||
#include "arch/utility.hh"
|
||||
#include "cpu/exetrace.hh"
|
||||
#include "cpu/simple/timing.hh"
|
||||
@@ -73,7 +74,8 @@ TimingSimpleCPU::CpuPort::recvAtomic(Packet *pkt)
|
||||
void
|
||||
TimingSimpleCPU::CpuPort::recvFunctional(Packet *pkt)
|
||||
{
|
||||
panic("TimingSimpleCPU doesn't expect recvFunctional callback!");
|
||||
//No internal storage to update, jusst return
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -94,7 +96,8 @@ TimingSimpleCPU::CpuPort::TickEvent::schedule(Packet *_pkt, Tick t)
|
||||
}
|
||||
|
||||
TimingSimpleCPU::TimingSimpleCPU(Params *p)
|
||||
: BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock)
|
||||
: BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock),
|
||||
cpu_id(p->cpu_id)
|
||||
{
|
||||
_status = Idle;
|
||||
ifetch_pkt = dcache_pkt = NULL;
|
||||
@@ -251,35 +254,35 @@ template <class T>
|
||||
Fault
|
||||
TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||
{
|
||||
// need to fill in CPU & thread IDs here
|
||||
Request *data_read_req = new Request();
|
||||
data_read_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
|
||||
data_read_req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
|
||||
Request *req =
|
||||
new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
|
||||
cpu_id, /* thread ID */ 0);
|
||||
|
||||
if (traceData) {
|
||||
traceData->setAddr(data_read_req->getVaddr());
|
||||
traceData->setAddr(req->getVaddr());
|
||||
}
|
||||
|
||||
// translate to physical address
|
||||
Fault fault = thread->translateDataReadReq(data_read_req);
|
||||
Fault fault = thread->translateDataReadReq(req);
|
||||
|
||||
// Now do the access.
|
||||
if (fault == NoFault) {
|
||||
Packet *data_read_pkt =
|
||||
new Packet(data_read_req, Packet::ReadReq, Packet::Broadcast);
|
||||
data_read_pkt->dataDynamic<T>(new T);
|
||||
Packet *pkt =
|
||||
new Packet(req, Packet::ReadReq, Packet::Broadcast);
|
||||
pkt->dataDynamic<T>(new T);
|
||||
|
||||
if (!dcachePort.sendTiming(data_read_pkt)) {
|
||||
if (!dcachePort.sendTiming(pkt)) {
|
||||
_status = DcacheRetry;
|
||||
dcache_pkt = data_read_pkt;
|
||||
dcache_pkt = pkt;
|
||||
} else {
|
||||
_status = DcacheWaitResponse;
|
||||
// memory system takes ownership of packet
|
||||
dcache_pkt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// This will need a new way to tell if it has a dcache attached.
|
||||
if (data_read_req->getFlags() & UNCACHEABLE)
|
||||
if (req->isUncacheable())
|
||||
recordEvent("Uncached Read");
|
||||
|
||||
return fault;
|
||||
@@ -332,31 +335,39 @@ template <class T>
|
||||
Fault
|
||||
TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||
{
|
||||
// need to fill in CPU & thread IDs here
|
||||
Request *data_write_req = new Request();
|
||||
data_write_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
|
||||
data_write_req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
|
||||
Request *req =
|
||||
new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
|
||||
cpu_id, /* thread ID */ 0);
|
||||
|
||||
// translate to physical address
|
||||
Fault fault = thread->translateDataWriteReq(data_write_req);
|
||||
Fault fault = thread->translateDataWriteReq(req);
|
||||
|
||||
// Now do the access.
|
||||
if (fault == NoFault) {
|
||||
Packet *data_write_pkt =
|
||||
new Packet(data_write_req, Packet::WriteReq, Packet::Broadcast);
|
||||
data_write_pkt->allocate();
|
||||
data_write_pkt->set(data);
|
||||
assert(dcache_pkt == NULL);
|
||||
dcache_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast);
|
||||
dcache_pkt->allocate();
|
||||
dcache_pkt->set(data);
|
||||
|
||||
if (!dcachePort.sendTiming(data_write_pkt)) {
|
||||
_status = DcacheRetry;
|
||||
dcache_pkt = data_write_pkt;
|
||||
} else {
|
||||
_status = DcacheWaitResponse;
|
||||
dcache_pkt = NULL;
|
||||
bool do_access = true; // flag to suppress cache access
|
||||
|
||||
if (req->isLocked()) {
|
||||
do_access = TheISA::handleLockedWrite(thread, req);
|
||||
}
|
||||
|
||||
if (do_access) {
|
||||
if (!dcachePort.sendTiming(dcache_pkt)) {
|
||||
_status = DcacheRetry;
|
||||
} else {
|
||||
_status = DcacheWaitResponse;
|
||||
// memory system takes ownership of packet
|
||||
dcache_pkt = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This will need a new way to tell if it's hooked up to a cache or not.
|
||||
if (data_write_req->getFlags() & UNCACHEABLE)
|
||||
if (req->isUncacheable())
|
||||
recordEvent("Uncached Write");
|
||||
|
||||
// If the write needs to have a fault on the access, consider calling
|
||||
@@ -416,9 +427,8 @@ TimingSimpleCPU::fetch()
|
||||
{
|
||||
checkForInterrupts();
|
||||
|
||||
// need to fill in CPU & thread IDs here
|
||||
Request *ifetch_req = new Request();
|
||||
ifetch_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
|
||||
ifetch_req->setThreadContext(cpu_id, /* thread ID */ 0);
|
||||
Fault fault = setupFetchRequest(ifetch_req);
|
||||
|
||||
ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
|
||||
@@ -483,12 +493,20 @@ TimingSimpleCPU::completeIfetch(Packet *pkt)
|
||||
if (curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) {
|
||||
// load or store: just send to dcache
|
||||
Fault fault = curStaticInst->initiateAcc(this, traceData);
|
||||
if (fault == NoFault) {
|
||||
// successfully initiated access: instruction will
|
||||
// complete in dcache response callback
|
||||
assert(_status == DcacheWaitResponse);
|
||||
if (_status != Running) {
|
||||
// instruction will complete in dcache response callback
|
||||
assert(_status == DcacheWaitResponse || _status == DcacheRetry);
|
||||
assert(fault == NoFault);
|
||||
} else {
|
||||
// fault: complete now to invoke fault handler
|
||||
if (fault == NoFault) {
|
||||
// early fail on store conditional: complete now
|
||||
assert(dcache_pkt != NULL);
|
||||
fault = curStaticInst->completeAcc(dcache_pkt, this,
|
||||
traceData);
|
||||
delete dcache_pkt->req;
|
||||
delete dcache_pkt;
|
||||
dcache_pkt = NULL;
|
||||
}
|
||||
postExecute();
|
||||
advanceInst(fault);
|
||||
}
|
||||
@@ -509,8 +527,7 @@ TimingSimpleCPU::IcachePort::ITickEvent::process()
|
||||
bool
|
||||
TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt)
|
||||
{
|
||||
// These next few lines could be replaced with something faster
|
||||
// who knows what though
|
||||
// delay processing of returned data until next CPU clock edge
|
||||
Tick time = pkt->req->getTime();
|
||||
while (time < curTick)
|
||||
time += lat;
|
||||
@@ -551,6 +568,10 @@ TimingSimpleCPU::completeDataAccess(Packet *pkt)
|
||||
|
||||
Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
|
||||
|
||||
if (pkt->isRead() && pkt->req->isLocked()) {
|
||||
TheISA::handleLockedRead(thread, pkt->req);
|
||||
}
|
||||
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
||||
@@ -578,6 +599,7 @@ TimingSimpleCPU::completeDrain()
|
||||
bool
|
||||
TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt)
|
||||
{
|
||||
// delay processing of returned data until next CPU clock edge
|
||||
Tick time = pkt->req->getTime();
|
||||
while (time < curTick)
|
||||
time += lat;
|
||||
@@ -606,6 +628,7 @@ TimingSimpleCPU::DcachePort::recvRetry()
|
||||
Packet *tmp = cpu->dcache_pkt;
|
||||
if (sendTiming(tmp)) {
|
||||
cpu->_status = DcacheWaitResponse;
|
||||
// memory system takes ownership of packet
|
||||
cpu->dcache_pkt = NULL;
|
||||
}
|
||||
}
|
||||
@@ -624,11 +647,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU)
|
||||
Param<Tick> progress_interval;
|
||||
SimObjectParam<MemObject *> mem;
|
||||
SimObjectParam<System *> system;
|
||||
Param<int> cpu_id;
|
||||
|
||||
#if FULL_SYSTEM
|
||||
SimObjectParam<AlphaITB *> itb;
|
||||
SimObjectParam<AlphaDTB *> dtb;
|
||||
Param<int> cpu_id;
|
||||
Param<Tick> profile;
|
||||
#else
|
||||
SimObjectParam<Process *> workload;
|
||||
@@ -657,11 +680,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU)
|
||||
INIT_PARAM(progress_interval, "Progress interval"),
|
||||
INIT_PARAM(mem, "memory"),
|
||||
INIT_PARAM(system, "system object"),
|
||||
INIT_PARAM(cpu_id, "processor ID"),
|
||||
|
||||
#if FULL_SYSTEM
|
||||
INIT_PARAM(itb, "Instruction TLB"),
|
||||
INIT_PARAM(dtb, "Data TLB"),
|
||||
INIT_PARAM(cpu_id, "processor ID"),
|
||||
INIT_PARAM(profile, ""),
|
||||
#else
|
||||
INIT_PARAM(workload, "processes to run"),
|
||||
@@ -693,11 +716,11 @@ CREATE_SIM_OBJECT(TimingSimpleCPU)
|
||||
params->functionTraceStart = function_trace_start;
|
||||
params->mem = mem;
|
||||
params->system = system;
|
||||
params->cpu_id = cpu_id;
|
||||
|
||||
#if FULL_SYSTEM
|
||||
params->itb = itb;
|
||||
params->dtb = dtb;
|
||||
params->cpu_id = cpu_id;
|
||||
params->profile = profile;
|
||||
#else
|
||||
params->process = workload;
|
||||
|
||||
@@ -92,7 +92,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
AddrRangeList &snoop)
|
||||
{ resp.clear(); snoop.clear(); }
|
||||
{ resp.clear(); snoop.clear(); snoop.push_back(RangeSize(0,-1)); }
|
||||
|
||||
struct TickEvent : public Event
|
||||
{
|
||||
@@ -166,6 +166,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||
Packet *ifetch_pkt;
|
||||
Packet *dcache_pkt;
|
||||
|
||||
int cpu_id;
|
||||
Tick previousTick;
|
||||
|
||||
public:
|
||||
|
||||
@@ -237,7 +237,7 @@ class SimpleThread : public ThreadState
|
||||
Fault read(RequestPtr &req, T &data)
|
||||
{
|
||||
#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
|
||||
req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
|
||||
}
|
||||
@@ -256,10 +256,10 @@ class SimpleThread : public ThreadState
|
||||
ExecContext *xc;
|
||||
|
||||
// If this is a store conditional, act appropriately
|
||||
if (req->flags & LOCKED) {
|
||||
if (req->isLocked()) {
|
||||
xc = req->xc;
|
||||
|
||||
if (req->flags & UNCACHEABLE) {
|
||||
if (req->isUncacheable()) {
|
||||
// Don't update result register (see stq_c in isa_desc)
|
||||
req->result = 2;
|
||||
xc->setStCondFailures(0);//Needed? [RGD]
|
||||
|
||||
Reference in New Issue
Block a user