RubyTester.cc revision 7632
15222Sksewell@umich.edu/* 25268Sksewell@umich.edu * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 35268Sksewell@umich.edu * Copyright (c) 2009 Advanced Micro Devices, Inc. 45222Sksewell@umich.edu * All rights reserved. 55268Sksewell@umich.edu * 65268Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without 75268Sksewell@umich.edu * modification, are permitted provided that the following conditions are 85268Sksewell@umich.edu * met: redistributions of source code must retain the above copyright 95268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer; 105268Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright 115268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the 125268Sksewell@umich.edu * documentation and/or other materials provided with the distribution; 135268Sksewell@umich.edu * neither the name of the copyright holders nor the names of its 145268Sksewell@umich.edu * contributors may be used to endorse or promote products derived from 155222Sksewell@umich.edu * this software without specific prior written permission. 165268Sksewell@umich.edu * 175268Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 185268Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 195268Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 205268Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 215268Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 225268Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 235268Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 245268Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 255268Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 265268Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 275222Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 285222Sksewell@umich.edu */ 295222Sksewell@umich.edu 305222Sksewell@umich.edu#include "cpu/testers/rubytest/Check.hh" 315222Sksewell@umich.edu#include "cpu/testers/rubytest/RubyTester.hh" 3211793Sbrandon.potter@amd.com#include "mem/ruby/common/Global.hh" 335222Sksewell@umich.edu#include "mem/ruby/common/SubBlock.hh" 345222Sksewell@umich.edu#include "mem/ruby/eventqueue/RubyEventQueue.hh" 355222Sksewell@umich.edu#include "mem/ruby/system/System.hh" 365222Sksewell@umich.edu#include "sim/sim_exit.hh" 375222Sksewell@umich.edu 385222Sksewell@umich.eduRubyTester::RubyTester(const Params *p) 395222Sksewell@umich.edu : MemObject(p), checkStartEvent(this), 405222Sksewell@umich.edu m_checks_to_complete(p->checks_to_complete), 415222Sksewell@umich.edu m_deadlock_threshold(p->deadlock_threshold), 425222Sksewell@umich.edu m_wakeup_frequency(p->wakeup_frequency) 435222Sksewell@umich.edu{ 445222Sksewell@umich.edu m_checks_completed = 0; 455222Sksewell@umich.edu 465222Sksewell@umich.edu // add the check start event to the event queue 475222Sksewell@umich.edu schedule(checkStartEvent, 1); 48} 49 50RubyTester::~RubyTester() 51{ 52 delete m_checkTable_ptr; 53 for (int i = 0; i < ports.size(); i++) 54 delete ports[i]; 55} 56 57void 58RubyTester::init() 59{ 60 assert(ports.size() > 0); 61 62 m_last_progress_vector.resize(ports.size()); 63 for (int i = 0; i < m_last_progress_vector.size(); i++) { 64 m_last_progress_vector[i] = 0; 65 } 66 67 m_num_cpu_sequencers = ports.size(); 68 69 m_checkTable_ptr = new CheckTable(m_num_cpu_sequencers, this); 70} 71 72Port * 73RubyTester::getPort(const std::string &if_name, int idx) 74{ 75 if (if_name != "cpuPort") { 76 panic("RubyTester::getPort: unknown port %s requested", if_name); 77 } 78 79 if (idx >= (int)ports.size()) { 80 ports.resize(idx + 1); 81 } 82 83 if (ports[idx] != NULL) { 84 panic("RubyTester::getPort: port %d already assigned", idx); 85 } 86 87 CpuPort *port = new CpuPort(csprintf("%s-port%d", name(), idx), this, idx); 88 89 ports[idx] = port; 90 return port; 91} 92 93Tick 94RubyTester::CpuPort::recvAtomic(PacketPtr pkt) 95{ 96 panic("RubyTester::CpuPort::recvAtomic() not implemented!\n"); 97 return 0; 98} 99 100bool 101RubyTester::CpuPort::recvTiming(PacketPtr pkt) 102{ 103 // retrieve the subblock and call hitCallback 104 RubyTester::SenderState* senderState = 105 safe_cast<RubyTester::SenderState*>(pkt->senderState); 106 SubBlock* subblock = senderState->subBlock; 107 assert(subblock != NULL); 108 109 // pop the sender state from the packet 110 pkt->senderState = senderState->saved; 111 112 tester->hitCallback(idx, subblock); 113 114 // Now that the tester has completed, delete the senderState 115 // (includes sublock) and the packet, then return 116 delete senderState; 117 delete pkt->req; 118 delete pkt; 119 return true; 120} 121 122Port* 123RubyTester::getCpuPort(int idx) 124{ 125 assert(idx >= 0 && idx < ports.size()); 126 127 return ports[idx]; 128} 129 130void 131RubyTester::hitCallback(NodeID proc, SubBlock* data) 132{ 133 // Mark that we made progress 134 m_last_progress_vector[proc] = g_eventQueue_ptr->getTime(); 135 136 DPRINTF(RubyTest, "completed request for proc: %d\n", proc); 137 DPRINTF(RubyTest, "addr: 0x%x, size: %d, data: ", 138 data->getAddress(), data->getSize()); 139 for (int byte = 0; byte < data->getSize(); byte++) { 140 DPRINTF(RubyTest, "%d", data->getByte(byte)); 141 } 142 DPRINTF(RubyTest, "\n"); 143 144 // This tells us our store has 'completed' or for a load gives us 145 // back the data to make the check 146 Check* check_ptr = m_checkTable_ptr->getCheck(data->getAddress()); 147 assert(check_ptr != NULL); 148 check_ptr->performCallback(proc, data); 149} 150 151void 152RubyTester::wakeup() 153{ 154 if (m_checks_completed < m_checks_to_complete) { 155 // Try to perform an action or check 156 Check* check_ptr = m_checkTable_ptr->getRandomCheck(); 157 assert(check_ptr != NULL); 158 check_ptr->initiate(); 159 160 checkForDeadlock(); 161 162 schedule(checkStartEvent, curTick + m_wakeup_frequency); 163 } else { 164 exitSimLoop("Ruby Tester completed"); 165 } 166} 167 168void 169RubyTester::checkForDeadlock() 170{ 171 int size = m_last_progress_vector.size(); 172 Time current_time = g_eventQueue_ptr->getTime(); 173 for (int processor = 0; processor < size; processor++) { 174 if ((current_time - m_last_progress_vector[processor]) > 175 m_deadlock_threshold) { 176 WARN_EXPR(current_time); 177 WARN_EXPR(m_last_progress_vector[processor]); 178 WARN_EXPR(current_time - m_last_progress_vector[processor]); 179 WARN_EXPR(processor); 180 ERROR_MSG("Deadlock detected."); 181 } 182 } 183} 184 185void 186RubyTester::print(std::ostream& out) const 187{ 188 out << "[RubyTester]" << std::endl; 189} 190 191RubyTester * 192RubyTesterParams::create() 193{ 194 return new RubyTester(this); 195} 196