Hello,

I am trying to implement cache partitioning in L2 CMP Caches, namely to change insertion/replacement policies. I want to ask if I have to modify anything else besides the things I'm stating just below.

As I have seen, to change the replacement policy, I only have to make changes within the components/CMPCache/StdArray.hpp (find attached), by creating a new template class, similar to the SetLRU class, i.e.:

template<typename _State, const _State &_DefaultState>
class SetPartition : public Set<_State, _DefaultState>

1) To change the eviction policy (like don't remove the LRU block, but something else), I only have to modify the method: virtual Block<_State,_DefaultState>* pickVictim() 2) To change the insertion policy (like don't move the block to the MRU, but somewhere else), I only have to modify the method: virtual void recordAccess(Block<_State,_DefaultState> *aBlock)

Am I missing something else that I have to change (in StdArray.hpp or in another file) or do I only have to change the aforementioned methods?


Thank you,
-George
// DO-NOT-REMOVE begin-copyright-block 
//
// Redistributions of any form whatsoever must retain and/or include the
// following acknowledgment, notices and disclaimer:
//
// This product includes software developed by Carnegie Mellon University.
//
// Copyright 2010 by Mohammad Alisafaee, Eric Chung, Michael Ferdman, Brian Gold,
// Jangwoo Kim, Pejman Lotfi-Kamran, Onur Kocberber, Ippokratis Pandis, 
// Djordje Jevdjic, Jared Smolens, Stephen Somogyi, Evangelos Vlachos, 
// Stavros Volos, Jason Zebchuk, Babak Falsafi, Nikos Hardavellas and Tom Wenisch 
// for the SimFlex Project, Computer Architecture Lab at Carnegie Mellon,
// Carnegie Mellon University.
//
// For more information, see the SimFlex project website at:
//   http://www.ece.cmu.edu/~simflex
//
// You may not use the name "Carnegie Mellon University" or derivations
// thereof to endorse or promote products derived from this software.
//
// If you modify the software you must place a notice on or within any
// modified version provided or made available to any third party stating
// that you have modified the software.  The notice shall include at least
// your name, address, phone number, email address and the date and purpose
// of the modification.
//
// THE SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY WARRANTY OF ANY KIND, EITHER
// EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO ANY WARRANTY
// THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS OR BE ERROR-FREE AND ANY
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
// TITLE, OR NON-INFRINGEMENT.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
// BE LIABLE FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO DIRECT, INDIRECT,
// SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN
// ANY WAY CONNECTED WITH THIS SOFTWARE (WHETHER OR NOT BASED UPON WARRANTY,
// CONTRACT, TORT OR OTHERWISE).
//
// DO-NOT-REMOVE end-copyright-block   

#ifndef _CMP_CACHE_STDARRAY_HPP
#define _CMP_CACHE_STDARRAY_HPP

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>

#include <exception>
#include <iostream>
#include <stdlib.h>

#include <boost/throw_exception.hpp>
#include <boost/dynamic_bitset.hpp>

#include <core/target.hpp>
#include <core/types.hpp>
#include <core/debug/debug.hpp>

#include <components/Common/Util.hpp>
#include <components/Common/Serializers.hpp>

#include <components/CMPCache/CMPCacheInfo.hpp>

using nCommonUtil::log_base2;
using nCommonSerializers::BlockSerializer;

namespace nCMPCache
{

	typedef Flexus::SharedTypes::PhysicalMemoryAddress MemoryAddress;

	typedef int32_t SetIndex;
	typedef uint32_t BlockOffset;

	enum ReplacementPolicy {
		REPLACEMENT_LRU,
		REPLACEMENT_PLRU
	};

	// This is a cache block.  The accessor functions are braindead simple.
	template<typename _State, const _State &_DefaultState>
	class Block {
	public:

		Block ( void ) : theTag ( 0 ), theState ( _DefaultState ) {}

		MemoryAddress tag ( void ) const { return theTag; }

		MemoryAddress & tag ( void ) { return theTag; }

		const _State& state( void ) const { return theState; }
		_State& state( void ) { return theState; }

