style: cleanup the Ruby Tester
This commit is contained in:
parent
1c98bc5a56
commit
60ae1d2b10
6 changed files with 635 additions and 730 deletions
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 Advanced Micro Devices, Inc.
|
||||
|
@ -28,370 +27,330 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "cpu/rubytest/Check.hh"
|
||||
#include "mem/ruby/common/SubBlock.hh"
|
||||
#include "mem/ruby/system/Sequencer.hh"
|
||||
#include "mem/ruby/system/System.hh"
|
||||
#include "mem/ruby/common/SubBlock.hh"
|
||||
|
||||
Check::Check(const Address& address,
|
||||
const Address& pc,
|
||||
int _num_cpu_sequencers,
|
||||
RubyTester* _tester)
|
||||
: m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester)
|
||||
typedef RubyTester::SenderState SenderState;
|
||||
|
||||
Check::Check(const Address& address, const Address& pc,
|
||||
int _num_cpu_sequencers, RubyTester* _tester)
|
||||
: m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester)
|
||||
{
|
||||
m_status = TesterStatus_Idle;
|
||||
m_status = TesterStatus_Idle;
|
||||
|
||||
pickValue();
|
||||
pickInitiatingNode();
|
||||
changeAddress(address);
|
||||
m_pc = pc;
|
||||
m_access_mode = AccessModeType(random() % AccessModeType_NUM);
|
||||
m_store_count = 0;
|
||||
pickValue();
|
||||
pickInitiatingNode();
|
||||
changeAddress(address);
|
||||
m_pc = pc;
|
||||
m_access_mode = AccessModeType(random() % AccessModeType_NUM);
|
||||
m_store_count = 0;
|
||||
}
|
||||
|
||||
void Check::initiate()
|
||||
void
|
||||
Check::initiate()
|
||||
{
|
||||
DPRINTF(RubyTest, "initiating\n");
|
||||
debugPrint();
|
||||
|
||||
//
|
||||
// currently no protocols support prefetches
|
||||
//
|
||||
if (false && (random() & 0xf) == 0) {
|
||||
initiatePrefetch(); // Prefetch from random processor
|
||||
}
|
||||
|
||||
if(m_status == TesterStatus_Idle) {
|
||||
initiateAction();
|
||||
} else if(m_status == TesterStatus_Ready) {
|
||||
initiateCheck();
|
||||
} else {
|
||||
// Pending - do nothing
|
||||
DPRINTF(RubyTest, "initiating action/check - failed: action/check is pending\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Check::initiatePrefetch()
|
||||
{
|
||||
DPRINTF(RubyTest, "initiating prefetch\n");
|
||||
|
||||
RubyTester::CpuPort* port
|
||||
= safe_cast<RubyTester::CpuPort*> \
|
||||
(m_tester_ptr->getCpuPort(random() % m_num_cpu_sequencers));
|
||||
|
||||
Request::Flags flags;
|
||||
flags.set(Request::PREFETCH);
|
||||
|
||||
//
|
||||
// Prefetches are assumed to be 0 sized
|
||||
//
|
||||
Request *req = new Request(m_address.getAddress(),
|
||||
0,
|
||||
flags,
|
||||
curTick,
|
||||
m_pc.getAddress());
|
||||
|
||||
Packet::Command cmd;
|
||||
|
||||
//
|
||||
// 1 in 8 chance this will be an exclusive prefetch
|
||||
//
|
||||
if ((random() & 0x7) != 0) {
|
||||
cmd = MemCmd::ReadReq;
|
||||
//
|
||||
// 50% chance that the request will be an instruction fetch
|
||||
//
|
||||
if ((random() & 0x1) == 0) {
|
||||
flags.set(Request::INST_FETCH);
|
||||
}
|
||||
} else {
|
||||
cmd = MemCmd::WriteReq;
|
||||
flags.set(Request::PF_EXCLUSIVE);
|
||||
}
|
||||
|
||||
PacketPtr pkt = new Packet(req, cmd, port->idx);
|
||||
|
||||
//
|
||||
// push the subblock onto the sender state. The sequencer will update the
|
||||
// subblock on the return
|
||||
//
|
||||
pkt->senderState = new RubyTester::SenderState(m_address,
|
||||
req->getSize(),
|
||||
pkt->senderState);
|
||||
|
||||
if (port->sendTiming(pkt)) {
|
||||
DPRINTF(RubyTest, "successfully initiated prefetch.\n");
|
||||
} else {
|
||||
//
|
||||
// If the packet did not issue, must delete
|
||||
//
|
||||
RubyTester::SenderState* senderState =
|
||||
safe_cast<RubyTester::SenderState*>(pkt->senderState);
|
||||
pkt->senderState = senderState->saved;
|
||||
delete senderState;
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
||||
DPRINTF(RubyTest, "prefetch initiation failed because Port was busy.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Check::initiateAction()
|
||||
{
|
||||
DPRINTF(RubyTest, "initiating Action\n");
|
||||
assert(m_status == TesterStatus_Idle);
|
||||
|
||||
RubyTester::CpuPort* port
|
||||
= safe_cast<RubyTester::CpuPort*> \
|
||||
(m_tester_ptr->getCpuPort(random() % m_num_cpu_sequencers));
|
||||
|
||||
Request::Flags flags;
|
||||
|
||||
//
|
||||
// Create the particular address for the next byte to be written
|
||||
//
|
||||
Address writeAddr(m_address.getAddress() + m_store_count);
|
||||
|
||||
//
|
||||
// Stores are assumed to be 1 byte-sized
|
||||
//
|
||||
Request *req = new Request(writeAddr.getAddress(),
|
||||
1,
|
||||
flags,
|
||||
curTick,
|
||||
m_pc.getAddress());
|
||||
|
||||
Packet::Command cmd;
|
||||
|
||||
//
|
||||
// 1 out of 8 chance, issue an atomic rather than a write
|
||||
//
|
||||
// if ((random() & 0x7) == 0) {
|
||||
// cmd = MemCmd::SwapReq;
|
||||
// } else {
|
||||
cmd = MemCmd::WriteReq;
|
||||
// }
|
||||
|
||||
PacketPtr pkt = new Packet(req, cmd, port->idx);
|
||||
uint8_t* writeData = new uint8_t;
|
||||
*writeData = m_value + m_store_count;
|
||||
pkt->dataDynamic(writeData);
|
||||
|
||||
DPRINTF(RubyTest,
|
||||
"data 0x%x check 0x%x\n",
|
||||
*(pkt->getPtr<uint8_t>()),
|
||||
*writeData);
|
||||
|
||||
//
|
||||
// push the subblock onto the sender state. The sequencer will update the
|
||||
// subblock on the return
|
||||
//
|
||||
pkt->senderState = new RubyTester::SenderState(writeAddr,
|
||||
req->getSize(),
|
||||
pkt->senderState);
|
||||
|
||||
if (port->sendTiming(pkt)) {
|
||||
DPRINTF(RubyTest, "initiating action - successful\n");
|
||||
DPRINTF(RubyTest,
|
||||
"status before action update: %s\n",
|
||||
(TesterStatus_to_string(m_status)).c_str());
|
||||
m_status = TesterStatus_Action_Pending;
|
||||
} else {
|
||||
//
|
||||
// If the packet did not issue, must delete
|
||||
// Note: No need to delete the data, the packet destructor will delete it
|
||||
//
|
||||
RubyTester::SenderState* senderState =
|
||||
safe_cast<RubyTester::SenderState*>(pkt->senderState);
|
||||
pkt->senderState = senderState->saved;
|
||||
delete senderState;
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
||||
DPRINTF(RubyTest, "failed to initiate action - sequencer not ready\n");
|
||||
}
|
||||
|
||||
DPRINTF(RubyTest,
|
||||
"status after action update: %s\n",
|
||||
(TesterStatus_to_string(m_status)).c_str());
|
||||
}
|
||||
|
||||
void Check::initiateCheck()
|
||||
{
|
||||
DPRINTF(RubyTest, "Initiating Check\n");
|
||||
assert(m_status == TesterStatus_Ready);
|
||||
|
||||
RubyTester::CpuPort* port
|
||||
= safe_cast<RubyTester::CpuPort*> \
|
||||
(m_tester_ptr->getCpuPort(random() % m_num_cpu_sequencers));
|
||||
|
||||
Request::Flags flags;
|
||||
|
||||
//
|
||||
// Checks are sized depending on the number of bytes written
|
||||
//
|
||||
Request *req = new Request(m_address.getAddress(),
|
||||
CHECK_SIZE,
|
||||
flags,
|
||||
curTick,
|
||||
m_pc.getAddress());
|
||||
|
||||
//
|
||||
// 50% chance that the request will be an instruction fetch
|
||||
//
|
||||
if ((random() & 0x1) == 0) {
|
||||
flags.set(Request::INST_FETCH);
|
||||
}
|
||||
|
||||
PacketPtr pkt = new Packet(req, MemCmd::ReadReq, port->idx);
|
||||
uint8_t* dataArray = new uint8_t[CHECK_SIZE];
|
||||
pkt->dataDynamicArray(dataArray);
|
||||
|
||||
//
|
||||
// push the subblock onto the sender state. The sequencer will update the
|
||||
// subblock on the return
|
||||
//
|
||||
pkt->senderState = new RubyTester::SenderState(m_address,
|
||||
req->getSize(),
|
||||
pkt->senderState);
|
||||
|
||||
if (port->sendTiming(pkt)) {
|
||||
DPRINTF(RubyTest, "initiating check - successful\n");
|
||||
DPRINTF(RubyTest,
|
||||
"status before check update: %s\n",
|
||||
(TesterStatus_to_string(m_status)).c_str());
|
||||
m_status = TesterStatus_Check_Pending;
|
||||
} else {
|
||||
//
|
||||
// If the packet did not issue, must delete
|
||||
// Note: No need to delete the data, the packet destructor will delete it
|
||||
//
|
||||
RubyTester::SenderState* senderState =
|
||||
safe_cast<RubyTester::SenderState*>(pkt->senderState);
|
||||
pkt->senderState = senderState->saved;
|
||||
delete senderState;
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
||||
DPRINTF(RubyTest, "failed to initiate check - cpu port not ready\n");
|
||||
}
|
||||
|
||||
DPRINTF(RubyTest,
|
||||
"status after check update: %s\n",
|
||||
(TesterStatus_to_string(m_status)).c_str());
|
||||
}
|
||||
|
||||
void Check::performCallback(NodeID proc, SubBlock* data)
|
||||
{
|
||||
Address address = data->getAddress();
|
||||
// assert(getAddress() == address); // This isn't exactly right since we now have multi-byte checks
|
||||
assert(getAddress().getLineAddress() == address.getLineAddress());
|
||||
assert(data != NULL);
|
||||
|
||||
DPRINTF(RubyTest, "RubyTester Callback\n");
|
||||
debugPrint();
|
||||
|
||||
if (m_status == TesterStatus_Action_Pending) {
|
||||
DPRINTF(RubyTest,
|
||||
"Action callback write value: %d, currently %d\n",
|
||||
(m_value + m_store_count),
|
||||
data->getByte(0));
|
||||
//
|
||||
// Perform store one byte at a time
|
||||
//
|
||||
data->setByte(0, (m_value + m_store_count));
|
||||
m_store_count++;
|
||||
if (m_store_count == CHECK_SIZE) {
|
||||
m_status = TesterStatus_Ready;
|
||||
} else {
|
||||
m_status = TesterStatus_Idle;
|
||||
}
|
||||
DPRINTF(RubyTest,
|
||||
"Action callback return data now %d\n",
|
||||
data->getByte(0));
|
||||
} else if (m_status == TesterStatus_Check_Pending) {
|
||||
DPRINTF(RubyTest, "Check callback\n");
|
||||
// Perform load/check
|
||||
for(int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
|
||||
if (uint8(m_value+byte_number) != data->getByte(byte_number)) {
|
||||
WARN_EXPR(proc);
|
||||
WARN_EXPR(address);
|
||||
WARN_EXPR(data);
|
||||
WARN_EXPR(byte_number);
|
||||
WARN_EXPR((int)m_value+byte_number);
|
||||
WARN_EXPR((int)data->getByte(byte_number));
|
||||
WARN_EXPR(*this);
|
||||
WARN_EXPR(g_eventQueue_ptr->getTime());
|
||||
ERROR_MSG("Action/check failure");
|
||||
}
|
||||
}
|
||||
DPRINTF(RubyTest, "Action/check success\n");
|
||||
DPRINTF(RubyTest, "initiating\n");
|
||||
debugPrint();
|
||||
|
||||
// successful check complete, increment complete
|
||||
m_tester_ptr->incrementCheckCompletions();
|
||||
// currently no protocols support prefetches
|
||||
if (false && (random() & 0xf) == 0) {
|
||||
initiatePrefetch(); // Prefetch from random processor
|
||||
}
|
||||
|
||||
if (m_status == TesterStatus_Idle) {
|
||||
initiateAction();
|
||||
} else if (m_status == TesterStatus_Ready) {
|
||||
initiateCheck();
|
||||
} else {
|
||||
// Pending - do nothing
|
||||
DPRINTF(RubyTest,
|
||||
"initiating action/check - failed: action/check is pending\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Check::initiatePrefetch()
|
||||
{
|
||||
DPRINTF(RubyTest, "initiating prefetch\n");
|
||||
|
||||
int index = random() % m_num_cpu_sequencers;
|
||||
RubyTester::CpuPort* port =
|
||||
safe_cast<RubyTester::CpuPort*>(m_tester_ptr->getCpuPort(index));
|
||||
|
||||
Request::Flags flags;
|
||||
flags.set(Request::PREFETCH);
|
||||
|
||||
// Prefetches are assumed to be 0 sized
|
||||
Request *req = new Request(m_address.getAddress(), 0, flags, curTick,
|
||||
m_pc.getAddress());
|
||||
|
||||
Packet::Command cmd;
|
||||
|
||||
// 1 in 8 chance this will be an exclusive prefetch
|
||||
if ((random() & 0x7) != 0) {
|
||||
cmd = MemCmd::ReadReq;
|
||||
|
||||
// 50% chance that the request will be an instruction fetch
|
||||
if ((random() & 0x1) == 0) {
|
||||
flags.set(Request::INST_FETCH);
|
||||
}
|
||||
} else {
|
||||
cmd = MemCmd::WriteReq;
|
||||
flags.set(Request::PF_EXCLUSIVE);
|
||||
}
|
||||
|
||||
PacketPtr pkt = new Packet(req, cmd, port->idx);
|
||||
|
||||
// push the subblock onto the sender state. The sequencer will
|
||||
// update the subblock on the return
|
||||
pkt->senderState =
|
||||
new SenderState(m_address, req->getSize(), pkt->senderState);
|
||||
|
||||
if (port->sendTiming(pkt)) {
|
||||
DPRINTF(RubyTest, "successfully initiated prefetch.\n");
|
||||
} else {
|
||||
// If the packet did not issue, must delete
|
||||
SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
|
||||
pkt->senderState = senderState->saved;
|
||||
delete senderState;
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
||||
DPRINTF(RubyTest,
|
||||
"prefetch initiation failed because Port was busy.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Check::initiateAction()
|
||||
{
|
||||
DPRINTF(RubyTest, "initiating Action\n");
|
||||
assert(m_status == TesterStatus_Idle);
|
||||
|
||||
int index = random() % m_num_cpu_sequencers;
|
||||
RubyTester::CpuPort* port =
|
||||
safe_cast<RubyTester::CpuPort*>(m_tester_ptr->getCpuPort(index));
|
||||
|
||||
Request::Flags flags;
|
||||
|
||||
// Create the particular address for the next byte to be written
|
||||
Address writeAddr(m_address.getAddress() + m_store_count);
|
||||
|
||||
// Stores are assumed to be 1 byte-sized
|
||||
Request *req = new Request(writeAddr.getAddress(), 1, flags, curTick,
|
||||
m_pc.getAddress());
|
||||
|
||||
Packet::Command cmd;
|
||||
|
||||
// 1 out of 8 chance, issue an atomic rather than a write
|
||||
// if ((random() & 0x7) == 0) {
|
||||
// cmd = MemCmd::SwapReq;
|
||||
// } else {
|
||||
cmd = MemCmd::WriteReq;
|
||||
// }
|
||||
|
||||
PacketPtr pkt = new Packet(req, cmd, port->idx);
|
||||
uint8_t* writeData = new uint8_t;
|
||||
*writeData = m_value + m_store_count;
|
||||
pkt->dataDynamic(writeData);
|
||||
|
||||
DPRINTF(RubyTest, "data 0x%x check 0x%x\n",
|
||||
*(pkt->getPtr<uint8_t>()), *writeData);
|
||||
|
||||
// push the subblock onto the sender state. The sequencer will
|
||||
// update the subblock on the return
|
||||
pkt->senderState =
|
||||
new SenderState(writeAddr, req->getSize(), pkt->senderState);
|
||||
|
||||
if (port->sendTiming(pkt)) {
|
||||
DPRINTF(RubyTest, "initiating action - successful\n");
|
||||
DPRINTF(RubyTest, "status before action update: %s\n",
|
||||
(TesterStatus_to_string(m_status)).c_str());
|
||||
m_status = TesterStatus_Action_Pending;
|
||||
} else {
|
||||
// If the packet did not issue, must delete
|
||||
// Note: No need to delete the data, the packet destructor
|
||||
// will delete it
|
||||
SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
|
||||
pkt->senderState = senderState->saved;
|
||||
delete senderState;
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
||||
DPRINTF(RubyTest, "failed to initiate action - sequencer not ready\n");
|
||||
}
|
||||
|
||||
DPRINTF(RubyTest, "status after action update: %s\n",
|
||||
(TesterStatus_to_string(m_status)).c_str());
|
||||
}
|
||||
|
||||
void
|
||||
Check::initiateCheck()
|
||||
{
|
||||
DPRINTF(RubyTest, "Initiating Check\n");
|
||||
assert(m_status == TesterStatus_Ready);
|
||||
|
||||
int index = random() % m_num_cpu_sequencers;
|
||||
RubyTester::CpuPort* port =
|
||||
safe_cast<RubyTester::CpuPort*>(m_tester_ptr->getCpuPort(index));
|
||||
|
||||
Request::Flags flags;
|
||||
|
||||
// Checks are sized depending on the number of bytes written
|
||||
Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags,
|
||||
curTick, m_pc.getAddress());
|
||||
|
||||
// 50% chance that the request will be an instruction fetch
|
||||
if ((random() & 0x1) == 0) {
|
||||
flags.set(Request::INST_FETCH);
|
||||
}
|
||||
|
||||
PacketPtr pkt = new Packet(req, MemCmd::ReadReq, port->idx);
|
||||
uint8_t* dataArray = new uint8_t[CHECK_SIZE];
|
||||
pkt->dataDynamicArray(dataArray);
|
||||
|
||||
// push the subblock onto the sender state. The sequencer will
|
||||
// update the subblock on the return
|
||||
pkt->senderState =
|
||||
new SenderState(m_address, req->getSize(), pkt->senderState);
|
||||
|
||||
if (port->sendTiming(pkt)) {
|
||||
DPRINTF(RubyTest, "initiating check - successful\n");
|
||||
DPRINTF(RubyTest, "status before check update: %s\n",
|
||||
TesterStatus_to_string(m_status).c_str());
|
||||
m_status = TesterStatus_Check_Pending;
|
||||
} else {
|
||||
// If the packet did not issue, must delete
|
||||
// Note: No need to delete the data, the packet destructor
|
||||
// will delete it
|
||||
SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
|
||||
pkt->senderState = senderState->saved;
|
||||
delete senderState;
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
|
||||
DPRINTF(RubyTest, "failed to initiate check - cpu port not ready\n");
|
||||
}
|
||||
|
||||
DPRINTF(RubyTest, "status after check update: %s\n",
|
||||
TesterStatus_to_string(m_status).c_str());
|
||||
}
|
||||
|
||||
void
|
||||
Check::performCallback(NodeID proc, SubBlock* data)
|
||||
{
|
||||
Address address = data->getAddress();
|
||||
|
||||
// This isn't exactly right since we now have multi-byte checks
|
||||
// assert(getAddress() == address);
|
||||
|
||||
assert(getAddress().getLineAddress() == address.getLineAddress());
|
||||
assert(data != NULL);
|
||||
|
||||
DPRINTF(RubyTest, "RubyTester Callback\n");
|
||||
debugPrint();
|
||||
|
||||
if (m_status == TesterStatus_Action_Pending) {
|
||||
DPRINTF(RubyTest, "Action callback write value: %d, currently %d\n",
|
||||
(m_value + m_store_count), data->getByte(0));
|
||||
// Perform store one byte at a time
|
||||
data->setByte(0, (m_value + m_store_count));
|
||||
m_store_count++;
|
||||
if (m_store_count == CHECK_SIZE) {
|
||||
m_status = TesterStatus_Ready;
|
||||
} else {
|
||||
m_status = TesterStatus_Idle;
|
||||
}
|
||||
DPRINTF(RubyTest, "Action callback return data now %d\n",
|
||||
data->getByte(0));
|
||||
} else if (m_status == TesterStatus_Check_Pending) {
|
||||
DPRINTF(RubyTest, "Check callback\n");
|
||||
// Perform load/check
|
||||
for (int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
|
||||
if (uint8(m_value + byte_number) != data->getByte(byte_number)) {
|
||||
WARN_EXPR(proc);
|
||||
WARN_EXPR(address);
|
||||
WARN_EXPR(data);
|
||||
WARN_EXPR(byte_number);
|
||||
WARN_EXPR((int)m_value + byte_number);
|
||||
WARN_EXPR((int)data->getByte(byte_number));
|
||||
WARN_EXPR(*this);
|
||||
WARN_EXPR(g_eventQueue_ptr->getTime());
|
||||
ERROR_MSG("Action/check failure");
|
||||
}
|
||||
}
|
||||
DPRINTF(RubyTest, "Action/check success\n");
|
||||
debugPrint();
|
||||
|
||||
// successful check complete, increment complete
|
||||
m_tester_ptr->incrementCheckCompletions();
|
||||
|
||||
m_status = TesterStatus_Idle;
|
||||
pickValue();
|
||||
|
||||
} else {
|
||||
WARN_EXPR(*this);
|
||||
WARN_EXPR(proc);
|
||||
WARN_EXPR(data);
|
||||
WARN_EXPR(m_status);
|
||||
WARN_EXPR(g_eventQueue_ptr->getTime());
|
||||
ERROR_MSG("Unexpected TesterStatus");
|
||||
}
|
||||
|
||||
DPRINTF(RubyTest, "proc: %d, Address: 0x%x\n", proc,
|
||||
getAddress().getLineAddress());
|
||||
DPRINTF(RubyTest, "Callback done\n");
|
||||
debugPrint();
|
||||
}
|
||||
|
||||
void
|
||||
Check::changeAddress(const Address& address)
|
||||
{
|
||||
assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready);
|
||||
m_status = TesterStatus_Idle;
|
||||
pickValue();
|
||||
|
||||
} else {
|
||||
WARN_EXPR(*this);
|
||||
WARN_EXPR(proc);
|
||||
WARN_EXPR(data);
|
||||
WARN_EXPR(m_status);
|
||||
WARN_EXPR(g_eventQueue_ptr->getTime());
|
||||
ERROR_MSG("Unexpected TesterStatus");
|
||||
}
|
||||
|
||||
DPRINTF(RubyTest, "proc: %d, Address: 0x%x\n", proc, getAddress().getLineAddress());
|
||||
DPRINTF(RubyTest, "Callback done\n");
|
||||
debugPrint();
|
||||
m_address = address;
|
||||
m_store_count = 0;
|
||||
}
|
||||
|
||||
void Check::changeAddress(const Address& address)
|
||||
void
|
||||
Check::pickValue()
|
||||
{
|
||||
assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready));
|
||||
m_status = TesterStatus_Idle;
|
||||
m_address = address;
|
||||
m_store_count = 0;
|
||||
assert(m_status == TesterStatus_Idle);
|
||||
m_status = TesterStatus_Idle;
|
||||
m_value = random() & 0xff; // One byte
|
||||
m_store_count = 0;
|
||||
}
|
||||
|
||||
void Check::pickValue()
|
||||
void
|
||||
Check::pickInitiatingNode()
|
||||
{
|
||||
assert(m_status == TesterStatus_Idle);
|
||||
m_status = TesterStatus_Idle;
|
||||
m_value = random() & 0xff; // One byte
|
||||
m_store_count = 0;
|
||||
assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready);
|
||||
m_status = TesterStatus_Idle;
|
||||
m_initiatingNode = (random() % m_num_cpu_sequencers);
|
||||
DPRINTF(RubyTest, "picked initiating node %d\n", m_initiatingNode);
|
||||
m_store_count = 0;
|
||||
}
|
||||
|
||||
void Check::pickInitiatingNode()
|
||||
void
|
||||
Check::print(ostream& out) const
|
||||
{
|
||||
assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready));
|
||||
m_status = TesterStatus_Idle;
|
||||
m_initiatingNode = (random() % m_num_cpu_sequencers);
|
||||
DPRINTF(RubyTest, "picked initiating node %d\n", m_initiatingNode);
|
||||
m_store_count = 0;
|
||||
out << "["
|
||||
<< m_address << ", value: "
|
||||
<< (int)m_value << ", status: "
|
||||
<< m_status << ", initiating node: "
|
||||
<< m_initiatingNode << ", store_count: "
|
||||
<< m_store_count
|
||||
<< "]" << flush;
|
||||
}
|
||||
|
||||
void Check::print(ostream& out) const
|
||||
void
|
||||
Check::debugPrint()
|
||||
{
|
||||
out << "["
|
||||
<< m_address << ", value: "
|
||||
<< (int) m_value << ", status: "
|
||||
<< m_status << ", initiating node: "
|
||||
<< m_initiatingNode << ", store_count: "
|
||||
<< m_store_count
|
||||
<< "]" << flush;
|
||||
}
|
||||
|
||||
void Check::debugPrint()
|
||||
{
|
||||
DPRINTF(RubyTest,
|
||||
"[0x%x, value: %d, status: %s, initiating node: %d, store_count: %d]\n",
|
||||
m_address.getAddress(),
|
||||
(int)m_value,
|
||||
(TesterStatus_to_string(m_status)).c_str(),
|
||||
m_initiatingNode,
|
||||
m_store_count);
|
||||
DPRINTF(RubyTest,
|
||||
"[%#x, value: %d, status: %s, initiating node: %d, store_count: %d]\n",
|
||||
m_address.getAddress(), (int)m_value,
|
||||
TesterStatus_to_string(m_status).c_str(),
|
||||
m_initiatingNode, m_store_count);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 Advanced Micro Devices, Inc.
|
||||
|
@ -28,78 +27,61 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CHECK_H
|
||||
#define CHECK_H
|
||||
#ifndef __CPU_RUBYTEST_CHECK_HH__
|
||||
#define __CPU_RUBYTEST_CHECK_HH__
|
||||
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/ruby/common/Address.hh"
|
||||
#include "mem/ruby/system/NodeID.hh"
|
||||
#include "mem/protocol/TesterStatus.hh"
|
||||
#include "mem/protocol/AccessModeType.hh"
|
||||
#include "cpu/rubytest/RubyTester.hh"
|
||||
#include "mem/protocol/AccessModeType.hh"
|
||||
#include "mem/protocol/TesterStatus.hh"
|
||||
#include "mem/ruby/common/Address.hh"
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/ruby/system/NodeID.hh"
|
||||
|
||||
class SubBlock;
|
||||
|
||||
const int CHECK_SIZE_BITS = 2;
|
||||
const int CHECK_SIZE = (1<<CHECK_SIZE_BITS);
|
||||
const int CHECK_SIZE = (1 << CHECK_SIZE_BITS);
|
||||
|
||||
class Check {
|
||||
public:
|
||||
// Constructors
|
||||
Check(const Address& address,
|
||||
const Address& pc,
|
||||
int _num_cpu_sequencer,
|
||||
RubyTester* _tester);
|
||||
class Check
|
||||
{
|
||||
public:
|
||||
Check(const Address& address, const Address& pc, int _num_cpu_sequencer,
|
||||
RubyTester* _tester);
|
||||
|
||||
// Default Destructor
|
||||
//~Check();
|
||||
|
||||
// Public Methods
|
||||
void initiate(); // Does Action or Check or nether
|
||||
void performCallback(NodeID proc, SubBlock* data);
|
||||
const Address& getAddress() { return m_address; }
|
||||
void changeAddress(const Address& address);
|
||||
|
||||
void initiate(); // Does Action or Check or nether
|
||||
void performCallback(NodeID proc, SubBlock* data);
|
||||
const Address& getAddress() { return m_address; }
|
||||
void changeAddress(const Address& address);
|
||||
void print(ostream& out) const;
|
||||
|
||||
void print(ostream& out) const;
|
||||
private:
|
||||
// Private Methods
|
||||
void initiatePrefetch();
|
||||
void initiateAction();
|
||||
void initiateCheck();
|
||||
private:
|
||||
void initiatePrefetch();
|
||||
void initiateAction();
|
||||
void initiateCheck();
|
||||
|
||||
void pickValue();
|
||||
void pickInitiatingNode();
|
||||
void pickValue();
|
||||
void pickInitiatingNode();
|
||||
|
||||
void debugPrint();
|
||||
void debugPrint();
|
||||
|
||||
// Using default copy constructor and assignment operator
|
||||
// Check(const Check& obj);
|
||||
// Check& operator=(const Check& obj);
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
TesterStatus m_status;
|
||||
uint8 m_value;
|
||||
int m_store_count;
|
||||
NodeID m_initiatingNode;
|
||||
Address m_address;
|
||||
Address m_pc;
|
||||
AccessModeType m_access_mode;
|
||||
int m_num_cpu_sequencers;
|
||||
RubyTester* m_tester_ptr;
|
||||
TesterStatus m_status;
|
||||
uint8 m_value;
|
||||
int m_store_count;
|
||||
NodeID m_initiatingNode;
|
||||
Address m_address;
|
||||
Address m_pc;
|
||||
AccessModeType m_access_mode;
|
||||
int m_num_cpu_sequencers;
|
||||
RubyTester* m_tester_ptr;
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
ostream& operator<<(ostream& out, const Check& obj);
|
||||
|
||||
// ******************* Definitions *******************
|
||||
|
||||
// Output operator definition
|
||||
extern inline
|
||||
ostream& operator<<(ostream& out, const Check& obj)
|
||||
inline ostream&
|
||||
operator<<(ostream& out, const Check& obj)
|
||||
{
|
||||
obj.print(out);
|
||||
out << flush;
|
||||
return out;
|
||||
obj.print(out);
|
||||
out << flush;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif //CHECK_H
|
||||
#endif // __CPU_RUBYTEST_CHECK_HH__
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 Advanced Micro Devices, Inc.
|
||||
|
@ -28,103 +27,105 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "cpu/rubytest/CheckTable.hh"
|
||||
#include "cpu/rubytest/CheckTable.hh"
|
||||
#include "cpu/rubytest/Check.hh"
|
||||
#include "cpu/rubytest/CheckTable.hh"
|
||||
#include "cpu/rubytest/CheckTable.hh"
|
||||
#include "mem/gems_common/Map.hh"
|
||||
|
||||
CheckTable::CheckTable(int _num_cpu_sequencers, RubyTester* _tester)
|
||||
: m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester)
|
||||
: m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester)
|
||||
{
|
||||
m_lookup_map_ptr = new Map<Address, Check*>;
|
||||
physical_address_t physical = 0;
|
||||
Address address;
|
||||
m_lookup_map_ptr = new Map<Address, Check*>;
|
||||
physical_address_t physical = 0;
|
||||
Address address;
|
||||
|
||||
const int size1 = 32;
|
||||
const int size2 = 100;
|
||||
const int size1 = 32;
|
||||
const int size2 = 100;
|
||||
|
||||
// The first set is to get some false sharing
|
||||
physical = 1000;
|
||||
for (int i=0; i<size1; i++) {
|
||||
// Setup linear addresses
|
||||
address.setAddress(physical);
|
||||
addCheck(address);
|
||||
physical += CHECK_SIZE;
|
||||
}
|
||||
// The first set is to get some false sharing
|
||||
physical = 1000;
|
||||
for (int i = 0; i < size1; i++) {
|
||||
// Setup linear addresses
|
||||
address.setAddress(physical);
|
||||
addCheck(address);
|
||||
physical += CHECK_SIZE;
|
||||
}
|
||||
|
||||
// The next two sets are to get some limited false sharing and cache conflicts
|
||||
physical = 1000;
|
||||
for (int i=0; i<size2; i++) {
|
||||
// Setup linear addresses
|
||||
address.setAddress(physical);
|
||||
addCheck(address);
|
||||
physical += 256;
|
||||
}
|
||||
// The next two sets are to get some limited false sharing and
|
||||
// cache conflicts
|
||||
physical = 1000;
|
||||
for (int i = 0; i < size2; i++) {
|
||||
// Setup linear addresses
|
||||
address.setAddress(physical);
|
||||
addCheck(address);
|
||||
physical += 256;
|
||||
}
|
||||
|
||||
physical = 1000 + CHECK_SIZE;
|
||||
for (int i=0; i<size2; i++) {
|
||||
// Setup linear addresses
|
||||
address.setAddress(physical);
|
||||
addCheck(address);
|
||||
physical += 256;
|
||||
}
|
||||
physical = 1000 + CHECK_SIZE;
|
||||
for (int i = 0; i < size2; i++) {
|
||||
// Setup linear addresses
|
||||
address.setAddress(physical);
|
||||
addCheck(address);
|
||||
physical += 256;
|
||||
}
|
||||
}
|
||||
|
||||
CheckTable::~CheckTable()
|
||||
{
|
||||
int size = m_check_vector.size();
|
||||
for (int i=0; i<size; i++) {
|
||||
delete m_check_vector[i];
|
||||
}
|
||||
delete m_lookup_map_ptr;
|
||||
int size = m_check_vector.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
delete m_check_vector[i];
|
||||
delete m_lookup_map_ptr;
|
||||
}
|
||||
|
||||
void CheckTable::addCheck(const Address& address)
|
||||
void
|
||||
CheckTable::addCheck(const Address& address)
|
||||
{
|
||||
if (log_int(CHECK_SIZE) != 0) {
|
||||
if (address.bitSelect(0,CHECK_SIZE_BITS-1) != 0) {
|
||||
ERROR_MSG("Check not aligned");
|
||||
if (log_int(CHECK_SIZE) != 0) {
|
||||
if (address.bitSelect(0, CHECK_SIZE_BITS - 1) != 0) {
|
||||
ERROR_MSG("Check not aligned");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<CHECK_SIZE; i++) {
|
||||
if (m_lookup_map_ptr->exist(Address(address.getAddress()+i))) {
|
||||
// A mapping for this byte already existed, discard the entire check
|
||||
return;
|
||||
for (int i = 0; i < CHECK_SIZE; i++) {
|
||||
if (m_lookup_map_ptr->exist(Address(address.getAddress()+i))) {
|
||||
// A mapping for this byte already existed, discard the
|
||||
// entire check
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Check* check_ptr = new Check(address,
|
||||
Address(100+m_check_vector.size()),
|
||||
m_num_cpu_sequencers,
|
||||
m_tester_ptr);
|
||||
for (int i=0; i<CHECK_SIZE; i++) {
|
||||
// Insert it once per byte
|
||||
m_lookup_map_ptr->add(Address(address.getAddress()+i), check_ptr);
|
||||
}
|
||||
m_check_vector.insertAtBottom(check_ptr);
|
||||
Check* check_ptr = new Check(address, Address(100 + m_check_vector.size()),
|
||||
m_num_cpu_sequencers, m_tester_ptr);
|
||||
for (int i = 0; i < CHECK_SIZE; i++) {
|
||||
// Insert it once per byte
|
||||
m_lookup_map_ptr->add(Address(address.getAddress() + i), check_ptr);
|
||||
}
|
||||
m_check_vector.insertAtBottom(check_ptr);
|
||||
}
|
||||
|
||||
Check* CheckTable::getRandomCheck()
|
||||
Check*
|
||||
CheckTable::getRandomCheck()
|
||||
{
|
||||
return m_check_vector[random() % m_check_vector.size()];
|
||||
return m_check_vector[random() % m_check_vector.size()];
|
||||
}
|
||||
|
||||
Check* CheckTable::getCheck(const Address& address)
|
||||
Check*
|
||||
CheckTable::getCheck(const Address& address)
|
||||
{
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, "Looking for check by address");
|
||||
DEBUG_EXPR(TESTER_COMP, MedPrio, address);
|
||||
DEBUG_MSG(TESTER_COMP, MedPrio, "Looking for check by address");
|
||||
DEBUG_EXPR(TESTER_COMP, MedPrio, address);
|
||||
|
||||
if (m_lookup_map_ptr->exist(address)) {
|
||||
Check* check = m_lookup_map_ptr->lookup(address);
|
||||
assert(check != NULL);
|
||||
return check;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
if (m_lookup_map_ptr->exist(address)) {
|
||||
Check* check = m_lookup_map_ptr->lookup(address);
|
||||
assert(check != NULL);
|
||||
return check;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CheckTable::print(ostream& out) const
|
||||
void
|
||||
CheckTable::print(ostream& out) const
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 Advanced Micro Devices, Inc.
|
||||
|
@ -28,66 +27,55 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CHECKTABLE_H
|
||||
#define CHECKTABLE_H
|
||||
#ifndef __CPU_RUBYTEST_CHECKTABLE_HH__
|
||||
#define __CPU_RUBYTEST_CHECKTABLE_HH__
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/gems_common/Vector.hh"
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
|
||||
class Address;
|
||||
class Check;
|
||||
class RubyTester;
|
||||
template <class KEY_TYPE, class VALUE_TYPE> class Map;
|
||||
|
||||
class CheckTable {
|
||||
public:
|
||||
// Constructors
|
||||
CheckTable(int _num_cpu_sequencers, RubyTester* _tester);
|
||||
class CheckTable
|
||||
{
|
||||
public:
|
||||
CheckTable(int _num_cpu_sequencers, RubyTester* _tester);
|
||||
~CheckTable();
|
||||
|
||||
// Destructor
|
||||
~CheckTable();
|
||||
|
||||
// Public Methods
|
||||
Check* getRandomCheck();
|
||||
Check* getCheck(const Address& address);
|
||||
|
||||
Check* getRandomCheck();
|
||||
Check* getCheck(const Address& address);
|
||||
// bool isPresent(const Address& address) const;
|
||||
// void removeCheckFromTable(const Address& address);
|
||||
// bool isTableFull() const;
|
||||
// Need a method to select a check or retrieve a check
|
||||
|
||||
// bool isPresent(const Address& address) const;
|
||||
// void removeCheckFromTable(const Address& address);
|
||||
// bool isTableFull() const;
|
||||
// Need a method to select a check or retrieve a check
|
||||
void print(std::ostream& out) const;
|
||||
|
||||
void print(std::ostream& out) const;
|
||||
private:
|
||||
// Private Methods
|
||||
void addCheck(const Address& address);
|
||||
private:
|
||||
void addCheck(const Address& address);
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
CheckTable(const CheckTable& obj);
|
||||
CheckTable& operator=(const CheckTable& obj);
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
Vector<Check*> m_check_vector;
|
||||
Map<Address, Check*>* m_lookup_map_ptr;
|
||||
// Private copy constructor and assignment operator
|
||||
CheckTable(const CheckTable& obj);
|
||||
CheckTable& operator=(const CheckTable& obj);
|
||||
|
||||
int m_num_cpu_sequencers;
|
||||
RubyTester* m_tester_ptr;
|
||||
Vector<Check*> m_check_vector;
|
||||
Map<Address, Check*>* m_lookup_map_ptr;
|
||||
|
||||
int m_num_cpu_sequencers;
|
||||
RubyTester* m_tester_ptr;
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
std::ostream& operator<<(std::ostream& out, const CheckTable& obj);
|
||||
|
||||
// ******************* Definitions *******************
|
||||
|
||||
// Output operator definition
|
||||
extern inline
|
||||
std::ostream& operator<<(std::ostream& out, const CheckTable& obj)
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& out, const CheckTable& obj)
|
||||
{
|
||||
obj.print(out);
|
||||
out << std::flush;
|
||||
return out;
|
||||
obj.print(out);
|
||||
out << std::flush;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif //CHECKTABLE_H
|
||||
#endif // __CPU_RUBYTEST_CHECKTABLE_HH__
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 Advanced Micro Devices, Inc.
|
||||
|
@ -28,54 +27,51 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/ruby/system/System.hh"
|
||||
#include "cpu/rubytest/RubyTester.hh"
|
||||
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
|
||||
#include "mem/ruby/common/SubBlock.hh"
|
||||
#include "cpu/rubytest/Check.hh"
|
||||
#include "cpu/rubytest/RubyTester.hh"
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/ruby/common/SubBlock.hh"
|
||||
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
|
||||
#include "mem/ruby/system/System.hh"
|
||||
#include "sim/sim_exit.hh"
|
||||
|
||||
RubyTester::RubyTester(const Params *p)
|
||||
: MemObject(p),
|
||||
checkStartEvent(this),
|
||||
: MemObject(p), checkStartEvent(this),
|
||||
m_checks_to_complete(p->checks_to_complete),
|
||||
m_deadlock_threshold(p->deadlock_threshold),
|
||||
m_wakeup_frequency(p->wakeup_frequency)
|
||||
{
|
||||
m_checks_completed = 0;
|
||||
|
||||
// add the check start event to the event queue
|
||||
schedule(checkStartEvent, 1);
|
||||
m_checks_completed = 0;
|
||||
|
||||
// add the check start event to the event queue
|
||||
schedule(checkStartEvent, 1);
|
||||
}
|
||||
|
||||
RubyTester::~RubyTester()
|
||||
{
|
||||
delete m_checkTable_ptr;
|
||||
for (int i = 0; i < ports.size(); i++) {
|
||||
delete ports[i];
|
||||
}
|
||||
delete m_checkTable_ptr;
|
||||
for (int i = 0; i < ports.size(); i++)
|
||||
delete ports[i];
|
||||
}
|
||||
|
||||
void RubyTester::init()
|
||||
void
|
||||
RubyTester::init()
|
||||
{
|
||||
assert(ports.size() > 0);
|
||||
assert(ports.size() > 0);
|
||||
|
||||
m_last_progress_vector.setSize(ports.size());
|
||||
for (int i = 0; i < m_last_progress_vector.size(); i++) {
|
||||
m_last_progress_vector[i] = 0;
|
||||
}
|
||||
m_last_progress_vector.setSize(ports.size());
|
||||
for (int i = 0; i < m_last_progress_vector.size(); i++) {
|
||||
m_last_progress_vector[i] = 0;
|
||||
}
|
||||
|
||||
m_num_cpu_sequencers = ports.size();
|
||||
m_num_cpu_sequencers = ports.size();
|
||||
|
||||
m_checkTable_ptr = new CheckTable(m_num_cpu_sequencers, this);
|
||||
m_checkTable_ptr = new CheckTable(m_num_cpu_sequencers, this);
|
||||
}
|
||||
|
||||
Port *
|
||||
RubyTester::getPort(const std::string &if_name, int idx)
|
||||
{
|
||||
|
||||
if (if_name != "cpuPort") {
|
||||
panic("RubyTester::getPort: unknown port %s requested", if_name);
|
||||
}
|
||||
|
@ -97,102 +93,99 @@ RubyTester::getPort(const std::string &if_name, int idx)
|
|||
Tick
|
||||
RubyTester::CpuPort::recvAtomic(PacketPtr pkt)
|
||||
{
|
||||
panic("RubyTester::CpuPort::recvAtomic() not implemented!\n");
|
||||
return 0;
|
||||
panic("RubyTester::CpuPort::recvAtomic() not implemented!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
RubyTester::CpuPort::recvTiming(PacketPtr pkt)
|
||||
{
|
||||
//
|
||||
// retrieve the subblock and call hitCallback
|
||||
//
|
||||
RubyTester::SenderState* senderState =
|
||||
safe_cast<RubyTester::SenderState*>(pkt->senderState);
|
||||
SubBlock* subblock = senderState->subBlock;
|
||||
assert(subblock != NULL);
|
||||
|
||||
// pop the sender state from the packet
|
||||
pkt->senderState = senderState->saved;
|
||||
// retrieve the subblock and call hitCallback
|
||||
RubyTester::SenderState* senderState =
|
||||
safe_cast<RubyTester::SenderState*>(pkt->senderState);
|
||||
SubBlock* subblock = senderState->subBlock;
|
||||
assert(subblock != NULL);
|
||||
|
||||
tester->hitCallback(idx, subblock);
|
||||
// pop the sender state from the packet
|
||||
pkt->senderState = senderState->saved;
|
||||
|
||||
//
|
||||
// Now that the tester has completed, delete the senderState
|
||||
// (includes sublock) and the packet, then return
|
||||
//
|
||||
delete senderState;
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
return true;
|
||||
tester->hitCallback(idx, subblock);
|
||||
|
||||
// Now that the tester has completed, delete the senderState
|
||||
// (includes sublock) and the packet, then return
|
||||
delete senderState;
|
||||
delete pkt->req;
|
||||
delete pkt;
|
||||
return true;
|
||||
}
|
||||
|
||||
Port*
|
||||
Port*
|
||||
RubyTester::getCpuPort(int idx)
|
||||
{
|
||||
assert(idx >= 0 && idx < ports.size());
|
||||
assert(idx >= 0 && idx < ports.size());
|
||||
|
||||
return ports[idx];
|
||||
return ports[idx];
|
||||
}
|
||||
|
||||
void RubyTester::hitCallback(NodeID proc, SubBlock* data)
|
||||
void
|
||||
RubyTester::hitCallback(NodeID proc, SubBlock* data)
|
||||
{
|
||||
// Mark that we made progress
|
||||
m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
|
||||
// Mark that we made progress
|
||||
m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
|
||||
|
||||
DPRINTF(RubyTest, "completed request for proc: %d\n", proc);
|
||||
DPRINTF(RubyTest,
|
||||
"addr: 0x%x, size: %d, data: ",
|
||||
data->getAddress(),
|
||||
data->getSize());
|
||||
for (int byte = 0; byte < data->getSize(); byte++) {
|
||||
DPRINTF(RubyTest, "%d", data->getByte(byte));
|
||||
}
|
||||
DPRINTF(RubyTest, "\n");
|
||||
|
||||
//
|
||||
// This tells us our store has 'completed' or for a load gives us
|
||||
// back the data to make the check
|
||||
//
|
||||
Check* check_ptr = m_checkTable_ptr->getCheck(data->getAddress());
|
||||
assert(check_ptr != NULL);
|
||||
check_ptr->performCallback(proc, data);
|
||||
}
|
||||
|
||||
void RubyTester::wakeup()
|
||||
{
|
||||
if (m_checks_completed < m_checks_to_complete) {
|
||||
// Try to perform an action or check
|
||||
Check* check_ptr = m_checkTable_ptr->getRandomCheck();
|
||||
assert(check_ptr != NULL);
|
||||
check_ptr->initiate();
|
||||
|
||||
checkForDeadlock();
|
||||
|
||||
schedule(checkStartEvent, curTick + m_wakeup_frequency);
|
||||
} else {
|
||||
exitSimLoop("Ruby Tester completed");
|
||||
}
|
||||
}
|
||||
|
||||
void RubyTester::checkForDeadlock()
|
||||
{
|
||||
int size = m_last_progress_vector.size();
|
||||
Time current_time = g_eventQueue_ptr->getTime();
|
||||
for (int processor = 0; processor < size; processor++) {
|
||||
if ((current_time - m_last_progress_vector[processor]) > m_deadlock_threshold) {
|
||||
WARN_EXPR(current_time);
|
||||
WARN_EXPR(m_last_progress_vector[processor]);
|
||||
WARN_EXPR(current_time - m_last_progress_vector[processor]);
|
||||
WARN_EXPR(processor);
|
||||
ERROR_MSG("Deadlock detected.");
|
||||
DPRINTF(RubyTest, "completed request for proc: %d\n", proc);
|
||||
DPRINTF(RubyTest, "addr: 0x%x, size: %d, data: ",
|
||||
data->getAddress(), data->getSize());
|
||||
for (int byte = 0; byte < data->getSize(); byte++) {
|
||||
DPRINTF(RubyTest, "%d", data->getByte(byte));
|
||||
}
|
||||
}
|
||||
DPRINTF(RubyTest, "\n");
|
||||
|
||||
// This tells us our store has 'completed' or for a load gives us
|
||||
// back the data to make the check
|
||||
Check* check_ptr = m_checkTable_ptr->getCheck(data->getAddress());
|
||||
assert(check_ptr != NULL);
|
||||
check_ptr->performCallback(proc, data);
|
||||
}
|
||||
|
||||
void RubyTester::print(ostream& out) const
|
||||
void
|
||||
RubyTester::wakeup()
|
||||
{
|
||||
out << "[RubyTester]" << endl;
|
||||
if (m_checks_completed < m_checks_to_complete) {
|
||||
// Try to perform an action or check
|
||||
Check* check_ptr = m_checkTable_ptr->getRandomCheck();
|
||||
assert(check_ptr != NULL);
|
||||
check_ptr->initiate();
|
||||
|
||||
checkForDeadlock();
|
||||
|
||||
schedule(checkStartEvent, curTick + m_wakeup_frequency);
|
||||
} else {
|
||||
exitSimLoop("Ruby Tester completed");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RubyTester::checkForDeadlock()
|
||||
{
|
||||
int size = m_last_progress_vector.size();
|
||||
Time current_time = g_eventQueue_ptr->getTime();
|
||||
for (int processor = 0; processor < size; processor++) {
|
||||
if ((current_time - m_last_progress_vector[processor]) >
|
||||
m_deadlock_threshold) {
|
||||
WARN_EXPR(current_time);
|
||||
WARN_EXPR(m_last_progress_vector[processor]);
|
||||
WARN_EXPR(current_time - m_last_progress_vector[processor]);
|
||||
WARN_EXPR(processor);
|
||||
ERROR_MSG("Deadlock detected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RubyTester::print(ostream& out) const
|
||||
{
|
||||
out << "[RubyTester]" << endl;
|
||||
}
|
||||
|
||||
RubyTester *
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||
* Copyright (c) 2009 Advanced Micro Devices, Inc.
|
||||
|
@ -28,135 +27,118 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RUBY_TESTER_H
|
||||
#define RUBY_TESTER_H
|
||||
#ifndef __CPU_RUBYTEST_RUBYTESTER_HH__
|
||||
#define __CPU_RUBYTEST_RUBYTESTER_HH__
|
||||
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/mem_object.hh"
|
||||
#include "cpu/rubytest/CheckTable.hh"
|
||||
#include "mem/ruby/system/RubyPort.hh"
|
||||
#include "mem/ruby/common/SubBlock.hh"
|
||||
#include "mem/ruby/common/DataBlock.hh"
|
||||
#include "mem/mem_object.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/ruby/common/DataBlock.hh"
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/ruby/common/SubBlock.hh"
|
||||
#include "mem/ruby/system/RubyPort.hh"
|
||||
#include "params/RubyTester.hh"
|
||||
|
||||
class RubyTester : public MemObject
|
||||
class RubyTester : public MemObject
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
class CpuPort : public SimpleTimingPort
|
||||
{
|
||||
RubyTester *tester;
|
||||
|
||||
public:
|
||||
|
||||
CpuPort(const std::string &_name,
|
||||
RubyTester *_tester,
|
||||
int _idx)
|
||||
: SimpleTimingPort(_name, _tester), tester(_tester), idx(_idx)
|
||||
{}
|
||||
|
||||
int idx;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
|
||||
virtual Tick recvAtomic(PacketPtr pkt);
|
||||
|
||||
};
|
||||
|
||||
struct SenderState : public Packet::SenderState
|
||||
{
|
||||
SubBlock* subBlock;
|
||||
Packet::SenderState *saved;
|
||||
|
||||
SenderState(Address addr,
|
||||
int size,
|
||||
Packet::SenderState *sender_state = NULL)
|
||||
: saved(sender_state)
|
||||
{subBlock = new SubBlock(addr, size);}
|
||||
|
||||
~SenderState() {delete subBlock;}
|
||||
};
|
||||
|
||||
typedef RubyTesterParams Params;
|
||||
// Constructors
|
||||
RubyTester(const Params *p);
|
||||
|
||||
// Destructor
|
||||
~RubyTester();
|
||||
|
||||
// Public Methods
|
||||
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||
|
||||
Port* getCpuPort(int idx);
|
||||
|
||||
void virtual init();
|
||||
|
||||
void wakeup();
|
||||
|
||||
void incrementCheckCompletions() { m_checks_completed++; }
|
||||
|
||||
void printStats(ostream& out) const {}
|
||||
void clearStats() {}
|
||||
void printConfig(ostream& out) const {}
|
||||
|
||||
void print(ostream& out) const;
|
||||
|
||||
protected:
|
||||
class CheckStartEvent : public Event
|
||||
{
|
||||
private:
|
||||
RubyTester *tester;
|
||||
|
||||
public:
|
||||
CheckStartEvent(RubyTester *_tester) : Event(CPU_Tick_Pri), tester(_tester) {}
|
||||
void process() { tester->wakeup(); }
|
||||
virtual const char *description() const { return "RubyTester tick"; }
|
||||
};
|
||||
|
||||
CheckStartEvent checkStartEvent;
|
||||
class CpuPort : public SimpleTimingPort
|
||||
{
|
||||
private:
|
||||
RubyTester *tester;
|
||||
|
||||
public:
|
||||
CpuPort(const std::string &_name, RubyTester *_tester, int _idx)
|
||||
: SimpleTimingPort(_name, _tester), tester(_tester), idx(_idx)
|
||||
{}
|
||||
|
||||
private:
|
||||
// Private Methods
|
||||
int idx;
|
||||
|
||||
void hitCallback(NodeID proc, SubBlock* data);
|
||||
protected:
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
virtual Tick recvAtomic(PacketPtr pkt);
|
||||
};
|
||||
|
||||
void checkForDeadlock();
|
||||
struct SenderState : public Packet::SenderState
|
||||
{
|
||||
SubBlock* subBlock;
|
||||
Packet::SenderState *saved;
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
RubyTester(const RubyTester& obj);
|
||||
RubyTester& operator=(const RubyTester& obj);
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
|
||||
CheckTable* m_checkTable_ptr;
|
||||
Vector<Time> m_last_progress_vector;
|
||||
SenderState(Address addr, int size,
|
||||
Packet::SenderState *sender_state = NULL)
|
||||
: saved(sender_state)
|
||||
{
|
||||
subBlock = new SubBlock(addr, size);
|
||||
}
|
||||
|
||||
uint64 m_checks_completed;
|
||||
std::vector<CpuPort*> ports;
|
||||
uint64 m_checks_to_complete;
|
||||
int m_deadlock_threshold;
|
||||
int m_num_cpu_sequencers;
|
||||
int m_wakeup_frequency;
|
||||
~SenderState()
|
||||
{
|
||||
delete subBlock;
|
||||
}
|
||||
};
|
||||
|
||||
typedef RubyTesterParams Params;
|
||||
RubyTester(const Params *p);
|
||||
~RubyTester();
|
||||
|
||||
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||
|
||||
Port* getCpuPort(int idx);
|
||||
|
||||
virtual void init();
|
||||
|
||||
void wakeup();
|
||||
|
||||
void incrementCheckCompletions() { m_checks_completed++; }
|
||||
|
||||
void printStats(ostream& out) const {}
|
||||
void clearStats() {}
|
||||
void printConfig(ostream& out) const {}
|
||||
|
||||
void print(ostream& out) const;
|
||||
|
||||
protected:
|
||||
class CheckStartEvent : public Event
|
||||
{
|
||||
private:
|
||||
RubyTester *tester;
|
||||
|
||||
public:
|
||||
CheckStartEvent(RubyTester *_tester)
|
||||
: Event(CPU_Tick_Pri), tester(_tester)
|
||||
{}
|
||||
void process() { tester->wakeup(); }
|
||||
virtual const char *description() const { return "RubyTester tick"; }
|
||||
};
|
||||
|
||||
CheckStartEvent checkStartEvent;
|
||||
|
||||
private:
|
||||
void hitCallback(NodeID proc, SubBlock* data);
|
||||
|
||||
void checkForDeadlock();
|
||||
|
||||
// Private copy constructor and assignment operator
|
||||
RubyTester(const RubyTester& obj);
|
||||
RubyTester& operator=(const RubyTester& obj);
|
||||
|
||||
CheckTable* m_checkTable_ptr;
|
||||
Vector<Time> m_last_progress_vector;
|
||||
|
||||
uint64 m_checks_completed;
|
||||
std::vector<CpuPort*> ports;
|
||||
uint64 m_checks_to_complete;
|
||||
int m_deadlock_threshold;
|
||||
int m_num_cpu_sequencers;
|
||||
int m_wakeup_frequency;
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
ostream& operator<<(ostream& out, const RubyTester& obj);
|
||||
|
||||
// ******************* Definitions *******************
|
||||
|
||||
// Output operator definition
|
||||
extern inline
|
||||
ostream& operator<<(ostream& out, const RubyTester& obj)
|
||||
inline ostream&
|
||||
operator<<(ostream& out, const RubyTester& obj)
|
||||
{
|
||||
obj.print(out);
|
||||
out << flush;
|
||||
return out;
|
||||
obj.print(out);
|
||||
out << flush;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif //RUBY_TESTER_H
|
||||
#endif // __CPU_RUBYTEST_RUBYTESTER_HH__
|
||||
|
|
Loading…
Reference in a new issue