atomic.cc (13652:45d94ac03a27) | atomic.cc (13954:2f400a5f2627) |
---|---|
1/* 2 * Copyright 2014 Google, Inc. 3 * Copyright (c) 2012-2013,2015,2017-2018 ARM Limited 4 * All rights reserved. 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating --- 35 unchanged lines hidden (view full) --- 44#include "cpu/simple/atomic.hh" 45 46#include "arch/locked_mem.hh" 47#include "arch/mmapped_ipr.hh" 48#include "arch/utility.hh" 49#include "base/output.hh" 50#include "config/the_isa.hh" 51#include "cpu/exetrace.hh" | 1/* 2 * Copyright 2014 Google, Inc. 3 * Copyright (c) 2012-2013,2015,2017-2018 ARM Limited 4 * All rights reserved. 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating --- 35 unchanged lines hidden (view full) --- 44#include "cpu/simple/atomic.hh" 45 46#include "arch/locked_mem.hh" 47#include "arch/mmapped_ipr.hh" 48#include "arch/utility.hh" 49#include "base/output.hh" 50#include "config/the_isa.hh" 51#include "cpu/exetrace.hh" |
52#include "cpu/utils.hh" |
|
52#include "debug/Drain.hh" 53#include "debug/ExecFaulting.hh" 54#include "debug/SimpleCPU.hh" 55#include "mem/packet.hh" 56#include "mem/packet_access.hh" 57#include "mem/physical.hh" 58#include "params/AtomicSimpleCPU.hh" 59#include "sim/faults.hh" --- 268 unchanged lines hidden (view full) --- 328 DPRINTF(SimpleCPU, "received invalidation for addr:%#x\n", 329 pkt->getAddr()); 330 for (auto &t_info : cpu->threadInfo) { 331 TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask); 332 } 333 } 334} 335 | 53#include "debug/Drain.hh" 54#include "debug/ExecFaulting.hh" 55#include "debug/SimpleCPU.hh" 56#include "mem/packet.hh" 57#include "mem/packet_access.hh" 58#include "mem/physical.hh" 59#include "params/AtomicSimpleCPU.hh" 60#include "sim/faults.hh" --- 268 unchanged lines hidden (view full) --- 329 DPRINTF(SimpleCPU, "received invalidation for addr:%#x\n", 330 pkt->getAddr()); 331 for (auto &t_info : cpu->threadInfo) { 332 TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask); 333 } 334 } 335} 336 |
337bool 338AtomicSimpleCPU::genMemFragmentRequest(const RequestPtr& req, Addr frag_addr, 339 int size, Request::Flags flags, 340 const std::vector<bool>& byte_enable, 341 int& frag_size, int& size_left) const 342{ 343 bool predicate = true; 344 Addr inst_addr = threadInfo[curThread]->thread->pcState().instAddr(); 345 346 frag_size = std::min( 347 cacheLineSize() - addrBlockOffset(frag_addr, cacheLineSize()), 348 (Addr) size_left); 349 size_left -= frag_size; 350 351 if (!byte_enable.empty()) { 352 // Set up byte-enable mask for the current fragment 353 auto it_start = byte_enable.begin() + (size - (frag_size + size_left)); 354 auto it_end = byte_enable.begin() + (size - size_left); 355 if (isAnyActiveElement(it_start, it_end)) { 356 req->setVirt(0, frag_addr, frag_size, flags, dataMasterId(), 357 inst_addr); 358 req->setByteEnable(std::vector<bool>(it_start, it_end)); 359 } else { 360 predicate = false; 361 } 362 } else { 363 req->setVirt(0, frag_addr, frag_size, flags, dataMasterId(), 364 inst_addr); 365 } 366 367 return predicate; 368} 369 |
|
336Fault 337AtomicSimpleCPU::readMem(Addr addr, uint8_t * data, unsigned size, | 370Fault 371AtomicSimpleCPU::readMem(Addr addr, uint8_t * data, unsigned size, |
338 Request::Flags flags) | 372 Request::Flags flags, 373 const std::vector<bool>& byteEnable) |
339{ 340 SimpleExecContext& t_info = *threadInfo[curThread]; 341 SimpleThread* thread = t_info.thread; 342 343 // use the CPU's statically allocated read request and packet objects 344 const RequestPtr &req = data_read_req; 345 346 if (traceData) 347 traceData->setMem(addr, size, flags); 348 | 374{ 375 SimpleExecContext& t_info = *threadInfo[curThread]; 376 SimpleThread* thread = t_info.thread; 377 378 // use the CPU's statically allocated read request and packet objects 379 const RequestPtr &req = data_read_req; 380 381 if (traceData) 382 traceData->setMem(addr, size, flags); 383 |
349 //The size of the data we're trying to read. 350 int fullSize = size; 351 352 //The address of the second part of this access if it needs to be split 353 //across a cache line boundary. 354 Addr secondAddr = roundDown(addr + size - 1, cacheLineSize()); 355 356 if (secondAddr > addr) 357 size = secondAddr - addr; 358 | |
359 dcache_latency = 0; 360 361 req->taskId(taskId()); | 384 dcache_latency = 0; 385 386 req->taskId(taskId()); |
387 388 Addr frag_addr = addr; 389 int frag_size = 0; 390 int size_left = size; 391 bool predicate; 392 Fault fault = NoFault; 393 |
|
362 while (1) { | 394 while (1) { |
363 req->setVirt(0, addr, size, flags, dataMasterId(), thread->pcState().instAddr()); | 395 predicate = genMemFragmentRequest(req, frag_addr, size, flags, 396 byteEnable, frag_size, size_left); |
364 365 // translate to physical address | 397 398 // translate to physical address |
366 Fault fault = thread->dtb->translateAtomic(req, thread->getTC(), 367 BaseTLB::Read); | 399 if (predicate) { 400 fault = thread->dtb->translateAtomic(req, thread->getTC(), 401 BaseTLB::Read); 402 } |
368 369 // Now do the access. | 403 404 // Now do the access. |
370 if (fault == NoFault && !req->getFlags().isSet(Request::NO_ACCESS)) { | 405 if (predicate && fault == NoFault && 406 !req->getFlags().isSet(Request::NO_ACCESS)) { |
371 Packet pkt(req, Packet::makeReadCmd(req)); 372 pkt.dataStatic(data); 373 374 if (req->isMmappedIpr()) { 375 dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt); 376 } else { 377 dcache_latency += sendPacket(dcachePort, &pkt); 378 } --- 10 unchanged lines hidden (view full) --- 389 if (fault != NoFault) { 390 if (req->isPrefetch()) { 391 return NoFault; 392 } else { 393 return fault; 394 } 395 } 396 | 407 Packet pkt(req, Packet::makeReadCmd(req)); 408 pkt.dataStatic(data); 409 410 if (req->isMmappedIpr()) { 411 dcache_latency += TheISA::handleIprRead(thread->getTC(), &pkt); 412 } else { 413 dcache_latency += sendPacket(dcachePort, &pkt); 414 } --- 10 unchanged lines hidden (view full) --- 425 if (fault != NoFault) { 426 if (req->isPrefetch()) { 427 return NoFault; 428 } else { 429 return fault; 430 } 431 } 432 |
397 //If we don't need to access a second cache line, stop now. 398 if (secondAddr <= addr) 399 { | 433 // If we don't need to access further cache lines, stop now. 434 if (size_left == 0) { |
400 if (req->isLockedRMW() && fault == NoFault) { 401 assert(!locked); 402 locked = true; 403 } | 435 if (req->isLockedRMW() && fault == NoFault) { 436 assert(!locked); 437 locked = true; 438 } |
404 | |
405 return fault; 406 } 407 408 /* | 439 return fault; 440 } 441 442 /* |
409 * Set up for accessing the second cache line. | 443 * Set up for accessing the next cache line. |
410 */ | 444 */ |
445 frag_addr += frag_size; |
|
411 412 //Move the pointer we're reading into to the correct location. | 446 447 //Move the pointer we're reading into to the correct location. |
413 data += size; 414 //Adjust the size to get the remaining bytes. 415 size = addr + fullSize - secondAddr; 416 //And access the right address. 417 addr = secondAddr; | 448 data += frag_size; |
418 } 419} 420 421Fault 422AtomicSimpleCPU::writeMem(uint8_t *data, unsigned size, Addr addr, | 449 } 450} 451 452Fault 453AtomicSimpleCPU::writeMem(uint8_t *data, unsigned size, Addr addr, |
423 Request::Flags flags, uint64_t *res) | 454 Request::Flags flags, uint64_t *res, 455 const std::vector<bool>& byteEnable) |
424{ 425 SimpleExecContext& t_info = *threadInfo[curThread]; 426 SimpleThread* thread = t_info.thread; 427 static uint8_t zero_array[64] = {}; 428 429 if (data == NULL) { 430 assert(size <= 64); 431 assert(flags & Request::STORE_NO_DATA); 432 // This must be a cache block cleaning request 433 data = zero_array; 434 } 435 436 // use the CPU's statically allocated write request and packet objects 437 const RequestPtr &req = data_write_req; 438 439 if (traceData) 440 traceData->setMem(addr, size, flags); 441 | 456{ 457 SimpleExecContext& t_info = *threadInfo[curThread]; 458 SimpleThread* thread = t_info.thread; 459 static uint8_t zero_array[64] = {}; 460 461 if (data == NULL) { 462 assert(size <= 64); 463 assert(flags & Request::STORE_NO_DATA); 464 // This must be a cache block cleaning request 465 data = zero_array; 466 } 467 468 // use the CPU's statically allocated write request and packet objects 469 const RequestPtr &req = data_write_req; 470 471 if (traceData) 472 traceData->setMem(addr, size, flags); 473 |
442 //The size of the data we're trying to read. 443 int fullSize = size; 444 445 //The address of the second part of this access if it needs to be split 446 //across a cache line boundary. 447 Addr secondAddr = roundDown(addr + size - 1, cacheLineSize()); 448 449 if (secondAddr > addr) 450 size = secondAddr - addr; 451 | |
452 dcache_latency = 0; 453 454 req->taskId(taskId()); | 474 dcache_latency = 0; 475 476 req->taskId(taskId()); |
477 478 Addr frag_addr = addr; 479 int frag_size = 0; 480 int size_left = size; 481 int curr_frag_id = 0; 482 bool predicate; 483 Fault fault = NoFault; 484 |
|
455 while (1) { | 485 while (1) { |
456 req->setVirt(0, addr, size, flags, dataMasterId(), thread->pcState().instAddr()); | 486 predicate = genMemFragmentRequest(req, frag_addr, size, flags, 487 byteEnable, frag_size, size_left); |
457 458 // translate to physical address | 488 489 // translate to physical address |
459 Fault fault = thread->dtb->translateAtomic(req, thread->getTC(), BaseTLB::Write); | 490 if (predicate) 491 fault = thread->dtb->translateAtomic(req, thread->getTC(), 492 BaseTLB::Write); |
460 461 // Now do the access. | 493 494 // Now do the access. |
462 if (fault == NoFault) { | 495 if (predicate && fault == NoFault) { |
463 bool do_access = true; // flag to suppress cache access 464 465 if (req->isLLSC()) { | 496 bool do_access = true; // flag to suppress cache access 497 498 if (req->isLLSC()) { |
466 do_access = TheISA::handleLockedWrite(thread, req, dcachePort.cacheBlockMask); | 499 assert(curr_frag_id == 0); 500 do_access = 501 TheISA::handleLockedWrite(thread, req, 502 dcachePort.cacheBlockMask); |
467 } else if (req->isSwap()) { | 503 } else if (req->isSwap()) { |
504 assert(curr_frag_id == 0); |
|
468 if (req->isCondSwap()) { 469 assert(res); 470 req->setExtraData(*res); 471 } 472 } 473 474 if (do_access && !req->getFlags().isSet(Request::NO_ACCESS)) { 475 Packet pkt(req, Packet::makeWriteCmd(req)); --- 7 unchanged lines hidden (view full) --- 483 484 // Notify other threads on this CPU of write 485 threadSnoop(&pkt, curThread); 486 } 487 dcache_access = true; 488 assert(!pkt.isError()); 489 490 if (req->isSwap()) { | 505 if (req->isCondSwap()) { 506 assert(res); 507 req->setExtraData(*res); 508 } 509 } 510 511 if (do_access && !req->getFlags().isSet(Request::NO_ACCESS)) { 512 Packet pkt(req, Packet::makeWriteCmd(req)); --- 7 unchanged lines hidden (view full) --- 520 521 // Notify other threads on this CPU of write 522 threadSnoop(&pkt, curThread); 523 } 524 dcache_access = true; 525 assert(!pkt.isError()); 526 527 if (req->isSwap()) { |
491 assert(res); 492 memcpy(res, pkt.getConstPtr<uint8_t>(), fullSize); | 528 assert(res && curr_frag_id == 0); 529 memcpy(res, pkt.getConstPtr<uint8_t>(), size); |
493 } 494 } 495 496 if (res && !req->isSwap()) { 497 *res = req->getExtraData(); 498 } 499 } 500 501 //If there's a fault or we don't need to access a second cache line, 502 //stop now. | 530 } 531 } 532 533 if (res && !req->isSwap()) { 534 *res = req->getExtraData(); 535 } 536 } 537 538 //If there's a fault or we don't need to access a second cache line, 539 //stop now. |
503 if (fault != NoFault || secondAddr <= addr) | 540 if (fault != NoFault || size_left == 0) |
504 { 505 if (req->isLockedRMW() && fault == NoFault) { | 541 { 542 if (req->isLockedRMW() && fault == NoFault) { |
506 assert(locked); | 543 assert(byteEnable.empty()); 544 assert(locked && curr_frag_id == 0); |
507 locked = false; 508 } 509 | 545 locked = false; 546 } 547 |
510 | |
511 if (fault != NoFault && req->isPrefetch()) { 512 return NoFault; 513 } else { 514 return fault; 515 } 516 } 517 518 /* | 548 if (fault != NoFault && req->isPrefetch()) { 549 return NoFault; 550 } else { 551 return fault; 552 } 553 } 554 555 /* |
519 * Set up for accessing the second cache line. | 556 * Set up for accessing the next cache line. |
520 */ | 557 */ |
558 frag_addr += frag_size; |
|
521 522 //Move the pointer we're reading into to the correct location. | 559 560 //Move the pointer we're reading into to the correct location. |
523 data += size; 524 //Adjust the size to get the remaining bytes. 525 size = addr + fullSize - secondAddr; 526 //And access the right address. 527 addr = secondAddr; | 561 data += frag_size; 562 563 curr_frag_id++; |
528 } 529} 530 531Fault 532AtomicSimpleCPU::amoMem(Addr addr, uint8_t* data, unsigned size, 533 Request::Flags flags, AtomicOpFunctor *amo_op) 534{ 535 SimpleExecContext& t_info = *threadInfo[curThread]; --- 223 unchanged lines hidden --- | 564 } 565} 566 567Fault 568AtomicSimpleCPU::amoMem(Addr addr, uint8_t* data, unsigned size, 569 Request::Flags flags, AtomicOpFunctor *amo_op) 570{ 571 SimpleExecContext& t_info = *threadInfo[curThread]; --- 223 unchanged lines hidden --- |