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