lsq.cc (13652:45d94ac03a27) | lsq.cc (13954:2f400a5f2627) |
---|---|
1/* | 1/* |
2 * Copyright (c) 2013-2014,2017 ARM Limited | 2 * Copyright (c) 2013-2014,2017-2018 ARM Limited |
3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated --- 33 unchanged lines hidden (view full) --- 44 45#include "arch/locked_mem.hh" 46#include "arch/mmapped_ipr.hh" 47#include "base/logging.hh" 48#include "cpu/minor/cpu.hh" 49#include "cpu/minor/exec_context.hh" 50#include "cpu/minor/execute.hh" 51#include "cpu/minor/pipeline.hh" | 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated --- 33 unchanged lines hidden (view full) --- 44 45#include "arch/locked_mem.hh" 46#include "arch/mmapped_ipr.hh" 47#include "base/logging.hh" 48#include "cpu/minor/cpu.hh" 49#include "cpu/minor/exec_context.hh" 50#include "cpu/minor/execute.hh" 51#include "cpu/minor/pipeline.hh" |
52#include "cpu/utils.hh" |
|
52#include "debug/Activity.hh" 53#include "debug/MinorMem.hh" 54 55namespace Minor 56{ 57 | 53#include "debug/Activity.hh" 54#include "debug/MinorMem.hh" 55 56namespace Minor 57{ 58 |
58/** Returns the offset of addr into an aligned a block of size block_size */ 59static Addr 60addrBlockOffset(Addr addr, unsigned int block_size) 61{ 62 return addr & (block_size - 1); 63} 64 65/** Returns true if the given [addr .. addr+size-1] transfer needs to be 66 * fragmented across a block size of block_size */ 67static bool 68transferNeedsBurst(Addr addr, unsigned int size, unsigned int block_size) 69{ 70 return (addrBlockOffset(addr, block_size) + size) > block_size; 71} 72 | |
73LSQ::LSQRequest::LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_, 74 PacketDataPtr data_, uint64_t *res_) : 75 SenderState(), 76 port(port_), 77 inst(inst_), 78 isLoad(isLoad_), 79 data(data_), 80 packet(NULL), 81 request(), 82 fault(NoFault), 83 res(res_), 84 skipped(false), 85 issuedToMemory(false), 86 state(NotIssued) 87{ 88 request = std::make_shared<Request>(); 89} 90 | 59LSQ::LSQRequest::LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_, 60 PacketDataPtr data_, uint64_t *res_) : 61 SenderState(), 62 port(port_), 63 inst(inst_), 64 isLoad(isLoad_), 65 data(data_), 66 packet(NULL), 67 request(), 68 fault(NoFault), 69 res(res_), 70 skipped(false), 71 issuedToMemory(false), 72 state(NotIssued) 73{ 74 request = std::make_shared<Request>(); 75} 76 |
77void 78LSQ::LSQRequest::disableMemAccess() 79{ 80 port.cpu.threads[inst->id.threadId]->setMemAccPredicate(false); 81 DPRINTFS(MinorMem, (&port), "Disable mem access for inst:%s\n", *inst); 82} 83 |
|
91LSQ::AddrRangeCoverage 92LSQ::LSQRequest::containsAddrRangeOf( 93 Addr req1_addr, unsigned int req1_size, 94 Addr req2_addr, unsigned int req2_size) 95{ 96 /* 'end' here means the address of the byte just past the request 97 * blocks */ 98 Addr req2_end_addr = req2_addr + req2_size; --- 152 unchanged lines hidden (view full) --- 251} 252 253void 254LSQ::SingleDataRequest::startAddrTranslation() 255{ 256 ThreadContext *thread = port.cpu.getContext( 257 inst->id.threadId); 258 | 84LSQ::AddrRangeCoverage 85LSQ::LSQRequest::containsAddrRangeOf( 86 Addr req1_addr, unsigned int req1_size, 87 Addr req2_addr, unsigned int req2_size) 88{ 89 /* 'end' here means the address of the byte just past the request 90 * blocks */ 91 Addr req2_end_addr = req2_addr + req2_size; --- 152 unchanged lines hidden (view full) --- 244} 245 246void 247LSQ::SingleDataRequest::startAddrTranslation() 248{ 249 ThreadContext *thread = port.cpu.getContext( 250 inst->id.threadId); 251 |
259 port.numAccessesInDTLB++; | 252 const auto &byteEnable = request->getByteEnable(); 253 if (byteEnable.size() == 0 || 254 isAnyActiveElement(byteEnable.cbegin(), byteEnable.cend())) { 255 port.numAccessesInDTLB++; |
260 | 256 |
261 setState(LSQ::LSQRequest::InTranslation); | 257 setState(LSQ::LSQRequest::InTranslation); |
262 | 258 |
263 DPRINTFS(MinorMem, (&port), "Submitting DTLB request\n"); 264 /* Submit the translation request. The response will come through 265 * finish/markDelayed on the LSQRequest as it bears the Translation 266 * interface */ 267 thread->getDTBPtr()->translateTiming( 268 request, thread, this, (isLoad ? BaseTLB::Read : BaseTLB::Write)); | 259 DPRINTFS(MinorMem, (&port), "Submitting DTLB request\n"); 260 /* Submit the translation request. The response will come through 261 * finish/markDelayed on the LSQRequest as it bears the Translation 262 * interface */ 263 thread->getDTBPtr()->translateTiming( 264 request, thread, this, (isLoad ? BaseTLB::Read : BaseTLB::Write)); 265 } else { 266 disableMemAccess(); 267 setState(LSQ::LSQRequest::Complete); 268 } |
269} 270 271void 272LSQ::SingleDataRequest::retireResponse(PacketPtr packet_) 273{ 274 DPRINTFS(MinorMem, (&port), "Retiring packet\n"); 275 packet = packet_; 276 packetInFlight = false; --- 75 unchanged lines hidden (view full) --- 352{ 353 Addr base_addr = request->getVaddr(); 354 unsigned int whole_size = request->getSize(); 355 unsigned int line_width = port.lineWidth; 356 357 unsigned int fragment_size; 358 Addr fragment_addr; 359 | 269} 270 271void 272LSQ::SingleDataRequest::retireResponse(PacketPtr packet_) 273{ 274 DPRINTFS(MinorMem, (&port), "Retiring packet\n"); 275 packet = packet_; 276 packetInFlight = false; --- 75 unchanged lines hidden (view full) --- 352{ 353 Addr base_addr = request->getVaddr(); 354 unsigned int whole_size = request->getSize(); 355 unsigned int line_width = port.lineWidth; 356 357 unsigned int fragment_size; 358 Addr fragment_addr; 359 |
360 std::vector<bool> fragment_write_byte_en; 361 |
|
360 /* Assume that this transfer is across potentially many block snap 361 * boundaries: 362 * 363 * | _|________|________|________|___ | 364 * | |0| 1 | 2 | 3 | 4 | | 365 * | |_|________|________|________|___| | 366 * | | | | | | 367 * --- 28 unchanged lines hidden (view full) --- 396 first_fragment_size + last_fragment_size) == whole_size); 397 398 fragment_addr = base_addr; 399 fragment_size = first_fragment_size; 400 401 /* Just past the last address in the request */ 402 Addr end_addr = base_addr + whole_size; 403 | 362 /* Assume that this transfer is across potentially many block snap 363 * boundaries: 364 * 365 * | _|________|________|________|___ | 366 * | |0| 1 | 2 | 3 | 4 | | 367 * | |_|________|________|________|___| | 368 * | | | | | | 369 * --- 28 unchanged lines hidden (view full) --- 398 first_fragment_size + last_fragment_size) == whole_size); 399 400 fragment_addr = base_addr; 401 fragment_size = first_fragment_size; 402 403 /* Just past the last address in the request */ 404 Addr end_addr = base_addr + whole_size; 405 |
406 auto& byte_enable = request->getByteEnable(); 407 unsigned int num_disabled_fragments = 0; 408 |
|
404 for (unsigned int fragment_index = 0; fragment_index < numFragments; 405 fragment_index++) 406 { 407 bool M5_VAR_USED is_last_fragment = false; 408 409 if (fragment_addr == base_addr) { 410 /* First fragment */ 411 fragment_size = first_fragment_size; --- 4 unchanged lines hidden (view full) --- 416 is_last_fragment = true; 417 } else { 418 /* Middle fragments */ 419 fragment_size = line_width; 420 } 421 } 422 423 RequestPtr fragment = std::make_shared<Request>(); | 409 for (unsigned int fragment_index = 0; fragment_index < numFragments; 410 fragment_index++) 411 { 412 bool M5_VAR_USED is_last_fragment = false; 413 414 if (fragment_addr == base_addr) { 415 /* First fragment */ 416 fragment_size = first_fragment_size; --- 4 unchanged lines hidden (view full) --- 421 is_last_fragment = true; 422 } else { 423 /* Middle fragments */ 424 fragment_size = line_width; 425 } 426 } 427 428 RequestPtr fragment = std::make_shared<Request>(); |
429 bool disabled_fragment = false; |
|
424 425 fragment->setContext(request->contextId()); | 430 431 fragment->setContext(request->contextId()); |
426 fragment->setVirt(0 /* asid */, 427 fragment_addr, fragment_size, request->getFlags(), 428 request->masterId(), 429 request->getPC()); | 432 if (byte_enable.empty()) { 433 fragment->setVirt(0 /* asid */, 434 fragment_addr, fragment_size, request->getFlags(), 435 request->masterId(), 436 request->getPC()); 437 } else { 438 // Set up byte-enable mask for the current fragment 439 auto it_start = byte_enable.begin() + 440 (fragment_addr - base_addr); 441 auto it_end = byte_enable.begin() + 442 (fragment_addr - base_addr) + fragment_size; 443 if (isAnyActiveElement(it_start, it_end)) { 444 fragment->setVirt(0 /* asid */, 445 fragment_addr, fragment_size, request->getFlags(), 446 request->masterId(), 447 request->getPC()); 448 fragment->setByteEnable(std::vector<bool>(it_start, it_end)); 449 } else { 450 disabled_fragment = true; 451 } 452 } |
430 | 453 |
431 DPRINTFS(MinorMem, (&port), "Generating fragment addr: 0x%x size: %d" 432 " (whole request addr: 0x%x size: %d) %s\n", 433 fragment_addr, fragment_size, base_addr, whole_size, 434 (is_last_fragment ? "last fragment" : "")); | 454 if (!disabled_fragment) { 455 DPRINTFS(MinorMem, (&port), "Generating fragment addr: 0x%x" 456 " size: %d (whole request addr: 0x%x size: %d) %s\n", 457 fragment_addr, fragment_size, base_addr, whole_size, 458 (is_last_fragment ? "last fragment" : "")); |
435 | 459 |
436 fragment_addr += fragment_size; | 460 fragmentRequests.push_back(fragment); 461 } else { 462 num_disabled_fragments++; 463 } |
437 | 464 |
438 fragmentRequests.push_back(fragment); | 465 fragment_addr += fragment_size; |
439 } | 466 } |
467 assert(numFragments >= num_disabled_fragments); 468 numFragments -= num_disabled_fragments; |
|
440} 441 442void 443LSQ::SplitDataRequest::makeFragmentPackets() 444{ | 469} 470 471void 472LSQ::SplitDataRequest::makeFragmentPackets() 473{ |
474 assert(numTranslatedFragments > 0); |
|
445 Addr base_addr = request->getVaddr(); 446 447 DPRINTFS(MinorMem, (&port), "Making packets for request: %s\n", *inst); 448 | 475 Addr base_addr = request->getVaddr(); 476 477 DPRINTFS(MinorMem, (&port), "Making packets for request: %s\n", *inst); 478 |
449 for (unsigned int fragment_index = 0; fragment_index < numFragments; | 479 for (unsigned int fragment_index = 0; 480 fragment_index < numTranslatedFragments; |
450 fragment_index++) 451 { 452 RequestPtr fragment = fragmentRequests[fragment_index]; 453 454 DPRINTFS(MinorMem, (&port), "Making packet %d for request: %s" 455 " (%d, 0x%x)\n", 456 fragment_index, *inst, 457 (fragment->hasPaddr() ? "has paddr" : "no paddr"), --- 27 unchanged lines hidden (view full) --- 485 * fragment */ 486 request->setPaddr(fragmentRequests[0]->getPaddr()); 487 makePacket(); 488} 489 490void 491LSQ::SplitDataRequest::startAddrTranslation() 492{ | 481 fragment_index++) 482 { 483 RequestPtr fragment = fragmentRequests[fragment_index]; 484 485 DPRINTFS(MinorMem, (&port), "Making packet %d for request: %s" 486 " (%d, 0x%x)\n", 487 fragment_index, *inst, 488 (fragment->hasPaddr() ? "has paddr" : "no paddr"), --- 27 unchanged lines hidden (view full) --- 516 * fragment */ 517 request->setPaddr(fragmentRequests[0]->getPaddr()); 518 makePacket(); 519} 520 521void 522LSQ::SplitDataRequest::startAddrTranslation() 523{ |
493 setState(LSQ::LSQRequest::InTranslation); 494 | |
495 makeFragmentRequests(); 496 | 524 makeFragmentRequests(); 525 |
497 numInTranslationFragments = 0; 498 numTranslatedFragments = 0; | 526 if (numFragments > 0) { 527 setState(LSQ::LSQRequest::InTranslation); 528 numInTranslationFragments = 0; 529 numTranslatedFragments = 0; |
499 | 530 |
500 /* @todo, just do these in sequence for now with 501 * a loop of: 502 * do { 503 * sendNextFragmentToTranslation ; translateTiming ; finish 504 * } while (numTranslatedFragments != numFragments); 505 */ | 531 /* @todo, just do these in sequence for now with 532 * a loop of: 533 * do { 534 * sendNextFragmentToTranslation ; translateTiming ; finish 535 * } while (numTranslatedFragments != numFragments); 536 */ |
506 | 537 |
507 /* Do first translation */ 508 sendNextFragmentToTranslation(); | 538 /* Do first translation */ 539 sendNextFragmentToTranslation(); 540 } else { 541 disableMemAccess(); 542 setState(LSQ::LSQRequest::Complete); 543 } |
509} 510 511PacketPtr 512LSQ::SplitDataRequest::getHeadPacket() 513{ | 544} 545 546PacketPtr 547LSQ::SplitDataRequest::getHeadPacket() 548{ |
514 assert(numIssuedFragments < numFragments); | 549 assert(numIssuedFragments < numTranslatedFragments); |
515 516 return fragmentPackets[numIssuedFragments]; 517} 518 519void 520LSQ::SplitDataRequest::stepToNextPacket() 521{ | 550 551 return fragmentPackets[numIssuedFragments]; 552} 553 554void 555LSQ::SplitDataRequest::stepToNextPacket() 556{ |
522 assert(numIssuedFragments < numFragments); | 557 assert(numIssuedFragments < numTranslatedFragments); |
523 524 numIssuedFragments++; 525} 526 527void 528LSQ::SplitDataRequest::retireResponse(PacketPtr response) 529{ | 558 559 numIssuedFragments++; 560} 561 562void 563LSQ::SplitDataRequest::retireResponse(PacketPtr response) 564{ |
530 assert(numRetiredFragments < numFragments); | 565 assert(numRetiredFragments < numTranslatedFragments); |
531 532 DPRINTFS(MinorMem, (&port), "Retiring fragment addr: 0x%x size: %d" | 566 567 DPRINTFS(MinorMem, (&port), "Retiring fragment addr: 0x%x size: %d" |
533 " offset: 0x%x (retired fragment num: %d) %s\n", | 568 " offset: 0x%x (retired fragment num: %d)\n", |
534 response->req->getVaddr(), response->req->getSize(), 535 request->getVaddr() - response->req->getVaddr(), | 569 response->req->getVaddr(), response->req->getSize(), 570 request->getVaddr() - response->req->getVaddr(), |
536 numRetiredFragments, 537 (fault == NoFault ? "" : fault->name())); | 571 numRetiredFragments); |
538 539 numRetiredFragments++; 540 541 if (skipped) { 542 /* Skip because we already knew the request had faulted or been 543 * skipped */ 544 DPRINTFS(MinorMem, (&port), "Skipping this fragment\n"); 545 } else if (response->isError()) { --- 22 unchanged lines hidden (view full) --- 568 /* Complete early if we're skipping are no more in-flight accesses */ 569 if (skipped && !hasPacketsInMemSystem()) { 570 DPRINTFS(MinorMem, (&port), "Completed skipped burst\n"); 571 setState(Complete); 572 if (packet->needsResponse()) 573 packet->makeResponse(); 574 } 575 | 572 573 numRetiredFragments++; 574 575 if (skipped) { 576 /* Skip because we already knew the request had faulted or been 577 * skipped */ 578 DPRINTFS(MinorMem, (&port), "Skipping this fragment\n"); 579 } else if (response->isError()) { --- 22 unchanged lines hidden (view full) --- 602 /* Complete early if we're skipping are no more in-flight accesses */ 603 if (skipped && !hasPacketsInMemSystem()) { 604 DPRINTFS(MinorMem, (&port), "Completed skipped burst\n"); 605 setState(Complete); 606 if (packet->needsResponse()) 607 packet->makeResponse(); 608 } 609 |
576 if (numRetiredFragments == numFragments) | 610 if (numRetiredFragments == numTranslatedFragments) |
577 setState(Complete); 578 579 if (!skipped && isComplete()) { 580 DPRINTFS(MinorMem, (&port), "Completed burst %d\n", packet != NULL); 581 582 DPRINTFS(MinorMem, (&port), "Retired packet isRead: %d isWrite: %d" 583 " needsResponse: %d packetSize: %s requestSize: %s responseSize:" 584 " %s\n", packet->isRead(), packet->isWrite(), --- 887 unchanged lines hidden (view full) --- 1472 DPRINTF(Activity, "Need to tick\n"); 1473 1474 return ret; 1475} 1476 1477void 1478LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data, 1479 unsigned int size, Addr addr, Request::Flags flags, | 611 setState(Complete); 612 613 if (!skipped && isComplete()) { 614 DPRINTFS(MinorMem, (&port), "Completed burst %d\n", packet != NULL); 615 616 DPRINTFS(MinorMem, (&port), "Retired packet isRead: %d isWrite: %d" 617 " needsResponse: %d packetSize: %s requestSize: %s responseSize:" 618 " %s\n", packet->isRead(), packet->isWrite(), --- 887 unchanged lines hidden (view full) --- 1506 DPRINTF(Activity, "Need to tick\n"); 1507 1508 return ret; 1509} 1510 1511void 1512LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data, 1513 unsigned int size, Addr addr, Request::Flags flags, |
1480 uint64_t *res, AtomicOpFunctor *amo_op) | 1514 uint64_t *res, AtomicOpFunctor *amo_op, 1515 const std::vector<bool>& byteEnable) |
1481{ 1482 bool needs_burst = transferNeedsBurst(addr, size, lineWidth); 1483 1484 if (needs_burst && inst->staticInst->isAtomic()) { 1485 // AMO requests that access across a cache line boundary are not 1486 // allowed since the cache does not guarantee AMO ops to be executed 1487 // atomically in two cache lines 1488 // For ISAs such as x86 that requires AMO operations to work on --- 39 unchanged lines hidden (view full) --- 1528 inst->traceData->setMem(addr, size, flags); 1529 1530 int cid = cpu.threads[inst->id.threadId]->getTC()->contextId(); 1531 request->request->setContext(cid); 1532 request->request->setVirt(0 /* asid */, 1533 addr, size, flags, cpu.dataMasterId(), 1534 /* I've no idea why we need the PC, but give it */ 1535 inst->pc.instAddr(), amo_op); | 1516{ 1517 bool needs_burst = transferNeedsBurst(addr, size, lineWidth); 1518 1519 if (needs_burst && inst->staticInst->isAtomic()) { 1520 // AMO requests that access across a cache line boundary are not 1521 // allowed since the cache does not guarantee AMO ops to be executed 1522 // atomically in two cache lines 1523 // For ISAs such as x86 that requires AMO operations to work on --- 39 unchanged lines hidden (view full) --- 1563 inst->traceData->setMem(addr, size, flags); 1564 1565 int cid = cpu.threads[inst->id.threadId]->getTC()->contextId(); 1566 request->request->setContext(cid); 1567 request->request->setVirt(0 /* asid */, 1568 addr, size, flags, cpu.dataMasterId(), 1569 /* I've no idea why we need the PC, but give it */ 1570 inst->pc.instAddr(), amo_op); |
1571 if (!byteEnable.empty()) { 1572 request->request->setByteEnable(byteEnable); 1573 } |
|
1536 1537 requests.push(request); 1538 request->startAddrTranslation(); 1539} 1540 1541void 1542LSQ::pushFailedRequest(MinorDynInstPtr inst) 1543{ --- 141 unchanged lines hidden --- | 1574 1575 requests.push(request); 1576 request->startAddrTranslation(); 1577} 1578 1579void 1580LSQ::pushFailedRequest(MinorDynInstPtr inst) 1581{ --- 141 unchanged lines hidden --- |