		bool valid() { return theState != _DefaultState; }

	private:
		MemoryAddress	theTag;
		_State 			theState;

	}; // class Block

	template<typename _State, const _State &_DefaultState> class Set;
	template<typename _State, const _State &_DefaultState> class StdArray;

	// The output of a cache lookup
	template<typename _State, const _State &_DefaultState>
	class StdLookupResult : public AbstractArrayLookupResult<_State> {
	public:
		virtual ~StdLookupResult () {}
		StdLookupResult (  Set<_State, _DefaultState>   * aSet,
						   Block<_State, _DefaultState> * aBlock,
						   MemoryAddress                  aBlockAddress,
						   bool                           aIsHit ) :
		  theSet          ( aSet ),
		  theBlock        ( aBlock ),
		  theBlockAddress ( aBlockAddress ),
		  isHit           ( aIsHit ),
		  theOrigState    ( aIsHit ? aBlock->state() : _DefaultState )
		{
DBG_Assert( (aBlock == NULL) || (aBlock->tag() == aBlockAddress), ( << "Created Lookup where tag " << std::hex << (uint64_t)aBlock->tag() << " != address " << (uint64_t)aBlockAddress ));
		}

		const _State& state() const { return (isHit ? theBlock->state() : theOrigState ); }
		void setState( const _State &aNewState) { theBlock->state() = aNewState; }
		void setProtected( bool val) { theBlock->state().setProtected(val); }
		void setPrefetched( bool val) { theBlock->state().setPrefetched(val); }

		bool hit  ( void ) const { return isHit; }
		bool miss ( void ) const { return !isHit; }
		bool found( void ) const { return theBlock != NULL; }
		bool valid( void ) const { return theBlock != NULL; }

		MemoryAddress blockAddress ( void ) const
		{
		  return theBlockAddress;
		}

	protected:
		Set<_State, _DefaultState>     * theSet;
		Block<_State, _DefaultState>  * theBlock;
		MemoryAddress					theBlockAddress;
		bool            				isHit;
		_State							theOrigState;

		friend class Set<_State, _DefaultState>;
		friend class StdArray<_State, _DefaultState>;
	}; // class LookupResult


	// The cache set, implements a set of cache blocks and applies a replacement policy
	// (from a derived class)
	template<typename _State, const _State &_DefaultState>
	class Set {
	public:
		Set ( const int32_t aAssociativity ) {
			theAssociativity = aAssociativity;
			theBlocks        = new Block<_State,_DefaultState>[theAssociativity];
			DBG_Assert ( theBlocks );
		}
		virtual ~Set ( ) {}

		typedef StdLookupResult<_State,_DefaultState>	LookupResult;
		typedef boost::intrusive_ptr<LookupResult>		LookupResult_p;

		LookupResult_p lookupBlock ( const MemoryAddress anAddress ) {
			int32_t i, t = -1;

			// Linearly search through the set for the matching block
			// This could be made faster for higher-associativity sets
			// Through other search methods
			for ( i = 0; i < theAssociativity; i++ ) {
				if ( theBlocks[i].tag() == anAddress ) {
					if ( theBlocks[i].valid() ) {
						return LookupResult_p( new LookupResult( this, &(theBlocks[i]), anAddress, true ) );
					}
					t = i;
				}
			}
			if(t >= 0) {
				return LookupResult_p( new LookupResult( this, &(theBlocks[t]), anAddress, false ) );
			}

			// Miss on this set
			return LookupResult_p( new LookupResult( this, NULL, anAddress, false ) );
		}
		
		virtual LookupResult_p  allocate(LookupResult_p lookup, MemoryAddress anAddress) {
			// First look for an invalid tag match
			if (lookup->theBlock != NULL) {
				lookup->isHit = true;
				DBG_Assert( lookup->theBlock->tag() == anAddress, ( << "Lookup Tag " << std::hex << (uint64_t)lookup->theBlock->tag() << " != " << (uint64_t)anAddress ));
				// don't need to change the lookup, just fix order and return no victim
				recordAccess(lookup->theBlock);
				return LookupResult_p( new LookupResult( this, NULL, anAddress, false ) );

			} else {
				Block<_State,_DefaultState> *victim = pickVictim();

				// Create lookup result now and remember the block state
				LookupResult_p v_lookup( new LookupResult( this, victim, blockAddress(victim), true) );
				v_lookup->isHit = false;

				victim->tag() = anAddress;

				lookup->isHit = true;
				lookup->theOrigState = _DefaultState;
				lookup->theBlock = victim;
				victim->state() = _DefaultState;

				recordAccess(victim);
				return v_lookup;
			}
		}

