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; --- 286 unchanged lines hidden (view full) --- 295 296bool 297RubyPort::M5Port::doFunctionalRead(PacketPtr pkt) 298{ 299 Address address(pkt->getAddr()); 300 Address line_address(address); 301 line_address.makeLineAddress(); 302 |
303 AccessPermission access_perm = AccessPermission_NotPresent; |
304 int num_controllers = ruby_system->m_abs_cntrl_vec.size(); 305 |
306 DPRINTF(RubyPort, "Functional Read request for %s\n",address); |
307 |
308 unsigned int num_ro = 0; 309 unsigned int num_rw = 0; 310 unsigned int num_busy = 0; 311 unsigned int num_backing_store = 0; 312 unsigned int num_invalid = 0; 313 314 // In this loop we count the number of controllers that have the given 315 // address in read only, read write and busy states. 316 for (int i = 0; i < num_controllers; ++i) { 317 access_perm = ruby_system->m_abs_cntrl_vec[i]-> 318 getAccessPermission(line_address); 319 if (access_perm == AccessPermission_Read_Only) 320 num_ro++; 321 else if (access_perm == AccessPermission_Read_Write) 322 num_rw++; 323 else if (access_perm == AccessPermission_Busy) 324 num_busy++; 325 else if (access_perm == AccessPermission_Backing_Store) 326 // See RubySlicc_Exports.sm for details, but Backing_Store is meant 327 // to represent blocks in memory *for Broadcast/Snooping protocols*, 328 // where memory has no idea whether it has an exclusive copy of data 329 // or not. 330 num_backing_store++; 331 else if (access_perm == AccessPermission_Invalid || 332 access_perm == AccessPermission_NotPresent) 333 num_invalid++; 334 } 335 assert(num_rw <= 1); 336 337 uint8* data = pkt->getPtr<uint8_t>(true); 338 unsigned int size_in_bytes = pkt->getSize(); 339 unsigned startByte = address.getAddress() - line_address.getAddress(); 340 341 // This if case is meant to capture what happens in a Broadcast/Snoop 342 // protocol where the block does not exist in the cache hierarchy. You 343 // only want to read from the Backing_Store memory if there is no copy in 344 // the cache hierarchy, otherwise you want to try to read the RO or RW 345 // copies existing in the cache hierarchy (covered by the else statement). 346 // The reason is because the Backing_Store memory could easily be stale, if 347 // there are copies floating around the cache hierarchy, so you want to read 348 // it only if it's not in the cache hierarchy at all. 349 if (num_invalid == (num_controllers - 1) && 350 num_backing_store == 1) 351 { 352 DPRINTF(RubyPort, "only copy in Backing_Store memory, read from it\n"); 353 for (int i = 0; i < num_controllers; ++i) { 354 access_perm = ruby_system->m_abs_cntrl_vec[i] 355 ->getAccessPermission(line_address); 356 if (access_perm == AccessPermission_Backing_Store) { 357 DataBlock& block = ruby_system->m_abs_cntrl_vec[i] |
358 ->getDataBlock(line_address); 359 |
360 DPRINTF(RubyPort, "reading from %s block %s\n", 361 ruby_system->m_abs_cntrl_vec[i]->name(), block); 362 for (unsigned i = 0; i < size_in_bytes; ++i) { 363 data[i] = block.getByte(i + startByte); 364 } 365 return true; 366 } 367 } 368 } else { 369 // In Broadcast/Snoop protocols, this covers if you know the block 370 // exists somewhere in the caching hierarchy, then you want to read any 371 // valid RO or RW block. In directory protocols, same thing, you want 372 // to read any valid readable copy of the block. 373 DPRINTF(RubyPort, "num_busy = %d, num_ro = %d, num_rw = %d\n", 374 num_busy, num_ro, num_rw); 375 // In this loop, we try to figure which controller has a read only or 376 // a read write copy of the given address. Any valid copy would suffice 377 // for a functional read. 378 for(int i = 0;i < num_controllers;++i) { 379 access_perm = ruby_system->m_abs_cntrl_vec[i] 380 ->getAccessPermission(line_address); 381 if(access_perm == AccessPermission_Read_Only || 382 access_perm == AccessPermission_Read_Write) |
383 { |
384 DataBlock& block = ruby_system->m_abs_cntrl_vec[i] 385 ->getDataBlock(line_address); 386 387 DPRINTF(RubyPort, "reading from %s block %s\n", 388 ruby_system->m_abs_cntrl_vec[i]->name(), block); 389 for (unsigned i = 0; i < size_in_bytes; ++i) { 390 data[i] = block.getByte(i + startByte); 391 } 392 return true; |
393 } |
394 } 395 } 396 return false; 397} 398 399bool 400RubyPort::M5Port::doFunctionalWrite(PacketPtr pkt) 401{ 402 Address addr(pkt->getAddr()); 403 Address line_addr = line_address(addr); |
404 AccessPermission access_perm = AccessPermission_NotPresent; |
405 int num_controllers = ruby_system->m_abs_cntrl_vec.size(); 406 407 DPRINTF(RubyPort, "Functional Write request for %s\n",addr); 408 409 unsigned int num_ro = 0; 410 unsigned int num_rw = 0; 411 unsigned int num_busy = 0; |
412 unsigned int num_backing_store = 0; 413 unsigned int num_invalid = 0; |
414 415 // In this loop we count the number of controllers that have the given 416 // address in read only, read write and busy states. |
417 for(int i = 0;i < num_controllers;++i) { 418 access_perm = ruby_system->m_abs_cntrl_vec[i]-> |
419 getAccessPermission(line_addr); |
420 if (access_perm == AccessPermission_Read_Only) 421 num_ro++; 422 else if (access_perm == AccessPermission_Read_Write) 423 num_rw++; 424 else if (access_perm == AccessPermission_Busy) 425 num_busy++; 426 else if (access_perm == AccessPermission_Backing_Store) 427 // See RubySlicc_Exports.sm for details, but Backing_Store is meant 428 // to represent blocks in memory *for Broadcast/Snooping protocols*, 429 // where memory has no idea whether it has an exclusive copy of data 430 // or not. 431 num_backing_store++; 432 else if (access_perm == AccessPermission_Invalid || 433 access_perm == AccessPermission_NotPresent) 434 num_invalid++; |
435 } 436 437 // If the number of read write copies is more than 1, then there is bug in 438 // coherence protocol. Otherwise, if all copies are in stable states, i.e. 439 // num_busy == 0, we update all the copies. If there is at least one copy 440 // in busy state, then we check if there is read write copy. If yes, then |
441 // also we let the access go through. Or, if there is no copy in the cache 442 // hierarchy at all, we still want to do the write to the memory 443 // (Backing_Store) instead of failing. |
444 445 DPRINTF(RubyPort, "num_busy = %d, num_ro = %d, num_rw = %d\n", 446 num_busy, num_ro, num_rw); 447 assert(num_rw <= 1); |
448 |
449 uint8* data = pkt->getPtr<uint8_t>(true); 450 unsigned int size_in_bytes = pkt->getSize(); 451 unsigned startByte = addr.getAddress() - line_addr.getAddress(); 452 453 if ((num_busy == 0 && num_ro > 0) || num_rw == 1 || 454 (num_invalid == (num_controllers - 1) && num_backing_store == 1)) 455 { 456 for(int i = 0; i < num_controllers;++i) { 457 access_perm = ruby_system->m_abs_cntrl_vec[i]-> |
458 getAccessPermission(line_addr); |
459 if(access_perm == AccessPermission_Read_Only || 460 access_perm == AccessPermission_Read_Write|| 461 access_perm == AccessPermission_Maybe_Stale || 462 access_perm == AccessPermission_Backing_Store) |
463 { 464 DataBlock& block = ruby_system->m_abs_cntrl_vec[i] 465 ->getDataBlock(line_addr); 466 467 DPRINTF(RubyPort, "%s\n",block); |
468 for (unsigned i = 0; i < size_in_bytes; ++i) { |
469 block.setByte(i + startByte, data[i]); 470 } 471 DPRINTF(RubyPort, "%s\n",block); 472 } 473 } 474 return true; 475 } 476 return false; --- 200 unchanged lines hidden --- |