lsq_unit.hh (4022:c422464ca16e) | lsq_unit.hh (4032:8b987a6a2afc) |
---|---|
1/* 2 * Copyright (c) 2004-2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; --- 483 unchanged lines hidden (view full) --- 492 // Make sure this isn't an uncacheable access 493 // A bit of a hackish way to get uncached accesses to work only if they're 494 // at the head of the LSQ and are ready to commit (at the head of the ROB 495 // too). 496 if (req->isUncacheable() && 497 (load_idx != loadHead || !load_inst->isAtCommit())) { 498 iewStage->rescheduleMemInst(load_inst); 499 ++lsqRescheduledLoads; | 1/* 2 * Copyright (c) 2004-2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; --- 483 unchanged lines hidden (view full) --- 492 // Make sure this isn't an uncacheable access 493 // A bit of a hackish way to get uncached accesses to work only if they're 494 // at the head of the LSQ and are ready to commit (at the head of the ROB 495 // too). 496 if (req->isUncacheable() && 497 (load_idx != loadHead || !load_inst->isAtCommit())) { 498 iewStage->rescheduleMemInst(load_inst); 499 ++lsqRescheduledLoads; |
500 501 // Must delete request now that it wasn't handed off to 502 // memory. This is quite ugly. @todo: Figure out the proper 503 // place to really handle request deletes. 504 delete req; |
|
500 return TheISA::genMachineCheckFault(); 501 } 502 503 // Check the SQ for any previous stores that might lead to forwarding 504 int store_idx = load_inst->sqIdx; 505 506 int store_size = 0; 507 --- 21 unchanged lines hidden (view full) --- 529 store_idx += SQEntries; 530 531 assert(storeQueue[store_idx].inst); 532 533 store_size = storeQueue[store_idx].size; 534 535 if (store_size == 0) 536 continue; | 505 return TheISA::genMachineCheckFault(); 506 } 507 508 // Check the SQ for any previous stores that might lead to forwarding 509 int store_idx = load_inst->sqIdx; 510 511 int store_size = 0; 512 --- 21 unchanged lines hidden (view full) --- 534 store_idx += SQEntries; 535 536 assert(storeQueue[store_idx].inst); 537 538 store_size = storeQueue[store_idx].size; 539 540 if (store_size == 0) 541 continue; |
542 else if (storeQueue[store_idx].inst->uncacheable()) 543 continue; |
|
537 | 544 |
545 assert(storeQueue[store_idx].inst->effAddrValid); 546 |
|
538 // Check if the store data is within the lower and upper bounds of 539 // addresses that the request needs. 540 bool store_has_lower_limit = 541 req->getVaddr() >= storeQueue[store_idx].inst->effAddr; 542 bool store_has_upper_limit = 543 (req->getVaddr() + req->getSize()) <= 544 (storeQueue[store_idx].inst->effAddr + store_size); 545 bool lower_load_has_store_part = 546 req->getVaddr() < (storeQueue[store_idx].inst->effAddr + 547 store_size); 548 bool upper_load_has_store_part = 549 (req->getVaddr() + req->getSize()) > 550 storeQueue[store_idx].inst->effAddr; 551 552 // If the store's data has all of the data needed, we can forward. | 547 // Check if the store data is within the lower and upper bounds of 548 // addresses that the request needs. 549 bool store_has_lower_limit = 550 req->getVaddr() >= storeQueue[store_idx].inst->effAddr; 551 bool store_has_upper_limit = 552 (req->getVaddr() + req->getSize()) <= 553 (storeQueue[store_idx].inst->effAddr + store_size); 554 bool lower_load_has_store_part = 555 req->getVaddr() < (storeQueue[store_idx].inst->effAddr + 556 store_size); 557 bool upper_load_has_store_part = 558 (req->getVaddr() + req->getSize()) > 559 storeQueue[store_idx].inst->effAddr; 560 561 // If the store's data has all of the data needed, we can forward. |
553 if (store_has_lower_limit && store_has_upper_limit) { | 562 if ((store_has_lower_limit && store_has_upper_limit)) { |
554 // Get shift amount for offset into the store's data. 555 int shift_amt = req->getVaddr() & (store_size - 1); 556 // @todo: Magic number, assumes byte addressing 557 shift_amt = shift_amt << 3; 558 559 // Cast this to type T? 560 data = storeQueue[store_idx].data >> shift_amt; 561 --- 7 unchanged lines hidden (view full) --- 569 load_inst->memData = new uint8_t[64]; 570 571 memcpy(load_inst->memData, &data, req->getSize()); 572 573 DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 574 "addr %#x, data %#x\n", 575 store_idx, req->getVaddr(), data); 576 | 563 // Get shift amount for offset into the store's data. 564 int shift_amt = req->getVaddr() & (store_size - 1); 565 // @todo: Magic number, assumes byte addressing 566 shift_amt = shift_amt << 3; 567 568 // Cast this to type T? 569 data = storeQueue[store_idx].data >> shift_amt; 570 --- 7 unchanged lines hidden (view full) --- 578 load_inst->memData = new uint8_t[64]; 579 580 memcpy(load_inst->memData, &data, req->getSize()); 581 582 DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 583 "addr %#x, data %#x\n", 584 store_idx, req->getVaddr(), data); 585 |
577 PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq, 578 Packet::Broadcast); | 586 PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast); |
579 data_pkt->dataStatic(load_inst->memData); 580 581 WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this); 582 583 // We'll say this has a 1 cycle load-store forwarding latency 584 // for now. 585 // @todo: Need to make this a parameter. 586 wb->schedule(curTick); --- 4 unchanged lines hidden (view full) --- 591 (store_has_upper_limit && upper_load_has_store_part) || 592 (lower_load_has_store_part && upper_load_has_store_part)) { 593 // This is the partial store-load forwarding case where a store 594 // has only part of the load's data. 595 596 // If it's already been written back, then don't worry about 597 // stalling on it. 598 if (storeQueue[store_idx].completed) { | 587 data_pkt->dataStatic(load_inst->memData); 588 589 WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this); 590 591 // We'll say this has a 1 cycle load-store forwarding latency 592 // for now. 593 // @todo: Need to make this a parameter. 594 wb->schedule(curTick); --- 4 unchanged lines hidden (view full) --- 599 (store_has_upper_limit && upper_load_has_store_part) || 600 (lower_load_has_store_part && upper_load_has_store_part)) { 601 // This is the partial store-load forwarding case where a store 602 // has only part of the load's data. 603 604 // If it's already been written back, then don't worry about 605 // stalling on it. 606 if (storeQueue[store_idx].completed) { |
607 panic("Should not check one of these"); |
|
599 continue; 600 } 601 602 // Must stall load and force it to retry, so long as it's the oldest 603 // load that needs to do so. 604 if (!stalled || 605 (stalled && 606 load_inst->seqNum < 607 loadQueue[stallingLoadIdx]->seqNum)) { 608 stalled = true; 609 stallingStoreIsn = storeQueue[store_idx].inst->seqNum; 610 stallingLoadIdx = load_idx; 611 } 612 613 // Tell IQ/mem dep unit that this instruction will need to be 614 // rescheduled eventually 615 iewStage->rescheduleMemInst(load_inst); 616 iewStage->decrWb(load_inst->seqNum); | 608 continue; 609 } 610 611 // Must stall load and force it to retry, so long as it's the oldest 612 // load that needs to do so. 613 if (!stalled || 614 (stalled && 615 load_inst->seqNum < 616 loadQueue[stallingLoadIdx]->seqNum)) { 617 stalled = true; 618 stallingStoreIsn = storeQueue[store_idx].inst->seqNum; 619 stallingLoadIdx = load_idx; 620 } 621 622 // Tell IQ/mem dep unit that this instruction will need to be 623 // rescheduled eventually 624 iewStage->rescheduleMemInst(load_inst); 625 iewStage->decrWb(load_inst->seqNum); |
626 load_inst->clearIssued(); |
|
617 ++lsqRescheduledLoads; 618 619 // Do not generate a writeback event as this instruction is not 620 // complete. 621 DPRINTF(LSQUnit, "Load-store forwarding mis-match. " 622 "Store idx %i to load addr %#x\n", 623 store_idx, req->getVaddr()); 624 | 627 ++lsqRescheduledLoads; 628 629 // Do not generate a writeback event as this instruction is not 630 // complete. 631 DPRINTF(LSQUnit, "Load-store forwarding mis-match. " 632 "Store idx %i to load addr %#x\n", 633 store_idx, req->getVaddr()); 634 |
625 ++lsqBlockedLoads; | 635 // Must delete request now that it wasn't handed off to 636 // memory. This is quite ugly. @todo: Figure out the 637 // proper place to really handle request deletes. 638 delete req; 639 |
626 return NoFault; 627 } 628 } 629 630 // If there's no forwarding case, then go access memory 631 DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n", 632 load_inst->seqNum, load_inst->readPC()); 633 634 assert(!load_inst->memData); 635 load_inst->memData = new uint8_t[64]; 636 637 ++usedPorts; 638 639 // if we the cache is not blocked, do cache access 640 if (!lsq->cacheBlocked()) { 641 PacketPtr data_pkt = | 640 return NoFault; 641 } 642 } 643 644 // If there's no forwarding case, then go access memory 645 DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n", 646 load_inst->seqNum, load_inst->readPC()); 647 648 assert(!load_inst->memData); 649 load_inst->memData = new uint8_t[64]; 650 651 ++usedPorts; 652 653 // if we the cache is not blocked, do cache access 654 if (!lsq->cacheBlocked()) { 655 PacketPtr data_pkt = |
642 new Packet(req, MemCmd::ReadReq, Packet::Broadcast); | 656 new Packet(req, Packet::ReadReq, Packet::Broadcast); |
643 data_pkt->dataStatic(load_inst->memData); 644 645 LSQSenderState *state = new LSQSenderState; 646 state->isLoad = true; 647 state->idx = load_idx; 648 state->inst = load_inst; 649 data_pkt->senderState = state; 650 651 if (!dcachePort->sendTiming(data_pkt)) { 652 Packet::Result result = data_pkt->result; 653 654 // Delete state and data packet because a load retry 655 // initiates a pipeline restart; it does not retry. 656 delete state; | 657 data_pkt->dataStatic(load_inst->memData); 658 659 LSQSenderState *state = new LSQSenderState; 660 state->isLoad = true; 661 state->idx = load_idx; 662 state->inst = load_inst; 663 data_pkt->senderState = state; 664 665 if (!dcachePort->sendTiming(data_pkt)) { 666 Packet::Result result = data_pkt->result; 667 668 // Delete state and data packet because a load retry 669 // initiates a pipeline restart; it does not retry. 670 delete state; |
671 delete data_pkt->req; |
|
657 delete data_pkt; 658 | 672 delete data_pkt; 673 |
674 req = NULL; 675 |
|
659 if (result == Packet::BadAddress) { 660 return TheISA::genMachineCheckFault(); 661 } 662 663 // If the access didn't succeed, tell the LSQ by setting 664 // the retry thread id. 665 lsq->setRetryTid(lsqID); 666 } 667 } 668 669 // If the cache was blocked, or has become blocked due to the access, 670 // handle it. 671 if (lsq->cacheBlocked()) { | 676 if (result == Packet::BadAddress) { 677 return TheISA::genMachineCheckFault(); 678 } 679 680 // If the access didn't succeed, tell the LSQ by setting 681 // the retry thread id. 682 lsq->setRetryTid(lsqID); 683 } 684 } 685 686 // If the cache was blocked, or has become blocked due to the access, 687 // handle it. 688 if (lsq->cacheBlocked()) { |
689 if (req) 690 delete req; 691 |
|
672 ++lsqCacheBlocked; 673 674 iewStage->decrWb(load_inst->seqNum); 675 // There's an older load that's already going to squash. 676 if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) 677 return NoFault; 678 679 // Record that the load was blocked due to memory. This --- 34 unchanged lines hidden --- | 692 ++lsqCacheBlocked; 693 694 iewStage->decrWb(load_inst->seqNum); 695 // There's an older load that's already going to squash. 696 if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) 697 return NoFault; 698 699 // Record that the load was blocked due to memory. This --- 34 unchanged lines hidden --- |