// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: LoadStoreBuffer.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// ========== Copyright Header End ============================================
/************************************************************************
** Copyright (C) 2002, Sun Microsystems, Inc.
** Sun considers its source code as an unpublished, proprietary
** trade secret and it is available only under strict license provisions.
** This copyright notice is placed here only to protect Sun in the event
** the source is deemed a published work. Disassembly, decompilation,
** or other means of reducing the object code to human readable form
** is prohibited by the license agreement under which this code is
** provided to the user or company in possession of this copy."
*************************************************************************/
#include "LoadStoreBuffer.h"
////////////////////////////////////////////////
LoadStoreBuffer::LoadStoreBuffer()
// cerr << "LoadStoreBuffer Created, size= " << buf_.size() << endl;
////////////////////////////////////////////////
LoadStoreBuffer::LoadStoreBuffer( const LoadStoreBuffer
& orig
)
////////////////////////////////////////////////
LoadStoreBuffer::~LoadStoreBuffer()
////////////////////////////////////////////////
LoadStoreBuffer::operator=( const LoadStoreBuffer
& rhs
)
////////////////////////////////////////////////
LoadStoreBuffer::operator==( const LoadStoreBuffer
& rhs
) const
////////////////////////////////////////////////
LoadStoreBuffer::toString() const
list
<LoadStoreEntry
>::const_iterator ii
;
os
<< bufName_
<< " (size=" << buf_
.size() << ")" << endl
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::pushBack(LoadStoreEntry
& entry
)
// cerr << "In LoadStoreBuffer::pushBack" << endl;
list
<LoadStoreEntry
>::iterator it
;
//MSYNC_DEBUG(1, "%s", toString().c_str());
MSYNC_DEBUG(1, "%s Pushback\n%s", bufName_
, entry
.toString().c_str());
MSYNC_DEBUG(1, "%s", toString().c_str());
LoadStoreBuffer::erase(list
<LoadStoreEntry
>::iterator ii
)
//assert(buf_.size() > 0);
if (buf_
.size() == 0) return;
MSYNC_DEBUG(1, "%s Erase\n%s", bufName_
, ii
->toString().c_str());
MSYNC_DEBUG(1, "%s", toString().c_str());
LoadStoreBuffer::popFront()
list
<LoadStoreEntry
>::iterator ii
;
//assert(buf_.size() > 0);
if (buf_
.size() == 0) return;
MSYNC_DEBUG(1, "%s Remove (front)\n%s", bufName_
, ii
->toString().c_str());
MSYNC_DEBUG(1, "%s", toString().c_str());
LoadStoreBuffer::popBack(int count
)
list
<LoadStoreEntry
>::iterator ii
;
//assert (buf_.size() >= count);
if (buf_
.size() < count
) return;
for (int i
= 0; i
< count
; i
++) {
MSYNC_DEBUG(1, "%s Remove (back)\n%s", bufName_
, ii
->toString().c_str());
MSYNC_DEBUG(1, "%s", toString().c_str());
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findMatchY2O(uint64_t addr
, uint8_t size_vector
)
list
<LoadStoreEntry
>::iterator ii
;
if ((addr
& ADDR_MASK
) == (ii
->getAddr() & ADDR_MASK
) &&
(size_vector
== (size_vector
& ii
->getSizeV()))) {
} while (ii
!= buf_
.begin());
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findMatchY2O(uint64_t id
, uint64_t addr
, uint8_t size_vector
)
list
<LoadStoreEntry
>::iterator ii
;
(addr
& ADDR_MASK
) == (ii
->getAddr() & ADDR_MASK
) &&
size_vector
== (size_vector
& ii
->getSizeV())) {
// assert(ii->isLinkValid() == false);
} while (ii
!= buf_
.begin());
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findMatchO2Y(uint64_t addr
, uint8_t size_vector
)
list
<LoadStoreEntry
>::iterator ii
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if (ii
->isLinkValid() == false &&
(addr
& ADDR_MASK
) == (ii
->getAddr() & ADDR_MASK
) &&
size_vector
== (size_vector
& ii
->getSizeV())) {
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findMatchO2Y(uint64_t id
, uint64_t addr
, uint8_t size_vector
)
list
<LoadStoreEntry
>::iterator ii
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
(addr
& ADDR_MASK
) == (ii
->getAddr() & ADDR_MASK
) &&
size_vector
== ii
->getSizeV()) {
// assert(ii->isLinkValid() == false);
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findMatchO2Y(uint64_t addr
, enum LS_ENTRY_STATE state
, uint64_t addrMask
)
list
<LoadStoreEntry
>::iterator ii
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if ((addr
& addrMask
) == (ii
->getAddr() & addrMask
) &&
state
== ii
->getState()) {
// assert(ii->isLinkValid() == false);
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findMatchO2Y(uint64_t addr
)
list
<LoadStoreEntry
>::iterator ii
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if (addr
== ii
->getAddr()) {
// assert(ii->isLinkValid() == false);
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findMatchO2Y(uint64_t addr
, bool rmo
, uint64_t addrMask
)
list
<LoadStoreEntry
>::iterator ii
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if (((addr
& addrMask
) == (ii
->getAddr() & addrMask
)) &&
((rmo
&& ii
->isRMOstore()) || (!rmo
&& !ii
->isRMOstore()))) {
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findNotIssuedO2Y(uint64_t addr
)
list
<LoadStoreEntry
>::iterator ii
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
(addr
== ii
->getAddr())) {
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::find1stNoLink(uint64_t id
, uint64_t addr
, uint64_t addrMask
)
list
<LoadStoreEntry
>::iterator ii
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if (!ii
->isLinkValid() &&
(ii
->getAddr() & addrMask
) == (addr
& addrMask
)) {
return (buf_
.end()); // use buf_.end() to indicate not found
/* Note that this function exclude prefetch instruction */
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::find1stNonExe()
list
<LoadStoreEntry
>::iterator ii
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if (!(ii
->isExecuted())) {
/* Riesling does not access memory for prefetch instruction, and hence
no STEP callback. To overcome this issue, the MemorySync model use
the next non-prefetch instruction to remove the prefetch instructions
in the LoadBuffer and MemoryAccessBuffer by setting its executed_.
if (ii
->getItype() != ITYPE_PREFETCH
) {
MS_ERROR("Found prio prefetch in LoadBuffer does not have LoadData");
ii
->getLink()->setExecuted(true);
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::find1stNonExeMatchedAddr(uint64_t addr
)
list
<LoadStoreEntry
>::iterator ii
;
MSYNC_DEBUG(1, "Find addr=%#llx \n%s", addr
, toString().c_str());
// cerr << "FIND addr=0x" << hex << addr << endl;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if (!(ii
->isExecuted()) && addr
== ii
->getAddr()) {
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::find1stNonExeFetch(uint64_t addr
)
list
<LoadStoreEntry
>::iterator ii
;
MSYNC_DEBUG(1, "Find addr=%#llx \n%s", addr
, toString().c_str());
// cerr << "FIND addr=0x" << hex << addr << endl;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if (!(ii
->isExecuted()) &&
// (ii->getState() == LS_ACK) &&
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::find1stNonExeOrMatchedAddrAtomic(uint64_t addr
)
list
<LoadStoreEntry
>::iterator ii
;
MSYNC_DEBUG(1, "Find addr=%#llx \n%s", addr
, toString().c_str());
// cerr << "FIND addr=0x" << hex << addr << endl;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if (!(ii
->isExecuted())) {
if (ii
->getItype() != ITYPE_ATOMIC
) {
if (addr
== ii
->getAddr()) {
ii
->getLink()->setExecuted(true);
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findNeedTDataO2Y(uint64_t addr
)
list
<LoadStoreEntry
>::iterator ii
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if (!ii
->isIssued() && ii
->getState() != LS_TDATA
&& // only possible states are NEW & RDATA
(addr
) == (ii
->getAddr())) {
// assert(ii->isLinkValid() == false);
return (buf_
.end()); // use buf_.end() to indicate not found
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findDataBypassing (uint64_t addr
, uint8_t size_vector
)
list
<LoadStoreEntry
>::iterator ii
;
if ((addr
& ADDR_MASK
) == (ii
->getAddr() & ADDR_MASK
)) {
overlap
= size_vector
& ii
->getSizeV();
if (overlap
== size_vector
) { // entry's data is a superset => bypassing
} else if (overlap
== 0) { // no overlap, search for next
} else { // partially overlap => access from L2
} while (ii
!= buf_
.begin());
return (buf_
.end()); // use buf_.end() to indicate not found
/******************************************************************************
* The store buffer bypassing check criteria is changed on 5/17/04 that treats
* multiple hits as partial hit. In other words, no bypassing. To know this,
* the algorithm has to check the whole store buffer.
******************************************************************************/
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::findN2DataBypassing (uint64_t addr
, uint8_t size_vector
)
list
<LoadStoreEntry
>::iterator ii
;
list
<LoadStoreEntry
>::iterator matched_ste
;
for (ii
= buf_
.begin(); ii
!= buf_
.end(); ii
++) {
if ((addr
& ADDR_MASK
) == (ii
->getAddr() & ADDR_MASK
)) {
overlap
= size_vector
& ii
->getSizeV();
if (overlap
== size_vector
) { // entry's data is a superset => bypassing
return (buf_
.end()); // multiple hits
} else if (overlap
== 0) { // no overlap, search for next
} else { // partially overlap => access from L2
return (matched
? matched_ste
: buf_
.end()); // use buf_.end() to indicate not found
//=============================================================================
//=============================================================================
//cerr << "DBX: LoadStoreBuffer::empty: " << bufName_ << " size=" << buf_.size() << endl;//DBX
//TODO make sure we free the space properly
// while (buf_.size() > 0) {
//=============================================================================
//=============================================================================
list
<LoadStoreEntry
>::iterator
LoadStoreBuffer::queryBack()
list
<LoadStoreEntry
>::iterator ii
;
//=============================================================================
//=============================================================================
LoadStoreBuffer::markPop()
list
<LoadStoreEntry
>::iterator ii
= buf_
.end();
if (ii
->isLinkValid() && ii
->getLink()->isPopped()) {