lsq.cc revision 11793
1/* 2 * Copyright (c) 2013-2014 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 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Andrew Bardsley 38 */ 39 40#include "cpu/minor/lsq.hh" 41 42#include <iomanip> 43#include <sstream> 44 45#include "arch/locked_mem.hh" 46#include "arch/mmapped_ipr.hh" 47#include "cpu/minor/cpu.hh" 48#include "cpu/minor/exec_context.hh" 49#include "cpu/minor/execute.hh" 50#include "cpu/minor/pipeline.hh" 51#include "debug/Activity.hh" 52#include "debug/MinorMem.hh" 53 54namespace Minor 55{ 56 57/** Returns the offset of addr into an aligned a block of size block_size */ 58static Addr 59addrBlockOffset(Addr addr, unsigned int block_size) 60{ 61 return addr & (block_size - 1); 62} 63 64/** Returns true if the given [addr .. addr+size-1] transfer needs to be 65 * fragmented across a block size of block_size */ 66static bool 67transferNeedsBurst(Addr addr, unsigned int size, unsigned int block_size) 68{ 69 return (addrBlockOffset(addr, block_size) + size) > block_size; 70} 71 72LSQ::LSQRequest::LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_, 73 PacketDataPtr data_, uint64_t *res_) : 74 SenderState(), 75 port(port_), 76 inst(inst_), 77 isLoad(isLoad_), 78 data(data_), 79 packet(NULL), 80 request(), 81 fault(NoFault), 82 res(res_), 83 skipped(false), 84 issuedToMemory(false), 85 state(NotIssued) 86{ } 87 88LSQ::AddrRangeCoverage 89LSQ::LSQRequest::containsAddrRangeOf( 90 Addr req1_addr, unsigned int req1_size, 91 Addr req2_addr, unsigned int req2_size) 92{ 93 /* 'end' here means the address of the byte just past the request 94 * blocks */ 95 Addr req2_end_addr = req2_addr + req2_size; 96 Addr req1_end_addr = req1_addr + req1_size; 97 98 AddrRangeCoverage ret; 99 100 if (req1_addr > req2_end_addr || req1_end_addr < req2_addr) 101 ret = NoAddrRangeCoverage; 102 else if (req1_addr <= req2_addr && req1_end_addr >= req2_end_addr) 103 ret = FullAddrRangeCoverage; 104 else 105 ret = PartialAddrRangeCoverage; 106 107 return ret; 108} 109 110LSQ::AddrRangeCoverage 111LSQ::LSQRequest::containsAddrRangeOf(LSQRequestPtr other_request) 112{ 113 return containsAddrRangeOf(request.getPaddr(), request.getSize(), 114 other_request->request.getPaddr(), other_request->request.getSize()); 115} 116 117bool 118LSQ::LSQRequest::isBarrier() 119{ 120 return inst->isInst() && inst->staticInst->isMemBarrier(); 121} 122 123bool 124LSQ::LSQRequest::needsToBeSentToStoreBuffer() 125{ 126 return state == StoreToStoreBuffer; 127} 128 129void 130LSQ::LSQRequest::setState(LSQRequestState new_state) 131{ 132 DPRINTFS(MinorMem, (&port), "Setting state from %d to %d for request:" 133 " %s\n", state, new_state, *inst); 134 state = new_state; 135} 136 137bool 138LSQ::LSQRequest::isComplete() const 139{ 140 /* @todo, There is currently only one 'completed' state. This 141 * may not be a good choice */ 142 return state == Complete; 143} 144 145void 146LSQ::LSQRequest::reportData(std::ostream &os) const 147{ 148 os << (isLoad ? 'R' : 'W') << ';'; 149 inst->reportData(os); 150 os << ';' << state; 151} 152 153std::ostream & 154operator <<(std::ostream &os, LSQ::AddrRangeCoverage coverage) 155{ 156 switch (coverage) { 157 case LSQ::PartialAddrRangeCoverage: 158 os << "PartialAddrRangeCoverage"; 159 break; 160 case LSQ::FullAddrRangeCoverage: 161 os << "FullAddrRangeCoverage"; 162 break; 163 case LSQ::NoAddrRangeCoverage: 164 os << "NoAddrRangeCoverage"; 165 break; 166 default: 167 os << "AddrRangeCoverage-" << static_cast<int>(coverage); 168 break; 169 } 170 return os; 171} 172 173std::ostream & 174operator <<(std::ostream &os, LSQ::LSQRequest::LSQRequestState state) 175{ 176 switch (state) { 177 case LSQ::LSQRequest::NotIssued: 178 os << "NotIssued"; 179 break; 180 case LSQ::LSQRequest::InTranslation: 181 os << "InTranslation"; 182 break; 183 case LSQ::LSQRequest::Translated: 184 os << "Translated"; 185 break; 186 case LSQ::LSQRequest::Failed: 187 os << "Failed"; 188 break; 189 case LSQ::LSQRequest::RequestIssuing: 190 os << "RequestIssuing"; 191 break; 192 case LSQ::LSQRequest::StoreToStoreBuffer: 193 os << "StoreToStoreBuffer"; 194 break; 195 case LSQ::LSQRequest::StoreInStoreBuffer: 196 os << "StoreInStoreBuffer"; 197 break; 198 case LSQ::LSQRequest::StoreBufferIssuing: 199 os << "StoreBufferIssuing"; 200 break; 201 case LSQ::LSQRequest::RequestNeedsRetry: 202 os << "RequestNeedsRetry"; 203 break; 204 case LSQ::LSQRequest::StoreBufferNeedsRetry: 205 os << "StoreBufferNeedsRetry"; 206 break; 207 case LSQ::LSQRequest::Complete: 208 os << "Complete"; 209 break; 210 default: 211 os << "LSQRequestState-" << static_cast<int>(state); 212 break; 213 } 214 return os; 215} 216 217void 218LSQ::clearMemBarrier(MinorDynInstPtr inst) 219{ 220 bool is_last_barrier = 221 inst->id.execSeqNum >= lastMemBarrier[inst->id.threadId]; 222 223 DPRINTF(MinorMem, "Moving %s barrier out of store buffer inst: %s\n", 224 (is_last_barrier ? "last" : "a"), *inst); 225 226 if (is_last_barrier) 227 lastMemBarrier[inst->id.threadId] = 0; 228} 229 230void 231LSQ::SingleDataRequest::finish(const Fault &fault_, RequestPtr request_, 232 ThreadContext *tc, BaseTLB::Mode mode) 233{ 234 fault = fault_; 235 236 port.numAccessesInDTLB--; 237 238 DPRINTFS(MinorMem, (&port), "Received translation response for" 239 " request: %s\n", *inst); 240 241 makePacket(); 242 243 setState(Translated); 244 port.tryToSendToTransfers(this); 245 246 /* Let's try and wake up the processor for the next cycle */ 247 port.cpu.wakeupOnEvent(Pipeline::ExecuteStageId); 248} 249 250void 251LSQ::SingleDataRequest::startAddrTranslation() 252{ 253 ThreadContext *thread = port.cpu.getContext( 254 inst->id.threadId); 255 256 port.numAccessesInDTLB++; 257 258 setState(LSQ::LSQRequest::InTranslation); 259 260 DPRINTFS(MinorMem, (&port), "Submitting DTLB request\n"); 261 /* Submit the translation request. The response will come through 262 * finish/markDelayed on the LSQRequest as it bears the Translation 263 * interface */ 264 thread->getDTBPtr()->translateTiming( 265 &request, thread, this, (isLoad ? BaseTLB::Read : BaseTLB::Write)); 266} 267 268void 269LSQ::SingleDataRequest::retireResponse(PacketPtr packet_) 270{ 271 DPRINTFS(MinorMem, (&port), "Retiring packet\n"); 272 packet = packet_; 273 packetInFlight = false; 274 setState(Complete); 275} 276 277void 278LSQ::SplitDataRequest::finish(const Fault &fault_, RequestPtr request_, 279 ThreadContext *tc, BaseTLB::Mode mode) 280{ 281 fault = fault_; 282 283 port.numAccessesInDTLB--; 284 285 unsigned int M5_VAR_USED expected_fragment_index = 286 numTranslatedFragments; 287 288 numInTranslationFragments--; 289 numTranslatedFragments++; 290 291 DPRINTFS(MinorMem, (&port), "Received translation response for fragment" 292 " %d of request: %s\n", expected_fragment_index, *inst); 293 294 assert(request_ == fragmentRequests[expected_fragment_index]); 295 296 /* Wake up next cycle to get things going again in case the 297 * tryToSendToTransfers does take */ 298 port.cpu.wakeupOnEvent(Pipeline::ExecuteStageId); 299 300 if (fault != NoFault) { 301 /* tryToSendToTransfers will handle the fault */ 302 303 DPRINTFS(MinorMem, (&port), "Faulting translation for fragment:" 304 " %d of request: %s\n", 305 expected_fragment_index, *inst); 306 307 setState(Translated); 308 port.tryToSendToTransfers(this); 309 } else if (numTranslatedFragments == numFragments) { 310 makeFragmentPackets(); 311 312 setState(Translated); 313 port.tryToSendToTransfers(this); 314 } else { 315 /* Avoid calling translateTiming from within ::finish */ 316 assert(!translationEvent.scheduled()); 317 port.cpu.schedule(translationEvent, curTick()); 318 } 319} 320 321LSQ::SplitDataRequest::SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_, 322 bool isLoad_, PacketDataPtr data_, uint64_t *res_) : 323 LSQRequest(port_, inst_, isLoad_, data_, res_), 324 translationEvent(*this), 325 numFragments(0), 326 numInTranslationFragments(0), 327 numTranslatedFragments(0), 328 numIssuedFragments(0), 329 numRetiredFragments(0), 330 fragmentRequests(), 331 fragmentPackets() 332{ 333 /* Don't know how many elements are needed until the request is 334 * populated by the caller. */ 335} 336 337LSQ::SplitDataRequest::~SplitDataRequest() 338{ 339 for (auto i = fragmentRequests.begin(); 340 i != fragmentRequests.end(); i++) 341 { 342 delete *i; 343 } 344 345 for (auto i = fragmentPackets.begin(); 346 i != fragmentPackets.end(); i++) 347 { 348 delete *i; 349 } 350} 351 352void 353LSQ::SplitDataRequest::makeFragmentRequests() 354{ 355 Addr base_addr = request.getVaddr(); 356 unsigned int whole_size = request.getSize(); 357 unsigned int line_width = port.lineWidth; 358 359 unsigned int fragment_size; 360 Addr fragment_addr; 361 362 /* Assume that this transfer is across potentially many block snap 363 * boundaries: 364 * 365 * | _|________|________|________|___ | 366 * | |0| 1 | 2 | 3 | 4 | | 367 * | |_|________|________|________|___| | 368 * | | | | | | 369 * 370 * The first transfer (0) can be up to lineWidth in size. 371 * All the middle transfers (1-3) are lineWidth in size 372 * The last transfer (4) can be from zero to lineWidth - 1 in size 373 */ 374 unsigned int first_fragment_offset = 375 addrBlockOffset(base_addr, line_width); 376 unsigned int last_fragment_size = 377 addrBlockOffset(base_addr + whole_size, line_width); 378 unsigned int first_fragment_size = 379 line_width - first_fragment_offset; 380 381 unsigned int middle_fragments_total_size = 382 whole_size - (first_fragment_size + last_fragment_size); 383 384 assert(addrBlockOffset(middle_fragments_total_size, line_width) == 0); 385 386 unsigned int middle_fragment_count = 387 middle_fragments_total_size / line_width; 388 389 numFragments = 1 /* first */ + middle_fragment_count + 390 (last_fragment_size == 0 ? 0 : 1); 391 392 DPRINTFS(MinorMem, (&port), "Dividing transfer into %d fragmentRequests." 393 " First fragment size: %d Last fragment size: %d\n", 394 numFragments, first_fragment_size, 395 (last_fragment_size == 0 ? line_width : last_fragment_size)); 396 397 assert(((middle_fragment_count * line_width) + 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 for (unsigned int fragment_index = 0; fragment_index < numFragments; 407 fragment_index++) 408 { 409 bool M5_VAR_USED is_last_fragment = false; 410 411 if (fragment_addr == base_addr) { 412 /* First fragment */ 413 fragment_size = first_fragment_size; 414 } else { 415 if ((fragment_addr + line_width) > end_addr) { 416 /* Adjust size of last fragment */ 417 fragment_size = end_addr - fragment_addr; 418 is_last_fragment = true; 419 } else { 420 /* Middle fragments */ 421 fragment_size = line_width; 422 } 423 } 424 425 Request *fragment = new Request(); 426 427 fragment->setContext(request.contextId()); 428 fragment->setVirt(0 /* asid */, 429 fragment_addr, fragment_size, request.getFlags(), 430 request.masterId(), 431 request.getPC()); 432 433 DPRINTFS(MinorMem, (&port), "Generating fragment addr: 0x%x size: %d" 434 " (whole request addr: 0x%x size: %d) %s\n", 435 fragment_addr, fragment_size, base_addr, whole_size, 436 (is_last_fragment ? "last fragment" : "")); 437 438 fragment_addr += fragment_size; 439 440 fragmentRequests.push_back(fragment); 441 } 442} 443 444void 445LSQ::SplitDataRequest::makeFragmentPackets() 446{ 447 Addr base_addr = request.getVaddr(); 448 449 DPRINTFS(MinorMem, (&port), "Making packets for request: %s\n", *inst); 450 451 for (unsigned int fragment_index = 0; fragment_index < numFragments; 452 fragment_index++) 453 { 454 Request *fragment = fragmentRequests[fragment_index]; 455 456 DPRINTFS(MinorMem, (&port), "Making packet %d for request: %s" 457 " (%d, 0x%x)\n", 458 fragment_index, *inst, 459 (fragment->hasPaddr() ? "has paddr" : "no paddr"), 460 (fragment->hasPaddr() ? fragment->getPaddr() : 0)); 461 462 Addr fragment_addr = fragment->getVaddr(); 463 unsigned int fragment_size = fragment->getSize(); 464 465 uint8_t *request_data = NULL; 466 467 if (!isLoad) { 468 /* Split data for Packets. Will become the property of the 469 * outgoing Packets */ 470 request_data = new uint8_t[fragment_size]; 471 std::memcpy(request_data, data + (fragment_addr - base_addr), 472 fragment_size); 473 } 474 475 assert(fragment->hasPaddr()); 476 477 PacketPtr fragment_packet = 478 makePacketForRequest(*fragment, isLoad, this, request_data); 479 480 fragmentPackets.push_back(fragment_packet); 481 /* Accumulate flags in parent request */ 482 request.setFlags(fragment->getFlags()); 483 } 484 485 /* Might as well make the overall/response packet here */ 486 /* Get the physical address for the whole request/packet from the first 487 * fragment */ 488 request.setPaddr(fragmentRequests[0]->getPaddr()); 489 makePacket(); 490} 491 492void 493LSQ::SplitDataRequest::startAddrTranslation() 494{ 495 setState(LSQ::LSQRequest::InTranslation); 496 497 makeFragmentRequests(); 498 499 numInTranslationFragments = 0; 500 numTranslatedFragments = 0; 501 502 /* @todo, just do these in sequence for now with 503 * a loop of: 504 * do { 505 * sendNextFragmentToTranslation ; translateTiming ; finish 506 * } while (numTranslatedFragments != numFragments); 507 */ 508 509 /* Do first translation */ 510 sendNextFragmentToTranslation(); 511} 512 513PacketPtr 514LSQ::SplitDataRequest::getHeadPacket() 515{ 516 assert(numIssuedFragments < numFragments); 517 518 return fragmentPackets[numIssuedFragments]; 519} 520 521void 522LSQ::SplitDataRequest::stepToNextPacket() 523{ 524 assert(numIssuedFragments < numFragments); 525 526 numIssuedFragments++; 527} 528 529void 530LSQ::SplitDataRequest::retireResponse(PacketPtr response) 531{ 532 assert(numRetiredFragments < numFragments); 533 534 DPRINTFS(MinorMem, (&port), "Retiring fragment addr: 0x%x size: %d" 535 " offset: 0x%x (retired fragment num: %d) %s\n", 536 response->req->getVaddr(), response->req->getSize(), 537 request.getVaddr() - response->req->getVaddr(), 538 numRetiredFragments, 539 (fault == NoFault ? "" : fault->name())); 540 541 numRetiredFragments++; 542 543 if (skipped) { 544 /* Skip because we already knew the request had faulted or been 545 * skipped */ 546 DPRINTFS(MinorMem, (&port), "Skipping this fragment\n"); 547 } else if (response->isError()) { 548 /* Mark up the error and leave to execute to handle it */ 549 DPRINTFS(MinorMem, (&port), "Fragment has an error, skipping\n"); 550 setSkipped(); 551 packet->copyError(response); 552 } else { 553 if (isLoad) { 554 if (!data) { 555 /* For a split transfer, a Packet must be constructed 556 * to contain all returning data. This is that packet's 557 * data */ 558 data = new uint8_t[request.getSize()]; 559 } 560 561 /* Populate the portion of the overall response data represented 562 * by the response fragment */ 563 std::memcpy( 564 data + (response->req->getVaddr() - request.getVaddr()), 565 response->getConstPtr<uint8_t>(), 566 response->req->getSize()); 567 } 568 } 569 570 /* Complete early if we're skipping are no more in-flight accesses */ 571 if (skipped && !hasPacketsInMemSystem()) { 572 DPRINTFS(MinorMem, (&port), "Completed skipped burst\n"); 573 setState(Complete); 574 if (packet->needsResponse()) 575 packet->makeResponse(); 576 } 577 578 if (numRetiredFragments == numFragments) 579 setState(Complete); 580 581 if (!skipped && isComplete()) { 582 DPRINTFS(MinorMem, (&port), "Completed burst %d\n", packet != NULL); 583 584 DPRINTFS(MinorMem, (&port), "Retired packet isRead: %d isWrite: %d" 585 " needsResponse: %d packetSize: %s requestSize: %s responseSize:" 586 " %s\n", packet->isRead(), packet->isWrite(), 587 packet->needsResponse(), packet->getSize(), request.getSize(), 588 response->getSize()); 589 590 /* A request can become complete by several paths, this is a sanity 591 * check to make sure the packet's data is created */ 592 if (!data) { 593 data = new uint8_t[request.getSize()]; 594 } 595 596 if (isLoad) { 597 DPRINTFS(MinorMem, (&port), "Copying read data\n"); 598 std::memcpy(packet->getPtr<uint8_t>(), data, request.getSize()); 599 } 600 packet->makeResponse(); 601 } 602 603 /* Packets are all deallocated together in ~SplitLSQRequest */ 604} 605 606void 607LSQ::SplitDataRequest::sendNextFragmentToTranslation() 608{ 609 unsigned int fragment_index = numTranslatedFragments; 610 611 ThreadContext *thread = port.cpu.getContext( 612 inst->id.threadId); 613 614 DPRINTFS(MinorMem, (&port), "Submitting DTLB request for fragment: %d\n", 615 fragment_index); 616 617 port.numAccessesInDTLB++; 618 numInTranslationFragments++; 619 620 thread->getDTBPtr()->translateTiming( 621 fragmentRequests[fragment_index], thread, this, (isLoad ? 622 BaseTLB::Read : BaseTLB::Write)); 623} 624 625bool 626LSQ::StoreBuffer::canInsert() const 627{ 628 /* @todo, support store amalgamation */ 629 return slots.size() < numSlots; 630} 631 632void 633LSQ::StoreBuffer::deleteRequest(LSQRequestPtr request) 634{ 635 auto found = std::find(slots.begin(), slots.end(), request); 636 637 if (found != slots.end()) { 638 DPRINTF(MinorMem, "Deleting request: %s %s %s from StoreBuffer\n", 639 request, *found, *(request->inst)); 640 slots.erase(found); 641 642 delete request; 643 } 644} 645 646void 647LSQ::StoreBuffer::insert(LSQRequestPtr request) 648{ 649 if (!canInsert()) { 650 warn("%s: store buffer insertion without space to insert from" 651 " inst: %s\n", name(), *(request->inst)); 652 } 653 654 DPRINTF(MinorMem, "Pushing store: %s into store buffer\n", request); 655 656 numUnissuedAccesses++; 657 658 if (request->state != LSQRequest::Complete) 659 request->setState(LSQRequest::StoreInStoreBuffer); 660 661 slots.push_back(request); 662 663 /* Let's try and wake up the processor for the next cycle to step 664 * the store buffer */ 665 lsq.cpu.wakeupOnEvent(Pipeline::ExecuteStageId); 666} 667 668LSQ::AddrRangeCoverage 669LSQ::StoreBuffer::canForwardDataToLoad(LSQRequestPtr request, 670 unsigned int &found_slot) 671{ 672 unsigned int slot_index = slots.size() - 1; 673 auto i = slots.rbegin(); 674 AddrRangeCoverage ret = NoAddrRangeCoverage; 675 676 /* Traverse the store buffer in reverse order (most to least recent) 677 * and try to find a slot whose address range overlaps this request */ 678 while (ret == NoAddrRangeCoverage && i != slots.rend()) { 679 LSQRequestPtr slot = *i; 680 681 if (slot->packet && 682 slot->inst->id.threadId == request->inst->id.threadId) { 683 AddrRangeCoverage coverage = slot->containsAddrRangeOf(request); 684 685 if (coverage != NoAddrRangeCoverage) { 686 DPRINTF(MinorMem, "Forwarding: slot: %d result: %s thisAddr:" 687 " 0x%x thisSize: %d slotAddr: 0x%x slotSize: %d\n", 688 slot_index, coverage, 689 request->request.getPaddr(), request->request.getSize(), 690 slot->request.getPaddr(), slot->request.getSize()); 691 692 found_slot = slot_index; 693 ret = coverage; 694 } 695 } 696 697 i++; 698 slot_index--; 699 } 700 701 return ret; 702} 703 704/** Fill the given packet with appropriate date from slot slot_number */ 705void 706LSQ::StoreBuffer::forwardStoreData(LSQRequestPtr load, 707 unsigned int slot_number) 708{ 709 assert(slot_number < slots.size()); 710 assert(load->packet); 711 assert(load->isLoad); 712 713 LSQRequestPtr store = slots[slot_number]; 714 715 assert(store->packet); 716 assert(store->containsAddrRangeOf(load) == FullAddrRangeCoverage); 717 718 Addr load_addr = load->request.getPaddr(); 719 Addr store_addr = store->request.getPaddr(); 720 Addr addr_offset = load_addr - store_addr; 721 722 unsigned int load_size = load->request.getSize(); 723 724 DPRINTF(MinorMem, "Forwarding %d bytes for addr: 0x%x from store buffer" 725 " slot: %d addr: 0x%x addressOffset: 0x%x\n", 726 load_size, load_addr, slot_number, 727 store_addr, addr_offset); 728 729 void *load_packet_data = load->packet->getPtr<void>(); 730 void *store_packet_data = store->packet->getPtr<uint8_t>() + addr_offset; 731 732 std::memcpy(load_packet_data, store_packet_data, load_size); 733} 734 735void 736LSQ::StoreBuffer::countIssuedStore(LSQRequestPtr request) 737{ 738 /* Barriers are accounted for as they are cleared from 739 * the queue, not after their transfers are complete */ 740 if (!request->isBarrier()) 741 numUnissuedAccesses--; 742} 743 744void 745LSQ::StoreBuffer::step() 746{ 747 DPRINTF(MinorMem, "StoreBuffer step numUnissuedAccesses: %d\n", 748 numUnissuedAccesses); 749 750 if (numUnissuedAccesses != 0 && lsq.state == LSQ::MemoryRunning) { 751 /* Clear all the leading barriers */ 752 while (!slots.empty() && 753 slots.front()->isComplete() && slots.front()->isBarrier()) 754 { 755 LSQRequestPtr barrier = slots.front(); 756 757 DPRINTF(MinorMem, "Clearing barrier for inst: %s\n", 758 *(barrier->inst)); 759 760 numUnissuedAccesses--; 761 lsq.clearMemBarrier(barrier->inst); 762 slots.pop_front(); 763 764 delete barrier; 765 } 766 767 auto i = slots.begin(); 768 bool issued = true; 769 unsigned int issue_count = 0; 770 771 /* Skip trying if the memory system is busy */ 772 if (lsq.state == LSQ::MemoryNeedsRetry) 773 issued = false; 774 775 /* Try to issue all stores in order starting from the head 776 * of the queue. Responses are allowed to be retired 777 * out of order */ 778 while (issued && 779 issue_count < storeLimitPerCycle && 780 lsq.canSendToMemorySystem() && 781 i != slots.end()) 782 { 783 LSQRequestPtr request = *i; 784 785 DPRINTF(MinorMem, "Considering request: %s, sentAllPackets: %d" 786 " state: %s\n", 787 *(request->inst), request->sentAllPackets(), 788 request->state); 789 790 if (request->isBarrier() && request->isComplete()) { 791 /* Give up at barriers */ 792 issued = false; 793 } else if (!(request->state == LSQRequest::StoreBufferIssuing && 794 request->sentAllPackets())) 795 { 796 DPRINTF(MinorMem, "Trying to send request: %s to memory" 797 " system\n", *(request->inst)); 798 799 if (lsq.tryToSend(request)) { 800 countIssuedStore(request); 801 issue_count++; 802 } else { 803 /* Don't step on to the next store buffer entry if this 804 * one hasn't issued all its packets as the store 805 * buffer must still enforce ordering */ 806 issued = false; 807 } 808 } 809 i++; 810 } 811 } 812} 813 814void 815LSQ::completeMemBarrierInst(MinorDynInstPtr inst, 816 bool committed) 817{ 818 if (committed) { 819 /* Not already sent to the store buffer as a store request? */ 820 if (!inst->inStoreBuffer) { 821 /* Insert an entry into the store buffer to tick off barriers 822 * until there are none in flight */ 823 storeBuffer.insert(new BarrierDataRequest(*this, inst)); 824 } 825 } else { 826 /* Clear the barrier anyway if it wasn't actually committed */ 827 clearMemBarrier(inst); 828 } 829} 830 831void 832LSQ::StoreBuffer::minorTrace() const 833{ 834 unsigned int size = slots.size(); 835 unsigned int i = 0; 836 std::ostringstream os; 837 838 while (i < size) { 839 LSQRequestPtr request = slots[i]; 840 841 request->reportData(os); 842 843 i++; 844 if (i < numSlots) 845 os << ','; 846 } 847 848 while (i < numSlots) { 849 os << '-'; 850 851 i++; 852 if (i < numSlots) 853 os << ','; 854 } 855 856 MINORTRACE("addr=%s num_unissued_stores=%d\n", os.str(), 857 numUnissuedAccesses); 858} 859 860void 861LSQ::tryToSendToTransfers(LSQRequestPtr request) 862{ 863 if (state == MemoryNeedsRetry) { 864 DPRINTF(MinorMem, "Request needs retry, not issuing to" 865 " memory until retry arrives\n"); 866 return; 867 } 868 869 if (request->state == LSQRequest::InTranslation) { 870 DPRINTF(MinorMem, "Request still in translation, not issuing to" 871 " memory\n"); 872 return; 873 } 874 875 assert(request->state == LSQRequest::Translated || 876 request->state == LSQRequest::RequestIssuing || 877 request->state == LSQRequest::Failed || 878 request->state == LSQRequest::Complete); 879 880 if (requests.empty() || requests.front() != request) { 881 DPRINTF(MinorMem, "Request not at front of requests queue, can't" 882 " issue to memory\n"); 883 return; 884 } 885 886 if (transfers.unreservedRemainingSpace() == 0) { 887 DPRINTF(MinorMem, "No space to insert request into transfers" 888 " queue\n"); 889 return; 890 } 891 892 if (request->isComplete() || request->state == LSQRequest::Failed) { 893 DPRINTF(MinorMem, "Passing a %s transfer on to transfers" 894 " queue\n", (request->isComplete() ? "completed" : "failed")); 895 request->setState(LSQRequest::Complete); 896 request->setSkipped(); 897 moveFromRequestsToTransfers(request); 898 return; 899 } 900 901 if (!execute.instIsRightStream(request->inst)) { 902 /* Wrong stream, try to abort the transfer but only do so if 903 * there are no packets in flight */ 904 if (request->hasPacketsInMemSystem()) { 905 DPRINTF(MinorMem, "Request's inst. is from the wrong stream," 906 " waiting for responses before aborting request\n"); 907 } else { 908 DPRINTF(MinorMem, "Request's inst. is from the wrong stream," 909 " aborting request\n"); 910 request->setState(LSQRequest::Complete); 911 request->setSkipped(); 912 moveFromRequestsToTransfers(request); 913 } 914 return; 915 } 916 917 if (request->fault != NoFault) { 918 if (request->inst->staticInst->isPrefetch()) { 919 DPRINTF(MinorMem, "Not signalling fault for faulting prefetch\n"); 920 } 921 DPRINTF(MinorMem, "Moving faulting request into the transfers" 922 " queue\n"); 923 request->setState(LSQRequest::Complete); 924 request->setSkipped(); 925 moveFromRequestsToTransfers(request); 926 return; 927 } 928 929 bool is_load = request->isLoad; 930 bool is_llsc = request->request.isLLSC(); 931 bool is_swap = request->request.isSwap(); 932 bool bufferable = !(request->request.isStrictlyOrdered() || 933 is_llsc || is_swap); 934 935 if (is_load) { 936 if (numStoresInTransfers != 0) { 937 DPRINTF(MinorMem, "Load request with stores still in transfers" 938 " queue, stalling\n"); 939 return; 940 } 941 } else { 942 /* Store. Can it be sent to the store buffer? */ 943 if (bufferable && !request->request.isMmappedIpr()) { 944 request->setState(LSQRequest::StoreToStoreBuffer); 945 moveFromRequestsToTransfers(request); 946 DPRINTF(MinorMem, "Moving store into transfers queue\n"); 947 return; 948 } 949 } 950 951 /* Check if this is the head instruction (and so must be executable as 952 * its stream sequence number was checked above) for loads which must 953 * not be speculatively issued and stores which must be issued here */ 954 if (!bufferable) { 955 if (!execute.instIsHeadInst(request->inst)) { 956 DPRINTF(MinorMem, "Memory access not the head inst., can't be" 957 " sure it can be performed, not issuing\n"); 958 return; 959 } 960 961 unsigned int forwarding_slot = 0; 962 963 if (storeBuffer.canForwardDataToLoad(request, forwarding_slot) != 964 NoAddrRangeCoverage) 965 { 966 DPRINTF(MinorMem, "Memory access can receive forwarded data" 967 " from the store buffer, need to wait for store buffer to" 968 " drain\n"); 969 return; 970 } 971 } 972 973 /* True: submit this packet to the transfers queue to be sent to the 974 * memory system. 975 * False: skip the memory and push a packet for this request onto 976 * requests */ 977 bool do_access = true; 978 979 if (!is_llsc) { 980 /* Check for match in the store buffer */ 981 if (is_load) { 982 unsigned int forwarding_slot = 0; 983 AddrRangeCoverage forwarding_result = 984 storeBuffer.canForwardDataToLoad(request, 985 forwarding_slot); 986 987 switch (forwarding_result) { 988 case FullAddrRangeCoverage: 989 /* Forward data from the store buffer into this request and 990 * repurpose this request's packet into a response packet */ 991 storeBuffer.forwardStoreData(request, forwarding_slot); 992 request->packet->makeResponse(); 993 994 /* Just move between queues, no access */ 995 do_access = false; 996 break; 997 case PartialAddrRangeCoverage: 998 DPRINTF(MinorMem, "Load partly satisfied by store buffer" 999 " data. Must wait for the store to complete\n"); 1000 return; 1001 break; 1002 case NoAddrRangeCoverage: 1003 DPRINTF(MinorMem, "No forwardable data from store buffer\n"); 1004 /* Fall through to try access */ 1005 break; 1006 } 1007 } 1008 } else { 1009 if (!canSendToMemorySystem()) { 1010 DPRINTF(MinorMem, "Can't send request to memory system yet\n"); 1011 return; 1012 } 1013 1014 SimpleThread &thread = *cpu.threads[request->inst->id.threadId]; 1015 1016 TheISA::PCState old_pc = thread.pcState(); 1017 ExecContext context(cpu, thread, execute, request->inst); 1018 1019 /* Handle LLSC requests and tests */ 1020 if (is_load) { 1021 TheISA::handleLockedRead(&context, &request->request); 1022 } else { 1023 do_access = TheISA::handleLockedWrite(&context, 1024 &request->request, cacheBlockMask); 1025 1026 if (!do_access) { 1027 DPRINTF(MinorMem, "Not perfoming a memory " 1028 "access for store conditional\n"); 1029 } 1030 } 1031 thread.pcState(old_pc); 1032 } 1033 1034 /* See the do_access comment above */ 1035 if (do_access) { 1036 if (!canSendToMemorySystem()) { 1037 DPRINTF(MinorMem, "Can't send request to memory system yet\n"); 1038 return; 1039 } 1040 1041 /* Remember if this is an access which can't be idly 1042 * discarded by an interrupt */ 1043 if (!bufferable && !request->issuedToMemory) { 1044 numAccessesIssuedToMemory++; 1045 request->issuedToMemory = true; 1046 } 1047 1048 if (tryToSend(request)) { 1049 moveFromRequestsToTransfers(request); 1050 } 1051 } else { 1052 request->setState(LSQRequest::Complete); 1053 moveFromRequestsToTransfers(request); 1054 } 1055} 1056 1057bool 1058LSQ::tryToSend(LSQRequestPtr request) 1059{ 1060 bool ret = false; 1061 1062 if (!canSendToMemorySystem()) { 1063 DPRINTF(MinorMem, "Can't send request: %s yet, no space in memory\n", 1064 *(request->inst)); 1065 } else { 1066 PacketPtr packet = request->getHeadPacket(); 1067 1068 DPRINTF(MinorMem, "Trying to send request: %s addr: 0x%x\n", 1069 *(request->inst), packet->req->getVaddr()); 1070 1071 /* The sender state of the packet *must* be an LSQRequest 1072 * so the response can be correctly handled */ 1073 assert(packet->findNextSenderState<LSQRequest>()); 1074 1075 if (request->request.isMmappedIpr()) { 1076 ThreadContext *thread = 1077 cpu.getContext(cpu.contextToThread( 1078 request->request.contextId())); 1079 1080 if (request->isLoad) { 1081 DPRINTF(MinorMem, "IPR read inst: %s\n", *(request->inst)); 1082 TheISA::handleIprRead(thread, packet); 1083 } else { 1084 DPRINTF(MinorMem, "IPR write inst: %s\n", *(request->inst)); 1085 TheISA::handleIprWrite(thread, packet); 1086 } 1087 1088 request->stepToNextPacket(); 1089 ret = request->sentAllPackets(); 1090 1091 if (!ret) { 1092 DPRINTF(MinorMem, "IPR access has another packet: %s\n", 1093 *(request->inst)); 1094 } 1095 1096 if (ret) 1097 request->setState(LSQRequest::Complete); 1098 else 1099 request->setState(LSQRequest::RequestIssuing); 1100 } else if (dcachePort.sendTimingReq(packet)) { 1101 DPRINTF(MinorMem, "Sent data memory request\n"); 1102 1103 numAccessesInMemorySystem++; 1104 1105 request->stepToNextPacket(); 1106 1107 ret = request->sentAllPackets(); 1108 1109 switch (request->state) { 1110 case LSQRequest::Translated: 1111 case LSQRequest::RequestIssuing: 1112 /* Fully or partially issued a request in the transfers 1113 * queue */ 1114 request->setState(LSQRequest::RequestIssuing); 1115 break; 1116 case LSQRequest::StoreInStoreBuffer: 1117 case LSQRequest::StoreBufferIssuing: 1118 /* Fully or partially issued a request in the store 1119 * buffer */ 1120 request->setState(LSQRequest::StoreBufferIssuing); 1121 break; 1122 default: 1123 assert(false); 1124 break; 1125 } 1126 1127 state = MemoryRunning; 1128 } else { 1129 DPRINTF(MinorMem, 1130 "Sending data memory request - needs retry\n"); 1131 1132 /* Needs to be resent, wait for that */ 1133 state = MemoryNeedsRetry; 1134 retryRequest = request; 1135 1136 switch (request->state) { 1137 case LSQRequest::Translated: 1138 case LSQRequest::RequestIssuing: 1139 request->setState(LSQRequest::RequestNeedsRetry); 1140 break; 1141 case LSQRequest::StoreInStoreBuffer: 1142 case LSQRequest::StoreBufferIssuing: 1143 request->setState(LSQRequest::StoreBufferNeedsRetry); 1144 break; 1145 default: 1146 assert(false); 1147 break; 1148 } 1149 } 1150 } 1151 1152 if (ret) 1153 threadSnoop(request); 1154 1155 return ret; 1156} 1157 1158void 1159LSQ::moveFromRequestsToTransfers(LSQRequestPtr request) 1160{ 1161 assert(!requests.empty() && requests.front() == request); 1162 assert(transfers.unreservedRemainingSpace() != 0); 1163 1164 /* Need to count the number of stores in the transfers 1165 * queue so that loads know when their store buffer forwarding 1166 * results will be correct (only when all those stores 1167 * have reached the store buffer) */ 1168 if (!request->isLoad) 1169 numStoresInTransfers++; 1170 1171 requests.pop(); 1172 transfers.push(request); 1173} 1174 1175bool 1176LSQ::canSendToMemorySystem() 1177{ 1178 return state == MemoryRunning && 1179 numAccessesInMemorySystem < inMemorySystemLimit; 1180} 1181 1182bool 1183LSQ::recvTimingResp(PacketPtr response) 1184{ 1185 LSQRequestPtr request = 1186 safe_cast<LSQRequestPtr>(response->popSenderState()); 1187 1188 DPRINTF(MinorMem, "Received response packet inst: %s" 1189 " addr: 0x%x cmd: %s\n", 1190 *(request->inst), response->getAddr(), 1191 response->cmd.toString()); 1192 1193 numAccessesInMemorySystem--; 1194 1195 if (response->isError()) { 1196 DPRINTF(MinorMem, "Received error response packet: %s\n", 1197 *request->inst); 1198 } 1199 1200 switch (request->state) { 1201 case LSQRequest::RequestIssuing: 1202 case LSQRequest::RequestNeedsRetry: 1203 /* Response to a request from the transfers queue */ 1204 request->retireResponse(response); 1205 1206 DPRINTF(MinorMem, "Has outstanding packets?: %d %d\n", 1207 request->hasPacketsInMemSystem(), request->isComplete()); 1208 1209 break; 1210 case LSQRequest::StoreBufferIssuing: 1211 case LSQRequest::StoreBufferNeedsRetry: 1212 /* Response to a request from the store buffer */ 1213 request->retireResponse(response); 1214 1215 /* Remove completed requests unless they are barriers (which will 1216 * need to be removed in order */ 1217 if (request->isComplete()) { 1218 if (!request->isBarrier()) { 1219 storeBuffer.deleteRequest(request); 1220 } else { 1221 DPRINTF(MinorMem, "Completed transfer for barrier: %s" 1222 " leaving the request as it is also a barrier\n", 1223 *(request->inst)); 1224 } 1225 } 1226 break; 1227 default: 1228 /* Shouldn't be allowed to receive a response from another 1229 * state */ 1230 assert(false); 1231 break; 1232 } 1233 1234 /* We go to idle even if there are more things in the requests queue 1235 * as it's the job of step to actually step us on to the next 1236 * transaction */ 1237 1238 /* Let's try and wake up the processor for the next cycle */ 1239 cpu.wakeupOnEvent(Pipeline::ExecuteStageId); 1240 1241 /* Never busy */ 1242 return true; 1243} 1244 1245void 1246LSQ::recvReqRetry() 1247{ 1248 DPRINTF(MinorMem, "Received retry request\n"); 1249 1250 assert(state == MemoryNeedsRetry); 1251 1252 switch (retryRequest->state) { 1253 case LSQRequest::RequestNeedsRetry: 1254 /* Retry in the requests queue */ 1255 retryRequest->setState(LSQRequest::Translated); 1256 break; 1257 case LSQRequest::StoreBufferNeedsRetry: 1258 /* Retry in the store buffer */ 1259 retryRequest->setState(LSQRequest::StoreInStoreBuffer); 1260 break; 1261 default: 1262 assert(false); 1263 } 1264 1265 /* Set state back to MemoryRunning so that the following 1266 * tryToSend can actually send. Note that this won't 1267 * allow another transfer in as tryToSend should 1268 * issue a memory request and either succeed for this 1269 * request or return the LSQ back to MemoryNeedsRetry */ 1270 state = MemoryRunning; 1271 1272 /* Try to resend the request */ 1273 if (tryToSend(retryRequest)) { 1274 /* Successfully sent, need to move the request */ 1275 switch (retryRequest->state) { 1276 case LSQRequest::RequestIssuing: 1277 /* In the requests queue */ 1278 moveFromRequestsToTransfers(retryRequest); 1279 break; 1280 case LSQRequest::StoreBufferIssuing: 1281 /* In the store buffer */ 1282 storeBuffer.countIssuedStore(retryRequest); 1283 break; 1284 default: 1285 assert(false); 1286 break; 1287 } 1288 1289 retryRequest = NULL; 1290 } 1291} 1292 1293LSQ::LSQ(std::string name_, std::string dcache_port_name_, 1294 MinorCPU &cpu_, Execute &execute_, 1295 unsigned int in_memory_system_limit, unsigned int line_width, 1296 unsigned int requests_queue_size, unsigned int transfers_queue_size, 1297 unsigned int store_buffer_size, 1298 unsigned int store_buffer_cycle_store_limit) : 1299 Named(name_), 1300 cpu(cpu_), 1301 execute(execute_), 1302 dcachePort(dcache_port_name_, *this, cpu_), 1303 lastMemBarrier(cpu.numThreads, 0), 1304 state(MemoryRunning), 1305 inMemorySystemLimit(in_memory_system_limit), 1306 lineWidth((line_width == 0 ? cpu.cacheLineSize() : line_width)), 1307 requests(name_ + ".requests", "addr", requests_queue_size), 1308 transfers(name_ + ".transfers", "addr", transfers_queue_size), 1309 storeBuffer(name_ + ".storeBuffer", 1310 *this, store_buffer_size, store_buffer_cycle_store_limit), 1311 numAccessesInMemorySystem(0), 1312 numAccessesInDTLB(0), 1313 numStoresInTransfers(0), 1314 numAccessesIssuedToMemory(0), 1315 retryRequest(NULL), 1316 cacheBlockMask(~(cpu_.cacheLineSize() - 1)) 1317{ 1318 if (in_memory_system_limit < 1) { 1319 fatal("%s: executeMaxAccessesInMemory must be >= 1 (%d)\n", name_, 1320 in_memory_system_limit); 1321 } 1322 1323 if (store_buffer_cycle_store_limit < 1) { 1324 fatal("%s: executeLSQMaxStoreBufferStoresPerCycle must be" 1325 " >= 1 (%d)\n", name_, store_buffer_cycle_store_limit); 1326 } 1327 1328 if (requests_queue_size < 1) { 1329 fatal("%s: executeLSQRequestsQueueSize must be" 1330 " >= 1 (%d)\n", name_, requests_queue_size); 1331 } 1332 1333 if (transfers_queue_size < 1) { 1334 fatal("%s: executeLSQTransfersQueueSize must be" 1335 " >= 1 (%d)\n", name_, transfers_queue_size); 1336 } 1337 1338 if (store_buffer_size < 1) { 1339 fatal("%s: executeLSQStoreBufferSize must be" 1340 " >= 1 (%d)\n", name_, store_buffer_size); 1341 } 1342 1343 if ((lineWidth & (lineWidth - 1)) != 0) { 1344 fatal("%s: lineWidth: %d must be a power of 2\n", name(), lineWidth); 1345 } 1346} 1347 1348LSQ::~LSQ() 1349{ } 1350 1351LSQ::LSQRequest::~LSQRequest() 1352{ 1353 if (packet) 1354 delete packet; 1355 if (data) 1356 delete [] data; 1357} 1358 1359/** 1360 * Step the memory access mechanism on to its next state. In reality, most 1361 * of the stepping is done by the callbacks on the LSQ but this 1362 * function is responsible for issuing memory requests lodged in the 1363 * requests queue. 1364 */ 1365void 1366LSQ::step() 1367{ 1368 /* Try to move address-translated requests between queues and issue 1369 * them */ 1370 if (!requests.empty()) 1371 tryToSendToTransfers(requests.front()); 1372 1373 storeBuffer.step(); 1374} 1375 1376LSQ::LSQRequestPtr 1377LSQ::findResponse(MinorDynInstPtr inst) 1378{ 1379 LSQ::LSQRequestPtr ret = NULL; 1380 1381 if (!transfers.empty()) { 1382 LSQRequestPtr request = transfers.front(); 1383 1384 /* Same instruction and complete access or a store that's 1385 * capable of being moved to the store buffer */ 1386 if (request->inst->id == inst->id) { 1387 bool complete = request->isComplete(); 1388 bool can_store = storeBuffer.canInsert(); 1389 bool to_store_buffer = request->state == 1390 LSQRequest::StoreToStoreBuffer; 1391 1392 if ((complete && !(request->isBarrier() && !can_store)) || 1393 (to_store_buffer && can_store)) 1394 { 1395 ret = request; 1396 } 1397 } 1398 } 1399 1400 if (ret) { 1401 DPRINTF(MinorMem, "Found matching memory response for inst: %s\n", 1402 *inst); 1403 } else { 1404 DPRINTF(MinorMem, "No matching memory response for inst: %s\n", 1405 *inst); 1406 } 1407 1408 return ret; 1409} 1410 1411void 1412LSQ::popResponse(LSQ::LSQRequestPtr response) 1413{ 1414 assert(!transfers.empty() && transfers.front() == response); 1415 1416 transfers.pop(); 1417 1418 if (!response->isLoad) 1419 numStoresInTransfers--; 1420 1421 if (response->issuedToMemory) 1422 numAccessesIssuedToMemory--; 1423 1424 if (response->state != LSQRequest::StoreInStoreBuffer) { 1425 DPRINTF(MinorMem, "Deleting %s request: %s\n", 1426 (response->isLoad ? "load" : "store"), 1427 *(response->inst)); 1428 1429 delete response; 1430 } 1431} 1432 1433void 1434LSQ::sendStoreToStoreBuffer(LSQRequestPtr request) 1435{ 1436 assert(request->state == LSQRequest::StoreToStoreBuffer); 1437 1438 DPRINTF(MinorMem, "Sending store: %s to store buffer\n", 1439 *(request->inst)); 1440 1441 request->inst->inStoreBuffer = true; 1442 1443 storeBuffer.insert(request); 1444} 1445 1446bool 1447LSQ::isDrained() 1448{ 1449 return requests.empty() && transfers.empty() && 1450 storeBuffer.isDrained(); 1451} 1452 1453bool 1454LSQ::needsToTick() 1455{ 1456 bool ret = false; 1457 1458 if (canSendToMemorySystem()) { 1459 bool have_translated_requests = !requests.empty() && 1460 requests.front()->state != LSQRequest::InTranslation && 1461 transfers.unreservedRemainingSpace() != 0; 1462 1463 ret = have_translated_requests || 1464 storeBuffer.numUnissuedStores() != 0; 1465 } 1466 1467 if (ret) 1468 DPRINTF(Activity, "Need to tick\n"); 1469 1470 return ret; 1471} 1472 1473void 1474LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data, 1475 unsigned int size, Addr addr, Request::Flags flags, 1476 uint64_t *res) 1477{ 1478 bool needs_burst = transferNeedsBurst(addr, size, lineWidth); 1479 LSQRequestPtr request; 1480 1481 /* Copy given data into the request. The request will pass this to the 1482 * packet and then it will own the data */ 1483 uint8_t *request_data = NULL; 1484 1485 DPRINTF(MinorMem, "Pushing request (%s) addr: 0x%x size: %d flags:" 1486 " 0x%x%s lineWidth : 0x%x\n", 1487 (isLoad ? "load" : "store"), addr, size, flags, 1488 (needs_burst ? " (needs burst)" : ""), lineWidth); 1489 1490 if (!isLoad) { 1491 /* request_data becomes the property of a ...DataRequest (see below) 1492 * and destroyed by its destructor */ 1493 request_data = new uint8_t[size]; 1494 if (flags & Request::CACHE_BLOCK_ZERO) { 1495 /* For cache zeroing, just use zeroed data */ 1496 std::memset(request_data, 0, size); 1497 } else { 1498 std::memcpy(request_data, data, size); 1499 } 1500 } 1501 1502 if (needs_burst) { 1503 request = new SplitDataRequest( 1504 *this, inst, isLoad, request_data, res); 1505 } else { 1506 request = new SingleDataRequest( 1507 *this, inst, isLoad, request_data, res); 1508 } 1509 1510 if (inst->traceData) 1511 inst->traceData->setMem(addr, size, flags); 1512 1513 int cid = cpu.threads[inst->id.threadId]->getTC()->contextId(); 1514 request->request.setContext(cid); 1515 request->request.setVirt(0 /* asid */, 1516 addr, size, flags, cpu.dataMasterId(), 1517 /* I've no idea why we need the PC, but give it */ 1518 inst->pc.instAddr()); 1519 1520 requests.push(request); 1521 request->startAddrTranslation(); 1522} 1523 1524void 1525LSQ::pushFailedRequest(MinorDynInstPtr inst) 1526{ 1527 LSQRequestPtr request = new FailedDataRequest(*this, inst); 1528 requests.push(request); 1529} 1530 1531void 1532LSQ::minorTrace() const 1533{ 1534 MINORTRACE("state=%s in_tlb_mem=%d/%d stores_in_transfers=%d" 1535 " lastMemBarrier=%d\n", 1536 state, numAccessesInDTLB, numAccessesInMemorySystem, 1537 numStoresInTransfers, lastMemBarrier[0]); 1538 requests.minorTrace(); 1539 transfers.minorTrace(); 1540 storeBuffer.minorTrace(); 1541} 1542 1543LSQ::StoreBuffer::StoreBuffer(std::string name_, LSQ &lsq_, 1544 unsigned int store_buffer_size, 1545 unsigned int store_limit_per_cycle) : 1546 Named(name_), lsq(lsq_), 1547 numSlots(store_buffer_size), 1548 storeLimitPerCycle(store_limit_per_cycle), 1549 slots(), 1550 numUnissuedAccesses(0) 1551{ 1552} 1553 1554PacketPtr 1555makePacketForRequest(Request &request, bool isLoad, 1556 Packet::SenderState *sender_state, PacketDataPtr data) 1557{ 1558 PacketPtr ret = isLoad ? Packet::createRead(&request) 1559 : Packet::createWrite(&request); 1560 1561 if (sender_state) 1562 ret->pushSenderState(sender_state); 1563 1564 if (isLoad) 1565 ret->allocate(); 1566 else 1567 ret->dataDynamic(data); 1568 1569 return ret; 1570} 1571 1572void 1573LSQ::issuedMemBarrierInst(MinorDynInstPtr inst) 1574{ 1575 assert(inst->isInst() && inst->staticInst->isMemBarrier()); 1576 assert(inst->id.execSeqNum > lastMemBarrier[inst->id.threadId]); 1577 1578 /* Remember the barrier. We only have a notion of one 1579 * barrier so this may result in some mem refs being 1580 * delayed if they are between barriers */ 1581 lastMemBarrier[inst->id.threadId] = inst->id.execSeqNum; 1582} 1583 1584void 1585LSQ::LSQRequest::makePacket() 1586{ 1587 /* Make the function idempotent */ 1588 if (packet) 1589 return; 1590 1591 // if the translation faulted, do not create a packet 1592 if (fault != NoFault) { 1593 assert(packet == NULL); 1594 return; 1595 } 1596 1597 packet = makePacketForRequest(request, isLoad, this, data); 1598 /* Null the ret data so we know not to deallocate it when the 1599 * ret is destroyed. The data now belongs to the ret and 1600 * the ret is responsible for its destruction */ 1601 data = NULL; 1602} 1603 1604std::ostream & 1605operator <<(std::ostream &os, LSQ::MemoryState state) 1606{ 1607 switch (state) { 1608 case LSQ::MemoryRunning: 1609 os << "MemoryRunning"; 1610 break; 1611 case LSQ::MemoryNeedsRetry: 1612 os << "MemoryNeedsRetry"; 1613 break; 1614 default: 1615 os << "MemoryState-" << static_cast<int>(state); 1616 break; 1617 } 1618 return os; 1619} 1620 1621void 1622LSQ::recvTimingSnoopReq(PacketPtr pkt) 1623{ 1624 /* LLSC operations in Minor can't be speculative and are executed from 1625 * the head of the requests queue. We shouldn't need to do more than 1626 * this action on snoops. */ 1627 for (ThreadID tid = 0; tid < cpu.numThreads; tid++) { 1628 if (cpu.getCpuAddrMonitor(tid)->doMonitor(pkt)) { 1629 cpu.wakeup(tid); 1630 } 1631 } 1632 1633 if (pkt->isInvalidate() || pkt->isWrite()) { 1634 for (ThreadID tid = 0; tid < cpu.numThreads; tid++) { 1635 TheISA::handleLockedSnoop(cpu.getContext(tid), pkt, 1636 cacheBlockMask); 1637 } 1638 } 1639} 1640 1641void 1642LSQ::threadSnoop(LSQRequestPtr request) 1643{ 1644 /* LLSC operations in Minor can't be speculative and are executed from 1645 * the head of the requests queue. We shouldn't need to do more than 1646 * this action on snoops. */ 1647 ThreadID req_tid = request->inst->id.threadId; 1648 PacketPtr pkt = request->packet; 1649 1650 for (ThreadID tid = 0; tid < cpu.numThreads; tid++) { 1651 if (tid != req_tid) { 1652 if (cpu.getCpuAddrMonitor(tid)->doMonitor(pkt)) { 1653 cpu.wakeup(tid); 1654 } 1655 1656 if (pkt->isInvalidate() || pkt->isWrite()) { 1657 TheISA::handleLockedSnoop(cpu.getContext(tid), pkt, 1658 cacheBlockMask); 1659 } 1660 } 1661 } 1662} 1663 1664} 1665