Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / sam / src / SS_SamIo.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: SS_SamIo.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_SamIo_h__
#define __SS_SamIo_h__
#ifdef COMPILE_FOR_SAM
#include "SS_Types.h"
#include "SS_AddressMap.h"
namespace Sam
{
#define bool_t bool
#include "vcpu.h"
};
class SS_Io : public SS_AddressMap
{
public:
SS_Io() : SS_AddressMap(), access_io(0) {}
~SS_Io() {}
enum access_io_status
{
NOT_HANDLED=-1,
OK=0,
FOLLOWME=1,
NOP=2,
RSV_READ=3, // read from reserved range
RSV_WRITE=4 // write to reserved range
};
// Supported User Interface Operations
void poke8( uint_t sid, uint64_t addr, uint8_t data ) { st8(sid,addr,data); }
void poke16( uint_t sid, uint64_t addr, uint16_t data ) { st16(sid,addr,data); }
void poke32( uint_t sid, uint64_t addr, uint32_t data ) { st32(sid,addr,data); }
void poke64( uint_t sid, uint64_t addr, uint64_t data ) { st64(sid,addr,data); }
uint8_t peek8u( uint_t sid, uint64_t addr ) { return ld8u(sid,addr); }
int8_t peek8s( uint_t sid, uint64_t addr ) { return ld8s(sid,addr); }
uint16_t peek16u( uint_t sid, uint64_t addr ) { return ld16u(sid,addr); }
int16_t peek16s( uint_t sid, uint64_t addr ) { return ld16s(sid,addr); }
uint32_t peek32u( uint_t sid, uint64_t addr ) { return ld32u(sid,addr); }
int32_t peek32s( uint_t sid, uint64_t addr ) { return ld32s(sid,addr); }
uint64_t peek64( uint_t sid, uint64_t addr ) { return ld64(sid,addr); }
// Supported Fetch Operation (instruction fetch)
uint32_t fetch32( uint_t sid, uint64_t addr ) { return ld32u(sid,addr); }
void fetch256( uint_t sid, uint64_t addr, uint64_t data[4] ) { ld256(sid,addr,data); }
void fetch512( uint_t sid, uint64_t addr, uint64_t data[8] ) { ld512(sid,addr,data); }
void st8 ( uint_t sid, uint64_t addr, uint8_t data )
{
uint64_t _data = data;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::STORE, addr, 1, &_data);
else
error[sid] = (access_io)(sid,Sam::VCPU_STORE_OP,addr,1,_data,~0);
}
void st16 ( uint_t sid, uint64_t addr, uint16_t data )
{
uint64_t _data = data;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::STORE, addr, 2, &_data);
else
error[sid] = (access_io)(sid,Sam::VCPU_STORE_OP,addr,2,_data,~0);
}
void st32 ( uint_t sid, uint64_t addr, uint32_t data )
{
uint64_t _data = data;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::STORE, addr, 4, &_data);
else
error[sid] = (access_io)(sid,Sam::VCPU_STORE_OP,addr,4,_data,~0);
}
void st64 ( uint_t sid, uint64_t addr, uint64_t data )
{
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::STORE, addr, 8, &data);
else
error[sid] = (access_io)(sid,Sam::VCPU_STORE_OP,addr,8,data,~0);
}
void st128( uint_t sid, uint64_t addr, uint64_t data[2] )
{
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::STORE, addr, 16, data);
else
io_error();
}
void st512( uint_t sid, uint64_t addr, uint64_t data[8] )
{
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::STORE, addr, 64, data);
else
io_error();
}
uint8_t ld8u ( uint_t sid, uint64_t addr )
{
return ld8s(sid, addr);
}
int8_t ld8s ( uint_t sid, uint64_t addr )
{
uint64_t _data;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::LOAD, addr, 1, &_data);
else
error[sid] = (access_io)(sid,Sam::VCPU_LOAD_OP,addr,1,_data,~0);
return _data;
}
uint16_t ld16u( uint_t sid, uint64_t addr )
{
return ld16s(sid, addr);
}
int16_t ld16s( uint_t sid, uint64_t addr )
{
uint64_t _data;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::LOAD, addr, 2, &_data);
else
error[sid] = (access_io)(sid,Sam::VCPU_LOAD_OP,addr,2,_data,~0);
return _data;
}
uint32_t ld32u( uint_t sid, uint64_t addr )
{
return ld32s(sid, addr);
}
int32_t ld32s( uint_t sid, uint64_t addr )
{
uint64_t _data;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::LOAD, addr, 4, &_data);
else
error[sid] = (access_io)(sid,Sam::VCPU_LOAD_OP,addr,4,_data,~0);
return _data;
}
uint64_t ld64 ( uint_t sid, uint64_t addr )
{
uint64_t _data;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::LOAD, addr, 8, &_data);
else
error[sid] = (access_io)(sid,Sam::VCPU_LOAD_OP,addr,8,_data,~0);
return _data;
}
void ld128( uint_t sid, uint64_t addr, uint64_t data[2] )
{
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::LOAD, addr, 16, data);
else
io_error();
}
void ld256( uint_t sid, uint64_t addr, uint64_t data[4] )
{
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::LOAD, addr, 32, data);
else
io_error();
}
void ld512( uint_t sid, uint64_t addr, uint64_t data[8] )
{
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::LOAD, addr, 64, data);
else
{
error[sid] = (access_io)(sid,Sam::VCPU_LOAD_OP,addr+0, 8,data[0],~0);
if (error[sid] == 0)
{
(access_io)(sid,Sam::VCPU_LOAD_OP,addr+8, 8,data[1],~0);
(access_io)(sid,Sam::VCPU_LOAD_OP,addr+16,8,data[2],~0);
(access_io)(sid,Sam::VCPU_LOAD_OP,addr+24,8,data[3],~0);
(access_io)(sid,Sam::VCPU_LOAD_OP,addr+32,8,data[4],~0);
(access_io)(sid,Sam::VCPU_LOAD_OP,addr+40,8,data[5],~0);
(access_io)(sid,Sam::VCPU_LOAD_OP,addr+48,8,data[6],~0);
(access_io)(sid,Sam::VCPU_LOAD_OP,addr+56,8,data[7],~0);
}
}
}
void st64partial( uint_t sid, uint64_t addr, uint64_t data, uint64_t mask )
{
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
{
uint64_t _data[2];
_data[0] = data;
_data[1] = mask;
range->cpu(sid, SS_Access::STP, addr, 8, _data);
}
else
error[sid] = (access_io)(sid,Sam::VCPU_STORE_PARTIAL_OP,addr,8,data,mask);
}
void ld128atomic( uint_t sid, uint64_t addr, uint64_t data[2] )
{
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::LOAD, addr, 16, data);
else
io_error();
}
uint8_t ldstub( uint_t sid, uint64_t addr )
{
uint64_t data = 0xff;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::LDST, addr, 1, &data);
else
io_error();
return data;
}
uint32_t swap( uint_t sid, uint64_t addr, uint32_t rd )
{
uint64_t data = rd;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::SWAP, addr, 4, &data);
else
io_error();
return data;
}
uint64_t casx( uint_t sid, uint64_t addr, uint64_t rd, uint64_t rs2 )
{
uint64_t data[2];
data[0] = rd;
data[1] = rs2;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::CAS, addr, 8, data);
else
io_error();
return data[0];
}
uint32_t cas( uint_t sid, uint64_t addr, uint32_t rd, uint32_t rs2 )
{
uint64_t data[2];
data[0] = rd;
data[1] = rs2;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
range->cpu(sid, SS_Access::CAS, addr, 4, data);
else
io_error();
return data[0];
}
void prefetch( uint_t sid, uint64_t addr, uint_t size )
{
uint64_t data;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
io_error();
else
(access_io)(sid,Sam::VCPU_PREFETCH_OP,addr,size,data,~0);
}
void flush( uint_t sid, uint64_t addr, uint_t size )
{
uint64_t data;
SS_AddressMap::Range* range = find(addr);
if (range != SS_AddressMap::fail)
io_error();
else
(access_io)(sid,Sam::VCPU_FLUSH_OP,addr,size,data,~0);
}
static SS_Io io;
typedef int (*AccessIO)( int sid, int type, uint64_t addr, uint32_t size, uint64_t &data, uint64_t mask );
void set_access_io( AccessIO _access_io ) { access_io = _access_io; }
int error[65536]; // 64K seems enough space for virtual strands
private:
void io_error();
AccessIO access_io;
};
#endif /* COMPILE_FOR_SAM */
#endif /* __SS_SamIo_h__ */