Check.cc (10566:c99c8d2a7c31) | Check.cc (11017:6ec228f6c143) |
---|---|
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/random.hh" 31#include "cpu/testers/rubytest/Check.hh" 32#include "debug/RubyTest.hh" 33#include "mem/ruby/common/SubBlock.hh" | 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/random.hh" 31#include "cpu/testers/rubytest/Check.hh" 32#include "debug/RubyTest.hh" 33#include "mem/ruby/common/SubBlock.hh" |
34#include "mem/ruby/system/Sequencer.hh" 35#include "mem/ruby/system/System.hh" | |
36 37typedef RubyTester::SenderState SenderState; 38 39Check::Check(const Address& address, const Address& pc, 40 int _num_writers, int _num_readers, RubyTester* _tester) 41 : m_num_writers(_num_writers), m_num_readers(_num_readers), 42 m_tester_ptr(_tester) 43{ 44 m_status = TesterStatus_Idle; 45 46 pickValue(); 47 pickInitiatingNode(); 48 changeAddress(address); 49 m_pc = pc; 50 m_access_mode = RubyAccessMode(random_mt.random(0, 51 RubyAccessMode_NUM - 1)); 52 m_store_count = 0; 53} 54 55void 56Check::initiate() 57{ 58 DPRINTF(RubyTest, "initiating\n"); 59 debugPrint(); 60 61 // currently no protocols support prefetches 62 if (false && (random_mt.random(0, 0xf) == 0)) { 63 initiatePrefetch(); // Prefetch from random processor 64 } 65 66 if (m_tester_ptr->getCheckFlush() && (random_mt.random(0, 0xff) == 0)) { 67 initiateFlush(); // issue a Flush request from random processor 68 } 69 70 if (m_status == TesterStatus_Idle) { 71 initiateAction(); 72 } else if (m_status == TesterStatus_Ready) { 73 initiateCheck(); 74 } else { 75 // Pending - do nothing 76 DPRINTF(RubyTest, 77 "initiating action/check - failed: action/check is pending\n"); 78 } 79} 80 81void 82Check::initiatePrefetch() 83{ 84 DPRINTF(RubyTest, "initiating prefetch\n"); 85 86 int index = random_mt.random(0, m_num_readers - 1); 87 MasterPort* port = m_tester_ptr->getReadableCpuPort(index); 88 89 Request::Flags flags; 90 flags.set(Request::PREFETCH); 91 92 Packet::Command cmd; 93 94 // 1 in 8 chance this will be an exclusive prefetch 95 if (random_mt.random(0, 0x7) != 0) { 96 cmd = MemCmd::ReadReq; 97 98 // if necessary, make the request an instruction fetch 99 if (m_tester_ptr->isInstReadableCpuPort(index)) { 100 flags.set(Request::INST_FETCH); 101 } 102 } else { 103 cmd = MemCmd::WriteReq; 104 flags.set(Request::PF_EXCLUSIVE); 105 } 106 107 // Prefetches are assumed to be 0 sized 108 Request *req = new Request(m_address.getAddress(), 0, flags, 109 m_tester_ptr->masterId(), curTick(), m_pc.getAddress()); 110 req->setThreadContext(index, 0); 111 112 PacketPtr pkt = new Packet(req, cmd); 113 // despite the oddity of the 0 size (questionable if this should 114 // even be allowed), a prefetch is still a read and as such needs 115 // a place to store the result 116 uint8_t *data = new uint8_t[1]; 117 pkt->dataDynamic(data); 118 119 // push the subblock onto the sender state. The sequencer will 120 // update the subblock on the return 121 pkt->senderState = new SenderState(m_address, req->getSize()); 122 123 if (port->sendTimingReq(pkt)) { 124 DPRINTF(RubyTest, "successfully initiated prefetch.\n"); 125 } else { 126 // If the packet did not issue, must delete 127 delete pkt->senderState; 128 delete pkt->req; 129 delete pkt; 130 131 DPRINTF(RubyTest, 132 "prefetch initiation failed because Port was busy.\n"); 133 } 134} 135 136void 137Check::initiateFlush() 138{ 139 140 DPRINTF(RubyTest, "initiating Flush\n"); 141 142 int index = random_mt.random(0, m_num_writers - 1); 143 MasterPort* port = m_tester_ptr->getWritableCpuPort(index); 144 145 Request::Flags flags; 146 147 Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags, 148 m_tester_ptr->masterId(), curTick(), m_pc.getAddress()); 149 150 Packet::Command cmd; 151 152 cmd = MemCmd::FlushReq; 153 154 PacketPtr pkt = new Packet(req, cmd); 155 156 // push the subblock onto the sender state. The sequencer will 157 // update the subblock on the return 158 pkt->senderState = new SenderState(m_address, req->getSize()); 159 160 if (port->sendTimingReq(pkt)) { 161 DPRINTF(RubyTest, "initiating Flush - successful\n"); 162 } 163} 164 165void 166Check::initiateAction() 167{ 168 DPRINTF(RubyTest, "initiating Action\n"); 169 assert(m_status == TesterStatus_Idle); 170 171 int index = random_mt.random(0, m_num_writers - 1); 172 MasterPort* port = m_tester_ptr->getWritableCpuPort(index); 173 174 Request::Flags flags; 175 176 // Create the particular address for the next byte to be written 177 Address writeAddr(m_address.getAddress() + m_store_count); 178 179 // Stores are assumed to be 1 byte-sized 180 Request *req = new Request(writeAddr.getAddress(), 1, flags, 181 m_tester_ptr->masterId(), curTick(), 182 m_pc.getAddress()); 183 184 req->setThreadContext(index, 0); 185 Packet::Command cmd; 186 187 // 1 out of 8 chance, issue an atomic rather than a write 188 // if ((random() & 0x7) == 0) { 189 // cmd = MemCmd::SwapReq; 190 // } else { 191 cmd = MemCmd::WriteReq; 192 // } 193 194 PacketPtr pkt = new Packet(req, cmd); 195 uint8_t *writeData = new uint8_t[1]; 196 *writeData = m_value + m_store_count; 197 pkt->dataDynamic(writeData); 198 199 DPRINTF(RubyTest, "data 0x%x check 0x%x\n", 200 *(pkt->getConstPtr<uint8_t>()), *writeData); 201 202 // push the subblock onto the sender state. The sequencer will 203 // update the subblock on the return 204 pkt->senderState = new SenderState(writeAddr, req->getSize()); 205 206 if (port->sendTimingReq(pkt)) { 207 DPRINTF(RubyTest, "initiating action - successful\n"); 208 DPRINTF(RubyTest, "status before action update: %s\n", 209 (TesterStatus_to_string(m_status)).c_str()); 210 m_status = TesterStatus_Action_Pending; 211 } else { 212 // If the packet did not issue, must delete 213 // Note: No need to delete the data, the packet destructor 214 // will delete it 215 delete pkt->senderState; 216 delete pkt->req; 217 delete pkt; 218 219 DPRINTF(RubyTest, "failed to initiate action - sequencer not ready\n"); 220 } 221 222 DPRINTF(RubyTest, "status after action update: %s\n", 223 (TesterStatus_to_string(m_status)).c_str()); 224} 225 226void 227Check::initiateCheck() 228{ 229 DPRINTF(RubyTest, "Initiating Check\n"); 230 assert(m_status == TesterStatus_Ready); 231 232 int index = random_mt.random(0, m_num_readers - 1); 233 MasterPort* port = m_tester_ptr->getReadableCpuPort(index); 234 235 Request::Flags flags; 236 237 // If necessary, make the request an instruction fetch 238 if (m_tester_ptr->isInstReadableCpuPort(index)) { 239 flags.set(Request::INST_FETCH); 240 } 241 242 // Checks are sized depending on the number of bytes written 243 Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags, 244 m_tester_ptr->masterId(), curTick(), m_pc.getAddress()); 245 246 req->setThreadContext(index, 0); 247 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 248 uint8_t *dataArray = new uint8_t[CHECK_SIZE]; 249 pkt->dataDynamic(dataArray); 250 251 // push the subblock onto the sender state. The sequencer will 252 // update the subblock on the return 253 pkt->senderState = new SenderState(m_address, req->getSize()); 254 255 if (port->sendTimingReq(pkt)) { 256 DPRINTF(RubyTest, "initiating check - successful\n"); 257 DPRINTF(RubyTest, "status before check update: %s\n", 258 TesterStatus_to_string(m_status).c_str()); 259 m_status = TesterStatus_Check_Pending; 260 } else { 261 // If the packet did not issue, must delete 262 // Note: No need to delete the data, the packet destructor 263 // will delete it 264 delete pkt->senderState; 265 delete pkt->req; 266 delete pkt; 267 268 DPRINTF(RubyTest, "failed to initiate check - cpu port not ready\n"); 269 } 270 271 DPRINTF(RubyTest, "status after check update: %s\n", 272 TesterStatus_to_string(m_status).c_str()); 273} 274 275void 276Check::performCallback(NodeID proc, SubBlock* data, Cycles curTime) 277{ 278 Address address = data->getAddress(); 279 280 // This isn't exactly right since we now have multi-byte checks 281 // assert(getAddress() == address); 282 283 assert(getAddress().getLineAddress() == address.getLineAddress()); 284 assert(data != NULL); 285 286 DPRINTF(RubyTest, "RubyTester Callback\n"); 287 debugPrint(); 288 289 if (m_status == TesterStatus_Action_Pending) { 290 DPRINTF(RubyTest, "Action callback write value: %d, currently %d\n", 291 (m_value + m_store_count), data->getByte(0)); 292 // Perform store one byte at a time 293 data->setByte(0, (m_value + m_store_count)); 294 m_store_count++; 295 if (m_store_count == CHECK_SIZE) { 296 m_status = TesterStatus_Ready; 297 } else { 298 m_status = TesterStatus_Idle; 299 } 300 DPRINTF(RubyTest, "Action callback return data now %d\n", 301 data->getByte(0)); 302 } else if (m_status == TesterStatus_Check_Pending) { 303 DPRINTF(RubyTest, "Check callback\n"); 304 // Perform load/check 305 for (int byte_number=0; byte_number<CHECK_SIZE; byte_number++) { 306 if (uint8_t(m_value + byte_number) != data->getByte(byte_number)) { 307 panic("Action/check failure: proc: %d address: %s data: %s " 308 "byte_number: %d m_value+byte_number: %d byte: %d %s" 309 "Time: %d\n", 310 proc, address, data, byte_number, 311 (int)m_value + byte_number, 312 (int)data->getByte(byte_number), *this, curTime); 313 } 314 } 315 DPRINTF(RubyTest, "Action/check success\n"); 316 debugPrint(); 317 318 // successful check complete, increment complete 319 m_tester_ptr->incrementCheckCompletions(); 320 321 m_status = TesterStatus_Idle; 322 pickValue(); 323 324 } else { 325 panic("Unexpected TesterStatus: %s proc: %d data: %s m_status: %s " 326 "time: %d\n", *this, proc, data, m_status, curTime); 327 } 328 329 DPRINTF(RubyTest, "proc: %d, Address: 0x%x\n", proc, 330 getAddress().getLineAddress()); 331 DPRINTF(RubyTest, "Callback done\n"); 332 debugPrint(); 333} 334 335void 336Check::changeAddress(const Address& address) 337{ 338 assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready); 339 m_status = TesterStatus_Idle; 340 m_address = address; 341 m_store_count = 0; 342} 343 344void 345Check::pickValue() 346{ 347 assert(m_status == TesterStatus_Idle); 348 m_status = TesterStatus_Idle; 349 m_value = random_mt.random(0, 0xff); // One byte 350 m_store_count = 0; 351} 352 353void 354Check::pickInitiatingNode() 355{ 356 assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready); 357 m_status = TesterStatus_Idle; 358 m_initiatingNode = (random_mt.random(0, m_num_writers - 1)); 359 DPRINTF(RubyTest, "picked initiating node %d\n", m_initiatingNode); 360 m_store_count = 0; 361} 362 363void 364Check::print(std::ostream& out) const 365{ 366 out << "[" 367 << m_address << ", value: " 368 << (int)m_value << ", status: " 369 << m_status << ", initiating node: " 370 << m_initiatingNode << ", store_count: " 371 << m_store_count 372 << "]" << std::flush; 373} 374 375void 376Check::debugPrint() 377{ 378 DPRINTF(RubyTest, 379 "[%#x, value: %d, status: %s, initiating node: %d, store_count: %d]\n", 380 m_address.getAddress(), (int)m_value, 381 TesterStatus_to_string(m_status).c_str(), 382 m_initiatingNode, m_store_count); 383} | 34 35typedef RubyTester::SenderState SenderState; 36 37Check::Check(const Address& address, const Address& pc, 38 int _num_writers, int _num_readers, RubyTester* _tester) 39 : m_num_writers(_num_writers), m_num_readers(_num_readers), 40 m_tester_ptr(_tester) 41{ 42 m_status = TesterStatus_Idle; 43 44 pickValue(); 45 pickInitiatingNode(); 46 changeAddress(address); 47 m_pc = pc; 48 m_access_mode = RubyAccessMode(random_mt.random(0, 49 RubyAccessMode_NUM - 1)); 50 m_store_count = 0; 51} 52 53void 54Check::initiate() 55{ 56 DPRINTF(RubyTest, "initiating\n"); 57 debugPrint(); 58 59 // currently no protocols support prefetches 60 if (false && (random_mt.random(0, 0xf) == 0)) { 61 initiatePrefetch(); // Prefetch from random processor 62 } 63 64 if (m_tester_ptr->getCheckFlush() && (random_mt.random(0, 0xff) == 0)) { 65 initiateFlush(); // issue a Flush request from random processor 66 } 67 68 if (m_status == TesterStatus_Idle) { 69 initiateAction(); 70 } else if (m_status == TesterStatus_Ready) { 71 initiateCheck(); 72 } else { 73 // Pending - do nothing 74 DPRINTF(RubyTest, 75 "initiating action/check - failed: action/check is pending\n"); 76 } 77} 78 79void 80Check::initiatePrefetch() 81{ 82 DPRINTF(RubyTest, "initiating prefetch\n"); 83 84 int index = random_mt.random(0, m_num_readers - 1); 85 MasterPort* port = m_tester_ptr->getReadableCpuPort(index); 86 87 Request::Flags flags; 88 flags.set(Request::PREFETCH); 89 90 Packet::Command cmd; 91 92 // 1 in 8 chance this will be an exclusive prefetch 93 if (random_mt.random(0, 0x7) != 0) { 94 cmd = MemCmd::ReadReq; 95 96 // if necessary, make the request an instruction fetch 97 if (m_tester_ptr->isInstReadableCpuPort(index)) { 98 flags.set(Request::INST_FETCH); 99 } 100 } else { 101 cmd = MemCmd::WriteReq; 102 flags.set(Request::PF_EXCLUSIVE); 103 } 104 105 // Prefetches are assumed to be 0 sized 106 Request *req = new Request(m_address.getAddress(), 0, flags, 107 m_tester_ptr->masterId(), curTick(), m_pc.getAddress()); 108 req->setThreadContext(index, 0); 109 110 PacketPtr pkt = new Packet(req, cmd); 111 // despite the oddity of the 0 size (questionable if this should 112 // even be allowed), a prefetch is still a read and as such needs 113 // a place to store the result 114 uint8_t *data = new uint8_t[1]; 115 pkt->dataDynamic(data); 116 117 // push the subblock onto the sender state. The sequencer will 118 // update the subblock on the return 119 pkt->senderState = new SenderState(m_address, req->getSize()); 120 121 if (port->sendTimingReq(pkt)) { 122 DPRINTF(RubyTest, "successfully initiated prefetch.\n"); 123 } else { 124 // If the packet did not issue, must delete 125 delete pkt->senderState; 126 delete pkt->req; 127 delete pkt; 128 129 DPRINTF(RubyTest, 130 "prefetch initiation failed because Port was busy.\n"); 131 } 132} 133 134void 135Check::initiateFlush() 136{ 137 138 DPRINTF(RubyTest, "initiating Flush\n"); 139 140 int index = random_mt.random(0, m_num_writers - 1); 141 MasterPort* port = m_tester_ptr->getWritableCpuPort(index); 142 143 Request::Flags flags; 144 145 Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags, 146 m_tester_ptr->masterId(), curTick(), m_pc.getAddress()); 147 148 Packet::Command cmd; 149 150 cmd = MemCmd::FlushReq; 151 152 PacketPtr pkt = new Packet(req, cmd); 153 154 // push the subblock onto the sender state. The sequencer will 155 // update the subblock on the return 156 pkt->senderState = new SenderState(m_address, req->getSize()); 157 158 if (port->sendTimingReq(pkt)) { 159 DPRINTF(RubyTest, "initiating Flush - successful\n"); 160 } 161} 162 163void 164Check::initiateAction() 165{ 166 DPRINTF(RubyTest, "initiating Action\n"); 167 assert(m_status == TesterStatus_Idle); 168 169 int index = random_mt.random(0, m_num_writers - 1); 170 MasterPort* port = m_tester_ptr->getWritableCpuPort(index); 171 172 Request::Flags flags; 173 174 // Create the particular address for the next byte to be written 175 Address writeAddr(m_address.getAddress() + m_store_count); 176 177 // Stores are assumed to be 1 byte-sized 178 Request *req = new Request(writeAddr.getAddress(), 1, flags, 179 m_tester_ptr->masterId(), curTick(), 180 m_pc.getAddress()); 181 182 req->setThreadContext(index, 0); 183 Packet::Command cmd; 184 185 // 1 out of 8 chance, issue an atomic rather than a write 186 // if ((random() & 0x7) == 0) { 187 // cmd = MemCmd::SwapReq; 188 // } else { 189 cmd = MemCmd::WriteReq; 190 // } 191 192 PacketPtr pkt = new Packet(req, cmd); 193 uint8_t *writeData = new uint8_t[1]; 194 *writeData = m_value + m_store_count; 195 pkt->dataDynamic(writeData); 196 197 DPRINTF(RubyTest, "data 0x%x check 0x%x\n", 198 *(pkt->getConstPtr<uint8_t>()), *writeData); 199 200 // push the subblock onto the sender state. The sequencer will 201 // update the subblock on the return 202 pkt->senderState = new SenderState(writeAddr, req->getSize()); 203 204 if (port->sendTimingReq(pkt)) { 205 DPRINTF(RubyTest, "initiating action - successful\n"); 206 DPRINTF(RubyTest, "status before action update: %s\n", 207 (TesterStatus_to_string(m_status)).c_str()); 208 m_status = TesterStatus_Action_Pending; 209 } else { 210 // If the packet did not issue, must delete 211 // Note: No need to delete the data, the packet destructor 212 // will delete it 213 delete pkt->senderState; 214 delete pkt->req; 215 delete pkt; 216 217 DPRINTF(RubyTest, "failed to initiate action - sequencer not ready\n"); 218 } 219 220 DPRINTF(RubyTest, "status after action update: %s\n", 221 (TesterStatus_to_string(m_status)).c_str()); 222} 223 224void 225Check::initiateCheck() 226{ 227 DPRINTF(RubyTest, "Initiating Check\n"); 228 assert(m_status == TesterStatus_Ready); 229 230 int index = random_mt.random(0, m_num_readers - 1); 231 MasterPort* port = m_tester_ptr->getReadableCpuPort(index); 232 233 Request::Flags flags; 234 235 // If necessary, make the request an instruction fetch 236 if (m_tester_ptr->isInstReadableCpuPort(index)) { 237 flags.set(Request::INST_FETCH); 238 } 239 240 // Checks are sized depending on the number of bytes written 241 Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags, 242 m_tester_ptr->masterId(), curTick(), m_pc.getAddress()); 243 244 req->setThreadContext(index, 0); 245 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 246 uint8_t *dataArray = new uint8_t[CHECK_SIZE]; 247 pkt->dataDynamic(dataArray); 248 249 // push the subblock onto the sender state. The sequencer will 250 // update the subblock on the return 251 pkt->senderState = new SenderState(m_address, req->getSize()); 252 253 if (port->sendTimingReq(pkt)) { 254 DPRINTF(RubyTest, "initiating check - successful\n"); 255 DPRINTF(RubyTest, "status before check update: %s\n", 256 TesterStatus_to_string(m_status).c_str()); 257 m_status = TesterStatus_Check_Pending; 258 } else { 259 // If the packet did not issue, must delete 260 // Note: No need to delete the data, the packet destructor 261 // will delete it 262 delete pkt->senderState; 263 delete pkt->req; 264 delete pkt; 265 266 DPRINTF(RubyTest, "failed to initiate check - cpu port not ready\n"); 267 } 268 269 DPRINTF(RubyTest, "status after check update: %s\n", 270 TesterStatus_to_string(m_status).c_str()); 271} 272 273void 274Check::performCallback(NodeID proc, SubBlock* data, Cycles curTime) 275{ 276 Address address = data->getAddress(); 277 278 // This isn't exactly right since we now have multi-byte checks 279 // assert(getAddress() == address); 280 281 assert(getAddress().getLineAddress() == address.getLineAddress()); 282 assert(data != NULL); 283 284 DPRINTF(RubyTest, "RubyTester Callback\n"); 285 debugPrint(); 286 287 if (m_status == TesterStatus_Action_Pending) { 288 DPRINTF(RubyTest, "Action callback write value: %d, currently %d\n", 289 (m_value + m_store_count), data->getByte(0)); 290 // Perform store one byte at a time 291 data->setByte(0, (m_value + m_store_count)); 292 m_store_count++; 293 if (m_store_count == CHECK_SIZE) { 294 m_status = TesterStatus_Ready; 295 } else { 296 m_status = TesterStatus_Idle; 297 } 298 DPRINTF(RubyTest, "Action callback return data now %d\n", 299 data->getByte(0)); 300 } else if (m_status == TesterStatus_Check_Pending) { 301 DPRINTF(RubyTest, "Check callback\n"); 302 // Perform load/check 303 for (int byte_number=0; byte_number<CHECK_SIZE; byte_number++) { 304 if (uint8_t(m_value + byte_number) != data->getByte(byte_number)) { 305 panic("Action/check failure: proc: %d address: %s data: %s " 306 "byte_number: %d m_value+byte_number: %d byte: %d %s" 307 "Time: %d\n", 308 proc, address, data, byte_number, 309 (int)m_value + byte_number, 310 (int)data->getByte(byte_number), *this, curTime); 311 } 312 } 313 DPRINTF(RubyTest, "Action/check success\n"); 314 debugPrint(); 315 316 // successful check complete, increment complete 317 m_tester_ptr->incrementCheckCompletions(); 318 319 m_status = TesterStatus_Idle; 320 pickValue(); 321 322 } else { 323 panic("Unexpected TesterStatus: %s proc: %d data: %s m_status: %s " 324 "time: %d\n", *this, proc, data, m_status, curTime); 325 } 326 327 DPRINTF(RubyTest, "proc: %d, Address: 0x%x\n", proc, 328 getAddress().getLineAddress()); 329 DPRINTF(RubyTest, "Callback done\n"); 330 debugPrint(); 331} 332 333void 334Check::changeAddress(const Address& address) 335{ 336 assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready); 337 m_status = TesterStatus_Idle; 338 m_address = address; 339 m_store_count = 0; 340} 341 342void 343Check::pickValue() 344{ 345 assert(m_status == TesterStatus_Idle); 346 m_status = TesterStatus_Idle; 347 m_value = random_mt.random(0, 0xff); // One byte 348 m_store_count = 0; 349} 350 351void 352Check::pickInitiatingNode() 353{ 354 assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready); 355 m_status = TesterStatus_Idle; 356 m_initiatingNode = (random_mt.random(0, m_num_writers - 1)); 357 DPRINTF(RubyTest, "picked initiating node %d\n", m_initiatingNode); 358 m_store_count = 0; 359} 360 361void 362Check::print(std::ostream& out) const 363{ 364 out << "[" 365 << m_address << ", value: " 366 << (int)m_value << ", status: " 367 << m_status << ", initiating node: " 368 << m_initiatingNode << ", store_count: " 369 << m_store_count 370 << "]" << std::flush; 371} 372 373void 374Check::debugPrint() 375{ 376 DPRINTF(RubyTest, 377 "[%#x, value: %d, status: %s, initiating node: %d, store_count: %d]\n", 378 m_address.getAddress(), (int)m_value, 379 TesterStatus_to_string(m_status).c_str(), 380 m_initiatingNode, m_store_count); 381} |