diff --git a/src/cpu/rubytest/Check.cc b/src/cpu/rubytest/Check.cc index 3b358e633..ca7ca8457 100644 --- a/src/cpu/rubytest/Check.cc +++ b/src/cpu/rubytest/Check.cc @@ -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 \ - (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(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 \ - (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()), - *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(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 \ - (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(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_numbergetByte(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(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(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(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()), *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(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(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(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_numbergetByte(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); } diff --git a/src/cpu/rubytest/Check.hh b/src/cpu/rubytest/Check.hh index ce42ed376..5f621a018 100644 --- a/src/cpu/rubytest/Check.hh +++ b/src/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,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<; - physical_address_t physical = 0; - Address address; + m_lookup_map_ptr = new Map; + 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; iexist(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; iadd(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 { } diff --git a/src/cpu/rubytest/CheckTable.hh b/src/cpu/rubytest/CheckTable.hh index 8b05e6541..a22fa7f73 100644 --- a/src/cpu/rubytest/CheckTable.hh +++ b/src/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,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 -#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 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 m_check_vector; - Map* 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 m_check_vector; + Map* 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__ diff --git a/src/cpu/rubytest/RubyTester.cc b/src/cpu/rubytest/RubyTester.cc index 547b0eb17..b2af22a6e 100644 --- a/src/cpu/rubytest/RubyTester.cc +++ b/src/cpu/rubytest/RubyTester.cc @@ -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(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(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 * diff --git a/src/cpu/rubytest/RubyTester.hh b/src/cpu/rubytest/RubyTester.hh index f1ed7e34e..f4cf4a04d 100644 --- a/src/cpu/rubytest/RubyTester.hh +++ b/src/cpu/rubytest/RubyTester.hh @@ -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