RubyPort.cc (8232:b28d06a175be) | RubyPort.cc (8436:5648986156db) |
---|---|
1/* 2 * Copyright (c) 2009 Advanced Micro Devices, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; --- 17 unchanged lines hidden (view full) --- 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config/the_isa.hh" 30#if THE_ISA == X86_ISA 31#include "arch/x86/insts/microldstop.hh" 32#endif // X86_ISA 33#include "cpu/testers/rubytest/RubyTester.hh" | 1/* 2 * Copyright (c) 2009 Advanced Micro Devices, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; --- 17 unchanged lines hidden (view full) --- 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config/the_isa.hh" 30#if THE_ISA == X86_ISA 31#include "arch/x86/insts/microldstop.hh" 32#endif // X86_ISA 33#include "cpu/testers/rubytest/RubyTester.hh" |
34#include "debug/MemoryAccess.hh" | |
35#include "debug/Ruby.hh" | 34#include "debug/Ruby.hh" |
35#include "mem/protocol/AccessPermission.hh" |
|
36#include "mem/ruby/slicc_interface/AbstractController.hh" 37#include "mem/ruby/system/RubyPort.hh" 38#include "mem/physical.hh" 39 40RubyPort::RubyPort(const Params *p) 41 : MemObject(p) 42{ 43 m_version = p->version; --- 5 unchanged lines hidden (view full) --- 49 m_mandatory_q_ptr = NULL; 50 51 m_request_cnt = 0; 52 pio_port = NULL; 53 physMemPort = NULL; 54 55 m_usingRubyTester = p->using_ruby_tester; 56 access_phys_mem = p->access_phys_mem; | 36#include "mem/ruby/slicc_interface/AbstractController.hh" 37#include "mem/ruby/system/RubyPort.hh" 38#include "mem/physical.hh" 39 40RubyPort::RubyPort(const Params *p) 41 : MemObject(p) 42{ 43 m_version = p->version; --- 5 unchanged lines hidden (view full) --- 49 m_mandatory_q_ptr = NULL; 50 51 m_request_cnt = 0; 52 pio_port = NULL; 53 physMemPort = NULL; 54 55 m_usingRubyTester = p->using_ruby_tester; 56 access_phys_mem = p->access_phys_mem; |
57 58 ruby_system = p->ruby_system; |
|
57} 58 59void 60RubyPort::init() 61{ 62 assert(m_controller != NULL); 63 m_mandatory_q_ptr = m_controller->getMandatoryQueue(); 64} 65 66Port * 67RubyPort::getPort(const std::string &if_name, int idx) 68{ 69 if (if_name == "port") { 70 return new M5Port(csprintf("%s-port%d", name(), idx), this, | 59} 60 61void 62RubyPort::init() 63{ 64 assert(m_controller != NULL); 65 m_mandatory_q_ptr = m_controller->getMandatoryQueue(); 66} 67 68Port * 69RubyPort::getPort(const std::string &if_name, int idx) 70{ 71 if (if_name == "port") { 72 return new M5Port(csprintf("%s-port%d", name(), idx), this, |
71 access_phys_mem); | 73 ruby_system, access_phys_mem); |
72 } 73 74 if (if_name == "pio_port") { 75 // ensure there is only one pio port 76 assert(pio_port == NULL); 77 78 pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx), this); 79 80 return pio_port; 81 } 82 83 if (if_name == "physMemPort") { 84 // RubyPort should only have one port to physical memory 85 assert (physMemPort == NULL); 86 87 physMemPort = new M5Port(csprintf("%s-physMemPort", name()), this, | 74 } 75 76 if (if_name == "pio_port") { 77 // ensure there is only one pio port 78 assert(pio_port == NULL); 79 80 pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx), this); 81 82 return pio_port; 83 } 84 85 if (if_name == "physMemPort") { 86 // RubyPort should only have one port to physical memory 87 assert (physMemPort == NULL); 88 89 physMemPort = new M5Port(csprintf("%s-physMemPort", name()), this, |
88 access_phys_mem); | 90 ruby_system, access_phys_mem); |
89 90 return physMemPort; 91 } 92 93 if (if_name == "functional") { 94 // Calls for the functional port only want to access 95 // functional memory. Therefore, directly pass these calls 96 // ports to physmem. --- 7 unchanged lines hidden (view full) --- 104RubyPort::PioPort::PioPort(const std::string &_name, 105 RubyPort *_port) 106 : SimpleTimingPort(_name, _port) 107{ 108 DPRINTF(RubyPort, "creating port to ruby sequencer to cpu %s\n", _name); 109 ruby_port = _port; 110} 111 | 91 92 return physMemPort; 93 } 94 95 if (if_name == "functional") { 96 // Calls for the functional port only want to access 97 // functional memory. Therefore, directly pass these calls 98 // ports to physmem. --- 7 unchanged lines hidden (view full) --- 106RubyPort::PioPort::PioPort(const std::string &_name, 107 RubyPort *_port) 108 : SimpleTimingPort(_name, _port) 109{ 110 DPRINTF(RubyPort, "creating port to ruby sequencer to cpu %s\n", _name); 111 ruby_port = _port; 112} 113 |
112RubyPort::M5Port::M5Port(const std::string &_name, 113 RubyPort *_port, bool _access_phys_mem) | 114RubyPort::M5Port::M5Port(const std::string &_name, RubyPort *_port, 115 RubySystem *_system, bool _access_phys_mem) |
114 : SimpleTimingPort(_name, _port) 115{ 116 DPRINTF(RubyPort, "creating port from ruby sequcner to cpu %s\n", _name); 117 ruby_port = _port; | 116 : SimpleTimingPort(_name, _port) 117{ 118 DPRINTF(RubyPort, "creating port from ruby sequcner to cpu %s\n", _name); 119 ruby_port = _port; |
120 ruby_system = _system; |
|
118 _onRetryList = false; 119 access_phys_mem = _access_phys_mem; 120} 121 122Tick 123RubyPort::PioPort::recvAtomic(PacketPtr pkt) 124{ 125 panic("RubyPort::PioPort::recvAtomic() not implemented!\n"); --- 158 unchanged lines hidden (view full) --- 284 pkt->getAddr(), RequestStatus_to_string(requestStatus)); 285 286 SenderState* senderState = safe_cast<SenderState*>(pkt->senderState); 287 pkt->senderState = senderState->saved; 288 delete senderState; 289 return false; 290} 291 | 121 _onRetryList = false; 122 access_phys_mem = _access_phys_mem; 123} 124 125Tick 126RubyPort::PioPort::recvAtomic(PacketPtr pkt) 127{ 128 panic("RubyPort::PioPort::recvAtomic() not implemented!\n"); --- 158 unchanged lines hidden (view full) --- 287 pkt->getAddr(), RequestStatus_to_string(requestStatus)); 288 289 SenderState* senderState = safe_cast<SenderState*>(pkt->senderState); 290 pkt->senderState = senderState->saved; 291 delete senderState; 292 return false; 293} 294 |
295bool 296RubyPort::M5Port::doFunctionalRead(PacketPtr pkt) 297{ 298 Address address(pkt->getAddr()); 299 Address line_address(address); 300 line_address.makeLineAddress(); 301 302 AccessPermission accessPerm = AccessPermission_NotPresent; 303 int num_controllers = ruby_system->m_abs_cntrl_vec.size(); 304 305 // In this loop, we try to figure which controller has a read only or 306 // a read write copy of the given address. Any valid copy would suffice 307 // for a functional read. 308 309 DPRINTF(RubyPort, "Functional Read request for %s\n",address); 310 for(int i = 0;i < num_controllers;++i) 311 { 312 accessPerm = ruby_system->m_abs_cntrl_vec[i] 313 ->getAccessPermission(line_address); 314 if(accessPerm == AccessPermission_Read_Only || 315 accessPerm == AccessPermission_Read_Write) 316 { 317 unsigned startByte = address.getAddress() - line_address.getAddress(); 318 319 uint8* data = pkt->getPtr<uint8_t>(true); 320 unsigned int size_in_bytes = pkt->getSize(); 321 DataBlock& block = ruby_system->m_abs_cntrl_vec[i] 322 ->getDataBlock(line_address); 323 324 DPRINTF(RubyPort, "reading from %s block %s\n", 325 ruby_system->m_abs_cntrl_vec[i]->name(), block); 326 for (unsigned i = 0; i < size_in_bytes; ++i) 327 { 328 data[i] = block.getByte(i + startByte); 329 } 330 return true; 331 } 332 } 333 return false; 334} 335 336bool 337RubyPort::M5Port::doFunctionalWrite(PacketPtr pkt) 338{ 339 Address addr(pkt->getAddr()); 340 Address line_addr = line_address(addr); 341 AccessPermission accessPerm = AccessPermission_NotPresent; 342 int num_controllers = ruby_system->m_abs_cntrl_vec.size(); 343 344 DPRINTF(RubyPort, "Functional Write request for %s\n",addr); 345 346 unsigned int num_ro = 0; 347 unsigned int num_rw = 0; 348 unsigned int num_busy = 0; 349 350 // In this loop we count the number of controllers that have the given 351 // address in read only, read write and busy states. 352 for(int i = 0;i < num_controllers;++i) 353 { 354 accessPerm = ruby_system->m_abs_cntrl_vec[i]-> 355 getAccessPermission(line_addr); 356 if(accessPerm == AccessPermission_Read_Only) num_ro++; 357 else if(accessPerm == AccessPermission_Read_Write) num_rw++; 358 else if(accessPerm == AccessPermission_Busy) num_busy++; 359 } 360 361 // If the number of read write copies is more than 1, then there is bug in 362 // coherence protocol. Otherwise, if all copies are in stable states, i.e. 363 // num_busy == 0, we update all the copies. If there is at least one copy 364 // in busy state, then we check if there is read write copy. If yes, then 365 // also we let the access go through. 366 367 DPRINTF(RubyPort, "num_busy = %d, num_ro = %d, num_rw = %d\n", 368 num_busy, num_ro, num_rw); 369 assert(num_rw <= 1); 370 if((num_busy == 0 && num_ro > 0) || num_rw == 1) 371 { 372 uint8* data = pkt->getPtr<uint8_t>(true); 373 unsigned int size_in_bytes = pkt->getSize(); 374 unsigned startByte = addr.getAddress() - line_addr.getAddress(); 375 376 for(int i = 0; i < num_controllers;++i) 377 { 378 accessPerm = ruby_system->m_abs_cntrl_vec[i]-> 379 getAccessPermission(line_addr); 380 if(accessPerm == AccessPermission_Read_Only || 381 accessPerm == AccessPermission_Read_Write|| 382 accessPerm == AccessPermission_Maybe_Stale) 383 { 384 DataBlock& block = ruby_system->m_abs_cntrl_vec[i] 385 ->getDataBlock(line_addr); 386 387 DPRINTF(RubyPort, "%s\n",block); 388 for (unsigned i = 0; i < size_in_bytes; ++i) 389 { 390 block.setByte(i + startByte, data[i]); 391 } 392 DPRINTF(RubyPort, "%s\n",block); 393 } 394 } 395 return true; 396 } 397 return false; 398} 399 |
|
292void | 400void |
401RubyPort::M5Port::recvFunctional(PacketPtr pkt) 402{ 403 DPRINTF(RubyPort, "Functional access caught for address %#x\n", 404 pkt->getAddr()); 405 406 // Check for pio requests and directly send them to the dedicated 407 // pio port. 408 if (!isPhysMemAddress(pkt->getAddr())) { 409 assert(ruby_port->pio_port != NULL); 410 DPRINTF(RubyPort, "Request for address 0x%#x is a pio request\n", 411 pkt->getAddr()); 412 panic("RubyPort::PioPort::recvFunctional() not implemented!\n"); 413 } 414 415 assert(pkt->getAddr() + pkt->getSize() <= 416 line_address(Address(pkt->getAddr())).getAddress() + 417 RubySystem::getBlockSizeBytes()); 418 419 bool accessSucceeded = false; 420 bool needsResponse = pkt->needsResponse(); 421 422 // Do the functional access on ruby memory 423 if (pkt->isRead()) { 424 accessSucceeded = doFunctionalRead(pkt); 425 } else if (pkt->isWrite()) { 426 accessSucceeded = doFunctionalWrite(pkt); 427 } else { 428 panic("RubyPort: unsupported functional command %s\n", 429 pkt->cmdString()); 430 } 431 432 // Unless the requester explicitly said otherwise, generate an error if 433 // the functional request failed 434 if (!accessSucceeded && !pkt->suppressFuncError()) { 435 fatal("Ruby functional %s failed for address %#x\n", 436 pkt->isWrite() ? "write" : "read", pkt->getAddr()); 437 } 438 439 if (access_phys_mem) { 440 // The attached physmem contains the official version of data. 441 // The following command performs the real functional access. 442 // This line should be removed once Ruby supplies the official version 443 // of data. 444 ruby_port->physMemPort->sendFunctional(pkt); 445 } 446 447 // turn packet around to go back to requester if response expected 448 if (needsResponse) { 449 pkt->setFunctionalResponseStatus(accessSucceeded); 450 DPRINTF(RubyPort, "Sending packet back over port\n"); 451 sendFunctional(pkt); 452 } 453 DPRINTF(RubyPort, "Functional access %s!\n", 454 accessSucceeded ? "successful":"failed"); 455} 456 457void |
|
293RubyPort::ruby_hit_callback(PacketPtr pkt) 294{ 295 // Retrieve the request port from the sender State 296 RubyPort::SenderState *senderState = 297 safe_cast<RubyPort::SenderState *>(pkt->senderState); 298 M5Port *port = senderState->port; 299 assert(port != NULL); 300 --- 132 unchanged lines hidden --- | 458RubyPort::ruby_hit_callback(PacketPtr pkt) 459{ 460 // Retrieve the request port from the sender State 461 RubyPort::SenderState *senderState = 462 safe_cast<RubyPort::SenderState *>(pkt->senderState); 463 M5Port *port = senderState->port; 464 assert(port != NULL); 465 --- 132 unchanged lines hidden --- |