		virtual Block<_State,_DefaultState>* pickVictim() = 0;
		virtual void recordAccess(Block<_State,_DefaultState> *aBlock) = 0;
		virtual void invalidateBlock(Block<_State,_DefaultState> *aBlock) = 0;

		virtual bool saveState ( std::ostream & s ) = 0;
		virtual bool loadState ( boost::archive::binary_iarchive & ia, int32_t theIndex, int32_t theSet ) = 0;

		MemoryAddress blockAddress ( const Block<_State,_DefaultState> * theBlock ) {
			return theBlock->tag();
		}

		int32_t count ( const MemoryAddress& aTag ) {
			int32_t i, res = 0;

			for(i = 0; i < theAssociativity; i++) {
				if(theBlocks[i].tag() == aTag) {
					res++;
				}
			}

			return res;
		}

		std::list<MemoryAddress> getTags() {
			std::list<MemoryAddress> tag_list;
			for(int32_t i = 0; i < theAssociativity; i++) {
				if(theBlocks[i].state().isValid()) {
					tag_list.push_back(theBlocks[i].tag());
				}
			}
			return tag_list;
		}

	protected:

		Block<_State,_DefaultState> * theBlocks;
		int32_t     theAssociativity;

	}; // class Set

	template<typename _State, const _State &_DefaultState>
	class SetLRU : public Set<_State, _DefaultState> {
	public:
		SetLRU( const int32_t aAssociativity )
				: Set<_State, _DefaultState> ( aAssociativity )
		{
			theMRUOrder = new int[aAssociativity];

			for ( int32_t i = 0; i < aAssociativity; i++ ) {
			  theMRUOrder[i] = i;
			}
		}

		virtual Block<_State,_DefaultState>* pickVictim() {
			for (int32_t i = Set<_State,_DefaultState>::theAssociativity-1; i >= 0; i--) {
				int32_t index = theMRUOrder[i];
				if (!Set<_State,_DefaultState>::theBlocks[index].state().isProtected()) {
					return &(Set<_State,_DefaultState>::theBlocks[index]);
				}
			}
			DBG_Assert(false, ( << "All blocks in the set are protected."));
			return NULL;
		}

		virtual void recordAccess(Block<_State,_DefaultState> *aBlock) {
			int32_t theBlockNum = aBlock - Set<_State,_DefaultState>::theBlocks;
			moveToHead( theBlockNum);
		}

		virtual void invalidateBlock(Block<_State,_DefaultState> *aBlock) {
			int32_t theBlockNum = aBlock - Set<_State,_DefaultState>::theBlocks;
			moveToTail( theBlockNum);
		}

		virtual bool saveState ( std::ostream & s ) {
			return true;
		}

		// return true if successful
		virtual bool loadState ( boost::archive::binary_iarchive & ia, int32_t theIndex, int32_t theSet ) {
			BlockSerializer bs;
			for(int32_t i = (Set<_State,_DefaultState>::theAssociativity - 1); i >= 0; i--) {
				ia >> bs;
DBG_(Trace, ( << theIndex << "-L3: Loading block " << std::hex << bs.tag << " in state " << (char)bs.state << " in way " << (int)bs.way << " in set " << theSet ));
				_State state(_State::char2State(bs.state));
				//int32_t way = bs.way;
				MemoryAddress tag = MemoryAddress(bs.tag);
				theMRUOrder[i] = i;
				Set<_State,_DefaultState>::theBlocks[i].tag() = tag;
				Set<_State,_DefaultState>::theBlocks[i].state() = state;
			}
			return true;
		}

