RubyTester.cc revision 7632
12131SN/A/* 25268Sksewell@umich.edu * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 35254Sksewell@umich.edu * Copyright (c) 2009 Advanced Micro Devices, Inc. 45254Sksewell@umich.edu * All rights reserved. 52131SN/A * 65254Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without 75254Sksewell@umich.edu * modification, are permitted provided that the following conditions are 85254Sksewell@umich.edu * met: redistributions of source code must retain the above copyright 95254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer; 105254Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright 115254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the 125254Sksewell@umich.edu * documentation and/or other materials provided with the distribution; 135254Sksewell@umich.edu * neither the name of the copyright holders nor the names of its 145254Sksewell@umich.edu * contributors may be used to endorse or promote products derived from 155254Sksewell@umich.edu * this software without specific prior written permission. 162131SN/A * 175254Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 185254Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 195254Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 205254Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 215254Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 225254Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 235254Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 245254Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 255254Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 265254Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 275254Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282665Ssaidi@eecs.umich.edu */ 295254Sksewell@umich.edu 305254Sksewell@umich.edu#include "cpu/testers/rubytest/Check.hh" 315222Sksewell@umich.edu#include "cpu/testers/rubytest/RubyTester.hh" 328696Sguodeyuan@tsinghua.org.cn#include "mem/ruby/common/Global.hh" 338696Sguodeyuan@tsinghua.org.cn#include "mem/ruby/common/SubBlock.hh" 342131SN/A#include "mem/ruby/eventqueue/RubyEventQueue.hh" 352131SN/A#include "mem/ruby/system/System.hh" 362239SN/A#include "sim/sim_exit.hh" 3711793Sbrandon.potter@amd.com 387676Snate@binkert.orgRubyTester::RubyTester(const Params *p) 397676Snate@binkert.org : MemObject(p), checkStartEvent(this), 407676Snate@binkert.org m_checks_to_complete(p->checks_to_complete), 412680Sktlim@umich.edu m_deadlock_threshold(p->deadlock_threshold), 428232Snate@binkert.org m_wakeup_frequency(p->wakeup_frequency) 437676Snate@binkert.org{ 442800Ssaidi@eecs.umich.edu m_checks_completed = 0; 452131SN/A 462447SN/A // add the check start event to the event queue 472447SN/A schedule(checkStartEvent, 1); 482131SN/A} 498566Sgblack@eecs.umich.edu 502131SN/ARubyTester::~RubyTester() 518578Sgblack@eecs.umich.edu{ 528578Sgblack@eecs.umich.edu delete m_checkTable_ptr; 538578Sgblack@eecs.umich.edu for (int i = 0; i < ports.size(); i++) 548578Sgblack@eecs.umich.edu delete ports[i]; 558578Sgblack@eecs.umich.edu} 568578Sgblack@eecs.umich.edu 578578Sgblack@eecs.umich.eduvoid 588578Sgblack@eecs.umich.eduRubyTester::init() 598578Sgblack@eecs.umich.edu{ 608578Sgblack@eecs.umich.edu assert(ports.size() > 0); 618578Sgblack@eecs.umich.edu 628578Sgblack@eecs.umich.edu m_last_progress_vector.resize(ports.size()); 638578Sgblack@eecs.umich.edu for (int i = 0; i < m_last_progress_vector.size(); i++) { 648578Sgblack@eecs.umich.edu m_last_progress_vector[i] = 0; 658578Sgblack@eecs.umich.edu } 668578Sgblack@eecs.umich.edu 678578Sgblack@eecs.umich.edu m_num_cpu_sequencers = ports.size(); 688578Sgblack@eecs.umich.edu 698578Sgblack@eecs.umich.edu m_checkTable_ptr = new CheckTable(m_num_cpu_sequencers, this); 708578Sgblack@eecs.umich.edu} 718578Sgblack@eecs.umich.edu 728566Sgblack@eecs.umich.eduPort * 738578Sgblack@eecs.umich.eduRubyTester::getPort(const std::string &if_name, int idx) 742447SN/A{ 758566Sgblack@eecs.umich.edu if (if_name != "cpuPort") { 768578Sgblack@eecs.umich.edu panic("RubyTester::getPort: unknown port %s requested", if_name); 778578Sgblack@eecs.umich.edu } 788578Sgblack@eecs.umich.edu 798578Sgblack@eecs.umich.edu if (idx >= (int)ports.size()) { 808578Sgblack@eecs.umich.edu ports.resize(idx + 1); 818578Sgblack@eecs.umich.edu } 828578Sgblack@eecs.umich.edu 838578Sgblack@eecs.umich.edu if (ports[idx] != NULL) { 848578Sgblack@eecs.umich.edu panic("RubyTester::getPort: port %d already assigned", idx); 858578Sgblack@eecs.umich.edu } 868578Sgblack@eecs.umich.edu 878578Sgblack@eecs.umich.edu CpuPort *port = new CpuPort(csprintf("%s-port%d", name(), idx), this, idx); 888578Sgblack@eecs.umich.edu 892447SN/A ports[idx] = port; 908566Sgblack@eecs.umich.edu return port; 918578Sgblack@eecs.umich.edu} 925222Sksewell@umich.edu 938573Sgblack@eecs.umich.eduTick 948578Sgblack@eecs.umich.eduRubyTester::CpuPort::recvAtomic(PacketPtr pkt) 955222Sksewell@umich.edu{ 968573Sgblack@eecs.umich.edu panic("RubyTester::CpuPort::recvAtomic() not implemented!\n"); 978578Sgblack@eecs.umich.edu return 0; 982447SN/A} 998737Skoansin.tan@gmail.com 1008578Sgblack@eecs.umich.edubool 1014661Sksewell@umich.eduRubyTester::CpuPort::recvTiming(PacketPtr pkt) 1026378Sgblack@eecs.umich.edu{ 1038566Sgblack@eecs.umich.edu // retrieve the subblock and call hitCallback 1045222Sksewell@umich.edu RubyTester::SenderState* senderState = 1056378Sgblack@eecs.umich.edu safe_cast<RubyTester::SenderState*>(pkt->senderState); 1066383Sgblack@eecs.umich.edu SubBlock* subblock = senderState->subBlock; 1076379Sgblack@eecs.umich.edu assert(subblock != NULL); 1086378Sgblack@eecs.umich.edu 1096383Sgblack@eecs.umich.edu // pop the sender state from the packet 1106379Sgblack@eecs.umich.edu pkt->senderState = senderState->saved; 1116379Sgblack@eecs.umich.edu 1126383Sgblack@eecs.umich.edu tester->hitCallback(idx, subblock); 1135222Sksewell@umich.edu 1145222Sksewell@umich.edu // Now that the tester has completed, delete the senderState 1156378Sgblack@eecs.umich.edu // (includes sublock) and the packet, then return 1166379Sgblack@eecs.umich.edu delete senderState; 1176383Sgblack@eecs.umich.edu delete pkt->req; 1185222Sksewell@umich.edu delete pkt; 1196378Sgblack@eecs.umich.edu return true; 1208574Sgblack@eecs.umich.edu} 1218574Sgblack@eecs.umich.edu 1228574Sgblack@eecs.umich.eduPort* 1238574Sgblack@eecs.umich.eduRubyTester::getCpuPort(int idx) 1248696Sguodeyuan@tsinghua.org.cn{ 1255222Sksewell@umich.edu assert(idx >= 0 && idx < ports.size()); 1266378Sgblack@eecs.umich.edu 1276383Sgblack@eecs.umich.edu return ports[idx]; 1286379Sgblack@eecs.umich.edu} 1298574Sgblack@eecs.umich.edu 1306379Sgblack@eecs.umich.eduvoid 1316383Sgblack@eecs.umich.eduRubyTester::hitCallback(NodeID proc, SubBlock* data) 1326378Sgblack@eecs.umich.edu{ 1336378Sgblack@eecs.umich.edu // Mark that we made progress 1346378Sgblack@eecs.umich.edu m_last_progress_vector[proc] = g_eventQueue_ptr->getTime(); 13510417Sandreas.hansson@arm.com 1366378Sgblack@eecs.umich.edu DPRINTF(RubyTest, "completed request for proc: %d\n", proc); 1378738Sgblack@eecs.umich.edu DPRINTF(RubyTest, "addr: 0x%x, size: %d, data: ", 1388578Sgblack@eecs.umich.edu data->getAddress(), data->getSize()); 1398578Sgblack@eecs.umich.edu for (int byte = 0; byte < data->getSize(); byte++) { 1408578Sgblack@eecs.umich.edu DPRINTF(RubyTest, "%d", data->getByte(byte)); 1416378Sgblack@eecs.umich.edu } 1428578Sgblack@eecs.umich.edu DPRINTF(RubyTest, "\n"); 1436378Sgblack@eecs.umich.edu 1446378Sgblack@eecs.umich.edu // This tells us our store has 'completed' or for a load gives us 1456378Sgblack@eecs.umich.edu // back the data to make the check 1466378Sgblack@eecs.umich.edu Check* check_ptr = m_checkTable_ptr->getCheck(data->getAddress()); 14710417Sandreas.hansson@arm.com assert(check_ptr != NULL); 1484661Sksewell@umich.edu check_ptr->performCallback(proc, data); 1498738Sgblack@eecs.umich.edu} 1508578Sgblack@eecs.umich.edu 1518578Sgblack@eecs.umich.eduvoid 1528578Sgblack@eecs.umich.eduRubyTester::wakeup() 1538578Sgblack@eecs.umich.edu{ 1548578Sgblack@eecs.umich.edu if (m_checks_completed < m_checks_to_complete) { 1558578Sgblack@eecs.umich.edu // Try to perform an action or check 1565224Sksewell@umich.edu Check* check_ptr = m_checkTable_ptr->getRandomCheck(); 1576378Sgblack@eecs.umich.edu assert(check_ptr != NULL); 1586383Sgblack@eecs.umich.edu check_ptr->initiate(); 1596379Sgblack@eecs.umich.edu 1606383Sgblack@eecs.umich.edu checkForDeadlock(); 1615222Sksewell@umich.edu 1625222Sksewell@umich.edu schedule(checkStartEvent, curTick + m_wakeup_frequency); 1636378Sgblack@eecs.umich.edu } else { 16410417Sandreas.hansson@arm.com exitSimLoop("Ruby Tester completed"); 1655222Sksewell@umich.edu } 1668578Sgblack@eecs.umich.edu} 1675222Sksewell@umich.edu 1685222Sksewell@umich.eduvoid 1696378Sgblack@eecs.umich.eduRubyTester::checkForDeadlock() 17010417Sandreas.hansson@arm.com{ 1715222Sksewell@umich.edu int size = m_last_progress_vector.size(); 1728578Sgblack@eecs.umich.edu Time current_time = g_eventQueue_ptr->getTime(); 1734661Sksewell@umich.edu for (int processor = 0; processor < size; processor++) { 1744661Sksewell@umich.edu if ((current_time - m_last_progress_vector[processor]) > 1752447SN/A m_deadlock_threshold) { 1762447SN/A 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