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