	protected:

		inline int32_t lruListHead ( void ) { return theMRUOrder[0]; }
		inline int32_t lruListTail ( void ) { return theMRUOrder[Set<_State,_DefaultState>::theAssociativity-1]; }

		inline void moveToHead ( const SetIndex aBlock ) {
			int32_t i = 0;
			while ( theMRUOrder[i] != aBlock ) i++;
			while ( i > 0 ) {
				theMRUOrder[i] = theMRUOrder[i - 1];
				i--;
			}
			theMRUOrder[0] = aBlock;
		}

		inline void moveToTail ( const SetIndex aBlock ) {
			int32_t i = 0;
			while( theMRUOrder[i] != aBlock) i++;
			while( i < (Set<_State,_DefaultState>::theAssociativity - 1) ) {
				theMRUOrder[i] = theMRUOrder[i+1];
				i++;
			}
			theMRUOrder[Set<_State,_DefaultState>::theAssociativity - 1] = aBlock;
		}

		SetIndex * theMRUOrder;

	}; // class SetLRU

	template<typename _State, const _State &_DefaultState>
	class SetPseudoLRU : public Set<_State, _DefaultState> {
	public:
		SetPseudoLRU( const int32_t anAssociativity )
				: Set<_State, _DefaultState> ( anAssociativity ), theMRUBits(anAssociativity, ((1ULL << anAssociativity) - 1) )
		{
		}

		virtual Block<_State,_DefaultState>* pickVictim() {
			// First look for "invalid block", ie. block in DefaultState
			for(int32_t i = 0; i < Set<_State,_DefaultState>::theAssociativity; i++) {
				if (Set<_State,_DefaultState>::theBlocks[i].state() == _DefaultState) {
					return &Set<_State,_DefaultState>::theBlocks[i];
				}
			}

			int32_t theBlockNum = theMRUBits.find_first();
			return Set<_State,_DefaultState>::theBlocks + theBlockNum;
		}

		virtual void recordAccess(Block<_State,_DefaultState> *aBlock) {
			int32_t theBlockNum = aBlock - Set<_State,_DefaultState>::theBlocks;
			theMRUBits[theBlockNum] = 0;
			if (theMRUBits.none()) {
				theMRUBits.flip();
				theMRUBits[theBlockNum] = 0;
			}
		}

		virtual void invalidateBlock(Block<_State,_DefaultState> *aBlock) {
			int32_t theBlockNum = aBlock - Set<_State,_DefaultState>::theBlocks;
			theMRUBits[theBlockNum] = 1;
		}

		virtual bool saveState ( std::ostream & s ) {
			return true;
		}

		virtual bool loadState ( boost::archive::binary_iarchive & ia, int32_t theIndex, int32_t theSet ) {
			return true;
		}

	protected:

		// This uses one bit per bool, pretty space-efficient
		boost::dynamic_bitset<> theMRUBits;

	}; // class SetLRU

	template<typename _State, const _State &_DefaultState>
	class StdArray : public AbstractArray<_State> {
	protected:

		CMPCacheInfo theInfo;

		// Masks to address portions of the cache
		int32_t theAssociativity;
		int32_t theReplacementPolicy;
		int32_t theBlockSize;
		int32_t theBanks;
		int32_t theTotalBanks;
		int32_t theGlobalBankIndex;
		int32_t theLocalBankIndex;
		int32_t theBankInterleaving;
		int32_t theGroups;
		int32_t theGroupIndex;
		int32_t theGroupInterleaving;


		int32_t theNumSets;
		MemoryAddress tagMask;
		int32_t setHighShift;
		int32_t setMidShift;
		int32_t setLowShift;
		uint64_t setLowMask;
		uint64_t setMidMask;
		uint64_t setHighMask;

		int32_t theBankMask, theBankShift;
		int32_t theGroupMask, theGroupShift;


		Set<_State,_DefaultState> ** theSets;

	public:

