diff options
Diffstat (limited to 'src/cpu/rubytest/Check.cc')
-rw-r--r-- | src/cpu/rubytest/Check.cc | 607 |
1 files changed, 283 insertions, 324 deletions
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; - - pickValue(); - pickInitiatingNode(); - changeAddress(address); - m_pc = pc; - m_access_mode = AccessModeType(random() % AccessModeType_NUM); - m_store_count = 0; + m_status = TesterStatus_Idle; + + 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"); - } + 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() +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); + 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"); } - } 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() +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 { + 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 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", + // } + + 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()); - 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() +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()); + 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) +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; + 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 { - 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(*this); 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(m_status); 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(); + ERROR_MSG("Unexpected TesterStatus"); + } - } 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(); + DPRINTF(RubyTest, "proc: %d, Address: 0x%x\n", proc, + getAddress().getLineAddress()); + DPRINTF(RubyTest, "Callback done\n"); + debugPrint(); } -void Check::changeAddress(const Address& address) +void +Check::changeAddress(const Address& address) { - 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_Ready); + m_status = TesterStatus_Idle; + m_address = address; + m_store_count = 0; } -void Check::pickValue() +void +Check::pickValue() { - 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_Idle; + m_value = random() & 0xff; // One byte + m_store_count = 0; } -void Check::pickInitiatingNode() +void +Check::pickInitiatingNode() { - 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; + 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::print(ostream& out) const +void +Check::print(ostream& out) const { - out << "[" - << m_address << ", value: " - << (int) m_value << ", status: " - << m_status << ", initiating node: " - << m_initiatingNode << ", store_count: " - << m_store_count - << "]" << flush; + out << "[" + << m_address << ", value: " + << (int)m_value << ", status: " + << m_status << ", initiating node: " + << m_initiatingNode << ", store_count: " + << m_store_count + << "]" << flush; } -void Check::debugPrint() +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); } |