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 ---