		virtual ~StdArray () {}
		StdArray ( CMPCacheInfo &aCacheInfo, const int32_t aBlockSize, const std::list< std::pair< std::string, std::string> > &theConfiguration)
			: theInfo(aCacheInfo)
		{
			theBlockSize = aBlockSize;
			theBanks = theInfo.theNumBanks;
			theBankInterleaving = theInfo.theBankInterleaving;
			theGroups = theInfo.theNumGroups;
			theGroupInterleaving = theInfo.theGroupInterleaving;
DBG_(Dev, ( << "theGroupInterleaving = " << theGroupInterleaving ));

			theGlobalBankIndex = theInfo.theNodeId;
			theLocalBankIndex = theInfo.theNodeId % theBanks;
			theGroupIndex = theInfo.theNodeId / theBanks;

			theTotalBanks = theBanks * theGroups;

			std::list< std::pair< std::string, std::string> >::const_iterator iter = theConfiguration.begin();
			for(; iter != theConfiguration.end(); iter++) {
				if (iter->first == "sets") {
					theNumSets = strtoll(iter->second.c_str(), NULL, 0);
				} else if (iter->first == "total_sets" || iter->first == "global_sets") {
					int32_t global_sets = strtol(iter->second.c_str(), NULL, 0);
					theNumSets = global_sets / theTotalBanks;
					DBG_Assert( (theNumSets * theTotalBanks) == global_sets, ( << "global_sets (" << global_sets 
							<< ") is not divisible by number of banks (" << theTotalBanks << ")" ));
				} else if (strcasecmp(iter->first.c_str(), "assoc") == 0 || strcasecmp(iter->first.c_str(), "associativity") == 0) {
					theAssociativity = strtol(iter->second.c_str(), NULL, 0);
				} else if (strcasecmp(iter->first.c_str(),"repl") == 0 || strcasecmp(iter->first.c_str(),"replacement") == 0) {
					if (strcasecmp(iter->second.c_str(),"lru") == 0) {
						theReplacementPolicy = REPLACEMENT_LRU;
					} else if (strcasecmp(iter->second.c_str(),"plru") == 0 
							|| strcasecmp(iter->second.c_str(),"pseudoLRU") == 0) {
						theReplacementPolicy = REPLACEMENT_PLRU;
					} else {
						DBG_Assert( false, ( << "Invalid replacement policy type " << iter->second ));
					}
				} else {
					DBG_Assert( false, ( << "Unknown configuration parameter '" << iter->first << "' while creating StdArray. Valid params are: sets, total_sets, assoc, repl" ));
				}
			}

			init();
		}

