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