Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / cpu / src / SS_AsiMap.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: SS_AsiMap.h
* 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 ============================================
*/
#ifndef __SS_AsiMap_h__
#define __SS_AsiMap_h__
#include <map>
#include <list>
#include "SS_Asi.h"
#include "SS_AsiSpace.h"
class SS_AsiMap
{
public:
SS_AsiMap();
void merge( SS_AsiMap& asi_map );
// set_asi_read() is used by the cosim environement to provide a per asi table that
// contain addr:value pairs that overwrite the value returned by ld64() or rd64().
void set_asi_read( std::map<SS_Vaddr,std::list<uint64_t>*>(* _asi_rd)[SS_Asi::MAX] ) { asi_rd = _asi_rd; }
SS_AsiSpace::Error ld64( SS_Strand* s, uint8_t asi, SS_Vaddr addr, uint64_t* data );
SS_AsiSpace::Error st64( SS_Strand* s, uint8_t asi, SS_Vaddr addr, uint64_t data );
SS_AsiSpace::Error rd64( SS_Strand* s, uint8_t asi, SS_Vaddr addr, uint64_t* data )
{
SS_AsiSpace::Error ok = table[asi].rd64(s,addr,data);
if ((ok == SS_AsiSpace::OK) && asi_rd)
{
addr &= table[asi].get_mask();
std::map<SS_Vaddr,std::list<uint64_t>*>::iterator i = (*asi_rd)[asi].find(addr);
if (i != (*asi_rd)[asi].end())
{
if ((*i).second->size())
{
uint64_t temp = (*i).second->front();
// asi_read follow-me is use-once-only, remove it after use
(*i).second->pop_front();
std::map<SS_Vaddr,uint64_t>::const_iterator m = asi_mask[asi].find(addr);
if (m != asi_mask[asi].end())
*data = (temp & (*m).second) | (*data &~ ((*m).second));
else
*data = temp;
}
}
}
return ok;
}
SS_AsiSpace::Error wr64( SS_Strand* s, uint8_t asi, SS_Vaddr addr, uint64_t data )
{
return table[asi].wr64(s,addr,data);
}
SS_AsiSpace& operator[]( SS_Asi asi ) { return table[asi()]; }
// set_mask() sets the mask that is applied to address before look up
// for all asi's (0 to 255). Note this mask doesw not apply to translating ASIs
void set_mask( SS_Vaddr mask );
void set_asi_va_follow_me_mask( uint8_t asi, SS_Vaddr va, uint64_t mask )
{
asi_mask[asi][va] = mask;
}
protected:
std::map<SS_Vaddr,std::list<uint64_t>*> (*asi_rd)[SS_Asi::MAX];
std::map<SS_Vaddr,uint64_t> asi_mask[SS_Asi::MAX];
SS_AsiSpace table[SS_Asi::MAX];
};
#endif