		void init() {
			DBG_Assert ( theNumSets     > 0 );
			DBG_Assert ( theAssociativity > 0 );
			DBG_Assert ( theBlockSize     > 0 );

			//  Physical address layout:
			//
			//  +---------+-------+-------------------+
			//  | Tag     | Index |    BlockOffset    |
			//  +---------+-------+-------------------+
			//                    |<- setIndexShift ->|
			//            |<----->|
			//             setIndexMask (shifted right)
			//  |<------->|
			//    tagMask
			//            |<------ tagShift --------->|


			// Set indexes and masks
			DBG_Assert( (theNumSets & (theNumSets - 1)) == 0);
			DBG_Assert( ((theBlockSize - 1) & theBlockSize) == 0);
			DBG_Assert( ((theBankInterleaving - 1) & theBankInterleaving) == 0);
			DBG_Assert( ((theGroupInterleaving - 1) & theGroupInterleaving) == 0);

			DBG_Assert( (theBankInterleaving * theBanks) <= theGroupInterleaving, ( << "Invalid interleaving: BI = " 
					<< theBankInterleaving << ", Banks = " << theBanks << ", GI = " << theGroupInterleaving << ", Groups = " << theGroups ));

			int32_t blockOffsetBits = log_base2(theBlockSize);
			int32_t indexBits = log_base2(theNumSets);
			int32_t bankBits = log_base2(theBanks);
			int32_t bankInterleavingBits = log_base2(theBankInterleaving);

			int32_t groupBits = log_base2(theGroups);
			int32_t groupInterleavingBits = log_base2(theGroupInterleaving);

			int32_t lowBits = bankInterleavingBits - blockOffsetBits;
			int32_t midBits = groupInterleavingBits - bankInterleavingBits - bankBits;
			int32_t highBits = indexBits - midBits - lowBits;
			if ((midBits + lowBits) > indexBits) {
				midBits = indexBits - lowBits;
				highBits = 0;
			}

			setLowMask = (1 << lowBits) - 1;
			setMidMask = ((1 << midBits) - 1) << lowBits;
			setHighMask = ((1 << highBits) - 1) << (midBits + lowBits);
		
			setLowShift = blockOffsetBits;
			setMidShift = bankBits + blockOffsetBits;
			setHighShift = groupBits + bankBits + blockOffsetBits;

			theBankMask = theBanks - 1;
			theBankShift = bankInterleavingBits;
			theGroupMask = theGroups - 1;
			theGroupShift = groupInterleavingBits;

DBG_(Dev, ( << "blockOffsetBits = " << std::dec << blockOffsetBits
<< ", indexBits = " << std::dec << indexBits
<< ", bankBits = " << std::dec << bankBits
<< ", bankInterleavingBits = " << std::dec << bankInterleavingBits
<< ", groupBits = " << std::dec << groupBits
<< ", groupInterleavingBits = " << std::dec << groupInterleavingBits
<< ", lowBits = " << std::dec << lowBits
<< ", midBits = " << std::dec << midBits
<< ", highBits = " << std::dec << highBits
<< ", setLowMask = " << std::hex << setLowMask
<< ", setMidMask = " << std::hex << setMidMask
<< ", setHighMask = " << std::hex << setHighMask
<< ", setLowShift = " << std::dec << setLowShift
<< ", setMidShift = " << std::dec << setMidShift
<< ", setHighShift = " << std::dec << setHighShift
<< ", theBankMask = " << std::hex << theBankMask
<< ", theBankShift = " << std::dec << theBankShift
<< ", theGroupMask = " << std::hex << theGroupMask
<< ", theGroupShift = " << std::dec << theGroupShift ));

			tagMask = MemoryAddress(~0ULL & ~((uint64_t)(theBlockSize - 1)));

			// Allocate the sets
			theSets = new Set<_State,_DefaultState>*[theNumSets];
			DBG_Assert ( theSets );

			for ( int32_t i = 0; i < theNumSets; i++ ) {

				switch ( theReplacementPolicy ) {
				case REPLACEMENT_LRU:
					theSets[i] = new SetLRU<_State,_DefaultState> ( theAssociativity );
					break;
				case REPLACEMENT_PLRU:
					theSets[i] = new SetPseudoLRU<_State,_DefaultState> ( theAssociativity );
					break;
				default:
					DBG_Assert ( 0 );
				};
			}
		}

	
		// Main array lookup function
		virtual boost::intrusive_ptr<AbstractArrayLookupResult<_State> > operator[] ( const MemoryAddress & anAddress ) {
DBG_(Trace, ( << "Looking for block " << std::hex << anAddress << " in set " << makeSet(anAddress) << " theNumSets = " << theNumSets ));
			boost::intrusive_ptr<AbstractArrayLookupResult<_State> > ret = theSets[makeSet(anAddress)]->lookupBlock( blockAddress(anAddress) );
			DBG_(Trace, ( << "Found block " << std::hex << anAddress << " in set " << makeSet(anAddress) << " in state " << ret->state() ));
			return ret;
		}

		virtual boost::intrusive_ptr<AbstractArrayLookupResult<_State> > allocate(	boost::intrusive_ptr<AbstractArrayLookupResult<_State> > lookup,
																			 	const MemoryAddress & anAddress )
		{
			StdLookupResult<_State,_DefaultState> *std_lookup = dynamic_cast<StdLookupResult<_State,_DefaultState>*>(lookup.get());
			DBG_Assert(std_lookup != NULL);

			return std_lookup->theSet->allocate(std_lookup, blockAddress(anAddress));

		}

