Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / rtl / src / SS_ExternalMemory.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: SS_ExternalMemory.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 ============================================
#include "SS_ExternalMemory.h"
SS_ExternalMemory SS_ExternalMemory::memory;
uint32_t SS_ExternalMemory::fetch32 ( uint64_t addr )/*{{{*/
{
int sid_local = sid;
uint64_t data;
uint_t n = 4 - (addr & 4);
(ld_callback)(sid_local,addr &~ 7,CODEFETCH,0xf << n,&data);
return data >> (n * 8);
}
/*}}}*/
void SS_ExternalMemory::fetch256( uint64_t addr, uint64_t data[4] )/*{{{*/
{
// in a multi-thread environment, SS_ExternalMemory::sid can be changed
// by a different thread while this thread is in the middle of ld/st
// operation, that may cause ld_callback() to have different sid value, so
// store the value in a local variable at the beginning to guarantee all
// ld/st calls within this function have the same sid.
int sid_local = sid;
(ld_callback)(sid_local,addr ,CODEFETCH,0xff,&data[0]);
(ld_callback)(sid_local,addr + 8,CODEFETCH,0xff,&data[1]);
(ld_callback)(sid_local,addr + 16,CODEFETCH,0xff,&data[2]);
(ld_callback)(sid_local,addr + 24,CODEFETCH,0xff,&data[3]);
}
/*}}}*/
void SS_ExternalMemory::fetch512( uint64_t addr, uint64_t data[8] )/*{{{*/
{
int sid_local = sid;
(ld_callback)(sid_local,addr ,CODEFETCH,0xff,&data[0]);
(ld_callback)(sid_local,addr + 8,CODEFETCH,0xff,&data[1]);
(ld_callback)(sid_local,addr + 16,CODEFETCH,0xff,&data[2]);
(ld_callback)(sid_local,addr + 24,CODEFETCH,0xff,&data[3]);
(ld_callback)(sid_local,addr + 32,CODEFETCH,0xff,&data[4]);
(ld_callback)(sid_local,addr + 40,CODEFETCH,0xff,&data[5]);
(ld_callback)(sid_local,addr + 48,CODEFETCH,0xff,&data[6]);
(ld_callback)(sid_local,addr + 56,CODEFETCH,0xff,&data[7]);
}
/*}}}*/
uint8_t SS_ExternalMemory::ld8u ( uint64_t addr )/*{{{*/
{
int sid_local = sid;
uint64_t data;
uint_t n = 7 - (addr & 7);
(ld_callback)(sid_local,addr &~ 7,NORMAL,0x1 << n,&data);
return data >> (n * 8);
}
/*}}}*/
int8_t SS_ExternalMemory::ld8s ( uint64_t addr )/*{{{*/
{
int sid_local = sid;
uint64_t data;
uint_t n = 7 - (addr & 7);
(ld_callback)(sid_local,addr &~ 7,NORMAL,0x1 << n,&data);
return data >> (n * 8);
}
/*}}}*/
uint16_t SS_ExternalMemory::ld16u( uint64_t addr )/*{{{*/
{
int sid_local = sid;
uint64_t data;
uint_t n = 6 - (addr & 6);
(ld_callback)(sid_local,addr &~ 7,NORMAL,0x3 << n,&data);
return data >> (n * 8);
}
/*}}}*/
int16_t SS_ExternalMemory::ld16s( uint64_t addr )/*{{{*/
{
int sid_local = sid;
uint64_t data;
uint_t n = 6 - (addr & 6);
(ld_callback)(sid_local,addr &~ 7,NORMAL,0x3 << n,&data);
return data >> (n * 8);
}
/*}}}*/
uint32_t SS_ExternalMemory::ld32u( uint64_t addr )/*{{{*/
{
int sid_local = sid;
uint64_t data;
uint_t n = 4 - (addr & 4);
(ld_callback)(sid_local,addr &~ 7,NORMAL,0xf << n,&data);
return data >> (n * 8);
}
/*}}}*/
int32_t SS_ExternalMemory::ld32s( uint64_t addr )/*{{{*/
{
int sid_local = sid;
uint64_t data;
uint_t n = 4 - (addr & 4);
(ld_callback)(sid_local,addr &~ 7,NORMAL,0xf << n,&data);
return data >> (n * 8);
}
/*}}}*/
uint64_t SS_ExternalMemory::ld64 ( uint64_t addr )/*{{{*/
{
int sid_local = sid;
uint64_t data;
(ld_callback)(sid_local,addr,NORMAL,0xff,&data);
return data;
}
/*}}}*/
void SS_ExternalMemory::ld128( uint64_t addr, uint64_t data[2] )/*{{{*/
{
int sid_local = sid;
(ld_callback)(sid_local,addr ,NORMAL,0xff,&data[0]);
(ld_callback)(sid_local,addr + 8,NORMAL,0xff,&data[1]);
}
/*}}}*/
void SS_ExternalMemory::ld256( uint64_t addr, uint64_t data[4] )/*{{{*/
{
int sid_local = sid;
(ld_callback)(sid_local,addr ,NORMAL,0xff,&data[0]);
(ld_callback)(sid_local,addr + 8,NORMAL,0xff,&data[1]);
(ld_callback)(sid_local,addr + 16,NORMAL,0xff,&data[2]);
(ld_callback)(sid_local,addr + 24,NORMAL,0xff,&data[3]);
}
/*}}}*/
void SS_ExternalMemory::ld512( uint64_t addr, uint64_t data[8] )/*{{{*/
{
int sid_local = sid;
(ld_callback)(sid_local,addr ,NORMAL,0xff,&data[0]);
(ld_callback)(sid_local,addr + 8,NORMAL,0xff,&data[1]);
(ld_callback)(sid_local,addr + 16,NORMAL,0xff,&data[2]);
(ld_callback)(sid_local,addr + 24,NORMAL,0xff,&data[3]);
(ld_callback)(sid_local,addr + 32,NORMAL,0xff,&data[4]);
(ld_callback)(sid_local,addr + 40,NORMAL,0xff,&data[5]);
(ld_callback)(sid_local,addr + 48,NORMAL,0xff,&data[6]);
(ld_callback)(sid_local,addr + 56,NORMAL,0xff,&data[7]);
}
/*}}}*/
void SS_ExternalMemory::st8( uint64_t addr, uint8_t data )/*{{{*/
{
int sid_local = sid;
uint_t n = 7 - (addr & 7);
(st_callback)(sid_local,addr &~ 7,NORMAL,0x1 << n,uint64_t(data) << (n * 8));
}
/*}}}*/
void SS_ExternalMemory::st16( uint64_t addr, uint16_t data )/*{{{*/
{
int sid_local = sid;
uint_t n = 6 - (addr & 6);
(st_callback)(sid_local,addr &~ 7,NORMAL,0x3 << n,uint64_t(data) << (n * 8));
}
/*}}}*/
void SS_ExternalMemory::st32( uint64_t addr, uint32_t data )/*{{{*/
{
int sid_local = sid;
uint_t n = 4 - (addr & 4);
(st_callback)(sid_local,addr &~ 7,NORMAL,0xf << n,uint64_t(data) << (n * 8));
}
/*}}}*/
void SS_ExternalMemory::st64( uint64_t addr, uint64_t data )/*{{{*/
{
int sid_local = sid;
(st_callback)(sid_local,addr,NORMAL,0xff,data);
}
/*}}}*/
void SS_ExternalMemory::st128( uint64_t addr, uint64_t data[2] )/*{{{*/
{
int sid_local = sid;
(st_callback)(sid_local,addr ,NORMAL,0xff,data[0]);
(st_callback)(sid_local,addr + 8,NORMAL,0xff,data[1]);
}
/*}}}*/
void SS_ExternalMemory::st512( uint64_t addr, uint64_t data[8] )/*{{{*/
{
int sid_local = sid;
(st_callback)(sid_local,addr ,NORMAL,0xff,data[0]);
(st_callback)(sid_local,addr + 8,NORMAL,0xff,data[1]);
(st_callback)(sid_local,addr + 16,NORMAL,0xff,data[2]);
(st_callback)(sid_local,addr + 24,NORMAL,0xff,data[3]);
(st_callback)(sid_local,addr + 32,NORMAL,0xff,data[4]);
(st_callback)(sid_local,addr + 40,NORMAL,0xff,data[5]);
(st_callback)(sid_local,addr + 48,NORMAL,0xff,data[6]);
(st_callback)(sid_local,addr + 56,NORMAL,0xff,data[7]);
}
/*}}}*/
void SS_ExternalMemory::st64partial( uint64_t addr, uint64_t data, uint64_t mask ) /*{{{*/
{
int sid_local = sid;
(st_callback)(sid_local,addr,NORMAL,mask,data);
}
/*}}}*/
void SS_ExternalMemory::ld128atomic( uint64_t addr, uint64_t data[2] )/*{{{*/
{
int sid_local = sid;
(ld_callback)(sid_local,addr ,ATOMIC,0xff,&data[0]);
(ld_callback)(sid_local,addr + 8,ATOMIC,0xff,&data[1]);
}
/*}}}*/
uint8_t SS_ExternalMemory::ldstub( uint64_t addr )/*{{{*/
{
int sid_local = sid;
uint64_t data;
uint_t n = 7 - (addr & 7);
(ld_callback)(sid_local,addr &~ 7,ATOMIC,0x1 << n,&data);
(st_callback)(sid_local,addr &~ 7,ATOMIC,0x1 << n,0xff << (n * 8));
return data >> (n * 8);
}
/*}}}*/
uint32_t SS_ExternalMemory::swap( uint64_t addr, uint32_t rd )/*{{{*/
{
int sid_local = sid;
uint64_t data;
uint_t n = 4 - (addr & 4);
(ld_callback)(sid_local,addr &~ 7,ATOMIC,0xf << n,&data);
(st_callback)(sid_local,addr &~ 7,ATOMIC,0xf << n,uint64_t(rd) << (n * 8));
return data >> (n * 8);
}
/*}}}*/
uint64_t SS_ExternalMemory::casx( uint64_t addr, uint64_t rd, uint64_t rs2 )/*{{{*/
{
int sid_local = sid;
uint64_t data;
(ld_callback)(sid_local,addr,ATOMIC,0xff,&data);
if (rs2 == data)
(st_callback)(sid_local,addr,ATOMIC,0xff,rd);
else if (dummy_st_for_cas)
(st_callback)(sid_local,addr,ATOMIC,0,rd);
return data;
}
/*}}}*/
uint32_t SS_ExternalMemory::cas( uint64_t addr, uint32_t rd, uint32_t rs2 )/*{{{*/
{
int sid_local = sid;
uint64_t data;
uint_t n = 4 - (addr & 4);
(ld_callback)(sid_local,addr &~ 7,ATOMIC,0xf << n,&data);
data = uint32_t(data >> (n * 8));
if (rs2 == data)
(st_callback)(sid_local,addr &~ 7,ATOMIC,0xf << n,uint64_t(rd) << (n * 8));
else if (dummy_st_for_cas)
(st_callback)(sid_local,addr &~ 7,ATOMIC,0,uint64_t(rd) << (n * 8));
return data;
}
/*}}}*/
void SS_ExternalMemory::prefetch( uint64_t addr, uint_t size )/*{{{*/
{
}
/*}}}*/
void SS_ExternalMemory::flush( uint64_t addr, uint_t size )/*{{{*/
{
}
/*}}}*/