Check.cc revision 6899
16145SN/A 28688SN/A/* 36145SN/A * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 46145SN/A * Copyright (c) 2009 Advanced Micro Devices, Inc. 56145SN/A * All rights reserved. 66145SN/A * 76145SN/A * Redistribution and use in source and binary forms, with or without 86145SN/A * modification, are permitted provided that the following conditions are 96145SN/A * met: redistributions of source code must retain the above copyright 106145SN/A * notice, this list of conditions and the following disclaimer; 116145SN/A * redistributions in binary form must reproduce the above copyright 126145SN/A * notice, this list of conditions and the following disclaimer in the 136145SN/A * documentation and/or other materials provided with the distribution; 146145SN/A * neither the name of the copyright holders nor the names of its 156145SN/A * contributors may be used to endorse or promote products derived from 166145SN/A * this software without specific prior written permission. 176145SN/A * 186145SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 196145SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 206145SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 216145SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 226145SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 236145SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 246145SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 256145SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 266145SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 276145SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 286145SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 296145SN/A */ 307039SN/A 317039SN/A 327039SN/A#include "cpu/rubytest/Check.hh" 336145SN/A#include "mem/ruby/system/Sequencer.hh" 346145SN/A#include "mem/ruby/system/System.hh" 357039SN/A#include "mem/ruby/common/SubBlock.hh" 367039SN/A 376145SN/ACheck::Check(const Address& address, 387039SN/A const Address& pc, 399350SN/A int _num_cpu_sequencers, 4011108Sdavid.hashe@amd.com RubyTester* _tester) 4110301SN/A : m_num_cpu_sequencers(_num_cpu_sequencers), m_tester_ptr(_tester) 4210301SN/A{ 4310301SN/A m_status = TesterStatus_Idle; 447039SN/A 459206SN/A pickValue(); 466145SN/A pickInitiatingNode(); 477039SN/A changeAddress(address); 4810920SN/A m_pc = pc; 496285SN/A m_access_mode = AccessModeType(random() % AccessModeType_NUM); 509206SN/A m_store_count = 0; 517039SN/A} 527039SN/A 538688SN/Avoid Check::initiate() 548688SN/A{ 558688SN/A DPRINTF(RubyTest, "initiating\n"); 568688SN/A debugPrint(); 578688SN/A 5810919SN/A // 598688SN/A // currently no protocols support prefetches 608688SN/A // 618688SN/A if (false && (random() & 0xf) == 0) { 628688SN/A initiatePrefetch(); // Prefetch from random processor 6310919SN/A } 648688SN/A 658688SN/A if(m_status == TesterStatus_Idle) { 668688SN/A initiateAction(); 678688SN/A } else if(m_status == TesterStatus_Ready) { 686876SN/A initiateCheck(); 696876SN/A } else { 707039SN/A // Pending - do nothing 716145SN/A DPRINTF(RubyTest, "initiating action/check - failed: action/check is pending\n"); 727039SN/A } 737039SN/A} 749504SN/A 759504SN/Avoid Check::initiatePrefetch() 769504SN/A{ 7710837SN/A DPRINTF(RubyTest, "initiating prefetch\n"); 7810837SN/A 796285SN/A RubyTester::CpuPort* port 8010525SN/A = safe_cast<RubyTester::CpuPort*> \ 8110918SN/A (m_tester_ptr->getCpuPort(random() % m_num_cpu_sequencers)); 8211294Sandreas.hansson@arm.com 8310525SN/A Request::Flags flags; 847039SN/A flags.set(Request::PREFETCH); 857039SN/A 867039SN/A // 877039SN/A // Prefetches are assumed to be 0 sized 8810012SN/A // 8910012SN/A Request *req = new Request(m_address.getAddress(), 907039SN/A 0, 916285SN/A flags, 9211169Sandreas.hansson@arm.com curTick, 9310012SN/A m_pc.getAddress()); 9411169Sandreas.hansson@arm.com 956285SN/A Packet::Command cmd; 9611169Sandreas.hansson@arm.com 9711168Sandreas.hansson@arm.com // 9811168Sandreas.hansson@arm.com // 1 in 8 chance this will be an exclusive prefetch 9911168Sandreas.hansson@arm.com // 1008688SN/A if ((random() & 0x7) != 0) { 10111169Sandreas.hansson@arm.com cmd = MemCmd::ReadReq; 1029270SN/A // 1039270SN/A // 50% chance that the request will be an instruction fetch 1047562SN/A // 1058436SN/A if ((random() & 0x1) == 0) { 1068436SN/A flags.set(Request::INST_FETCH); 1078436SN/A } 1088937SN/A } else { 1098937SN/A cmd = MemCmd::WriteReq; 1108937SN/A flags.set(Request::PF_EXCLUSIVE); 1118937SN/A } 1128937SN/A 1138937SN/A PacketPtr pkt = new Packet(req, cmd, port->idx); 1148937SN/A 1157039SN/A // 1167039SN/A // push the subblock onto the sender state. The sequencer will update the 1177039SN/A // subblock on the return 1187039SN/A // 1196285SN/A pkt->senderState = new RubyTester::SenderState(m_address, 12010991SN/A req->getSize(), 12111061SN/A pkt->senderState); 12211061SN/A 12310991SN/A if (port->sendTiming(pkt)) { 12411060SN/A DPRINTF(RubyTest, "successfully initiated prefetch.\n"); 12511060SN/A } else { 12611061SN/A // 12711060SN/A // If the packet did not issue, must delete 12811061SN/A // 1297039SN/A RubyTester::SenderState* senderState = 1307039SN/A safe_cast<RubyTester::SenderState*>(pkt->senderState); 1317039SN/A pkt->senderState = senderState->saved; 1327039SN/A delete senderState; 1339504SN/A delete pkt->req; 1349504SN/A delete pkt; 1359504SN/A 13610919SN/A DPRINTF(RubyTest, "prefetch initiation failed because Port was busy.\n"); 13710837SN/A } 13810837SN/A} 13910837SN/A 14010525SN/Avoid Check::initiateAction() 14110706SN/A{ 1427039SN/A DPRINTF(RubyTest, "initiating Action\n"); 14310012SN/A assert(m_status == TesterStatus_Idle); 1449300SN/A 14510918SN/A RubyTester::CpuPort* port 1469103SN/A = safe_cast<RubyTester::CpuPort*> \ 1477039SN/A (m_tester_ptr->getCpuPort(random() % m_num_cpu_sequencers)); 14810012SN/A 1498688SN/A Request::Flags flags; 15010920SN/A 1516145SN/A // 1526145SN/A // Create the particular address for the next byte to be written 15310012SN/A // 1546895SN/A Address writeAddr(m_address.getAddress() + m_store_count); 1556895SN/A 15610919SN/A // 1576895SN/A // Stores are assumed to be 1 byte-sized 1586895SN/A // 15910012SN/A Request *req = new Request(writeAddr.getAddress(), 16010919SN/A 1, 16110919SN/A flags, 1626895SN/A curTick, 1636895SN/A m_pc.getAddress()); 1647039SN/A 165 Packet::Command cmd; 166 167 // 168 // 1 out of 8 chance, issue an atomic rather than a write 169 // 170// if ((random() & 0x7) == 0) { 171// cmd = MemCmd::SwapReq; 172// } else { 173 cmd = MemCmd::WriteReq; 174// } 175 176 PacketPtr pkt = new Packet(req, cmd, port->idx); 177 uint8_t* writeData = new uint8_t; 178 *writeData = m_value + m_store_count; 179 pkt->dataDynamic(writeData); 180 181 DPRINTF(RubyTest, 182 "data 0x%x check 0x%x\n", 183 *(pkt->getPtr<uint8_t>()), 184 *writeData); 185 186 // 187 // push the subblock onto the sender state. The sequencer will update the 188 // subblock on the return 189 // 190 pkt->senderState = new RubyTester::SenderState(writeAddr, 191 req->getSize(), 192 pkt->senderState); 193 194 if (port->sendTiming(pkt)) { 195 DPRINTF(RubyTest, "initiating action - successful\n"); 196 DPRINTF(RubyTest, 197 "status before action update: %s\n", 198 (TesterStatus_to_string(m_status)).c_str()); 199 m_status = TesterStatus_Action_Pending; 200 } else { 201 // 202 // If the packet did not issue, must delete 203 // Note: No need to delete the data, the packet destructor will delete it 204 // 205 RubyTester::SenderState* senderState = 206 safe_cast<RubyTester::SenderState*>(pkt->senderState); 207 pkt->senderState = senderState->saved; 208 delete senderState; 209 delete pkt->req; 210 delete pkt; 211 212 DPRINTF(RubyTest, "failed to initiate action - sequencer not ready\n"); 213 } 214 215 DPRINTF(RubyTest, 216 "status after action update: %s\n", 217 (TesterStatus_to_string(m_status)).c_str()); 218} 219 220void Check::initiateCheck() 221{ 222 DPRINTF(RubyTest, "Initiating Check\n"); 223 assert(m_status == TesterStatus_Ready); 224 225 RubyTester::CpuPort* port 226 = safe_cast<RubyTester::CpuPort*> \ 227 (m_tester_ptr->getCpuPort(random() % m_num_cpu_sequencers)); 228 229 Request::Flags flags; 230 231 // 232 // Checks are sized depending on the number of bytes written 233 // 234 Request *req = new Request(m_address.getAddress(), 235 CHECK_SIZE, 236 flags, 237 curTick, 238 m_pc.getAddress()); 239 240 // 241 // 50% chance that the request will be an instruction fetch 242 // 243 if ((random() & 0x1) == 0) { 244 flags.set(Request::INST_FETCH); 245 } 246 247 PacketPtr pkt = new Packet(req, MemCmd::ReadReq, port->idx); 248 uint8_t* dataArray = new uint8_t[CHECK_SIZE]; 249 pkt->dataDynamicArray(dataArray); 250 251 // 252 // push the subblock onto the sender state. The sequencer will update the 253 // subblock on the return 254 // 255 pkt->senderState = new RubyTester::SenderState(m_address, 256 req->getSize(), 257 pkt->senderState); 258 259 if (port->sendTiming(pkt)) { 260 DPRINTF(RubyTest, "initiating check - successful\n"); 261 DPRINTF(RubyTest, 262 "status before check update: %s\n", 263 (TesterStatus_to_string(m_status)).c_str()); 264 m_status = TesterStatus_Check_Pending; 265 } else { 266 // 267 // If the packet did not issue, must delete 268 // Note: No need to delete the data, the packet destructor will delete it 269 // 270 RubyTester::SenderState* senderState = 271 safe_cast<RubyTester::SenderState*>(pkt->senderState); 272 pkt->senderState = senderState->saved; 273 delete senderState; 274 delete pkt->req; 275 delete pkt; 276 277 DPRINTF(RubyTest, "failed to initiate check - cpu port not ready\n"); 278 } 279 280 DPRINTF(RubyTest, 281 "status after check update: %s\n", 282 (TesterStatus_to_string(m_status)).c_str()); 283} 284 285void Check::performCallback(NodeID proc, SubBlock* data) 286{ 287 Address address = data->getAddress(); 288 // assert(getAddress() == address); // This isn't exactly right since we now have multi-byte checks 289 assert(getAddress().getLineAddress() == address.getLineAddress()); 290 assert(data != NULL); 291 292 DPRINTF(RubyTest, "RubyTester Callback\n"); 293 debugPrint(); 294 295 if (m_status == TesterStatus_Action_Pending) { 296 DPRINTF(RubyTest, 297 "Action callback write value: %d, currently %d\n", 298 (m_value + m_store_count), 299 data->getByte(0)); 300 // 301 // Perform store one byte at a time 302 // 303 data->setByte(0, (m_value + m_store_count)); 304 m_store_count++; 305 if (m_store_count == CHECK_SIZE) { 306 m_status = TesterStatus_Ready; 307 } else { 308 m_status = TesterStatus_Idle; 309 } 310 DPRINTF(RubyTest, 311 "Action callback return data now %d\n", 312 data->getByte(0)); 313 } else if (m_status == TesterStatus_Check_Pending) { 314 DPRINTF(RubyTest, "Check callback\n"); 315 // Perform load/check 316 for(int byte_number=0; byte_number<CHECK_SIZE; byte_number++) { 317 if (uint8(m_value+byte_number) != data->getByte(byte_number)) { 318 WARN_EXPR(proc); 319 WARN_EXPR(address); 320 WARN_EXPR(data); 321 WARN_EXPR(byte_number); 322 WARN_EXPR((int)m_value+byte_number); 323 WARN_EXPR((int)data->getByte(byte_number)); 324 WARN_EXPR(*this); 325 WARN_EXPR(g_eventQueue_ptr->getTime()); 326 ERROR_MSG("Action/check failure"); 327 } 328 } 329 DPRINTF(RubyTest, "Action/check success\n"); 330 debugPrint(); 331 332 // successful check complete, increment complete 333 m_tester_ptr->incrementCheckCompletions(); 334 335 m_status = TesterStatus_Idle; 336 pickValue(); 337 338 } else { 339 WARN_EXPR(*this); 340 WARN_EXPR(proc); 341 WARN_EXPR(data); 342 WARN_EXPR(m_status); 343 WARN_EXPR(g_eventQueue_ptr->getTime()); 344 ERROR_MSG("Unexpected TesterStatus"); 345 } 346 347 DPRINTF(RubyTest, "proc: %d, Address: 0x%x\n", proc, getAddress().getLineAddress()); 348 DPRINTF(RubyTest, "Callback done\n"); 349 debugPrint(); 350} 351 352void Check::changeAddress(const Address& address) 353{ 354 assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready)); 355 m_status = TesterStatus_Idle; 356 m_address = address; 357 m_store_count = 0; 358} 359 360void Check::pickValue() 361{ 362 assert(m_status == TesterStatus_Idle); 363 m_status = TesterStatus_Idle; 364 m_value = random() & 0xff; // One byte 365 m_store_count = 0; 366} 367 368void Check::pickInitiatingNode() 369{ 370 assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready)); 371 m_status = TesterStatus_Idle; 372 m_initiatingNode = (random() % m_num_cpu_sequencers); 373 DPRINTF(RubyTest, "picked initiating node %d\n", m_initiatingNode); 374 m_store_count = 0; 375} 376 377void Check::print(ostream& out) const 378{ 379 out << "[" 380 << m_address << ", value: " 381 << (int) m_value << ", status: " 382 << m_status << ", initiating node: " 383 << m_initiatingNode << ", store_count: " 384 << m_store_count 385 << "]" << flush; 386} 387 388void Check::debugPrint() 389{ 390 DPRINTF(RubyTest, 391 "[0x%x, value: %d, status: %s, initiating node: %d, store_count: %d]\n", 392 m_address.getAddress(), 393 (int)m_value, 394 (TesterStatus_to_string(m_status)).c_str(), 395 m_initiatingNode, 396 m_store_count); 397} 398