		virtual void recordAccess(boost::intrusive_ptr<AbstractArrayLookupResult<_State> > lookup) {
			StdLookupResult<_State,_DefaultState> *std_lookup = dynamic_cast<StdLookupResult<_State,_DefaultState>*>(lookup.get());
			DBG_Assert(std_lookup != NULL);
			DBG_Assert( std_lookup->valid() );

			std_lookup->theSet->recordAccess(std_lookup->theBlock);
		}

		virtual void invalidateBlock(boost::intrusive_ptr<AbstractArrayLookupResult<_State> > lookup) {
			StdLookupResult<_State,_DefaultState> *std_lookup = dynamic_cast<StdLookupResult<_State,_DefaultState>*>(lookup.get());
			DBG_Assert(std_lookup != NULL);
			DBG_Assert( std_lookup->valid() );

			std_lookup->theSet->invalidateBlock(std_lookup->theBlock);
		}

		virtual std::pair<_State,MemoryAddress> getPreemptiveEviction() {
			return std::make_pair(_DefaultState, MemoryAddress(0));
		}

		// Checkpoint reading/writing functions
		virtual bool saveState ( std::ostream & s ) {

			return true;

		}

		virtual bool loadState ( std::istream & s, int32_t theIndex ) {

			boost::archive::binary_iarchive ia(s);

			BlockSerializer serializer;

			MemoryAddress addr(0);
			int32_t theTotalSets = theNumSets * theBanks * theGroups;
DBG_(Trace, ( << "theTotalSets:" << theTotalSets << " = product of: theNumSets:" << theNumSets << " theBanks:" << theBanks << " theGroups:" << theGroups));
			int32_t local_set = 0;
			int32_t global_set = 0;

			uint64_t set_count = 0;
			uint32_t associativity = 0;

			ia >> set_count;
			ia >> associativity;

			DBG_Assert( set_count == (uint64_t)theTotalSets, ( << "Error loading cache state. Flexpoint contains " << set_count << " sets but simulator configured for " << theTotalSets << " total sets." ));
			DBG_Assert( associativity == (uint64_t)theAssociativity, ( << "Error loading cache state. Flexpoint contains " << associativity << "-way sets but simulator configured for " << theAssociativity << "-way sets." ));

			for(; global_set < theTotalSets; global_set++,addr+=theBlockSize) {
				if ((getBank(addr) == theLocalBankIndex) && (getGroup(addr) == theGroupIndex)) {
DBG_(Trace, ( << "Attempting to load local_set " << local_set << "(group = " << theGroupIndex << ", bank = " << theLocalBankIndex << ", gset = " << global_set ));
					if (!theSets[local_set]->loadState(ia, theIndex, local_set)) {
						DBG_Assert(false, ( << "failed to load cache set " << local_set ));
						return true;
					}
					local_set++;
				} else {
DBG_(Trace, ( << "Skipping " << theAssociativity << " ways from gset " << global_set ));
					for(int32_t way = 0; way < theAssociativity; way++) {
						// Skip over entries that belong to other banks
						ia >> serializer;
					}
				}
			}

			return true;	// true == no errors
		}

		// Addressing helper functions
		MemoryAddress blockAddress ( MemoryAddress const & anAddress ) const
		{
		  return MemoryAddress ( anAddress & tagMask );
		}

		SetIndex makeSet ( const MemoryAddress & anAddress ) const
		{
		  return ((anAddress >> setLowShift) & setLowMask) | ((anAddress >> setMidShift) & setMidMask) | ((anAddress >> setHighShift) & setHighMask);
		}

		int32_t getBank( const MemoryAddress &anAddress) const
		{
			return ((anAddress >> theBankShift) & theBankMask);
		}

		int32_t getGroup( const MemoryAddress &anAddress) const
		{
			return ((anAddress >> theGroupShift) & theGroupMask);
		}

		virtual bool sameSet(MemoryAddress a, MemoryAddress b) { 
			return (makeSet(a) == makeSet(b)); 
		}

		virtual std::list<MemoryAddress>  getSetTags(MemoryAddress addr) { 
			return theSets[makeSet(addr)]->getTags();
		}

	}; // class StdArray

};  // namespace nCMPCache

#endif /* _CMP_CACHE_STDARRAY_HPP */

Reply via email to